nss_test1.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /* Template generic NSS service provider. See nss_test.h for usage.
  2. Copyright (C) 2017-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. #include <errno.h>
  16. #include <nss.h>
  17. #include <pthread.h>
  18. #include <string.h>
  19. #include <stdio.h>
  20. #include <alloc_buffer.h>
  21. /* We need to be able to handle NULLs "properly" within the testsuite,
  22. to test known bad data. */
  23. #define alloc_buffer_maybe_copy_string(b,s) s ? alloc_buffer_copy_string (b, s) : NULL;
  24. /* This file is the master template. Other instances of this test
  25. module should define NAME(x) to have their name instead of "test1",
  26. then include this file.
  27. */
  28. #define NAME_(x,n) _nss_##n##_##x
  29. #ifndef NAME
  30. #define NAME(x) NAME_(x,test1)
  31. #endif
  32. #define NAMESTR__(x) #x
  33. #define NAMESTR_(x) NAMESTR__(x)
  34. #define NAMESTR(x) NAMESTR_(NAME(x))
  35. #include "nss_test.h"
  36. /* -------------------------------------------------- */
  37. /* Default Data. */
  38. static struct passwd default_pwd_data[] =
  39. {
  40. #define PWD(u) \
  41. { .pw_name = (char *) "name" #u, .pw_passwd = (char *) "*", .pw_uid = u, \
  42. .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*", \
  43. .pw_shell = (char *) "*" }
  44. PWD (30),
  45. PWD (100),
  46. PWD (200),
  47. PWD (60),
  48. PWD (20000)
  49. };
  50. #define default_npwd_data \
  51. (sizeof (default_pwd_data) / sizeof (default_pwd_data[0]))
  52. static struct passwd *pwd_data = default_pwd_data;
  53. static int npwd_data = default_npwd_data;
  54. static struct group *grp_data = NULL;
  55. static int ngrp_data = 0;
  56. /* This function will get called, and once per session, look back into
  57. the test case's executable for an init hook function, and call
  58. it. */
  59. static int initted = 0;
  60. static void
  61. init(void)
  62. {
  63. test_tables t;
  64. int i;
  65. if (initted)
  66. return;
  67. if (NAME(init_hook))
  68. {
  69. memset (&t, 0, sizeof(t));
  70. NAME(init_hook)(&t);
  71. if (t.pwd_table)
  72. {
  73. pwd_data = t.pwd_table;
  74. for (i=0; ! PWD_ISLAST(& pwd_data[i]); i++)
  75. ;
  76. npwd_data = i;
  77. }
  78. if (t.grp_table)
  79. {
  80. grp_data = t.grp_table;
  81. for (i=0; ! GRP_ISLAST(& grp_data[i]); i++)
  82. ;
  83. ngrp_data = i;
  84. }
  85. }
  86. initted = 1;
  87. }
  88. /* -------------------------------------------------- */
  89. /* Password handling. */
  90. static size_t pwd_iter;
  91. #define CURPWD pwd_data[pwd_iter]
  92. static pthread_mutex_t pwd_lock = PTHREAD_MUTEX_INITIALIZER;
  93. enum nss_status
  94. NAME(setpwent) (int stayopen)
  95. {
  96. init();
  97. pwd_iter = 0;
  98. return NSS_STATUS_SUCCESS;
  99. }
  100. enum nss_status
  101. NAME(endpwent) (void)
  102. {
  103. init();
  104. return NSS_STATUS_SUCCESS;
  105. }
  106. static enum nss_status
  107. copy_passwd (struct passwd *result, struct passwd *local,
  108. char *buffer, size_t buflen, int *errnop)
  109. {
  110. struct alloc_buffer buf = alloc_buffer_create (buffer, buflen);
  111. result->pw_name = alloc_buffer_maybe_copy_string (&buf, local->pw_name);
  112. result->pw_passwd = alloc_buffer_maybe_copy_string (&buf, local->pw_passwd);
  113. result->pw_uid = local->pw_uid;
  114. result->pw_gid = local->pw_gid;
  115. result->pw_gecos = alloc_buffer_maybe_copy_string (&buf, local->pw_gecos);
  116. result->pw_dir = alloc_buffer_maybe_copy_string (&buf, local->pw_dir);
  117. result->pw_shell = alloc_buffer_maybe_copy_string (&buf, local->pw_shell);
  118. if (alloc_buffer_has_failed (&buf))
  119. {
  120. *errnop = ERANGE;
  121. return NSS_STATUS_TRYAGAIN;
  122. }
  123. return NSS_STATUS_SUCCESS;
  124. }
  125. enum nss_status
  126. NAME(getpwent_r) (struct passwd *result, char *buffer, size_t buflen,
  127. int *errnop)
  128. {
  129. int res = NSS_STATUS_SUCCESS;
  130. init();
  131. pthread_mutex_lock (&pwd_lock);
  132. if (pwd_iter >= npwd_data)
  133. res = NSS_STATUS_NOTFOUND;
  134. else
  135. {
  136. res = copy_passwd (result, &CURPWD, buffer, buflen, errnop);
  137. ++pwd_iter;
  138. }
  139. pthread_mutex_unlock (&pwd_lock);
  140. return res;
  141. }
  142. enum nss_status
  143. NAME(getpwuid_r) (uid_t uid, struct passwd *result, char *buffer,
  144. size_t buflen, int *errnop)
  145. {
  146. init();
  147. for (size_t idx = 0; idx < npwd_data; ++idx)
  148. if (pwd_data[idx].pw_uid == uid)
  149. return copy_passwd (result, &pwd_data[idx], buffer, buflen, errnop);
  150. return NSS_STATUS_NOTFOUND;
  151. }
  152. enum nss_status
  153. NAME(getpwnam_r) (const char *name, struct passwd *result, char *buffer,
  154. size_t buflen, int *errnop)
  155. {
  156. init();
  157. for (size_t idx = 0; idx < npwd_data; ++idx)
  158. if (strcmp (pwd_data[idx].pw_name, name) == 0)
  159. return copy_passwd (result, &pwd_data[idx], buffer, buflen, errnop);
  160. return NSS_STATUS_NOTFOUND;
  161. }
  162. /* -------------------------------------------------- */
  163. /* Group handling. */
  164. static size_t grp_iter;
  165. #define CURGRP grp_data[grp_iter]
  166. static pthread_mutex_t grp_lock = PTHREAD_MUTEX_INITIALIZER;
  167. enum nss_status
  168. NAME(setgrent) (int stayopen)
  169. {
  170. init();
  171. grp_iter = 0;
  172. return NSS_STATUS_SUCCESS;
  173. }
  174. enum nss_status
  175. NAME(endgrent) (void)
  176. {
  177. init();
  178. return NSS_STATUS_SUCCESS;
  179. }
  180. static enum nss_status
  181. copy_group (struct group *result, struct group *local,
  182. char *buffer, size_t buflen, int *errnop)
  183. {
  184. struct alloc_buffer buf = alloc_buffer_create (buffer, buflen);
  185. char **memlist;
  186. int i;
  187. if (local->gr_mem)
  188. {
  189. i = 0;
  190. while (local->gr_mem[i])
  191. ++i;
  192. memlist = alloc_buffer_alloc_array (&buf, char *, i + 1);
  193. if (memlist) {
  194. for (i = 0; local->gr_mem[i]; ++i)
  195. memlist[i] = alloc_buffer_maybe_copy_string (&buf, local->gr_mem[i]);
  196. memlist[i] = NULL;
  197. }
  198. result->gr_mem = memlist;
  199. }
  200. else
  201. result->gr_mem = NULL;
  202. result->gr_name = alloc_buffer_maybe_copy_string (&buf, local->gr_name);
  203. result->gr_passwd = alloc_buffer_maybe_copy_string (&buf, local->gr_passwd);
  204. result->gr_gid = local->gr_gid;
  205. if (alloc_buffer_has_failed (&buf))
  206. {
  207. *errnop = ERANGE;
  208. return NSS_STATUS_TRYAGAIN;
  209. }
  210. return NSS_STATUS_SUCCESS;
  211. }
  212. enum nss_status
  213. NAME(getgrent_r) (struct group *result, char *buffer, size_t buflen,
  214. int *errnop)
  215. {
  216. int res = NSS_STATUS_SUCCESS;
  217. init();
  218. pthread_mutex_lock (&grp_lock);
  219. if (grp_iter >= ngrp_data)
  220. res = NSS_STATUS_NOTFOUND;
  221. else
  222. {
  223. res = copy_group (result, &CURGRP, buffer, buflen, errnop);
  224. ++grp_iter;
  225. }
  226. pthread_mutex_unlock (&pwd_lock);
  227. return res;
  228. }
  229. enum nss_status
  230. NAME(getgrgid_r) (gid_t gid, struct group *result, char *buffer,
  231. size_t buflen, int *errnop)
  232. {
  233. init();
  234. for (size_t idx = 0; idx < ngrp_data; ++idx)
  235. if (grp_data[idx].gr_gid == gid)
  236. return copy_group (result, &grp_data[idx], buffer, buflen, errnop);
  237. return NSS_STATUS_NOTFOUND;
  238. }
  239. enum nss_status
  240. NAME(getgrnam_r) (const char *name, struct group *result, char *buffer,
  241. size_t buflen, int *errnop)
  242. {
  243. init();
  244. for (size_t idx = 0; idx < ngrp_data; ++idx)
  245. if (strcmp (pwd_data[idx].pw_name, name) == 0)
  246. {
  247. return copy_group (result, &grp_data[idx], buffer, buflen, errnop);
  248. }
  249. return NSS_STATUS_NOTFOUND;
  250. }