ReactOS 0.4.15-dev-7705-g2320c37
key_call.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009, Sun Microsystems, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of Sun Microsystems, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28/*
29 * Copyright (c) 1986-1991 by Sun Microsystems Inc.
30 */
31
32
33//#include <sys/cdefs.h>
34
35/*
36 * key_call.c, Interface to keyserver
37 *
38 * setsecretkey(key) - set your secret key
39 * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent
40 * decryptsessionkey(agent, deskey) - decrypt ditto
41 * gendeskey(deskey) - generate a secure des key
42 */
43
44#ifndef _WIN32
45
46#include <pthread.h>
47#include <reentrant.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <unistd.h>
51#include <errno.h>
52#include <rpc/rpc.h>
53#include <rpc/auth.h>
54#include <rpc/auth_unix.h>
55#include <rpc/key_prot.h>
56#include <string.h>
57#include <netconfig.h>
58#include <sys/utsname.h>
59#include <stdlib.h>
60#include <signal.h>
61#include <sys/wait.h>
62#include <sys/fcntl.h>
63
64
65#define KEY_TIMEOUT 5 /* per-try timeout in seconds */
66#define KEY_NRETRY 12 /* number of retries */
67
68#ifdef DEBUG
69#define debug(msg) (void) fprintf(stderr, "%s\n", msg);
70#else
71#define debug(msg)
72#endif /* DEBUG */
73
74/*
75 * Hack to allow the keyserver to use AUTH_DES (for authenticated
76 * NIS+ calls, for example). The only functions that get called
77 * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
78 *
79 * The approach is to have the keyserver fill in pointers to local
80 * implementations of these functions, and to call those in key_call().
81 */
82
83cryptkeyres *(*__key_encryptsession_pk_LOCAL)() = 0;
84cryptkeyres *(*__key_decryptsession_pk_LOCAL)() = 0;
85des_block *(*__key_gendes_LOCAL)() = 0;
86
87static int key_call( u_long, xdrproc_t, void *, xdrproc_t, void *);
88
89int
90key_setsecret(secretkey)
91 const char *secretkey;
92{
93 keystatus status;
94
95 if (!key_call((u_long) KEY_SET, (xdrproc_t)xdr_keybuf,
96 (void *)secretkey,
98 return (-1);
99 }
100 if (status != KEY_SUCCESS) {
101 debug("set status is nonzero");
102 return (-1);
103 }
104 return (0);
105}
106
107
108/* key_secretkey_is_set() returns 1 if the keyserver has a secret key
109 * stored for the caller's effective uid; it returns 0 otherwise
110 *
111 * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't
112 * be using it, because it allows them to get the user's secret key.
113 */
114
115int
117{
118 struct key_netstres kres;
119
120 memset((void*)&kres, 0, sizeof (kres));
121 if (key_call((u_long) KEY_NET_GET, (xdrproc_t)xdr_void, NULL,
122 (xdrproc_t)xdr_key_netstres, &kres) &&
123 (kres.status == KEY_SUCCESS) &&
124 (kres.key_netstres_u.knet.st_priv_key[0] != 0)) {
125 /* avoid leaving secret key in memory */
126 memset(kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES);
127 return (1);
128 }
129 return (0);
130}
131
132int
133key_encryptsession_pk(remotename, remotekey, deskey)
134 char *remotename;
135 netobj *remotekey;
137{
138 cryptkeyarg2 arg;
139 cryptkeyres res;
140
141 arg.remotename = remotename;
142 arg.remotekey = *remotekey;
143 arg.deskey = *deskey;
144 if (!key_call((u_long)KEY_ENCRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg,
146 return (-1);
147 }
148 if (res.status != KEY_SUCCESS) {
149 debug("encrypt status is nonzero");
150 return (-1);
151 }
152 *deskey = res.cryptkeyres_u.deskey;
153 return (0);
154}
155
156int
157key_decryptsession_pk(remotename, remotekey, deskey)
158 char *remotename;
159 netobj *remotekey;
161{
162 cryptkeyarg2 arg;
163 cryptkeyres res;
164
165 arg.remotename = remotename;
166 arg.remotekey = *remotekey;
167 arg.deskey = *deskey;
168 if (!key_call((u_long)KEY_DECRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg,
170 return (-1);
171 }
172 if (res.status != KEY_SUCCESS) {
173 debug("decrypt status is nonzero");
174 return (-1);
175 }
176 *deskey = res.cryptkeyres_u.deskey;
177 return (0);
178}
179
180int
182 const char *remotename;
184{
185 cryptkeyarg arg;
186 cryptkeyres res;
187
188 arg.remotename = (char *) remotename;
189 arg.deskey = *deskey;
190 if (!key_call((u_long)KEY_ENCRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg,
192 return (-1);
193 }
194 if (res.status != KEY_SUCCESS) {
195 debug("encrypt status is nonzero");
196 return (-1);
197 }
198 *deskey = res.cryptkeyres_u.deskey;
199 return (0);
200}
201
202int
204 const char *remotename;
206{
207 cryptkeyarg arg;
208 cryptkeyres res;
209
210 arg.remotename = (char *) remotename;
211 arg.deskey = *deskey;
212 if (!key_call((u_long)KEY_DECRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg,
214 return (-1);
215 }
216 if (res.status != KEY_SUCCESS) {
217 debug("decrypt status is nonzero");
218 return (-1);
219 }
220 *deskey = res.cryptkeyres_u.deskey;
221 return (0);
222}
223
224int
226 des_block *key;
227{
228 if (!key_call((u_long)KEY_GEN, (xdrproc_t)xdr_void, NULL,
230 return (-1);
231 }
232 return (0);
233}
234
235int
237struct key_netstarg *arg;
238{
239 keystatus status;
240
241
242 if (!key_call((u_long) KEY_NET_PUT, (xdrproc_t)xdr_key_netstarg, arg,
244 return (-1);
245 }
246
247 if (status != KEY_SUCCESS) {
248 debug("key_setnet status is nonzero");
249 return (-1);
250 }
251 return (1);
252}
253
254
255int
257 char *pkey;
259{
260 cryptkeyres res;
261
262 if (!key_call((u_long) KEY_GET_CONV, (xdrproc_t)xdr_keybuf, pkey,
264 return (-1);
265 }
266 if (res.status != KEY_SUCCESS) {
267 debug("get_conv status is nonzero");
268 return (-1);
269 }
270 *deskey = res.cryptkeyres_u.deskey;
271 return (0);
272}
273
275 CLIENT *client; /* Client handle */
276 pid_t pid; /* process-id at moment of creation */
277 uid_t uid; /* user-id at last authorization */
278};
280
281static void
283{
284 struct key_call_private *kcp = (struct key_call_private *)vp;
285
286 if (kcp) {
287 if (kcp->client)
288 clnt_destroy(kcp->client);
289 free(kcp);
290 }
291}
292
293/*
294 * Keep the handle cached. This call may be made quite often.
295 */
296static CLIENT *
298int vers;
299{
300 void *localhandle;
301 struct netconfig *nconf;
302 struct netconfig *tpconf;
304 struct timeval wait_time;
305 struct utsname u;
306 int fd;
307 extern thread_key_t key_call_key;
308 extern mutex_t tsd_lock;
309
310#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */
311#define TOTAL_TRIES 5 /* Number of tries */
312
313 if (key_call_key == -1) {
315 if (key_call_key == -1)
316 thr_keycreate(&key_call_key, key_call_destroy);
318 }
319 kcp = (struct key_call_private *)thr_getspecific(key_call_key);
320 if (kcp == (struct key_call_private *)NULL) {
321 kcp = (struct key_call_private *)malloc(sizeof (*kcp));
322 if (kcp == (struct key_call_private *)NULL) {
323 return ((CLIENT *) NULL);
324 }
325 thr_setspecific(key_call_key, (void *) kcp);
326 kcp->client = NULL;
327 }
328
329 /* if pid has changed, destroy client and rebuild */
330 if (kcp->client != NULL && kcp->pid != getpid()) {
331 clnt_destroy(kcp->client);
332 kcp->client = NULL;
333 }
334
335 if (kcp->client != NULL) {
336 /* if uid has changed, build client handle again */
337 if (kcp->uid != geteuid()) {
338 kcp->uid = geteuid();
340 kcp->client->cl_auth =
341 authsys_create("", kcp->uid, 0, 0, NULL);
342 if (kcp->client->cl_auth == NULL) {
343 clnt_destroy(kcp->client);
344 kcp->client = NULL;
345 return ((CLIENT *) NULL);
346 }
347 }
348 /* Change the version number to the new one */
349 clnt_control(kcp->client, CLSET_VERS, (void *)&vers);
350 return (kcp->client);
351 }
352 if (!(localhandle = setnetconfig())) {
353 return ((CLIENT *) NULL);
354 }
355 tpconf = NULL;
356#if defined(__FreeBSD__)
357 if (uname(&u) == -1)
358#else
359#if defined(i386)
360 if (uname(&u) == -1)
361#elif defined(sparc)
362 if (uname(&u) == -1)
363#else
364#error Unknown architecture!
365#endif
366#endif
367 {
368 endnetconfig(localhandle);
369 return ((CLIENT *) NULL);
370 }
371 while ((nconf = getnetconfig(localhandle)) != NULL) {
372 if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
373 /*
374 * We use COTS_ORD here so that the caller can
375 * find out immediately if the server is dead.
376 */
377 if (nconf->nc_semantics == NC_TPI_COTS_ORD) {
378 kcp->client = clnt_tp_create(u.nodename,
379 KEY_PROG, vers, nconf);
380 if (kcp->client)
381 break;
382 } else {
383 tpconf = nconf;
384 }
385 }
386 }
387 if ((kcp->client == (CLIENT *) NULL) && (tpconf))
388 /* Now, try the CLTS or COTS loopback transport */
389 kcp->client = clnt_tp_create(u.nodename,
390 KEY_PROG, vers, tpconf);
391 endnetconfig(localhandle);
392
393 if (kcp->client == (CLIENT *) NULL) {
394 return ((CLIENT *) NULL);
395 }
396 kcp->uid = geteuid();
397 kcp->pid = getpid();
398 kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL);
399 if (kcp->client->cl_auth == NULL) {
400 clnt_destroy(kcp->client);
401 kcp->client = NULL;
402 return ((CLIENT *) NULL);
403 }
404
405 wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES;
406 wait_time.tv_usec = 0;
408 (char *)&wait_time);
409 if (clnt_control(kcp->client, CLGET_FD, (char *)&fd))
410 fcntl(fd, F_SETFD, 1); /* make it "close on exec" */
411
412 return (kcp->client);
413}
414
415/* returns 0 on failure, 1 on success */
416
417static int
418key_call(proc, xdr_arg, arg, xdr_rslt, rslt)
419 u_long proc;
420 xdrproc_t xdr_arg;
421 void *arg;
422 xdrproc_t xdr_rslt;
423 void *rslt;
424{
425 CLIENT *clnt;
426 struct timeval wait_time;
427
428 if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) {
429 cryptkeyres *res;
430 res = (*__key_encryptsession_pk_LOCAL)(geteuid(), arg);
431 *(cryptkeyres*)rslt = *res;
432 return (1);
433 } else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) {
434 cryptkeyres *res;
435 res = (*__key_decryptsession_pk_LOCAL)(geteuid(), arg);
436 *(cryptkeyres*)rslt = *res;
437 return (1);
438 } else if (proc == KEY_GEN && __key_gendes_LOCAL) {
439 des_block *res;
440 res = (*__key_gendes_LOCAL)(geteuid(), 0);
441 *(des_block*)rslt = *res;
442 return (1);
443 }
444
445 if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) ||
446 (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) ||
447 (proc == KEY_GET_CONV))
448 clnt = getkeyserv_handle(2); /* talk to version 2 */
449 else
450 clnt = getkeyserv_handle(1); /* talk to version 1 */
451
452 if (clnt == NULL) {
453 return (0);
454 }
455
456 wait_time.tv_sec = TOTAL_TIMEOUT;
457 wait_time.tv_usec = 0;
458
459 if (clnt_call(clnt, proc, xdr_arg, arg, xdr_rslt, rslt,
460 wait_time) == RPC_SUCCESS) {
461 return (1);
462 } else {
463 return (0);
464 }
465}
466#endif
bool_t xdr_void(void)
Definition: xdr.c:92
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int key_encryptsession_pk()
long uid_t
Definition: various.h:8
#define clnt_control(cl, rq, in)
Definition: clnt.h:241
#define CLGET_FD
Definition: clnt.h:249
#define CLSET_VERS
Definition: clnt.h:256
#define CLSET_RETRY_TIMEOUT
Definition: clnt.h:265
#define clnt_destroy(rh)
Definition: clnt.h:276
#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs)
Definition: clnt.h:202
CLIENT * clnt_tp_create(const char *hostname, const rpcprog_t prog, const rpcvers_t vers, const struct netconfig *nconf)
Definition: clnt_generic.c:282
@ RPC_SUCCESS
Definition: clnt_stat.h:22
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define auth_destroy(auth)
Definition: auth.h:259
#define authsys_create(c, i1, i2, i3, ip)
Definition: auth.h:323
#define NULL
Definition: types.h:112
DWORD pid_t
Definition: types.h:91
static void deskey(const unsigned char *key, short edf, ulong32 *keyout)
Definition: des.c:1285
unsigned long u_long
Definition: linux.h:269
int endnetconfig(void *handlep)
Definition: getnetconfig.c:373
struct netconfig * getnetconfig(void *handlep)
Definition: getnetconfig.c:253
void * setnetconfig()
Definition: getnetconfig.c:217
GLuint res
Definition: glext.h:9613
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
cryptkeyres *(* __key_encryptsession_pk_LOCAL)()=0
Definition: key_call.c:83
int key_setsecret(char *secretkey) const
Definition: key_call.c:90
#define debug(msg)
Definition: key_call.c:71
static int key_call(u_long, xdrproc_t, void *, xdrproc_t, void *)
Definition: key_call.c:418
#define TOTAL_TIMEOUT
int key_decryptsession(char *remotename, des_block *deskey) const
Definition: key_call.c:203
static void key_call_destroy(void *vp)
Definition: key_call.c:282
#define TOTAL_TRIES
cryptkeyres *(* __key_decryptsession_pk_LOCAL)()=0
Definition: key_call.c:84
static struct key_call_private * key_call_private_main
Definition: key_call.c:279
int key_get_conv(char *pkey, des_block *deskey)
Definition: key_call.c:256
des_block *(* __key_gendes_LOCAL)()=0
Definition: key_call.c:85
static CLIENT * getkeyserv_handle(int vers)
Definition: key_call.c:297
int key_secretkey_is_set(void)
Definition: key_call.c:116
int key_decryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey)
Definition: key_call.c:157
int key_setnet(struct key_netstarg *arg)
Definition: key_call.c:236
int key_gendes(des_block *key)
Definition: key_call.c:225
int key_encryptsession(char *remotename, des_block *deskey) const
Definition: key_call.c:181
bool_t xdr_key_netstres(register XDR *xdrs, key_netstres *objp)
Definition: key_prot_xdr.c:158
bool_t xdr_key_netstarg(register XDR *xdrs, key_netstarg *objp)
Definition: key_prot_xdr.c:145
bool_t xdr_cryptkeyres(register XDR *xdrs, cryptkeyres *objp)
Definition: key_prot_xdr.c:97
bool_t xdr_cryptkeyarg(register XDR *xdrs, cryptkeyarg *objp)
Definition: key_prot_xdr.c:73
bool_t xdr_keybuf(register XDR *xdrs, keybuf objp)
Definition: key_prot_xdr.c:55
bool_t xdr_cryptkeyarg2(register XDR *xdrs, cryptkeyarg2 *objp)
Definition: key_prot_xdr.c:84
bool_t xdr_keystatus(register XDR *xdrs, keystatus *objp)
Definition: key_prot_xdr.c:46
mutex_t tsd_lock
Definition: mt_misc.c:86
#define NC_LOOPBACK
Definition: netconfig.h:51
#define NC_TPI_COTS_ORD
Definition: netconfig.h:37
static HANDLE proc()
Definition: pdb.c:34
#define thr_setspecific(k, p)
Definition: reentrant.h:146
#define mutex_lock(m)
Definition: reentrant.h:128
#define thr_getspecific(k)
Definition: reentrant.h:147
#define mutex_unlock(m)
Definition: reentrant.h:129
#define thr_keycreate(k, d)
Definition: reentrant.h:144
#define thread_key_t
Definition: reentrant.h:124
bool_t xdr_des_block(XDR *xdrs, des_block *blkp)
Definition: rpc_prot.c:100
static int fd
Definition: io.c:51
#define memset(x, y, z)
Definition: compat.h:39
AUTH * cl_auth
Definition: clnt.h:122
CLIENT * client
Definition: key_call.c:275
Definition: copy.c:22
Definition: module.h:456
unsigned long nc_semantics
Definition: netconfig.h:17
char * nc_protofmly
Definition: netconfig.h:19
Definition: xdr.h:332
Definition: ps.c:97
unsigned long tv_sec
Definition: linux.h:1738
unsigned long tv_usec
Definition: linux.h:1739
EXPORT uid_t geteuid()
Definition: uid.c:37
void * arg
Definition: msvc.h:10
#define getpid
Definition: wintirpc.h:52
bool_t(* xdrproc_t)(XDR *,...)
Definition: xdr.h:144