static char sccsid
[] = "@(#)keyserv.c 2.4 88/08/15 4.0 RPCSRC Copyr 1988 Sun Micro";
* 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
* 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.
* Mountain View, California 94043
* Copyright (C) 1986, Sun Microsystems, Inc.
* 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 <rpc/key_prot.h>
char ROOTKEY
[] = "/etc/.rootkey";
extern keystatus
pk_setkey();
extern keystatus
pk_encrypt();
extern keystatus
pk_decrypt();
static void keyprogram();
nflag
= (argc
== 2) && (strcmp(argv
[1], "-n") == 0);
if (!(argc
== 1 || nflag
)) {
(void) fprintf(stderr
, "usage: %s [-n]\n", argv
[0]);
(void) umask(066); /* paranoia */
(void) fprintf(stderr
, "%s must be run as root\n", argv
[0]);
getrootkey(&masterkey
, nflag
);
* create the service, register it, and run
transp
= svcudp_create(RPC_ANYSOCK
);
"%s: unable to create udp service\n", argv
[0]);
pmap_unset(KEY_PROG
, KEY_VERS
);
if (!svc_register(transp
, KEY_PROG
, KEY_VERS
, keyprogram
,
(void) fprintf(stderr
, "%s: unable to register service\n",
* In the event that we don't get a root password, we try to randomize the
* master key the best we can
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
));
master
->key
.low
= random();
master
->key
.high
= random();
* Try to get root's secret key, by prompting if terminal is a tty, else trying
getrootkey(master
, prompt
)
char name
[MAXNETNAMELEN
+ 1];
char secret
[HEXKEYBYTES
+ 1];
* Read secret key out of $ROOTKEY
fd
= open(ROOTKEY
, O_RDONLY
, 0);
if (read(fd
, secret
, HEXKEYBYTES
) < 0) {
(void) fprintf(stderr
, "Invalid %s\n", ROOTKEY
);
* Decrypt yellow pages entry to get secret key
passwd
= getpass("root password:");
passwd2des(passwd
, master
);
if (!getsecretkey(name
, secret
, passwd
)) {
"Can't find %s's secret key\n", name
);
"Invalid password for %s\n", name
);
(void) pk_setkey(0, secret
);
* Procedures to implement RPC service
return ("KEY_SYSTEMERR");
return ("(bad result code)");
(void) fprintf(stderr
, "set(%d, %.*s) = ", uid
,
status
= pk_setkey(uid
, key
);
(void) fprintf(stderr
, "%s\n", strstatus(status
));
(void) fprintf(stderr
, "encrypt(%d, %s, %08x%08x) = ", uid
,
arg
->remotename
, arg
->deskey
.key
.high
,
res
.cryptkeyres_u
.deskey
= arg
->deskey
;
res
.status
= pk_encrypt(uid
, arg
->remotename
, &res
.cryptkeyres_u
.deskey
);
if (res
.status
== KEY_SUCCESS
) {
(void) fprintf(stderr
, "%08x%08x\n",
res
.cryptkeyres_u
.deskey
.key
.high
,
res
.cryptkeyres_u
.deskey
.key
.low
);
"%s\n", strstatus(res
.status
));
(void) fprintf(stderr
, "decrypt(%d, %s, %08x%08x) = ", uid
,
arg
->remotename
, arg
->deskey
.key
.high
,
res
.cryptkeyres_u
.deskey
= arg
->deskey
;
res
.status
= pk_decrypt(uid
, arg
->remotename
,
&res
.cryptkeyres_u
.deskey
);
if (res
.status
== KEY_SUCCESS
) {
(void) fprintf(stderr
, "%08x%08x\n",
res
.cryptkeyres_u
.deskey
.key
.high
,
res
.cryptkeyres_u
.deskey
.key
.low
);
(void) fprintf(stderr
, "%s\n", strstatus(res
.status
));
(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
);
(void) fprintf(stderr
, "gen() = %08x%08x\n", key
.key
.high
,
static int gids
[NGROUPS
];
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
;
res
.status
= KEY_SUCCESS
;
(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
);
(void) fprintf(stderr
, "%s\n", strstatus(res
.status
));
keyprogram(rqstp
, transp
)
cryptkeyarg key_encrypt_1_arg
;
cryptkeyarg key_decrypt_1_arg
;
bool_t(*xdr_argument
) (), (*xdr_result
) ();
struct sockaddr_in remote
;
switch (rqstp
->rq_proc
) {
svc_sendreply(transp
, xdr_void
, (char *) NULL
);
xdr_argument
= xdr_keybuf
;
local
= (char *(*)()) key_set_1
;
xdr_argument
= xdr_cryptkeyarg
;
xdr_result
= xdr_cryptkeyres
;
local
= (char *(*)()) key_encrypt_1
;
xdr_argument
= xdr_cryptkeyarg
;
xdr_result
= xdr_cryptkeyres
;
local
= (char *(*)()) key_decrypt_1
;
xdr_result
= xdr_des_block
;
local
= (char *(*)()) key_gen_1
;
xdr_argument
= xdr_netnamestr
;
xdr_result
= xdr_getcredres
;
local
= (char *(*)()) key_getcred_1
;
remote
= *svc_getcaller(transp
);
if (ntohs(remote
.sin_port
) >= IPPORT_RESERVED
||
ntohl(remote
.sin_addr
.s_addr
) != INADDR_LOOPBACK
) {
"not local privileged process\n");
if (rqstp
->rq_cred
.oa_flavor
!= AUTH_UNIX
) {
"not unix authentication\n");
uid
= ((struct authunix_parms
*) rqstp
->rq_clntcred
)->aup_uid
;
bzero((char *) &argument
, sizeof(argument
));
if (!svc_getargs(transp
, xdr_argument
, &argument
)) {
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");