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>
43 #include <afs/afsint.h>
44 #include <afs/prs_fs.h>
45 #include <afs/com_err.h>
55 struct AclEntry *pluslist;
56 struct AclEntry *minuslist;
60 struct AclEntry *next;
65 static int PruneList();
68 /*------------------------------------------------------------------------
72 * String comparison with case-folding.
75 * a_str1 : First string.
76 * a_str2 : Second string.
79 * 0 if the two strings match,
83 * Nothing interesting.
87 *------------------------------------------------------------------------*/
90 foldcmp(a_str1, a_str2)
91 register char *a_str1;
92 register char *a_str2;
101 if (t >= 'A' && t <= 'Z')
103 if (u >= 'A' && u <= 'Z')
106 return (1); /*Difference */
108 return (0); /*Match */
113 /*------------------------------------------------------------------------
117 * Convert rights as expressed in a character string to an integer
118 * with the appropriate bits set.
121 * a_rights : String version of access rights.
127 * Nothing interesting.
130 * Exits the program if a badly-formatted rights string is
132 *------------------------------------------------------------------------*/
136 register char *a_rights;
144 if (!strcmp(a_rights, "read"))
145 return (PRSFS_READ | PRSFS_LOOKUP);
147 if (!strcmp(a_rights, "write"))
148 return (PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
149 PRSFS_WRITE | PRSFS_LOCK);
151 if (!strcmp(a_rights, "mail"))
152 return (PRSFS_INSERT | PRSFS_LOCK | PRSFS_LOOKUP);
154 if (!strcmp(a_rights, "all"))
155 return (PRSFS_READ | PRSFS_LOOKUP | PRSFS_INSERT | PRSFS_DELETE |
156 PRSFS_WRITE | PRSFS_LOCK | PRSFS_ADMINISTER);
158 if (!strcmp(a_rights, "none"))
161 len = strlen(a_rights);
163 for (i = 0; i < len; i++) {
168 mode |= PRSFS_LOOKUP;
170 mode |= PRSFS_INSERT;
172 mode |= PRSFS_DELETE;
178 mode |= PRSFS_ADMINISTER;
180 printf("%s: Bogus rights character '%c'.\n", uss_whoami, tc);
189 /*------------------------------------------------------------------------
193 * Find the entry with the given name in the passed-in ACL.
196 * a_alist : Internalized ACL to look through.
197 * a_name : Name to find.
200 * Ptr to the ACL entry found, or null pointer if none.
203 * Nothing interesting.
207 *------------------------------------------------------------------------*/
209 static struct AclEntry *
210 FindList(a_alist, a_name)
211 register struct AclEntry *a_alist;
217 if (!foldcmp(a_alist->name, a_name))
219 a_alist = a_alist->next;
226 /*------------------------------------------------------------------------
230 * Set the rights for the named entry to the given value, creating
231 * an entry if one does not yet exist.
234 * a_al : Ptr to the internalized ACL.
235 * a_plus : Positive or negative rights?
236 * a_name : Name to look for.
237 * a_rights : Rights to set.
240 * 0 if the two strings match,
244 * Nothing interesting.
248 *------------------------------------------------------------------------*/
251 ChangeList(a_al, a_plus, a_name, a_rights)
259 struct AclEntry *tlist;
261 tlist = (a_plus ? a_al->pluslist : a_al->minuslist);
262 tlist = FindList(tlist, a_name);
265 * Found the item already in the list.
267 tlist->rights = a_rights;
269 a_al->nplus -= PruneList(&a_al->pluslist);
271 a_al->nminus -= PruneList(&a_al->minuslist);
276 * Otherwise, we make a new item and plug in the new data.
278 tlist = (struct AclEntry *)malloc(sizeof(struct AclEntry));
279 strcpy(tlist->name, a_name);
280 tlist->rights = a_rights;
282 tlist->next = a_al->pluslist;
283 a_al->pluslist = tlist;
286 a_al->nplus -= PruneList(&a_al->pluslist);
288 tlist->next = a_al->minuslist;
289 a_al->minuslist = tlist;
292 a_al->nminus -= PruneList(&a_al->minuslist);
297 /*------------------------------------------------------------------------
301 * Remove all entries whose rights fields are set to zero.
304 * a_aclPP : Ptr to the location of the ACL to purne.
307 * Number of entries pruned off.
310 * Nothing interesting.
314 *------------------------------------------------------------------------*/
318 struct AclEntry **a_aclPP;
322 struct AclEntry **lPP;
323 struct AclEntry *tP, *nP;
328 for (tP = *a_aclPP; tP; tP = nP) {
329 if (tP->rights == 0) {
345 /*------------------------------------------------------------------------
349 * Skip chars until we eat a newline.
352 * a_str : String to process.
355 * Ptr to the first char past the newline.
358 * Nothing interesting.
362 *------------------------------------------------------------------------*/
366 register char *a_str;
370 while (*a_str != '\n')
378 /*------------------------------------------------------------------------
382 * Create an empty internalized ACL.
388 * Ptr to an initialized and empty internalized ACL.
391 * Nothing interesting.
395 *------------------------------------------------------------------------*/
401 register struct Acl *tp;
403 tp = (struct Acl *)malloc(sizeof(struct Acl));
404 tp->nplus = tp->nminus = 0;
405 tp->pluslist = tp->minuslist = 0;
411 /*------------------------------------------------------------------------
415 * Given an externalized ACL (i.e., in string format), convert it
416 * into its internalized form.
419 * a_str : Ptr to Externalized ACL.
422 * Ptr to the equivalent internalized ACL.
425 * Nothing interesting.
429 *------------------------------------------------------------------------*/
437 int nplus, nminus, i, trights;
439 struct AclEntry *first, *last, *tl;
443 * Pull out the number of positive & negative entries in the externalized
446 sscanf(a_str, "%d", &nplus);
447 a_str = SkipLine(a_str);
448 sscanf(a_str, "%d", &nminus);
449 a_str = SkipLine(a_str);
452 * Allocate and initialize the first entry.
454 ta = (struct Acl *)malloc(sizeof(struct Acl));
459 * Translate the positive entries.
463 for (i = 0; i < nplus; i++) {
464 sscanf(a_str, "%100s %d", tname, &trights);
465 a_str = SkipLine(a_str);
466 tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
469 strcpy(tl->name, tname);
470 tl->rights = trights;
476 ta->pluslist = first;
479 * Translate the negative entries.
483 for (i = 0; i < nminus; i++) {
484 sscanf(a_str, "%100s %d", tname, &trights);
485 a_str = SkipLine(a_str);
486 tl = (struct AclEntry *)malloc(sizeof(struct AclEntry));
489 strcpy(tl->name, tname);
490 tl->rights = trights;
496 ta->minuslist = first;
503 /*------------------------------------------------------------------------
507 * Given an internalized ACL, convert it to its externalized form,
508 * namely a character string.
511 * a_acl : Internalized ACL to externalize.
514 * Ptr to the externalized version.
517 * Nothing interesting.
521 *------------------------------------------------------------------------*/
529 static char mydata[MAXSIZE];
530 char tstring[MAXSIZE];
534 * Print out the number of positive & negative entries on one line.
536 sprintf(mydata, "%d\n%d\n", a_acl->nplus, a_acl->nminus);
539 * Externalize the positive list.
541 for (tp = a_acl->pluslist; tp; tp = tp->next) {
542 sprintf(tstring, "%s %d\n", tp->name, tp->rights);
543 strcat(mydata, tstring);
547 * Externalize the negative list.
549 for (tp = a_acl->minuslist; tp; tp = tp->next) {
550 sprintf(tstring, "%s %d\n", tp->name, tp->rights);
551 strcat(mydata, tstring);
558 /*------------------------------------------------------------------------
559 * static uss_acl_SetAccess
562 * ACL comes in as a single string, prefixed with the pathname to
563 * which the ACL is applied. The a_clear argument, if set, causes
564 * us to act like sac instead of sa.
568 *------------------------------------------------------------------------*/
571 uss_acl_SetAccess(a_access, a_clear, a_negative)
576 { /*uss_acl_SetAccess */
578 register afs_int32 code;
579 static char rn[] = "uss_acl_SetAccess";
581 char *externalizedACL;
584 char tmp_str[MAXSIZE];
585 char path_field[MAXSIZE], user_field[64], rights_field[64], *tp;
591 * Pull out the pathname from our argument.
593 tp = uss_common_FieldCp(path_field, a_access, ' ', sizeof(path_field),
596 fprintf(stderr, "%s: * Pathname field too long (max is %d chars)\n",
597 uss_whoami, sizeof(path_field));
602 * Ask the Cache Manager to give us the externalized ACL for the
605 code = uss_fs_GetACL(path_field, tmp_str, MAXSIZE);
607 afs_com_err(uss_whoami, code, "while getting access list for %s",
610 printf("%s: Error code from uss_fs_GetACL %d, errno %d\n", rn, code,
612 #endif /* USS_ACL_DB */
617 printf("%s: ACL for pathname '%s' is: '%s'\n", rn, path_field,
619 #endif /* USS_ACL_DB */
622 * Generate the proper internalized ACL.
627 ta = ParseAcl(tmp_str);
630 * For each given entry, pull out the information and alter the
631 * internalized ACL to reflect it.
633 while (*tp != '\0') {
634 tp = uss_common_FieldCp(user_field, tp, ' ', 64, &overflow);
636 fprintf(stderr, "%s: * User field too long (max is 64 chars)\n",
641 printf("%s: Missing second half of user/access pair.\n",
645 tp = uss_common_FieldCp(rights_field, tp, ' ', 64, &overflow);
647 fprintf(stderr, "%s: * Rights field too long (max is 64 chars)\n",
651 rights = Convert(rights_field);
652 ChangeList(ta, plusp, user_field, rights);
656 * Externalize the fully-processed internal ACL, then pass it back
657 * to the Cache Manager.
659 externalizedACL = AclToString(ta);
661 uss_fs_SetACL(path_field, externalizedACL,
662 strlen(externalizedACL) + 1);
665 printf("%s: uss_fs_SetACL() failed, code is %d, errno is %d\n", rn,
667 #endif /* USS_ACL_DB */
668 if (errno == EINVAL) {
669 printf("Can't set ACL for directory '%s' to '%s'\n", path_field,
671 printf("Invalid argument, possible reasons include:\n");
672 printf("\t1. File not in AFS, or\n");
673 printf("\t2. Too many users on the ACL, or\n");
674 printf("\t3. Non-existent user or group on ACL.\n");
677 afs_com_err(uss_whoami, code, "while setting the access list");
683 } /*uss_acl_SetAccess */
686 /*------------------------------------------------------------------------
687 * static us_acl_SetDiskQuota
690 * Nothing interesting.
694 *------------------------------------------------------------------------*/
697 uss_acl_SetDiskQuota(a_path, a_q)
701 { /*uss_acl_SetDiskQuota */
703 register afs_int32 code;
704 static char rn[] = "uss_acl_SetDiskQuota";
705 uss_VolumeStatus_t *status;
706 char *name, *motd, *offmsg;
708 char tmp_str[MAXSIZE];
712 "Setting disk quota on volume mounted at '%s' to %d blocks\n",
715 status = (uss_VolumeStatus_t *) tmp_str;
716 status->MinQuota = status->MaxQuota = -1;
717 name = motd = offmsg = NULL;
718 status->MaxQuota = a_q;
720 input = (char *)status + sizeof(*status);
725 code = uss_fs_SetVolStat(a_path, tmp_str, sizeof(*status) + 3);
727 afs_com_err(uss_whoami, code, "while setting disk quota");
729 printf("%s: uss_fs_SetVolStat() error code: %d, errno is %d\n", rn,
731 #endif /* USS_ACL_DB */
737 } /*uss_acl_SetDiskQuota */
740 /*-----------------------------------------------------------------------
741 * EXPORTED uss_acl_CleanUp
744 * The uss_currentDir variable contains directories touched by the
749 *------------------------------------------------------------------------*/
753 { /*uss_acl_CleanUp */
755 static char rn[] = "uss_acl_CleanUp";
756 struct uss_subdir *t, *old_t = NULL;
757 char tmp_str[uss_MAX_SIZE];
760 * Restore the ACL for each directory created for our caller to its
761 * original setting. The uss_AccountCreator's access was (potentially)
762 * amplified to full rights - any excess ability must now be removed.
764 for (t = uss_currentDir; t != NULL; t = t->previous) {
765 sprintf(tmp_str, "%s %s", t->path, t->finalACL);
767 fprintf(stderr, "Setting ACL: '%s'\n", tmp_str);
769 uss_acl_SetAccess(tmp_str, 1, 0);
771 fprintf(stderr, "\t[Dry run: uss_acl_SetAccess(%s) on '%s']\n",
777 } /*Remove caller from user directory ACL */
783 * Return successfully.
787 } /*uss_acl_CleanUp */