diff options
Diffstat (limited to 'lib/librpc/secure_rpc')
44 files changed, 7088 insertions, 0 deletions
diff --git a/lib/librpc/secure_rpc/README b/lib/librpc/secure_rpc/README new file mode 100644 index 0000000..b8a860e --- /dev/null +++ b/lib/librpc/secure_rpc/README @@ -0,0 +1,92 @@ +Export restriction prohibit us from including DES encryption routines in RPCSRC +4.0. The main RPCSRC 4.0 hierarchy does not include DES Authentication, +however this directory contains the documentation and code used to build secure +rpc. THIS DISTRIBUTION OF SECURE RPC NEEDS EXTENSIVE WORK BEFORE IT CAN BE +USED. PLEASE READ THE PORTING GUIDLINES BELOW. + +HIERARCHY + +bin/ + + This directory contains chkey and keylogin. These are user programs + used to establish the credentials of an RPC user. + +demo/ + The 'whoami' service is found here. It can be used to test secure RPC. + rpcgen is used to build the client and server. + +des/ + + des_crypt.h defines the interfaces to cbc_crypt() and ecb_crypt(), + the DES routines used by DES Authentication. + des.h defines the desparams structure that is used internally by + these routines. Secure RPC expects it to be installed in + /usr/include/sys. + des_crypt.c defines the cbc_crypt() and ecb_crypt() routines. These + eventually call the routine _des_crypt(), which is *not* provided. + des_soft.c contains the des_setparity() routine. + +doc/ + + The document "nfs.secure.ms" is found here. It describes Secure + RPC and Secure NFS. + +keyserv/ + + This is an RPC based program that stores the private keys for + users that are using secure RPC. + +man/ + + Manual pages for the programs and library routines are found here. + +rpc/ + + The routines in this directory should be integrated with the + default rpc directory to make a single RPC library. The Makefile + found in this directory replaces the one in ../rpc. Note: the file + svc_auth.c in this directory replaces the one in ../rpc. Also, the + file ../rpc/rpc.h should be edited to include the file <rpc/des_auth.h> + (it presently is commented out). + +PORTING GUIDELINES + +You will need to provide a DES encryption routine. man/des_crypt.3 describes +the interface to ecb_crypt() and cbc_crypt() (secure RPC uses both modes). The +des/ directory has the "front-end" for these routines in the des_crypt.c file. + +Since public key authentication systems require a network global data lookup +facility, this implementation uses Sun's Yellow Pages. If your site does not +have Yellow Pages, you will have to modify the routines in rpc/publickey.c and +bin/chkey.c. One possible approach is to replace the YP calls with code to +read the file /etc/publickey; this file would presumably be shared by all +secure RPC sites via NFS or some equivalent file sharing facility. If you wish +to implement YP yourself, the RPCL (.x) protocol description file can be found +in ../rpcsvc/yp.x. + +The routines in rpc/ and keyserv/ assume that the file des/des_crypt.h +is installed in /usr/include (they include <des_crypt.h>). The file +des/des_crypt.c assumes that des.h is installed in /usr/include/sys (it +include <sys/des.h>). The des/ directory does not have a Makefile that +would install these header files, so you will either have to do this +by hand, or modify the routines to include the header files in a way suitable +for your site. + +While the programs in bin/ and keyserv/ can be built in place (assuming +the header files they include and the RPC library are available), the files +in rpc/ must be moved into ../rpc/, the main RPC library. The Makefile and +svc_auth.c found in rpc/ will replace those found in ../rpc/. You must also +edit ../rpc/rpc.h to include <rpc/des_auth.h>. + +OPERATION + +Please read the documentation and manual pages for information on how to +administer secure RPC. + +In the demo/ directory you'll find the 'whoami' service. This service uses DES +Authentication, and can be used to check out secure RPC. The client program, +'rme' takes a host as an argument. This host must be running the keyserv +daemon and the 'whoami_svc' server. The service returns the identity of the +client-user as known to the system on which the server is running. This +information is only returned, however, if the client request has proper DES +credentials. diff --git a/lib/librpc/secure_rpc/bin/Makefile b/lib/librpc/secure_rpc/bin/Makefile new file mode 100644 index 0000000..9d08018 --- /dev/null +++ b/lib/librpc/secure_rpc/bin/Makefile @@ -0,0 +1,50 @@ +# +# @(#)Makefile 2.1 88/08/10 4.0 RPCSRC +# +DESTDIR= +CFLAGS= -O +RPCLIB= -lrpclib + +# C programs that live in the current directory and need explicit make lines. +# (make depend has special rules for these files) +# +NSTD= chkey keylogin + +all: ${NSTD} + +chkey: chkey.c + ${CC} ${CFLAGS} -o chkey chkey.c -lrpcsvc -lmp ${RPCLIB} + +keylogin: keylogin.c + ${CC} ${CFLAGS} -o keylogin keylogin.c -lrpcsvc ${RPCLIB} + +install: + -for i in ${NSTD}; do \ + (install -s $$i ${DESTDIR}/usr/bin/$$i); done + +clean: + rm -f a.out core *.s *.o + rm -f ${NSTD} + +depend: + for i in ${NSTD}; do \ + cc -M ${INCPATH} $$i.c | sed 's/\.o//' | \ + awk ' { if ($$1 != prev) \ + { if (rec != "") print rec; rec = $$0; prev = $$1; } \ + else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ + else rec = rec " " $$2 } } \ + END { print rec } ' >> makedep; done + echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep + echo '$$r makedep' >>eddep + echo 'w' >>eddep + cp Makefile Makefile.bak + ed - Makefile < eddep + rm eddep makedep + echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile + echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile + echo '# see make depend above' >> Makefile + +# Files listed in ${NSTD} have explicit make lines given below. + +# DO NOT DELETE THIS LINE -- make depend uses it + diff --git a/lib/librpc/secure_rpc/bin/chkey.c b/lib/librpc/secure_rpc/bin/chkey.c new file mode 100644 index 0000000..eefb34e --- /dev/null +++ b/lib/librpc/secure_rpc/bin/chkey.c @@ -0,0 +1,302 @@ +#ifndef lint +static char sccsid[] = "@(#)chkey.c 2.3 88/08/15 4.0 RPCSRC"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ + +/* + * Command to change one's public key in the public key database + */ +#include <stdio.h> +#include <rpc/rpc.h> +#include <rpc/key_prot.h> +#include <rpcsvc/ypclnt.h> +#include <sys/file.h> +#include <pwd.h> +#include <mp.h> + +extern char *getpass(); +extern char *index(); +extern char *crypt(); +extern char *sprintf(); +extern long random(); + +static char PKMAP[] = "publickey.byname"; +static char *domain; +struct passwd *ypgetpwuid(); + +main(argc, argv) + int argc; + char **argv; +{ + char name[MAXNETNAMELEN+1]; + char public[HEXKEYBYTES + 1]; + char secret[HEXKEYBYTES + 1]; + char crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE + 1]; + char crypt2[HEXKEYBYTES + KEYCHECKSUMSIZE + 1]; + int status; + char *pass; + struct passwd *pw; + char *master; + int euid; + int fd; + int force; + char *self; + + self = argv[0]; + force = 0; + for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) { + if (argv[0][2] != 0) { + usage(self); + } + switch (argv[0][1]) { + case 'f': + force = 1; + break; + default: + usage(self); + } + } + if (argc != 0) { + usage(self); + } + + (void)yp_get_default_domain(&domain); + if (yp_master(domain, PKMAP, &master) != 0) { + (void)fprintf(stderr, + "can't find master of publickey database\n"); + exit(1); + } + + getnetname(name); + (void)printf("Generating new key for %s.\n", name); + + euid = geteuid(); + if (euid != 0) { + pw = ypgetpwuid(euid); + if (pw == NULL) { + (void)fprintf(stderr, + "No yp password found: can't change key.\n"); + exit(1); + } + } else { + pw = getpwuid(0); + if (pw == NULL) { + (void)fprintf(stderr, + "No password found: can't change key.\n"); + exit(1); + } + } + pass = getpass("Password:"); + if (!force) { + if (strcmp(crypt(pass, pw->pw_passwd), pw->pw_passwd) != 0) { + (void)fprintf(stderr, "Invalid password.\n"); + exit(1); + } + } + + genkeys(public, secret, pass); + + bcopy(secret, crypt1, HEXKEYBYTES); + bcopy(secret, crypt1 + HEXKEYBYTES, KEYCHECKSUMSIZE); + crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0; + xencrypt(crypt1, pass); + + if (force) { + bcopy(crypt1, crypt2, HEXKEYBYTES + KEYCHECKSUMSIZE + 1); + xdecrypt(crypt2, getpass("Retype password:")); + if (bcmp(crypt2, crypt2 + HEXKEYBYTES, KEYCHECKSUMSIZE) != 0 || + bcmp(crypt2, secret, HEXKEYBYTES) != 0) { + (void)fprintf(stderr, "Password incorrect.\n"); + exit(1); + } + } + + (void)printf("Sending key change request to %s...\n", master); + status = setpublicmap(name, public, crypt1); + if (status != 0) { + (void)printf("%s: unable to update yp database (%u): %s\n", + self, status, yperr_string(status)); + (void)printf("Perhaps %s is down?\n", master); + exit(1); + } + (void)printf("Done.\n"); + + if (key_setsecret(secret) < 0) { + (void)printf("Unable to login with new secret key.\n"); + exit(1); + } +} + +usage(name) + char *name; +{ + (void)fprintf(stderr, "usage: %s [-f]\n", name); + exit(1); +} + + +/* + * Generate a seed + */ +getseed(seed, seedsize, pass) + char *seed; + int seedsize; + unsigned char *pass; +{ + int i; + int rseed; + struct timeval tv; + + (void)gettimeofday(&tv, (struct timezone *)NULL); + rseed = tv.tv_sec + tv.tv_usec; + for (i = 0; i < 8; i++) { + rseed ^= (rseed << 8) | pass[i]; + } + srandom(rseed); + + for (i = 0; i < seedsize; i++) { + seed[i] = (random() & 0xff) ^ pass[i % 8]; + } +} + + +/* + * Generate a random public/secret key pair + */ +genkeys(public, secret, pass) + char *public; + char *secret; + char *pass; +{ + int i; + +#define BASEBITS (8*sizeof(short) - 1) +#define BASE (1 << BASEBITS) + + MINT *pk = itom(0); + MINT *sk = itom(0); + MINT *tmp; + MINT *base = itom(BASE); + MINT *root = itom(PROOT); + MINT *modulus = xtom(HEXMODULUS); + short r; + unsigned short seed[KEYSIZE/BASEBITS + 1]; + char *xkey; + + getseed((char *)seed, sizeof(seed), (unsigned char *)pass); + for (i = 0; i < KEYSIZE/BASEBITS + 1; i++) { + r = seed[i] % BASE; + tmp = itom(r); + mult(sk, base, sk); + madd(sk, tmp, sk); + mfree(tmp); + } + tmp = itom(0); + mdiv(sk, modulus, tmp, sk); + mfree(tmp); + pow(root, sk, modulus, pk); + xkey = mtox(sk); + adjust(secret, xkey); + xkey = mtox(pk); + adjust(public, xkey); + mfree(sk); + mfree(base); + mfree(pk); + mfree(root); + mfree(modulus); +} + +/* + * Adjust the input key so that it is 0-filled on the left + */ +adjust(keyout, keyin) + char keyout[HEXKEYBYTES+1]; + char *keyin; +{ + char *p; + char *s; + + for (p = keyin; *p; p++) + ; + for (s = keyout + HEXKEYBYTES; p >= keyin; p--, s--) { + *s = *p; + } + while (s >= keyout) { + *s-- = '0'; + } +} + +/* + * Set the entry in the public key map + */ +setpublicmap(name, public, secret) + char *name; + char *public; + char *secret; +{ + char pkent[1024]; + u_int rslt; + + (void)sprintf(pkent,"%s:%s", public, secret); + rslt = yp_update(domain, PKMAP, YPOP_STORE, + name, strlen(name), pkent, strlen(pkent)); + return (rslt); +} + +struct passwd * +ypgetpwuid(uid) + int uid; +{ + char uidstr[10]; + char *val; + int vallen; + static struct passwd pw; + char *p; + + (void)sprintf(uidstr, "%d", uid); + if (yp_match(domain, "passwd.byuid", uidstr, strlen(uidstr), + &val, &vallen) != 0) { + return (NULL); + } + p = index(val, ':'); + if (p == NULL) { + return (NULL); + } + pw.pw_passwd = p + 1; + p = index(pw.pw_passwd, ':'); + if (p == NULL) { + return (NULL); + } + *p = 0; + return (&pw); +} diff --git a/lib/librpc/secure_rpc/bin/keylogin.c b/lib/librpc/secure_rpc/bin/keylogin.c new file mode 100644 index 0000000..0643f07 --- /dev/null +++ b/lib/librpc/secure_rpc/bin/keylogin.c @@ -0,0 +1,66 @@ +#ifndef lint +static char sccsid[] = "@(#)keylogin.c 2.2 88/08/10 4.0 RPCSRC"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ + +/* + * Set secret key on local machine + */ +#include <stdio.h> +#include <rpc/rpc.h> +#include <rpc/key_prot.h> + +main(argc,argv) + int argc; + char *argv[]; +{ + char fullname[MAXNETNAMELEN + 1]; + char secret[HEXKEYBYTES + 1]; + char *getpass(); + + getnetname(fullname); + if (! getsecretkey(fullname, secret, getpass("Password:"))) { + fprintf(stderr, "Can't find %s's secret key\n", fullname); + exit(1); + } + if (secret[0] == 0) { + fprintf(stderr, "Password incorrect for %s\n", fullname); + exit(1); + } + if (key_setsecret(secret) < 0) { + fprintf(stderr, "Could not set %s's secret key\n", fullname); + fprintf(stderr, "Maybe the keyserver is down?\n"); + exit(1); + } + exit(0); +} diff --git a/lib/librpc/secure_rpc/demo/Makefile b/lib/librpc/secure_rpc/demo/Makefile new file mode 100644 index 0000000..f1e62a7 --- /dev/null +++ b/lib/librpc/secure_rpc/demo/Makefile @@ -0,0 +1,28 @@ +# +# @(#)Makefile 2.2 88/08/15 4.0 RPCSRC +# +BIN = whoami_svc rme +GEN = whoami_clnt.c whoami_svc.c whoami_xdr.c whoami.h +LIB = -lrpclib +#use this line on SunOS or NFSSRC-based systems. +#LIB = -lrpcsvc +RPCCOM = rpcgen + +all: $(BIN) + +$(GEN): whoami.x + $(RPCCOM) whoami.x + +whoami_svc: whoami_proc.o whoami_svc.o whoami_xdr.o + $(CC) -o $@ whoami_proc.o whoami_svc.o whoami_xdr.o $(LIB) + +rme: rme.o whoami_clnt.o whoami_xdr.o + $(CC) -o $@ rme.o whoami_clnt.o whoami_xdr.o $(LIB) + +rme.o: rme.c whoami.h + +whoami_proc.o: whoami_proc.c whoami.h + +clean cleanup: + rm -f $(GEN) *.o $(BIN) + diff --git a/lib/librpc/secure_rpc/demo/rme.c b/lib/librpc/secure_rpc/demo/rme.c new file mode 100644 index 0000000..773eafa --- /dev/null +++ b/lib/librpc/secure_rpc/demo/rme.c @@ -0,0 +1,96 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rme.c 2.3 88/09/09 4.0 RPCSRC"; +#endif +/* + * rme.c: secure identity verifier and reporter: client side + */ +#include <rpc/rpc.h> +#include <stdio.h> +#include "whoami.h" + +/* + * Before running this program, the user must have a key in the publickey + * database, and must have logged in with a password (or used keylogin). + * The user's machine and the server's machine must both be running keyserv. + */ + +main(argc, argv) + int argc; + char *argv[]; +{ + CLIENT *cl; + char *server; + remote_identity *remote_me; + name *servername; + void *nullp; + + if (argc != 2) { + fprintf(stderr, "usage: %s host\n", argv[0]); + exit(1); + } + + /* + * Remember what our command line argument refers to + */ + server = argv[1]; + + /* + * Create client "handle" used for calling WHOAMI on the + * server designated on the command line. We tell the rpc package + * to use the "udp" protocol when contacting the server. + */ + cl = clnt_create(server, WHOAMI, WHOAMI_V1, "udp"); + if (cl == NULL) { + /* + * Couldn't establish connection with server. + * Print error message and die. + */ + clnt_pcreateerror(server); + exit(1); + } + /* + * Get network identifier for server machine. + */ + servername = whoami_whoru_1(nullp, cl); + if (servername == NULL) + { + fprintf(stderr, "Trouble communicating with %s\n", + clnt_sperror(cl, server)); + exit(1); + } + else if (*servername[0] == '\0') + { + fprintf(stderr, "Could not determine netname of WHOAMI server.\n"); + exit(1); + } + printf("Server's netname is: %s\n", *servername); + + /* + * A wide window and no synchronization is used. Client and server + * clock must be with five minutes of each other. + */ + if ((cl->cl_auth = authdes_create(*servername, 300, NULL, NULL)) == NULL) + { + fprintf(stderr, "Could not establish DES credentials of netname %s\n", + servername); + exit(1); + } + + /* + * Find out who I am, in the server's point of view. + */ + remote_me = whoami_iask_1(nullp, cl); + if (remote_me == NULL) + { + fprintf(stderr, "Trouble getting my identity from %s\n", + clnt_sperror(cl, server)); + exit(1); + } + /* + * Print out my identity. + */ + printf("My remote user name: %s\n", remote_me->remote_username); + printf("My remote real name: %s\n", remote_me->remote_realname); + + exit(0); +} diff --git a/lib/librpc/secure_rpc/demo/whoami.x b/lib/librpc/secure_rpc/demo/whoami.x new file mode 100644 index 0000000..041cd0a --- /dev/null +++ b/lib/librpc/secure_rpc/demo/whoami.x @@ -0,0 +1,33 @@ +/* @(#)whoami.x 2.2 88/08/22 4.0 RPCSRC */ + +const WHOAMI_NGROUPS = 16; + +typedef string name<MAXNETNAMELEN>; + +struct remote_identity { + bool authenticated; /* TRUE if the server authenticates us */ + name remote_username; /* login name */ + name remote_realname; /* gcos-field name (long name) */ + int uid; + int gid; + int gids<WHOAMI_NGROUPS>; +}; + +program WHOAMI { + version WHOAMI_V1 { + /* + * Report on the server's notion of the client's identity. + * Will respond to AUTH_DES only. + */ + remote_identity + WHOAMI_IASK(void) = 1; + /* + * Return server's netname. AUTH_NONE is okay. + * This routine allows this server to be started under any uid, + * and the client can ask it its netname for use in authdes_create(). + */ + name + WHOAMI_WHORU(void) = 2; + + } = 1; +} = 80955; diff --git a/lib/librpc/secure_rpc/demo/whoami_proc.c b/lib/librpc/secure_rpc/demo/whoami_proc.c new file mode 100644 index 0000000..231d322 --- /dev/null +++ b/lib/librpc/secure_rpc/demo/whoami_proc.c @@ -0,0 +1,95 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)whoami_proc.c 2.3 89/07/11 4.0 RPCSRC"; +#endif +/* + * whoami_proc.c: secure identity verifier and reporter: server proc + */ +#include <sys/param.h> +#include <rpc/rpc.h> +#include <rpc/key_prot.h> +#include <pwd.h> +#include "whoami.h" + +extern char *strcpy(); + +/* + * Report on the server's notion of the client's identity. + */ +remote_identity * +whoami_iask_1(nullarg, rqstp) + void *nullarg; + struct svc_req *rqstp; +{ +static remote_identity whoisthem; +static char username[MAXNETNAMELEN+1]; +static char realname[MAXNETNAMELEN+1]; /* really gecos field */ +static int grouplist[NGROUPS]; + char publickey[HEXKEYBYTES+1]; + + struct authdes_cred *des_cred; + struct passwd *pwdent; + + switch (rqstp->rq_cred.oa_flavor) + { + case AUTH_DES: + whoisthem.remote_username = username; + whoisthem.remote_realname = realname; + whoisthem.gids.gids_val = grouplist; + des_cred = (struct authdes_cred *) rqstp->rq_clntcred; + /* + * Check to see if the netname being used is in the public key + * database (if not, reject this (potential) imposter). + */ + if (! getpublickey(des_cred->adc_fullname.name, publickey)) + { + svcerr_weakauth(rqstp->rq_xprt); + return(NULL); + } + /* + * Get the info that the client wants. + */ + if (! netname2user(des_cred->adc_fullname.name, &whoisthem.uid, + &whoisthem.gid, &whoisthem.gids.gids_len, + whoisthem.gids.gids_val)) + { /* netname not found */ + whoisthem.authenticated = FALSE; + strcpy(whoisthem.remote_username, "nobody"); + strcpy(whoisthem.remote_realname, "INTERLOPER!"); + whoisthem.uid = -2; + whoisthem.gid = -2; + whoisthem.gids.gids_len = 0; + return(&whoisthem); + } + /* else we found the netname */ + whoisthem.authenticated = TRUE; + pwdent = getpwuid(whoisthem.uid); + strcpy(whoisthem.remote_username, pwdent->pw_name); + strcpy(whoisthem.remote_realname, pwdent->pw_gecos); + return(&whoisthem); + break; + case AUTH_UNIX: + case AUTH_NULL: + default: + svcerr_weakauth(rqstp->rq_xprt); + return(NULL); + } +} + +/* + * Return server's netname. AUTH_NONE is valid. + * This routine allows this server to be started under any uid, + * and the client can ask us our netname for use in authdes_create(). + */ +name * +whoami_whoru_1(nullarg, rqstp) + void *nullarg; + struct svc_req *rqstp; +{ +static name whoru; +static char servername[MAXNETNAMELEN+1]; + + whoru = servername; + getnetname(servername); + + return(&whoru); +} diff --git a/lib/librpc/secure_rpc/des/des.h b/lib/librpc/secure_rpc/des/des.h new file mode 100644 index 0000000..c237f23 --- /dev/null +++ b/lib/librpc/secure_rpc/des/des.h @@ -0,0 +1,68 @@ +/* @(#)des.h 2.2 88/08/10 4.0 RPCSRC; from 2.7 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Generic DES driver interface + * Keep this file hardware independent! + * Copyright (c) 1986 by Sun Microsystems, Inc. + */ + +#define DES_MAXLEN 65536 /* maximum # of bytes to encrypt */ +#define DES_QUICKLEN 16 /* maximum # of bytes to encrypt quickly */ + +enum desdir { ENCRYPT, DECRYPT }; +enum desmode { CBC, ECB }; + +/* + * parameters to ioctl call + */ +struct desparams { + u_char des_key[8]; /* key (with low bit parity) */ + enum desdir des_dir; /* direction */ + enum desmode des_mode; /* mode */ + u_char des_ivec[8]; /* input vector */ + unsigned des_len; /* number of bytes to crypt */ + union { + u_char UDES_data[DES_QUICKLEN]; + u_char *UDES_buf; + } UDES; +# define des_data UDES.UDES_data /* direct data here if quick */ +# define des_buf UDES.UDES_buf /* otherwise, pointer to data */ +}; + +/* + * Encrypt an arbitrary sized buffer + */ +#define DESIOCBLOCK _IOWR(d, 6, struct desparams) + +/* + * Encrypt of small amount of data, quickly + */ +#define DESIOCQUICK _IOWR(d, 7, struct desparams) + diff --git a/lib/librpc/secure_rpc/des/des_crypt.c b/lib/librpc/secure_rpc/des/des_crypt.c new file mode 100644 index 0000000..57a9e71 --- /dev/null +++ b/lib/librpc/secure_rpc/des/des_crypt.c @@ -0,0 +1,138 @@ +#ifndef lint +static char sccsid[] = "@(#)des_crypt.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * des_crypt.c, DES encryption library routines + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +#include <sys/types.h> +#include <des_crypt.h> +#include <sys/des.h> + +/* + * To see if chip is installed + */ +#define UNOPENED (-2) +static int g_desfd = UNOPENED; + + +/* + * Copy 8 bytes + */ +#define COPY8(src, dst) { \ + register char *a = (char *) dst; \ + register char *b = (char *) src; \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ +} + +/* + * Copy multiple of 8 bytes + */ +#define DESCOPY(src, dst, len) { \ + register char *a = (char *) dst; \ + register char *b = (char *) src; \ + register int i; \ + for (i = (int) len; i > 0; i -= 8) { \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ + } \ +} + +/* + * CBC mode encryption + */ +cbc_crypt(key, buf, len, mode, ivec) + char *key; + char *buf; + unsigned len; + unsigned mode; + char *ivec; +{ + int err; + struct desparams dp; + + dp.des_mode = CBC; + COPY8(ivec, dp.des_ivec); + err = common_crypt(key, buf, len, mode, &dp); + COPY8(dp.des_ivec, ivec); + return(err); +} + + +/* + * ECB mode encryption + */ +ecb_crypt(key, buf, len, mode) + char *key; + char *buf; + unsigned len; + unsigned mode; +{ + struct desparams dp; + + dp.des_mode = ECB; + return(common_crypt(key, buf, len, mode, &dp)); +} + + + +/* + * Common code to cbc_crypt() & ecb_crypt() + */ +static +common_crypt(key, buf, len, mode, desp) + char *key; + char *buf; + register unsigned len; + unsigned mode; + register struct desparams *desp; +{ + register int desdev; + register int res; + + if ((len % 8) != 0 || len > DES_MAXDATA) { + return(DESERR_BADPARAM); + } + desp->des_dir = + ((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT; + + desdev = mode & DES_DEVMASK; + COPY8(key, desp->des_key); + /* + * software + */ + if (!_des_crypt(buf, len, desp)) { + return (DESERR_HWERROR); + } + return(desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE); +} diff --git a/lib/librpc/secure_rpc/des/des_crypt.h b/lib/librpc/secure_rpc/des/des_crypt.h new file mode 100644 index 0000000..d21d095 --- /dev/null +++ b/lib/librpc/secure_rpc/des/des_crypt.h @@ -0,0 +1,101 @@ +/* + * @(#)des_crypt.h 2.1 88/08/11 4.0 RPCSRC; from 1.4 88/02/08 (C) 1986 SMI + * + * des_crypt.h, des library routine interface + * Copyright (C) 1986, Sun Microsystems, Inc. + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#define DES_MAXDATA 8192 /* max bytes encrypted in one call */ +#define DES_DIRMASK (1 << 0) +#define DES_ENCRYPT (0*DES_DIRMASK) /* Encrypt */ +#define DES_DECRYPT (1*DES_DIRMASK) /* Decrypt */ + + +#define DES_DEVMASK (1 << 1) +#define DES_HW (0*DES_DEVMASK) /* Use hardware device */ +#define DES_SW (1*DES_DEVMASK) /* Use software device */ + + +#define DESERR_NONE 0 /* succeeded */ +#define DESERR_NOHWDEVICE 1 /* succeeded, but hw device not available */ +#define DESERR_HWERROR 2 /* failed, hardware/driver error */ +#define DESERR_BADPARAM 3 /* failed, bad parameter to call */ + +#define DES_FAILED(err) \ + ((err) > DESERR_NOHWDEVICE) + +/* + * cbc_crypt() + * ecb_crypt() + * + * Encrypt (or decrypt) len bytes of a buffer buf. + * The length must be a multiple of eight. + * The key should have odd parity in the low bit of each byte. + * ivec is the input vector, and is updated to the new one (cbc only). + * The mode is created by oring together the appropriate parameters. + * DESERR_NOHWDEVICE is returned if DES_HW was specified but + * there was no hardware to do it on (the data will still be + * encrypted though, in software). + */ + + +/* + * Cipher Block Chaining mode + */ +cbc_crypt(/* key, buf, len, mode, ivec */); /* + char *key; + char *buf; + unsigned len; + unsigned mode; + char *ivec; +*/ + + +/* + * Electronic Code Book mode + */ +ecb_crypt(/* key, buf, len, mode */); /* + char *key; + char *buf; + unsigned len; + unsigned mode; +*/ + + +#ifndef KERNEL +/* + * Set des parity for a key. + * DES parity is odd and in the low bit of each byte + */ +void +des_setparity(/* key */); /* + char *key; +*/ +#endif diff --git a/lib/librpc/secure_rpc/des/des_soft.c b/lib/librpc/secure_rpc/des/des_soft.c new file mode 100644 index 0000000..01dd7f2 --- /dev/null +++ b/lib/librpc/secure_rpc/des/des_soft.c @@ -0,0 +1,67 @@ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)des_soft.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Table giving odd parity in the low bit for ASCII characters + */ +static char partab[128] = { + 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, + 0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e, + 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, + 0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f, + 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, + 0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f, + 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, + 0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e, + 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, + 0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f, + 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, + 0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e, + 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, + 0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e, + 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, + 0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f, +}; + +/* + * Add odd parity to low bit of 8 byte key + */ +void +des_setparity(p) + char *p; +{ + int i; + + for (i = 0; i < 8; i++) { + *p = partab[*p & 0x7f]; + p++; + } +} diff --git a/lib/librpc/secure_rpc/doc/Makefile b/lib/librpc/secure_rpc/doc/Makefile new file mode 100644 index 0000000..3cfbe9e --- /dev/null +++ b/lib/librpc/secure_rpc/doc/Makefile @@ -0,0 +1,40 @@ +# +# @(#)Makefile 2.1 88/08/10 4.0 RPCSRC +# +# +TROFF= ditroff +TOPTS= -t +NROFF= nroff +NOPTS= +PIC= pic +TBL= tbl +EQN= eqn + +SRC= nfs.secure.ms + +all default: all.nroff + +install: all.nroff + @echo "Nothing installed." + +all.nroff: ${SRC} + ${TBL} ${SRC} | ${EQN} | ${NROFF} ${NOPTS} -ms >all.nroff + +all.troff: ${SRC} + ${TBL} ${SRC} | ${PIC} | ${EQN} | ${TROFF} ${TOPTS} -ms >all.troff + +# + +nfs.secure.nroff: nfs.secure.ms + ${TBL} nfs.secure.ms | ${EQN} | ${NROFF} ${NOPTS} -ms >nfs.secure.nroff + +nfs.secure.troff: nfs.secure.ms + ${TBL} nfs.secure.ms|${PIC}|${EQN}| ${TROFF} ${TOPTS} -ms >nfs.secure.troff + +clean: + rm -f *.nroff *.troff + +spell: ${SRC} + @for i in ${SRC}; do \ + echo $$i; spell $$i | sort | comm -23 - spell.ok > $$i.spell; \ + done diff --git a/lib/librpc/secure_rpc/doc/nfs.secure.ms b/lib/librpc/secure_rpc/doc/nfs.secure.ms new file mode 100644 index 0000000..2476790 --- /dev/null +++ b/lib/librpc/secure_rpc/doc/nfs.secure.ms @@ -0,0 +1,934 @@ +.\" Must use -- pic tbl eqn -- with this one. +.\" +.\" @(#)nfs.secure.ms 2.2 88/08/09 4.0 RPCSRC +.de BT +.if \\n%=1 .tl ''- % -'' +.. +.ND +.\" prevent excess underlining in nroff +.if n .fp 2 R +.OH 'Secure Networking''Page %' +.EH 'Page %''Secure Networking' +.if \\n%=1 .bp +.EQ +delim $$ +gsize 11 +.EN +.SH +\&Secure Networking +.nr OF 1 +.IX "security" "of networks" "" "" PAGE START +.IX "network security" "" "" "" PAGE START +.IX "NFS security" "" "" "" PAGE START +.LP +RPCSRC 4.0 includes an authentication system +that greatly improves the security of network environments. +The system is general enough to be used by other +.UX +and non-UNIX systems. +The system uses DES encryption and public key cryptography +to authenticate both users and machines in the network. +(DES stands for Data Encryption Standard.) +.LP +Public key cryptography is a cipher system that involves two keys: +one public and the other private. +The public key is published, while the private key is not; +the private (or secret) key is used to encrypt and decrypt data. +Sun's system differs from some other public key cryptography systems +in that the public and secret keys are used to generate a common key, +which is used in turn to create a DES key. +DES is relatively fast, +and on Sun Workstations, +optional hardware is available to make it even faster. +.# +.NH 0 +\&Administering Secure RPC +.IX "administering secure RPC" +.IX "security" "RPC administration" +.LP +This section describes what the system administrator must do +in order to use secure networking. +.IP 1 +RPCSRC now includes the +.I /etc/publickey +.IX "etc/publickey" "" "\&\fI/etc/publickey\fP" +database, which should contain three fields for each user: +the user's netname, a public key, and an encrypted secret key. +The corresponding Yellow Pages map is available to YP clients as +.I publickey.byname +but the database should reside only on the YP master. Make sure +.I /etc/netid +exists on the YP master server. +As normally installed, the only user is +.I nobody . +This is convenient administratively, +because users can establish their own public keys using +.I chkey (1) +.IX "chkey command" "" "\&\fIchkey\fP command" +without administrator intervention. +For even greater security, +the administrator can establish public keys for everyone using +.I newkey (8). +.IX "newkey command" "" "\&\fInewkey\fP command" +Note that the Yellow Pages take time to propagate a new map, +so it's a good idea for users to run +.I chkey , +or for the administrator to run +.I newkey , +just before going home for the night. +.IP 2 +Verify that the +.I keyserv (8c) +.IX "keyserv daemon" "" "\&\fIkeyserv\fP daemon" +daemon was started by +.I /etc/rc.local +and is still running. +This daemon performs public key encryption +and stores the private key (encrypted, of course) in +.I /etc/keystore : +.DS +% \fBps aux | grep keyserv\fP +root 1354 0.0 4.1 128 296 p0 I Oct 15 0:13 keyserv +.DE +When users log in with +.I login +.IX "login command" "" "\&\fIlogin\fP command" +or remote log in with +.I rlogin , +these programs use the typed password to decrypt the secret key stored in +.I /etc/publickey . +This becomes the private key, and gets passed to the +.I keyserv +daemon. +If users don't type a password for +.I login +or +.I rlogin , +either because their password field is empty +or because their machine is in the +.I hosts\fR.\fPequiv +.IX "etc/hosts.equiv" "" "\&\fI/etc/hosts.equiv\fP" +file of the remote host, +they can still place a private key in +.I /etc/keystore +by invoking the +.I keylogin (1) +.IX "keylogin command" "" "\&\fIkeylogin\fP command" +program. +Administrators should take care not to delete +.I /etc/keystore +and +.I /etc/.rootkey +(the latter file contains the private key for +.I root ). +.IP 3 +When you reinstall, move, or upgrade a machine, save +.I /etc/keystore +and +.I /etc/.rootkey +along with everything else you normally save. +.LP +.LP +Note that if you +.I login , +.I rlogin , +or +.I telnet +to another machine, are asked for your password, and type it correctly, +you've given away access to your own account. +This is because your secret key is now stored in +.I /etc/keystore +on that remote machine. +This is only a concern if you don't trust the remote machine. +If this is the case, +don't ever log in to a remote machine if it asks for your password. +Instead, use NFS to remote mount the files you're looking for. +At this point there is no +.I keylogout +command, even though there should be. +.LP +The remainder of this chapter discusses the theory of secure networking, +and is useful as a background for both users and administrators. +.# +.NH 1 +\&Security Shortcomings of NFS +.IX "security" "shortcomings of NFS" +.LP +Sun's Remote Procedure Call (RPC) mechanism has proved to be a very +powerful primitive for building network services. +The most well-known of these services is the Network File System (NFS), +a service that provides transparent file-sharing +between heterogeneous machine architectures and operating systems. +The NFS is not without its shortcomings, however. +Currently, an NFS server authenticates a file request by authenticating the +machine making the request, but not the user. +On NFS-based filesystems, it is a simple matter of running +.I su +.IX "su command" "" "\&\fIsu\fP command" +to impersonate the rightful owner of a file. +But the security weaknesses of the NFS are nothing new. +The familiar command +.I rlogin +is subject to exactly the same attacks as the NFS +because it uses the same kind of authentication. +.LP +A common solution to network security problems +is to leave the solution to each application. +A far better solution is to put authentication at the RPC level. +The result is a standard authentication system +that covers all RPC-based applications, +such as the NFS and the Yellow Pages (a name-lookup service). +Our system allows the authentication of users as well as machines. +The advantage of this is that it makes a network environment +more like the older time-sharing environment. +Users can log in on any machine, +just as they could log in on any terminal. +Their login password is their passport to network security. +No knowledge of the underlying authentication system is required. +Our goal was a system that is as secure and easy to use +as a time-sharing system. +.LP +Several remarks are in order. Given +.I root +access and a good knowledge of network programming, +anyone is capable of injecting arbitrary data into the network, +and picking up any data from the network. +However, on a local area network, no machine is capable of packet smashing \(en +capturing packets before they reach their destination, changing the contents, +then sending packets back on their original course \(en +because packets reach all machines, including the server, at the same time. +Packet smashing is possible on a gateway, though, +so make sure you trust all gateways on the network. +The most dangerous attacks are those involving the injection of data, +such as impersonating a user by generating the right packets, +or recording conversations and replaying them later. +These attacks affect data integrity. +Attacks involving passive eavesdropping \(en +merely listening to network traffic without impersonating anybody \(en +are not as dangerous, since data integrity had not been compromised. +Users can protect the privacy of sensitive information +by encrypting data that goes over the network. +It's not easy to make sense of network traffic, anyway. +.# +.NH 1 +\&RPC Authentication +.IX "RPC authentication" +.IX "authentication" "RPC" +.LP +RPC is at the core of the new network security system. +To understand the big picture, +it's necessary to understand how authentication works in RPC. +RPC's authentication is open-ended: +a variety of authentication systems may be plugged into it +and may coexist on the network. +Currently, we have two: UNIX and DES. +UNIX authentication is the older, weaker system; +DES authentication is the new system discussed in this chapter. +Two terms are important for any RPC authentication system: +.I credentials +and +.I verifiers . +Using ID badges as an example, the credential is what identifies a person: +a name, address, birth date, etc. +The verifier is the photo attached to the badge: +you can be sure the badge has not been stolen by checking the photo +on the badge against the person carrying it. +In RPC, things are similar. +The client process sends both a credential and a verifier +to the server with each RPC request. +The server sends back only a verifier, +since the client already knows the server's credentials. +.# +.NH 2 +\&UNIX Authentication +.IX "UNIX authentication" +.IX "authentication" "UNIX" +.LP +UNIX authentication was used by most of Sun's original network services. +The credentials contain the client's machine-name, +.I uid , +.I gid , +and group-access-list. +The verifier contains \fBnothing\fP! +There are two problems with this system. +The glaring problem is the empty verifier, +which makes it easy to cook up the right credential using +.I hostname +.IX "hostname command" "" "\&\fIhostname\fP command" +and +.I su . +.IX "su command" "" "\&\fIsu\fP command" +If you trust all root users in the network, this is not really a problem. +But many networks \(en especially at universities \(en are not this secure. +The NFS tries to combat deficiencies in UNIX authentication +by checking the source Internet address of +.I mount +requests as a verifier of the +.I hostname +field, and accepting requests only from privileged Internet ports. +Still, it is not difficult to circumvent these measures, +and NFS really has no way to verify the user-ID. +.LP +The other problem with UNIX authentication appears in the name UNIX. +It is unrealistic to assume that all machines on a network +will be UNIX machines. +The NFS works with MS-DOS and VMS machines, +but UNIX authentication breaks down when applied to them. +For instance, MS-DOS doesn't even have a notion of different user IDs. +.LP +Given these shortcomings, +it is clear what is needed in a new authentication system: +operating system independent credentials, and secure verifiers. +This is the essence of DES authentication discussed below. +.# +.NH 2 +\&DES Authentication +.IX "DES authentication" +.IX "authentication" "DES" +.LP +The security of DES authentication is based on +a sender's ability to encrypt the current time, +which the receiver can then decrypt and check against its own clock. +The timestamp is encrypted with DES. +Two things are necessary for this scheme to work: +1) the two agents must agree on what the current time is, and +2) the sender and receiver must be using the same encryption key. +.LP +If a network has time synchronization (Berkeley's TEMPO for example), +then client/server time synchronization is performed automatically. +However, if this is not available, +timestamps can be computed using the server's time instead of network time. +In order to do this, the client asks the server what time it is, +before starting the RPC session, +then computes the time difference between its own clock and the server's. +This difference is used to offset the client's clock when computing timestamps. +If the client and server clocks get out of sync +to the point where the server begins rejecting the client's requests, +the DES authentication system just resynchronizes with the server. +.LP +Here's how the client and server arrive at the same encryption key. +When a client wishes to talk to a server, it generates at random +a key to be used for encrypting the timestamps (among other things). +This key is known as the +.I "conversation key, CK." +The client encrypts the conversation key using a public key scheme, +and sends it to the server in its first transaction. +This key is the only thing that is ever encrypted with public key cryptography. +The particular scheme used is described further on in this chapter. +For now, suffice to say that for any two agents A and B, +there is a DES key $K sub AB$ that only A and B can deduce. +This key is known as the +.I "common key," +$K sub AB$. +.EQ +gsize 10 +.EN +.ne 1i +.PS +.in +.7i +circlerad=.4 +boxht=.2 +boxwid=1.3 +circle "\s+9A\s-9" "(client)" at 0,1.2 +circle "\s+9B\s-9" "(server)" at 5.1,1.2 +line invis at .5,2 ; box invis "\fBCredential\fP"; line invis; + box invis "\fBVerifier\fP" +arrow at .5,1.7; box "$A, K sub AB (CK), CK(win)$"; arrow; + box "$CK(t sub 1 ), CK(win + 1)$"; arrow +arrow <- at .5,1.4; line right 1.3; line; + box "$CK(t sub 1 - 1), ID$"; arrow <- +arrow at .5,1; box "ID"; arrow; + box "$CK(t sub 2 )$"; arrow +arrow <- at .5,.7; line right 1.3; line; + box "$CK(t sub 2 - 1), ID$"; arrow <- +arrow at .5,.3; box "ID"; arrow; + box "$CK(t sub n )$"; arrow +arrow <- at .5,0; line right 1.3; line; + box "$CK(t sub n - 1), ID$"; arrow <- +.PE +.EQ +gsize 11 +.EN +.in -.7i +.LP +The figure above illustrates the authentication protocol in more detail, +describing client A talking to server B. +A term of the form $K(x)$ means $x$ encrypted with the DES key $K$. +Examining the figure, you can see that for its first request, +the client's credential contains three things: +its name $A$, the conversation key $CK$ encrypted with the common key +$K sub AB$, and a thing called $win$ (window) encrypted with $CK$. +What the window says to the server, in effect, is this: +.LP +.I +I will be sending you many credentials in the future, +but there may be crackers sending them too, +trying to impersonate me with bogus timestamps. +When you receive a timestamp, check to see if your current time +is somewhere between the timestamp and the timestamp plus the window. +If it's not, please reject the credential. +.LP +For secure NFS filesystems, the window currently defaults to 30 minutes. +The client's verifier in the first request contains the encrypted timestamp +and an encrypted verifier of the specified window, $win + 1$. +The reason this exists is the following. +Suppose somebody wanted to impersonate A by writing a program +that instead of filling in the encrypted fields of the credential and verifier, +just stuffs in random bits. +The server will decrypt CK into some random DES key, +and use it to decrypt the window and the timestamp. +These will just end up as random numbers. +After a few thousand trials, there is a good chance +that the random window/timestamp pair will pass the authentication system. +The window verifier makes guessing the right credential much more difficult. +.LP +After authenticating the client, +the server stores four things into a credential table: +the client's name A, the conversation key $CK$, the window, and the timestamp. +The reason the server stores the first three things should be clear: +it needs them for future use. +The reason for storing the timestamp is to protect against replays. +The server will only accept timestamps +that are chronologically greater than the last one seen, +so any replayed transactions are guaranteed to be rejected. +The server returns to the client in its verifier an index ID +into its credential table, plus the client's timestamp minus one, +encrypted by $CK$. +The client knows that only the server could have sent such a verifier, +since only the server knows what timestamp the client sent. +The reason for subtracting one from it is to insure that it is invalid +and cannot be reused as a client verifier. +.LP +The first transaction is rather complicated, +but after this things go very smoothly. +The client just sends its ID and an encrypted timestamp to the server, +and the server sends back the client's timestamp minus one, +encrypted by $CK$. +.# +.NH 1 +\&Public Key Encryption +.IX "public key encryption" +.LP +The particular public key encryption scheme Sun uses +is the Diffie-Hellman method. +The way this algorithm works is to generate a +.I "secret key" +$SK sub A$ at random +and compute a +.I "public key" +$PK sub A$ using the following formula +($PK$ and $SK$ are 192 bit numbers and \(*a is a well-known constant): +.EQ +PK sub A ~ = ~ alpha sup {SK sub A} +.EN +Public key $PK sub A$ is stored in a public directory, +but secret key $SK sub A$ is kept private. +Next, $PK sub B$ is generated from $SK sub B$ in the same manner as above. +Now common key $K sub AB$ can be derived as follows: +.EQ +K sub AB ~ = ~ PK sub B sup {SK sub A} ~ = ~ +( alpha sup {SK sub B} ) sup {SK sub A} ~ = ~ +alpha sup {( SK sub A SK sub B )} +.EN +Without knowing the client's secret key, +the server can calculate the same common key $K sub AB$ +in a different way, as follows: +.EQ +K sub AB ~ = ~ PK sub A sup {SK sub B} ~ = ~ +( alpha sup {SK sub A} ) sup {SK sub B} ~ = ~ +alpha sup {( SK sub A SK sub B )} +.EN +Notice that nobody else but the server and client can calculate $K sub AB$, +since doing so requires knowing either one secret key or the other. +All of this arithmetic is actually computed modulo $M$, +which is another well-known constant. +It would seem at first that somebody could guess your secret key +by taking the logarithm of your public one, +but $M$ is so large that this is a computationally infeasible task. +To be secure, $K sub AB$ has too many bits to be used as a DES key, +so 56 bits are extracted from it to form the DES key. +.LP +Both the public and the secret keys +are stored indexed by netname in the Yellow Pages map +.I publickey.byname +the secret key is DES-encrypted with your login password. +When you log in to a machine, the +.I login +program grabs your encrypted secret key, +decrypts it with your login password, +and gives it to a secure local keyserver to save +for use in future RPC transactions. +Note that ordinary users do not have to be aware of +their public and secret keys. +In addition to changing your login password, the +.I yppasswd +.IX "yppasswd command" "" "\&\fIyppasswd\fP command" +program randomly generates a new public/secret key pair as well. +.LP +The keyserver +.I keyserv (8c) +.IX "keyserv daemon" "" "\&\fIkeyserv\fP daemon" +is an RPC service local to each machine +that performs all of the public key operations, +of which there are only three. They are: +.DS +setsecretkey(secretkey) +encryptsessionkey(servername, des_key) +decryptsessionkey(clientname, des_key) +.DE +.I setsecretkey() +tells the keyserver to store away your secret key $SK sub A$ for future use; +it is normally called by +.I login . +The client program calls +.I encryptsessionkey() +to generate the encrypted conversation key +that is passed in the first RPC transaction to a server. +The keyserver looks up +.I servername 's +public key and combines it with the client's secret key (set up by a previous +.I setsecretkey() +call) to generate the key that encrypts +.I des_key . +The server asks the keyserver to decrypt the conversation key by calling +.I decryptsessionkey(). +Note that implicit in these procedures is the name of caller, +who must be authenticated in some manner. +The keyserver cannot use DES authentication to do this, +since it would create deadlock. +The keyserver solves this problem by storing the secret keys by +.I uid , +and only granting requests to local root processes. +The client process then executes a +.I setuid +process, owned by root, which makes the request on the part of the client, +telling the keyserver the real +.I uid +of the client. Ideally, the three operations described above +would be system calls, and the kernel would talk to the keyserver directly, +instead of executing the +.I setuid +program. +.# +.NH 1 +\&Naming of Network Entities +.IX "naming of network entities" +.IX "network naming" +.LP +The old UNIX authentication system has a few problems when it comes to naming. +Recall that with UNIX authentication, +the name of a network entity is basically the +.I uid . +These +.I uid s +are assigned per Yellow Pages naming domain, +which typically spans several machines. +We have already stated one problem with this system, +that it is too UNIX system oriented, +but there are two other problems as well. +One is the problem of +.I uid +clashes when domains are linked together. +The other problem is that the super-user (with +.I uid +of 0) should not be assigned on a per-domain basis, +but rather on a per-machine basis. +By default, the NFS deals with this latter problem in a severe manner: +it does not allow root access across the network by +.I uid +0 at all. +.LP +DES authentication corrects these problems +by basing naming upon new names that we call +.I netnames. +Simply put, a netname is just a string of printable characters, +and fundamentally, it is really these netnames that we authenticate. +The public and secret keys are stored on a per-netname, +rather than per-username, basis. +The Yellow Pages map +.I netid.byname +maps the netname into a local +.I uid +and group-access-list, +though non-Sun environments may map the netname into something else. +.LP +We solve the Internet naming problem by choosing globally unique netnames. +This is far easier then choosing globally unique user IDs. +In the Sun environment, user names are unique within each Yellow Page domain. +Netnames are assigned by concatenating the operating system and user ID +with the Yellow Pages and ARPA domain names. +For example, a UNIX system user with a user ID of 508 in the domain +.I eng.sun.COM +would be assigned the following netname: +.I unix.508@eng.sun.COM . +A good convention for naming domains is to append +the ARPA domain name (COM, EDU, GOV, MIL) to the local domain name. +Thus, the Yellow Pages domain +.I eng +within the ARPA domain +.I sun.COM +becomes +.I eng.sun.COM . +.LP +We solve the problem of multiple super-users per domain +by assigning netnames to machines as well as to users. +A machine's netname is formed much like a user's. +For example, a UNIX machine named +.I hal +in the same domain as before has the netname +.I unix.hal@eng.sun.COM . +Proper authentication of machines is very important for diskless machines +that need full access to their home directories over the net. +.LP +Non-Sun environments will have other ways of generating netnames, +but this does not preclude them from accessing +the secure network services of the Sun environment. +To authenticate users from any remote domain, +all that has to be done is make entries for them in two Yellow Pages databases. +One is an entry for their public and secret keys, +the other is for their local +.I uid +and group-access-list mapping. +Upon doing this, users in the remote domain +will be able access all of the local network services, +such as the NFS and remote logins. +.# +.NH 1 +\&Applications of DES Authentication +.IX "applications of DES authentication" +.IX "authentication" "DES" +.LP +The first application of DES authentication +is a generalized Yellow Pages update service. +This service allows users to update private fields in Yellow Page databases. +So far the Yellow Pages maps +.I hosts, +.I ethers, +.I bootparams +and +.I publickey +employ the DES-based update service. +Before the advent of an update service for mail aliases, +Sun had to hire a full-time person just to update mail aliases. +.LP +The second application of DES authentication is the most important: +a more secure Network File System. +There are three security problems with the +old NFS using UNIX authentication. +The first is that verification of credentials occurs only at mount time +when the client gets from the server a piece of information +that is its key to all further requests: the +.I "file handle" . +Security can be broken if one can figure out a file handle +without contacting the server, perhaps by tapping into the net or by guessing. +After an NFS file system has been mounted, +there is no checking of credentials during file requests, +which brings up the second problem. +If a file system has been mounted from a server that serves multiple clients +(as is typically the case), there is no protection +against someone who has root permission on their machine using +.I su +(or some other means of changing +.I uid ) +gaining unauthorized access to other people's files. +The third problem with the NFS is the severe method it uses to circumvent +the problem of not being able to authenticate remote client super-users: +denying them super-user access altogether. +.LP +The new authentication system corrects all of these problems. +Guessing file handles is no longer a problem since in order to gain +unauthorized access, the miscreant will also have to guess the right +encrypted timestamp to place in the credential, +which is a virtually impossible task. +The problem of authenticating root users is solved, +since the new system can authenticate machines. +At this point, however, +secure NFS is not used for root filesystems. +Root users of nonsecure filesystems are identified by IP address. +.LP +Actually, the level of security associated with each filesystem +may be altered by the administrator. The file +.I /etc/exports +.IX "etc/exports" "" "\&\fI/etc/exports\fP" +contains a list of filesystems and which machines may mount them. +By default, filesystems are exported with UNIX authentication, +but the administrator can have them exported with DES authentication +by specifying +.I -secure +on any line in the +.I /etc/exports +file. Associated with DES authentication is a parameter: +the maximum window size that the server is willing to accept. +.# +.NH 1 +\&Security Issues Remaining +.IX "security" "issues remaining" +.IX "remaining security issues" +.LP +There are several ways to break DES authentication, but using +.I su +is not one of them. In order to be authenticated, +your secret key must be stored by your workstation. +This usually occurs when you login, with the +.I login +program decrypting your secret key with your login password, +and storing it away for you. +If somebody tries to use +.I su +to impersonate you, it won't work, +because they won't be able to decrypt your secret key. Editing +.I /etc/passwd +isn't going to help them either, because the thing they need to edit, +your encrypted secret key, is stored in the Yellow Pages. +If you log into somebody else's workstation and type in your password, +then your secret key would be stored in their workstation and they could use +.I su +to impersonate you. But this is not a problem since you should not +be giving away your password to a machine you don't trust anyway. +Someone on that machine could just as easily change +.I login +to save all the passwords it sees into a file. +.LP +Not having +.I su +to employ any more, how can nefarious users impersonate others now? +Probably the easiest way is to guess somebody's password, +since most people don't choose very secure passwords. +We offer no protection against this; +it's up to each user to choose a secure password. +.LP +The next best attack would be to attempt replays. +For example, let's say I have been squirreling away +all of your NFS transactions with a particular server. +As long as the server remains up, +I won't succeed by replaying them since the server always demands timestamps +that are greater than the previous ones seen. +But suppose I go and pull the plug on your server, causing it to crash. +As it reboots, its credential table will be clean, +so it has lost all track of previously seen timestamps, +and now I am free to replay your transactions. +There are few things to be said about this. +First of all, servers should be kept in a secure place +so that no one can go and pull the plug on them. +But even if they are physically secure, +servers occasionally crash without any help. +Replaying transactions is not a very big security problem, +but even so, there is protection against it. +If a client specifies a window size that is smaller than the time it takes +a server to reboot (5 to 10 minutes), the server will reject +any replayed transactions because they will have expired. +.LP +There are other ways to break DES authentication, +but they are much more difficult. +These methods involve breaking the DES key itself, +or computing the logarithm of the public key, +both of which would would take months of compute time on a supercomputer. +But it is important to keep our goals in mind. +Sun did not aim for super-secure network computing. +What we wanted was something as secure as a good time-sharing system, +and in that we have been successful. +.LP +There is another security issue that DES authentication does not address, +and that is tapping of the net. +Even with DES authentication in place, +there is no protection against somebody watching what goes across the net. +This is not a big problem for most things, +such as the NFS, since very few files are not publically readable, and besides, +trying to make sense of all the bits flying over the net is not a trivial task. +For logins, this is a bit of a problem because you wouldn't +want somebody to pick up your password over the net. +As we mentioned before, +a side effect of the authentication system is a key exchange, +so that the network tapping problem can be tackled on a per-application basis. +.# +.NH 1 +\&Performance +.IX "performance of DES authentication" +.IX "authentication" "performance" +.LP +Public key systems are known to be slow, +but there is not much actual public key encryption going on in Sun's system. +Public key encryption only occurs in the first transaction with a service, +and even then, there is caching that speeds things up considerably. +The first time a client program contacts a server, +both it and the server will have to calculate the common key. +The time it takes to compute the common key is basically the time it takes +to compute an exponential modulo $M$. +On a Sun-3 using a 192-bit modulus, this takes roughly 1 second, +which means it takes 2 seconds just to get things started, +since both client and server have to perform this operation. +This is a long time, +but you have to wait only the first time you contact a machine. +Since the keyserver caches the results of previous computations, +it does not have to recompute the exponential every time. +.LP +The most important service in terms of performance is the secure NFS, +which is acceptably fast. +The extra overhead that DES authentication requires versus UNIX authentication +is the encryption. +A timestamp is a 64-bit quantity, +which also happens to be the DES block size. +Four encryption operations take place in an average RPC transaction: +the client encrypts the request timestamp, the server decrypts it, +the server encrypts the reply timestamp, and the client decrypts it. +On a Sun-3, the time it takes to encrypt one block is about +half a millisecond if performed by hardware, +and 1.2 milliseconds if performed by software. +So, the extra time added to the round trip time is about +2 milliseconds for hardware encryption and 5 for software. +The round trip time for the average NFS request is about 20 milliseconds, +resulting in a performance hit of 10 percent if one has encryption hardware, +and 25 percent if not. +Remember that this is the impact on network performance. +The fact is that not all file operations go over the wire, +so the impact on total system performance will actually be lower than this. +It is also important to remember that security is optional, +so environments that require higher performance can turn it off. +.# +.NH 1 +\&Problems with Booting and \&\fBsetuid\fP Programs +.IX "problems with booting and \&\fIsetuid\fP programs" +.IX "booting and \&\fIsetuid\fP problems" +.LP +Consider the problem of a machine rebooting, +say after a power failure at some strange hour when nobody is around. +All of the secret keys that were stored get wiped out, +and now no process will be able to access secure network services, +such as mounting an NFS filesystem. +The important processes at this time are usually root processes, +so things would work OK if root's secret key were stored away, +but nobody is around to type the password that decrypts it. +The solution to this problem is to store root's decrypted secret key in a file, +which the keyserver can read. +This works well for diskful machines that can store the secret key +on a physically secure local disk, +but not so well for diskless machines, +whose secret key must be stored across the network. +If you tap the net when a diskless machine is booting, +you will find the decrypted key. +This is not very easy to accomplish, though. +.LP +Another booting problem is the single-user boot. +There is a mode of booting known as single-user mode, where a +.I root +login shell appears on the console. +The problem here is that a password is not required for this. +With C2 security installed, +a password is required in order to boot single-user. +Without C2 security installed, +machines can still be booted single-user without a password, +as long as the entry for +.I console +in the +.I /etc/ttytab +.IX "etc/ttytab" "" "\&\fI/etc/ttytab\fP" +file is labeled as physically +.I secure +(this is the default). +.LP +Yet another problem is that diskless machine booting is not totally secure. +It is possible for somebody to impersonate the boot-server, +and boot a devious kernel that, for example, +makes a record of your secret key on a remote machine. +The problem is that our system is set up to provide protection +only after the kernel and the keyserver are running. +Before that, there is no way to authenticate +the replies given by the boot server. +We don't consider this a serious problem, +because it is highly unlikely that somebody would be able to write +this funny kernel without source code. +Also, the crime is not without evidence. +If you polled the net for boot-servers, +you would discover the devious boot-server's location. +.LP +Not all +.I setuid +programs will behave as they should. +For example, if a +.I setuid +program is owned by +.I dave , +who has not logged into the machine since it booted, +then the program will not be able to access any secure network services as +.I dave . +The good news is that most +.I setuid +programs are owned by root, +and since root's secret key is always stored at boot time, +these programs will behave as they always have. +.# +.NH 1 +\&Conclusion +.IX "network security" "summary" +.LP +Our goal was to build a system as secure as a time-shared system. +This goal has been met. +The way you are authenticated in a time-sharing system +is by knowing your password. +With DES authentication, the same is true. +In time-sharing the person you trust is your system administrator, +who has an ethical obligation +not to change your password in order to impersonate you. +In Sun's system, you trust your network administrator, +who does not alter your entry in the public key database. +In one sense, our system is even more secure than time-sharing, +because it is useless to place a tap on the network +in hopes of catching a password or encryption key, +since these are encrypted. +Most time-sharing environments do not encrypt data emanating from the terminal; +users must trust that nobody is tapping their terminal lines. +.LP +DES authentication is perhaps not the ultimate authentication system. +In the future it is likely there will be sufficient advances +in algorithms and hardware to render the public key system +as we have defined it useless. +But at least DES authentication offers a smooth migration path for the future. +Syntactically speaking, +nothing in the protocol requires the encryption of the conversation +key to be Diffie-Hellman, or even public key encryption in general. +To make the authentication stronger in the future, +all that needs to be done is to strengthen the way +the conversation key is encrypted. +Semantically, this will be a different protocol, +but the beauty of RPC is that it can be plugged in +and live peacefully with any authentication system. +.LP +For the present at least, DES authentication satisfies our requirements +for a secure networking environment. +From it we built a system secure enough for use in unfriendly networks, +such as a student-run university workstation environment. +The price for this security is not high. +Nobody has to carry around a magnetic card or remember +any hundred digit numbers. +You use your login password to authenticate yourself, just as before. +There is a small impact on performance, +but if this worries you and you have a friendly net, +you can turn authentication off. +.# +.NH 1 +\&References +.IX "references on network security" +.LP +Diffie and Hellman, ``New Directions in Cryptography,'' +\fIIEEE Transactions on Information Theory IT-22,\fP +November 1976. +.LP +Gusella & Zatti, ``TEMPO: A Network Time Controller +for a Distributed Berkeley UNIX System,'' +\fIUSENIX 1984 Summer Conference Proceedings,\fP +June 1984. +.LP +National Bureau of Standards, ``Data Encryption Standard,'' +\fIFederal Information Processing Standards Publication 46,\fP +January 15, 1977. +.LP +Needham & Schroeder, ``Using Encryption for Authentication +in Large Networks of Computers,'' +\fIXerox Corporation CSL-78-4,\fP +September 1978. +.EQ +delim off +.EN +.IX "security" "of networks" "" "" PAGE END +.IX "network security" "" "" "" PAGE END +.IX "NFS security" "" "" "" PAGE END diff --git a/lib/librpc/secure_rpc/keyserv/Makefile b/lib/librpc/secure_rpc/keyserv/Makefile new file mode 100644 index 0000000..de6771e --- /dev/null +++ b/lib/librpc/secure_rpc/keyserv/Makefile @@ -0,0 +1,49 @@ +# +# @(#)Makefile 2.4 88/08/15 4.0 RPCSRC; from 1.9 87/11/29 SMI +# +CFLAGS= -O +RPCLIB= -lrpclib +#RPCLIB= -lrpcsvc + +KEYSERV_OBJS = keyserv.o setkey.o detach.o mp.o +KEYENVOY_OBJS = keyenvoy.o +SRCS = keyserv.c setkey.c detach.c keyenvoy.c mp.c + +ALL= keyserv keyenvoy + +all: $(ALL) + +keyserv: $(KEYSERV_OBJS) + $(CC) $(CFLAGS) $(KEYSERV_OBJS) -lmp $(LIBC) $(RPCLIB) -o $@ + +keyenvoy: $(KEYENVOY_OBJS) + $(CC) $(CFLAGS) $(KEYENVOY_OBJS) $(LIBC) $(RPCLIB) -o $@ + +clean: + rm -f $(ALL) $(KEYSERV_OBJS) $(KEYENVOY_OBJS) + +install: $(ALL) + install -s -m 755 keyserv $(DESTDIR)/usr/etc + install -s -m 4755 keyenvoy $(DESTDIR)/usr/etc + +depend: + rm -f makedep + for i in ${SRCS}; do \ + ${CC} -M ${INCPATH} $$i | \ + awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \ + else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ + else rec = rec " " $$2 } } \ + END { print rec } ' >> makedep; done + echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep + echo '$$r makedep' >>eddep + echo 'w' >>eddep + cp Makefile Makefile.bak + ed - Makefile < eddep + rm eddep makedep + echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile + echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile + echo '# see make depend above' >> Makefile + +# DO NOT DELETE THIS LINE -- make depend uses it + + diff --git a/lib/librpc/secure_rpc/keyserv/detach.c b/lib/librpc/secure_rpc/keyserv/detach.c new file mode 100644 index 0000000..ff1fac3 --- /dev/null +++ b/lib/librpc/secure_rpc/keyserv/detach.c @@ -0,0 +1,69 @@ +#ifndef lint +static char sccsid[] = "@(#)detach.c 2.2 88/08/10 4.0 RPCSRC"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +#include <sys/ioctl.h> +#include <fcntl.h> + +/* + * detach from tty + */ +detachfromtty() +{ + int tt; + + close(0); + close(1); + close(2); + switch (fork()) { + case -1: + perror("fork"); + break; + case 0: + break; + default: + exit(0); + } + tt = open("/dev/tty", O_RDWR); + if (tt > 0) { + ioctl(tt, TIOCNOTTY, 0); + close(tt); + } + (void)open("/dev/null", O_RDWR, 0); + dup(0); + dup(0); +} + + diff --git a/lib/librpc/secure_rpc/keyserv/keyenvoy.c b/lib/librpc/secure_rpc/keyserv/keyenvoy.c new file mode 100644 index 0000000..5379651 --- /dev/null +++ b/lib/librpc/secure_rpc/keyserv/keyenvoy.c @@ -0,0 +1,213 @@ +#ifndef lint +static char sccsid[] = "@(#)keyenvoy.c 2.2 88/08/10 4.0 RPCSRC"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (C) 1986, Sun Microsystems, Inc. + */ +#include <stdio.h> +#include <rpc/rpc.h> +#include <rpc/key_prot.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/time.h> +#include <fcntl.h> + +/* + * Talk to the keyserver on a privileged port on the part of a calling program. + * + * Protocol is for caller to send through stdin the procedure number + * to call followed by the argument data. We call the keyserver, and + * send the results back to the caller through stdout. + * Non-zero exit status means something went wrong. + */ + +#ifndef DEBUG +#define debug(msg) +#endif + +#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */ +#define TOTAL_TRIES 10 /* Number of tries */ + +/* + * Opaque data that we send and receive + */ +#define MAXOPAQUE 256 +struct opaqn { + u_int len; + u_int data[MAXOPAQUE]; +}; +bool_t xdr_opaqn(); + + +main(argc,argv) + int argc; + char *argv[]; +{ + XDR xdrs_args; + XDR xdrs_rslt; + int proc; + struct opaqn args, rslt; + + + if (isatty(0)) { + fprintf(stderr, + "This program cannot be used interactively.\n"); + exit(1); + } + +#ifdef DEBUG + close(2); + open("/dev/console", O_WRONLY, 0); +#endif + + xdrstdio_create(&xdrs_args, stdin, XDR_DECODE); + xdrstdio_create(&xdrs_rslt, stdout, XDR_ENCODE); + + if ( ! xdr_u_long(&xdrs_args, &proc)) { + debug("no proc"); + exit(1); + } + if (! xdr_opaqn(&xdrs_args, &args)) { + debug("recving args failed"); + exit(1); + } + if (! callkeyserver(proc, xdr_opaqn, &args, xdr_opaqn, &rslt)) { + debug("rpc_call failed"); + exit(1); + } + if (! xdr_opaqn(&xdrs_rslt, &rslt)) { + debug("sending args failed"); + exit(1); + } + exit(0); +} + + + +callkeyserver(proc, xdr_args, args, xdr_rslt, rslt) + u_long proc; + bool_t (*xdr_args)(); + void *args; + bool_t (*xdr_rslt)(); + void *rslt; + +{ + struct sockaddr_in remote; + int port; + struct timeval wait; + enum clnt_stat stat; + CLIENT *client; + int sd; + + /* + * set up the remote address + * and create client + */ + remote.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + remote.sin_family = AF_INET; + remote.sin_port = 0; + wait.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES; wait.tv_usec = 0; + sd = RPC_ANYSOCK; + client = clntudp_create(&remote, KEY_PROG, KEY_VERS, wait, &sd); + if (client == NULL) { + debug("no client"); + return (0); + } + + /* + * Check that server is bound to a reserved port, so + * that noone can masquerade as the keyserver. + */ + if (ntohs(remote.sin_port) >= IPPORT_RESERVED) { + debug("insecure port"); + return (0); + } + + /* + * Create authentication + * All we care about really is sending the real uid + */ + client->cl_auth = authunix_create("", getuid(), 0, 0, NULL); + if (client->cl_auth == NULL) { + debug("no auth"); + return (0); + } + wait.tv_sec = TOTAL_TIMEOUT; wait.tv_usec = 0; + stat = clnt_call(client, proc, xdr_args, args, xdr_rslt, rslt, wait); + if (stat != RPC_SUCCESS) { + debug("clnt_call failed"); + } + return (stat == RPC_SUCCESS); +} + + +/* + * XDR opaque data + * Don't know the length on decode, so just keep receiving until failure. + */ +bool_t +xdr_opaqn(xdrs, objp) + XDR *xdrs; + struct opaqn *objp; +{ + int i; + + switch (xdrs->x_op) { + case XDR_FREE: + break; + case XDR_DECODE: + for (i = 0; i < MAXOPAQUE && xdr_int(xdrs, &objp->data[i]); i++) { + } + if (i == MAXOPAQUE) { + return (FALSE); + } + objp->len = i; + break; + case XDR_ENCODE: + for (i = 0; i < objp->len; i++) { + if (! xdr_int(xdrs, &objp->data[i])) { + return (FALSE); + } + } + break; + } + return (TRUE); +} + + +#ifdef DEBUG +debug(msg) + char *msg; +{ + fprintf(stderr, "%s\n", msg); +} +#endif diff --git a/lib/librpc/secure_rpc/keyserv/keyserv.c b/lib/librpc/secure_rpc/keyserv/keyserv.c new file mode 100644 index 0000000..d82dc12 --- /dev/null +++ b/lib/librpc/secure_rpc/keyserv/keyserv.c @@ -0,0 +1,458 @@ +#ifndef lint +static char sccsid[] = "@(#)keyserv.c 2.4 88/08/15 4.0 RPCSRC Copyr 1988 Sun Micro"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +/* + * Keyserver + * Store secret keys per uid. Do public key encryption and decryption + * operations. Generate "random" keys. Do not talk to anything but a local root + * process (by checking that the source port < IPPORT_RESERVED and by binding + * to the loopback address). + */ + +#include <stdio.h> +#include <sys/param.h> +#include <rpc/rpc.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <pwd.h> +#include <des_crypt.h> +#include <rpc/key_prot.h> + + +char ROOTKEY[] = "/etc/.rootkey"; + +extern long random(); + +extern keystatus pk_setkey(); +extern keystatus pk_encrypt(); +extern keystatus pk_decrypt(); + + +#ifdef DEBUG +int debugging = 1; +#else +int debugging = 0; +#endif + +static void keyprogram(); +des_block masterkey; + +main(argc, argv) + int argc; + char *argv[]; + +{ + SVCXPRT *transp; + int nflag; + + nflag = (argc == 2) && (strcmp(argv[1], "-n") == 0); + if (!(argc == 1 || nflag)) { + (void) fprintf(stderr, "usage: %s [-n]\n", argv[0]); + exit(1); + } + /* + * Initialize + */ + (void) umask(066); /* paranoia */ + if (geteuid() != 0) { + (void) fprintf(stderr, "%s must be run as root\n", argv[0]); + exit(1); + } + setmodulus(HEXMODULUS); + openstore(); + getrootkey(&masterkey, nflag); + readkeys(); + + /* + * create the service, register it, and run + */ + transp = svcudp_create(RPC_ANYSOCK); + if (transp == NULL) { + (void) fprintf(stderr, + "%s: unable to create udp service\n", argv[0]); + exit(1); + } + pmap_unset(KEY_PROG, KEY_VERS); + if (!svc_register(transp, KEY_PROG, KEY_VERS, keyprogram, + IPPROTO_UDP)) { + (void) fprintf(stderr, "%s: unable to register service\n", + argv[0]); + exit(1); + } + /* + * run + */ + if (!debugging) { + detachfromtty(); + } + svc_run(); + abort(); +} + +/* + * In the event that we don't get a root password, we try to randomize the + * master key the best we can + */ +randomize(master) + des_block *master; +{ + int i; + int seed; + struct timeval tv; + int shift; + + seed = 0; + for (i = 0; i < 1024; i++) { + (void) gettimeofday(&tv, (struct timezone *) NULL); + shift = i % 8 * sizeof(int); + seed ^= (tv.tv_usec << shift) | (tv.tv_usec >> (32 - shift)); + } + srandom(seed); + master->key.low = random(); + master->key.high = random(); + srandom(seed); +} + + + +/* + * Try to get root's secret key, by prompting if terminal is a tty, else trying + * from standard input. + */ +getrootkey(master, prompt) + des_block *master; + int prompt; +{ + char *getpass(); + char *passwd; + char name[MAXNETNAMELEN + 1]; + char secret[HEXKEYBYTES + 1]; + char *crypt(); + int fd; + + if (!prompt) { + /* + * Read secret key out of $ROOTKEY + */ + fd = open(ROOTKEY, O_RDONLY, 0); + if (fd < 0) { + randomize(master); + return (0); + } + if (read(fd, secret, HEXKEYBYTES) < 0) { + (void) fprintf(stderr, "Invalid %s\n", ROOTKEY); + (void) close(fd); + return (0); + } + (void) close(fd); + secret[HEXKEYBYTES] = 0; + } else { + /* + * Decrypt yellow pages entry to get secret key + */ + passwd = getpass("root password:"); + passwd2des(passwd, master); + getnetname(name); + if (!getsecretkey(name, secret, passwd)) { + (void) fprintf(stderr, + "Can't find %s's secret key\n", name); + return (0); + } + if (secret[0] == 0) { + (void) fprintf(stderr, + "Invalid password for %s\n", name); + return (0); + } + } + (void) pk_setkey(0, secret); + return (1); +} + + +/* + * Procedures to implement RPC service + */ + +char * +strstatus(status) + keystatus status; +{ + switch (status) { + case KEY_SUCCESS: + return ("KEY_SUCCESS"); + case KEY_NOSECRET: + return ("KEY_NOSECRET"); + case KEY_UNKNOWN: + return ("KEY_UNKNOWN"); + case KEY_SYSTEMERR: + return ("KEY_SYSTEMERR"); + default: + return ("(bad result code)"); + } +} + +keystatus * +key_set_1(uid, key) + short uid; + keybuf key; +{ + static keystatus status; + + if (debugging) { + (void) fprintf(stderr, "set(%d, %.*s) = ", uid, + sizeof(keybuf), key); + } + status = pk_setkey(uid, key); + if (debugging) { + (void) fprintf(stderr, "%s\n", strstatus(status)); + (void) fflush(stderr); + } + return (&status); +} + + + +cryptkeyres * +key_encrypt_1(uid, arg) + short uid; + cryptkeyarg *arg; +{ + static cryptkeyres res; + + if (debugging) { + (void) fprintf(stderr, "encrypt(%d, %s, %08x%08x) = ", uid, + arg->remotename, arg->deskey.key.high, + arg->deskey.key.low); + } + res.cryptkeyres_u.deskey = arg->deskey; + res.status = pk_encrypt(uid, arg->remotename, &res.cryptkeyres_u.deskey); + if (debugging) { + if (res.status == KEY_SUCCESS) { + (void) fprintf(stderr, "%08x%08x\n", + res.cryptkeyres_u.deskey.key.high, + res.cryptkeyres_u.deskey.key.low); + } else { + (void) fprintf(stderr, + "%s\n", strstatus(res.status)); + } + (void) fflush(stderr); + } + return (&res); +} + +cryptkeyres * +key_decrypt_1(uid, arg) + short uid; + cryptkeyarg *arg; +{ + static cryptkeyres res; + + if (debugging) { + (void) fprintf(stderr, "decrypt(%d, %s, %08x%08x) = ", uid, + arg->remotename, arg->deskey.key.high, + arg->deskey.key.low); + } + res.cryptkeyres_u.deskey = arg->deskey; + res.status = pk_decrypt(uid, arg->remotename, + &res.cryptkeyres_u.deskey); + if (debugging) { + if (res.status == KEY_SUCCESS) { + (void) fprintf(stderr, "%08x%08x\n", + res.cryptkeyres_u.deskey.key.high, + res.cryptkeyres_u.deskey.key.low); + } else { + (void) fprintf(stderr, "%s\n", strstatus(res.status)); + } + (void) fflush(stderr); + } + return (&res); +} + +des_block * +key_gen_1() +{ + struct timeval time; + static des_block keygen; + static des_block key; + + (void) gettimeofday(&time, (struct timezone *) NULL); + keygen.key.high += (time.tv_sec ^ time.tv_usec); + keygen.key.low += (time.tv_sec ^ time.tv_usec); + ecb_crypt(&masterkey, &keygen, sizeof(keygen), DES_ENCRYPT | DES_HW); + key = keygen; + des_setparity(&key); + if (debugging) { + (void) fprintf(stderr, "gen() = %08x%08x\n", key.key.high, + key.key.low); + (void) fflush(stderr); + } + return (&key); +} + +/* ARGSUSED */ +getcredres * +key_getcred_1(uid, name) + short uid; + netnamestr *name; +{ + static getcredres res; + static int gids[NGROUPS]; + struct unixcred *cred; + + cred = &res.getcredres_u.cred; + cred->gids.gids_val = gids; + if (!netname2user(*name, &cred->uid, &cred->gid, + &cred->gids.gids_len, gids)) { + res.status = KEY_UNKNOWN; + } else { + res.status = KEY_SUCCESS; + } + if (debugging) { + (void) fprintf(stderr, "getcred(%s) = ", *name); + if (res.status == KEY_SUCCESS) { + (void) fprintf(stderr, "uid=%d,gid=%d,grouplen=%d\n", + cred->uid, cred->gid, cred->gids.gids_len); + } else { + (void) fprintf(stderr, "%s\n", strstatus(res.status)); + } + (void) fflush(stderr); + } + return (&res); +} + + +/* + * RPC boilerplate + */ +static void +keyprogram(rqstp, transp) + struct svc_req *rqstp; + SVCXPRT *transp; +{ + union { + keybuf key_set_1_arg; + cryptkeyarg key_encrypt_1_arg; + cryptkeyarg key_decrypt_1_arg; + des_block key_gen_1_arg; + } argument; + char *result; + + bool_t(*xdr_argument) (), (*xdr_result) (); + char *(*local) (); + struct sockaddr_in remote; + int uid; + int check_auth; + + switch (rqstp->rq_proc) { + case NULLPROC: + svc_sendreply(transp, xdr_void, (char *) NULL); + return; + + case KEY_SET: + xdr_argument = xdr_keybuf; + xdr_result = xdr_int; + local = (char *(*)()) key_set_1; + check_auth = 1; + break; + + case KEY_ENCRYPT: + xdr_argument = xdr_cryptkeyarg; + xdr_result = xdr_cryptkeyres; + local = (char *(*)()) key_encrypt_1; + check_auth = 1; + break; + + case KEY_DECRYPT: + xdr_argument = xdr_cryptkeyarg; + xdr_result = xdr_cryptkeyres; + local = (char *(*)()) key_decrypt_1; + check_auth = 1; + break; + + case KEY_GEN: + xdr_argument = xdr_void; + xdr_result = xdr_des_block; + local = (char *(*)()) key_gen_1; + check_auth = 0; + break; + + case KEY_GETCRED: + xdr_argument = xdr_netnamestr; + xdr_result = xdr_getcredres; + local = (char *(*)()) key_getcred_1; + check_auth = 0; + break; + + default: + svcerr_noproc(transp); + return; + } + if (check_auth) { + remote = *svc_getcaller(transp); + if (ntohs(remote.sin_port) >= IPPORT_RESERVED || + ntohl(remote.sin_addr.s_addr) != INADDR_LOOPBACK) { + if (debugging) { + (void) fprintf(stderr, + "not local privileged process\n"); + } + svcerr_weakauth(transp); + return; + } + if (rqstp->rq_cred.oa_flavor != AUTH_UNIX) { + if (debugging) { + (void) fprintf(stderr, + "not unix authentication\n"); + } + svcerr_weakauth(transp); + return; + } + uid = ((struct authunix_parms *) rqstp->rq_clntcred)->aup_uid; + } + bzero((char *) &argument, sizeof(argument)); + if (!svc_getargs(transp, xdr_argument, &argument)) { + svcerr_decode(transp); + return; + } + result = (*local) (uid, &argument); + if (!svc_sendreply(transp, xdr_result, (char *) result)) { + (void) fprintf(stderr, "unable to reply\n"); + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, xdr_argument, &argument)) { + (void) fprintf(stderr, "unable to free arguments\n"); + exit(1); + } +} diff --git a/lib/librpc/secure_rpc/keyserv/mp.c b/lib/librpc/secure_rpc/keyserv/mp.c new file mode 100644 index 0000000..97c85b0 --- /dev/null +++ b/lib/librpc/secure_rpc/keyserv/mp.c @@ -0,0 +1,145 @@ +#ifndef lint +static char sccsid[] = "@(#)mp.c 2.1 88/08/15 4.0 RPCSRC Copyr 1988 Sun Micro"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * These routines add hexadecimal functionality to the multiple-precision + * library. + */ +#include <stdio.h> +#include <mp.h> + +void mfree(); + +/* + * Convert hex digit to binary value + */ +static int +xtoi(c) + char c; +{ + if (c >= '0' && c <= '9') { + return(c - '0'); + } else if (c >= 'a' && c <= 'f') { + return(c - 'a' + 10); + } else { + return(-1); + } +} + +/* + * Convert hex key to MINT key + */ +MINT * +xtom(key) + char *key; +{ + int digit; + MINT *m = itom(0); + MINT *d; + MINT *sixteen; + sixteen = itom(16); + for (; *key; key++) { + digit = xtoi(*key); + if (digit < 0) { + return(NULL); + } + d = itom(digit); + mult(m,sixteen,m); + madd(m,d,m); + mfree(d); + } + mfree(sixteen); + return(m); +} +static char +itox(d) + short d; +{ + d &= 15; + if (d < 10) { + return('0' + d); + } else { + return('a' - 10 + d); + } +} +/* + * Convert MINT key to hex key + */ +char * +mtox(key) + MINT *key; +{ + MINT *m = itom(0); + MINT *zero = itom(0); + short r; + char *p; + char c; + char *s; + char *hex; + int size; +#define BASEBITS (8*sizeof(short) - 1) + if (key->len >= 0) { + size = key->len; + } else { + size = -key->len; + } + hex = malloc((unsigned) ((size * BASEBITS + 3)) / 4 + 1); + if (hex == NULL) { + return(NULL); + } + move(key,m); + p = hex; + do { + sdiv(m,16,m,&r); + *p++ = itox(r); + } while (mcmp(m,zero) != 0); + mfree(m); + mfree(zero); + *p = 0; + for (p--, s = hex; s < p; s++, p--) { + c = *p; + *p = *s; + *s = c; + } + return(hex); +} +/* + * Deallocate a multiple precision integer + */ +void +mfree(a) + MINT *a; +{ + xfree(a); + free((char *)a); +} + diff --git a/lib/librpc/secure_rpc/keyserv/setkey.c b/lib/librpc/secure_rpc/keyserv/setkey.c new file mode 100644 index 0000000..d62dc9c --- /dev/null +++ b/lib/librpc/secure_rpc/keyserv/setkey.c @@ -0,0 +1,514 @@ +#ifndef lint +static char sccsid[] = "@(#)setkey.c 2.2 88/08/10 4.0 RPCSRC; from Copyr 1988 Sun Micro"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +/* + * Do the real work of the keyserver . + * Store secret keys. Compute common keys, + * and use them to decrypt and encrypt DES keys . + * Cache the common keys, so the + * expensive computation is avoided. + */ +#include <stdio.h> +#include <sys/file.h> +#include <mp.h> +#include <rpc/rpc.h> +#include <rpc/key_prot.h> +#include <des_crypt.h> +#include <sys/errno.h> + +extern char *malloc(); +extern char ROOTKEY[]; + +static MINT *MODULUS; +static char *fetchsecretkey(); +static keystatus pk_crypt(); + + +/* + * Set the modulus for all our Diffie-Hellman operations + */ +setmodulus(modx) + char *modx; +{ + MODULUS = xtom(modx); +} + + +/* + * Set the secretkey key for this uid + */ +keystatus +pk_setkey(uid, skey) + short uid; + keybuf skey; +{ + if (!storesecretkey(uid, skey)) { + return (KEY_SYSTEMERR); + } + return (KEY_SUCCESS); +} + + +/* + * Encrypt the key using the public key associated with remote_name and the + * secret key associated with uid. + */ +keystatus +pk_encrypt(uid, remote_name, key) + short uid; + char *remote_name; + des_block *key; +{ + return (pk_crypt(uid, remote_name, key, DES_ENCRYPT)); +} + + +/* + * Decrypt the key using the public key associated with remote_name and the + * secret key associated with uid. + */ +keystatus +pk_decrypt(uid, remote_name, key) + short uid; + char *remote_name; + des_block *key; +{ + return (pk_crypt(uid, remote_name, key, DES_DECRYPT)); +} + + +/* + * Do the work of pk_encrypt && pk_decrypt + */ +static keystatus +pk_crypt(uid, remote_name, key, mode) + short uid; + char *remote_name; + des_block *key; + int mode; +{ + char *xsecret; + char xpublic[HEXKEYBYTES + 1]; + char xsecret_hold[HEXKEYBYTES + 1]; + des_block deskey; + int err; + MINT *public; + MINT *secret; + MINT *common; + char zero[8]; + + xsecret = fetchsecretkey(uid); + if (xsecret == NULL) { + bzero(zero, sizeof(zero)); + xsecret = xsecret_hold; + if (!getsecretkey("nobody", xsecret, zero) || + xsecret[0] == 0) { + return (KEY_NOSECRET); + } + } + if (!getpublickey(remote_name, xpublic) && + !getpublickey("nobody", xpublic)) { + return (KEY_UNKNOWN); + } + if (!readcache(xpublic, xsecret, &deskey)) { + public = xtom(xpublic); + secret = xtom(xsecret); + common = itom(0); + pow(public, secret, MODULUS, common); + extractdeskey(common, &deskey); + writecache(xpublic, xsecret, &deskey); + mfree(secret); + mfree(public); + mfree(common); + } + err = ecb_crypt(&deskey, key, sizeof(des_block), DES_HW | mode); + if (DES_FAILED(err)) { + return (KEY_SYSTEMERR); + } + return (KEY_SUCCESS); +} + + +/* + * Choose middle 64 bits of the common key to use as our des key, possibly + * overwriting the lower order bits by setting parity. + */ +static +extractdeskey(ck, deskey) + MINT *ck; + des_block *deskey; +{ + MINT *a; + short r; + int i; + short base = (1 << 8); + char *k; + + + a = itom(0); + move(ck, a); + for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { + sdiv(a, base, a, &r); + } + k = deskey->c; + for (i = 0; i < 8; i++) { + sdiv(a, base, a, &r); + *k++ = r; + } + mfree(a); + des_setparity(deskey); +} + + +/* + * Key storage management + */ + +struct secretkey_list { + short uid; + char secretkey[HEXKEYBYTES+1]; + struct secretkey_list *next; +}; + +static struct secretkey_list *g_secretkeys; + +/* + * Fetch the secret key for this uid + */ +static char * +fetchsecretkey(uid) + short uid; +{ + struct secretkey_list *l; + + for (l = g_secretkeys; l != NULL; l = l->next) { + if (l->uid == uid) { + return (l->secretkey); + } + } + return (NULL); +} + +/* + * Store the secretkey for this uid + */ +storesecretkey(uid, key) + short uid; + keybuf key; +{ + struct secretkey_list *new; + struct secretkey_list **l; + int nitems; + + + nitems = 0; + for (l = &g_secretkeys; *l != NULL && (*l)->uid != uid; + l = &(*l)->next) { + nitems++; + } + if (*l == NULL) { + new = (struct secretkey_list *)malloc(sizeof(*new)); + if (new == NULL) { + return (0); + } + new->uid = uid; + new->next = NULL; + *l = new; + } else { + new = *l; + } + bcopy(key, new->secretkey, HEXKEYBYTES); + new->secretkey[HEXKEYBYTES] = 0; + seekitem(nitems); + writeitem(uid, new->secretkey); + return (1); +} + + +hexdigit(val) + int val; +{ + return ("0123456789abcdef"[val]); + +} +bin2hex(bin, hex, size) + unsigned char *bin; + unsigned char *hex; + int size; +{ + int i; + + for (i = 0; i < size; i++) { + *hex++ = hexdigit(*bin >> 4); + *hex++ = hexdigit(*bin++ & 0xf); + } +} + +hexval(dig) + char dig; +{ + if ('0' <= dig && dig <= '9') { + return (dig - '0'); + } else if ('a' <= dig && dig <= 'f') { + return (dig - 'a' + 10); + } else if ('A' <= dig && dig <= 'F') { + return (dig - 'A' + 10); + } else { + return (-1); + } +} + +hex2bin(hex, bin, size) + unsigned char *hex; + unsigned char *bin; + int size; +{ + int i; + + for (i = 0; i < size; i++) { + *bin = hexval(*hex++) << 4; + *bin++ |= hexval(*hex++); + } +} + +static char KEYSTORE[] = "/etc/keystore"; +FILE *kf; + +openstore() +{ + kf = fopen(KEYSTORE, "r+"); + if (kf == NULL) { + kf = fopen(KEYSTORE, "w+"); + if (kf == NULL) { + return (0); + } + } + setbuf(kf, NULL); + return (1); +} + +static char rootkey[KEYBYTES]; +static int haverootkey; +struct storedkey { + short uid; + char crypt[KEYBYTES]; +}; + +readkeys() +{ + struct secretkey_list *node; + struct secretkey_list **l; + int uid; + char secretkey[HEXKEYBYTES+1]; + + if (kf == NULL) { + return; + } + l = &g_secretkeys; + seekitem(0); + while (readitem(&uid, secretkey)) { + node = (struct secretkey_list *)malloc(sizeof(*node)); + if (node == NULL) { + return; + } + node->uid = uid; + bcopy(secretkey, node->secretkey, HEXKEYBYTES + 1); + node->next = NULL; + *l = node; + l = &node->next; + } +} + +writekeys() +{ + struct secretkey_list *k; + + seekitem(0); + for (k = g_secretkeys; k != NULL; k = k->next) { + writeitem(k->uid, k->secretkey); + } +} + +seekitem(item) + int item; +{ + if (kf != NULL) { + fseek(kf, item * sizeof(struct storedkey), 0); + } +} + +writeitem(uid, key) + int uid; + char *key; +{ + struct storedkey item; + char rootkey_tmp[KEYBYTES]; + int reencrypt; + + if (kf == NULL) { + return (1); + } + if (uid == 0) { + writerootkey(key); + hex2bin(key, rootkey_tmp, KEYBYTES); + reencrypt = (haverootkey && + bcmp(rootkey, rootkey_tmp, KEYBYTES) != 0); + bcopy(rootkey_tmp, rootkey, KEYBYTES); + haverootkey = 1; + if (reencrypt) { + writekeys(); + return (1); + } + } + if (!haverootkey) { + return (1); + } + item.uid = uid; + hex2bin(key, item.crypt, KEYBYTES); + ecb_crypt(rootkey, item.crypt, KEYBYTES, DES_ENCRYPT|DES_HW); + return (fwrite(&item, sizeof(item), 1, kf) >= 0); +} + + +readitem(uidp, key) + int *uidp; + char *key; +{ + struct storedkey item; + + if (!haverootkey || kf == NULL) { + return (0); + } + if (fread(&item, sizeof(item), 1, kf) != 1) { + return (0); + } + *uidp = item.uid; + ecb_crypt(rootkey, item.crypt, KEYBYTES, DES_DECRYPT|DES_HW); + bin2hex(item.crypt, key, KEYBYTES); + key[HEXKEYBYTES] = 0; + return (1); +} + +/* + * Root users store their key in /etc/$ROOTKEY so + * that they can auto reboot without having to be + * around to type a password. Storing this in a file + * is rather dubious: it should really be in the EEPROM + * so it does not go over the net for diskless machines. + */ +writerootkey(secret) + char *secret; +{ + char newline = '\n'; + int fd; + + fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0); + if (fd < 0) { + perror(ROOTKEY); + } else { + if (write(fd, secret, strlen(secret)) < 0 || + write(fd, &newline, sizeof(newline)) < 0) { + (void)fprintf(stderr, "%s: ", ROOTKEY); + perror("write"); + } + close(fd); + } +} + + +/* + * Exponential caching management + */ +struct cachekey_list { + keybuf secret; + keybuf public; + des_block deskey; + struct cachekey_list *next; +}; +static struct cachekey_list *g_cachedkeys; + + +/* + * cache result of expensive multiple precision exponential operation + */ +static +writecache(pub, sec, deskey) + char *pub; + char *sec; + des_block *deskey; +{ + struct cachekey_list *new; + + new = (struct cachekey_list *) malloc(sizeof(struct cachekey_list)); + if (new == NULL) { + return; + } + bcopy(pub, new->public, sizeof(keybuf)); + bcopy(sec, new->secret, sizeof(keybuf)); + new->deskey = *deskey; + new->next = g_cachedkeys; + g_cachedkeys = new; +} + +/* + * Try to find the common key in the cache + */ +static +readcache(pub, sec, deskey) + char *pub; + char *sec; + des_block *deskey; +{ + struct cachekey_list *found; + register struct cachekey_list **l; + +#define cachehit(pub, sec, list) \ + (bcmp(pub, (list)->public, sizeof(keybuf)) == 0 && \ + bcmp(sec, (list)->secret, sizeof(keybuf)) == 0) + + for (l = &g_cachedkeys; + (*l) != NULL && !cachehit(pub, sec, *l); + l = &(*l)->next); + if ((*l) == NULL) { + return (0); + } + found = *l; + (*l) = (*l)->next; + found->next = g_cachedkeys; + g_cachedkeys = found; + *deskey = found->deskey; + return (1); +} diff --git a/lib/librpc/secure_rpc/man/chkey.1 b/lib/librpc/secure_rpc/man/chkey.1 new file mode 100644 index 0000000..fbf1fcd --- /dev/null +++ b/lib/librpc/secure_rpc/man/chkey.1 @@ -0,0 +1,19 @@ +.\" @(#)chkey.1 2.1 88/08/10 4.0 RPCSRC; from 1.6 88/02/29 SMI; +.TH CHKEY 1 "9 September 1987" +.SH NAME +chkey \- change your encryption key +.SH SYNOPSIS +.B chkey +.SH DESCRIPTION +.IX "chkey command" "" "\fLchkey\fP command" +.IX "encryption key, change, \fLchkey\fR command" +.B chkey +prompts the user for their login password, and uses it to encrypt +a new encryption key for the user to be stored in the +.BR publickey (5) +database. +.SH "SEE ALSO" +.BR keylogin (1), +.BR publickey (5), +.BR keyserv (8C), +.BR newkey (8) diff --git a/lib/librpc/secure_rpc/man/des_crypt.3 b/lib/librpc/secure_rpc/man/des_crypt.3 new file mode 100644 index 0000000..ca0a33e --- /dev/null +++ b/lib/librpc/secure_rpc/man/des_crypt.3 @@ -0,0 +1,126 @@ +.\" @(#)des_crypt.3 2.1 88/08/11 4.0 RPCSRC; from 1.16 88/03/02 SMI; +.TH DES_CRYPT 3 "6 October 1987" +.SH NAME +des_crypt, ecb_crypt, cbc_crypt, des_setparity \- fast DES encryption +.SH SYNOPSIS +.nf +.B #include <des_crypt.h> +.LP +.B int ecb_crypt(key, data, datalen, mode) +.B char *key; +.B char *data; +.B unsigned datalen; +.B unsigned mode; +.LP +.B int cbc_crypt(key, data, datalen, mode, ivec) +.B char *key; +.B char *data; +.B unsigned datalen; +.B unsigned mode; +.B char *ivec; +.LP +.B void des_setparity(key) +.B char *key; +.fi +.SH DESCRIPTION +.IX encryption cbc_crypt "" \fLcbc_crypt\fP +.IX "des encryption" cbc_crypt "DES encryption" \fLcbc_crypt\fP +.IX encryption des_setparity "" \fLdes_setparity\fP +.IX "des encryption" des_setparity "DES encryption" \fLdes_setparity\fP +.B ecb_crypt(\|) +and +.B cbc_crypt(\|) +implement the +.SM NBS +.SM DES +(Data Encryption Standard). +These routines are faster and more general purpose than +.BR crypt (3). +They also are able to utilize +.SM DES +hardware if it is available. +.B ecb_crypt(\|) +encrypts in +.SM ECB +(Electronic Code Book) +mode, which encrypts blocks of data independently. +.B cbc_crypt(\|) +encrypts in +.SM CBC +(Cipher Block Chaining) +mode, which chains together +successive blocks. +.SM CBC +mode protects against insertions, deletions and +substitutions of blocks. Also, regularities in the clear text will +not appear in the cipher text. +.LP +Here is how to use these routines. The first parameter, +.IR key , +is the 8-byte encryption key with parity. +To set the key's parity, which for +.SM DES +is in the low bit of each byte, use +.IR des_setparity . +The second parameter, +.IR data , +contains the data to be encrypted or decrypted. The +third parameter, +.IR datalen , +is the length in bytes of +.IR data , +which must be a multiple of 8. The fourth parameter, +.IR mode , +is formed by +.SM OR\s0'ing +together some things. For the encryption direction 'or' in either +.SM DES_ENCRYPT +or +.SM DES_DECRYPT\s0. +For software versus hardware +encryption, 'or' in either +.SM DES_HW +or +.SM DES_SW\s0. +If +.SM DES_HW +is specified, and there is no hardware, then the encryption is performed +in software and the routine returns +.SM DESERR_NOHWDEVICE\s0. +For +.IR cbc_crypt , +the parameter +.I ivec +is the the 8-byte initialization +vector for the chaining. It is updated to the next initialization +vector upon return. +.LP +.SH "SEE ALSO" +.BR des (1), +.BR crypt (3) +.SH DIAGNOSTICS +.PD 0 +.TP 20 +.SM DESERR_NONE +No error. +.TP +.SM DESERR_NOHWDEVICE +Encryption succeeded, but done in software instead of the requested hardware. +.TP +.SM DESERR_HWERR +An error occurred in the hardware or driver. +.TP +.SM DESERR_BADPARAM +Bad parameter to routine. +.PD +.LP +Given a result status +.IR stat , +the macro +.SM DES_FAILED\c +.BR ( stat ) +is false only for the first two statuses. +.SH RESTRICTIONS +These routines are not available in RPCSRC 4.0. +This information is provided to describe the DES interface expected by +Secure RPC. diff --git a/lib/librpc/secure_rpc/man/keyenvoy.8c b/lib/librpc/secure_rpc/man/keyenvoy.8c new file mode 100644 index 0000000..8cf7bc3 --- /dev/null +++ b/lib/librpc/secure_rpc/man/keyenvoy.8c @@ -0,0 +1,22 @@ +.\" @(#)keyenvoy.8c 2.1 88/08/10 4.0 RPCSRC; from 1.5 88/03/01 SMI; +.TH KEYENVOY 8C "9 September 1987" +.SH NAME +keyenvoy \- talk to keyserver +.SH SYNOPSIS +.B keyenvoy +.SH DESCRIPTION +.IX "keyenvoy command" "" "\fLkeyenvoy\fP command" +.B keyenvoy +is used by some +.SM RPC +programs to talk to the key server, +.BR keyserv (8C). +The key server will not talk to anything but a root process, and +.B keyenvoy +is a set-uid root process that acts as an intermediary between a user +process that wishes to talk to the +key server and the key server itself. +.LP +This program cannot be run interactively. +.SH "SEE ALSO" +.BR keyserv (8C) diff --git a/lib/librpc/secure_rpc/man/keylogin.1 b/lib/librpc/secure_rpc/man/keylogin.1 new file mode 100644 index 0000000..516d9de --- /dev/null +++ b/lib/librpc/secure_rpc/man/keylogin.1 @@ -0,0 +1,32 @@ +.\" @(#)keylogin.1 2.1 88/08/10 4.0 RPCSRC; from 1.6 88/02/29 SMI; +.TH KEYLOGIN 1 "9 September 1987" +.SH NAME +keylogin \- decrypt and store secret key +.SH SYNOPSIS +.B keylogin +.SH DESCRIPTION +.IX "keylogin command" "" "\fLkeylogin\fR command" +.LP +.B keylogin +prompts the user for their login password, and uses it do decrypt +the user's secret key stored in the +.BR publickey (5) +database. Once decrypted, the user's key is stored by the local +key server process +.BR keyserv (8C) +to be used by any secure network services, such as +.SM NFS\s0. +.LP +Normally, +.BR login (1) +does this work when the user logs onto the system, but running +.B keylogin +may be necessary if +the user did not type a password to +.BR login (1). +.SH "SEE ALSO" +.BR chkey (1), +.BR login (1), +.BR publickey (5), +.BR keyserv (8C), +.BR newkey (8) diff --git a/lib/librpc/secure_rpc/man/keyserv.8c b/lib/librpc/secure_rpc/man/keyserv.8c new file mode 100644 index 0000000..aa153ed --- /dev/null +++ b/lib/librpc/secure_rpc/man/keyserv.8c @@ -0,0 +1,52 @@ +.\" @(#)keyserv.8c 2.1 88/08/10 4.0 RPCSRC; from 1.6 88/03/01 SMI; +.TH KEYSERV 8C "9 September 1987" +.SH NAME +keyserv \- server for storing public and private keys +.SH SYNOPSIS +.B keyserv +[ +.B \-n +] +.SH DESCRIPTION +.IX "keyenvoy server" "" "\fLkeyenvoy\fP server" +.B keyserv +is a daemon that is used for storing the +private encryption keys of each +user logged into the system. These encryption +keys are using for accessing +secure network services such as secure +.SM NFS\s0. +When a user logs in to the system, the +.BR login(1) +program uses the login password to decrypt +the user's encryption key stored +in the Yellow Pages, and then gives the decrypted key to the +.B keyserv +daemon to store away. +.LP +Normally, root's key is read from the file +.B /etc/.rootkey +when the daemon starts up. This is useful during power-fail reboots +when no one is around to type a password, yet you still want the +secure network services to operate normally. +.SH OPTIONS +.TP +.B \-n +Do not read root's key from +.BR /etc/.rootkey . +Instead, prompt the user for the password to decrypt +.B root 's +key stored in the Yellow Pages and then store the decrypted key in +.B /etc/.rootkey +for future use. +This option is useful if the +.B /etc/.rootkey +file ever gets out of date or corrupted. +.SH FILES +.PD 0 +.TP 20 +.B /etc/.rootkey +.PD +.SH "SEE ALSO" +.BR login (1), +.BR publickey (5) diff --git a/lib/librpc/secure_rpc/man/publickey.3r b/lib/librpc/secure_rpc/man/publickey.3r new file mode 100644 index 0000000..7063e8a --- /dev/null +++ b/lib/librpc/secure_rpc/man/publickey.3r @@ -0,0 +1,44 @@ +.\" @(#)publickey.3r 2.1 88/08/07 4.0 RPCSRC +.TH PUBLICKEY 3R "6 October 1987" +.SH NAME +publickey, getpublickey, getsecretkey \- get public or secret key +.SH SYNOPSIS +.nf +.B #include <rpc/rpc.h> +.B #include <rpc/key_prot.h> +.LP +.B getpublickey(netname, publickey) +.B char netname[\s-1MAXNETNAMELEN\s0+1]; +.B char publickey[\s-1HEXKEYBYTES\s0+1]; +.LP +.B getsecretkey(netname, secretkey, passwd) +.B char netname[\s-1MAXNETNAMELEN\s0+1]; +.B char secretkey[\s-1HEXKEYBYTES\s0+1]; +.B char *passwd; +.fi +.SH DESCRIPTION +.IX "getpublickey function" "" "\fLgetpublickey()\fP function" +.IX "getsecretkey function" "" "\fLgetsecretkey()\fP function" +These routines are used to get public and secret keys from the +.SM YP +database. +.B getsecretkey(\|) +has an extra argument, +.IR passwd , +which is used to decrypt the encrypted secret key stored in the database. +Both routines return 1 if they are successful in finding the key, 0 otherwise. +The keys are returned as +.SM NULL\s0-terminated, +hexadecimal strings. If the password supplied to +.B getsecretkey(\|) +fails to decrypt the secret key, the routine will return 1 but the +.I secretkey +argument will be a +.SM NULL +string (``''). +.SH "SEE ALSO" +.BR publickey (5) +.LP +.I \s-1RPC\s0 Programmer's Manual +in +.TX NETP diff --git a/lib/librpc/secure_rpc/man/publickey.5 b/lib/librpc/secure_rpc/man/publickey.5 new file mode 100644 index 0000000..de3c1e9 --- /dev/null +++ b/lib/librpc/secure_rpc/man/publickey.5 @@ -0,0 +1,37 @@ +.\" @(#)publickey.5 2.1 88/08/07 4.0 RPCSRC; from 1.6 88/02/29 SMI; +.TH PUBLICKEY 5 "19 October 1987" +.SH NAME +publickey \- public key database +.SH SYNOPSIS +.B /etc/publickey +.SH DESCRIPTION +.LP +.B /etc/publickey +is the public key database used for secure +networking. Each entry in +the database consists of a network user +name (which may either refer to +a user or a hostname), followed by the user's +public key (in hex +notation), a colon, and then the user's +secret key encrypted with +its login password (also in hex notation). +.LP +This file is altered either by the user through the +.BR chkey (1) +command or by the system administrator through the +.BR newkey (8) +command. +The file +.B /etc/publickey +should only contain data on the Yellow +Pages master machine, where it +is converted into the +.SM YP +database +.BR publickey.byname . +.SH SEE ALSO +.BR chkey (1), +.BR publickey (3R), +.BR newkey (8), +.BR ypupdated (8C) diff --git a/lib/librpc/secure_rpc/man/rpc_secure.3n b/lib/librpc/secure_rpc/man/rpc_secure.3n new file mode 100644 index 0000000..6e9a2ee --- /dev/null +++ b/lib/librpc/secure_rpc/man/rpc_secure.3n @@ -0,0 +1,330 @@ +.\" @(#)rpc_secure.3n 2.1 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI +.TH RPC 3N "16 February 1988" +.SH NAME +rpc_secure \- library routines for secure remote procedure calls +.SH SYNOPSIS AND DESCRIPTION +These routines are part of the RPC library. They implement DES +Authentication. See +.BR rpc (3N) +for further details about RPC. +.LP +.ft B +.nf +.sp .5 +#include <rpc/rpc.h> +.fi +.ft R +.br +.if t .ne 22 +.LP +.ft B +.nf +.sp .5 +\s-1AUTH\s0 * +authdes_create(name, window, syncaddr, ckey) +char *name; +unsigned window; +struct sockaddr_in *addr; +des_block *ckey; +.fi +.ft R +.IP +.B authdes_create(\|) +is the first of two routines which interface to the +.SM RPC +secure authentication system, known as +.SM DES +authentication. +The second is +.BR authdes_getucred(\|) , +below. Note: the keyserver daemon +.BR keyserv (8C) +must be running for the +.SM DES +authentication system to work. +.IP +.BR authdes_create(\|) , +used on the client side, returns an authentication handle that +will enable the use of the secure authentication system. +The first parameter +.I name +is the network name, or +.IR netname , +of the owner of the server process. This field usually +represents a +.I hostname +derived from the utility routine +.BR host2netname , +but could also represent a user name using +.BR user2netname . +The second field is window on the validity of +the client credential, given in seconds. A small +window is more secure than a large one, but choosing +too small of a window will increase the frequency of +resynchronizations because of clock drift. The third +parameter +.I syncaddr +is optional. If it is +.SM NULL\s0, +then the authentication system will assume +that the local clock is always in sync with the server's +clock, and will not attempt resynchronizations. If an address +is supplied, however, then the system will use the address +for consulting the remote time service whenever +resynchronization +is required. This parameter is usually the +address of the +.SM RPC +server itself. The final parameter +.I ckey +is also optional. If it is +.SM NULL\s0, +then the authentication system will +generate a random +.SM DES +key to be used for the encryption of credentials. +If it is supplied, however, then it will be used instead. +.br +.if t .ne 13 +.LP +.ft B +.nf +.sp .5 +authdes_getucred(adc, uid, gid, grouplen, groups) +struct authdes_cred *adc; +short *uid; +short *gid; +short *grouplen; +int *groups; +.fi +.ft R +.IP +.BR authdes_getucred(\|) , +the second of the two +.SM DES +authentication routines, +is used on the server side for converting a +.SM DES +credential, which is +operating system independent, into a +.UX +credential. This routine differs from utility routine +.B netname2user +in that +.B authdes_getucred(\|) +pulls its information from a cache, and does not have to do a +Yellow Pages lookup every time it is called to get its information. +.br +.ft .ne 8 +.LP +.ft B +.nf +.sp .5 +host2netname(name, host, domain) +char *name; +char *host; +char *domain; +.fi +.ft R +.IP +Convert from a domain-specific hostname to an +operating-system independent netname. Return +.SM TRUE +if it succeeds and +.SM FALSE +if it fails. Inverse of +.BR netname2host(\|) . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +key_decryptsession(remotename, deskey) +char *remotename; +des_block *deskey; +.fi +.ft R +.IP +.B key_decryptsession(\|) +is an interface to the keyserver daemon, which is associated +with +.SM RPC\s0's +secure authentication system (\s-1DES\s0 +authentication). +User programs rarely need to call it, or its associated routines +.BR key_encryptsession(\|) , +.B key_gendes(\|) +and +.BR key_setsecret(\|) . +System commands such as +.B login +and the +.SM RPC +library are the main clients of these four routines. +.IP +.B key_decryptsession(\|) +takes a server netname and a des key, and decrypts the key by +using the the public key of the the server and the secret key +associated with the effective uid of the calling process. It +is the inverse of +.BR key_encryptsession(\|) . +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +key_encryptsession(remotename, deskey) +char *remotename; +des_block *deskey; +.fi +.ft R +.IP +.B key_encryptsession(\|) +is a keyserver interface routine. It +takes a server netname and a des key, and encrypts +it using the public key of the the server and the secret key +associated with the effective uid of the calling process. It +is the inverse of +.BR key_decryptsession(\|) . +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +key_gendes(deskey) +des_block *deskey; +.fi +.ft R +.IP +.B key_gendes(\|) +is a keyserver interface routine. It +is used to ask the keyserver for a secure conversation key. +Choosing one at \(lqrandom\(rq is usually not good enough, +because +the common ways of choosing random numbers, such as using the +current time, are very easy to guess. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +key_setsecret(key) +char *key; +.fi +.ft R +.IP +.B key_setsecret(\|) +is a keyserver interface routine. It is used to set the key for +the effective +.I uid +of the calling process. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +getnetname(name) +char name[\s-1MAXNETNAMELEN\s0]; +.fi +.ft R +.IP +.B getnetname(\|) +installs the unique, operating-system independent netname of +the +caller in the fixed-length array +.IR name . +Returns +.SM TRUE +if it succeeds and +.SM FALSE +if it fails. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +netname2host(name, host, hostlen) +char *name; +char *host; +int hostlen; +.fi +.ft R +.IP +Convert from an operating-system independent netname to a +domain-specific hostname. Returns +.SM TRUE +if it succeeds and +.SM FALSE +if it fails. Inverse of +.BR host2netname(\|) . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +netname2user(name, uidp, gidp, gidlenp, gidlist) +char *name; +int *uidp; +int *gidp; +int *gidlenp; +int *gidlist; +.fi +.ft R +.IP +Convert from an operating-system independent netname to a +domain-specific user +.SM ID. +Returns +.SM TRUE +if it succeeds and +.SM FALSE +if it fails. Inverse of +.BR user2netname(\|) . +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +user2netname(name, uid, domain) +char *name; +int uid; +char *domain; +.fi +.ft R +.IP +Convert from a domain-specific username to an operating-system +independent netname. Returns +.SM TRUE +if it succeeds and +.SM FALSE +if it fails. Inverse of +.BR netname2user(\|) . +.br +.SH SEE ALSO +.BR xdr (3N), +.BR keyserv (8C), +.BR rpc (3N) +.br +The following manuals: +.RS +.ft I +Remote Procedure Calls: Protocol Specification +.br +Remote Procedure Call Programming Guide +.br +rpcgen Programming Guide +.br +.ft R +.RE +.IR "\s-1RPC\s0: Remote Procedure Call Protocol Specification" , +.SM RFC1050, Sun Microsystems, Inc., +.SM USC-ISI\s0. + diff --git a/lib/librpc/secure_rpc/man/rtime.3n b/lib/librpc/secure_rpc/man/rtime.3n new file mode 100644 index 0000000..af0c1ca --- /dev/null +++ b/lib/librpc/secure_rpc/man/rtime.3n @@ -0,0 +1,43 @@ +.\" @(#)rtime.3n 2.1 88/08/08 4.0 RPCSRC; from 1.5 88/02/08 SMI +.TH RTIME 3 "22 November 1987" +.SH NAME +rtime \- get remote time +.SH SYNOPSIS +.nf +.B #include <sys/types.h> +.B #include <sys/time.h> +.B #include <netinet/in.h> +.LP +.B int rtime(addrp, timep, timeout) +.B struct sockaddr_in \(**addrp; +.B struct timeval \(**timep; +.B struct timeval \(**timeout; +.fi +.SH DESCRIPTION +.B rtime(\|) +consults the Internet Time Server at the address pointed to by +.I addrp +and returns the remote time in the +.B timeval +struct pointed to by +.IR timep . +Normally, the +.SM UDP +protocol is used when consulting the Time Server. The +.I timeout +parameter specifies how long the +routine should wait before giving +up when waiting for a reply. If +.I timeout +is specified as +.SM NULL\s0, +however, the routine will instead use +.SM TCP +and block until a reply is received from the time server. +.LP +The routine returns 0 if it is successful. Otherwise, +it returns \-1 and +.B errno +is set to reflect the cause of the error. +.SH "SEE ALSO" +.BR timed (8c) diff --git a/lib/librpc/secure_rpc/rpc/Makefile b/lib/librpc/secure_rpc/rpc/Makefile new file mode 100644 index 0000000..88b242f --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/Makefile @@ -0,0 +1,109 @@ +# +# @(#)Makefile 2.3 88/08/15 4.0 RPCSRC +# +# +# Copyright (c) 1987 by Sun Microsystems, Inc. +# + +DESTDIR= + +CFLAGS = -I.. + +SRCS = auth_des.c authdes_prot.c key_call.c key_prot.c netname.c svcauth_des.c \ + openchild.c rtime.c publickey.c xcrypt.c \ + auth_none.c auth_unix.c authunix_prot.c bindresvport.c \ + clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \ + clnt_udp.c rpc_dtablesize.c get_myaddress.c getrpcent.c getrpcport.c \ + pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \ + pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \ + svc.c svc_auth.c svc_auth_unix.c svc_raw.c svc_run.c svc_simple.c \ + svc_tcp.c svc_udp.c xdr.c xdr_array.c xdr_float.c xdr_mem.c \ + xdr_rec.c xdr_reference.c xdr_stdio.c + +OBJS = auth_des.o authdes_prot.o key_call.o key_prot.o netname.o svcauth_des.o \ + openchild.o rtime.o publickey.o xcrypt.o \ + auth_none.o auth_unix.o authunix_prot.o bindresvport.o \ + clnt_generic.o clnt_perror.o clnt_raw.o clnt_simple.o clnt_tcp.o \ + clnt_udp.o rpc_dtablesize.o get_myaddress.o getrpcent.o getrpcport.o \ + pmap_clnt.o pmap_getmaps.o pmap_getport.o pmap_prot.o \ + pmap_prot2.o pmap_rmt.o rpc_prot.o rpc_commondata.o rpc_callmsg.o \ + svc.o svc_auth.o svc_auth_unix.o svc_raw.o svc_run.o svc_simple.o \ + svc_tcp.o svc_udp.o xdr.o xdr_array.o xdr_float.o xdr_mem.o \ + xdr_rec.o xdr_reference.o xdr_stdio.o + +HDRS = key_prot.h \ + auth.h auth_unix.h auth_des.h clnt.h netdb.h pmap_clnt.h \ + pmap_prot.h pmap_rmt.h rpc.h rpc_msg.h svc.h svc_auth.h types.h xdr.h + +XFILES= key_prot.x + +all rpclib: librpclib.a + +librpclib.a: ${OBJS} + @echo "building librpclib.a" + @ar cru librpclib.a ${OBJS} + +install: $(HDRS) librpclib.a + @echo "Creating RPC header directory" + -mkdir ${DESTDIR}/usr/include/rpc && \ + chown bin ${DESTDIR}/usr/include/rpc && \ + chmod 755 ${DESTDIR}/usr/include/rpc + @echo "Installing RPC header files" + -set -x;for i in $(HDRS) $(XFILES) ; do \ + (install -c -m 644 $$i ${DESTDIR}/usr/include/rpc) done + @echo "Installing RPC library" + install -c -m 644 librpclib.a ${DESTDIR}/usr/lib + ranlib ${DESTDIR}/usr/lib/librpclib.a + +tags: $(SRCS) $(HDRS) + ctags -tw $(SRCS) $(HDRS) + +ref: tags + sed 's, /.*,,' tags | \ + awk ' { printf("%-26s%-16s%s\n", $$1, $$2, $$3) }' > ref + +lint: $(SRCS) $(HDRS) + $(LINT.c) $(SRCS) + +clean: rm -f *.o rpclib.a + +.SUFFIXES: .x .x~ + +.x.c: + rpcgen -c $< | \ + sed 's/^#include \"$*\.h\"/#include <rpc\/$*\.h>/' > $@ + +.x.h: + rpcgen -h $< > $@ + +depend: $(SRCS) $(HDRS) + @${CC} ${CFLAGS} -M ${SRCS} > makedep + @echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep + @echo '$$r makedep' >>eddep + @echo 'w' >>eddep + @cp Makefile makefile.bak + @ed - Makefile < eddep + @rm eddep makedep makefile.bak + +depend.42BSD depend.42bsd: + cp /dev/null x.c + for i in $(SRCS) ; do \ + (/bin/grep '^#[ ]*include' x.c $$i | sed \ + -e '/\.\.\/h/d' \ + -e '/\.\.\/ufs/d' \ + -e 's,<\(.*\)>,"/usr/include/\1",' \ + -e 's/:[^"]*"\([^"]*\)".*/: \1/' \ + -e 's/\.c/\.o/' >>makedep); done + echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep + echo '$$r makedep' >>eddep + echo 'w' >>eddep + cp Makefile Makefile.bak + ed - Makefile < eddep + rm eddep makedep x.c + echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile + echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile + echo '# see make depend above' >> Makefile + +# DO NOT DELETE THIS LINE + + diff --git a/lib/librpc/secure_rpc/rpc/auth_des.c b/lib/librpc/secure_rpc/rpc/auth_des.c new file mode 100644 index 0000000..a757c49 --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/auth_des.c @@ -0,0 +1,411 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)auth_des.c 2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ +/* + * auth_des.c, client-side implementation of DES authentication + */ + +#include <des_crypt.h> +#include <rpc/types.h> +#include <rpc/auth.h> +#include <rpc/auth_des.h> +#include <rpc/xdr.h> +#include <netinet/in.h> /* XXX: just to get htonl() and ntohl() */ +#include <sys/socket.h> + +#define MILLION 1000000L +#define RTIME_TIMEOUT 5 /* seconds to wait for sync */ + +#define AUTH_PRIVATE(auth) (struct ad_private *) auth->ah_private +#define ALLOC(object_type) (object_type *) mem_alloc(sizeof(object_type)) +#define FREE(ptr, size) mem_free((char *)(ptr), (int) size) +#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE) + +#define debug(msg) /*printf("%s\n", msg) */ + +/* + * DES authenticator operations vector + */ +static void authdes_nextverf(); +static bool_t authdes_marshal(); +static bool_t authdes_validate(); +static bool_t authdes_refresh(); +static void authdes_destroy(); +static struct auth_ops authdes_ops = { + authdes_nextverf, + authdes_marshal, + authdes_validate, + authdes_refresh, + authdes_destroy +}; + + +/* + * This struct is pointed to by the ah_private field of an "AUTH *" + */ +struct ad_private { + char *ad_fullname; /* client's full name */ + u_int ad_fullnamelen; /* length of name, rounded up */ + char *ad_servername; /* server's full name */ + u_int ad_servernamelen; /* length of name, rounded up */ + u_int ad_window; /* client specified window */ + bool_t ad_dosync; /* synchronize? */ + struct sockaddr ad_syncaddr; /* remote host to synch with */ + struct timeval ad_timediff; /* server's time - client's time */ + u_long ad_nickname; /* server's nickname for client */ + struct authdes_cred ad_cred; /* storage for credential */ + struct authdes_verf ad_verf; /* storage for verifier */ + struct timeval ad_timestamp; /* timestamp sent */ + des_block ad_xkey; /* encrypted conversation key */ +}; + + +/* + * Create the client des authentication object + */ +AUTH * +authdes_create(servername, window, syncaddr, ckey) + char *servername; /* network name of server */ + u_int window; /* time to live */ + struct sockaddr *syncaddr; /* optional addr of host to sync with */ + des_block *ckey; /* optional conversation key to use*/ +{ + + AUTH *auth; + struct ad_private *ad; + char namebuf[MAXNETNAMELEN+1]; + + /* + * Allocate everything now + */ + auth = ALLOC(AUTH); + ad = ALLOC(struct ad_private); + (void) getnetname(namebuf); + + ad->ad_fullnamelen = RNDUP(strlen(namebuf)); + ad->ad_fullname = mem_alloc(ad->ad_fullnamelen + 1); + + ad->ad_servernamelen = strlen(servername); + ad->ad_servername = mem_alloc(ad->ad_servernamelen + 1); + + if (auth == NULL || ad == NULL || ad->ad_fullname == NULL || + ad->ad_servername == NULL) { + debug("authdes_create: out of memory"); + goto failed; + } + + /* + * Set up private data + */ + bcopy(namebuf, ad->ad_fullname, ad->ad_fullnamelen + 1); + bcopy(servername, ad->ad_servername, ad->ad_servernamelen + 1); + if (syncaddr != NULL) { + ad->ad_syncaddr = *syncaddr; + ad->ad_dosync = TRUE; + } else { + ad->ad_dosync = FALSE; + } + ad->ad_window = window; + if (ckey == NULL) { + if (key_gendes(&auth->ah_key) < 0) { + debug("authdes_create: unable to gen conversation key"); + return (NULL); + } + } else { + auth->ah_key = *ckey; + } + + /* + * Set up auth handle + */ + auth->ah_cred.oa_flavor = AUTH_DES; + auth->ah_verf.oa_flavor = AUTH_DES; + auth->ah_ops = &authdes_ops; + auth->ah_private = (caddr_t)ad; + + if (!authdes_refresh(auth)) { + goto failed; + } + return (auth); + +failed: + if (auth != NULL) + FREE(auth, sizeof(AUTH)); + if (ad != NULL) + FREE(ad, sizeof(struct ad_private)); + if (ad->ad_fullname != NULL) + FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); + if (ad->ad_servername != NULL) + FREE(ad->ad_servername, ad->ad_servernamelen + 1); + return (NULL); +} + +/* + * Implement the five authentication operations + */ + + +/* + * 1. Next Verifier + */ +/*ARGSUSED*/ +static void +authdes_nextverf(auth) + AUTH *auth; +{ + /* what the heck am I supposed to do??? */ +} + + + +/* + * 2. Marshal + */ +static bool_t +authdes_marshal(auth, xdrs) + AUTH *auth; + XDR *xdrs; +{ + struct ad_private *ad = AUTH_PRIVATE(auth); + struct authdes_cred *cred = &ad->ad_cred; + struct authdes_verf *verf = &ad->ad_verf; + des_block cryptbuf[2]; + des_block ivec; + int status; + int len; + register long *ixdr; + + /* + * Figure out the "time", accounting for any time difference + * with the server if necessary. + */ + (void) gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL); + ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec; + ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec; + if (ad->ad_timestamp.tv_usec >= MILLION) { + ad->ad_timestamp.tv_usec -= MILLION; + ad->ad_timestamp.tv_sec += 1; + } + + /* + * XDR the timestamp and possibly some other things, then + * encrypt them. + */ + ixdr = (long *)cryptbuf; + IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_sec); + IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_usec); + if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { + IXDR_PUT_U_LONG(ixdr, ad->ad_window); + IXDR_PUT_U_LONG(ixdr, ad->ad_window - 1); + ivec.key.high = ivec.key.low = 0; + status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf, + 2*sizeof(des_block), DES_ENCRYPT | DES_HW, (char *)&ivec); + } else { + status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf, + sizeof(des_block), DES_ENCRYPT | DES_HW); + } + if (DES_FAILED(status)) { + debug("authdes_marshal: DES encryption failure"); + return (FALSE); + } + ad->ad_verf.adv_xtimestamp = cryptbuf[0]; + if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { + ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high; + ad->ad_verf.adv_winverf = cryptbuf[1].key.low; + } else { + ad->ad_cred.adc_nickname = ad->ad_nickname; + ad->ad_verf.adv_winverf = 0; + } + + /* + * Serialize the credential and verifier into opaque + * authentication data. + */ + if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { + len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen); + } else { + len = (1 + 1)*BYTES_PER_XDR_UNIT; + } + + if (ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT)) { + IXDR_PUT_LONG(ixdr, AUTH_DES); + IXDR_PUT_LONG(ixdr, len); + } else { + ATTEMPT(xdr_putlong(xdrs, &auth->ah_cred.oa_flavor)); + ATTEMPT(xdr_putlong(xdrs, &len)); + } + ATTEMPT(xdr_authdes_cred(xdrs, cred)); + + len = (2 + 1)*BYTES_PER_XDR_UNIT; + if (ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT)) { + IXDR_PUT_LONG(ixdr, AUTH_DES); + IXDR_PUT_LONG(ixdr, len); + } else { + ATTEMPT(xdr_putlong(xdrs, &auth->ah_verf.oa_flavor)); + ATTEMPT(xdr_putlong(xdrs, &len)); + } + ATTEMPT(xdr_authdes_verf(xdrs, verf)); + return (TRUE); +} + + +/* + * 3. Validate + */ +static bool_t +authdes_validate(auth, rverf) + AUTH *auth; + struct opaque_auth *rverf; +{ + struct ad_private *ad = AUTH_PRIVATE(auth); + struct authdes_verf verf; + int status; + register u_long *ixdr; + + if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) { + return (FALSE); + } + ixdr = (u_long *)rverf->oa_base; + verf.adv_xtimestamp.key.high = (u_long)*ixdr++; + verf.adv_xtimestamp.key.low = (u_long)*ixdr++; + verf.adv_int_u = (u_long)*ixdr++; /* nickname not XDR'd ! */ + + /* + * Decrypt the timestamp + */ + status = ecb_crypt((char *)&auth->ah_key, (char *)&verf.adv_xtimestamp, + sizeof(des_block), DES_DECRYPT | DES_HW); + + if (DES_FAILED(status)) { + debug("authdes_validate: DES decryption failure"); + return (FALSE); + } + + /* + * xdr the decrypted timestamp + */ + ixdr = (u_long *)verf.adv_xtimestamp.c; + verf.adv_timestamp.tv_sec = IXDR_GET_LONG(ixdr) + 1; + verf.adv_timestamp.tv_usec = IXDR_GET_LONG(ixdr); + + /* + * validate + */ + if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp, + sizeof(struct timeval)) != 0) { + debug("authdes_validate: verifier mismatch\n"); + return (FALSE); + } + + /* + * We have a nickname now, let's use it + */ + ad->ad_nickname = verf.adv_nickname; + ad->ad_cred.adc_namekind = ADN_NICKNAME; + return (TRUE); +} + +/* + * 4. Refresh + */ +static bool_t +authdes_refresh(auth) + AUTH *auth; +{ + struct ad_private *ad = AUTH_PRIVATE(auth); + struct authdes_cred *cred = &ad->ad_cred; + + if (ad->ad_dosync && + !synchronize(&ad->ad_syncaddr, &ad->ad_timediff)) { + /* + * Hope the clocks are synced! + */ + ad->ad_timediff.tv_sec = ad->ad_timediff.tv_usec = 0; + debug("authdes_refresh: unable to synchronize with server"); + } + ad->ad_xkey = auth->ah_key; + if (key_encryptsession(ad->ad_servername, &ad->ad_xkey) < 0) { + debug("authdes_create: unable to encrypt conversation key"); + return (FALSE); + } + cred->adc_fullname.key = ad->ad_xkey; + cred->adc_namekind = ADN_FULLNAME; + cred->adc_fullname.name = ad->ad_fullname; + return (TRUE); +} + + +/* + * 5. Destroy + */ +static void +authdes_destroy(auth) + AUTH *auth; +{ + struct ad_private *ad = AUTH_PRIVATE(auth); + + FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); + FREE(ad->ad_servername, ad->ad_servernamelen + 1); + FREE(ad, sizeof(struct ad_private)); + FREE(auth, sizeof(AUTH)); +} + + + +/* + * Synchronize with the server at the given address, that is, + * adjust timep to reflect the delta between our clocks + */ +static bool_t +synchronize(syncaddr, timep) + struct sockaddr *syncaddr; + struct timeval *timep; +{ + struct timeval mytime; + struct timeval timeout; + + timeout.tv_sec = RTIME_TIMEOUT; + timeout.tv_usec = 0; + if (rtime((struct sockaddr_in *)syncaddr, timep, &timeout) < 0) { + return (FALSE); + } + (void) gettimeofday(&mytime, (struct timezone *)NULL); + timep->tv_sec -= mytime.tv_sec; + if (mytime.tv_usec > timep->tv_usec) { + timep->tv_sec -= 1; + timep->tv_usec += MILLION; + } + timep->tv_usec -= mytime.tv_usec; + return (TRUE); +} diff --git a/lib/librpc/secure_rpc/rpc/auth_des.h b/lib/librpc/secure_rpc/rpc/auth_des.h new file mode 100644 index 0000000..4ae4761 --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/auth_des.h @@ -0,0 +1,105 @@ +/* @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC; from 1.3 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ + +/* + * auth_des.h, Protocol for DES style authentication for RPC + */ + +#ifndef _AUTH_DES_ +#define _AUTH_DES_ + +/* + * There are two kinds of "names": fullnames and nicknames + */ +enum authdes_namekind { + ADN_FULLNAME, + ADN_NICKNAME +}; + +/* + * A fullname contains the network name of the client, + * a conversation key and the window + */ +struct authdes_fullname { + char *name; /* network name of client, up to MAXNETNAMELEN */ + des_block key; /* conversation key */ + u_long window; /* associated window */ +}; + + +/* + * A credential + */ +struct authdes_cred { + enum authdes_namekind adc_namekind; + struct authdes_fullname adc_fullname; + u_long adc_nickname; +}; + + + +/* + * A des authentication verifier + */ +struct authdes_verf { + union { + struct timeval adv_ctime; /* clear time */ + des_block adv_xtime; /* crypt time */ + } adv_time_u; + u_long adv_int_u; +}; + +/* + * des authentication verifier: client variety + * + * adv_timestamp is the current time. + * adv_winverf is the credential window + 1. + * Both are encrypted using the conversation key. + */ +#define adv_timestamp adv_time_u.adv_ctime +#define adv_xtimestamp adv_time_u.adv_xtime +#define adv_winverf adv_int_u + +/* + * des authentication verifier: server variety + * + * adv_timeverf is the client's timestamp + client's window + * adv_nickname is the server's nickname for the client. + * adv_timeverf is encrypted using the conversation key. + */ +#define adv_timeverf adv_time_u.adv_ctime +#define adv_xtimeverf adv_time_u.adv_xtime +#define adv_nickname adv_int_u + +#endif /* ndef _AUTH_DES_ */ diff --git a/lib/librpc/secure_rpc/rpc/authdes_prot.c b/lib/librpc/secure_rpc/rpc/authdes_prot.c new file mode 100644 index 0000000..14679c0 --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/authdes_prot.c @@ -0,0 +1,82 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)authdes_prot.c 2.1 88/07/29 4.0 RPCSRC; from 1.6 88/02/08 SMI"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ + +/* + * authdes_prot.c, XDR routines for DES authentication + */ + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> +#include <rpc/auth_des.h> + +#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE) + +bool_t +xdr_authdes_cred(xdrs, cred) + XDR *xdrs; + struct authdes_cred *cred; +{ + /* + * Unrolled xdr + */ + ATTEMPT(xdr_enum(xdrs, (enum_t *)&cred->adc_namekind)); + switch (cred->adc_namekind) { + case ADN_FULLNAME: + ATTEMPT(xdr_string(xdrs, &cred->adc_fullname.name, MAXNETNAMELEN)); + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.key, sizeof(des_block))); + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.window, sizeof(cred->adc_fullname.window))); + return (TRUE); + case ADN_NICKNAME: + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_nickname, sizeof(cred->adc_nickname))); + return (TRUE); + default: + return (FALSE); + } +} + + +bool_t +xdr_authdes_verf(xdrs, verf) + register XDR *xdrs; + register struct authdes_verf *verf; +{ + /* + * Unrolled xdr + */ + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_xtimestamp, sizeof(des_block))); + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_int_u, sizeof(verf->adv_int_u))); + return (TRUE); +} diff --git a/lib/librpc/secure_rpc/rpc/key_call.c b/lib/librpc/secure_rpc/rpc/key_call.c new file mode 100644 index 0000000..c2fd335 --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/key_call.c @@ -0,0 +1,228 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)key_call.c 2.2 88/08/15 4.0 RPCSRC; from 1.11 88/02/08 SMI"; +#endif +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * key_call.c, Interface to keyserver + * + * setsecretkey(key) - set your secret key + * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent + * decryptsessionkey(agent, deskey) - decrypt ditto + * gendeskey(deskey) - generate a secure des key + * netname2user(...) - get unix credential for given name (kernel only) + */ +#include <sys/param.h> +#include <sys/socket.h> +#include <rpc/rpc.h> +#include <rpc/key_prot.h> + +#define KEY_TIMEOUT 5 /* per-try timeout in seconds */ +#define KEY_NRETRY 12 /* number of retries */ + +#define debug(msg) /* turn off debugging */ + +static struct timeval trytimeout = { KEY_TIMEOUT, 0 }; +static struct timeval tottimeout = { KEY_TIMEOUT * KEY_NRETRY, 0 }; + +key_setsecret(secretkey) + char *secretkey; +{ + keystatus status; + + if (!key_call((u_long)KEY_SET, xdr_keybuf, secretkey, xdr_keystatus, + (char*)&status)) + { + return (-1); + } + if (status != KEY_SUCCESS) { + debug("set status is nonzero"); + return (-1); + } + return (0); +} + + +key_encryptsession(remotename, deskey) + char *remotename; + des_block *deskey; +{ + cryptkeyarg arg; + cryptkeyres res; + + arg.remotename = remotename; + arg.deskey = *deskey; + if (!key_call((u_long)KEY_ENCRYPT, + xdr_cryptkeyarg, (char *)&arg, xdr_cryptkeyres, (char *)&res)) + { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("encrypt status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); +} + + +key_decryptsession(remotename, deskey) + char *remotename; + des_block *deskey; +{ + cryptkeyarg arg; + cryptkeyres res; + + arg.remotename = remotename; + arg.deskey = *deskey; + if (!key_call((u_long)KEY_DECRYPT, + xdr_cryptkeyarg, (char *)&arg, xdr_cryptkeyres, (char *)&res)) + { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("decrypt status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); +} + +key_gendes(key) + des_block *key; +{ + struct sockaddr_in sin; + CLIENT *client; + int socket; + enum clnt_stat stat; + + + sin.sin_family = AF_INET; + sin.sin_port = 0; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + bzero(sin.sin_zero, sizeof(sin.sin_zero)); + socket = RPC_ANYSOCK; + client = clntudp_bufcreate(&sin, (u_long)KEY_PROG, (u_long)KEY_VERS, + trytimeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + if (client == NULL) { + return (-1); + } + stat = clnt_call(client, KEY_GEN, xdr_void, NULL, + xdr_des_block, key, tottimeout); + clnt_destroy(client); + (void) close(socket); + if (stat != RPC_SUCCESS) { + return (-1); + } + return (0); +} + + +#include <stdio.h> +#include <sys/wait.h> + + +static +key_call(proc, xdr_arg, arg, xdr_rslt, rslt) + u_long proc; + bool_t (*xdr_arg)(); + char *arg; + bool_t (*xdr_rslt)(); + char *rslt; +{ + XDR xdrargs; + XDR xdrrslt; + FILE *fargs; + FILE *frslt; + int (*osigchild)(); + union wait status; + int pid; + int success; + int ruid; + int euid; + static char MESSENGER[] = "/usr/etc/keyenvoy"; + + success = 1; + osigchild = signal(SIGCHLD, SIG_IGN); + + /* + * We are going to exec a set-uid program which makes our effective uid + * zero, and authenticates us with our real uid. We need to make the + * effective uid be the real uid for the setuid program, and + * the real uid be the effective uid so that we can change things back. + */ + euid = geteuid(); + ruid = getuid(); + (void) setreuid(euid, ruid); + pid = _openchild(MESSENGER, &fargs, &frslt); + (void) setreuid(ruid, euid); + if (pid < 0) { + debug("open_streams"); + return (0); + } + xdrstdio_create(&xdrargs, fargs, XDR_ENCODE); + xdrstdio_create(&xdrrslt, frslt, XDR_DECODE); + + if (!xdr_u_long(&xdrargs, &proc) || !(*xdr_arg)(&xdrargs, arg)) { + debug("xdr args"); + success = 0; + } + (void) fclose(fargs); + + if (success && !(*xdr_rslt)(&xdrrslt, rslt)) { + debug("xdr rslt"); + success = 0; + } + +#ifdef NOTDEF + /* + * WARNING! XXX + * The original code appears first. wait4 returns only after the process + * with the requested pid terminates. The effect of using wait() instead + * has not been determined. + */ + (void) fclose(frslt); + if (wait4(pid, &status, 0, NULL) < 0 || status.w_retcode != 0) { + debug("wait4"); + success = 0; + } +#endif /* def NOTDEF */ + if (wait(&status) < 0 || status.w_retcode != 0) { + debug("wait"); + success = 0; + } + (void)signal(SIGCHLD, osigchild); + + return (success); +} + diff --git a/lib/librpc/secure_rpc/rpc/key_prot.c b/lib/librpc/secure_rpc/rpc/key_prot.c new file mode 100644 index 0000000..a93f543 --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/key_prot.c @@ -0,0 +1,165 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)key_prot.c 2.1 88/08/07 4.0 RPCSRC; from 1.4 88/02/08 SMI"; +#endif + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#include <rpc/rpc.h> +#include <rpc/key_prot.h> + + +/* + * Compiled from key_prot.x using rpcgen. + * DO NOT EDIT THIS FILE! + * This is NOT source code! + */ + + +bool_t +xdr_keystatus(xdrs, objp) + XDR *xdrs; + keystatus *objp; +{ + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + + + + +bool_t +xdr_keybuf(xdrs, objp) + XDR *xdrs; + keybuf objp; +{ + if (!xdr_opaque(xdrs, objp, HEXKEYBYTES)) { + return (FALSE); + } + return (TRUE); +} + + + + +bool_t +xdr_netnamestr(xdrs, objp) + XDR *xdrs; + netnamestr *objp; +{ + if (!xdr_string(xdrs, objp, MAXNETNAMELEN)) { + return (FALSE); + } + return (TRUE); +} + + + + +bool_t +xdr_cryptkeyarg(xdrs, objp) + XDR *xdrs; + cryptkeyarg *objp; +{ + if (!xdr_netnamestr(xdrs, &objp->remotename)) { + return (FALSE); + } + if (!xdr_des_block(xdrs, &objp->deskey)) { + return (FALSE); + } + return (TRUE); +} + + + + +bool_t +xdr_cryptkeyres(xdrs, objp) + XDR *xdrs; + cryptkeyres *objp; +{ + if (!xdr_keystatus(xdrs, &objp->status)) { + return (FALSE); + } + switch (objp->status) { + case KEY_SUCCESS: + if (!xdr_des_block(xdrs, &objp->cryptkeyres_u.deskey)) { + return (FALSE); + } + break; + } + return (TRUE); +} + + + + +bool_t +xdr_unixcred(xdrs, objp) + XDR *xdrs; + unixcred *objp; +{ + if (!xdr_int(xdrs, &objp->uid)) { + return (FALSE); + } + if (!xdr_int(xdrs, &objp->gid)) { + return (FALSE); + } + if (!xdr_array(xdrs, (char **)&objp->gids.gids_val, (u_int *)&objp->gids.gids_len, MAXGIDS, sizeof(int), xdr_int)) { + return (FALSE); + } + return (TRUE); +} + + + + +bool_t +xdr_getcredres(xdrs, objp) + XDR *xdrs; + getcredres *objp; +{ + if (!xdr_keystatus(xdrs, &objp->status)) { + return (FALSE); + } + switch (objp->status) { + case KEY_SUCCESS: + if (!xdr_unixcred(xdrs, &objp->getcredres_u.cred)) { + return (FALSE); + } + break; + } + return (TRUE); +} + + diff --git a/lib/librpc/secure_rpc/rpc/key_prot.h b/lib/librpc/secure_rpc/rpc/key_prot.h new file mode 100644 index 0000000..277e4b8 --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/key_prot.h @@ -0,0 +1,114 @@ +/* @(#)key_prot.h 2.1 88/08/07 4.0 RPCSRC; from 1.4 87/03/10 Copyr 1986 Sun Micro */ + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + + +/* + * Compiled from key_prot.x using rpcgen. + * DO NOT EDIT THIS FILE! + * This is NOT source code! + */ + +#define KEY_PROG 100029 +#define KEY_VERS 1 +#define KEY_SET 1 +#define KEY_ENCRYPT 2 +#define KEY_DECRYPT 3 +#define KEY_GEN 4 +#define KEY_GETCRED 5 + +#define PROOT 3 +#define HEXMODULUS "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b" +#define HEXKEYBYTES 48 +#define KEYSIZE 192 +#define KEYBYTES 24 +#define KEYCHECKSUMSIZE 16 + +enum keystatus { + KEY_SUCCESS = 0, + KEY_NOSECRET = 1, + KEY_UNKNOWN = 2, + KEY_SYSTEMERR = 3, +}; +typedef enum keystatus keystatus; +bool_t xdr_keystatus(); + + +typedef char keybuf[HEXKEYBYTES]; +bool_t xdr_keybuf(); + + +typedef char *netnamestr; +bool_t xdr_netnamestr(); + + +struct cryptkeyarg { + netnamestr remotename; + des_block deskey; +}; +typedef struct cryptkeyarg cryptkeyarg; +bool_t xdr_cryptkeyarg(); + + +struct cryptkeyres { + keystatus status; + union { + des_block deskey; + } cryptkeyres_u; +}; +typedef struct cryptkeyres cryptkeyres; +bool_t xdr_cryptkeyres(); + +#define MAXGIDS 16 + +struct unixcred { + int uid; + int gid; + struct { + u_int gids_len; + int *gids_val; + } gids; +}; +typedef struct unixcred unixcred; +bool_t xdr_unixcred(); + + +struct getcredres { + keystatus status; + union { + unixcred cred; + } getcredres_u; +}; +typedef struct getcredres getcredres; +bool_t xdr_getcredres(); + diff --git a/lib/librpc/secure_rpc/rpc/key_prot.x b/lib/librpc/secure_rpc/rpc/key_prot.x new file mode 100644 index 0000000..2f6ebdb --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/key_prot.x @@ -0,0 +1,151 @@ +%/* @(#)key_prot.x 2.1 88/08/07 4.0 RPCSRC; from 1.7 88/02/08 SMI */ +% +%/* +% * Copyright (c) 1988 by Sun Microsystems, Inc. +% */ +% +%/* +% * Compiled from key_prot.x using rpcgen. +% * DO NOT EDIT THIS FILE! +% * This is NOT source code! +% */ + +/* + * Key server protocol definition + * Copyright (C) 1987 Sun Microsystems, Inc. + * + * The keyserver is a public key storage/encryption/decryption service + * The encryption method used is Diffie-Hellman with 128 bit keys. + * + * The key server is local to each machine, akin to the portmapper. + * Only privileged processes may talk to the key server, so + * user processes must communicate through a privileged dispatcher (such + * as the kernel or a set-uid-root process). + */ +program KEY_PROG { + version KEY_VERS { + /* + * This is my secret key. + * Store it for me. + */ + int + KEY_SET(keybuf) = 1; + + /* + * I want to talk to X. + * Encrypt a conversation key for me. + */ + cryptkeyres + KEY_ENCRYPT(cryptkeyarg) = 2; + + /* + * X just sent me a message. + * Decrypt the conversation key for me. + */ + cryptkeyres + KEY_DECRYPT(cryptkeyarg) = 3; + + /* + * Generate a secure conversation key for me + */ + des_block + KEY_GEN(void) = 4; + + /* + * Get me the uid, gid and group-access-list associated + * with this netname (for kernel which cannot use yp) + */ + getcredres + KEY_GETCRED(netnamestr) = 5; + } = 1; +} = 100029; + + +/* + * PROOT and MODULUS define the way the Diffie-Hellman key is generated. + * + * MODULUS should be chosen as a prime of the form: MODULUS == 2*p + 1, + * where p is also prime. + * + * PROOT satisfies the following two conditions: + * (1) (PROOT ** 2) % MODULUS != 1 + * (2) (PROOT ** p) % MODULUS != 1 + * + */ + +const PROOT = 3; +const HEXMODULUS = "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b"; + +const HEXKEYBYTES = 48; /* HEXKEYBYTES == strlen(HEXMODULUS) */ +const KEYSIZE = 192; /* KEYSIZE == bit length of key */ +const KEYBYTES = 24; /* byte length of key */ + +/* + * The first 16 hex digits of the encrypted secret key are used as + * a checksum in the database. + */ +const KEYCHECKSUMSIZE = 16; + +/* + * status of operation + */ +enum keystatus { + KEY_SUCCESS, /* no problems */ + KEY_NOSECRET, /* no secret key stored */ + KEY_UNKNOWN, /* unknown netname */ + KEY_SYSTEMERR /* system error (out of memory, encryption failure) */ +}; + +/* + * The kernel doesn't use keybuf, so we insure that it + * is ifdef'd out in the output files. The proper way to do + * this is to #ifndef KERNEL it here, and have the kernel build + * use rpcgen, but config doesn't understand rpcgen files so + * it is done this way. + */ +#ifndef RPC_SVC +%#ifndef KERNEL +typedef opaque keybuf[HEXKEYBYTES]; /* store key in hex */ +%#endif +#endif + +typedef string netnamestr<MAXNETNAMELEN>; + +/* + * Argument to ENCRYPT or DECRYPT + */ +struct cryptkeyarg { + netnamestr remotename; + des_block deskey; +}; + +/* + * Result of ENCRYPT or DECRYPT + */ +union cryptkeyres switch (keystatus status) { +case KEY_SUCCESS: + des_block deskey; +default: + void; +}; + +const MAXGIDS = 16; /* max number of gids in gid list */ + +/* + * Unix credential + */ +struct unixcred { + int uid; + int gid; + int gids<MAXGIDS>; +}; + +/* + * Result returned from GETCRED + */ +union getcredres switch (keystatus status) { +case KEY_SUCCESS: + unixcred cred; +default: + void; +}; diff --git a/lib/librpc/secure_rpc/rpc/netname.c b/lib/librpc/secure_rpc/rpc/netname.c new file mode 100644 index 0000000..21e2491 --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/netname.c @@ -0,0 +1,239 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)netname.c 2.2 88/08/10 4.0 RPCSRC; from 1.9 88/02/08 SMI"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ + +/* + * netname utility routines + * convert from unix names to network names and vice-versa + * This module is operating system dependent! + * What we define here will work with any unix system that has adopted + * the sun yp domain architecture. + */ +#include <sys/param.h> +#include <rpc/rpc.h> +#include <ctype.h> + +extern char *sprintf(); +extern char *strncpy(); + +static char OPSYS[] = "unix"; +static char NETID[] = "netid.byname"; + +/* + * Convert network-name into unix credential + */ +netname2user(netname, uidp, gidp, gidlenp, gidlist) + char netname[MAXNETNAMELEN+1]; + int *uidp; + int *gidp; + int *gidlenp; + int *gidlist; +{ + int stat; + char *val; + char *p; + int vallen; + char *domain; + int gidlen; + + stat = yp_get_default_domain(&domain); + if (stat != 0) { + return (0); + } + stat = yp_match(domain, NETID, netname, strlen(netname), &val, &vallen); + if (stat != 0) { + return (0); + } + val[vallen] = 0; + p = val; + *uidp = atois(&p); + if (p == NULL || *p++ != ':') { + free(val); + return (0); + } + *gidp = atois(&p); + if (p == NULL) { + free(val); + return (0); + } + gidlen = 0; + for (gidlen = 0; gidlen < NGROUPS; gidlen++) { + if (*p++ != ',') { + break; + } + gidlist[gidlen] = atois(&p); + if (p == NULL) { + free(val); + return (0); + } + } + *gidlenp = gidlen; + free(val); + return (1); +} + +/* + * Convert network-name to hostname + */ +netname2host(netname, hostname, hostlen) + char netname[MAXNETNAMELEN+1]; + char *hostname; + int hostlen; +{ + int stat; + char *val; + int vallen; + char *domain; + + stat = yp_get_default_domain(&domain); + if (stat != 0) { + return (0); + } + stat = yp_match(domain, NETID, netname, strlen(netname), &val, &vallen); + if (stat != 0) { + return (0); + } + val[vallen] = 0; + if (*val != '0') { + free(val); + return (0); + } + if (val[1] != ':') { + free(val); + return (0); + } + (void) strncpy(hostname, val + 2, hostlen); + free(val); + return (1); +} + + +/* + * Figure out my fully qualified network name + */ +getnetname(name) + char name[MAXNETNAMELEN+1]; +{ + int uid; + + uid = geteuid(); + if (uid == 0) { + return (host2netname(name, (char *) NULL, (char *) NULL)); + } else { + return (user2netname(name, uid, (char *) NULL)); + } +} + + +/* + * Convert unix cred to network-name + */ +user2netname(netname, uid, domain) + char netname[MAXNETNAMELEN + 1]; + int uid; + char *domain; +{ + char *dfltdom; + +#define MAXIPRINT (11) /* max length of printed integer */ + + if (domain == NULL) { + if (yp_get_default_domain(&dfltdom) != 0) { + return (0); + } + domain = dfltdom; + } + if (strlen(domain) + 1 + MAXIPRINT > MAXNETNAMELEN) { + return (0); + } + (void) sprintf(netname, "%s.%d@%s", OPSYS, uid, domain); + return (1); +} + + +/* + * Convert host to network-name + */ +host2netname(netname, host, domain) + char netname[MAXNETNAMELEN + 1]; + char *host; + char *domain; +{ + char *dfltdom; + char hostname[MAXHOSTNAMELEN+1]; + + if (domain == NULL) { + if (yp_get_default_domain(&dfltdom) != 0) { + return (0); + } + domain = dfltdom; + } + if (host == NULL) { + (void) gethostname(hostname, sizeof(hostname)); + host = hostname; + } + if (strlen(domain) + 1 + strlen(host) > MAXNETNAMELEN) { + return (0); + } + (void) sprintf(netname, "%s.%s@%s", OPSYS, host, domain); + return (1); +} + + +static +atois(str) + char **str; +{ + char *p; + int n; + int sign; + + if (**str == '-') { + sign = -1; + (*str)++; + } else { + sign = 1; + } + n = 0; + for (p = *str; isdigit(*p); p++) { + n = (10 * n) + (*p - '0'); + } + if (p == *str) { + *str = NULL; + return (0); + } + *str = p; + return (n * sign); +} diff --git a/lib/librpc/secure_rpc/rpc/openchild.c b/lib/librpc/secure_rpc/rpc/openchild.c new file mode 100644 index 0000000..b30e615 --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/openchild.c @@ -0,0 +1,133 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)openchild.c 2.3 88/08/15 4.0 RPCSRC; from 1.7 88/02/08 SMI"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ + +/* + * Open two pipes to a child process, one for reading, one for writing. + * The pipes are accessed by FILE pointers. This is NOT a public + * interface, but for internal use only! + */ +#include <stdio.h> + +extern char *malloc(); +extern char *rindex(); +extern char *sprintf(); + +static char *basename(); +static char SHELL[] = "/bin/sh"; + + +/* + * returns pid, or -1 for failure + */ +_openchild(command, fto, ffrom) + char *command; + FILE **fto; + FILE **ffrom; +{ + int i; + int pid; + int pdto[2]; + int pdfrom[2]; + char *com; + + + if (pipe(pdto) < 0) { + goto error1; + } + if (pipe(pdfrom) < 0) { + goto error2; + } + switch (pid = vfork()) { + case -1: + goto error3; + + case 0: + /* + * child: read from pdto[0], write into pdfrom[1] + */ + (void) close(0); + (void) dup(pdto[0]); + (void) close(1); + (void) dup(pdfrom[1]); + for (i = _rpc_dtablesize() - 1; i >= 3; i--) { + (void) close(i); + } + com = malloc((unsigned) strlen(command) + 6); + if (com == NULL) { + _exit(~0); + } + (void) sprintf(com, "exec %s", command); + execl(SHELL, basename(SHELL), "-c", com, NULL); + _exit(~0); + + default: + /* + * parent: write into pdto[1], read from pdfrom[0] + */ + *fto = fdopen(pdto[1], "w"); + (void) close(pdto[0]); + *ffrom = fdopen(pdfrom[0], "r"); + (void) close(pdfrom[1]); + break; + } + return (pid); + + /* + * error cleanup and return + */ +error3: + (void) close(pdfrom[0]); + (void) close(pdfrom[1]); +error2: + (void) close(pdto[0]); + (void) close(pdto[1]); +error1: + return (-1); +} + +static char * +basename(path) + char *path; +{ + char *p; + + p = rindex(path, '/'); + if (p == NULL) { + return (path); + } else { + return (p + 1); + } +} diff --git a/lib/librpc/secure_rpc/rpc/publickey.c b/lib/librpc/secure_rpc/rpc/publickey.c new file mode 100644 index 0000000..d403b63 --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/publickey.c @@ -0,0 +1,129 @@ +#ifndef lint +static char sccsid[] = "@(#)publickey.c 2.3 88/08/15 4.0 RPCSRC"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + * @(#) from SUN 1.3 + */ + +/* + * Public key lookup routines + */ +#include <stdio.h> +#include <pwd.h> +#include <rpc/rpc.h> +#include <rpc/key_prot.h> + + +extern char *index(); +extern char *strcpy(); + +static char PKMAP[] = "publickey.byname"; + +/* + * Get somebody's encrypted secret key from the database, using + * the given passwd to decrypt it. + */ +getsecretkey(netname, secretkey, passwd) + char *netname; + char *secretkey; + char *passwd; +{ + char *domain; + int len; + char *lookup; + int err; + char *p; + + + err = yp_get_default_domain(&domain); + if (err) { + return(0); + } + err = yp_match(domain, PKMAP, netname, strlen(netname), &lookup, &len); + if (err) { + return(0); + } + lookup[len] = 0; + p = index(lookup,':'); + if (p == NULL) { + free(lookup); + return(0); + } + p++; + if (!xdecrypt(p, passwd)) { + free(lookup); + return(0); + } + if (bcmp(p, p + HEXKEYBYTES, KEYCHECKSUMSIZE) != 0) { + secretkey[0] = 0; + free(lookup); + return(1); + } + p[HEXKEYBYTES] = 0; + (void) strcpy(secretkey, p); + free(lookup); + return(1); +} + + + +/* + * Get somebody's public key + */ +getpublickey(netname, publickey) + char *netname; + char *publickey; +{ + char *domain; + int len; + char *lookup; + int err; + char *p; + + err = yp_get_default_domain(&domain); + if (err) { + return(0); + } + err = yp_match(domain, PKMAP, netname, strlen(netname), &lookup, &len); + if (err) { + return(0); + } + p = index(lookup, ':'); + if (p == NULL) { + free(lookup); + return(0); + } + *p = 0; + (void) strcpy(publickey, lookup); + return(1); +} diff --git a/lib/librpc/secure_rpc/rpc/rtime.c b/lib/librpc/secure_rpc/rpc/rtime.c new file mode 100644 index 0000000..725995c --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/rtime.c @@ -0,0 +1,141 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + + */ + +/* + * rtime - get time from remote machine + * + * gets time, obtaining value from host + * on the udp/time socket. Since timeserver returns + * with time of day in seconds since Jan 1, 1900, must + * subtract seconds before Jan 1, 1970 to get + * what unix uses. + */ +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/errno.h> +#include <netinet/in.h> +#include <stdio.h> + +#define NYEARS (1970 - 1900) +#define TOFFSET (60*60*24*(365*NYEARS + (NYEARS/4))) +extern errno; + +static void do_close(); + +rtime(addrp, timep, timeout) + struct sockaddr_in *addrp; + struct timeval *timep; + struct timeval *timeout; +{ + int s; + fd_set readfds; + int res; + unsigned long thetime; + struct sockaddr_in from; + int fromlen; + int type; + + if (timeout == NULL) { + type = SOCK_STREAM; + } else { + type = SOCK_DGRAM; + } + s = socket(AF_INET, type, 0); + if (s < 0) { + return(-1); + } + addrp->sin_family = AF_INET; + addrp->sin_port = htons(IPPORT_TIMESERVER); + if (type == SOCK_DGRAM) { + res = sendto(s, (char *)&thetime, sizeof(thetime), 0, + (struct sockaddr *)addrp, sizeof(*addrp)); + if (res < 0) { + do_close(s); + return(-1); + } + do { + FD_ZERO(&readfds); + FD_SET(s, &readfds); + res = select(_rpc_dtablesize(), &readfds, (int *)NULL, + (int *)NULL, timeout); + } while (res < 0 && errno == EINTR); + if (res <= 0) { + if (res == 0) { + errno = ETIMEDOUT; + } + do_close(s); + return(-1); + } + fromlen = sizeof(from); + res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0, + (struct sockaddr *)&from, &fromlen); + do_close(s); + if (res < 0) { + return(-1); + } + } else { + if (connect(s, (struct sockaddr *)addrp, sizeof(*addrp)) < 0) { + do_close(s); + return(-1); + } + res = read(s, (char *)&thetime, sizeof(thetime)); + do_close(s); + if (res < 0) { + return(-1); + } + } + if (res != sizeof(thetime)) { + errno = EIO; + return(-1); + } + thetime = ntohl(thetime); + timep->tv_sec = thetime - TOFFSET; + timep->tv_usec = 0; + return(0); +} + +static void +do_close(s) + int s; +{ + int save; + + save = errno; + (void) close(s); + errno = save; +} diff --git a/lib/librpc/secure_rpc/rpc/svc_auth.c b/lib/librpc/secure_rpc/rpc/svc_auth.c new file mode 100644 index 0000000..7ad47ca --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/svc_auth.c @@ -0,0 +1,116 @@ +/* @(#)svc_auth.c 2.4 88/08/15 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)svc_auth.c 1.19 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_auth.c, Server-side rpc authenticator interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include <rpc/rpc.h> + +/* + * svcauthsw is the bdevsw of server side authentication. + * + * Server side authenticators are called from authenticate by + * using the client auth struct flavor field to index into svcauthsw. + * The server auth flavors must implement a routine that looks + * like: + * + * enum auth_stat + * flavorx_auth(rqst, msg) + * register struct svc_req *rqst; + * register struct rpc_msg *msg; + * + */ + +enum auth_stat _svcauth_null(); /* no authentication */ +enum auth_stat _svcauth_unix(); /* unix style (uid, gids) */ +enum auth_stat _svcauth_short(); /* short hand unix style */ +enum auth_stat _svcauth_des(); /* des style */ + +static struct { + enum auth_stat (*authenticator)(); +} svcauthsw[] = { + _svcauth_null, /* AUTH_NULL */ + _svcauth_unix, /* AUTH_UNIX */ + _svcauth_short, /* AUTH_SHORT */ + _svcauth_des /* AUTH_DES */ +}; +#define AUTH_MAX 3 /* HIGHEST AUTH NUMBER */ + + +/* + * The call rpc message, msg has been obtained from the wire. The msg contains + * the raw form of credentials and verifiers. authenticate returns AUTH_OK + * if the msg is successfully authenticated. If AUTH_OK then the routine also + * does the following things: + * set rqst->rq_xprt->verf to the appropriate response verifier; + * sets rqst->rq_client_cred to the "cooked" form of the credentials. + * + * NB: rqst->rq_cxprt->verf must be pre-alloctaed; + * its length is set appropriately. + * + * The caller still owns and is responsible for msg->u.cmb.cred and + * msg->u.cmb.verf. The authentication system retains ownership of + * rqst->rq_client_cred, the cooked credentials. + * + * There is an assumption that any flavour less than AUTH_NULL is + * invalid. + */ +enum auth_stat +_authenticate(rqst, msg) + register struct svc_req *rqst; + struct rpc_msg *msg; +{ + register int cred_flavor; + + rqst->rq_cred = msg->rm_call.cb_cred; + rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; + rqst->rq_xprt->xp_verf.oa_length = 0; + cred_flavor = rqst->rq_cred.oa_flavor; + if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) { + return ((*(svcauthsw[cred_flavor].authenticator))(rqst, msg)); + } + + return (AUTH_REJECTEDCRED); +} + +enum auth_stat +_svcauth_null(/*rqst, msg*/) + /*struct svc_req *rqst; + struct rpc_msg *msg;*/ +{ + + return (AUTH_OK); +} diff --git a/lib/librpc/secure_rpc/rpc/svcauth_des.c b/lib/librpc/secure_rpc/rpc/svcauth_des.c new file mode 100644 index 0000000..0129bef --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/svcauth_des.c @@ -0,0 +1,519 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)svcauth_des.c 2.3 89/07/11 4.0 RPCSRC; from 1.15 88/02/08 SMI"; +#endif + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svcauth_des.c, server-side des authentication + * + * We insure for the service the following: + * (1) The timestamp microseconds do not exceed 1 million. + * (2) The timestamp plus the window is less than the current time. + * (3) The timestamp is not less than the one previously + * seen in the current session. + * + * It is up to the server to determine if the window size is + * too small . + * + */ + +#include <des_crypt.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> +#include <rpc/auth_des.h> +#include <rpc/svc_auth.h> +#include <rpc/svc.h> +#include <rpc/rpc_msg.h> + + +#define debug(msg) /*printf("svcauth_des: %s\n", msg)*/ + +extern char *strcpy(); + +#define USEC_PER_SEC ((u_long) 1000000L) +#define BEFORE(t1, t2) timercmp(t1, t2, <) + +/* + * LRU cache of conversation keys and some other useful items. + */ +#define AUTHDES_CACHESZ 64 +struct cache_entry { + des_block key; /* conversation key */ + char *rname; /* client's name */ + u_int window; /* credential lifetime window */ + struct timeval laststamp; /* detect replays of creds */ + char *localcred; /* generic local credential */ +}; +static struct cache_entry *authdes_cache/* [AUTHDES_CACHESZ] */; +static short *authdes_lru/* [AUTHDES_CACHESZ] */; + +static void cache_init(); /* initialize the cache */ +static short cache_spot(); /* find an entry in the cache */ +static void cache_ref(/*short sid*/); /* note that sid was ref'd */ + +static void invalidate(); /* invalidate entry in cache */ + +/* + * cache statistics + */ +struct { + u_long ncachehits; /* times cache hit, and is not replay */ + u_long ncachereplays; /* times cache hit, and is replay */ + u_long ncachemisses; /* times cache missed */ +} svcauthdes_stats; + +/* + * Service side authenticator for AUTH_DES + */ +enum auth_stat +_svcauth_des(rqst, msg) + register struct svc_req *rqst; + register struct rpc_msg *msg; +{ + + register long *ixdr; + des_block cryptbuf[2]; + register struct authdes_cred *cred; + struct authdes_verf verf; + int status; + register struct cache_entry *entry; + short sid; + des_block *sessionkey; + des_block ivec; + u_int window; + struct timeval timestamp; + u_long namelen; + struct area { + struct authdes_cred area_cred; + char area_netname[MAXNETNAMELEN+1]; + } *area; + + if (authdes_cache == NULL) { + cache_init(); + } + + area = (struct area *)rqst->rq_clntcred; + cred = (struct authdes_cred *)&area->area_cred; + + /* + * Get the credential + */ + ixdr = (long *)msg->rm_call.cb_cred.oa_base; + cred->adc_namekind = IXDR_GET_ENUM(ixdr, enum authdes_namekind); + switch (cred->adc_namekind) { + case ADN_FULLNAME: + namelen = IXDR_GET_U_LONG(ixdr); + if (namelen > MAXNETNAMELEN) { + return (AUTH_BADCRED); + } + cred->adc_fullname.name = area->area_netname; + bcopy((char *)ixdr, cred->adc_fullname.name, + (u_int)namelen); + cred->adc_fullname.name[namelen] = 0; + ixdr += (RNDUP(namelen) / BYTES_PER_XDR_UNIT); + cred->adc_fullname.key.key.high = (u_long)*ixdr++; + cred->adc_fullname.key.key.low = (u_long)*ixdr++; + cred->adc_fullname.window = (u_long)*ixdr++; + break; + case ADN_NICKNAME: + cred->adc_nickname = (u_long)*ixdr++; + break; + default: + return (AUTH_BADCRED); + } + + /* + * Get the verifier + */ + ixdr = (long *)msg->rm_call.cb_verf.oa_base; + verf.adv_xtimestamp.key.high = (u_long)*ixdr++; + verf.adv_xtimestamp.key.low = (u_long)*ixdr++; + verf.adv_int_u = (u_long)*ixdr++; + + + /* + * Get the conversation key + */ + if (cred->adc_namekind == ADN_FULLNAME) { + sessionkey = &cred->adc_fullname.key; + if (key_decryptsession(cred->adc_fullname.name, + sessionkey) < 0) { + debug("decryptsessionkey"); + return (AUTH_BADCRED); /* key not found */ + } + } else { /* ADN_NICKNAME */ + sid = (short)cred->adc_nickname; + if (sid >= AUTHDES_CACHESZ) { + debug("bad nickname"); + return (AUTH_BADCRED); /* garbled credential */ + } + sessionkey = &authdes_cache[sid].key; + } + + + /* + * Decrypt the timestamp + */ + cryptbuf[0] = verf.adv_xtimestamp; + if (cred->adc_namekind == ADN_FULLNAME) { + cryptbuf[1].key.high = cred->adc_fullname.window; + cryptbuf[1].key.low = verf.adv_winverf; + ivec.key.high = ivec.key.low = 0; + status = cbc_crypt((char *)sessionkey, (char *)cryptbuf, + 2*sizeof(des_block), DES_DECRYPT | DES_HW, + (char *)&ivec); + } else { + status = ecb_crypt((char *)sessionkey, (char *)cryptbuf, + sizeof(des_block), DES_DECRYPT | DES_HW); + } + if (DES_FAILED(status)) { + debug("decryption failure"); + return (AUTH_FAILED); /* system error */ + } + + /* + * XDR the decrypted timestamp + */ + ixdr = (long *)cryptbuf; + timestamp.tv_sec = IXDR_GET_LONG(ixdr); + timestamp.tv_usec = IXDR_GET_LONG(ixdr); + + /* + * Check for valid credentials and verifiers. + * They could be invalid because the key was flushed + * out of the cache, and so a new session should begin. + * Be sure and send AUTH_REJECTED{CRED, VERF} if this is the case. + */ + { + struct timeval current; + int nick; + int winverf; + + if (cred->adc_namekind == ADN_FULLNAME) { + window = IXDR_GET_U_LONG(ixdr); + winverf = IXDR_GET_U_LONG(ixdr); + if (winverf != window - 1) { + debug("window verifier mismatch"); + return (AUTH_BADCRED); /* garbled credential */ + } + sid = cache_spot(sessionkey, cred->adc_fullname.name, + ×tamp); + if (sid < 0) { + debug("replayed credential"); + return (AUTH_REJECTEDCRED); /* replay */ + } + nick = 0; + } else { /* ADN_NICKNAME */ + window = authdes_cache[sid].window; + nick = 1; + } + + if ((u_long)timestamp.tv_usec >= USEC_PER_SEC) { + debug("invalid usecs"); + /* cached out (bad key), or garbled verifier */ + return (nick ? AUTH_REJECTEDVERF : AUTH_BADVERF); + } + if (nick && BEFORE(×tamp, + &authdes_cache[sid].laststamp)) { + debug("timestamp before last seen"); + return (AUTH_REJECTEDVERF); /* replay */ + } + (void) gettimeofday(¤t, (struct timezone *)NULL); + current.tv_sec -= window; /* allow for expiration */ + if (!BEFORE(¤t, ×tamp)) { + debug("timestamp expired"); + /* replay, or garbled credential */ + return (nick ? AUTH_REJECTEDVERF : AUTH_BADCRED); + } + } + + /* + * Set up the reply verifier + */ + verf.adv_nickname = (u_long)sid; + + /* + * xdr the timestamp before encrypting + */ + ixdr = (long *)cryptbuf; + IXDR_PUT_LONG(ixdr, timestamp.tv_sec - 1); + IXDR_PUT_LONG(ixdr, timestamp.tv_usec); + + /* + * encrypt the timestamp + */ + status = ecb_crypt((char *)sessionkey, (char *)cryptbuf, + sizeof(des_block), DES_ENCRYPT | DES_HW); + if (DES_FAILED(status)) { + debug("encryption failure"); + return (AUTH_FAILED); /* system error */ + } + verf.adv_xtimestamp = cryptbuf[0]; + + /* + * Serialize the reply verifier, and update rqst + */ + ixdr = (long *)msg->rm_call.cb_verf.oa_base; + *ixdr++ = (long)verf.adv_xtimestamp.key.high; + *ixdr++ = (long)verf.adv_xtimestamp.key.low; + *ixdr++ = (long)verf.adv_int_u; + + rqst->rq_xprt->xp_verf.oa_flavor = AUTH_DES; + rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base; + rqst->rq_xprt->xp_verf.oa_length = + (char *)ixdr - msg->rm_call.cb_verf.oa_base; + + /* + * We succeeded, commit the data to the cache now and + * finish cooking the credential. + */ + entry = &authdes_cache[sid]; + entry->laststamp = timestamp; + cache_ref(sid); + if (cred->adc_namekind == ADN_FULLNAME) { + cred->adc_fullname.window = window; + cred->adc_nickname = (u_long)sid; /* save nickname */ + if (entry->rname != NULL) { + mem_free(entry->rname, strlen(entry->rname) + 1); + } + entry->rname = mem_alloc((u_int)strlen(cred->adc_fullname.name) + + 1); + if (entry->rname != NULL) { + (void) strcpy(entry->rname, cred->adc_fullname.name); + } else { + debug("out of memory"); + } + entry->key = *sessionkey; + entry->window = window; + invalidate(entry->localcred); /* mark any cached cred invalid */ + } else { /* ADN_NICKNAME */ + /* + * nicknames are cooked into fullnames + */ + cred->adc_namekind = ADN_FULLNAME; + cred->adc_fullname.name = entry->rname; + cred->adc_fullname.key = entry->key; + cred->adc_fullname.window = entry->window; + } + return (AUTH_OK); /* we made it!*/ +} + + +/* + * Initialize the cache + */ +static void +cache_init() +{ + register int i; + + authdes_cache = (struct cache_entry *) + mem_alloc(sizeof(struct cache_entry) * AUTHDES_CACHESZ); + bzero((char *)authdes_cache, + sizeof(struct cache_entry) * AUTHDES_CACHESZ); + + authdes_lru = (short *)mem_alloc(sizeof(short) * AUTHDES_CACHESZ); + /* + * Initialize the lru list + */ + for (i = 0; i < AUTHDES_CACHESZ; i++) { + authdes_lru[i] = i; + } +} + + +/* + * Find the lru victim + */ +static short +cache_victim() +{ + return (authdes_lru[AUTHDES_CACHESZ-1]); +} + +/* + * Note that sid was referenced + */ +static void +cache_ref(sid) + register short sid; +{ + register int i; + register short curr; + register short prev; + + prev = authdes_lru[0]; + authdes_lru[0] = sid; + for (i = 1; prev != sid; i++) { + curr = authdes_lru[i]; + authdes_lru[i] = prev; + prev = curr; + } +} + + +/* + * Find a spot in the cache for a credential containing + * the items given. Return -1 if a replay is detected, otherwise + * return the spot in the cache. + */ +static short +cache_spot(key, name, timestamp) + register des_block *key; + char *name; + struct timeval *timestamp; +{ + register struct cache_entry *cp; + register int i; + register u_long hi; + + hi = key->key.high; + for (cp = authdes_cache, i = 0; i < AUTHDES_CACHESZ; i++, cp++) { + if (cp->key.key.high == hi && + cp->key.key.low == key->key.low && + cp->rname != NULL && + bcmp(cp->rname, name, strlen(name) + 1) == 0) { + if (BEFORE(timestamp, &cp->laststamp)) { + svcauthdes_stats.ncachereplays++; + return (-1); /* replay */ + } + svcauthdes_stats.ncachehits++; + return (i); /* refresh */ + } + } + svcauthdes_stats.ncachemisses++; + return (cache_victim()); /* new credential */ +} + + +#if (defined(sun) || defined(vax)) +/* + * Local credential handling stuff. + * NOTE: bsd unix dependent. + * Other operating systems should put something else here. + */ +#define UNKNOWN -2 /* grouplen, if cached cred is unknown user */ +#define INVALID -1 /* grouplen, if cache entry is invalid */ + +struct bsdcred { + short uid; /* cached uid */ + short gid; /* cached gid */ + short grouplen; /* length of cached groups */ + short groups[NGROUPS]; /* cached groups */ +}; + +/* + * Map a des credential into a unix cred. + * We cache the credential here so the application does + * not have to make an rpc call every time to interpret + * the credential. + */ +authdes_getucred(adc, uid, gid, grouplen, groups) + struct authdes_cred *adc; + short *uid; + short *gid; + short *grouplen; + register int *groups; +{ + unsigned sid; + register int i; + int i_uid; + int i_gid; + int i_grouplen; + struct bsdcred *cred; + + sid = adc->adc_nickname; + if (sid >= AUTHDES_CACHESZ) { + debug("invalid nickname"); + return (0); + } + cred = (struct bsdcred *)authdes_cache[sid].localcred; + if (cred == NULL) { + cred = (struct bsdcred *)mem_alloc(sizeof(struct bsdcred)); + authdes_cache[sid].localcred = (char *)cred; + cred->grouplen = INVALID; + } + if (cred->grouplen == INVALID) { + /* + * not in cache: lookup + */ + if (!netname2user(adc->adc_fullname.name, &i_uid, &i_gid, + &i_grouplen, groups)) + { + debug("unknown netname"); + cred->grouplen = UNKNOWN; /* mark as lookup up, but not found */ + return (0); + } + debug("missed ucred cache"); + *uid = cred->uid = i_uid; + *gid = cred->gid = i_gid; + *grouplen = cred->grouplen = i_grouplen; + for (i = i_grouplen - 1; i >= 0; i--) { + cred->groups[i] = groups[i]; /* int to short */ + } + return (1); + } else if (cred->grouplen == UNKNOWN) { + /* + * Already lookup up, but no match found + */ + return (0); + } + + /* + * cached credentials + */ + *uid = cred->uid; + *gid = cred->gid; + *grouplen = cred->grouplen; + for (i = cred->grouplen - 1; i >= 0; i--) { + groups[i] = cred->groups[i]; /* short to int */ + } + return (1); +} + +static void +invalidate(cred) + char *cred; +{ + if (cred == NULL) { + return; + } + ((struct bsdcred *)cred)->grouplen = INVALID; +} +#endif + diff --git a/lib/librpc/secure_rpc/rpc/xcrypt.c b/lib/librpc/secure_rpc/rpc/xcrypt.c new file mode 100644 index 0000000..215fda6 --- /dev/null +++ b/lib/librpc/secure_rpc/rpc/xcrypt.c @@ -0,0 +1,183 @@ +#ifndef lint +static char sccsid[] = "@(#)xcrypt.c 2.2 88/08/10 4.0 RPCSRC"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Hex encryption/decryption and utility routines + * + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +#include <stdio.h> +#include <des_crypt.h> + +extern char *malloc(); + +extern char hex[]; /* forward */ +static char hexval(); + +/* + * Encrypt a secret key given passwd + * The secret key is passed and returned in hex notation. + * Its length must be a multiple of 16 hex digits (64 bits). + */ +xencrypt(secret, passwd) + char *secret; + char *passwd; +{ + char key[8]; + char ivec[8]; + char *buf; + int err; + int len; + + len = strlen(secret) / 2; + buf = malloc((unsigned)len); + + hex2bin(len, secret, buf); + passwd2des(passwd, key); + bzero(ivec, 8); + + err = cbc_crypt(key, buf, len, DES_ENCRYPT | DES_HW, ivec); + if (DES_FAILED(err)) { + free(buf); + return (0); + } + bin2hex(len, (unsigned char *) buf, secret); + free(buf); + return (1); +} + +/* + * Decrypt secret key using passwd + * The secret key is passed and returned in hex notation. + * Once again, the length is a multiple of 16 hex digits + */ +xdecrypt(secret, passwd) + char *secret; + char *passwd; +{ + char key[8]; + char ivec[8]; + char *buf; + int err; + int len; + + len = strlen(secret) / 2; + buf = malloc((unsigned)len); + + hex2bin(len, secret, buf); + passwd2des(passwd, key); + bzero(ivec, 8); + + err = cbc_crypt(key, buf, len, DES_DECRYPT | DES_HW, ivec); + if (DES_FAILED(err)) { + free(buf); + return (0); + } + bin2hex(len, (unsigned char *) buf, secret); + free(buf); + return (1); +} + + +/* + * Turn password into DES key + */ +passwd2des(pw, key) + char *pw; + char *key; +{ + int i; + + bzero(key, 8); + for (i = 0; *pw; i = (i+1)%8) { + key[i] ^= *pw++ << 1; + } + des_setparity(key); +} + + + +/* + * Hex to binary conversion + */ +static +hex2bin(len, hexnum, binnum) + int len; + char *hexnum; + char *binnum; +{ + int i; + + for (i = 0; i < len; i++) { + *binnum++ = 16 * hexval(hexnum[2*i]) + hexval(hexnum[2*i+1]); + } +} + +/* + * Binary to hex conversion + */ +static +bin2hex(len, binnum, hexnum) + int len; + unsigned char *binnum; + char *hexnum; +{ + int i; + unsigned val; + + for (i = 0; i < len; i++) { + val = binnum[i]; + hexnum[i*2] = hex[val >> 4]; + hexnum[i*2+1] = hex[val & 0xf]; + } + hexnum[len*2] = 0; +} + +static char hex[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', +}; + +static char +hexval(c) + char c; +{ + if (c >= '0' && c <= '9') { + return (c - '0'); + } else if (c >= 'a' && c <= 'z') { + return (c - 'a' + 10); + } else if (c >= 'A' && c <= 'Z') { + return (c - 'A' + 10); + } else { + return (-1); + } +} |