2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include <afs/param.h>
15 #include <afs/pthread_glock.h>
16 #include <sys/types.h>
23 #include <netinet/in.h>
28 #include <stdlib.h> /* for realpath() */
36 #include <afs/afsutil.h>
37 #include <afs/fileutil.h>
39 #ifdef AFS_ATHENA_STDENV
44 #include "cellconfig.h"
46 #include "afs/audit.h"
50 afsconf_CheckAuth(void *arock, struct rx_call *acall)
52 struct afsconf_dir *adir = (struct afsconf_dir *) arock;
55 rc = ((afsconf_SuperUser(adir, acall, NULL) == 0) ? 10029 : 0);
59 #endif /* !defined(UKERNEL) */
62 GetNoAuthFlag(struct afsconf_dir *adir)
64 if (access(AFSDIR_SERVER_NOAUTH_FILEPATH, 0) == 0) {
65 osi_audit(NoAuthEvent, 0, AUD_END); /* some random server is running noauth */
66 return 1; /* if /usr/afs/local/NoAuth file exists, allow access */
73 afsconf_GetNoAuthFlag(struct afsconf_dir *adir)
78 rc = GetNoAuthFlag(adir);
84 afsconf_SetNoAuthFlag(struct afsconf_dir *adir, int aflag)
90 /* turn off noauth flag */
91 code = (unlink(AFSDIR_SERVER_NOAUTH_FILEPATH) ? errno : 0);
92 osi_audit(NoAuthDisableEvent, code, AUD_END);
94 /* try to create file */
96 open(AFSDIR_SERVER_NOAUTH_FILEPATH, O_CREAT | O_TRUNC | O_RDWR,
100 osi_audit(NoAuthEnableEvent, 0, AUD_END);
102 osi_audit(NoAuthEnableEvent, errno, AUD_END);
107 /* deletes a user from the UserList file */
109 afsconf_DeleteUser(struct afsconf_dir *adir, char *auser)
123 strcompose(tbuffer, sizeof tbuffer, adir->name, "/",
124 AFSDIR_ULIST_FILE, NULL);
128 * We attempt to fully resolve this pathname, so that the rename
129 * of the temporary file will work even if UserList is a symlink
130 * into a different filesystem.
132 char resolved_path[1024];
134 if (realpath(tbuffer, resolved_path)) {
135 strcpy(tbuffer, resolved_path);
138 #endif /* AFS_NT40_ENV */
139 tf = fopen(tbuffer, "r");
144 code = stat(tbuffer, &tstat);
149 strcpy(nbuffer, tbuffer);
150 strcat(nbuffer, ".NXX");
151 nf = fopen(nbuffer, "w+");
160 /* check for our user id */
161 tp = fgets(nbuffer, sizeof(nbuffer), tf);
164 code = sscanf(nbuffer, "%64s", tname);
165 if (code == 1 && strcmp(tname, auser) == 0) {
166 /* found the guy, don't copy to output file */
169 /* otherwise copy original line to output */
170 fprintf(nf, "%s", nbuffer);
176 if (fclose(nf) == EOF)
178 strcpy(nbuffer, tbuffer);
179 strcat(nbuffer, ".NXX"); /* generate new file name again */
182 flag = renamefile(nbuffer, tbuffer);
184 flag = chmod(tbuffer, tstat.st_mode);
188 /* finally, decide what to return to the caller */
191 return EIO; /* something mysterious went wrong */
193 return ENOENT; /* entry wasn't found, no changes made */
194 return 0; /* everything was fine */
197 /* returns nth super user from the UserList file */
199 afsconf_GetNthUser(struct afsconf_dir *adir, afs_int32 an, char *abuffer,
200 afs_int32 abufferLen)
210 strcompose(tbuffer, sizeof tbuffer, adir->name, "/",
211 AFSDIR_ULIST_FILE, NULL);
212 tf = fopen(tbuffer, "r");
219 /* check for our user id */
220 tp = fgets(tbuffer, sizeof(tbuffer), tf);
223 code = sscanf(tbuffer, "%64s", tname);
224 if (code == 1 && an-- == 0) {
230 strcpy(abuffer, tname);
236 /* returns true iff user is in the UserList file */
238 FindUser(struct afsconf_dir *adir, char *auser)
247 strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE,
249 bp = BufioOpen(tbuffer, O_RDONLY, 0);
254 /* check for our user id */
255 rc = BufioGets(bp, tbuffer, sizeof(tbuffer));
258 code = sscanf(tbuffer, "%64s", tname);
259 if (code == 1 && strcmp(tname, auser) == 0) {
268 /* add a user to the user list, checking for duplicates */
270 afsconf_AddUser(struct afsconf_dir *adir, char *aname)
277 if (FindUser(adir, aname)) {
279 return EEXIST; /* already in the list */
282 strcompose(tbuffer, sizeof tbuffer, adir->name, "/", AFSDIR_ULIST_FILE,
284 tf = fopen(tbuffer, "a+");
289 fprintf(tf, "%s\n", aname);
299 /* special CompFindUser routine that builds up a princ and then
300 calls finduser on it. If found, returns char * to user string,
301 otherwise returns NULL. The resulting string should be immediately
302 copied to other storage prior to release of mutex. */
304 CompFindUser(struct afsconf_dir *adir, char *name, char *sep, char *inst,
307 static char fullname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
309 /* always must have name */
310 if (!name || !name[0]) {
313 strcpy(fullname, name);
315 /* might have instance */
316 if (inst && inst[0]) {
317 if (!sep || !sep[0]) {
321 strcat(fullname, sep);
322 strcat(fullname, inst);
325 /* might have realm */
326 if (realm && realm[0]) {
327 strcat(fullname, "@");
328 strcat(fullname, realm);
331 if (FindUser(adir, fullname)) {
339 kerberosSuperUser(struct afsconf_dir *adir, char *tname, char *tinst,
340 char *tcell, char *namep)
342 char tcell_l[MAXKTCREALMLEN];
345 /* keep track of which one actually authorized request */
346 char uname[MAXKTCNAMELEN + MAXKTCNAMELEN + MAXKTCREALMLEN + 3];
348 static char lcell[MAXCELLCHARS] = "";
349 static char lrealms[AFS_NUM_LREALMS][AFS_REALM_SZ];
350 static int num_lrealms = -1;
351 int lrealm_match = 0, i;
354 /* generate lowercased version of cell name */
355 strcpy(tcell_l, tcell);
358 *tmp = tolower(*tmp);
362 /* determine local cell name. It's static, so will only get
363 * calculated the first time through */
365 afsconf_GetLocalCell(adir, lcell, sizeof(lcell));
367 /* if running a krb environment, also get the local realm */
368 /* note - this assumes AFS_REALM_SZ <= MAXCELLCHARS */
369 /* just set it to lcell if it fails */
370 if (num_lrealms == -1) {
371 for (i=0; i<AFS_NUM_LREALMS; i++) {
372 if (afs_krb_get_lrealm(lrealms[i], i) != 0 /*KSUCCESS*/)
377 strncpy(lrealms[0], lcell, AFS_REALM_SZ);
384 /* See if the ticket cell matches one of the local realms */
386 for ( i=0;i<num_lrealms;i++ ) {
387 if (!strcasecmp(lrealms[i], tcell)) {
393 /* If yes, then make sure that the name is not present in
394 * an exclusion list */
397 snprintf(uname,sizeof(uname),"%s.%s@%s",tname,tinst,tcell);
399 snprintf(uname,sizeof(uname),"%s@%s",tname,tcell);
401 if (afs_krb_exclusion(uname))
405 /* start with no uname and no authorization */
409 /* localauth special case */
410 if (strlen(tinst) == 0 && strlen(tcell) == 0
411 && !strcmp(tname, AUTH_SUPERUSER)) {
412 strcpy(uname, "<LocalAuth>");
415 /* cell of connection matches local cell or one of the realms */
416 } else if (!strcasecmp(tcell, lcell) || lrealm_match) {
417 if ((tmp = CompFindUser(adir, tname, ".", tinst, NULL))) {
421 } else if ((tmp = CompFindUser(adir, tname, "/", tinst, NULL))) {
426 /* cell of conn doesn't match local cell or realm */
428 if ((tmp = CompFindUser(adir, tname, ".", tinst, tcell))) {
432 } else if ((tmp = CompFindUser(adir, tname, "/", tinst, tcell))) {
436 } else if ((tmp = CompFindUser(adir, tname, ".", tinst, tcell_l))) {
440 } else if ((tmp = CompFindUser(adir, tname, "/", tinst, tcell_l))) {
448 strcpy(namep, uname);
454 rxkadSuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
456 char tname[MAXKTCNAMELEN]; /* authentication from ticket */
457 char tinst[MAXKTCNAMELEN];
458 char tcell[MAXKTCREALMLEN];
463 /* get auth details from server connection */
464 code = rxkad_GetServerInfo(acall->conn, NULL, &exp, tname, tinst, tcell,
467 return 0; /* bogus connection/other error */
469 /* don't bother checking anything else if tix have expired */
470 #ifdef AFS_PTHREAD_ENV
471 if (exp < clock_Sec())
473 if (exp < FT_ApproxTime())
475 return 0; /* expired tix */
477 return kerberosSuperUser(adir, tname, tinst, tcell, namep);
480 /* make sure user authenticated on rx call acall is in list of valid
481 users. Copy the "real name" of the authenticated user into namep
482 if a pointer is passed.
485 afsconf_SuperUser(struct afsconf_dir *adir, struct rx_call *acall, char *namep)
487 struct rx_connection *tconn;
497 if (afsconf_GetNoAuthFlag(adir)) {
499 strcpy(namep, "<NoAuth>");
504 tconn = rx_ConnectionOf(acall);
505 code = rx_SecurityClassOf(tconn);
508 return 0; /* not authenticated at all, answer is no */
509 } else if (code == 1) {
512 return 0; /* not supported any longer */
513 } else if (code == 2) {
514 flag = rxkadSuperUser(adir, acall, namep);
517 } else { /* some other auth type */
519 return 0; /* mysterious, just say no */