]> andersk Git - moira.git/blame - afssync/ptutils.c
from Richard
[moira.git] / afssync / ptutils.c
CommitLineData
dba0cf81 1/* Copyright (C) 1989 Transarc Corporation - All rights reserved */
e1f001e5 2/*
3 * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1988
4 * LICENSED MATERIALS - PROPERTY OF IBM
5 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
6 */
7
dba0cf81 8#ifndef lint
9static char rcsid[] = "$Header$";
10#endif
11
e1f001e5 12/*
13 Sherri Nichols
14 Information Technology Center
15 November, 1988
16
17 Modified May, 1989 by Jeff Schiller to keep disk file in
18 network byte order
19
20*/
21
dba0cf81 22#include <afs/param.h>
23#include <sys/types.h>
e1f001e5 24#include <stdio.h>
e1f001e5 25#include <lock.h>
dba0cf81 26#include <netinet/in.h>
e1f001e5 27#include <ubik.h>
28#include <rx/xdr.h>
dba0cf81 29#include <afs/com_err.h>
30#include "ptserver.h"
31#include "pterror.h"
32#include <strings.h>
e1f001e5 33
e1f001e5 34extern struct ubik_dbase *dbase;
35extern struct afsconf_dir *prdir;
dba0cf81 36extern int pr_noAuth;
e1f001e5 37
dba0cf81 38static char *whoami = "ptserver";
39
40/* CorrectUserName - Check to make sure a user name is OK. It must not include
41 * either a colon (or it would look like a group) or an atsign (or it would
42 * look like a foreign user). The length is checked as well to make sure
43 * that the user name, an atsign, and the local cell name will fit in
44 * PR_MAXNAMELEN. This is so this user can fit in another cells database as
45 * a foreign user with our cell name tacked on. This is a predicate, so it
46 * return one if name is OK and zero if name is bogus. */
47
48static int CorrectUserName (name)
49 char *name;
50{
51 extern int pr_realmNameLen;
52
53 if (index (name, ':') || index(name, '@') || index(name, '\n')) return 0;
54 if (strlen (name) >= PR_MAXNAMELEN - pr_realmNameLen - 1) return 0;
55 return 1;
56}
57
58static long CorrectGroupName (ut, aname, cid, oid, cname)
59 struct ubik_trans *ut;
60 char aname[PR_MAXNAMELEN]; /* name for group */
61 long cid; /* caller id */
62 long oid; /* owner of group */
63 char cname[PR_MAXNAMELEN]; /* correct name for group */
64{
65 long code;
66 int admin;
67 char *prefix; /* ptr to group owner part */
68 char *suffix; /* ptr to group name part */
69 char name[PR_MAXNAMELEN]; /* correct name for group */
70 struct prentry tentry;
71
72 if (strlen (aname) >= PR_MAXNAMELEN) return PRBADNAM;
73 admin = pr_noAuth || IsAMemberOf (ut, cid, SYSADMINID);
74
75 if (oid == 0) oid = cid;
76
77 /* Determine the correct prefix for the name. */
78 if (oid == SYSADMINID) prefix = "system";
79 else {
80 long loc = FindByID (ut, oid);
81 if (loc == 0) {
82 /* let admin create groups owned by non-existent ids (probably
83 * setting a group to own itself). Check that they look like
84 * groups (with a colon) or otherwise are good user names. */
85 if (admin) {
86 strcpy (cname, aname);
87 goto done;
88 }
89 return PRNOENT;
90 }
91 code = pr_Read (ut, 0, loc, &tentry, sizeof(tentry));
92 if (code) return code;
93 if (ntohl(tentry.flags) & PRGRP) {
94 if ((tentry.count == 0) && !admin) return PRGROUPEMPTY;
95 /* terminate prefix at colon if there is one */
96 if (prefix = index(tentry.name, ':')) *prefix = 0;
97 }
98 prefix = tentry.name;
99 }
100 /* only sysadmin allow to use 'system:' prefix */
101 if ((strcmp (prefix, "system") == 0) && !admin) return PRPERM;
102
103 strcpy (name, aname); /* in case aname & cname are same */
104 suffix = index(name, ':');
105 if (suffix == 0) {
106 /* sysadmin can make groups w/o ':', but they must still look like
107 * legal user names. */
108 if (!admin) return PRBADNAM;
109 strcpy (cname, name);
110 }
111 else {
112 if (strlen(prefix)+strlen(suffix) >= PR_MAXNAMELEN) return PRBADNAM;
113 strcpy (cname, prefix);
114 strcat (cname, suffix);
115 }
116 done:
117 /* check for legal name with either group rules or user rules */
118 if (suffix = index(cname, ':')) {
119 /* check for confusing characters */
120 if (index(cname, '@') || /* avoid confusion w/ foreign users */
121 index(cname, '\n') || /* restrict so recreate can work */
122 index(suffix+1, ':')) /* avoid multiple colons */
123 return PRBADNAM;
124 } else {
125 if (!CorrectUserName (cname)) return PRBADNAM;
126 }
127 return 0;
128}
129
130int AccessOK (ut, cid, tentry, mem, any)
131 struct ubik_trans *ut;
132 long cid; /* caller id */
133 struct prentry *tentry; /* object being accessed */
134 int mem; /* check membership in aid, if group */
135 int any; /* if set return true */
136{ long flags;
137 long oid;
138 long aid;
139
140 if (pr_noAuth) return 1;
141 if (tentry) {
142 flags = tentry->flags;
143 oid = tentry->owner;
144 aid = tentry->id;
145 } else {
146 flags = oid = aid = 0;
147 }
148 if (!(flags & PRACCESS)) /* provide default access */
149 if (flags & PRGRP)
150 flags |= PRP_GROUP_DEFAULT;
151 else
152 flags |= PRP_USER_DEFAULT;
153
154 if (flags & any) return 1;
155 if (oid) {
156 if ((cid == oid) ||
157 IsAMemberOf (ut, cid, oid)) return 1;
158 }
159 if (aid > 0) { /* checking on a user */
160 if (aid == cid) return 1;
161 } else if (aid < 0) { /* checking on group */
162 if ((flags & mem) && IsAMemberOf (ut, cid, aid)) return 1;
163 }
164 if (IsAMemberOf (ut, cid, SYSADMINID)) return 1;
165 return 0; /* no access */
166}
167
168long CreateEntry (at, aname, aid, idflag, flag, oid, creator)
169 register struct ubik_trans *at;
170 char aname[PR_MAXNAMELEN];
171 long *aid;
172 long idflag;
173 long flag;
174 long oid;
175 long creator;
e1f001e5 176{
177 /* get and init a new entry */
178 register long code;
179 long newEntry;
180 long temp;
181 struct prentry tentry;
182
183 bzero(&tentry, sizeof(tentry));
dba0cf81 184
185 if ((oid == 0) || (oid == ANONYMOUSID)) oid = creator;
186
187 if (flag & PRGRP) {
188 code = CorrectGroupName (at, aname, creator, oid, tentry.name);
189 if (code) return code;
190 if (strcmp (aname, tentry.name) != 0) return PRBADNAM;
191 } else { /* non-group must not have colon */
192 if (!CorrectUserName(aname)) return PRBADNAM;
193 strcpy (tentry.name, aname);
194 }
195
196 if (FindByName(at,aname)) return PREXIST;
197
e1f001e5 198 newEntry = AllocBlock(at);
199 if (!newEntry) return PRDBFAIL;
dba0cf81 200#ifdef PR_REMEMBER_TIMES
201 tentry.createTime = time(0);
202#endif
e1f001e5 203 if (flag & PRGRP) {
204 tentry.flags |= PRGRP;
205 tentry.owner = oid;
206 }
207 else if (flag & PRFOREIGN) {
208 tentry.flags |= PRFOREIGN;
209 tentry.owner = oid;
210 }
211 else tentry.owner = SYSADMINID;
212 if (idflag)
213 tentry.id = *aid;
214 else {
215 code= AllocID(at,flag,&tentry.id);
216 if (code != PRSUCCESS) return code;
217 }
218 if (flag & PRGRP) {
dba0cf81 219 /* group ids are negative */
220 if (tentry.id < (long)ntohl(cheader.maxGroup)) {
221 code = set_header_word (at, maxGroup, htonl(tentry.id));
e1f001e5 222 if (code) return PRDBFAIL;
223 }
224 }
225 else if (flag & PRFOREIGN) {
dba0cf81 226 if (tentry.id > (long)ntohl(cheader.maxForeign)) {
227 code = set_header_word (at, maxForeign, htonl(tentry.id));
e1f001e5 228 if (code) return PRDBFAIL;
229 }
230 }
231 else {
dba0cf81 232 if (tentry.id > (long)ntohl(cheader.maxID)) {
233 code = set_header_word (at, maxID, htonl(tentry.id));
e1f001e5 234 if (code) return PRDBFAIL;
235 }
236 }
dba0cf81 237 /* PRACCESS is off until set, defaults provided in AccessOK */
238 if (flag == 0) { /* only normal users get quota */
239 tentry.flags |= PRQUOTA;
240 tentry.ngroups = tentry.nusers = 20;
241 }
242
243 if (flag & (PRGRP | PRFOREIGN)) {
244 long loc = FindByID (at, creator);
245 struct prentry centry;
246 long *nP; /* ptr to entry to be decremented */
247 long n; /* quota to check */
248
249 if (loc) { /* this should only fail during initialization */
250 code = pr_Read (at, 0, loc, &centry, sizeof(centry));
251 if (code) return code;
252
253 if (flag & PRGRP) nP = &centry.ngroups;
254 else if (flag & PRFOREIGN) nP = &centry.nusers;
255 else nP = 0;
256
257 if (nP) {
258 if (!(ntohl(centry.flags) & PRQUOTA)) {
259 /* quota uninitialized, so do it now */
260 centry.flags = htonl (ntohl(centry.flags) | PRQUOTA);
261 centry.ngroups = centry.nusers = htonl(20);
262 }
263 n = ntohl(*nP);
264 if (n <= 0) {
265 if (!pr_noAuth &&
266 !IsAMemberOf (at, creator, SYSADMINID))
267 return PRNOMORE;
268 }
269 else *nP = htonl(n-1);
270 }
271 code = pr_Write (at, 0, loc, &centry, sizeof(centry));
272 if (code) return code;
273 } /* if (loc) */
274 } /* need to check creation quota */
e1f001e5 275 tentry.creator = creator;
276 *aid = tentry.id;
e1f001e5 277 code = pr_WriteEntry(at, 0, newEntry, &tentry);
278 if (code) return PRDBFAIL;
279 code = AddToIDHash(at,*aid,newEntry);
280 if (code != PRSUCCESS) return code;
281 code = AddToNameHash(at,aname,newEntry);
282 if (code != PRSUCCESS) return code;
283 if (tentry.flags & PRGRP) {
284 code = AddToOwnerChain(at,tentry.id,oid);
285 if (code) return code;
286 }
287 if (tentry.flags & PRGRP) {
dba0cf81 288 if (inc_header_word (at, groupcount, 1)) return PRDBFAIL;
e1f001e5 289 }
290 else if (tentry.flags & PRFOREIGN) {
dba0cf81 291 if (inc_header_word (at, foreigncount, 1)) return PRDBFAIL;
e1f001e5 292 }
293 else if (tentry.flags & PRINST) {
dba0cf81 294 if (inc_header_word (at, instcount, 1)) return PRDBFAIL;
e1f001e5 295 }
296 else {
dba0cf81 297 if (inc_header_word (at, usercount, 1)) return PRDBFAIL;
e1f001e5 298 }
299 return PRSUCCESS;
300}
301
302
dba0cf81 303/* RemoveFromEntry - remove aid from bid's entries list, freeing a continuation
304 * entry if appropriate */
e1f001e5 305
dba0cf81 306long RemoveFromEntry (at, aid, bid)
307 register struct ubik_trans *at;
308 register long aid;
309 register long bid;
e1f001e5 310{
e1f001e5 311 register long code;
312 struct prentry tentry;
313 struct contentry centry;
314 struct contentry hentry;
315 long temp;
e1f001e5 316 long i,j;
317 long nptr;
dba0cf81 318 long hloc;
e1f001e5 319
dba0cf81 320 if (aid == bid) return PRINCONSISTENT;
e1f001e5 321 bzero(&hentry,sizeof(hentry));
322 temp = FindByID(at,bid);
dba0cf81 323 if (temp == 0) return PRNOENT;
e1f001e5 324 code = pr_ReadEntry(at, 0, temp, &tentry);
325 if (code != 0) return code;
dba0cf81 326#ifdef PR_REMEMBER_TIMES
327 tentry.removeTime = time(0);
328#endif
e1f001e5 329 for (i=0;i<PRSIZE;i++) {
330 if (tentry.entries[i] == aid) {
331 tentry.entries[i] = PRBADID;
332 tentry.count--;
333 code = pr_WriteEntry(at,0,temp,&tentry);
334 if (code != 0) return code;
335 return PRSUCCESS;
336 }
337 if (tentry.entries[i] == 0) /* found end of list */
338 return PRNOENT;
339 }
dba0cf81 340 hloc = 0;
341 nptr = tentry.next;
342 while (nptr != NULL) {
343 code = pr_ReadCoEntry(at,0,nptr,&centry);
344 if (code != 0) return code;
345 if ((centry.id != bid) || !(centry.flags & PRCONT)) return PRDBBAD;
346 for (i=0;i<COSIZE;i++) {
347 if (centry.entries[i] == aid) {
348 centry.entries[i] = PRBADID;
349 for (j=0;j<COSIZE;j++)
350 if (centry.entries[j] != PRBADID &&
351 centry.entries[j] != 0) break;
352 if (j == COSIZE) { /* can free this block */
353 if (hloc == 0) {
354 tentry.next = centry.next;
e1f001e5 355 }
dba0cf81 356 else {
357 hentry.next = centry.next;
358 code = pr_WriteCoEntry (at, 0, hloc, &hentry);
e1f001e5 359 if (code != 0) return code;
e1f001e5 360 }
dba0cf81 361 code = FreeBlock (at, nptr);
362 if (code) return code;
e1f001e5 363 }
dba0cf81 364 else { /* can't free it yet */
365 code = pr_WriteCoEntry(at,0,nptr,&centry);
366 if (code != 0) return code;
367 }
368 tentry.count--;
369 code = pr_WriteEntry(at,0,temp,&tentry);
370 if (code) return PRDBFAIL;
371 return 0;
e1f001e5 372 }
dba0cf81 373 if (centry.entries[i] == 0) return PRNOENT;
374 } /* for all coentry slots */
375 hloc = nptr;
376 nptr = centry.next;
377 bcopy(&centry,&hentry,sizeof(centry));
378 } /* while there are coentries */
379 return PRNOENT;
e1f001e5 380}
381
dba0cf81 382/* DeleteEntry - delete the entry in tentry at loc, removing it from all
383 * groups, putting groups owned by it on orphan chain, and freeing the space */
384
385long DeleteEntry (at, tentry, loc)
386 register struct ubik_trans *at;
387 struct prentry *tentry;
388 long loc;
e1f001e5 389{
e1f001e5 390 register long code;
e1f001e5 391 long temp1;
e1f001e5 392 struct contentry centry;
393 struct prentry nentry;
394 register long i;
395 long nptr;
dba0cf81 396
397 /* First remove the entire membership list */
e1f001e5 398 for (i=0;i<PRSIZE;i++) {
dba0cf81 399 if (tentry->entries[i] == PRBADID) continue;
400 if (tentry->entries[i] == 0) break;
401 code = RemoveFromEntry (at, tentry->id, tentry->entries[i]);
402 if (code) return code;
e1f001e5 403 }
dba0cf81 404 nptr = tentry->next;
e1f001e5 405 while (nptr != NULL) {
406 code = pr_ReadCoEntry(at,0,nptr,&centry);
407 if (code != 0) return PRDBFAIL;
408 for (i=0;i<COSIZE;i++) {
dba0cf81 409 if (centry.entries[i] == PRBADID) continue;
e1f001e5 410 if (centry.entries[i] == 0) break;
dba0cf81 411 code = RemoveFromEntry (at, tentry->id, centry.entries[i]);
412 if (code) return code;
e1f001e5 413 }
dba0cf81 414 code = FreeBlock (at, nptr); /* free continuation block */
415 if (code) return code;
e1f001e5 416 nptr = centry.next;
417 }
dba0cf81 418
419 /* Remove us from other's owned chain. Note that this will zero our owned
420 * field (on disk) so this step must follow the above step in case we are
421 * on our own owned list. */
422 if (tentry->flags & PRGRP) {
423 if (tentry->owner) {
424 code = RemoveFromOwnerChain (at, tentry->id, tentry->owner);
e1f001e5 425 if (code) return code;
426 }
427 else {
dba0cf81 428 code = RemoveFromOrphan (at, tentry->id);
e1f001e5 429 if (code) return code;
430 }
431 }
dba0cf81 432
433 code = RemoveFromIDHash(at,tentry->id,&loc);
e1f001e5 434 if (code != PRSUCCESS) return code;
dba0cf81 435 code = RemoveFromNameHash(at,tentry->name,&loc);
e1f001e5 436 if (code != PRSUCCESS) return code;
dba0cf81 437
438 if (tentry->flags & (PRGRP | PRFOREIGN)) {
439 long loc = FindByID (at, tentry->creator);
440 struct prentry centry;
441 if (loc) {
442 code = pr_Read (at, 0, loc, &centry, sizeof(centry));
443 if (code) return code;
444 if (ntohl(centry.flags) & PRQUOTA) {
445 if (tentry->flags & PRGRP) {
446 centry.ngroups = htonl(ntohl(centry.ngroups) + 1);
447 } else if (tentry->flags & PRFOREIGN) {
448 centry.nusers = htonl(ntohl(centry.nusers) + 1);
449 }
450 }
451 code = pr_Write (at, 0, loc, &centry, sizeof(centry));
452 if (code) return code;
453 }
e1f001e5 454 }
dba0cf81 455
456 if (tentry->flags & PRGRP) {
457 if (inc_header_word (at, groupcount, -1)) return PRDBFAIL;
e1f001e5 458 }
dba0cf81 459 else if (tentry->flags & PRFOREIGN) {
460 if (inc_header_word (at, foreigncount, -1)) return PRDBFAIL;
461 }
462 else if (tentry->flags & PRINST) {
463 if (inc_header_word (at, instcount, -1)) return PRDBFAIL;
e1f001e5 464 }
465 else {
dba0cf81 466 if (inc_header_word (at, usercount, -1)) return PRDBFAIL;
e1f001e5 467 }
dba0cf81 468 code = FreeBlock(at, loc);
469 return code;
e1f001e5 470}
471
dba0cf81 472/* AddToEntry - add aid to entry's entries list, alloc'ing a continuation block
473 * if needed.
474 *
475 * Note the entry is written out by this routine. */
e1f001e5 476
dba0cf81 477long AddToEntry (tt, entry, loc, aid)
478 struct ubik_trans *tt;
479 struct prentry *entry;
480 long loc;
481 long aid;
e1f001e5 482{
e1f001e5 483 register long code;
484 long i;
485 struct contentry nentry;
486 struct contentry aentry;
487 long nptr;
dba0cf81 488 long last; /* addr of last cont. block */
e1f001e5 489 long first = 0;
490 long cloc;
491 long slot = -1;
492
dba0cf81 493 if (entry->id == aid) return PRINCONSISTENT;
494#ifdef PR_REMEMBER_TIMES
495 entry->addTime = time(0);
496#endif
e1f001e5 497 for (i=0;i<PRSIZE;i++) {
dba0cf81 498 if (entry->entries[i] == aid)
e1f001e5 499 return PRIDEXIST;
dba0cf81 500 if (entry->entries[i] == PRBADID) { /* remember this spot */
e1f001e5 501 first = 1;
502 slot = i;
503 }
dba0cf81 504 else if (entry->entries[i] == 0) { /* end of the line */
e1f001e5 505 if (slot == -1) {
506 first = 1;
507 slot = i;
508 }
509 break;
510 }
511 }
dba0cf81 512 last = 0;
513 nptr = entry->next;
e1f001e5 514 while (nptr != NULL) {
dba0cf81 515 code = pr_ReadCoEntry(tt,0,nptr,&nentry);
e1f001e5 516 if (code != 0) return code;
dba0cf81 517 last = nptr;
e1f001e5 518 if (!(nentry.flags & PRCONT)) return PRDBFAIL;
519 for (i=0;i<COSIZE;i++) {
520 if (nentry.entries[i] == aid)
521 return PRIDEXIST;
522 if (nentry.entries[i] == PRBADID) {
523 if (slot == -1) {
524 slot = i;
525 cloc = nptr;
526 }
527 }
dba0cf81 528 else if (nentry.entries[i] == 0) {
e1f001e5 529 if (slot == -1) {
530 slot = i;
531 cloc = nptr;
532 }
533 break;
534 }
535 }
e1f001e5 536 nptr = nentry.next;
537 }
dba0cf81 538 if (slot != -1) { /* we found a place */
539 entry->count++;
e1f001e5 540 if (first) { /* place is in first block */
dba0cf81 541 entry->entries[slot] = aid;
542 code = pr_WriteEntry (tt, 0, loc, entry);
e1f001e5 543 if (code != 0) return code;
544 return PRSUCCESS;
545 }
dba0cf81 546 code = pr_WriteEntry (tt, 0, loc, entry);
547 if (code) return code;
e1f001e5 548 code = pr_ReadCoEntry(tt,0,cloc,&aentry);
549 if (code != 0) return code;
550 aentry.entries[slot] = aid;
551 code = pr_WriteCoEntry(tt,0,cloc,&aentry);
552 if (code != 0) return code;
553 return PRSUCCESS;
554 }
555 /* have to allocate a continuation block if we got here */
556 nptr = AllocBlock(tt);
dba0cf81 557 if (last) {
558 /* then we should tack new block after last block in cont. chain */
e1f001e5 559 nentry.next = nptr;
560 code = pr_WriteCoEntry(tt,0,last,&nentry);
561 if (code != 0) return code;
562 }
563 else {
dba0cf81 564 entry->next = nptr;
e1f001e5 565 }
dba0cf81 566 bzero(&aentry,sizeof(aentry));
e1f001e5 567 aentry.flags |= PRCONT;
dba0cf81 568 aentry.id = entry->id;
e1f001e5 569 aentry.next = NULL;
570 aentry.entries[0] = aid;
571 code = pr_WriteCoEntry(tt,0,nptr,&aentry);
572 if (code != 0) return code;
573 /* don't forget to update count, here! */
dba0cf81 574 entry->count++;
575 code = pr_WriteEntry (tt, 0, loc, entry);
576 return code;
e1f001e5 577
578}
579
dba0cf81 580long AddToPRList (alist, sizeP, id)
581 prlist *alist;
582 int *sizeP;
583 long id;
584{
585 if (alist->prlist_len >= PR_MAXGROUPS) return PRTOOMANY;
586 if (alist->prlist_len >= *sizeP) {
587 *sizeP = *sizeP + 100;
588 if (*sizeP > PR_MAXGROUPS) *sizeP = PR_MAXGROUPS;
589 alist->prlist_val =
590 (long *) ((alist->prlist_val) ?
591 realloc (alist->prlist_val, (*sizeP)*sizeof(long)) :
592 malloc ((*sizeP)*sizeof(long)));
593 }
594 alist->prlist_val[alist->prlist_len++] = id;
595 return 0;
596}
597
598long GetList (at, tentry, alist, add)
599 struct ubik_trans *at;
600 struct prentry *tentry;
601 prlist *alist;
602 long add;
e1f001e5 603{
604 register long code;
e1f001e5 605 long i;
e1f001e5 606 struct contentry centry;
607 long nptr;
dba0cf81 608 int size;
609 int count = 0;
e1f001e5 610 extern long IDCmp();
611
dba0cf81 612 size = 0;
613 alist->prlist_val = 0;
e1f001e5 614 alist->prlist_len = 0;
dba0cf81 615
e1f001e5 616 for (i=0;i<PRSIZE;i++) {
dba0cf81 617 if (tentry->entries[i] == PRBADID) continue;
618 if (tentry->entries[i] == 0) break;
619 code = AddToPRList (alist, &size, tentry->entries[i]);
620 if (code) return code;
e1f001e5 621 }
dba0cf81 622
623 nptr = tentry->next;
e1f001e5 624 while (nptr != NULL) {
625 /* look through cont entries */
626 code = pr_ReadCoEntry(at,0,nptr,&centry);
627 if (code != 0) return code;
628 for (i=0;i<COSIZE;i++) {
629 if (centry.entries[i] == PRBADID) continue;
630 if (centry.entries[i] == 0) break;
dba0cf81 631 code = AddToPRList (alist, &size, centry.entries[i]);
632 if (code) return code;
e1f001e5 633 }
634 nptr = centry.next;
dba0cf81 635 if (count++ > 50) IOMGR_Poll(), count = 0;
e1f001e5 636 }
dba0cf81 637
e1f001e5 638 if (add) { /* this is for a CPS, so tack on appropriate stuff */
dba0cf81 639 if (tentry->id != ANONYMOUSID && tentry->id != ANYUSERID) {
640 if ((code = AddToPRList (alist, &size, ANYUSERID)) ||
641 (code = AddToPRList (alist, &size, AUTHUSERID)) ||
642 (code = AddToPRList (alist, &size, tentry->id))) return code;
e1f001e5 643 }
644 else {
dba0cf81 645 if ((code = AddToPRList (alist, &size, ANYUSERID)) ||
646 (code = AddToPRList (alist, &size, tentry->id))) return code;
e1f001e5 647 }
648 }
dba0cf81 649 if (alist->prlist_len > 100) IOMGR_Poll();
650 qsort(alist->prlist_val,alist->prlist_len,sizeof(long),IDCmp);
651 return PRSUCCESS;
652}
653
654long GetOwnedChain (ut, next, alist)
655 struct ubik_trans *ut;
656 long next;
657 prlist *alist;
658{ register long code;
659 struct prentry tentry;
660 int size;
661 int count = 0;
662
663 size = 0;
664 alist->prlist_val = 0;
665 alist->prlist_len = 0;
666
667 while (next) {
668 code = pr_Read (ut, 0, next, &tentry, sizeof(tentry));
669 if (code) return code;
670 code = AddToPRList (alist, &size, ntohl(tentry.id));
671 if (code) return code;
672 next = ntohl(tentry.nextOwned);
673 if (count++ > 50) IOMGR_Poll(), count = 0;
674 }
675 if (alist->prlist_len > 100) IOMGR_Poll();
e1f001e5 676 qsort(alist->prlist_val,alist->prlist_len,sizeof(long),IDCmp);
677 return PRSUCCESS;
678}
679
680long GetMax(at,uid,gid)
681register struct ubik_trans *at;
682long *uid;
683long *gid;
684{
685 *uid = ntohl(cheader.maxID);
686 *gid = ntohl(cheader.maxGroup);
687 return PRSUCCESS;
688}
689
690long SetMax(at,id,flag)
691register struct ubik_trans *at;
692long id;
693long flag;
694{
695 register long code;
696 if (flag & PRGRP) {
697 cheader.maxGroup = htonl(id);
698 code = pr_Write(at,0,16,(char *)&cheader.maxGroup,sizeof(cheader.maxGroup));
699 if (code != 0) return code;
700 }
701 else {
702 cheader.maxID = htonl(id);
703 code = pr_Write(at,0,20,(char *)&cheader.maxID,sizeof(cheader.maxID));
704 if (code != 0) return code;
705 }
706 return PRSUCCESS;
707}
708
dba0cf81 709int pr_noAuth;
710
711long Initdb()
e1f001e5 712{
713 long code;
714 struct ubik_trans *tt;
715 long len;
e1f001e5 716 static long initd=0;
dba0cf81 717#if 0
e1f001e5 718 static struct ubik_version curver;
719 struct ubik_version newver;
dba0cf81 720#endif
e1f001e5 721
722 /* init the database. We'll try reading it, but if we're starting from scratch, we'll have to do a write transaction. */
723
dba0cf81 724 pr_noAuth = afsconf_GetNoAuthFlag(prdir);
725
e1f001e5 726 code = ubik_BeginTrans(dbase,UBIK_READTRANS, &tt);
727 if (code) return code;
728 code = ubik_SetLock(tt,1,1,LOCKREAD);
729 if (code) {
730 ubik_AbortTrans(tt);
731 return code;
732 }
733 if (!initd) {
734 initd = 1;
dba0cf81 735#if 0
e1f001e5 736 bzero(&curver,sizeof(curver));
dba0cf81 737#endif
738 } else if (!ubik_CacheUpdate (tt)) {
739 code = ubik_EndTrans(tt);
740 return code;
741 }
742#if 0
743 code = ubik_GetVersion(tt,&newver);
744 if (vcmp(curver,newver) == 0) {
745 /* same version */
746 code = ubik_EndTrans(tt);
747 if (code) return code;
748 return PRSUCCESS;
e1f001e5 749 }
dba0cf81 750 bcopy(&newver,&curver,sizeof(struct ubik_version));
751#endif
752
e1f001e5 753 len = sizeof(cheader);
754 code = pr_Read(tt, 0, 0, (char *) &cheader, len);
755 if (code != 0) {
dba0cf81 756 com_err (whoami, code, "couldn't read header");
e1f001e5 757 ubik_AbortTrans(tt);
758 return code;
759 }
dba0cf81 760 if ((ntohl(cheader.version) == PRDBVERSION) &&
761 ntohl(cheader.headerSize) == sizeof(cheader) &&
762 ntohl(cheader.eofPtr) != NULL &&
763 FindByID(tt,ANONYMOUSID) != 0){
e1f001e5 764 /* database exists, so we don't have to build it */
765 code = ubik_EndTrans(tt);
766 if (code) return code;
767 return PRSUCCESS;
768 }
769 /* else we need to build a database */
770 code = ubik_EndTrans(tt);
771 if (code) return code;
dba0cf81 772
773 /* Only rebuild database if the db was deleted (the header is zero) and we
774 are running noAuth. */
775 { char *bp = (char *)&cheader;
776 int i;
777 for (i=0; i<sizeof(cheader); i++)
778 if (bp[i]) {
779 code = PRDBBAD;
780 com_err (whoami, code,
781 "Can't rebuild database because it is not empty");
782 return code;
783 }
784 }
785 if (!pr_noAuth) {
786 code = PRDBBAD;
787 com_err (whoami, code,
788 "Can't rebuild database because not running NoAuth");
789 return code;
790 }
791
e1f001e5 792 code = ubik_BeginTrans(dbase,UBIK_WRITETRANS, &tt);
793 if (code) return code;
794 code = ubik_SetLock(tt,1,1,LOCKWRITE);
795 if (code) {
796 ubik_AbortTrans(tt);
797 return code;
798 }
dba0cf81 799
800 /* Initialize the database header */
801
802 if ((code = set_header_word (tt, version, htonl(PRDBVERSION))) ||
803 (code = set_header_word (tt, headerSize, htonl(sizeof(cheader)))) ||
804 (code = set_header_word (tt, eofPtr, cheader.headerSize))) {
805 com_err (whoami, code, "couldn't write header words");
e1f001e5 806 ubik_AbortTrans(tt);
807 return code;
808 }
dba0cf81 809
810#define InitialGroup(id,name) do { \
811 long temp = (id); \
812 long flag = (id) < 0 ? PRGRP : 0; \
813 code = CreateEntry \
814 (tt, (name), &temp, /*idflag*/1, flag, SYSADMINID, SYSADMINID); \
815 if (code) { \
816 com_err (whoami, code, "couldn't create %s with id %di.", \
817 (name), (id)); \
818 ubik_AbortTrans(tt); \
819 return code; \
820 } \
821} while (0)
822
823 InitialGroup (SYSADMINID, "system:administrators");
824 InitialGroup (ANYUSERID, "system:anyuser");
825 InitialGroup (AUTHUSERID, "system:authuser");
826 InitialGroup (ANONYMOUSID, "anonymous");
827
828 /* Well, we don't really want the max id set to anonymousid, so we'll set
829 * it back to 0 */
830 code = set_header_word (tt, maxID, 0); /* correct in any byte order */
831 if (code) {
832 com_err (whoami, code, "couldn't reset max id");
e1f001e5 833 ubik_AbortTrans(tt);
834 return code;
835 }
dba0cf81 836
e1f001e5 837 code = ubik_EndTrans(tt);
838 if (code) return code;
839 return PRSUCCESS;
840}
841
dba0cf81 842long ChangeEntry (at, aid, cid, name, oid, newid)
843 struct ubik_trans *at;
844 long aid;
845 long cid;
846 char *name;
847 long oid;
848 long newid;
e1f001e5 849{
850 register long code;
851 long pos;
852 struct prentry tentry;
853 long loc;
dba0cf81 854 long oldowner;
e1f001e5 855 char holder[PR_MAXNAMELEN];
856 char temp[PR_MAXNAMELEN];
dba0cf81 857 char oldname[PR_MAXNAMELEN];
e1f001e5 858
e1f001e5 859 bzero(holder,PR_MAXNAMELEN);
860 bzero(temp,PR_MAXNAMELEN);
861 loc = FindByID(at,aid);
862 if (!loc) return PRNOENT;
863 code = pr_ReadEntry(at,0,loc,&tentry);
864 if (code) return PRDBFAIL;
dba0cf81 865 if (tentry.owner != cid &&
866 !IsAMemberOf(at,cid,SYSADMINID) &&
867 !IsAMemberOf(at,cid,tentry.owner) &&
868 !pr_noAuth) return PRPERM;
869#ifdef PR_REMEMBER_TIMES
870 tentry.changeTime = time(0);
871#endif
872
873 /* we're actually trying to change the id */
874 if (aid != newid && newid != 0) {
875 if (!IsAMemberOf(at,cid,SYSADMINID) && !pr_noAuth) return PRPERM;
e1f001e5 876 pos = FindByID(at,newid);
877 if (pos) return PRIDEXIST; /* new id already in use! */
878 if ((aid < 0 && newid) > 0 || (aid > 0 && newid < 0)) return PRPERM;
879 /* if new id is not in use, rehash things */
880 code = RemoveFromIDHash(at,aid,&loc);
881 if (code != PRSUCCESS) return code;
882 tentry.id = newid;
883 code = pr_WriteEntry(at,0,loc,&tentry);
dba0cf81 884 if (code) return code;
e1f001e5 885 code = AddToIDHash(at,tentry.id,loc);
886 if (code) return code;
dba0cf81 887 /* get current data */
888 code = pr_ReadEntry(at,0,loc,&tentry);
889 if (code) return PRDBFAIL;
e1f001e5 890 }
dba0cf81 891
892 /* Change the owner */
e1f001e5 893 if (tentry.owner != oid && oid) {
dba0cf81 894 /* only groups can have their owner's changed */
895 if (!(tentry.flags & PRGRP)) return PRPERM;
896 oldowner = tentry.owner;
897 tentry.owner = oid;
898 /* The entry must be written through first so Remove and Add routines
899 * can operate on disk data */
900 code = pr_WriteEntry(at,0,loc,(char *)&tentry);
901 if (code) return PRDBFAIL;
e1f001e5 902 if (tentry.flags & PRGRP) {
dba0cf81 903 /* switch owner chains */
904 if (oldowner) /* if it has an owner */
905 code = RemoveFromOwnerChain(at,tentry.id,oldowner);
906 else /* must be an orphan */
e1f001e5 907 code = RemoveFromOrphan(at,tentry.id);
908 if (code) return code;
dba0cf81 909 code = AddToOwnerChain(at,tentry.id,tentry.owner);
e1f001e5 910 if (code) return code;
911 }
dba0cf81 912 /* fix up the name */
913 if ((tentry.flags & PRGRP) && (strlen(name) == 0)) name = tentry.name;
914 /* get current data */
915 code = pr_ReadEntry(at,0,loc,&tentry);
e1f001e5 916 if (code) return PRDBFAIL;
917 }
dba0cf81 918
919 /* Change the name, if name is a ptr to tentry.name then this name change
920 * is due to a chown, otherwise caller has specified a new name */
921 if ((name == tentry.name) ||
922 (*name && (strcmp (tentry.name, name) != 0))) {
923 strncpy (oldname, tentry.name, PR_MAXNAMELEN);
e1f001e5 924 if (tentry.flags & PRGRP) {
dba0cf81 925 code = CorrectGroupName (at, name, cid, tentry.owner, tentry.name);
926 if (code) return code;
927
928 if (name == tentry.name) { /* owner fixup */
929 if (strcmp (oldname, tentry.name) == 0) goto nameOK;
930 } else { /* new name, caller must be correct */
931 if (strcmp (name, tentry.name) != 0) return PRBADNAM;
932 }
e1f001e5 933 }
934 else
dba0cf81 935 if (!CorrectUserName(name)) return PRBADNAM;
936
e1f001e5 937 pos = FindByName(at,name);
938 if (pos) return PREXIST;
dba0cf81 939 code = RemoveFromNameHash (at, oldname, &loc);
e1f001e5 940 if (code != PRSUCCESS) return code;
dba0cf81 941 strncpy (tentry.name, name, PR_MAXNAMELEN);
942 code = pr_WriteEntry(at,0,loc,(char *)&tentry);
e1f001e5 943 if (code) return PRDBFAIL;
944 code = AddToNameHash(at,tentry.name,loc);
945 if (code != PRSUCCESS) return code;
dba0cf81 946nameOK:;
e1f001e5 947 }
948 return PRSUCCESS;
949}
This page took 0.201678 seconds and 5 git commands to generate.