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, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include <rpc/rpc.h>
30 #include <rpc/key_prot.h>
31 #include <rpcsvc/nis_dhext.h>
32 #include <syslog.h>
33 #include <note.h>
34
35 /* defined in usr/src/libnsl/rpc/key_call.c */
36 extern bool_t (*__key_encryptsession_pk_LOCAL)();
37 extern bool_t (*__key_decryptsession_pk_LOCAL)();
38 extern bool_t (*__key_gendes_LOCAL)();
39
40 #define CLASSIC_PK_DH(k, a) (((k) == 192) && ((a) == 0))
41
42 /*
43 * authsys_create_uid(uid_t uid)
44 *
45 * Create SYS (UNIX) style authenticator for the given uid/gid
46 * We don't include suplementary groups, since these are of no
47 * interest for the keyserv operations that we do.
48 */
49 AUTH *
authsys_create_uid(uid_t uid,gid_t gid)50 authsys_create_uid(uid_t uid, gid_t gid)
51 {
52 char host[MAX_MACHINE_NAME + 1];
53 AUTH *res;
54
55 if (gethostname(host, sizeof (host) - 1) == -1) {
56 syslog(LOG_ERR,
57 "pam_dhkeys: Can't determine hostname: %m");
58 return (NULL);
59 }
60 host[MAX_MACHINE_NAME] = '\0';
61
62 res = authsys_create(host, uid, gid, 0, (gid_t *)NULL);
63
64 return (res);
65 }
66
67 /*
68 * my_key_call(proc, xdr_arg, arg, xdr_rslt, rslt, uit, gid)
69 *
70 * my_key_call is a copy of key_call() from libnsl with the
71 * added AUTHSYS rpc credential to make the keyserver use our
72 * REAL UID instead of our EFFECTIVE UID when handling our keys.
73 */
74 int
my_key_call(rpcproc_t proc,xdrproc_t xdr_arg,char * arg,xdrproc_t xdr_rslt,char * rslt,uid_t uid,gid_t gid)75 my_key_call(rpcproc_t proc, xdrproc_t xdr_arg, char *arg,
76 xdrproc_t xdr_rslt, char *rslt, uid_t uid, gid_t gid)
77 {
78 CLIENT *clnt;
79 struct timeval wait_time = {0, 0};
80 enum clnt_stat status;
81 int vers;
82
83 if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) {
84 cryptkeyres res;
85 bool_t r;
86 r = (*__key_encryptsession_pk_LOCAL)(uid, arg, &res);
87 if (r == TRUE) {
88 /* LINTED pointer alignment */
89 *(cryptkeyres*)rslt = res;
90 return (1);
91 }
92 return (0);
93 }
94 if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) {
95 cryptkeyres res;
96 bool_t r;
97 r = (*__key_decryptsession_pk_LOCAL)(uid, arg, &res);
98 if (r == TRUE) {
99 /* LINTED pointer alignment */
100 *(cryptkeyres*)rslt = res;
101 return (1);
102 }
103 return (0);
104 }
105 if (proc == KEY_GEN && __key_gendes_LOCAL) {
106 des_block res;
107 bool_t r;
108 r = (*__key_gendes_LOCAL)(uid, 0, &res);
109 if (r == TRUE) {
110 /* LINTED pointer alignment */
111 *(des_block*)rslt = res;
112 return (1);
113 }
114 return (0);
115 }
116
117 if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) ||
118 (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) ||
119 (proc == KEY_GET_CONV))
120 vers = 2; /* talk to version 2 */
121 else
122 vers = 1; /* talk to version 1 */
123
124 clnt = clnt_door_create(KEY_PROG, vers, 0);
125
126 if (clnt == NULL)
127 return (0);
128
129 clnt->cl_auth = authsys_create_uid(uid, gid);
130
131 status = CLNT_CALL(clnt, proc, xdr_arg, arg, xdr_rslt,
132 rslt, wait_time);
133
134 auth_destroy(clnt->cl_auth);
135 clnt_destroy(clnt);
136
137 return (status == RPC_SUCCESS ? 1 : 0);
138 }
139
140 int
key_setnet_uid(struct key_netstarg * arg,uid_t uid,gid_t gid)141 key_setnet_uid(struct key_netstarg *arg, uid_t uid, gid_t gid)
142 {
143 keystatus status;
144
145 if (!my_key_call((rpcproc_t)KEY_NET_PUT, xdr_key_netstarg,
146 (char *)arg, xdr_keystatus, (char *)&status, uid, gid)) {
147 return (-1);
148 }
149 if (status != KEY_SUCCESS) {
150 return (-1);
151 }
152
153 return (1);
154 }
155
156 int
key_setnet_g_uid(const char * netname,const char * skey,keylen_t skeylen,const char * pkey,keylen_t pkeylen,algtype_t algtype,uid_t uid,gid_t gid)157 key_setnet_g_uid(const char *netname, const char *skey, keylen_t skeylen,
158 const char *pkey, keylen_t pkeylen, algtype_t algtype,
159 uid_t uid, gid_t gid)
160 {
161 key_netstarg3 arg;
162 keystatus status;
163
164 arg.st_netname = (char *)netname;
165 arg.algtype = algtype;
166
167 if (skeylen == 0)
168 arg.st_priv_key.keybuf3_len = 0;
169 else
170 arg.st_priv_key.keybuf3_len = skeylen/4 + 1;
171
172 arg.st_priv_key.keybuf3_val = (char *)skey;
173
174 if (pkeylen == 0)
175 arg.st_pub_key.keybuf3_len = 0;
176 else
177 arg.st_pub_key.keybuf3_len = pkeylen/4 + 1;
178
179 arg.st_pub_key.keybuf3_val = (char *)pkey;
180
181 if (skeylen == 0) {
182 if (pkeylen == 0) {
183 /* debug("keylens are both 0"); */
184 return (-1);
185 }
186 arg.keylen = pkeylen;
187 } else {
188 if ((pkeylen != 0) && (skeylen != pkeylen)) {
189 /* debug("keylens don't match"); */
190 return (-1);
191 }
192 arg.keylen = skeylen;
193 }
194
195 if (CLASSIC_PK_DH(arg.keylen, arg.algtype)) {
196 key_netstarg tmp;
197
198 if (skeylen != 0) {
199 (void) memcpy(&tmp.st_priv_key, skey,
200 sizeof (tmp.st_priv_key));
201 } else {
202 (void) memset(&tmp.st_priv_key, 0,
203 sizeof (tmp.st_priv_key));
204 }
205 if (pkeylen != 0) {
206 (void) memcpy(&tmp.st_pub_key, skey,
207 sizeof (tmp.st_pub_key));
208 } else {
209 (void) memset(&tmp.st_pub_key, 0,
210 sizeof (tmp.st_pub_key));
211 }
212 tmp.st_netname = (char *)netname;
213 return (key_setnet_uid(&tmp, uid, gid));
214 }
215
216 if (!my_key_call((rpcproc_t)KEY_NET_PUT_3, xdr_key_netstarg3,
217 (char *)&arg, xdr_keystatus, (char *)&status, uid, gid)) {
218 return (-1);
219 }
220
221 if (status != KEY_SUCCESS) {
222 /* debug("key_setnet3 status is nonzero"); */
223 return (-1);
224 }
225 return (0);
226 }
227
228
229 /*
230 * key_secretkey_is_set_uid() returns 1 if the keyserver has a secret key
231 * stored for the caller's REAL uid; it returns 0 otherwise
232 */
233 int
key_secretkey_is_set_uid(uid_t uid,gid_t gid)234 key_secretkey_is_set_uid(uid_t uid, gid_t gid)
235 {
236 struct key_netstres kres;
237
238 (void) memset((void*)&kres, 0, sizeof (kres));
239
240 if (my_key_call((rpcproc_t)KEY_NET_GET, xdr_void, (char *)NULL,
241 xdr_key_netstres, (char *)&kres, uid, gid) &&
242 (kres.status == KEY_SUCCESS) &&
243 (kres.key_netstres_u.knet.st_priv_key[0] != 0)) {
244 /* avoid leaving secret key in memory */
245 (void) memset(kres.key_netstres_u.knet.st_priv_key, 0,
246 HEXKEYBYTES);
247 xdr_free(xdr_key_netstres, (char *)&kres);
248 return (1);
249 }
250 return (0);
251 }
252
253 int
key_removesecret_g_uid(uid_t uid,gid_t gid)254 key_removesecret_g_uid(uid_t uid, gid_t gid)
255 {
256 keystatus status;
257
258 if (my_key_call((rpcproc_t)KEY_CLEAR_3, xdr_void, (char *)NULL,
259 xdr_keystatus, (char *)&status, uid, gid))
260 return (-1);
261
262 if (status != KEY_SUCCESS)
263 return (-1);
264
265 return (0);
266 }
267