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