]> git.pld-linux.org Git - packages/apache1-mod_auth_yp.git/blob - mod_auth_yp.c
- apxs1 in apache1-devel now
[packages/apache1-mod_auth_yp.git] / mod_auth_yp.c
1 /*
2  * Authenticates user names/passwords and
3  * user names/groups through NIS (Yellow Pages).
4  *
5  * July 1999
6  * Ian Prideaux
7  */
8
9 /*
10  * http_auth: authentication
11  * 
12  * Rob McCool
13  * 
14  * Adapted to Apache by rst.
15  *
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.
21  */
22
23 #include <rpc/rpc.h>
24 #include <rpcsvc/ypclnt.h>
25 #include <rpcsvc/yp_prot.h>
26
27 #include "httpd.h"
28 #include "http_config.h"
29 #include "http_core.h"
30 #include "http_log.h"
31 #include "http_protocol.h"
32 #include "ap_md5.h"
33
34 typedef struct auth_yp_config_struct {
35     char *auth_yp_domain;
36     char *auth_yp_pwtable;
37     char *auth_yp_grptable;
38     int auth_yp_authoritative;
39         int auth_yp;
40 } auth_yp_config_rec;
41
42 static void *create_auth_yp_dir_config(pool *p, char *d)
43 {
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 */
50         sec->auth_yp = NULL;
51     return sec;
52 }
53
54 static const char *set_auth_yp_slot(cmd_parms *cmd, void *offset, char *f, char *t)
55 {
56 if (t && strcmp(t, "standard"))
57         return ap_pstrcat(cmd->pool, "Invalid auth file type: ", t, NULL);
58
59 return ap_set_file_slot(cmd, offset, f);
60 }
61
62 static const command_rec auth_yp_cmds[] =
63 {
64         {"AuthYPDomain", set_auth_yp_slot,
65          (void *) XtOffsetOf(auth_yp_config_rec, auth_yp_domain), OR_AUTHCFG, TAKE1,
66          "NIS domain name"},
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),
75          OR_AUTHCFG, FLAG,
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)"},
80         {NULL}
81 };
82
83 module MODULE_VAR_EXPORT auth_yp_module;
84
85 static char *get_yp_domain(request_rec *r, char *auth_yp_domain)
86 {
87 char *domainname;
88 int err;
89
90 if(auth_yp_domain)      return(auth_yp_domain);
91
92 err=yp_get_default_domain(&domainname);
93 if(err == 0)
94         {
95         return(domainname);
96         }
97 else
98         {
99         ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "%s", yperr_string(err) );
100         return NULL;
101         }
102 }
103
104 static char *user_in_yp_group(request_rec *r, const char *group_to_check, char *auth_yp_grptable, char *auth_yp_domain)
105 {
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;
110
111 domainname=get_yp_domain(r, auth_yp_domain);
112 if(!domainname) return NULL;
113
114 if(!auth_yp_grptable)   auth_yp_grptable="group.byname";
115
116 err=yp_match(domainname, auth_yp_grptable, group_to_check, strlen(group_to_check), &value, &valuelen);
117 if(err != 0)
118         {
119         ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "%s", yperr_string(err) );
120         return NULL;
121         }
122
123 strncpy(groupline, value, valuelen);
124 groupline[valuelen]=(char)NULL;
125 for(colons=3, groups=groupline; colons; groups++)
126         if(*groups == ':')      colons--;
127
128 while(isprint((int)*groups))
129         {
130         unameidx=0;
131         while(isprint((int)*groups) && *groups != ',')
132                 {
133                 uname[unameidx++]=*groups++;
134                 }
135         groups++;
136         uname[unameidx++]=(char)NULL;
137         printf("%s\n", uname);
138  
139         if(!strcmp(user, uname))
140                 {
141                 /* printf("Found %s\n", argv[2]); */
142                 return group_to_check;
143                 }
144         }
145 /* printf("Unable to find %s\n", argv[2]); */
146 return NULL;
147 }
148
149 static char *get_pw(request_rec *r, char *user, char *auth_yp_pwtable, char *auth_yp_domain)
150 {
151 char *domainname, *value, *passwd, *passwdend;
152 char passwdline[MAX_STRING_LEN];
153 int err, valuelen;
154
155 domainname=get_yp_domain(r, auth_yp_domain);
156 if(!domainname) return NULL;
157
158 if(!auth_yp_pwtable)    auth_yp_pwtable="passwd.byname";
159 err=yp_match(domainname, auth_yp_pwtable, user, strlen(user), &value, &valuelen);
160 if(err != 0)
161         {
162         ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "%s", yperr_string(err) );
163         return NULL;
164         }
165  
166 strcpy(passwdline, value);
167  
168 for(passwd=passwdline; *passwd!=':'; passwd++);
169 passwd++;
170  
171 for(passwdend=passwd; *passwdend!=':'; passwdend++);
172 *passwdend=(char)NULL;
173  
174 return ap_pstrdup (r->pool, passwd);
175 }
176
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.
181  *
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
184  * reported as such.
185  */
186
187 /* Determine user ID, and check if it really is that user, for HTTP
188  * basic authentication...
189  */
190
191 static int authenticate_basic_user(request_rec *r)
192 {
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;
196     const char *sent_pw;
197     char *real_pw;
198     char *invalid_pw;
199     int res;
200
201     if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
202         return res;
203
204     /* If YP is not enabled - IanP */
205     if(!sec->auth_yp)   return DECLINED;
206
207     if (!(real_pw = get_pw(r, c->user, sec->auth_yp_pwtable, sec->auth_yp_domain))) {
208         if (!(sec->auth_yp_authoritative))
209             return DECLINED;
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;
214     }
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;
222     }
223     return OK;
224 }
225
226 /* Checking ID */
227
228 static int check_user_access(request_rec *r)
229 {
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;
235     register int x;
236     const char *t, *w;
237     table *grpstatus;
238     const array_header *reqs_arr = ap_requires(r);
239     require_line *reqs;
240
241     /* If YP is not enabled - IanP */
242     if(!sec->auth_yp)   return DECLINED;
243
244     /* BUG FIX: tadc, 11-Nov-1995.  If there is no "requires" directive, 
245      * then any user will do.
246      */
247     if (!reqs_arr)      return (OK);
248
249     reqs = (require_line *) reqs_arr->elts;
250
251     for (x = 0; x < reqs_arr->nelts; x++) {
252
253         if (!(reqs[x].method_mask & (1 << m)))
254             continue;
255
256         method_restricted = 1;
257
258         t = reqs[x].requirement;
259         w = ap_getword_white(r->pool, &t);
260         if (!strcmp(w, "valid-user"))
261             return OK;
262         if (!strcmp(w, "user")) {
263             while (t[0]) {
264                 w = ap_getword_conf(r->pool, &t);
265                 if (!strcmp(user, w))
266                     return OK;
267             }
268         }
269         else if (!strcmp(w, "group")) {
270             /* if (!grpstatus)
271                 return DECLINED;        /* DBM group?  Something else? */
272
273             while (t[0]) {
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))
277                         return OK;
278             }
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.
285              */
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);
289         }
290     }
291
292     if (!method_restricted)
293         return OK;
294
295     if (!(sec->auth_yp_authoritative))
296         return DECLINED;
297
298     ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,
299         "access to %s failed, reason: user %s not allowed access",
300         r->uri, user);
301         
302     ap_note_basic_auth_failure(r);
303     return AUTH_REQUIRED;
304 }
305
306 module MODULE_VAR_EXPORT auth_yp_module =
307 {
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 */
315     NULL,                       /* handlers */
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 */
321     NULL,                       /* fixups */
322     NULL,                       /* logger */
323     NULL,                       /* header parser */
324     NULL,                       /* child_init */
325     NULL,                       /* child_exit */
326     NULL                        /* post read-request */
327 };
This page took 0.084527 seconds and 3 git commands to generate.