/* 1. is this directory in AFS? * 2. Is every component of the pathname secure * (ie, only system:administrators have w or a rights)? */ static int is_secure(char *dir) { char *temp; struct ViceIoctl blob; struct AclEntry *te; char space[2046]; afs_int32 code; struct Acl *ta; if (!InAFS(dir)) /* final component *must* be in AFS */ return 0; #ifndef INSECURE for (temp = safestrtok(dir, "/"); temp; temp = safestrtok(NULL, "/")) { /* strtok keeps sticking NUL in place of /, so we can look at * ever-longer chunks of the path. */ if (!InAFS(dir)) continue; blob.out_size = AFS_PIOCTL_MAXSIZE; blob.in_size = 0; blob.out = space; code = pioctl(dir, VIOCGETAL, &blob, 1); if (code) { continue; } ta = ParseAcl(space); if (ta->nplus <= 0) continue; for (te = ta->pluslist; te; te = te->next) { if (((te->rights & PRSFS_INSERT) && (te->rights & PRSFS_DELETE)) || (te->rights & (PRSFS_WRITE | PRSFS_ADMINISTER))) if (strcmp(te->name, "system:administrators")) return 0; /* somebody who we can't trust has got power */ } } #endif /* INSECURE */ return 1; }
afs_int32 uss_acl_SetAccess(char *a_access, int a_clear, int a_negative) { /*uss_acl_SetAccess */ afs_int32 code; #ifdef USS_ACL_DB static char rn[] = "uss_acl_SetAccess"; #endif struct Acl *ta; char *externalizedACL; int plusp; afs_int32 rights; char tmp_str[AFS_PIOCTL_MAXSIZE]; char path_field[AFS_PIOCTL_MAXSIZE], user_field[64], rights_field[64], *tp; int overflow; plusp = !a_negative; /* * Pull out the pathname from our argument. */ tp = uss_common_FieldCp(path_field, a_access, ' ', sizeof(path_field), &overflow); if (overflow) { fprintf(stderr, "%s: * Pathname field too long (max is %" AFS_SIZET_FMT " chars)\n", uss_whoami, sizeof(path_field)); return (-1); } /* * Ask the Cache Manager to give us the externalized ACL for the * given directory. */ code = uss_fs_GetACL(path_field, tmp_str, AFS_PIOCTL_MAXSIZE); if (code) { afs_com_err(uss_whoami, code, "while getting access list for %s", path_field); #ifdef USS_ACL_DB printf("%s: Error code from uss_fs_GetACL %d, errno %d\n", rn, code, errno); #endif /* USS_ACL_DB */ return (code); } #ifdef USS_ACL_DB else printf("%s: ACL for pathname '%s' is: '%s'\n", rn, path_field, tmp_str); #endif /* USS_ACL_DB */ /* * Generate the proper internalized ACL. */ if (a_clear) ta = EmptyAcl(); else ta = ParseAcl(tmp_str); /* * For each given entry, pull out the information and alter the * internalized ACL to reflect it. */ while (*tp != '\0') { tp = uss_common_FieldCp(user_field, tp, ' ', 64, &overflow); if (overflow) { fprintf(stderr, "%s: * User field too long (max is 64 chars)\n", uss_whoami); return (-1); } if (*tp == '\0') { printf("%s: Missing second half of user/access pair.\n", uss_whoami); return (1); } tp = uss_common_FieldCp(rights_field, tp, ' ', 64, &overflow); if (overflow) { fprintf(stderr, "%s: * Rights field too long (max is 64 chars)\n", uss_whoami); return (-1); } rights = Convert(rights_field); ChangeList(ta, plusp, user_field, rights); } /* * Externalize the fully-processed internal ACL, then pass it back * to the Cache Manager. */ externalizedACL = AclToString(ta); code = uss_fs_SetACL(path_field, externalizedACL, strlen(externalizedACL) + 1); if (code) { #ifdef USS_ACL_DB printf("%s: uss_fs_SetACL() failed, code is %d, errno is %d\n", rn, code, errno); #endif /* USS_ACL_DB */ if (errno == EINVAL) { printf("Can't set ACL for directory '%s' to '%s'\n", path_field, externalizedACL); printf("Invalid argument, possible reasons include:\n"); printf("\t1. File not in AFS, or\n"); printf("\t2. Too many users on the ACL, or\n"); printf("\t3. Non-existent user or group on ACL.\n"); return (code); } else { afs_com_err(uss_whoami, code, "while setting the access list"); return (code); } } return (0); } /*uss_acl_SetAccess */