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 <afs/afsint.h>
26 #include <afs/prs_fs.h>
27 #include <afs/com_err.h>
28 #include <afs/afs_consts.h>
32 #include "uss_common.h"
42 struct AclEntry
*pluslist
;
43 struct AclEntry
*minuslist
;
47 struct AclEntry
*next
;
52 static int PruneList(struct AclEntry
**a_aclPP
);
55 /*------------------------------------------------------------------------
59 * String comparison with case-folding.
62 * a_str1 : First string.
63 * a_str2 : Second string.
66 * 0 if the two strings match,
70 * Nothing interesting.
74 *------------------------------------------------------------------------*/
77 foldcmp(char *a_str1
, char *a_str2
)
85 if (t
>= 'A' && t
<= 'Z')
87 if (u
>= 'A' && u
<= 'Z')
90 return (1); /*Difference */
92 return (0); /*Match */
97 /*------------------------------------------------------------------------
101 * Convert rights as expressed in a character string to an integer
102 * with the appropriate bits set.
105 * a_rights : String version of access rights.
111 * Nothing interesting.
114 * Exits the program if a badly-formatted rights string is
116 *------------------------------------------------------------------------*/
119 Convert(char *a_rights
)
126 if (!strcmp(a_rights
, "read"))
127 return (PRSFS_READ
| PRSFS_LOOKUP
);
129 if (!strcmp(a_rights
, "write"))
130 return (PRSFS_READ
| PRSFS_LOOKUP
| PRSFS_INSERT
| PRSFS_DELETE
|
131 PRSFS_WRITE
| PRSFS_LOCK
);
133 if (!strcmp(a_rights
, "mail"))
134 return (PRSFS_INSERT
| PRSFS_LOCK
| PRSFS_LOOKUP
);
136 if (!strcmp(a_rights
, "all"))
137 return (PRSFS_READ
| PRSFS_LOOKUP
| PRSFS_INSERT
| PRSFS_DELETE
|
138 PRSFS_WRITE
| PRSFS_LOCK
| PRSFS_ADMINISTER
);
140 if (!strcmp(a_rights
, "none"))
143 len
= strlen(a_rights
);
145 for (i
= 0; i
< len
; i
++) {
150 mode
|= PRSFS_LOOKUP
;
152 mode
|= PRSFS_INSERT
;
154 mode
|= PRSFS_DELETE
;
160 mode
|= PRSFS_ADMINISTER
;
162 printf("%s: Bogus rights character '%c'.\n", uss_whoami
, tc
);
171 /*------------------------------------------------------------------------
175 * Find the entry with the given name in the passed-in ACL.
178 * a_alist : Internalized ACL to look through.
179 * a_name : Name to find.
182 * Ptr to the ACL entry found, or null pointer if none.
185 * Nothing interesting.
189 *------------------------------------------------------------------------*/
191 static struct AclEntry
*
192 FindList(struct AclEntry
*a_alist
, char *a_name
)
196 if (!foldcmp(a_alist
->name
, a_name
))
198 a_alist
= a_alist
->next
;
205 /*------------------------------------------------------------------------
209 * Set the rights for the named entry to the given value, creating
210 * an entry if one does not yet exist.
213 * a_al : Ptr to the internalized ACL.
214 * a_plus : Positive or negative rights?
215 * a_name : Name to look for.
216 * a_rights : Rights to set.
219 * 0 if the two strings match,
223 * Nothing interesting.
227 *------------------------------------------------------------------------*/
230 ChangeList(struct Acl
*a_al
, afs_int32 a_plus
, char *a_name
,
234 struct AclEntry
*tlist
;
236 tlist
= (a_plus
? a_al
->pluslist
: a_al
->minuslist
);
237 tlist
= FindList(tlist
, a_name
);
240 * Found the item already in the list.
242 tlist
->rights
= a_rights
;
244 a_al
->nplus
-= PruneList(&a_al
->pluslist
);
246 a_al
->nminus
-= PruneList(&a_al
->minuslist
);
251 * Otherwise, we make a new item and plug in the new data.
253 tlist
= malloc(sizeof(struct AclEntry
));
254 strcpy(tlist
->name
, a_name
);
255 tlist
->rights
= a_rights
;
257 tlist
->next
= a_al
->pluslist
;
258 a_al
->pluslist
= tlist
;
261 a_al
->nplus
-= PruneList(&a_al
->pluslist
);
263 tlist
->next
= a_al
->minuslist
;
264 a_al
->minuslist
= tlist
;
267 a_al
->nminus
-= PruneList(&a_al
->minuslist
);
272 /*------------------------------------------------------------------------
276 * Remove all entries whose rights fields are set to zero.
279 * a_aclPP : Ptr to the location of the ACL to purne.
282 * Number of entries pruned off.
285 * Nothing interesting.
289 *------------------------------------------------------------------------*/
292 PruneList(struct AclEntry
**a_aclPP
)
295 struct AclEntry
**lPP
;
296 struct AclEntry
*tP
, *nP
;
301 for (tP
= *a_aclPP
; tP
; tP
= nP
) {
302 if (tP
->rights
== 0) {
318 /*------------------------------------------------------------------------
322 * Skip chars until we eat a newline.
325 * a_str : String to process.
328 * Ptr to the first char past the newline.
331 * Nothing interesting.
335 *------------------------------------------------------------------------*/
338 SkipLine(char *a_str
)
341 while (*a_str
!= '\n')
349 /*------------------------------------------------------------------------
353 * Create an empty internalized ACL.
359 * Ptr to an initialized and empty internalized ACL.
362 * Nothing interesting.
366 *------------------------------------------------------------------------*/
374 tp
= malloc(sizeof(struct Acl
));
375 tp
->nplus
= tp
->nminus
= 0;
376 tp
->pluslist
= tp
->minuslist
= 0;
382 /*------------------------------------------------------------------------
386 * Given an externalized ACL (i.e., in string format), convert it
387 * into its internalized form.
390 * a_str : Ptr to Externalized ACL.
393 * Ptr to the equivalent internalized ACL.
396 * Nothing interesting.
400 *------------------------------------------------------------------------*/
403 ParseAcl(char *a_str
)
406 int nplus
, nminus
, i
, trights
;
408 struct AclEntry
*first
, *last
, *tl
;
412 * Pull out the number of positive & negative entries in the externalized
415 sscanf(a_str
, "%d", &nplus
);
416 a_str
= SkipLine(a_str
);
417 sscanf(a_str
, "%d", &nminus
);
418 a_str
= SkipLine(a_str
);
421 * Allocate and initialize the first entry.
423 ta
= malloc(sizeof(struct Acl
));
428 * Translate the positive entries.
432 for (i
= 0; i
< nplus
; i
++) {
433 sscanf(a_str
, "%100s %d", tname
, &trights
);
434 a_str
= SkipLine(a_str
);
435 tl
= malloc(sizeof(struct AclEntry
));
438 strcpy(tl
->name
, tname
);
439 tl
->rights
= trights
;
445 ta
->pluslist
= first
;
448 * Translate the negative entries.
452 for (i
= 0; i
< nminus
; i
++) {
453 sscanf(a_str
, "%100s %d", tname
, &trights
);
454 a_str
= SkipLine(a_str
);
455 tl
= malloc(sizeof(struct AclEntry
));
458 strcpy(tl
->name
, tname
);
459 tl
->rights
= trights
;
465 ta
->minuslist
= first
;
472 /*------------------------------------------------------------------------
476 * Given an internalized ACL, convert it to its externalized form,
477 * namely a character string.
480 * a_acl : Internalized ACL to externalize.
483 * Ptr to the externalized version.
486 * Nothing interesting.
490 *------------------------------------------------------------------------*/
493 AclToString(struct Acl
*a_acl
)
496 static char mydata
[AFS_PIOCTL_MAXSIZE
];
497 char tstring
[AFS_PIOCTL_MAXSIZE
];
501 * Print out the number of positive & negative entries on one line.
503 sprintf(mydata
, "%d\n%d\n", a_acl
->nplus
, a_acl
->nminus
);
506 * Externalize the positive list.
508 for (tp
= a_acl
->pluslist
; tp
; tp
= tp
->next
) {
509 sprintf(tstring
, "%s %d\n", tp
->name
, tp
->rights
);
510 strcat(mydata
, tstring
);
514 * Externalize the negative list.
516 for (tp
= a_acl
->minuslist
; tp
; tp
= tp
->next
) {
517 sprintf(tstring
, "%s %d\n", tp
->name
, tp
->rights
);
518 strcat(mydata
, tstring
);
525 /*------------------------------------------------------------------------
526 * static uss_acl_SetAccess
529 * ACL comes in as a single string, prefixed with the pathname to
530 * which the ACL is applied. The a_clear argument, if set, causes
531 * us to act like sac instead of sa.
535 *------------------------------------------------------------------------*/
538 uss_acl_SetAccess(char *a_access
, int a_clear
, int a_negative
)
539 { /*uss_acl_SetAccess */
543 static char rn
[] = "uss_acl_SetAccess";
546 char *externalizedACL
;
549 char tmp_str
[AFS_PIOCTL_MAXSIZE
];
550 char path_field
[AFS_PIOCTL_MAXSIZE
], user_field
[64], rights_field
[64], *tp
;
556 * Pull out the pathname from our argument.
558 tp
= uss_common_FieldCp(path_field
, a_access
, ' ', sizeof(path_field
),
561 fprintf(stderr
, "%s: * Pathname field too long (max is %" AFS_SIZET_FMT
" chars)\n",
562 uss_whoami
, sizeof(path_field
));
567 * Ask the Cache Manager to give us the externalized ACL for the
570 code
= uss_fs_GetACL(path_field
, tmp_str
, AFS_PIOCTL_MAXSIZE
);
572 afs_com_err(uss_whoami
, code
, "while getting access list for %s",
575 printf("%s: Error code from uss_fs_GetACL %d, errno %d\n", rn
, code
,
577 #endif /* USS_ACL_DB */
582 printf("%s: ACL for pathname '%s' is: '%s'\n", rn
, path_field
,
584 #endif /* USS_ACL_DB */
587 * Generate the proper internalized ACL.
592 ta
= ParseAcl(tmp_str
);
595 * For each given entry, pull out the information and alter the
596 * internalized ACL to reflect it.
598 while (*tp
!= '\0') {
599 tp
= uss_common_FieldCp(user_field
, tp
, ' ', 64, &overflow
);
601 fprintf(stderr
, "%s: * User field too long (max is 64 chars)\n",
606 printf("%s: Missing second half of user/access pair.\n",
610 tp
= uss_common_FieldCp(rights_field
, tp
, ' ', 64, &overflow
);
612 fprintf(stderr
, "%s: * Rights field too long (max is 64 chars)\n",
616 rights
= Convert(rights_field
);
617 ChangeList(ta
, plusp
, user_field
, rights
);
621 * Externalize the fully-processed internal ACL, then pass it back
622 * to the Cache Manager.
624 externalizedACL
= AclToString(ta
);
626 uss_fs_SetACL(path_field
, externalizedACL
,
627 strlen(externalizedACL
) + 1);
630 printf("%s: uss_fs_SetACL() failed, code is %d, errno is %d\n", rn
,
632 #endif /* USS_ACL_DB */
633 if (errno
== EINVAL
) {
634 printf("Can't set ACL for directory '%s' to '%s'\n", path_field
,
636 printf("Invalid argument, possible reasons include:\n");
637 printf("\t1. File not in AFS, or\n");
638 printf("\t2. Too many users on the ACL, or\n");
639 printf("\t3. Non-existent user or group on ACL.\n");
642 afs_com_err(uss_whoami
, code
, "while setting the access list");
648 } /*uss_acl_SetAccess */
651 /*------------------------------------------------------------------------
652 * static us_acl_SetDiskQuota
655 * Nothing interesting.
659 *------------------------------------------------------------------------*/
662 uss_acl_SetDiskQuota(char *a_path
, int a_q
)
663 { /*uss_acl_SetDiskQuota */
667 static char rn
[] = "uss_acl_SetDiskQuota";
669 uss_VolumeStatus_t
*status
;
671 char tmp_str
[AFS_PIOCTL_MAXSIZE
];
675 "Setting disk quota on volume mounted at '%s' to %d blocks\n",
678 status
= (uss_VolumeStatus_t
*) tmp_str
;
679 status
->MinQuota
= status
->MaxQuota
= -1;
680 status
->MaxQuota
= a_q
;
682 input
= (char *)status
+ sizeof(*status
);
687 code
= uss_fs_SetVolStat(a_path
, tmp_str
, sizeof(*status
) + 3);
689 afs_com_err(uss_whoami
, code
, "while setting disk quota");
691 printf("%s: uss_fs_SetVolStat() error code: %d, errno is %d\n", rn
,
693 #endif /* USS_ACL_DB */
699 } /*uss_acl_SetDiskQuota */
702 /*-----------------------------------------------------------------------
703 * EXPORTED uss_acl_CleanUp
706 * The uss_currentDir variable contains directories touched by the
711 *------------------------------------------------------------------------*/
714 uss_acl_CleanUp(void)
715 { /*uss_acl_CleanUp */
717 struct uss_subdir
*t
, *old_t
= NULL
;
718 char tmp_str
[uss_MAX_SIZE
];
721 * Restore the ACL for each directory created for our caller to its
722 * original setting. The uss_AccountCreator's access was (potentially)
723 * amplified to full rights - any excess ability must now be removed.
725 for (t
= uss_currentDir
; t
!= NULL
; t
= t
->previous
) {
726 sprintf(tmp_str
, "%s %s", t
->path
, t
->finalACL
);
728 fprintf(stderr
, "Setting ACL: '%s'\n", tmp_str
);
730 uss_acl_SetAccess(tmp_str
, 1, 0);
732 fprintf(stderr
, "\t[Dry run: uss_acl_SetAccess(%s) on '%s']\n",
738 } /*Remove caller from user directory ACL */
744 * Return successfully.
748 } /*uss_acl_CleanUp */