Apache HTTPD
mod_authn_dbd.c
Go to the documentation of this file.
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 "http_request.h"
22#include "apr_lib.h"
23#include "apr_dbd.h"
24#include "mod_dbd.h"
25#include "apr_strings.h"
26#include "mod_auth.h"
27#include "apr_md5.h"
28#include "apu_version.h"
29
30module AP_MODULE_DECLARE_DATA authn_dbd_module;
31
32typedef struct {
33 const char *user;
34 const char *realm;
36
37/* optional function - look it up once in post_config */
38static ap_dbd_t *(*authn_dbd_acquire_fn)(request_rec*) = NULL;
39static void (*authn_dbd_prepare_fn)(server_rec*, const char*, const char*) = NULL;
41#define AUTHN_CACHE_STORE(r,user,realm,data) \
42 if (authn_cache_store != NULL) \
43 authn_cache_store((r), "dbd", (user), (realm), (data))
44
46{
48 return ret;
49}
50
51static void *authn_dbd_merge_conf(apr_pool_t *pool, void *BASE, void *ADD)
52{
53 authn_dbd_conf *add = ADD;
56 ret->user = (add->user == NULL) ? base->user : add->user;
57 ret->realm = (add->realm == NULL) ? base->realm : add->realm;
58 return ret;
59}
60
61static const char *authn_dbd_prepare(cmd_parms *cmd, void *cfg, const char *query)
62{
63 static unsigned int label_num = 0;
64 char *label;
66 if (err)
67 return err;
68
72 return "You must load mod_dbd to enable AuthDBD functions";
73 }
75 }
76 label = apr_psprintf(cmd->pool, "authn_dbd_%d", ++label_num);
77
79
80 /* save the label here for our own use */
81 return ap_set_string_slot(cmd, cfg, label);
82}
83
85{
86 AP_INIT_TAKE1("AuthDBDUserPWQuery", authn_dbd_prepare,
88 "Query used to fetch password for user"),
89 AP_INIT_TAKE1("AuthDBDUserRealmQuery", authn_dbd_prepare,
91 "Query used to fetch password for user+realm"),
92 {NULL}
93};
94
95static authn_status authn_dbd_password(request_rec *r, const char *user,
96 const char *password)
97{
98 apr_status_t rv;
99 const char *dbd_password = NULL;
103 int ret;
104
106 &authn_dbd_module);
108 if (dbd == NULL) {
110 "Failed to acquire database connection to look up "
111 "user '%s'", user);
112 return AUTH_GENERAL_ERROR;
113 }
114
115 if (conf->user == NULL) {
117 "No AuthDBDUserPWQuery has been specified");
118 return AUTH_GENERAL_ERROR;
119 }
120
122 if (statement == NULL) {
124 "A prepared statement could not be found for "
125 "AuthDBDUserPWQuery with the key '%s'", conf->user);
126 return AUTH_GENERAL_ERROR;
127 }
128 if ((ret = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res,
129 statement, 0, user, NULL)) != 0) {
131 "Query execution error looking up '%s' "
132 "in database [%s]",
133 user, apr_dbd_error(dbd->driver, dbd->handle, ret));
134 return AUTH_GENERAL_ERROR;
135 }
136 for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
137 rv != -1;
138 rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
139 if (rv != 0) {
141 "Error retrieving results while looking up '%s' "
142 "in database", user);
143 return AUTH_GENERAL_ERROR;
144 }
145 if (dbd_password == NULL) {
146 /* add the rest of the columns to the environment */
147 int i = 1;
148 const char *name;
149 for (name = apr_dbd_get_name(dbd->driver, res, i);
150 name != NULL;
151 name = apr_dbd_get_name(dbd->driver, res, i)) {
152
154 name,
155 NULL);
156 int j = sizeof(AUTHN_PREFIX)-1; /* string length of "AUTHENTICATE_", excluding the trailing NIL */
157 while (str[j]) {
158 if (!apr_isalnum(str[j])) {
159 str[j] = '_';
160 }
161 else {
162 str[j] = apr_toupper(str[j]);
163 }
164 j++;
165 }
167 apr_dbd_get_entry(dbd->driver, row, i));
168 i++;
169 }
170
172 apr_dbd_get_entry(dbd->driver, row, 0));
173 }
174 /* we can't break out here or row won't get cleaned up */
175 }
176
177 if (!dbd_password) {
178 return AUTH_USER_NOT_FOUND;
179 }
181
183
184 if (rv != APR_SUCCESS) {
185 return AUTH_DENIED;
186 }
187
188 return AUTH_GRANTED;
189}
190
191static authn_status authn_dbd_realm(request_rec *r, const char *user,
192 const char *realm, char **rethash)
193{
194 apr_status_t rv;
195 const char *dbd_hash = NULL;
199 int ret;
200
202 &authn_dbd_module);
204 if (dbd == NULL) {
206 "Failed to acquire database connection to look up "
207 "user '%s:%s'", user, realm);
208 return AUTH_GENERAL_ERROR;
209 }
210 if (conf->realm == NULL) {
212 "No AuthDBDUserRealmQuery has been specified");
213 return AUTH_GENERAL_ERROR;
214 }
216 if (statement == NULL) {
218 "A prepared statement could not be found for "
219 "AuthDBDUserRealmQuery with the key '%s'", conf->realm);
220 return AUTH_GENERAL_ERROR;
221 }
222 if ((ret = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res,
223 statement, 0, user, realm, NULL)) != 0) {
225 "Query execution error looking up '%s:%s' "
226 "in database [%s]",
227 user, realm,
228 apr_dbd_error(dbd->driver, dbd->handle, ret));
229 return AUTH_GENERAL_ERROR;
230 }
231 for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
232 rv != -1;
233 rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
234 if (rv != 0) {
236 "Error retrieving results while looking up '%s:%s' "
237 "in database", user, realm);
238 return AUTH_GENERAL_ERROR;
239 }
240 if (dbd_hash == NULL) {
241 /* add the rest of the columns to the environment */
242 int i = 1;
243 const char *name;
244 for (name = apr_dbd_get_name(dbd->driver, res, i);
245 name != NULL;
246 name = apr_dbd_get_name(dbd->driver, res, i)) {
247
249 name,
250 NULL);
251 int j = sizeof(AUTHN_PREFIX)-1; /* string length of "AUTHENTICATE_", excluding the trailing NIL */
252 while (str[j]) {
253 if (!apr_isalnum(str[j])) {
254 str[j] = '_';
255 }
256 else {
257 str[j] = apr_toupper(str[j]);
258 }
259 j++;
260 }
262 apr_dbd_get_entry(dbd->driver, row, i));
263 i++;
264 }
265
267 apr_dbd_get_entry(dbd->driver, row, 0));
268 }
269 /* we can't break out here or row won't get cleaned up */
270 }
271
272 if (!dbd_hash) {
273 return AUTH_USER_NOT_FOUND;
274 }
275 AUTHN_CACHE_STORE(r, user, realm, dbd_hash);
277 return AUTH_USER_FOUND;
278}
279
284
297
299{
303 NULL,
304 NULL,
307};
Apache Provider API.
APR-UTIL DBD library.
APR general purpose library routines.
APR MD5 Routines.
APR Strings library.
APR-util Versioning Interface.
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define ap_get_module_config(v, m)
#define AP_DECLARE_MODULE(foo)
ap_conf_vector_t * base
const char * ap_set_string_slot(cmd_parms *cmd, void *struct_ptr, const char *arg)
Definition config.c:1469
request_rec * r
void ap_hook_optional_fn_retrieve(ap_HOOK_optional_fn_retrieve_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
Definition config.c:195
#define APLOGNO(n)
Definition http_log.h:117
#define ap_log_rerror
Definition http_log.h:454
#define APLOG_ERR
Definition http_log.h:67
#define APLOG_MARK
Definition http_log.h:283
apr_status_t ap_register_auth_provider(apr_pool_t *pool, const char *provider_group, const char *provider_name, const char *provider_version, const void *provider, int type)
Definition request.c:2179
#define AP_AUTH_INTERNAL_PER_CONF
void * dummy
Definition http_vhost.h:62
apr_pool_t apr_dbd_t const char * query
Definition apr_dbd.h:396
struct apr_dbd_prepared_t apr_dbd_prepared_t
Definition apr_dbd.h:87
apr_pool_t apr_dbd_t const char const char * label
Definition apr_dbd.h:397
apr_pool_t apr_dbd_t apr_dbd_results_t ** res
Definition apr_dbd.h:287
apr_dbd_t int const char * statement
Definition apr_dbd.h:272
struct apr_dbd_results_t apr_dbd_results_t
Definition apr_dbd.h:85
apr_pool_t apr_dbd_results_t apr_dbd_row_t ** row
Definition apr_dbd.h:320
struct apr_dbd_row_t apr_dbd_row_t
Definition apr_dbd.h:86
#define APR_HOOK_MIDDLE
Definition apr_hooks.h:303
#define APR_RETRIEVE_OPTIONAL_FN(name)
#define APR_OPTIONAL_FN_TYPE(name)
#define ACCESS_CONF
ap_dbd_t * ap_dbd_acquire(request_rec *r)
Definition mod_dbd.c:929
void ap_dbd_prepare(server_rec *s, const char *query, const char *label)
Definition mod_dbd.c:313
#define STANDARD20_MODULE_STUFF
#define NOT_IN_HTACCESS
const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden)
Definition core.c:1301
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define apr_isalnum(c)
Definition apr_lib.h:203
#define apr_toupper(c)
Definition apr_lib.h:233
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
#define APR_HASH_KEY_STRING
Definition apr_hash.h:47
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char const char * password
apr_int32_t apr_int32_t apr_int32_t err
apr_cmdtype_e cmd
Apache Configuration.
Apache Logging library.
Apache Request library.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
Authentication and Authorization Extension for Apache.
#define AUTHN_PROVIDER_VERSION
Definition mod_auth.h:41
#define AUTHN_PROVIDER_GROUP
Definition mod_auth.h:39
authn_status
Definition mod_auth.h:64
@ AUTH_GRANTED
Definition mod_auth.h:66
@ AUTH_DENIED
Definition mod_auth.h:65
@ AUTH_USER_FOUND
Definition mod_auth.h:67
@ AUTH_GENERAL_ERROR
Definition mod_auth.h:69
@ AUTH_USER_NOT_FOUND
Definition mod_auth.h:68
#define AUTHN_PREFIX
Definition mod_auth.h:48
static const command_rec authn_dbd_cmds[]
static void * authn_dbd_merge_conf(apr_pool_t *pool, void *BASE, void *ADD)
static const char * authn_dbd_prepare(cmd_parms *cmd, void *cfg, const char *query)
static authn_status authn_dbd_password(request_rec *r, const char *user, const char *password)
static ap_dbd_t *(* authn_dbd_acquire_fn)(request_rec *)
static void opt_retr(void)
static void * authn_dbd_cr_conf(apr_pool_t *pool, char *dummy)
static authn_status authn_dbd_realm(request_rec *r, const char *user, const char *realm, char **rethash)
#define AUTHN_CACHE_STORE(r, user, realm, data)
static apr_OFN_ap_authn_cache_store_t * authn_cache_store
static void(* authn_dbd_prepare_fn)(server_rec *, const char *, const char *)
static void authn_dbd_hooks(apr_pool_t *p)
static void ap_authn_cache_store(request_rec *r, const char *module, const char *user, const char *realm, const char *data)
Database Access Extension Module for Apache.
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
char * name
const char * realm
const char * user
A structure that represents the current request.
Definition httpd.h:845
apr_pool_t * pool
Definition httpd.h:847
apr_table_t * subprocess_env
Definition httpd.h:983
struct ap_conf_vector_t * per_dir_config
Definition httpd.h:1047
A structure to store information for each virtual server.
Definition httpd.h:1322
#define str