PageRenderTime 38ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/src/uts/common/rpc/sec/key_call.c

https://bitbucket.org/a3217055/illumos-joyent
C | 323 lines | 218 code | 42 blank | 63 comment | 27 complexity | 9f2691c601e28b57e30a495236ca3ed1 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, GPL-2.0, GPL-3.0, 0BSD, BSD-2-Clause, BSD-3-Clause-No-Nuclear-License-2014, MPL-2.0-no-copyleft-exception, AGPL-1.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License (the "License").
  6. * You may not use this file except in compliance with the License.
  7. *
  8. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  9. * or http://www.opensolaris.org/os/licensing.
  10. * See the License for the specific language governing permissions
  11. * and limitations under the License.
  12. *
  13. * When distributing Covered Code, include this CDDL HEADER in each
  14. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15. * If applicable, add the following below this CDDL HEADER, with the
  16. * fields enclosed by brackets "[]" replaced with your own identifying
  17. * information: Portions Copyright [yyyy] [name of copyright owner]
  18. *
  19. * CDDL HEADER END
  20. */
  21. /*
  22. * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
  23. * Use is subject to license terms.
  24. */
  25. /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  26. /* All Rights Reserved */
  27. /*
  28. * Portions of this source code were derived from Berkeley 4.3 BSD
  29. * under license from the Regents of the University of California.
  30. */
  31. #pragma ident "%Z%%M% %I% %E% SMI"
  32. /*
  33. * key_call.c, Interface to keyserver
  34. * key_encryptsession(agent, deskey, cr)-encrypt a session key to talk to agent
  35. * key_decryptsession(agent, deskey) - decrypt ditto
  36. * key_gendes(deskey) - generate a secure des key
  37. * key_getnetname(netname, cr) - get the netname from the keyserv
  38. * netname2user(...) - get unix credential for given name (kernel only)
  39. */
  40. #include <sys/param.h>
  41. #include <sys/types.h>
  42. #include <sys/time.h>
  43. #include <sys/systm.h>
  44. #include <sys/user.h>
  45. #include <sys/proc.h>
  46. #include <sys/pathname.h>
  47. #include <sys/sysmacros.h>
  48. #include <sys/vnode.h>
  49. #include <sys/uio.h>
  50. #include <sys/debug.h>
  51. #include <sys/utsname.h>
  52. #include <sys/cmn_err.h>
  53. #include <rpc/rpc.h>
  54. #include <rpc/key_prot.h>
  55. #define KEY_TIMEOUT 30 /* per-try timeout in seconds */
  56. #define KEY_NRETRY 6 /* number of retries */
  57. struct auth_globals {
  58. struct knetconfig auth_config;
  59. char auth_keyname[SYS_NMLN+16];
  60. };
  61. static struct timeval keytrytimeout = { KEY_TIMEOUT, 0 };
  62. static enum clnt_stat key_call(rpcproc_t, xdrproc_t, char *, xdrproc_t, char *,
  63. cred_t *);
  64. /* ARGSUSED */
  65. void *
  66. auth_zone_init(zoneid_t zoneid)
  67. {
  68. struct auth_globals *authg;
  69. authg = kmem_zalloc(sizeof (*authg), KM_SLEEP);
  70. return (authg);
  71. }
  72. /* ARGSUSED */
  73. void
  74. auth_zone_fini(zoneid_t zoneid, void *data)
  75. {
  76. struct auth_globals *authg = data;
  77. kmem_free(authg, sizeof (*authg));
  78. }
  79. enum clnt_stat
  80. key_encryptsession(char *remotename, des_block *deskey, cred_t *cr)
  81. {
  82. cryptkeyarg arg;
  83. cryptkeyres res;
  84. enum clnt_stat stat;
  85. RPCLOG(8, "key_encryptsession(%s, ", remotename);
  86. RPCLOG(8, "%x", *(uint32_t *)deskey);
  87. RPCLOG(8, "%x)\n", *(((uint32_t *)(deskey))+1));
  88. arg.remotename = remotename;
  89. arg.deskey = *deskey;
  90. if ((stat = key_call(KEY_ENCRYPT, xdr_cryptkeyarg, (char *)&arg,
  91. xdr_cryptkeyres, (char *)&res, cr)) != RPC_SUCCESS) {
  92. RPCLOG(1, "key_encryptsession(%d, ", (int)crgetuid(cr));
  93. RPCLOG(1, "%s): ", remotename);
  94. RPCLOG(1, "rpc status %d ", stat);
  95. RPCLOG(1, "(%s)\n", clnt_sperrno(stat));
  96. return (stat);
  97. }
  98. if (res.status != KEY_SUCCESS) {
  99. RPCLOG(1, "key_encryptsession(%d, ", (int)crgetuid(cr));
  100. RPCLOG(1, "%s): ", remotename);
  101. RPCLOG(1, "key status %d\n", res.status);
  102. return (RPC_FAILED); /* XXX */
  103. }
  104. *deskey = res.cryptkeyres_u.deskey;
  105. return (RPC_SUCCESS);
  106. }
  107. enum clnt_stat
  108. key_decryptsession(char *remotename, des_block *deskey)
  109. {
  110. cryptkeyarg arg;
  111. cryptkeyres res;
  112. enum clnt_stat stat;
  113. RPCLOG(8, "key_decryptsession(%s, ", remotename);
  114. RPCLOG(2, "%x", *(uint32_t *)deskey);
  115. RPCLOG(2, "%x)\n", *(((uint32_t *)(deskey))+1));
  116. arg.remotename = remotename;
  117. arg.deskey = *deskey;
  118. if ((stat = key_call(KEY_DECRYPT, xdr_cryptkeyarg, (char *)&arg,
  119. xdr_cryptkeyres, (char *)&res, kcred)) != RPC_SUCCESS) {
  120. RPCLOG(1, "key_decryptsession(%s): ", remotename);
  121. RPCLOG(1, "rpc status %d ", stat);
  122. RPCLOG(1, "(%s)\n", clnt_sperrno(stat));
  123. return (stat);
  124. }
  125. if (res.status != KEY_SUCCESS) {
  126. RPCLOG(1, "key_decryptsession(%s): ", remotename);
  127. RPCLOG(1, "key status %d\n", res.status);
  128. return (RPC_FAILED); /* XXX */
  129. }
  130. *deskey = res.cryptkeyres_u.deskey;
  131. return (RPC_SUCCESS);
  132. }
  133. enum clnt_stat
  134. key_gendes(des_block *key)
  135. {
  136. return (key_call(KEY_GEN, xdr_void, NULL, xdr_des_block, (char *)key,
  137. CRED()));
  138. }
  139. /*
  140. * Call up to keyserv to get the netname of the client based
  141. * on its uid. The netname is written into the string that "netname"
  142. * points to; the caller is responsible for ensuring that sufficient space
  143. * is available.
  144. */
  145. enum clnt_stat
  146. key_getnetname(netname, cr)
  147. char *netname;
  148. cred_t *cr;
  149. {
  150. key_netstres kres;
  151. enum clnt_stat stat;
  152. /*
  153. * Look up the keyserv interface routines to see if
  154. * netname is stored there.
  155. */
  156. kres.key_netstres_u.knet.st_netname = netname;
  157. if ((stat = key_call((rpcproc_t)KEY_NET_GET, xdr_void, NULL,
  158. xdr_key_netstres, (char *)&kres, cr)) != RPC_SUCCESS) {
  159. RPCLOG(1, "key_getnetname(%d): ", (int)crgetuid(cr));
  160. RPCLOG(1, "rpc status %d ", stat);
  161. RPCLOG(1, "(%s)\n", clnt_sperrno(stat));
  162. return (stat);
  163. }
  164. if (kres.status != KEY_SUCCESS) {
  165. RPCLOG(1, "key_getnetname(%d): ", (int)crgetuid(cr));
  166. RPCLOG(1, "key status %d\n", kres.status);
  167. return (RPC_FAILED);
  168. }
  169. return (RPC_SUCCESS);
  170. }
  171. enum clnt_stat
  172. netname2user(char *name, uid_t *uid, gid_t *gid, int *len, gid_t *groups)
  173. {
  174. struct getcredres res;
  175. enum clnt_stat stat;
  176. res.getcredres_u.cred.gids.gids_val = (uint_t *)groups;
  177. if ((stat = key_call(KEY_GETCRED, xdr_netnamestr, (char *)&name,
  178. xdr_getcredres, (char *)&res, CRED())) != RPC_SUCCESS) {
  179. RPCLOG(1, "netname2user(%s): ", name);
  180. RPCLOG(1, "rpc status %d ", stat);
  181. RPCLOG(1, "(%s)\n", clnt_sperrno(stat));
  182. return (stat);
  183. }
  184. if (res.status != KEY_SUCCESS) {
  185. RPCLOG(1, "netname2user(%s): ", name);
  186. RPCLOG(1, "key status %d\n", res.status);
  187. return (RPC_FAILED); /* XXX */
  188. }
  189. *uid = res.getcredres_u.cred.uid;
  190. *gid = res.getcredres_u.cred.gid;
  191. *len = res.getcredres_u.cred.gids.gids_len;
  192. return (RPC_SUCCESS);
  193. }
  194. #define NC_LOOPBACK "loopback" /* XXX */
  195. char loopback_name[] = NC_LOOPBACK;
  196. static enum clnt_stat
  197. key_call(rpcproc_t procn, xdrproc_t xdr_args, caddr_t args,
  198. xdrproc_t xdr_rslt, caddr_t rslt, cred_t *cr)
  199. {
  200. struct netbuf netaddr;
  201. CLIENT *client;
  202. enum clnt_stat stat;
  203. vnode_t *vp;
  204. int error;
  205. struct auth_globals *authg;
  206. char *keyname;
  207. struct knetconfig *configp;
  208. k_sigset_t smask;
  209. authg = zone_getspecific(auth_zone_key, curproc->p_zone);
  210. keyname = authg->auth_keyname;
  211. configp = &authg->auth_config;
  212. /*
  213. * Using a global here is obviously busted and fraught with danger.
  214. */
  215. (void) strcpy(keyname, uts_nodename());
  216. netaddr.len = strlen(keyname);
  217. (void) strcpy(&keyname[netaddr.len], ".keyserv");
  218. netaddr.buf = keyname;
  219. /*
  220. * 8 = strlen(".keyserv");
  221. */
  222. netaddr.len = netaddr.maxlen = netaddr.len + 8;
  223. /*
  224. * filch a knetconfig structure.
  225. */
  226. if (configp->knc_rdev == 0) {
  227. if ((error = lookupname("/dev/ticlts", UIO_SYSSPACE,
  228. FOLLOW, NULLVPP, &vp)) != 0) {
  229. RPCLOG(1, "key_call: lookupname: %d\n", error);
  230. return (RPC_UNKNOWNPROTO);
  231. }
  232. configp->knc_rdev = vp->v_rdev;
  233. configp->knc_protofmly = loopback_name;
  234. VN_RELE(vp);
  235. }
  236. configp->knc_semantics = NC_TPI_CLTS;
  237. RPCLOG(8, "key_call: procn %d, ", procn);
  238. RPCLOG(8, "rdev %lx, ", configp->knc_rdev);
  239. RPCLOG(8, "len %d, ", netaddr.len);
  240. RPCLOG(8, "maxlen %d, ", netaddr.maxlen);
  241. RPCLOG(8, "name %p\n", (void *)netaddr.buf);
  242. /*
  243. * now call the proper stuff.
  244. */
  245. error = clnt_tli_kcreate(configp, &netaddr, KEY_PROG, KEY_VERS,
  246. 0, KEY_NRETRY, cr, &client);
  247. if (error != 0) {
  248. RPCLOG(1, "key_call: clnt_tli_kcreate: error %d\n", error);
  249. switch (error) {
  250. case EINTR:
  251. return (RPC_INTR);
  252. case ETIMEDOUT:
  253. return (RPC_TIMEDOUT);
  254. default:
  255. return (RPC_FAILED); /* XXX */
  256. }
  257. }
  258. auth_destroy(client->cl_auth);
  259. client->cl_auth = authloopback_create();
  260. if (client->cl_auth == NULL) {
  261. clnt_destroy(client);
  262. RPCLOG(1, "key_call: authloopback_create: error %d\n", EINTR);
  263. return (RPC_INTR);
  264. }
  265. /* Mask out all signals except SIGHUP, SIGQUIT, and SIGTERM. */
  266. sigintr(&smask, 0);
  267. stat = clnt_call(client, procn, xdr_args, args, xdr_rslt, rslt,
  268. keytrytimeout);
  269. sigunintr(&smask);
  270. auth_destroy(client->cl_auth);
  271. clnt_destroy(client);
  272. if (stat != RPC_SUCCESS) {
  273. RPCLOG(1, "key_call: keyserver clnt_call failed: stat %d ",
  274. stat);
  275. RPCLOG(1, "(%s)\n", clnt_sperrno(stat));
  276. RPCLOG0(1, "\n");
  277. return (stat);
  278. }
  279. RPCLOG(8, "key call: (%d) ok\n", procn);
  280. return (RPC_SUCCESS);
  281. }