]> andersk Git - moira.git/blame - afssync/ptutils.c
Command line printer manipulation client, and build goo.
[moira.git] / afssync / ptutils.c
CommitLineData
e1f001e5 1/*
5b723b3d 2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
e1f001e5 8 */
9
dba0cf81 10#include <afs/param.h>
5b723b3d 11
da0b4fd5 12#include <afs/stds.h>
dba0cf81 13#include <sys/types.h>
e1f001e5 14#include <stdio.h>
5b723b3d 15#ifdef AFS_NT40_ENV
16#include <winsock2.h>
da0b4fd5 17#else
5b723b3d 18#include <netinet/in.h>
da0b4fd5 19#endif
5b723b3d 20#include <string.h>
e1f001e5 21#include <lock.h>
22#include <ubik.h>
23#include <rx/xdr.h>
dba0cf81 24#include <afs/com_err.h>
5b723b3d 25#include <afs/cellconfig.h>
dba0cf81 26#include "ptserver.h"
27#include "pterror.h"
5b723b3d 28#include <stdlib.h>
29
30/* Foreign cells are represented by the group system:authuser@cell*/
31#define AUTHUSER_GROUP "system:authuser"
da0b4fd5 32
e1f001e5 33
e1f001e5 34extern struct ubik_dbase *dbase;
35extern struct afsconf_dir *prdir;
dba0cf81 36extern int pr_noAuth;
5b723b3d 37extern int IDCmp();
e1f001e5 38
5b723b3d 39extern afs_int32 AddToEntry();
dba0cf81 40static char *whoami = "ptserver";
41
42/* CorrectUserName - Check to make sure a user name is OK. It must not include
43 * either a colon (or it would look like a group) or an atsign (or it would
44 * look like a foreign user). The length is checked as well to make sure
45 * that the user name, an atsign, and the local cell name will fit in
46 * PR_MAXNAMELEN. This is so this user can fit in another cells database as
47 * a foreign user with our cell name tacked on. This is a predicate, so it
48 * return one if name is OK and zero if name is bogus. */
49
50static int CorrectUserName (name)
51 char *name;
52{
53 extern int pr_realmNameLen;
54
5b723b3d 55 /* We accept foreign names, so we will deal with '@' later */
56 if (strchr (name, ':') || strchr(name, '\n')) return 0;
dba0cf81 57 if (strlen (name) >= PR_MAXNAMELEN - pr_realmNameLen - 1) return 0;
58 return 1;
59}
60
da0b4fd5 61/* CorrectGroupName - Like the above but handles more complicated cases caused
62 * by including the ownership in the name. The interface works by calculating
63 * the correct name based on a given name and owner. This allows easy use by
64 * rename, which then compares the correct name with the requested new name. */
65
5b723b3d 66static afs_int32 CorrectGroupName (ut, aname, cid, oid, cname)
dba0cf81 67 struct ubik_trans *ut;
68 char aname[PR_MAXNAMELEN]; /* name for group */
5b723b3d 69 afs_int32 cid; /* caller id */
70 afs_int32 oid; /* owner of group */
dba0cf81 71 char cname[PR_MAXNAMELEN]; /* correct name for group */
72{
5b723b3d 73 afs_int32 code;
dba0cf81 74 int admin;
75 char *prefix; /* ptr to group owner part */
76 char *suffix; /* ptr to group name part */
77 char name[PR_MAXNAMELEN]; /* correct name for group */
78 struct prentry tentry;
79
80 if (strlen (aname) >= PR_MAXNAMELEN) return PRBADNAM;
5b723b3d 81 admin = pr_noAuth || IsAMemberOf (ut, cid, SYSADMINID);
dba0cf81 82
83 if (oid == 0) oid = cid;
84
85 /* Determine the correct prefix for the name. */
86 if (oid == SYSADMINID) prefix = "system";
87 else {
5b723b3d 88 afs_int32 loc = FindByID (ut, oid);
dba0cf81 89 if (loc == 0) {
90 /* let admin create groups owned by non-existent ids (probably
91 * setting a group to own itself). Check that they look like
92 * groups (with a colon) or otherwise are good user names. */
93 if (admin) {
94 strcpy (cname, aname);
95 goto done;
96 }
97 return PRNOENT;
98 }
99 code = pr_Read (ut, 0, loc, &tentry, sizeof(tentry));
100 if (code) return code;
101 if (ntohl(tentry.flags) & PRGRP) {
102 if ((tentry.count == 0) && !admin) return PRGROUPEMPTY;
103 /* terminate prefix at colon if there is one */
5b723b3d 104 if ((prefix = strchr(tentry.name, ':'))) *prefix = 0;
dba0cf81 105 }
106 prefix = tentry.name;
107 }
108 /* only sysadmin allow to use 'system:' prefix */
109 if ((strcmp (prefix, "system") == 0) && !admin) return PRPERM;
110
111 strcpy (name, aname); /* in case aname & cname are same */
5b723b3d 112 suffix = strchr(name, ':');
dba0cf81 113 if (suffix == 0) {
114 /* sysadmin can make groups w/o ':', but they must still look like
115 * legal user names. */
116 if (!admin) return PRBADNAM;
117 strcpy (cname, name);
118 }
119 else {
120 if (strlen(prefix)+strlen(suffix) >= PR_MAXNAMELEN) return PRBADNAM;
121 strcpy (cname, prefix);
122 strcat (cname, suffix);
123 }
124 done:
125 /* check for legal name with either group rules or user rules */
5b723b3d 126 if ((suffix = strchr(cname, ':'))) {
dba0cf81 127 /* check for confusing characters */
5b723b3d 128 if (strchr(cname, '\n') || /* restrict so recreate can work */
129 strchr(suffix+1, ':')) /* avoid multiple colons */
dba0cf81 130 return PRBADNAM;
131 } else {
132 if (!CorrectUserName (cname)) return PRBADNAM;
133 }
134 return 0;
135}
136
137int AccessOK (ut, cid, tentry, mem, any)
138 struct ubik_trans *ut;
5b723b3d 139 afs_int32 cid; /* caller id */
dba0cf81 140 struct prentry *tentry; /* object being accessed */
141 int mem; /* check membership in aid, if group */
142 int any; /* if set return true */
5b723b3d 143{ afs_int32 flags;
144 afs_int32 oid;
145 afs_int32 aid;
dba0cf81 146
147 if (pr_noAuth) return 1;
da0b4fd5 148 if (cid == SYSADMINID) return 1; /* special case fileserver */
dba0cf81 149 if (tentry) {
150 flags = tentry->flags;
151 oid = tentry->owner;
152 aid = tentry->id;
153 } else {
154 flags = oid = aid = 0;
155 }
5b723b3d 156 if (!(flags & PRACCESS)) { /* provide default access */
dba0cf81 157 if (flags & PRGRP)
158 flags |= PRP_GROUP_DEFAULT;
159 else
160 flags |= PRP_USER_DEFAULT;
5b723b3d 161 }
dba0cf81 162
163 if (flags & any) return 1;
164 if (oid) {
165 if ((cid == oid) ||
166 IsAMemberOf (ut, cid, oid)) return 1;
167 }
168 if (aid > 0) { /* checking on a user */
169 if (aid == cid) return 1;
170 } else if (aid < 0) { /* checking on group */
171 if ((flags & mem) && IsAMemberOf (ut, cid, aid)) return 1;
172 }
5b723b3d 173 /* Allow members of SYSVIEWERID to get membership and status only */
174 if (((mem == PRP_STATUS_MEM)||(mem == PRP_MEMBER_MEM))&&(IsAMemberOf (ut, cid, SYSVIEWERID))) return 1;
dba0cf81 175 if (IsAMemberOf (ut, cid, SYSADMINID)) return 1;
176 return 0; /* no access */
177}
178
5b723b3d 179afs_int32 CreateEntry (at, aname, aid, idflag, flag, oid, creator)
180 struct ubik_trans *at;
dba0cf81 181 char aname[PR_MAXNAMELEN];
5b723b3d 182 afs_int32 *aid;
183 afs_int32 idflag;
184 afs_int32 flag;
185 afs_int32 oid;
186 afs_int32 creator;
e1f001e5 187{
188 /* get and init a new entry */
5b723b3d 189 afs_int32 code;
190 afs_int32 newEntry;
191 struct prentry tentry, tent;
192 char *atsign;
e1f001e5 193
5b723b3d 194 memset(&tentry, 0, sizeof(tentry));
dba0cf81 195
196 if ((oid == 0) || (oid == ANONYMOUSID)) oid = creator;
197
198 if (flag & PRGRP) {
199 code = CorrectGroupName (at, aname, creator, oid, tentry.name);
200 if (code) return code;
201 if (strcmp (aname, tentry.name) != 0) return PRBADNAM;
202 } else { /* non-group must not have colon */
203 if (!CorrectUserName(aname)) return PRBADNAM;
204 strcpy (tentry.name, aname);
205 }
206
5b723b3d 207 if (FindByName(at,aname, &tent)) return PREXIST;
dba0cf81 208
e1f001e5 209 newEntry = AllocBlock(at);
210 if (!newEntry) return PRDBFAIL;
dba0cf81 211#ifdef PR_REMEMBER_TIMES
212 tentry.createTime = time(0);
213#endif
5b723b3d 214
e1f001e5 215 if (flag & PRGRP) {
5b723b3d 216 tentry.flags = PRGRP;
e1f001e5 217 tentry.owner = oid;
5b723b3d 218 } else if (flag == 0) {
219 tentry.flags = 0;
220 tentry.owner = SYSADMINID;
221 } else {
222 return PRBADARG;
da0b4fd5 223 }
224
5b723b3d 225 atsign = strchr(aname, '@');
226 if (!atsign) {
227 /* A normal user or group. Pick an id for it */
228 if (idflag)
229 tentry.id = *aid;
230 else {
231 code= AllocID(at,flag,&tentry.id);
232 if (code != PRSUCCESS) return code;
233 }
234 } else if (flag & PRGRP) {
235 /* A foreign group. Its format must be AUTHUSER_GROUP@cellname
236 * Then pick an id for the group.
237 */
238 int badFormat;
239
240 *atsign = '\0';
241 badFormat = strcmp(AUTHUSER_GROUP, aname);
242 *atsign = '@';
243 if (badFormat) return PRBADNAM;
244
245 if (idflag)
246 tentry.id = *aid;
247 else {
248 code= AllocID(at,flag,&tentry.id);
249 if (code != PRSUCCESS) return code;
250 }
251 } else {
252 /* A foreign user: <name>@<cell>. The foreign user is added to
253 * its representing group. It is
254 */
255 char *cellGroup;
256 afs_int32 pos, n;
257 struct prentry centry;
258 extern afs_int32 allocNextId();
259
260 /* To create the user <name>@<cell> the group AUTHUSER_GROUP@<cell>
261 * must exist.
262 */
263 cellGroup = (char *)malloc(strlen(AUTHUSER_GROUP) + strlen(atsign) + 1);
264 strcpy(cellGroup, AUTHUSER_GROUP);
265 strcat(cellGroup, atsign);
266 pos = FindByName(at, cellGroup, &centry);
267 if (!pos) return PRBADNAM;
268 code = pr_Read (at, 0, pos, &centry, sizeof(centry));
269 if (code) return code;
270
271 /* cellid is the id of the group representing the cell */
272 tentry.cellid = ntohl(centry.id);
273
274 if (idflag) {
275 /* Check if id is good */
276 if (!inRange(&centry,*aid)) return PRBADARG;
277 tentry.id = *aid;
278 } else {
279 /* Allocate an ID special for this foreign user. It is based
280 * on the representing group's id and nusers count.
281 */
282 tentry.id = allocNextId(&centry);
283 }
284
285 /* The foreign user will be added to the representing foreign
286 * group. The group can hold up to 30 entries.
287 */
288 if (!(ntohl(centry.flags) & PRQUOTA)) {
289 centry.flags = htonl (ntohl(centry.flags) | PRQUOTA);
290 centry.ngroups = htonl(30);
291 }
292 n = ntohl(centry.ngroups);
293 if ( (n <= 0) && !pr_noAuth ) return PRNOMORE;
294 centry.ngroups = htonl(n - 1);
295
296 /* write updated entry for group */
297 code = pr_Write (at, 0, pos, &centry, sizeof(centry));
298
299 /* Now add the new user entry to the database */
300 tentry.creator = creator;
301 *aid = tentry.id;
302 code = pr_WriteEntry(at, 0, newEntry, &tentry);
303 if (code) return PRDBFAIL;
304 code = AddToIDHash(at, *aid, newEntry);
305 if (code != PRSUCCESS) return code;
306 code = AddToNameHash(at, aname, newEntry);
307 if (code != PRSUCCESS) return code;
308 if (inc_header_word (at, foreigncount, 1)) return PRDBFAIL;
309
310 /* Now add the entry to the authuser group for this cell.
311 * We will reread the entries for the user and the group
312 * instead of modifying them before writing them in the
313 * previous steps. Although not very efficient, much simpler
314 */
315 pos = FindByID(at, tentry.cellid);
316 if (!pos) return PRBADNAM;
317 code = pr_ReadEntry (at, 0, pos, &centry);
318 if (code) return code;
319 code = AddToEntry(at, &centry, pos, *aid);
320 if (code) return code;
321 /* and now the user entry */
322 pos = FindByID(at,*aid);
323 if (!pos) return PRBADNAM;
324 code = pr_ReadEntry (at, 0, pos, &tentry);
325 if (code) return code;
326 code = AddToEntry(at, &tentry, pos, tentry.cellid);
327 if (code) return code;
328
329 return PRSUCCESS;
e1f001e5 330 }
da0b4fd5 331
5b723b3d 332 /* Remember the largest group id or largest user id */
e1f001e5 333 if (flag & PRGRP) {
dba0cf81 334 /* group ids are negative */
5b723b3d 335 if (tentry.id < (afs_int32)ntohl(cheader.maxGroup)) {
dba0cf81 336 code = set_header_word (at, maxGroup, htonl(tentry.id));
e1f001e5 337 if (code) return PRDBFAIL;
338 }
339 }
e1f001e5 340 else {
5b723b3d 341 if (tentry.id > (afs_int32)ntohl(cheader.maxID)) {
dba0cf81 342 code = set_header_word (at, maxID, htonl(tentry.id));
e1f001e5 343 if (code) return PRDBFAIL;
344 }
345 }
dba0cf81 346
5b723b3d 347 /* Charge the creator for this group */
348 if (flag & PRGRP) {
349 afs_int32 loc = FindByID (at, creator);
dba0cf81 350 struct prentry centry;
5b723b3d 351 int admin;
dba0cf81 352
353 if (loc) { /* this should only fail during initialization */
354 code = pr_Read (at, 0, loc, &centry, sizeof(centry));
355 if (code) return code;
356
5b723b3d 357 /* If quota is uninitialized, do it */
358 if (!(ntohl(centry.flags) & PRQUOTA)) {
359 centry.flags = htonl (ntohl(centry.flags) | PRQUOTA);
360 centry.ngroups = centry.nusers = htonl(20);
dba0cf81 361 }
5b723b3d 362
363 /* Admins don't get charged for creating a group.
364 * If in noAuth mode, you get changed for it but you
365 * are still allowed to create as many groups as you want.
366 */
367 admin = ( (creator == SYSADMINID) ||
368 IsAMemberOf(at,creator,SYSADMINID) );
369 if (!admin) {
370 if (ntohl(centry.ngroups) <= 0) {
371 if (!pr_noAuth) return PRNOMORE;
372 } else {
373 centry.ngroups = htonl(ntohl(centry.ngroups)-1);
374 }
375 }
376
dba0cf81 377 code = pr_Write (at, 0, loc, &centry, sizeof(centry));
378 if (code) return code;
379 } /* if (loc) */
5b723b3d 380 }
381 else {
382 /* Initialize the quota for the user. Groups don't have their
383 * quota initialized.
384 */
385 tentry.flags |= PRQUOTA;
386 tentry.ngroups = tentry.nusers = 20;
387 }
388
e1f001e5 389 tentry.creator = creator;
390 *aid = tentry.id;
e1f001e5 391 code = pr_WriteEntry(at, 0, newEntry, &tentry);
392 if (code) return PRDBFAIL;
393 code = AddToIDHash(at,*aid,newEntry);
394 if (code != PRSUCCESS) return code;
395 code = AddToNameHash(at,aname,newEntry);
396 if (code != PRSUCCESS) return code;
397 if (tentry.flags & PRGRP) {
398 code = AddToOwnerChain(at,tentry.id,oid);
399 if (code) return code;
400 }
401 if (tentry.flags & PRGRP) {
dba0cf81 402 if (inc_header_word (at, groupcount, 1)) return PRDBFAIL;
e1f001e5 403 }
e1f001e5 404 else if (tentry.flags & PRINST) {
dba0cf81 405 if (inc_header_word (at, instcount, 1)) return PRDBFAIL;
e1f001e5 406 }
407 else {
dba0cf81 408 if (inc_header_word (at, usercount, 1)) return PRDBFAIL;
e1f001e5 409 }
410 return PRSUCCESS;
411}
412
413
dba0cf81 414/* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
415 * entry if appropriate */
e1f001e5 416
5b723b3d 417afs_int32 RemoveFromEntry (at, aid, bid)
418 struct ubik_trans *at;
419 afs_int32 aid;
420 afs_int32 bid;
e1f001e5 421{
5b723b3d 422 afs_int32 code;
e1f001e5 423 struct prentry tentry;
424 struct contentry centry;
425 struct contentry hentry;
5b723b3d 426 afs_int32 temp;
427 afs_int32 i,j;
428 afs_int32 nptr;
429 afs_int32 hloc;
e1f001e5 430
dba0cf81 431 if (aid == bid) return PRINCONSISTENT;
5b723b3d 432 memset(&hentry, 0, sizeof(hentry));
e1f001e5 433 temp = FindByID(at,bid);
dba0cf81 434 if (temp == 0) return PRNOENT;
e1f001e5 435 code = pr_ReadEntry(at, 0, temp, &tentry);
436 if (code != 0) return code;
dba0cf81 437#ifdef PR_REMEMBER_TIMES
438 tentry.removeTime = time(0);
439#endif
e1f001e5 440 for (i=0;i<PRSIZE;i++) {
441 if (tentry.entries[i] == aid) {
442 tentry.entries[i] = PRBADID;
443 tentry.count--;
444 code = pr_WriteEntry(at,0,temp,&tentry);
445 if (code != 0) return code;
446 return PRSUCCESS;
447 }
448 if (tentry.entries[i] == 0) /* found end of list */
449 return PRNOENT;
450 }
dba0cf81 451 hloc = 0;
452 nptr = tentry.next;
5b723b3d 453 while (nptr != 0) {
dba0cf81 454 code = pr_ReadCoEntry(at,0,nptr,&centry);
455 if (code != 0) return code;
456 if ((centry.id != bid) || !(centry.flags & PRCONT)) return PRDBBAD;
457 for (i=0;i<COSIZE;i++) {
458 if (centry.entries[i] == aid) {
459 centry.entries[i] = PRBADID;
460 for (j=0;j<COSIZE;j++)
461 if (centry.entries[j] != PRBADID &&
462 centry.entries[j] != 0) break;
463 if (j == COSIZE) { /* can free this block */
464 if (hloc == 0) {
465 tentry.next = centry.next;
e1f001e5 466 }
dba0cf81 467 else {
468 hentry.next = centry.next;
469 code = pr_WriteCoEntry (at, 0, hloc, &hentry);
e1f001e5 470 if (code != 0) return code;
e1f001e5 471 }
dba0cf81 472 code = FreeBlock (at, nptr);
473 if (code) return code;
e1f001e5 474 }
dba0cf81 475 else { /* can't free it yet */
476 code = pr_WriteCoEntry(at,0,nptr,&centry);
477 if (code != 0) return code;
478 }
479 tentry.count--;
480 code = pr_WriteEntry(at,0,temp,&tentry);
481 if (code) return PRDBFAIL;
482 return 0;
e1f001e5 483 }
dba0cf81 484 if (centry.entries[i] == 0) return PRNOENT;
485 } /* for all coentry slots */
486 hloc = nptr;
487 nptr = centry.next;
5b723b3d 488 memcpy(&hentry, &centry, sizeof(centry));
dba0cf81 489 } /* while there are coentries */
490 return PRNOENT;
e1f001e5 491}
492
dba0cf81 493/* DeleteEntry - delete the entry in tentry at loc, removing it from all
494 * groups, putting groups owned by it on orphan chain, and freeing the space */
495
5b723b3d 496afs_int32 DeleteEntry (at, tentry, loc)
497 struct ubik_trans *at;
dba0cf81 498 struct prentry *tentry;
5b723b3d 499 afs_int32 loc;
e1f001e5 500{
5b723b3d 501 afs_int32 code;
e1f001e5 502 struct contentry centry;
5b723b3d 503 afs_int32 i;
504 afs_int32 nptr;
505
506 if (strchr(tentry->name,'@')) {
507 if (tentry->flags & PRGRP) {
508 /* If there are still foreign user accounts from that cell
509 don't delete the group */
510 if (tentry->count) return PRBADARG;
da0b4fd5 511 } else {
5b723b3d 512 /* adjust quota */
513
514 afs_int32 loc = FindByID (at, tentry->cellid);
515 struct prentry centry;
516 if (loc) {
517 code = pr_Read (at, 0, loc, &centry, sizeof(centry));
518 if (code) return code;
519 if (ntohl(centry.flags) & PRQUOTA) {
520 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
da0b4fd5 521 }
5b723b3d 522 code = pr_Write (at, 0, loc, &centry, sizeof(centry));
523 if (code) return code;
524 }
525 }
da0b4fd5 526 }
dba0cf81 527 /* First remove the entire membership list */
e1f001e5 528 for (i=0;i<PRSIZE;i++) {
dba0cf81 529 if (tentry->entries[i] == PRBADID) continue;
530 if (tentry->entries[i] == 0) break;
531 code = RemoveFromEntry (at, tentry->id, tentry->entries[i]);
532 if (code) return code;
e1f001e5 533 }
dba0cf81 534 nptr = tentry->next;
5b723b3d 535 while (nptr != (afs_int32)NULL) {
e1f001e5 536 code = pr_ReadCoEntry(at,0,nptr,&centry);
537 if (code != 0) return PRDBFAIL;
538 for (i=0;i<COSIZE;i++) {
dba0cf81 539 if (centry.entries[i] == PRBADID) continue;
e1f001e5 540 if (centry.entries[i] == 0) break;
dba0cf81 541 code = RemoveFromEntry (at, tentry->id, centry.entries[i]);
542 if (code) return code;
e1f001e5 543 }
dba0cf81 544 code = FreeBlock (at, nptr); /* free continuation block */
545 if (code) return code;
e1f001e5 546 nptr = centry.next;
547 }
dba0cf81 548
549 /* Remove us from other's owned chain. Note that this will zero our owned
550 * field (on disk) so this step must follow the above step in case we are
551 * on our own owned list. */
552 if (tentry->flags & PRGRP) {
553 if (tentry->owner) {
554 code = RemoveFromOwnerChain (at, tentry->id, tentry->owner);
e1f001e5 555 if (code) return code;
556 }
557 else {
dba0cf81 558 code = RemoveFromOrphan (at, tentry->id);
e1f001e5 559 if (code) return code;
560 }
561 }
dba0cf81 562
563 code = RemoveFromIDHash(at,tentry->id,&loc);
e1f001e5 564 if (code != PRSUCCESS) return code;
dba0cf81 565 code = RemoveFromNameHash(at,tentry->name,&loc);
e1f001e5 566 if (code != PRSUCCESS) return code;
dba0cf81 567
5b723b3d 568 if (tentry->flags & PRGRP) {
569 afs_int32 loc = FindByID(at, tentry->creator);
dba0cf81 570 struct prentry centry;
da0b4fd5 571 int admin;
5b723b3d 572
dba0cf81 573 if (loc) {
574 code = pr_Read (at, 0, loc, &centry, sizeof(centry));
575 if (code) return code;
5b723b3d 576 admin = ( (tentry->creator == SYSADMINID) ||
577 IsAMemberOf(at,tentry->creator,SYSADMINID) );
dba0cf81 578 if (ntohl(centry.flags) & PRQUOTA) {
5b723b3d 579 if (!(admin && (ntohl(centry.ngroups) >= 20))) {
dba0cf81 580 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
5b723b3d 581 }
dba0cf81 582 }
583 code = pr_Write (at, 0, loc, &centry, sizeof(centry));
584 if (code) return code;
585 }
e1f001e5 586 }
dba0cf81 587
588 if (tentry->flags & PRGRP) {
5b723b3d 589 if (inc_header_word (at, groupcount, -1)) return PRDBFAIL;
dba0cf81 590 }
591 else if (tentry->flags & PRINST) {
592 if (inc_header_word (at, instcount, -1)) return PRDBFAIL;
e1f001e5 593 }
594 else {
5b723b3d 595 if (strchr(tentry->name,'@')) {
596 if (inc_header_word (at, foreigncount, -1)) return PRDBFAIL;
597 } else {
598 if (inc_header_word (at, usercount, -1)) return PRDBFAIL;
599 }
e1f001e5 600 }
dba0cf81 601 code = FreeBlock(at, loc);
602 return code;
e1f001e5 603}
604
dba0cf81 605/* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
606 * if needed.
607 *
608 * Note the entry is written out by this routine. */
e1f001e5 609
5b723b3d 610afs_int32 AddToEntry (tt, entry, loc, aid)
dba0cf81 611 struct ubik_trans *tt;
612 struct prentry *entry;
5b723b3d 613 afs_int32 loc;
614 afs_int32 aid;
e1f001e5 615{
5b723b3d 616 afs_int32 code;
617 afs_int32 i;
e1f001e5 618 struct contentry nentry;
619 struct contentry aentry;
5b723b3d 620 afs_int32 nptr;
621 afs_int32 last; /* addr of last cont. block */
622 afs_int32 first = 0;
623 afs_int32 cloc = 0;
624 afs_int32 slot = -1;
e1f001e5 625
dba0cf81 626 if (entry->id == aid) return PRINCONSISTENT;
627#ifdef PR_REMEMBER_TIMES
628 entry->addTime = time(0);
629#endif
e1f001e5 630 for (i=0;i<PRSIZE;i++) {
dba0cf81 631 if (entry->entries[i] == aid)
e1f001e5 632 return PRIDEXIST;
dba0cf81 633 if (entry->entries[i] == PRBADID) { /* remember this spot */
e1f001e5 634 first = 1;
635 slot = i;
636 }
dba0cf81 637 else if (entry->entries[i] == 0) { /* end of the line */
e1f001e5 638 if (slot == -1) {
639 first = 1;
640 slot = i;
641 }
642 break;
643 }
644 }
dba0cf81 645 last = 0;
646 nptr = entry->next;
5b723b3d 647 while (nptr != (afs_int32)NULL) {
dba0cf81 648 code = pr_ReadCoEntry(tt,0,nptr,&nentry);
e1f001e5 649 if (code != 0) return code;
dba0cf81 650 last = nptr;
e1f001e5 651 if (!(nentry.flags & PRCONT)) return PRDBFAIL;
652 for (i=0;i<COSIZE;i++) {
653 if (nentry.entries[i] == aid)
654 return PRIDEXIST;
655 if (nentry.entries[i] == PRBADID) {
656 if (slot == -1) {
657 slot = i;
658 cloc = nptr;
659 }
660 }
dba0cf81 661 else if (nentry.entries[i] == 0) {
e1f001e5 662 if (slot == -1) {
663 slot = i;
664 cloc = nptr;
665 }
666 break;
667 }
668 }
e1f001e5 669 nptr = nentry.next;
670 }
dba0cf81 671 if (slot != -1) { /* we found a place */
672 entry->count++;
e1f001e5 673 if (first) { /* place is in first block */
dba0cf81 674 entry->entries[slot] = aid;
675 code = pr_WriteEntry (tt, 0, loc, entry);
e1f001e5 676 if (code != 0) return code;
677 return PRSUCCESS;
678 }
dba0cf81 679 code = pr_WriteEntry (tt, 0, loc, entry);
680 if (code) return code;
e1f001e5 681 code = pr_ReadCoEntry(tt,0,cloc,&aentry);
682 if (code != 0) return code;
683 aentry.entries[slot] = aid;
684 code = pr_WriteCoEntry(tt,0,cloc,&aentry);
685 if (code != 0) return code;
686 return PRSUCCESS;
687 }
688 /* have to allocate a continuation block if we got here */
689 nptr = AllocBlock(tt);
dba0cf81 690 if (last) {
691 /* then we should tack new block after last block in cont. chain */
e1f001e5 692 nentry.next = nptr;
693 code = pr_WriteCoEntry(tt,0,last,&nentry);
694 if (code != 0) return code;
695 }
696 else {
dba0cf81 697 entry->next = nptr;
e1f001e5 698 }
5b723b3d 699 memset(&aentry, 0, sizeof(aentry));
e1f001e5 700 aentry.flags |= PRCONT;
dba0cf81 701 aentry.id = entry->id;
5b723b3d 702 aentry.next = 0;
e1f001e5 703 aentry.entries[0] = aid;
704 code = pr_WriteCoEntry(tt,0,nptr,&aentry);
705 if (code != 0) return code;
706 /* don't forget to update count, here! */
dba0cf81 707 entry->count++;
708 code = pr_WriteEntry (tt, 0, loc, entry);
709 return code;
e1f001e5 710
711}
712
5b723b3d 713afs_int32 AddToPRList (alist, sizeP, id)
dba0cf81 714 prlist *alist;
715 int *sizeP;
5b723b3d 716 afs_int32 id;
dba0cf81 717{
5b723b3d 718 char *tmp;
719 int count;
720
dba0cf81 721 if (alist->prlist_len >= *sizeP) {
5b723b3d 722 count = alist->prlist_len + 100;
723 if (alist->prlist_val) {
724 tmp = (char *) realloc(alist->prlist_val, count*sizeof(afs_int32));
725 } else {
726 tmp = (char *) malloc(count*sizeof(afs_int32));
727 }
728 if (!tmp) return(PRNOMEM);
729 alist->prlist_val = (afs_int32 *)tmp;
730 *sizeP = count;
dba0cf81 731 }
732 alist->prlist_val[alist->prlist_len++] = id;
733 return 0;
734}
735
5b723b3d 736afs_int32 GetList (at, tentry, alist, add)
dba0cf81 737 struct ubik_trans *at;
738 struct prentry *tentry;
739 prlist *alist;
5b723b3d 740 afs_int32 add;
e1f001e5 741{
5b723b3d 742 afs_int32 code;
743 afs_int32 i;
e1f001e5 744 struct contentry centry;
5b723b3d 745 afs_int32 nptr;
dba0cf81 746 int size;
747 int count = 0;
e1f001e5 748
dba0cf81 749 size = 0;
750 alist->prlist_val = 0;
e1f001e5 751 alist->prlist_len = 0;
dba0cf81 752
e1f001e5 753 for (i=0;i<PRSIZE;i++) {
dba0cf81 754 if (tentry->entries[i] == PRBADID) continue;
755 if (tentry->entries[i] == 0) break;
756 code = AddToPRList (alist, &size, tentry->entries[i]);
757 if (code) return code;
e1f001e5 758 }
dba0cf81 759
5b723b3d 760 for (nptr = tentry->next; nptr != 0; nptr = centry.next) {
e1f001e5 761 /* look through cont entries */
762 code = pr_ReadCoEntry(at,0,nptr,&centry);
763 if (code != 0) return code;
764 for (i=0;i<COSIZE;i++) {
765 if (centry.entries[i] == PRBADID) continue;
766 if (centry.entries[i] == 0) break;
dba0cf81 767 code = AddToPRList (alist, &size, centry.entries[i]);
768 if (code) return code;
e1f001e5 769 }
dba0cf81 770 if (count++ > 50) IOMGR_Poll(), count = 0;
e1f001e5 771 }
dba0cf81 772
e1f001e5 773 if (add) { /* this is for a CPS, so tack on appropriate stuff */
dba0cf81 774 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
da0b4fd5 775 if ((code = AddToPRList (alist, &size, ANYUSERID)) ||
5b723b3d 776 (code = AddAuthGroup(tentry, alist, &size)) ||
da0b4fd5 777 (code = AddToPRList (alist, &size, tentry->id))) return code;
5b723b3d 778 }
779 else {
780 if ((code = AddToPRList (alist, &size, ANYUSERID)) ||
781 (code = AddToPRList (alist, &size, tentry->id))) return code;
782 }
783 }
784 if (alist->prlist_len > 100) IOMGR_Poll();
785 qsort(alist->prlist_val,alist->prlist_len,sizeof(afs_int32),IDCmp);
786 return PRSUCCESS;
787}
788
789
790afs_int32 GetList2 (at, tentry, tentry2 , alist, add)
791 struct ubik_trans *at;
792 struct prentry *tentry;
793 struct prentry *tentry2;
794 prlist *alist;
795 afs_int32 add;
796{
797 afs_int32 code = 0;
798 afs_int32 i;
799 struct contentry centry;
800 afs_int32 nptr;
801 afs_int32 size;
802 int count = 0;
803
804 size = 0;
805 alist->prlist_val = 0;
806 alist->prlist_len = 0;
807 for (i=0;i<PRSIZE;i++) {
808 if (tentry->entries[i] == PRBADID) continue;
809 if (tentry->entries[i] == 0) break;
810 code = AddToPRList (alist, &size, tentry->entries[i]);
811 if (code) return code;
812 }
813
814 nptr = tentry->next;
815 while (nptr != (afs_uint32)NULL) {
816 /* look through cont entries */
817 code = pr_ReadCoEntry(at,0,nptr,&centry);
818 if (code != 0) return code;
819 for (i=0;i<COSIZE;i++) {
820 if (centry.entries[i] == PRBADID) continue;
821 if (centry.entries[i] == 0) break;
822 code = AddToPRList (alist, &size, centry.entries[i]);
823 if (code) return code;
824 }
825 nptr = centry.next;
826 if (count++ > 50) IOMGR_Poll(), count = 0;
827 }
828
829 for (i=0;i<PRSIZE;i++) {
830 if (tentry2->entries[i] == PRBADID) continue;
831 if (tentry2->entries[i] == 0) break;
832 code = AddToPRList (alist, &size, tentry2->entries[i]);
833 if (code) break;
834 }
835
836 if (!code) {
837 nptr = tentry2->next;
838 while (nptr != (afs_uint32)NULL) {
839 /* look through cont entries */
840 code = pr_ReadCoEntry(at,0,nptr,&centry);
841 if (code != 0) break;
842 for (i=0;i<COSIZE;i++) {
843 if (centry.entries[i] == PRBADID) continue;
844 if (centry.entries[i] == 0) break;
845 code = AddToPRList (alist, &size, centry.entries[i]);
846 if (code) break;
847 }
848 nptr = centry.next;
849 if (count++ > 50) IOMGR_Poll(), count = 0;
850 }
851 }
852 if (add) { /* this is for a CPS, so tack on appropriate stuff */
853 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
dba0cf81 854 if ((code = AddToPRList (alist, &size, ANYUSERID)) ||
855 (code = AddToPRList (alist, &size, AUTHUSERID)) ||
856 (code = AddToPRList (alist, &size, tentry->id))) return code;
e1f001e5 857 }
858 else {
dba0cf81 859 if ((code = AddToPRList (alist, &size, ANYUSERID)) ||
860 (code = AddToPRList (alist, &size, tentry->id))) return code;
e1f001e5 861 }
862 }
dba0cf81 863 if (alist->prlist_len > 100) IOMGR_Poll();
5b723b3d 864 qsort(alist->prlist_val,alist->prlist_len,sizeof(afs_int32),IDCmp);
dba0cf81 865 return PRSUCCESS;
866}
867
5b723b3d 868afs_int32 GetOwnedChain (ut, next, alist)
dba0cf81 869 struct ubik_trans *ut;
5b723b3d 870 afs_int32 *next;
dba0cf81 871 prlist *alist;
5b723b3d 872{ afs_int32 code;
dba0cf81 873 struct prentry tentry;
874 int size;
875 int count = 0;
876
877 size = 0;
878 alist->prlist_val = 0;
879 alist->prlist_len = 0;
880
5b723b3d 881 for (; *next; *next = ntohl(tentry.nextOwned)) {
882 code = pr_Read (ut, 0, *next, &tentry, sizeof(tentry));
dba0cf81 883 if (code) return code;
884 code = AddToPRList (alist, &size, ntohl(tentry.id));
5b723b3d 885 if (alist->prlist_len >= PR_MAXGROUPS) {
886 return PRTOOMANY;
887 }
dba0cf81 888 if (code) return code;
dba0cf81 889 if (count++ > 50) IOMGR_Poll(), count = 0;
890 }
891 if (alist->prlist_len > 100) IOMGR_Poll();
5b723b3d 892 qsort(alist->prlist_val,alist->prlist_len,sizeof(afs_int32),IDCmp);
e1f001e5 893 return PRSUCCESS;
894}
895
5b723b3d 896afs_int32 GetMax(at,uid,gid)
897struct ubik_trans *at;
898afs_int32 *uid;
899afs_int32 *gid;
e1f001e5 900{
901 *uid = ntohl(cheader.maxID);
902 *gid = ntohl(cheader.maxGroup);
903 return PRSUCCESS;
904}
905
5b723b3d 906afs_int32 SetMax(at,id,flag)
907struct ubik_trans *at;
908afs_int32 id;
909afs_int32 flag;
e1f001e5 910{
5b723b3d 911 afs_int32 code;
e1f001e5 912 if (flag & PRGRP) {
913 cheader.maxGroup = htonl(id);
914 code = pr_Write(at,0,16,(char *)&cheader.maxGroup,sizeof(cheader.maxGroup));
915 if (code != 0) return code;
916 }
917 else {
918 cheader.maxID = htonl(id);
919 code = pr_Write(at,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
920 if (code != 0) return code;
921 }
922 return PRSUCCESS;
923}
924
5b723b3d 925afs_int32 read_DbHeader(tt)
926 struct ubik_trans *tt;
927{
928 afs_int32 code;
929
930 if (!ubik_CacheUpdate(tt)) return 0;
931
932 code = pr_Read(tt, 0, 0, (char *)&cheader, sizeof(cheader));
933 if (code != 0) {
934 com_err (whoami, code, "Couldn't read header");
935 }
936 return code;
937}
938
dba0cf81 939int pr_noAuth;
5b723b3d 940afs_int32 initd=0;
dba0cf81 941
5b723b3d 942afs_int32 Initdb()
e1f001e5 943{
5b723b3d 944 afs_int32 code;
e1f001e5 945 struct ubik_trans *tt;
5b723b3d 946 afs_int32 len;
e1f001e5 947
5b723b3d 948 /* init the database. We'll try reading it, but if we're starting
949 * from scratch, we'll have to do a write transaction. */
e1f001e5 950
dba0cf81 951 pr_noAuth = afsconf_GetNoAuthFlag(prdir);
952
da0b4fd5 953 code = ubik_BeginTransReadAny(dbase,UBIK_READTRANS, &tt);
e1f001e5 954 if (code) return code;
955 code = ubik_SetLock(tt,1,1,LOCKREAD);
956 if (code) {
957 ubik_AbortTrans(tt);
958 return code;
959 }
960 if (!initd) {
961 initd = 1;
dba0cf81 962 } else if (!ubik_CacheUpdate (tt)) {
963 code = ubik_EndTrans(tt);
964 return code;
965 }
dba0cf81 966
e1f001e5 967 len = sizeof(cheader);
968 code = pr_Read(tt, 0, 0, (char *) &cheader, len);
969 if (code != 0) {
dba0cf81 970 com_err (whoami, code, "couldn't read header");
e1f001e5 971 ubik_AbortTrans(tt);
972 return code;
973 }
dba0cf81 974 if ((ntohl(cheader.version) == PRDBVERSION) &&
975 ntohl(cheader.headerSize) == sizeof(cheader) &&
5b723b3d 976 ntohl(cheader.eofPtr) != (afs_uint32)NULL &&
dba0cf81 977 FindByID(tt,ANONYMOUSID) != 0){
e1f001e5 978 /* database exists, so we don't have to build it */
979 code = ubik_EndTrans(tt);
980 if (code) return code;
981 return PRSUCCESS;
982 }
983 /* else we need to build a database */
984 code = ubik_EndTrans(tt);
985 if (code) return code;
dba0cf81 986
987 /* Only rebuild database if the db was deleted (the header is zero) and we
988 are running noAuth. */
989 { char *bp = (char *)&cheader;
990 int i;
991 for (i=0; i<sizeof(cheader); i++)
992 if (bp[i]) {
993 code = PRDBBAD;
994 com_err (whoami, code,
995 "Can't rebuild database because it is not empty");
996 return code;
997 }
998 }
999 if (!pr_noAuth) {
1000 code = PRDBBAD;
1001 com_err (whoami, code,
1002 "Can't rebuild database because not running NoAuth");
1003 return code;
1004 }
1005
e1f001e5 1006 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS, &tt);
1007 if (code) return code;
da0b4fd5 1008
e1f001e5 1009 code = ubik_SetLock(tt,1,1,LOCKWRITE);
1010 if (code) {
1011 ubik_AbortTrans(tt);
1012 return code;
1013 }
dba0cf81 1014
da0b4fd5 1015 /* before doing a rebuild, check again that the dbase looks bad, because
1016 * the previous check was only under a ReadAny transaction, and there could
1017 * actually have been a good database out there. Now that we have a
1018 * real write transaction, make sure things are still bad.
1019 */
1020 if ((ntohl(cheader.version) == PRDBVERSION) &&
1021 ntohl(cheader.headerSize) == sizeof(cheader) &&
5b723b3d 1022 ntohl(cheader.eofPtr) != (afs_uint32)NULL &&
da0b4fd5 1023 FindByID(tt,ANONYMOUSID) != 0){
1024 /* database exists, so we don't have to build it */
1025 code = ubik_EndTrans(tt);
1026 if (code) return code;
1027 return PRSUCCESS;
1028 }
dba0cf81 1029
da0b4fd5 1030 /* Initialize the database header */
dba0cf81 1031 if ((code = set_header_word (tt, version, htonl(PRDBVERSION))) ||
1032 (code = set_header_word (tt, headerSize, htonl(sizeof(cheader)))) ||
1033 (code = set_header_word (tt, eofPtr, cheader.headerSize))) {
1034 com_err (whoami, code, "couldn't write header words");
e1f001e5 1035 ubik_AbortTrans(tt);
1036 return code;
1037 }
dba0cf81 1038
1039#define InitialGroup(id,name) do { \
5b723b3d 1040 afs_int32 temp = (id); \
1041 afs_int32 flag = (id) < 0 ? PRGRP : 0; \
dba0cf81 1042 code = CreateEntry \
1043 (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
1044 if (code) { \
1045 com_err (whoami, code, "couldn't create %s with id %di.", \
1046 (name), (id)); \
1047 ubik_AbortTrans(tt); \
1048 return code; \
1049 } \
1050} while (0)
1051
1052 InitialGroup (SYSADMINID, "system:administrators");
5b723b3d 1053 InitialGroup (SYSBACKUPID, "system:backup");
dba0cf81 1054 InitialGroup (ANYUSERID, "system:anyuser");
1055 InitialGroup (AUTHUSERID, "system:authuser");
5b723b3d 1056 InitialGroup (SYSVIEWERID, "system:ptsviewers");
dba0cf81 1057 InitialGroup (ANONYMOUSID, "anonymous");
1058
1059 /* Well, we don't really want the max id set to anonymousid, so we'll set
1060 * it back to 0 */
1061 code = set_header_word (tt, maxID, 0); /* correct in any byte order */
1062 if (code) {
1063 com_err (whoami, code, "couldn't reset max id");
e1f001e5 1064 ubik_AbortTrans(tt);
1065 return code;
1066 }
dba0cf81 1067
e1f001e5 1068 code = ubik_EndTrans(tt);
1069 if (code) return code;
1070 return PRSUCCESS;
1071}
1072
5b723b3d 1073afs_int32 ChangeEntry (at, aid, cid, name, oid, newid)
dba0cf81 1074 struct ubik_trans *at;
5b723b3d 1075 afs_int32 aid;
1076 afs_int32 cid;
dba0cf81 1077 char *name;
5b723b3d 1078 afs_int32 oid;
1079 afs_int32 newid;
e1f001e5 1080{
5b723b3d 1081 afs_int32 code;
1082 afs_int32 i, nptr, pos;
2ba81a31 1083 struct contentry centry;
5b723b3d 1084 struct prentry tentry, tent;
1085 afs_int32 loc;
1086 afs_int32 oldowner;
e1f001e5 1087 char holder[PR_MAXNAMELEN];
1088 char temp[PR_MAXNAMELEN];
dba0cf81 1089 char oldname[PR_MAXNAMELEN];
da0b4fd5 1090 char *atsign;
e1f001e5 1091
5b723b3d 1092 memset(holder, 0, PR_MAXNAMELEN);
1093 memset(temp, 0, PR_MAXNAMELEN);
e1f001e5 1094 loc = FindByID(at,aid);
1095 if (!loc) return PRNOENT;
1096 code = pr_ReadEntry(at,0,loc,&tentry);
1097 if (code) return PRDBFAIL;
dba0cf81 1098 if (tentry.owner != cid &&
1099 !IsAMemberOf(at,cid,SYSADMINID) &&
1100 !IsAMemberOf(at,cid,tentry.owner) &&
1101 !pr_noAuth) return PRPERM;
1102#ifdef PR_REMEMBER_TIMES
1103 tentry.changeTime = time(0);
1104#endif
1105
1106 /* we're actually trying to change the id */
5b723b3d 1107 if (newid && (newid != aid)) {
dba0cf81 1108 if (!IsAMemberOf(at,cid,SYSADMINID) && !pr_noAuth) return PRPERM;
5b723b3d 1109
e1f001e5 1110 pos = FindByID(at,newid);
1111 if (pos) return PRIDEXIST; /* new id already in use! */
da0b4fd5 1112 if ((aid < 0 && newid > 0) || (aid > 0 && newid < 0)) return PRPERM;
5b723b3d 1113
1114 /* Should check that foreign users id to change to is good: inRange() */
1115
e1f001e5 1116 /* if new id is not in use, rehash things */
1117 code = RemoveFromIDHash(at,aid,&loc);
1118 if (code != PRSUCCESS) return code;
1119 tentry.id = newid;
1120 code = pr_WriteEntry(at,0,loc,&tentry);
dba0cf81 1121 if (code) return code;
e1f001e5 1122 code = AddToIDHash(at,tentry.id,loc);
1123 if (code) return code;
5b723b3d 1124
dba0cf81 1125 /* get current data */
5b723b3d 1126 code = pr_ReadEntry(at, 0, loc, &tentry);
dba0cf81 1127 if (code) return PRDBFAIL;
2ba81a31 1128
5b723b3d 1129 /* Also change the references from the membership list */
1130 for (i=0; i<PRSIZE; i++) {
1131 if (tentry.entries[i] == PRBADID) continue;
1132 if (tentry.entries[i] == 0) break;
1133 pos = FindByID(at, tentry.entries[i]);
1134 if (!pos) return(PRDBFAIL);
1135 code = RemoveFromEntry(at, aid, tentry.entries[i]);
1136 if (code) return code;
1137 code = pr_ReadEntry(at, 0, pos, &tent);
1138 if (code) return code;
1139 code = AddToEntry(at, &tent, pos, newid);
1140 if (code) return code;
2ba81a31 1141 }
5b723b3d 1142 /* Look through cont entries too. This needs to be broken into
1143 * seperate transaction so that no one transaction becomes too
1144 * large to complete.
1145 */
1146 for (nptr=tentry.next; nptr; nptr=centry.next) {
1147 code = pr_ReadCoEntry(at, 0, nptr, &centry);
1148 if (code) return code;
1149 for (i=0; i<COSIZE; i++) {
1150 if (centry.entries[i] == PRBADID) continue;
1151 if (centry.entries[i] == 0) break;
1152 pos = FindByID(at, centry.entries[i]);
1153 if (!pos) return(PRDBFAIL);
1154 code = RemoveFromEntry(at, aid, centry.entries[i]);
1155 if (code) return code;
1156 code = pr_ReadEntry(at, 0, pos, &tent);
1157 if (code) return code;
1158 code = AddToEntry(at, &tent, pos, newid);
1159 if (code) return code;
1160 }
1161 }
e1f001e5 1162 }
dba0cf81 1163
5b723b3d 1164 atsign = strchr(tentry.name, '@'); /* check for foreign entry */
da0b4fd5 1165
dba0cf81 1166 /* Change the owner */
5b723b3d 1167 if (oid && (oid != tentry.owner)) {
dba0cf81 1168 /* only groups can have their owner's changed */
1169 if (!(tentry.flags & PRGRP)) return PRPERM;
5b723b3d 1170 if (atsign != NULL) return PRPERM;
dba0cf81 1171 oldowner = tentry.owner;
1172 tentry.owner = oid;
1173 /* The entry must be written through first so Remove and Add routines
1174 * can operate on disk data */
1175 code = pr_WriteEntry(at,0,loc,(char *)&tentry);
1176 if (code) return PRDBFAIL;
5b723b3d 1177
1178 /* switch owner chains */
1179 if (oldowner) /* if it has an owner */
1180 code = RemoveFromOwnerChain(at,tentry.id,oldowner);
1181 else /* must be an orphan */
1182 code = RemoveFromOrphan(at,tentry.id);
1183 if (code) return code;
1184 code = AddToOwnerChain(at,tentry.id,tentry.owner);
1185 if (code) return code;
1186
dba0cf81 1187 /* fix up the name */
5b723b3d 1188 if (strlen(name) == 0) name = tentry.name;
dba0cf81 1189 /* get current data */
1190 code = pr_ReadEntry(at,0,loc,&tentry);
e1f001e5 1191 if (code) return PRDBFAIL;
1192 }
dba0cf81 1193
1194 /* Change the name, if name is a ptr to tentry.name then this name change
1195 * is due to a chown, otherwise caller has specified a new name */
1196 if ((name == tentry.name) ||
1197 (*name && (strcmp (tentry.name, name) != 0))) {
1198 strncpy (oldname, tentry.name, PR_MAXNAMELEN);
e1f001e5 1199 if (tentry.flags & PRGRP) {
5b723b3d 1200 /* don't let foreign cell groups change name */
1201 if (atsign != NULL) return PRPERM;
dba0cf81 1202 code = CorrectGroupName (at, name, cid, tentry.owner, tentry.name);
1203 if (code) return code;
1204
1205 if (name == tentry.name) { /* owner fixup */
1206 if (strcmp (oldname, tentry.name) == 0) goto nameOK;
1207 } else { /* new name, caller must be correct */
1208 if (strcmp (name, tentry.name) != 0) return PRBADNAM;
1209 }
5b723b3d 1210 }
1211 else
1212 /* Allow a foreign name change only if the cellname part is
1213 the same */
1214 {
da0b4fd5 1215 char *newatsign;
1216
5b723b3d 1217 newatsign = strchr(name, '@');
1218 if (newatsign != atsign){ /* if they are the same no problem*/
1219 /*if the pointers are not equal the strings better be */
1220 if ((atsign == NULL) || (newatsign == NULL) ||
1221 strcmp (atsign,newatsign)) return PRPERM;
1222 }
1223 if (!CorrectUserName(name)) return PRBADNAM;
1224 }
dba0cf81 1225
5b723b3d 1226 pos = FindByName(at,name, &tent);
e1f001e5 1227 if (pos) return PREXIST;
dba0cf81 1228 code = RemoveFromNameHash (at, oldname, &loc);
e1f001e5 1229 if (code != PRSUCCESS) return code;
dba0cf81 1230 strncpy (tentry.name, name, PR_MAXNAMELEN);
1231 code = pr_WriteEntry(at,0,loc,(char *)&tentry);
e1f001e5 1232 if (code) return PRDBFAIL;
1233 code = AddToNameHash(at,tentry.name,loc);
1234 if (code != PRSUCCESS) return code;
dba0cf81 1235nameOK:;
e1f001e5 1236 }
5b723b3d 1237 return PRSUCCESS;
e1f001e5 1238}
da0b4fd5 1239
5b723b3d 1240
1241afs_int32 allocNextId(cellEntry)
1242 struct prentry *cellEntry;
da0b4fd5 1243{
5b723b3d 1244 /* Id's for foreign cell entries are constructed as follows:
1245 The 16 low order bits are the group id of the cell and the
1246 top 16 bits identify the particular users in that cell */
1247
1248 afs_int32 id;
1249
1250
1251 id = (ntohl(cellEntry -> nusers) +1);
1252 cellEntry->nusers = htonl(id);
1253 /* use the field nusers to keep
1254 the next available id in that
1255 foreign cell's group. Note :
1256 It would seem more appropriate
1257 to use ngroup for that and nusers
1258 to enforce the quota, however pts
1259 does not have an option to change
1260 foreign users quota yet */
1261
1262 id = (id << 16) | ((ntohl(cellEntry-> id)) & 0x0000ffff);
1263 return id;
da0b4fd5 1264}
1265
1266int inRange(cellEntry,aid)
1267struct prentry *cellEntry;
5b723b3d 1268afs_int32 aid;
da0b4fd5 1269{
5b723b3d 1270 afs_uint32 id,cellid,groupid;
1271
1272
1273 /*
1274 The only thing that we want to make sure here is that
1275 the id is in the legal range of this group. If it is
1276 a duplicate we don't care since it will get caught
1277 in a different check.
1278 */
1279
1280 cellid = aid & 0x0000ffff;
1281 groupid = (ntohl(cellEntry-> id)) & 0x0000ffff;
1282 if (cellid != groupid) return 0; /* not in range */
1283
1284 /*
1285 if we got here we're ok but we need to update the nusers
1286 field in order to get the id correct the next time that
1287 we try to allocate it automatically
1288 */
1289
1290 id = aid >> 16;
1291 if (id > ntohl(cellEntry -> nusers))
1292 cellEntry -> nusers = htonl(id);
1293 return 1;
1294
da0b4fd5 1295}
1296
1297AddAuthGroup(tentry, alist, size)
5b723b3d 1298 struct prentry *tentry;
1299 prlist *alist;
1300 afs_int32 *size;
da0b4fd5 1301{
5b723b3d 1302 if (!(strchr(tentry->name, '@')))
1303 return (AddToPRList (alist, size, AUTHUSERID));
1304 else
1305 return PRSUCCESS;
da0b4fd5 1306}
This page took 0.295112 seconds and 5 git commands to generate.