]>
Commit | Line | Data |
---|---|---|
800d775e | 1 | /* |
a7ab6ec8 | 2 | * Copyright (c) 2010, Oracle America, Inc. |
cb636bb2 | 3 | * |
a7ab6ec8 UD |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions are | |
6 | * met: | |
cb636bb2 | 7 | * |
a7ab6ec8 UD |
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. | |
800d775e | 17 | * |
a7ab6ec8 UD |
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. | |
54f4f73e | 30 | */ |
800d775e UD |
31 | /* |
32 | * The original source is from the RPCSRC 4.0 package from Sun Microsystems. | |
54f4f73e UD |
33 | * The Interface to keyserver protocoll 2, RPC over AF_UNIX and Linux/doors |
34 | * was added by Thorsten Kukuk <kukuk@suse.de> | |
35 | * Since the Linux/doors project was stopped, I doubt that this code will | |
36 | * ever be useful <kukuk@suse.de>. | |
800d775e UD |
37 | */ |
38 | ||
39 | #include <stdio.h> | |
9a0a462c | 40 | #include <errno.h> |
e852e889 | 41 | #include <fcntl.h> |
800d775e UD |
42 | #include <signal.h> |
43 | #include <unistd.h> | |
44 | #include <string.h> | |
45 | #include <rpc/rpc.h> | |
46 | #include <rpc/auth.h> | |
47 | #include <sys/wait.h> | |
48 | #include <sys/param.h> | |
49 | #include <sys/socket.h> | |
50 | #include <rpc/key_prot.h> | |
ec999b8e | 51 | #include <libc-lock.h> |
82f43dd2 | 52 | #include <shlib-compat.h> |
800d775e UD |
53 | |
54 | #define KEY_TIMEOUT 5 /* per-try timeout in seconds */ | |
55 | #define KEY_NRETRY 12 /* number of retries */ | |
56 | ||
57 | #define debug(msg) /* turn off debugging */ | |
58 | ||
54f4f73e | 59 | #ifndef SO_PASSCRED |
c4563d2d | 60 | extern int _openchild (const char *command, FILE **fto, FILE **ffrom); |
54f4f73e | 61 | #endif |
800d775e UD |
62 | |
63 | static int key_call (u_long, xdrproc_t xdr_arg, char *, | |
ca4ec803 | 64 | xdrproc_t xdr_rslt, char *); |
800d775e | 65 | |
c4563d2d UD |
66 | static const struct timeval trytimeout = {KEY_TIMEOUT, 0}; |
67 | static const struct timeval tottimeout = {KEY_TIMEOUT *KEY_NRETRY, 0}; | |
800d775e UD |
68 | |
69 | int | |
70 | key_setsecret (char *secretkey) | |
71 | { | |
72 | keystatus status; | |
73 | ||
7b57bfe5 UD |
74 | if (!key_call ((u_long) KEY_SET, (xdrproc_t) xdr_keybuf, secretkey, |
75 | (xdrproc_t) xdr_keystatus, (char *) &status)) | |
800d775e UD |
76 | return -1; |
77 | if (status != KEY_SUCCESS) | |
78 | { | |
79 | debug ("set status is nonzero"); | |
80 | return -1; | |
81 | } | |
82 | return 0; | |
83 | } | |
021db4be | 84 | libc_hidden_nolink_sunrpc (key_setsecret, GLIBC_2_1) |
800d775e UD |
85 | |
86 | /* key_secretkey_is_set() returns 1 if the keyserver has a secret key | |
87 | * stored for the caller's effective uid; it returns 0 otherwise | |
88 | * | |
89 | * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't | |
90 | * be using it, because it allows them to get the user's secret key. | |
91 | */ | |
92 | int | |
93 | key_secretkey_is_set (void) | |
94 | { | |
95 | struct key_netstres kres; | |
96 | ||
97 | memset (&kres, 0, sizeof (kres)); | |
7b57bfe5 UD |
98 | if (key_call ((u_long) KEY_NET_GET, (xdrproc_t) xdr_void, |
99 | (char *) NULL, (xdrproc_t) xdr_key_netstres, | |
77fe0b9c | 100 | (char *) &kres) && |
800d775e UD |
101 | (kres.status == KEY_SUCCESS) && |
102 | (kres.key_netstres_u.knet.st_priv_key[0] != 0)) | |
103 | { | |
104 | /* avoid leaving secret key in memory */ | |
105 | memset (kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES); | |
106 | return 1; | |
107 | } | |
108 | return 0; | |
109 | } | |
7b57bfe5 UD |
110 | #ifdef EXPORT_RPC_SYMBOLS |
111 | libc_hidden_def (key_secretkey_is_set) | |
112 | #else | |
021db4be | 113 | libc_hidden_nolink_sunrpc (key_secretkey_is_set, GLIBC_2_1) |
7b57bfe5 | 114 | #endif |
800d775e UD |
115 | |
116 | int | |
9a0a462c | 117 | key_encryptsession (char *remotename, des_block *deskey) |
800d775e UD |
118 | { |
119 | cryptkeyarg arg; | |
120 | cryptkeyres res; | |
121 | ||
122 | arg.remotename = remotename; | |
123 | arg.deskey = *deskey; | |
7b57bfe5 UD |
124 | if (!key_call ((u_long) KEY_ENCRYPT, (xdrproc_t) xdr_cryptkeyarg, |
125 | (char *) &arg, (xdrproc_t) xdr_cryptkeyres, | |
77fe0b9c | 126 | (char *) &res)) |
800d775e UD |
127 | return -1; |
128 | ||
129 | if (res.status != KEY_SUCCESS) | |
130 | { | |
131 | debug ("encrypt status is nonzero"); | |
132 | return -1; | |
133 | } | |
134 | *deskey = res.cryptkeyres_u.deskey; | |
135 | return 0; | |
136 | } | |
021db4be | 137 | libc_hidden_nolink_sunrpc (key_encryptsession, GLIBC_2_1) |
800d775e UD |
138 | |
139 | int | |
9a0a462c | 140 | key_decryptsession (char *remotename, des_block *deskey) |
800d775e UD |
141 | { |
142 | cryptkeyarg arg; | |
143 | cryptkeyres res; | |
144 | ||
145 | arg.remotename = remotename; | |
146 | arg.deskey = *deskey; | |
7b57bfe5 UD |
147 | if (!key_call ((u_long) KEY_DECRYPT, (xdrproc_t) xdr_cryptkeyarg, |
148 | (char *) &arg, (xdrproc_t) xdr_cryptkeyres, | |
77fe0b9c | 149 | (char *) &res)) |
800d775e UD |
150 | return -1; |
151 | if (res.status != KEY_SUCCESS) | |
152 | { | |
153 | debug ("decrypt status is nonzero"); | |
154 | return -1; | |
155 | } | |
156 | *deskey = res.cryptkeyres_u.deskey; | |
157 | return 0; | |
158 | } | |
021db4be | 159 | libc_hidden_nolink_sunrpc (key_decryptsession, GLIBC_2_1) |
800d775e UD |
160 | |
161 | int | |
9a0a462c UD |
162 | key_encryptsession_pk (char *remotename, netobj *remotekey, |
163 | des_block *deskey) | |
800d775e UD |
164 | { |
165 | cryptkeyarg2 arg; | |
166 | cryptkeyres res; | |
167 | ||
168 | arg.remotename = remotename; | |
169 | arg.remotekey = *remotekey; | |
170 | arg.deskey = *deskey; | |
7b57bfe5 UD |
171 | if (!key_call ((u_long) KEY_ENCRYPT_PK, (xdrproc_t) xdr_cryptkeyarg2, |
172 | (char *) &arg, (xdrproc_t) xdr_cryptkeyres, | |
77fe0b9c | 173 | (char *) &res)) |
800d775e UD |
174 | return -1; |
175 | ||
176 | if (res.status != KEY_SUCCESS) | |
177 | { | |
178 | debug ("encrypt status is nonzero"); | |
179 | return -1; | |
180 | } | |
181 | *deskey = res.cryptkeyres_u.deskey; | |
182 | return 0; | |
183 | } | |
021db4be | 184 | libc_hidden_nolink_sunrpc (key_encryptsession_pk, GLIBC_2_1) |
800d775e UD |
185 | |
186 | int | |
9a0a462c UD |
187 | key_decryptsession_pk (char *remotename, netobj *remotekey, |
188 | des_block *deskey) | |
800d775e UD |
189 | { |
190 | cryptkeyarg2 arg; | |
191 | cryptkeyres res; | |
192 | ||
193 | arg.remotename = remotename; | |
194 | arg.remotekey = *remotekey; | |
195 | arg.deskey = *deskey; | |
7b57bfe5 UD |
196 | if (!key_call ((u_long) KEY_DECRYPT_PK, (xdrproc_t) xdr_cryptkeyarg2, |
197 | (char *) &arg, (xdrproc_t) xdr_cryptkeyres, | |
77fe0b9c | 198 | (char *) &res)) |
800d775e UD |
199 | return -1; |
200 | ||
201 | if (res.status != KEY_SUCCESS) | |
202 | { | |
203 | debug ("decrypt status is nonzero"); | |
204 | return -1; | |
205 | } | |
206 | *deskey = res.cryptkeyres_u.deskey; | |
207 | return 0; | |
208 | } | |
021db4be | 209 | libc_hidden_nolink_sunrpc (key_decryptsession_pk, GLIBC_2_1) |
800d775e UD |
210 | |
211 | int | |
9a0a462c | 212 | key_gendes (des_block *key) |
800d775e UD |
213 | { |
214 | struct sockaddr_in sin; | |
215 | CLIENT *client; | |
216 | int socket; | |
217 | enum clnt_stat stat; | |
218 | ||
219 | sin.sin_family = AF_INET; | |
220 | sin.sin_port = 0; | |
221 | sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); | |
d99431e5 | 222 | memset (sin.sin_zero, 0, sizeof (sin.sin_zero)); |
800d775e | 223 | socket = RPC_ANYSOCK; |
7b57bfe5 UD |
224 | client = clntudp_bufcreate (&sin, (u_long) KEY_PROG, (u_long) KEY_VERS, |
225 | trytimeout, &socket, RPCSMALLMSGSIZE, | |
226 | RPCSMALLMSGSIZE); | |
800d775e UD |
227 | if (client == NULL) |
228 | return -1; | |
229 | ||
7b57bfe5 UD |
230 | stat = clnt_call (client, KEY_GEN, (xdrproc_t) xdr_void, NULL, |
231 | (xdrproc_t) xdr_des_block, (caddr_t) key, | |
77fe0b9c | 232 | tottimeout); |
800d775e | 233 | clnt_destroy (client); |
50304ef0 | 234 | __close (socket); |
800d775e UD |
235 | if (stat != RPC_SUCCESS) |
236 | return -1; | |
237 | ||
238 | return 0; | |
239 | } | |
7b57bfe5 | 240 | #ifdef EXPORT_RPC_SYMBOLS |
9b0b40d3 | 241 | libc_hidden_def (key_gendes) |
7b57bfe5 | 242 | #else |
021db4be | 243 | libc_hidden_nolink_sunrpc (key_gendes, GLIBC_2_1) |
7b57bfe5 | 244 | #endif |
800d775e UD |
245 | |
246 | int | |
247 | key_setnet (struct key_netstarg *arg) | |
248 | { | |
249 | keystatus status; | |
250 | ||
7b57bfe5 UD |
251 | if (!key_call ((u_long) KEY_NET_PUT, (xdrproc_t) xdr_key_netstarg, |
252 | (char *) arg,(xdrproc_t) xdr_keystatus, | |
77fe0b9c | 253 | (char *) &status)) |
800d775e UD |
254 | return -1; |
255 | ||
256 | if (status != KEY_SUCCESS) | |
257 | { | |
258 | debug ("key_setnet status is nonzero"); | |
259 | return -1; | |
260 | } | |
261 | return 1; | |
262 | } | |
021db4be | 263 | libc_hidden_nolink_sunrpc (key_setnet, GLIBC_2_1) |
800d775e UD |
264 | |
265 | int | |
9a0a462c | 266 | key_get_conv (char *pkey, des_block *deskey) |
800d775e UD |
267 | { |
268 | cryptkeyres res; | |
269 | ||
7b57bfe5 UD |
270 | if (!key_call ((u_long) KEY_GET_CONV, (xdrproc_t) xdr_keybuf, pkey, |
271 | (xdrproc_t) xdr_cryptkeyres, (char *) &res)) | |
800d775e UD |
272 | return -1; |
273 | ||
274 | if (res.status != KEY_SUCCESS) | |
275 | { | |
276 | debug ("get_conv status is nonzero"); | |
277 | return -1; | |
278 | } | |
279 | *deskey = res.cryptkeyres_u.deskey; | |
280 | return 0; | |
281 | } | |
021db4be | 282 | libc_hidden_nolink_sunrpc (key_get_conv, GLIBC_2_1) |
800d775e UD |
283 | |
284 | /* | |
285 | * Hack to allow the keyserver to use AUTH_DES (for authenticated | |
286 | * NIS+ calls, for example). The only functions that get called | |
287 | * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes. | |
288 | * | |
289 | * The approach is to have the keyserver fill in pointers to local | |
290 | * implementations of these functions, and to call those in key_call(). | |
291 | */ | |
292 | ||
c4563d2d UD |
293 | cryptkeyres *(*__key_encryptsession_pk_LOCAL) (uid_t, char *); |
294 | cryptkeyres *(*__key_decryptsession_pk_LOCAL) (uid_t, char *); | |
295 | des_block *(*__key_gendes_LOCAL) (uid_t, char *); | |
800d775e | 296 | |
54f4f73e | 297 | #ifndef SO_PASSCRED |
800d775e | 298 | static int |
e852e889 UD |
299 | key_call_keyenvoy (u_long proc, xdrproc_t xdr_arg, char *arg, |
300 | xdrproc_t xdr_rslt, char *rslt) | |
800d775e UD |
301 | { |
302 | XDR xdrargs; | |
303 | XDR xdrrslt; | |
304 | FILE *fargs; | |
305 | FILE *frslt; | |
9a0a462c | 306 | sigset_t oldmask, mask; |
30bcdc18 | 307 | int status; |
800d775e UD |
308 | int pid; |
309 | int success; | |
310 | uid_t ruid; | |
311 | uid_t euid; | |
c4563d2d | 312 | static const char MESSENGER[] = "/usr/etc/keyenvoy"; |
800d775e | 313 | |
9a0a462c UD |
314 | success = 1; |
315 | sigemptyset (&mask); | |
316 | sigaddset (&mask, SIGCHLD); | |
50304ef0 | 317 | __sigprocmask (SIG_BLOCK, &mask, &oldmask); |
9a0a462c | 318 | |
800d775e UD |
319 | /* |
320 | * We are going to exec a set-uid program which makes our effective uid | |
321 | * zero, and authenticates us with our real uid. We need to make the | |
322 | * effective uid be the real uid for the setuid program, and | |
323 | * the real uid be the effective uid so that we can change things back. | |
324 | */ | |
50304ef0 UD |
325 | euid = __geteuid (); |
326 | ruid = __getuid (); | |
327 | __setreuid (euid, ruid); | |
800d775e | 328 | pid = _openchild (MESSENGER, &fargs, &frslt); |
50304ef0 | 329 | __setreuid (ruid, euid); |
800d775e UD |
330 | if (pid < 0) |
331 | { | |
332 | debug ("open_streams"); | |
50304ef0 | 333 | __sigprocmask (SIG_SETMASK, &oldmask, NULL); |
800d775e UD |
334 | return (0); |
335 | } | |
336 | xdrstdio_create (&xdrargs, fargs, XDR_ENCODE); | |
337 | xdrstdio_create (&xdrrslt, frslt, XDR_DECODE); | |
338 | ||
7b57bfe5 | 339 | if (!xdr_u_long (&xdrargs, &proc) || !(*xdr_arg) (&xdrargs, arg)) |
800d775e UD |
340 | { |
341 | debug ("xdr args"); | |
342 | success = 0; | |
343 | } | |
344 | fclose (fargs); | |
345 | ||
346 | if (success && !(*xdr_rslt) (&xdrrslt, rslt)) | |
347 | { | |
348 | debug ("xdr rslt"); | |
349 | success = 0; | |
350 | } | |
9a0a462c | 351 | fclose(frslt); |
800d775e | 352 | |
9a0a462c | 353 | wait_again: |
50304ef0 | 354 | if (__wait4 (pid, &status, 0, NULL) < 0) |
800d775e | 355 | { |
9a0a462c UD |
356 | if (errno == EINTR) |
357 | goto wait_again; | |
50304ef0 | 358 | debug ("wait4"); |
9a0a462c | 359 | if (errno == ECHILD || errno == ESRCH) |
50304ef0 | 360 | perror ("wait"); |
9a0a462c UD |
361 | else |
362 | success = 0; | |
800d775e | 363 | } |
9a0a462c | 364 | else |
30bcdc18 | 365 | if (status != 0) |
9a0a462c | 366 | { |
50304ef0 | 367 | debug ("wait4 1"); |
9a0a462c UD |
368 | success = 0; |
369 | } | |
50304ef0 | 370 | __sigprocmask (SIG_SETMASK, &oldmask, NULL); |
800d775e | 371 | |
50304ef0 | 372 | return success; |
800d775e | 373 | } |
54f4f73e | 374 | #endif |
e852e889 UD |
375 | |
376 | struct key_call_private { | |
377 | CLIENT *client; /* Client handle */ | |
378 | pid_t pid; /* process-id at moment of creation */ | |
379 | uid_t uid; /* user-id at last authorization */ | |
380 | }; | |
1bc1a2b9 | 381 | #define key_call_private_main RPC_THREAD_VARIABLE(key_call_private_s) |
e852e889 UD |
382 | __libc_lock_define_initialized (static, keycall_lock) |
383 | ||
384 | /* | |
385 | * Keep the handle cached. This call may be made quite often. | |
386 | */ | |
387 | static CLIENT * | |
388 | getkeyserv_handle (int vers) | |
389 | { | |
390 | struct key_call_private *kcp = key_call_private_main; | |
391 | struct timeval wait_time; | |
392 | int fd; | |
393 | struct sockaddr_un name; | |
9cfe5381 | 394 | socklen_t namelen = sizeof(struct sockaddr_un); |
e852e889 UD |
395 | |
396 | #define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */ | |
397 | #define TOTAL_TRIES 5 /* Number of tries */ | |
398 | ||
399 | if (kcp == (struct key_call_private *)NULL) | |
400 | { | |
401 | kcp = (struct key_call_private *)malloc (sizeof (*kcp)); | |
402 | if (kcp == (struct key_call_private *)NULL) | |
403 | return (CLIENT *) NULL; | |
404 | ||
405 | key_call_private_main = kcp; | |
406 | kcp->client = NULL; | |
407 | } | |
408 | ||
409 | /* if pid has changed, destroy client and rebuild */ | |
410 | if (kcp->client != NULL && kcp->pid != __getpid ()) | |
411 | { | |
360d5cf4 | 412 | auth_destroy (kcp->client->cl_auth); |
e852e889 UD |
413 | clnt_destroy (kcp->client); |
414 | kcp->client = NULL; | |
415 | } | |
416 | ||
417 | if (kcp->client != NULL) | |
418 | { | |
419 | /* if other side closed socket, build handle again */ | |
420 | clnt_control (kcp->client, CLGET_FD, (char *)&fd); | |
4aebaa6b | 421 | if (__getpeername (fd,(struct sockaddr *)&name,&namelen) == -1) |
e852e889 UD |
422 | { |
423 | auth_destroy (kcp->client->cl_auth); | |
424 | clnt_destroy (kcp->client); | |
425 | kcp->client = NULL; | |
426 | } | |
427 | } | |
428 | ||
429 | if (kcp->client != NULL) | |
430 | { | |
431 | /* if uid has changed, build client handle again */ | |
432 | if (kcp->uid != __geteuid ()) | |
433 | { | |
7b57bfe5 UD |
434 | kcp->uid = __geteuid (); |
435 | auth_destroy (kcp->client->cl_auth); | |
436 | kcp->client->cl_auth = | |
437 | authunix_create ((char *)"", kcp->uid, 0, 0, NULL); | |
438 | if (kcp->client->cl_auth == NULL) | |
439 | { | |
440 | clnt_destroy (kcp->client); | |
441 | kcp->client = NULL; | |
442 | return ((CLIENT *) NULL); | |
443 | } | |
e852e889 UD |
444 | } |
445 | /* Change the version number to the new one */ | |
446 | clnt_control (kcp->client, CLSET_VERS, (void *)&vers); | |
447 | return kcp->client; | |
448 | } | |
449 | ||
450 | if ((kcp->client == (CLIENT *) NULL)) | |
451 | /* Use the AF_UNIX transport */ | |
7b57bfe5 | 452 | kcp->client = clnt_create ("/var/run/keyservsock", KEY_PROG, vers, "unix"); |
e852e889 UD |
453 | |
454 | if (kcp->client == (CLIENT *) NULL) | |
455 | return (CLIENT *) NULL; | |
456 | ||
457 | kcp->uid = __geteuid (); | |
458 | kcp->pid = __getpid (); | |
7b57bfe5 | 459 | kcp->client->cl_auth = authunix_create ((char *)"", kcp->uid, 0, 0, NULL); |
e852e889 UD |
460 | if (kcp->client->cl_auth == NULL) |
461 | { | |
462 | clnt_destroy (kcp->client); | |
463 | kcp->client = NULL; | |
464 | return (CLIENT *) NULL; | |
465 | } | |
466 | ||
467 | wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES; | |
468 | wait_time.tv_usec = 0; | |
469 | clnt_control (kcp->client, CLSET_RETRY_TIMEOUT, | |
470 | (char *)&wait_time); | |
471 | if (clnt_control (kcp->client, CLGET_FD, (char *)&fd)) | |
31f3b159 | 472 | __fcntl (fd, F_SETFD, FD_CLOEXEC); /* make it "close on exec" */ |
e852e889 UD |
473 | |
474 | return kcp->client; | |
475 | } | |
476 | ||
477 | /* returns 0 on failure, 1 on success */ | |
478 | static int | |
e852e889 | 479 | key_call_socket (u_long proc, xdrproc_t xdr_arg, char *arg, |
7b57bfe5 | 480 | xdrproc_t xdr_rslt, char *rslt) |
e852e889 UD |
481 | { |
482 | CLIENT *clnt; | |
483 | struct timeval wait_time; | |
484 | int result = 0; | |
485 | ||
486 | __libc_lock_lock (keycall_lock); | |
487 | if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) || | |
488 | (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) || | |
489 | (proc == KEY_GET_CONV)) | |
490 | clnt = getkeyserv_handle(2); /* talk to version 2 */ | |
491 | else | |
492 | clnt = getkeyserv_handle(1); /* talk to version 1 */ | |
493 | ||
494 | if (clnt != NULL) | |
495 | { | |
496 | wait_time.tv_sec = TOTAL_TIMEOUT; | |
497 | wait_time.tv_usec = 0; | |
498 | ||
499 | if (clnt_call (clnt, proc, xdr_arg, arg, xdr_rslt, rslt, | |
500 | wait_time) == RPC_SUCCESS) | |
501 | result = 1; | |
502 | } | |
503 | ||
504 | __libc_lock_unlock (keycall_lock); | |
505 | ||
506 | return result; | |
507 | } | |
508 | ||
7cabd57c UD |
509 | |
510 | /* returns 0 on failure, 1 on success */ | |
e852e889 | 511 | static int |
e852e889 UD |
512 | key_call (u_long proc, xdrproc_t xdr_arg, char *arg, |
513 | xdrproc_t xdr_rslt, char *rslt) | |
514 | { | |
54f4f73e | 515 | #ifndef SO_PASSCRED |
c4563d2d | 516 | static int use_keyenvoy; |
54f4f73e | 517 | #endif |
e852e889 UD |
518 | |
519 | if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) | |
520 | { | |
521 | cryptkeyres *res; | |
522 | res = (*__key_encryptsession_pk_LOCAL) (__geteuid (), arg); | |
523 | *(cryptkeyres *) rslt = *res; | |
524 | return 1; | |
525 | } | |
526 | else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) | |
527 | { | |
528 | cryptkeyres *res; | |
529 | res = (*__key_decryptsession_pk_LOCAL) (__geteuid (), arg); | |
530 | *(cryptkeyres *) rslt = *res; | |
531 | return 1; | |
532 | } | |
533 | else if (proc == KEY_GEN && __key_gendes_LOCAL) | |
534 | { | |
535 | des_block *res; | |
536 | res = (*__key_gendes_LOCAL) (__geteuid (), 0); | |
537 | *(des_block *) rslt = *res; | |
538 | return 1; | |
539 | } | |
540 | ||
54f4f73e UD |
541 | #ifdef SO_PASSCRED |
542 | return key_call_socket (proc, xdr_arg, arg, xdr_rslt, rslt); | |
543 | #else | |
e852e889 UD |
544 | if (!use_keyenvoy) |
545 | { | |
546 | if (key_call_socket (proc, xdr_arg, arg, xdr_rslt, rslt)) | |
547 | return 1; | |
548 | use_keyenvoy = 1; | |
549 | } | |
550 | return key_call_keyenvoy (proc, xdr_arg, arg, xdr_rslt, rslt); | |
54f4f73e | 551 | #endif |
e852e889 | 552 | } |
f1e4a4a4 | 553 | |
f1e4a4a4 UD |
554 | void |
555 | __rpc_thread_key_cleanup (void) | |
556 | { | |
557 | struct key_call_private *kcp = RPC_THREAD_VARIABLE(key_call_private_s); | |
558 | ||
559 | if (kcp) { | |
48be3114 UD |
560 | if (kcp->client) { |
561 | if (kcp->client->cl_auth) | |
562 | auth_destroy (kcp->client->cl_auth); | |
f1e4a4a4 | 563 | clnt_destroy(kcp->client); |
48be3114 | 564 | } |
f1e4a4a4 UD |
565 | free (kcp); |
566 | } | |
567 | } |