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