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>
47 #include <sys/param.h>
48 #include <sys/socket.h>
49 #include <rpc/key_prot.h>
51 #define KEY_TIMEOUT 5 /* per-try timeout in seconds */
52 #define KEY_NRETRY 12 /* number of retries */
54 #define debug(msg) /* turn off debugging */
56 extern int _openchild (char *command
, FILE **fto
, FILE **ffrom
);
59 static int key_call (u_long
, xdrproc_t xdr_arg
, char *,
60 xdrproc_t xdr_rslt
, char *) internal_function
;
62 static struct timeval trytimeout
= {KEY_TIMEOUT
, 0};
63 static struct timeval tottimeout
= {KEY_TIMEOUT
*KEY_NRETRY
, 0};
66 key_setsecret (char *secretkey
)
70 if (!key_call ((u_long
) KEY_SET
, (xdrproc_t
) xdr_keybuf
, secretkey
,
71 (xdrproc_t
) xdr_keystatus
, (char *) &status
))
73 if (status
!= KEY_SUCCESS
)
75 debug ("set status is nonzero");
81 /* key_secretkey_is_set() returns 1 if the keyserver has a secret key
82 * stored for the caller's effective uid; it returns 0 otherwise
84 * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't
85 * be using it, because it allows them to get the user's secret key.
88 key_secretkey_is_set (void)
90 struct key_netstres kres
;
92 memset (&kres
, 0, sizeof (kres
));
93 if (key_call ((u_long
) KEY_NET_GET
, (xdrproc_t
) xdr_void
, (char *) NULL
,
94 (xdrproc_t
) xdr_key_netstres
, (char *) &kres
) &&
95 (kres
.status
== KEY_SUCCESS
) &&
96 (kres
.key_netstres_u
.knet
.st_priv_key
[0] != 0))
98 /* avoid leaving secret key in memory */
99 memset (kres
.key_netstres_u
.knet
.st_priv_key
, 0, HEXKEYBYTES
);
106 key_encryptsession (char *remotename
, des_block
*deskey
)
111 arg
.remotename
= remotename
;
112 arg
.deskey
= *deskey
;
113 if (!key_call ((u_long
) KEY_ENCRYPT
, (xdrproc_t
) xdr_cryptkeyarg
,
114 (char *) &arg
, (xdrproc_t
) xdr_cryptkeyres
, (char *) &res
))
117 if (res
.status
!= KEY_SUCCESS
)
119 debug ("encrypt status is nonzero");
122 *deskey
= res
.cryptkeyres_u
.deskey
;
127 key_decryptsession (char *remotename
, des_block
*deskey
)
132 arg
.remotename
= remotename
;
133 arg
.deskey
= *deskey
;
134 if (!key_call ((u_long
) KEY_DECRYPT
, (xdrproc_t
) xdr_cryptkeyarg
,
135 (char *) &arg
, (xdrproc_t
) xdr_cryptkeyres
, (char *) &res
))
137 if (res
.status
!= KEY_SUCCESS
)
139 debug ("decrypt status is nonzero");
142 *deskey
= res
.cryptkeyres_u
.deskey
;
147 key_encryptsession_pk (char *remotename
, netobj
*remotekey
,
153 arg
.remotename
= remotename
;
154 arg
.remotekey
= *remotekey
;
155 arg
.deskey
= *deskey
;
156 if (!key_call ((u_long
) KEY_ENCRYPT_PK
, (xdrproc_t
) xdr_cryptkeyarg2
,
157 (char *) &arg
, (xdrproc_t
) xdr_cryptkeyres
, (char *) &res
))
160 if (res
.status
!= KEY_SUCCESS
)
162 debug ("encrypt status is nonzero");
165 *deskey
= res
.cryptkeyres_u
.deskey
;
170 key_decryptsession_pk (char *remotename
, netobj
*remotekey
,
176 arg
.remotename
= remotename
;
177 arg
.remotekey
= *remotekey
;
178 arg
.deskey
= *deskey
;
179 if (!key_call ((u_long
) KEY_DECRYPT_PK
, (xdrproc_t
) xdr_cryptkeyarg2
,
180 (char *) &arg
, (xdrproc_t
) xdr_cryptkeyres
, (char *) &res
))
183 if (res
.status
!= KEY_SUCCESS
)
185 debug ("decrypt status is nonzero");
188 *deskey
= res
.cryptkeyres_u
.deskey
;
193 key_gendes (des_block
*key
)
195 struct sockaddr_in sin
;
200 sin
.sin_family
= AF_INET
;
202 sin
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
203 __bzero (sin
.sin_zero
, sizeof (sin
.sin_zero
));
204 socket
= RPC_ANYSOCK
;
205 client
= clntudp_bufcreate (&sin
, (u_long
) KEY_PROG
, (u_long
) KEY_VERS
,
206 trytimeout
, &socket
, RPCSMALLMSGSIZE
,
211 stat
= clnt_call (client
, KEY_GEN
, (xdrproc_t
) xdr_void
, NULL
,
212 (xdrproc_t
) xdr_des_block
, (caddr_t
) key
, tottimeout
);
213 clnt_destroy (client
);
215 if (stat
!= RPC_SUCCESS
)
222 key_setnet (struct key_netstarg
*arg
)
226 if (!key_call ((u_long
) KEY_NET_PUT
, (xdrproc_t
) xdr_key_netstarg
,
227 (char *) arg
,(xdrproc_t
) xdr_keystatus
, (char *) &status
))
230 if (status
!= KEY_SUCCESS
)
232 debug ("key_setnet status is nonzero");
239 key_get_conv (char *pkey
, des_block
*deskey
)
243 if (!key_call ((u_long
) KEY_GET_CONV
, (xdrproc_t
) xdr_keybuf
, pkey
,
244 (xdrproc_t
) xdr_cryptkeyres
, (char *) &res
))
247 if (res
.status
!= KEY_SUCCESS
)
249 debug ("get_conv status is nonzero");
252 *deskey
= res
.cryptkeyres_u
.deskey
;
257 * Hack to allow the keyserver to use AUTH_DES (for authenticated
258 * NIS+ calls, for example). The only functions that get called
259 * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
261 * The approach is to have the keyserver fill in pointers to local
262 * implementations of these functions, and to call those in key_call().
265 cryptkeyres
*(*__key_encryptsession_pk_LOCAL
) (uid_t
, char *) = 0;
266 cryptkeyres
*(*__key_decryptsession_pk_LOCAL
) (uid_t
, char *) = 0;
267 des_block
*(*__key_gendes_LOCAL
) (uid_t
, char *) = 0;
271 key_call (u_long proc
, xdrproc_t xdr_arg
, char *arg
,
272 xdrproc_t xdr_rslt
, char *rslt
)
278 sigset_t oldmask
, mask
;
284 static char MESSENGER
[] = "/usr/etc/keyenvoy";
286 if (proc
== KEY_ENCRYPT_PK
&& __key_encryptsession_pk_LOCAL
)
289 res
= (*__key_encryptsession_pk_LOCAL
) (__geteuid (), arg
);
290 *(cryptkeyres
*) rslt
= *res
;
293 else if (proc
== KEY_DECRYPT_PK
&& __key_decryptsession_pk_LOCAL
)
296 res
= (*__key_decryptsession_pk_LOCAL
) (__geteuid (), arg
);
297 *(cryptkeyres
*) rslt
= *res
;
300 else if (proc
== KEY_GEN
&& __key_gendes_LOCAL
)
303 res
= (*__key_gendes_LOCAL
) (__geteuid (), 0);
304 *(des_block
*) rslt
= *res
;
310 sigaddset (&mask
, SIGCHLD
);
311 __sigprocmask (SIG_BLOCK
, &mask
, &oldmask
);
314 * We are going to exec a set-uid program which makes our effective uid
315 * zero, and authenticates us with our real uid. We need to make the
316 * effective uid be the real uid for the setuid program, and
317 * the real uid be the effective uid so that we can change things back.
321 __setreuid (euid
, ruid
);
322 pid
= _openchild (MESSENGER
, &fargs
, &frslt
);
323 __setreuid (ruid
, euid
);
326 debug ("open_streams");
327 __sigprocmask (SIG_SETMASK
, &oldmask
, NULL
);
330 xdrstdio_create (&xdrargs
, fargs
, XDR_ENCODE
);
331 xdrstdio_create (&xdrrslt
, frslt
, XDR_DECODE
);
333 if (!xdr_u_long (&xdrargs
, &proc
) || !(*xdr_arg
) (&xdrargs
, arg
))
340 if (success
&& !(*xdr_rslt
) (&xdrrslt
, rslt
))
348 if (__wait4 (pid
, &status
, 0, NULL
) < 0)
353 if (errno
== ECHILD
|| errno
== ESRCH
)
359 if (status
.w_retcode
)
364 __sigprocmask (SIG_SETMASK
, &oldmask
, NULL
);