in auth/auth.c [79:170]
static int handle_auth_headers(int code,
apr_hash_t *hdrs,
serf_request_t *request,
serf_bucket_t *response,
apr_pool_t *pool)
{
int scheme_idx;
serf_connection_t *conn = request->conn;
serf_context_t *ctx = conn->ctx;
apr_status_t status;
status = SERF_ERROR_AUTHN_NOT_SUPPORTED;
/* Find the matching authentication handler.
Note that we don't reuse the auth scheme stored in the context,
as that may have changed. (ex. fallback from ntlm to basic.) */
for (scheme_idx = 0; serf_authn_schemes[scheme_idx]; ++scheme_idx) {
const char *auth_hdr;
serf__auth_handler_func_t handler;
serf__authn_info_t *authn_info;
const serf__authn_scheme_t *scheme = serf_authn_schemes[scheme_idx];
if (! (ctx->authn_types & scheme->type))
continue;
serf__log(LOGLVL_INFO, LOGCOMP_AUTHN, __FILE__, conn->config,
"Client supports: %s\n", scheme->name);
auth_hdr = apr_hash_get(hdrs, scheme->key, APR_HASH_KEY_STRING);
if (!auth_hdr)
continue;
if (code == 401) {
authn_info = serf__get_authn_info_for_server(conn);
} else {
authn_info = &ctx->proxy_authn_info;
}
if (authn_info->failed_authn_types & scheme->type) {
/* Skip this authn type since we already tried it before. */
continue;
}
/* Found a matching scheme */
status = APR_SUCCESS;
handler = scheme->handle_func;
serf__log(LOGLVL_INFO, LOGCOMP_AUTHN, __FILE__, conn->config,
"... matched: %s\n", scheme->name);
/* If this is the first time we use this scheme on this connection,
make sure to initialize the authentication handler first. */
if (authn_info->scheme != scheme) {
status = scheme->init_conn_func(scheme, code, conn,
conn->pool);
if (!status)
authn_info->scheme = scheme;
else
authn_info->scheme = NULL;
}
if (!status) {
const char *auth_attr = strchr(auth_hdr, ' ');
if (auth_attr) {
auth_attr++;
}
status = handler(scheme, code, request, response,
auth_hdr, auth_attr, ctx->pool);
}
if (status == APR_SUCCESS)
break;
/* No success authenticating with this scheme, try the next.
If no more authn schemes are found the status of this scheme will be
returned.
*/
serf__log(LOGLVL_INFO, LOGCOMP_AUTHN, __FILE__, conn->config,
"%s authentication failed.\n", scheme->name);
/* Clear per-request auth_baton when switching to next auth scheme. */
request->auth_baton = NULL;
/* Remember failed auth types to skip it in future. */
authn_info->failed_authn_types |= scheme->type;
}
return status;
}