126219Swpaul/*
226219Swpaul * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
326219Swpaul * unrestricted use provided that this legend is included on all tape
426219Swpaul * media and as a part of the software program in whole or part.  Users
526219Swpaul * may copy or modify Sun RPC without charge, but are not authorized
626219Swpaul * to license or distribute it to anyone else except as part of a product or
726219Swpaul * program developed by the user.
826219Swpaul *
926219Swpaul * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1026219Swpaul * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1126219Swpaul * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1226219Swpaul *
1326219Swpaul * Sun RPC is provided with no support and without any obligation on the
1426219Swpaul * part of Sun Microsystems, Inc. to assist in its use, correction,
1526219Swpaul * modification or enhancement.
1626219Swpaul *
1726219Swpaul * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
1826219Swpaul * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
1926219Swpaul * OR ANY PART THEREOF.
2026219Swpaul *
2126219Swpaul * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2226219Swpaul * or profits or other special, indirect and consequential damages, even if
2326219Swpaul * Sun has been advised of the possibility of such damages.
2426219Swpaul *
2526219Swpaul * Sun Microsystems, Inc.
2626219Swpaul * 2550 Garcia Avenue
2726219Swpaul * Mountain View, California  94043
2826219Swpaul */
2926219Swpaul/*
3026219Swpaul * Copyright (c) 1988 by Sun Microsystems, Inc.
3126219Swpaul */
3226219Swpaul/*
3326219Swpaul * auth_des.c, client-side implementation of DES authentication
3426219Swpaul */
3592990Sobrien
3675094Siedowse#include "namespace.h"
3774462Salfred#include "reentrant.h"
3874462Salfred#include <err.h>
3974462Salfred#include <errno.h>
4026219Swpaul#include <string.h>
4126219Swpaul#include <stdlib.h>
4226219Swpaul#include <unistd.h>
4326219Swpaul#include <sys/cdefs.h>
4426219Swpaul#include <rpc/des_crypt.h>
4574462Salfred#include <syslog.h>
4626219Swpaul#include <rpc/types.h>
4726219Swpaul#include <rpc/auth.h>
4826219Swpaul#include <rpc/auth_des.h>
4974462Salfred#include <rpc/clnt.h>
5074462Salfred#include <rpc/xdr.h>
5126219Swpaul#include <sys/socket.h>
5226219Swpaul#undef NIS
5326219Swpaul#include <rpcsvc/nis.h>
5474462Salfred#include "un-namespace.h"
55156090Sdeischen#include "mt_misc.h"
5626219Swpaul
5726219Swpaul#if defined(LIBC_SCCS) && !defined(lint)
58136581Sobrienstatic char sccsid[] = 	"@(#)auth_des.c	2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI";
5926219Swpaul#endif
6092990Sobrien#include <sys/cdefs.h>
6192990Sobrien__FBSDID("$FreeBSD$");
6226219Swpaul
6374462Salfred#define USEC_PER_SEC		1000000
6474462Salfred#define RTIME_TIMEOUT		5	/* seconds to wait for sync */
6526219Swpaul
6626219Swpaul#define AUTH_PRIVATE(auth)	(struct ad_private *) auth->ah_private
6726219Swpaul#define ALLOC(object_type)	(object_type *) mem_alloc(sizeof(object_type))
6826219Swpaul#define FREE(ptr, size)		mem_free((char *)(ptr), (int) size)
6926219Swpaul#define ATTEMPT(xdr_op)		if (!(xdr_op)) return (FALSE)
7026219Swpaul
7174462Salfredextern bool_t xdr_authdes_cred( XDR *, struct authdes_cred *);
7274462Salfredextern bool_t xdr_authdes_verf( XDR *, struct authdes_verf *);
7374462Salfredextern int key_encryptsession_pk();
7426219Swpaul
7574462Salfredextern bool_t __rpc_get_time_offset(struct timeval *, nis_server *, char *,
7674462Salfred	char **, char **);
7774462Salfred
7826219Swpaul/*
7926219Swpaul * DES authenticator operations vector
8026219Swpaul */
8174462Salfredstatic void	authdes_nextverf(AUTH *);
8274462Salfredstatic bool_t	authdes_marshal(AUTH *, XDR *);
8374462Salfredstatic bool_t	authdes_validate(AUTH *, struct opaque_auth *);
8474462Salfredstatic bool_t	authdes_refresh(AUTH *, void *);
8574462Salfredstatic void	authdes_destroy(AUTH *);
8674462Salfred
8774462Salfredstatic struct auth_ops *authdes_ops(void);
8874462Salfred
8926219Swpaul/*
9026219Swpaul * This struct is pointed to by the ah_private field of an "AUTH *"
9126219Swpaul */
9226219Swpaulstruct ad_private {
9326219Swpaul	char *ad_fullname; 		/* client's full name */
9426219Swpaul	u_int ad_fullnamelen;		/* length of name, rounded up */
9526219Swpaul	char *ad_servername; 		/* server's full name */
9626219Swpaul	u_int ad_servernamelen;		/* length of name, rounded up */
9726219Swpaul	u_int ad_window;	  	/* client specified window */
9826219Swpaul	bool_t ad_dosync;		/* synchronize? */
9974462Salfred	struct netbuf ad_syncaddr;	/* remote host to synch with */
10026219Swpaul	char *ad_timehost;		/* remote host to synch with */
10126219Swpaul	struct timeval ad_timediff;	/* server's time - client's time */
10274462Salfred	u_int ad_nickname;		/* server's nickname for client */
10326219Swpaul	struct authdes_cred ad_cred;	/* storage for credential */
10426219Swpaul	struct authdes_verf ad_verf;	/* storage for verifier */
10526219Swpaul	struct timeval ad_timestamp;	/* timestamp sent */
10626219Swpaul	des_block ad_xkey;		/* encrypted conversation key */
10726219Swpaul	u_char ad_pkey[1024];		/* Server's actual public key */
10826219Swpaul	char *ad_netid;			/* Timehost netid */
10926219Swpaul	char *ad_uaddr;			/* Timehost uaddr */
11026219Swpaul	nis_server *ad_nis_srvr;	/* NIS+ server struct */
11126219Swpaul};
11274462Salfred
11374462SalfredAUTH *authdes_pk_seccreate(const char *, netobj *, u_int, const char *,
11474462Salfred	const des_block *, nis_server *);
11526219Swpaul
11674462Salfred/*
11774462Salfred * documented version of authdes_seccreate
11874462Salfred */
11974462Salfred/*
12074462Salfred	servername:	network name of server
12174462Salfred	win:		time to live
12274462Salfred	timehost:	optional hostname to sync with
12374462Salfred	ckey:		optional conversation key to use
12474462Salfred*/
12526219Swpaul
12626219SwpaulAUTH *
12774462Salfredauthdes_seccreate(const char *servername, const u_int win,
12874462Salfred	const char *timehost, const des_block *ckey)
12926219Swpaul{
13074462Salfred	u_char  pkey_data[1024];
13174462Salfred	netobj  pkey;
13274462Salfred	AUTH    *dummy;
13326219Swpaul
13474462Salfred	if (! getpublickey(servername, (char *) pkey_data)) {
13574462Salfred		syslog(LOG_ERR,
13674462Salfred		    "authdes_seccreate: no public key found for %s",
13774462Salfred		    servername);
13874462Salfred		return (NULL);
13926219Swpaul	}
14026219Swpaul
14174462Salfred	pkey.n_bytes = (char *) pkey_data;
14274462Salfred	pkey.n_len = (u_int)strlen((char *)pkey_data) + 1;
14374462Salfred	dummy = authdes_pk_seccreate(servername, &pkey, win, timehost,
14474462Salfred	    ckey, NULL);
14574462Salfred	return (dummy);
14626219Swpaul}
14726219Swpaul
14826219Swpaul/*
14974462Salfred * Slightly modified version of authdessec_create which takes the public key
15026219Swpaul * of the server principal as an argument. This spares us a call to
15126219Swpaul * getpublickey() which in the nameserver context can cause a deadlock.
15226219Swpaul */
15326219SwpaulAUTH *
15474462Salfredauthdes_pk_seccreate(const char *servername, netobj *pkey, u_int window,
15574462Salfred	const char *timehost, const des_block *ckey, nis_server *srvr)
15626219Swpaul{
15726219Swpaul	AUTH *auth;
15826219Swpaul	struct ad_private *ad;
15926219Swpaul	char namebuf[MAXNETNAMELEN+1];
16026219Swpaul
16126219Swpaul	/*
16226219Swpaul	 * Allocate everything now
16326219Swpaul	 */
16426219Swpaul	auth = ALLOC(AUTH);
16526219Swpaul	if (auth == NULL) {
16674462Salfred		syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
16726219Swpaul		return (NULL);
16826219Swpaul	}
16926219Swpaul	ad = ALLOC(struct ad_private);
17026219Swpaul	if (ad == NULL) {
17174462Salfred		syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
17226219Swpaul		goto failed;
17326219Swpaul	}
17426219Swpaul	ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */
17526219Swpaul	ad->ad_timehost = NULL;
17626219Swpaul	ad->ad_netid = NULL;
17726219Swpaul	ad->ad_uaddr = NULL;
17826219Swpaul	ad->ad_nis_srvr = NULL;
17926219Swpaul	ad->ad_timediff.tv_sec = 0;
18026219Swpaul	ad->ad_timediff.tv_usec = 0;
18126219Swpaul	memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len);
18226219Swpaul	if (!getnetname(namebuf))
18326219Swpaul		goto failed;
18426219Swpaul	ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf));
18526219Swpaul	ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1);
18626219Swpaul	ad->ad_servernamelen = strlen(servername);
18726219Swpaul	ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1);
18826219Swpaul
18926219Swpaul	if (ad->ad_fullname == NULL || ad->ad_servername == NULL) {
19074462Salfred		syslog(LOG_ERR, "authdes_seccreate: out of memory");
19126219Swpaul		goto failed;
19226219Swpaul	}
19326219Swpaul	if (timehost != NULL) {
19426219Swpaul		ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1);
19526219Swpaul		if (ad->ad_timehost == NULL) {
19674462Salfred			syslog(LOG_ERR, "authdes_seccreate: out of memory");
19726219Swpaul			goto failed;
19826219Swpaul		}
19926219Swpaul		memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1);
20026219Swpaul		ad->ad_dosync = TRUE;
20126219Swpaul	} else if (srvr != NULL) {
20226219Swpaul		ad->ad_nis_srvr = srvr;	/* transient */
20326219Swpaul		ad->ad_dosync = TRUE;
20426219Swpaul	} else {
20526219Swpaul		ad->ad_dosync = FALSE;
20626219Swpaul	}
20726219Swpaul	memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1);
20826219Swpaul	memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1);
20926219Swpaul	ad->ad_window = window;
21026219Swpaul	if (ckey == NULL) {
21126219Swpaul		if (key_gendes(&auth->ah_key) < 0) {
21274462Salfred			syslog(LOG_ERR,
21374462Salfred	    "authdes_seccreate: keyserv(1m) is unable to generate session key");
21426219Swpaul			goto failed;
21526219Swpaul		}
21626219Swpaul	} else {
21726219Swpaul		auth->ah_key = *ckey;
21826219Swpaul	}
21926219Swpaul
22026219Swpaul	/*
22126219Swpaul	 * Set up auth handle
22226219Swpaul	 */
22326219Swpaul	auth->ah_cred.oa_flavor = AUTH_DES;
22426219Swpaul	auth->ah_verf.oa_flavor = AUTH_DES;
22574462Salfred	auth->ah_ops = authdes_ops();
22626219Swpaul	auth->ah_private = (caddr_t)ad;
22726219Swpaul
22874462Salfred	if (!authdes_refresh(auth, NULL)) {
22926219Swpaul		goto failed;
23026219Swpaul	}
23126219Swpaul	ad->ad_nis_srvr = NULL; /* not needed any longer */
23226219Swpaul	return (auth);
23326219Swpaul
23426219Swpaulfailed:
23526219Swpaul	if (auth)
23626219Swpaul		FREE(auth, sizeof (AUTH));
23726219Swpaul	if (ad) {
23826219Swpaul		if (ad->ad_fullname)
23926219Swpaul			FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
24026219Swpaul		if (ad->ad_servername)
24126219Swpaul			FREE(ad->ad_servername, ad->ad_servernamelen + 1);
24226219Swpaul		if (ad->ad_timehost)
24326219Swpaul			FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
24426219Swpaul		if (ad->ad_netid)
24574462Salfred			FREE(ad->ad_netid, strlen(ad->ad_netid) + 1);
24626219Swpaul		if (ad->ad_uaddr)
24774462Salfred			FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1);
24826219Swpaul		FREE(ad, sizeof (struct ad_private));
24926219Swpaul	}
25026219Swpaul	return (NULL);
25126219Swpaul}
25274462Salfred
25326219Swpaul/*
25426219Swpaul * Implement the five authentication operations
25526219Swpaul */
25626219Swpaul
25726219Swpaul
25826219Swpaul/*
25926219Swpaul * 1. Next Verifier
26026219Swpaul */
26126219Swpaul/*ARGSUSED*/
26226219Swpaulstatic void
26374462Salfredauthdes_nextverf(AUTH *auth)
26426219Swpaul{
26526219Swpaul	/* what the heck am I supposed to do??? */
26626219Swpaul}
26726219Swpaul
26826219Swpaul
26926219Swpaul/*
27026219Swpaul * 2. Marshal
27126219Swpaul */
27226219Swpaulstatic bool_t
27374462Salfredauthdes_marshal(AUTH *auth, XDR *xdrs)
27426219Swpaul{
27574462Salfred/* LINTED pointer alignment */
27626219Swpaul	struct ad_private *ad = AUTH_PRIVATE(auth);
27726219Swpaul	struct authdes_cred *cred = &ad->ad_cred;
27826219Swpaul	struct authdes_verf *verf = &ad->ad_verf;
27926219Swpaul	des_block cryptbuf[2];
28026219Swpaul	des_block ivec;
28126219Swpaul	int status;
28274462Salfred	int len;
28392889Sobrien	rpc_inline_t *ixdr;
28426219Swpaul
28526219Swpaul	/*
28626219Swpaul	 * Figure out the "time", accounting for any time difference
28726219Swpaul	 * with the server if necessary.
28826219Swpaul	 */
289239991Sed	(void)gettimeofday(&ad->ad_timestamp, NULL);
29026219Swpaul	ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
29126219Swpaul	ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
29274462Salfred	while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) {
29374462Salfred		ad->ad_timestamp.tv_usec -= USEC_PER_SEC;
29474462Salfred		ad->ad_timestamp.tv_sec++;
29526219Swpaul	}
29626219Swpaul
29726219Swpaul	/*
29826219Swpaul	 * XDR the timestamp and possibly some other things, then
29926219Swpaul	 * encrypt them.
30026219Swpaul	 */
30174462Salfred	ixdr = (rpc_inline_t *)cryptbuf;
30274462Salfred	IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec);
30374462Salfred	IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec);
30426219Swpaul	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
30574462Salfred		IXDR_PUT_U_INT32(ixdr, ad->ad_window);
30674462Salfred		IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1);
30726219Swpaul		ivec.key.high = ivec.key.low = 0;
30826219Swpaul		status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf,
30974462Salfred			(u_int) 2 * sizeof (des_block),
31074462Salfred			DES_ENCRYPT | DES_HW, (char *)&ivec);
31126219Swpaul	} else {
31226219Swpaul		status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf,
31374462Salfred			(u_int) sizeof (des_block),
31474462Salfred			DES_ENCRYPT | DES_HW);
31526219Swpaul	}
31626219Swpaul	if (DES_FAILED(status)) {
31774462Salfred		syslog(LOG_ERR, "authdes_marshal: DES encryption failure");
31826219Swpaul		return (FALSE);
31926219Swpaul	}
32026219Swpaul	ad->ad_verf.adv_xtimestamp = cryptbuf[0];
32126219Swpaul	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
32226219Swpaul		ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
32326219Swpaul		ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
32426219Swpaul	} else {
32526219Swpaul		ad->ad_cred.adc_nickname = ad->ad_nickname;
32626219Swpaul		ad->ad_verf.adv_winverf = 0;
32726219Swpaul	}
32826219Swpaul
32926219Swpaul	/*
33026219Swpaul	 * Serialize the credential and verifier into opaque
33126219Swpaul	 * authentication data.
33226219Swpaul	 */
33326219Swpaul	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
33426219Swpaul		len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
33526219Swpaul	} else {
33626219Swpaul		len = (1 + 1)*BYTES_PER_XDR_UNIT;
33726219Swpaul	}
33826219Swpaul
33926219Swpaul	if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
34074462Salfred		IXDR_PUT_INT32(ixdr, AUTH_DES);
34174462Salfred		IXDR_PUT_INT32(ixdr, len);
34226219Swpaul	} else {
34374462Salfred		ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor));
34474462Salfred		ATTEMPT(xdr_putint32(xdrs, &len));
34526219Swpaul	}
34626219Swpaul	ATTEMPT(xdr_authdes_cred(xdrs, cred));
34726219Swpaul
34826219Swpaul	len = (2 + 1)*BYTES_PER_XDR_UNIT;
34926219Swpaul	if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
35074462Salfred		IXDR_PUT_INT32(ixdr, AUTH_DES);
35174462Salfred		IXDR_PUT_INT32(ixdr, len);
35226219Swpaul	} else {
35374462Salfred		ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor));
35474462Salfred		ATTEMPT(xdr_putint32(xdrs, &len));
35526219Swpaul	}
35626219Swpaul	ATTEMPT(xdr_authdes_verf(xdrs, verf));
35726219Swpaul	return (TRUE);
35826219Swpaul}
35926219Swpaul
36026219Swpaul
36126219Swpaul/*
36226219Swpaul * 3. Validate
36326219Swpaul */
36426219Swpaulstatic bool_t
36574462Salfredauthdes_validate(AUTH *auth, struct opaque_auth *rverf)
36626219Swpaul{
36774462Salfred/* LINTED pointer alignment */
36826219Swpaul	struct ad_private *ad = AUTH_PRIVATE(auth);
36926219Swpaul	struct authdes_verf verf;
37026219Swpaul	int status;
37192889Sobrien	uint32_t *ixdr;
37274462Salfred	des_block buf;
37326219Swpaul
37426219Swpaul	if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) {
37526219Swpaul		return (FALSE);
37626219Swpaul	}
37774462Salfred/* LINTED pointer alignment */
37874462Salfred	ixdr = (uint32_t *)rverf->oa_base;
37974462Salfred	buf.key.high = (uint32_t)*ixdr++;
38074462Salfred	buf.key.low = (uint32_t)*ixdr++;
38174462Salfred	verf.adv_int_u = (uint32_t)*ixdr++;
38226219Swpaul
38326219Swpaul	/*
38426219Swpaul	 * Decrypt the timestamp
38526219Swpaul	 */
38674462Salfred	status = ecb_crypt((char *)&auth->ah_key, (char *)&buf,
38774462Salfred		(u_int)sizeof (des_block), DES_DECRYPT | DES_HW);
38826219Swpaul
38926219Swpaul	if (DES_FAILED(status)) {
39074462Salfred		syslog(LOG_ERR, "authdes_validate: DES decryption failure");
39126219Swpaul		return (FALSE);
39226219Swpaul	}
39326219Swpaul
39426219Swpaul	/*
39574462Salfred	 * xdr the decrypted timestamp
39626219Swpaul	 */
39774462Salfred/* LINTED pointer alignment */
39874462Salfred	ixdr = (uint32_t *)buf.c;
39974462Salfred	verf.adv_timestamp.tv_sec = IXDR_GET_INT32(ixdr) + 1;
40074462Salfred	verf.adv_timestamp.tv_usec = IXDR_GET_INT32(ixdr);
40126219Swpaul
40226219Swpaul	/*
40326219Swpaul	 * validate
40426219Swpaul	 */
40526219Swpaul	if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp,
40626219Swpaul		 sizeof(struct timeval)) != 0) {
40774462Salfred		syslog(LOG_DEBUG, "authdes_validate: verifier mismatch");
40826219Swpaul		return (FALSE);
40926219Swpaul	}
41026219Swpaul
41126219Swpaul	/*
41226219Swpaul	 * We have a nickname now, let's use it
41326219Swpaul	 */
41474462Salfred	ad->ad_nickname = verf.adv_nickname;
41574462Salfred	ad->ad_cred.adc_namekind = ADN_NICKNAME;
41674462Salfred	return (TRUE);
41726219Swpaul}
41826219Swpaul
41926219Swpaul/*
42026219Swpaul * 4. Refresh
42126219Swpaul */
42274462Salfred/*ARGSUSED*/
42326219Swpaulstatic bool_t
42474462Salfredauthdes_refresh(AUTH *auth, void *dummy)
42526219Swpaul{
42674462Salfred/* LINTED pointer alignment */
42726219Swpaul	struct ad_private *ad = AUTH_PRIVATE(auth);
42826219Swpaul	struct authdes_cred *cred = &ad->ad_cred;
42974462Salfred	int		ok;
43026219Swpaul	netobj		pkey;
43126219Swpaul
43274462Salfred	if (ad->ad_dosync) {
43374462Salfred                ok = __rpc_get_time_offset(&ad->ad_timediff, ad->ad_nis_srvr,
43474462Salfred		    ad->ad_timehost, &(ad->ad_uaddr),
43574462Salfred		    &(ad->ad_netid));
43674462Salfred		if (! ok) {
43774462Salfred			/*
43874462Salfred			 * Hope the clocks are synced!
43974462Salfred			 */
44074462Salfred			ad->ad_dosync = 0;
44174462Salfred			syslog(LOG_DEBUG,
44274462Salfred			    "authdes_refresh: unable to synchronize clock");
44374462Salfred		 }
44426219Swpaul	}
44526219Swpaul	ad->ad_xkey = auth->ah_key;
44626219Swpaul	pkey.n_bytes = (char *)(ad->ad_pkey);
44774462Salfred	pkey.n_len = (u_int)strlen((char *)ad->ad_pkey) + 1;
44826219Swpaul	if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) {
44974462Salfred		syslog(LOG_INFO,
45074462Salfred		    "authdes_refresh: keyserv(1m) is unable to encrypt session key");
45126219Swpaul		return (FALSE);
45226219Swpaul	}
45326219Swpaul	cred->adc_fullname.key = ad->ad_xkey;
45426219Swpaul	cred->adc_namekind = ADN_FULLNAME;
45526219Swpaul	cred->adc_fullname.name = ad->ad_fullname;
45626219Swpaul	return (TRUE);
45726219Swpaul}
45826219Swpaul
45926219Swpaul
46026219Swpaul/*
46126219Swpaul * 5. Destroy
46226219Swpaul */
46326219Swpaulstatic void
46474462Salfredauthdes_destroy(AUTH *auth)
46526219Swpaul{
46674462Salfred/* LINTED pointer alignment */
46726219Swpaul	struct ad_private *ad = AUTH_PRIVATE(auth);
46826219Swpaul
46926219Swpaul	FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
47026219Swpaul	FREE(ad->ad_servername, ad->ad_servernamelen + 1);
47174462Salfred	if (ad->ad_timehost)
47274462Salfred		FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
47374462Salfred	if (ad->ad_netid)
47474462Salfred		FREE(ad->ad_netid, strlen(ad->ad_netid) + 1);
47574462Salfred	if (ad->ad_uaddr)
47674462Salfred		FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1);
47774462Salfred	FREE(ad, sizeof (struct ad_private));
47826219Swpaul	FREE(auth, sizeof(AUTH));
47926219Swpaul}
48026219Swpaul
48174462Salfredstatic struct auth_ops *
48274462Salfredauthdes_ops(void)
48326219Swpaul{
48474462Salfred	static struct auth_ops ops;
48526219Swpaul
48674462Salfred	/* VARIABLES PROTECTED BY ops_lock: ops */
48774462Salfred
48874462Salfred	mutex_lock(&authdes_ops_lock);
48974462Salfred	if (ops.ah_nextverf == NULL) {
49074462Salfred		ops.ah_nextverf = authdes_nextverf;
49174462Salfred		ops.ah_marshal = authdes_marshal;
49274462Salfred		ops.ah_validate = authdes_validate;
49374462Salfred		ops.ah_refresh = authdes_refresh;
49474462Salfred		ops.ah_destroy = authdes_destroy;
49574462Salfred        }
49674462Salfred	mutex_unlock(&authdes_ops_lock);
49774462Salfred	return (&ops);
49826219Swpaul}
499