/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #include #include RCSID("$Header$"); #include #include #include #include #include #include #include #include #include #include #ifdef AFS_NT40_ENV #include #else #include #endif #ifdef HAVE_STRING_H #include #else #ifdef HAVE_STRINGS_H #include #endif #endif #include "ptserver.h" #include "pterror.h" #include "afs/audit.h" #ifdef AFS_ATHENA_STDENV #include #endif #define IP_WILDCARDS 1 /* XXX Should be defined outside of here XXX */ extern struct ubik_dbase *dbase; extern afs_int32 Initdb(); extern int pr_noAuth; extern afs_int32 initd; afs_int32 iNewEntry(), newEntry(), whereIsIt(), dumpEntry(), addToGroup(), nameToID(), Delete(), removeFromGroup(); afs_int32 getCPS(), getCPS2(), getHostCPS(), listMax(), setMax(), listEntry(); afs_int32 listEntries(), changeEntry(), setFieldsEntry(), put_prentries(); afs_int32 listElements(), listOwned(), isAMemberOf(), idToName(); static stolower(); extern int IDCmp(); /* When abort, reset initd so that the header is read in on next call. * Abort the transarction and return the code. */ #define ABORT_WITH(tt,code) return(initd=0,ubik_AbortTrans(tt),code) static int CreateOK (ut, cid, oid, flag, admin) struct ubik_trans *ut; afs_int32 cid; /* id of caller */ afs_int32 oid; /* id of owner */ afs_int32 flag; /* indicates type of entry */ int admin; /* sysadmin membership */ { if (flag & PRFOREIGN) { /* Foreign users are recognized by the '@' sign and * not by the PRFOREIGN flag. */ return 0; } else if (flag & PRGRP) { /* Allow anonymous group creation only if owner specified * and running noAuth. */ if (cid == ANONYMOUSID) { if ((oid == 0) || !pr_noAuth) return 0; } } else { /* creating a user */ if (!admin && !pr_noAuth) return 0; } return 1; /* OK! */ } afs_int32 WhoIsThis (acall, at, aid) struct rx_call *acall; struct ubik_trans *at; afs_int32 *aid; { int foreign = 0; /* aid is set to the identity of the caller, if known, else ANONYMOUSID */ /* returns -1 and sets aid to ANONYMOUSID on any failure */ register struct rx_connection *tconn; register afs_int32 code; char tcell[MAXKTCREALMLEN]; char name[MAXKTCNAMELEN]; char inst[MAXKTCNAMELEN]; int ilen; char vname[256]; *aid = ANONYMOUSID; tconn = rx_ConnectionOf(acall); code = rx_SecurityClassOf(tconn); if (code == 0) return 0; else if (code == 1) { /* vab class */ goto done; /* no longer supported */ } else if (code == 2) { /* kad class */ if ((code = rxkad_GetServerInfo (acall->conn, (afs_int32 *) 0, 0/*was &exp*/, name, inst, tcell, (afs_int32 *) 0))) goto done; #if 0 /* This test is unnecessary, since rxkad_GetServerInfo already check. * In addition, this is wrong since exp must be unsigned. */ if (exp < FT_ApproxTime()) goto done; #endif if (strlen (tcell)) { extern char *pr_realmName; #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV) static char local_realm[AFS_REALM_SZ] = ""; if (!local_realm[0]) { if (afs_krb_get_lrealm(local_realm, 0) != 0/*KSUCCESS*/) strncpy(local_realm, pr_realmName, AFS_REALM_SZ); } #endif if ( #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV) strcasecmp (local_realm, tcell) && #endif strcasecmp (pr_realmName, tcell)) foreign = 1; } strncpy (vname, name, sizeof(vname)); if (ilen = strlen (inst)) { if (strlen(vname) + 1 + ilen >= sizeof(vname)) goto done; strcat (vname, "."); strcat (vname, inst); } if (foreign) { if (strlen(vname) + strlen(tcell) + 1 >= sizeof(vname)) goto done; strcat (vname, "@"); strcat (vname, tcell); } if (strcmp (AUTH_SUPERUSER, vname) == 0) *aid = SYSADMINID; /* special case for the fileserver */ else { lcstring(vname, vname, sizeof(vname)); code = NameToID(at,vname,aid); } } done: if (code && !pr_noAuth) return -1; return 0; } afs_int32 SPR_INewEntry (call,aname,aid,oid) struct rx_call *call; char aname[PR_MAXNAMELEN]; afs_int32 aid; afs_int32 oid; { afs_int32 code; code = iNewEntry (call,aname,aid,oid); osi_auditU (call, PTS_INewEntEvent, code, AUD_LONG, aid, AUD_STR, aname, AUD_LONG, oid, AUD_END); return code; } afs_int32 iNewEntry (call,aname,aid,oid) struct rx_call *call; char aname[PR_MAXNAMELEN]; afs_int32 aid; afs_int32 oid; { /* used primarily for conversion - not intended to be used as usual means of entering people into the database. */ struct ubik_trans *tt; register afs_int32 code; afs_int32 gflag = 0; afs_int32 cid; int admin; stolower(aname); code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTrans(dbase,UBIK_WRITETRANS, &tt); if (code) return code; code = ubik_SetLock(tt, 1,1,LOCKWRITE); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = WhoIsThis(call,tt,&cid); if (code) ABORT_WITH(tt,PRPERM); admin = IsAMemberOf(tt,cid,SYSADMINID); /* first verify the id is good */ if (aid == 0) ABORT_WITH(tt,PRPERM); if (aid < 0) { gflag |= PRGRP; /* only sysadmin can reuse a group id */ if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup)-1)) ABORT_WITH(tt,PRPERM); } if (FindByID (tt, aid)) ABORT_WITH(tt,PRIDEXIST); /* check a few other things */ if (!CreateOK (tt, cid, oid, gflag, admin)) ABORT_WITH(tt,PRPERM); code = CreateEntry (tt,aname,&aid,1,gflag,oid,cid); if (code != PRSUCCESS) ABORT_WITH(tt,code); /* finally, commit transaction */ code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } afs_int32 SPR_NewEntry (call, aname, flag, oid, aid) struct rx_call *call; char aname[PR_MAXNAMELEN]; afs_int32 flag; afs_int32 oid; afs_int32 *aid; { afs_int32 code; code = newEntry (call, aname, flag, oid, aid); osi_auditU (call, PTS_NewEntEvent, code, AUD_LONG, *aid, AUD_STR, aname, AUD_LONG, oid, AUD_END); return code; } afs_int32 newEntry (call, aname, flag, oid, aid) struct rx_call *call; char aname[PR_MAXNAMELEN]; afs_int32 flag; afs_int32 oid; afs_int32 *aid; { register afs_int32 code; struct ubik_trans *tt; afs_int32 cid; int admin; extern afs_int32 WhoIsThisWithName(); char cname[PR_MAXNAMELEN]; stolower(aname); code = Initdb(); if (code) return code; code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKWRITE); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); /* this is for cross-cell self registration. It is not added in the * SPR_INewEntry because we want self-registration to only do * automatic id assignment. */ code = WhoIsThisWithName(call,tt,&cid,cname); if (code != 2) {/* 2 specifies that this is a foreign cell request */ if (code) ABORT_WITH(tt,PRPERM); admin = IsAMemberOf(tt,cid,SYSADMINID); } else { admin = (!strcmp(aname,cname)) || IsAMemberOf(tt,cid,SYSADMINID); oid = cid = SYSADMINID; } if (!CreateOK (tt, cid, oid, flag, admin)) ABORT_WITH(tt,PRPERM); code = CreateEntry (tt,aname,aid,0,flag,oid,cid); if (code != PRSUCCESS) ABORT_WITH(tt,code); code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } afs_int32 SPR_WhereIsIt (call,aid,apos) struct rx_call *call; afs_int32 aid; afs_int32 *apos; { afs_int32 code; code = whereIsIt(call,aid,apos); osi_auditU (call, PTS_WheIsItEvent, code, AUD_LONG, aid, AUD_LONG, *apos, AUD_END); return code; } afs_int32 whereIsIt (call,aid,apos) struct rx_call *call; afs_int32 aid; afs_int32 *apos; { register afs_int32 code; struct ubik_trans *tt; afs_int32 temp; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); temp = FindByID(tt,aid); if (!temp) ABORT_WITH(tt,PRNOENT); *apos = temp; code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } afs_int32 SPR_DumpEntry (call,apos, aentry) struct rx_call *call; afs_int32 apos; struct prdebugentry *aentry; { afs_int32 code; code = dumpEntry(call,apos, aentry); osi_auditU (call, PTS_DmpEntEvent, code, AUD_LONG, apos, AUD_END); return code; } afs_int32 dumpEntry (call,apos, aentry) struct rx_call *call; afs_int32 apos; struct prdebugentry *aentry; { register afs_int32 code; afs_int32 cid; struct ubik_trans *tt; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = WhoIsThis(call,tt,&cid); if (code) ABORT_WITH(tt,PRPERM); code = pr_ReadEntry(tt, 0, apos, aentry); if (code) ABORT_WITH(tt,code); if (!AccessOK (tt, cid, aentry, PRP_STATUS_MEM, PRP_STATUS_ANY)) ABORT_WITH(tt,PRPERM); /* Since prdebugentry is in the form of a prentry not a coentry, we will * return the coentry slots in network order where the string is. */ #if 0 if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */ code = pr_ReadCoEntry(tt, 0, apos, aentry); if (code) ABORT_WITH(tt,code); } #endif code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } afs_int32 SPR_AddToGroup (call,aid,gid) struct rx_call *call; afs_int32 aid; afs_int32 gid; { afs_int32 code; code = addToGroup (call,aid,gid); osi_auditU (call, PTS_AdToGrpEvent, code, AUD_LONG, gid, AUD_LONG, aid, AUD_END); return code; } afs_int32 addToGroup (call,aid,gid) struct rx_call *call; afs_int32 aid; afs_int32 gid; { register afs_int32 code; struct ubik_trans *tt; afs_int32 tempu; afs_int32 tempg; struct prentry tentry; struct prentry uentry; afs_int32 cid; code = Initdb(); if (code != PRSUCCESS) return code; if (gid == ANYUSERID || gid == AUTHUSERID) return PRPERM; if (aid == ANONYMOUSID) return PRPERM; code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKWRITE); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = WhoIsThis(call, tt, &cid); if (code) ABORT_WITH(tt,PRPERM); tempu = FindByID(tt,aid); if (!tempu) ABORT_WITH(tt,PRNOENT); memset(&uentry, 0, sizeof(uentry)); code = pr_ReadEntry(tt,0,tempu,&uentry); if (code != 0) ABORT_WITH(tt,code); /* we don't allow groups as members of groups at present */ if (uentry.flags & PRGRP) ABORT_WITH(tt,PRNOTUSER); tempg = FindByID(tt,gid); if (!tempg) ABORT_WITH(tt,PRNOENT); code = pr_ReadEntry(tt,0,tempg,&tentry); if (code != 0) ABORT_WITH(tt,code); /* make sure that this is a group */ if (!(tentry.flags & PRGRP)) ABORT_WITH(tt,PRNOTGROUP); if (!AccessOK (tt, cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY)) ABORT_WITH(tt,PRPERM); code = AddToEntry (tt, &tentry, tempg, aid); if (code != PRSUCCESS) ABORT_WITH(tt,code); /* now, modify the user's entry as well */ code = AddToEntry (tt, &uentry, tempu, gid); if (code != PRSUCCESS) ABORT_WITH(tt,code); code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } afs_int32 SPR_NameToID (call, aname, aid) struct rx_call *call; namelist *aname; idlist *aid; { afs_int32 code; code = nameToID (call, aname, aid); osi_auditU (call, PTS_NmToIdEvent, code, AUD_END); return code; } afs_int32 nameToID (call, aname, aid) struct rx_call *call; namelist *aname; idlist *aid; { register afs_int32 code; struct ubik_trans *tt; afs_int32 i; int size; int count = 0; /* Initialize return struct */ aid->idlist_len = 0; aid->idlist_val = (afs_int32 *)0; size = aname->namelist_len; if (size == 0) return 0; if (size < 0) return PRTOOMANY; aid->idlist_val = (afs_int32 *)malloc(size*sizeof(afs_int32)); if (!aid->idlist_val) return PRNOMEM; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); for (i=0;inamelist_len;i++) { code = NameToID(tt,aname->namelist_val[i],&aid->idlist_val[i]); if (code != PRSUCCESS) aid->idlist_val[i] = ANONYMOUSID; if (count++ > 50) IOMGR_Poll(), count = 0; } aid->idlist_len = aname->namelist_len; code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } /* * SPR_IDToName * Given an array of ids, find the name for each of them. * The array of ids and names is unlimited. */ afs_int32 SPR_IDToName (call, aid, aname) struct rx_call *call; idlist *aid; namelist *aname; { afs_int32 code; code = idToName (call, aid, aname); osi_auditU (call, PTS_IdToNmEvent, code, AUD_LONG, aid, AUD_END); return code; } afs_int32 idToName (call, aid, aname) struct rx_call *call; idlist *aid; namelist *aname; { register afs_int32 code; struct ubik_trans *tt; afs_int32 i; int size; int count = 0; /* leave this first for rpc stub */ size = aid->idlist_len; if (size <= 0) size = 0; aname->namelist_val = (prname *)malloc(size*PR_MAXNAMELEN); aname->namelist_len = 0; if (aname->namelist_val == 0) return PRNOMEM; if (aid->idlist_len == 0) return 0; if (size == 0) return PRTOOMANY; /* rxgen will probably handle this */ code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); for (i=0;iidlist_len;i++) { code = IDToName(tt,aid->idlist_val[i],aname->namelist_val[i]); if (code != PRSUCCESS) sprintf(aname->namelist_val[i],"%d",aid->idlist_val[i]); if (count++ > 50) IOMGR_Poll(), count = 0; } aname->namelist_len = aid->idlist_len; code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } afs_int32 SPR_Delete (call, aid) struct rx_call *call; afs_int32 aid; { afs_int32 code; code = Delete (call, aid); osi_auditU (call, PTS_DelEvent, code, AUD_LONG, aid, AUD_END); return code; } afs_int32 Delete (call, aid) struct rx_call *call; afs_int32 aid; { register afs_int32 code; struct ubik_trans *tt; afs_int32 cid; struct prentry tentry; afs_int32 loc, nptr; int count; code = Initdb(); if (code) return code; if (code != PRSUCCESS) return code; if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID) return PRPERM; code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKWRITE); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = WhoIsThis(call,tt,&cid); if (code) ABORT_WITH(tt,PRPERM); /* Read in entry to be deleted */ loc = FindByID (tt, aid); if (loc == 0) ABORT_WITH(tt,PRNOENT); code = pr_ReadEntry (tt, 0, loc, &tentry); if (code) ABORT_WITH(tt,PRDBFAIL); /* Do some access checking */ if (tentry.owner != cid && !IsAMemberOf (tt, cid, SYSADMINID) && !IsAMemberOf (tt, cid, tentry.owner) && !pr_noAuth) ABORT_WITH(tt,PRPERM); /* Delete each continuation block as a separate transaction so that no one * transaction become to large to complete. */ nptr = tentry.next; while (nptr != (afs_int32)NULL) { struct contentry centry; int i; code = pr_ReadCoEntry(tt, 0, nptr, ¢ry); if (code != 0) ABORT_WITH(tt,PRDBFAIL); for (i=0;iMask & PRUPDATE_NAMEHASH) { int tloc; code = RemoveFromNameHash(tt, tentry.name, &tloc); if (code != PRSUCCESS) ABORT_WITH(tt,PRDBFAIL); code = AddToNameHash(tt, tentry.name, loc); if (code) ABORT_WITH(tt,code); } if (uentry->Mask & PRUPDATE_IDHASH) { int tloc; if (!id) id = tentry.id; code = RemoveFromIDHash(tt, id, &tloc); if (code != PRSUCCESS) ABORT_WITH(tt,PRDBFAIL); code = AddToIDHash(tt, id, loc); if (code) ABORT_WITH(tt,code); } code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } afs_int32 SPR_RemoveFromGroup (call,aid,gid) struct rx_call *call; afs_int32 aid; afs_int32 gid; { afs_int32 code; code = removeFromGroup (call,aid,gid); osi_auditU (call, PTS_RmFmGrpEvent, code, AUD_LONG, gid, AUD_LONG, aid, AUD_END); return code; } afs_int32 removeFromGroup (call,aid,gid) struct rx_call *call; afs_int32 aid; afs_int32 gid; { register afs_int32 code; struct ubik_trans *tt; afs_int32 tempu; afs_int32 tempg; struct prentry uentry; struct prentry gentry; afs_int32 cid; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKWRITE); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = WhoIsThis(call,tt,&cid); if (code) ABORT_WITH(tt,PRPERM); tempu = FindByID(tt,aid); if (!tempu) ABORT_WITH(tt,PRNOENT); tempg = FindByID(tt,gid); if (!tempg) ABORT_WITH(tt,PRNOENT); memset(&uentry, 0, sizeof(uentry)); memset(&gentry, 0, sizeof(gentry)); code = pr_ReadEntry(tt,0,tempu,&uentry); if (code != 0) ABORT_WITH(tt,code); code = pr_ReadEntry(tt,0,tempg,&gentry); if (code != 0) ABORT_WITH(tt,code); if (!(gentry.flags & PRGRP)) ABORT_WITH(tt,PRNOTGROUP); if (uentry.flags & PRGRP) ABORT_WITH(tt,PRNOTUSER); if (!AccessOK (tt, cid, &gentry, PRP_REMOVE_MEM, 0)) ABORT_WITH(tt,PRPERM); code = RemoveFromEntry(tt,aid,gid); if (code != PRSUCCESS) ABORT_WITH(tt,code); code = RemoveFromEntry(tt,gid,aid); if (code != PRSUCCESS) ABORT_WITH(tt,code); code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } afs_int32 SPR_GetCPS (call, aid, alist, over) struct rx_call *call; afs_int32 aid; prlist *alist; afs_int32 *over; { afs_int32 code; code = getCPS (call, aid, alist, over); osi_auditU (call, PTS_GetCPSEvent, code, AUD_LONG, aid, AUD_END); return code; } afs_int32 getCPS (call, aid, alist, over) struct rx_call *call; afs_int32 aid; prlist *alist; afs_int32 *over; { register afs_int32 code; struct ubik_trans *tt; afs_int32 temp; afs_int32 cid; struct prentry tentry; *over = 0; alist->prlist_len = 0; alist->prlist_val = (afs_int32 *) 0; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); temp = FindByID (tt, aid); if (!temp) ABORT_WITH(tt,PRNOENT); code = pr_ReadEntry (tt, 0, temp, &tentry); if (code) ABORT_WITH(tt,code); /* afs does authenticate now */ code = WhoIsThis (call, tt, &cid); if (code || !AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) ABORT_WITH(tt,PRPERM); code = GetList(tt, &tentry, alist, 1); if (code != PRSUCCESS) ABORT_WITH(tt,code); code = ubik_EndTrans(tt); return code; } #ifdef IP_WILDCARDS int inCPS (CPS,id) prlist CPS; afs_int32 id; { int i; for (i = (CPS.prlist_len-1) ; i >= 0; i--) { if (CPS.prlist_val[i] == id) return(1); } return(0); } #endif /* IP_WILDCARDS */ afs_int32 SPR_GetCPS2 (call, aid, ahost, alist, over) struct rx_call *call; afs_int32 aid; afs_int32 ahost; prlist *alist; afs_int32 *over; { afs_int32 code; code = getCPS2 (call, aid, ahost, alist, over); osi_auditU (call, PTS_GetCPS2Event, code, AUD_LONG, aid, AUD_HOST, ahost, AUD_END); return code; } afs_int32 getCPS2 (call, aid, ahost, alist, over) struct rx_call *call; afs_int32 aid; afs_int32 ahost; prlist *alist; afs_int32 *over; { register afs_int32 code; struct ubik_trans *tt; afs_int32 temp; afs_int32 cid; struct prentry tentry; struct prentry host_tentry; afs_int32 hostid; int host_list = 0; struct in_addr iaddr; #if IP_WILDCARDS extern afs_int32 addWildCards(); #endif /* IP_WILDCARDS */ *over = 0; iaddr.s_addr = ntohl(ahost); alist->prlist_len = 0; alist->prlist_val = (afs_int32 *) 0; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); if (aid != PRBADID) { temp = FindByID(tt,aid); if (!temp) ABORT_WITH(tt,PRNOENT); code = pr_ReadEntry (tt, 0, temp, &tentry); if (code) ABORT_WITH(tt,code); /* afs does authenticate now */ code = WhoIsThis (call, tt, &cid); if (code || !AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) ABORT_WITH(tt,PRPERM); } code = NameToID(tt, inet_ntoa(iaddr),&hostid); if (code == PRSUCCESS && hostid != 0) { temp = FindByID(tt,hostid); if (temp){ code = pr_ReadEntry (tt, 0, temp, &host_tentry); if (code == PRSUCCESS) host_list = 1; else fprintf(stderr,"pr_ReadEntry returned %d\n",code); } else fprintf(stderr,"FindByID Failed -- Not found\n"); } if (host_list) code = GetList2(tt, &tentry, &host_tentry, alist, 1); else code = GetList(tt, &tentry, alist, 1); #if IP_WILDCARDS if (!code) code = addWildCards(tt,alist,ntohl(ahost)); #endif /* IP_WILDCARDS */ if (code != PRSUCCESS) ABORT_WITH(tt,code); code = ubik_EndTrans(tt); return code; } afs_int32 SPR_GetHostCPS (call, ahost, alist, over) struct rx_call *call; afs_int32 ahost; prlist *alist; afs_int32 *over; { afs_int32 code; code = getHostCPS (call, ahost, alist, over); osi_auditU (call, PTS_GetHCPSEvent, code, AUD_HOST, ahost, AUD_END); return code; } afs_int32 getHostCPS (call, ahost, alist, over) struct rx_call *call; afs_int32 ahost; prlist *alist; afs_int32 *over; { register afs_int32 code, temp; struct ubik_trans *tt; struct prentry host_tentry; afs_int32 hostid; struct in_addr iaddr; #if IP_WILDCARDS extern afs_int32 addWildCards(); #endif /* IP_WILDCARDS */ *over = 0; iaddr.s_addr = ntohl(ahost); alist->prlist_len = 0; alist->prlist_val = (afs_int32 *) 0; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = NameToID(tt, inet_ntoa(iaddr), &hostid); if (code == PRSUCCESS && hostid != 0) { temp = FindByID(tt,hostid); if (temp) { code = pr_ReadEntry (tt, 0, temp, &host_tentry); if (code == PRSUCCESS) { code = GetList(tt, &host_tentry, alist, 0); if (code) goto bad; } else fprintf(stderr,"pr_ReadEntry returned %d\n",code); } else fprintf(stderr,"FindByID Failed -- Not found\n"); } #if IP_WILDCARDS code = addWildCards(tt,alist,ntohl(ahost)); #endif /* IP_WILDCARDS */ bad: if (code != PRSUCCESS) ABORT_WITH(tt,code); code = ubik_EndTrans(tt); return code; } afs_int32 SPR_ListMax (call,uid,gid) struct rx_call *call; afs_int32 *uid; afs_int32 *gid; { afs_int32 code; code = listMax(call,uid,gid); osi_auditU (call, PTS_LstMaxEvent, code, AUD_END); return code; } afs_int32 listMax (call,uid,gid) struct rx_call *call; afs_int32 *uid; afs_int32 *gid; { register afs_int32 code; struct ubik_trans *tt; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = GetMax(tt,uid,gid); if (code != PRSUCCESS) ABORT_WITH(tt,code); code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } afs_int32 SPR_SetMax (call,aid,gflag) struct rx_call *call; afs_int32 aid; afs_int32 gflag; { afs_int32 code; code = setMax (call,aid,gflag); osi_auditU (call, PTS_SetMaxEvent, code, AUD_LONG, aid, AUD_LONG, gflag, AUD_END); return code; } afs_int32 setMax (call,aid,gflag) struct rx_call *call; afs_int32 aid; afs_int32 gflag; { register afs_int32 code; struct ubik_trans *tt; afs_int32 cid; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKWRITE); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = WhoIsThis(call,tt,&cid); if (code) ABORT_WITH(tt,PRPERM); if (!AccessOK (tt, cid, 0, 0, 0)) ABORT_WITH(tt,PRPERM); if (((gflag & PRGRP) && (aid > 0)) || (!(gflag & PRGRP) && (aid < 0))) ABORT_WITH(tt,PRBADARG); code = SetMax(tt,aid,gflag); if (code != PRSUCCESS) ABORT_WITH(tt,code); code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } afs_int32 SPR_ListEntry (call,aid,aentry) struct rx_call *call; afs_int32 aid; struct prcheckentry *aentry; { afs_int32 code; code = listEntry (call,aid,aentry); osi_auditU (call, PTS_LstEntEvent, code, AUD_LONG, aid, AUD_END); return code; } afs_int32 listEntry (call,aid,aentry) struct rx_call *call; afs_int32 aid; struct prcheckentry *aentry; { register afs_int32 code; struct ubik_trans *tt; afs_int32 cid; afs_int32 temp; struct prentry tentry; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = WhoIsThis(call,tt,&cid); if (code) ABORT_WITH(tt,PRPERM); temp = FindByID(tt,aid); if (!temp) ABORT_WITH(tt,PRNOENT); code = pr_ReadEntry(tt, 0, temp, &tentry); if (code != 0) ABORT_WITH(tt,code); if (!AccessOK (tt, cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY)) ABORT_WITH(tt,PRPERM); aentry->flags = tentry.flags >> PRIVATE_SHIFT; if (aentry->flags == 0) { if (tentry.flags & PRGRP) aentry->flags = PRP_GROUP_DEFAULT >> PRIVATE_SHIFT; else aentry->flags = PRP_USER_DEFAULT >> PRIVATE_SHIFT; } aentry->owner = tentry.owner; aentry->id = tentry.id; strncpy(aentry->name,tentry.name,PR_MAXNAMELEN); aentry->creator = tentry.creator; aentry->ngroups = tentry.ngroups; aentry->nusers = tentry.nusers; aentry->count = tentry.count; memset(aentry->reserved, 0, sizeof(aentry->reserved)); code = ubik_EndTrans(tt); if (code) return code; return PRSUCCESS; } afs_int32 SPR_ListEntries(call, flag, startindex, bulkentries, nextstartindex) struct rx_call *call; afs_int32 flag; afs_int32 startindex; prentries *bulkentries; afs_int32 *nextstartindex; { afs_int32 code; code = listEntries(call, flag, startindex, bulkentries, nextstartindex); osi_auditU (call, PTS_LstEntsEvent, code, AUD_LONG, flag, AUD_END); return code; } afs_int32 listEntries(call, flag, startindex, bulkentries, nextstartindex) struct rx_call *call; afs_int32 flag; afs_int32 startindex; prentries *bulkentries; afs_int32 *nextstartindex; { afs_int32 code; struct ubik_trans *tt; afs_int32 cid; afs_int32 i, eof, pos, maxentries, f; struct prentry tentry; afs_int32 pollcount=0; *nextstartindex = -1; bulkentries->prentries_val = 0; bulkentries->prentries_len = 0; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); /* Make sure we are an authenticated caller and that we are on the * SYSADMIN list. */ code = WhoIsThis(call,tt,&cid); if (code) ABORT_WITH(tt,PRPERM); code = IsAMemberOf (tt, cid, SYSADMINID); if (!code && !pr_noAuth) ABORT_WITH(tt,PRPERM); eof = ntohl(cheader.eofPtr) - sizeof(cheader); maxentries = eof / sizeof(struct prentry); for (i=startindex; i 50) { IOMGR_Poll(); pollcount = 0; } f = (tentry.flags & PRTYPE); if ( ((flag & PRUSERS ) && (f == 0) ) || /* User entry */ ((flag & PRGROUPS) && (f & PRGRP)) ) { /* Group entry */ code = put_prentries(&tentry, bulkentries); if (code == -1) break; /* Filled return array */ if (code) goto done; } } code = 0; if (i < maxentries) *nextstartindex = i; done: if (code) { if (bulkentries->prentries_val) free(bulkentries->prentries_val); bulkentries->prentries_val = 0; bulkentries->prentries_len = 0; ABORT_WITH(tt, code); } else { code = ubik_EndTrans(tt); } if (code) return code; return PRSUCCESS; } #define PR_MAXENTRIES 500 afs_int32 put_prentries(tentry, bulkentries) struct prentry *tentry; prentries *bulkentries; { struct prlistentries *entry; if (bulkentries->prentries_val == 0) { bulkentries->prentries_len = 0; bulkentries->prentries_val = (struct prlistentries *)malloc(PR_MAXENTRIES * sizeof(struct prentry)); if (!bulkentries->prentries_val) { return(PRNOMEM); } } if (bulkentries->prentries_len >= PR_MAXENTRIES) { return(-1); } entry = (struct prlistentries *)bulkentries->prentries_val; entry += bulkentries->prentries_len; entry->flags = tentry->flags >> PRIVATE_SHIFT; if (entry->flags == 0) { entry->flags = ( (tentry->flags & PRGRP)?PRP_GROUP_DEFAULT :PRP_USER_DEFAULT ) >> PRIVATE_SHIFT; } entry->owner = tentry->owner; entry->id = tentry->id; entry->creator = tentry->creator; entry->ngroups = tentry->ngroups; entry->nusers = tentry->nusers; entry->count = tentry->count; strncpy(entry->name,tentry->name,PR_MAXNAMELEN); memset(entry->reserved, 0, sizeof(entry->reserved)); bulkentries->prentries_len++; return 0; } afs_int32 SPR_ChangeEntry (call,aid,name,oid,newid) struct rx_call *call; afs_int32 aid; char *name; afs_int32 oid; afs_int32 newid; { afs_int32 code; code = changeEntry (call,aid,name,oid,newid); osi_auditU (call, PTS_ChgEntEvent, code, AUD_LONG, aid, AUD_STR, name, AUD_LONG, oid, AUD_LONG, newid, AUD_END); return code; } afs_int32 changeEntry (call,aid,name,oid,newid) struct rx_call *call; afs_int32 aid; char *name; afs_int32 oid; afs_int32 newid; { register afs_int32 code; struct ubik_trans *tt; afs_int32 pos; afs_int32 cid; if (!name) return PRPERM; stolower(name); code = Initdb(); if (code) return code; if (aid == ANYUSERID || aid == AUTHUSERID || aid == ANONYMOUSID || aid == SYSADMINID) return PRPERM; if (code != PRSUCCESS) return code; code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKWRITE); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = WhoIsThis(call,tt,&cid); if (code) ABORT_WITH(tt,PRPERM); pos = FindByID(tt,aid); if (!pos) ABORT_WITH(tt,PRNOENT); /* protection check in changeentry */ code = ChangeEntry(tt,aid,cid,name,oid,newid); if (code != PRSUCCESS) ABORT_WITH(tt,code); code = ubik_EndTrans(tt); return code; } afs_int32 SPR_SetFieldsEntry (call, id, mask, flags, ngroups, nusers, spare1, spare2) struct rx_call *call; afs_int32 id; afs_int32 mask; /* specify which fields to update */ afs_int32 flags, ngroups, nusers; afs_int32 spare1, spare2; { afs_int32 code; code = setFieldsEntry (call, id, mask, flags, ngroups, nusers, spare1, spare2); osi_auditU (call, PTS_SetFldEntEvent, code, AUD_LONG, id, AUD_END); return code; } afs_int32 setFieldsEntry (call, id, mask, flags, ngroups, nusers, spare1, spare2) struct rx_call *call; afs_int32 id; afs_int32 mask; /* specify which fields to update */ afs_int32 flags, ngroups, nusers; afs_int32 spare1, spare2; { register afs_int32 code; struct ubik_trans *tt; afs_int32 pos; afs_int32 cid; struct prentry tentry; afs_int32 tflags; if (mask == 0) return 0; /* no-op */ code = Initdb(); if (code) return code; if (id == ANYUSERID || id == AUTHUSERID || id == ANONYMOUSID) return PRPERM; if (code != PRSUCCESS) return code; code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKWRITE); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = WhoIsThis(call,tt,&cid); if (code) ABORT_WITH(tt,PRPERM); pos = FindByID(tt,id); if (!pos) ABORT_WITH(tt,PRNOENT); code = pr_ReadEntry (tt, 0, pos, &tentry); if (code) ABORT_WITH(tt,code); tflags = tentry.flags; if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) { if (!AccessOK (tt, cid, 0, 0, 0)) ABORT_WITH(tt,PRPERM); if ((tflags & PRQUOTA) == 0) { /* default if only setting one */ tentry.ngroups = tentry.nusers = 20; } } else { if (!AccessOK (tt, cid, &tentry, 0, 0)) ABORT_WITH(tt,PRPERM); } if (mask & 0xffff) { /* if setting flag bits */ afs_int32 flagsMask = mask & 0xffff; tflags &= ~(flagsMask << PRIVATE_SHIFT); tflags |= (flags & flagsMask) << PRIVATE_SHIFT; tflags |= PRACCESS; } if (mask & PR_SF_NGROUPS) { /* setting group limit */ if (ngroups < 0) ABORT_WITH(tt,PRBADARG); tentry.ngroups = ngroups; tflags |= PRQUOTA; } if (mask & PR_SF_NUSERS) { /* setting foreign user limit */ if (nusers < 0) ABORT_WITH(tt,PRBADARG); tentry.nusers = nusers; tflags |= PRQUOTA; } tentry.flags = tflags; code = pr_WriteEntry (tt, 0, pos, &tentry); if (code) ABORT_WITH(tt,code); code = ubik_EndTrans(tt); return code; } afs_int32 SPR_ListElements (call, aid, alist, over) struct rx_call *call; afs_int32 aid; prlist *alist; afs_int32 *over; { afs_int32 code; code = listElements (call, aid, alist, over); osi_auditU (call, PTS_LstEleEvent, code, AUD_LONG, aid, AUD_END); return code; } afs_int32 listElements (call, aid, alist, over) struct rx_call *call; afs_int32 aid; prlist *alist; afs_int32 *over; { register afs_int32 code; struct ubik_trans *tt; afs_int32 cid; afs_int32 temp; struct prentry tentry; *over = 0; alist->prlist_len = 0; alist->prlist_val = (afs_int32 *) 0; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = WhoIsThis(call,tt,&cid); if (code) ABORT_WITH(tt,PRPERM); temp = FindByID(tt,aid); if (!temp) ABORT_WITH(tt,PRNOENT); code = pr_ReadEntry (tt, 0, temp, &tentry); if (code) ABORT_WITH(tt,code); if (!AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) ABORT_WITH(tt,PRPERM); code = GetList (tt, &tentry, alist, 0); if (code != PRSUCCESS) ABORT_WITH(tt,code); code = ubik_EndTrans(tt); return code; } /* * SPR_ListOwned * List the entries owned by this id. If the id is zero, * return the orphans list. This will return up to PR_MAXGROUPS * at a time with the lastP available to get the rest. The * maximum value is enforced in GetOwnedChain(). */ afs_int32 SPR_ListOwned (call, aid, alist, lastP) struct rx_call *call; afs_int32 aid; prlist *alist; afs_int32 *lastP; { afs_int32 code; code = listOwned (call, aid, alist, lastP); osi_auditU (call, PTS_LstOwnEvent, code, AUD_LONG, aid, AUD_END); return code; } afs_int32 listOwned (call, aid, alist, lastP) struct rx_call *call; afs_int32 aid; prlist *alist; afs_int32 *lastP; { register afs_int32 code; struct ubik_trans *tt; afs_int32 cid; struct prentry tentry; afs_int32 head=0; afs_int32 start; alist->prlist_len = 0; alist->prlist_val = (afs_int32 *) 0; if (!lastP) return PRBADARG; start = *lastP; *lastP = 0; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); code = WhoIsThis(call,tt,&cid); if (code) ABORT_WITH(tt,PRPERM); if (start) { code = pr_ReadEntry (tt, 0, start, &tentry); if (!code && (tentry.owner == aid)) head = start; /* pick up where we left off */ } if (!head) { if (aid) { afs_int32 loc = FindByID (tt, aid); if (loc == 0) ABORT_WITH(tt,PRNOENT); code = pr_ReadEntry (tt, 0, loc, &tentry); if (code) ABORT_WITH(tt,code); if (!AccessOK (tt, cid, &tentry, -1, PRP_OWNED_ANY)) ABORT_WITH(tt,PRPERM); head = tentry.owned; } else { if (!AccessOK (tt, cid, 0, 0, 0)) ABORT_WITH(tt,PRPERM); head = ntohl(cheader.orphan); } } code = GetOwnedChain (tt, &head, alist); if (code) { if (code == PRTOOMANY) *lastP = head; else ABORT_WITH(tt,code); } code = ubik_EndTrans(tt); return code; } afs_int32 SPR_IsAMemberOf (call,uid,gid,flag) struct rx_call *call; afs_int32 uid; afs_int32 gid; afs_int32 *flag; { afs_int32 code; code = isAMemberOf (call,uid,gid,flag); osi_auditU (call, PTS_IsMemOfEvent, code, AUD_LONG, uid, AUD_LONG, gid, AUD_END); return code; } afs_int32 isAMemberOf (call,uid,gid,flag) struct rx_call *call; afs_int32 uid; afs_int32 gid; afs_int32 *flag; { register afs_int32 code; struct ubik_trans *tt; code = Initdb(); if (code != PRSUCCESS) return code; code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS,&tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); if (code) ABORT_WITH(tt,code); code = read_DbHeader(tt); if (code) ABORT_WITH(tt,code); { afs_int32 cid; afs_int32 uloc = FindByID (tt, uid); afs_int32 gloc = FindByID (tt, gid); struct prentry uentry, gentry; if (!uloc || !gloc) ABORT_WITH(tt,PRNOENT); code = WhoIsThis(call, tt, &cid); if (code) ABORT_WITH(tt,PRPERM); code = pr_ReadEntry (tt, 0, uloc, &uentry); if (code) ABORT_WITH(tt,code); code = pr_ReadEntry (tt, 0, gloc, &gentry); if (code) ABORT_WITH(tt,code); if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP)) ABORT_WITH(tt,PRBADARG); if (!AccessOK (tt, cid, &uentry, 0, PRP_MEMBER_ANY) && !AccessOK (tt, cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) ABORT_WITH(tt,PRPERM); } *flag = IsAMemberOf(tt,uid,gid); code = ubik_EndTrans(tt); return code; } static stolower(s) register char *s; { register int tc; while ((tc = *s)) { if (isupper(tc)) *s = tolower(tc); s++; } } #if IP_WILDCARDS afs_int32 addWildCards(tt,alist,host) struct ubik_trans *tt; prlist *alist; afs_int32 host; { afs_int32 temp; struct prentry tentry; prlist wlist; unsigned wild = htonl(0xffffff00); struct in_addr iaddr; afs_int32 hostid; int size = 0, i, code; int added = 0; while ((host = (host & wild))) { wild = htonl ( ntohl(wild) << 8) ; iaddr.s_addr = host; code = NameToID(tt, inet_ntoa(iaddr),&hostid); if (code == PRSUCCESS && hostid != 0) { temp = FindByID(tt,hostid); if (temp){ code = pr_ReadEntry (tt, 0, temp, &tentry); if (code != PRSUCCESS) continue; } else continue; } else continue; wlist.prlist_len = 0; wlist.prlist_val = (afs_int32 *) 0; code = GetList (tt, &tentry, &wlist, 0); if (code) return code; added += wlist.prlist_len; for (i=0; i< wlist.prlist_len; i++) { if (!inCPS(*alist,wlist.prlist_val[i])) if ((code = AddToPRList (alist, &size, wlist.prlist_val[i] ))) { free(wlist.prlist_val); return(code); } } if (wlist.prlist_val) free(wlist.prlist_val); } if (added) qsort(alist->prlist_val,alist->prlist_len,sizeof(afs_int32),IDCmp); return 0; } #endif /* IP_WILDCARDS */ afs_int32 WhoIsThisWithName(acall, at, aid, aname) struct rx_call *acall; struct ubik_trans *at; afs_int32 *aid; char *aname; { /* aid is set to the identity of the caller, if known, else ANONYMOUSID */ /* returns -1 and sets aid to ANONYMOUSID on any failure */ register struct rx_connection *tconn; register afs_int32 code; char tcell[MAXKTCREALMLEN]; char name[MAXKTCNAMELEN]; char inst[MAXKTCNAMELEN]; int ilen; char vname[256]; *aid = ANONYMOUSID; tconn = rx_ConnectionOf(acall); code = rx_SecurityClassOf(tconn); if (code == 0) return 0; else if (code == 1) { /* vab class */ goto done; /* no longer supported */ } else if (code == 2) { /* kad class */ int clen; extern char *pr_realmName; if ((code = rxkad_GetServerInfo (acall->conn, (afs_int32 *) 0, 0/*was &exp*/, name, inst, tcell, (afs_int32 *) 0))) goto done; strncpy (vname, name, sizeof(vname)); if ((ilen = strlen(inst))) { if (strlen(vname) + 1 + ilen >= sizeof(vname)) goto done; strcat (vname, "."); strcat (vname, inst); } if ( (clen = strlen(tcell))) { #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV) static char local_realm[AFS_REALM_SZ] = ""; if (!local_realm[0]) { if (afs_krb_get_lrealm(local_realm, 0) != 0/*KSUCCESS*/) strncpy(local_realm, pr_realmName, AFS_REALM_SZ); } #endif if ( #if defined(AFS_ATHENA_STDENV) || defined(AFS_KERBREALM_ENV) strcasecmp (local_realm, tcell) && #endif strcasecmp (pr_realmName, tcell)) { if (strlen(vname) + 1 + clen >= sizeof(vname)) goto done; strcat(vname,"@"); strcat(vname,tcell); lcstring(vname, vname, sizeof(vname)); code = NameToID(at,vname,aid); strcpy(aname,vname); return 2; } } if (strcmp (AUTH_SUPERUSER, vname) == 0) *aid = SYSADMINID; /* special case for the fileserver */ else { lcstring(vname, vname, sizeof(vname)); code = NameToID(at,vname,aid); } } done: if (code && !pr_noAuth) return -1; return 0; }