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 * Adapted to allow anonymous logins, just like with Anon-FTP, when 19 * one gives the magic user name 'anonymous' and ones email address 20 * as the password. 21 * 22 * Just add the following tokes to your <directory> setup: 23 * 24 * Anonymous magic-userid [magic-userid]... 25 * 26 * Anonymous_MustGiveEmail [ on | off ] default = on 27 * Anonymous_LogEmail [ on | off ] default = on 28 * Anonymous_VerifyEmail [ on | off ] default = off 29 * Anonymous_NoUserId [ on | off ] default = off 30 * 31 * The magic user id is something like 'anonymous', it is NOT case sensitive. 32 * 33 * The MustGiveEmail flag can be used to force users to enter something 34 * in the password field (like an email address). Default is on. 35 * 36 * Furthermore the 'NoUserID' flag can be set to allow completely empty 37 * usernames in as well; this can be is convenient as a single return 38 * in broken GUIs like W95 is often given by the user. The Default is off. 39 * 40 * Dirk.vanGulik@jrc.it; http://ewse.ceo.org; http://me-www.jrc.it/~dirkx 41 * 42 */ 43 44#include "apr_strings.h" 45 46#define APR_WANT_STRFUNC 47#include "apr_want.h" 48 49#include "ap_provider.h" 50#include "httpd.h" 51#include "http_config.h" 52#include "http_core.h" 53#include "http_log.h" 54#include "http_request.h" 55#include "http_protocol.h" 56 57#include "mod_auth.h" 58 59typedef struct anon_auth_user { 60 char *user; 61 struct anon_auth_user *next; 62} anon_auth_user; 63 64typedef struct { 65 anon_auth_user *users; 66 int nouserid; 67 int logemail; 68 int verifyemail; 69 int mustemail; 70 int anyuserid; 71} authn_anon_config_rec; 72 73static void *create_authn_anon_dir_config(apr_pool_t *p, char *d) 74{ 75 authn_anon_config_rec *conf = apr_palloc(p, sizeof(*conf)); 76 77 /* just to illustrate the defaults really. */ 78 conf->users = NULL; 79 80 conf->nouserid = 0; 81 conf->anyuserid = 0; 82 conf->logemail = 1; 83 conf->verifyemail = 0; 84 conf->mustemail = 1; 85 return conf; 86} 87 88static const char *anon_set_string_slots(cmd_parms *cmd, 89 void *my_config, const char *arg) 90{ 91 authn_anon_config_rec *conf = my_config; 92 anon_auth_user *first; 93 94 if (!*arg) { 95 return "Anonymous string cannot be empty, use Anonymous_NoUserId"; 96 } 97 98 /* squeeze in a record */ 99 if (!conf->anyuserid) { 100 if (!strcmp(arg, "*")) { 101 conf->anyuserid = 1; 102 } 103 else { 104 first = conf->users; 105 conf->users = apr_palloc(cmd->pool, sizeof(*conf->users)); 106 conf->users->user = apr_pstrdup(cmd->pool, arg); 107 conf->users->next = first; 108 } 109 } 110 111 return NULL; 112} 113 114static const command_rec authn_anon_cmds[] = 115{ 116 AP_INIT_ITERATE("Anonymous", anon_set_string_slots, NULL, OR_AUTHCFG, 117 "a space-separated list of user IDs"), 118 AP_INIT_FLAG("Anonymous_MustGiveEmail", ap_set_flag_slot, 119 (void *)APR_OFFSETOF(authn_anon_config_rec, mustemail), 120 OR_AUTHCFG, "Limited to 'on' or 'off'"), 121 AP_INIT_FLAG("Anonymous_NoUserId", ap_set_flag_slot, 122 (void *)APR_OFFSETOF(authn_anon_config_rec, nouserid), 123 OR_AUTHCFG, "Limited to 'on' or 'off'"), 124 AP_INIT_FLAG("Anonymous_VerifyEmail", ap_set_flag_slot, 125 (void *)APR_OFFSETOF(authn_anon_config_rec, verifyemail), 126 OR_AUTHCFG, "Limited to 'on' or 'off'"), 127 AP_INIT_FLAG("Anonymous_LogEmail", ap_set_flag_slot, 128 (void *)APR_OFFSETOF(authn_anon_config_rec, logemail), 129 OR_AUTHCFG, "Limited to 'on' or 'off'"), 130 {NULL} 131}; 132 133module AP_MODULE_DECLARE_DATA authn_anon_module; 134 135static authn_status check_anonymous(request_rec *r, const char *user, 136 const char *sent_pw) 137{ 138 authn_anon_config_rec *conf = ap_get_module_config(r->per_dir_config, 139 &authn_anon_module); 140 authn_status res = AUTH_USER_NOT_FOUND; 141 142 /* Ignore if we are not configured */ 143 if (!conf->users && !conf->anyuserid) { 144 return AUTH_USER_NOT_FOUND; 145 } 146 147 /* Do we allow an empty userID and/or is it the magic one 148 */ 149 if (!*user) { 150 if (conf->nouserid) { 151 res = AUTH_USER_FOUND; 152 } 153 } 154 else if (conf->anyuserid) { 155 res = AUTH_USER_FOUND; 156 } 157 else { 158 anon_auth_user *p = conf->users; 159 160 while (p) { 161 if (!strcasecmp(user, p->user)) { 162 res = AUTH_USER_FOUND; 163 break; 164 } 165 p = p->next; 166 } 167 } 168 169 /* Now if the supplied user-ID was ok, grant access if: 170 * (a) no passwd was sent and no password and no verification 171 * were configured. 172 * (b) password was sent and no verification was configured 173 * (c) verification was configured and the password (sent or not) 174 * looks like an email address 175 */ 176 if ( (res == AUTH_USER_FOUND) 177 && (!conf->mustemail || *sent_pw) 178 && ( !conf->verifyemail 179 || (ap_strchr_c(sent_pw, '@') && ap_strchr_c(sent_pw, '.')))) 180 { 181 if (conf->logemail && ap_is_initial_req(r)) { 182 ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, 183 "Anonymous: Passwd <%s> Accepted", 184 sent_pw ? sent_pw : "\'none\'"); 185 } 186 187 return AUTH_GRANTED; 188 } 189 190 return (res == AUTH_USER_NOT_FOUND ? res : AUTH_DENIED); 191} 192 193static const authn_provider authn_anon_provider = 194{ 195 &check_anonymous, 196 NULL 197}; 198 199static void register_hooks(apr_pool_t *p) 200{ 201 ap_register_provider(p, AUTHN_PROVIDER_GROUP, "anon", "0", 202 &authn_anon_provider); 203} 204 205module AP_MODULE_DECLARE_DATA authn_anon_module = 206{ 207 STANDARD20_MODULE_STUFF, 208 create_authn_anon_dir_config, /* dir config creater */ 209 NULL, /* dir merger ensure strictness */ 210 NULL, /* server config */ 211 NULL, /* merge server config */ 212 authn_anon_cmds, /* command apr_table_t */ 213 register_hooks /* register hooks */ 214}; 215