2 * Authenticates user names/passwords and
3 * user names/groups through NIS (Yellow Pages).
10 * http_auth: authentication
14 * Adapted to Apache by rst.
16 * dirkx - Added Authoritative control to allow passing on to lower
17 * modules if and only if the user-id is not known to this
18 * module. A known user with a faulty or absent password still
19 * causes an AuthRequired. The default is 'Authoritative', i.e.
20 * no control is passed along.
24 #include <rpcsvc/ypclnt.h>
25 #include <rpcsvc/yp_prot.h>
28 #include "http_config.h"
29 #include "http_core.h"
31 #include "http_protocol.h"
34 typedef struct auth_yp_config_struct {
36 char *auth_yp_pwtable;
37 char *auth_yp_grptable;
38 int auth_yp_authoritative;
42 static void *create_auth_yp_dir_config(pool *p, char *d)
44 auth_yp_config_rec *sec =
45 (auth_yp_config_rec *) ap_pcalloc(p, sizeof(auth_yp_config_rec));
46 sec->auth_yp_domain = NULL;
47 sec->auth_yp_pwtable = NULL; /* just to illustrate the default really */
48 sec->auth_yp_grptable = NULL; /* unless you have a broken HP cc */
49 sec->auth_yp_authoritative = 1; /* keep the fortress secure by default */
54 static const char *set_auth_yp_slot(cmd_parms *cmd, void *offset, char *f, char *t)
56 if (t && strcmp(t, "standard"))
57 return ap_pstrcat(cmd->pool, "Invalid auth file type: ", t, NULL);
59 return ap_set_file_slot(cmd, offset, f);
62 static const command_rec auth_yp_cmds[] =
64 {"AuthYPDomain", set_auth_yp_slot,
65 (void *) XtOffsetOf(auth_yp_config_rec, auth_yp_domain), OR_AUTHCFG, TAKE1,
67 {"AuthYPUserTable", set_auth_yp_slot,
68 (void *) XtOffsetOf(auth_yp_config_rec, auth_yp_pwtable), OR_AUTHCFG, TAKE1,
69 "NIS table containing user IDs and passwords"},
70 {"AuthYPGroupTable", set_auth_yp_slot,
71 (void *) XtOffsetOf(auth_yp_config_rec, auth_yp_grptable), OR_AUTHCFG, TAKE1,
72 "NIS table containing group names and member user IDs"},
73 {"AuthYPAuthoritative", ap_set_flag_slot,
74 (void *) XtOffsetOf(auth_yp_config_rec, auth_yp_authoritative),
76 "Set to 'no' to allow access control to be passed along to lower modules if the UserID is not known to this module"},
77 {"AuthYP", ap_set_flag_slot,
78 (void*)XtOffsetOf(auth_yp_config_rec, auth_yp), OR_AUTHCFG, FLAG,
79 "Authenticate user using yp (nis)"},
83 module MODULE_VAR_EXPORT auth_yp_module;
85 static char *get_yp_domain(request_rec *r, char *auth_yp_domain)
90 if(auth_yp_domain) return(auth_yp_domain);
92 err=yp_get_default_domain(&domainname);
99 ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "%s", yperr_string(err) );
104 static char *user_in_yp_group(request_rec *r, const char *group_to_check, char *auth_yp_grptable, char *auth_yp_domain)
106 char *user=r->connection->user;
107 char *domainname, *value, *groups;
108 char groupline[MAX_STRING_LEN], uname[MAX_STRING_LEN];
109 int err, valuelen, unameidx, colons;
111 domainname=get_yp_domain(r, auth_yp_domain);
112 if(!domainname) return NULL;
114 if(!auth_yp_grptable) auth_yp_grptable="group.byname";
116 err=yp_match(domainname, auth_yp_grptable, group_to_check, strlen(group_to_check), &value, &valuelen);
119 ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "%s", yperr_string(err) );
123 strncpy(groupline, value, valuelen);
124 groupline[valuelen]=(char)NULL;
125 for(colons=3, groups=groupline; colons; groups++)
126 if(*groups == ':') colons--;
128 while(isprint((int)*groups))
131 while(isprint((int)*groups) && *groups != ',')
133 uname[unameidx++]=*groups++;
136 uname[unameidx++]=(char)NULL;
137 printf("%s\n", uname);
139 if(!strcmp(user, uname))
141 /* printf("Found %s\n", argv[2]); */
142 return group_to_check;
145 /* printf("Unable to find %s\n", argv[2]); */
149 static char *get_pw(request_rec *r, char *user, char *auth_yp_pwtable, char *auth_yp_domain)
151 char *domainname, *value, *passwd, *passwdend;
152 char passwdline[MAX_STRING_LEN];
155 domainname=get_yp_domain(r, auth_yp_domain);
156 if(!domainname) return NULL;
158 if(!auth_yp_pwtable) auth_yp_pwtable="passwd.byname";
159 err=yp_match(domainname, auth_yp_pwtable, user, strlen(user), &value, &valuelen);
162 ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "%s", yperr_string(err) );
166 strcpy(passwdline, value);
168 for(passwd=passwdline; *passwd!=':'; passwd++);
171 for(passwdend=passwd; *passwdend!=':'; passwdend++);
172 *passwdend=(char)NULL;
174 return ap_pstrdup (r->pool, passwd);
177 /* These functions return 0 if client is OK, and proper error status
178 * if not... either AUTH_REQUIRED, if we made a check, and it failed, or
179 * SERVER_ERROR, if things are so totally confused that we couldn't
180 * figure out how to tell if the client is authorized or not.
182 * If they return DECLINED, and all other modules also decline, that's
183 * treated by the server core as a configuration error, logged and
187 /* Determine user ID, and check if it really is that user, for HTTP
188 * basic authentication...
191 static int authenticate_basic_user(request_rec *r)
193 auth_yp_config_rec *sec =
194 (auth_yp_config_rec *) ap_get_module_config(r->per_dir_config, &auth_yp_module);
195 conn_rec *c = r->connection;
201 if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
204 /* If YP is not enabled - IanP */
205 if(!sec->auth_yp) return DECLINED;
207 if (!(real_pw = get_pw(r, c->user, sec->auth_yp_pwtable, sec->auth_yp_domain))) {
208 if (!(sec->auth_yp_authoritative))
210 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
211 "user %s not found: %s", c->user, r->uri);
212 ap_note_basic_auth_failure(r);
213 return AUTH_REQUIRED;
215 invalid_pw = ap_validate_password(sent_pw, real_pw);
216 if (invalid_pw != NULL) {
217 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
218 "user %s: authentication failure for \"%s\": %s",
219 c->user, r->uri, invalid_pw);
220 ap_note_basic_auth_failure(r);
221 return AUTH_REQUIRED;
228 static int check_user_access(request_rec *r)
230 auth_yp_config_rec *sec =
231 (auth_yp_config_rec *) ap_get_module_config(r->per_dir_config, &auth_yp_module);
232 char *user = r->connection->user;
233 int m = r->method_number;
234 int method_restricted = 0;
238 const array_header *reqs_arr = ap_requires(r);
241 /* If YP is not enabled - IanP */
242 if(!sec->auth_yp) return DECLINED;
244 /* BUG FIX: tadc, 11-Nov-1995. If there is no "requires" directive,
245 * then any user will do.
247 if (!reqs_arr) return (OK);
249 reqs = (require_line *) reqs_arr->elts;
251 for (x = 0; x < reqs_arr->nelts; x++) {
253 if (!(reqs[x].method_mask & (1 << m)))
256 method_restricted = 1;
258 t = reqs[x].requirement;
259 w = ap_getword_white(r->pool, &t);
260 if (!strcmp(w, "valid-user"))
262 if (!strcmp(w, "user")) {
264 w = ap_getword_conf(r->pool, &t);
265 if (!strcmp(user, w))
269 else if (!strcmp(w, "group")) {
271 return DECLINED; /* DBM group? Something else? */
274 w = ap_getword_conf(r->pool, &t); /* w=group name - IanP */
275 /* New Function - IanP */
276 if(user_in_yp_group(r, w, sec->auth_yp_grptable, sec->auth_yp_domain))
279 } else if (sec->auth_yp_authoritative) {
280 /* if we aren't authoritative, any require directive could be
281 * valid even if we don't grok it. However, if we are
282 * authoritative, we can warn the user they did something wrong.
283 * That something could be a missing "AuthAuthoritative off", but
284 * more likely is a typo in the require directive.
286 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
287 "access to %s failed, reason: unknown require directive:"
288 "\"%s\"", r->uri, reqs[x].requirement);
292 if (!method_restricted)
295 if (!(sec->auth_yp_authoritative))
298 ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
299 "access to %s failed, reason: user %s not allowed access",
302 ap_note_basic_auth_failure(r);
303 return AUTH_REQUIRED;
306 module MODULE_VAR_EXPORT auth_yp_module =
308 STANDARD_MODULE_STUFF,
309 NULL, /* initializer */
310 create_auth_yp_dir_config, /* dir config creater */
311 NULL, /* dir merger --- default is to override */
312 NULL, /* server config */
313 NULL, /* merge server config */
314 auth_yp_cmds, /* command table */
316 NULL, /* filename translation */
317 authenticate_basic_user, /* check_user_id */
318 check_user_access, /* check auth */
319 NULL, /* check access */
320 NULL, /* type_checker */
323 NULL, /* header parser */
324 NULL, /* child_init */
325 NULL, /* child_exit */
326 NULL /* post read-request */