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

📄 httpauth.c

📁 站点映像程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	sess->stored_rdig = rdig;    }    /* And finally, H(A2) */    md5_process_bytes( a2_md5_ascii, 32, &rdig );    md5_finish_ctx( &rdig, rdig_md5 );    md5_hexify( rdig_md5, rdig_md5_ascii );        /* Buffer size calculation. */        retlen = 	6                                      /* Digest */	+ 1 + 8 + 1 + 2 + strlen(sess->username)  /*  username="..." */	+ 2 + 5 + 1 + 2 + strlen(sess->unq_realm) /* , realm="..." */	+ 2 + 5 + 1 + 2 + strlen(sess->unq_nonce) /* , nonce="..." */	+ 2 + 3 + 1 + 2 + strlen(sess->uri)       /* , uri="..." */	+ 2 + 8 + 1 + 2 + 32                      /* , response="..." */	+ 2 + 9 + 1 + strlen(http_auth_alg_names[sess->alg]) /* , algorithm= */	;    if( sess->opaque != NULL )	retlen += 2 + 6 + 1 + strlen(sess->opaque);   /* , opaque=... */    if( sess->qop != http_auth_qop_none )	retlen += 	    2 + 6 + 2 + 1 + strlen(sess->unq_cnonce) +   /* , cnonce="..." */	    2 + 2 + 1 + 8 +                       /* , nc=... */	    2 + 3 + 1 + strlen(http_auth_qop_values[sess->qop]) /* , qop=... */	    ;    retlen += 2;   /* \r\n */    DEBUG( DEBUG_HTTPAUTH, "Calculated length of buffer: %d\n", retlen );    ret = malloc( retlen + 1 );    sprintf( ret,	      "Digest username=\"%s\", realm=\"%s\""	      ", nonce=\"%s\", uri=\"%s\", response=\"%s\""	      ", algorithm=%s",	      sess->username, sess->unq_realm, 	      sess->unq_nonce, sess->uri, rdig_md5_ascii,	      http_auth_alg_names[sess->alg]);        if( sess->opaque != NULL ) {	/* We never unquote it, so it's still quoted here */	strcat( ret, ", opaque=" );	strcat( ret, sess->opaque );    }    if( sess->qop != http_auth_qop_none ) {	/* Add in cnonce and nc-value fields */	strcat( ret, ", cnonce=\"" );	strcat( ret, sess->unq_cnonce );	strcat( ret, "\", nc=" );	strcat( ret, nc_value );	strcat( ret, ", qop=" );	strcat( ret, http_auth_qop_values[sess->qop] );    }    DEBUG( DEBUG_HTTPAUTH, "Digest header field value:\n%s\n", ret );    strcat( ret, "\r\n" );    DEBUG( DEBUG_HTTPAUTH, "Calculated length: %d, actual length: %d\n", 	   retlen, strlen( ret ) );        return ret;}inline void http_auth_response_body( http_auth_session_t *sess, 				     const char *buffer, size_t buffer_len ) {    if( sess->scheme != http_auth_scheme_digest ) return;    DEBUG( DEBUG_HTTPAUTH, "Digesting %d bytes of response body.\n" );    md5_process_bytes( buffer, buffer_len, &sess->response_body );}/* Pass this the value of the 'Authentication-Info:' header field, if * one is received. Returns false if gives incorrect authentication * information for the server. */bool http_auth_verify_response( http_auth_session_t *sess, const char *value ) {    char **pairs;    http_auth_qop_t qop = http_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 */	*unquoted, *qop_value = NULL;    int n, nonce_count;    bool okay;        if( sess->scheme != http_auth_scheme_digest ) {	DEBUG( DEBUG_HTTPAUTH, "Found Auth-Info header not in response to Digest credentials - dodgy.\n" );	return false;    }        pairs = strpairs( value, ',', '=', http_quotes, http_whitespace );        for( n = 0; pairs[n]!=NULL; n+=2 ) {	unquoted = strstrip( pairs[n+1], '"' );	if( strcasecmp( pairs[n], "qop" ) == 0 ) {	    qop_value = strdup( pairs[n+1] );	    if( strcasecmp( pairs[n+1], "auth-int" ) == 0 ) {		qop = http_auth_qop_auth_int;	    } else if( strcasecmp( pairs[n+1], "auth" ) == 0 ) {		qop = http_auth_qop_auth;	    } else {		qop = http_auth_qop_none;	    }	} else if( strcasecmp( pairs[n], "nextnonce" ) == 0 ) {	    nextnonce = strdup( unquoted );	} else if( strcasecmp( pairs[n], "rspauth" ) == 0 ) {	    rspauth = strdup( unquoted );	} else if( strcasecmp( pairs[n], "cnonce" ) == 0 ) {	    cnonce = strdup( unquoted );	} else if( strcasecmp( pairs[n], "nc" ) == 0 ) { 	    nc = strdup( pairs[n] );	    if( sscanf( pairs[n+1], "%x", &nonce_count ) != 1 ) {		DEBUG( DEBUG_HTTPAUTH, "Couldn't scan [%s] for nonce count.\n",		       pairs[n+1] );	    } else {		DEBUG( DEBUG_HTTPAUTH, "Got nonce_count: %d\n", nonce_count );	    }	}	free( unquoted );    }    strpairs_free( pairs );    /* Presume the worst */    okay = false;    if( (qop != http_auth_qop_none) && (qop_value != NULL) ) {	if( (rspauth == NULL) || (cnonce == NULL) || (nc == NULL) ) {	    DEBUG( DEBUG_HTTPAUTH, "Missing rspauth, cnonce or nc with qop.\n" );	} else { /* Have got rspauth, cnonce and nc */	    if( strcmp( cnonce, sess->unq_cnonce ) != 0 ) {		DEBUG( DEBUG_HTTPAUTH, "Response cnonce doesn't match.\n" );	    } else if( nonce_count != sess->nonce_count ) { 		DEBUG( DEBUG_HTTPAUTH, "Response nonce count doesn't match.\n" );	    } else {		/* Calculate and check the response-digest value. */		/* TODO: Should we use our sent qop-value here, or		 * the one the server gave us? Currently, we use the server		 * qop-value... that's what mod_digest does.		 */		struct md5_ctx a2;		unsigned char a2_md5[16], rdig_md5[16];		char a2_md5_ascii[33], rdig_md5_ascii[33];		DEBUG( DEBUG_HTTPAUTH, "Calculating response-digest.\n" );		/* First off, H(A2) again. */		md5_init_ctx( &a2 );		md5_process_bytes( ":", 1, &a2 );		md5_process_bytes( sess->uri, strlen(sess->uri), &a2 );		if( qop == http_auth_qop_auth_int ) {		    unsigned char heb_md5[16];		    char heb_md5_ascii[33];		    /* Add on ":" H(entity-body) */		    md5_finish_ctx( &sess->response_body, heb_md5 );		    md5_hexify( heb_md5, heb_md5_ascii );		    md5_process_bytes( ":", 1, &a2 );		    md5_process_bytes( heb_md5_ascii, 32, &a2 );		    DEBUG( DEBUG_HTTPAUTH, "Digested [:%s]\n", heb_md5_ascii );		}		md5_finish_ctx( &a2, a2_md5 );		md5_hexify( 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 safe digesting them again.		 *		 */		if( qop != http_auth_qop_none ) {		    /* Add in qop-value */		    DEBUG( DEBUG_HTTPAUTH, "Digesting qop-value [%s:].\n", 			   qop_value );		    md5_process_bytes( qop_value, strlen(qop_value), 				       &sess->stored_rdig );		    md5_process_bytes( ":", 1, &sess->stored_rdig );		}		/* Digest ":" H(A2) */		md5_process_bytes( a2_md5_ascii, 32, &sess->stored_rdig );		/* All done */		md5_finish_ctx( &sess->stored_rdig, rdig_md5 );		md5_hexify( rdig_md5, rdig_md5_ascii );		DEBUG( DEBUG_HTTPAUTH, "Calculated response-digest of: [%s]\n",		       rdig_md5_ascii );		DEBUG( DEBUG_HTTPAUTH, "Given response-digest of:      [%s]\n",		       rspauth );		/* And... do they match? */		okay = (strcmp( rdig_md5_ascii, rspauth ) == 0);				DEBUG( DEBUG_HTTPAUTH, "Matched: %s\n", 		       okay?"OH YES!":"nope." );	    }	    free( rspauth );	    free( cnonce );	    free( nc );	}	free( qop_value );    } else {	DEBUG( DEBUG_HTTPAUTH, "No qop directive, auth okay.\n" );	okay = true;    }    /* Check for a nextnonce */    if( nextnonce != NULL ) {	DEBUG( DEBUG_HTTPAUTH, "Found nextnonce of [%s].\n", nextnonce );	if( sess->unq_nonce != NULL )	    free( sess->unq_nonce );	sess->unq_nonce = nextnonce;    }    return okay;}bool http_auth_challenge( http_auth_session_t *sess, const char *value ) {    char **pairs, *pnt, *unquoted, *key;    http_auth_chall_t **challenges = NULL, *this_chall = NULL;    int numchalls = 0, n;    bool success;    DEBUG( DEBUG_HTTPAUTH, "Got new auth challenge: %s\n", value );    /* Clean up old session information. */    http_auth_clean( sess );    /* The header value may be made up of one or more challenges.     * We split it down into attribute-value pairs, then search for     * schemes in the pair keys.     */    pairs = strpairs( value, ',', '=', http_quotes, http_whitespace );    for( n = 0; pairs[n]!=NULL; n+=2 ) {	/* Look for an auth-scheme in the key */	pnt = strchr( pairs[n], ' ' );	if( pnt != NULL ) {	    /* We have a new challenge */	    DEBUG( DEBUG_HTTPAUTH, "New challenge.\n" );	    numchalls++;	    challenges = realloc( challenges, 				  numchalls * sizeof(http_auth_chall_t *) );	    challenges[numchalls-1] = malloc( sizeof(http_auth_chall_t) );	    this_chall = challenges[numchalls-1];	    /* Initialize the challenge parameters */	    memset( this_chall, 0, sizeof(http_auth_chall_t) );	    /* Which auth-scheme is it (case-insensitive matching) */	    if( strncasecmp( pairs[n], "basic ", 6 ) == 0 ) {		DEBUG( DEBUG_HTTPAUTH, "Basic scheme.\n" );		this_chall->scheme = http_auth_scheme_basic;	    } else if( strncasecmp( pairs[n], "digest ", 7 ) == 0 ) {		DEBUG( DEBUG_HTTPAUTH, "Digest scheme.\n" );		this_chall->scheme = http_auth_scheme_digest;	    } else {		DEBUG( DEBUG_HTTPAUTH, "Unknown scheme.\n" );		this_chall->scheme = http_auth_scheme_none;	    }	    /* Now, the real key for this pair starts after the 	     * auth-scheme... skipping whitespace */	    while( strchr( http_whitespace, *(++pnt) ) != NULL )		/* nullop */;	    key = pnt;	} else if( this_chall == NULL ) {	    /* If we haven't got an auth-scheme, and we're	     * haven't yet found a challenge, skip this pair.	     */	    continue;	} else {	    key = pairs[n];	}	DEBUG( DEBUG_HTTPAUTH, "Got pair: [%s] = [%s]\n", key, pairs[n+1] );	/* Most values are quoted, so unquote them here */	unquoted = strstrip( pairs[n+1], '"' );	/* Now parse the attribute */	DEBUG( DEBUG_HTTPAUTH, "Unquoted pair is: [%s]\n", unquoted );	if( strcasecmp( key, "realm" ) == 0 ) {	    this_chall->realm = pairs[n+1];	} else if( strcasecmp( key, "nonce" ) == 0 ) {	    this_chall->nonce = pairs[n+1];	} /* else if( strcasecmp( key, "domain" ) == 0 ) {	    this_chall->domain = pairs[n+1]; 	    } */ else if( strcasecmp( key, "opaque" ) == 0 ) {	    this_chall->opaque = pairs[n+1];	} else if( strcasecmp( key, "stale" ) == 0 ) {	    /* Truth value */	    this_chall->stale = 		( strcasecmp( unquoted, "true" ) == 0 );	} else if( strcasecmp( key, "algorithm" ) == 0 ) {	    if( strcasecmp( unquoted, "md5" ) == 0 ) {		this_chall->alg = http_auth_alg_md5;	    } else if( strcasecmp( unquoted, "md5-sess" ) == 0 ) {		this_chall->alg = http_auth_alg_md5_sess;	    } else {		this_chall->alg = http_auth_alg_unknown;	    }	} else if( strcasecmp( key, "qop" ) == 0 ) {	    char **qops;	    int qop;	    qops = strsplit( unquoted, ',', NULL, http_whitespace );	    this_chall->got_qop = true;	    for( qop = 0; qops[qop] != NULL; qop++ ) {		if( strcasecmp( qops[qop], "auth" ) == 0 ) {		    this_chall->qop_auth = true;		} else if( strcasecmp( qops[qop], "auth-int" ) == 0 ) {		    this_chall->qop_auth_int = true;		}	    }	    strsplit_free( qops );	}	free( unquoted );    }    /* Did we find any challenges */    if( numchalls == 0 )	return false;        DEBUG( DEBUG_HTTPAUTH, "Finished parsing parameters.\n" );    success = false;    DEBUG( DEBUG_HTTPAUTH, "Looking for Digest challenges.\n" );    /* Try a digest challenge */    for( n = 0; n < numchalls; n++ ) {	if( challenges[n]->scheme == http_auth_scheme_digest ) {	    if( http_auth_challenge_digest( sess, challenges[n] ) ) {		success = true;		break;	    }	}    }    if( !success ) {	DEBUG( DEBUG_HTTPAUTH, "No good Digest challenges, looking for Basic.\n" );	for( n = 0; n < numchalls; n++ ) {	    if( challenges[n]->scheme == http_auth_scheme_basic ) {		if( http_auth_challenge_basic( sess, challenges[n] ) ) {		    success = true;		    break;		}	    }	}	if( !success ) {	    /* No good challenges - record this in the session state */	    DEBUG( DEBUG_HTTPAUTH, "Did not understand any challenges.\n" );	    sess->scheme = http_auth_scheme_none;	}    }    /* Free up the parsed header values */    strpairs_free( pairs );    return success; 		    }

⌨️ 快捷键说明

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