From dba0cf81984c56e6f2b1486f247952a0358bb0b5 Mon Sep 17 00:00:00 2001 From: mar Date: Fri, 21 Sep 1990 15:17:34 +0000 Subject: [PATCH] from Richard --- afssync/ptprocs.c | 1134 +++++++++++++++++++++++++++++++++++++++++++++ afssync/ptutils.c | 966 ++++++++++++++++++++++---------------- afssync/resync.qc | 6 +- afssync/sync.qc | 6 +- afssync/ubik.c | 75 ++- afssync/utils.c | 267 ++++++----- 6 files changed, 1937 insertions(+), 517 deletions(-) create mode 100644 afssync/ptprocs.c diff --git a/afssync/ptprocs.c b/afssync/ptprocs.c new file mode 100644 index 00000000..ab8a1195 --- /dev/null +++ b/afssync/ptprocs.c @@ -0,0 +1,1134 @@ +/* Copyright (C) 1989 Transarc Corporation - All rights reserved */ + +/* + * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988 + * LICENSED MATERIALS - PROPERTY OF IBM + * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083 + */ + +#ifndef lint +static char rcsid[] = "$Header$"; +#endif + +/* + Sherri Nichols + Information Technology Center + November, 1988 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ptserver.h" +#include "pterror.h" +#include + +#ifdef AFS_ATHENA_STDENV +#include +#endif + +extern struct ubik_dbase *dbase; +extern long Initdb(); +extern int pr_noAuth; + +static int CreateOK (ut, cid, oid, flag, admin) + struct ubik_trans *ut; + long cid; /* id of caller */ + long oid; /* id of owner */ + long flag; /* indicates type of entry */ + int admin; /* sysadmin membership */ +{ + if (flag & (PRGRP | PRFOREIGN)) { + /* 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! */ +} + +long WhoIsThis (acall, at, aid) + struct rx_call *acall; + struct ubik_trans *at; + long *aid; +{ + /* aid is set to the identity of the caller, if known, ANONYMOUSID otherwise */ + /* returns -1 and sets aid to ANONYMOUSID on any failure */ + register struct rx_connection *tconn; + struct rxvab_conn *tc; + register long code; + char tcell[MAXKTCREALMLEN]; + long exp; + 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 */ + tc = (struct rxvab_conn *) tconn->securityData; + if (!tc) goto done; + *aid = ntohl(tc->viceID); + code = 0; + } + else if (code == 2) { /* kad class */ + if (code = rxkad_GetServerInfo + (acall->conn, (long *) 0, &exp, name, inst, tcell, (long *) 0)) + goto done; + if (exp < FT_ApproxTime()) goto done; + if (strlen (tcell)) { + extern char *pr_realmName; +#ifdef AFS_ATHENA_STDENV + static char local_realm[REALM_SZ] = ""; + if (!local_realm[0]) { + krb_get_lrealm (local_realm, 0); + } +#endif + if ( +#ifdef AFS_ATHENA_STDENV + strcasecmp (local_realm, tcell) && +#endif + strcasecmp (pr_realmName, tcell)) + 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); + } + lcstring(vname, vname, sizeof(vname)); + code = NameToID(at,vname,aid); + } + done: + if (code && !pr_noAuth) return -1; + return 0; +} + +long PR_INewEntry(call,aname,aid,oid) + struct rx_call *call; + char aname[PR_MAXNAMELEN]; + long aid; + long oid; +{ + /* used primarily for conversion - not intended to be used as usual means + of entering people into the database. */ + struct ubik_trans *tt; + register long code; + long gflag = 0; + long cid; + int admin; + +#define abort_with(code) return (ubik_AbortTrans(tt),code) + + 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 (code); + + code = WhoIsThis(call,tt,&cid); + if (code) abort_with (PRPERM); + admin = IsAMemberOf(tt,cid,SYSADMINID); + + /* first verify the id is good */ + if (aid == 0) abort_with (PRPERM); + if (aid < 0) { + gflag |= PRGRP; + /* only sysadmin can reuse a group id */ + if (!admin && !pr_noAuth && (aid != ntohl(cheader.maxGroup)-1)) + abort_with (PRPERM); + } + if (FindByID (tt, aid)) abort_with (PRIDEXIST); + + /* check a few other things */ + if (!CreateOK (tt, cid, oid, gflag, admin)) abort_with (PRPERM); + + code = CreateEntry (tt,aname,&aid,1,gflag,oid,cid); + if (code != PRSUCCESS) { + ubik_AbortTrans(tt); + return code; + } + /* finally, commit transaction */ + code = ubik_EndTrans(tt); + if (code) return code; + return PRSUCCESS; +} + + +long PR_NewEntry (call, aname, flag, oid, aid) + struct rx_call *call; + char aname[PR_MAXNAMELEN]; + long flag; + long oid; + long *aid; +{ + register long code; + struct ubik_trans *tt; + long cid; + int admin; + + 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: + ubik_AbortTrans(tt); + return code; + } + code = WhoIsThis(call,tt,&cid); + if (code) { + perm: + ubik_AbortTrans(tt); + return PRPERM; + } + admin = IsAMemberOf(tt,cid,SYSADMINID); + + if (!CreateOK (tt, cid, oid, flag, admin)) goto perm; + + code = CreateEntry (tt,aname,aid,0,flag,oid,cid); + if (code != PRSUCCESS) goto abort; + + code = ubik_EndTrans(tt); + if (code) return code; + return PRSUCCESS; +} + + + +PR_WhereIsIt(call,aid,apos) +struct rx_call *call; +long aid; +long *apos; +{ + register long code; + struct ubik_trans *tt; + long temp; + + code = Initdb(); + if (code != PRSUCCESS) return code; + code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt); + if (code) return code; + code = ubik_SetLock(tt,1,1,LOCKREAD); + if (code) { + ubik_AbortTrans(tt); + return code; + } + temp = FindByID(tt,aid); + if (!temp) { + ubik_AbortTrans(tt); + return PRNOENT; + } + *apos = temp; + code = ubik_EndTrans(tt); + if (code) return code; + return PRSUCCESS; +} + + +PR_DumpEntry(call,apos, aentry) +struct rx_call *call; +long apos; +struct prdebugentry *aentry; +{ + register long code; + struct ubik_trans *tt; + + code = Initdb(); + if (code != PRSUCCESS) return code; + code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt); + if (code) return code; + code = ubik_SetLock(tt,1,1,LOCKREAD); + if (code) { + abort: + ubik_AbortTrans(tt); + return code; + } + code = pr_ReadEntry(tt, 0, apos, aentry); + if (code) goto abort; + + if (aentry->flags & PRCONT) { /* wrong type, get coentry instead */ + code = pr_ReadCoEntry(tt, 0, apos, aentry); + if (code) goto abort; + } + code = ubik_EndTrans(tt); + if (code) return code; + return PRSUCCESS; +} + +PR_AddToGroup(call,aid,gid) +struct rx_call *call; +long aid; +long gid; +{ + register long code; + struct ubik_trans *tt; + long tempu; + long tempg; + struct prentry tentry; + struct prentry uentry; + long 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) { + ubik_AbortTrans(tt); + return code; + } + code = WhoIsThis(call, tt, &cid); + if (code) { + ubik_AbortTrans(tt); + return PRPERM; + } + tempu = FindByID(tt,aid); + if (!tempu) { + ubik_AbortTrans(tt); + return PRNOENT; + } + bzero(&uentry,sizeof(uentry)); + code = pr_ReadEntry(tt,0,tempu,&uentry); + if (code != 0) { + ubik_AbortTrans(tt); + return code; + } + /* we don't allow groups as members of groups at present */ + if (uentry.flags & PRGRP) { + ubik_AbortTrans(tt); + return PRNOTUSER; + } + tempg = FindByID(tt,gid); + if (!tempg) { + ubik_AbortTrans(tt); + return PRNOENT; + } + code = pr_ReadEntry(tt,0,tempg,&tentry); + if (code != 0) { + ubik_AbortTrans(tt); + return code; + } + /* make sure that this is a group */ + if (!(tentry.flags & PRGRP)) { + ubik_AbortTrans(tt); + return PRNOTGROUP; + } + if (!AccessOK (tt, cid, &tentry, PRP_ADD_MEM, PRP_ADD_ANY)) { + ubik_AbortTrans(tt); + return PRPERM; + } + + code = AddToEntry (tt, &tentry, tempg, aid); + if (code != PRSUCCESS) { + ubik_AbortTrans(tt); + return code; + } + /* now, modify the user's entry as well */ + code = AddToEntry (tt, &uentry, tempu, gid); + if (code != PRSUCCESS) { + ubik_AbortTrans(tt); + return code; + } + code = ubik_EndTrans(tt); + if (code) return code; + return PRSUCCESS; +} + +long PR_NameToID (call, aname, aid) + struct rx_call *call; + namelist *aname; + idlist *aid; +{ + register long code; + struct ubik_trans *tt; + long i; + int size; + int count = 0; + + /* must do this first for RPC stub to work */ + size = aname->namelist_len; + if ((size <= 0) || (size > PR_MAXLIST)) size = 0; + aid->idlist_val = (long *)malloc(size*sizeof(long)); + aid->idlist_len = 0; + if (aname->namelist_len == 0) return 0; + if (size == 0) return PRTOOMANY; /* rxgen will probably handle this */ + + code = Initdb(); + if (code != PRSUCCESS) return code; + code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt); + if (code) return code; + code = ubik_SetLock(tt,1,1,LOCKREAD); + if (code) { + ubik_AbortTrans(tt); + return 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; +} + +long PR_IDToName (call, aid, aname) + struct rx_call *call; + idlist *aid; + namelist *aname; +{ + register long code; + struct ubik_trans *tt; + long i; + int size; + int count = 0; + + /* leave this first for rpc stub */ + size = aid->idlist_len; + if ((size <= 0) || (size > PR_MAXLIST)) size = 0; + aname->namelist_val = (prname *)malloc(size*PR_MAXNAMELEN); + aname->namelist_len = 0; + 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_BeginTrans(dbase,UBIK_READTRANS,&tt); + if (code) return code; + code = ubik_SetLock(tt,1,1,LOCKREAD); + if (code) { + ubik_AbortTrans(tt); + return code; + } + for (i=0;iidlist_len;i++) { + /* interface won't allow more than PR_MAXLIST to be sent in */ + 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; +} + +long PR_Delete (call, aid) + struct rx_call *call; + long aid; +{ + register long code; + struct ubik_trans *tt; + long cid; + struct prentry tentry; + long 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: + ubik_AbortTrans(tt); + return code; + } + code = WhoIsThis(call,tt,&cid); + if (code) { + ubik_AbortTrans(tt); + return PRPERM; + } + + /* Read in entry to be deleted */ + loc = FindByID (tt, aid); + if (loc == 0) {code = PRNOENT; goto abort;} + code = pr_ReadEntry (tt, 0, loc, &tentry); + if (code) {code = PRDBFAIL; goto abort;} + + /* Do some access checking */ + if (tentry.owner != cid && + !IsAMemberOf (tt, cid, SYSADMINID) && + !IsAMemberOf (tt, cid, tentry.owner) && !pr_noAuth) + {code = PRPERM; goto abort;} + + /* Delete each continuation block as a separate transaction so that no one + * transaction become to large to complete. */ + nptr = tentry.next; + while (nptr != NULL) { + struct contentry centry; + int i; + + code = pr_ReadCoEntry(tt, 0, nptr, ¢ry); + if (code != 0) {code = PRDBFAIL; goto abort;} + for (i=0;iprlist_len = 0; + alist->prlist_val = (long *) 0; + code = Initdb(); + if (code != PRSUCCESS) goto done; + code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt); + if (code) goto done; + code = ubik_SetLock(tt,1,1,LOCKREAD); + if (code) { + abort: + ubik_AbortTrans(tt); + goto done; + } + + + temp = FindByID(tt,aid); + if (!temp) {code = PRNOENT; goto abort;} + code = pr_ReadEntry (tt, 0, temp, &tentry); + if (code) goto abort; + + if (0) { /* afs doesn't authenticate yet */ + code = WhoIsThis (call, tt, &cid); + if (code || !AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) { + code = PRPERM; + goto abort; + } + } + + code = GetList(tt, &tentry, alist, 1); + *over = 0; + if (code == PRTOOMANY) *over = 1; + else if (code != PRSUCCESS) { + ubik_AbortTrans(tt); + goto done; + } + + code = ubik_EndTrans(tt); + +done: + /* return code, making sure that prlist_val points to malloc'd memory */ + if (!alist->prlist_val) + alist->prlist_val = (long *) malloc(0); /* make xdr stub happy */ + return code; +} + +PR_ListMax(call,uid,gid) +struct rx_call *call; +long *uid; +long *gid; +{ + register long code; + struct ubik_trans *tt; + + code = Initdb(); + if (code != PRSUCCESS) return code; + code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt); + if (code) return code; + code = ubik_SetLock(tt,1,1,LOCKREAD); + if (code) { + ubik_AbortTrans(tt); + return code; + } + code = GetMax(tt,uid,gid); + if (code != PRSUCCESS) { + ubik_AbortTrans(tt); + return code; + } + code = ubik_EndTrans(tt); + if (code) return code; + return PRSUCCESS; +} + +PR_SetMax(call,aid,gflag) +struct rx_call *call; +long aid; +long gflag; +{ + register long code; + struct ubik_trans *tt; + long 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) { + ubik_AbortTrans(tt); + return code; + } + code = WhoIsThis(call,tt,&cid); + if (code) { + ubik_AbortTrans(tt); + return PRPERM; + } + if (!AccessOK (tt, cid, 0, 0, 0)) { + ubik_AbortTrans(tt); + return PRPERM; + } + if (((gflag & PRGRP) && (aid > 0)) || + (!(gflag & PRGRP) && (aid < 0))) { + code = PRBADARG; + goto abort; + } + + code = SetMax(tt,aid,gflag); + if (code != PRSUCCESS) { + abort: + ubik_AbortTrans(tt); + return code; + } + code = ubik_EndTrans(tt); + if (code) return code; + return PRSUCCESS; +} + +PR_ListEntry(call,aid,aentry) +struct rx_call *call; +long aid; +struct prcheckentry *aentry; +{ + register long code; + struct ubik_trans *tt; + long cid; + long temp; + struct prentry tentry; + + code = Initdb(); + if (code != PRSUCCESS) return code; + code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt); + if (code) return code; + code = ubik_SetLock(tt,1,1,LOCKREAD); + if (code) { + ubik_AbortTrans(tt); + return code; + } + code = WhoIsThis(call,tt,&cid); + if (code) { + perm: + ubik_AbortTrans(tt); + return PRPERM; + } + temp = FindByID(tt,aid); + if (!temp) { + ubik_AbortTrans(tt); + return PRNOENT; + } + code = pr_ReadEntry(tt, 0, temp, &tentry); + if (code != 0) { + ubik_AbortTrans(tt); + return code; + } + if (!AccessOK (tt, cid, &tentry, PRP_STATUS_MEM, PRP_STATUS_ANY)) goto perm; + + 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->flags; + 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; + bzero (aentry->reserved, sizeof(aentry->reserved)); + code = ubik_EndTrans(tt); + if (code) return code; + return PRSUCCESS; +} + +PR_ChangeEntry(call,aid,name,oid,newid) +struct rx_call *call; +long aid; +char *name; +long oid; +long newid; +{ + register long code; + struct ubik_trans *tt; + long pos; + long cid; + + 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) { + ubik_AbortTrans(tt); + return code; + } + code = WhoIsThis(call,tt,&cid); + if (code) { + ubik_AbortTrans(tt); + return PRPERM; + } + pos = FindByID(tt,aid); + if (!pos) { + ubik_AbortTrans(tt); + return PRNOENT; + } + /* protection check in changeentry */ + code = ChangeEntry(tt,aid,cid,name,oid,newid); + if (code != PRSUCCESS) { + ubik_AbortTrans(tt); + return code; + } + code = ubik_EndTrans(tt); + return code; +} + +PR_SetFieldsEntry(call, id, mask, flags, ngroups, nusers, spare1, spare2) + struct rx_call *call; + long id; + long mask; /* specify which fields to update */ + long flags, ngroups, nusers; + long spare1, spare2; +{ + register long code; + struct ubik_trans *tt; + long pos; + long cid; + struct prentry tentry; + long 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: + ubik_AbortTrans(tt); + return code; + } + code = WhoIsThis(call,tt,&cid); + if (code) { + perm: + ubik_AbortTrans(tt); + return PRPERM; + } + pos = FindByID(tt,id); + if (!pos) { + ubik_AbortTrans(tt); + return PRNOENT; + } + code = pr_ReadEntry (tt, 0, pos, &tentry); + if (code) goto abort; + tflags = tentry.flags; + + if (mask & (PR_SF_NGROUPS | PR_SF_NUSERS)) { + if (!AccessOK (tt, cid, 0, 0, 0)) goto perm; + if ((tflags & PRQUOTA) == 0) { /* default if only setting one */ + tentry.ngroups = tentry.nusers = 20; + } + } else { + if (!AccessOK (tt, cid, &tentry, 0, 0)) goto perm; + } + + if (mask & 0xffff) { /* if setting flag bits */ + long 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) {code = PRBADARG; goto abort;} + tentry.ngroups = ngroups; + tflags |= PRQUOTA; + } + + if (mask & PR_SF_NUSERS) { /* setting foreign user limit */ + if (nusers < 0) {code = PRBADARG; goto abort;} + tentry.nusers = nusers; + tflags |= PRQUOTA; + } + tentry.flags = tflags; + + code = pr_WriteEntry (tt, 0, pos, &tentry); + if (code) goto abort; + + code = ubik_EndTrans(tt); + return code; +} + +long PR_ListElements (call, aid, alist, over) + struct rx_call *call; + long aid; + prlist *alist; + long *over; +{ + register long code; + struct ubik_trans *tt; + long cid; + long temp; + struct prentry tentry; + + alist->prlist_len = 0; + alist->prlist_val = (long *) 0; + + code = Initdb(); + if (code != PRSUCCESS) goto done; + code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt); + if (code) goto done; + code = ubik_SetLock(tt,1,1,LOCKREAD); + if (code) { + abort: + ubik_AbortTrans(tt); + goto done; + } + code = WhoIsThis(call,tt,&cid); + if (code) { + perm: + code = PRPERM; + ubik_AbortTrans(tt); + goto done; + } + + temp = FindByID(tt,aid); + if (!temp) {code = PRNOENT; goto abort;} + code = pr_ReadEntry (tt, 0, temp, &tentry); + if (code) goto abort; + if (!AccessOK (tt, cid, &tentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) + goto perm; + + code = GetList (tt, &tentry, alist, 0); + *over = 0; + if (code == PRTOOMANY) *over = 1; + else if (code != PRSUCCESS) goto abort; + + code = ubik_EndTrans(tt); + +done: + if (!alist->prlist_val) + alist->prlist_val = (long *) malloc(0); /* make calling stub happy */ + return code; +} + +/* List the entries owned by this id. If the id is zero return the orphans + * list. */ + +PR_ListOwned (call, aid, alist, over) + struct rx_call *call; + long aid; + prlist *alist; + long *over; +{ + register long code; + struct ubik_trans *tt; + long cid; + struct prentry tentry; + long head; + + alist->prlist_len = 0; + alist->prlist_val = (long *) 0; + + code = Initdb(); + if (code != PRSUCCESS) goto done; + code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt); + if (code) goto done; + code = ubik_SetLock(tt,1,1,LOCKREAD); + if (code) { + abort: + ubik_AbortTrans(tt); + goto done; + } + code = WhoIsThis(call,tt,&cid); + if (code) { + perm: + code = PRPERM; + ubik_AbortTrans(tt); + goto done; + } + + if (aid) { + long loc = FindByID (tt, aid); + if (loc == 0) { code = PRNOENT; goto abort; } + code = pr_ReadEntry (tt, 0, loc, &tentry); + if (code) goto abort; +; + if (!AccessOK (tt, cid, &tentry, -1, PRP_OWNED_ANY)) goto perm; + head = tentry.owned; + } else { + if (!AccessOK (tt, cid, 0, 0, 0)) goto perm; + head = ntohl(cheader.orphan); + } + + code = GetOwnedChain (tt, head, alist); + *over = 0; + if (code == PRTOOMANY) *over = 1; + else if (code) goto abort; + + code = ubik_EndTrans(tt); + +done: + if (!alist->prlist_val) + alist->prlist_val = (long *) malloc(0); /* make calling stub happy */ + return code; +} + +PR_IsAMemberOf(call,uid,gid,flag) +struct rx_call *call; +long uid; +long gid; +long *flag; +{ + register long code; + struct ubik_trans *tt; + + code = Initdb(); + if (code != PRSUCCESS) return code; + code = ubik_BeginTrans(dbase,UBIK_READTRANS,&tt); + if (code) return code; + code = ubik_SetLock(tt,1,1,LOCKREAD); + if (code) { + abort: + ubik_AbortTrans(tt); + return code; + } + { long cid; + long uloc = FindByID (tt, uid); + long gloc = FindByID (tt, gid); + struct prentry uentry, gentry; + + if (!uloc || !gloc) { + code = PRNOENT; + goto abort; + } + code = WhoIsThis(call, tt, &cid); + if (code) { + perm: + code = PRPERM; + goto abort; + } + code = pr_ReadEntry (tt, 0, uloc, &uentry); + if (code) goto abort; + code = pr_ReadEntry (tt, 0, gloc, &gentry); + if (code) goto abort; + if ((uentry.flags & PRGRP) || !(gentry.flags & PRGRP)) { + code = PRBADARG; + goto abort; + } + if (!AccessOK (tt, cid, &uentry, 0, PRP_MEMBER_ANY) && + !AccessOK (tt, cid, &gentry, PRP_MEMBER_MEM, PRP_MEMBER_ANY)) goto perm; + } + + *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++; + } +} diff --git a/afssync/ptutils.c b/afssync/ptutils.c index a8e2b341..ef6e3d6b 100644 --- a/afssync/ptutils.c +++ b/afssync/ptutils.c @@ -1,13 +1,14 @@ -/* $Header$ */ -/* $Source$ */ - - +/* Copyright (C) 1989 Transarc Corporation - All rights reserved */ /* * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988 * LICENSED MATERIALS - PROPERTY OF IBM * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083 */ +#ifndef lint +static char rcsid[] = "$Header$"; +#endif + /* Sherri Nichols Information Technology Center @@ -18,29 +19,160 @@ */ +#include +#include #include -#include #include -#define UBIK_INTERNALS +#include #include #include -#include "print.h" -#include "prserver.h" -#include "prerror.h" -#include +#include +#include "ptserver.h" +#include "pterror.h" +#include -extern struct prheader cheader; extern struct ubik_dbase *dbase; extern struct afsconf_dir *prdir; +extern int pr_noAuth; -long CreateEntry(at, aname, aid, idflag,flag,oid,creator) -register struct ubik_trans *at; -char aname[PR_MAXNAMELEN]; -long *aid; -long idflag; -long flag; -long oid; -long creator; +static char *whoami = "ptserver"; + +/* CorrectUserName - Check to make sure a user name is OK. It must not include + * either a colon (or it would look like a group) or an atsign (or it would + * look like a foreign user). The length is checked as well to make sure + * that the user name, an atsign, and the local cell name will fit in + * PR_MAXNAMELEN. This is so this user can fit in another cells database as + * a foreign user with our cell name tacked on. This is a predicate, so it + * return one if name is OK and zero if name is bogus. */ + +static int CorrectUserName (name) + char *name; +{ + extern int pr_realmNameLen; + + if (index (name, ':') || index(name, '@') || index(name, '\n')) return 0; + if (strlen (name) >= PR_MAXNAMELEN - pr_realmNameLen - 1) return 0; + return 1; +} + +static long CorrectGroupName (ut, aname, cid, oid, cname) + struct ubik_trans *ut; + char aname[PR_MAXNAMELEN]; /* name for group */ + long cid; /* caller id */ + long oid; /* owner of group */ + char cname[PR_MAXNAMELEN]; /* correct name for group */ +{ + long code; + int admin; + char *prefix; /* ptr to group owner part */ + char *suffix; /* ptr to group name part */ + char name[PR_MAXNAMELEN]; /* correct name for group */ + struct prentry tentry; + + if (strlen (aname) >= PR_MAXNAMELEN) return PRBADNAM; + admin = pr_noAuth || IsAMemberOf (ut, cid, SYSADMINID); + + if (oid == 0) oid = cid; + + /* Determine the correct prefix for the name. */ + if (oid == SYSADMINID) prefix = "system"; + else { + long loc = FindByID (ut, oid); + if (loc == 0) { + /* let admin create groups owned by non-existent ids (probably + * setting a group to own itself). Check that they look like + * groups (with a colon) or otherwise are good user names. */ + if (admin) { + strcpy (cname, aname); + goto done; + } + return PRNOENT; + } + code = pr_Read (ut, 0, loc, &tentry, sizeof(tentry)); + if (code) return code; + if (ntohl(tentry.flags) & PRGRP) { + if ((tentry.count == 0) && !admin) return PRGROUPEMPTY; + /* terminate prefix at colon if there is one */ + if (prefix = index(tentry.name, ':')) *prefix = 0; + } + prefix = tentry.name; + } + /* only sysadmin allow to use 'system:' prefix */ + if ((strcmp (prefix, "system") == 0) && !admin) return PRPERM; + + strcpy (name, aname); /* in case aname & cname are same */ + suffix = index(name, ':'); + if (suffix == 0) { + /* sysadmin can make groups w/o ':', but they must still look like + * legal user names. */ + if (!admin) return PRBADNAM; + strcpy (cname, name); + } + else { + if (strlen(prefix)+strlen(suffix) >= PR_MAXNAMELEN) return PRBADNAM; + strcpy (cname, prefix); + strcat (cname, suffix); + } + done: + /* check for legal name with either group rules or user rules */ + if (suffix = index(cname, ':')) { + /* check for confusing characters */ + if (index(cname, '@') || /* avoid confusion w/ foreign users */ + index(cname, '\n') || /* restrict so recreate can work */ + index(suffix+1, ':')) /* avoid multiple colons */ + return PRBADNAM; + } else { + if (!CorrectUserName (cname)) return PRBADNAM; + } + return 0; +} + +int AccessOK (ut, cid, tentry, mem, any) + struct ubik_trans *ut; + long cid; /* caller id */ + struct prentry *tentry; /* object being accessed */ + int mem; /* check membership in aid, if group */ + int any; /* if set return true */ +{ long flags; + long oid; + long aid; + + if (pr_noAuth) return 1; + if (tentry) { + flags = tentry->flags; + oid = tentry->owner; + aid = tentry->id; + } else { + flags = oid = aid = 0; + } + if (!(flags & PRACCESS)) /* provide default access */ + if (flags & PRGRP) + flags |= PRP_GROUP_DEFAULT; + else + flags |= PRP_USER_DEFAULT; + + if (flags & any) return 1; + if (oid) { + if ((cid == oid) || + IsAMemberOf (ut, cid, oid)) return 1; + } + if (aid > 0) { /* checking on a user */ + if (aid == cid) return 1; + } else if (aid < 0) { /* checking on group */ + if ((flags & mem) && IsAMemberOf (ut, cid, aid)) return 1; + } + if (IsAMemberOf (ut, cid, SYSADMINID)) return 1; + return 0; /* no access */ +} + +long CreateEntry (at, aname, aid, idflag, flag, oid, creator) + register struct ubik_trans *at; + char aname[PR_MAXNAMELEN]; + long *aid; + long idflag; + long flag; + long oid; + long creator; { /* get and init a new entry */ register long code; @@ -49,8 +181,25 @@ long creator; struct prentry tentry; bzero(&tentry, sizeof(tentry)); + + if ((oid == 0) || (oid == ANONYMOUSID)) oid = creator; + + if (flag & PRGRP) { + code = CorrectGroupName (at, aname, creator, oid, tentry.name); + if (code) return code; + if (strcmp (aname, tentry.name) != 0) return PRBADNAM; + } else { /* non-group must not have colon */ + if (!CorrectUserName(aname)) return PRBADNAM; + strcpy (tentry.name, aname); + } + + if (FindByName(at,aname)) return PREXIST; + newEntry = AllocBlock(at); if (!newEntry) return PRDBFAIL; +#ifdef PR_REMEMBER_TIMES + tentry.createTime = time(0); +#endif if (flag & PRGRP) { tentry.flags |= PRGRP; tentry.owner = oid; @@ -67,29 +216,64 @@ long creator; if (code != PRSUCCESS) return code; } if (flag & PRGRP) { - if (tentry.id < ntohl(cheader.maxGroup)) { - cheader.maxGroup = htonl(tentry.id); - code = pr_Write(at,0,16,(char *) &cheader.maxGroup,sizeof(cheader.maxGroup)); + /* group ids are negative */ + if (tentry.id < (long)ntohl(cheader.maxGroup)) { + code = set_header_word (at, maxGroup, htonl(tentry.id)); if (code) return PRDBFAIL; } } else if (flag & PRFOREIGN) { - if (tentry.id > ntohl(cheader.maxForeign)) { - cheader.maxForeign = htonl(tentry.id); - code = pr_Write(at,0,24,(char *) &cheader.maxForeign,sizeof(cheader.maxForeign)); + if (tentry.id > (long)ntohl(cheader.maxForeign)) { + code = set_header_word (at, maxForeign, htonl(tentry.id)); if (code) return PRDBFAIL; } } else { - if (tentry.id > ntohl(cheader.maxID)) { - cheader.maxID = htonl(tentry.id); - code = pr_Write(at,0,20,(char *) &cheader.maxID,sizeof(cheader.maxID)); + if (tentry.id > (long)ntohl(cheader.maxID)) { + code = set_header_word (at, maxID, htonl(tentry.id)); if (code) return PRDBFAIL; } } + /* PRACCESS is off until set, defaults provided in AccessOK */ + if (flag == 0) { /* only normal users get quota */ + tentry.flags |= PRQUOTA; + tentry.ngroups = tentry.nusers = 20; + } + + if (flag & (PRGRP | PRFOREIGN)) { + long loc = FindByID (at, creator); + struct prentry centry; + long *nP; /* ptr to entry to be decremented */ + long n; /* quota to check */ + + if (loc) { /* this should only fail during initialization */ + code = pr_Read (at, 0, loc, ¢ry, sizeof(centry)); + if (code) return code; + + if (flag & PRGRP) nP = ¢ry.ngroups; + else if (flag & PRFOREIGN) nP = ¢ry.nusers; + else nP = 0; + + if (nP) { + if (!(ntohl(centry.flags) & PRQUOTA)) { + /* quota uninitialized, so do it now */ + centry.flags = htonl (ntohl(centry.flags) | PRQUOTA); + centry.ngroups = centry.nusers = htonl(20); + } + n = ntohl(*nP); + if (n <= 0) { + if (!pr_noAuth && + !IsAMemberOf (at, creator, SYSADMINID)) + return PRNOMORE; + } + else *nP = htonl(n-1); + } + code = pr_Write (at, 0, loc, ¢ry, sizeof(centry)); + if (code) return code; + } /* if (loc) */ + } /* need to check creation quota */ tentry.creator = creator; *aid = tentry.id; - strncpy(tentry.name, aname, PR_MAXNAMELEN); code = pr_WriteEntry(at, 0, newEntry, &tentry); if (code) return PRDBFAIL; code = AddToIDHash(at,*aid,newEntry); @@ -101,55 +285,47 @@ long creator; if (code) return code; } if (tentry.flags & PRGRP) { - temp = ntohl(cheader.groupcount) + 1; - cheader.groupcount = htonl(temp); - code = pr_Write(at,0,40,(char *)&cheader.groupcount,sizeof(cheader.groupcount)); - if (code) return PRDBFAIL; + if (inc_header_word (at, groupcount, 1)) return PRDBFAIL; } else if (tentry.flags & PRFOREIGN) { - temp = ntohl(cheader.foreigncount) + 1; - cheader.foreigncount = htonl(temp); - code = pr_Write(at,0,44,(char *)&cheader.foreigncount,sizeof(cheader.foreigncount)); - if (code) return PRDBFAIL; + if (inc_header_word (at, foreigncount, 1)) return PRDBFAIL; } else if (tentry.flags & PRINST) { - temp = ntohl(cheader.instcount) + 1; - cheader.instcount = htonl(temp); - code = pr_Write(at,0,48,(char *)&cheader.instcount,sizeof(cheader.instcount)); - if (code) return PRDBFAIL; + if (inc_header_word (at, instcount, 1)) return PRDBFAIL; } else { - temp = ntohl(cheader.usercount) + 1; - cheader.usercount = htonl(temp); - code = pr_Write(at,0,36,(char *)&cheader.usercount,sizeof(cheader.usercount)); - if (code) return PRDBFAIL; + if (inc_header_word (at, usercount, 1)) return PRDBFAIL; } return PRSUCCESS; } +/* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation + * entry if appropriate */ -long RemoveFromEntry(at,aid,bid) -register struct ubik_trans *at; -register long aid; -register long bid; +long RemoveFromEntry (at, aid, bid) + register struct ubik_trans *at; + register long aid; + register long bid; { - /* remove aid from bid's entries list, freeing a continuation entry if appropriate */ - register long code; struct prentry tentry; struct contentry centry; struct contentry hentry; long temp; - long first; long i,j; long nptr; - long hloc = 0; + long hloc; + if (aid == bid) return PRINCONSISTENT; bzero(&hentry,sizeof(hentry)); temp = FindByID(at,bid); + if (temp == 0) return PRNOENT; code = pr_ReadEntry(at, 0, temp, &tentry); if (code != 0) return code; +#ifdef PR_REMEMBER_TIMES + tentry.removeTime = time(0); +#endif for (i=0;ientries[i] == PRBADID) continue; + if (tentry->entries[i] == 0) break; + code = RemoveFromEntry (at, tentry->id, tentry->entries[i]); + if (code) return code; } - nptr = tentry.next; + nptr = tentry->next; while (nptr != NULL) { code = pr_ReadCoEntry(at,0,nptr,¢ry); if (code != 0) return PRDBFAIL; for (i=0;iid, centry.entries[i]); + if (code) return code; } + code = FreeBlock (at, nptr); /* free continuation block */ + if (code) return code; nptr = centry.next; } - if (tentry.flags & PRGRP) { - if (FindByID(at,tentry.owner)) { - code = RemoveFromOwnerChain(at,aid,tentry.owner); + + /* Remove us from other's owned chain. Note that this will zero our owned + * field (on disk) so this step must follow the above step in case we are + * on our own owned list. */ + if (tentry->flags & PRGRP) { + if (tentry->owner) { + code = RemoveFromOwnerChain (at, tentry->id, tentry->owner); if (code) return code; } else { - code = RemoveFromOrphan(at,aid); + code = RemoveFromOrphan (at, tentry->id); if (code) return code; } } - if (tentry.owned) { - nptr = tentry.owned; - while (nptr != NULL) { - code = pr_ReadEntry(at,0,nptr,&nentry); - if (code != 0) return PRDBFAIL; - if (nentry.id != aid) /* don't add this entry to orphan chain! */ - code = AddToOrphan(at,nentry.id); - nptr = nentry.nextOwned; - } - } - code = RemoveFromIDHash(at,tentry.id,&temp); + + code = RemoveFromIDHash(at,tentry->id,&loc); if (code != PRSUCCESS) return code; - code = RemoveFromNameHash(at,tentry.name,&temp); + code = RemoveFromNameHash(at,tentry->name,&loc); if (code != PRSUCCESS) return code; - if (tentry.flags & PRGRP) { - temp1 = ntohl(cheader.groupcount) + 1; - cheader.groupcount = htonl(temp1); - code = pr_Write(at,0,40,(char *)&cheader.groupcount,sizeof(cheader.groupcount)); - if (code) return PRDBFAIL; + + if (tentry->flags & (PRGRP | PRFOREIGN)) { + long loc = FindByID (at, tentry->creator); + struct prentry centry; + if (loc) { + code = pr_Read (at, 0, loc, ¢ry, sizeof(centry)); + if (code) return code; + if (ntohl(centry.flags) & PRQUOTA) { + if (tentry->flags & PRGRP) { + centry.ngroups = htonl(ntohl(centry.ngroups) + 1); + } else if (tentry->flags & PRFOREIGN) { + centry.nusers = htonl(ntohl(centry.nusers) + 1); + } + } + code = pr_Write (at, 0, loc, ¢ry, sizeof(centry)); + if (code) return code; + } } - else if (tentry.flags & PRFOREIGN) { - temp1 = ntohl(cheader.foreigncount) + 1; - cheader.foreigncount = htonl(temp1); - code = pr_Write(at,0,44,(char *)&cheader.foreigncount,sizeof(cheader.foreigncount)); - if (code) return PRDBFAIL; + + if (tentry->flags & PRGRP) { + if (inc_header_word (at, groupcount, -1)) return PRDBFAIL; } - else if (tentry.flags & PRINST) { - temp1 = ntohl(cheader.instcount) + 1; - cheader.instcount = htonl(temp1); - code = pr_Write(at,0,48,(char *)&cheader.instcount,sizeof(cheader.instcount)); - if (code) return PRDBFAIL; + else if (tentry->flags & PRFOREIGN) { + if (inc_header_word (at, foreigncount, -1)) return PRDBFAIL; + } + else if (tentry->flags & PRINST) { + if (inc_header_word (at, instcount, -1)) return PRDBFAIL; } else { - temp1 = ntohl(cheader.usercount) + 1; - cheader.usercount = htonl(temp1); - code = pr_Write(at,0,36,(char *)&cheader.usercount,sizeof(cheader.usercount)); - if (code) return PRDBFAIL; + if (inc_header_word (at, usercount, -1)) return PRDBFAIL; } - FreeBlock(at,temp); - return PRSUCCESS; + code = FreeBlock(at, loc); + return code; } +/* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block + * if needed. + * + * Note the entry is written out by this routine. */ - - -long AddToEntry(tt,entry,loc,aid) -struct ubik_trans *tt; -struct prentry entry; -long loc; -long aid; +long AddToEntry (tt, entry, loc, aid) + struct ubik_trans *tt; + struct prentry *entry; + long loc; + long aid; { - /* add aid to entry's entries list, alloc'ing a continuation block if needed */ register long code; long i; struct contentry nentry; struct contentry aentry; long nptr; - long last = 0; + long last; /* addr of last cont. block */ long first = 0; long cloc; long slot = -1; - bzero(&nentry,sizeof(nentry)); - bzero(&aentry,sizeof(aentry)); + if (entry->id == aid) return PRINCONSISTENT; +#ifdef PR_REMEMBER_TIMES + entry->addTime = time(0); +#endif for (i=0;ientries[i] == aid) return PRIDEXIST; - if (entry.entries[i] == PRBADID) { /* remember this spot */ + if (entry->entries[i] == PRBADID) { /* remember this spot */ first = 1; slot = i; } - if (entry.entries[i] == 0) { /* end of the line */ + else if (entry->entries[i] == 0) { /* end of the line */ if (slot == -1) { first = 1; slot = i; @@ -332,10 +509,12 @@ long aid; break; } } - nptr = entry.next; + last = 0; + nptr = entry->next; while (nptr != NULL) { - code = pr_ReadCoEntry(tt,0,nptr,&nentry); + code = pr_ReadCoEntry(tt,0,nptr,&nentry); if (code != 0) return code; + last = nptr; if (!(nentry.flags & PRCONT)) return PRDBFAIL; for (i=0;icount++; if (first) { /* place is in first block */ - entry.entries[slot] = aid; - code = pr_WriteEntry(tt,0,loc,&entry); + entry->entries[slot] = aid; + code = pr_WriteEntry (tt, 0, loc, entry); if (code != 0) return code; return PRSUCCESS; } - code = pr_WriteEntry(tt,0,loc,&entry); + code = pr_WriteEntry (tt, 0, loc, entry); + if (code) return code; code = pr_ReadCoEntry(tt,0,cloc,&aentry); if (code != 0) return code; aentry.entries[slot] = aid; @@ -375,62 +554,73 @@ long aid; } /* have to allocate a continuation block if we got here */ nptr = AllocBlock(tt); - if (nentry.flags & PRCONT) { - /* then we should tack new block here */ + if (last) { + /* then we should tack new block after last block in cont. chain */ nentry.next = nptr; code = pr_WriteCoEntry(tt,0,last,&nentry); if (code != 0) return code; } else { - entry.next = nptr; - code = pr_WriteEntry(tt,0,loc,&entry); - if (code != 0) return code; + entry->next = nptr; } + bzero(&aentry,sizeof(aentry)); aentry.flags |= PRCONT; - aentry.id = entry.id; + aentry.id = entry->id; aentry.next = NULL; aentry.entries[0] = aid; code = pr_WriteCoEntry(tt,0,nptr,&aentry); if (code != 0) return code; /* don't forget to update count, here! */ - entry.count++; - code = pr_WriteEntry(tt,0,loc,&entry); - return PRSUCCESS; + entry->count++; + code = pr_WriteEntry (tt, 0, loc, entry); + return code; } -long GetList(at,aid,alist,add) -struct ubik_trans *at; -long aid; -prlist *alist; -long add; +long AddToPRList (alist, sizeP, id) + prlist *alist; + int *sizeP; + long id; +{ + if (alist->prlist_len >= PR_MAXGROUPS) return PRTOOMANY; + if (alist->prlist_len >= *sizeP) { + *sizeP = *sizeP + 100; + if (*sizeP > PR_MAXGROUPS) *sizeP = PR_MAXGROUPS; + alist->prlist_val = + (long *) ((alist->prlist_val) ? + realloc (alist->prlist_val, (*sizeP)*sizeof(long)) : + malloc ((*sizeP)*sizeof(long))); + } + alist->prlist_val[alist->prlist_len++] = id; + return 0; +} + +long GetList (at, tentry, alist, add) + struct ubik_trans *at; + struct prentry *tentry; + prlist *alist; + long add; { register long code; - long temp; long i; - long count; - struct prentry tentry; struct contentry centry; long nptr; - long size; + int size; + int count = 0; extern long IDCmp(); - temp = FindByID(at,aid); - if (!temp) return PRNOENT; - code = pr_ReadEntry(at,0,temp,&tentry); - if (code != 0) return code; - alist->prlist_val = (long *)malloc(100*sizeof(long)); - size = 100; + size = 0; + alist->prlist_val = 0; alist->prlist_len = 0; - count = 0; + for (i=0;iprlist_val[count]= tentry.entries[i]; - count++; - alist->prlist_len++; + if (tentry->entries[i] == PRBADID) continue; + if (tentry->entries[i] == 0) break; + code = AddToPRList (alist, &size, tentry->entries[i]); + if (code) return code; } - nptr = tentry.next; + + nptr = tentry->next; while (nptr != NULL) { /* look through cont entries */ code = pr_ReadCoEntry(at,0,nptr,¢ry); @@ -438,38 +628,51 @@ long add; for (i=0;iprlist_len >= size) { - alist->prlist_val = (long *)realloc(alist->prlist_val,(size+100)*sizeof(long)); - size += 100; - } - alist->prlist_val[count] = centry.entries[i]; - count++; - alist->prlist_len++; + code = AddToPRList (alist, &size, centry.entries[i]); + if (code) return code; } nptr = centry.next; + if (count++ > 50) IOMGR_Poll(), count = 0; } + if (add) { /* this is for a CPS, so tack on appropriate stuff */ - if (aid != ANONYMOUSID && aid != ANYUSERID) { - if (alist->prlist_len >= size) - alist->prlist_val = (long *)realloc(alist->prlist_val,(size + 3)*sizeof(long)); - alist->prlist_val[count] = ANYUSERID; - count++; - alist->prlist_val[count] = AUTHUSERID; - count++; - alist->prlist_val[count] = aid; - count++; - alist->prlist_len += 3; + if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) { + if ((code = AddToPRList (alist, &size, ANYUSERID)) || + (code = AddToPRList (alist, &size, AUTHUSERID)) || + (code = AddToPRList (alist, &size, tentry->id))) return code; } else { - if (alist->prlist_len >= size) - alist->prlist_val = (long *)realloc(alist->prlist_val,(size + 2)*sizeof(long)); - alist->prlist_val[count] = ANYUSERID; - count++; - alist->prlist_val[count] = aid; - count++; - alist->prlist_len += 2; + if ((code = AddToPRList (alist, &size, ANYUSERID)) || + (code = AddToPRList (alist, &size, tentry->id))) return code; } } + if (alist->prlist_len > 100) IOMGR_Poll(); + qsort(alist->prlist_val,alist->prlist_len,sizeof(long),IDCmp); + return PRSUCCESS; +} + +long GetOwnedChain (ut, next, alist) + struct ubik_trans *ut; + long next; + prlist *alist; +{ register long code; + struct prentry tentry; + int size; + int count = 0; + + size = 0; + alist->prlist_val = 0; + alist->prlist_len = 0; + + while (next) { + code = pr_Read (ut, 0, next, &tentry, sizeof(tentry)); + if (code) return code; + code = AddToPRList (alist, &size, ntohl(tentry.id)); + if (code) return code; + next = ntohl(tentry.nextOwned); + if (count++ > 50) IOMGR_Poll(), count = 0; + } + if (alist->prlist_len > 100) IOMGR_Poll(); qsort(alist->prlist_val,alist->prlist_len,sizeof(long),IDCmp); return PRSUCCESS; } @@ -503,20 +706,23 @@ long flag; return PRSUCCESS; } -Initdb() +int pr_noAuth; + +long Initdb() { long code; struct ubik_trans *tt; long len; - long temp; - long flag = 0; static long initd=0; +#if 0 static struct ubik_version curver; struct ubik_version newver; - struct ubik_hdr header; +#endif /* init the database. We'll try reading it, but if we're starting from scratch, we'll have to do a write transaction. */ + pr_noAuth = afsconf_GetNoAuthFlag(prdir); + code = ubik_BeginTrans(dbase,UBIK_READTRANS, &tt); if (code) return code; code = ubik_SetLock(tt,1,1,LOCKREAD); @@ -526,16 +732,35 @@ Initdb() } if (!initd) { initd = 1; +#if 0 bzero(&curver,sizeof(curver)); +#endif + } else if (!ubik_CacheUpdate (tt)) { + code = ubik_EndTrans(tt); + return code; + } +#if 0 + code = ubik_GetVersion(tt,&newver); + if (vcmp(curver,newver) == 0) { + /* same version */ + code = ubik_EndTrans(tt); + if (code) return code; + return PRSUCCESS; } + bcopy(&newver,&curver,sizeof(struct ubik_version)); +#endif + len = sizeof(cheader); code = pr_Read(tt, 0, 0, (char *) &cheader, len); if (code != 0) { - printf("prserver: couldn't read header -code is %d\n",code); + com_err (whoami, code, "couldn't read header"); ubik_AbortTrans(tt); return code; } - if (ntohl(cheader.headerSize) == sizeof(cheader) && ntohl(cheader.eofPtr) != NULL && FindByID(tt,ANONYMOUSID) != 0){ + if ((ntohl(cheader.version) == PRDBVERSION) && + ntohl(cheader.headerSize) == sizeof(cheader) && + ntohl(cheader.eofPtr) != NULL && + FindByID(tt,ANONYMOUSID) != 0){ /* database exists, so we don't have to build it */ code = ubik_EndTrans(tt); if (code) return code; @@ -544,7 +769,26 @@ Initdb() /* else we need to build a database */ code = ubik_EndTrans(tt); if (code) return code; - fprintf(stderr, "Creating new database\n"); + + /* Only rebuild database if the db was deleted (the header is zero) and we + are running noAuth. */ + { char *bp = (char *)&cheader; + int i; + for (i=0; i 0 || (aid > 0 && newid < 0)) return PRPERM; @@ -701,71 +881,69 @@ long newid; if (code != PRSUCCESS) return code; tentry.id = newid; code = pr_WriteEntry(at,0,loc,&tentry); + if (code) return code; code = AddToIDHash(at,tentry.id,loc); if (code) return code; + /* get current data */ + code = pr_ReadEntry(at,0,loc,&tentry); + if (code) return PRDBFAIL; } + + /* Change the owner */ if (tentry.owner != oid && oid) { + /* only groups can have their owner's changed */ + if (!(tentry.flags & PRGRP)) return PRPERM; + oldowner = tentry.owner; + tentry.owner = oid; + /* The entry must be written through first so Remove and Add routines + * can operate on disk data */ + code = pr_WriteEntry(at,0,loc,(char *)&tentry); + if (code) return PRDBFAIL; if (tentry.flags & PRGRP) { - /* switch owner chains before we lose old owner */ - if (FindByID(at,tentry.owner)) /* if it has an owner */ - code = RemoveFromOwnerChain(at,tentry.id,tentry.owner); - else /* must be an orphan */ + /* switch owner chains */ + if (oldowner) /* if it has an owner */ + code = RemoveFromOwnerChain(at,tentry.id,oldowner); + else /* must be an orphan */ code = RemoveFromOrphan(at,tentry.id); if (code) return code; - code = AddToOwnerChain(at,tentry.id,oid); + code = AddToOwnerChain(at,tentry.id,tentry.owner); if (code) return code; } - tentry.owner = oid; - if ((tentry.flags & PRGRP) && (strlen(name) == 0)) { - /* if we change the owner of a group, it's name will change as well */ - if (tentry.owner < 0) { - code = IDToName(at,tentry.owner,temp); - if (code) return code; - check = index(temp,':'); - strncpy(holder,temp,check - temp); - } - else { - code = IDToName(at,tentry.owner,holder); - if (code) return code; - } - strncat(holder,":",PR_MAXNAMELEN); - /* now the rest of the name */ - check = index(tentry.name,':'); - strncat(holder,++check,PR_MAXNAMELEN); - if (strcmp(holder,tentry.name)) { - /* then the name really did change */ - pos = FindByName(at,holder); - if (pos) return PREXIST; - code = RemoveFromNameHash(at,tentry.name,&loc); - if (code != PRSUCCESS) return code; - strncpy(tentry.name,holder,PR_MAXNAMELEN); - code = AddToNameHash(at,tentry.name,loc); - if (code != PRSUCCESS) return code; - } - } - code = pr_WriteEntry(at,0,loc,&tentry); + /* fix up the name */ + if ((tentry.flags & PRGRP) && (strlen(name) == 0)) name = tentry.name; + /* get current data */ + code = pr_ReadEntry(at,0,loc,&tentry); if (code) return PRDBFAIL; } - if ((strcmp(tentry.name,name)) && (strlen(name)!= 0)) { + + /* Change the name, if name is a ptr to tentry.name then this name change + * is due to a chown, otherwise caller has specified a new name */ + if ((name == tentry.name) || + (*name && (strcmp (tentry.name, name) != 0))) { + strncpy (oldname, tentry.name, PR_MAXNAMELEN); if (tentry.flags & PRGRP) { - if ((check = index(name,':')) == NULL) return PRBADNAM; - strncpy(temp,name,check-name); - code = NameToID(at,temp,&tid); - if (tid != tentry.owner) return PRPERM; + code = CorrectGroupName (at, name, cid, tentry.owner, tentry.name); + if (code) return code; + + if (name == tentry.name) { /* owner fixup */ + if (strcmp (oldname, tentry.name) == 0) goto nameOK; + } else { /* new name, caller must be correct */ + if (strcmp (name, tentry.name) != 0) return PRBADNAM; + } } else - /* if it's not a group, shouldn't have a : in it */ - if ((check = index(name,':')) != NULL) - return PRBADNAM; + if (!CorrectUserName(name)) return PRBADNAM; + pos = FindByName(at,name); if (pos) return PREXIST; - code = RemoveFromNameHash(at,tentry.name,&loc); + code = RemoveFromNameHash (at, oldname, &loc); if (code != PRSUCCESS) return code; - strncpy(tentry.name,name,PR_MAXNAMELEN); - code = pr_WriteEntry(at,0,loc,&tentry); + strncpy (tentry.name, name, PR_MAXNAMELEN); + code = pr_WriteEntry(at,0,loc,(char *)&tentry); if (code) return PRDBFAIL; code = AddToNameHash(at,tentry.name,loc); if (code != PRSUCCESS) return code; +nameOK:; } return PRSUCCESS; } diff --git a/afssync/resync.qc b/afssync/resync.qc index c0ebfb6f..701d9b7b 100644 --- a/afssync/resync.qc +++ b/afssync/resync.qc @@ -6,9 +6,9 @@ #include #include #include -#include "print.h" -#include "prserver.h" -#include "prerror.h" +#include +#include +#include #include #include #include diff --git a/afssync/sync.qc b/afssync/sync.qc index 18a2d794..ed6606d2 100644 --- a/afssync/sync.qc +++ b/afssync/sync.qc @@ -10,9 +10,9 @@ #include #include #include -#include "print.h" -#include "prserver.h" -#include "prerror.h" +#include +#include +#include #include #include #include diff --git a/afssync/ubik.c b/afssync/ubik.c index 07fa2d3f..149a9bbe 100644 --- a/afssync/ubik.c +++ b/afssync/ubik.c @@ -11,7 +11,37 @@ struct ubik_dbase *dbase; -long ubik_BeginTrans() +int ubik_ServerInit() +{ + return(0); +} + +int ubik_BeginTrans() +{ + return(0); +} + +int ubik_BeginTransReadAny() +{ + return(0); +} + +int ubik_AbortTrans() +{ + return(0); +} + +int ubik_EndTrans() +{ + return(0); +} + +int ubik_Tell() +{ + return(0); +} + +int ubik_Truncate() { return(0); } @@ -21,28 +51,37 @@ long ubik_SetLock() return(0); } -long ubik_AbortTrans() +int ubik_WaitVersion() { return(0); } -long ubik_GetVersion(dummy, ver) -int dummy; -struct ubik_version *ver; +int ubik_CacheUpdate() { - bzero(ver, sizeof(struct ubik_version)); return(0); } -long ubik_EndTrans() +int panic(a, b, c, d) +char *a, *b, *c, *d; { + printf(a, b, c, d); + abort(); + printf("BACK FROM ABORT\n"); /* shouldn't come back from floating pt exception */ + exit(1); /* never know, though */ +} + +int ubik_GetVersion(dummy, ver) +int dummy; +struct ubik_version *ver; +{ + bzero(ver, sizeof(struct ubik_version)); return(0); } extern int dbase_fd; -long ubik_Seek(tt, afd, pos) +int ubik_Seek(tt, afd, pos) struct ubik_trans *tt; long afd; long pos; @@ -54,7 +93,7 @@ long pos; return(0); } -long ubik_Write(tt, buf, len) +int ubik_Write(tt, buf, len) struct ubik_trans *tt; char *buf; long len; @@ -69,7 +108,7 @@ long len; return(0); } -long ubik_Read(tt, buf, len) +int ubik_Read(tt, buf, len) struct ubik_trans *tt; char *buf; long len; @@ -87,7 +126,18 @@ long len; } -char *prdir = "/dev/null"; +/* Global declarations from ubik.c */ +long ubik_quorum=0; +struct ubik_dbase *ubik_dbase=0; +struct ubik_stats ubik_stats; +long ubik_host; +long ubik_epochTime = 0; +long urecovery_state = 0; + +struct rx_securityClass *ubik_sc[3]; + + +/* Other declarations */ afsconf_GetNoAuthFlag() { @@ -95,4 +145,7 @@ afsconf_GetNoAuthFlag() } +char *prdir = "/dev/null"; struct prheader cheader; +int pr_realmNameLen; +char *pr_realmName; diff --git a/afssync/utils.c b/afssync/utils.c index c4d21a66..4736ce34 100644 --- a/afssync/utils.c +++ b/afssync/utils.c @@ -1,41 +1,33 @@ -/* $Header$ */ -/* $Source$ */ - - +/* Copyright (C) 1989 Transarc Corporation - All rights reserved */ /* * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988 * LICENSED MATERIALS - PROPERTY OF IBM * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083 */ +#ifndef lint +static char rcsid[] = "$Header$"; +#endif + /* Sherri Nichols Information Technology Center November, 1988 + Modified May, 1989 by Jeff Schiller to keep disk file in network byte order */ - #include #include #include #include #include #include -#include -#include -#include -#include "print.h" -#include "prserver.h" -#include "prerror.h" - -#define USERSMS 14487 - -extern struct prheader cheader; -extern struct ubik_dbase *dbase; +#include "ptserver.h" +#include "pterror.h" long IDHash(x) long x; @@ -66,6 +58,10 @@ long len; { /* package up seek and write into one procedure for ease of use */ long code; + if ((pos < sizeof(cheader)) && (buff != (char *)&cheader + pos)) { + fprintf (stderr, "ptserver: dbwrite: Illegal attempt to write a location 0\n"); + return PRDBFAIL; + } code = ubik_Seek(tt,afd,pos); if (code) return code; code = ubik_Write(tt,buff,len); @@ -96,7 +92,9 @@ struct prentry *tentry; long code; register long i; struct prentry nentry; + if (ntohl(1) != 1) { /* Need to swap bytes. */ + bzero (&nentry, sizeof(nentry)); /* make sure reseved fields are zero */ nentry.flags = htonl(tentry->flags); nentry.id = htonl(tentry->id); nentry.cellid = htonl(tentry->cellid); @@ -115,20 +113,20 @@ struct prentry *tentry; nentry.sibling = htonl(tentry->sibling); nentry.child = htonl(tentry->child); strncpy(nentry.name, tentry->name, PR_MAXNAMELEN); +#ifdef PR_REMEMBER_TIMES + nentry.createTime = htonl(tentry->createTime); + nentry.addTime = htonl(tentry->addTime); + nentry.removeTime = htonl(tentry->removeTime); + nentry.changeTime = htonl(tentry->changeTime); +#endif for (i = 0; i < PRSIZE; i++) nentry.entries[i] = htonl(tentry->entries[i]); - code = ubik_Seek(tt, afd, pos); - if (code) return (code); - code = ubik_Write(tt, (char *) &nentry, sizeof(struct prentry)); - return(code); - } else { - code = ubik_Seek(tt, afd, pos); - if (code) return (code); - code = ubik_Write(tt, (char *) tentry, sizeof(struct prentry)); - return(code); + tentry = &nentry; } + code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct prentry)); + return(code); } - + pr_ReadEntry(tt, afd, pos, tentry) struct ubik_trans *tt; long afd; @@ -146,6 +144,7 @@ struct prentry *tentry; } code = ubik_Read(tt, (char *) &nentry, sizeof(struct prentry)); if (code) return (code); + bzero (tentry, sizeof(*tentry)); /* make sure reseved fields are zero */ tentry->flags = ntohl(nentry.flags); tentry->id = ntohl(nentry.id); tentry->cellid = ntohl(nentry.cellid); @@ -164,35 +163,38 @@ struct prentry *tentry; tentry->sibling = ntohl(nentry.sibling); tentry->child = ntohl(nentry.child); strncpy(tentry->name, nentry.name, PR_MAXNAMELEN); +#ifdef PR_REMEMBER_TIMES + tentry->createTime = ntohl(nentry.createTime); + tentry->addTime = ntohl(nentry.addTime); + tentry->removeTime = ntohl(nentry.removeTime); + tentry->changeTime = ntohl(nentry.changeTime); +#endif for (i = 0; i < PRSIZE; i++) tentry->entries[i] = ntohl(nentry.entries[i]); return(code); } pr_WriteCoEntry(tt, afd, pos, tentry) -struct ubik_trans *tt; -long afd; -long pos; -struct contentry *tentry; + struct ubik_trans *tt; + long afd; + long pos; + struct contentry *tentry; { long code; register long i; struct contentry nentry; - if (ntohl(1) == 1) { /* No need to swap */ - code = ubik_Seek(tt, afd, pos); - if (code) return(code); - code = ubik_Write(tt, (char *) tentry, sizeof(struct contentry)); - return(code); + + if (ntohl(1) != 1) { /* No need to swap */ + bzero (&nentry, sizeof(nentry)); /* make reseved fields zero */ + nentry.flags = htonl(tentry->flags); + nentry.id = htonl(tentry->id); + nentry.cellid = htonl(tentry->cellid); + nentry.next = htonl(tentry->next); + for (i = 0; i < COSIZE; i++) + nentry.entries[i] = htonl(tentry->entries[i]); + tentry = &nentry; } - nentry.flags = htonl(tentry->flags); - nentry.id = htonl(tentry->id); - nentry.cellid = htonl(tentry->cellid); - nentry.next = htonl(tentry->next); - for (i = 0; i < COSIZE; i++) - nentry.entries[i] = htonl(tentry->entries[i]); - code = ubik_Seek(tt, afd, pos); - if (code) return (code); - code = ubik_Write(tt, (char *) &nentry, sizeof(struct contentry)); + code = pr_Write (tt, afd, pos, (char *)tentry, sizeof(struct contentry)); return(code); } @@ -213,6 +215,7 @@ struct contentry *tentry; } code = ubik_Read(tt, (char *) &nentry, sizeof(struct contentry)); if (code) return (code); + bzero (tentry, sizeof(*tentry)); /* make reseved fields zero */ tentry->flags = ntohl(nentry.flags); tentry->id = ntohl(nentry.id); tentry->cellid = ntohl(nentry.cellid); @@ -222,10 +225,12 @@ struct contentry *tentry; return(code); } +/* AllocBloc - allocate a free block of storage for entry, returning address of + * new entry */ + long AllocBlock(at) -register struct ubik_trans *at; + register struct ubik_trans *at; { - /* allocate a free block of storage for entry, returning address of new entry */ register long code; long temp; struct prentry tentry; @@ -279,6 +284,7 @@ long aid; struct prentry tentry; long entry; + if ((aid == PRBADID) || (aid == 0)) return 0; i = IDHash(aid); entry = ntohl(cheader.idHash[i]); if (entry == 0) return entry; @@ -378,6 +384,40 @@ long *aid; } } +long IDToName(at, aid, aname) + register struct ubik_trans *at; + long aid; + char aname[PR_MAXNAMELEN]; +{ + long temp; + struct prentry tentry; + register long code; + + temp = FindByID(at,aid); + if (temp == 0) return PRNOENT; + code = pr_Read (at, 0, temp, (char *)&tentry, sizeof(tentry)); + if (code) return code; + strncpy (aname, tentry.name, PR_MAXNAMELEN); + return PRSUCCESS; +} + +long NameToID(at, aname, aid) +register struct ubik_trans *at; +char aname[PR_MAXNAMELEN]; +long *aid; +{ + register long code; + long temp; + struct prentry tentry; + + temp = FindByName(at,aname); + if (!temp) return PRNOENT; + code = pr_ReadEntry(at, 0, temp, &tentry); + if (code != 0) return code; + *aid = tentry.id; + return PRSUCCESS; +} + long IDCmp(a,b) long *a; long *b; @@ -391,7 +431,7 @@ long *b; long RemoveFromIDHash(tt,aid,loc) struct ubik_trans *tt; long aid; -long *loc; +long *loc; /* ??? in case ID hashed twice ??? */ { /* remove entry designated by aid from id hash table */ register long code; @@ -399,12 +439,13 @@ long *loc; struct prentry tentry; struct prentry bentry; + if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT; i = IDHash(aid); current = ntohl(cheader.idHash[i]); bzero(&tentry,sizeof(tentry)); bzero(&bentry,sizeof(bentry)); trail = 0; - if (current == NULL) return PRNOENT; + if (current == NULL) return PRSUCCESS; /* already gone */ code = pr_ReadEntry(tt,0,current,&tentry); if (code) return PRDBFAIL; while (aid != tentry.id) { @@ -414,7 +455,7 @@ long *loc; code = pr_ReadEntry(tt,0,current,&tentry); if (code) return PRDBFAIL; } - if (current == NULL) return PRNOENT; /* we didn't find him */ + if (current == NULL) return PRSUCCESS; /* we didn't find him, so he's already gone */ if (trail == NULL) { /* it's the first entry! */ cheader.idHash[i] = htonl(tentry.nextID); @@ -434,13 +475,14 @@ long *loc; long AddToIDHash(tt, aid, loc) struct ubik_trans *tt; long aid; -long loc; +long loc; /* ??? */ { /* add entry at loc designated by aid to id hash table */ register long code; long i; struct prentry tentry; + if ((aid == PRBADID) || (aid == 0)) return PRINCONSISTENT; i = IDHash(aid); bzero(&tentry,sizeof(tentry)); code = pr_ReadEntry(tt,0,loc,&tentry); @@ -470,7 +512,7 @@ long *loc; bzero(&tentry,sizeof(tentry)); bzero(&bentry,sizeof(bentry)); trail = 0; - if (current == NULL) return PRNOENT; + if (current == NULL) return PRSUCCESS; /* already gone */ code = pr_ReadEntry(tt,0,current,&tentry); if (code) return PRDBFAIL; while (strcmp(aname,tentry.name)) { @@ -480,7 +522,7 @@ long *loc; code = pr_ReadEntry(tt,0,current,&tentry); if (code) return PRDBFAIL; } - if (current == NULL) return PRNOENT; /* we dnamen't find him */ + if (current == NULL) return PRSUCCESS; /* we didn't find him, already gone */ if (trail == NULL) { /* it's the first entry! */ cheader.nameHash[i] = htonl(tentry.nextName); @@ -521,79 +563,97 @@ long loc; } long AddToOwnerChain(at,gid,oid) -struct ubik_trans *at; -long gid; -long oid; + struct ubik_trans *at; + long gid; + long oid; { /* add entry designated by gid to owner chain of entry designated by oid */ register long code; long loc; - long gloc; struct prentry tentry; struct prentry gentry; + long gloc; loc = FindByID(at,oid); if (!loc) return PRNOENT; code = pr_ReadEntry(at,0,loc,&tentry); if (code != 0) return PRDBFAIL; - gloc = FindByID(at,gid); - code = pr_ReadEntry(at,0,gloc,&gentry); - if (code != 0) return PRDBFAIL; - gentry.nextOwned = tentry.owned; - tentry.owned = gloc; + if (oid == gid) { /* added it to its own chain */ + tentry.nextOwned = tentry.owned; + tentry.owned = loc; + } else { + gloc = FindByID(at,gid); + code = pr_ReadEntry(at,0,gloc,&gentry); + if (code != 0) return PRDBFAIL; + gentry.nextOwned = tentry.owned; + tentry.owned = gloc; + code = pr_WriteEntry(at,0,gloc,&gentry); + if (code != 0) return PRDBFAIL; + } code = pr_WriteEntry(at,0,loc,&tentry); if (code != 0) return PRDBFAIL; - code = pr_WriteEntry(at,0,gloc,&gentry); - if (code != 0) return PRDBFAIL; return PRSUCCESS; } +/* RemoveFromOwnerChain - remove gid from owner chain for oid */ + long RemoveFromOwnerChain(at,gid,oid) -struct ubik_trans *at; -long gid; -long oid; + struct ubik_trans *at; + long gid; + long oid; { - /* remove gid from owner chain for oid */ register long code; long nptr; - struct prentry tentry; - struct prentry bentry; - long loc; + struct prentry thisEntry; + struct prentry thatEntry; + struct prentry *te; /* pointer to current (this) entry */ + struct prentry *le; /* pointer to previous (last) entry */ + long loc, lastLoc; loc = FindByID(at,oid); if (!loc) return PRNOENT; - code = pr_ReadEntry(at,0,loc,&tentry); + code = pr_ReadEntry (at, 0, loc, &thisEntry); if (code != 0) return PRDBFAIL; - if (!tentry.owned) return PRNOENT; - nptr = tentry.owned; - bcopy(&tentry,&bentry,sizeof(tentry)); + le = &thisEntry; + lastLoc = 0; + nptr = thisEntry.owned; while (nptr != NULL) { - code = pr_ReadEntry(at,0,nptr,&tentry); - if (code != 0) return PRDBFAIL; - if (tentry.id == gid) { - /* found it */ - if (nptr == bentry.owned) /* modifying first of chain */ - bentry.owned = tentry.nextOwned; - else bentry.nextOwned = tentry.nextOwned; - tentry.nextOwned = 0; - code = pr_WriteEntry(at,0,loc,&bentry); + if (nptr == lastLoc) te = le; + else { + if (&thisEntry == le) te = &thatEntry; + else te = &thisEntry; + code = pr_ReadEntry (at, 0, nptr, te); if (code != 0) return PRDBFAIL; - code = pr_WriteEntry(at,0,nptr,&tentry); + } + if (te->id == gid) { + /* found it */ + if (lastLoc == 0) { /* modifying first of chain */ + le->owned = te->nextOwned; + lastLoc = loc; /* so we write to correct location */ + } + else le->nextOwned = te->nextOwned; + te->nextOwned = 0; + if (te != le) { + code = pr_WriteEntry (at, 0, nptr, te); + if (code != 0) return PRDBFAIL; + } + code = pr_WriteEntry (at, 0, lastLoc, le); if (code != 0) return PRDBFAIL; return PRSUCCESS; } - loc = nptr; - nptr = tentry.nextOwned; - bcopy(&tentry,&bentry,sizeof(tentry)); + lastLoc = nptr; + le = te; + nptr = te->nextOwned; } - return PRNOENT; + return PRSUCCESS; /* already removed? */ } +/* AddToOrphan - add gid to orphan list, as it's owner has died */ + long AddToOrphan(at,gid) -struct ubik_trans *at; -long gid; + struct ubik_trans *at; + long gid; { - /* add gid to orphan list, as it's owner has died */ register long code; long loc; struct prentry tentry; @@ -603,10 +663,10 @@ long gid; code = pr_ReadEntry(at,0,loc,&tentry); if (code != 0) return PRDBFAIL; tentry.nextOwned = ntohl(cheader.orphan); - cheader.orphan = htonl(loc); - code = pr_WriteEntry(at,0,loc,&tentry); + code = set_header_word (at, orphan, htonl(loc)); if (code != 0) return PRDBFAIL; - code = pr_Write(at,0,32,(char *)&cheader.orphan,sizeof(cheader.orphan)); + tentry.owner = 0; /* so there's no confusion later */ + code = pr_WriteEntry(at,0,loc,&tentry); if (code != 0) return PRDBFAIL; return PRSUCCESS; } @@ -653,9 +713,9 @@ long gid; } loc = nptr; nptr = tentry.nextOwned; - bcopy(&tentry,&bentry,sizeof(tentry)); + bcopy(&tentry,&bentry, sizeof(tentry)); } - return PRNOENT; + return PRSUCCESS; } long IsOwnerOf(at,aid,gid) @@ -693,15 +753,6 @@ long gid; } -long WhoIsThis(acall, at, aid) -struct rx_call *acall; -struct ubik_trans *at; -long *aid; -{ - *aid = USERSMS; - return 0; -} - long IsAMemberOf(at,aid,gid) struct ubik_trans *at; long aid; @@ -714,6 +765,10 @@ long gid; long i; long loc; + /* special case anyuser and authuser */ + if (gid == ANYUSERID) return 1; + if (gid == AUTHUSERID && aid != ANONYMOUSID) return 1; + if ((gid == 0) || (aid == 0)) return 0; loc = FindByID(at,gid); if (!loc) return 0; bzero(&tentry,sizeof(tentry)); @@ -721,8 +776,8 @@ long gid; if (code) return 0; if (!(tentry.flags & PRGRP)) return 0; for (i= 0;i