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