Apache HTTPD
mod_authz_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 "httpd.h"
18#include "http_log.h"
19#include "http_config.h"
20#include "ap_provider.h"
21#include "http_request.h"
22#include "http_protocol.h"
23#include "http_core.h"
24#include "apr_dbd.h"
25#include "mod_dbd.h"
26#include "apr_strings.h"
27#include "mod_authz_dbd.h"
28
29#include "mod_auth.h"
30
31
32module AP_MODULE_DECLARE_DATA authz_dbd_module;
33
34/* Export a hook for modules that manage clientside sessions
35 * (e.g. mod_auth_cookie)
36 * to deal with those when we successfully login/logout at the server
37 *
38 * XXX: WHY would this be specific to dbd_authz? Why wouldn't we track
39 * this across all authz user providers in a lower level mod, such as
40 * mod_auth_basic/digest?
41 */
43 (request_rec *r, int code, const char *action),
44 (r, code, action), OK, DECLINED)
45
46
48 const char *query;
49 const char *redir_query;
52
53static ap_dbd_t *(*dbd_handle)(request_rec*) = NULL;
54static void (*dbd_prepare)(server_rec*, const char*, const char*) = NULL;
55
56static const char *const noerror = "???";
57
59{
61 ret->redirect = -1;
62 return ret;
63}
64
65static void *authz_dbd_merge_cfg(apr_pool_t *pool, void *BASE, void *ADD)
66{
68 authz_dbd_cfg *add = ADD;
70
71 ret->query = (add->query == NULL) ? base->query : add->query;
72 ret->redir_query = (add->redir_query == NULL)
73 ? base->redir_query : add->redir_query;
74 ret->redirect = (add->redirect == -1) ? base->redirect : add->redirect;
75 return ret;
76}
77
78static const char *authz_dbd_prepare(cmd_parms *cmd, void *cfg,
79 const char *query)
80{
81 static unsigned int label_num = 0;
82 char *label;
84 if (err)
85 return err;
86
87 if (dbd_prepare == NULL) {
89 if (dbd_prepare == NULL) {
90 return "You must load mod_dbd to enable AuthzDBD functions";
91 }
93 }
94 label = apr_psprintf(cmd->pool, "authz_dbd_%d", ++label_num);
95
96 dbd_prepare(cmd->server, query, label);
97
98 /* save the label here for our own use */
99 return ap_set_string_slot(cmd, cfg, label);
100}
101
102static const command_rec authz_dbd_cmds[] = {
103 AP_INIT_FLAG("AuthzDBDLoginToReferer", ap_set_flag_slot,
104 (void*)APR_OFFSETOF(authz_dbd_cfg, redirect), ACCESS_CONF,
105 "Whether to redirect to referer on successful login"),
106 AP_INIT_TAKE1("AuthzDBDQuery", authz_dbd_prepare,
108 "SQL query for DBD Authz or login"),
109 AP_INIT_TAKE1("AuthzDBDRedirectQuery", authz_dbd_prepare,
110 (void*)APR_OFFSETOF(authz_dbd_cfg, redir_query), ACCESS_CONF,
111 "SQL query to get per-user redirect URL after login"),
112 {NULL}
113};
114
116 const char *action)
117{
118 int rv;
119 const char *newuri = NULL;
120 int nrows;
121 const char *message;
122 ap_dbd_t *dbd;
126
127 if (cfg->query == NULL) {
129 "No query configured for %s!", action);
131 }
132
133 dbd = dbd_handle(r);
134 if (dbd == NULL) {
136 "No db handle available for %s! "
137 "Check your database access",
138 action);
140 }
141
142 query = apr_hash_get(dbd->prepared, cfg->query, APR_HASH_KEY_STRING);
143 if (query == NULL) {
145 "Error retrieving Query for %s!", action);
147 }
148
149 rv = apr_dbd_pvquery(dbd->driver, r->pool, dbd->handle, &nrows,
150 query, r->user, NULL);
151 if (rv == 0) {
152 if (nrows != 1) {
154 "authz_dbd: %s of user %s updated %d rows",
155 action, r->user, nrows);
156 }
157 }
158 else {
159 message = apr_dbd_error(dbd->driver, dbd->handle, rv);
161 "authz_dbd: query for %s failed; user %s [%s]",
162 action, r->user, message?message:noerror);
164 }
165
166 if (cfg->redirect == 1) {
167 newuri = apr_table_get(r->headers_in, "Referer");
168 }
169
170 if (!newuri && cfg->redir_query) {
171 query = apr_hash_get(dbd->prepared, cfg->redir_query,
173 if (query == NULL) {
175 "authz_dbd: no redirect query!");
176 /* OK, this is non-critical; we can just not-redirect */
177 }
178 else if ((rv = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle,
179 &res, query, 0, r->user, NULL)) == 0) {
180 for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
181 rv != -1;
182 rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
183 if (rv != 0) {
184 message = apr_dbd_error(dbd->driver, dbd->handle, rv);
186 "authz_dbd in get_row; action=%s user=%s [%s]",
187 action, r->user, message?message:noerror);
188 }
189 else if (newuri == NULL) {
190 newuri =
192 apr_dbd_get_entry(dbd->driver, row, 0));
193 }
194 /* we can't break out here or row won't get cleaned up */
195 }
196 }
197 else {
198 message = apr_dbd_error(dbd->driver, dbd->handle, rv);
200 "authz_dbd/redirect for %s of %s [%s]",
201 action, r->user, message?message:noerror);
202 }
203 }
204 if (newuri != NULL) {
206 apr_table_set(r->err_headers_out, "Location", newuri);
207 }
209 return OK;
210}
211
214{
215 /* SELECT user_group FROM authz WHERE user = %s */
216 int rv;
217 const char *message;
218 ap_dbd_t *dbd;
222
223 if (cfg->query == NULL) {
225 "No query configured for dbd-group!");
227 }
228
229 dbd = dbd_handle(r);
230 if (dbd == NULL) {
232 "No db handle available for dbd-query! "
233 "Check your database access");
235 }
236
237 query = apr_hash_get(dbd->prepared, cfg->query, APR_HASH_KEY_STRING);
238 if (query == NULL) {
240 "Error retrieving query for dbd-group!");
242 }
243 rv = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res,
244 query, 0, r->user, NULL);
245 if (rv == 0) {
246 for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1);
247 rv != -1;
248 rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) {
249 if (rv == 0) {
250 APR_ARRAY_PUSH(groups, const char *) =
252 apr_dbd_get_entry(dbd->driver, row, 0));
253 }
254 else {
255 message = apr_dbd_error(dbd->driver, dbd->handle, rv);
257 "authz_dbd in get_row; user_group query for user=%s [%s]",
260 }
261 }
262 }
263 else {
264 message = apr_dbd_error(dbd->driver, dbd->handle, rv);
266 "authz_dbd, in groups query for %s [%s]",
269 }
270 return OK;
271}
272
274 const char *require_args,
275 const void *parsed_require_args)
276{
277 int rv;
278 const char *w;
280
281 const char *err = NULL;
283 const char *require;
284
285 const char *t;
287 &authz_dbd_module);
288
289 if (!r->user) {
291 }
292
293 groups = apr_array_make(r->pool, 4, sizeof(const char*));
294 rv = authz_dbd_group_query(r, cfg, groups);
295 if (rv != OK) {
296 return AUTHZ_GENERAL_ERROR;
297 }
298
299 require = ap_expr_str_exec(r, expr, &err);
300 if (err) {
302 "authz_dbd authorize: require dbd-group: Can't "
303 "evaluate require expression: %s", err);
304 return AUTHZ_DENIED;
305 }
306
307 t = require;
308 while (t[0]) {
309 w = ap_getword_white(r->pool, &t);
311 return AUTHZ_GRANTED;
312 }
313 }
314
315 return AUTHZ_DENIED;
316}
317
319 const char *require_args,
320 const void *parsed_require_args)
321{
323 &authz_dbd_module);
324
325 if (!r->user) {
327 }
328
329 return (authz_dbd_login(r, cfg, "login") == OK ? AUTHZ_GRANTED : AUTHZ_DENIED);
330}
331
333 const char *require_args,
334 const void *parsed_require_args)
335{
337 &authz_dbd_module);
338
339 if (!r->user) {
341 }
342
343 return (authz_dbd_login(r, cfg, "logout") == OK ? AUTHZ_GRANTED : AUTHZ_DENIED);
344}
345
346static const char *dbd_parse_config(cmd_parms *cmd, const char *require_line,
347 const void **parsed_require_line)
348{
349 const char *expr_err = NULL;
350 ap_expr_info_t *expr;
351
353 &expr_err, NULL);
354
355 if (expr_err) {
356 return apr_pstrcat(cmd->temp_pool,
357 "Cannot parse expression in require line: ",
358 expr_err, NULL);
359 }
360
361 *parsed_require_line = expr;
362
363 return NULL;
364}
365
371
377
383
399
401{
405 NULL,
406 NULL,
409};
Apache Provider API.
APR-UTIL DBD library.
APR Strings library.
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define ap_get_module_config(v, m)
#define AP_DECLARE_MODULE(foo)
#define AP_INIT_FLAG(directive, func, mconfig, where, help)
ap_conf_vector_t * base
const char * ap_set_string_slot(cmd_parms *cmd, void *struct_ptr, const char *arg)
Definition config.c:1469
const char * ap_set_flag_slot(cmd_parms *cmd, void *struct_ptr, int arg)
Definition config.c:1512
request_rec * r
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
#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
#define APLOG_WARNING
Definition http_log.h:68
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
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
apr_dbd_t int * nrows
Definition apr_dbd.h:272
struct apr_dbd_row_t apr_dbd_row_t
Definition apr_dbd.h:86
#define APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ns, link, ret, name, args_decl, args_use, ok, decline)
#define APR_RETRIEVE_OPTIONAL_FN(name)
#define AP_EXPR_FLAG_STRING_RESULT
Definition ap_expr.h:68
#define ap_expr_parse_cmd(cmd, expr, flags, err, lookup_fn)
Definition ap_expr.h:340
const char * ap_expr_str_exec(request_rec *r, const ap_expr_info_t *expr, const char **err)
#define ACCESS_CONF
#define HTTP_INTERNAL_SERVER_ERROR
Definition httpd.h:535
#define HTTP_MOVED_TEMPORARILY
Definition httpd.h:502
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
char * ap_getword_white(apr_pool_t *p, const char **line)
Definition util.c:751
int ap_array_str_contains(const apr_array_header_t *array, const char *s)
Definition util.c:3446
#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_HASH_KEY_STRING
Definition apr_hash.h:47
apr_interval_time_t t
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
#define APR_ARRAY_PUSH(ary, type)
Definition apr_tables.h:150
apr_int32_t apr_int32_t apr_int32_t err
apr_cmdtype_e cmd
Apache Configuration.
CORE HTTP Daemon.
Apache Logging library.
HTTP protocol handling.
Apache Request library.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
Authentication and Authorization Extension for Apache.
authz_status
Definition mod_auth.h:72
@ AUTHZ_DENIED
Definition mod_auth.h:73
@ AUTHZ_GENERAL_ERROR
Definition mod_auth.h:76
@ AUTHZ_DENIED_NO_USER
Definition mod_auth.h:77
@ AUTHZ_GRANTED
Definition mod_auth.h:74
#define AUTHZ_PROVIDER_VERSION
Definition mod_auth.h:42
#define AUTHZ_PROVIDER_GROUP
Definition mod_auth.h:40
static void authz_dbd_hooks(apr_pool_t *p)
static authz_status dbdlogout_check_authorization(request_rec *r, const char *require_args, const void *parsed_require_args)
static const command_rec authz_dbd_cmds[]
static const char * authz_dbd_prepare(cmd_parms *cmd, void *cfg, const char *query)
static const authz_provider authz_dbdlogin_provider
static const char * dbd_parse_config(cmd_parms *cmd, const char *require_line, const void **parsed_require_line)
static const char *const noerror
static const authz_provider authz_dbdlogout_provider
static int authz_dbd_login(request_rec *r, authz_dbd_cfg *cfg, const char *action)
static void * authz_dbd_cr_cfg(apr_pool_t *pool, char *dummy)
static authz_status dbdgroup_check_authorization(request_rec *r, const char *require_args, const void *parsed_require_args)
static ap_dbd_t *(* dbd_handle)(request_rec *)
int authz_dbd_run_client_login(request_rec *r, int code, const char *action)
static void(* dbd_prepare)(server_rec *, const char *, const char *)
static authz_status dbdlogin_check_authorization(request_rec *r, const char *require_args, const void *parsed_require_args)
static const authz_provider authz_dbdgroup_provider
static void * authz_dbd_merge_cfg(apr_pool_t *pool, void *BASE, void *ADD)
static int authz_dbd_group_query(request_rec *r, authz_dbd_cfg *cfg, apr_array_header_t *groups)
Database Access Extension Module for Apache.
return NULL
Definition mod_so.c:359
const char * redir_query
const char * query
A structure that represents the current request.
Definition httpd.h:845
char * user
Definition httpd.h:1005
int status
Definition httpd.h:891
apr_pool_t * pool
Definition httpd.h:847
apr_table_t * err_headers_out
Definition httpd.h:981
apr_table_t * headers_in
Definition httpd.h:976
struct ap_conf_vector_t * per_dir_config
Definition httpd.h:1047
A structure to keep track of authorization requirements.
Definition http_core.h:316
A structure to store information for each virtual server.
Definition httpd.h:1322