Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / keyserv / keyserv.c
1 /*
2  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3  * unrestricted use provided that this legend is included on all tape
4  * media and as a part of the software program in whole or part.  Users
5  * may copy or modify Sun RPC without charge, but are not authorized
6  * to license or distribute it to anyone else except as part of a product or
7  * program developed by the user.
8  * 
9  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12  * 
13  * Sun RPC is provided with no support and without any obligation on the
14  * part of Sun Microsystems, Inc. to assist in its use, correction,
15  * modification or enhancement.
16  * 
17  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19  * OR ANY PART THEREOF.
20  * 
21  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22  * or profits or other special, indirect and consequential damages, even if
23  * Sun has been advised of the possibility of such damages.
24  * 
25  * Sun Microsystems, Inc.
26  * 2550 Garcia Avenue
27  * Mountain View, California  94043
28  *
29  * @(#)keyserv.c        1.15    94/04/25 SMI
30  * $FreeBSD: src/usr.sbin/keyserv/keyserv.c,v 1.3.2.2 2001/07/19 10:58:22 roam Exp $
31  * $DragonFly: src/usr.sbin/keyserv/keyserv.c,v 1.2 2003/06/17 04:29:55 dillon Exp $
32  */
33
34 /*
35  * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
36  */
37
38 /*
39  * Keyserver
40  * Store secret keys per uid. Do public key encryption and decryption
41  * operations. Generate "random" keys.
42  * Do not talk to anything but a local root
43  * process on the local transport only
44  */
45
46 #include <err.h>
47 #include <pwd.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <sys/stat.h>
53 #include <sys/types.h>
54 #include <rpc/rpc.h>
55 #include <rpc/pmap_clnt.h>
56 #include <sys/param.h>
57 #include <sys/file.h>
58 #include <rpc/des_crypt.h>
59 #include <rpc/des.h>
60 #include <rpc/key_prot.h>
61 #include <rpcsvc/crypt.h>
62 #include "keyserv.h"
63
64 #ifndef NGROUPS
65 #define NGROUPS 16
66 #endif
67
68 #ifndef KEYSERVSOCK
69 #define KEYSERVSOCK "/var/run/keyservsock"
70 #endif
71
72 static void randomize __P(( des_block * ));
73 static void usage __P(( void ));
74 static int getrootkey __P(( des_block *, int ));
75 static int root_auth __P(( SVCXPRT *, struct svc_req * ));
76
77 #ifdef DEBUG
78 static int debugging = 1;
79 #else
80 static int debugging = 0;
81 #endif
82
83 static void keyprogram();
84 static des_block masterkey;
85 char *getenv();
86 static char ROOTKEY[] = "/etc/.rootkey";
87
88 /*
89  * Hack to allow the keyserver to use AUTH_DES (for authenticated
90  * NIS+ calls, for example).  The only functions that get called
91  * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
92  *
93  * The approach is to have the keyserver fill in pointers to local
94  * implementations of these functions, and to call those in key_call().
95  */
96
97 extern cryptkeyres *(*__key_encryptsession_pk_LOCAL)();
98 extern cryptkeyres *(*__key_decryptsession_pk_LOCAL)();
99 extern des_block *(*__key_gendes_LOCAL)();
100 extern int (*__des_crypt_LOCAL)();
101
102 cryptkeyres *key_encrypt_pk_2_svc_prog __P(( uid_t, cryptkeyarg2 * ));
103 cryptkeyres *key_decrypt_pk_2_svc_prog __P(( uid_t, cryptkeyarg2 * ));
104 des_block *key_gen_1_svc_prog __P(( void *, struct svc_req * ));
105
106 int
107 main(argc, argv)
108         int argc;
109         char *argv[];
110 {
111         int nflag = 0;
112         int c;
113         register SVCXPRT *transp;
114         int sock = RPC_ANYSOCK;
115         int warn = 0;
116         char *path = NULL;
117
118         __key_encryptsession_pk_LOCAL = &key_encrypt_pk_2_svc_prog;
119         __key_decryptsession_pk_LOCAL = &key_decrypt_pk_2_svc_prog;
120         __key_gendes_LOCAL = &key_gen_1_svc_prog;
121
122         while ((c = getopt(argc, argv, "ndDvp:")) != -1)
123                 switch (c) {
124                 case 'n':
125                         nflag++;
126                         break;
127                 case 'd':
128                         pk_nodefaultkeys();
129                         break;
130                 case 'D':
131                         debugging = 1;
132                         break;
133                 case 'v':
134                         warn = 1;
135                         break;
136                 case 'p':
137                         path = optarg;
138                         break;
139                 default:
140                         usage();
141                 }
142
143         load_des(warn, path);
144         __des_crypt_LOCAL = _my_crypt;
145         if (svc_auth_reg(AUTH_DES, _svcauth_des) == -1)
146                 errx(1, "failed to register AUTH_DES authenticator");
147
148         if (optind != argc) {
149                 usage();
150         }
151
152         /*
153          * Initialize
154          */
155         (void) umask(066);      /* paranoia */
156         if (geteuid() != 0)
157                 errx(1, "keyserv must be run as root");
158         setmodulus(HEXMODULUS);
159         getrootkey(&masterkey, nflag);
160
161
162         /* Create services. */
163
164         (void) pmap_unset(KEY_PROG, KEY_VERS);
165         (void) pmap_unset(KEY_PROG, KEY_VERS2);
166         unlink(KEYSERVSOCK);
167
168         transp = svcudp_create(RPC_ANYSOCK);
169         if (transp == NULL)
170                 errx(1, "cannot create udp service");
171         if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, IPPROTO_UDP))
172                 errx(1, "unable to register (KEY_PROG, KEY_VERS, udp)");
173         if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, IPPROTO_UDP))
174                 errx(1, "unable to register (KEY_PROG, KEY_VERS2, udp)");
175
176         transp = svctcp_create(RPC_ANYSOCK, 0, 0);
177         if (transp == NULL)
178                 errx(1, "cannot create tcp service");
179         if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, IPPROTO_TCP))
180                 errx(1, "unable to register (KEY_PROG, KEY_VERS, tcp)");
181         if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, IPPROTO_TCP))
182                 errx(1, "unable to register (KEY_PROG, KEY_VERS2, tcp)");
183
184         transp = svcunix_create(sock, 0, 0, KEYSERVSOCK);
185         chmod(KEYSERVSOCK, 0666);
186         if (transp == NULL)
187                 errx(1, "cannot create AF_UNIX service");
188         if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, 0))
189                 errx(1, "unable to register (KEY_PROG, KEY_VERS, unix)");
190         if (!svc_register(transp, KEY_PROG, KEY_VERS2, keyprogram, 0))
191                 errx(1, "unable to register (KEY_PROG, KEY_VERS2, unix)");
192         if (!svc_register(transp, CRYPT_PROG, CRYPT_VERS, crypt_prog_1, 0))
193                 errx(1, "unable to register (CRYPT_PROG, CRYPT_VERS, unix)");
194
195         if (!debugging) {
196                 daemon(0,0);
197         }
198
199         signal(SIGPIPE, SIG_IGN);
200
201         svc_run();
202         abort();
203         /* NOTREACHED */
204 }
205
206 /*
207  * In the event that we don't get a root password, we try to
208  * randomize the master key the best we can
209  */
210 static void
211 randomize(master)
212         des_block *master;
213 {
214         int i;
215         int seed;
216         struct timeval tv;
217         int shift;
218
219         seed = 0;
220         for (i = 0; i < 1024; i++) {
221                 (void) gettimeofday(&tv, (struct timezone *) NULL);
222                 shift = i % 8 * sizeof (int);
223                 seed ^= (tv.tv_usec << shift) | (tv.tv_usec >> (32 - shift));
224         }
225 #ifdef KEYSERV_RANDOM
226         srandom(seed);
227         master->key.low = random();
228         master->key.high = random();
229         srandom(seed);
230 #else
231         /* use stupid dangerous bad rand() */
232         srand(seed);
233         master->key.low = rand();
234         master->key.high = rand();
235         srand(seed);
236 #endif
237 }
238
239 /*
240  * Try to get root's secret key, by prompting if terminal is a tty, else trying
241  * from standard input.
242  * Returns 1 on success.
243  */
244 static int
245 getrootkey(master, prompt)
246         des_block *master;
247         int prompt;
248 {
249         char *passwd;
250         char name[MAXNETNAMELEN + 1];
251         char secret[HEXKEYBYTES];
252         key_netstarg netstore;
253         int fd;
254
255         if (!prompt) {
256                 /*
257                  * Read secret key out of ROOTKEY
258                  */
259                 fd = open(ROOTKEY, O_RDONLY, 0);
260                 if (fd < 0) {
261                         randomize(master);
262                         return (0);
263                 }
264                 if (read(fd, secret, HEXKEYBYTES) < HEXKEYBYTES) {
265                         warnx("the key read from %s was too short", ROOTKEY);
266                         (void) close(fd);
267                         return (0);
268                 }
269                 (void) close(fd);
270                 if (!getnetname(name)) {
271                     warnx(
272         "failed to generate host's netname when establishing root's key");
273                     return (0);
274                 }
275                 memcpy(netstore.st_priv_key, secret, HEXKEYBYTES);
276                 memset(netstore.st_pub_key, 0, HEXKEYBYTES);
277                 netstore.st_netname = name;
278                 if (pk_netput(0, &netstore) != KEY_SUCCESS) {
279                     warnx("could not set root's key and netname");
280                     return (0);
281                 }
282                 return (1);
283         }
284         /*
285          * Decrypt yellow pages publickey entry to get secret key
286          */
287         passwd = getpass("root password:");
288         passwd2des(passwd, (char *)master);
289         getnetname(name);
290         if (!getsecretkey(name, secret, passwd)) {
291                 warnx("can't find %s's secret key", name);
292                 return (0);
293         }
294         if (secret[0] == 0) {
295                 warnx("password does not decrypt secret key for %s", name);
296                 return (0);
297         }
298         (void) pk_setkey(0, secret);
299         /*
300          * Store it for future use in $ROOTKEY, if possible
301          */
302         fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0);
303         if (fd > 0) {
304                 char newline = '\n';
305
306                 write(fd, secret, strlen(secret));
307                 write(fd, &newline, sizeof (newline));
308                 close(fd);
309         }
310         return (1);
311 }
312
313 /*
314  * Procedures to implement RPC service
315  */
316 char *
317 strstatus(status)
318         keystatus status;
319 {
320         switch (status) {
321         case KEY_SUCCESS:
322                 return ("KEY_SUCCESS");
323         case KEY_NOSECRET:
324                 return ("KEY_NOSECRET");
325         case KEY_UNKNOWN:
326                 return ("KEY_UNKNOWN");
327         case KEY_SYSTEMERR:
328                 return ("KEY_SYSTEMERR");
329         default:
330                 return ("(bad result code)");
331         }
332 }
333
334 keystatus *
335 key_set_1_svc_prog(uid, key)
336         uid_t uid;
337         keybuf key;
338 {
339         static keystatus status;
340
341         if (debugging) {
342                 (void) fprintf(stderr, "set(%ld, %.*s) = ", uid,
343                                 (int) sizeof (keybuf), key);
344         }
345         status = pk_setkey(uid, key);
346         if (debugging) {
347                 (void) fprintf(stderr, "%s\n", strstatus(status));
348                 (void) fflush(stderr);
349         }
350         return (&status);
351 }
352
353 cryptkeyres *
354 key_encrypt_pk_2_svc_prog(uid, arg)
355         uid_t uid;
356         cryptkeyarg2 *arg;
357 {
358         static cryptkeyres res;
359
360         if (debugging) {
361                 (void) fprintf(stderr, "encrypt(%ld, %s, %08x%08x) = ", uid,
362                                 arg->remotename, arg->deskey.key.high,
363                                 arg->deskey.key.low);
364         }
365         res.cryptkeyres_u.deskey = arg->deskey;
366         res.status = pk_encrypt(uid, arg->remotename, &(arg->remotekey),
367                                 &res.cryptkeyres_u.deskey);
368         if (debugging) {
369                 if (res.status == KEY_SUCCESS) {
370                         (void) fprintf(stderr, "%08x%08x\n",
371                                         res.cryptkeyres_u.deskey.key.high,
372                                         res.cryptkeyres_u.deskey.key.low);
373                 } else {
374                         (void) fprintf(stderr, "%s\n", strstatus(res.status));
375                 }
376                 (void) fflush(stderr);
377         }
378         return (&res);
379 }
380
381 cryptkeyres *
382 key_decrypt_pk_2_svc_prog(uid, arg)
383         uid_t uid;
384         cryptkeyarg2 *arg;
385 {
386         static cryptkeyres res;
387
388         if (debugging) {
389                 (void) fprintf(stderr, "decrypt(%ld, %s, %08x%08x) = ", uid,
390                                 arg->remotename, arg->deskey.key.high,
391                                 arg->deskey.key.low);
392         }
393         res.cryptkeyres_u.deskey = arg->deskey;
394         res.status = pk_decrypt(uid, arg->remotename, &(arg->remotekey),
395                                 &res.cryptkeyres_u.deskey);
396         if (debugging) {
397                 if (res.status == KEY_SUCCESS) {
398                         (void) fprintf(stderr, "%08x%08x\n",
399                                         res.cryptkeyres_u.deskey.key.high,
400                                         res.cryptkeyres_u.deskey.key.low);
401                 } else {
402                         (void) fprintf(stderr, "%s\n", strstatus(res.status));
403                 }
404                 (void) fflush(stderr);
405         }
406         return (&res);
407 }
408
409 keystatus *
410 key_net_put_2_svc_prog(uid, arg)
411         uid_t uid;
412         key_netstarg *arg;
413 {
414         static keystatus status;
415
416         if (debugging) {
417                 (void) fprintf(stderr, "net_put(%s, %.*s, %.*s) = ",
418                         arg->st_netname, (int)sizeof (arg->st_pub_key),
419                         arg->st_pub_key, (int)sizeof (arg->st_priv_key),
420                         arg->st_priv_key);
421         };
422
423         status = pk_netput(uid, arg);
424
425         if (debugging) {
426                 (void) fprintf(stderr, "%s\n", strstatus(status));
427                 (void) fflush(stderr);
428         }
429
430         return (&status);
431 }
432
433 key_netstres *
434 key_net_get_2_svc_prog(uid, arg)
435         uid_t uid;
436         void *arg;
437 {
438         static key_netstres keynetname;
439
440         if (debugging)
441                 (void) fprintf(stderr, "net_get(%ld) = ", uid);
442
443         keynetname.status = pk_netget(uid, &keynetname.key_netstres_u.knet);
444         if (debugging) {
445                 if (keynetname.status == KEY_SUCCESS) {
446                         fprintf(stderr, "<%s, %.*s, %.*s>\n",
447                         keynetname.key_netstres_u.knet.st_netname,
448                         (int)sizeof (keynetname.key_netstres_u.knet.st_pub_key),
449                         keynetname.key_netstres_u.knet.st_pub_key,
450                         (int)sizeof (keynetname.key_netstres_u.knet.st_priv_key),
451                         keynetname.key_netstres_u.knet.st_priv_key);
452                 } else {
453                         (void) fprintf(stderr, "NOT FOUND\n");
454                 }
455                 (void) fflush(stderr);
456         }
457
458         return (&keynetname);
459
460 }
461
462 cryptkeyres *
463 key_get_conv_2_svc_prog(uid, arg)
464         uid_t uid;
465         keybuf arg;
466 {
467         static cryptkeyres  res;
468
469         if (debugging)
470                 (void) fprintf(stderr, "get_conv(%ld, %.*s) = ", uid,
471                         (int)sizeof (arg), arg);
472
473
474         res.status = pk_get_conv_key(uid, arg, &res);
475
476         if (debugging) {
477                 if (res.status == KEY_SUCCESS) {
478                         (void) fprintf(stderr, "%08x%08x\n",
479                                 res.cryptkeyres_u.deskey.key.high,
480                                 res.cryptkeyres_u.deskey.key.low);
481                 } else {
482                         (void) fprintf(stderr, "%s\n", strstatus(res.status));
483                 }
484                 (void) fflush(stderr);
485         }
486         return (&res);
487 }
488
489
490 cryptkeyres *
491 key_encrypt_1_svc_prog(uid, arg)
492         uid_t uid;
493         cryptkeyarg *arg;
494 {
495         static cryptkeyres res;
496
497         if (debugging) {
498                 (void) fprintf(stderr, "encrypt(%ld, %s, %08x%08x) = ", uid,
499                                 arg->remotename, arg->deskey.key.high,
500                                 arg->deskey.key.low);
501         }
502         res.cryptkeyres_u.deskey = arg->deskey;
503         res.status = pk_encrypt(uid, arg->remotename, NULL,
504                                 &res.cryptkeyres_u.deskey);
505         if (debugging) {
506                 if (res.status == KEY_SUCCESS) {
507                         (void) fprintf(stderr, "%08x%08x\n",
508                                         res.cryptkeyres_u.deskey.key.high,
509                                         res.cryptkeyres_u.deskey.key.low);
510                 } else {
511                         (void) fprintf(stderr, "%s\n", strstatus(res.status));
512                 }
513                 (void) fflush(stderr);
514         }
515         return (&res);
516 }
517
518 cryptkeyres *
519 key_decrypt_1_svc_prog(uid, arg)
520         uid_t uid;
521         cryptkeyarg *arg;
522 {
523         static cryptkeyres res;
524
525         if (debugging) {
526                 (void) fprintf(stderr, "decrypt(%ld, %s, %08x%08x) = ", uid,
527                                 arg->remotename, arg->deskey.key.high,
528                                 arg->deskey.key.low);
529         }
530         res.cryptkeyres_u.deskey = arg->deskey;
531         res.status = pk_decrypt(uid, arg->remotename, NULL,
532                                 &res.cryptkeyres_u.deskey);
533         if (debugging) {
534                 if (res.status == KEY_SUCCESS) {
535                         (void) fprintf(stderr, "%08x%08x\n",
536                                         res.cryptkeyres_u.deskey.key.high,
537                                         res.cryptkeyres_u.deskey.key.low);
538                 } else {
539                         (void) fprintf(stderr, "%s\n", strstatus(res.status));
540                 }
541                 (void) fflush(stderr);
542         }
543         return (&res);
544 }
545
546 /* ARGSUSED */
547 des_block *
548 key_gen_1_svc_prog(v, s)
549         void    *v;
550         struct svc_req  *s;
551 {
552         struct timeval time;
553         static des_block keygen;
554         static des_block key;
555
556         (void) gettimeofday(&time, (struct timezone *) NULL);
557         keygen.key.high += (time.tv_sec ^ time.tv_usec);
558         keygen.key.low += (time.tv_sec ^ time.tv_usec);
559         ecb_crypt((char *)&masterkey, (char *)&keygen, sizeof (keygen),
560                 DES_ENCRYPT | DES_HW);
561         key = keygen;
562         des_setparity((char *)&key);
563         if (debugging) {
564                 (void) fprintf(stderr, "gen() = %08x%08x\n", key.key.high,
565                                         key.key.low);
566                 (void) fflush(stderr);
567         }
568         return (&key);
569 }
570
571 getcredres *
572 key_getcred_1_svc_prog(uid, name)
573         uid_t uid;
574         netnamestr *name;
575 {
576         static getcredres res;
577         static u_int gids[NGROUPS];
578         struct unixcred *cred;
579
580         cred = &res.getcredres_u.cred;
581         cred->gids.gids_val = gids;
582         if (!netname2user(*name, (uid_t *) &cred->uid, (gid_t *) &cred->gid,
583                         (int *)&cred->gids.gids_len, (gid_t *)gids)) {
584                 res.status = KEY_UNKNOWN;
585         } else {
586                 res.status = KEY_SUCCESS;
587         }
588         if (debugging) {
589                 (void) fprintf(stderr, "getcred(%s) = ", *name);
590                 if (res.status == KEY_SUCCESS) {
591                         (void) fprintf(stderr, "uid=%d, gid=%d, grouplen=%d\n",
592                                 cred->uid, cred->gid, cred->gids.gids_len);
593                 } else {
594                         (void) fprintf(stderr, "%s\n", strstatus(res.status));
595                 }
596                 (void) fflush(stderr);
597         }
598         return (&res);
599 }
600
601 /*
602  * RPC boilerplate
603  */
604 static void
605 keyprogram(rqstp, transp)
606         struct svc_req *rqstp;
607         SVCXPRT *transp;
608 {
609         union {
610                 keybuf key_set_1_arg;
611                 cryptkeyarg key_encrypt_1_arg;
612                 cryptkeyarg key_decrypt_1_arg;
613                 netnamestr key_getcred_1_arg;
614                 cryptkeyarg key_encrypt_2_arg;
615                 cryptkeyarg key_decrypt_2_arg;
616                 netnamestr key_getcred_2_arg;
617                 cryptkeyarg2 key_encrypt_pk_2_arg;
618                 cryptkeyarg2 key_decrypt_pk_2_arg;
619                 key_netstarg key_net_put_2_arg;
620                 netobj  key_get_conv_2_arg;
621         } argument;
622         char *result;
623         bool_t(*xdr_argument)(), (*xdr_result)();
624         char *(*local) ();
625         uid_t uid = -1;
626         int check_auth;
627
628         switch (rqstp->rq_proc) {
629         case NULLPROC:
630                 svc_sendreply(transp, xdr_void, (char *)NULL);
631                 return;
632
633         case KEY_SET:
634                 xdr_argument = xdr_keybuf;
635                 xdr_result = xdr_int;
636                 local = (char *(*)()) key_set_1_svc_prog;
637                 check_auth = 1;
638                 break;
639
640         case KEY_ENCRYPT:
641                 xdr_argument = xdr_cryptkeyarg;
642                 xdr_result = xdr_cryptkeyres;
643                 local = (char *(*)()) key_encrypt_1_svc_prog;
644                 check_auth = 1;
645                 break;
646
647         case KEY_DECRYPT:
648                 xdr_argument = xdr_cryptkeyarg;
649                 xdr_result = xdr_cryptkeyres;
650                 local = (char *(*)()) key_decrypt_1_svc_prog;
651                 check_auth = 1;
652                 break;
653
654         case KEY_GEN:
655                 xdr_argument = xdr_void;
656                 xdr_result = xdr_des_block;
657                 local = (char *(*)()) key_gen_1_svc_prog;
658                 check_auth = 0;
659                 break;
660
661         case KEY_GETCRED:
662                 xdr_argument = xdr_netnamestr;
663                 xdr_result = xdr_getcredres;
664                 local = (char *(*)()) key_getcred_1_svc_prog;
665                 check_auth = 0;
666                 break;
667
668         case KEY_ENCRYPT_PK:
669                 xdr_argument = xdr_cryptkeyarg2;
670                 xdr_result = xdr_cryptkeyres;
671                 local = (char *(*)()) key_encrypt_pk_2_svc_prog;
672                 check_auth = 1;
673                 break;
674
675         case KEY_DECRYPT_PK:
676                 xdr_argument = xdr_cryptkeyarg2;
677                 xdr_result = xdr_cryptkeyres;
678                 local = (char *(*)()) key_decrypt_pk_2_svc_prog;
679                 check_auth = 1;
680                 break;
681
682
683         case KEY_NET_PUT:
684                 xdr_argument = xdr_key_netstarg;
685                 xdr_result = xdr_keystatus;
686                 local = (char *(*)()) key_net_put_2_svc_prog;
687                 check_auth = 1;
688                 break;
689
690         case KEY_NET_GET:
691                 xdr_argument = (xdrproc_t) xdr_void;
692                 xdr_result = xdr_key_netstres;
693                 local = (char *(*)()) key_net_get_2_svc_prog;
694                 check_auth = 1;
695                 break;
696
697         case KEY_GET_CONV:
698                 xdr_argument = (xdrproc_t) xdr_keybuf;
699                 xdr_result = xdr_cryptkeyres;
700                 local = (char *(*)()) key_get_conv_2_svc_prog;
701                 check_auth = 1;
702                 break;
703
704         default:
705                 svcerr_noproc(transp);
706                 return;
707         }
708         if (check_auth) {
709                 if (root_auth(transp, rqstp) == 0) {
710                         if (debugging) {
711                                 (void) fprintf(stderr,
712                                 "not local privileged process\n");
713                         }
714                         svcerr_weakauth(transp);
715                         return;
716                 }
717                 if (rqstp->rq_cred.oa_flavor != AUTH_SYS) {
718                         if (debugging) {
719                                 (void) fprintf(stderr,
720                                 "not unix authentication\n");
721                         }
722                         svcerr_weakauth(transp);
723                         return;
724                 }
725                 uid = ((struct authsys_parms *)rqstp->rq_clntcred)->aup_uid;
726         }
727
728         memset((char *) &argument, 0, sizeof (argument));
729         if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
730                 svcerr_decode(transp);
731                 return;
732         }
733         result = (*local) (uid, &argument);
734         if (!svc_sendreply(transp, xdr_result, (char *) result)) {
735                 if (debugging)
736                         (void) fprintf(stderr, "unable to reply\n");
737                 svcerr_systemerr(transp);
738         }
739         if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) {
740                 if (debugging)
741                         (void) fprintf(stderr,
742                         "unable to free arguments\n");
743                 exit(1);
744         }
745         return;
746 }
747
748 static int
749 root_auth(trans, rqstp)
750         SVCXPRT *trans;
751         struct svc_req *rqstp;
752 {
753         uid_t uid;
754         struct sockaddr_in *remote;
755
756         remote = svc_getcaller(trans);
757         if (remote->sin_family == AF_INET) {
758                 if (debugging)
759                         fprintf(stderr, "client didn't use AF_UNIX\n");
760                 return (0);
761         }
762
763         if (__rpc_get_local_uid(&uid, trans) < 0) {
764                 if (debugging)
765                         fprintf(stderr, "__rpc_get_local_uid failed\n");
766                 return (0);
767         }
768
769         if (debugging)
770                 fprintf(stderr, "local_uid  %ld\n", uid);
771         if (uid == 0)
772                 return (1);
773         if (rqstp->rq_cred.oa_flavor == AUTH_SYS) {
774                 if (((uid_t) ((struct authunix_parms *)
775                         rqstp->rq_clntcred)->aup_uid)
776                         == uid) {
777                         return (1);
778                 } else {
779                         if (debugging)
780                                 fprintf(stderr,
781                         "local_uid  %ld mismatches auth %ld\n", uid,
782 ((uid_t) ((struct authunix_parms *)rqstp->rq_clntcred)->aup_uid));
783                         return (0);
784                 }
785         } else {
786                 if (debugging)
787                         fprintf(stderr, "Not auth sys\n");
788                 return (0);
789         }
790 }
791
792 static void
793 usage()
794 {
795         (void) fprintf(stderr,
796                         "usage: keyserv [-n] [-D] [-d] [-v] [-p path]\n");
797         (void) fprintf(stderr, "-d disables the use of default keys\n");
798         exit(1);
799 }