PageRenderTime 24ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/samba-3.5.6/source3/lib/system_smbd.c

https://github.com/theuni/XBMC-deps
C | 198 lines | 123 code | 30 blank | 45 comment | 25 complexity | bd5e5f117629c6745168b376d2e48aba MD5 | raw file
  1. /*
  2. Unix SMB/CIFS implementation.
  3. system call wrapper interface.
  4. Copyright (C) Andrew Tridgell 2002
  5. Copyright (C) Andrew Barteltt 2002
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. /*
  18. This file may assume linkage with smbd - for things like become_root()
  19. etc.
  20. */
  21. #include "includes.h"
  22. #ifndef HAVE_GETGROUPLIST
  23. /*
  24. This is a *much* faster way of getting the list of groups for a user
  25. without changing the current supplementary group list. The old
  26. method used getgrent() which could take 20 minutes on a really big
  27. network with hundeds of thousands of groups and users. The new method
  28. takes a couple of seconds.
  29. NOTE!! this function only works if it is called as root!
  30. */
  31. static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups,
  32. int *grpcnt)
  33. {
  34. gid_t *gids_saved;
  35. int ret, ngrp_saved, num_gids;
  36. if (non_root_mode()) {
  37. *grpcnt = 0;
  38. return 0;
  39. }
  40. /* work out how many groups we need to save */
  41. ngrp_saved = getgroups(0, NULL);
  42. if (ngrp_saved == -1) {
  43. /* this shouldn't happen */
  44. return -1;
  45. }
  46. gids_saved = SMB_MALLOC_ARRAY(gid_t, ngrp_saved+1);
  47. if (!gids_saved) {
  48. errno = ENOMEM;
  49. return -1;
  50. }
  51. ngrp_saved = getgroups(ngrp_saved, gids_saved);
  52. if (ngrp_saved == -1) {
  53. SAFE_FREE(gids_saved);
  54. /* very strange! */
  55. return -1;
  56. }
  57. if (initgroups(user, gid) != 0) {
  58. DEBUG(0, ("getgrouplist_internals: initgroups() failed!\n"));
  59. SAFE_FREE(gids_saved);
  60. return -1;
  61. }
  62. /* this must be done to cope with systems that put the current egid in the
  63. return from getgroups() */
  64. save_re_gid();
  65. set_effective_gid(gid);
  66. setgid(gid);
  67. num_gids = getgroups(0, NULL);
  68. if (num_gids == -1) {
  69. SAFE_FREE(gids_saved);
  70. /* very strange! */
  71. return -1;
  72. }
  73. if (num_gids + 1 > *grpcnt) {
  74. *grpcnt = num_gids + 1;
  75. ret = -1;
  76. } else {
  77. ret = getgroups(*grpcnt - 1, &groups[1]);
  78. if (ret < 0) {
  79. SAFE_FREE(gids_saved);
  80. /* very strange! */
  81. return -1;
  82. }
  83. groups[0] = gid;
  84. *grpcnt = ret + 1;
  85. }
  86. restore_re_gid();
  87. if (sys_setgroups(gid, ngrp_saved, gids_saved) != 0) {
  88. /* yikes! */
  89. DEBUG(0,("ERROR: getgrouplist: failed to reset group list!\n"));
  90. smb_panic("getgrouplist: failed to reset group list!");
  91. }
  92. free(gids_saved);
  93. return ret;
  94. }
  95. #endif
  96. static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
  97. {
  98. int retval;
  99. bool winbind_env;
  100. DEBUG(10,("sys_getgrouplist: user [%s]\n", user));
  101. /* This is only ever called for Unix users, remote memberships are
  102. * always determined by the info3 coming back from auth3 or the
  103. * PAC. */
  104. winbind_env = winbind_env_set();
  105. (void)winbind_off();
  106. #ifdef HAVE_GETGROUPLIST
  107. retval = getgrouplist(user, gid, groups, grpcnt);
  108. #else
  109. become_root();
  110. retval = getgrouplist_internals(user, gid, groups, grpcnt);
  111. unbecome_root();
  112. #endif
  113. /* allow winbindd lookups, but only if they were not already disabled */
  114. if (!winbind_env) {
  115. (void)winbind_on();
  116. }
  117. return retval;
  118. }
  119. bool getgroups_unix_user(TALLOC_CTX *mem_ctx, const char *user,
  120. gid_t primary_gid,
  121. gid_t **ret_groups, size_t *p_ngroups)
  122. {
  123. size_t ngrp;
  124. int max_grp;
  125. gid_t *temp_groups;
  126. gid_t *groups;
  127. int i;
  128. max_grp = MIN(128, groups_max());
  129. temp_groups = SMB_MALLOC_ARRAY(gid_t, max_grp);
  130. if (! temp_groups) {
  131. return False;
  132. }
  133. if (sys_getgrouplist(user, primary_gid, temp_groups, &max_grp) == -1) {
  134. temp_groups = SMB_REALLOC_ARRAY(temp_groups, gid_t, max_grp);
  135. if (!temp_groups) {
  136. return False;
  137. }
  138. if (sys_getgrouplist(user, primary_gid,
  139. temp_groups, &max_grp) == -1) {
  140. DEBUG(0, ("get_user_groups: failed to get the unix "
  141. "group list\n"));
  142. SAFE_FREE(temp_groups);
  143. return False;
  144. }
  145. }
  146. ngrp = 0;
  147. groups = NULL;
  148. /* Add in primary group first */
  149. if (!add_gid_to_array_unique(mem_ctx, primary_gid, &groups, &ngrp)) {
  150. SAFE_FREE(temp_groups);
  151. return False;
  152. }
  153. for (i=0; i<max_grp; i++) {
  154. if (!add_gid_to_array_unique(mem_ctx, temp_groups[i],
  155. &groups, &ngrp)) {
  156. SAFE_FREE(temp_groups);
  157. return False;
  158. }
  159. }
  160. *p_ngroups = ngrp;
  161. *ret_groups = groups;
  162. SAFE_FREE(temp_groups);
  163. return True;
  164. }