]>
Commit | Line | Data |
---|---|---|
800d775e UD |
1 | /* |
2 | * Sun RPC is a product of Sun Microsystems, Inc. and is provided for | |
3 | * unrestricted use provided that this legend is included on all tape | |
4 | * media and as a part of the software program in whole or part. Users | |
5 | * may copy or modify Sun RPC without charge, but are not authorized | |
6 | * to license or distribute it to anyone else except as part of a product or | |
7 | * program developed by the user. | |
8 | * | |
9 | * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE | |
10 | * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR | |
11 | * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. | |
12 | * | |
13 | * Sun RPC is provided with no support and without any obligation on the | |
14 | * part of Sun Microsystems, Inc. to assist in its use, correction, | |
15 | * modification or enhancement. | |
16 | * | |
17 | * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE | |
18 | * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC | |
19 | * OR ANY PART THEREOF. | |
20 | * | |
21 | * In no event will Sun Microsystems, Inc. be liable for any lost revenue | |
22 | * or profits or other special, indirect and consequential damages, even if | |
23 | * Sun has been advised of the possibility of such damages. | |
24 | * | |
25 | * Sun Microsystems, Inc. | |
26 | * 2550 Garcia Avenue | |
27 | * Mountain View, California 94043 | |
28 | */ | |
54f4f73e UD |
29 | /* |
30 | * Copyright (c) 1988 by Sun Microsystems, Inc. | |
31 | */ | |
800d775e UD |
32 | /* |
33 | * The original source is from the RPCSRC 4.0 package from Sun Microsystems. | |
54f4f73e UD |
34 | * The Interface to keyserver protocoll 2, RPC over AF_UNIX and Linux/doors |
35 | * was added by Thorsten Kukuk <kukuk@suse.de> | |
36 | * Since the Linux/doors project was stopped, I doubt that this code will | |
37 | * ever be useful <kukuk@suse.de>. | |
800d775e UD |
38 | */ |
39 | ||
40 | #include <stdio.h> | |
9a0a462c | 41 | #include <errno.h> |
e852e889 | 42 | #include <fcntl.h> |
800d775e UD |
43 | #include <signal.h> |
44 | #include <unistd.h> | |
45 | #include <string.h> | |
46 | #include <rpc/rpc.h> | |
47 | #include <rpc/auth.h> | |
48 | #include <sys/wait.h> | |
49 | #include <sys/param.h> | |
50 | #include <sys/socket.h> | |
51 | #include <rpc/key_prot.h> | |
e852e889 | 52 | #include <bits/libc-lock.h> |
800d775e | 53 | |
7cabd57c UD |
54 | #ifdef HAVE_DOORS |
55 | # include "door/door.h" | |
56 | #endif | |
57 | ||
800d775e UD |
58 | #define KEY_TIMEOUT 5 /* per-try timeout in seconds */ |
59 | #define KEY_NRETRY 12 /* number of retries */ | |
60 | ||
61 | #define debug(msg) /* turn off debugging */ | |
62 | ||
54f4f73e | 63 | #ifndef SO_PASSCRED |
c4563d2d | 64 | extern int _openchild (const char *command, FILE **fto, FILE **ffrom); |
54f4f73e | 65 | #endif |
800d775e UD |
66 | |
67 | static int key_call (u_long, xdrproc_t xdr_arg, char *, | |
dfd2257a | 68 | xdrproc_t xdr_rslt, char *) internal_function; |
800d775e | 69 | |
c4563d2d UD |
70 | static const struct timeval trytimeout = {KEY_TIMEOUT, 0}; |
71 | static const struct timeval tottimeout = {KEY_TIMEOUT *KEY_NRETRY, 0}; | |
800d775e UD |
72 | |
73 | int | |
74 | key_setsecret (char *secretkey) | |
75 | { | |
76 | keystatus status; | |
77 | ||
77fe0b9c UD |
78 | if (!key_call ((u_long) KEY_SET, (xdrproc_t) INTUSE(xdr_keybuf), secretkey, |
79 | (xdrproc_t) INTUSE(xdr_keystatus), (char *) &status)) | |
800d775e UD |
80 | return -1; |
81 | if (status != KEY_SUCCESS) | |
82 | { | |
83 | debug ("set status is nonzero"); | |
84 | return -1; | |
85 | } | |
86 | return 0; | |
87 | } | |
88 | ||
89 | /* key_secretkey_is_set() returns 1 if the keyserver has a secret key | |
90 | * stored for the caller's effective uid; it returns 0 otherwise | |
91 | * | |
92 | * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't | |
93 | * be using it, because it allows them to get the user's secret key. | |
94 | */ | |
95 | int | |
96 | key_secretkey_is_set (void) | |
97 | { | |
98 | struct key_netstres kres; | |
99 | ||
100 | memset (&kres, 0, sizeof (kres)); | |
77fe0b9c UD |
101 | if (key_call ((u_long) KEY_NET_GET, (xdrproc_t) INTUSE(xdr_void), |
102 | (char *) NULL, (xdrproc_t) INTUSE(xdr_key_netstres), | |
103 | (char *) &kres) && | |
800d775e UD |
104 | (kres.status == KEY_SUCCESS) && |
105 | (kres.key_netstres_u.knet.st_priv_key[0] != 0)) | |
106 | { | |
107 | /* avoid leaving secret key in memory */ | |
108 | memset (kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES); | |
109 | return 1; | |
110 | } | |
111 | return 0; | |
112 | } | |
113 | ||
114 | int | |
9a0a462c | 115 | key_encryptsession (char *remotename, des_block *deskey) |
800d775e UD |
116 | { |
117 | cryptkeyarg arg; | |
118 | cryptkeyres res; | |
119 | ||
120 | arg.remotename = remotename; | |
121 | arg.deskey = *deskey; | |
77fe0b9c UD |
122 | if (!key_call ((u_long) KEY_ENCRYPT, (xdrproc_t) INTUSE(xdr_cryptkeyarg), |
123 | (char *) &arg, (xdrproc_t) INTUSE(xdr_cryptkeyres), | |
124 | (char *) &res)) | |
800d775e UD |
125 | return -1; |
126 | ||
127 | if (res.status != KEY_SUCCESS) | |
128 | { | |
129 | debug ("encrypt status is nonzero"); | |
130 | return -1; | |
131 | } | |
132 | *deskey = res.cryptkeyres_u.deskey; | |
133 | return 0; | |
134 | } | |
135 | ||
136 | int | |
9a0a462c | 137 | key_decryptsession (char *remotename, des_block *deskey) |
800d775e UD |
138 | { |
139 | cryptkeyarg arg; | |
140 | cryptkeyres res; | |
141 | ||
142 | arg.remotename = remotename; | |
143 | arg.deskey = *deskey; | |
77fe0b9c UD |
144 | if (!key_call ((u_long) KEY_DECRYPT, (xdrproc_t) INTUSE(xdr_cryptkeyarg), |
145 | (char *) &arg, (xdrproc_t) INTUSE(xdr_cryptkeyres), | |
146 | (char *) &res)) | |
800d775e UD |
147 | return -1; |
148 | if (res.status != KEY_SUCCESS) | |
149 | { | |
150 | debug ("decrypt status is nonzero"); | |
151 | return -1; | |
152 | } | |
153 | *deskey = res.cryptkeyres_u.deskey; | |
154 | return 0; | |
155 | } | |
156 | ||
157 | int | |
9a0a462c UD |
158 | key_encryptsession_pk (char *remotename, netobj *remotekey, |
159 | des_block *deskey) | |
800d775e UD |
160 | { |
161 | cryptkeyarg2 arg; | |
162 | cryptkeyres res; | |
163 | ||
164 | arg.remotename = remotename; | |
165 | arg.remotekey = *remotekey; | |
166 | arg.deskey = *deskey; | |
77fe0b9c UD |
167 | if (!key_call ((u_long) KEY_ENCRYPT_PK, (xdrproc_t) INTUSE(xdr_cryptkeyarg2), |
168 | (char *) &arg, (xdrproc_t) INTUSE(xdr_cryptkeyres), | |
169 | (char *) &res)) | |
800d775e UD |
170 | return -1; |
171 | ||
172 | if (res.status != KEY_SUCCESS) | |
173 | { | |
174 | debug ("encrypt status is nonzero"); | |
175 | return -1; | |
176 | } | |
177 | *deskey = res.cryptkeyres_u.deskey; | |
178 | return 0; | |
179 | } | |
180 | ||
181 | int | |
9a0a462c UD |
182 | key_decryptsession_pk (char *remotename, netobj *remotekey, |
183 | des_block *deskey) | |
800d775e UD |
184 | { |
185 | cryptkeyarg2 arg; | |
186 | cryptkeyres res; | |
187 | ||
188 | arg.remotename = remotename; | |
189 | arg.remotekey = *remotekey; | |
190 | arg.deskey = *deskey; | |
77fe0b9c UD |
191 | if (!key_call ((u_long) KEY_DECRYPT_PK, (xdrproc_t) INTUSE(xdr_cryptkeyarg2), |
192 | (char *) &arg, (xdrproc_t) INTUSE(xdr_cryptkeyres), | |
193 | (char *) &res)) | |
800d775e UD |
194 | return -1; |
195 | ||
196 | if (res.status != KEY_SUCCESS) | |
197 | { | |
198 | debug ("decrypt status is nonzero"); | |
199 | return -1; | |
200 | } | |
201 | *deskey = res.cryptkeyres_u.deskey; | |
202 | return 0; | |
203 | } | |
204 | ||
205 | int | |
9a0a462c | 206 | key_gendes (des_block *key) |
800d775e UD |
207 | { |
208 | struct sockaddr_in sin; | |
209 | CLIENT *client; | |
210 | int socket; | |
211 | enum clnt_stat stat; | |
212 | ||
213 | sin.sin_family = AF_INET; | |
214 | sin.sin_port = 0; | |
215 | sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); | |
50304ef0 | 216 | __bzero (sin.sin_zero, sizeof (sin.sin_zero)); |
800d775e UD |
217 | socket = RPC_ANYSOCK; |
218 | client = clntudp_bufcreate (&sin, (u_long) KEY_PROG, (u_long) KEY_VERS, | |
219 | trytimeout, &socket, RPCSMALLMSGSIZE, | |
220 | RPCSMALLMSGSIZE); | |
221 | if (client == NULL) | |
222 | return -1; | |
223 | ||
77fe0b9c UD |
224 | stat = clnt_call (client, KEY_GEN, (xdrproc_t) INTUSE(xdr_void), NULL, |
225 | (xdrproc_t) INTUSE(xdr_des_block), (caddr_t) key, | |
226 | tottimeout); | |
800d775e | 227 | clnt_destroy (client); |
50304ef0 | 228 | __close (socket); |
800d775e UD |
229 | if (stat != RPC_SUCCESS) |
230 | return -1; | |
231 | ||
232 | return 0; | |
233 | } | |
234 | ||
235 | int | |
236 | key_setnet (struct key_netstarg *arg) | |
237 | { | |
238 | keystatus status; | |
239 | ||
77fe0b9c UD |
240 | if (!key_call ((u_long) KEY_NET_PUT, (xdrproc_t) INTUSE(xdr_key_netstarg), |
241 | (char *) arg,(xdrproc_t) INTUSE(xdr_keystatus), | |
242 | (char *) &status)) | |
800d775e UD |
243 | return -1; |
244 | ||
245 | if (status != KEY_SUCCESS) | |
246 | { | |
247 | debug ("key_setnet status is nonzero"); | |
248 | return -1; | |
249 | } | |
250 | return 1; | |
251 | } | |
252 | ||
253 | int | |
9a0a462c | 254 | key_get_conv (char *pkey, des_block *deskey) |
800d775e UD |
255 | { |
256 | cryptkeyres res; | |
257 | ||
77fe0b9c UD |
258 | if (!key_call ((u_long) KEY_GET_CONV, (xdrproc_t) INTUSE(xdr_keybuf), pkey, |
259 | (xdrproc_t) INTUSE(xdr_cryptkeyres), (char *) &res)) | |
800d775e UD |
260 | return -1; |
261 | ||
262 | if (res.status != KEY_SUCCESS) | |
263 | { | |
264 | debug ("get_conv status is nonzero"); | |
265 | return -1; | |
266 | } | |
267 | *deskey = res.cryptkeyres_u.deskey; | |
268 | return 0; | |
269 | } | |
270 | ||
271 | /* | |
272 | * Hack to allow the keyserver to use AUTH_DES (for authenticated | |
273 | * NIS+ calls, for example). The only functions that get called | |
274 | * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes. | |
275 | * | |
276 | * The approach is to have the keyserver fill in pointers to local | |
277 | * implementations of these functions, and to call those in key_call(). | |
278 | */ | |
279 | ||
c4563d2d UD |
280 | cryptkeyres *(*__key_encryptsession_pk_LOCAL) (uid_t, char *); |
281 | cryptkeyres *(*__key_decryptsession_pk_LOCAL) (uid_t, char *); | |
282 | des_block *(*__key_gendes_LOCAL) (uid_t, char *); | |
800d775e | 283 | |
54f4f73e | 284 | #ifndef SO_PASSCRED |
800d775e | 285 | static int |
dfd2257a | 286 | internal_function |
e852e889 UD |
287 | key_call_keyenvoy (u_long proc, xdrproc_t xdr_arg, char *arg, |
288 | xdrproc_t xdr_rslt, char *rslt) | |
800d775e UD |
289 | { |
290 | XDR xdrargs; | |
291 | XDR xdrrslt; | |
292 | FILE *fargs; | |
293 | FILE *frslt; | |
9a0a462c | 294 | sigset_t oldmask, mask; |
800d775e UD |
295 | union wait status; |
296 | int pid; | |
297 | int success; | |
298 | uid_t ruid; | |
299 | uid_t euid; | |
c4563d2d | 300 | static const char MESSENGER[] = "/usr/etc/keyenvoy"; |
800d775e | 301 | |
9a0a462c UD |
302 | success = 1; |
303 | sigemptyset (&mask); | |
304 | sigaddset (&mask, SIGCHLD); | |
50304ef0 | 305 | __sigprocmask (SIG_BLOCK, &mask, &oldmask); |
9a0a462c | 306 | |
800d775e UD |
307 | /* |
308 | * We are going to exec a set-uid program which makes our effective uid | |
309 | * zero, and authenticates us with our real uid. We need to make the | |
310 | * effective uid be the real uid for the setuid program, and | |
311 | * the real uid be the effective uid so that we can change things back. | |
312 | */ | |
50304ef0 UD |
313 | euid = __geteuid (); |
314 | ruid = __getuid (); | |
315 | __setreuid (euid, ruid); | |
800d775e | 316 | pid = _openchild (MESSENGER, &fargs, &frslt); |
50304ef0 | 317 | __setreuid (ruid, euid); |
800d775e UD |
318 | if (pid < 0) |
319 | { | |
320 | debug ("open_streams"); | |
50304ef0 | 321 | __sigprocmask (SIG_SETMASK, &oldmask, NULL); |
800d775e UD |
322 | return (0); |
323 | } | |
324 | xdrstdio_create (&xdrargs, fargs, XDR_ENCODE); | |
325 | xdrstdio_create (&xdrrslt, frslt, XDR_DECODE); | |
326 | ||
77fe0b9c | 327 | if (!INTUSE(xdr_u_long) (&xdrargs, &proc) || !(*xdr_arg) (&xdrargs, arg)) |
800d775e UD |
328 | { |
329 | debug ("xdr args"); | |
330 | success = 0; | |
331 | } | |
332 | fclose (fargs); | |
333 | ||
334 | if (success && !(*xdr_rslt) (&xdrrslt, rslt)) | |
335 | { | |
336 | debug ("xdr rslt"); | |
337 | success = 0; | |
338 | } | |
9a0a462c | 339 | fclose(frslt); |
800d775e | 340 | |
9a0a462c | 341 | wait_again: |
50304ef0 | 342 | if (__wait4 (pid, &status, 0, NULL) < 0) |
800d775e | 343 | { |
9a0a462c UD |
344 | if (errno == EINTR) |
345 | goto wait_again; | |
50304ef0 | 346 | debug ("wait4"); |
9a0a462c | 347 | if (errno == ECHILD || errno == ESRCH) |
50304ef0 | 348 | perror ("wait"); |
9a0a462c UD |
349 | else |
350 | success = 0; | |
800d775e | 351 | } |
9a0a462c UD |
352 | else |
353 | if (status.w_retcode) | |
354 | { | |
50304ef0 | 355 | debug ("wait4 1"); |
9a0a462c UD |
356 | success = 0; |
357 | } | |
50304ef0 | 358 | __sigprocmask (SIG_SETMASK, &oldmask, NULL); |
800d775e | 359 | |
50304ef0 | 360 | return success; |
800d775e | 361 | } |
54f4f73e | 362 | #endif |
e852e889 UD |
363 | |
364 | struct key_call_private { | |
365 | CLIENT *client; /* Client handle */ | |
366 | pid_t pid; /* process-id at moment of creation */ | |
367 | uid_t uid; /* user-id at last authorization */ | |
368 | }; | |
f1e4a4a4 UD |
369 | #ifdef _RPC_THREAD_SAFE_ |
370 | #define key_call_private_main ((struct key_call_private *)RPC_THREAD_VARIABLE(key_call_private_s)) | |
371 | #else | |
c4563d2d | 372 | static struct key_call_private *key_call_private_main; |
f1e4a4a4 | 373 | #endif |
e852e889 UD |
374 | __libc_lock_define_initialized (static, keycall_lock) |
375 | ||
376 | /* | |
377 | * Keep the handle cached. This call may be made quite often. | |
378 | */ | |
379 | static CLIENT * | |
380 | getkeyserv_handle (int vers) | |
381 | { | |
382 | struct key_call_private *kcp = key_call_private_main; | |
383 | struct timeval wait_time; | |
384 | int fd; | |
385 | struct sockaddr_un name; | |
386 | int namelen = sizeof(struct sockaddr_un); | |
387 | ||
388 | #define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */ | |
389 | #define TOTAL_TRIES 5 /* Number of tries */ | |
390 | ||
391 | if (kcp == (struct key_call_private *)NULL) | |
392 | { | |
393 | kcp = (struct key_call_private *)malloc (sizeof (*kcp)); | |
394 | if (kcp == (struct key_call_private *)NULL) | |
395 | return (CLIENT *) NULL; | |
396 | ||
397 | key_call_private_main = kcp; | |
398 | kcp->client = NULL; | |
399 | } | |
400 | ||
401 | /* if pid has changed, destroy client and rebuild */ | |
402 | if (kcp->client != NULL && kcp->pid != __getpid ()) | |
403 | { | |
404 | clnt_destroy (kcp->client); | |
405 | kcp->client = NULL; | |
406 | } | |
407 | ||
408 | if (kcp->client != NULL) | |
409 | { | |
410 | /* if other side closed socket, build handle again */ | |
411 | clnt_control (kcp->client, CLGET_FD, (char *)&fd); | |
4aebaa6b | 412 | if (__getpeername (fd,(struct sockaddr *)&name,&namelen) == -1) |
e852e889 UD |
413 | { |
414 | auth_destroy (kcp->client->cl_auth); | |
415 | clnt_destroy (kcp->client); | |
416 | kcp->client = NULL; | |
417 | } | |
418 | } | |
419 | ||
420 | if (kcp->client != NULL) | |
421 | { | |
422 | /* if uid has changed, build client handle again */ | |
423 | if (kcp->uid != __geteuid ()) | |
424 | { | |
425 | kcp->uid = __geteuid (); | |
426 | auth_destroy (kcp->client->cl_auth); | |
427 | kcp->client->cl_auth = | |
428 | authunix_create ((char *)"", kcp->uid, 0, 0, NULL); | |
429 | if (kcp->client->cl_auth == NULL) | |
430 | { | |
431 | clnt_destroy (kcp->client); | |
432 | kcp->client = NULL; | |
433 | return ((CLIENT *) NULL); | |
434 | } | |
435 | } | |
436 | /* Change the version number to the new one */ | |
437 | clnt_control (kcp->client, CLSET_VERS, (void *)&vers); | |
438 | return kcp->client; | |
439 | } | |
440 | ||
441 | if ((kcp->client == (CLIENT *) NULL)) | |
442 | /* Use the AF_UNIX transport */ | |
443 | kcp->client = clnt_create ("/var/run/keyservsock", KEY_PROG, vers, "unix"); | |
444 | ||
445 | if (kcp->client == (CLIENT *) NULL) | |
446 | return (CLIENT *) NULL; | |
447 | ||
448 | kcp->uid = __geteuid (); | |
449 | kcp->pid = __getpid (); | |
450 | kcp->client->cl_auth = authunix_create ((char *)"", kcp->uid, 0, 0, NULL); | |
451 | if (kcp->client->cl_auth == NULL) | |
452 | { | |
453 | clnt_destroy (kcp->client); | |
454 | kcp->client = NULL; | |
455 | return (CLIENT *) NULL; | |
456 | } | |
457 | ||
458 | wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES; | |
459 | wait_time.tv_usec = 0; | |
460 | clnt_control (kcp->client, CLSET_RETRY_TIMEOUT, | |
461 | (char *)&wait_time); | |
462 | if (clnt_control (kcp->client, CLGET_FD, (char *)&fd)) | |
d17a729b | 463 | __fcntl (fd, F_SETFD, 1); /* make it "close on exec" */ |
e852e889 UD |
464 | |
465 | return kcp->client; | |
466 | } | |
467 | ||
468 | /* returns 0 on failure, 1 on success */ | |
469 | static int | |
470 | internal_function | |
471 | key_call_socket (u_long proc, xdrproc_t xdr_arg, char *arg, | |
472 | xdrproc_t xdr_rslt, char *rslt) | |
473 | { | |
474 | CLIENT *clnt; | |
475 | struct timeval wait_time; | |
476 | int result = 0; | |
477 | ||
478 | __libc_lock_lock (keycall_lock); | |
479 | if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) || | |
480 | (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) || | |
481 | (proc == KEY_GET_CONV)) | |
482 | clnt = getkeyserv_handle(2); /* talk to version 2 */ | |
483 | else | |
484 | clnt = getkeyserv_handle(1); /* talk to version 1 */ | |
485 | ||
486 | if (clnt != NULL) | |
487 | { | |
488 | wait_time.tv_sec = TOTAL_TIMEOUT; | |
489 | wait_time.tv_usec = 0; | |
490 | ||
491 | if (clnt_call (clnt, proc, xdr_arg, arg, xdr_rslt, rslt, | |
492 | wait_time) == RPC_SUCCESS) | |
493 | result = 1; | |
494 | } | |
495 | ||
496 | __libc_lock_unlock (keycall_lock); | |
497 | ||
498 | return result; | |
499 | } | |
500 | ||
7cabd57c UD |
501 | #ifdef HAVE_DOORS |
502 | /* returns 0 on failure, 1 on success */ | |
503 | static int | |
504 | internal_function | |
505 | key_call_door (u_long proc, xdrproc_t xdr_arg, char *arg, | |
506 | xdrproc_t xdr_rslt, char *rslt) | |
507 | { | |
508 | XDR xdrs; | |
32abdb71 | 509 | int fd, ret; |
7cabd57c UD |
510 | door_arg_t args; |
511 | char *data_ptr; | |
512 | u_long data_len = 0; | |
513 | char res[255]; | |
514 | ||
515 | if ((fd = open("/var/run/keyservdoor", O_RDONLY)) < 0) | |
516 | return 0; | |
517 | res[0] = 0; | |
518 | ||
519 | data_len = xdr_sizeof (xdr_arg, arg); | |
520 | data_ptr = calloc (1, data_len + 2 * sizeof (u_long)); | |
521 | if (data_ptr == NULL) | |
522 | return 0; | |
523 | ||
77fe0b9c UD |
524 | INTUSE(xdrmem_create) (&xdrs, &data_ptr[2 * sizeof (u_long)], data_len, |
525 | XDR_ENCODE); | |
7cabd57c UD |
526 | if (!xdr_arg (&xdrs, arg)) |
527 | { | |
528 | xdr_destroy (&xdrs); | |
529 | free (data_ptr); | |
530 | return 0; | |
531 | } | |
532 | xdr_destroy (&xdrs); | |
533 | ||
534 | memcpy (data_ptr, &proc, sizeof (u_long)); | |
535 | memcpy (&data_ptr[sizeof (proc)], &data_len, sizeof (u_long)); | |
536 | ||
537 | args.data_ptr = data_ptr; | |
538 | args.data_size = data_len + 2 * sizeof (u_long); | |
539 | args.desc_ptr = NULL; | |
540 | args.desc_num = 0; | |
541 | args.rbuf = res; | |
542 | args.rsize = sizeof (res); | |
543 | ||
32abdb71 | 544 | ret = __door_call (fd, &args); |
7cabd57c UD |
545 | free (data_ptr); |
546 | close (fd); | |
547 | ||
32abdb71 UD |
548 | if (ret < 0) |
549 | return 0; | |
550 | ||
7cabd57c UD |
551 | memcpy (&data_len, args.data_ptr, sizeof (u_long)); |
552 | if (data_len != 0) | |
553 | return 0; | |
554 | ||
555 | memcpy (&data_len, &args.data_ptr[sizeof (u_long)], sizeof (u_long)); | |
77fe0b9c UD |
556 | INTUSE(xdrmem_create) (&xdrs, &args.data_ptr[2 * sizeof (u_long)], |
557 | data_len, XDR_DECODE); | |
7cabd57c UD |
558 | if (!xdr_rslt (&xdrs, rslt)) |
559 | { | |
560 | xdr_destroy (&xdrs); | |
561 | return 0; | |
562 | } | |
563 | xdr_destroy (&xdrs); | |
564 | ||
565 | return 1; | |
566 | } | |
567 | #endif | |
568 | ||
569 | /* returns 0 on failure, 1 on success */ | |
e852e889 UD |
570 | static int |
571 | internal_function | |
572 | key_call (u_long proc, xdrproc_t xdr_arg, char *arg, | |
573 | xdrproc_t xdr_rslt, char *rslt) | |
574 | { | |
54f4f73e | 575 | #ifndef SO_PASSCRED |
c4563d2d | 576 | static int use_keyenvoy; |
54f4f73e | 577 | #endif |
7cabd57c | 578 | #ifdef HAVE_DOORS |
c4563d2d | 579 | static int not_use_doors; |
7cabd57c | 580 | #endif |
e852e889 UD |
581 | |
582 | if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) | |
583 | { | |
584 | cryptkeyres *res; | |
585 | res = (*__key_encryptsession_pk_LOCAL) (__geteuid (), arg); | |
586 | *(cryptkeyres *) rslt = *res; | |
587 | return 1; | |
588 | } | |
589 | else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) | |
590 | { | |
591 | cryptkeyres *res; | |
592 | res = (*__key_decryptsession_pk_LOCAL) (__geteuid (), arg); | |
593 | *(cryptkeyres *) rslt = *res; | |
594 | return 1; | |
595 | } | |
596 | else if (proc == KEY_GEN && __key_gendes_LOCAL) | |
597 | { | |
598 | des_block *res; | |
599 | res = (*__key_gendes_LOCAL) (__geteuid (), 0); | |
600 | *(des_block *) rslt = *res; | |
601 | return 1; | |
602 | } | |
603 | ||
7cabd57c | 604 | #ifdef HAVE_DOORS |
c4563d2d | 605 | if (!not_use_doors) |
7cabd57c UD |
606 | { |
607 | if (key_call_door (proc, xdr_arg, arg, xdr_rslt, rslt)) | |
608 | return 1; | |
c4563d2d | 609 | not_use_doors = 1; |
7cabd57c UD |
610 | } |
611 | #endif | |
54f4f73e UD |
612 | |
613 | #ifdef SO_PASSCRED | |
614 | return key_call_socket (proc, xdr_arg, arg, xdr_rslt, rslt); | |
615 | #else | |
e852e889 UD |
616 | if (!use_keyenvoy) |
617 | { | |
618 | if (key_call_socket (proc, xdr_arg, arg, xdr_rslt, rslt)) | |
619 | return 1; | |
620 | use_keyenvoy = 1; | |
621 | } | |
622 | return key_call_keyenvoy (proc, xdr_arg, arg, xdr_rslt, rslt); | |
54f4f73e | 623 | #endif |
e852e889 | 624 | } |
f1e4a4a4 UD |
625 | |
626 | #ifdef _RPC_THREAD_SAFE_ | |
627 | void | |
628 | __rpc_thread_key_cleanup (void) | |
629 | { | |
630 | struct key_call_private *kcp = RPC_THREAD_VARIABLE(key_call_private_s); | |
631 | ||
632 | if (kcp) { | |
633 | if (kcp->client) | |
634 | clnt_destroy(kcp->client); | |
635 | free (kcp); | |
636 | } | |
637 | } | |
638 | #endif /* _RPC_THREAD_SAFE_ */ |