auth_unix.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*
  2. * Copyright (c) 2010, 2011, Oracle America, Inc.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above
  11. * copyright notice, this list of conditions and the following
  12. * disclaimer in the documentation and/or other materials
  13. * provided with the distribution.
  14. * * Neither the name of the "Oracle America, Inc." nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  22. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  23. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  25. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  27. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. /*
  32. * auth_unix.c, Implements UNIX style authentication parameters.
  33. *
  34. * The system is very weak. The client uses no encryption for it's
  35. * credentials and only sends null verifiers. The server sends backs
  36. * null verifiers or optionally a verifier that suggests a new short hand
  37. * for the credentials.
  38. */
  39. #include <errno.h>
  40. #include <limits.h>
  41. #include <stdbool.h>
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include <unistd.h>
  45. #include <libintl.h>
  46. #include <sys/param.h>
  47. #include <wchar.h>
  48. #include <shlib-compat.h>
  49. #include <rpc/types.h>
  50. #include <rpc/xdr.h>
  51. #include <rpc/auth.h>
  52. #include <rpc/auth_unix.h>
  53. /*
  54. * Unix authenticator operations vector
  55. */
  56. static void authunix_nextverf (AUTH *);
  57. static bool_t authunix_marshal (AUTH *, XDR *);
  58. static bool_t authunix_validate (AUTH *, struct opaque_auth *);
  59. static bool_t authunix_refresh (AUTH *);
  60. static void authunix_destroy (AUTH *);
  61. static const struct auth_ops auth_unix_ops = {
  62. authunix_nextverf,
  63. authunix_marshal,
  64. authunix_validate,
  65. authunix_refresh,
  66. authunix_destroy
  67. };
  68. /*
  69. * This struct is pointed to by the ah_private field of an auth_handle.
  70. */
  71. struct audata {
  72. struct opaque_auth au_origcred; /* original credentials */
  73. struct opaque_auth au_shcred; /* short hand cred */
  74. u_long au_shfaults; /* short hand cache faults */
  75. char au_marshed[MAX_AUTH_BYTES];
  76. u_int au_mpos; /* xdr pos at end of marshed */
  77. };
  78. #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
  79. static bool_t marshal_new_auth (AUTH *);
  80. /*
  81. * Create a unix style authenticator.
  82. * Returns an auth handle with the given stuff in it.
  83. */
  84. AUTH *
  85. authunix_create (char *machname, uid_t uid, gid_t gid, int len,
  86. gid_t *aup_gids)
  87. {
  88. struct authunix_parms aup;
  89. char mymem[MAX_AUTH_BYTES];
  90. struct timeval now;
  91. XDR xdrs;
  92. AUTH *auth;
  93. struct audata *au;
  94. /*
  95. * Allocate and set up auth handle
  96. */
  97. auth = (AUTH *) mem_alloc (sizeof (*auth));
  98. au = (struct audata *) mem_alloc (sizeof (*au));
  99. if (auth == NULL || au == NULL)
  100. {
  101. no_memory:
  102. (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
  103. mem_free (auth, sizeof (*auth));
  104. mem_free (au, sizeof (*au));
  105. return NULL;
  106. }
  107. auth->ah_ops = (struct auth_ops *) &auth_unix_ops;
  108. auth->ah_private = (caddr_t) au;
  109. auth->ah_verf = au->au_shcred = _null_auth;
  110. au->au_shfaults = 0;
  111. /*
  112. * fill in param struct from the given params
  113. */
  114. (void) __gettimeofday (&now, (struct timezone *) 0);
  115. aup.aup_time = now.tv_sec;
  116. aup.aup_machname = machname;
  117. aup.aup_uid = uid;
  118. aup.aup_gid = gid;
  119. aup.aup_len = (u_int) len;
  120. aup.aup_gids = aup_gids;
  121. /*
  122. * Serialize the parameters into origcred
  123. */
  124. xdrmem_create (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
  125. if (!xdr_authunix_parms (&xdrs, &aup))
  126. abort ();
  127. au->au_origcred.oa_length = len = XDR_GETPOS (&xdrs);
  128. au->au_origcred.oa_flavor = AUTH_UNIX;
  129. au->au_origcred.oa_base = mem_alloc ((u_int) len);
  130. if (au->au_origcred.oa_base == NULL)
  131. goto no_memory;
  132. memcpy(au->au_origcred.oa_base, mymem, (u_int) len);
  133. /*
  134. * set auth handle to reflect new cred.
  135. */
  136. auth->ah_cred = au->au_origcred;
  137. marshal_new_auth (auth);
  138. return auth;
  139. }
  140. libc_hidden_nolink_sunrpc (authunix_create, GLIBC_2_0)
  141. /*
  142. * Returns an auth handle with parameters determined by doing lots of
  143. * syscalls.
  144. */
  145. AUTH *
  146. authunix_create_default (void)
  147. {
  148. char machname[MAX_MACHINE_NAME + 1];
  149. if (__gethostname (machname, MAX_MACHINE_NAME) == -1)
  150. abort ();
  151. machname[MAX_MACHINE_NAME] = 0;
  152. uid_t uid = __geteuid ();
  153. gid_t gid = __getegid ();
  154. int max_nr_groups;
  155. /* When we have to try a second time, do not use alloca() again. We
  156. might have reached the stack limit already. */
  157. bool retry = false;
  158. again:
  159. /* Ask the kernel how many groups there are exactly. Note that we
  160. might have to redo all this if the number of groups has changed
  161. between the two calls. */
  162. max_nr_groups = __getgroups (0, NULL);
  163. /* Just some random reasonable stack limit. */
  164. #define ALLOCA_LIMIT (1024 / sizeof (gid_t))
  165. gid_t *gids = NULL;
  166. if (max_nr_groups < ALLOCA_LIMIT && ! retry)
  167. gids = (gid_t *) alloca (max_nr_groups * sizeof (gid_t));
  168. else
  169. {
  170. gids = (gid_t *) malloc (max_nr_groups * sizeof (gid_t));
  171. if (gids == NULL)
  172. return NULL;
  173. }
  174. int len = __getgroups (max_nr_groups, gids);
  175. if (len == -1)
  176. {
  177. if (errno == EINVAL)
  178. {
  179. /* New groups added in the meantime. Try again. */
  180. if (max_nr_groups >= ALLOCA_LIMIT || retry)
  181. free (gids);
  182. retry = true;
  183. goto again;
  184. }
  185. /* No other error can happen. */
  186. abort ();
  187. }
  188. /* This braindamaged Sun code forces us here to truncate the
  189. list of groups to NGRPS members since the code in
  190. authuxprot.c transforms a fixed array. Grrr. */
  191. AUTH *result = authunix_create (machname, uid, gid, MIN (NGRPS, len), gids);
  192. if (max_nr_groups >= ALLOCA_LIMIT || retry)
  193. free (gids);
  194. return result;
  195. }
  196. #ifdef EXPORT_RPC_SYMBOLS
  197. libc_hidden_def (authunix_create_default)
  198. #else
  199. libc_hidden_nolink_sunrpc (authunix_create_default, GLIBC_2_0)
  200. #endif
  201. /*
  202. * authunix operations
  203. */
  204. static void
  205. authunix_nextverf (AUTH *auth)
  206. {
  207. /* no action necessary */
  208. }
  209. static bool_t
  210. authunix_marshal (AUTH *auth, XDR *xdrs)
  211. {
  212. struct audata *au = AUTH_PRIVATE (auth);
  213. return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos);
  214. }
  215. static bool_t
  216. authunix_validate (AUTH *auth, struct opaque_auth *verf)
  217. {
  218. struct audata *au;
  219. XDR xdrs;
  220. if (verf->oa_flavor == AUTH_SHORT)
  221. {
  222. au = AUTH_PRIVATE (auth);
  223. xdrmem_create (&xdrs, verf->oa_base, verf->oa_length, XDR_DECODE);
  224. if (au->au_shcred.oa_base != NULL)
  225. {
  226. mem_free (au->au_shcred.oa_base,
  227. au->au_shcred.oa_length);
  228. au->au_shcred.oa_base = NULL;
  229. }
  230. if (xdr_opaque_auth (&xdrs, &au->au_shcred))
  231. {
  232. auth->ah_cred = au->au_shcred;
  233. }
  234. else
  235. {
  236. xdrs.x_op = XDR_FREE;
  237. (void) xdr_opaque_auth (&xdrs, &au->au_shcred);
  238. au->au_shcred.oa_base = NULL;
  239. auth->ah_cred = au->au_origcred;
  240. }
  241. marshal_new_auth (auth);
  242. }
  243. return TRUE;
  244. }
  245. static bool_t
  246. authunix_refresh (AUTH *auth)
  247. {
  248. struct audata *au = AUTH_PRIVATE (auth);
  249. struct authunix_parms aup;
  250. struct timeval now;
  251. XDR xdrs;
  252. int stat;
  253. if (auth->ah_cred.oa_base == au->au_origcred.oa_base)
  254. {
  255. /* there is no hope. Punt */
  256. return FALSE;
  257. }
  258. au->au_shfaults++;
  259. /* first deserialize the creds back into a struct authunix_parms */
  260. aup.aup_machname = NULL;
  261. aup.aup_gids = (gid_t *) NULL;
  262. xdrmem_create (&xdrs, au->au_origcred.oa_base,
  263. au->au_origcred.oa_length, XDR_DECODE);
  264. stat = xdr_authunix_parms (&xdrs, &aup);
  265. if (!stat)
  266. goto done;
  267. /* update the time and serialize in place */
  268. (void) __gettimeofday (&now, (struct timezone *) 0);
  269. aup.aup_time = now.tv_sec;
  270. xdrs.x_op = XDR_ENCODE;
  271. XDR_SETPOS (&xdrs, 0);
  272. stat = xdr_authunix_parms (&xdrs, &aup);
  273. if (!stat)
  274. goto done;
  275. auth->ah_cred = au->au_origcred;
  276. marshal_new_auth (auth);
  277. done:
  278. /* free the struct authunix_parms created by deserializing */
  279. xdrs.x_op = XDR_FREE;
  280. (void) xdr_authunix_parms (&xdrs, &aup);
  281. XDR_DESTROY (&xdrs);
  282. return stat;
  283. }
  284. static void
  285. authunix_destroy (AUTH *auth)
  286. {
  287. struct audata *au = AUTH_PRIVATE (auth);
  288. mem_free (au->au_origcred.oa_base, au->au_origcred.oa_length);
  289. if (au->au_shcred.oa_base != NULL)
  290. mem_free (au->au_shcred.oa_base, au->au_shcred.oa_length);
  291. mem_free (auth->ah_private, sizeof (struct audata));
  292. if (auth->ah_verf.oa_base != NULL)
  293. mem_free (auth->ah_verf.oa_base, auth->ah_verf.oa_length);
  294. mem_free ((caddr_t) auth, sizeof (*auth));
  295. }
  296. /*
  297. * Marshals (pre-serializes) an auth struct.
  298. * sets private data, au_marshed and au_mpos
  299. */
  300. static bool_t
  301. marshal_new_auth (AUTH *auth)
  302. {
  303. XDR xdr_stream;
  304. XDR *xdrs = &xdr_stream;
  305. struct audata *au = AUTH_PRIVATE (auth);
  306. xdrmem_create (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
  307. if ((!xdr_opaque_auth (xdrs, &(auth->ah_cred))) ||
  308. (!xdr_opaque_auth (xdrs, &(auth->ah_verf))))
  309. perror (_("auth_unix.c: Fatal marshalling problem"));
  310. else
  311. au->au_mpos = XDR_GETPOS (xdrs);
  312. XDR_DESTROY (xdrs);
  313. return TRUE;
  314. }