xref: /onnv-gate/usr/src/lib/libnsl/rpc/auth_des.c (revision 132:e3f7eaf7dde4)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
21*132Srobinson  */
22*132Srobinson 
23*132Srobinson /*
24*132Srobinson  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
250Sstevel@tonic-gate  * Use is subject to license terms.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
280Sstevel@tonic-gate /* All Rights Reserved */
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley
310Sstevel@tonic-gate  * 4.3 BSD under license from the Regents of the University of
320Sstevel@tonic-gate  * California.
330Sstevel@tonic-gate  */
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate  * auth_des.c, client-side implementation of DES authentication
390Sstevel@tonic-gate  *
400Sstevel@tonic-gate  */
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #include "mt.h"
430Sstevel@tonic-gate #include "rpc_mt.h"
440Sstevel@tonic-gate #include <rpc/rpc.h>
450Sstevel@tonic-gate #include <rpc/des_crypt.h>
460Sstevel@tonic-gate #include <syslog.h>
470Sstevel@tonic-gate #include <stdlib.h>
480Sstevel@tonic-gate #include <string.h>
490Sstevel@tonic-gate #include <synch.h>
500Sstevel@tonic-gate #undef NIS
510Sstevel@tonic-gate #include <rpcsvc/nis.h>
520Sstevel@tonic-gate 
530Sstevel@tonic-gate #define	USEC_PER_SEC		1000000
540Sstevel@tonic-gate #define	RTIME_TIMEOUT		5	/* seconds to wait for sync */
550Sstevel@tonic-gate 
560Sstevel@tonic-gate extern bool_t xdr_authdes_cred(XDR *, struct authdes_cred *);
570Sstevel@tonic-gate extern bool_t xdr_authdes_verf(XDR *, struct authdes_verf *);
58*132Srobinson extern int key_encryptsession_pk(const char *, netobj *, des_block *);
590Sstevel@tonic-gate 
600Sstevel@tonic-gate extern bool_t __rpc_get_time_offset(struct timeval *, nis_server *, char *,
610Sstevel@tonic-gate 						char **, char **);
62*132Srobinson static struct auth_ops *authdes_ops(void);
63*132Srobinson static bool_t authdes_refresh(AUTH *, void *);
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /*
660Sstevel@tonic-gate  * This struct is pointed to by the ah_private field of an "AUTH *"
670Sstevel@tonic-gate  */
680Sstevel@tonic-gate struct ad_private {
690Sstevel@tonic-gate 	char *ad_fullname;		/* client's full name */
700Sstevel@tonic-gate 	uint_t ad_fullnamelen;		/* length of name, rounded up */
710Sstevel@tonic-gate 	char *ad_servername;		/* server's full name */
720Sstevel@tonic-gate 	size_t ad_servernamelen;	/* length of name, rounded up */
730Sstevel@tonic-gate 	uint_t ad_window;		/* client specified window */
740Sstevel@tonic-gate 	bool_t ad_dosync;		/* synchronize? */
750Sstevel@tonic-gate 	char *ad_timehost;		/* remote host to sync with */
760Sstevel@tonic-gate 	struct timeval ad_timediff;	/* server's time - client's time */
770Sstevel@tonic-gate 	uint_t ad_nickname;		/* server's nickname for client */
780Sstevel@tonic-gate 	struct authdes_cred ad_cred;	/* storage for credential */
790Sstevel@tonic-gate 	struct authdes_verf ad_verf;	/* storage for verifier */
800Sstevel@tonic-gate 	struct timeval ad_timestamp;	/* timestamp sent */
810Sstevel@tonic-gate 	des_block ad_xkey;		/* encrypted conversation key */
820Sstevel@tonic-gate 	uchar_t ad_pkey[1024];		/* Servers actual public key */
830Sstevel@tonic-gate 	char *ad_netid;			/* Timehost netid */
840Sstevel@tonic-gate 	char *ad_uaddr;			/* Timehost uaddr */
850Sstevel@tonic-gate 	nis_server *ad_nis_srvr;	/* NIS+ server struct */
860Sstevel@tonic-gate };
870Sstevel@tonic-gate 
88*132Srobinson extern AUTH *authdes_pk_seccreate(const char *, netobj *, uint_t, const char *,
890Sstevel@tonic-gate 				const des_block *, nis_server *);
900Sstevel@tonic-gate 
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate  * documented version of authdes_seccreate
930Sstevel@tonic-gate  */
940Sstevel@tonic-gate /*
950Sstevel@tonic-gate  *	servername: 	network name of server
960Sstevel@tonic-gate  *	win:		time to live
970Sstevel@tonic-gate  *	timehost:	optional hostname to sync with
980Sstevel@tonic-gate  *	ckey:		optional conversation key to use
990Sstevel@tonic-gate  */
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate AUTH *
authdes_seccreate(const char * servername,const uint_t win,const char * timehost,const des_block * ckey)1020Sstevel@tonic-gate authdes_seccreate(const char *servername, const uint_t win,
1030Sstevel@tonic-gate 	const char *timehost, const des_block *ckey)
1040Sstevel@tonic-gate {
1050Sstevel@tonic-gate 	uchar_t	pkey_data[1024];
1060Sstevel@tonic-gate 	netobj	pkey;
1070Sstevel@tonic-gate 
108*132Srobinson 	if (!getpublickey(servername, (char *)pkey_data)) {
1090Sstevel@tonic-gate 		syslog(LOG_ERR,
1100Sstevel@tonic-gate 			"authdes_seccreate: no public key found for %s",
1110Sstevel@tonic-gate 			servername);
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 		return (NULL);
1140Sstevel@tonic-gate 	}
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 	pkey.n_bytes = (char *)pkey_data;
1170Sstevel@tonic-gate 	pkey.n_len = (uint_t)strlen((char *)pkey_data) + 1;
118*132Srobinson 	return (authdes_pk_seccreate(servername, &pkey, win, timehost,
119*132Srobinson 					ckey, NULL));
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate /*
1230Sstevel@tonic-gate  * Slightly modified version of authdes_seccreate which takes the public key
1240Sstevel@tonic-gate  * of the server principal as an argument. This spares us a call to
1250Sstevel@tonic-gate  * getpublickey() which in the nameserver context can cause a deadlock.
1260Sstevel@tonic-gate  */
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate AUTH *
authdes_pk_seccreate(const char * servername,netobj * pkey,uint_t window,const char * timehost,const des_block * ckey,nis_server * srvr)1290Sstevel@tonic-gate authdes_pk_seccreate(const char *servername, netobj *pkey, uint_t window,
1300Sstevel@tonic-gate 	const char *timehost, const des_block *ckey, nis_server *srvr)
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate 	AUTH *auth;
1330Sstevel@tonic-gate 	struct ad_private *ad;
1340Sstevel@tonic-gate 	char namebuf[MAXNETNAMELEN+1];
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	/*
1370Sstevel@tonic-gate 	 * Allocate everything now
1380Sstevel@tonic-gate 	 */
139*132Srobinson 	auth = malloc(sizeof (AUTH));
1400Sstevel@tonic-gate 	if (auth == NULL) {
1410Sstevel@tonic-gate 		syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
1420Sstevel@tonic-gate 		return (NULL);
1430Sstevel@tonic-gate 	}
144*132Srobinson 	ad = malloc(sizeof (struct ad_private));
1450Sstevel@tonic-gate 	if (ad == NULL) {
1460Sstevel@tonic-gate 		syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
1470Sstevel@tonic-gate 		goto failed;
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 	ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */
1500Sstevel@tonic-gate 	ad->ad_timehost = NULL;
1510Sstevel@tonic-gate 	ad->ad_netid = NULL;
1520Sstevel@tonic-gate 	ad->ad_uaddr = NULL;
1530Sstevel@tonic-gate 	ad->ad_nis_srvr = NULL;
1540Sstevel@tonic-gate 	ad->ad_timediff.tv_sec = 0;
1550Sstevel@tonic-gate 	ad->ad_timediff.tv_usec = 0;
156*132Srobinson 	(void) memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len);
1570Sstevel@tonic-gate 	if (!getnetname(namebuf))
1580Sstevel@tonic-gate 		goto failed;
1590Sstevel@tonic-gate 	ad->ad_fullnamelen = RNDUP((uint_t)strlen(namebuf));
160*132Srobinson 	ad->ad_fullname = malloc(ad->ad_fullnamelen + 1);
1610Sstevel@tonic-gate 	ad->ad_servernamelen = strlen(servername);
162*132Srobinson 	ad->ad_servername = malloc(ad->ad_servernamelen + 1);
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	if (ad->ad_fullname == NULL || ad->ad_servername == NULL) {
1650Sstevel@tonic-gate 		syslog(LOG_ERR, "authdes_seccreate: out of memory");
1660Sstevel@tonic-gate 		goto failed;
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 	if (timehost != NULL) {
169*132Srobinson 		ad->ad_timehost = malloc(strlen(timehost) + 1);
1700Sstevel@tonic-gate 		if (ad->ad_timehost == NULL) {
1710Sstevel@tonic-gate 			syslog(LOG_ERR, "authdes_seccreate: out of memory");
1720Sstevel@tonic-gate 			goto failed;
1730Sstevel@tonic-gate 		}
174*132Srobinson 		(void) memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1);
1750Sstevel@tonic-gate 		ad->ad_dosync = TRUE;
1760Sstevel@tonic-gate 	} else if (srvr != NULL) {
1770Sstevel@tonic-gate 		ad->ad_nis_srvr = srvr;	/* transient */
1780Sstevel@tonic-gate 		ad->ad_dosync = TRUE;
1790Sstevel@tonic-gate 	} else {
1800Sstevel@tonic-gate 		ad->ad_dosync = FALSE;
1810Sstevel@tonic-gate 	}
182*132Srobinson 	(void) memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1);
183*132Srobinson 	(void) memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1);
1840Sstevel@tonic-gate 	ad->ad_window = window;
1850Sstevel@tonic-gate 	if (ckey == NULL) {
1860Sstevel@tonic-gate 		if (key_gendes(&auth->ah_key) < 0) {
1870Sstevel@tonic-gate 			syslog(LOG_ERR,
1880Sstevel@tonic-gate 	"authdes_seccreate: keyserv(1m) is unable to generate session key");
1890Sstevel@tonic-gate 			goto failed;
1900Sstevel@tonic-gate 		}
1910Sstevel@tonic-gate 	} else
1920Sstevel@tonic-gate 		auth->ah_key = *ckey;
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	/*
1950Sstevel@tonic-gate 	 * Set up auth handle
1960Sstevel@tonic-gate 	 */
1970Sstevel@tonic-gate 	auth->ah_cred.oa_flavor = AUTH_DES;
1980Sstevel@tonic-gate 	auth->ah_verf.oa_flavor = AUTH_DES;
1990Sstevel@tonic-gate 	auth->ah_ops = authdes_ops();
2000Sstevel@tonic-gate 	auth->ah_private = (caddr_t)ad;
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	if (!authdes_refresh(auth, NULL)) {
2030Sstevel@tonic-gate 		goto failed;
2040Sstevel@tonic-gate 	}
2050Sstevel@tonic-gate 	ad->ad_nis_srvr = NULL; /* not needed any longer */
2060Sstevel@tonic-gate 	return (auth);
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate failed:
2090Sstevel@tonic-gate 	if (auth)
210*132Srobinson 		free(auth);
2110Sstevel@tonic-gate 	if (ad) {
2120Sstevel@tonic-gate 		if (ad->ad_fullname)
213*132Srobinson 			free(ad->ad_fullname);
2140Sstevel@tonic-gate 		if (ad->ad_servername)
215*132Srobinson 			free(ad->ad_servername);
2160Sstevel@tonic-gate 		if (ad->ad_timehost)
217*132Srobinson 			free(ad->ad_timehost);
2180Sstevel@tonic-gate 		if (ad->ad_netid)
219*132Srobinson 			free(ad->ad_netid);
2200Sstevel@tonic-gate 		if (ad->ad_uaddr)
221*132Srobinson 			free(ad->ad_uaddr);
222*132Srobinson 		free(ad);
2230Sstevel@tonic-gate 	}
2240Sstevel@tonic-gate 	return (NULL);
2250Sstevel@tonic-gate }
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate /*
2280Sstevel@tonic-gate  * Implement the five authentication operations
2290Sstevel@tonic-gate  */
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate /*
2320Sstevel@tonic-gate  * 1. Next Verifier
2330Sstevel@tonic-gate  */
2340Sstevel@tonic-gate /*ARGSUSED*/
2350Sstevel@tonic-gate static void
authdes_nextverf(AUTH * auth)2360Sstevel@tonic-gate authdes_nextverf(AUTH *auth)
2370Sstevel@tonic-gate {
2380Sstevel@tonic-gate 	/* what the heck am I supposed to do??? */
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate /*
2430Sstevel@tonic-gate  * 2. Marshal
2440Sstevel@tonic-gate  */
2450Sstevel@tonic-gate static bool_t
authdes_marshal(AUTH * auth,XDR * xdrs)2460Sstevel@tonic-gate authdes_marshal(AUTH *auth, XDR *xdrs)
2470Sstevel@tonic-gate {
2480Sstevel@tonic-gate /* LINTED pointer alignment */
249*132Srobinson 	struct ad_private *ad = (struct ad_private *)auth->ah_private;
2500Sstevel@tonic-gate 	struct authdes_cred *cred = &ad->ad_cred;
2510Sstevel@tonic-gate 	struct authdes_verf *verf = &ad->ad_verf;
2520Sstevel@tonic-gate 	des_block cryptbuf[2];
2530Sstevel@tonic-gate 	des_block ivec;
2540Sstevel@tonic-gate 	int status;
2550Sstevel@tonic-gate 	int len;
2560Sstevel@tonic-gate 	rpc_inline_t *ixdr;
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	/*
2590Sstevel@tonic-gate 	 * Figure out the "time", accounting for any time difference
2600Sstevel@tonic-gate 	 * with the server if necessary.
2610Sstevel@tonic-gate 	 */
262*132Srobinson 	(void) gettimeofday(&ad->ad_timestamp, NULL);
2630Sstevel@tonic-gate 	ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
2640Sstevel@tonic-gate 	ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
2650Sstevel@tonic-gate 	while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) {
2660Sstevel@tonic-gate 		ad->ad_timestamp.tv_usec -= USEC_PER_SEC;
2670Sstevel@tonic-gate 		ad->ad_timestamp.tv_sec++;
2680Sstevel@tonic-gate 	}
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	/*
2710Sstevel@tonic-gate 	 * XDR the timestamp and possibly some other things, then
2720Sstevel@tonic-gate 	 * encrypt them.
2730Sstevel@tonic-gate 	 */
2740Sstevel@tonic-gate 	ixdr = (rpc_inline_t *)cryptbuf;
2750Sstevel@tonic-gate 	IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec);
2760Sstevel@tonic-gate 	IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec);
2770Sstevel@tonic-gate 	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
2780Sstevel@tonic-gate 		IXDR_PUT_U_INT32(ixdr, ad->ad_window);
2790Sstevel@tonic-gate 		IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1);
2800Sstevel@tonic-gate 		ivec.key.high = ivec.key.low = 0;
2810Sstevel@tonic-gate 		status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf,
2820Sstevel@tonic-gate 				2 * sizeof (des_block),
2830Sstevel@tonic-gate 				DES_ENCRYPT | DES_HW, (char *)&ivec);
2840Sstevel@tonic-gate 	} else {
2850Sstevel@tonic-gate 		status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf,
2860Sstevel@tonic-gate 				sizeof (des_block),
2870Sstevel@tonic-gate 				DES_ENCRYPT | DES_HW);
2880Sstevel@tonic-gate 	}
2890Sstevel@tonic-gate 	if (DES_FAILED(status)) {
2900Sstevel@tonic-gate 		syslog(LOG_ERR, "authdes_marshal: DES encryption failure");
2910Sstevel@tonic-gate 		return (FALSE);
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate 	ad->ad_verf.adv_xtimestamp = cryptbuf[0];
2940Sstevel@tonic-gate 	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
2950Sstevel@tonic-gate 		ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
2960Sstevel@tonic-gate 		ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
2970Sstevel@tonic-gate 	} else {
2980Sstevel@tonic-gate 		ad->ad_cred.adc_nickname = ad->ad_nickname;
2990Sstevel@tonic-gate 		ad->ad_verf.adv_winverf = 0;
3000Sstevel@tonic-gate 	}
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate 	/*
3030Sstevel@tonic-gate 	 * Serialize the credential and verifier into opaque
3040Sstevel@tonic-gate 	 * authentication data.
3050Sstevel@tonic-gate 	 */
3060Sstevel@tonic-gate 	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
3070Sstevel@tonic-gate 		len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
3080Sstevel@tonic-gate 	} else {
3090Sstevel@tonic-gate 		len = (1 + 1)*BYTES_PER_XDR_UNIT;
3100Sstevel@tonic-gate 	}
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	if (ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT)) {
3130Sstevel@tonic-gate 		IXDR_PUT_INT32(ixdr, AUTH_DES);
3140Sstevel@tonic-gate 		IXDR_PUT_INT32(ixdr, len);
3150Sstevel@tonic-gate 	} else {
316*132Srobinson 		if (!xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor))
317*132Srobinson 			return (FALSE);
318*132Srobinson 		if (!xdr_putint32(xdrs, &len))
319*132Srobinson 			return (FALSE);
3200Sstevel@tonic-gate 	}
321*132Srobinson 	if (!xdr_authdes_cred(xdrs, cred))
322*132Srobinson 		return (FALSE);
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	len = (2 + 1)*BYTES_PER_XDR_UNIT;
3250Sstevel@tonic-gate 	if (ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT)) {
3260Sstevel@tonic-gate 		IXDR_PUT_INT32(ixdr, AUTH_DES);
3270Sstevel@tonic-gate 		IXDR_PUT_INT32(ixdr, len);
3280Sstevel@tonic-gate 	} else {
329*132Srobinson 		if (!xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor))
330*132Srobinson 			return (FALSE);
331*132Srobinson 		if (!xdr_putint32(xdrs, &len))
332*132Srobinson 			return (FALSE);
3330Sstevel@tonic-gate 	}
334*132Srobinson 	return (xdr_authdes_verf(xdrs, verf));
3350Sstevel@tonic-gate }
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate /*
3390Sstevel@tonic-gate  * 3. Validate
3400Sstevel@tonic-gate  */
3410Sstevel@tonic-gate static bool_t
authdes_validate(AUTH * auth,struct opaque_auth * rverf)3420Sstevel@tonic-gate authdes_validate(AUTH *auth, struct opaque_auth *rverf)
3430Sstevel@tonic-gate {
3440Sstevel@tonic-gate /* LINTED pointer alignment */
345*132Srobinson 	struct ad_private *ad = (struct ad_private *)auth->ah_private;
3460Sstevel@tonic-gate 	struct authdes_verf verf;
3470Sstevel@tonic-gate 	int status;
3480Sstevel@tonic-gate 	uint32_t *ixdr;
3490Sstevel@tonic-gate 	des_block buf;
3500Sstevel@tonic-gate 
351*132Srobinson 	if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT)
3520Sstevel@tonic-gate 		return (FALSE);
3530Sstevel@tonic-gate /* LINTED pointer alignment */
3540Sstevel@tonic-gate 	ixdr = (uint32_t *)rverf->oa_base;
3550Sstevel@tonic-gate 	buf.key.high = (uint32_t)*ixdr++;
3560Sstevel@tonic-gate 	buf.key.low = (uint32_t)*ixdr++;
3570Sstevel@tonic-gate 	verf.adv_int_u = (uint32_t)*ixdr++;
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 	/*
3600Sstevel@tonic-gate 	 * Decrypt the timestamp
3610Sstevel@tonic-gate 	 */
3620Sstevel@tonic-gate 	status = ecb_crypt((char *)&auth->ah_key, (char *)&buf,
3630Sstevel@tonic-gate 		sizeof (des_block), DES_DECRYPT | DES_HW);
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	if (DES_FAILED(status)) {
3660Sstevel@tonic-gate 		syslog(LOG_ERR, "authdes_validate: DES decryption failure");
3670Sstevel@tonic-gate 		return (FALSE);
3680Sstevel@tonic-gate 	}
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	/*
3710Sstevel@tonic-gate 	 * xdr the decrypted timestamp
3720Sstevel@tonic-gate 	 */
3730Sstevel@tonic-gate /* LINTED pointer alignment */
3740Sstevel@tonic-gate 	ixdr = (uint32_t *)buf.c;
3750Sstevel@tonic-gate 	verf.adv_timestamp.tv_sec = IXDR_GET_INT32(ixdr) + 1;
3760Sstevel@tonic-gate 	verf.adv_timestamp.tv_usec = IXDR_GET_INT32(ixdr);
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	/*
3790Sstevel@tonic-gate 	 * validate
3800Sstevel@tonic-gate 	 */
381*132Srobinson 	if (memcmp(&ad->ad_timestamp, &verf.adv_timestamp,
3820Sstevel@tonic-gate 		sizeof (struct timeval)) != 0) {
3830Sstevel@tonic-gate 		syslog(LOG_DEBUG, "authdes_validate: verifier mismatch");
3840Sstevel@tonic-gate 		return (FALSE);
3850Sstevel@tonic-gate 	}
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	/*
3880Sstevel@tonic-gate 	 * We have a nickname now, let's use it
3890Sstevel@tonic-gate 	 */
3900Sstevel@tonic-gate 	ad->ad_nickname = verf.adv_nickname;
3910Sstevel@tonic-gate 	ad->ad_cred.adc_namekind = ADN_NICKNAME;
3920Sstevel@tonic-gate 	return (TRUE);
3930Sstevel@tonic-gate }
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate /*
3960Sstevel@tonic-gate  * 4. Refresh
3970Sstevel@tonic-gate  */
3980Sstevel@tonic-gate /*ARGSUSED*/
3990Sstevel@tonic-gate static bool_t
authdes_refresh(AUTH * auth,void * dummy)4000Sstevel@tonic-gate authdes_refresh(AUTH *auth, void *dummy)
4010Sstevel@tonic-gate {
4020Sstevel@tonic-gate /* LINTED pointer alignment */
403*132Srobinson 	struct ad_private *ad = (struct ad_private *)auth->ah_private;
4040Sstevel@tonic-gate 	struct authdes_cred *cred = &ad->ad_cred;
4050Sstevel@tonic-gate 	int		ok;
4060Sstevel@tonic-gate 	netobj		pkey;
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	if (ad->ad_dosync) {
4090Sstevel@tonic-gate 		ok = __rpc_get_time_offset(&ad->ad_timediff, ad->ad_nis_srvr,
4100Sstevel@tonic-gate 					    ad->ad_timehost, &(ad->ad_uaddr),
4110Sstevel@tonic-gate 					    &(ad->ad_netid));
412*132Srobinson 		if (!ok) {
4130Sstevel@tonic-gate 			/*
4140Sstevel@tonic-gate 			 * Hope the clocks are synced!
4150Sstevel@tonic-gate 			 */
4160Sstevel@tonic-gate 			ad->ad_dosync = 0;
4170Sstevel@tonic-gate 			syslog(LOG_DEBUG,
4180Sstevel@tonic-gate 		    "authdes_refresh: unable to synchronize clock");
4190Sstevel@tonic-gate 		}
4200Sstevel@tonic-gate 	}
4210Sstevel@tonic-gate 	ad->ad_xkey = auth->ah_key;
4220Sstevel@tonic-gate 	pkey.n_bytes = (char *)(ad->ad_pkey);
4230Sstevel@tonic-gate 	pkey.n_len = (uint_t)strlen((char *)ad->ad_pkey) + 1;
4240Sstevel@tonic-gate 	if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) {
4250Sstevel@tonic-gate 		syslog(LOG_INFO,
4260Sstevel@tonic-gate 	"authdes_refresh: keyserv(1m) is unable to encrypt session key");
4270Sstevel@tonic-gate 		return (FALSE);
4280Sstevel@tonic-gate 	}
4290Sstevel@tonic-gate 	cred->adc_fullname.key = ad->ad_xkey;
4300Sstevel@tonic-gate 	cred->adc_namekind = ADN_FULLNAME;
4310Sstevel@tonic-gate 	cred->adc_fullname.name = ad->ad_fullname;
4320Sstevel@tonic-gate 	return (TRUE);
4330Sstevel@tonic-gate }
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate /*
4370Sstevel@tonic-gate  * 5. Destroy
4380Sstevel@tonic-gate  */
4390Sstevel@tonic-gate static void
authdes_destroy(AUTH * auth)4400Sstevel@tonic-gate authdes_destroy(AUTH *auth)
4410Sstevel@tonic-gate {
4420Sstevel@tonic-gate /* LINTED pointer alignment */
443*132Srobinson 	struct ad_private *ad = (struct ad_private *)auth->ah_private;
4440Sstevel@tonic-gate 
445*132Srobinson 	free(ad->ad_fullname);
446*132Srobinson 	free(ad->ad_servername);
4470Sstevel@tonic-gate 	if (ad->ad_timehost)
448*132Srobinson 		free(ad->ad_timehost);
4490Sstevel@tonic-gate 	if (ad->ad_netid)
450*132Srobinson 		free(ad->ad_netid);
4510Sstevel@tonic-gate 	if (ad->ad_uaddr)
452*132Srobinson 		free(ad->ad_uaddr);
453*132Srobinson 	free(ad);
454*132Srobinson 	free(auth);
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate static struct auth_ops *
authdes_ops(void)4580Sstevel@tonic-gate authdes_ops(void)
4590Sstevel@tonic-gate {
4600Sstevel@tonic-gate 	static struct auth_ops ops;
4610Sstevel@tonic-gate 	extern mutex_t ops_lock;
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	/* VARIABLES PROTECTED BY ops_lock: ops */
4640Sstevel@tonic-gate 
465*132Srobinson 	(void) mutex_lock(&ops_lock);
4660Sstevel@tonic-gate 	if (ops.ah_nextverf == NULL) {
4670Sstevel@tonic-gate 		ops.ah_nextverf = authdes_nextverf;
4680Sstevel@tonic-gate 		ops.ah_marshal = authdes_marshal;
4690Sstevel@tonic-gate 		ops.ah_validate = authdes_validate;
4700Sstevel@tonic-gate 		ops.ah_refresh = authdes_refresh;
4710Sstevel@tonic-gate 		ops.ah_destroy = authdes_destroy;
4720Sstevel@tonic-gate 	}
473*132Srobinson 	(void) mutex_unlock(&ops_lock);
4740Sstevel@tonic-gate 	return (&ops);
4750Sstevel@tonic-gate }
476