Exemplo n.º 1
0
/* setup the necessary info to log the username */
static void
authDigestLogUsername(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);
}
Exemplo n.º 2
0
/* UserNameCacheAdd: add a auth_user structure to the username cache */
void
authenticateUserNameCacheAdd(auth_user_t * auth_user)
{
    auth_user_hash_pointer *usernamehash;
    usernamehash = memAllocate(MEM_AUTH_USER_HASH);
    usernamehash->key = authenticateUserUsername(auth_user);
    usernamehash->auth_user = auth_user;
    hash_join(proxy_auth_username_cache, (hash_link *) usernamehash);
    auth_user->usernamehash = usernamehash;
    /* lock for presence in the cache */
    authenticateAuthUserLock(auth_user);
}
Exemplo n.º 3
0
static void
authenticateDecodeNegotiateAuth(auth_user_request_t * auth_user_request, const char *proxy_auth)
{
    dlink_node *node;
    assert(auth_user_request->auth_user == NULL);
    auth_user_request->auth_user = authenticateAuthUserNew("negotiate");
    auth_user_request->auth_user->auth_type = AUTH_NEGOTIATE;
    auth_user_request->auth_user->scheme_data = memPoolAlloc(negotiate_user_pool);
    auth_user_request->scheme_data = memPoolAlloc(negotiate_request_pool);
    memset(auth_user_request->scheme_data, '\0', sizeof(negotiate_request_t));
    /* lock for the auth_user_request link */
    authenticateAuthUserLock(auth_user_request->auth_user);
    node = dlinkNodeNew();
    dlinkAdd(auth_user_request, node, &auth_user_request->auth_user->requests);

    /* the helper does the rest, with data collected in
     * authenticateNegotiateAuthenticateUser */
    debug(29, 9) ("authenticateDecodeNegotiateAuth: Negotiate authentication\n");
    return;
}
Exemplo n.º 4
0
static void
authenticateBasicDecodeAuth(auth_user_request_t * auth_user_request, const char *proxy_auth)
{
    char *sent_auth;
    char *cleartext;
    basic_data *basic_auth, local_basic;
    auth_user_t *auth_user;
    dlink_node *node;

    /* decode the username */
    /* trim BASIC from string */
    while (xisgraph(*proxy_auth))
	proxy_auth++;

    local_basic.passwd = NULL;

    /* Trim leading whitespace before decoding */
    while (xisspace(*proxy_auth))
	proxy_auth++;
    /* username and password */
    sent_auth = xstrdup(proxy_auth);
    /* Trim trailing \n before decoding */
    strtok(sent_auth, "\n");
    cleartext = uudecode(sent_auth);
    xfree(sent_auth);
    /*
     * Don't allow NL or CR in the credentials.
     * Oezguer Kesim <*****@*****.**>
     */
    debug(29, 9) ("authenticateBasicDecodeAuth: cleartext = '%s'\n", cleartext);
    if (strcspn(cleartext, "\r\n") != strlen(cleartext)) {
	debug(29, 1) ("authenticateBasicDecodeAuth: bad characters in authorization header '%s'\n",
	    proxy_auth);
	xfree(cleartext);
	return;
    }
    local_basic.username = cleartext;
    if ((cleartext = strchr(local_basic.username, ':')) != NULL)
	*(cleartext)++ = '\0';
    local_basic.passwd = cleartext;
    if (cleartext == NULL) {
	debug(29, 4) ("authenticateBasicDecodeAuth: no password in proxy authorization header '%s'\n",
	    proxy_auth);
	local_basic.passwd = NULL;
	auth_user_request->message = xstrdup("no password was present in the HTTP [proxy-]authorization header. This is most likely a browser bug");
    } else if (*cleartext == '\0' && !basicConfig->blankpassword) {
	debug(29, 4) ("authenticateBasicDecodeAuth: Disallowing empty password,"
	    "user is '%s'\n", local_basic.username);
	local_basic.passwd = NULL;
	auth_user_request->message = xstrdup("Request denied because you provided an empty password. Users MUST have a password.");
    }
    /* special case: we have to free the strings for user and password
     * if we are not returning a filled out structure 
     */
    if (local_basic.passwd == NULL) {
	if (local_basic.username) {
	    /* log the username */
	    debug(29, 9) ("authBasicDecodeAuth: Creating new user for logging '%s'\n", local_basic.username);
	    /* new auth_user */
	    auth_user = authenticateAuthUserNew("basic");
	    /* new scheme data */
	    basic_auth = authBasicDataNew();
	    /* save the credentials */
	    basic_auth->username = local_basic.username;
	    /* link the scheme data in */
	    auth_user->scheme_data = basic_auth;
	    /* 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);
	}
	return;
    } else {
	local_basic.passwd = xstrndup(cleartext, USER_IDENT_SZ);
    }

    if (!basicConfig->casesensitive)
	Tolower(local_basic.username);
    /* now lookup and see if we have a matching auth_user structure in memory. */

    if ((auth_user = authBasicAuthUserFindUsername(local_basic.username)) == NULL) {
	/* the user doesn't exist in the username cache yet */
	debug(29, 9) ("authBasicDecodeAuth: Creating new user '%s'\n", local_basic.username);
	/* new auth_user */
	auth_user = authenticateAuthUserNew("basic");
	/* new scheme data */
	basic_auth = authBasicDataNew();
	/* save the credentials */
	basic_auth->username = local_basic.username;
	basic_auth->passwd = local_basic.passwd;
	/* link the scheme data in */
	auth_user->scheme_data = basic_auth;
	/* set the auth_user type */
	auth_user->auth_type = AUTH_BASIC;
	/* current time for timeouts */
	auth_user->expiretime = current_time.tv_sec;

	/* this auth_user struct is the 'lucky one' to get added to the username cache */
	/* the requests after this link to the auth_user */
	/* store user in hash */
	authenticateUserNameCacheAdd(auth_user);
    } else {
	debug(29, 9) ("authBasicDecodeAuth: Found user '%s' in the user cache as '%p'\n", local_basic.username, auth_user);
	xfree(local_basic.username);
	basic_auth = auth_user->scheme_data;
	if (strcmp(local_basic.passwd, basic_auth->passwd)) {
	    debug(29, 4) ("authBasicDecodeAuth: new password found. Updating in user master record and resetting auth state to unchecked\n");
	    basic_auth->flags.credentials_ok = 0;
	    xfree(basic_auth->passwd);
	    basic_auth->passwd = local_basic.passwd;
	} else
	    xfree(local_basic.passwd);
	if (basic_auth->flags.credentials_ok == 3) {
	    debug(29, 4) ("authBasicDecodeAuth: last attempt to authenticate this user failed, resetting auth state to unchecked\n");
	    basic_auth->flags.credentials_ok = 0;
	}
    }
    /* 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);
    return;
}
Exemplo n.º 5
0
static void
authenticateDigestDecodeAuth(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 recieved\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 recieved a qop option we didn't send */
	debug(29, 4) ("authenticateDigestDecode: Invalid qop option recieved\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 = '******'\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;
}