186757afe51933be3d2246dc77befa34c7dfc4da
[openafs.git] / src / auth / userok.c
1 /* Copyright (C) 1990, 1998 Transarc Corporation - All rights reserved */
2 /*
3  * (C) COPYRIGHT IBM CORPORATION 1988, 1989
4  * LICENSED MATERIALS - PROPERTY OF IBM
5  */
6 /*
7  * Revision 2.3  91/08/09  18:10:56
8  * added a new param to afsconf_SuperUser
9  * 
10  * Revision 2.2  90/08/29  15:10:43
11  * Cleanups.
12  * Reject security index #1: rxvab/bcrypt.
13  * 
14  * Revision 2.1  90/08/07  18:52:21
15  * Start with clean version to sync test and dev trees.
16  * */
17
18 #include <afs/param.h>
19 #include <afs/stds.h>
20 #include <afs/pthread_glock.h>
21 #include <sys/types.h>
22 #ifdef AFS_NT40_ENV
23 #include <winsock2.h>
24 #include <fcntl.h>
25 #include <io.h>
26 #else
27 #include <sys/file.h>
28 #include <netinet/in.h>
29 #include <netdb.h>
30 #endif
31 #include <sys/stat.h>
32 #include <stdlib.h>     /* for realpath() */
33 #include <errno.h>
34
35 #include <rx/xdr.h>
36 #include <rx/rx.h>
37 #include <stdio.h>
38 #include <afs/afsutil.h>
39 #include <afs/fileutil.h>
40
41 #ifdef AFS_ATHENA_STDENV
42 #include <krb.h>
43 #endif
44
45 #include "auth.h"
46 #include "cellconfig.h"
47 #include "keys.h"
48 #include "afs/audit.h"
49
50
51 static GetNoAuthFlag(adir)
52 struct afsconf_dir *adir; {
53     if (access(AFSDIR_SERVER_NOAUTH_FILEPATH, 0) == 0) {
54         osi_audit ( NoAuthEvent, 0, AUD_END ); /* some random server is running noauth */
55         return 1;   /* if /usr/afs/local/NoAuth file exists, allow access */
56       }
57     return 0;
58 }
59
60
61 afsconf_GetNoAuthFlag(adir)
62 struct afsconf_dir *adir; {
63     int rc;
64
65     LOCK_GLOBAL_MUTEX
66     rc = GetNoAuthFlag(adir);
67     UNLOCK_GLOBAL_MUTEX
68     return rc;
69 }
70
71 afsconf_SetNoAuthFlag(adir, aflag)
72 struct afsconf_dir *adir;
73 int aflag; {
74     register afs_int32 code;
75     
76     LOCK_GLOBAL_MUTEX
77
78     if (aflag == 0) {
79         /* turn off noauth flag */
80         code = ( unlink(AFSDIR_SERVER_NOAUTH_FILEPATH) ? errno : 0 );
81         osi_audit ( NoAuthDisableEvent, code, AUD_END ); 
82     }
83     else {
84         /* try to create file */
85         code = open(AFSDIR_SERVER_NOAUTH_FILEPATH, O_CREAT | O_TRUNC | O_RDWR, 0666);
86         if (code >= 0) { 
87           close(code);
88           osi_audit ( NoAuthEnableEvent, 0, AUD_END ); 
89         }
90         else 
91           osi_audit ( NoAuthEnableEvent, errno, AUD_END ); 
92     }
93     UNLOCK_GLOBAL_MUTEX
94 }
95
96 /* deletes a user from the UserList file */
97 afsconf_DeleteUser(adir, auser)
98 struct afsconf_dir *adir;
99 register char *auser; {
100     char tbuffer[1024];
101     char nbuffer[1024];
102     register FILE *tf;
103     register FILE *nf;
104     register int flag;
105     char tname[64];
106     char *tp;
107     int found;
108     struct stat tstat;
109     register afs_int32 code;
110
111     LOCK_GLOBAL_MUTEX
112     strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE, NULL);
113 #ifndef AFS_NT40_ENV
114     {
115         /*
116          * We attempt to fully resolve this pathname, so that the rename
117          * of the temporary file will work even if UserList is a symlink
118          * into a different filesystem.
119          */
120         char resolved_path[1024];
121
122         if (realpath(tbuffer, resolved_path)) {
123             strcpy(tbuffer, resolved_path);
124         }
125     }
126 #endif /* AFS_NT40_ENV */
127     tf = fopen(tbuffer, "r");
128     if (!tf) {
129         UNLOCK_GLOBAL_MUTEX
130         return -1;
131     }
132     code = stat(tbuffer, &tstat);
133     if (code < 0) {
134         UNLOCK_GLOBAL_MUTEX
135         return code;
136     }
137     strcpy(nbuffer, tbuffer);
138     strcat(nbuffer, ".NXX");
139     nf = fopen(nbuffer, "w+");
140     if (!nf) {
141         fclose(tf);
142         UNLOCK_GLOBAL_MUTEX
143         return EIO;
144     }
145     flag = 0;
146     found = 0;
147     while (1) {
148         /* check for our user id */
149         tp = fgets(nbuffer, sizeof(nbuffer), tf);
150         if (tp == (char *)0) break;
151         code = sscanf(nbuffer, "%64s", tname);
152         if (code == 1 && strcmp(tname, auser) == 0) {
153             /* found the guy, don't copy to output file */
154             found = 1;
155         }
156         else {
157             /* otherwise copy original line  to output */
158             fprintf(nf, "%s", nbuffer);
159         }
160     }
161     fclose(tf);
162     if (ferror(nf)) flag = 1;
163     if (fclose(nf) == EOF) flag = 1;
164     strcpy(nbuffer, tbuffer);
165     strcat(nbuffer, ".NXX");    /* generate new file name again */
166     if (flag == 0) {
167         /* try the rename */
168         flag = renamefile(nbuffer, tbuffer);
169         if (flag == 0)
170             flag = chmod(tbuffer, tstat.st_mode);
171     }
172     else unlink(nbuffer);
173
174     /* finally, decide what to return to the caller */
175     UNLOCK_GLOBAL_MUTEX
176     if (flag) return EIO;       /* something mysterious went wrong */
177     if (!found) return ENOENT;  /* entry wasn't found, no changes made */
178     return 0;                   /* everything was fine */
179 }
180
181 /* returns nth super user from the UserList file */
182 afsconf_GetNthUser(adir, an, abuffer, abufferLen)
183 struct afsconf_dir *adir;
184 afs_int32 an;
185 char *abuffer;
186 afs_int32 abufferLen; {
187     char tbuffer[256];
188     register FILE *tf;
189     char tname[64];
190     register char *tp;
191     register int flag;
192     register afs_int32 code;
193
194     LOCK_GLOBAL_MUTEX
195     strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE, NULL);
196     tf = fopen(tbuffer, "r");
197     if (!tf) {
198         UNLOCK_GLOBAL_MUTEX
199         return 1;
200     }
201     flag = 1;
202     while (1) {
203         /* check for our user id */
204         tp = fgets(tbuffer, sizeof(tbuffer), tf);
205         if (tp == (char *)0) break;
206         code = sscanf(tbuffer, "%64s", tname);
207         if (code == 1 && an-- == 0) {
208             flag = 0;
209             break;
210         }
211     }
212     if (flag == 0) strcpy(abuffer, tname);
213     fclose(tf);
214     UNLOCK_GLOBAL_MUTEX
215     return flag;
216 }
217
218 /* returns true iff user is in the UserList file */
219 static FindUser(adir, auser)
220 struct afsconf_dir *adir;
221 register char *auser; {
222     char tbuffer[256];
223     register bufio_p bp;
224     char tname[64];
225     register char *tp;
226     register int flag;
227     register afs_int32 code;
228     int rc;
229
230     strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE, NULL);
231     bp = BufioOpen(tbuffer, O_RDONLY, 0);
232     if (!bp) return 0;
233     flag = 0;
234     while (1) {
235         /* check for our user id */
236         rc = BufioGets(bp, tbuffer, sizeof(tbuffer));
237         if (rc < 0) break;
238         code = sscanf(tbuffer, "%64s", tname);
239         if (code == 1 && strcmp(tname, auser) == 0) {
240             flag = 1;
241             break;
242         }
243     }
244     BufioClose(bp);
245     return flag;
246 }
247
248 /* add a user to the user list, checking for duplicates */
249 afsconf_AddUser(adir, aname)
250 struct afsconf_dir *adir;
251 char *aname; {
252     FILE *tf;
253     register afs_int32 code;
254     char tbuffer[256];
255
256     LOCK_GLOBAL_MUTEX
257     if (FindUser(adir, aname)) {
258         UNLOCK_GLOBAL_MUTEX
259         return EEXIST;  /* already in the list */
260     }
261
262     strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE, NULL);
263     tf = fopen(tbuffer, "a+");
264     if (!tf) {
265         UNLOCK_GLOBAL_MUTEX
266         return EIO;
267     }
268     fprintf(tf, "%s\n", aname);
269     code = 0;
270     if (ferror(tf)) code = EIO;
271     if (fclose(tf)) code = EIO;
272     UNLOCK_GLOBAL_MUTEX
273     return code;
274 }
275
276 /* make sure user authenticated on rx call acall is in list of valid
277     users.
278 */
279 afsconf_SuperUser(adir, acall, namep)
280 struct afsconf_dir *adir;
281 struct rx_call *acall;
282 char *namep; {
283     register struct rx_connection *tconn;
284     register afs_int32 code;
285     int flag;
286
287     LOCK_GLOBAL_MUTEX
288     if (!adir) {
289         UNLOCK_GLOBAL_MUTEX
290         return 0;
291     }
292     if (afsconf_GetNoAuthFlag(adir)) {
293         if (namep) strcpy(namep, "<noauth>");
294         UNLOCK_GLOBAL_MUTEX
295         return 1;
296     }
297     tconn = rx_ConnectionOf(acall);
298     code = rx_SecurityClassOf(tconn);
299     if (code == 0) {
300         UNLOCK_GLOBAL_MUTEX
301         return 0;           /* not authenticated at all, answer is no */
302     }
303     else if (code == 1) {
304         /* bcrypt tokens */
305         UNLOCK_GLOBAL_MUTEX
306         return 0;                       /* not supported any longer */
307     }
308     else if (code == 2) {
309         char tname[MAXKTCNAMELEN];      /* authentication from ticket */
310         char tinst[MAXKTCNAMELEN];
311         char tcell[MAXKTCREALMLEN];
312         char uname[MAXKTCNAMELEN];      /* name.instance */
313         int  ilen;                      /* length of instance */
314         afs_uint32 exp;
315         static char localcellname[MAXCELLCHARS] = "";
316 #if     defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
317         static char local_realm[AFS_REALM_SZ] = "";
318 #endif
319         
320         /* des tokens */
321         code = rxkad_GetServerInfo
322             (acall->conn, (afs_int32 *) 0, &exp, tname, tinst, tcell, (afs_int32 *) 0);
323         if (code) {
324             UNLOCK_GLOBAL_MUTEX
325             return 0; /* bogus */
326         }
327
328         if (strlen (tcell)) {
329             if (!localcellname[0])
330                 afsconf_GetLocalCell
331                     (adir, localcellname, sizeof(localcellname));
332 #if     defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV)
333             if (!local_realm[0]) {
334                 if (afs_krb_get_lrealm(local_realm, 0) != 0/*KSUCCESS*/)
335                     strncpy(local_realm, localcellname, AFS_REALM_SZ);
336             }
337             if (strcasecmp(local_realm, tcell) &&
338                (strcasecmp(localcellname, tcell)))
339 #else
340             if (strcasecmp(localcellname, tcell))
341 #endif
342                 {
343                     UNLOCK_GLOBAL_MUTEX
344                     return 0;
345                 }
346         }
347         ilen = strlen(tinst);
348         strncpy (uname, tname, sizeof(uname));
349         if (ilen) {
350             if (strlen(uname) + 1 + ilen >= sizeof(uname)) {
351                 UNLOCK_GLOBAL_MUTEX
352                 return 0;
353             }
354             strcat (uname, ".");
355             strcat (uname, tinst);
356         }
357
358 #ifdef AFS_PTHREAD_ENV
359         if (exp < clock_Sec()) {
360 #else
361         if (exp < FT_ApproxTime()) {
362 #endif
363             UNLOCK_GLOBAL_MUTEX
364             return 0;   /* expired tix */
365         }
366         if (strcmp(AUTH_SUPERUSER, uname) == 0) flag = 1;
367         else flag = FindUser(adir, uname);      /* true iff in userlist file */
368         if (namep)
369             strcpy(namep, uname);
370         UNLOCK_GLOBAL_MUTEX
371         return flag;
372     }
373     else {
374         UNLOCK_GLOBAL_MUTEX
375         return  0;          /* mysterious, just say no */
376     }
377 }