--- /dev/null
+/* 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 <afs/param.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <lock.h>
+#include <ubik.h>
+#include <rx/xdr.h>
+#include <rx/rx.h>
+#include <rx/rx_vab.h>
+#include <rx/rxkad.h>
+#include <afs/auth.h>
+#include <netinet/in.h>
+#include "ptserver.h"
+#include "pterror.h"
+#include <strings.h>
+
+#ifdef AFS_ATHENA_STDENV
+#include <krb.h>
+#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;i<aname->namelist_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;i<aid->idlist_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;i<COSIZE;i++) {
+ if (centry.entries[i] == PRBADID) continue;
+ if (centry.entries[i] == 0) break;
+ code = RemoveFromEntry (tt, aid, centry.entries[i]);
+ if (code) goto abort;
+ tentry.count--; /* maintain count */
+ if ((i&3) == 0) IOMGR_Poll();
+ }
+ tentry.next = centry.next; /* thread out this block */
+ code = FreeBlock (tt, nptr); /* free continuation block */
+ if (code) goto abort;
+ code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
+ if (code) goto abort;
+
+ /* end this trans and start a new one */
+ code = ubik_EndTrans(tt);
+ if (code) return code;
+ IOMGR_Poll(); /* just to keep the connection alive */
+ code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
+ if (code) return code;
+ code = ubik_SetLock(tt,1,1,LOCKWRITE);
+ if (code) goto abort;
+
+ /* re-read entry to get consistent uptodate info */
+ loc = FindByID (tt, aid);
+ if (loc == 0) {code = PRNOENT; goto abort;}
+ code = pr_ReadEntry (tt, 0, loc, &tentry);
+ if (code) {code = PRDBFAIL; goto abort;}
+
+ nptr = tentry.next;
+ }
+
+ /* Then move the owned chain, except possibly ourself to the orphan list.
+ * Because this list can be very long and so exceed the size of a ubik
+ * transaction, we start a new transaction every 50 entries. */
+ count = 0;
+ nptr = tentry.owned;
+ while (nptr != NULL) {
+ struct prentry nentry;
+
+ code = pr_ReadEntry (tt, 0, nptr, &nentry);
+ if (code) {code = PRDBFAIL; goto abort;}
+ nptr = tentry.owned = nentry.nextOwned; /* thread out */
+
+ if (nentry.id != tentry.id) { /* don't add us to orphan chain! */
+ code = AddToOrphan (tt, nentry.id);
+ if (code) goto abort;
+ count++;
+ if ((count & 3) == 0) IOMGR_Poll();
+ }
+ if (count < 50) continue;
+ code = pr_WriteEntry (tt, 0, loc, &tentry); /* update main entry */
+ if (code) goto abort;
+
+ /* end this trans and start a new one */
+ code = ubik_EndTrans(tt);
+ if (code) return code;
+ IOMGR_Poll(); /* just to keep the connection alive */
+ code = ubik_BeginTrans(dbase,UBIK_WRITETRANS,&tt);
+ if (code) return code;
+ code = ubik_SetLock(tt,1,1,LOCKWRITE);
+ if (code) goto abort;
+
+ /* re-read entry to get consistent uptodate info */
+ loc = FindByID (tt, aid);
+ if (loc == 0) {code = PRNOENT; goto abort;}
+ code = pr_ReadEntry (tt, 0, loc, &tentry);
+ if (code) {code = PRDBFAIL; goto abort;}
+
+ nptr = tentry.owned;
+ }
+
+ /* now do what's left of the deletion stuff */
+ code = DeleteEntry (tt, &tentry, loc);
+ if (code != PRSUCCESS) {
+ ubik_AbortTrans(tt);
+ return code;
+ }
+ code = ubik_EndTrans(tt);
+ if (code) return code;
+ return PRSUCCESS;
+}
+
+PR_RemoveFromGroup(call,aid,gid)
+struct rx_call *call;
+long aid;
+long gid;
+{
+ register long code;
+ struct ubik_trans *tt;
+ long tempu;
+ long tempg;
+ struct prentry uentry;
+ struct prentry gentry;
+ 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;
+ }
+ tempu = FindByID(tt,aid);
+ if (!tempu) {
+ ubik_AbortTrans(tt);
+ return PRNOENT;
+ }
+ tempg = FindByID(tt,gid);
+ if (!tempg) {
+ ubik_AbortTrans(tt);
+ return PRNOENT;
+ }
+ bzero(&uentry,sizeof(uentry));
+ bzero(&gentry,sizeof(gentry));
+ code = pr_ReadEntry(tt,0,tempu,&uentry);
+ if (code != 0) {
+ ubik_AbortTrans(tt);
+ return code;
+ }
+ code = pr_ReadEntry(tt,0,tempg,&gentry);
+ if (code != 0) {
+ ubik_AbortTrans(tt);
+ return code;
+ }
+ if (!(gentry.flags & PRGRP)) {
+ ubik_AbortTrans(tt);
+ return PRNOTGROUP;
+ }
+ if (uentry.flags & PRGRP) {
+ ubik_AbortTrans(tt);
+ return PRNOTUSER;
+ }
+ if (!AccessOK (tt, cid, &gentry, PRP_REMOVE_MEM, 0)) {
+ ubik_AbortTrans(tt);
+ return PRPERM;
+ }
+ code = RemoveFromEntry(tt,aid,gid);
+ if (code != PRSUCCESS) {
+ ubik_AbortTrans(tt);
+ return code;
+ }
+ code = RemoveFromEntry(tt,gid,aid);
+ if (code != PRSUCCESS) {
+ ubik_AbortTrans(tt);
+ return code;
+ }
+ code = ubik_EndTrans(tt);
+ if (code) return code;
+ return PRSUCCESS;
+}
+
+long PR_GetCPS (call, aid, alist, over)
+ struct rx_call *call;
+ long aid;
+ prlist *alist;
+ long *over;
+{
+ register long code;
+ struct ubik_trans *tt;
+ long temp;
+ long cid;
+ 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;
+ }
+
+
+ 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++;
+ }
+}
-/* $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
*/
+#include <afs/param.h>
+#include <sys/types.h>
#include <stdio.h>
-#include <strings.h>
#include <lock.h>
-#define UBIK_INTERNALS
+#include <netinet/in.h>
#include <ubik.h>
#include <rx/xdr.h>
-#include "print.h"
-#include "prserver.h"
-#include "prerror.h"
-#include <netinet/in.h>
+#include <afs/com_err.h>
+#include "ptserver.h"
+#include "pterror.h"
+#include <strings.h>
-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;
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;
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);
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;i<PRSIZE;i++) {
if (tentry.entries[i] == aid) {
tentry.entries[i] = PRBADID;
if (tentry.entries[i] == 0) /* found end of list */
return PRNOENT;
}
- if (tentry.next != NULL) {
- nptr = tentry.next;
- first = 1;
- while (nptr != NULL) {
- code = pr_ReadCoEntry(at,0,nptr,¢ry);
- if (code != 0) return code;
- for (i=0;i<COSIZE;i++) {
- if (centry.entries[i] == aid) {
- centry.entries[i] = PRBADID;
- tentry.count--;
- code = pr_WriteEntry(at,0,temp,&tentry);
- if (code) return PRDBFAIL;
- for (j=0;j<COSIZE;j++)
- if (centry.entries[j] != PRBADID && centry.entries[j] != 0) break;
- if (j == COSIZE) { /* can free this block */
- if (first) {
- tentry.next = centry.next;
- code = pr_WriteEntry(at,0,temp,&tentry);
- if (code != 0) return code;
- }
- else {
- hentry.next = centry.next;
- code = pr_WriteCoEntry(at,0,hloc,(char *) &hentry);
- if (code != 0) return code;
- }
- code = FreeBlock(at,nptr);
- return code;
+ hloc = 0;
+ nptr = tentry.next;
+ while (nptr != NULL) {
+ code = pr_ReadCoEntry(at,0,nptr,¢ry);
+ if (code != 0) return code;
+ if ((centry.id != bid) || !(centry.flags & PRCONT)) return PRDBBAD;
+ for (i=0;i<COSIZE;i++) {
+ if (centry.entries[i] == aid) {
+ centry.entries[i] = PRBADID;
+ for (j=0;j<COSIZE;j++)
+ if (centry.entries[j] != PRBADID &&
+ centry.entries[j] != 0) break;
+ if (j == COSIZE) { /* can free this block */
+ if (hloc == 0) {
+ tentry.next = centry.next;
}
- else { /* can't free it yet */
- code = pr_WriteCoEntry(at,0,nptr,¢ry);
+ else {
+ hentry.next = centry.next;
+ code = pr_WriteCoEntry (at, 0, hloc, &hentry);
if (code != 0) return code;
- return PRSUCCESS;
}
+ code = FreeBlock (at, nptr);
+ if (code) return code;
}
- if (centry.entries[i] == 0) return PRNOENT;
+ else { /* can't free it yet */
+ code = pr_WriteCoEntry(at,0,nptr,¢ry);
+ if (code != 0) return code;
+ }
+ tentry.count--;
+ code = pr_WriteEntry(at,0,temp,&tentry);
+ if (code) return PRDBFAIL;
+ return 0;
}
- hloc = nptr;
- nptr = centry.next;
- bcopy(¢ry,&hentry,sizeof(centry));
- }
- }
- else return PRNOENT;
- return PRSUCCESS;
+ if (centry.entries[i] == 0) return PRNOENT;
+ } /* for all coentry slots */
+ hloc = nptr;
+ nptr = centry.next;
+ bcopy(¢ry,&hentry,sizeof(centry));
+ } /* while there are coentries */
+ return PRNOENT;
}
-long DeleteEntry(at,aid,cid)
-register struct ubik_trans *at;
-long aid;
-long cid;
+/* DeleteEntry - delete the entry in tentry at loc, removing it from all
+ * groups, putting groups owned by it on orphan chain, and freeing the space */
+
+long DeleteEntry (at, tentry, loc)
+ register struct ubik_trans *at;
+ struct prentry *tentry;
+ long loc;
{
- /* delete the entry aid, removing it from all groups, putting groups owned by it on orphan chain, and freeing the space */
register long code;
- long temp;
long temp1;
- struct prentry tentry;
struct contentry centry;
struct prentry nentry;
register long i;
long nptr;
- long noAuth;
-
- noAuth = afsconf_GetNoAuthFlag(prdir);
- bzero(&tentry,sizeof(tentry));
- temp = FindByID(at,aid);
- if (!temp) return PRNOENT;
- code = pr_ReadEntry(at,0,temp,&tentry);
- if (code != 0) return PRDBFAIL;
- if (tentry.owner != cid && !IsAMemberOf(at,cid,SYSADMINID) && !IsAMemberOf(at,cid,tentry.owner) && !noAuth) return PRPERM;
+
+ /* First remove the entire membership list */
for (i=0;i<PRSIZE;i++) {
- if (tentry.entries[i] == 0) break;
- RemoveFromEntry(at,aid,tentry.entries[i]);
+ if (tentry->entries[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;i<COSIZE;i++) {
+ if (centry.entries[i] == PRBADID) continue;
if (centry.entries[i] == 0) break;
- RemoveFromEntry(at,aid,centry.entries[i]);
+ code = RemoveFromEntry (at, tentry->id, 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;i<PRSIZE;i++) {
- if (entry.entries[i] == aid)
+ if (entry->entries[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;
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;i<COSIZE;i++) {
if (nentry.entries[i] == aid)
cloc = nptr;
}
}
- if (nentry.entries[i] == 0) {
+ else if (nentry.entries[i] == 0) {
if (slot == -1) {
slot = i;
cloc = nptr;
break;
}
}
- last = nptr;
nptr = nentry.next;
}
- if (slot != -1) { /* we found a place */
- entry.count++;
+ if (slot != -1) { /* we found a place */
+ entry->count++;
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;
}
/* 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;i<PRSIZE;i++) {
- if (tentry.entries[i] == PRBADID) continue;
- if (tentry.entries[i] == 0) break;
- alist->prlist_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);
for (i=0;i<COSIZE;i++) {
if (centry.entries[i] == PRBADID) continue;
if (centry.entries[i] == 0) break;
- if (alist->prlist_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;
}
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);
}
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;
/* 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<sizeof(cheader); i++)
+ if (bp[i]) {
+ code = PRDBBAD;
+ com_err (whoami, code,
+ "Can't rebuild database because it is not empty");
+ return code;
+ }
+ }
+ if (!pr_noAuth) {
+ code = PRDBBAD;
+ com_err (whoami, code,
+ "Can't rebuild database because not running NoAuth");
+ return code;
+ }
+
code = ubik_BeginTrans(dbase,UBIK_WRITETRANS, &tt);
if (code) return code;
code = ubik_SetLock(tt,1,1,LOCKWRITE);
ubik_AbortTrans(tt);
return code;
}
- header.magic = htonl(UBIK_MAGIC);
- header.pad1 = 0;
- header.size = 0;
- header.version.epoch = header.version.counter = htonl(1);
- code = pr_Write(tt, 0, -(HDRSIZE), (char *)&header, sizeof(header));
- if (code != 0) {
- printf("prserver: couldn't write ubik header - code is %d.\n", code);
- return code;
- }
- cheader.headerSize = htonl(sizeof(cheader));
- code = pr_Write(tt,0,4,(char *)&cheader.headerSize,sizeof(cheader.headerSize));
- if (code != 0) {
- printf("prserver: couldn't write header size - code is %d.\n",code);
+
+ /* Initialize the database header */
+
+ if ((code = set_header_word (tt, version, htonl(PRDBVERSION))) ||
+ (code = set_header_word (tt, headerSize, htonl(sizeof(cheader)))) ||
+ (code = set_header_word (tt, eofPtr, cheader.headerSize))) {
+ com_err (whoami, code, "couldn't write header words");
ubik_AbortTrans(tt);
return code;
}
- cheader.eofPtr = cheader.headerSize; /* already in network order! */
- code = pr_Write(tt,0,12,(char *)&cheader.eofPtr,sizeof(cheader.eofPtr));
- if (code != 0) {
- printf("prserver: couldn't write eof Ptr - code is %d.\n",code);
+
+#define InitialGroup(id,name) do { \
+ long temp = (id); \
+ long flag = (id) < 0 ? PRGRP : 0; \
+ code = CreateEntry \
+ (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
+ if (code) { \
+ com_err (whoami, code, "couldn't create %s with id %di.", \
+ (name), (id)); \
+ ubik_AbortTrans(tt); \
+ return code; \
+ } \
+} while (0)
+
+ InitialGroup (SYSADMINID, "system:administrators");
+ InitialGroup (ANYUSERID, "system:anyuser");
+ InitialGroup (AUTHUSERID, "system:authuser");
+ InitialGroup (ANONYMOUSID, "anonymous");
+
+ /* Well, we don't really want the max id set to anonymousid, so we'll set
+ * it back to 0 */
+ code = set_header_word (tt, maxID, 0); /* correct in any byte order */
+ if (code) {
+ com_err (whoami, code, "couldn't reset max id");
ubik_AbortTrans(tt);
return code;
}
- temp = SYSADMINID;
- if (FindByID(tt,SYSADMINID) == 0) {
- /* init sysadmin */
- flag |= PRGRP;
- code = CreateEntry(tt,"system:administrators",&temp,1,flag,SYSADMINID,SYSADMINID);
- if (code != PRSUCCESS) {
- printf("prserver: couldn't create system:administrators.\n");
- ubik_AbortTrans(tt);
- return code;
- }
- flag = 0;
- }
- temp = ANYUSERID;
- if ( FindByID(tt,temp) == 0) { /* init sysadmin */
- flag |= PRGRP;
- code = CreateEntry(tt,"system:anyuser",&temp,1,flag,SYSADMINID,SYSADMINID);
- if (code != PRSUCCESS) {
- printf("prserver: couldn't create system:anyuser.\n");
- ubik_AbortTrans(tt);
- return code;
- }
- flag = 0;
- }
- temp = AUTHUSERID;
- if (FindByID(tt,temp) == 0) { /* init sysadmin */
- flag |= PRGRP;
- code = CreateEntry(tt,"system:authuser",&temp,1,flag,SYSADMINID,SYSADMINID);
- if (code != PRSUCCESS) {
- printf("prserver: couldn't create system:authuser.\n");
- ubik_AbortTrans(tt);
- return code;
- }
- flag = 0;
- }
- temp = ANONYMOUSID;
- if (FindByID(tt,temp) == 0) { /* init sysadmin */
- code = CreateEntry(tt,"anonymous",&temp,1,flag,SYSADMINID,SYSADMINID);
- if (code != PRSUCCESS) {
- printf("prserver: couldn't create anonymous.\n");
- ubik_AbortTrans(tt);
- return code;
- }
- /* well, we don't really want the max id set to anonymousid, so we'll set it back to 0 */
- cheader.maxID = 0; /* Zero is in correct byte order no matter what! */
- code = pr_Write(tt,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
- if (code) {
- printf("prserver: couldn't set max id - code is %d.\n");
- ubik_AbortTrans(tt);
- return code;
- }
- }
+
code = ubik_EndTrans(tt);
if (code) return code;
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 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) return PRNOENT;
- code = pr_ReadEntry(at,0,temp,&tentry);
- if (code != 0) return code;
- strncpy(aname,tentry.name,PR_MAXNAMELEN);
- return PRSUCCESS;
-}
-
-long ChangeEntry(at, aid,cid,name,oid,newid)
-struct ubik_trans *at;
-long aid;
-long cid;
-char *name;
-long oid;
-long newid;
+long ChangeEntry (at, aid, cid, name, oid, newid)
+ struct ubik_trans *at;
+ long aid;
+ long cid;
+ char *name;
+ long oid;
+ long newid;
{
register long code;
long pos;
struct prentry tentry;
long loc;
- long noAuth;
- char *check;
- long tid;
+ long oldowner;
char holder[PR_MAXNAMELEN];
char temp[PR_MAXNAMELEN];
+ char oldname[PR_MAXNAMELEN];
- noAuth = afsconf_GetNoAuthFlag(prdir);
bzero(holder,PR_MAXNAMELEN);
bzero(temp,PR_MAXNAMELEN);
loc = FindByID(at,aid);
if (!loc) return PRNOENT;
code = pr_ReadEntry(at,0,loc,&tentry);
if (code) return PRDBFAIL;
- if (tentry.owner != cid && !IsAMemberOf(at,cid,SYSADMINID) && !IsAMemberOf(at,cid,tentry.owner) && !noAuth)
- return PRPERM;
- if (aid != newid && newid != 0) { /* then we're actually trying to change the id */
+ if (tentry.owner != cid &&
+ !IsAMemberOf(at,cid,SYSADMINID) &&
+ !IsAMemberOf(at,cid,tentry.owner) &&
+ !pr_noAuth) return PRPERM;
+#ifdef PR_REMEMBER_TIMES
+ tentry.changeTime = time(0);
+#endif
+
+ /* we're actually trying to change the id */
+ if (aid != newid && newid != 0) {
+ if (!IsAMemberOf(at,cid,SYSADMINID) && !pr_noAuth) return PRPERM;
pos = FindByID(at,newid);
if (pos) return PRIDEXIST; /* new id already in use! */
if ((aid < 0 && newid) > 0 || (aid > 0 && newid < 0)) return PRPERM;
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;
}
#include <stdio.h>
#include <sys/file.h>
#include <rx/xdr.h>
-#include "print.h"
-#include "prserver.h"
-#include "prerror.h"
+#include <afs/ptint.h>
+#include <afs/ptserver.h>
+#include <afs/pterror.h>
#include <moira.h>
#include <moira_site.h>
#include <ctype.h>
#include <stdio.h>
#include <sys/file.h>
#include <rx/xdr.h>
-#include "print.h"
-#include "prserver.h"
-#include "prerror.h"
+#include <afs/ptint.h>
+#include <afs/ptserver.h>
+#include <afs/pterror.h>
#include <moira.h>
#include <moira_site.h>
#include <ctype.h>
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);
}
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;
return(0);
}
-long ubik_Write(tt, buf, len)
+int ubik_Write(tt, buf, len)
struct ubik_trans *tt;
char *buf;
long len;
return(0);
}
-long ubik_Read(tt, buf, len)
+int ubik_Read(tt, buf, len)
struct ubik_trans *tt;
char *buf;
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()
{
}
+char *prdir = "/dev/null";
struct prheader cheader;
+int pr_realmNameLen;
+char *pr_realmName;
-/* $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 <sys/types.h>
#include <lock.h>
#include <ubik.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>
-#include <rx/xdr.h>
-#include <rx/rx.h>
-#include <rx/rx_vab.h>
-#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;
{
/* 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);
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);
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;
}
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);
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);
}
}
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);
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;
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;
}
}
+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;
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;
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) {
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);
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);
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)) {
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);
}
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;
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;
}
}
loc = nptr;
nptr = tentry.nextOwned;
- bcopy(&tentry,&bentry,sizeof(tentry));
+ bcopy(&tentry,&bentry, sizeof(tentry));
}
- return PRNOENT;
+ return PRSUCCESS;
}
long IsOwnerOf(at,aid,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;
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));
if (code) return 0;
if (!(tentry.flags & PRGRP)) return 0;
for (i= 0;i<PRSIZE;i++) {
- if (tentry.entries[i] == aid) return 1;
if (tentry.entries[i] == 0) return 0;
+ if (tentry.entries[i] == aid) return 1;
}
if (tentry.next) {
loc = tentry.next;