PageRenderTime 55ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/release/src/router/samba3/source/modules/vfs_posixacl.c

https://gitlab.com/envieidoc/advancedtomato2
C | 398 lines | 322 code | 52 blank | 24 comment | 54 complexity | 53049625876122f0b676527482eff0da MD5 | raw file
  1. /*
  2. Unix SMB/Netbios implementation.
  3. VFS module to get and set posix acls
  4. Copyright (C) Volker Lendecke 2006
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17. #include "includes.h"
  18. /* prototypes for static functions first - for clarity */
  19. static BOOL smb_ace_to_internal(acl_entry_t posix_ace,
  20. struct smb_acl_entry *ace);
  21. static struct smb_acl_t *smb_acl_to_internal(acl_t acl);
  22. static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm);
  23. static acl_t smb_acl_to_posix(const struct smb_acl_t *acl);
  24. /* public functions - the api */
  25. SMB_ACL_T posixacl_sys_acl_get_file(vfs_handle_struct *handle,
  26. const char *path_p,
  27. SMB_ACL_TYPE_T type)
  28. {
  29. struct smb_acl_t *result;
  30. acl_type_t acl_type;
  31. acl_t acl;
  32. switch(type) {
  33. case SMB_ACL_TYPE_ACCESS:
  34. acl_type = ACL_TYPE_ACCESS;
  35. break;
  36. case SMB_ACL_TYPE_DEFAULT:
  37. acl_type = ACL_TYPE_DEFAULT;
  38. break;
  39. default:
  40. errno = EINVAL;
  41. return NULL;
  42. }
  43. acl = acl_get_file(path_p, acl_type);
  44. if (acl == NULL) {
  45. return NULL;
  46. }
  47. result = smb_acl_to_internal(acl);
  48. acl_free(acl);
  49. return result;
  50. }
  51. SMB_ACL_T posixacl_sys_acl_get_fd(vfs_handle_struct *handle,
  52. files_struct *fsp,
  53. int fd)
  54. {
  55. struct smb_acl_t *result;
  56. acl_t acl = acl_get_fd(fd);
  57. if (acl == NULL) {
  58. return NULL;
  59. }
  60. result = smb_acl_to_internal(acl);
  61. acl_free(acl);
  62. return result;
  63. }
  64. int posixacl_sys_acl_set_file(vfs_handle_struct *handle,
  65. const char *name,
  66. SMB_ACL_TYPE_T type,
  67. SMB_ACL_T theacl)
  68. {
  69. int res;
  70. acl_type_t acl_type;
  71. acl_t acl;
  72. DEBUG(10, ("Calling acl_set_file: %s, %d\n", name, type));
  73. switch(type) {
  74. case SMB_ACL_TYPE_ACCESS:
  75. acl_type = ACL_TYPE_ACCESS;
  76. break;
  77. case SMB_ACL_TYPE_DEFAULT:
  78. acl_type = ACL_TYPE_DEFAULT;
  79. break;
  80. default:
  81. errno = EINVAL;
  82. return -1;
  83. }
  84. if ((acl = smb_acl_to_posix(theacl)) == NULL) {
  85. return -1;
  86. }
  87. res = acl_set_file(name, acl_type, acl);
  88. if (res != 0) {
  89. DEBUG(10, ("acl_set_file failed: %s\n", strerror(errno)));
  90. }
  91. acl_free(acl);
  92. return res;
  93. }
  94. int posixacl_sys_acl_set_fd(vfs_handle_struct *handle,
  95. files_struct *fsp,
  96. int fd, SMB_ACL_T theacl)
  97. {
  98. int res;
  99. acl_t acl = smb_acl_to_posix(theacl);
  100. if (acl == NULL) {
  101. return -1;
  102. }
  103. res = acl_set_fd(fd, acl);
  104. acl_free(acl);
  105. return res;
  106. }
  107. int posixacl_sys_acl_delete_def_file(vfs_handle_struct *handle,
  108. const char *path)
  109. {
  110. return acl_delete_def_file(path);
  111. }
  112. /* private functions */
  113. static BOOL smb_ace_to_internal(acl_entry_t posix_ace,
  114. struct smb_acl_entry *ace)
  115. {
  116. acl_tag_t tag;
  117. acl_permset_t permset;
  118. if (acl_get_tag_type(posix_ace, &tag) != 0) {
  119. DEBUG(0, ("smb_acl_get_tag_type failed\n"));
  120. return False;
  121. }
  122. switch(tag) {
  123. case ACL_USER:
  124. ace->a_type = SMB_ACL_USER;
  125. break;
  126. case ACL_USER_OBJ:
  127. ace->a_type = SMB_ACL_USER_OBJ;
  128. break;
  129. case ACL_GROUP:
  130. ace->a_type = SMB_ACL_GROUP;
  131. break;
  132. case ACL_GROUP_OBJ:
  133. ace->a_type = SMB_ACL_GROUP_OBJ;
  134. break;
  135. case ACL_OTHER:
  136. ace->a_type = SMB_ACL_OTHER;
  137. break;
  138. case ACL_MASK:
  139. ace->a_type = SMB_ACL_MASK;
  140. break;
  141. default:
  142. DEBUG(0, ("unknown tag type %d\n", (unsigned int)tag));
  143. return False;
  144. }
  145. switch(ace->a_type) {
  146. case SMB_ACL_USER: {
  147. uid_t *puid = (uid_t *)acl_get_qualifier(posix_ace);
  148. if (puid == NULL) {
  149. DEBUG(0, ("smb_acl_get_qualifier failed\n"));
  150. return False;
  151. }
  152. ace->uid = *puid;
  153. acl_free(puid);
  154. break;
  155. }
  156. case SMB_ACL_GROUP: {
  157. gid_t *pgid = (uid_t *)acl_get_qualifier(posix_ace);
  158. if (pgid == NULL) {
  159. DEBUG(0, ("smb_acl_get_qualifier failed\n"));
  160. return False;
  161. }
  162. ace->gid = *pgid;
  163. acl_free(pgid);
  164. break;
  165. }
  166. default:
  167. break;
  168. }
  169. if (acl_get_permset(posix_ace, &permset) != 0) {
  170. DEBUG(0, ("smb_acl_get_mode failed\n"));
  171. return False;
  172. }
  173. ace->a_perm = 0;
  174. #ifdef HAVE_ACL_GET_PERM_NP
  175. ace->a_perm |= (acl_get_perm_np(permset, ACL_READ) ? SMB_ACL_READ : 0);
  176. ace->a_perm |= (acl_get_perm_np(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0);
  177. ace->a_perm |= (acl_get_perm_np(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
  178. #else
  179. ace->a_perm |= (acl_get_perm(permset, ACL_READ) ? SMB_ACL_READ : 0);
  180. ace->a_perm |= (acl_get_perm(permset, ACL_WRITE) ? SMB_ACL_WRITE : 0);
  181. ace->a_perm |= (acl_get_perm(permset, ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
  182. #endif
  183. return True;
  184. }
  185. static struct smb_acl_t *smb_acl_to_internal(acl_t acl)
  186. {
  187. struct smb_acl_t *result = SMB_MALLOC_P(struct smb_acl_t);
  188. int entry_id = ACL_FIRST_ENTRY;
  189. acl_entry_t e;
  190. if (result == NULL) {
  191. return NULL;
  192. }
  193. ZERO_STRUCTP(result);
  194. while (acl_get_entry(acl, entry_id, &e) == 1) {
  195. entry_id = ACL_NEXT_ENTRY;
  196. result = (struct smb_acl_t *)SMB_REALLOC(
  197. result, sizeof(struct smb_acl_t) +
  198. (sizeof(struct smb_acl_entry) * (result->count+1)));
  199. if (result == NULL) {
  200. DEBUG(0, ("SMB_REALLOC failed\n"));
  201. errno = ENOMEM;
  202. return NULL;
  203. }
  204. if (!smb_ace_to_internal(e, &result->acl[result->count])) {
  205. SAFE_FREE(result);
  206. return NULL;
  207. }
  208. result->count += 1;
  209. }
  210. return result;
  211. }
  212. static int smb_acl_set_mode(acl_entry_t entry, SMB_ACL_PERM_T perm)
  213. {
  214. int ret;
  215. acl_permset_t permset;
  216. if ((ret = acl_get_permset(entry, &permset)) != 0) {
  217. return ret;
  218. }
  219. if ((ret = acl_clear_perms(permset)) != 0) {
  220. return ret;
  221. }
  222. if ((perm & SMB_ACL_READ) &&
  223. ((ret = acl_add_perm(permset, ACL_READ)) != 0)) {
  224. return ret;
  225. }
  226. if ((perm & SMB_ACL_WRITE) &&
  227. ((ret = acl_add_perm(permset, ACL_WRITE)) != 0)) {
  228. return ret;
  229. }
  230. if ((perm & SMB_ACL_EXECUTE) &&
  231. ((ret = acl_add_perm(permset, ACL_EXECUTE)) != 0)) {
  232. return ret;
  233. }
  234. return acl_set_permset(entry, permset);
  235. }
  236. static acl_t smb_acl_to_posix(const struct smb_acl_t *acl)
  237. {
  238. acl_t result;
  239. int i;
  240. result = acl_init(acl->count);
  241. if (result == NULL) {
  242. DEBUG(10, ("acl_init failed\n"));
  243. return NULL;
  244. }
  245. for (i=0; i<acl->count; i++) {
  246. const struct smb_acl_entry *entry = &acl->acl[i];
  247. acl_entry_t e;
  248. acl_tag_t tag;
  249. if (acl_create_entry(&result, &e) != 0) {
  250. DEBUG(1, ("acl_create_entry failed: %s\n",
  251. strerror(errno)));
  252. goto fail;
  253. }
  254. switch (entry->a_type) {
  255. case SMB_ACL_USER:
  256. tag = ACL_USER;
  257. break;
  258. case SMB_ACL_USER_OBJ:
  259. tag = ACL_USER_OBJ;
  260. break;
  261. case SMB_ACL_GROUP:
  262. tag = ACL_GROUP;
  263. break;
  264. case SMB_ACL_GROUP_OBJ:
  265. tag = ACL_GROUP_OBJ;
  266. break;
  267. case SMB_ACL_OTHER:
  268. tag = ACL_OTHER;
  269. break;
  270. case SMB_ACL_MASK:
  271. tag = ACL_MASK;
  272. break;
  273. default:
  274. DEBUG(1, ("Unknown tag value %d\n", entry->a_type));
  275. goto fail;
  276. }
  277. if (acl_set_tag_type(e, tag) != 0) {
  278. DEBUG(10, ("acl_set_tag_type(%d) failed: %s\n",
  279. tag, strerror(errno)));
  280. goto fail;
  281. }
  282. switch (entry->a_type) {
  283. case SMB_ACL_USER:
  284. if (acl_set_qualifier(e, &entry->uid) != 0) {
  285. DEBUG(1, ("acl_set_qualifiier failed: %s\n",
  286. strerror(errno)));
  287. goto fail;
  288. }
  289. break;
  290. case SMB_ACL_GROUP:
  291. if (acl_set_qualifier(e, &entry->gid) != 0) {
  292. DEBUG(1, ("acl_set_qualifiier failed: %s\n",
  293. strerror(errno)));
  294. goto fail;
  295. }
  296. break;
  297. default: /* Shut up, compiler! :-) */
  298. break;
  299. }
  300. if (smb_acl_set_mode(e, entry->a_perm) != 0) {
  301. goto fail;
  302. }
  303. }
  304. if (acl_valid(result) != 0) {
  305. DEBUG(0, ("smb_acl_to_posix: ACL is invalid for set (%s)\n",
  306. strerror(errno)));
  307. goto fail;
  308. }
  309. return result;
  310. fail:
  311. if (result != NULL) {
  312. acl_free(result);
  313. }
  314. return NULL;
  315. }
  316. /* VFS operations structure */
  317. static vfs_op_tuple posixacl_op_tuples[] = {
  318. /* Disk operations */
  319. {SMB_VFS_OP(posixacl_sys_acl_get_file),
  320. SMB_VFS_OP_SYS_ACL_GET_FILE,
  321. SMB_VFS_LAYER_TRANSPARENT},
  322. {SMB_VFS_OP(posixacl_sys_acl_get_fd),
  323. SMB_VFS_OP_SYS_ACL_GET_FD,
  324. SMB_VFS_LAYER_TRANSPARENT},
  325. {SMB_VFS_OP(posixacl_sys_acl_set_file),
  326. SMB_VFS_OP_SYS_ACL_SET_FILE,
  327. SMB_VFS_LAYER_TRANSPARENT},
  328. {SMB_VFS_OP(posixacl_sys_acl_set_fd),
  329. SMB_VFS_OP_SYS_ACL_SET_FD,
  330. SMB_VFS_LAYER_TRANSPARENT},
  331. {SMB_VFS_OP(posixacl_sys_acl_delete_def_file),
  332. SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
  333. SMB_VFS_LAYER_TRANSPARENT},
  334. {SMB_VFS_OP(NULL),
  335. SMB_VFS_OP_NOOP,
  336. SMB_VFS_LAYER_NOOP}
  337. };
  338. NTSTATUS vfs_posixacl_init(void);
  339. NTSTATUS vfs_posixacl_init(void)
  340. {
  341. return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "posixacl",
  342. posixacl_op_tuples);
  343. }