Esempio n. 1
0
auth_acl_t
authenticateTryToAuthenticateAndSetAuthUser(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr)
{
    /* If we have already been called, return the cached value */
    auth_user_request_t *t = authTryGetUser(auth_user_request, conn, request);
    auth_acl_t result;
    if (t && t->lastReply != AUTH_ACL_CANNOT_AUTHENTICATE
	&& t->lastReply != AUTH_ACL_HELPER) {
	if (!*auth_user_request) {
	    *auth_user_request = t;
	    authenticateAuthUserRequestLock(*auth_user_request);
	}
	if (!request->auth_user_request) {
	    request->auth_user_request = t;
	    authenticateAuthUserRequestLock(request->auth_user_request);
	}
	return t->lastReply;
    }
    /* ok, call the actual authenticator routine. */
    result = authenticateAuthenticate(auth_user_request, headertype, request, conn, src_addr);
    t = authTryGetUser(auth_user_request, conn, request);
    if (t && result != AUTH_ACL_CANNOT_AUTHENTICATE &&
	result != AUTH_ACL_HELPER) {
	t->lastReply = result;
    }
    return result;
}
Esempio n. 2
0
/* send the initial data to a digest authenticator module */
static void
authenticateDigestStart(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);
}
Esempio n. 3
0
static void
authenticateAuthUserRequestLinkIp(auth_user_request_t * auth_user_request, const struct in_addr ipaddr, request_t * request)
{
	auth_user_request_ip_hash_t *hash_entry;

	if (!Config.authenticateIpShortcircuitTTL)
		return;

#ifdef CC_FRAMEWORK
	acl_access * acl = cc_get_acl_access_by_token_and_host("authenticate_ip_shortcircuit_access",request->host);
	if (acl && !aclCheckFastRequest(acl, request))
#else
	if (Config.accessList.auth_ip_shortcircuit && !aclCheckFastRequest(Config.accessList.auth_ip_shortcircuit, request))
#endif
		return;

	if (!auth_user_request_ip_hash)
	{
		auth_user_request_ip_hash = hash_create((HASHCMP *) cmp_in_addr, 7921, hash_in_addr);
		auth_user_request_ip_pool = memPoolCreate("auth_user_request_ip_hash_t", sizeof(auth_user_request_ip_hash_t));
	}
	authenticateAuthUserRequestUnlinkIp(ipaddr);

	hash_entry = memPoolAlloc(auth_user_request_ip_pool);
	hash_entry->ipaddr = ipaddr;
	hash_entry->hash.key = &hash_entry->ipaddr;
	hash_entry->auth_user_request = auth_user_request;
	authenticateAuthUserRequestLock(hash_entry->auth_user_request);
	hash_entry->last_seen = squid_curtime;
	hash_join(auth_user_request_ip_hash, &hash_entry->hash);
}
Esempio n. 4
0
/* Get Auth User: Return a filled out auth_user structure for the given
 * Proxy Auth (or Auth) header. It may be a cached Auth User or a new
 * Unauthenticated structure. The structure is given an inital lock here.
 */
static auth_user_request_t *
authenticateGetAuthUser(const char *proxy_auth)
{
    auth_user_request_t *auth_user_request = authenticateAuthUserRequestNew();
    /* and lock for the callers instance */
    authenticateAuthUserRequestLock(auth_user_request);
    /* The scheme is allowed to provide a cached auth_user or a new one */
    authenticateDecodeAuth(proxy_auth, auth_user_request);
    return auth_user_request;
}
Esempio n. 5
0
/* send the initial data to a basic authenticator module */
static void
authenticateBasicStart(auth_user_request_t * auth_user_request, RH * handler, void *data)
{
    authenticateStateData *r = NULL;
    char buf[8192];
    char user[1024], pass[1024];
    basic_data *basic_auth;
    assert(auth_user_request);
    assert(handler);
    assert(auth_user_request->auth_user->auth_type == AUTH_BASIC);
    assert(auth_user_request->auth_user->scheme_data != NULL);
    basic_auth = auth_user_request->auth_user->scheme_data;
    debug(29, 9) ("authenticateStart: '%s:%s'\n", basic_auth->username,
	basic_auth->passwd);
    if (basicConfig->authenticate == NULL) {
	handler(data, NULL);
	return;
    }
    /* check to see if the auth_user already has a request outstanding */
    if (basic_auth->flags.credentials_ok == 2) {
	/* there is a request with the same credentials already being verified */
	auth_basic_queue_node *node;
	node = xmalloc(sizeof(auth_basic_queue_node));
	assert(node);
	/* save the details */
	node->next = basic_auth->auth_queue;
	basic_auth->auth_queue = node;
	node->handler = handler;
	node->data = data;
	cbdataLock(data);
	return;
    } else {
	r = cbdataAlloc(authenticateStateData);
	r->handler = handler;
	cbdataLock(data);
	r->data = data;
	r->auth_user_request = auth_user_request;
	authenticateAuthUserRequestLock(r->auth_user_request);
	/* mark the user as haveing verification in progress */
	basic_auth->flags.credentials_ok = 2;
	if (basicConfig->utf8) {
	    latin1_to_utf8(user, sizeof(user), basic_auth->username);
	    latin1_to_utf8(pass, sizeof(pass), basic_auth->passwd);
	    xstrncpy(user, rfc1738_escape(user), sizeof(user));
	    xstrncpy(pass, rfc1738_escape(pass), sizeof(pass));
	} else {
	    xstrncpy(user, rfc1738_escape(basic_auth->username), sizeof(user));
	    xstrncpy(pass, rfc1738_escape(basic_auth->passwd), sizeof(pass));
	}
	snprintf(buf, sizeof(buf), "%s %s\n", user, pass);
	helperSubmit(basicauthenticators, buf, authenticateBasicHandleReply, r);
    }
}
Esempio n. 6
0
static inline void modify_request(clientHttpRequest * http)
{
	debug(97, 3)("modify_request: start, uri=[%s]\n", http->uri);
	request_t* old_request = http->request;
	request_t* new_request = urlParse(old_request->method, http->uri);
	safe_free(http->uri);

	if (new_request)
	{
		safe_free(http->uri);
		http->uri = xstrdup(urlCanonical(new_request));
		if(!http->log_uri)
			http->log_uri = xstrdup(urlCanonicalClean(old_request));
		new_request->http_ver = old_request->http_ver;
		httpHeaderAppend(&new_request->header, &old_request->header);
		new_request->client_addr = old_request->client_addr;
		new_request->client_port = old_request->client_port;
#if FOLLOW_X_FORWARDED_FOR
		new_request->indirect_client_addr = old_request->indirect_client_addr;
#endif /* FOLLOW_X_FORWARDED_FOR */
		new_request->my_addr = old_request->my_addr;
		new_request->my_port = old_request->my_port;
		new_request->flags = old_request->flags;
		new_request->flags.redirected = 1;
		if (old_request->auth_user_request)
		{
			new_request->auth_user_request = old_request->auth_user_request;
			authenticateAuthUserRequestLock(new_request->auth_user_request);
		}
		if (old_request->body_reader)
		{
			new_request->body_reader = old_request->body_reader;
			new_request->body_reader_data = old_request->body_reader_data;
			old_request->body_reader = NULL;
			old_request->body_reader_data = NULL;
		}
		new_request->content_length = old_request->content_length;
		if (strBuf(old_request->extacl_log))
			new_request->extacl_log = stringDup(&old_request->extacl_log);
		if (old_request->extacl_user)
			new_request->extacl_user = xstrdup(old_request->extacl_user);
		if (old_request->extacl_passwd)
			new_request->extacl_passwd = xstrdup(old_request->extacl_passwd);
		if(old_request->cc_request_private_data)
		{
			new_request->cc_request_private_data = old_request->cc_request_private_data;
			old_request->cc_request_private_data = NULL;
		}
		requestUnlink(old_request);
		http->request = requestLink(new_request);
	}
}
Esempio n. 7
0
static auth_user_request_t *
authTryGetUser(auth_user_request_t ** auth_user_request, ConnStateData * conn, request_t * request)
{
	if (*auth_user_request)
		return *auth_user_request;
	else if (request && request->auth_user_request)
		return request->auth_user_request;
	else if (conn && conn->auth_user_request)
		return conn->auth_user_request;
	else
	{
		request->auth_user_request = authenticateAuthUserRequestFindByIp(request->client_addr);
		if (request->auth_user_request)
			authenticateAuthUserRequestLock(request->auth_user_request);
		return request->auth_user_request;
	}
}
Esempio n. 8
0
/* send the initial data to a stateful negotiate authenticator module */
static void
authenticateNegotiateStart(auth_user_request_t * auth_user_request, RH * handler, void *data)
{
    authenticateStateData *r = NULL;
    char buf[MAX_AUTHTOKEN_LEN];
    char *sent_string = NULL;
    negotiate_user_t *negotiate_user;
    negotiate_request_t *negotiate_request;
    auth_user_t *auth_user;

    assert(auth_user_request);
    auth_user = auth_user_request->auth_user;
    negotiate_user = auth_user->scheme_data;
    negotiate_request = auth_user_request->scheme_data;
    assert(negotiate_user);
    assert(negotiate_request);
    assert(handler);
    assert(data);
    assert(auth_user->auth_type == AUTH_NEGOTIATE);
    debug(29, 9) ("authenticateNegotiateStart: auth state '%d'\n", negotiate_request->auth_state);
    sent_string = negotiate_request->client_blob;

    debug(29, 9) ("authenticateNegotiateStart: state '%d'\n", negotiate_request->auth_state);
    debug(29, 9) ("authenticateNegotiateStart: '%s'\n", sent_string);
    if (negotiateConfig->authenticate == NULL) {
	debug(29, 0) ("authenticateNegotiateStart: no Negotiate program specified:'%s'\n", sent_string);
	handler(data, NULL);
	return;
    }
    /* Send blob to helper */
    r = cbdataAlloc(authenticateStateData);
    r->handler = handler;
    cbdataLock(data);
    r->data = data;
    r->auth_user_request = auth_user_request;
    authenticateAuthUserRequestLock(r->auth_user_request);
    if (negotiate_request->auth_state == AUTHENTICATE_STATE_INITIAL) {
	snprintf(buf, MAX_AUTHTOKEN_LEN, "YR %s\n", sent_string);
    } else {
	snprintf(buf, MAX_AUTHTOKEN_LEN, "KK %s\n", sent_string);
    }
    negotiate_request->waiting = 1;
    safe_free(negotiate_request->client_blob);
    helperStatefulSubmit(negotiateauthenticators, buf, authenticateNegotiateHandleReply, r, negotiate_request->authserver);
}
Esempio n. 9
0
/* returns one of
 * AUTH_ACL_CHALLENGE,
 * AUTH_ACL_HELPER,
 * AUTH_ACL_CANNOT_AUTHENTICATE,
 * AUTH_AUTHENTICATED
 *
 * How to use: In your proxy-auth dependent acl code, use the following 
 * construct:
 * int rv;
 * if ((rv = AuthenticateAuthenticate()) != AUTH_AUTHENTICATED)
 *   return rv;
 * 
 * when this code is reached, the request/connection is authenticated.
 *
 * if you have non-acl code, but want to force authentication, you need a 
 * callback mechanism like the acl testing routines that will send a 40[1|7] to
 * the client when rv==AUTH_ACL_CHALLENGE, and will communicate with 
 * the authenticateStart routine for rv==AUTH_ACL_HELPER
 */
auth_acl_t
authenticateAuthenticate(auth_user_request_t ** auth_user_request, http_hdr_type headertype, request_t * request, ConnStateData * conn, struct in_addr src_addr)
{
    const char *proxy_auth;
    assert(headertype != 0);

    proxy_auth = httpHeaderGetStr(&request->header, headertype);

    /*
     * a note on proxy_auth logix here:
     * proxy_auth==NULL -> unauthenticated request || already
     * authenticated connection so we test for an authenticated
     * connection when we recieve no authentication header.
     */
    if (((proxy_auth == NULL) && (!authenticateUserAuthenticated(authTryGetUser(auth_user_request, conn, request))))
	|| (conn && conn->auth_type == AUTH_BROKEN)) {
	/* no header or authentication failed/got corrupted - restart */
	if (conn)
	    conn->auth_type = AUTH_UNKNOWN;
	debug(28, 4) ("authenticateAuthenticate: broken auth or no proxy_auth header. Requesting auth header.\n");
	/* something wrong with the AUTH credentials. Force a new attempt */
	if (conn && conn->auth_user_request) {
	    authenticateAuthUserRequestUnlock(conn->auth_user_request);
	    conn->auth_user_request = NULL;
	}
	if (*auth_user_request) {
	    /* unlock the ACL lock */
	    authenticateAuthUserRequestUnlock(*auth_user_request);
	    *auth_user_request = NULL;
	}
	return AUTH_ACL_CHALLENGE;
    }
#if 0
    /* 
     * Is this an already authenticated connection with a new auth header?
     * No check for function required in the if: its compulsory for conn based 
     * auth modules
     */
    if (proxy_auth && conn && conn->auth_user_request &&
	authenticateUserAuthenticated(conn->auth_user_request) &&
	strcmp(proxy_auth, authscheme_list[conn->auth_user_request->auth_user->auth_module - 1].authConnLastHeader(conn->auth_user_request))) {
	debug(28, 2) ("authenticateAuthenticate: DUPLICATE AUTH - authentication header on already authenticated connection!. AU %p, Current user '%s' proxy_auth %s\n", conn->auth_user_request, authenticateUserRequestUsername(conn->auth_user_request), proxy_auth);
	/* remove this request struct - the link is already authed and it can't be to 
	 * reauth.
	 */

	/* This should _only_ ever occur on the first pass through 
	 * authenticateAuthenticate 
	 */
	assert(*auth_user_request == NULL);
	/* unlock the conn lock on the auth_user_request */
	authenticateAuthUserRequestUnlock(conn->auth_user_request);
	/* mark the conn as non-authed. */
	conn->auth_user_request = NULL;
	/* Set the connection auth type */
	conn->auth_type = AUTH_UNKNOWN;
    }
#endif
    /* we have a proxy auth header and as far as we know this connection has
     * not had bungled connection oriented authentication happen on it. */
    debug(28, 9) ("authenticateAuthenticate: header %s.\n", proxy_auth ? proxy_auth : NULL);
    if (*auth_user_request == NULL) {
	debug(28, 9) ("authenticateAuthenticate: This is a new checklist test on FD:%d\n",
	    conn ? conn->fd : -1);
	if ((!request->auth_user_request)
	    && (!conn || conn->auth_type == AUTH_UNKNOWN)) {
	    /* beginning of a new request check */
	    debug(28, 4) ("authenticateAuthenticate: no connection authentication type\n");
	    if (!authenticateValidateUser(*auth_user_request =
		    authenticateGetAuthUser(proxy_auth))) {
		/* the decode might have left a username for logging, or a message to
		 * the user */
		if (authenticateUserRequestUsername(*auth_user_request)) {
		    /* lock the user for the request structure link */
		    authenticateAuthUserRequestLock(*auth_user_request);
		    request->auth_user_request = *auth_user_request;
		}
		/* unlock the ACL reference granted by ...GetAuthUser. */
		authenticateAuthUserRequestUnlock(*auth_user_request);
		*auth_user_request = NULL;
		return AUTH_ACL_CHALLENGE;
	    }
	    /* the user_request comes prelocked for the caller to GetAuthUser (us) */
	} else if (request->auth_user_request) {
	    *auth_user_request = request->auth_user_request;
	    /* lock the user request for this ACL processing */
	    authenticateAuthUserRequestLock(*auth_user_request);
	} else {
	    assert(conn);
	    if (conn->auth_user_request != NULL) {
		*auth_user_request = conn->auth_user_request;
		/* lock the user request for this ACL processing */
		authenticateAuthUserRequestLock(*auth_user_request);
	    } else {
		/* failed connection based authentication */
		debug(28, 4) ("authenticateAuthenticate: Auth user request %p conn-auth user request %p conn type %d authentication failed.\n",
		    *auth_user_request, conn->auth_user_request, conn->auth_type);
		authenticateAuthUserRequestUnlock(*auth_user_request);
		*auth_user_request = NULL;
		return AUTH_ACL_CHALLENGE;
	    }
	}
    }
    if (!authenticateUserAuthenticated(*auth_user_request)) {
	/* User not logged in. Log them in */
	authenticateAuthenticateUser(*auth_user_request, request,
	    conn, headertype);
	switch (authenticateDirection(*auth_user_request)) {
	case 1:
	    if (!request->auth_user_request) {
		/* lock the user for the request structure link */
		authenticateAuthUserRequestLock(*auth_user_request);
		request->auth_user_request = *auth_user_request;
	    }
	    /* fallthrough to -2 */
	case -2:
	    /* this ACL check is finished. Unlock. */
	    authenticateAuthUserRequestUnlock(*auth_user_request);
	    *auth_user_request = NULL;
	    return AUTH_ACL_CHALLENGE;
	case -1:
	    /* we are partway through authentication within squid,
	     * the *auth_user_request variables stores the auth_user_request
	     * for the callback to here - Do not Unlock */
	    return AUTH_ACL_HELPER;
	}
	/* on 0 the authentication is finished - fallthrough */
	/* See if user authentication failed for some reason */
	if (!authenticateUserAuthenticated(*auth_user_request)) {
	    if ((authenticateUserRequestUsername(*auth_user_request))) {
		if (!request->auth_user_request) {
		    /* lock the user for the request structure link */
		    authenticateAuthUserRequestLock(*auth_user_request);
		    request->auth_user_request = *auth_user_request;
		}
	    }
	    /* this ACL check is finished. Unlock. */
	    authenticateAuthUserRequestUnlock(*auth_user_request);
	    *auth_user_request = NULL;
	    return AUTH_ACL_CHALLENGE;
	}
    }
    /* copy username to request for logging on client-side */
    /* the credentials are correct at this point */
    if (!request->auth_user_request) {
	/* lock the user for the request structure link */
	authenticateAuthUserRequestLock(*auth_user_request);
	request->auth_user_request = *auth_user_request;
	authenticateAuthUserRequestSetIp(*auth_user_request, src_addr);
    }
    /* Unlock the request - we've authenticated it */
    authenticateAuthUserRequestUnlock(*auth_user_request);
    *auth_user_request = NULL;
    return AUTH_AUTHENTICATED;
}
Esempio n. 10
0
static void
authenticateNegotiateAuthenticateUser(auth_user_request_t * auth_user_request, request_t * request, ConnStateData * conn, http_hdr_type type)
{
    const char *proxy_auth, *blob;
    auth_user_t *auth_user;
    negotiate_request_t *negotiate_request;

    auth_user = auth_user_request->auth_user;
    assert(auth_user);
    assert(auth_user->auth_type == AUTH_NEGOTIATE);
    assert(auth_user->scheme_data != NULL);
    assert(auth_user_request->scheme_data != NULL);
    negotiate_request = auth_user_request->scheme_data;
    /* Check that we are in the client side, where we can generate
     * auth challenges */
    if (!conn) {
	negotiate_request->auth_state = AUTHENTICATE_STATE_FAILED;
	debug(29, 1) ("authenticateNegotiateAuthenticateUser: attempt to perform authentication without a connection!\n");
	return;
    }
    if (negotiate_request->waiting) {
	debug(29, 1) ("authenticateNegotiateAuthenticateUser: waiting for helper reply!\n");
	return;
    }
    if (negotiate_request->server_blob) {
	debug(29, 2) ("authenticateNegotiateAuthenticateUser: need to challenge client '%s'!\n", negotiate_request->server_blob);
	return;
    }
    /* get header */
    proxy_auth = httpHeaderGetStr(&request->header, type);
    blob = proxy_auth;
    while (xisspace(*blob) && *blob)
	blob++;
    while (!xisspace(*blob) && *blob)
	blob++;
    while (xisspace(*blob) && *blob)
	blob++;

    switch (negotiate_request->auth_state) {
    case AUTHENTICATE_STATE_NONE:
	/* we've received a negotiate request. pass to a helper */
	debug(29, 9) ("authenticateNegotiateAuthenticateUser: auth state negotiate none. %s\n", proxy_auth);
	negotiate_request->auth_state = AUTHENTICATE_STATE_INITIAL;
	safe_free(negotiate_request->client_blob);
	negotiate_request->client_blob = xstrdup(blob);
	conn->auth_type = AUTH_NEGOTIATE;
	conn->auth_user_request = auth_user_request;
	negotiate_request->conn = conn;
	/* and lock for the connection duration */
	debug(29, 9) ("authenticateNegotiateAuthenticateUser: Locking auth_user from the connection.\n");
	authenticateAuthUserRequestLock(auth_user_request);
	negotiate_request->request = requestLink(request);
	return;
	break;
    case AUTHENTICATE_STATE_INITIAL:
	debug(29, 1) ("authenticateNegotiateAuthenticateUser: need to ask helper!\n");
	return;
	break;
    case AUTHENTICATE_STATE_NEGOTIATE:
	/* we should have received a blob from the clien. pass it to the same 
	 * helper process */
	debug(29, 9) ("authenticateNegotiateAuthenticateUser: auth state challenge with header %s.\n", proxy_auth);
	/* do a cache lookup here. If it matches it's a successful negotiate 
	 * challenge - release the helper and use the existing auth_user 
	 * details. */
	safe_free(negotiate_request->client_blob);
	negotiate_request->client_blob = xstrdup(blob);
	if (negotiate_request->request)
	    requestUnlink(negotiate_request->request);
	negotiate_request->request = requestLink(request);
	return;
	break;
    case AUTHENTICATE_STATE_DONE:
	fatal("authenticateNegotiateAuthenticateUser: unexpect auth state DONE! Report a bug to the squid developers.\n");
	break;
    case AUTHENTICATE_STATE_FAILED:
	/* we've failed somewhere in authentication */
	debug(29, 9) ("authenticateNegotiateAuthenticateUser: auth state negotiate failed. %s\n", proxy_auth);
	return;
    }
    return;
}