?? auth_digest.c
字號:
node = digest_user->nonces.head; while (node && (node->data != nonce)) node = node->next; if (node) return; node = dlinkNodeNew(); dlinkAddTail(nonce, node, &digest_user->nonces); authDigestNonceLink(nonce); /* ping this nonce to this auth user */ assert((nonce->auth_user == NULL) || (nonce->auth_user = auth_user)); /* we don't lock this reference because removing the auth_user removes the * hash too. Of course if that changes we're stuffed so read the code huh? */ nonce->auth_user = auth_user;}/* authenticateDigestUsername: return a pointer to the username in the */static char *authenticateDigestUsername(auth_user_t * auth_user){ digest_user_h *digest_user = auth_user->scheme_data; if (digest_user) return digest_user->username; return NULL;}/* setup the necessary info to log the username */static voidauthDigestLogUsername(auth_user_request_t * auth_user_request, char *username){ auth_user_t *auth_user; digest_user_h *digest_user; dlink_node *node; /* log the username */ debug(29, 9) ("authDigestLogUsername: Creating new user for logging '%s'\n", username); /* new auth_user */ auth_user = authenticateAuthUserNew("digest"); /* new scheme data */ digest_user = authDigestUserNew(); /* save the credentials */ digest_user->username = username; /* link the scheme data in */ auth_user->scheme_data = digest_user; /* set the auth_user type */ auth_user->auth_type = AUTH_BROKEN; /* link the request to the user */ auth_user_request->auth_user = auth_user; /* lock for the auth_user_request link */ authenticateAuthUserLock(auth_user); node = dlinkNodeNew(); dlinkAdd(auth_user_request, node, &auth_user->requests);}/* * Decode a Digest [Proxy-]Auth string, placing the results in the passed * Auth_user structure. */static voidauthenticateDigestDecodeAuth(auth_user_request_t * auth_user_request, const char *proxy_auth){ String temp; const char *item; const char *p; const char *pos = NULL; char *username = NULL; digest_nonce_h *nonce; int ilen; digest_request_h *digest_request; digest_user_h *digest_user; auth_user_t *auth_user; dlink_node *node; debug(29, 9) ("authenticateDigestDecodeAuth: beginning\n"); assert(auth_user_request != NULL); digest_request = authDigestRequestNew(); /* trim DIGEST from string */ while (xisgraph(*proxy_auth)) proxy_auth++; /* Trim leading whitespace before decoding */ while (xisspace(*proxy_auth)) proxy_auth++; stringInit(&temp, proxy_auth); while (strListGetItem(&temp, ',', &item, &ilen, &pos)) { if ((p = strchr(item, '=')) && (p - item < ilen)) ilen = p++ - item; if (!strncmp(item, "username", ilen)) { /* white space */ while (xisspace(*p)) p++; /* quote mark */ p++; username = xstrndup(p, strchr(p, '"') + 1 - p); debug(29, 9) ("authDigestDecodeAuth: Found Username '%s'\n", username); } else if (!strncmp(item, "realm", ilen)) { /* white space */ while (xisspace(*p)) p++; /* quote mark */ p++; digest_request->realm = xstrndup(p, strchr(p, '"') + 1 - p); debug(29, 9) ("authDigestDecodeAuth: Found realm '%s'\n", digest_request->realm); } else if (!strncmp(item, "qop", ilen)) { /* white space */ while (xisspace(*p)) p++; if (*p == '\"') /* quote mark */ p++; digest_request->qop = xstrndup(p, strcspn(p, "\" \t\r\n()<>@,;:\\/[]?={}") + 1); debug(29, 9) ("authDigestDecodeAuth: Found qop '%s'\n", digest_request->qop); } else if (!strncmp(item, "algorithm", ilen)) { /* white space */ while (xisspace(*p)) p++; if (*p == '\"') /* quote mark */ p++; digest_request->algorithm = xstrndup(p, strcspn(p, "\" \t\r\n()<>@,;:\\/[]?={}") + 1); debug(29, 9) ("authDigestDecodeAuth: Found algorithm '%s'\n", digest_request->algorithm); } else if (!strncmp(item, "uri", ilen)) { /* white space */ while (xisspace(*p)) p++; /* quote mark */ p++; digest_request->uri = xstrndup(p, strchr(p, '"') + 1 - p); debug(29, 9) ("authDigestDecodeAuth: Found uri '%s'\n", digest_request->uri); } else if (!strncmp(item, "nonce", ilen)) { /* white space */ while (xisspace(*p)) p++; /* quote mark */ p++; digest_request->nonceb64 = xstrndup(p, strchr(p, '"') + 1 - p); debug(29, 9) ("authDigestDecodeAuth: Found nonce '%s'\n", digest_request->nonceb64); } else if (!strncmp(item, "nc", ilen)) { /* white space */ while (xisspace(*p)) p++; xstrncpy(digest_request->nc, p, 9); debug(29, 9) ("authDigestDecodeAuth: Found noncecount '%s'\n", digest_request->nc); } else if (!strncmp(item, "cnonce", ilen)) { /* white space */ while (xisspace(*p)) p++; /* quote mark */ p++; digest_request->cnonce = xstrndup(p, strchr(p, '"') + 1 - p); debug(29, 9) ("authDigestDecodeAuth: Found cnonce '%s'\n", digest_request->cnonce); } else if (!strncmp(item, "response", ilen)) { /* white space */ while (xisspace(*p)) p++; /* quote mark */ p++; digest_request->response = xstrndup(p, strchr(p, '"') + 1 - p); debug(29, 9) ("authDigestDecodeAuth: Found response '%s'\n", digest_request->response); } } stringClean(&temp); /* now we validate the data given to us */ /* * TODO: on invalid parameters we should return 400, not 407. * Find some clean way of doing this. perhaps return a valid * struct, and set the direction to clientwards combined with * a change to the clientwards handling code (ie let the * clientwards call set the error type (but limited to known * correct values - 400/401/407 */ /* first the NONCE count */ if (digest_request->cnonce && strlen(digest_request->nc) != 8) { debug(29, 4) ("authenticateDigestDecode: nonce count length invalid\n"); authDigestLogUsername(auth_user_request, username); /* we don't need the scheme specific data anymore */ authDigestRequestDelete(digest_request); auth_user_request->scheme_data = NULL; return; } /* now the nonce */ nonce = authenticateDigestNonceFindNonce(digest_request->nonceb64); if (!nonce) { /* we couldn't find a matching nonce! */ debug(29, 4) ("authenticateDigestDecode: Unexpected or invalid nonce received\n"); authDigestLogUsername(auth_user_request, username); /* we don't need the scheme specific data anymore */ authDigestRequestDelete(digest_request); auth_user_request->scheme_data = NULL; return; } digest_request->nonce = nonce; authDigestNonceLink(nonce); /* check the qop is what we expected. Note that for compatability with * RFC 2069 we should support a missing qop. Tough. */ if (!digest_request->qop || strcmp(digest_request->qop, QOP_AUTH)) { /* we received a qop option we didn't send */ debug(29, 4) ("authenticateDigestDecode: Invalid qop option received\n"); authDigestLogUsername(auth_user_request, username); /* we don't need the scheme specific data anymore */ authDigestRequestDelete(digest_request); auth_user_request->scheme_data = NULL; return; } /* we can't check the URI just yet. We'll check it in the * authenticate phase */ /* is the response the correct length? */ if (!digest_request->response || strlen(digest_request->response) != 32) { debug(29, 4) ("authenticateDigestDecode: Response length invalid\n"); authDigestLogUsername(auth_user_request, username); /* we don't need the scheme specific data anymore */ authDigestRequestDelete(digest_request); auth_user_request->scheme_data = NULL; return; } /* do we have a username ? */ if (!username || username[0] == '\0') { debug(29, 4) ("authenticateDigestDecode: Empty or not present username\n"); authDigestLogUsername(auth_user_request, username); /* we don't need the scheme specific data anymore */ authDigestRequestDelete(digest_request); auth_user_request->scheme_data = NULL; return; } /* check that we're not being hacked / the username hasn't changed */ if (nonce->auth_user && strcmp(username, authenticateUserUsername(nonce->auth_user))) { debug(29, 4) ("authenticateDigestDecode: Username for the nonce does not equal the username for the request\n"); authDigestLogUsername(auth_user_request, username); /* we don't need the scheme specific data anymore */ authDigestRequestDelete(digest_request); auth_user_request->scheme_data = NULL; return; } /* if we got a qop, did we get a cnonce or did we get a cnonce wihtout a qop? */ if ((digest_request->qop && !digest_request->cnonce) || (!digest_request->qop && digest_request->cnonce)) { debug(29, 4) ("authenticateDigestDecode: qop without cnonce, or vice versa!\n"); authDigestLogUsername(auth_user_request, username); /* we don't need the scheme specific data anymore */ authDigestRequestDelete(digest_request); auth_user_request->scheme_data = NULL; return; } /* check the algorithm is present and supported */ if (!digest_request->algorithm) digest_request->algorithm = xstrndup("MD5", 4); else if (strcmp(digest_request->algorithm, "MD5") && strcmp(digest_request->algorithm, "MD5-sess")) { debug(29, 4) ("authenticateDigestDecode: invalid algorithm specified!\n"); authDigestLogUsername(auth_user_request, username); /* we don't need the scheme specific data anymore */ authDigestRequestDelete(digest_request); auth_user_request->scheme_data = NULL; return; } /* the method we'll check at the authenticate step as well */ /* we don't send or parse opaques. Ok so we're flexable ... */ /* find the user */ if ((auth_user = authDigestUserFindUsername(username)) == NULL) { /* the user doesn't exist in the username cache yet */ debug(29, 9) ("authDigestDecodeAuth: Creating new digest user '%s'\n", username); /* new auth_user */ auth_user = authenticateAuthUserNew("digest"); /* new scheme user data */ digest_user = authDigestUserNew(); /* save the username */ digest_user->username = username; /* link the primary struct in */ auth_user->scheme_data = digest_user; /* set the user type */ auth_user->auth_type = AUTH_DIGEST; /* this auth_user struct is the one to get added to the * username cache */ /* store user in hash's */ authenticateUserNameCacheAdd(auth_user); /* * Add the digest to the user so we can tell if a hacking * or spoofing attack is taking place. We do this by assuming * the user agent won't change user name without warning. */ authDigestUserLinkNonce(auth_user, nonce); } else { debug(29, 9) ("authDigestDecodeAuth: Found user '%s' in the user cache as '%p'\n", username, auth_user); digest_user = auth_user->scheme_data; xfree(username); } /*link the request and the user */ auth_user_request->auth_user = auth_user; auth_user_request->scheme_data = digest_request; /* lock for the request link */ authenticateAuthUserLock(auth_user); node = dlinkNodeNew(); dlinkAdd(auth_user_request, node, &auth_user->requests); debug(29, 9) ("username = '%s'\nrealm = '%s'\nqop = '%s'\nalgorithm = '%s'\nuri = '%s'\nnonce = '%s'\nnc = '%s'\ncnonce = '%s'\nresponse = '%s'\ndigestnonce = '%p'\n", digest_user->username, digest_request->realm, digest_request->qop, digest_request->algorithm, digest_request->uri, digest_request->nonceb64, digest_request->nc, digest_request->cnonce, digest_request->response, nonce); return;}/* send the initial data to a digest authenticator module */static voidauthenticateDigestStart(auth_user_request_t * auth_user_request, RH * handler, void *data){ authenticateStateData *r = NULL; char buf[8192]; digest_request_h *digest_request; digest_user_h *digest_user; assert(auth_user_request); assert(handler); assert(auth_user_request->auth_user->auth_type == AUTH_DIGEST); assert(auth_user_request->auth_user->scheme_data != NULL); assert(auth_user_request->scheme_data != NULL); digest_request = auth_user_request->scheme_data; digest_user = auth_user_request->auth_user->scheme_data; debug(29, 9) ("authenticateStart: '\"%s\":\"%s\"'\n", digest_user->username, digest_request->realm); if (digestConfig->authenticate == NULL) { handler(data, NULL); return; } r = cbdataAlloc(authenticateStateData); r->handler = handler; cbdataLock(data); r->data = data; r->auth_user_request = auth_user_request; authenticateAuthUserRequestLock(r->auth_user_request); snprintf(buf, 8192, "\"%s\":\"%s\"\n", digest_user->username, digest_request->realm); helperSubmit(digestauthenticators, buf, authenticateDigestHandleReply, r);}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -