1261046Smav/*-
2261046Smav * Copyright (c) 2009, Sun Microsystems, Inc.
3261046Smav * All rights reserved.
4261046Smav *
5261046Smav * Redistribution and use in source and binary forms, with or without
6261046Smav * modification, are permitted provided that the following conditions are met:
7261046Smav * - Redistributions of source code must retain the above copyright notice,
8261046Smav *   this list of conditions and the following disclaimer.
9261046Smav * - Redistributions in binary form must reproduce the above copyright notice,
10261046Smav *   this list of conditions and the following disclaimer in the documentation
11261046Smav *   and/or other materials provided with the distribution.
12261046Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its
13261046Smav *   contributors may be used to endorse or promote products derived
14261046Smav *   from this software without specific prior written permission.
1526219Swpaul *
16261046Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17261046Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18261046Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19261046Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20261046Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21261046Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22261046Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23261046Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24261046Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25261046Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26261046Smav * POSSIBILITY OF SUCH DAMAGE.
2726219Swpaul */
2826219Swpaul/*
2926219Swpaul * Copyright (c) 1988 by Sun Microsystems, Inc.
3026219Swpaul */
3126219Swpaul/*
3226219Swpaul * auth_des.c, client-side implementation of DES authentication
3326219Swpaul */
3492990Sobrien
3575094Siedowse#include "namespace.h"
3674462Salfred#include "reentrant.h"
3774462Salfred#include <err.h>
3874462Salfred#include <errno.h>
3926219Swpaul#include <string.h>
4026219Swpaul#include <stdlib.h>
4126219Swpaul#include <unistd.h>
4226219Swpaul#include <sys/cdefs.h>
4326219Swpaul#include <rpc/des_crypt.h>
4474462Salfred#include <syslog.h>
4526219Swpaul#include <rpc/types.h>
4626219Swpaul#include <rpc/auth.h>
4726219Swpaul#include <rpc/auth_des.h>
4874462Salfred#include <rpc/clnt.h>
4974462Salfred#include <rpc/xdr.h>
5026219Swpaul#include <sys/socket.h>
5126219Swpaul#undef NIS
5226219Swpaul#include <rpcsvc/nis.h>
5374462Salfred#include "un-namespace.h"
54156090Sdeischen#include "mt_misc.h"
5526219Swpaul
5626219Swpaul#if defined(LIBC_SCCS) && !defined(lint)
57136581Sobrienstatic char sccsid[] = 	"@(#)auth_des.c	2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI";
5826219Swpaul#endif
5992990Sobrien#include <sys/cdefs.h>
6092990Sobrien__FBSDID("$FreeBSD: releng/10.2/lib/libc/rpc/auth_des.c 261046 2014-01-22 23:45:27Z mav $");
6126219Swpaul
6274462Salfred#define USEC_PER_SEC		1000000
6374462Salfred#define RTIME_TIMEOUT		5	/* seconds to wait for sync */
6426219Swpaul
6526219Swpaul#define AUTH_PRIVATE(auth)	(struct ad_private *) auth->ah_private
6626219Swpaul#define ALLOC(object_type)	(object_type *) mem_alloc(sizeof(object_type))
6726219Swpaul#define FREE(ptr, size)		mem_free((char *)(ptr), (int) size)
6826219Swpaul#define ATTEMPT(xdr_op)		if (!(xdr_op)) return (FALSE)
6926219Swpaul
7074462Salfredextern bool_t xdr_authdes_cred( XDR *, struct authdes_cred *);
7174462Salfredextern bool_t xdr_authdes_verf( XDR *, struct authdes_verf *);
7274462Salfredextern int key_encryptsession_pk();
7326219Swpaul
7474462Salfredextern bool_t __rpc_get_time_offset(struct timeval *, nis_server *, char *,
7574462Salfred	char **, char **);
7674462Salfred
7726219Swpaul/*
7826219Swpaul * DES authenticator operations vector
7926219Swpaul */
8074462Salfredstatic void	authdes_nextverf(AUTH *);
8174462Salfredstatic bool_t	authdes_marshal(AUTH *, XDR *);
8274462Salfredstatic bool_t	authdes_validate(AUTH *, struct opaque_auth *);
8374462Salfredstatic bool_t	authdes_refresh(AUTH *, void *);
8474462Salfredstatic void	authdes_destroy(AUTH *);
8574462Salfred
8674462Salfredstatic struct auth_ops *authdes_ops(void);
8774462Salfred
8826219Swpaul/*
8926219Swpaul * This struct is pointed to by the ah_private field of an "AUTH *"
9026219Swpaul */
9126219Swpaulstruct ad_private {
9226219Swpaul	char *ad_fullname; 		/* client's full name */
9326219Swpaul	u_int ad_fullnamelen;		/* length of name, rounded up */
9426219Swpaul	char *ad_servername; 		/* server's full name */
9526219Swpaul	u_int ad_servernamelen;		/* length of name, rounded up */
9626219Swpaul	u_int ad_window;	  	/* client specified window */
9726219Swpaul	bool_t ad_dosync;		/* synchronize? */
9874462Salfred	struct netbuf ad_syncaddr;	/* remote host to synch with */
9926219Swpaul	char *ad_timehost;		/* remote host to synch with */
10026219Swpaul	struct timeval ad_timediff;	/* server's time - client's time */
10174462Salfred	u_int ad_nickname;		/* server's nickname for client */
10226219Swpaul	struct authdes_cred ad_cred;	/* storage for credential */
10326219Swpaul	struct authdes_verf ad_verf;	/* storage for verifier */
10426219Swpaul	struct timeval ad_timestamp;	/* timestamp sent */
10526219Swpaul	des_block ad_xkey;		/* encrypted conversation key */
10626219Swpaul	u_char ad_pkey[1024];		/* Server's actual public key */
10726219Swpaul	char *ad_netid;			/* Timehost netid */
10826219Swpaul	char *ad_uaddr;			/* Timehost uaddr */
10926219Swpaul	nis_server *ad_nis_srvr;	/* NIS+ server struct */
11026219Swpaul};
11174462Salfred
11274462SalfredAUTH *authdes_pk_seccreate(const char *, netobj *, u_int, const char *,
11374462Salfred	const des_block *, nis_server *);
11426219Swpaul
11574462Salfred/*
11674462Salfred * documented version of authdes_seccreate
11774462Salfred */
11874462Salfred/*
11974462Salfred	servername:	network name of server
12074462Salfred	win:		time to live
12174462Salfred	timehost:	optional hostname to sync with
12274462Salfred	ckey:		optional conversation key to use
12374462Salfred*/
12426219Swpaul
12526219SwpaulAUTH *
12674462Salfredauthdes_seccreate(const char *servername, const u_int win,
12774462Salfred	const char *timehost, const des_block *ckey)
12826219Swpaul{
12974462Salfred	u_char  pkey_data[1024];
13074462Salfred	netobj  pkey;
13174462Salfred	AUTH    *dummy;
13226219Swpaul
13374462Salfred	if (! getpublickey(servername, (char *) pkey_data)) {
13474462Salfred		syslog(LOG_ERR,
13574462Salfred		    "authdes_seccreate: no public key found for %s",
13674462Salfred		    servername);
13774462Salfred		return (NULL);
13826219Swpaul	}
13926219Swpaul
14074462Salfred	pkey.n_bytes = (char *) pkey_data;
14174462Salfred	pkey.n_len = (u_int)strlen((char *)pkey_data) + 1;
14274462Salfred	dummy = authdes_pk_seccreate(servername, &pkey, win, timehost,
14374462Salfred	    ckey, NULL);
14474462Salfred	return (dummy);
14526219Swpaul}
14626219Swpaul
14726219Swpaul/*
14874462Salfred * Slightly modified version of authdessec_create which takes the public key
14926219Swpaul * of the server principal as an argument. This spares us a call to
15026219Swpaul * getpublickey() which in the nameserver context can cause a deadlock.
15126219Swpaul */
15226219SwpaulAUTH *
15374462Salfredauthdes_pk_seccreate(const char *servername, netobj *pkey, u_int window,
15474462Salfred	const char *timehost, const des_block *ckey, nis_server *srvr)
15526219Swpaul{
15626219Swpaul	AUTH *auth;
15726219Swpaul	struct ad_private *ad;
15826219Swpaul	char namebuf[MAXNETNAMELEN+1];
15926219Swpaul
16026219Swpaul	/*
16126219Swpaul	 * Allocate everything now
16226219Swpaul	 */
16326219Swpaul	auth = ALLOC(AUTH);
16426219Swpaul	if (auth == NULL) {
16574462Salfred		syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
16626219Swpaul		return (NULL);
16726219Swpaul	}
16826219Swpaul	ad = ALLOC(struct ad_private);
16926219Swpaul	if (ad == NULL) {
17074462Salfred		syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
17126219Swpaul		goto failed;
17226219Swpaul	}
17326219Swpaul	ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */
17426219Swpaul	ad->ad_timehost = NULL;
17526219Swpaul	ad->ad_netid = NULL;
17626219Swpaul	ad->ad_uaddr = NULL;
17726219Swpaul	ad->ad_nis_srvr = NULL;
17826219Swpaul	ad->ad_timediff.tv_sec = 0;
17926219Swpaul	ad->ad_timediff.tv_usec = 0;
18026219Swpaul	memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len);
18126219Swpaul	if (!getnetname(namebuf))
18226219Swpaul		goto failed;
18326219Swpaul	ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf));
18426219Swpaul	ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1);
18526219Swpaul	ad->ad_servernamelen = strlen(servername);
18626219Swpaul	ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1);
18726219Swpaul
18826219Swpaul	if (ad->ad_fullname == NULL || ad->ad_servername == NULL) {
18974462Salfred		syslog(LOG_ERR, "authdes_seccreate: out of memory");
19026219Swpaul		goto failed;
19126219Swpaul	}
19226219Swpaul	if (timehost != NULL) {
19326219Swpaul		ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1);
19426219Swpaul		if (ad->ad_timehost == NULL) {
19574462Salfred			syslog(LOG_ERR, "authdes_seccreate: out of memory");
19626219Swpaul			goto failed;
19726219Swpaul		}
19826219Swpaul		memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1);
19926219Swpaul		ad->ad_dosync = TRUE;
20026219Swpaul	} else if (srvr != NULL) {
20126219Swpaul		ad->ad_nis_srvr = srvr;	/* transient */
20226219Swpaul		ad->ad_dosync = TRUE;
20326219Swpaul	} else {
20426219Swpaul		ad->ad_dosync = FALSE;
20526219Swpaul	}
20626219Swpaul	memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1);
20726219Swpaul	memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1);
20826219Swpaul	ad->ad_window = window;
20926219Swpaul	if (ckey == NULL) {
21026219Swpaul		if (key_gendes(&auth->ah_key) < 0) {
21174462Salfred			syslog(LOG_ERR,
21274462Salfred	    "authdes_seccreate: keyserv(1m) is unable to generate session key");
21326219Swpaul			goto failed;
21426219Swpaul		}
21526219Swpaul	} else {
21626219Swpaul		auth->ah_key = *ckey;
21726219Swpaul	}
21826219Swpaul
21926219Swpaul	/*
22026219Swpaul	 * Set up auth handle
22126219Swpaul	 */
22226219Swpaul	auth->ah_cred.oa_flavor = AUTH_DES;
22326219Swpaul	auth->ah_verf.oa_flavor = AUTH_DES;
22474462Salfred	auth->ah_ops = authdes_ops();
22526219Swpaul	auth->ah_private = (caddr_t)ad;
22626219Swpaul
22774462Salfred	if (!authdes_refresh(auth, NULL)) {
22826219Swpaul		goto failed;
22926219Swpaul	}
23026219Swpaul	ad->ad_nis_srvr = NULL; /* not needed any longer */
23126219Swpaul	return (auth);
23226219Swpaul
23326219Swpaulfailed:
23426219Swpaul	if (auth)
23526219Swpaul		FREE(auth, sizeof (AUTH));
23626219Swpaul	if (ad) {
23726219Swpaul		if (ad->ad_fullname)
23826219Swpaul			FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
23926219Swpaul		if (ad->ad_servername)
24026219Swpaul			FREE(ad->ad_servername, ad->ad_servernamelen + 1);
24126219Swpaul		if (ad->ad_timehost)
24226219Swpaul			FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
24326219Swpaul		if (ad->ad_netid)
24474462Salfred			FREE(ad->ad_netid, strlen(ad->ad_netid) + 1);
24526219Swpaul		if (ad->ad_uaddr)
24674462Salfred			FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1);
24726219Swpaul		FREE(ad, sizeof (struct ad_private));
24826219Swpaul	}
24926219Swpaul	return (NULL);
25026219Swpaul}
25174462Salfred
25226219Swpaul/*
25326219Swpaul * Implement the five authentication operations
25426219Swpaul */
25526219Swpaul
25626219Swpaul
25726219Swpaul/*
25826219Swpaul * 1. Next Verifier
25926219Swpaul */
26026219Swpaul/*ARGSUSED*/
26126219Swpaulstatic void
26274462Salfredauthdes_nextverf(AUTH *auth)
26326219Swpaul{
26426219Swpaul	/* what the heck am I supposed to do??? */
26526219Swpaul}
26626219Swpaul
26726219Swpaul
26826219Swpaul/*
26926219Swpaul * 2. Marshal
27026219Swpaul */
27126219Swpaulstatic bool_t
27274462Salfredauthdes_marshal(AUTH *auth, XDR *xdrs)
27326219Swpaul{
27474462Salfred/* LINTED pointer alignment */
27526219Swpaul	struct ad_private *ad = AUTH_PRIVATE(auth);
27626219Swpaul	struct authdes_cred *cred = &ad->ad_cred;
27726219Swpaul	struct authdes_verf *verf = &ad->ad_verf;
27826219Swpaul	des_block cryptbuf[2];
27926219Swpaul	des_block ivec;
28026219Swpaul	int status;
28174462Salfred	int len;
28292889Sobrien	rpc_inline_t *ixdr;
28326219Swpaul
28426219Swpaul	/*
28526219Swpaul	 * Figure out the "time", accounting for any time difference
28626219Swpaul	 * with the server if necessary.
28726219Swpaul	 */
288239991Sed	(void)gettimeofday(&ad->ad_timestamp, NULL);
28926219Swpaul	ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
29026219Swpaul	ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
29174462Salfred	while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) {
29274462Salfred		ad->ad_timestamp.tv_usec -= USEC_PER_SEC;
29374462Salfred		ad->ad_timestamp.tv_sec++;
29426219Swpaul	}
29526219Swpaul
29626219Swpaul	/*
29726219Swpaul	 * XDR the timestamp and possibly some other things, then
29826219Swpaul	 * encrypt them.
29926219Swpaul	 */
30074462Salfred	ixdr = (rpc_inline_t *)cryptbuf;
30174462Salfred	IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec);
30274462Salfred	IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec);
30326219Swpaul	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
30474462Salfred		IXDR_PUT_U_INT32(ixdr, ad->ad_window);
30574462Salfred		IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1);
30626219Swpaul		ivec.key.high = ivec.key.low = 0;
30726219Swpaul		status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf,
30874462Salfred			(u_int) 2 * sizeof (des_block),
30974462Salfred			DES_ENCRYPT | DES_HW, (char *)&ivec);
31026219Swpaul	} else {
31126219Swpaul		status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf,
31274462Salfred			(u_int) sizeof (des_block),
31374462Salfred			DES_ENCRYPT | DES_HW);
31426219Swpaul	}
31526219Swpaul	if (DES_FAILED(status)) {
31674462Salfred		syslog(LOG_ERR, "authdes_marshal: DES encryption failure");
31726219Swpaul		return (FALSE);
31826219Swpaul	}
31926219Swpaul	ad->ad_verf.adv_xtimestamp = cryptbuf[0];
32026219Swpaul	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
32126219Swpaul		ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
32226219Swpaul		ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
32326219Swpaul	} else {
32426219Swpaul		ad->ad_cred.adc_nickname = ad->ad_nickname;
32526219Swpaul		ad->ad_verf.adv_winverf = 0;
32626219Swpaul	}
32726219Swpaul
32826219Swpaul	/*
32926219Swpaul	 * Serialize the credential and verifier into opaque
33026219Swpaul	 * authentication data.
33126219Swpaul	 */
33226219Swpaul	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
33326219Swpaul		len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
33426219Swpaul	} else {
33526219Swpaul		len = (1 + 1)*BYTES_PER_XDR_UNIT;
33626219Swpaul	}
33726219Swpaul
33826219Swpaul	if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
33974462Salfred		IXDR_PUT_INT32(ixdr, AUTH_DES);
34074462Salfred		IXDR_PUT_INT32(ixdr, len);
34126219Swpaul	} else {
34274462Salfred		ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor));
34374462Salfred		ATTEMPT(xdr_putint32(xdrs, &len));
34426219Swpaul	}
34526219Swpaul	ATTEMPT(xdr_authdes_cred(xdrs, cred));
34626219Swpaul
34726219Swpaul	len = (2 + 1)*BYTES_PER_XDR_UNIT;
34826219Swpaul	if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
34974462Salfred		IXDR_PUT_INT32(ixdr, AUTH_DES);
35074462Salfred		IXDR_PUT_INT32(ixdr, len);
35126219Swpaul	} else {
35274462Salfred		ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor));
35374462Salfred		ATTEMPT(xdr_putint32(xdrs, &len));
35426219Swpaul	}
35526219Swpaul	ATTEMPT(xdr_authdes_verf(xdrs, verf));
35626219Swpaul	return (TRUE);
35726219Swpaul}
35826219Swpaul
35926219Swpaul
36026219Swpaul/*
36126219Swpaul * 3. Validate
36226219Swpaul */
36326219Swpaulstatic bool_t
36474462Salfredauthdes_validate(AUTH *auth, struct opaque_auth *rverf)
36526219Swpaul{
36674462Salfred/* LINTED pointer alignment */
36726219Swpaul	struct ad_private *ad = AUTH_PRIVATE(auth);
36826219Swpaul	struct authdes_verf verf;
36926219Swpaul	int status;
37092889Sobrien	uint32_t *ixdr;
37174462Salfred	des_block buf;
37226219Swpaul
37326219Swpaul	if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) {
37426219Swpaul		return (FALSE);
37526219Swpaul	}
37674462Salfred/* LINTED pointer alignment */
37774462Salfred	ixdr = (uint32_t *)rverf->oa_base;
37874462Salfred	buf.key.high = (uint32_t)*ixdr++;
37974462Salfred	buf.key.low = (uint32_t)*ixdr++;
38074462Salfred	verf.adv_int_u = (uint32_t)*ixdr++;
38126219Swpaul
38226219Swpaul	/*
38326219Swpaul	 * Decrypt the timestamp
38426219Swpaul	 */
38574462Salfred	status = ecb_crypt((char *)&auth->ah_key, (char *)&buf,
38674462Salfred		(u_int)sizeof (des_block), DES_DECRYPT | DES_HW);
38726219Swpaul
38826219Swpaul	if (DES_FAILED(status)) {
38974462Salfred		syslog(LOG_ERR, "authdes_validate: DES decryption failure");
39026219Swpaul		return (FALSE);
39126219Swpaul	}
39226219Swpaul
39326219Swpaul	/*
39474462Salfred	 * xdr the decrypted timestamp
39526219Swpaul	 */
39674462Salfred/* LINTED pointer alignment */
39774462Salfred	ixdr = (uint32_t *)buf.c;
39874462Salfred	verf.adv_timestamp.tv_sec = IXDR_GET_INT32(ixdr) + 1;
39974462Salfred	verf.adv_timestamp.tv_usec = IXDR_GET_INT32(ixdr);
40026219Swpaul
40126219Swpaul	/*
40226219Swpaul	 * validate
40326219Swpaul	 */
40426219Swpaul	if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp,
40526219Swpaul		 sizeof(struct timeval)) != 0) {
40674462Salfred		syslog(LOG_DEBUG, "authdes_validate: verifier mismatch");
40726219Swpaul		return (FALSE);
40826219Swpaul	}
40926219Swpaul
41026219Swpaul	/*
41126219Swpaul	 * We have a nickname now, let's use it
41226219Swpaul	 */
41374462Salfred	ad->ad_nickname = verf.adv_nickname;
41474462Salfred	ad->ad_cred.adc_namekind = ADN_NICKNAME;
41574462Salfred	return (TRUE);
41626219Swpaul}
41726219Swpaul
41826219Swpaul/*
41926219Swpaul * 4. Refresh
42026219Swpaul */
42174462Salfred/*ARGSUSED*/
42226219Swpaulstatic bool_t
42374462Salfredauthdes_refresh(AUTH *auth, void *dummy)
42426219Swpaul{
42574462Salfred/* LINTED pointer alignment */
42626219Swpaul	struct ad_private *ad = AUTH_PRIVATE(auth);
42726219Swpaul	struct authdes_cred *cred = &ad->ad_cred;
42874462Salfred	int		ok;
42926219Swpaul	netobj		pkey;
43026219Swpaul
43174462Salfred	if (ad->ad_dosync) {
43274462Salfred                ok = __rpc_get_time_offset(&ad->ad_timediff, ad->ad_nis_srvr,
43374462Salfred		    ad->ad_timehost, &(ad->ad_uaddr),
43474462Salfred		    &(ad->ad_netid));
43574462Salfred		if (! ok) {
43674462Salfred			/*
43774462Salfred			 * Hope the clocks are synced!
43874462Salfred			 */
43974462Salfred			ad->ad_dosync = 0;
44074462Salfred			syslog(LOG_DEBUG,
44174462Salfred			    "authdes_refresh: unable to synchronize clock");
44274462Salfred		 }
44326219Swpaul	}
44426219Swpaul	ad->ad_xkey = auth->ah_key;
44526219Swpaul	pkey.n_bytes = (char *)(ad->ad_pkey);
44674462Salfred	pkey.n_len = (u_int)strlen((char *)ad->ad_pkey) + 1;
44726219Swpaul	if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) {
44874462Salfred		syslog(LOG_INFO,
44974462Salfred		    "authdes_refresh: keyserv(1m) is unable to encrypt session key");
45026219Swpaul		return (FALSE);
45126219Swpaul	}
45226219Swpaul	cred->adc_fullname.key = ad->ad_xkey;
45326219Swpaul	cred->adc_namekind = ADN_FULLNAME;
45426219Swpaul	cred->adc_fullname.name = ad->ad_fullname;
45526219Swpaul	return (TRUE);
45626219Swpaul}
45726219Swpaul
45826219Swpaul
45926219Swpaul/*
46026219Swpaul * 5. Destroy
46126219Swpaul */
46226219Swpaulstatic void
46374462Salfredauthdes_destroy(AUTH *auth)
46426219Swpaul{
46574462Salfred/* LINTED pointer alignment */
46626219Swpaul	struct ad_private *ad = AUTH_PRIVATE(auth);
46726219Swpaul
46826219Swpaul	FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
46926219Swpaul	FREE(ad->ad_servername, ad->ad_servernamelen + 1);
47074462Salfred	if (ad->ad_timehost)
47174462Salfred		FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
47274462Salfred	if (ad->ad_netid)
47374462Salfred		FREE(ad->ad_netid, strlen(ad->ad_netid) + 1);
47474462Salfred	if (ad->ad_uaddr)
47574462Salfred		FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1);
47674462Salfred	FREE(ad, sizeof (struct ad_private));
47726219Swpaul	FREE(auth, sizeof(AUTH));
47826219Swpaul}
47926219Swpaul
48074462Salfredstatic struct auth_ops *
48174462Salfredauthdes_ops(void)
48226219Swpaul{
48374462Salfred	static struct auth_ops ops;
48426219Swpaul
48574462Salfred	/* VARIABLES PROTECTED BY ops_lock: ops */
48674462Salfred
48774462Salfred	mutex_lock(&authdes_ops_lock);
48874462Salfred	if (ops.ah_nextverf == NULL) {
48974462Salfred		ops.ah_nextverf = authdes_nextverf;
49074462Salfred		ops.ah_marshal = authdes_marshal;
49174462Salfred		ops.ah_validate = authdes_validate;
49274462Salfred		ops.ah_refresh = authdes_refresh;
49374462Salfred		ops.ah_destroy = authdes_destroy;
49474462Salfred        }
49574462Salfred	mutex_unlock(&authdes_ops_lock);
49674462Salfred	return (&ops);
49726219Swpaul}
498