static int handle_auth_headers()

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;
}