archive_disk_acl_sunos.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  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. free(aclp);
  132. aclp = NULL;
  133. break;
  134. }
  135. }
  136. *aclcnt = cnt;
  137. return (aclp);
  138. }
  139. /*
  140. * Check if acl is trivial
  141. * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
  142. */
  143. static int
  144. sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4,
  145. int is_dir, int *trivialp)
  146. {
  147. #if ARCHIVE_ACL_SUNOS_NFS4
  148. int i, p;
  149. const uint32_t rperm = ACE_READ_DATA;
  150. const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
  151. const uint32_t eperm = ACE_EXECUTE;
  152. const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
  153. ACE_READ_ACL | ACE_SYNCHRONIZE;
  154. const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
  155. ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
  156. ace_t *ace;
  157. ace_t tace[6];
  158. #endif
  159. if (aclp == NULL || trivialp == NULL)
  160. return (-1);
  161. *trivialp = 0;
  162. /*
  163. * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
  164. * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
  165. * including mask.
  166. */
  167. if (!is_nfs4) {
  168. if (aclcnt == 4)
  169. *trivialp = 1;
  170. return (0);
  171. }
  172. #if ARCHIVE_ACL_SUNOS_NFS4
  173. /*
  174. * Continue with checking NFSv4 ACLs
  175. *
  176. * Create list of trivial ace's to be compared
  177. */
  178. /* owner@ allow pre */
  179. tace[0].a_flags = ACE_OWNER;
  180. tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
  181. tace[0].a_access_mask = 0;
  182. /* owner@ deny */
  183. tace[1].a_flags = ACE_OWNER;
  184. tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
  185. tace[1].a_access_mask = 0;
  186. /* group@ deny */
  187. tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
  188. tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
  189. tace[2].a_access_mask = 0;
  190. /* owner@ allow */
  191. tace[3].a_flags = ACE_OWNER;
  192. tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
  193. tace[3].a_access_mask = ownset;
  194. /* group@ allow */
  195. tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
  196. tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
  197. tace[4].a_access_mask = pubset;
  198. /* everyone@ allow */
  199. tace[5].a_flags = ACE_EVERYONE;
  200. tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
  201. tace[5].a_access_mask = pubset;
  202. /* Permissions for everyone@ */
  203. if (mode & 0004)
  204. tace[5].a_access_mask |= rperm;
  205. if (mode & 0002)
  206. tace[5].a_access_mask |= wperm;
  207. if (mode & 0001)
  208. tace[5].a_access_mask |= eperm;
  209. /* Permissions for group@ */
  210. if (mode & 0040)
  211. tace[4].a_access_mask |= rperm;
  212. else if (mode & 0004)
  213. tace[2].a_access_mask |= rperm;
  214. if (mode & 0020)
  215. tace[4].a_access_mask |= wperm;
  216. else if (mode & 0002)
  217. tace[2].a_access_mask |= wperm;
  218. if (mode & 0010)
  219. tace[4].a_access_mask |= eperm;
  220. else if (mode & 0001)
  221. tace[2].a_access_mask |= eperm;
  222. /* Permissions for owner@ */
  223. if (mode & 0400) {
  224. tace[3].a_access_mask |= rperm;
  225. if (!(mode & 0040) && (mode & 0004))
  226. tace[0].a_access_mask |= rperm;
  227. } else if ((mode & 0040) || (mode & 0004))
  228. tace[1].a_access_mask |= rperm;
  229. if (mode & 0200) {
  230. tace[3].a_access_mask |= wperm;
  231. if (!(mode & 0020) && (mode & 0002))
  232. tace[0].a_access_mask |= wperm;
  233. } else if ((mode & 0020) || (mode & 0002))
  234. tace[1].a_access_mask |= wperm;
  235. if (mode & 0100) {
  236. tace[3].a_access_mask |= eperm;
  237. if (!(mode & 0010) && (mode & 0001))
  238. tace[0].a_access_mask |= eperm;
  239. } else if ((mode & 0010) || (mode & 0001))
  240. tace[1].a_access_mask |= eperm;
  241. /* Check if the acl count matches */
  242. p = 3;
  243. for (i = 0; i < 3; i++) {
  244. if (tace[i].a_access_mask != 0)
  245. p++;
  246. }
  247. if (aclcnt != p)
  248. return (0);
  249. p = 0;
  250. for (i = 0; i < 6; i++) {
  251. if (tace[i].a_access_mask != 0) {
  252. ace = &((ace_t *)aclp)[p];
  253. /*
  254. * Illumos added ACE_DELETE_CHILD to write perms for
  255. * directories. We have to check against that, too.
  256. */
  257. if (ace->a_flags != tace[i].a_flags ||
  258. ace->a_type != tace[i].a_type ||
  259. (ace->a_access_mask != tace[i].a_access_mask &&
  260. (!is_dir || (tace[i].a_access_mask & wperm) == 0 ||
  261. ace->a_access_mask !=
  262. (tace[i].a_access_mask | ACE_DELETE_CHILD))))
  263. return (0);
  264. p++;
  265. }
  266. }
  267. *trivialp = 1;
  268. #else /* !ARCHIVE_ACL_SUNOS_NFS4 */
  269. (void)is_dir; /* UNUSED */
  270. (void)aclp; /* UNUSED */
  271. #endif /* !ARCHIVE_ACL_SUNOS_NFS4 */
  272. return (0);
  273. }
  274. /*
  275. * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
  276. */
  277. static int
  278. translate_acl(struct archive_read_disk *a,
  279. struct archive_entry *entry, void *aclp, int aclcnt,
  280. int default_entry_acl_type)
  281. {
  282. int e, i;
  283. int ae_id, ae_tag, ae_perm;
  284. int entry_acl_type;
  285. const char *ae_name;
  286. aclent_t *aclent;
  287. #if ARCHIVE_ACL_SUNOS_NFS4
  288. ace_t *ace;
  289. #endif
  290. if (aclcnt <= 0)
  291. return (ARCHIVE_OK);
  292. for (e = 0; e < aclcnt; e++) {
  293. ae_name = NULL;
  294. ae_tag = 0;
  295. ae_perm = 0;
  296. #if ARCHIVE_ACL_SUNOS_NFS4
  297. if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  298. ace = &((ace_t *)aclp)[e];
  299. ae_id = ace->a_who;
  300. switch(ace->a_type) {
  301. case ACE_ACCESS_ALLOWED_ACE_TYPE:
  302. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
  303. break;
  304. case ACE_ACCESS_DENIED_ACE_TYPE:
  305. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
  306. break;
  307. case ACE_SYSTEM_AUDIT_ACE_TYPE:
  308. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
  309. break;
  310. case ACE_SYSTEM_ALARM_ACE_TYPE:
  311. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
  312. break;
  313. default:
  314. /* Unknown entry type, skip */
  315. continue;
  316. }
  317. if ((ace->a_flags & ACE_OWNER) != 0)
  318. ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
  319. else if ((ace->a_flags & ACE_GROUP) != 0)
  320. ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
  321. else if ((ace->a_flags & ACE_EVERYONE) != 0)
  322. ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
  323. else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
  324. ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
  325. ae_name = archive_read_disk_gname(&a->archive,
  326. ae_id);
  327. } else {
  328. ae_tag = ARCHIVE_ENTRY_ACL_USER;
  329. ae_name = archive_read_disk_uname(&a->archive,
  330. ae_id);
  331. }
  332. for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
  333. if ((ace->a_flags &
  334. acl_nfs4_flag_map[i].p_perm) != 0)
  335. ae_perm |= acl_nfs4_flag_map[i].a_perm;
  336. }
  337. for (i = 0; i < acl_nfs4_perm_map_size; ++i) {
  338. if ((ace->a_access_mask &
  339. acl_nfs4_perm_map[i].p_perm) != 0)
  340. ae_perm |= acl_nfs4_perm_map[i].a_perm;
  341. }
  342. } else
  343. #endif /* ARCHIVE_ACL_SUNOS_NFS4 */
  344. if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
  345. aclent = &((aclent_t *)aclp)[e];
  346. if ((aclent->a_type & ACL_DEFAULT) != 0)
  347. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
  348. else
  349. entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
  350. ae_id = aclent->a_id;
  351. switch(aclent->a_type) {
  352. case DEF_USER:
  353. case USER:
  354. ae_name = archive_read_disk_uname(&a->archive,
  355. ae_id);
  356. ae_tag = ARCHIVE_ENTRY_ACL_USER;
  357. break;
  358. case DEF_GROUP:
  359. case GROUP:
  360. ae_name = archive_read_disk_gname(&a->archive,
  361. ae_id);
  362. ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
  363. break;
  364. case DEF_CLASS_OBJ:
  365. case CLASS_OBJ:
  366. ae_tag = ARCHIVE_ENTRY_ACL_MASK;
  367. break;
  368. case DEF_USER_OBJ:
  369. case USER_OBJ:
  370. ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
  371. break;
  372. case DEF_GROUP_OBJ:
  373. case GROUP_OBJ:
  374. ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
  375. break;
  376. case DEF_OTHER_OBJ:
  377. case OTHER_OBJ:
  378. ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
  379. break;
  380. default:
  381. /* Unknown tag type, skip */
  382. continue;
  383. }
  384. for (i = 0; i < acl_posix_perm_map_size; ++i) {
  385. if ((aclent->a_perm &
  386. acl_posix_perm_map[i].p_perm) != 0)
  387. ae_perm |= acl_posix_perm_map[i].a_perm;
  388. }
  389. } else
  390. return (ARCHIVE_WARN);
  391. archive_entry_acl_add_entry(entry, entry_acl_type,
  392. ae_perm, ae_tag, ae_id, ae_name);
  393. }
  394. return (ARCHIVE_OK);
  395. }
  396. static int
  397. set_acl(struct archive *a, int fd, const char *name,
  398. struct archive_acl *abstract_acl,
  399. int ae_requested_type, const char *tname)
  400. {
  401. aclent_t *aclent;
  402. #if ARCHIVE_ACL_SUNOS_NFS4
  403. ace_t *ace;
  404. #endif
  405. int cmd, e, r;
  406. void *aclp;
  407. int ret;
  408. int ae_type, ae_permset, ae_tag, ae_id;
  409. int perm_map_size;
  410. const acl_perm_map_t *perm_map;
  411. uid_t ae_uid;
  412. gid_t ae_gid;
  413. const char *ae_name;
  414. int entries;
  415. int i;
  416. ret = ARCHIVE_OK;
  417. entries = archive_acl_reset(abstract_acl, ae_requested_type);
  418. if (entries == 0)
  419. return (ARCHIVE_OK);
  420. switch (ae_requested_type) {
  421. case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
  422. cmd = SETACL;
  423. aclp = malloc(entries * sizeof(aclent_t));
  424. break;
  425. #if ARCHIVE_ACL_SUNOS_NFS4
  426. case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
  427. cmd = ACE_SETACL;
  428. aclp = malloc(entries * sizeof(ace_t));
  429. break;
  430. #endif
  431. default:
  432. errno = ENOENT;
  433. archive_set_error(a, errno, "Unsupported ACL type");
  434. return (ARCHIVE_FAILED);
  435. }
  436. if (aclp == NULL) {
  437. archive_set_error(a, errno,
  438. "Can't allocate memory for acl buffer");
  439. return (ARCHIVE_FAILED);
  440. }
  441. e = 0;
  442. while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
  443. &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
  444. aclent = NULL;
  445. #if ARCHIVE_ACL_SUNOS_NFS4
  446. ace = NULL;
  447. #endif
  448. if (cmd == SETACL) {
  449. aclent = &((aclent_t *)aclp)[e];
  450. aclent->a_id = -1;
  451. aclent->a_type = 0;
  452. aclent->a_perm = 0;
  453. }
  454. #if ARCHIVE_ACL_SUNOS_NFS4
  455. else { /* cmd == ACE_SETACL */
  456. ace = &((ace_t *)aclp)[e];
  457. ace->a_who = -1;
  458. ace->a_access_mask = 0;
  459. ace->a_flags = 0;
  460. }
  461. #endif /* ARCHIVE_ACL_SUNOS_NFS4 */
  462. switch (ae_tag) {
  463. case ARCHIVE_ENTRY_ACL_USER:
  464. ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
  465. if (aclent != NULL) {
  466. aclent->a_id = ae_uid;
  467. aclent->a_type |= USER;
  468. }
  469. #if ARCHIVE_ACL_SUNOS_NFS4
  470. else {
  471. ace->a_who = ae_uid;
  472. }
  473. #endif
  474. break;
  475. case ARCHIVE_ENTRY_ACL_GROUP:
  476. ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
  477. if (aclent != NULL) {
  478. aclent->a_id = ae_gid;
  479. aclent->a_type |= GROUP;
  480. }
  481. #if ARCHIVE_ACL_SUNOS_NFS4
  482. else {
  483. ace->a_who = ae_gid;
  484. ace->a_flags |= ACE_IDENTIFIER_GROUP;
  485. }
  486. #endif
  487. break;
  488. case ARCHIVE_ENTRY_ACL_USER_OBJ:
  489. if (aclent != NULL)
  490. aclent->a_type |= USER_OBJ;
  491. #if ARCHIVE_ACL_SUNOS_NFS4
  492. else {
  493. ace->a_flags |= ACE_OWNER;
  494. }
  495. #endif
  496. break;
  497. case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
  498. if (aclent != NULL)
  499. aclent->a_type |= GROUP_OBJ;
  500. #if ARCHIVE_ACL_SUNOS_NFS4
  501. else {
  502. ace->a_flags |= ACE_GROUP;
  503. ace->a_flags |= ACE_IDENTIFIER_GROUP;
  504. }
  505. #endif
  506. break;
  507. case ARCHIVE_ENTRY_ACL_MASK:
  508. if (aclent != NULL)
  509. aclent->a_type |= CLASS_OBJ;
  510. break;
  511. case ARCHIVE_ENTRY_ACL_OTHER:
  512. if (aclent != NULL)
  513. aclent->a_type |= OTHER_OBJ;
  514. break;
  515. #if ARCHIVE_ACL_SUNOS_NFS4
  516. case ARCHIVE_ENTRY_ACL_EVERYONE:
  517. if (ace != NULL)
  518. ace->a_flags |= ACE_EVERYONE;
  519. break;
  520. #endif
  521. default:
  522. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  523. "Unsupported ACL tag");
  524. ret = ARCHIVE_FAILED;
  525. goto exit_free;
  526. }
  527. r = 0;
  528. switch (ae_type) {
  529. #if ARCHIVE_ACL_SUNOS_NFS4
  530. case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
  531. if (ace != NULL)
  532. ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
  533. else
  534. r = -1;
  535. break;
  536. case ARCHIVE_ENTRY_ACL_TYPE_DENY:
  537. if (ace != NULL)
  538. ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE;
  539. else
  540. r = -1;
  541. break;
  542. case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
  543. if (ace != NULL)
  544. ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE;
  545. else
  546. r = -1;
  547. break;
  548. case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
  549. if (ace != NULL)
  550. ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE;
  551. else
  552. r = -1;
  553. break;
  554. #endif
  555. case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
  556. if (aclent == NULL)
  557. r = -1;
  558. break;
  559. case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
  560. if (aclent != NULL)
  561. aclent->a_type |= ACL_DEFAULT;
  562. else
  563. r = -1;
  564. break;
  565. default:
  566. archive_set_error(a, ARCHIVE_ERRNO_MISC,
  567. "Unsupported ACL entry type");
  568. ret = ARCHIVE_FAILED;
  569. goto exit_free;
  570. }
  571. if (r != 0) {
  572. errno = EINVAL;
  573. archive_set_error(a, errno,
  574. "Failed to set ACL entry type");
  575. ret = ARCHIVE_FAILED;
  576. goto exit_free;
  577. }
  578. #if ARCHIVE_ACL_SUNOS_NFS4
  579. if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  580. perm_map_size = acl_nfs4_perm_map_size;
  581. perm_map = acl_nfs4_perm_map;
  582. } else {
  583. #endif
  584. perm_map_size = acl_posix_perm_map_size;
  585. perm_map = acl_posix_perm_map;
  586. #if ARCHIVE_ACL_SUNOS_NFS4
  587. }
  588. #endif
  589. for (i = 0; i < perm_map_size; ++i) {
  590. if (ae_permset & perm_map[i].a_perm) {
  591. #if ARCHIVE_ACL_SUNOS_NFS4
  592. if (ae_requested_type ==
  593. ARCHIVE_ENTRY_ACL_TYPE_NFS4)
  594. ace->a_access_mask |=
  595. perm_map[i].p_perm;
  596. else
  597. #endif
  598. aclent->a_perm |= perm_map[i].p_perm;
  599. }
  600. }
  601. #if ARCHIVE_ACL_SUNOS_NFS4
  602. if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
  603. for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
  604. if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
  605. ace->a_flags |=
  606. acl_nfs4_flag_map[i].p_perm;
  607. }
  608. }
  609. }
  610. #endif
  611. e++;
  612. }
  613. /* Try restoring the ACL through 'fd' if we can. */
  614. if (fd >= 0) {
  615. if (facl(fd, cmd, entries, aclp) == 0)
  616. ret = ARCHIVE_OK;
  617. else {
  618. if (errno == EOPNOTSUPP) {
  619. /* Filesystem doesn't support ACLs */
  620. ret = ARCHIVE_OK;
  621. } else {
  622. archive_set_error(a, errno,
  623. "Failed to set acl on fd: %s", tname);
  624. ret = ARCHIVE_WARN;
  625. }
  626. }
  627. } else if (acl(name, cmd, entries, aclp) != 0) {
  628. if (errno == EOPNOTSUPP) {
  629. /* Filesystem doesn't support ACLs */
  630. ret = ARCHIVE_OK;
  631. } else {
  632. archive_set_error(a, errno, "Failed to set acl: %s",
  633. tname);
  634. ret = ARCHIVE_WARN;
  635. }
  636. }
  637. exit_free:
  638. free(aclp);
  639. return (ret);
  640. }
  641. int
  642. archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
  643. struct archive_entry *entry, int *fd)
  644. {
  645. const char *accpath;
  646. void *aclp;
  647. int aclcnt;
  648. int r;
  649. accpath = NULL;
  650. if (*fd < 0) {
  651. accpath = archive_read_disk_entry_setup_path(a, entry, fd);
  652. if (accpath == NULL)
  653. return (ARCHIVE_WARN);
  654. }
  655. archive_entry_acl_clear(entry);
  656. aclp = NULL;
  657. #if ARCHIVE_ACL_SUNOS_NFS4
  658. if (*fd >= 0)
  659. aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL);
  660. else if ((!a->follow_symlinks)
  661. && (archive_entry_filetype(entry) == AE_IFLNK))
  662. /* We can't get the ACL of a symlink, so we assume it can't
  663. have one. */
  664. aclp = NULL;
  665. else
  666. aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath);
  667. if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
  668. archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)),
  669. &r) == 0 && r == 1) {
  670. free(aclp);
  671. aclp = NULL;
  672. return (ARCHIVE_OK);
  673. }
  674. if (aclp != NULL) {
  675. r = translate_acl(a, entry, aclp, aclcnt,
  676. ARCHIVE_ENTRY_ACL_TYPE_NFS4);
  677. free(aclp);
  678. aclp = NULL;
  679. if (r != ARCHIVE_OK) {
  680. archive_set_error(&a->archive, errno,
  681. "Couldn't translate NFSv4 ACLs");
  682. }
  683. return (r);
  684. }
  685. #endif /* ARCHIVE_ACL_SUNOS_NFS4 */
  686. /* Retrieve POSIX.1e ACLs from file. */
  687. if (*fd >= 0)
  688. aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL);
  689. else if ((!a->follow_symlinks)
  690. && (archive_entry_filetype(entry) == AE_IFLNK))
  691. /* We can't get the ACL of a symlink, so we assume it can't
  692. have one. */
  693. aclp = NULL;
  694. else
  695. aclp = sunacl_get(GETACL, &aclcnt, 0, accpath);
  696. /* Ignore "trivial" ACLs that just mirror the file mode. */
  697. if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
  698. archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)),
  699. &r) == 0 && r == 1) {
  700. free(aclp);
  701. aclp = NULL;
  702. }
  703. if (aclp != NULL)
  704. {
  705. r = translate_acl(a, entry, aclp, aclcnt,
  706. ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
  707. free(aclp);
  708. aclp = NULL;
  709. if (r != ARCHIVE_OK) {
  710. archive_set_error(&a->archive, errno,
  711. "Couldn't translate access ACLs");
  712. return (r);
  713. }
  714. }
  715. return (ARCHIVE_OK);
  716. }
  717. int
  718. archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
  719. struct archive_acl *abstract_acl, __LA_MODE_T mode)
  720. {
  721. int ret = ARCHIVE_OK;
  722. (void)mode; /* UNUSED */
  723. if ((archive_acl_types(abstract_acl)
  724. & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
  725. /* Solaris writes POSIX.1e access and default ACLs together */
  726. ret = set_acl(a, fd, name, abstract_acl,
  727. ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, "posix1e");
  728. /* Simultaneous POSIX.1e and NFSv4 is not supported */
  729. return (ret);
  730. }
  731. #if ARCHIVE_ACL_SUNOS_NFS4
  732. else if ((archive_acl_types(abstract_acl) &
  733. ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
  734. ret = set_acl(a, fd, name, abstract_acl,
  735. ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
  736. }
  737. #endif
  738. return (ret);
  739. }
  740. #endif /* ARCHIVE_ACL_SUNOS */