~ubuntu-branches/ubuntu/trusty/serf/trusty-proposed

« back to all changes in this revision

Viewing changes to auth/auth_basic.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter Samuelson
  • Date: 2011-06-03 03:18:07 UTC
  • mto: (9.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 10.
  • Revision ID: james.westby@ubuntu.com-20110603031807-6y8ky58ac0q82etq
Tags: upstream-0.7.2
ImportĀ upstreamĀ versionĀ 0.7.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2009 Justin Erenkrantz and Greg Stein
 
2
 *
 
3
 * Licensed under the Apache License, Version 2.0 (the "License");
 
4
 * you may not use this file except in compliance with the License.
 
5
 * You may obtain a copy of the License at
 
6
 *
 
7
 *     http://www.apache.org/licenses/LICENSE-2.0
 
8
 *
 
9
 * Unless required by applicable law or agreed to in writing, software
 
10
 * distributed under the License is distributed on an "AS IS" BASIS,
 
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
12
 * See the License for the specific language governing permissions and
 
13
 * limitations under the License.
 
14
 */
 
15
 
 
16
/*** Basic authentication ***/
 
17
 
 
18
#include <serf.h>
 
19
#include <serf_private.h>
 
20
#include <auth/auth.h>
 
21
 
 
22
#include <apr.h>
 
23
#include <apr_base64.h>
 
24
#include <apr_strings.h>
 
25
 
 
26
typedef struct basic_authn_info_t {
 
27
    const char *header;
 
28
    const char *value;
 
29
} basic_authn_info_t;
 
30
 
 
31
apr_status_t
 
32
serf__handle_basic_auth(int code,
 
33
                        serf_request_t *request,
 
34
                        serf_bucket_t *response,
 
35
                        const char *auth_hdr,
 
36
                        const char *auth_attr,
 
37
                        void *baton,
 
38
                        apr_pool_t *pool)
 
39
{
 
40
    const char *tmp;
 
41
    apr_size_t tmp_len;
 
42
    serf_connection_t *conn = request->conn;
 
43
    serf_context_t *ctx = conn->ctx;
 
44
    serf__authn_info_t *authn_info = (code == 401) ? &ctx->authn_info :
 
45
        &ctx->proxy_authn_info;
 
46
    basic_authn_info_t *basic_info = authn_info->baton;
 
47
    apr_status_t status;
 
48
    apr_pool_t *cred_pool;
 
49
    char *username, *password;
 
50
 
 
51
    /* Can't do Basic authentication if there's no callback to get
 
52
       username & password. */
 
53
    if (!ctx->cred_cb) {
 
54
        return SERF_ERROR_AUTHN_FAILED;
 
55
    }
 
56
 
 
57
    if (!authn_info->realm) {
 
58
        char *realm_name = NULL;
 
59
        const char *eq = strchr(auth_attr, '=');
 
60
 
 
61
        if (eq && strncasecmp(auth_attr, "realm", 5) == 0) {
 
62
            realm_name = apr_pstrdup(pool, eq + 1);
 
63
            if (realm_name[0] == '\"') {
 
64
                apr_size_t realm_len;
 
65
 
 
66
                realm_len = strlen(realm_name);
 
67
                if (realm_name[realm_len - 1] == '\"') {
 
68
                    realm_name[realm_len - 1] = '\0';
 
69
                    realm_name++;
 
70
                }
 
71
            }
 
72
        }
 
73
 
 
74
        if (!realm_name) {
 
75
            return SERF_ERROR_AUTHN_MISSING_ATTRIBUTE;
 
76
        }
 
77
 
 
78
        authn_info->realm = apr_psprintf(conn->pool, "<%s://%s:%d> %s",
 
79
                                         conn->host_info.scheme,
 
80
                                         conn->host_info.hostname,
 
81
                                         conn->host_info.port,
 
82
                                         realm_name);
 
83
    }
 
84
 
 
85
    /* Ask the application for credentials */
 
86
    apr_pool_create(&cred_pool, pool);
 
87
    status = (*ctx->cred_cb)(&username, &password, request, baton,
 
88
                             code, authn_info->scheme->name,
 
89
                             authn_info->realm, cred_pool);
 
90
    if (status) {
 
91
        apr_pool_destroy(cred_pool);
 
92
        return status;
 
93
    }
 
94
 
 
95
    tmp = apr_pstrcat(conn->pool, username, ":", password, NULL);
 
96
    tmp_len = strlen(tmp);
 
97
    apr_pool_destroy(cred_pool);
 
98
 
 
99
    serf__encode_auth_header(&basic_info->value,
 
100
                             authn_info->scheme->name,
 
101
                             tmp, tmp_len, pool);
 
102
    basic_info->header = (code == 401) ? "Authorization" : "Proxy-Authorization";
 
103
 
 
104
    return APR_SUCCESS;
 
105
}
 
106
 
 
107
/* For Basic authentication we expect all authn info to be the same for all
 
108
   connections in the context (same realm, username, password). Therefore we
 
109
   can keep the header value in the context instead of per connection. */
 
110
apr_status_t
 
111
serf__init_basic(int code,
 
112
                 serf_context_t *ctx,
 
113
                 apr_pool_t *pool)
 
114
{
 
115
    if (code == 401) {
 
116
        ctx->authn_info.baton = apr_pcalloc(pool, sizeof(basic_authn_info_t));
 
117
    } else {
 
118
        ctx->proxy_authn_info.baton = apr_pcalloc(pool, sizeof(basic_authn_info_t));
 
119
    }
 
120
 
 
121
    return APR_SUCCESS;
 
122
}
 
123
 
 
124
apr_status_t
 
125
serf__init_basic_connection(int code,
 
126
                            serf_connection_t *conn,
 
127
                            apr_pool_t *pool)
 
128
{
 
129
    return APR_SUCCESS;
 
130
}
 
131
 
 
132
apr_status_t
 
133
serf__setup_request_basic_auth(int code,
 
134
                               serf_connection_t *conn,
 
135
                               const char *method,
 
136
                               const char *uri,
 
137
                               serf_bucket_t *hdrs_bkt)
 
138
{
 
139
    serf_context_t *ctx = conn->ctx;
 
140
    basic_authn_info_t *authn_info;
 
141
 
 
142
    if (code == 401) {
 
143
        authn_info = ctx->authn_info.baton;
 
144
    } else {
 
145
        authn_info = ctx->proxy_authn_info.baton;
 
146
    }
 
147
 
 
148
    if (authn_info && authn_info->header && authn_info->value) {
 
149
        serf_bucket_headers_setn(hdrs_bkt, authn_info->header,
 
150
                                 authn_info->value);
 
151
        return APR_SUCCESS;
 
152
    }
 
153
 
 
154
    return SERF_ERROR_AUTHN_FAILED;
 
155
}