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