+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;
+
+#ifdef CROSS_CELL
+ if (index (name, ':') || index(name, '\n')) return 0;
+#else
+ if (index (name, ':') || index(name, '@') || index(name, '\n')) return 0;
+#endif
+ if (strlen (name) >= PR_MAXNAMELEN - pr_realmNameLen - 1) return 0;
+ return 1;
+}
+
+/* CorrectGroupName - Like the above but handles more complicated cases caused
+ * by including the ownership in the name. The interface works by calculating
+ * the correct name based on a given name and owner. This allows easy use by
+ * rename, which then compares the correct name with the requested new name. */
+
+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 || (cid==SYSADMINID) || 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 */
+#ifdef CROSS_CELL
+ if (index(cname, '\n') || /* restrict so recreate can work */
+ index(suffix+1, ':')) /* avoid multiple colons */
+ return PRBADNAM;
+#else
+ if (index(cname, '@') || /* avoid confusion w/ foreign users */
+ index(cname, '\n') || /* restrict so recreate can work */
+ index(suffix+1, ':')) /* avoid multiple colons */
+ return PRBADNAM;
+#endif
+ } 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 (cid == SYSADMINID) return 1; /* special case fileserver */
+ 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;