]> granicus.if.org Git - apache/blob - modules/aaa/mod_auth_anon.c
adjust remaining modules to use the new handler hook method (Alan Edwards)
[apache] / modules / aaa / mod_auth_anon.c
1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  *    if any, must include the following acknowledgment:
21  *       "This product includes software developed by the
22  *        Apache Software Foundation (http://www.apache.org/)."
23  *    Alternately, this acknowledgment may appear in the software itself,
24  *    if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  *    not be used to endorse or promote products derived from this
28  *    software without prior written permission. For written
29  *    permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  *    nor may "Apache" appear in their name, without prior written
33  *    permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation.  For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  *
54  * Portions of this software are based upon public domain software
55  * originally written at the National Center for Supercomputing Applications,
56  * University of Illinois, Urbana-Champaign.
57  */
58
59 /*
60  * http_auth: authentication
61  * 
62  * Rob McCool & Brian Behlendorf.
63  * 
64  * Adapted to Apache by rst.
65  *
66  * Version 0.5 May 1996
67  *
68  * Modified by Dirk.vanGulik@jrc.it to
69  * 
70  * Adapted to allow anonymous logins, just like with Anon-FTP, when
71  * one gives the magic user name 'anonymous' and ones email address
72  * as the password.
73  *
74  * Just add the following tokes to your <directory> setup:
75  * 
76  * Anonymous                    magic-userid [magic-userid]...
77  *
78  * Anonymous_MustGiveEmail      [ on | off ] default = on
79  * Anonymous_LogEmail           [ on | off ] default = on
80  * Anonymous_VerifyEmail        [ on | off ] default = off
81  * Anonymous_NoUserId           [ on | off ] default = off
82  * Anonymous_Authoritative      [ on | off ] default = off
83  *
84  * The magic user id is something like 'anonymous', it is NOT case sensitive. 
85  * 
86  * The MustGiveEmail flag can be used to force users to enter something
87  * in the password field (like an email address). Default is on.
88  *
89  * Furthermore the 'NoUserID' flag can be set to allow completely empty
90  * usernames in as well; this can be is convenient as a single return
91  * in broken GUIs like W95 is often given by the user. The Default is off.
92  *
93  * Dirk.vanGulik@jrc.it; http://ewse.ceo.org; http://me-www.jrc.it/~dirkx
94  * 
95  */
96
97 #include "httpd.h"
98 #include "http_config.h"
99 #include "http_core.h"
100 #include "http_log.h"
101 #include "http_protocol.h"
102 #include "http_request.h"
103 #include "apr_strings.h"
104
105 typedef struct anon_auth {
106     char *password;
107     struct anon_auth *next;
108 } anon_auth;
109
110 typedef struct {
111
112     anon_auth *anon_auth_passwords;
113     int anon_auth_nouserid;
114     int anon_auth_logemail;
115     int anon_auth_verifyemail;
116     int anon_auth_mustemail;
117     int anon_auth_authoritative;
118
119 } anon_auth_config_rec;
120
121 static void *create_anon_auth_dir_config(apr_pool_t *p, char *d)
122 {
123     anon_auth_config_rec *sec = (anon_auth_config_rec *)
124     apr_pcalloc(p, sizeof(anon_auth_config_rec));
125
126     if (!sec)
127         return NULL;            /* no memory... */
128
129     /* just to illustrate the defaults really. */
130     sec->anon_auth_passwords = NULL;
131
132     sec->anon_auth_nouserid = 0;
133     sec->anon_auth_logemail = 1;
134     sec->anon_auth_verifyemail = 0;
135     sec->anon_auth_mustemail = 1;
136     sec->anon_auth_authoritative = 0;
137     return sec;
138 }
139
140 static const char *anon_set_passwd_flag(cmd_parms *cmd,
141                                  void *dummy, int arg)
142 {
143     anon_auth_config_rec *sec = dummy;
144     sec->anon_auth_mustemail = arg;
145     return NULL;
146 }
147
148 static const char *anon_set_userid_flag(cmd_parms *cmd,
149                                  void *dummy, int arg)
150 {
151     anon_auth_config_rec *sec = dummy;
152     sec->anon_auth_nouserid = arg;
153     return NULL;
154 }
155
156 static const char *anon_set_logemail_flag(cmd_parms *cmd,
157                                    void *dummy, int arg)
158 {
159     anon_auth_config_rec *sec = dummy;
160     sec->anon_auth_logemail = arg;
161     return NULL;
162 }
163
164 static const char *anon_set_verifyemail_flag(cmd_parms *cmd,
165                                       void *dummy, int arg)
166 {
167     anon_auth_config_rec *sec = dummy;
168     sec->anon_auth_verifyemail = arg;
169     return NULL;
170 }
171 static const char *anon_set_authoritative_flag(cmd_parms *cmd,
172                                         void *dummy, int arg)
173 {
174     anon_auth_config_rec *sec = dummy;
175     sec->anon_auth_authoritative = arg;
176     return NULL;
177 }
178
179 static const char *anon_set_string_slots(cmd_parms *cmd,
180                                   void *dummy, const char *arg)
181 {
182     anon_auth_config_rec *sec = dummy;
183     anon_auth *first;
184
185     if (!(*arg))
186         return "Anonymous string cannot be empty, use Anonymous_NoUserId instead";
187
188     /* squeeze in a record */
189     first = sec->anon_auth_passwords;
190
191     if (!(sec->anon_auth_passwords = apr_palloc(cmd->pool, sizeof(anon_auth))) ||
192        !(sec->anon_auth_passwords->password = apr_pstrdup(cmd->pool, arg)))
193              return "Failed to claim memory for an anonymous password...";
194
195     /* and repair the next */
196     sec->anon_auth_passwords->next = first;
197
198     return NULL;
199 }
200
201 static const command_rec anon_auth_cmds[] =
202 {
203     AP_INIT_ITERATE("Anonymous", anon_set_string_slots, NULL, OR_AUTHCFG, 
204      "a space-separated list of user IDs"),
205     AP_INIT_FLAG("Anonymous_MustGiveEmail", anon_set_passwd_flag, NULL, 
206      OR_AUTHCFG, "Limited to 'on' or 'off'"),
207     AP_INIT_FLAG("Anonymous_NoUserId", anon_set_userid_flag, NULL, OR_AUTHCFG, 
208      "Limited to 'on' or 'off'"),
209     AP_INIT_FLAG("Anonymous_VerifyEmail", anon_set_verifyemail_flag, NULL, 
210      OR_AUTHCFG, "Limited to 'on' or 'off'"),
211     AP_INIT_FLAG("Anonymous_LogEmail", anon_set_logemail_flag, NULL, OR_AUTHCFG,
212      "Limited to 'on' or 'off'"),
213     AP_INIT_FLAG("Anonymous_Authoritative", anon_set_authoritative_flag, NULL, 
214      OR_AUTHCFG, "Limited to 'on' or 'off'"),
215     {NULL}
216 };
217
218 module AP_MODULE_DECLARE_DATA anon_auth_module;
219
220 static int anon_authenticate_basic_user(request_rec *r)
221 {
222     anon_auth_config_rec *sec =
223     (anon_auth_config_rec *) ap_get_module_config(r->per_dir_config,
224                                                &anon_auth_module);
225     const char *sent_pw;
226     int res = DECLINED;
227
228     if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
229         return res;
230
231     /* Ignore if we are not configured */
232     if (!sec->anon_auth_passwords)
233         return DECLINED;
234
235     /* Do we allow an empty userID and/or is it the magic one
236      */
237
238     if ((!(r->user[0])) && (sec->anon_auth_nouserid)) {
239         res = OK;
240     }
241     else {
242         anon_auth *p = sec->anon_auth_passwords;
243         res = DECLINED;
244         while ((res == DECLINED) && (p != NULL)) {
245             if (!(strcasecmp(r->user, p->password)))
246                 res = OK;
247             p = p->next;
248         }
249     }
250     if (
251     /* username is OK */
252            (res == OK)
253     /* password been filled out ? */
254            && ((!sec->anon_auth_mustemail) || strlen(sent_pw))
255     /* does the password look like an email address ? */
256            && ((!sec->anon_auth_verifyemail)
257                || ((strpbrk("@", sent_pw) != NULL)
258                    && (strpbrk(".", sent_pw) != NULL)))) {
259         if (sec->anon_auth_logemail && ap_is_initial_req(r)) {
260             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, r,
261                         "Anonymous: Passwd <%s> Accepted",
262                         sent_pw ? sent_pw : "\'none\'");
263         }
264         return OK;
265     }
266     else {
267         if (sec->anon_auth_authoritative) {
268             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, APR_SUCCESS, r,
269                         "Anonymous: Authoritative, Passwd <%s> not accepted",
270                         sent_pw ? sent_pw : "\'none\'");
271             return HTTP_UNAUTHORIZED;
272         }
273         /* Drop out the bottom to return DECLINED */
274     }
275
276     return DECLINED;
277 }
278
279 static int check_anon_access(request_rec *r)
280 {
281 #ifdef NOTYET
282     conn_rec *c = r->connection;
283     anon_auth_config_rec *sec =
284     (anon_auth_config_rec *) ap_get_module_config(r->per_dir_config,
285                                                &anon_auth_module);
286
287     if (!sec->anon_auth)
288         return DECLINED;
289
290     if (strcasecmp(r->connection->user, sec->anon_auth))
291         return DECLINED;
292
293     return OK;
294 #endif
295     return DECLINED;
296 }
297 static void register_hooks(void)
298 {
299     ap_hook_check_user_id(anon_authenticate_basic_user,NULL,NULL,AP_HOOK_MIDDLE);
300     ap_hook_auth_checker(check_anon_access,NULL,NULL,AP_HOOK_MIDDLE);
301 }
302
303 module AP_MODULE_DECLARE_DATA anon_auth_module =
304 {
305     STANDARD20_MODULE_STUFF,
306     create_anon_auth_dir_config,/* dir config creater */
307     NULL,                       /* dir merger ensure strictness */
308     NULL,                       /* server config */
309     NULL,                       /* merge server config */
310     anon_auth_cmds,             /* command apr_table_t */
311     register_hooks              /* register hooks */
312 };