static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm) { int ret; acl_permset_t permset; if ((ret = acl_get_permset(entry, &permset)) != 0) { return ret; } if ((ret = acl_clear_perms(permset)) != 0) { return ret; } if ((perm & SMB_ACL_READ) && ((ret = acl_add_perm(permset, ACL_READ)) != 0)) { return ret; } if ((perm & SMB_ACL_WRITE) && ((ret = acl_add_perm(permset, ACL_WRITE)) != 0)) { return ret; } if ((perm & SMB_ACL_EXECUTE) && ((ret = acl_add_perm(permset, ACL_EXECUTE)) != 0)) { return ret; } return acl_set_permset(entry, permset); }
static void setmode(acl_permset_t *permset_p, int mode) { if (mode & ACL_READ) { acl_add_perm(*permset_p, ACL_READ); } if (mode & ACL_WRITE) { acl_add_perm(*permset_p, ACL_WRITE); } if (mode & ACL_EXECUTE) { acl_add_perm(*permset_p, ACL_EXECUTE); } }
/* Add the perms specified in modifier to rentry */ static int merge_entry_perms(acl_entry_t rentry, acl_entry_t modifier) { acl_permset_t rperms, mperms; acl_flagset_t rflags, mflags; int i; if ((acl_get_permset(rentry, &rperms) != 0) || (acl_get_flagset_np(rentry, &rflags) != 0) || (acl_get_permset(modifier, &mperms) != 0) || (acl_get_flagset_np(modifier, &mflags) != 0)) err(1, "error computing ACL modification"); for (i = 0; acl_perms[i].name != NULL; i++) { if (acl_get_perm_np(mperms, acl_perms[i].perm)) acl_add_perm(rperms, acl_perms[i].perm); } for (i = 0; acl_flags[i].name != NULL; i++) { if (acl_get_flag_np(mflags, acl_flags[i].flag)) acl_add_flag_np(rflags, acl_flags[i].flag); } acl_set_permset(rentry, rperms); acl_set_flagset_np(rentry, rflags); return 0; }
/* Add the perms specified in modifier to rentry */ static int merge_entry_perms(acl_entry_t rentry, acl_entry_t modifier) { acl_permset_t rperms, mperms; acl_flagset_t rflags, mflags; int i; if ((acl_get_permset(rentry, &rperms) != 0) || (acl_get_flagset_np(rentry, &rflags) != 0) || (acl_get_permset(modifier, &mperms) != 0) || (acl_get_flagset_np(modifier, &mflags) != 0)) { // err(1, "error computing ACL modification"); fprintf(stderr, "chmod: error computing ACL modification: %s\n", strerror(errno)); pthread_exit(NULL); } for (i = 0; acl_perms[i].name != NULL; i++) { if (acl_get_perm_np(mperms, acl_perms[i].perm)) acl_add_perm(rperms, acl_perms[i].perm); } for (i = 0; acl_flags[i].name != NULL; i++) { if (acl_get_flag_np(mflags, acl_flags[i].flag)) acl_add_flag_np(rflags, acl_flags[i].flag); } acl_set_permset(rentry, rperms); acl_set_flagset_np(rentry, rflags); return 0; }
static void set_permset (acl_permset_t permset, mode_t perm) { if (perm & CMD_PERM_READ) acl_add_perm (permset, ACL_READ); else acl_delete_perm (permset, ACL_READ); if (perm & CMD_PERM_WRITE) acl_add_perm (permset, ACL_WRITE); else acl_delete_perm (permset, ACL_WRITE); if (perm & CMD_PERM_EXECUTE) acl_add_perm (permset, ACL_EXECUTE); else acl_delete_perm (permset, ACL_EXECUTE); }
/** * update a perm_set_t in entry to the one in aclentry * entry: acl entry to change from in-memory * acl_entry: where to retrieve new perms from * returns status **/ static _BOOL acl_update_perm(acl_entry_t *entry,acl_entry_in *entry_in){ if(entry_in == NULL) return; acl_permset_t perm_set; if(acl_get_permset(*entry,&perm_set)!=ACL_OK) return FALSE; if(((entry_in->permset.nibble&READ) ? acl_add_perm(perm_set,ACL_READ) : acl_delete_perm(perm_set,ACL_READ))!=ACL_OK) return FALSE; if(((entry_in->permset.nibble&WRITE)? acl_add_perm(perm_set,ACL_WRITE) : acl_delete_perm(perm_set,ACL_WRITE))!=ACL_OK) return FALSE; if(((entry_in->permset.nibble&EXEC) ? acl_add_perm(perm_set,ACL_EXECUTE): acl_delete_perm(perm_set,ACL_EXECUTE))!=ACL_OK) return FALSE; if(acl_set_permset(*entry,perm_set)!=ACL_OK) return FALSE; return TRUE; }
static void set_perm( acl_entry_t ent, mode_t add, mode_t remove) { acl_permset_t set; acl_get_permset(ent, &set); if (remove & CMD_PERM_READ) acl_delete_perm(set, ACL_READ); if (remove & CMD_PERM_WRITE) acl_delete_perm(set, ACL_WRITE); if (remove & CMD_PERM_EXECUTE) acl_delete_perm(set, ACL_EXECUTE); if (add & CMD_PERM_READ) acl_add_perm(set, ACL_READ); if (add & CMD_PERM_WRITE) acl_add_perm(set, ACL_WRITE); if (add & CMD_PERM_EXECUTE) acl_add_perm(set, ACL_EXECUTE); }
static void setPerms(acl_entry_t entry, int perms) { acl_permset_t permset; if (acl_get_permset(entry, &permset) == -1) errExit("acl_get_permset"); if (acl_clear_perms(permset) == -1) errExit("acl_clear_perms"); if (perms & ACL_READ) if (acl_add_perm(permset, ACL_READ) == -1) errExit("acl_add_perm"); if (perms & ACL_WRITE) if (acl_add_perm(permset, ACL_WRITE) == -1) errExit("acl_add_perm"); if (perms & ACL_EXECUTE) if (acl_add_perm(permset, ACL_EXECUTE) == -1) errExit("acl_add_perm"); if (acl_set_permset(entry, permset) == -1) errExit("acl_set_permset"); }
static int fix_acl(int fd, uid_t uid) { #ifdef HAVE_ACL _cleanup_(acl_freep) acl_t acl = NULL; acl_entry_t entry; acl_permset_t permset; assert(fd >= 0); if (uid <= SYSTEM_UID_MAX) return 0; /* Make sure normal users can read (but not write or delete) * their own coredumps */ acl = acl_get_fd(fd); if (!acl) { log_error("Failed to get ACL: %m"); return -errno; } if (acl_create_entry(&acl, &entry) < 0 || acl_set_tag_type(entry, ACL_USER) < 0 || acl_set_qualifier(entry, &uid) < 0) { log_error("Failed to patch ACL: %m"); return -errno; } if (acl_get_permset(entry, &permset) < 0 || acl_add_perm(permset, ACL_READ) < 0 || calc_acl_mask_if_needed(&acl) < 0) { log_warning("Failed to patch ACL: %m"); return -errno; } if (acl_set_fd(fd, acl) < 0) { log_error("Failed to apply ACL: %m"); return -errno; } #endif return 0; }
static int fix_acl(int fd, uid_t uid) { #if HAVE_ACL _cleanup_(acl_freep) acl_t acl = NULL; acl_entry_t entry; acl_permset_t permset; int r; assert(fd >= 0); if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY) return 0; /* Make sure normal users can read (but not write or delete) * their own coredumps */ acl = acl_get_fd(fd); if (!acl) return log_error_errno(errno, "Failed to get ACL: %m"); if (acl_create_entry(&acl, &entry) < 0 || acl_set_tag_type(entry, ACL_USER) < 0 || acl_set_qualifier(entry, &uid) < 0) return log_error_errno(errno, "Failed to patch ACL: %m"); if (acl_get_permset(entry, &permset) < 0 || acl_add_perm(permset, ACL_READ) < 0) return log_warning_errno(errno, "Failed to patch ACL: %m"); r = calc_acl_mask_if_needed(&acl); if (r < 0) return log_warning_errno(r, "Failed to patch ACL: %m"); if (acl_set_fd(fd, acl) < 0) return log_error_errno(errno, "Failed to apply ACL: %m"); #endif return 0; }
void cupsdAddCert(int pid, /* I - Process ID */ const char *username, /* I - Username */ int type) /* I - AuthType for username */ { int i; /* Looping var */ cupsd_cert_t *cert; /* Current certificate */ int fd; /* Certificate file */ char filename[1024]; /* Certificate filename */ static const char hex[] = "0123456789ABCDEF"; /* Hex constants... */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddCert: Adding certificate for PID %d", pid); /* * Allocate memory for the certificate... */ if ((cert = calloc(sizeof(cupsd_cert_t), 1)) == NULL) return; /* * Fill in the certificate information... */ cert->pid = pid; cert->type = type; strlcpy(cert->username, username, sizeof(cert->username)); for (i = 0; i < 32; i ++) cert->certificate[i] = hex[CUPS_RAND() & 15]; /* * Save the certificate to a file readable only by the User and Group * (or root and SystemGroup for PID == 0)... */ snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, pid); unlink(filename); if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400)) < 0) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create certificate file %s - %s", filename, strerror(errno)); free(cert); return; } if (pid == 0) { #ifdef HAVE_ACL_INIT acl_t acl; /* ACL information */ acl_entry_t entry; /* ACL entry */ acl_permset_t permset; /* Permissions */ # ifdef HAVE_MBR_UID_TO_UUID uuid_t group; /* Group ID */ # endif /* HAVE_MBR_UID_TO_UUID */ static int acls_not_supported = 0; /* Only warn once */ #endif /* HAVE_ACL_INIT */ /* * Root certificate... */ fchmod(fd, 0440); fchown(fd, RunUser, SystemGroupIDs[0]); cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddCert: NumSystemGroups=%d", NumSystemGroups); #ifdef HAVE_ACL_INIT if (NumSystemGroups > 1) { /* * Set POSIX ACLs for the root certificate so that all system * groups can access it... */ int j; /* Looping var */ # ifdef HAVE_MBR_UID_TO_UUID /* * On MacOS X, ACLs use UUIDs instead of GIDs... */ acl = acl_init(NumSystemGroups - 1); for (i = 1; i < NumSystemGroups; i ++) { /* * Add each group ID to the ACL... */ for (j = 0; j < i; j ++) if (SystemGroupIDs[j] == SystemGroupIDs[i]) break; if (j < i) continue; /* Skip duplicate groups */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ_DATA); acl_set_tag_type(entry, ACL_EXTENDED_ALLOW); mbr_gid_to_uuid((gid_t)SystemGroupIDs[i], group); acl_set_qualifier(entry, &group); acl_set_permset(entry, permset); } # else /* * POSIX ACLs need permissions for owner, group, other, and mask * in addition to the rest of the system groups... */ acl = acl_init(NumSystemGroups + 3); /* Owner */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ); acl_set_tag_type(entry, ACL_USER_OBJ); acl_set_permset(entry, permset); /* Group */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ); acl_set_tag_type(entry, ACL_GROUP_OBJ); acl_set_permset(entry, permset); /* Others */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, 0); acl_set_tag_type(entry, ACL_OTHER); acl_set_permset(entry, permset); /* Mask */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ); acl_set_tag_type(entry, ACL_MASK); acl_set_permset(entry, permset); for (i = 1; i < NumSystemGroups; i ++) { /* * Add each group ID to the ACL... */ for (j = 0; j < i; j ++) if (SystemGroupIDs[j] == SystemGroupIDs[i]) break; if (j < i) continue; /* Skip duplicate groups */ acl_create_entry(&acl, &entry); acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ); acl_set_tag_type(entry, ACL_GROUP); acl_set_qualifier(entry, SystemGroupIDs + i); acl_set_permset(entry, permset); } if (acl_valid(acl)) { char *text, *textptr; /* Temporary string */ cupsdLogMessage(CUPSD_LOG_ERROR, "ACL did not validate: %s", strerror(errno)); text = acl_to_text(acl, NULL); for (textptr = strchr(text, '\n'); textptr; textptr = strchr(textptr + 1, '\n')) *textptr = ','; cupsdLogMessage(CUPSD_LOG_ERROR, "ACL: %s", text); acl_free(text); } # endif /* HAVE_MBR_UID_TO_UUID */ if (acl_set_fd(fd, acl)) { if (errno != EOPNOTSUPP || !acls_not_supported) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to set ACLs on root certificate \"%s\" - %s", filename, strerror(errno)); if (errno == EOPNOTSUPP) acls_not_supported = 1; } acl_free(acl); } #endif /* HAVE_ACL_INIT */ RootCertTime = time(NULL); } else { /* * CGI certificate... */ fchmod(fd, 0400); fchown(fd, User, Group); } DEBUG_printf(("ADD pid=%d, username=%s, cert=%s\n", pid, username, cert->certificate)); write(fd, cert->certificate, strlen(cert->certificate)); close(fd); /* * Insert the certificate at the front of the list... */ cert->next = Certs; Certs = cert; }
int devnode_acl(const char *path, bool flush, bool del, uid_t old_uid, bool add, uid_t new_uid) { acl_t acl; int r = 0; bool changed = false; assert(path); acl = acl_get_file(path, ACL_TYPE_ACCESS); if (!acl) return -errno; if (flush) { r = flush_acl(acl); if (r < 0) goto finish; if (r > 0) changed = true; } else if (del && old_uid > 0) { acl_entry_t entry; r = acl_find_uid(acl, old_uid, &entry); if (r < 0) goto finish; if (r > 0) { if (acl_delete_entry(acl, entry) < 0) { r = -errno; goto finish; } changed = true; } } if (add && new_uid > 0) { acl_entry_t entry; acl_permset_t permset; int rd, wt; r = acl_find_uid(acl, new_uid, &entry); if (r < 0) goto finish; if (r == 0) { if (acl_create_entry(&acl, &entry) < 0) { r = -errno; goto finish; } if (acl_set_tag_type(entry, ACL_USER) < 0 || acl_set_qualifier(entry, &new_uid) < 0) { r = -errno; goto finish; } } if (acl_get_permset(entry, &permset) < 0) { r = -errno; goto finish; } rd = acl_get_perm(permset, ACL_READ); if (rd < 0) { r = -errno; goto finish; } wt = acl_get_perm(permset, ACL_WRITE); if (wt < 0) { r = -errno; goto finish; } if (!rd || !wt) { if (acl_add_perm(permset, ACL_READ|ACL_WRITE) < 0) { r = -errno; goto finish; } changed = true; } } if (!changed) goto finish; if (acl_calc_mask(&acl) < 0) { r = -errno; goto finish; } if (acl_set_file(path, ACL_TYPE_ACCESS, acl) < 0) { r = -errno; goto finish; } r = 0; finish: acl_free(acl); return r; }
static int ParseModePosixLinux(char *mode, acl_permset_t perms) { int retv; int more_entries; acl_perm_t perm; enum { add, del } op; op = add; if (*mode == '\0' || *mode == ':') { if (acl_clear_perms(perms) != 0) { Log(LOG_LEVEL_ERR, "Error clearing perms. (acl_clear_perms: %s)", GetErrorStr()); return false; } else { return true; } } more_entries = true; while (more_entries) { switch (*mode) { case '+': op = add; mode++; break; case '-': op = del; mode++; break; case '=': mode++; // fallthrough default: // if mode does not start with + or -, we clear existing perms op = add; if (acl_clear_perms(perms) != 0) { Log(LOG_LEVEL_ERR, "Unable to clear ACL permissions. (acl_clear_perms: %s)", GetErrorStr()); return false; } } // parse generic perms (they are 1-1 on Posix) while (*mode != '\0' && strchr(CF_VALID_GPERMS, *mode)) { if (*mode == '\0') { break; } switch (*mode) { case 'r': perm = ACL_READ; break; case 'w': perm = ACL_WRITE; break; case 'x': perm = ACL_EXECUTE; break; default: Log(LOG_LEVEL_ERR, "No linux support for generic permission flag '%c'", *mode); return false; } if (op == add) { retv = acl_add_perm(perms, perm); } else { retv = acl_delete_perm(perms, perm); } if (retv != 0) { Log(LOG_LEVEL_ERR, "Could not change ACE permission. (acl_[add|delete]_perms: %s)", GetErrorStr()); return false; } mode++; } // parse native perms if (*mode == CF_NATIVE_PERMS_SEP_START) { mode++; while (*mode != '\0' && strchr(CF_VALID_NPERMS_POSIX, *mode)) { switch (*mode) { case 'r': perm = ACL_READ; break; case 'w': perm = ACL_WRITE; break; case 'x': perm = ACL_EXECUTE; break; default: Log(LOG_LEVEL_ERR, "No linux support for native permission flag '%c'", *mode); return false; } if (op == add) { retv = acl_add_perm(perms, perm); } else { retv = acl_delete_perm(perms, perm); } if (retv != 0) { Log(LOG_LEVEL_ERR, "Could not change ACE permission. (acl_[add|delete]_perm: %s)", GetErrorStr()); return false; } mode++; } // scan past native perms end seperator mode++; } if (*mode == ',') { more_entries = true; mode++; } else { more_entries = false; } } return true; }
/* * return an ACL corresponding to the permissions * contained in struct stat */ static acl_t acl_from_stat(struct stat sb) { acl_t acl; acl_entry_t entry; acl_permset_t perms; /* create the ACL */ acl = acl_init(3); if (!acl) return NULL; /* First entry: ACL_USER_OBJ */ if (acl_create_entry(&acl, &entry) == -1) return NULL; if (acl_set_tag_type(entry, ACL_USER_OBJ) == -1) return NULL; if (acl_get_permset(entry, &perms) == -1) return NULL; if (acl_clear_perms(perms) == -1) return NULL; /* calculate user mode */ if (sb.st_mode & S_IRUSR) if (acl_add_perm(perms, ACL_READ) == -1) return NULL; if (sb.st_mode & S_IWUSR) if (acl_add_perm(perms, ACL_WRITE) == -1) return NULL; if (sb.st_mode & S_IXUSR) if (acl_add_perm(perms, ACL_EXECUTE) == -1) return NULL; if (acl_set_permset(entry, perms) == -1) return NULL; /* Second entry: ACL_GROUP_OBJ */ if (acl_create_entry(&acl, &entry) == -1) return NULL; if (acl_set_tag_type(entry, ACL_GROUP_OBJ) == -1) return NULL; if (acl_get_permset(entry, &perms) == -1) return NULL; if (acl_clear_perms(perms) == -1) return NULL; /* calculate group mode */ if (sb.st_mode & S_IRGRP) if (acl_add_perm(perms, ACL_READ) == -1) return NULL; if (sb.st_mode & S_IWGRP) if (acl_add_perm(perms, ACL_WRITE) == -1) return NULL; if (sb.st_mode & S_IXGRP) if (acl_add_perm(perms, ACL_EXECUTE) == -1) return NULL; if (acl_set_permset(entry, perms) == -1) return NULL; /* Third entry: ACL_OTHER */ if (acl_create_entry(&acl, &entry) == -1) return NULL; if (acl_set_tag_type(entry, ACL_OTHER) == -1) return NULL; if (acl_get_permset(entry, &perms) == -1) return NULL; if (acl_clear_perms(perms) == -1) return NULL; /* calculate other mode */ if (sb.st_mode & S_IROTH) if (acl_add_perm(perms, ACL_READ) == -1) return NULL; if (sb.st_mode & S_IWOTH) if (acl_add_perm(perms, ACL_WRITE) == -1) return NULL; if (sb.st_mode & S_IXOTH) if (acl_add_perm(perms, ACL_EXECUTE) == -1) return NULL; if (acl_set_permset(entry, perms) == -1) return NULL; return(acl); }
acl_t pfl_acl_from_xattr(const void *buf, size_t size) { int i, entries; const struct acl_ea_header *h = buf; const struct acl_ea_entry *xe = PSC_AGP(h + 1, 0); unsigned int xperms; acl_permset_t permset; acl_entry_t e; acl_tag_t tag; acl_t a; if (size < sizeof(*h)) { errno = EINVAL; return (NULL); } if (le32toh(h->version) != ACL_EA_VERSION) { errno = EINVAL; return (NULL); } size -= sizeof(*h); if (size % sizeof(*xe)) { errno = EINVAL; return (NULL); } entries = size / sizeof(*xe); a = acl_init(entries); if (a == NULL) return (NULL); for (i = 0; i < entries; i++, xe++) { acl_create_entry(&a, &e); if (acl_get_permset(e, &permset) == -1) psclog_error("get_permset"); acl_clear_perms(permset); xperms = le16toh(xe->perm); if (xperms & ACL_READ) acl_add_perm(permset, ACL_READ); if (xperms & ACL_WRITE) acl_add_perm(permset, ACL_WRITE); if (xperms & ACL_EXECUTE) acl_add_perm(permset, ACL_EXECUTE); if (acl_set_permset(e, permset) == -1) psclog_error("set_permset"); acl_set_tag_type(e, tag = le16toh(xe->tag)); switch (tag) { case ACL_USER: { uid_t uid = le32toh(xe->id); acl_set_qualifier(e, &uid); break; } case ACL_GROUP: { gid_t gid = le32toh(xe->id); acl_set_qualifier(e, &gid); break; } } } return (a); }
/* Convert an acl entry in string form to an acl_entry_t */ int parse_entry(char *entrybuf, acl_entry_t newent) { char *tok; char *pebuf; uuid_t *entryg; acl_tag_t tag; acl_permset_t perms; acl_flagset_t flags; unsigned permcount = 0; unsigned pindex = 0; char *delimiter = " "; int nametype = NAME_EITHER; acl_get_permset(newent, &perms); acl_get_flagset_np(newent, &flags); pebuf = entrybuf; if (0 == strncmp(entrybuf, "user:"******"group:", 6)) { nametype = NAME_GROUP; pebuf += 6; } if (strchr(pebuf, ':')) /* User/Group names can have spaces */ delimiter = ":"; tok = strsep(&pebuf, delimiter); if ((tok == NULL) || *tok == '\0') { // errx(1, "Invalid entry format -- expected user or group name"); fprintf(stderr, "chmod: Invalid entry format -- expected user or group name\n"); pthread_exit(NULL); } /* parse the name into a qualifier */ entryg = name_to_uuid(tok, nametype); tok = strsep(&pebuf, ": "); /* Stick with delimiter? */ if ((tok == NULL) || *tok == '\0') { // errx(1, "Invalid entry format -- expected allow or deny"); fprintf(stderr, "chmod: Invalid entry format -- expected allow or deny\n"); pthread_exit(NULL); } /* is the verb 'allow' or 'deny'? */ if (!strcmp(tok, "allow")) { tag = ACL_EXTENDED_ALLOW; } else if (!strcmp(tok, "deny")) { tag = ACL_EXTENDED_DENY; } else { // errx(1, "Unknown tag type '%s'", tok); fprintf(stderr, "chmod: Unknown tag type '%s'\n", tok); pthread_exit(NULL); } /* parse permissions */ for (; (tok = strsep(&pebuf, ",")) != NULL;) { if (*tok != '\0') { /* is it a permission? */ for (pindex = 0; acl_perms[pindex].name != NULL; pindex++) { if (!strcmp(acl_perms[pindex].name, tok)) { /* got one */ acl_add_perm(perms, acl_perms[pindex].perm); permcount++; goto found; } } /* is it a flag? */ for (pindex = 0; acl_flags[pindex].name != NULL; pindex++) { if (!strcmp(acl_flags[pindex].name, tok)) { /* got one */ acl_add_flag_np(flags, acl_flags[pindex].flag); permcount++; goto found; } } // errx(1,"Invalid permission type '%s'", tok); fprintf(stderr,"chmod: Invalid permission type '%s'\n", tok); pthread_exit(NULL); found: continue; } } if (0 == permcount) { // errx(1, "No permissions specified"); fprintf(stderr, "chmod: No permissions specified\n"); pthread_exit(NULL); } acl_set_tag_type(newent, tag); acl_set_qualifier(newent, entryg); acl_set_permset(newent, perms); acl_set_flagset_np(newent, flags); free(entryg); entryg = NULL; return(0); }
int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp) /* {{{ */ { struct fpm_worker_pool_config_s *c = wp->config; #ifdef HAVE_FPM_ACL int n; /* uninitialized */ wp->socket_acl = NULL; #endif wp->socket_uid = -1; wp->socket_gid = -1; wp->socket_mode = 0660; if (!c) { return 0; } if (c->listen_mode && *c->listen_mode) { wp->socket_mode = strtoul(c->listen_mode, 0, 8); } #ifdef HAVE_FPM_ACL /* count the users and groups configured */ n = 0; if (c->listen_acl_users && *c->listen_acl_users) { char *p; n++; for (p=strchr(c->listen_acl_users, ',') ; p ; p=strchr(p+1, ',')) { n++; } } if (c->listen_acl_groups && *c->listen_acl_groups) { char *p; n++; for (p=strchr(c->listen_acl_groups, ',') ; p ; p=strchr(p+1, ',')) { n++; } } /* if ACL configured */ if (n) { acl_t acl; acl_entry_t entry; acl_permset_t perm; char *tmp, *p, *end; acl = acl_init(n); if (!acl) { zlog(ZLOG_SYSERROR, "[pool %s] cannot allocate ACL", wp->config->name); return -1; } /* Create USER ACL */ if (c->listen_acl_users && *c->listen_acl_users) { struct passwd *pwd; tmp = estrdup(c->listen_acl_users); for (p=tmp ; p ; p=end) { if ((end = strchr(p, ','))) { *end++ = 0; } pwd = getpwnam(p); if (pwd) { zlog(ZLOG_DEBUG, "[pool %s] user '%s' have uid=%d", wp->config->name, p, pwd->pw_uid); } else { zlog(ZLOG_SYSERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, p); acl_free(acl); efree(tmp); return -1; } if (0 > acl_create_entry(&acl, &entry) || 0 > acl_set_tag_type(entry, ACL_USER) || 0 > acl_set_qualifier(entry, &pwd->pw_uid) || 0 > acl_get_permset(entry, &perm) || 0 > acl_clear_perms (perm) || 0 > acl_add_perm (perm, ACL_READ) || 0 > acl_add_perm (perm, ACL_WRITE)) { zlog(ZLOG_SYSERROR, "[pool %s] cannot create ACL for user '%s'", wp->config->name, p); acl_free(acl); efree(tmp); return -1; } } efree(tmp); } /* Create GROUP ACL */ if (c->listen_acl_groups && *c->listen_acl_groups) { struct group *grp; tmp = estrdup(c->listen_acl_groups); for (p=tmp ; p ; p=end) { if ((end = strchr(p, ','))) { *end++ = 0; } grp = getgrnam(p); if (grp) { zlog(ZLOG_DEBUG, "[pool %s] group '%s' have gid=%d", wp->config->name, p, grp->gr_gid); } else { zlog(ZLOG_SYSERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, p); acl_free(acl); efree(tmp); return -1; } if (0 > acl_create_entry(&acl, &entry) || 0 > acl_set_tag_type(entry, ACL_GROUP) || 0 > acl_set_qualifier(entry, &grp->gr_gid) || 0 > acl_get_permset(entry, &perm) || 0 > acl_clear_perms (perm) || 0 > acl_add_perm (perm, ACL_READ) || 0 > acl_add_perm (perm, ACL_WRITE)) { zlog(ZLOG_SYSERROR, "[pool %s] cannot create ACL for group '%s'", wp->config->name, p); acl_free(acl); efree(tmp); return -1; } } efree(tmp); } if (c->listen_owner && *c->listen_owner) { zlog(ZLOG_WARNING, "[pool %s] ACL set, listen.owner = '%s' is ignored", wp->config->name, c->listen_owner); } if (c->listen_group && *c->listen_group) { zlog(ZLOG_WARNING, "[pool %s] ACL set, listen.group = '%s' is ignored", wp->config->name, c->listen_group); } wp->socket_acl = acl; return 0; } /* When listen.users and listen.groups not configured, continue with standard right */ #endif if (c->listen_owner && *c->listen_owner) { struct passwd *pwd; pwd = getpwnam(c->listen_owner); if (!pwd) { zlog(ZLOG_SYSERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, c->listen_owner); return -1; } wp->socket_uid = pwd->pw_uid; wp->socket_gid = pwd->pw_gid; } if (c->listen_group && *c->listen_group) { struct group *grp; grp = getgrnam(c->listen_group); if (!grp) { zlog(ZLOG_SYSERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, c->listen_group); return -1; } wp->socket_gid = grp->gr_gid; } return 0; }
acl_t acl_from_text(const char *buf_p) { int i, error = 0, need_tag, ug_tag; char *buf, *orig_buf; char *entry, *field, *sub; uuid_t *uu = NULL; struct passwd *tpass = NULL; struct group *tgrp = NULL; acl_entry_t acl_entry; acl_flagset_t flags = NULL; acl_permset_t perms = NULL; acl_tag_t tag; acl_t acl_ret; if (buf_p == NULL) { errno = EINVAL; return NULL; } if ((buf = strdup(buf_p)) == NULL) return NULL; if ((acl_ret = acl_init(1)) == NULL) return NULL; orig_buf = buf; /* global acl flags * format: !#acl <version> [<flags>] */ if ((entry = strsep(&buf, "\n")) != NULL && *entry) { /* field 1: !#acl */ field = strsep(&entry, " "); if (*field && strncmp(field, "!#acl", strlen("!#acl"))) { error = EINVAL; goto exit; } /* field 2: <version> * currently only accepts 1 */ field = strsep(&entry, " "); errno = 0; if (!*field || strtol(field, NULL, 0) != 1) { error = EINVAL; goto exit; } /* field 3: <flags> * optional */ if((field = strsep(&entry, " ")) != NULL && *field) { acl_get_flagset_np(acl_ret, &flags); while ((sub = strsep(&field, ",")) && *sub) { for (i = 0; acl_flags[i].name != NULL; ++i) { if (acl_flags[i].type & ACL_TYPE_ACL && !strcmp(acl_flags[i].name, sub)) { acl_add_flag_np(flags, acl_flags[i].flag); break; } } if (acl_flags[i].name == NULL) { /* couldn't find flag */ error = EINVAL; goto exit; } } } } else { error = EINVAL; goto exit; } /* parse each acl line * format: <user|group>: * [<uuid>]: * [<user|group>]: * [<uid|gid>]: * <allow|deny>[,<flags>] * [:<permissions>[,<permissions>]] * * only one of the user/group identifies is required * the first one found is used */ while ((entry = strsep(&buf, "\n")) && *entry) { need_tag = 1; ug_tag = -1; /* field 1: <user|group> */ field = strsep(&entry, ":"); if(uu) bzero(uu, sizeof(uuid_t)); else if((uu = calloc(1, sizeof(uuid_t))) == NULL) { error = errno; goto exit; } if(acl_create_entry(&acl_ret, &acl_entry)) { error = errno; goto exit; } if (-1 == acl_get_flagset_np(acl_entry, &flags) || -1 == acl_get_permset(acl_entry, &perms)) { error = errno; goto exit; } switch(*field) { case 'u': if(!strcmp(field, "user")) ug_tag = ID_TYPE_UID; break; case 'g': if(!strcmp(field, "group")) ug_tag = ID_TYPE_GID; break; default: error = EINVAL; goto exit; } /* field 2: <uuid> */ if ((field = strsep(&entry, ":")) != NULL && *field) { uuid_parse(field, *uu); need_tag = 0; } /* field 3: <username|groupname> */ if ((field = strsep(&entry, ":")) != NULL && *field && need_tag) { switch(ug_tag) { case ID_TYPE_UID: if((tpass = getpwnam(field)) != NULL) if (mbr_uid_to_uuid(tpass->pw_uid, *uu) != 0) { error = EINVAL; goto exit; } break; case ID_TYPE_GID: if ((tgrp = getgrnam(field)) != NULL) if (mbr_gid_to_uuid(tgrp->gr_gid, *uu) != 0) { error = EINVAL; goto exit; } break; default: error = EINVAL; goto exit; } need_tag = 0; } /* field 4: <uid|gid> */ if ((field = strsep(&entry, ":")) != NULL && *field && need_tag) { uid_t id; error = 0; if((id = strtol(field, NULL, 10)) == 0 && error) { error = EINVAL; goto exit; } switch(ug_tag) { case ID_TYPE_UID: if((tpass = getpwuid((uid_t)id)) != NULL) if (mbr_uid_to_uuid(tpass->pw_uid, *uu) != 0) { error = EINVAL; goto exit; } break; case ID_TYPE_GID: if ((tgrp = getgrgid((gid_t)id)) != NULL) if (mbr_gid_to_uuid(tgrp->gr_gid, *uu) != 0) { error = EINVAL; goto exit; } break; } need_tag = 0; } /* sanity check: nothing set as qualifier */ if (need_tag) { error = EINVAL; goto exit; } /* field 5: <flags> */ if((field = strsep(&entry, ":")) == NULL || !*field) { error = EINVAL; goto exit; } for (tag = 0; (sub = strsep(&field, ",")) && *sub;) { if (!tag) { if (!strcmp(sub, "allow")) tag = ACL_EXTENDED_ALLOW; else if (!strcmp(sub, "deny")) tag = ACL_EXTENDED_DENY; else { error = EINVAL; goto exit; } continue; } for (i = 0; acl_flags[i].name != NULL; ++i) { if (acl_flags[i].type & (ACL_TYPE_FILE | ACL_TYPE_DIR) && !strcmp(acl_flags[i].name, sub)) { acl_add_flag_np(flags, acl_flags[i].flag); break; } } if (acl_flags[i].name == NULL) { /* couldn't find perm */ error = EINVAL; goto exit; } } /* field 6: <perms> (can be empty) */ if((field = strsep(&entry, ":")) != NULL && *field) { while ((sub = strsep(&field, ",")) && *sub) { for (i = 0; acl_perms[i].name != NULL; i++) { if (acl_perms[i].type & (ACL_TYPE_FILE | ACL_TYPE_DIR) && !strcmp(acl_perms[i].name, sub)) { acl_add_perm(perms, acl_perms[i].perm); break; } } if (acl_perms[i].name == NULL) { /* couldn't find perm */ error = EINVAL; goto exit; } } } acl_set_tag_type(acl_entry, tag); acl_set_qualifier(acl_entry, *uu); } exit: if(uu) free(uu); free(orig_buf); if (error) { acl_free(acl_ret); acl_ret = NULL; errno = error; } return acl_ret; }
int __oldacl_add_perm(acl_permset_t permset_d, oldacl_perm_t perm) { return (acl_add_perm(permset_d, perm)); }
static int set_facl(const char* filename, uid_t uid, int add) { int get; acl_t acl; acl_entry_t entry = NULL; acl_entry_t e; acl_permset_t permset; int ret; /* don't touch ACLs for root */ if (uid == 0) return 0; /* read current record */ acl = acl_get_file(filename, ACL_TYPE_ACCESS); if (!acl) return -1; /* locate ACL_USER entry for uid */ get = acl_get_entry(acl, ACL_FIRST_ENTRY, &e); while (get == 1) { acl_tag_t t; acl_get_tag_type(e, &t); if (t == ACL_USER) { uid_t *u; u = (uid_t*)acl_get_qualifier(e); if (u == NULL) { ret = -1; goto out; } if (*u == uid) { entry = e; acl_free(u); break; } acl_free(u); } get = acl_get_entry(acl, ACL_NEXT_ENTRY, &e); } /* remove ACL_USER entry for uid */ if (!add) { if (entry == NULL) { ret = 0; goto out; } acl_delete_entry(acl, entry); goto update; } /* create ACL_USER entry for uid */ if (entry == NULL) { ret = acl_create_entry(&acl, &entry); if (ret != 0) goto out; acl_set_tag_type(entry, ACL_USER); acl_set_qualifier(entry, &uid); } /* add permissions for uid */ acl_get_permset(entry, &permset); acl_add_perm(permset, ACL_READ|ACL_WRITE); update: /* update record */ if (debug) printf("%c%u %s\n", add ? '+' : '-', uid, filename); acl_calc_mask(&acl); ret = acl_set_file(filename, ACL_TYPE_ACCESS, acl); if (ret != 0) goto out; out: acl_free(acl); return ret; }
int acl_readonly_example(uuid_t *uuid) { int fd; acl_t acl; acl_entry_t ace; acl_permset_t perms; filesec_t fsec; /* initialize our ACL */ if (NULL == (acl = acl_init(32))) err(1, "acl_init()"); /* * create an ACE * * acl_create_entry_np() has a position capability via the * 'entry_index' argument (ACL_FIRST_ENTRY or ACL_LAST_ENTRY) */ if (0 != acl_create_entry(&acl, &ace)) err(1, "acl_create_entry()"); /* allow or deny */ if (0 != acl_set_tag_type(ace, ACL_EXTENDED_ALLOW)) err(1, "acl_set_tag_type()"); /* associate this with our uuid */ if (0 != acl_set_qualifier(ace, uuid)) err(1, "acl_set_qualifier()"); /* grant "read only" permissions */ if (0 != acl_get_permset(ace, &perms)) err(1, "acl_get_permset()"); if (0 != acl_clear_perms(perms)) err(1, "acl_clear_perms()"); if (0 != acl_add_perm(perms, ROPERMS)) err(1, "acl_add_perm()"); if (0 != acl_set_permset(ace, perms)) err(1, "acl_set_permset()"); /* create a file security object */ fsec = filesec_init(); /* add the ACL to the security descriptor */ filesec_set_property(fsec, FILESEC_ACL, &acl); acl_free(acl); /* turn off all other permissions on the file */ filesec_set_property(fsec, FILESEC_MODE, 0); /* create a file using our ACL */ fd = openx_np("foo", O_CREAT|O_EXCL|O_RDWR, fsec); /* clean up */ filesec_free(fsec); if (-1 != fd ) close(fd); return(fd); }
static int set_acl(struct archive *a, int fd, const char *name, struct archive_acl *abstract_acl, acl_type_t acl_type, int ae_requested_type, const char *tname) { acl_t acl; acl_entry_t acl_entry; acl_permset_t acl_permset; #ifdef ACL_TYPE_NFS4 acl_flagset_t acl_flagset; int r; #endif int ret; int ae_type, ae_permset, ae_tag, ae_id; uid_t ae_uid; gid_t ae_gid; const char *ae_name; int entries; int i; ret = ARCHIVE_OK; entries = archive_acl_reset(abstract_acl, ae_requested_type); if (entries == 0) return (ARCHIVE_OK); acl = acl_init(entries); while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type, &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) { acl_create_entry(&acl, &acl_entry); switch (ae_tag) { case ARCHIVE_ENTRY_ACL_USER: acl_set_tag_type(acl_entry, ACL_USER); ae_uid = archive_write_disk_uid(a, ae_name, ae_id); acl_set_qualifier(acl_entry, &ae_uid); break; case ARCHIVE_ENTRY_ACL_GROUP: acl_set_tag_type(acl_entry, ACL_GROUP); ae_gid = archive_write_disk_gid(a, ae_name, ae_id); acl_set_qualifier(acl_entry, &ae_gid); break; case ARCHIVE_ENTRY_ACL_USER_OBJ: acl_set_tag_type(acl_entry, ACL_USER_OBJ); break; case ARCHIVE_ENTRY_ACL_GROUP_OBJ: acl_set_tag_type(acl_entry, ACL_GROUP_OBJ); break; case ARCHIVE_ENTRY_ACL_MASK: acl_set_tag_type(acl_entry, ACL_MASK); break; case ARCHIVE_ENTRY_ACL_OTHER: acl_set_tag_type(acl_entry, ACL_OTHER); break; #ifdef ACL_TYPE_NFS4 case ARCHIVE_ENTRY_ACL_EVERYONE: acl_set_tag_type(acl_entry, ACL_EVERYONE); break; #endif default: /* XXX */ break; } #ifdef ACL_TYPE_NFS4 switch (ae_type) { case ARCHIVE_ENTRY_ACL_TYPE_ALLOW: acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALLOW); break; case ARCHIVE_ENTRY_ACL_TYPE_DENY: acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_DENY); break; case ARCHIVE_ENTRY_ACL_TYPE_AUDIT: acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_AUDIT); break; case ARCHIVE_ENTRY_ACL_TYPE_ALARM: acl_set_entry_type_np(acl_entry, ACL_ENTRY_TYPE_ALARM); break; case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: // These don't translate directly into the system ACL. break; default: // XXX error handling here. break; } #endif acl_get_permset(acl_entry, &acl_permset); acl_clear_perms(acl_permset); for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { if (ae_permset & acl_perm_map[i].archive_perm) acl_add_perm(acl_permset, acl_perm_map[i].platform_perm); } #ifdef ACL_TYPE_NFS4 // XXX acl_get_flagset_np on FreeBSD returns EINVAL for // non-NFSv4 ACLs r = acl_get_flagset_np(acl_entry, &acl_flagset); if (r == 0) { acl_clear_flags_np(acl_flagset); for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { if (ae_permset & acl_inherit_map[i].archive_inherit) acl_add_flag_np(acl_flagset, acl_inherit_map[i].platform_inherit); } } #endif } /* Try restoring the ACL through 'fd' if we can. */ #if HAVE_ACL_SET_FD if (fd >= 0 && acl_type == ACL_TYPE_ACCESS && acl_set_fd(fd, acl) == 0) ret = ARCHIVE_OK; else #else #if HAVE_ACL_SET_FD_NP if (fd >= 0 && acl_set_fd_np(fd, acl, acl_type) == 0) ret = ARCHIVE_OK; else #endif #endif #if HAVE_ACL_SET_LINK_NP if (acl_set_link_np(name, acl_type, acl) != 0) { archive_set_error(a, errno, "Failed to set %s acl", tname); ret = ARCHIVE_WARN; } #else /* TODO: Skip this if 'name' is a symlink. */ if (acl_set_file(name, acl_type, acl) != 0) { archive_set_error(a, errno, "Failed to set %s acl", tname); ret = ARCHIVE_WARN; } #endif acl_free(acl); return (ret); }
static int acl_from_text_callback(acl_tag_t tag, int perms, const char *name, size_t name_len, void *params_casted) { DEBUG("acl_from_text: tag: %d, name: %s, name_len: %lu\n", tag, name, (long unsigned)name_len); struct acl_from_text_params *params = (struct acl_from_text_params *)(params_casted); if (params->acl != NULL) { resolve resolve_func = params->custom_resolve; void *resolve_data = params->custom_resolve_data; uint32_t id = ((name == NULL || name_len == 0) ? ACL_UNDEFINED_ID : resolve_func(tag, name, name_len, resolve_data)); switch (tag) { case ACL_USER: case ACL_GROUP: if (id == ACL_UNDEFINED_ID) { return -ENOENT; } break; } acl_entry_t entry = NULL; errno = 0; if (acl_create_entry(params->acl, &entry) != 0) { DEBUG("%d\n", 1); return -errno; } errno = 0; if (acl_set_tag_type(entry, tag) != 0) { DEBUG("%d\n", 2); return -errno; } acl_permset_t permset = NULL; errno = 0; if (acl_get_permset(entry, &permset) != 0) { return -errno; } if ((perms & ACL_READ) != 0) { errno = 0; if (acl_add_perm(permset, ACL_READ) != 0) { return -errno; } } if ((perms & ACL_WRITE) != 0) { errno = 0; if (acl_add_perm(permset, ACL_WRITE) != 0) { return -errno; } } if ((perms & ACL_EXECUTE) != 0) { errno = 0; if (acl_add_perm(permset, ACL_EXECUTE) != 0) { return -errno; } } errno = 0; if (acl_set_permset(entry, permset) != 0) { return -errno; } switch (tag) { case ACL_USER: { uid_t uid = (uid_t)(id); errno = 0; if (acl_set_qualifier(entry, (void *)&uid) != 0) { DEBUG("%d\n", 4); return -errno; } } case ACL_GROUP: { gid_t gid = (gid_t)(id); errno = 0; if (acl_set_qualifier(entry, (void *)&gid) != 0) { DEBUG("%d\n", 5); return -errno; } } break; } } ++params->count; return 0; }