2 * Copyright (c) 1988 by Sun Microsystems, Inc.
5 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
6 * unrestricted use provided that this legend is included on all tape
7 * media and as a part of the software program in whole or part. Users
8 * may copy or modify Sun RPC without charge, but are not authorized
9 * to license or distribute it to anyone else except as part of a product or
10 * program developed by the user.
12 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
13 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
14 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
16 * Sun RPC is provided with no support and without any obligation on the
17 * part of Sun Microsystems, Inc. to assist in its use, correction,
18 * modification or enhancement.
20 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
21 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
22 * OR ANY PART THEREOF.
24 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
25 * or profits or other special, indirect and consequential damages, even if
26 * Sun has been advised of the possibility of such damages.
28 * Sun Microsystems, Inc.
30 * Mountain View, California 94043
34 * The original source is from the RPCSRC 4.0 package from Sun Microsystems.
35 * The Interface to keyserver protocoll 2 was added by
36 * Thorsten Kukuk <kukuk@vt.uni-paderborn.de>
46 #include <sys/param.h>
47 #include <sys/socket.h>
48 #include <rpc/key_prot.h>
50 #define KEY_TIMEOUT 5 /* per-try timeout in seconds */
51 #define KEY_NRETRY 12 /* number of retries */
53 #define debug(msg) /* turn off debugging */
55 extern int _openchild (char *command
, FILE ** fto
, FILE ** ffrom
);
58 static int key_call (u_long
, xdrproc_t xdr_arg
, char *,
59 xdrproc_t xdr_rslt
, char *);
61 static struct timeval trytimeout
= {KEY_TIMEOUT
, 0};
62 static struct timeval tottimeout
= {KEY_TIMEOUT
* KEY_NRETRY
, 0};
65 key_setsecret (char *secretkey
)
69 if (!key_call ((u_long
) KEY_SET
, (xdrproc_t
) xdr_keybuf
, secretkey
,
70 (xdrproc_t
) xdr_keystatus
, (char *) &status
))
72 if (status
!= KEY_SUCCESS
)
74 debug ("set status is nonzero");
80 /* key_secretkey_is_set() returns 1 if the keyserver has a secret key
81 * stored for the caller's effective uid; it returns 0 otherwise
83 * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't
84 * be using it, because it allows them to get the user's secret key.
87 key_secretkey_is_set (void)
89 struct key_netstres kres
;
91 memset (&kres
, 0, sizeof (kres
));
92 if (key_call ((u_long
) KEY_NET_GET
, (xdrproc_t
) xdr_void
, (char *) NULL
,
93 (xdrproc_t
) xdr_key_netstres
, (char *) &kres
) &&
94 (kres
.status
== KEY_SUCCESS
) &&
95 (kres
.key_netstres_u
.knet
.st_priv_key
[0] != 0))
97 /* avoid leaving secret key in memory */
98 memset (kres
.key_netstres_u
.knet
.st_priv_key
, 0, HEXKEYBYTES
);
105 key_encryptsession (char *remotename
, des_block
* deskey
)
110 arg
.remotename
= remotename
;
111 arg
.deskey
= *deskey
;
112 if (!key_call ((u_long
) KEY_ENCRYPT
, (xdrproc_t
) xdr_cryptkeyarg
,
113 (char *) &arg
, (xdrproc_t
) xdr_cryptkeyres
, (char *) &res
))
116 if (res
.status
!= KEY_SUCCESS
)
118 debug ("encrypt status is nonzero");
121 *deskey
= res
.cryptkeyres_u
.deskey
;
126 key_decryptsession (char *remotename
, des_block
* deskey
)
131 arg
.remotename
= remotename
;
132 arg
.deskey
= *deskey
;
133 if (!key_call ((u_long
) KEY_DECRYPT
, (xdrproc_t
) xdr_cryptkeyarg
,
134 (char *) &arg
, (xdrproc_t
) xdr_cryptkeyres
, (char *) &res
))
136 if (res
.status
!= KEY_SUCCESS
)
138 debug ("decrypt status is nonzero");
141 *deskey
= res
.cryptkeyres_u
.deskey
;
146 key_encryptsession_pk (char *remotename
, netobj
* remotekey
,
152 arg
.remotename
= remotename
;
153 arg
.remotekey
= *remotekey
;
154 arg
.deskey
= *deskey
;
155 if (!key_call ((u_long
) KEY_ENCRYPT_PK
, (xdrproc_t
) xdr_cryptkeyarg2
,
156 (char *) &arg
, (xdrproc_t
) xdr_cryptkeyres
, (char *) &res
))
159 if (res
.status
!= KEY_SUCCESS
)
161 debug ("encrypt status is nonzero");
164 *deskey
= res
.cryptkeyres_u
.deskey
;
169 key_decryptsession_pk (char *remotename
, netobj
* remotekey
,
175 arg
.remotename
= remotename
;
176 arg
.remotekey
= *remotekey
;
177 arg
.deskey
= *deskey
;
178 if (!key_call ((u_long
) KEY_DECRYPT_PK
, (xdrproc_t
) xdr_cryptkeyarg2
,
179 (char *) &arg
, (xdrproc_t
) xdr_cryptkeyres
, (char *) &res
))
182 if (res
.status
!= KEY_SUCCESS
)
184 debug ("decrypt status is nonzero");
187 *deskey
= res
.cryptkeyres_u
.deskey
;
192 key_gendes (des_block
* key
)
194 struct sockaddr_in sin
;
199 sin
.sin_family
= AF_INET
;
201 sin
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
202 bzero (sin
.sin_zero
, sizeof (sin
.sin_zero
));
203 socket
= RPC_ANYSOCK
;
204 client
= clntudp_bufcreate (&sin
, (u_long
) KEY_PROG
, (u_long
) KEY_VERS
,
205 trytimeout
, &socket
, RPCSMALLMSGSIZE
,
210 stat
= clnt_call (client
, KEY_GEN
, (xdrproc_t
) xdr_void
, NULL
,
211 (xdrproc_t
) xdr_des_block
, (caddr_t
) key
, tottimeout
);
212 clnt_destroy (client
);
214 if (stat
!= RPC_SUCCESS
)
221 key_setnet (struct key_netstarg
*arg
)
225 if (!key_call ((u_long
) KEY_NET_PUT
, (xdrproc_t
) xdr_key_netstarg
,
226 (char *) arg
,(xdrproc_t
) xdr_keystatus
, (char *) &status
))
229 if (status
!= KEY_SUCCESS
)
231 debug ("key_setnet status is nonzero");
238 key_get_conv (char *pkey
, des_block
* deskey
)
242 if (!key_call ((u_long
) KEY_GET_CONV
, (xdrproc_t
) xdr_keybuf
, pkey
,
243 (xdrproc_t
) xdr_cryptkeyres
, (char *) &res
))
246 if (res
.status
!= KEY_SUCCESS
)
248 debug ("get_conv status is nonzero");
251 *deskey
= res
.cryptkeyres_u
.deskey
;
256 * Hack to allow the keyserver to use AUTH_DES (for authenticated
257 * NIS+ calls, for example). The only functions that get called
258 * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
260 * The approach is to have the keyserver fill in pointers to local
261 * implementations of these functions, and to call those in key_call().
264 cryptkeyres
*(*__key_encryptsession_pk_LOCAL
) (uid_t
, char *) = 0;
265 cryptkeyres
*(*__key_decryptsession_pk_LOCAL
) (uid_t
, char *) = 0;
266 des_block
*(*__key_gendes_LOCAL
) (uid_t
, char *) = 0;
269 key_call (u_long proc
, xdrproc_t xdr_arg
, char *arg
,
270 xdrproc_t xdr_rslt
, char *rslt
)
276 void (*osigchild
) (int);
282 static char MESSENGER
[] = "/usr/etc/keyenvoy";
285 osigchild
= signal (SIGCHLD
, SIG_IGN
);
287 if (proc
== KEY_ENCRYPT_PK
&& __key_encryptsession_pk_LOCAL
)
290 res
= (*__key_encryptsession_pk_LOCAL
) (geteuid (), arg
);
291 *(cryptkeyres
*) rslt
= *res
;
294 else if (proc
== KEY_DECRYPT_PK
&& __key_decryptsession_pk_LOCAL
)
297 res
= (*__key_decryptsession_pk_LOCAL
) (geteuid (), arg
);
298 *(cryptkeyres
*) rslt
= *res
;
301 else if (proc
== KEY_GEN
&& __key_gendes_LOCAL
)
304 res
= (*__key_gendes_LOCAL
) (geteuid (), 0);
305 *(des_block
*) rslt
= *res
;
310 * We are going to exec a set-uid program which makes our effective uid
311 * zero, and authenticates us with our real uid. We need to make the
312 * effective uid be the real uid for the setuid program, and
313 * the real uid be the effective uid so that we can change things back.
317 setreuid (euid
, ruid
);
318 pid
= _openchild (MESSENGER
, &fargs
, &frslt
);
319 setreuid (ruid
, euid
);
322 debug ("open_streams");
325 xdrstdio_create (&xdrargs
, fargs
, XDR_ENCODE
);
326 xdrstdio_create (&xdrrslt
, frslt
, XDR_DECODE
);
328 if (!xdr_u_long (&xdrargs
, &proc
) || !(*xdr_arg
) (&xdrargs
, arg
))
335 if (success
&& !(*xdr_rslt
) (&xdrrslt
, rslt
))
344 * The original code appears first. wait4 returns only after the process
345 * with the requested pid terminates. The effect of using wait() instead
346 * has not been determined.
349 if (wait4 (pid
, &status
, 0, NULL
) < 0 || status
.w_retcode
!= 0)
354 #endif /* def NOTDEF */
355 if (wait (&status
) < 0 || status
.w_retcode
!= 0)
360 signal (SIGCHLD
, osigchild
);