static int get_acl_string(struct asfd *asfd, acl_t acl, char **acltext, size_t *alen, const char *path, char type, struct cntr *cntr) { int ret=0; char pre[10]=""; char *tmp=NULL; ssize_t tlen=0; char *ourtext=NULL; ssize_t maxlen=0xFFFFFFFF/2; if(!(tmp=acl_to_text(acl, NULL))) { logw(asfd, cntr, "could not get ACL text of '%s'\n", path); goto end; // carry on } tlen=strlen(tmp); if(tlen>maxlen) { logw(asfd, cntr, "ACL of '%s' too long: %d\n", path, tlen); goto end; // carry on } snprintf(pre, sizeof(pre), "%c%08X", type, (unsigned int)tlen); if(!(ourtext=prepend(pre, tmp)) || !(*acltext=prepend_len(*acltext, *alen, ourtext, tlen+9, "", 0, alen))) ret=-1; end: free_w(&tmp); free_w(&ourtext); return ret; }
/* "system.posix_acl_default" */ static void xattrs__acls_get_d (int parentfd, char const *file_name, struct tar_stat_info *st, char **ret_ptr, size_t * ret_len) { char *val = NULL; ssize_t len; acl_t acl; if (!(acl = acl_get_file_at (parentfd, file_name, ACL_TYPE_DEFAULT))) { if (errno != ENOTSUP) call_arg_warn ("acl_get_file_at", file_name); return; } val = acl_to_text (acl, &len); acl_free (acl); if (!val) { call_arg_warn ("acl_to_text", file_name); return; } *ret_ptr = xstrdup (val); *ret_len = len; acl_free (val); }
int acl_entries (acl_t acl) { char *t; int entries = 0; char *text = acl_to_text (acl, NULL); if (! text) return -1; for (t = text; *t; t++) entries += (*t == '\n'); acl_free_text (text); return entries; }
QString KrVfsHandler::getACL(const QString & path, int type) { Q_UNUSED(path); Q_UNUSED(type); #ifdef HAVE_POSIX_ACL acl_t acl = 0; // do we have an acl for the file, and/or a default acl for the dir, if it is one? if ((acl = acl_get_file(path.toLocal8Bit(), type)) != 0) { bool aclExtended = false; #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS aclExtended = acl_equiv_mode(acl, 0); #else acl_entry_t entry; int ret = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); while (ret == 1) { acl_tag_t currentTag; acl_get_tag_type(entry, ¤tTag); if (currentTag != ACL_USER_OBJ && currentTag != ACL_GROUP_OBJ && currentTag != ACL_OTHER) { aclExtended = true; break; } ret = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); } #endif if (!aclExtended) { acl_free(acl); acl = 0; } } if (acl == 0) return QString(); char *aclString = acl_to_text(acl, 0); QString ret = QString::fromLatin1(aclString); acl_free((void*)aclString); acl_free(acl); return ret; #else return QString(); #endif }
int do_getfacl(const char *path, const char *filter) { char *textacl; acl_t acl; ssize_t size; const char *p; const char *loc; char c; int def; int k; errno = 0; def = !strcmp(filter,"default"); if (def || !strcmp(filter,"access")) { acl = acl_get_file(path,(def ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS)); if (acl) { /* * When there is no extended ACL, we get * ENODATA (not mentioned in the man.) * In such situation return basic ACL * (or void for default ACL) with no error */ if (errno == ENODATA) errno = 0; textacl = acl_to_text(acl,&size); /* getting all the access or default rights */ k = 0; p = textacl; while (p && *p) { loc = p; if (loc && strchr("ugom",*loc)) { c = *loc; loc = strchr(loc,':'); if (loc) { if (k) { putchar(','); k++; } putchar(c); k++; while (*loc && (*loc != '\n') && (*loc != '\t')) { c = *loc++; putchar(c); k++; } } } while (*p && (*p != '\n')) p++; if (*p) p++; } if (textacl) acl_free(textacl); if (k) putchar('\n'); else printf("void\n"); acl_free(acl); /* for some reason the functions above may set errno */ errno = 0; } } else errno = EBADRQC; /* "bad request" */ return (-errno); }
int main (int argc, char *argv[]) { const char *file1; const char *file2; set_program_name (argv[0]); ASSERT (argc == 3); file1 = argv[1]; file2 = argv[2]; /* Compare the contents of the two files. */ { size_t size1; char *contents1; size_t size2; char *contents2; contents1 = read_file (file1, &size1); if (contents1 == NULL) { fprintf (stderr, "error reading file %s: errno = %d\n", file1, errno); fflush (stderr); abort (); } contents2 = read_file (file2, &size2); if (contents2 == NULL) { fprintf (stderr, "error reading file %s: errno = %d\n", file2, errno); fflush (stderr); abort (); } if (size2 != size1) { fprintf (stderr, "files %s and %s have different sizes\n", file1, file2); fflush (stderr); abort (); } if (memcmp (contents1, contents2, size1) != 0) { fprintf (stderr, "files %s and %s have different contents\n", file1, file2); fflush (stderr); abort (); } } /* Compare the access permissions of the two files, including ACLs. */ { struct stat statbuf1; struct stat statbuf2; if (stat (file1, &statbuf1) < 0) { fprintf (stderr, "error accessing file %s: errno = %d\n", file1, errno); fflush (stderr); abort (); } if (stat (file2, &statbuf2) < 0) { fprintf (stderr, "error accessing file %s: errno = %d\n", file2, errno); fflush (stderr); abort (); } if (statbuf1.st_mode != statbuf2.st_mode) { fprintf (stderr, "files %s and %s have different access modes: %03o and %03o\n", file1, file2, (unsigned int) statbuf1.st_mode, (unsigned int) statbuf2.st_mode); return 1; } } { #if HAVE_ACL_GET_FILE /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */ static const int types[] = { ACL_TYPE_ACCESS # if HAVE_ACL_TYPE_EXTENDED /* MacOS X */ , ACL_TYPE_EXTENDED # endif }; int t; for (t = 0; t < sizeof (types) / sizeof (types[0]); t++) { int type = types[t]; acl_t acl1; char *text1; int errno1; acl_t acl2; char *text2; int errno2; acl1 = acl_get_file (file1, type); if (acl1 == (acl_t)NULL) { text1 = NULL; errno1 = errno; } else { text1 = acl_to_text (acl1, NULL); if (text1 == NULL) errno1 = errno; else errno1 = 0; } acl2 = acl_get_file (file2, type); if (acl2 == (acl_t)NULL) { text2 = NULL; errno2 = errno; } else { text2 = acl_to_text (acl2, NULL); if (text2 == NULL) errno2 = errno; else errno2 = 0; } if (acl1 != (acl_t)NULL) { if (acl2 != (acl_t)NULL) { if (text1 != NULL) { if (text2 != NULL) { if (strcmp (text1, text2) != 0) { fprintf (stderr, "files %s and %s have different ACLs:\n%s\n%s\n", file1, file2, text1, text2); return 1; } } else { fprintf (stderr, "file %s has a valid ACL, but file %s has an invalid ACL\n", file1, file2); return 1; } } else { if (text2 != NULL) { fprintf (stderr, "file %s has an invalid ACL, but file %s has a valid ACL\n", file1, file2); return 1; } else { if (errno1 != errno2) { fprintf (stderr, "files %s and %s have differently invalid ACLs, errno = %d vs. %d\n", file1, file2, errno1, errno2); return 1; } } } } else { fprintf (stderr, "file %s has an ACL, but file %s has no ACL\n", file1, file2); return 1; } } else { if (acl2 != (acl_t)NULL) { fprintf (stderr, "file %s has no ACL, but file %s has an ACL\n", file1, file2); return 1; } } } #elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ int count1; int count2; count1 = acl (file1, GETACLCNT, 0, NULL); if (count1 < 0 && errno == ENOSYS) /* Can happen on Solaris 10 with ZFS */ count1 = 0; count2 = acl (file2, GETACLCNT, 0, NULL); if (count2 < 0 && errno == ENOSYS) /* Can happen on Solaris 10 with ZFS */ count2 = 0; if (count1 < 0) { fprintf (stderr, "error accessing the ACLs of file %s\n", file1); fflush (stderr); abort (); } if (count2 < 0) { fprintf (stderr, "error accessing the ACLs of file %s\n", file2); fflush (stderr); abort (); } if (count1 != count2) { fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n", file1, file2, count1, count2); return 1; } else { aclent_t *entries1 = XNMALLOC (count1, aclent_t); aclent_t *entries2 = XNMALLOC (count2, aclent_t); int i; if (count1 > 0 && acl (file1, GETACL, count1, entries1) < count1) { fprintf (stderr, "error retrieving the ACLs of file %s\n", file1); fflush (stderr); abort (); } if (count2 > 0 && acl (file2, GETACL, count2, entries2) < count1) { fprintf (stderr, "error retrieving the ACLs of file %s\n", file2); fflush (stderr); abort (); } for (i = 0; i < count1; i++) { if (entries1[i].a_type != entries2[i].a_type) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different types %d and %d\n", file1, file2, i, entries1[i].a_type, entries2[i].a_type); return 1; } if (entries1[i].a_id != entries2[i].a_id) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different ids %d and %d\n", file1, file2, i, (int)entries1[i].a_id, (int)entries2[i].a_id); return 1; } if (entries1[i].a_perm != entries2[i].a_perm) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n", file1, file2, i, (unsigned int) entries1[i].a_perm, (unsigned int) entries2[i].a_perm); return 1; } } } # ifdef ACE_GETACL count1 = acl (file1, ACE_GETACLCNT, 0, NULL); if (count1 < 0 && errno == EINVAL) count1 = 0; count2 = acl (file2, ACE_GETACLCNT, 0, NULL); if (count2 < 0 && errno == EINVAL) count2 = 0; if (count1 < 0) { fprintf (stderr, "error accessing the ACE-ACLs of file %s\n", file1); fflush (stderr); abort (); } if (count2 < 0) { fprintf (stderr, "error accessing the ACE-ACLs of file %s\n", file2); fflush (stderr); abort (); } if (count1 != count2) { fprintf (stderr, "files %s and %s have different number of ACE-ACLs: %d and %d\n", file1, file2, count1, count2); return 1; } else if (count1 > 0) { ace_t *entries1 = XNMALLOC (count1, ace_t); ace_t *entries2 = XNMALLOC (count2, ace_t); int i; if (acl (file1, ACE_GETACL, count1, entries1) < count1) { fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file1); fflush (stderr); abort (); } if (acl (file2, ACE_GETACL, count2, entries2) < count1) { fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file2); fflush (stderr); abort (); } for (i = 0; i < count1; i++) { if (entries1[i].a_type != entries2[i].a_type) { fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different types %d and %d\n", file1, file2, i, entries1[i].a_type, entries2[i].a_type); return 1; } if (entries1[i].a_who != entries2[i].a_who) { fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different ids %d and %d\n", file1, file2, i, (int)entries1[i].a_who, (int)entries2[i].a_who); return 1; } if (entries1[i].a_access_mask != entries2[i].a_access_mask) { fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different access masks %03o and %03o\n", file1, file2, i, (unsigned int) entries1[i].a_access_mask, (unsigned int) entries2[i].a_access_mask); return 1; } if (entries1[i].a_flags != entries2[i].a_flags) { fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different flags 0x%x and 0x%x\n", file1, file2, i, (unsigned int) entries1[i].a_flags, (unsigned int) entries2[i].a_flags); return 1; } } } # endif #elif HAVE_GETACL /* HP-UX */ int count1; int count2; count1 = getacl (file1, 0, NULL); if (count1 < 0 && (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)) count1 = 0; count2 = getacl (file2, 0, NULL); if (count2 < 0 && (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)) count2 = 0; if (count1 < 0) { fprintf (stderr, "error accessing the ACLs of file %s\n", file1); fflush (stderr); abort (); } if (count2 < 0) { fprintf (stderr, "error accessing the ACLs of file %s\n", file2); fflush (stderr); abort (); } if (count1 != count2) { fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n", file1, file2, count1, count2); return 1; } else if (count1 > 0) { struct acl_entry *entries1 = XNMALLOC (count1, struct acl_entry); struct acl_entry *entries2 = XNMALLOC (count2, struct acl_entry); int i; if (getacl (file1, count1, entries1) < count1) { fprintf (stderr, "error retrieving the ACLs of file %s\n", file1); fflush (stderr); abort (); } if (getacl (file2, count2, entries2) < count1) { fprintf (stderr, "error retrieving the ACLs of file %s\n", file2); fflush (stderr); abort (); } for (i = 0; i < count1; i++) { if (entries1[i].uid != entries2[i].uid) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different uids %d and %d\n", file1, file2, i, (int)entries1[i].uid, (int)entries2[i].uid); return 1; } if (entries1[i].gid != entries2[i].gid) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different gids %d and %d\n", file1, file2, i, (int)entries1[i].gid, (int)entries2[i].gid); return 1; } if (entries1[i].mode != entries2[i].mode) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n", file1, file2, i, (unsigned int) entries1[i].mode, (unsigned int) entries2[i].mode); return 1; } } } # if HAVE_ACLV_H /* HP-UX >= 11.11 */ { struct acl dummy_entries[NACLVENTRIES]; count1 = acl ((char *) file1, ACL_CNT, NACLVENTRIES, dummy_entries); if (count1 < 0 && (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)) count1 = 0; count2 = acl ((char *) file2, ACL_CNT, NACLVENTRIES, dummy_entries); if (count2 < 0 && (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)) count2 = 0; } if (count1 < 0) { fprintf (stderr, "error accessing the ACLs of file %s\n", file1); fflush (stderr); abort (); } if (count2 < 0) { fprintf (stderr, "error accessing the ACLs of file %s\n", file2); fflush (stderr); abort (); } if (count1 != count2) { fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n", file1, file2, count1, count2); return 1; } else if (count1 > 0) { struct acl *entries1 = XNMALLOC (count1, struct acl); struct acl *entries2 = XNMALLOC (count2, struct acl); int i; if (acl ((char *) file1, ACL_GET, count1, entries1) < count1) { fprintf (stderr, "error retrieving the ACLs of file %s\n", file1); fflush (stderr); abort (); } if (acl ((char *) file2, ACL_GET, count2, entries2) < count1) { fprintf (stderr, "error retrieving the ACLs of file %s\n", file2); fflush (stderr); abort (); } for (i = 0; i < count1; i++) { if (entries1[i].a_type != entries2[i].a_type) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different types %d and %d\n", file1, file2, i, entries1[i].a_type, entries2[i].a_type); return 1; } if (entries1[i].a_id != entries2[i].a_id) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different ids %d and %d\n", file1, file2, i, (int)entries1[i].a_id, (int)entries2[i].a_id); return 1; } if (entries1[i].a_perm != entries2[i].a_perm) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n", file1, file2, i, (unsigned int) entries1[i].a_perm, (unsigned int) entries2[i].a_perm); return 1; } } } # endif #elif HAVE_ACLX_GET /* AIX */ acl_type_t type1; char acl1[1000]; size_t aclsize1 = sizeof (acl1); mode_t mode1; char text1[1000]; size_t textsize1 = sizeof (text1); acl_type_t type2; char acl2[1000]; size_t aclsize2 = sizeof (acl2); mode_t mode2; char text2[1000]; size_t textsize2 = sizeof (text2); /* The docs say that type1 being 0 is equivalent to ACL_ANY, but it is not true, in AIX 5.3. */ type1.u64 = ACL_ANY; if (aclx_get (file1, 0, &type1, acl1, &aclsize1, &mode1) < 0) { if (errno == ENOSYS) text1[0] = '\0'; else { fprintf (stderr, "error accessing the ACLs of file %s\n", file1); fflush (stderr); abort (); } } else if (aclx_printStr (text1, &textsize1, acl1, aclsize1, type1, file1, 0) < 0) { fprintf (stderr, "cannot convert the ACLs of file %s to text\n", file1); fflush (stderr); abort (); } /* The docs say that type2 being 0 is equivalent to ACL_ANY, but it is not true, in AIX 5.3. */ type2.u64 = ACL_ANY; if (aclx_get (file2, 0, &type2, acl2, &aclsize2, &mode2) < 0) { if (errno == ENOSYS) text2[0] = '\0'; else { fprintf (stderr, "error accessing the ACLs of file %s\n", file2); fflush (stderr); abort (); } } else if (aclx_printStr (text2, &textsize2, acl2, aclsize2, type2, file2, 0) < 0) { fprintf (stderr, "cannot convert the ACLs of file %s to text\n", file2); fflush (stderr); abort (); } if (strcmp (text1, text2) != 0) { fprintf (stderr, "files %s and %s have different ACLs:\n%s\n%s\n", file1, file2, text1, text2); return 1; } #elif HAVE_STATACL /* older AIX */ union { struct acl a; char room[4096]; } acl1; union { struct acl a; char room[4096]; } acl2; unsigned int i; if (statacl (file1, STX_NORMAL, &acl1.a, sizeof (acl1)) < 0) { fprintf (stderr, "error accessing the ACLs of file %s\n", file1); fflush (stderr); abort (); } if (statacl (file2, STX_NORMAL, &acl2.a, sizeof (acl2)) < 0) { fprintf (stderr, "error accessing the ACLs of file %s\n", file2); fflush (stderr); abort (); } if (acl1.a.acl_len != acl2.a.acl_len) { fprintf (stderr, "files %s and %s have different ACL lengths: %u and %u\n", file1, file2, acl1.a.acl_len, acl2.a.acl_len); return 1; } if (acl1.a.acl_mode != acl2.a.acl_mode) { fprintf (stderr, "files %s and %s have different ACL modes: %03o and %03o\n", file1, file2, acl1.a.acl_mode, acl2.a.acl_mode); return 1; } if (acl1.a.u_access != acl2.a.u_access || acl1.a.g_access != acl2.a.g_access || acl1.a.o_access != acl2.a.o_access) { fprintf (stderr, "files %s and %s have different ACL access masks: %03o %03o %03o and %03o %03o %03o\n", file1, file2, acl1.a.u_access, acl1.a.g_access, acl1.a.o_access, acl2.a.u_access, acl2.a.g_access, acl2.a.o_access); return 1; } if (memcmp (acl1.a.acl_ext, acl2.a.acl_ext, acl1.a.acl_len) != 0) { fprintf (stderr, "files %s and %s have different ACL entries\n", file1, file2); return 1; } #elif HAVE_ACLSORT /* NonStop Kernel */ int count1; int count2; count1 = acl ((char *) file1, ACL_CNT, NACLENTRIES, NULL); count2 = acl ((char *) file2, ACL_CNT, NACLENTRIES, NULL); if (count1 < 0) { fprintf (stderr, "error accessing the ACLs of file %s\n", file1); fflush (stderr); abort (); } if (count2 < 0) { fprintf (stderr, "error accessing the ACLs of file %s\n", file2); fflush (stderr); abort (); } if (count1 != count2) { fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n", file1, file2, count1, count2); return 1; } else if (count1 > 0) { struct acl *entries1 = XNMALLOC (count1, struct acl); struct acl *entries2 = XNMALLOC (count2, struct acl); int i; if (acl ((char *) file1, ACL_GET, count1, entries1) < count1) { fprintf (stderr, "error retrieving the ACLs of file %s\n", file1); fflush (stderr); abort (); } if (acl ((char *) file2, ACL_GET, count2, entries2) < count1) { fprintf (stderr, "error retrieving the ACLs of file %s\n", file2); fflush (stderr); abort (); } for (i = 0; i < count1; i++) { if (entries1[i].a_type != entries2[i].a_type) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different types %d and %d\n", file1, file2, i, entries1[i].a_type, entries2[i].a_type); return 1; } if (entries1[i].a_id != entries2[i].a_id) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different ids %d and %d\n", file1, file2, i, (int)entries1[i].a_id, (int)entries2[i].a_id); return 1; } if (entries1[i].a_perm != entries2[i].a_perm) { fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n", file1, file2, i, (unsigned int) entries1[i].a_perm, (unsigned int) entries2[i].a_perm); return 1; } } } #endif } return 0; }
/* Obtain the ACL of the given file in long text form. @param path Path to the file @param text Will hold the result. This is a managed object which finally has to be freed by a call to this function with bit15 of flag. @param flag Bitfield for control purposes (bit0= obtain default ACL rather than access ACL) bit4= set *text = NULL and return 2 if the ACL matches st_mode permissions. bit5= in case of symbolic link: inquire link target bit15= free text and return 1 @return > 0 ok 0 ACL support not enabled at compile time or filesystem does not support ACL -1 failure of system ACL service (see errno) -2 attempt to inquire ACL of a symbolic link without bit4 or bit5 */ int aaip_get_acl_text(char *path, char **text, int flag) { #ifdef Libisofs_with_aaip_acL acl_t acl= NULL; #endif struct stat stbuf; int ret; if(flag & (1 << 15)) { if(*text != NULL) #ifdef Libisofs_with_aaip_acL acl_free(*text); #else free(*text); #endif *text= NULL; return(1); } *text= NULL; if(flag & 32) ret= stat(path, &stbuf); else ret= lstat(path, &stbuf); if(ret == -1) return(-1); if((stbuf.st_mode & S_IFMT) == S_IFLNK) { if(flag & 16) return(2); return(-2); } /* Note: no ACL_TYPE_DEFAULT in FreeBSD */ if(flag & 1) return(0); #ifdef Libisofs_with_aaip_acL acl= acl_get_file(path, ACL_TYPE_ACCESS); if(acl == NULL) { if(errno == EOPNOTSUPP) { /* filesystem does not support ACL */ if(flag & 16) return(2); /* >>> ??? fake ACL from POSIX permissions ? */; return(0); } return(-1); } *text= acl_to_text(acl, NULL); acl_free(acl); #else /* Libisofs_with_aaip_acL */ /* ??? >>> Fake ACL */; return(0); #endif /* ! Libisofs_with_aaip_acL */ if(*text == NULL) return(-1); if(flag & 16) { ret = aaip_cleanout_st_mode(*text, &(stbuf.st_mode), 2); if(!(ret & (7 | 64))) (*text)[0]= 0; if((*text)[0] == 0 || strcmp(*text, "\n") == 0) { #ifdef Libisofs_with_aaip_acL acl_free(*text); #else free(*text); #endif *text= NULL; return(2); } } return(1); }
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 modify_file_acl(unsigned int optflags, const char *path, acl_t modifier, int position, int inheritance_level, int follow) { acl_t oacl = NULL; unsigned aindex = 0, flag_new_acl = 0; acl_entry_t newent = NULL; acl_entry_t entry = NULL; unsigned retval = 0; extern int chmod_fflag; /* XXX acl_get_file() returns a zero entry ACL if an ACL was previously * associated with the file, and has had its entries removed. * However, POSIX 1003.1e states that a zero entry ACL should be * returned if the caller asks for ACL_TYPE_DEFAULT, and no ACL is * associated with the path; it * does not specifically state that a request for ACL_TYPE_EXTENDED * should not return a zero entry ACL, however. */ /* Determine if we've been given a zero entry ACL, or create an ACL if * none exists. There are some issues to consider here: Should we create * a zero-entry ACL for a delete or check canonicity operation? */ if (path == NULL) chmod_usage(); if (optflags & ACL_CLEAR_FLAG) { filesec_t fsec = filesec_init(); if (fsec == NULL) { // err(1, "filesec_init() failed"); fprintf(stderr, "chmod: filesec_init() failed: %s\n", strerror(errno)); pthread_exit(NULL); } if (filesec_set_property(fsec, FILESEC_ACL, _FILESEC_REMOVE_ACL) != 0) { // err(1, "filesec_set_property() failed"); fprintf(stderr, "chmod: filesec_set_property() failed: %s\n", strerror(errno)); pthread_exit(NULL); } if (follow) { if (chmodx_np(path, fsec) != 0) { if (!chmod_fflag) { // warn("Failed to clear ACL on file %s", path); fprintf(stderr, "chmod: Failed to clear ACL on file %s: %s\n", path, strerror(errno)); } retval = 1; } } else { int fd = open(path, O_SYMLINK); if (fd != -1) { if (fchmodx_np(fd, fsec) != 0) { if (!chmod_fflag) { fprintf(stderr, "chmod: Failed to clear ACL on file %s: %s\n", path, strerror(errno)); // warn("Failed to clear ACL on file %s", path); } retval = 1; } close(fd); } else { if (!chmod_fflag) { // warn("Failed to open file %s", path); fprintf(stderr, "chmod: Failed to open file %s: %s\n", path, strerror(errno)); } retval = 1; } } filesec_free(fsec); return (retval); } if (optflags & ACL_FROM_STDIN) { oacl = acl_dup(modifier); } else { if (follow) { oacl = acl_get_file(path, ACL_TYPE_EXTENDED); } else { int fd = open(path, O_SYMLINK); if (fd != -1) { oacl = acl_get_fd_np(fd, ACL_TYPE_EXTENDED); close(fd); } } if ((oacl == NULL) || (acl_get_entry(oacl,ACL_FIRST_ENTRY, &newent) != 0)) { if ((oacl = acl_init(1)) == NULL) { // err(1, "acl_init() failed"); fprintf(stderr, "chmod: acl_init() failed: %s\n", strerror(errno)); pthread_exit(NULL); } flag_new_acl = 1; position = 0; } if ((0 == flag_new_acl) && (optflags & (ACL_REMOVE_INHERIT_FLAG | ACL_REMOVE_INHERITED_ENTRIES))) { acl_t facl = NULL; if ((facl = acl_init(1)) == NULL) { //err(1, "acl_init() failed"); fprintf(stderr, "chmod: acl_init() failed: %s\n", strerror(errno)); pthread_exit(NULL); } for (aindex = 0; acl_get_entry(oacl, (entry == NULL ? ACL_FIRST_ENTRY : ACL_NEXT_ENTRY), &entry) == 0; aindex++) { acl_flagset_t eflags; acl_entry_t fent = NULL; if (acl_get_flagset_np(entry, &eflags) != 0) { fprintf(stderr, "chmod: Unable to obtain flagset: %s\n", strerror(errno)); pthread_exit(NULL); // err(1, "Unable to obtain flagset"); } if (acl_get_flag_np(eflags, ACL_ENTRY_INHERITED)) { if (optflags & ACL_REMOVE_INHERIT_FLAG) { acl_delete_flag_np(eflags, ACL_ENTRY_INHERITED); acl_set_flagset_np(entry, eflags); acl_create_entry(&facl, &fent); acl_copy_entry(fent, entry); } } else { acl_create_entry(&facl, &fent); acl_copy_entry(fent, entry); } } if (oacl) acl_free(oacl); oacl = facl; } else if (optflags & ACL_TO_STDOUT) { ssize_t len; /* need to get printacl() from ls(1) */ char *text = acl_to_text(oacl, &len); puts(text); acl_free(text); } else if (optflags & ACL_CHECK_CANONICITY) { if (flag_new_acl) { // warnx("No ACL currently associated with file '%s'", path); fprintf(stderr, "chmod: No ACL currently associated with file '%s'\n", path); } retval = is_canonical(oacl); } else if ((optflags & ACL_SET_FLAG) && (position == -1) && (!is_canonical(oacl))) { // warnx("The specified file '%s' does not have an ACL in canonical order, please specify a position with +a# ", path); fprintf(stderr, "chmod: The specified file '%s' does not have an ACL in canonical order, please specify a position with +a# \n", path); retval = 1; } else if (((optflags & ACL_DELETE_FLAG) && (position != -1)) || (optflags & ACL_CHECK_CANONICITY)) { retval = modify_acl(&oacl, NULL, optflags, position, inheritance_level, flag_new_acl, path); } else if ((optflags & (ACL_REMOVE_INHERIT_FLAG|ACL_REMOVE_INHERITED_ENTRIES)) && flag_new_acl) { // warnx("No ACL currently associated with file '%s'", path); fprintf(stderr, "chmod: No ACL currently associated with file '%s'\n", path); retval = 1; } else { if (!modifier) { /* avoid bus error in acl_get_entry */ // errx(1, "Internal error: modifier should not be NULL"); fprintf(stderr, "Internal error: modifier should not be NULL\n"); pthread_exit(NULL); } for (aindex = 0; acl_get_entry(modifier, (entry == NULL ? ACL_FIRST_ENTRY : ACL_NEXT_ENTRY), &entry) == 0; aindex++) { retval += modify_acl(&oacl, entry, optflags, position, inheritance_level, flag_new_acl, path); } } } /* XXX Potential race here, since someone else could've modified or * read the ACL on this file (with the intention of modifying it) in * the interval from acl_get_file() to acl_set_file(); we can * minimize one aspect of this window by comparing the original acl * to a fresh one from acl_get_file() but we could consider a * "changeset" mechanism, common locking strategy, or kernel * supplied reservation mechanism to prevent this race. */ if (!(optflags & (ACL_TO_STDOUT|ACL_CHECK_CANONICITY))) { int status = -1; if (follow) { status = acl_set_file(path, ACL_TYPE_EXTENDED, oacl); } else { int fd = open(path, O_SYMLINK); if (fd != -1) { status = acl_set_fd_np(fd, oacl, ACL_TYPE_EXTENDED); close(fd); } } if (status != 0) { if (!chmod_fflag) fprintf(stderr, "chmod: Failed to set ACL on file '%s': %s\n", path, strerror(errno)); // warn("Failed to set ACL on file '%s'", path); retval = 1; } } if (oacl) acl_free(oacl); return retval; }
static int32_t aacls(xar_file_t f, const char *file) { #ifdef HAVE_SYS_ACL_H #if !defined(__APPLE__) acl_t a; const char *type; xar_prop_get(f, "type", &type); if( !type || (strcmp(type, "symlink") == 0) ) return 0; a = acl_get_file(file, ACL_TYPE_DEFAULT); if( a ) { char *t; acl_entry_t e; /* If the acl is empty, or not valid, skip it */ if( acl_get_entry(a, ACL_FIRST_ENTRY, &e) != 1 ) goto NEXT; t = acl_to_text(a, NULL); if( t ) { xar_prop_set(f, "acl/default", t); acl_free(t); } acl_free(a); } NEXT: a = acl_get_file(file, ACL_TYPE_ACCESS); if( a ) { char *t; acl_entry_t e; /* If the acl is empty, or not valid, skip it */ if( acl_get_entry(a, ACL_FIRST_ENTRY, &e) != 1 ) goto DONE; t = acl_to_text(a, NULL); if( t ) { xar_prop_set(f, "acl/access", t); acl_free(t); } acl_free(a); } DONE: #else /* !__AAPLE__ */ acl_entry_t e = NULL; acl_t a; int i; a = acl_get_file(file, ACL_TYPE_EXTENDED); if( !a ) return 0; for( i = 0; acl_get_entry(a, e == NULL ? ACL_FIRST_ENTRY : ACL_NEXT_ENTRY, &e) == 0; i++ ) { char *t; t = acl_to_text(a, NULL); if( t ) { xar_prop_set(f, "acl/appleextended", t); acl_free(t); } } acl_free(a); #endif /* !__APPLE__ */ #endif return 0; }