2 * Copyright 2000, International Business Machines Corporation and others.
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
11 * Implementation of the ACL and quota-related operations used
12 * by the AFS user account facility.
16 * --------------------- Required definitions ---------------------
18 #include <afsconfig.h>
19 #include <afs/param.h>
25 #include "uss_common.h"
28 #include <sys/socket.h>
29 #include <sys/types.h>
37 #include <afs/afsint.h>
38 #include <afs/prs_fs.h>
39 #include <afs/com_err.h>
49 struct AclEntry *pluslist;
50 struct AclEntry *minuslist;
54 struct AclEntry *next;
59 static int PruneList();
62 /*------------------------------------------------------------------------
66 * String comparison with case-folding.
69 * a_str1 : First string.
70 * a_str2 : Second string.
73 * 0 if the two strings match,
77 * Nothing interesting.
81 *------------------------------------------------------------------------*/
84 foldcmp(a_str1, a_str2)
85 register char *a_str1;
86 register char *a_str2;
95 if (t >= 'A' && t <= 'Z')
97 if (u >= 'A' && u <= 'Z')
100 return (1); /*Difference */
102 return (0); /*Match */
107 /*------------------------------------------------------------------------
111 * Convert rights as expressed in a character string to an integer
112 * with the appropriate bits set.
115 * a_rights : String version of access rights.
121 * Nothing interesting.
124 * Exits the program if a badly-formatted rights string is
126 *------------------------------------------------------------------------*/
130 register char *a_rights;
138 if (!strcmp(a_rights, "read"))
139 return (PRSFS_READ | PRSFS_LOOKUP);
141 if (!strcmp(a_rights, "write"))
142 return (PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
143 PRSFS_WRITE | PRSFS_LOCK);
145 if (!strcmp(a_rights, "mail"))
146 return (PRSFS_INSERT | PRSFS_LOCK | PRSFS_LOOKUP);
148 if (!strcmp(a_rights, "all"))
149 return (PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
150 PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER);
152 if (!strcmp(a_rights, "none"))
155 len = strlen(a_rights);
157 for (i = 0; i < len; i++) {
162 mode |= PRSFS_LOOKUP;
164 mode |= PRSFS_INSERT;
166 mode |= PRSFS_DELETE;
172 mode |= PRSFS_ADMINISTER;
174 printf("%s: Bogus rights character '%c'.\n", uss_whoami, tc);
183 /*------------------------------------------------------------------------
187 * Find the entry with the given name in the passed-in ACL.
190 * a_alist : Internalized ACL to look through.
191 * a_name : Name to find.
194 * Ptr to the ACL entry found, or null pointer if none.
197 * Nothing interesting.
201 *------------------------------------------------------------------------*/
203 static struct AclEntry *
204 FindList(a_alist, a_name)
205 register struct AclEntry *a_alist;
211 if (!foldcmp(a_alist->name, a_name))
213 a_alist = a_alist->next;
220 /*------------------------------------------------------------------------
224 * Set the rights for the named entry to the given value, creating
225 * an entry if one does not yet exist.
228 * a_al : Ptr to the internalized ACL.
229 * a_plus : Positive or negative rights?
230 * a_name : Name to look for.
231 * a_rights : Rights to set.
234 * 0 if the two strings match,
238 * Nothing interesting.
242 *------------------------------------------------------------------------*/
245 ChangeList(a_al, a_plus, a_name, a_rights)
253 struct AclEntry *tlist;
255 tlist = (a_plus ? a_al->pluslist : a_al->minuslist);
256 tlist = FindList(tlist, a_name);
259 * Found the item already in the list.
261 tlist->rights = a_rights;
263 a_al->nplus -= PruneList(&a_al->pluslist);
265 a_al->nminus -= PruneList(&a_al->minuslist);
270 * Otherwise, we make a new item and plug in the new data.
272 tlist = (struct AclEntry *)malloc(sizeof(struct AclEntry));
273 strcpy(tlist->name, a_name);
274 tlist->rights = a_rights;
276 tlist->next = a_al->pluslist;
277 a_al->pluslist = tlist;
280 a_al->nplus -= PruneList(&a_al->pluslist);
282 tlist->next = a_al->minuslist;
283 a_al->minuslist = tlist;
286 a_al->nminus -= PruneList(&a_al->minuslist);
291 /*------------------------------------------------------------------------
295 * Remove all entries whose rights fields are set to zero.
298 * a_aclPP : Ptr to the location of the ACL to purne.
301 * Number of entries pruned off.
304 * Nothing interesting.
308 *------------------------------------------------------------------------*/
312 struct AclEntry **a_aclPP;
316 struct AclEntry **lPP;
317 struct AclEntry *tP, *nP;
322 for (tP = *a_aclPP; tP; tP = nP) {
323 if (tP->rights == 0) {
339 /*------------------------------------------------------------------------
343 * Skip chars until we eat a newline.
346 * a_str : String to process.
349 * Ptr to the first char past the newline.
352 * Nothing interesting.
356 *------------------------------------------------------------------------*/
360 register char *a_str;
364 while (*a_str != '\n')
372 /*------------------------------------------------------------------------
376 * Create an empty internalized ACL.
382 * Ptr to an initialized and empty internalized ACL.
385 * Nothing interesting.
389 *------------------------------------------------------------------------*/
395 register struct Acl *tp;
397 tp = (struct Acl *)malloc(sizeof(struct Acl));
398 tp->nplus = tp->nminus = 0;
399 tp->pluslist = tp->minuslist = 0;
405 /*------------------------------------------------------------------------
409 * Given an externalized ACL (i.e., in string format), convert it
410 * into its internalized form.
413 * a_str : Ptr to Externalized ACL.
416 * Ptr to the equivalent internalized ACL.
419 * Nothing interesting.
423 *------------------------------------------------------------------------*/
431 int nplus, nminus, i, trights;
433 struct AclEntry *first, *last, *tl;
437 * Pull out the number of positive & negative entries in the externalized
440 sscanf(a_str, "%d", &nplus);
441 a_str = SkipLine(a_str);
442 sscanf(a_str, "%d", &nminus);
443 a_str = SkipLine(a_str);
446 * Allocate and initialize the first entry.
448 ta = (struct Acl *)malloc(sizeof(struct Acl));
453 * Translate the positive entries.
457 for (i = 0; i < nplus; i++) {
458 sscanf(a_str, "%100s %d", tname, &trights);
459 a_str = SkipLine(a_str);
460 tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
463 strcpy(tl->name, tname);
464 tl->rights = trights;
470 ta->pluslist = first;
473 * Translate the negative entries.
477 for (i = 0; i < nminus; i++) {
478 sscanf(a_str, "%100s %d", tname, &trights);
479 a_str = SkipLine(a_str);
480 tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
483 strcpy(tl->name, tname);
484 tl->rights = trights;
490 ta->minuslist = first;
497 /*------------------------------------------------------------------------
501 * Given an internalized ACL, convert it to its externalized form,
502 * namely a character string.
505 * a_acl : Internalized ACL to externalize.
508 * Ptr to the externalized version.
511 * Nothing interesting.
515 *------------------------------------------------------------------------*/
523 static char mydata[MAXSIZE];
524 char tstring[MAXSIZE];
528 * Print out the number of positive & negative entries on one line.
530 sprintf(mydata, "%d\n%d\n", a_acl->nplus, a_acl->nminus);
533 * Externalize the positive list.
535 for (tp = a_acl->pluslist; tp; tp = tp->next) {
536 sprintf(tstring, "%s %d\n", tp->name, tp->rights);
537 strcat(mydata, tstring);
541 * Externalize the negative list.
543 for (tp = a_acl->minuslist; tp; tp = tp->next) {
544 sprintf(tstring, "%s %d\n", tp->name, tp->rights);
545 strcat(mydata, tstring);
552 /*------------------------------------------------------------------------
553 * static uss_acl_SetAccess
556 * ACL comes in as a single string, prefixed with the pathname to
557 * which the ACL is applied. The a_clear argument, if set, causes
558 * us to act like sac instead of sa.
562 *------------------------------------------------------------------------*/
565 uss_acl_SetAccess(a_access, a_clear, a_negative)
570 { /*uss_acl_SetAccess */
572 register afs_int32 code;
573 static char rn[] = "uss_acl_SetAccess";
575 char *externalizedACL;
578 char tmp_str[MAXSIZE];
579 char path_field[MAXSIZE], user_field[64], rights_field[64], *tp;
585 * Pull out the pathname from our argument.
587 tp = uss_common_FieldCp(path_field, a_access, ' ', sizeof(path_field),
590 fprintf(stderr, "%s: * Pathname field too long (max is %d chars)\n",
591 uss_whoami, sizeof(path_field));
596 * Ask the Cache Manager to give us the externalized ACL for the
599 code = uss_fs_GetACL(path_field, tmp_str, MAXSIZE);
601 afs_com_err(uss_whoami, code, "while getting access list for %s",
604 printf("%s: Error code from uss_fs_GetACL %d, errno %d\n", rn, code,
606 #endif /* USS_ACL_DB */
611 printf("%s: ACL for pathname '%s' is: '%s'\n", rn, path_field,
613 #endif /* USS_ACL_DB */
616 * Generate the proper internalized ACL.
621 ta = ParseAcl(tmp_str);
624 * For each given entry, pull out the information and alter the
625 * internalized ACL to reflect it.
627 while (*tp != '\0') {
628 tp = uss_common_FieldCp(user_field, tp, ' ', 64, &overflow);
630 fprintf(stderr, "%s: * User field too long (max is 64 chars)\n",
635 printf("%s: Missing second half of user/access pair.\n",
639 tp = uss_common_FieldCp(rights_field, tp, ' ', 64, &overflow);
641 fprintf(stderr, "%s: * Rights field too long (max is 64 chars)\n",
645 rights = Convert(rights_field);
646 ChangeList(ta, plusp, user_field, rights);
650 * Externalize the fully-processed internal ACL, then pass it back
651 * to the Cache Manager.
653 externalizedACL = AclToString(ta);
655 uss_fs_SetACL(path_field, externalizedACL,
656 strlen(externalizedACL) + 1);
659 printf("%s: uss_fs_SetACL() failed, code is %d, errno is %d\n", rn,
661 #endif /* USS_ACL_DB */
662 if (errno == EINVAL) {
663 printf("Can't set ACL for directory '%s' to '%s'\n", path_field,
665 printf("Invalid argument, possible reasons include:\n");
666 printf("\t1. File not in AFS, or\n");
667 printf("\t2. Too many users on the ACL, or\n");
668 printf("\t3. Non-existent user or group on ACL.\n");
671 afs_com_err(uss_whoami, code, "while setting the access list");
677 } /*uss_acl_SetAccess */
680 /*------------------------------------------------------------------------
681 * static us_acl_SetDiskQuota
684 * Nothing interesting.
688 *------------------------------------------------------------------------*/
691 uss_acl_SetDiskQuota(a_path, a_q)
695 { /*uss_acl_SetDiskQuota */
697 register afs_int32 code;
698 static char rn[] = "uss_acl_SetDiskQuota";
699 uss_VolumeStatus_t *status;
700 char *name, *motd, *offmsg;
702 char tmp_str[MAXSIZE];
706 "Setting disk quota on volume mounted at '%s' to %d blocks\n",
709 status = (uss_VolumeStatus_t *) tmp_str;
710 status->MinQuota = status->MaxQuota = -1;
711 name = motd = offmsg = NULL;
712 status->MaxQuota = a_q;
714 input = (char *)status + sizeof(*status);
719 code = uss_fs_SetVolStat(a_path, tmp_str, sizeof(*status) + 3);
721 afs_com_err(uss_whoami, code, "while setting disk quota");
723 printf("%s: uss_fs_SetVolStat() error code: %d, errno is %d\n", rn,
725 #endif /* USS_ACL_DB */
731 } /*uss_acl_SetDiskQuota */
734 /*-----------------------------------------------------------------------
735 * EXPORTED uss_acl_CleanUp
738 * The uss_currentDir variable contains directories touched by the
743 *------------------------------------------------------------------------*/
747 { /*uss_acl_CleanUp */
749 static char rn[] = "uss_acl_CleanUp";
750 struct uss_subdir *t, *old_t = NULL;
751 char tmp_str[uss_MAX_SIZE];
754 * Restore the ACL for each directory created for our caller to its
755 * original setting. The uss_AccountCreator's access was (potentially)
756 * amplified to full rights - any excess ability must now be removed.
758 for (t = uss_currentDir; t != NULL; t = t->previous) {
759 sprintf(tmp_str, "%s %s", t->path, t->finalACL);
761 fprintf(stderr, "Setting ACL: '%s'\n", tmp_str);
763 uss_acl_SetAccess(tmp_str, 1, 0);
765 fprintf(stderr, "\t[Dry run: uss_acl_SetAccess(%s) on '%s']\n",
771 } /*Remove caller from user directory ACL */
777 * Return successfully.
781 } /*uss_acl_CleanUp */