⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne_auth.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
{    struct ne_md5_ctx tmp;    unsigned char tmp_md5[16];    char password[NE_ABUFSIZ];    /* Verify they've given us the right bits. */    if (parms->alg == auth_alg_unknown ||	((parms->alg == auth_alg_md5_sess) &&	 !(parms->qop_auth || parms->qop_auth_int)) ||	parms->realm==NULL || parms->nonce==NULL) {	NE_DEBUG(NE_DBG_HTTPAUTH, "Invalid challenge.");	return -1;    }    if (parms->stale) {	/* Just a stale response, don't need to get a new username/password */	NE_DEBUG(NE_DBG_HTTPAUTH, "Stale digest challenge.\n");    } else {	/* Forget the old session details */	NE_DEBUG(NE_DBG_HTTPAUTH, "In digest challenge.\n");	clean_session(sess);	sess->realm = ne_strdup(parms->realm);	/* Not a stale response: really need user authentication */	if (get_credentials(sess, password)) {	    /* Failed to get credentials */	    return -1;	}    }    sess->alg = parms->alg;    sess->scheme = auth_scheme_digest;    sess->nonce = ne_strdup(parms->nonce);    sess->cnonce = get_cnonce();    /* TODO: add domain handling. */    if (parms->opaque != NULL) {	sess->opaque = ne_strdup(parms->opaque); /* don't strip the quotes */    }        if (parms->got_qop) {	/* What type of qop are we to apply to the message? */	NE_DEBUG(NE_DBG_HTTPAUTH, "Got qop directive.\n");	sess->nonce_count = 0;	if (parms->qop_auth_int) {	    sess->qop = auth_qop_auth_int;	} else {	    sess->qop = auth_qop_auth;	}    } else {	/* No qop at all/ */	sess->qop = auth_qop_none;    }        if (!parms->stale) {	/* Calculate H(A1).	 * tmp = H(unq(username-value) ":" unq(realm-value) ":" passwd)	 */	NE_DEBUG(NE_DBG_HTTPAUTH, "Calculating H(A1).\n");	ne_md5_init_ctx(&tmp);	ne_md5_process_bytes(sess->username, strlen(sess->username), &tmp);	ne_md5_process_bytes(":", 1, &tmp);	ne_md5_process_bytes(sess->realm, strlen(sess->realm), &tmp);	ne_md5_process_bytes(":", 1, &tmp);	ne_md5_process_bytes(password, strlen(password), &tmp);	memset(password, 0, sizeof password); /* done with that. */	ne_md5_finish_ctx(&tmp, tmp_md5);	if (sess->alg == auth_alg_md5_sess) {	    unsigned char a1_md5[16];	    struct ne_md5_ctx a1;	    char tmp_md5_ascii[33];	    /* Now we calculate the SESSION H(A1)	     *    A1 = H(...above...) ":" unq(nonce-value) ":" unq(cnonce-value) 	     */	    ne_md5_to_ascii(tmp_md5, tmp_md5_ascii);	    ne_md5_init_ctx(&a1);	    ne_md5_process_bytes(tmp_md5_ascii, 32, &a1);	    ne_md5_process_bytes(":", 1, &a1);	    ne_md5_process_bytes(sess->nonce, strlen(sess->nonce), &a1);	    ne_md5_process_bytes(":", 1, &a1);	    ne_md5_process_bytes(sess->cnonce, strlen(sess->cnonce), &a1);	    ne_md5_finish_ctx(&a1, a1_md5);	    ne_md5_to_ascii(a1_md5, sess->h_a1);	    NE_DEBUG(NE_DBG_HTTPAUTH, "Session H(A1) is [%s]\n", sess->h_a1);	} else {	    ne_md5_to_ascii(tmp_md5, sess->h_a1);	    NE_DEBUG(NE_DBG_HTTPAUTH, "H(A1) is [%s]\n", sess->h_a1);	}	    }        NE_DEBUG(NE_DBG_HTTPAUTH, "I like this Digest challenge.\n");    return 0;}/* callback for ne_pull_request_body. */static int digest_body(void *userdata, const char *buf, size_t count){    struct ne_md5_ctx *ctx = userdata;    ne_md5_process_bytes(buf, count, ctx);    return 0;}/* Return Digest authentication credentials header value for the given * session. */static char *request_digest(auth_session *sess, struct auth_request *req) {    struct ne_md5_ctx a2, rdig;    unsigned char a2_md5[16], rdig_md5[16];    char a2_md5_ascii[33], rdig_md5_ascii[33];    char nc_value[9] = {0};    const char *qop_value; /* qop-value */    ne_buffer *ret;    /* Increase the nonce-count */    if (sess->qop != auth_qop_none) {	sess->nonce_count++;	ne_snprintf(nc_value, 9, "%08x", sess->nonce_count);	NE_DEBUG(NE_DBG_HTTPAUTH, "Nonce count is %u, nc is [%s]\n", 		 sess->nonce_count, nc_value);    }    qop_value = sess->qop == auth_qop_auth_int ? "auth-int" : "auth";    /* Calculate H(A2). */    ne_md5_init_ctx(&a2);    ne_md5_process_bytes(req->method, strlen(req->method), &a2);    ne_md5_process_bytes(":", 1, &a2);    ne_md5_process_bytes(req->uri, strlen(req->uri), &a2);        if (sess->qop == auth_qop_auth_int) {	struct ne_md5_ctx body;	char tmp_md5_ascii[33];	unsigned char tmp_md5[16];		ne_md5_init_ctx(&body);	/* Calculate H(entity-body): pull in the request body from	 * where-ever it is coming from, and calculate the digest. */		NE_DEBUG(NE_DBG_HTTPAUTH, "Digesting request body...\n");	ne_pull_request_body(req->request, digest_body, &body);	NE_DEBUG(NE_DBG_HTTPAUTH, "Digesting request body done.\n");			ne_md5_finish_ctx(&body, tmp_md5);	ne_md5_to_ascii(tmp_md5, tmp_md5_ascii);	NE_DEBUG(NE_DBG_HTTPAUTH, "H(entity-body) is [%s]\n", tmp_md5_ascii);		/* Append to A2 */	ne_md5_process_bytes(":", 1, &a2);	ne_md5_process_bytes(tmp_md5_ascii, 32, &a2);    }    ne_md5_finish_ctx(&a2, a2_md5);    ne_md5_to_ascii(a2_md5, a2_md5_ascii);    NE_DEBUG(NE_DBG_HTTPAUTH, "H(A2): %s\n", a2_md5_ascii);    NE_DEBUG(NE_DBG_HTTPAUTH, "Calculating Request-Digest.\n");    /* Now, calculation of the Request-Digest.     * The first section is the regardless of qop value     *     H(A1) ":" unq(nonce-value) ":" */    ne_md5_init_ctx(&rdig);    /* Use the calculated H(A1) */    ne_md5_process_bytes(sess->h_a1, 32, &rdig);    ne_md5_process_bytes(":", 1, &rdig);    ne_md5_process_bytes(sess->nonce, strlen(sess->nonce), &rdig);    ne_md5_process_bytes(":", 1, &rdig);    if (sess->qop != auth_qop_none) {	/* Add on:	 *    nc-value ":" unq(cnonce-value) ":" unq(qop-value) ":"	 */	NE_DEBUG(NE_DBG_HTTPAUTH, "Have qop directive, digesting: [%s:%s:%s]\n",		 nc_value, sess->cnonce, qop_value);	ne_md5_process_bytes(nc_value, 8, &rdig);	ne_md5_process_bytes(":", 1, &rdig);	ne_md5_process_bytes(sess->cnonce, strlen(sess->cnonce), &rdig);	ne_md5_process_bytes(":", 1, &rdig);	/* Store a copy of this structure (see note below) */	sess->stored_rdig = rdig;	ne_md5_process_bytes(qop_value, strlen(qop_value), &rdig);	ne_md5_process_bytes(":", 1, &rdig);    } else {	/* Store a copy of this structure... we do this because the	 * calculation of the rspauth= field in the Auth-Info header 	 * is the same as this digest, up to this point. */	sess->stored_rdig = rdig;    }    /* And finally, H(A2) */    ne_md5_process_bytes(a2_md5_ascii, 32, &rdig);    ne_md5_finish_ctx(&rdig, rdig_md5);    ne_md5_to_ascii(rdig_md5, rdig_md5_ascii);        ret = ne_buffer_create();    ne_buffer_concat(ret, 		     "Digest username=\"", sess->username, "\", "		     "realm=\"", sess->realm, "\", "		     "nonce=\"", sess->nonce, "\", "		     "uri=\"", req->uri, "\", "		     "response=\"", rdig_md5_ascii, "\", "		     "algorithm=\"", sess->alg == auth_alg_md5 ? "MD5" : "MD5-sess", "\"", 		     NULL);        if (sess->opaque != NULL) {	ne_buffer_concat(ret, ", opaque=\"", sess->opaque, "\"", NULL);    }    if (sess->qop != auth_qop_none) {	/* Add in cnonce and nc-value fields */	ne_buffer_concat(ret, ", cnonce=\"", sess->cnonce, "\", "			 "nc=", nc_value, ", "			 "qop=\"", qop_value, "\"", NULL);    }    ne_buffer_zappend(ret, "\r\n");        NE_DEBUG(NE_DBG_HTTPAUTH, "Digest request header is %s\n", ret->data);    return ne_buffer_finish(ret);}/* Parse line of comma-separated key-value pairs.  If 'ischall' == 1, * then also return a leading space-separated token, as *value == NULL. * Otherwise, if return value is 0, *key and *value will be non-NULL. * If return value is non-zero, parsing has ended. */static int tokenize(char **hdr, char **key, char **value, int ischall){    char *pnt = *hdr;    enum { BEFORE_EQ, AFTER_EQ, AFTER_EQ_QUOTED } state = BEFORE_EQ;        if (**hdr == '\0')	return 1;    *key = NULL;    do {	switch (state) {	case BEFORE_EQ:	    if (*pnt == '=') {		if (*key == NULL)		    return -1;		*pnt = '\0';		*value = pnt + 1;		state = AFTER_EQ;	    } else if (*pnt == ' ' && ischall && *key != NULL) {		*value = NULL;		*pnt = '\0';		*hdr = pnt + 1;		return 0;	    } else if (*key == NULL && strchr(" \r\n\t", *pnt) == NULL) {		*key = pnt;	    }	    break;	case AFTER_EQ:	    if (*pnt == ',') {		*pnt = '\0';		*hdr = pnt + 1;		return 0;	    } else if (*pnt == '\"') {		state = AFTER_EQ_QUOTED;	    }	    break;	case AFTER_EQ_QUOTED:	    if (*pnt == '\"') {		state = AFTER_EQ;	    }	    break;	}    } while (*++pnt != '\0');        if (state == BEFORE_EQ && ischall && *key != NULL) {	*value = NULL;    }    *hdr = pnt;    /* End of string: */    return 0;}/* Pass this the value of the 'Authentication-Info:' header field, if * one is received. * Returns: *    0 if it gives a valid authentication for the server  *    non-zero otherwise (don't believe the response in this case!). */static int verify_response(struct auth_request *req, auth_session *sess,			   const char *value) {    char *hdr, *pnt, *key, *val;    auth_qop qop = auth_qop_none;    char *nextnonce = NULL, /* for the nextnonce= value */	*rspauth = NULL, /* for the rspauth= value */	*cnonce = NULL, /* for the cnonce= value */	*nc = NULL, /* for the nc= value */	*qop_value = NULL;    unsigned int nonce_count;    int okay;        if (!req->will_handle) {	/* Ignore it */	return 0;    }        if (sess->scheme != auth_scheme_digest) {	NE_DEBUG(NE_DBG_HTTPAUTH, "Found Auth-Info header not in response "		 " to Digest credentials - dodgy.\n");	return -1;    }    pnt = hdr = ne_strdup(value);        NE_DEBUG(NE_DBG_HTTPAUTH, "Auth-Info header: %s\n", value);    while (tokenize(&pnt, &key, &val, 0) == 0) {	val = ne_shave(val, "\"");	NE_DEBUG(NE_DBG_HTTPAUTH, "Pair: [%s] = [%s]\n", key, val);	if (strcasecmp(key, "qop") == 0) {	    qop_value = val;	    if (strcasecmp(val, "auth-int") == 0) {		qop = auth_qop_auth_int;	    } else if (strcasecmp(val, "auth") == 0) {		qop = auth_qop_auth;	    } else {		qop = auth_qop_none;	    }	} else if (strcasecmp(key, "nextnonce") == 0) {	    nextnonce = val;	} else if (strcasecmp(key, "rspauth") == 0) {	    rspauth = val;	} else if (strcasecmp(key, "cnonce") == 0) {	    cnonce = val;	} else if (strcasecmp(key, "nc") == 0) { 	    nc = val;	    if (sscanf(val, "%x", &nonce_count) != 1) {		NE_DEBUG(NE_DBG_HTTPAUTH, "Couldn't find nonce count.\n");	    } else {		NE_DEBUG(NE_DBG_HTTPAUTH, "Got nonce_count: %u\n", nonce_count);	    }	}    }    /* Presume the worst */    okay = -1;    if ((qop != auth_qop_none) && (qop_value != NULL)) {	if ((rspauth == NULL) || (cnonce == NULL) || (nc == NULL)) {	    NE_DEBUG(NE_DBG_HTTPAUTH, "Missing rspauth, cnonce or nc with qop.\n");	} else { /* Have got rspauth, cnonce and nc */	    if (strcmp(cnonce, sess->cnonce) != 0) {		NE_DEBUG(NE_DBG_HTTPAUTH, "Response cnonce doesn't match.\n");	    } else if (nonce_count != sess->nonce_count) { 		NE_DEBUG(NE_DBG_HTTPAUTH, "Response nonce count doesn't match.\n");	    } else {		/* Calculate and check the response-digest value.		 * joe: IMO the spec is slightly ambiguous as to whether		 * we use the qop which WE sent, or the qop which THEY		 * sent...  */		struct ne_md5_ctx a2;		unsigned char a2_md5[16], rdig_md5[16];		char a2_md5_ascii[33], rdig_md5_ascii[33];		NE_DEBUG(NE_DBG_HTTPAUTH, "Calculating response-digest.\n");		/* First off, H(A2) again. */		ne_md5_init_ctx(&a2);		ne_md5_process_bytes(":", 1, &a2);		ne_md5_process_bytes(req->uri, strlen(req->uri), &a2);		if (qop == auth_qop_auth_int) {		    unsigned char heb_md5[16];		    char heb_md5_ascii[33];		    /* Add on ":" H(entity-body) */		    ne_md5_finish_ctx(&req->response_body, heb_md5);		    ne_md5_to_ascii(heb_md5, heb_md5_ascii);		    ne_md5_process_bytes(":", 1, &a2);		    ne_md5_process_bytes(heb_md5_ascii, 32, &a2);		    NE_DEBUG(NE_DBG_HTTPAUTH, "Digested [:%s]\n", heb_md5_ascii);		}		ne_md5_finish_ctx(&a2, a2_md5);		ne_md5_to_ascii(a2_md5, a2_md5_ascii);				/* We have the stored digest-so-far of 		 *   H(A1) ":" unq(nonce-value) 		 *        [ ":" nc-value ":" unq(cnonce-value) ] for qop		 * in sess->stored_rdig, to save digesting them again.		 *		 */		if (qop != auth_qop_none) {		    /* Add in qop-value */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -