upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / modules / aaa / mod_auth_anon.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  * Version 0.5 May 1996
25  *
26  * Modified by Dirk.vanGulik@jrc.it to
27  * 
28  * Adapted to allow anonymous logins, just like with Anon-FTP, when
29  * one gives the magic user name 'anonymous' and ones email address
30  * as the password.
31  *
32  * Just add the following tokes to your <directory> setup:
33  * 
34  * Anonymous                    magic-userid [magic-userid]...
35  *
36  * Anonymous_MustGiveEmail      [ on | off ] default = on
37  * Anonymous_LogEmail           [ on | off ] default = on
38  * Anonymous_VerifyEmail        [ on | off ] default = off
39  * Anonymous_NoUserId           [ on | off ] default = off
40  * Anonymous_Authoritative      [ on | off ] default = off
41  *
42  * The magic user id is something like 'anonymous', it is NOT case sensitive. 
43  * 
44  * The MustGiveEmail flag can be used to force users to enter something
45  * in the password field (like an email address). Default is on.
46  *
47  * Furthermore the 'NoUserID' flag can be set to allow completely empty
48  * usernames in as well; this can be is convenient as a single return
49  * in broken GUIs like W95 is often given by the user. The Default is off.
50  *
51  * Dirk.vanGulik@jrc.it; http://ewse.ceo.org; http://me-www.jrc.it/~dirkx
52  * 
53  */
54
55 #include "apr_strings.h"
56
57 #define APR_WANT_STRFUNC
58 #include "apr_want.h"
59
60 #include "httpd.h"
61 #include "http_config.h"
62 #include "http_core.h"
63 #include "http_log.h"
64 #include "http_request.h"
65 #include "http_protocol.h"
66
67 typedef struct anon_auth {
68     char *password;
69     struct anon_auth *next;
70 } anon_auth;
71
72 typedef struct {
73     anon_auth *anon_auth_passwords;
74     int anon_auth_nouserid;
75     int anon_auth_logemail;
76     int anon_auth_verifyemail;
77     int anon_auth_mustemail;
78     int anon_auth_authoritative;
79 } anon_auth_config_rec;
80
81 static void *create_anon_auth_dir_config(apr_pool_t *p, char *d)
82 {
83     anon_auth_config_rec *conf = apr_palloc(p, sizeof(*conf));
84
85     /* just to illustrate the defaults really. */
86     conf->anon_auth_passwords = NULL;
87
88     conf->anon_auth_nouserid = 0;
89     conf->anon_auth_logemail = 1;
90     conf->anon_auth_verifyemail = 0;
91     conf->anon_auth_mustemail = 1;
92     conf->anon_auth_authoritative = 0;
93     return conf;
94 }
95
96 static const char *anon_set_string_slots(cmd_parms *cmd,
97                                          void *my_config, const char *arg)
98 {
99     anon_auth_config_rec *conf = my_config;
100     anon_auth *first;
101
102     if (!(*arg))
103         return "Anonymous string cannot be empty, use Anonymous_NoUserId instead";
104
105     /* squeeze in a record */
106     first = conf->anon_auth_passwords;
107
108     if (!(conf->anon_auth_passwords = apr_palloc(cmd->pool, sizeof(anon_auth))) ||
109        !(conf->anon_auth_passwords->password = apr_pstrdup(cmd->pool, arg)))
110              return "Failed to claim memory for an anonymous password...";
111
112     /* and repair the next */
113     conf->anon_auth_passwords->next = first;
114
115     return NULL;
116 }
117
118 static const command_rec anon_auth_cmds[] =
119 {
120     AP_INIT_ITERATE("Anonymous", anon_set_string_slots, NULL, OR_AUTHCFG, 
121      "a space-separated list of user IDs"),
122     AP_INIT_FLAG("Anonymous_MustGiveEmail", ap_set_flag_slot,
123      (void *)APR_OFFSETOF(anon_auth_config_rec, anon_auth_mustemail),
124      OR_AUTHCFG, "Limited to 'on' or 'off'"),
125     AP_INIT_FLAG("Anonymous_NoUserId", ap_set_flag_slot,
126      (void *)APR_OFFSETOF(anon_auth_config_rec, anon_auth_nouserid),
127      OR_AUTHCFG, "Limited to 'on' or 'off'"),
128     AP_INIT_FLAG("Anonymous_VerifyEmail", ap_set_flag_slot,
129      (void *)APR_OFFSETOF(anon_auth_config_rec, anon_auth_verifyemail),
130      OR_AUTHCFG, "Limited to 'on' or 'off'"),
131     AP_INIT_FLAG("Anonymous_LogEmail", ap_set_flag_slot,
132      (void *)APR_OFFSETOF(anon_auth_config_rec, anon_auth_logemail),
133      OR_AUTHCFG, "Limited to 'on' or 'off'"),
134     AP_INIT_FLAG("Anonymous_Authoritative", ap_set_flag_slot,
135      (void *)APR_OFFSETOF(anon_auth_config_rec, anon_auth_authoritative),
136      OR_AUTHCFG, "Limited to 'on' or 'off'"),
137     {NULL}
138 };
139
140 module AP_MODULE_DECLARE_DATA auth_anon_module;
141
142 static int anon_authenticate_basic_user(request_rec *r)
143 {
144     anon_auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
145                                                       &auth_anon_module);
146     const char *sent_pw;
147     int res = DECLINED;
148
149     if ((res = ap_get_basic_auth_pw(r, &sent_pw))) {
150         return res;
151     }
152
153     /* Ignore if we are not configured */
154     if (!conf->anon_auth_passwords) {
155         return DECLINED;
156     }
157
158     /* Do we allow an empty userID and/or is it the magic one
159      */
160
161     if ((!(r->user[0])) && (conf->anon_auth_nouserid)) {
162         res = OK;
163     }
164     else {
165         anon_auth *p = conf->anon_auth_passwords;
166         res = DECLINED;
167         while ((res == DECLINED) && (p != NULL)) {
168             if (!(strcasecmp(r->user, p->password))) {
169                 res = OK;
170             }
171             p = p->next;
172         }
173     }
174     if (
175         /* username is OK */
176         (res == OK)
177         /* password been filled out ? */
178            && ((!conf->anon_auth_mustemail) || strlen(sent_pw))
179         /* does the password look like an email address ? */
180            && ((!conf->anon_auth_verifyemail)
181                || ((strpbrk("@", sent_pw) != NULL)
182                    && (strpbrk(".", sent_pw) != NULL)))) {
183         if (conf->anon_auth_logemail && ap_is_initial_req(r)) {
184             ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r,
185                         "Anonymous: Passwd <%s> Accepted",
186                         sent_pw ? sent_pw : "\'none\'");
187         }
188         return OK;
189     }
190     else {
191         if (conf->anon_auth_authoritative) {
192             ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r,
193                         "Anonymous: Authoritative, Passwd <%s> not accepted",
194                         sent_pw ? sent_pw : "\'none\'");
195             return HTTP_UNAUTHORIZED;
196         }
197         /* Drop out the bottom to return DECLINED */
198     }
199
200     return DECLINED;
201 }
202
203 static int check_anon_access(request_rec *r)
204 {
205 #ifdef NOTYET
206     conn_rec *c = r->connection;
207     anon_auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
208                                                       &auth_anon_module);
209
210     if (!conf->anon_auth) {
211         return DECLINED;
212     }
213
214     if (strcasecmp(r->connection->user, conf->anon_auth)) {
215         return DECLINED;
216     }
217
218     return OK;
219 #endif
220     return DECLINED;
221 }
222
223 static void register_hooks(apr_pool_t *p)
224 {
225     ap_hook_check_user_id(anon_authenticate_basic_user,NULL,NULL,APR_HOOK_MIDDLE);
226     ap_hook_auth_checker(check_anon_access,NULL,NULL,APR_HOOK_MIDDLE);
227 }
228
229 module AP_MODULE_DECLARE_DATA auth_anon_module =
230 {
231     STANDARD20_MODULE_STUFF,
232     create_anon_auth_dir_config,    /* dir config creater */
233     NULL,                           /* dir merger ensure strictness */
234     NULL,                           /* server config */
235     NULL,                           /* merge server config */
236     anon_auth_cmds,                 /* command apr_table_t */
237     register_hooks                  /* register hooks */
238 };