| /* Licensed to the Apache Software Foundation (ASF) under one or more | |
| * contributor license agreements. See the NOTICE file distributed with | |
| * this work for additional information regarding copyright ownership. | |
| * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| * (the "License"); you may not use this file except in compliance with | |
| * the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| /* | |
| * Adapted to allow anonymous logins, just like with Anon-FTP, when | |
| * one gives the magic user name 'anonymous' and ones email address | |
| * as the password. | |
| * | |
| * Just add the following tokes to your <directory> setup: | |
| * | |
| * Anonymous magic-userid [magic-userid]... | |
| * | |
| * Anonymous_MustGiveEmail [ on | off ] default = on | |
| * Anonymous_LogEmail [ on | off ] default = on | |
| * Anonymous_VerifyEmail [ on | off ] default = off | |
| * Anonymous_NoUserId [ on | off ] default = off | |
| * | |
| * The magic user id is something like 'anonymous', it is NOT case sensitive. | |
| * | |
| * The MustGiveEmail flag can be used to force users to enter something | |
| * in the password field (like an email address). Default is on. | |
| * | |
| * Furthermore the 'NoUserID' flag can be set to allow completely empty | |
| * usernames in as well; this can be is convenient as a single return | |
| * in broken GUIs like W95 is often given by the user. The Default is off. | |
| * | |
| * Dirk.vanGulik@jrc.it; http://ewse.ceo.org; http://me-www.jrc.it/~dirkx | |
| * | |
| */ | |
| #include "apr_strings.h" | |
| #define APR_WANT_STRFUNC | |
| #include "apr_want.h" | |
| #include "ap_provider.h" | |
| #include "httpd.h" | |
| #include "http_config.h" | |
| #include "http_core.h" | |
| #include "http_log.h" | |
| #include "http_request.h" | |
| #include "http_protocol.h" | |
| #include "mod_auth.h" | |
| typedef struct anon_auth_user { | |
| const char *user; | |
| struct anon_auth_user *next; | |
| } anon_auth_user; | |
| typedef struct { | |
| anon_auth_user *users; | |
| int nouserid; | |
| int logemail; | |
| int verifyemail; | |
| int mustemail; | |
| int anyuserid; | |
| } authn_anon_config_rec; | |
| static void *create_authn_anon_dir_config(apr_pool_t *p, char *d) | |
| { | |
| authn_anon_config_rec *conf = apr_palloc(p, sizeof(*conf)); | |
| /* just to illustrate the defaults really. */ | |
| conf->users = NULL; | |
| conf->nouserid = 0; | |
| conf->anyuserid = 0; | |
| conf->logemail = 1; | |
| conf->verifyemail = 0; | |
| conf->mustemail = 1; | |
| return conf; | |
| } | |
| static const char *anon_set_string_slots(cmd_parms *cmd, | |
| void *my_config, const char *arg) | |
| { | |
| authn_anon_config_rec *conf = my_config; | |
| anon_auth_user *first; | |
| if (!*arg) { | |
| return "Anonymous string cannot be empty, use Anonymous_NoUserId"; | |
| } | |
| /* squeeze in a record */ | |
| if (!conf->anyuserid) { | |
| if (!strcmp(arg, "*")) { | |
| conf->anyuserid = 1; | |
| } | |
| else { | |
| first = conf->users; | |
| conf->users = apr_palloc(cmd->pool, sizeof(*conf->users)); | |
| conf->users->user = arg; | |
| conf->users->next = first; | |
| } | |
| } | |
| return NULL; | |
| } | |
| static const command_rec authn_anon_cmds[] = | |
| { | |
| AP_INIT_ITERATE("Anonymous", anon_set_string_slots, NULL, OR_AUTHCFG, | |
| "a space-separated list of user IDs"), | |
| AP_INIT_FLAG("Anonymous_MustGiveEmail", ap_set_flag_slot, | |
| (void *)APR_OFFSETOF(authn_anon_config_rec, mustemail), | |
| OR_AUTHCFG, "Limited to 'on' or 'off'"), | |
| AP_INIT_FLAG("Anonymous_NoUserId", ap_set_flag_slot, | |
| (void *)APR_OFFSETOF(authn_anon_config_rec, nouserid), | |
| OR_AUTHCFG, "Limited to 'on' or 'off'"), | |
| AP_INIT_FLAG("Anonymous_VerifyEmail", ap_set_flag_slot, | |
| (void *)APR_OFFSETOF(authn_anon_config_rec, verifyemail), | |
| OR_AUTHCFG, "Limited to 'on' or 'off'"), | |
| AP_INIT_FLAG("Anonymous_LogEmail", ap_set_flag_slot, | |
| (void *)APR_OFFSETOF(authn_anon_config_rec, logemail), | |
| OR_AUTHCFG, "Limited to 'on' or 'off'"), | |
| {NULL} | |
| }; | |
| module AP_MODULE_DECLARE_DATA authn_anon_module; | |
| static authn_status check_anonymous(request_rec *r, const char *user, | |
| const char *sent_pw) | |
| { | |
| authn_anon_config_rec *conf = ap_get_module_config(r->per_dir_config, | |
| &authn_anon_module); | |
| authn_status res = AUTH_USER_NOT_FOUND; | |
| /* Ignore if we are not configured */ | |
| if (!conf->users && !conf->anyuserid) { | |
| return AUTH_USER_NOT_FOUND; | |
| } | |
| /* Do we allow an empty userID and/or is it the magic one | |
| */ | |
| if (!*user) { | |
| if (conf->nouserid) { | |
| res = AUTH_USER_FOUND; | |
| } | |
| } | |
| else if (conf->anyuserid) { | |
| res = AUTH_USER_FOUND; | |
| } | |
| else { | |
| anon_auth_user *p = conf->users; | |
| while (p) { | |
| if (!strcasecmp(user, p->user)) { | |
| res = AUTH_USER_FOUND; | |
| break; | |
| } | |
| p = p->next; | |
| } | |
| } | |
| /* Now if the supplied user-ID was ok, grant access if: | |
| * (a) no passwd was sent and no password and no verification | |
| * were configured. | |
| * (b) password was sent and no verification was configured | |
| * (c) verification was configured and the password (sent or not) | |
| * looks like an email address | |
| */ | |
| if ( (res == AUTH_USER_FOUND) | |
| && (!conf->mustemail || *sent_pw) | |
| && ( !conf->verifyemail | |
| || (ap_strchr_c(sent_pw, '@') && ap_strchr_c(sent_pw, '.')))) | |
| { | |
| if (conf->logemail && ap_is_initial_req(r)) { | |
| ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, APLOGNO(01672) | |
| "Anonymous: Passwd <%s> Accepted", | |
| sent_pw ? sent_pw : "\'none\'"); | |
| } | |
| return AUTH_GRANTED; | |
| } | |
| return (res == AUTH_USER_NOT_FOUND ? res : AUTH_DENIED); | |
| } | |
| static const authn_provider authn_anon_provider = | |
| { | |
| &check_anonymous, | |
| NULL | |
| }; | |
| static void register_hooks(apr_pool_t *p) | |
| { | |
| ap_register_auth_provider(p, AUTHN_PROVIDER_GROUP, "anon", | |
| AUTHN_PROVIDER_VERSION, | |
| &authn_anon_provider, AP_AUTH_INTERNAL_PER_CONF); | |
| } | |
| AP_DECLARE_MODULE(authn_anon) = | |
| { | |
| STANDARD20_MODULE_STUFF, | |
| create_authn_anon_dir_config, /* dir config creater */ | |
| NULL, /* dir merger ensure strictness */ | |
| NULL, /* server config */ | |
| NULL, /* merge server config */ | |
| authn_anon_cmds, /* command apr_table_t */ | |
| register_hooks /* register hooks */ | |
| }; |