ReactOS  0.4.13-dev-563-g0561610
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 
83 cryptkeyres *(*__key_encryptsession_pk_LOCAL)() = 0;
84 cryptkeyres *(*__key_decryptsession_pk_LOCAL)() = 0;
85 des_block *(*__key_gendes_LOCAL)() = 0;
86 
87 static int key_call( u_long, xdrproc_t, void *, xdrproc_t, void *);
88 
89 int
90 key_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 
115 int
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 
132 int
133 key_encryptsession_pk(remotename, remotekey, deskey)
134  char *remotename;
135  netobj *remotekey;
136  des_block *deskey;
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 
156 int
157 key_decryptsession_pk(remotename, remotekey, deskey)
158  char *remotename;
159  netobj *remotekey;
160  des_block *deskey;
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 
180 int
182  const char *remotename;
183  des_block *deskey;
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 
202 int
204  const char *remotename;
205  des_block *deskey;
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 
224 int
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 
235 int
237 struct 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 
255 int
257  char *pkey;
258  des_block *deskey;
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 
281 static 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  */
296 static CLIENT *
298 int 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();
339  auth_destroy(kcp->client->cl_auth);
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 
417 static int
418 key_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
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
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
bool_t xdr_key_netstarg(register XDR *xdrs, key_netstarg *objp)
Definition: key_prot_xdr.c:145
unsigned long u_long
Definition: linux.h:269
static void deskey(const unsigned char *key, short edf, ulong32 *keyout)
Definition: des.c:1285
cryptkeyres *(* __key_decryptsession_pk_LOCAL)()=0
Definition: key_call.c:84
#define CLSET_RETRY_TIMEOUT
Definition: clnt.h:265
#define thr_keycreate(k, d)
Definition: reentrant.h:144
#define CLGET_FD
Definition: clnt.h:249
static void key_call_destroy(void *vp)
Definition: key_call.c:282
#define thr_setspecific(k, p)
Definition: reentrant.h:146
int key_get_conv(char *pkey, des_block *deskey)
Definition: key_call.c:256
#define free
Definition: debug_ros.c:5
unsigned long tv_sec
Definition: linux.h:1738
CLIENT * client
Definition: key_call.c:275
static CLIENT * getkeyserv_handle(int vers)
Definition: key_call.c:297
int key_gendes(des_block *key)
Definition: key_call.c:225
des_block *(* __key_gendes_LOCAL)()=0
Definition: key_call.c:85
DWORD pid_t
Definition: types.h:91
static int fd
Definition: io.c:51
int key_encryptsession(char *remotename, des_block *deskey) const
Definition: key_call.c:181
void * arg
Definition: msvc.h:12
static HANDLE proc()
Definition: pdb.c:32
long uid_t
Definition: various.h:8
static int key_call(u_long, xdrproc_t, void *, xdrproc_t, void *)
Definition: key_call.c:418
#define mutex_lock(m)
Definition: reentrant.h:128
int key_setnet(struct key_netstarg *arg)
Definition: key_call.c:236
struct netconfig * getnetconfig(void *handlep)
Definition: getnetconfig.c:253
#define mutex_unlock(m)
Definition: reentrant.h:129
bool_t(* xdrproc_t)(XDR *,...)
Definition: xdr.h:144
#define TOTAL_TRIES
int key_encryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey)
Definition: key_call.c:133
#define thread_key_t
Definition: reentrant.h:124
bool_t xdr_des_block(XDR *xdrs, des_block *blkp)
Definition: rpc_prot.c:100
#define NC_TPI_COTS_ORD
Definition: netconfig.h:32
char * nc_protofmly
Definition: netconfig.h:14
Definition: xdr.h:332
smooth NULL
Definition: ftsmooth.c:416
unsigned long tv_usec
Definition: linux.h:1739
AUTH * cl_auth
Definition: clnt.h:122
int key_decryptsession(char *remotename, des_block *deskey) const
Definition: key_call.c:203
mutex_t tsd_lock
Definition: mt_misc.c:86
_CRTIMP int __cdecl getpid(void)
int key_setsecret(char *secretkey) const
Definition: key_call.c:90
cryptkeyres *(* __key_encryptsession_pk_LOCAL)()=0
Definition: key_call.c:83
#define thr_getspecific(k)
Definition: reentrant.h:147
#define TOTAL_TIMEOUT
HKEY key
Definition: reg.c:42
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
bool_t xdr_void(void)
Definition: xdr.c:92
int endnetconfig(void *handlep)
Definition: getnetconfig.c:373
#define clnt_control(cl, rq, in)
Definition: clnt.h:241
EXPORT uid_t geteuid()
Definition: uid.c:37
int key_secretkey_is_set(void)
Definition: key_call.c:116
#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs)
Definition: clnt.h:202
bool_t xdr_cryptkeyres(register XDR *xdrs, cryptkeyres *objp)
Definition: key_prot_xdr.c:97
#define CLSET_VERS
Definition: clnt.h:256
GLuint res
Definition: glext.h:9613
#define authsys_create(c, i1, i2, i3, ip)
Definition: auth.h:323
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define debug(msg)
Definition: key_call.c:71
CLIENT * clnt_tp_create(const char *hostname, const rpcprog_t prog, const rpcvers_t vers, const struct netconfig *nconf)
Definition: clnt_generic.c:282
#define malloc
Definition: debug_ros.c:4
bool_t xdr_cryptkeyarg(register XDR *xdrs, cryptkeyarg *objp)
Definition: key_prot_xdr.c:73
unsigned long nc_semantics
Definition: netconfig.h:12
int key_decryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey)
Definition: key_call.c:157
Definition: module.h:446
void * setnetconfig()
Definition: getnetconfig.c:217
static struct key_call_private * key_call_private_main
Definition: key_call.c:279
#define memset(x, y, z)
Definition: compat.h:39
static SERVICE_STATUS status
Definition: service.c:31
#define NC_LOOPBACK
Definition: netconfig.h:46
#define clnt_destroy(rh)
Definition: clnt.h:276
#define auth_destroy(auth)
Definition: auth.h:259
Definition: path.c:42
bool_t xdr_key_netstres(register XDR *xdrs, key_netstres *objp)
Definition: key_prot_xdr.c:158
Definition: ps.c:97
bool_t xdr_keybuf(register XDR *xdrs, keybuf objp)
Definition: key_prot_xdr.c:55