archive_disk_acl_sunos.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. /*-
  2. * Copyright (c) 2017 Martin Matuska
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "archive_platform.h"
  26. #if ARCHIVE_ACL_SUNOS
  27. #ifdef HAVE_ERRNO_H
  28. #include <errno.h>
  29. #endif
  30. #ifdef HAVE_FCNTL_H
  31. #include <fcntl.h>
  32. #endif
  33. #ifdef HAVE_SYS_TYPES_H
  34. #include <sys/types.h>
  35. #endif
  36. #ifdef HAVE_SYS_ACL_H
  37. #define _ACL_PRIVATE /* For debugging */
  38. #include <sys/acl.h>
  39. #endif
  40. #include "archive_entry.h"
  41. #include "archive_private.h"
  42. #include "archive_read_disk_private.h"
  43. #include "archive_write_disk_private.h"
  44. typedef struct {
  45. const int a_perm; /* Libarchive permission or flag */
  46. const int p_perm; /* Platform permission or flag */
  47. } acl_perm_map_t;
  48. static const acl_perm_map_t acl_posix_perm_map[] = {
  49. {ARCHIVE_ENTRY_ACL_EXECUTE, S_IXOTH },
  50. {ARCHIVE_ENTRY_ACL_WRITE, S_IWOTH },
  51. {ARCHIVE_ENTRY_ACL_READ, S_IROTH }
  52. };
  53. static const int acl_posix_perm_map_size =
  54. (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
  55. #if ARCHIVE_ACL_SUNOS_NFS4
  56. static const acl_perm_map_t acl_nfs4_perm_map[] = {
  57. {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
  58. {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
  59. {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
  60. {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
  61. {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
  62. {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
  63. {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
  64. {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
  65. {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
  66. {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
  67. {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
  68. {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
  69. {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
  70. {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
  71. {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
  72. {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
  73. {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
  74. };
  75. static const int acl_nfs4_perm_map_size =
  76. (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
  77. static const acl_perm_map_t acl_nfs4_flag_map[] = {
  78. {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
  79. {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
  80. {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
  81. {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
  82. {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
  83. {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
  84. #ifdef ACE_INHERITED_ACE
  85. {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
  86. #endif
  87. };
  88. const int acl_nfs4_flag_map_size =
  89. (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
  90. #endif /* ARCHIVE_ACL_SUNOS_NFS4 */
  91. static void *
  92. sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
  93. {
  94. int cnt, cntcmd;
  95. size_t size;
  96. void *aclp;
  97. if (cmd == GETACL) {
  98. cntcmd = GETACLCNT;
  99. size = sizeof(aclent_t);
  100. }
  101. #if ARCHIVE_ACL_SUNOS_NFS4
  102. else if (cmd == ACE_GETACL) {
  103. cntcmd = ACE_GETACLCNT;
  104. size = sizeof(ace_t);
  105. }
  106. #endif
  107. else {
  108. errno = EINVAL;
  109. *aclcnt = -1;
  110. return (NULL);
  111. }
  112. aclp = NULL;
  113. cnt = -2;
  114. while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) {
  115. if (path != NULL)
  116. cnt = acl(path, cntcmd, 0, NULL);
  117. else
  118. cnt = facl(fd, cntcmd, 0, NULL);
  119. if (cnt > 0) {
  120. if (aclp == NULL)
  121. aclp = malloc(cnt * size);
  122. else
  123. aclp = realloc(NULL, cnt * size);
  124. if (aclp != NULL) {
  125. if (path != NULL)
  126. cnt = acl(path, cmd, cnt, aclp);
  127. else
  128. cnt = facl(fd, cmd, cnt, aclp);
  129. }
  130. } else {
  131. if (aclp != NULL) {
  132. free(aclp);
  133. aclp = NULL;
  134. }
  135. break;
  136. }
  137. }
  138. *aclcnt = cnt;
  139. return (aclp);
  140. }
  141. /*
  142. * Check if acl is trivial
  143. * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
  144. */
  145. static int
  146. sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4,
  147. int is_dir, int *trivialp)
  148. {
  149. #if ARCHIVE_ACL_SUNOS_NFS4
  150. int i, p;
  151. const uint32_t rperm = ACE_READ_DATA;
  152. const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
  153. const uint32_t eperm = ACE_EXECUTE;
  154. const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
  155. ACE_READ_ACL | ACE_SYNCHRONIZE;
  156. const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
  157. ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
  158. ace_t *ace;
  159. ace_t tace[6];
  160. #endif
  161. if (aclp == NULL || trivialp == NULL)
  162. return (-1);
  163. *trivialp = 0;
  164. /*
  165. * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
  166. * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
  167. * including mask.
  168. */
  169. if (!is_nfs4) {
  170. if (aclcnt == 4)
  171. *trivialp = 1;
  172. return (0);
  173. }
  174. #if ARCHIVE_ACL_SUNOS_NFS4
  175. /*
  176. * Continue with checking NFSv4 ACLs
  177. *
  178. * Create list of trivial ace's to be compared
  179. */
  180. /* owner@ allow pre */
  181. tace[0].a_flags = ACE_OWNER;
  182. tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
  183. tace[0].a_access_mask = 0;
  184. /* owner@ deny */
  185. tace[1].a_flags = ACE_OWNER;
  186. tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
  187. tace[1].a_access_mask = 0;
  188. /* group@ deny */
  189. tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
  190. tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
  191. tace[2].a_access_mask = 0;
  192. /* owner@ allow */
  193. tace[3].a_flags = ACE_OWNER;
  194. tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
  195. tace[3].a_access_mask = ownset;
  196. /* group@ allow */
  197. tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
  198. tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
  199. tace[4].a_access_mask = pubset;
  200. /* everyone@ allow */
  201. tace[5].a_flags = ACE_EVERYONE;
  202. tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
  203. tace[5].a_access_mask = pubset;
  204. /* Permissions for everyone@ */
  205. if (mode & 0004)
  206. tace[5].a_access_mask |= rperm;
  207. if (mode & 0002)
  208. tace[5].a_access_mask |= wperm;
  209. if (mode & 0001)
  210. tace[5].a_access_mask |= eperm;
  211. /* Permissions for group@ */
  212. if (mode & 0040)
  213. tace[4].a_access_mask |= rperm;
  214. else if (mode & 0004)
  215. tace[2].a_access_mask |= rperm;
  216. if (mode & 0020)
  217. tace[4].a_access_mask |= wperm;
  218. else if (mode & 0002)
  219. tace[2].a_access_mask |= wperm;
  220. if (mode & 0010)
  221. tace[4].a_access_mask |= eperm;
  222. else if (mode & 0001)
  223. tace[2].a_access_mask |= eperm;
  224. /* Permissions for owner@ */
  225. if (mode & 0400) {
  226. tace[3].a_access_mask |= rperm;
  227. if (!(mode & 0040) && (mode & 0004))
  228. tace[0].a_access_mask |= rperm;
  229. } else if ((mode & 0040) || (mode & 0004))
  230. tace[1].a_access_mask |= rperm;
  231. if (mode & 0200) {
  232. tace[3].a_access_mask |= wperm;
  233. if (!(mode & 0020) && (mode & 0002))
  234. tace[0].a_access_mask |= wperm;
  235. } else if ((mode & 0020) || (mode & 0002))
  236. tace[1].a_access_mask |= wperm;
  237. if (mode & 0100) {
  238. tace[3].a_access_mask |= eperm;
  239. if (!(mode & 0010) && (mode & 0001))
  240. tace[0].a_access_mask |= eperm;
  241. } else if ((mode & 0010) || (mode & 0001))
  242. tace[1].a_access_mask |= eperm;
  243. /* Check if the acl count matches */
  244. p = 3;
  245. for (i = 0; i < 3; i++) {
  246. if (tace[i].a_access_mask != 0)
  247. p++;
  248. }
  249. if (aclcnt != p)
  250. return (0);
  251. p = 0;
  252. for (i = 0; i < 6; i++) {
  253. if (tace[i].a_access_mask != 0) {
  254. ace = &((ace_t *)aclp)[p];
  255. /*
  256. * Illumos added ACE_DELETE_CHILD to write perms for
  257. * directories. We have to check against that, too.
  258. */
  259. if (ace->a_flags != tace[i].a_flags ||
  260. ace->a_type != tace[i].a_type ||
  261. (ace->a_access_mask != tace[i].a_access_mask &&
  262. (!is_dir || (tace[i].a_access_mask & wperm) == 0 ||
  263. ace->a_access_mask !=
  264. (tace[i].a_access_mask | ACE_DELETE_CHILD))))
  265. return (0);
  266. p++;
  267. }
  268. }
  269. *trivialp = 1;
  270. #else /* !ARCHIVE_ACL_SUNOS_NFS4 */
  271. (void)is_dir; /* UNUSED */
  272. (void)aclp; /* UNUSED */
  273. #endif /* !ARCHIVE_ACL_SUNOS_NFS4 */
  274. return (0);
  275. }
  276. /*
  277. * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
  278. */
  279. static int
  280. translate_acl(struct archive_read_disk *a,
  281. struct archive_entry *entry, void *aclp, int aclcnt,
  282. int default_entry_acl_type)
  283. {
  284. int e, i;
  285. int ae_id, ae_tag, ae_perm;
  286. int entry_acl_type;
  287. const char *ae_name;
  288. aclent_t *aclent;
  289. #if ARCHIVE_ACL_SUNOS_NFS4
  290. ace_t *ace;
  291. #endif
  292. if (aclcnt <= 0)
  293. return (ARCHIVE_OK);
  294. for (e = 0; e < aclcnt; e++) {
  295. ae_name = NULL;
  296. ae_tag = 0;
  297. ae_perm = 0;
  298. #if ARCHIVE_ACL_SUNOS_NFS4
  299. if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  300. ace = &((ace_t *)aclp)[e];
  301. ae_id = ace->a_who;
  302. switch(ace->a_type) {
  303. case ACE_ACCESS_ALLOWED_ACE_TYPE:
  304. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
  305. break;
  306. case ACE_ACCESS_DENIED_ACE_TYPE:
  307. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
  308. break;
  309. case ACE_SYSTEM_AUDIT_ACE_TYPE:
  310. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
  311. break;
  312. case ACE_SYSTEM_ALARM_ACE_TYPE:
  313. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
  314. break;
  315. default:
  316. /* Unknown entry type, skip */
  317. continue;
  318. }
  319. if ((ace->a_flags & ACE_OWNER) != 0)
  320. ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
  321. else if ((ace->a_flags & ACE_GROUP) != 0)
  322. ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
  323. else if ((ace->a_flags & ACE_EVERYONE) != 0)
  324. ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
  325. else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
  326. ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
  327. ae_name = archive_read_disk_gname(&a->archive,
  328. ae_id);
  329. } else {
  330. ae_tag = ARCHIVE_ENTRY_ACL_USER;
  331. ae_name = archive_read_disk_uname(&a->archive,
  332. ae_id);
  333. }
  334. for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
  335. if ((ace->a_flags &
  336. acl_nfs4_flag_map[i].p_perm) != 0)
  337. ae_perm |= acl_nfs4_flag_map[i].a_perm;
  338. }
  339. for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
  340. if ((ace->a_access_mask &
  341. acl_nfs4_perm_map[i].p_perm) != 0)
  342. ae_perm |= acl_nfs4_perm_map[i].a_perm;
  343. }
  344. } else
  345. #endif /* ARCHIVE_ACL_SUNOS_NFS4 */
  346. if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
  347. aclent = &((aclent_t *)aclp)[e];
  348. if ((aclent->a_type & ACL_DEFAULT) != 0)
  349. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
  350. else
  351. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
  352. ae_id = aclent->a_id;
  353. switch(aclent->a_type) {
  354. case DEF_USER:
  355. case USER:
  356. ae_name = archive_read_disk_uname(&a->archive,
  357. ae_id);
  358. ae_tag = ARCHIVE_ENTRY_ACL_USER;
  359. break;
  360. case DEF_GROUP:
  361. case GROUP:
  362. ae_name = archive_read_disk_gname(&a->archive,
  363. ae_id);
  364. ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
  365. break;
  366. case DEF_CLASS_OBJ:
  367. case CLASS_OBJ:
  368. ae_tag = ARCHIVE_ENTRY_ACL_MASK;
  369. break;
  370. case DEF_USER_OBJ:
  371. case USER_OBJ:
  372. ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
  373. break;
  374. case DEF_GROUP_OBJ:
  375. case GROUP_OBJ:
  376. ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
  377. break;
  378. case DEF_OTHER_OBJ:
  379. case OTHER_OBJ:
  380. ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
  381. break;
  382. default:
  383. /* Unknown tag type, skip */
  384. continue;
  385. }
  386. for (i = 0; i < acl_posix_perm_map_size; ++i) {
  387. if ((aclent->a_perm &
  388. acl_posix_perm_map[i].p_perm) != 0)
  389. ae_perm |= acl_posix_perm_map[i].a_perm;
  390. }
  391. } else
  392. return (ARCHIVE_WARN);
  393. archive_entry_acl_add_entry(entry, entry_acl_type,
  394. ae_perm, ae_tag, ae_id, ae_name);
  395. }
  396. return (ARCHIVE_OK);
  397. }
  398. static int
  399. set_acl(struct archive *a, int fd, const char *name,
  400. struct archive_acl *abstract_acl,
  401. int ae_requested_type, const char *tname)
  402. {
  403. aclent_t *aclent;
  404. #if ARCHIVE_ACL_SUNOS_NFS4
  405. ace_t *ace;
  406. #endif
  407. int cmd, e, r;
  408. void *aclp;
  409. int ret;
  410. int ae_type, ae_permset, ae_tag, ae_id;
  411. int perm_map_size;
  412. const acl_perm_map_t *perm_map;
  413. uid_t ae_uid;
  414. gid_t ae_gid;
  415. const char *ae_name;
  416. int entries;
  417. int i;
  418. ret = ARCHIVE_OK;
  419. entries = archive_acl_reset(abstract_acl, ae_requested_type);
  420. if (entries == 0)
  421. return (ARCHIVE_OK);
  422. switch (ae_requested_type) {
  423. case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
  424. cmd = SETACL;
  425. aclp = malloc(entries * sizeof(aclent_t));
  426. break;
  427. #if ARCHIVE_ACL_SUNOS_NFS4
  428. case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
  429. cmd = ACE_SETACL;
  430. aclp = malloc(entries * sizeof(ace_t));
  431. break;
  432. #endif
  433. default:
  434. errno = ENOENT;
  435. archive_set_error(a, errno, "Unsupported ACL type");
  436. return (ARCHIVE_FAILED);
  437. }
  438. if (aclp == NULL) {
  439. archive_set_error(a, errno,
  440. "Can't allocate memory for acl buffer");
  441. return (ARCHIVE_FAILED);
  442. }
  443. e = 0;
  444. while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
  445. &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
  446. aclent = NULL;
  447. #if ARCHIVE_ACL_SUNOS_NFS4
  448. ace = NULL;
  449. #endif
  450. if (cmd == SETACL) {
  451. aclent = &((aclent_t *)aclp)[e];
  452. aclent->a_id = -1;
  453. aclent->a_type = 0;
  454. aclent->a_perm = 0;
  455. }
  456. #if ARCHIVE_ACL_SUNOS_NFS4
  457. else { /* cmd == ACE_SETACL */
  458. ace = &((ace_t *)aclp)[e];
  459. ace->a_who = -1;
  460. ace->a_access_mask = 0;
  461. ace->a_flags = 0;
  462. }
  463. #endif /* ARCHIVE_ACL_SUNOS_NFS4 */
  464. switch (ae_tag) {
  465. case ARCHIVE_ENTRY_ACL_USER:
  466. ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
  467. if (aclent != NULL) {
  468. aclent->a_id = ae_uid;
  469. aclent->a_type |= USER;
  470. }
  471. #if ARCHIVE_ACL_SUNOS_NFS4
  472. else {
  473. ace->a_who = ae_uid;
  474. }
  475. #endif
  476. break;
  477. case ARCHIVE_ENTRY_ACL_GROUP:
  478. ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
  479. if (aclent != NULL) {
  480. aclent->a_id = ae_gid;
  481. aclent->a_type |= GROUP;
  482. }
  483. #if ARCHIVE_ACL_SUNOS_NFS4
  484. else {
  485. ace->a_who = ae_gid;
  486. ace->a_flags |= ACE_IDENTIFIER_GROUP;
  487. }
  488. #endif
  489. break;
  490. case ARCHIVE_ENTRY_ACL_USER_OBJ:
  491. if (aclent != NULL)
  492. aclent->a_type |= USER_OBJ;
  493. #if ARCHIVE_ACL_SUNOS_NFS4
  494. else {
  495. ace->a_flags |= ACE_OWNER;
  496. }
  497. #endif
  498. break;
  499. case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
  500. if (aclent != NULL)
  501. aclent->a_type |= GROUP_OBJ;
  502. #if ARCHIVE_ACL_SUNOS_NFS4
  503. else {
  504. ace->a_flags |= ACE_GROUP;
  505. ace->a_flags |= ACE_IDENTIFIER_GROUP;
  506. }
  507. #endif
  508. break;
  509. case ARCHIVE_ENTRY_ACL_MASK:
  510. if (aclent != NULL)
  511. aclent->a_type |= CLASS_OBJ;
  512. break;
  513. case ARCHIVE_ENTRY_ACL_OTHER:
  514. if (aclent != NULL)
  515. aclent->a_type |= OTHER_OBJ;
  516. break;
  517. #if ARCHIVE_ACL_SUNOS_NFS4
  518. case ARCHIVE_ENTRY_ACL_EVERYONE:
  519. if (ace != NULL)
  520. ace->a_flags |= ACE_EVERYONE;
  521. break;
  522. #endif
  523. default:
  524. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  525. "Unsupported ACL tag");
  526. ret = ARCHIVE_FAILED;
  527. goto exit_free;
  528. }
  529. r = 0;
  530. switch (ae_type) {
  531. #if ARCHIVE_ACL_SUNOS_NFS4
  532. case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
  533. if (ace != NULL)
  534. ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
  535. else
  536. r = -1;
  537. break;
  538. case ARCHIVE_ENTRY_ACL_TYPE_DENY:
  539. if (ace != NULL)
  540. ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
  541. else
  542. r = -1;
  543. break;
  544. case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
  545. if (ace != NULL)
  546. ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
  547. else
  548. r = -1;
  549. break;
  550. case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
  551. if (ace != NULL)
  552. ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
  553. else
  554. r = -1;
  555. break;
  556. #endif
  557. case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
  558. if (aclent == NULL)
  559. r = -1;
  560. break;
  561. case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
  562. if (aclent != NULL)
  563. aclent->a_type |= ACL_DEFAULT;
  564. else
  565. r = -1;
  566. break;
  567. default:
  568. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  569. "Unsupported ACL entry type");
  570. ret = ARCHIVE_FAILED;
  571. goto exit_free;
  572. }
  573. if (r != 0) {
  574. errno = EINVAL;
  575. archive_set_error(a, errno,
  576. "Failed to set ACL entry type");
  577. ret = ARCHIVE_FAILED;
  578. goto exit_free;
  579. }
  580. #if ARCHIVE_ACL_SUNOS_NFS4
  581. if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  582. perm_map_size = acl_nfs4_perm_map_size;
  583. perm_map = acl_nfs4_perm_map;
  584. } else {
  585. #endif
  586. perm_map_size = acl_posix_perm_map_size;
  587. perm_map = acl_posix_perm_map;
  588. #if ARCHIVE_ACL_SUNOS_NFS4
  589. }
  590. #endif
  591. for (i = 0; i < perm_map_size; ++i) {
  592. if (ae_permset & perm_map[i].a_perm) {
  593. #if ARCHIVE_ACL_SUNOS_NFS4
  594. if (ae_requested_type ==
  595. ARCHIVE_ENTRY_ACL_TYPE_NFS4)
  596. ace->a_access_mask |=
  597. perm_map[i].p_perm;
  598. else
  599. #endif
  600. aclent->a_perm |= perm_map[i].p_perm;
  601. }
  602. }
  603. #if ARCHIVE_ACL_SUNOS_NFS4
  604. if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  605. for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
  606. if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
  607. ace->a_flags |=
  608. acl_nfs4_flag_map[i].p_perm;
  609. }
  610. }
  611. }
  612. #endif
  613. e++;
  614. }
  615. /* Try restoring the ACL through 'fd' if we can. */
  616. if (fd >= 0) {
  617. if (facl(fd, cmd, entries, aclp) == 0)
  618. ret = ARCHIVE_OK;
  619. else {
  620. if (errno == EOPNOTSUPP) {
  621. /* Filesystem doesn't support ACLs */
  622. ret = ARCHIVE_OK;
  623. } else {
  624. archive_set_error(a, errno,
  625. "Failed to set acl on fd: %s", tname);
  626. ret = ARCHIVE_WARN;
  627. }
  628. }
  629. } else if (acl(name, cmd, entries, aclp) != 0) {
  630. if (errno == EOPNOTSUPP) {
  631. /* Filesystem doesn't support ACLs */
  632. ret = ARCHIVE_OK;
  633. } else {
  634. archive_set_error(a, errno, "Failed to set acl: %s",
  635. tname);
  636. ret = ARCHIVE_WARN;
  637. }
  638. }
  639. exit_free:
  640. free(aclp);
  641. return (ret);
  642. }
  643. int
  644. archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
  645. struct archive_entry *entry, int *fd)
  646. {
  647. const char *accpath;
  648. void *aclp;
  649. int aclcnt;
  650. int r;
  651. accpath = NULL;
  652. if (*fd < 0) {
  653. accpath = archive_read_disk_entry_setup_path(a, entry, fd);
  654. if (accpath == NULL)
  655. return (ARCHIVE_WARN);
  656. }
  657. archive_entry_acl_clear(entry);
  658. aclp = NULL;
  659. #if ARCHIVE_ACL_SUNOS_NFS4
  660. if (*fd >= 0)
  661. aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL);
  662. else if ((!a->follow_symlinks)
  663. && (archive_entry_filetype(entry) == AE_IFLNK))
  664. /* We can't get the ACL of a symlink, so we assume it can't
  665. have one. */
  666. aclp = NULL;
  667. else
  668. aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath);
  669. if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
  670. archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)),
  671. &r) == 0 && r == 1) {
  672. free(aclp);
  673. aclp = NULL;
  674. return (ARCHIVE_OK);
  675. }
  676. if (aclp != NULL) {
  677. r = translate_acl(a, entry, aclp, aclcnt,
  678. ARCHIVE_ENTRY_ACL_TYPE_NFS4);
  679. free(aclp);
  680. aclp = NULL;
  681. if (r != ARCHIVE_OK) {
  682. archive_set_error(&a->archive, errno,
  683. "Couldn't translate NFSv4 ACLs");
  684. }
  685. return (r);
  686. }
  687. #endif /* ARCHIVE_ACL_SUNOS_NFS4 */
  688. /* Retrieve POSIX.1e ACLs from file. */
  689. if (*fd >= 0)
  690. aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL);
  691. else if ((!a->follow_symlinks)
  692. && (archive_entry_filetype(entry) == AE_IFLNK))
  693. /* We can't get the ACL of a symlink, so we assume it can't
  694. have one. */
  695. aclp = NULL;
  696. else
  697. aclp = sunacl_get(GETACL, &aclcnt, 0, accpath);
  698. /* Ignore "trivial" ACLs that just mirror the file mode. */
  699. if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
  700. archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)),
  701. &r) == 0 && r == 1) {
  702. free(aclp);
  703. aclp = NULL;
  704. }
  705. if (aclp != NULL)
  706. {
  707. r = translate_acl(a, entry, aclp, aclcnt,
  708. ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
  709. free(aclp);
  710. aclp = NULL;
  711. if (r != ARCHIVE_OK) {
  712. archive_set_error(&a->archive, errno,
  713. "Couldn't translate access ACLs");
  714. return (r);
  715. }
  716. }
  717. return (ARCHIVE_OK);
  718. }
  719. int
  720. archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
  721. struct archive_acl *abstract_acl, __LA_MODE_T mode)
  722. {
  723. int ret = ARCHIVE_OK;
  724. (void)mode; /* UNUSED */
  725. if ((archive_acl_types(abstract_acl)
  726. & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
  727. /* Solaris writes POSIX.1e access and default ACLs together */
  728. ret = set_acl(a, fd, name, abstract_acl,
  729. ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
  730. /* Simultaneous POSIX.1e and NFSv4 is not supported */
  731. return (ret);
  732. }
  733. #if ARCHIVE_ACL_SUNOS_NFS4
  734. else if ((archive_acl_types(abstract_acl) &
  735. ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
  736. ret = set_acl(a, fd, name, abstract_acl,
  737. ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
  738. }
  739. #endif
  740. return (ret);
  741. }
  742. #endif /* ARCHIVE_ACL_SUNOS */