OPENAFS-SA-2018-002 ptserver: prevent PR_ListEntries information leak
[openafs.git] / src / ptserver / ptprocs.c
index ee09718..4ce1cbf 100644 (file)
 #include <rx/rx.h>
 #include <rx/rxkad.h>
 #include <afs/auth.h>
+#include <afs/cellconfig.h>
 
 #include "ptserver.h"
 #include "pterror.h"
 #include "ptprototypes.h"
 #include "afs/audit.h"
 
-#ifdef AFS_ATHENA_STDENV
-#include <krb.h>
-#endif
-
 extern int restricted;
+extern int restrict_anonymous;
 extern struct ubik_dbase *dbase;
 extern int pr_noAuth;
-extern char *pr_realmName;
 extern int prp_group_default;
 extern int prp_user_default;
+extern struct afsconf_dir *prdir;
 
 static afs_int32 iNewEntry(struct rx_call *call, char aname[], afs_int32 aid,
                           afs_int32 oid, afs_int32 *cid);
@@ -91,7 +89,7 @@ static afs_int32 dumpEntry(struct rx_call *call, afs_int32 apos,
 static afs_int32 addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
                            afs_int32 *cid);
 static afs_int32 nameToID(struct rx_call *call, namelist *aname, idlist *aid);
-static afs_int32 idToName(struct rx_call *call, idlist *aid, namelist *aname);
+static afs_int32 idToName(struct rx_call *call, idlist *aid, namelist *aname, afs_int32 *cid);
 static afs_int32 Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid);
 static afs_int32 UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
                             struct PrUpdateEntry *uentry, afs_int32 *cid);
@@ -102,8 +100,8 @@ static afs_int32 getCPS(struct rx_call *call, afs_int32 aid, prlist *alist,
 static afs_int32 getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost,
                         prlist *alist, afs_int32 *over, afs_int32 *cid);
 static afs_int32 getHostCPS(struct rx_call *call, afs_uint32 ahost,
-                           prlist *alist, afs_int32 *over);
-static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid);
+                           prlist *alist, afs_int32 *over, afs_int32 *cid);
+static afs_int32 listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid, afs_int32 *cid);
 static afs_int32 setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag,
                        afs_int32 *cid);
 static afs_int32 listEntry(struct rx_call *call, afs_int32 aid,
@@ -163,6 +161,8 @@ CreateOK(struct ubik_trans *ut, afs_int32 cid, afs_int32 oid, afs_int32 flag,
                return 0;
        }
     } else {                   /* creating a user */
+       if (oid == ANONYMOUSID)
+           return 0;
        if (!admin && !pr_noAuth)
            return 0;
     }
@@ -178,6 +178,58 @@ WhoIsThis(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid)
     return code;
 }
 
+static int
+WritePreamble(struct ubik_trans **tt)
+{
+    int code;
+
+    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)
+       goto out;
+
+    code = read_DbHeader(*tt);
+
+out:
+    if (code)
+       ubik_AbortTrans(*tt);
+
+    return code;
+}
+
+static int
+ReadPreamble(struct ubik_trans **tt)
+{
+    int code;
+
+    code = Initdb();
+    if (code)
+       return code;
+
+    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, tt);
+    if (code)
+       return code;
+
+    code = ubik_SetLock(*tt, 1, 1, LOCKREAD);
+    if (code)
+       goto out;
+
+    code = read_DbHeader(*tt);
+
+out:
+    if (code)
+       ubik_AbortTrans(*tt);
+
+    return code;
+}
+
 afs_int32
 SPR_INewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid)
 {
@@ -203,18 +255,10 @@ iNewEntry(struct rx_call *call, char aname[], afs_int32 aid, afs_int32 oid,
     int admin;
 
     stolower(aname);
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
+
+    code = WritePreamble(&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)
@@ -270,38 +314,44 @@ newEntry(struct rx_call *call, char aname[], afs_int32 flag, afs_int32 oid,
     afs_int32 code;
     struct ubik_trans *tt;
     int admin;
+    int foreign = 0;
     char cname[PR_MAXNAMELEN];
     stolower(aname);
-    code = Initdb();
-    if (code)
-       return code;
-    code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
+
+    code = WritePreamble(&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 = ((!restricted && !strcmp(aname, cname))) || IsAMemberOf(tt, *cid, SYSADMINID);
-       oid = *cid = SYSADMINID;
+    if (code && code != 2)
+       ABORT_WITH(tt, PRPERM);
+    admin = IsAMemberOf(tt, *cid, SYSADMINID);
+    if (code == 2 /* foreign cell request */) {
+       foreign = 1;
+
+       if (!restricted && (strcmp(aname, cname) == 0)) {
+           /* can't autoregister while providing an owner id */
+           if (oid != 0)
+               ABORT_WITH(tt, PRPERM);
+
+           admin = 1;
+           oid = SYSADMINID;
+       }
     }
     if (!CreateOK(tt, *cid, oid, flag, admin))
        ABORT_WITH(tt, PRPERM);
 
     code = CreateEntry(tt, aname, aid, 0, flag, oid, *cid);
+    /*
+     * If this was an autoregistration then be sure to audit log
+     * the proper id as the creator.
+     */
+    if (foreign && code == 0 && *aid > 0)
+       *cid = *aid;
     if (code != PRSUCCESS)
        ABORT_WITH(tt, code);
 
@@ -333,22 +383,15 @@ whereIsIt(struct rx_call *call, afs_int32 aid, afs_int32 *apos, afs_int32 *cid)
     struct ubik_trans *tt;
     afs_int32 temp;
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+    code = ReadPreamble(&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 (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
 
     temp = FindByID(tt, aid);
     if (!temp)
@@ -381,18 +424,9 @@ dumpEntry(struct rx_call *call, afs_int32 apos, struct prdebugentry *aentry,
     afs_int32 code;
     struct ubik_trans *tt;
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+    code = ReadPreamble(&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)
@@ -442,22 +476,14 @@ addToGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid, afs_int32 *cid)
     struct prentry tentry;
     struct prentry uentry;
 
-    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);
+
+    code = WritePreamble(&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)
@@ -537,26 +563,18 @@ nameToID(struct rx_call *call, namelist *aname, idlist *aid)
     if (size < 0)
        return PRTOOMANY;
 
-    aid->idlist_val = (afs_int32 *) malloc(size * sizeof(afs_int32));
+    aid->idlist_val = 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);
+    code = ReadPreamble(&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; i < aname->namelist_len; i++) {
        char vname[256];
        char *nameinst, *cell;
+       afs_int32 islocal = 1;
 
        strncpy(vname, aname->namelist_val[i], sizeof(vname));
        vname[sizeof(vname)-1] ='\0';
@@ -568,10 +586,16 @@ nameToID(struct rx_call *call, namelist *aname, idlist *aid)
            cell++;
        }
 
-       if (cell && afs_is_foreign_ticket_name(nameinst,NULL,cell,pr_realmName))
-           code = NameToID(tt, aname->namelist_val[i], &aid->idlist_val[i]);
-       else
+       if (cell && *cell) {
+           code = afsconf_IsLocalRealmMatch(prdir, &islocal, nameinst, NULL, cell);
+           ViceLog(125,
+                   ("PTS_NameToID: afsconf_IsLocalRealmMatch(); code=%d, nameinst=%s, cell=%s\n",
+                    code, nameinst, cell));
+       }
+       if (islocal)
            code = NameToID(tt, nameinst, &aid->idlist_val[i]);
+       else
+           code = NameToID(tt, aname->namelist_val[i], &aid->idlist_val[i]);
 
        if (code != PRSUCCESS)
            aid->idlist_val[i] = ANONYMOUSID;
@@ -604,15 +628,16 @@ afs_int32
 SPR_IDToName(struct rx_call *call, idlist *aid, namelist *aname)
 {
     afs_int32 code;
+    afs_int32 cid = ANONYMOUSID;
 
-    code = idToName(call, aid, aname);
+    code = idToName(call, aid, aname, &cid);
     osi_auditU(call, PTS_IdToNmEvent, code, AUD_END);
     ViceLog(125, ("PTS_IDToName: code %d\n", code));
     return code;
 }
 
 static afs_int32
-idToName(struct rx_call *call, idlist *aid, namelist *aname)
+idToName(struct rx_call *call, idlist *aid, namelist *aname, afs_int32 *cid)
 {
     afs_int32 code;
     struct ubik_trans *tt;
@@ -624,9 +649,9 @@ idToName(struct rx_call *call, idlist *aid, namelist *aname)
     size = aid->idlist_len;
     if (size == 0)
        return 0;
-    if (size < 0)
+    if (size < 0 || size > INT_MAX / PR_MAXNAMELEN)
        return PRTOOMANY;
-    aname->namelist_val = (prname *) malloc(size * PR_MAXNAMELEN);
+    aname->namelist_val = calloc(size, PR_MAXNAMELEN);
     aname->namelist_len = 0;
     if (aname->namelist_val == 0)
        return PRNOMEM;
@@ -635,18 +660,15 @@ idToName(struct rx_call *call, idlist *aid, namelist *aname)
     if (size == 0)
        return PRTOOMANY;       /* rxgen will probably handle this */
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+    code = ReadPreamble(&tt);
     if (code)
        return code;
-    code = ubik_SetLock(tt, 1, 1, LOCKREAD);
-    if (code)
-       ABORT_WITH(tt, code);
-    code = read_DbHeader(tt);
+
+    code = WhoIsThis(call, tt, cid);
     if (code)
-       ABORT_WITH(tt, code);
+       ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
 
     for (i = 0; i < aid->idlist_len; i++) {
        code = IDToName(tt, aid->idlist_val[i], aname->namelist_val[i]);
@@ -692,23 +714,13 @@ Delete(struct rx_call *call, afs_int32 aid, afs_int32 *cid)
     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);
+
+    code = WritePreamble(&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)
@@ -941,26 +953,16 @@ UpdateEntry(struct rx_call *call, afs_int32 aid, char *name,
     afs_int32 loc;
     int id = 0;
 
-    code = Initdb();
-    if (code)
-       return code;
-    if (code != PRSUCCESS)
-       return code;
     if (aid) {
        id = aid;
        if (aid == SYSADMINID || aid == ANYUSERID || aid == AUTHUSERID
            || aid == ANONYMOUSID)
            return PRPERM;
     }
-    code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
+
+    code = WritePreamble(&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)
@@ -1033,18 +1035,9 @@ removeFromGroup(struct rx_call *call, afs_int32 aid, afs_int32 gid,
     struct prentry uentry;
     struct prentry gentry;
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
+    code = WritePreamble(&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)
@@ -1116,18 +1109,16 @@ getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over,
     *over = 0;
     alist->prlist_len = 0;
     alist->prlist_val = NULL;
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+
+    code = ReadPreamble(&tt);
     if (code)
        return code;
-    code = ubik_SetLock(tt, 1, 1, LOCKREAD);
-    if (code)
-       ABORT_WITH(tt, code);
-    code = read_DbHeader(tt);
+
+    code = WhoIsThis(call, tt, cid);
     if (code)
-       ABORT_WITH(tt, code);
+       ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
 
     temp = FindByID(tt, aid);
     if (!temp)
@@ -1136,9 +1127,7 @@ getCPS(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *over,
     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))
+    if (!AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
        ABORT_WITH(tt, PRPERM);
 
     code = GetList(tt, &tentry, alist, 1);
@@ -1189,23 +1178,16 @@ getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost, prlist *alist,
     afs_int32 hostid;
     int host_list = 0;
     struct in_addr iaddr;
+    char hoststr[16];
 
     *over = 0;
     iaddr.s_addr = ntohl(ahost);
     alist->prlist_len = 0;
     alist->prlist_val = NULL;
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+
+    code = ReadPreamble(&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);
@@ -1221,7 +1203,7 @@ getCPS2(struct rx_call *call, afs_int32 aid, afs_uint32 ahost, prlist *alist,
            || !AccessOK(tt, *cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY))
            ABORT_WITH(tt, PRPERM);
     }
-    code = NameToID(tt, inet_ntoa(iaddr), &hostid);
+    code = NameToID(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr), &hostid);
     if (code == PRSUCCESS && hostid != 0) {
        temp = FindByID(tt, hostid);
        if (temp) {
@@ -1252,41 +1234,41 @@ SPR_GetHostCPS(struct rx_call *call, afs_int32 ahost, prlist *alist,
               afs_int32 *over)
 {
     afs_int32 code;
+    afs_int32 cid = ANONYMOUSID;
 
-    code = getHostCPS(call, ahost, alist, over);
+    code = getHostCPS(call, ahost, alist, over, &cid);
     osi_auditU(call, PTS_GetHCPSEvent, code, AUD_HOST, htonl(ahost), AUD_END);
-    ViceLog(125, ("PTS_GetHostCPS: code %d ahost %d\n", code, ahost));
+    ViceLog(125, ("PTS_GetHostCPS: code %d ahost %u (0x%x)\n", code, ahost, ahost));
     return code;
 }
 
 afs_int32
 getHostCPS(struct rx_call *call, afs_uint32 ahost, prlist *alist,
-          afs_int32 *over)
+          afs_int32 *over, afs_int32 *cid)
 {
     afs_int32 code, temp;
     struct ubik_trans *tt;
     struct prentry host_tentry;
     afs_int32 hostid;
     struct in_addr iaddr;
+    char hoststr[16];
 
     *over = 0;
     iaddr.s_addr = ntohl(ahost);
     alist->prlist_len = 0;
     alist->prlist_val = NULL;
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+
+    code = ReadPreamble(&tt);
     if (code)
        return code;
-    code = ubik_SetLock(tt, 1, 1, LOCKREAD);
-    if (code)
-       ABORT_WITH(tt, code);
-    code = read_DbHeader(tt);
+
+    code = WhoIsThis(call, tt, cid);
     if (code)
-       ABORT_WITH(tt, code);
+       ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
 
-    code = NameToID(tt, inet_ntoa(iaddr), &hostid);
+    code = NameToID(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr), &hostid);
     if (code == PRSUCCESS && hostid != 0) {
        temp = FindByID(tt, hostid);
        if (temp) {
@@ -1314,31 +1296,29 @@ afs_int32
 SPR_ListMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
 {
     afs_int32 code;
+    afs_int32 cid = ANONYMOUSID;
 
-    code = listMax(call, uid, gid);
+    code = listMax(call, uid, gid, &cid);
     osi_auditU(call, PTS_LstMaxEvent, code, AUD_END);
     ViceLog(125, ("PTS_ListMax: code %d\n", code));
     return code;
 }
 
 afs_int32
-listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid)
+listMax(struct rx_call *call, afs_int32 *uid, afs_int32 *gid, afs_int32 *cid)
 {
     afs_int32 code;
     struct ubik_trans *tt;
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+    code = ReadPreamble(&tt);
     if (code)
        return code;
-    code = ubik_SetLock(tt, 1, 1, LOCKREAD);
-    if (code)
-       ABORT_WITH(tt, code);
-    code = read_DbHeader(tt);
+
+    code = WhoIsThis(call, tt, cid);
     if (code)
-       ABORT_WITH(tt, code);
+       ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
 
     code = GetMax(tt, uid, gid);
     if (code != PRSUCCESS)
@@ -1369,18 +1349,9 @@ setMax(struct rx_call *call, afs_int32 aid, afs_int32 gflag, afs_int32 *cid)
     afs_int32 code;
     struct ubik_trans *tt;
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTrans(dbase, UBIK_WRITETRANS, &tt);
+    code = WritePreamble(&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)
@@ -1421,22 +1392,15 @@ listEntry(struct rx_call *call, afs_int32 aid, struct prcheckentry *aentry,
     afs_int32 temp;
     struct prentry tentry;
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+    code = ReadPreamble(&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 (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
     temp = FindByID(tt, aid);
     if (!temp)
        ABORT_WITH(tt, PRNOENT);
@@ -1494,18 +1458,9 @@ listEntries(struct rx_call *call, afs_int32 flag, afs_int32 startindex,
     bulkentries->prentries_val = 0;
     bulkentries->prentries_len = 0;
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+    code = ReadPreamble(&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.
@@ -1569,9 +1524,8 @@ put_prentries(struct prentry *tentry, prentries *bulkentries)
 
     if (bulkentries->prentries_val == 0) {
        bulkentries->prentries_len = 0;
-       bulkentries->prentries_val =
-           (struct prlistentries *)malloc(PR_MAXENTRIES *
-                                          sizeof(struct prentry));
+       bulkentries->prentries_val = malloc(PR_MAXENTRIES *
+                                           sizeof(struct prlistentries));
        if (!bulkentries->prentries_val) {
            return (PRNOMEM);
        }
@@ -1581,9 +1535,10 @@ put_prentries(struct prentry *tentry, prentries *bulkentries)
        return (-1);
     }
 
-    entry = (struct prlistentries *)bulkentries->prentries_val;
+    entry = bulkentries->prentries_val;
     entry += bulkentries->prentries_len;
 
+    memset(entry, 0, sizeof(*entry));
     entry->flags = tentry->flags >> PRIVATE_SHIFT;
     if (entry->flags == 0) {
        entry->flags =
@@ -1598,7 +1553,6 @@ put_prentries(struct prentry *tentry, prentries *bulkentries)
     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;
 }
@@ -1629,23 +1583,13 @@ changeEntry(struct rx_call *call, afs_int32 aid, char *name, afs_int32 oid,
        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);
+
+    code = WritePreamble(&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)
@@ -1695,22 +1639,13 @@ setFieldsEntry(struct rx_call *call,
 
     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);
+
+    code = WritePreamble(&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)
@@ -1790,18 +1725,9 @@ listElements(struct rx_call *call, afs_int32 aid, prlist *alist,
     alist->prlist_len = 0;
     alist->prlist_val = NULL;
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+    code = ReadPreamble(&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)
@@ -1855,18 +1781,19 @@ listSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
     alist->prlist_len = 0;
     alist->prlist_val = (afs_int32 *) 0;
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       goto done;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+    code = ReadPreamble(&tt);
     if (code)
-       goto done;
-    code = ubik_SetLock(tt, 1, 1, LOCKREAD);
-    if (code)
-       ABORT_WITH(tt, code);
+       return code;
+
     code = WhoIsThis(call, tt, cid);
     if (code)
        ABORT_WITH(tt, PRPERM);
+    if (!pr_noAuth && restrict_anonymous && *cid == ANONYMOUSID)
+       ABORT_WITH(tt, PRPERM);
+
+    code = ubik_SetLock(tt, 1, 1, LOCKREAD);
+    if (code)
+       ABORT_WITH(tt, code);
 
     temp = FindByID(tt, aid);
     if (!temp)
@@ -1886,7 +1813,6 @@ listSuperGroups(struct rx_call *call, afs_int32 aid, prlist *alist,
 
     code = ubik_EndTrans(tt);
 
-  done:
     return code;
 }
 
@@ -1930,18 +1856,9 @@ listOwned(struct rx_call *call, afs_int32 aid, prlist *alist, afs_int32 *lastP,
     start = *lastP;
     *lastP = 0;
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+    code = ReadPreamble(&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)
@@ -2005,18 +1922,9 @@ isAMemberOf(struct rx_call *call, afs_int32 uid, afs_int32 gid, afs_int32 *flag,
     afs_int32 code;
     struct ubik_trans *tt;
 
-    code = Initdb();
-    if (code != PRSUCCESS)
-       return code;
-    code = ubik_BeginTransReadAny(dbase, UBIK_READTRANS, &tt);
+    code = ReadPreamble(&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 uloc = FindByID(tt, uid);
@@ -2062,11 +1970,12 @@ addWildCards(struct ubik_trans *tt, prlist *alist, afs_uint32 host)
     afs_int32 hostid;
     int size = 0, i, code;
     int added = 0;
+    char hoststr[16];
 
     while ((host = (host & wild))) {
        wild = htonl(ntohl(wild) << 8);
        iaddr.s_addr = host;
-       code = NameToID(tt, inet_ntoa(iaddr), &hostid);
+       code = NameToID(tt, afs_inet_ntoa_r(iaddr.s_addr, hoststr), &hostid);
        if (code == PRSUCCESS && hostid != 0) {
            temp = FindByID(tt, hostid);
            if (temp) {
@@ -2103,7 +2012,7 @@ static afs_int32
 WhoIsThisWithName(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid,
                  char *aname)
 {
-    int foreign = 0;
+    afs_int32 islocal = 1;
     /* aid is set to the identity of the caller, if known, else ANONYMOUSID */
     /* returns -1 and sets aid to ANONYMOUSID on any failure */
     struct rx_connection *tconn;
@@ -2117,19 +2026,20 @@ WhoIsThisWithName(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid,
     *aid = ANONYMOUSID;
     tconn = rx_ConnectionOf(acall);
     code = rx_SecurityClassOf(tconn);
-    if (code == 0)
+    if (code == RX_SECIDX_NULL)
        return 0;
-    else if (code == 1) {      /* vab class */
+    else if (code == RX_SECIDX_VAB) {
        goto done;              /* no longer supported */
-    } else if (code == 2) {    /* kad class */
+    } else if (code == RX_SECIDX_KAD) {
        if ((code = rxkad_GetServerInfo(rx_ConnectionOf(acall), NULL, NULL,
                                        name, inst, tcell, NULL)))
            goto done;
 
-       if (tcell[0])
-           foreign = afs_is_foreign_ticket_name(name, inst, tcell,
-                                                pr_realmName);
-
+       if (tcell[0]) {
+           code = afsconf_IsLocalRealmMatch(prdir, &islocal, name, inst, tcell);
+           if (code)
+               goto done;
+       }
        strncpy(vname, name, sizeof(vname));
        if ((ilen = strlen(inst))) {
            if (strlen(vname) + 1 + ilen >= sizeof(vname))
@@ -2137,13 +2047,13 @@ WhoIsThisWithName(struct rx_call *acall, struct ubik_trans *at, afs_int32 *aid,
            strcat(vname, ".");
            strcat(vname, inst);
        }
-       if (foreign) {
+       if (!islocal) {
             if (strlen(vname) + strlen(tcell) + 1  >= sizeof(vname))
                goto done;
             strcat(vname, "@");
             strcat(vname, tcell);
             lcstring(vname, vname, sizeof(vname));
-            code = NameToID(at, vname, aid);
+            NameToID(at, vname, aid);
             if (aname)
                strcpy(aname, vname);
             return 2;