acl-internal.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*-
  2. Copyright (C) 2002-2003, 2005-2017 Free Software Foundation, Inc.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible. */
  14. #include <config.h>
  15. #include "acl.h"
  16. #include "acl-internal.h"
  17. #if USE_ACL && HAVE_ACL_GET_FILE
  18. # if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
  19. /* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
  20. Return 1 if the given ACL is non-trivial.
  21. Return 0 if it is trivial. */
  22. int
  23. acl_extended_nontrivial (acl_t acl)
  24. {
  25. /* acl is non-trivial if it is non-empty. */
  26. return (acl_entries (acl) > 0);
  27. }
  28. # else /* Linux, FreeBSD, IRIX, Tru64 */
  29. /* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS.
  30. Return 1 if the given ACL is non-trivial.
  31. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.
  32. Return -1 and set errno upon failure to determine it. */
  33. int
  34. acl_access_nontrivial (acl_t acl)
  35. {
  36. /* acl is non-trivial if it has some entries other than for "user::",
  37. "group::", and "other::". Normally these three should be present
  38. at least, allowing us to write
  39. return (3 < acl_entries (acl));
  40. but the following code is more robust. */
  41. # if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD */
  42. acl_entry_t ace;
  43. int got_one;
  44. for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
  45. got_one > 0;
  46. got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
  47. {
  48. acl_tag_t tag;
  49. if (acl_get_tag_type (ace, &tag) < 0)
  50. return -1;
  51. if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
  52. return 1;
  53. }
  54. return got_one;
  55. # elif HAVE_ACL_TO_SHORT_TEXT /* IRIX */
  56. /* Don't use acl_get_entry: it is undocumented. */
  57. int count = acl->acl_cnt;
  58. int i;
  59. for (i = 0; i < count; i++)
  60. {
  61. acl_entry_t ace = &acl->acl_entry[i];
  62. acl_tag_t tag = ace->ae_tag;
  63. if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ
  64. || tag == ACL_OTHER_OBJ))
  65. return 1;
  66. }
  67. return 0;
  68. # elif HAVE_ACL_FREE_TEXT /* Tru64 */
  69. /* Don't use acl_get_entry: it takes only one argument and does not work. */
  70. int count = acl->acl_num;
  71. acl_entry_t ace;
  72. for (ace = acl->acl_first; count > 0; ace = ace->next, count--)
  73. {
  74. acl_tag_t tag;
  75. acl_perm_t perm;
  76. tag = ace->entry->acl_type;
  77. if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
  78. return 1;
  79. perm = ace->entry->acl_perm;
  80. /* On Tru64, perm can also contain non-standard bits such as
  81. PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ... */
  82. if ((perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)) != 0)
  83. return 1;
  84. }
  85. return 0;
  86. # else
  87. errno = ENOSYS;
  88. return -1;
  89. # endif
  90. }
  91. int
  92. acl_default_nontrivial (acl_t acl)
  93. {
  94. /* acl is non-trivial if it is non-empty. */
  95. return (acl_entries (acl) > 0);
  96. }
  97. # endif
  98. #elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
  99. /* Test an ACL retrieved with GETACL.
  100. Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
  101. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  102. int
  103. acl_nontrivial (int count, aclent_t *entries)
  104. {
  105. int i;
  106. for (i = 0; i < count; i++)
  107. {
  108. aclent_t *ace = &entries[i];
  109. /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
  110. If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
  111. We don't need to check ace->a_id in these cases. */
  112. if (!(ace->a_type == USER_OBJ
  113. || ace->a_type == GROUP_OBJ
  114. || ace->a_type == OTHER_OBJ
  115. /* Note: Cygwin does not return a CLASS_OBJ ("mask:") entry
  116. sometimes. */
  117. || ace->a_type == CLASS_OBJ))
  118. return 1;
  119. }
  120. return 0;
  121. }
  122. # ifdef ACE_GETACL
  123. /* A shortcut for a bitmask. */
  124. # define NEW_ACE_WRITEA_DATA (NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA)
  125. /* Test an ACL retrieved with ACE_GETACL.
  126. Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
  127. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  128. int
  129. acl_ace_nontrivial (int count, ace_t *entries)
  130. {
  131. int i;
  132. /* The flags in the ace_t structure changed in a binary incompatible way
  133. when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15.
  134. How to distinguish the two conventions at runtime?
  135. In the old convention, usually three ACEs have a_flags = ACE_OWNER /
  136. ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. In the new
  137. convention, these values are not used. */
  138. int old_convention = 0;
  139. for (i = 0; i < count; i++)
  140. if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER))
  141. {
  142. old_convention = 1;
  143. break;
  144. }
  145. if (old_convention)
  146. /* Running on Solaris 10. */
  147. for (i = 0; i < count; i++)
  148. {
  149. ace_t *ace = &entries[i];
  150. /* Note:
  151. If ace->a_flags = ACE_OWNER, ace->a_who is the st_uid from stat().
  152. If ace->a_flags = ACE_GROUP, ace->a_who is the st_gid from stat().
  153. We don't need to check ace->a_who in these cases. */
  154. if (!(ace->a_type == OLD_ALLOW
  155. && (ace->a_flags == OLD_ACE_OWNER
  156. || ace->a_flags == OLD_ACE_GROUP
  157. || ace->a_flags == OLD_ACE_OTHER)))
  158. return 1;
  159. }
  160. else
  161. {
  162. /* Running on Solaris 10 (newer version) or Solaris 11. */
  163. unsigned int access_masks[6] =
  164. {
  165. 0, /* owner@ deny */
  166. 0, /* owner@ allow */
  167. 0, /* group@ deny */
  168. 0, /* group@ allow */
  169. 0, /* everyone@ deny */
  170. 0 /* everyone@ allow */
  171. };
  172. for (i = 0; i < count; i++)
  173. {
  174. ace_t *ace = &entries[i];
  175. unsigned int index1;
  176. unsigned int index2;
  177. if (ace->a_type == NEW_ACE_ACCESS_ALLOWED_ACE_TYPE)
  178. index1 = 1;
  179. else if (ace->a_type == NEW_ACE_ACCESS_DENIED_ACE_TYPE)
  180. index1 = 0;
  181. else
  182. return 1;
  183. if (ace->a_flags == NEW_ACE_OWNER)
  184. index2 = 0;
  185. else if (ace->a_flags == (NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP))
  186. index2 = 2;
  187. else if (ace->a_flags == NEW_ACE_EVERYONE)
  188. index2 = 4;
  189. else
  190. return 1;
  191. access_masks[index1 + index2] |= ace->a_access_mask;
  192. }
  193. /* The same bit shouldn't be both allowed and denied. */
  194. if (access_masks[0] & access_masks[1])
  195. return 1;
  196. if (access_masks[2] & access_masks[3])
  197. return 1;
  198. if (access_masks[4] & access_masks[5])
  199. return 1;
  200. /* Check minimum masks. */
  201. if ((NEW_ACE_WRITE_NAMED_ATTRS
  202. | NEW_ACE_WRITE_ATTRIBUTES
  203. | NEW_ACE_WRITE_ACL
  204. | NEW_ACE_WRITE_OWNER)
  205. & ~ access_masks[1])
  206. return 1;
  207. access_masks[1] &= ~(NEW_ACE_WRITE_NAMED_ATTRS
  208. | NEW_ACE_WRITE_ATTRIBUTES
  209. | NEW_ACE_WRITE_ACL
  210. | NEW_ACE_WRITE_OWNER);
  211. if ((NEW_ACE_READ_NAMED_ATTRS
  212. | NEW_ACE_READ_ATTRIBUTES
  213. | NEW_ACE_READ_ACL
  214. | NEW_ACE_SYNCHRONIZE)
  215. & ~ access_masks[5])
  216. return 1;
  217. access_masks[5] &= ~(NEW_ACE_READ_NAMED_ATTRS
  218. | NEW_ACE_READ_ATTRIBUTES
  219. | NEW_ACE_READ_ACL
  220. | NEW_ACE_SYNCHRONIZE);
  221. /* Check the allowed or denied bits. */
  222. switch ((access_masks[0] | access_masks[1])
  223. & ~(NEW_ACE_READ_NAMED_ATTRS
  224. | NEW_ACE_READ_ATTRIBUTES
  225. | NEW_ACE_READ_ACL
  226. | NEW_ACE_SYNCHRONIZE))
  227. {
  228. case 0:
  229. case NEW_ACE_READ_DATA:
  230. case NEW_ACE_WRITEA_DATA:
  231. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
  232. case NEW_ACE_EXECUTE:
  233. case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE:
  234. case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  235. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  236. break;
  237. default:
  238. return 1;
  239. }
  240. switch ((access_masks[2] | access_masks[3])
  241. & ~(NEW_ACE_READ_NAMED_ATTRS
  242. | NEW_ACE_READ_ATTRIBUTES
  243. | NEW_ACE_READ_ACL
  244. | NEW_ACE_SYNCHRONIZE))
  245. {
  246. case 0:
  247. case NEW_ACE_READ_DATA:
  248. case NEW_ACE_WRITEA_DATA:
  249. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
  250. case NEW_ACE_EXECUTE:
  251. case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE:
  252. case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  253. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  254. break;
  255. default:
  256. return 1;
  257. }
  258. switch ((access_masks[4] | access_masks[5])
  259. & ~(NEW_ACE_WRITE_NAMED_ATTRS
  260. | NEW_ACE_WRITE_ATTRIBUTES
  261. | NEW_ACE_WRITE_ACL
  262. | NEW_ACE_WRITE_OWNER))
  263. {
  264. case 0:
  265. case NEW_ACE_READ_DATA:
  266. case NEW_ACE_WRITEA_DATA:
  267. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
  268. case NEW_ACE_EXECUTE:
  269. case NEW_ACE_READ_DATA | NEW_ACE_EXECUTE:
  270. case NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  271. case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
  272. break;
  273. default:
  274. return 1;
  275. }
  276. /* Check that the NEW_ACE_WRITE_DATA and NEW_ACE_APPEND_DATA bits are
  277. either both allowed or both denied. */
  278. if (((access_masks[0] & NEW_ACE_WRITE_DATA) != 0)
  279. != ((access_masks[0] & NEW_ACE_APPEND_DATA) != 0))
  280. return 1;
  281. if (((access_masks[2] & NEW_ACE_WRITE_DATA) != 0)
  282. != ((access_masks[2] & NEW_ACE_APPEND_DATA) != 0))
  283. return 1;
  284. if (((access_masks[4] & NEW_ACE_WRITE_DATA) != 0)
  285. != ((access_masks[4] & NEW_ACE_APPEND_DATA) != 0))
  286. return 1;
  287. }
  288. return 0;
  289. }
  290. # endif
  291. #elif USE_ACL && HAVE_GETACL /* HP-UX */
  292. /* Return 1 if the given ACL is non-trivial.
  293. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  294. int
  295. acl_nontrivial (int count, struct acl_entry *entries)
  296. {
  297. int i;
  298. if (count > 3)
  299. return 1;
  300. for (i = 0; i < count; i++)
  301. {
  302. struct acl_entry *ace = &entries[i];
  303. if (ace->uid != ACL_NSUSER && ace->gid != ACL_NSGROUP)
  304. return 1;
  305. }
  306. return 0;
  307. }
  308. # if HAVE_ACLV_H /* HP-UX >= 11.11 */
  309. /* Return 1 if the given ACL is non-trivial.
  310. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  311. int
  312. aclv_nontrivial (int count, struct acl *entries)
  313. {
  314. int i;
  315. for (i = 0; i < count; i++)
  316. {
  317. struct acl *ace = &entries[i];
  318. /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
  319. If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
  320. We don't need to check ace->a_id in these cases. */
  321. if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
  322. || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
  323. || ace->a_type == CLASS_OBJ
  324. || ace->a_type == OTHER_OBJ))
  325. return 1;
  326. }
  327. return 0;
  328. }
  329. # endif
  330. #elif USE_ACL && (HAVE_ACLX_GET || HAVE_STATACL) /* AIX */
  331. /* Return 1 if the given ACL is non-trivial.
  332. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  333. int
  334. acl_nontrivial (struct acl *a)
  335. {
  336. /* The normal way to iterate through an ACL is like this:
  337. struct acl_entry *ace;
  338. for (ace = a->acl_ext; ace != acl_last (a); ace = acl_nxt (ace))
  339. {
  340. struct ace_id *aei;
  341. switch (ace->ace_type)
  342. {
  343. case ACC_PERMIT:
  344. case ACC_DENY:
  345. case ACC_SPECIFY:
  346. ...;
  347. }
  348. for (aei = ace->ace_id; aei != id_last (ace); aei = id_nxt (aei))
  349. ...
  350. }
  351. */
  352. return (acl_last (a) != a->acl_ext ? 1 : 0);
  353. }
  354. # if HAVE_ACLX_GET && defined ACL_AIX_WIP /* newer AIX */
  355. /* Return 1 if the given ACL is non-trivial.
  356. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  357. int
  358. acl_nfs4_nontrivial (nfs4_acl_int_t *a)
  359. {
  360. # if 1 /* let's try this first */
  361. return (a->aclEntryN > 0 ? 1 : 0);
  362. # else
  363. int count = a->aclEntryN;
  364. int i;
  365. for (i = 0; i < count; i++)
  366. {
  367. nfs4_ace_int_t *ace = &a->aclEntry[i];
  368. if (!((ace->flags & ACE4_ID_SPECIAL) != 0
  369. && (ace->aceWho.special_whoid == ACE4_WHO_OWNER
  370. || ace->aceWho.special_whoid == ACE4_WHO_GROUP
  371. || ace->aceWho.special_whoid == ACE4_WHO_EVERYONE)
  372. && ace->aceType == ACE4_ACCESS_ALLOWED_ACE_TYPE
  373. && ace->aceFlags == 0
  374. && (ace->aceMask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY
  375. | ACE4_WRITE_DATA | ACE4_ADD_FILE
  376. | ACE4_EXECUTE)) == 0))
  377. return 1;
  378. }
  379. return 0;
  380. # endif
  381. }
  382. # endif
  383. #elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */
  384. /* Test an ACL retrieved with ACL_GET.
  385. Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
  386. Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */
  387. int
  388. acl_nontrivial (int count, struct acl *entries)
  389. {
  390. int i;
  391. for (i = 0; i < count; i++)
  392. {
  393. struct acl *ace = &entries[i];
  394. /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
  395. If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
  396. We don't need to check ace->a_id in these cases. */
  397. if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
  398. || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
  399. || ace->a_type == CLASS_OBJ
  400. || ace->a_type == OTHER_OBJ))
  401. return 1;
  402. }
  403. return 0;
  404. }
  405. #endif
  406. void
  407. free_permission_context (struct permission_context *ctx)
  408. {
  409. #if USE_ACL
  410. # if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
  411. if (ctx->acl)
  412. acl_free (ctx->acl);
  413. # if !HAVE_ACL_TYPE_EXTENDED
  414. if (ctx->default_acl)
  415. acl_free (ctx->default_acl);
  416. # endif
  417. # elif defined GETACL /* Solaris, Cygwin */
  418. free (ctx->entries);
  419. # ifdef ACE_GETACL
  420. free (ctx->ace_entries);
  421. # endif
  422. # elif HAVE_GETACL /* HP-UX */
  423. # if HAVE_ACLV_H
  424. # endif
  425. # elif HAVE_STATACL /* older AIX */
  426. # elif HAVE_ACLSORT /* NonStop Kernel */
  427. # endif
  428. #endif
  429. }