auth: Let superuser identities be superusers
[openafs.git] / src / auth / userok.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #include <roken.h>
15 #include <afs/opr.h>
16
17 #include <ctype.h>
18
19 #include <afs/pthread_glock.h>
20 #include <rx/xdr.h>
21 #include <rx/rx.h>
22 #include <rx/rx_identity.h>
23 #include <afs/afsutil.h>
24 #include <afs/fileutil.h>
25
26 #include "base64.h"
27 #include "auth.h"
28 #include "cellconfig.h"
29 #include "keys.h"
30 #include "afs/audit.h"
31
32 /* The display names for localauth and noauth identities; they aren't used
33  * inside tickets or anything, but just serve as something to display in logs,
34  * etc. */
35 #define AFS_LOCALAUTH_NAME "<LocalAuth>"
36 #define AFS_LOCALAUTH_LEN  (sizeof(AFS_LOCALAUTH_NAME)-1)
37 #define AFS_NOAUTH_NAME "<NoAuth>"
38 #define AFS_NOAUTH_LEN  (sizeof(AFS_NOAUTH_NAME)-1)
39
40 static int ParseLine(char *buffer, struct rx_identity *user);
41
42 static void
43 UserListFileName(struct afsconf_dir *adir,
44                  char *buffer, size_t len)
45 {
46     strcompose(buffer, len, adir->name, "/", AFSDIR_ULIST_FILE, (char *)NULL);
47 }
48
49 int
50 afsconf_CheckAuth(void *arock, struct rx_call *acall)
51 {
52     struct afsconf_dir *adir = (struct afsconf_dir *) arock;
53     int rc;
54     LOCK_GLOBAL_MUTEX;
55     rc = ((afsconf_SuperUser(adir, acall, NULL) == 0) ? 10029 : 0);
56     UNLOCK_GLOBAL_MUTEX;
57     return rc;
58 }
59
60 static int
61 GetNoAuthFlag(struct afsconf_dir *adir)
62 {
63     if (access(AFSDIR_SERVER_NOAUTH_FILEPATH, 0) == 0) {
64         osi_audit(NoAuthEvent, 0, AUD_END);     /* some random server is running noauth */
65         return 1;               /* if /usr/afs/local/NoAuth file exists, allow access */
66     }
67     return 0;
68 }
69
70
71 int
72 afsconf_GetNoAuthFlag(struct afsconf_dir *adir)
73 {
74     int rc;
75
76     LOCK_GLOBAL_MUTEX;
77     rc = GetNoAuthFlag(adir);
78     UNLOCK_GLOBAL_MUTEX;
79     return rc;
80 }
81
82 void
83 afsconf_SetNoAuthFlag(struct afsconf_dir *adir, int aflag)
84 {
85     afs_int32 code;
86
87     LOCK_GLOBAL_MUTEX;
88     if (aflag == 0) {
89         /* turn off noauth flag */
90         code = (unlink(AFSDIR_SERVER_NOAUTH_FILEPATH) ? errno : 0);
91         osi_audit(NoAuthDisableEvent, code, AUD_END);
92     } else {
93         /* try to create file */
94         code =
95             open(AFSDIR_SERVER_NOAUTH_FILEPATH, O_CREAT | O_TRUNC | O_RDWR,
96                  0666);
97         if (code >= 0) {
98             close(code);
99             osi_audit(NoAuthEnableEvent, 0, AUD_END);
100         } else
101             osi_audit(NoAuthEnableEvent, errno, AUD_END);
102     }
103     UNLOCK_GLOBAL_MUTEX;
104 }
105
106 /*!
107  * Remove an identity from the UserList file
108  *
109  * This function removes the given identity from the user list file.
110  * For the purposes of identifying entries to remove, only the
111  * type and exportedName portions of the identity are used. Callers
112  * should remember that a given identity may be listed in the file in
113  * a number of different ways.
114  *
115  * @param adir
116  *      A structure representing the configuration directory currently
117  *      in use
118  * @param user
119  *      The RX identity to delete
120  *
121  * @returns
122  *      0 on success, an error code on failure
123  */
124
125 int
126 afsconf_DeleteIdentity(struct afsconf_dir *adir, struct rx_identity *user)
127 {
128     char *filename, *nfilename;
129     char *buffer;
130     char *copy;
131     FILE *tf;
132     FILE *nf;
133     int flag;
134     char *tp;
135     int found;
136     struct stat tstat;
137     struct rx_identity identity;
138     afs_int32 code;
139
140     memset(&identity, 0, sizeof(struct rx_identity));
141
142     buffer = malloc(AFSDIR_PATH_MAX);
143     if (buffer == NULL)
144         return ENOMEM;
145     filename = malloc(AFSDIR_PATH_MAX);
146     if (filename == NULL) {
147         free(buffer);
148         return ENOMEM;
149     }
150
151     LOCK_GLOBAL_MUTEX;
152     UserListFileName(adir, filename, AFSDIR_PATH_MAX);
153 #ifndef AFS_NT40_ENV
154     {
155         /*
156          * We attempt to fully resolve this pathname, so that the rename
157          * of the temporary file will work even if UserList is a symlink
158          * into a different filesystem.
159          */
160         nfilename = malloc(AFSDIR_PATH_MAX);
161         if (nfilename == NULL) {
162             UNLOCK_GLOBAL_MUTEX;
163             free(filename);
164             free(buffer);
165             return ENOMEM;
166         }
167         if (realpath(filename, nfilename)) {
168             free(filename);
169             filename = nfilename;
170         } else {
171             free(nfilename);
172         }
173     }
174 #endif /* AFS_NT40_ENV */
175     if (asprintf(&nfilename, "%s.NXX", filename) < 0) {
176         UNLOCK_GLOBAL_MUTEX;
177         free(filename);
178         free(buffer);
179         return -1;
180     }
181     tf = fopen(filename, "r");
182     if (!tf) {
183         UNLOCK_GLOBAL_MUTEX;
184         free(filename);
185         free(nfilename);
186         free(buffer);
187         return -1;
188     }
189     code = stat(filename, &tstat);
190     if (code < 0) {
191         UNLOCK_GLOBAL_MUTEX;
192         free(filename);
193         free(nfilename);
194         free(buffer);
195         return code;
196     }
197     nf = fopen(nfilename, "w+");
198     if (!nf) {
199         fclose(tf);
200         UNLOCK_GLOBAL_MUTEX;
201         free(filename);
202         free(nfilename);
203         free(buffer);
204         return EIO;
205     }
206     flag = 0;
207     found = 0;
208     while (1) {
209         /* check for our user id */
210         tp = fgets(buffer, AFSDIR_PATH_MAX, tf);
211         if (tp == NULL)
212             break;
213
214         copy = strdup(buffer);
215         if (copy == NULL) {
216             flag = 1;
217             break;
218         }
219         code = ParseLine(copy, &identity);
220         if (code == 0 && rx_identity_match(user, &identity)) {
221             /* found the guy, don't copy to output file */
222             found = 1;
223         } else {
224             /* otherwise copy original line to output */
225             fprintf(nf, "%s", buffer);
226         }
227         free(copy);
228         rx_identity_freeContents(&identity);
229     }
230     fclose(tf);
231     free(buffer);
232     if (ferror(nf))
233         flag = 1;
234     if (fclose(nf) == EOF)
235         flag = 1;
236     if (flag == 0) {
237         /* try the rename */
238         flag = rk_rename(nfilename, filename);
239         if (flag == 0)
240             flag = chmod(filename, tstat.st_mode);
241     } else
242         unlink(nfilename);
243
244     /* finally, decide what to return to the caller */
245     UNLOCK_GLOBAL_MUTEX;
246     free(filename);
247     free(nfilename);
248     if (flag)
249         return EIO;             /* something mysterious went wrong */
250     if (!found)
251         return ENOENT;          /* entry wasn't found, no changes made */
252     return 0;                   /* everything was fine */
253 }
254
255 /*!
256  * Remove a legacy Kerberos 4 name from the UserList file.
257  *
258  * This function removes a Kerberos 4 name from the super user list. It
259  * can only remove names which were added by the afsconf_AddUser interface,
260  * or with an explicit Kerberos v4 type.
261  *
262  * @param[in] adir
263  *      A structure representing the configuration directory
264  * @param[in] name
265  *      The Kerberos v4 name to remove
266  *
267  * @returns
268  *      0 on success, an error code upon failure.
269  *
270  * Note that this function is deprecated. New callers should use
271  * afsconf_DeleteIdentity instead.
272  */
273
274 int
275 afsconf_DeleteUser(struct afsconf_dir *adir, char *name)
276 {
277     struct rx_identity *user;
278     int code;
279
280     user = rx_identity_new(RX_ID_KRB4, name, name, strlen(name));
281     if (!user)
282         return ENOMEM;
283
284     code = afsconf_DeleteIdentity(adir, user);
285
286     rx_identity_free(&user);
287
288     return code;
289 }
290
291 /* This is a multi-purpose funciton for use by either
292  * GetNthIdentity or GetNthUser. The parameter 'id' indicates
293  * whether we are counting all identities (if true), or just
294  * ones which can be represented by the old-style interfaces
295  * We return -1 for EOF, 0 for success, and >0 for all errors.
296  */
297 static int
298 GetNthIdentityOrUser(struct afsconf_dir *dir, int count,
299                      struct rx_identity **identity, int id)
300 {
301     bufio_p bp;
302     char *tbuffer;
303     struct rx_identity fileUser;
304     afs_int32 code;
305
306     tbuffer = malloc(AFSDIR_PATH_MAX);
307     if (tbuffer == NULL)
308         return ENOMEM;
309
310     LOCK_GLOBAL_MUTEX;
311     UserListFileName(dir, tbuffer, AFSDIR_PATH_MAX);
312     bp = BufioOpen(tbuffer, O_RDONLY, 0);
313     if (!bp) {
314         UNLOCK_GLOBAL_MUTEX;
315         free(tbuffer);
316         return -1;
317     }
318     while (1) {
319         code = BufioGets(bp, tbuffer, AFSDIR_PATH_MAX);
320         if (code < 0) {
321             code = -1;
322             break;
323         }
324
325         code = ParseLine(tbuffer, &fileUser);
326         if (code != 0)
327             break;
328
329         if (id || fileUser.kind == RX_ID_KRB4)
330             count--;
331
332         if (count < 0)
333             break;
334         else
335             rx_identity_freeContents(&fileUser);
336     }
337     if (code == 0) {
338         *identity = rx_identity_copy(&fileUser);
339         rx_identity_freeContents(&fileUser);
340     }
341
342     BufioClose(bp);
343
344     UNLOCK_GLOBAL_MUTEX;
345     free(tbuffer);
346     return code;
347 }
348
349 /*!
350  * Return the Nth super user identity from the UserList
351  *
352  * @param[in] dir
353  *      A structure representing the configuration directory
354  * @param[in] count
355  *      A count (from zero) of the entries to return from the
356  *      UserList
357  * @param[out] identity
358  *      A pointer to the Nth identity
359  * @returns
360  *      status code
361  * @retval 0 Success
362  * @retval -1 We have searched beyond the end of the list.
363  * @retval >0 Error
364  */
365
366 int
367 afsconf_GetNthIdentity(struct afsconf_dir *dir, int count,
368                        struct rx_identity **identity)
369 {
370    return GetNthIdentityOrUser(dir, count, identity, 1);
371 }
372
373 /*!
374  * Return the Nth Kerberos v4 identity from the UserList
375  *
376  * This returns the Nth old, kerberos v4 style name from
377  * the UserList file. In counting entries it skips any other
378  * name types it encounters - so will hide any new-style
379  * identities from its callers.
380  *
381  * @param[in] dir
382  *      A structure representing the configuration directory
383  * @param[in] count
384  *      A count (from zero) of the entries to return from the
385  *      UserList
386  * @param abuffer
387  *      A string in which to write the name of the Nth identity
388  * @param abufferLen
389  *      The length of the buffer passed in abuffer
390  * @returns
391  *      status code
392  * @retval 0 Success
393  * @retval 1 Either an EPERM error, or we have searched beyond the end of the
394  *           list.
395  * @retval >1 All other errors.
396  *
397  * This function is deprecated, all new callers should use
398  * GetNthIdentity instead. This function is particularly dangerous
399  * as it will hide any new-style identities from callers. It is also
400  * impossible to distinguish an EPERM error from a normal end-of-file
401  * condition with this function.
402  */
403
404 int
405 afsconf_GetNthUser(struct afsconf_dir *adir, afs_int32 an, char *abuffer,
406                    afs_int32 abufferLen)
407 {
408     struct rx_identity *identity;
409     int code;
410
411     code = GetNthIdentityOrUser(adir, an, &identity, 0);
412     if (code == 0) {
413         strlcpy(abuffer, identity->displayName, abufferLen);
414         rx_identity_free(&identity);
415     }
416     if (code == -1) {
417         /* The new functions use -1 to indicate EOF, but the old interface
418          * uses 1 to indicate EOF. */
419         code = 1;
420     }
421     return code;
422 }
423
424 /*!
425  * Parse a UserList list
426  *
427  * Parse a line of data from a UserList file
428  *
429  * This parses a line of data in a UserList, and populates the passed
430  * rx_identity structure with the information about the user.
431  *
432  * @param buffer        A string containing the line to be parsed
433  * @param user          The user structure to be populated
434  *
435  * Note that the user->displayName, and user->exportedName.val fields
436  * must be freed with free() by the caller.
437  *
438  * This function damages the buffer thats passed to it. Callers are
439  * expected to make a copy if they want the buffer preserved.
440  *
441  * @return
442  *      0 on success, non-zero on failure.
443  */
444
445 static int
446 ParseLine(char *buffer, struct rx_identity *user)
447 {
448     char *ptr;
449     char *ename;
450     char *displayName;
451     char *decodedName;
452     char name[64+1];
453     int len;
454     int kind;
455     int code;
456
457     if (buffer[0] == ' ') { /* extended names have leading space */
458         ptr = buffer + 1;
459         code = sscanf(ptr, "%i", &kind);
460         if (code != 1)
461             return EINVAL;
462
463         strsep(&ptr, " "); /* skip the bit we just read with scanf */
464         ename = strsep(&ptr, " "); /* Pull out the ename */
465         displayName = strsep(&ptr, " "); /* Display name runs to the end */
466         if (ename == NULL || displayName == NULL)
467             return EINVAL;
468
469         decodedName = malloc(strlen(ename));
470         if (decodedName == NULL)
471             return ENOMEM;
472
473         len = base64_decode(ename, decodedName);
474         if (len<0) {
475             free(decodedName);
476             return EINVAL;
477         }
478
479         rx_identity_populate(user, kind, displayName, decodedName, len);
480         free(decodedName);
481
482         return 0; /* Success ! */
483     }
484
485     /* No extended name, try for a legacy name */
486     code = sscanf(buffer, "%64s", name);
487     if (code != 1)
488         return EINVAL;
489
490     rx_identity_populate(user, RX_ID_KRB4, name, name, strlen(name));
491     return 0;
492 }
493
494 /*!
495  * Check if a given identity is in the UserList file,
496  * and thus is a super user
497  *
498  * @param adir
499  *      A structure representing the configuration directory to check
500  * @param user
501  *      The identity to check
502  * @returns
503  *      True if the user is listed in the UserList, otherwise false
504  */
505
506 int
507 afsconf_IsSuperIdentity(struct afsconf_dir *adir,
508                         struct rx_identity *user)
509 {
510     bufio_p bp;
511     char *tbuffer;
512     struct rx_identity fileUser;
513     int match;
514     afs_int32 code;
515
516     if (user->kind == RX_ID_SUPERUSER)
517         return 1;
518
519     tbuffer = malloc(AFSDIR_PATH_MAX);
520     if (tbuffer == NULL)
521         return 0;
522
523     UserListFileName(adir, tbuffer, AFSDIR_PATH_MAX);
524     bp = BufioOpen(tbuffer, O_RDONLY, 0);
525     if (!bp) {
526         free(tbuffer);
527         return 0;
528     }
529     match = 0;
530     while (!match) {
531         code = BufioGets(bp, tbuffer, AFSDIR_PATH_MAX);
532         if (code < 0)
533             break;
534
535         code = ParseLine(tbuffer, &fileUser);
536         if (code != 0)
537            break;
538
539         match = rx_identity_match(user, &fileUser);
540
541         rx_identity_freeContents(&fileUser);
542     }
543     BufioClose(bp);
544     free(tbuffer);
545     return match;
546 }
547
548 /* add a user to the user list, checking for duplicates */
549 int
550 afsconf_AddIdentity(struct afsconf_dir *adir, struct rx_identity *user)
551 {
552     FILE *tf;
553     afs_int32 code;
554     char *ename;
555     char *tbuffer;
556
557     LOCK_GLOBAL_MUTEX;
558     if (afsconf_IsSuperIdentity(adir, user)) {
559         UNLOCK_GLOBAL_MUTEX;
560         return EEXIST;          /* already in the list */
561     }
562
563     tbuffer = malloc(AFSDIR_PATH_MAX);
564     UserListFileName(adir, tbuffer, AFSDIR_PATH_MAX);
565     tf = fopen(tbuffer, "a+");
566     free(tbuffer);
567     if (!tf) {
568         UNLOCK_GLOBAL_MUTEX;
569         return EIO;
570     }
571     if (user->kind == RX_ID_KRB4) {
572         fprintf(tf, "%s\n", user->displayName);
573     } else {
574         base64_encode(user->exportedName.val, user->exportedName.len,
575                       &ename);
576         fprintf(tf, " %d %s %s\n", user->kind, ename, user->displayName);
577         free(ename);
578     }
579     code = 0;
580     if (ferror(tf))
581         code = EIO;
582     if (fclose(tf))
583         code = EIO;
584     UNLOCK_GLOBAL_MUTEX;
585     return code;
586 }
587
588 int
589 afsconf_AddUser(struct afsconf_dir *adir, char *aname)
590 {
591     struct rx_identity *user;
592     int code;
593
594     user = rx_identity_new(RX_ID_KRB4, aname, aname, strlen(aname));
595     if (user == NULL)
596         return ENOMEM;
597
598     code = afsconf_AddIdentity(adir, user);
599
600     rx_identity_free(&user);
601
602     return code;
603 }
604
605 /* special CompFindUser routine that builds up a princ and then
606         calls finduser on it. If found, returns char * to user string,
607         otherwise returns NULL. The resulting string should be immediately
608         copied to other storage prior to release of mutex. */
609 static int
610 CompFindUser(struct afsconf_dir *adir, char *name, char *sep, char *inst,
611              char *realm, struct rx_identity **identity)
612 {
613     static char fullname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
614     struct rx_identity *testId;
615
616     /* always must have name */
617     if (!name || !name[0]) {
618         return 0;
619     }
620
621     if (strlcpy(fullname, name, sizeof(fullname)) >= sizeof(fullname))
622         return 0;
623
624     /* might have instance */
625     if (inst && inst[0]) {
626         if (!sep || !sep[0]) {
627             return 0;
628         }
629
630         if (strlcat(fullname, sep, sizeof(fullname)) >= sizeof(fullname))
631             return 0;
632
633         if (strlcat(fullname, inst, sizeof(fullname)) >= sizeof(fullname))
634             return 0;
635     }
636
637     /* might have realm */
638     if (realm && realm[0]) {
639         if (strlcat(fullname, "@", sizeof(fullname)) >= sizeof(fullname))
640             return 0;
641
642         if (strlcat(fullname, realm, sizeof(fullname)) >= sizeof(fullname))
643             return 0;
644     }
645
646     testId = rx_identity_new(RX_ID_KRB4, fullname, fullname, strlen(fullname));
647     if (afsconf_IsSuperIdentity(adir, testId)) {
648         if (identity)
649              *identity = testId;
650         else
651              rx_identity_free(&testId);
652         return 1;
653     }
654
655     rx_identity_free(&testId);
656     return 0;
657 }
658
659 static int
660 kerberosSuperUser(struct afsconf_dir *adir, char *tname, char *tinst,
661                   char *tcell, struct rx_identity **identity)
662 {
663     char tcell_l[MAXKTCREALMLEN] = "";
664     int code;
665     afs_int32 islocal;
666     int flag;
667
668     /* generate lowercased version of cell name */
669     if (tcell)
670         opr_lcstring(tcell_l, tcell, sizeof(tcell_l));
671
672     code = afsconf_IsLocalRealmMatch(adir, &islocal, tname, tinst, tcell);
673     if (code) {
674         return 0;
675     }
676
677     /* start with no authorization */
678     flag = 0;
679
680     /* localauth special case */
681     if ((tinst == NULL || strlen(tinst) == 0) &&
682         (tcell == NULL || strlen(tcell) == 0)
683         && !strcmp(tname, AUTH_SUPERUSER)) {
684         if (identity)
685             *identity = rx_identity_new(RX_ID_KRB4, AFS_LOCALAUTH_NAME,
686                                         AFS_LOCALAUTH_NAME, AFS_LOCALAUTH_LEN);
687         flag = 1;
688
689         /* cell of connection matches local cell or one of the realms */
690     } else if (islocal) {
691         if (CompFindUser(adir, tname, ".", tinst, NULL, identity)) {
692             flag = 1;
693         }
694         /* cell of conn doesn't match local cell or realm */
695     } else {
696         if (CompFindUser(adir, tname, ".", tinst, tcell, identity)) {
697             flag = 1;
698         } else if (CompFindUser(adir, tname, ".", tinst, tcell_l, identity)) {
699             flag = 1;
700         }
701     }
702
703     return flag;
704 }
705
706 static int
707 rxkadSuperUser(struct afsconf_dir *adir, struct rx_call *acall,
708                struct rx_identity **identity)
709 {
710     char tname[MAXKTCNAMELEN];  /* authentication from ticket */
711     char tinst[MAXKTCNAMELEN];
712     char tcell[MAXKTCREALMLEN];
713
714     afs_uint32 exp;
715     int code;
716
717     /* get auth details from server connection */
718     code = rxkad_GetServerInfo(rx_ConnectionOf(acall), NULL, &exp, tname,
719                                tinst, tcell, NULL);
720     if (code)
721         return 0;               /* bogus connection/other error */
722
723     return kerberosSuperUser(adir, tname, tinst, tcell, identity);
724 }
725
726 /*!
727  * Check whether the user authenticated on a given RX call is a super
728  * user or not. If they are, return a pointer to the identity of that
729  * user.
730  *
731  * @param[in] adir
732  *      The configuration directory currently in use
733  * @param[in] acall
734  *      The RX call whose authenticated identity is being checked
735  * @param[out] identity
736  *      The RX identity of the user. Caller must free this structure.
737  * @returns
738  *      True if the user is a super user, or if the server is running
739  *      in noauth mode. Otherwise, false.
740  */
741 afs_int32
742 afsconf_SuperIdentity(struct afsconf_dir *adir, struct rx_call *acall,
743                       struct rx_identity **identity)
744 {
745     struct rx_connection *tconn;
746     afs_int32 code;
747     int flag;
748
749     LOCK_GLOBAL_MUTEX;
750     if (!adir) {
751         UNLOCK_GLOBAL_MUTEX;
752         return 0;
753     }
754
755     if (afsconf_GetNoAuthFlag(adir)) {
756         if (identity)
757             *identity = rx_identity_new(RX_ID_KRB4, AFS_NOAUTH_NAME,
758                                         AFS_NOAUTH_NAME, AFS_NOAUTH_LEN);
759         UNLOCK_GLOBAL_MUTEX;
760         return 1;
761     }
762
763     tconn = rx_ConnectionOf(acall);
764     code = rx_SecurityClassOf(tconn);
765     if (code == RX_SECIDX_NULL) {
766         UNLOCK_GLOBAL_MUTEX;
767         return 0;               /* not authenticated at all, answer is no */
768     } else if (code == RX_SECIDX_VAB) {
769         /* bcrypt tokens */
770         UNLOCK_GLOBAL_MUTEX;
771         return 0;               /* not supported any longer */
772     } else if (code == RX_SECIDX_KAD) {
773         flag = rxkadSuperUser(adir, acall, identity);
774         UNLOCK_GLOBAL_MUTEX;
775         return flag;
776     } else {                    /* some other auth type */
777         UNLOCK_GLOBAL_MUTEX;
778         return 0;               /* mysterious, just say no */
779     }
780 }
781
782 /*!
783  * Check whether the user authenticated on a given RX call is a super
784  * user or not. If they are, return a pointer to the name of that
785  * user.
786  *
787  * @param[in] adir
788  *      The configuration directory currently in use
789  * @param[in] acall
790  *      The RX call whose authenticated identity is being checked
791  * @param[out] namep
792  *      A printable version of the name of the user
793  * @returns
794  *      True if the user is a super user, or if the server is running
795  *      in noauth mode. Otherwise, false.
796  *
797  * This function is provided for backwards compatibility. New callers
798  * should use the afsconf_SuperIdentity function.
799  */
800
801 afs_int32
802 afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall,
803                   char *namep)
804 {
805     struct rx_identity *identity;
806     int ret;
807
808     if (namep) {
809         ret = afsconf_SuperIdentity(adir, acall, &identity);
810         if (ret) {
811             if (identity->kind == RX_ID_KRB4) {
812                 strlcpy(namep, identity->displayName, MAXKTCNAMELEN-1);
813             } else {
814                 snprintf(namep, MAXKTCNAMELEN-1, "eName: %s",
815                          identity->displayName);
816             }
817             rx_identity_free(&identity);
818         }
819     } else {
820         ret = afsconf_SuperIdentity(adir, acall, NULL);
821     }
822
823     return ret;
824 }
825
826 /*!
827  * Check whether the user authenticated on a given RX call is
828  * compatible with the access specified by needed_level.
829  *
830  * @param[in] adir
831  *      The configuration directory currently in use
832  * @param[in] acall
833  *      The RX call whose authenticated identity is being checked
834  * @param[in] needed_level
835  *      Either RESTRICTED_QUERY_ANYUSER for allowing any access or
836  *      RESTRICTED_QUERY_ADMIN for allowing super user only.
837  * @returns
838  *      True if the user is compatible with needed_level.
839  *      Otherwise, false.
840  */
841
842 int
843 afsconf_CheckRestrictedQuery(struct afsconf_dir *adir,
844                              struct rx_call *acall,
845                              int needed_level)
846 {
847     if (needed_level == RESTRICTED_QUERY_ANYUSER)
848         return 1;
849
850     return afsconf_SuperIdentity(adir, acall, NULL);
851 }