~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to modules/aaa/mod_authn_dbd.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
 
2
 * contributor license agreements.  See the NOTICE file distributed with
 
3
 * this work for additional information regarding copyright ownership.
 
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
 
5
 * (the "License"); you may not use this file except in compliance with
 
6
 * the License.  You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
#include "ap_provider.h"
 
18
#include "httpd.h"
 
19
#include "http_config.h"
 
20
#include "http_log.h"
 
21
#include "apr_dbd.h"
 
22
#include "mod_dbd.h"
 
23
#include "apr_strings.h"
 
24
#include "mod_auth.h"
 
25
#include "apr_md5.h"
 
26
 
 
27
module AP_MODULE_DECLARE_DATA authn_dbd_module;
 
28
 
 
29
typedef struct {
 
30
    const char *user;
 
31
    const char *realm;
 
32
} authn_dbd_conf;
 
33
typedef struct {
 
34
    const char *label;
 
35
    const char *query;
 
36
} authn_dbd_rec;
 
37
 
 
38
/* optional function - look it up once in post_config */
 
39
static ap_dbd_t *(*authn_dbd_acquire_fn)(request_rec*) = NULL;
 
40
static void (*authn_dbd_prepare_fn)(server_rec*, const char*, const char*) = NULL;
 
41
 
 
42
static void *authn_dbd_cr_conf(apr_pool_t *pool, char *dummy)
 
43
{
 
44
    authn_dbd_conf *ret = apr_pcalloc(pool, sizeof(authn_dbd_conf));
 
45
    return ret;
 
46
}
 
47
static void *authn_dbd_merge_conf(apr_pool_t *pool, void *BASE, void *ADD)
 
48
{
 
49
    authn_dbd_conf *add = ADD;
 
50
    authn_dbd_conf *base = BASE;
 
51
    authn_dbd_conf *ret = apr_palloc(pool, sizeof(authn_dbd_conf));
 
52
    ret->user = (add->user == NULL) ? base->user : add->user;
 
53
    ret->realm = (add->realm == NULL) ? base->realm : add->realm;
 
54
    return ret;
 
55
}
 
56
static const char *authn_dbd_prepare(cmd_parms *cmd, void *cfg, const char *query)
 
57
{
 
58
    static unsigned int label_num = 0;
 
59
    char *label;
 
60
 
 
61
    if (authn_dbd_prepare_fn == NULL) {
 
62
        authn_dbd_prepare_fn = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_prepare);
 
63
        if (authn_dbd_prepare_fn == NULL) {
 
64
            return "You must load mod_dbd to enable AuthDBD functions";
 
65
        }
 
66
        authn_dbd_acquire_fn = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_acquire);
 
67
    }
 
68
    label = apr_psprintf(cmd->pool, "authn_dbd_%d", ++label_num);
 
69
 
 
70
    authn_dbd_prepare_fn(cmd->server, query, label);
 
71
 
 
72
    /* save the label here for our own use */
 
73
    return ap_set_string_slot(cmd, cfg, label);
 
74
}
 
75
static const command_rec authn_dbd_cmds[] =
 
76
{
 
77
    AP_INIT_TAKE1("AuthDBDUserPWQuery", authn_dbd_prepare,
 
78
                  (void *)APR_OFFSETOF(authn_dbd_conf, user), ACCESS_CONF,
 
79
                  "Query used to fetch password for user"),
 
80
    AP_INIT_TAKE1("AuthDBDUserRealmQuery", authn_dbd_prepare,
 
81
                  (void *)APR_OFFSETOF(authn_dbd_conf, realm), ACCESS_CONF,
 
82
                  "Query used to fetch password for user+realm"),
 
83
    {NULL}
 
84
};
 
85
static authn_status authn_dbd_password(request_rec *r, const char *user,
 
86
                                       const char *password)
 
87
{
 
88
    apr_status_t rv;
 
89
    const char *dbd_password = NULL;
 
90
    apr_dbd_prepared_t *statement;
 
91
    apr_dbd_results_t *res = NULL;
 
92
    apr_dbd_row_t *row = NULL;
 
93
 
 
94
    authn_dbd_conf *conf = ap_get_module_config(r->per_dir_config,
 
95
                                                &authn_dbd_module);
 
96
    ap_dbd_t *dbd = authn_dbd_acquire_fn(r);
 
97
    if (dbd == NULL) {
 
98
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
99
                      "Error looking up %s in database", user);
 
100
        return AUTH_GENERAL_ERROR;
 
101
    }
 
102
 
 
103
    if (conf->user == NULL) {
 
104
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "No DBD Authn configured!");
 
105
        return AUTH_GENERAL_ERROR;
 
106
    }
 
107
 
 
108
    statement = apr_hash_get(dbd->prepared, conf->user, APR_HASH_KEY_STRING);
 
109
    if (statement == NULL) {
 
110
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "No DBD Authn configured!");
 
111
        return AUTH_GENERAL_ERROR;
 
112
    }
 
113
    if (apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, statement,
 
114
                              0, user, NULL) != 0) {
 
115
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
116
                      "Error looking up %s in database", user);
 
117
        return AUTH_GENERAL_ERROR;
 
118
    }
 
119
    for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
 
120
         rv != -1;
 
121
         rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
 
122
        if (rv != 0) {
 
123
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
 
124
                      "Error looking up %s in database", user);
 
125
            return AUTH_GENERAL_ERROR;
 
126
        }
 
127
        if (dbd_password == NULL) {
 
128
            dbd_password = apr_dbd_get_entry(dbd->driver, row, 0);
 
129
        }
 
130
        /* we can't break out here or row won't get cleaned up */
 
131
    }
 
132
 
 
133
    if (!dbd_password) {
 
134
        return AUTH_USER_NOT_FOUND;
 
135
    }
 
136
 
 
137
    rv = apr_password_validate(password, dbd_password);
 
138
 
 
139
    if (rv != APR_SUCCESS) {
 
140
        return AUTH_DENIED;
 
141
    }
 
142
 
 
143
    return AUTH_GRANTED;
 
144
}
 
145
static authn_status authn_dbd_realm(request_rec *r, const char *user,
 
146
                                    const char *realm, char **rethash)
 
147
{
 
148
    apr_status_t rv;
 
149
    const char *dbd_hash = NULL;
 
150
    apr_dbd_prepared_t *statement;
 
151
    apr_dbd_results_t *res = NULL;
 
152
    apr_dbd_row_t *row = NULL;
 
153
 
 
154
    authn_dbd_conf *conf = ap_get_module_config(r->per_dir_config,
 
155
                                                &authn_dbd_module);
 
156
    ap_dbd_t *dbd = authn_dbd_acquire_fn(r);
 
157
    if (dbd == NULL) {
 
158
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
159
                      "Error looking up %s in database", user);
 
160
        return AUTH_GENERAL_ERROR;
 
161
    }
 
162
    if (conf->realm == NULL) {
 
163
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "No DBD Authn configured!");
 
164
        return AUTH_GENERAL_ERROR;
 
165
    }
 
166
    statement = apr_hash_get(dbd->prepared, conf->realm, APR_HASH_KEY_STRING);
 
167
    if (statement == NULL) {
 
168
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "No DBD Authn configured!");
 
169
        return AUTH_GENERAL_ERROR;
 
170
    }
 
171
    if (apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, statement,
 
172
                              0, user, realm, NULL) != 0) {
 
173
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
174
                      "Error looking up %s:%s in database", user, realm);
 
175
        return AUTH_GENERAL_ERROR;
 
176
    }
 
177
    for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
 
178
         rv != -1;
 
179
         rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
 
180
        if (rv != 0) {
 
181
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
 
182
                      "Error looking up %s in database", user);
 
183
            return AUTH_GENERAL_ERROR;
 
184
        }
 
185
        if (dbd_hash == NULL) {
 
186
            dbd_hash = apr_dbd_get_entry(dbd->driver, row, 0);
 
187
        }
 
188
        /* we can't break out here or row won't get cleaned up */
 
189
    }
 
190
 
 
191
    if (!dbd_hash) {
 
192
        return AUTH_USER_NOT_FOUND;
 
193
    }
 
194
 
 
195
    *rethash = apr_pstrdup(r->pool, dbd_hash);
 
196
    return AUTH_USER_FOUND;
 
197
}
 
198
static void authn_dbd_hooks(apr_pool_t *p)
 
199
{
 
200
    static const authn_provider authn_dbd_provider = {
 
201
        &authn_dbd_password,
 
202
        &authn_dbd_realm
 
203
    };
 
204
 
 
205
    ap_register_provider(p, AUTHN_PROVIDER_GROUP, "dbd", "0", &authn_dbd_provider);
 
206
}
 
207
module AP_MODULE_DECLARE_DATA authn_dbd_module =
 
208
{
 
209
    STANDARD20_MODULE_STUFF,
 
210
    authn_dbd_cr_conf,
 
211
    authn_dbd_merge_conf,
 
212
    NULL,
 
213
    NULL,
 
214
    authn_dbd_cmds,
 
215
    authn_dbd_hooks
 
216
};