]> granicus.if.org Git - apache/blob - modules/aaa/mod_authn_dbm.c
move a temporary table from r->pool to a temporary
[apache] / modules / aaa / mod_authn_dbm.c
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 /*
18  * http_auth: authentication
19  *
20  * Rob McCool & Brian Behlendorf.
21  *
22  * Adapted to Apache by rst.
23  *
24  */
25
26 #define APR_WANT_STRFUNC
27 #include "apr_want.h"
28 #include "apr_strings.h"
29 #include "apr_dbm.h"
30
31 #include "ap_provider.h"
32 #include "httpd.h"
33 #include "http_config.h"
34 #include "http_core.h"
35 #include "http_log.h"
36 #include "http_protocol.h"
37 #include "http_request.h"   /* for ap_hook_(check_user_id | auth_checker)*/
38
39 #include "mod_auth.h"
40
41 static APR_OPTIONAL_FN_TYPE(ap_authn_cache_store) *authn_cache_store = NULL;
42 #define AUTHN_CACHE_STORE(r,user,realm,data) \
43     if (authn_cache_store != NULL) \
44         authn_cache_store((r), "dbm", (user), (realm), (data))
45
46 typedef struct {
47     const char *pwfile;
48     const char *dbmtype;
49 } authn_dbm_config_rec;
50
51 static void *create_authn_dbm_dir_config(apr_pool_t *p, char *d)
52 {
53     authn_dbm_config_rec *conf = apr_palloc(p, sizeof(*conf));
54
55     conf->pwfile = NULL;
56     conf->dbmtype = "default";
57
58     return conf;
59 }
60
61 static const char *set_dbm_type(cmd_parms *cmd,
62                                 void *dir_config,
63                                 const char *arg)
64 {
65     authn_dbm_config_rec *conf = dir_config;
66
67     conf->dbmtype = apr_pstrdup(cmd->pool, arg);
68     return NULL;
69 }
70
71 static const command_rec authn_dbm_cmds[] =
72 {
73     AP_INIT_TAKE1("AuthDBMUserFile", ap_set_file_slot,
74      (void *)APR_OFFSETOF(authn_dbm_config_rec, pwfile),
75      OR_AUTHCFG, "dbm database file containing user IDs and passwords"),
76     AP_INIT_TAKE1("AuthDBMType", set_dbm_type,
77      NULL,
78      OR_AUTHCFG, "what type of DBM file the user file is"),
79     {NULL}
80 };
81
82 module AP_MODULE_DECLARE_DATA authn_dbm_module;
83
84 static apr_status_t fetch_dbm_value(const char *dbmtype, const char *dbmfile,
85                                     const char *user, char **value,
86                                     apr_pool_t *pool)
87 {
88     apr_dbm_t *f;
89     apr_datum_t key, val;
90     apr_status_t rv;
91
92     rv = apr_dbm_open_ex(&f, dbmtype, dbmfile, APR_DBM_READONLY,
93                          APR_OS_DEFAULT, pool);
94
95     if (rv != APR_SUCCESS) {
96         return rv;
97     }
98
99     key.dptr = (char*)user;
100 #ifndef NETSCAPE_DBM_COMPAT
101     key.dsize = strlen(key.dptr);
102 #else
103     key.dsize = strlen(key.dptr) + 1;
104 #endif
105
106     *value = NULL;
107
108     if (apr_dbm_fetch(f, key, &val) == APR_SUCCESS && val.dptr) {
109         *value = apr_pstrmemdup(pool, val.dptr, val.dsize);
110     }
111
112     apr_dbm_close(f);
113
114     return rv;
115 }
116
117 static authn_status check_dbm_pw(request_rec *r, const char *user,
118                                  const char *password)
119 {
120     authn_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config,
121                                                       &authn_dbm_module);
122     apr_status_t rv;
123     char *dbm_password;
124     char *colon_pw;
125
126     rv = fetch_dbm_value(conf->dbmtype, conf->pwfile, user, &dbm_password,
127                          r->pool);
128
129     if (rv != APR_SUCCESS) {
130         ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01754)
131                       "could not open dbm (type %s) auth file: %s",
132                       conf->dbmtype, conf->pwfile);
133         return AUTH_GENERAL_ERROR;
134     }
135
136     if (!dbm_password) {
137         return AUTH_USER_NOT_FOUND;
138     }
139
140     colon_pw = ap_strchr(dbm_password, ':');
141     if (colon_pw) {
142         *colon_pw = '\0';
143     }
144     AUTHN_CACHE_STORE(r, user, NULL, dbm_password);
145
146     rv = ap_password_validate(r, user, password, dbm_password);
147
148     if (rv != APR_SUCCESS) {
149         return AUTH_DENIED;
150     }
151
152     return AUTH_GRANTED;
153 }
154
155 static authn_status get_dbm_realm_hash(request_rec *r, const char *user,
156                                        const char *realm, char **rethash)
157 {
158     authn_dbm_config_rec *conf = ap_get_module_config(r->per_dir_config,
159                                                       &authn_dbm_module);
160     apr_status_t rv;
161     char *dbm_hash;
162     char *colon_hash;
163
164     rv = fetch_dbm_value(conf->dbmtype, conf->pwfile,
165                          apr_pstrcat(r->pool, user, ":", realm, NULL),
166                          &dbm_hash, r->pool);
167
168     if (rv != APR_SUCCESS) {
169         ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01755)
170                       "Could not open dbm (type %s) hash file: %s",
171                       conf->dbmtype, conf->pwfile);
172         return AUTH_GENERAL_ERROR;
173     }
174
175     if (!dbm_hash) {
176         return AUTH_USER_NOT_FOUND;
177     }
178
179     colon_hash = ap_strchr(dbm_hash, ':');
180     if (colon_hash) {
181         *colon_hash = '\0';
182     }
183
184     *rethash = dbm_hash;
185     AUTHN_CACHE_STORE(r, user, realm, dbm_hash);
186
187     return AUTH_USER_FOUND;
188 }
189
190 static const authn_provider authn_dbm_provider =
191 {
192     &check_dbm_pw,
193     &get_dbm_realm_hash,
194 };
195
196 static void opt_retr(void)
197 {
198     authn_cache_store = APR_RETRIEVE_OPTIONAL_FN(ap_authn_cache_store);
199 }
200 static void register_hooks(apr_pool_t *p)
201 {
202     ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "dbm",
203                               AUTHN_PROVIDER_VERSION,
204                               &authn_dbm_provider, AP_AUTH_INTERNAL_PER_CONF);
205     ap_hook_optional_fn_retrieve(opt_retr, NULL, NULL, APR_HOOK_MIDDLE);
206 }
207
208 AP_DECLARE_MODULE(authn_dbm) =
209 {
210     STANDARD20_MODULE_STUFF,
211     create_authn_dbm_dir_config, /* dir config creater */
212     NULL,                        /* dir merger --- default is to override */
213     NULL,                        /* server config */
214     NULL,                        /* merge server config */
215     authn_dbm_cmds,              /* command apr_table_t */
216     register_hooks               /* register hooks */
217 };