129088Smarkm/*-
229088Smarkm * Copyright (c) 1992, 1993
329088Smarkm *	The Regents of the University of California.  All rights reserved.
429088Smarkm *
529088Smarkm * Redistribution and use in source and binary forms, with or without
629088Smarkm * modification, are permitted provided that the following conditions
729088Smarkm * are met:
829088Smarkm * 1. Redistributions of source code must retain the above copyright
929088Smarkm *    notice, this list of conditions and the following disclaimer.
1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1129088Smarkm *    notice, this list of conditions and the following disclaimer in the
1229088Smarkm *    documentation and/or other materials provided with the distribution.
1329088Smarkm * 3. All advertising materials mentioning features or use of this software
1429088Smarkm *    must display the following acknowledgement:
1529088Smarkm *	This product includes software developed by the University of
1629088Smarkm *	California, Berkeley and its contributors.
1729088Smarkm * 4. Neither the name of the University nor the names of its contributors
1829088Smarkm *    may be used to endorse or promote products derived from this software
1929088Smarkm *    without specific prior written permission.
2029088Smarkm *
2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2429088Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3129088Smarkm * SUCH DAMAGE.
3229088Smarkm */
3329088Smarkm
3484305Smarkm#include <sys/cdefs.h>
3587139Smarkm
3684305Smarkm__FBSDID("$FreeBSD$");
3784305Smarkm
3829088Smarkm#ifndef lint
3929088Smarkmstatic char sccsid[] = "@(#)krb4encpwd.c	8.3 (Berkeley) 5/30/95";
4029088Smarkm#endif /* not lint */
4129088Smarkm
4229088Smarkm
4329088Smarkm#ifdef	KRB4_ENCPWD
4429088Smarkm/*
4529088Smarkm * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
4629088Smarkm * ALL RIGHTS RESERVED
4729088Smarkm *
4829088Smarkm * "Digital Equipment Corporation authorizes the reproduction,
4929088Smarkm * distribution and modification of this software subject to the following
5029088Smarkm * restrictions:
5129088Smarkm *
5229088Smarkm * 1.  Any partial or whole copy of this software, or any modification
5329088Smarkm * thereof, must include this copyright notice in its entirety.
5429088Smarkm *
5529088Smarkm * 2.  This software is supplied "as is" with no warranty of any kind,
5629088Smarkm * expressed or implied, for any purpose, including any warranty of fitness
5729088Smarkm * or merchantibility.  DIGITAL assumes no responsibility for the use or
5829088Smarkm * reliability of this software, nor promises to provide any form of
5929088Smarkm * support for it on any basis.
6029088Smarkm *
6129088Smarkm * 3.  Distribution of this software is authorized only if no profit or
6229088Smarkm * remuneration of any kind is received in exchange for such distribution.
6329088Smarkm *
6429088Smarkm * 4.  This software produces public key authentication certificates
6529088Smarkm * bearing an expiration date established by DIGITAL and RSA Data
6629088Smarkm * Security, Inc.  It may cease to generate certificates after the expiration
6729088Smarkm * date.  Any modification of this software that changes or defeats
6829088Smarkm * the expiration date or its effect is unauthorized.
6929088Smarkm *
7029088Smarkm * 5.  Software that will renew or extend the expiration date of
7129088Smarkm * authentication certificates produced by this software may be obtained
7229088Smarkm * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
7329088Smarkm * 94065, (415)595-8782, or from DIGITAL"
7429088Smarkm *
7529088Smarkm */
7629088Smarkm
7729088Smarkm#include <sys/types.h>
7887139Smarkm#include <openssl/des.h>
7929088Smarkm#include <arpa/telnet.h>
8087139Smarkm#include <krb.h>
8129088Smarkm#include <pwd.h>
8229088Smarkm#include <stdio.h>
8329088Smarkm#include <stdlib.h>
8429088Smarkm#include <string.h>
8529088Smarkm
8629088Smarkm#include "encrypt.h"
8729088Smarkm#include "auth.h"
8829088Smarkm#include "misc.h"
8929088Smarkm
9087155Smarkmint krb_mk_encpwd_req(KTEXT, char *, char *, char *, char *, char *, char *);
9187155Smarkmint krb_rd_encpwd_req(KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *);
9229088Smarkm
9329088Smarkmextern auth_debug_mode;
9429088Smarkm
9529088Smarkmstatic unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
9629088Smarkm			  		AUTHTYPE_KRB4_ENCPWD, };
9729088Smarkmstatic unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
9829088Smarkm					TELQUAL_NAME, };
9929088Smarkm
10029088Smarkm#define	KRB4_ENCPWD_AUTH	0	/* Authentication data follows */
10129088Smarkm#define	KRB4_ENCPWD_REJECT	1	/* Rejected (reason might follow) */
10229088Smarkm#define KRB4_ENCPWD_ACCEPT	2	/* Accepted */
10329088Smarkm#define	KRB4_ENCPWD_CHALLENGE	3	/* Challenge for mutual auth. */
10429088Smarkm#define	KRB4_ENCPWD_ACK		4	/* Acknowledge */
10529088Smarkm
10629088Smarkm#define KRB_SERVICE_NAME    "rcmd"
10729088Smarkm
10829088Smarkmstatic	KTEXT_ST auth;
10929088Smarkmstatic	char name[ANAME_SZ];
11029088Smarkmstatic	char user_passwd[ANAME_SZ];
11129088Smarkmstatic	AUTH_DAT adat = { 0 };
11229088Smarkm#ifdef	ENCRYPTION
11329088Smarkmstatic Block	session_key	= { 0 };
11429088Smarkm#endif	/* ENCRYPTION */
11529088Smarkmstatic char  challenge[REALM_SZ];
11629088Smarkm
11729088Smarkm	static int
11829088SmarkmData(ap, type, d, c)
11929088Smarkm	Authenticator *ap;
12029088Smarkm	int type;
12129088Smarkm	void *d;
12229088Smarkm	int c;
12329088Smarkm{
12429088Smarkm	unsigned char *p = str_data + 4;
12529088Smarkm	unsigned char *cd = (unsigned char *)d;
12629088Smarkm
12729088Smarkm	if (c == -1)
12829088Smarkm		c = strlen((char *)cd);
12929088Smarkm
13029088Smarkm	if (0) {
13129088Smarkm		printf("%s:%d: [%d] (%d)",
13229088Smarkm			str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
13329088Smarkm			str_data[3],
13429088Smarkm			type, c);
13529088Smarkm		printd(d, c);
13629088Smarkm		printf("\r\n");
13729088Smarkm	}
13829088Smarkm	*p++ = ap->type;
13929088Smarkm	*p++ = ap->way;
14029088Smarkm	*p++ = type;
14129088Smarkm	while (c-- > 0) {
14229088Smarkm		if ((*p++ = *cd++) == IAC)
14329088Smarkm			*p++ = IAC;
14429088Smarkm	}
14529088Smarkm	*p++ = IAC;
14629088Smarkm	*p++ = SE;
14729088Smarkm	if (str_data[3] == TELQUAL_IS)
14829088Smarkm		printsub('>', &str_data[2], p - (&str_data[2]));
14929088Smarkm	return(net_write(str_data, p - str_data));
15029088Smarkm}
15129088Smarkm
15229088Smarkm	int
15329088Smarkmkrb4encpwd_init(ap, server)
15429088Smarkm	Authenticator *ap;
15529088Smarkm	int server;
15629088Smarkm{
15729088Smarkm	char hostname[80], *cp, *realm;
15829088Smarkm	C_Block skey;
15929088Smarkm
16029088Smarkm	if (server) {
16129088Smarkm		str_data[3] = TELQUAL_REPLY;
16229088Smarkm	} else {
16329088Smarkm		str_data[3] = TELQUAL_IS;
16429088Smarkm		gethostname(hostname, sizeof(hostname));
16529088Smarkm		realm = krb_realmofhost(hostname);
16629088Smarkm		cp = strchr(hostname, '.');
16729088Smarkm		if (*cp != NULL) *cp = NULL;
16829088Smarkm		if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0,
16929088Smarkm					KEYFILE, (char *)skey)) {
17029088Smarkm		  return(0);
17129088Smarkm		}
17229088Smarkm	}
17329088Smarkm	return(1);
17429088Smarkm}
17529088Smarkm
17629088Smarkm	int
17729088Smarkmkrb4encpwd_send(ap)
17829088Smarkm	Authenticator *ap;
17929088Smarkm{
18029088Smarkm
18129088Smarkm	printf("[ Trying KRB4ENCPWD ... ]\n");
18229088Smarkm	if (!UserNameRequested) {
18329088Smarkm		return(0);
18429088Smarkm	}
18529088Smarkm	if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
18629088Smarkm		return(0);
18729088Smarkm	}
18829088Smarkm
18929088Smarkm	if (!Data(ap, KRB4_ENCPWD_ACK, (void *)NULL, 0)) {
19029088Smarkm		return(0);
19129088Smarkm	}
19229088Smarkm
19329088Smarkm	return(1);
19429088Smarkm}
19529088Smarkm
19629088Smarkm	void
19729088Smarkmkrb4encpwd_is(ap, data, cnt)
19829088Smarkm	Authenticator *ap;
19929088Smarkm	unsigned char *data;
20029088Smarkm	int cnt;
20129088Smarkm{
20229088Smarkm	Session_Key skey;
20329088Smarkm	Block datablock;
20429088Smarkm	char  r_passwd[ANAME_SZ], r_user[ANAME_SZ];
20529088Smarkm	char  lhostname[ANAME_SZ], *cp;
20629088Smarkm	int r;
20729088Smarkm	time_t now;
20829088Smarkm
20929088Smarkm	if (cnt-- < 1)
21029088Smarkm		return;
21129088Smarkm	switch (*data++) {
21229088Smarkm	case KRB4_ENCPWD_AUTH:
21329088Smarkm		memmove((void *)auth.dat, (void *)data, auth.length = cnt);
21429088Smarkm
21529088Smarkm		gethostname(lhostname, sizeof(lhostname));
21629088Smarkm		if ((cp = strchr(lhostname, '.')) != 0)  *cp = '\0';
21729088Smarkm
21829088Smarkm		if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) {
21929088Smarkm			Data(ap, KRB4_ENCPWD_REJECT, (void *)"Auth failed", -1);
22029088Smarkm			auth_finished(ap, AUTH_REJECT);
22129088Smarkm			return;
22229088Smarkm		}
22329088Smarkm		auth_encrypt_userpwd(r_passwd);
22429088Smarkm		if (passwdok(UserNameRequested, UserPassword) == 0) {
22529088Smarkm		  /*
22629088Smarkm		   *  illegal username and password
22729088Smarkm		   */
22829088Smarkm		  Data(ap, KRB4_ENCPWD_REJECT, (void *)"Illegal password", -1);
22929088Smarkm		  auth_finished(ap, AUTH_REJECT);
23029088Smarkm		  return;
23129088Smarkm		}
23229088Smarkm
23329088Smarkm		memmove((void *)session_key, (void *)adat.session, sizeof(Block));
23429088Smarkm		Data(ap, KRB4_ENCPWD_ACCEPT, (void *)0, 0);
23529088Smarkm		auth_finished(ap, AUTH_USER);
23629088Smarkm		break;
23729088Smarkm
23829088Smarkm	case KRB4_ENCPWD_CHALLENGE:
23929088Smarkm		/*
24029088Smarkm		 *  Take the received random challenge text and save
24129088Smarkm		 *  for future authentication.
24229088Smarkm		 */
24329088Smarkm		memmove((void *)challenge, (void *)data, sizeof(Block));
24429088Smarkm		break;
24529088Smarkm
24629088Smarkm
24729088Smarkm	case KRB4_ENCPWD_ACK:
24829088Smarkm		/*
24929088Smarkm		 *  Receive ack, if mutual then send random challenge
25029088Smarkm		 */
25129088Smarkm
25229088Smarkm		/*
25329088Smarkm		 * If we are doing mutual authentication, get set up to send
25429088Smarkm		 * the challenge, and verify it when the response comes back.
25529088Smarkm		 */
25629088Smarkm
25729088Smarkm		if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
25829088Smarkm		  register int i;
25929088Smarkm
26029088Smarkm		  time(&now);
26129088Smarkm		  sprintf(challenge, "%x", now);
26229088Smarkm		  Data(ap, KRB4_ENCPWD_CHALLENGE, (void *)challenge, strlen(challenge));
26329088Smarkm		}
26429088Smarkm		break;
26529088Smarkm
26629088Smarkm	default:
26729088Smarkm		Data(ap, KRB4_ENCPWD_REJECT, 0, 0);
26829088Smarkm		break;
26929088Smarkm	}
27029088Smarkm}
27129088Smarkm
27229088Smarkm
27329088Smarkm	void
27429088Smarkmkrb4encpwd_reply(ap, data, cnt)
27529088Smarkm	Authenticator *ap;
27629088Smarkm	unsigned char *data;
27729088Smarkm	int cnt;
27829088Smarkm{
27929088Smarkm	Session_Key skey;
28029088Smarkm	KTEXT_ST krb_token;
28129088Smarkm	Block enckey;
28229088Smarkm	CREDENTIALS cred;
28329088Smarkm	int r;
28429088Smarkm	char	randchal[REALM_SZ], instance[ANAME_SZ], *cp;
28529088Smarkm	char	hostname[80], *realm;
28629088Smarkm
28729088Smarkm	if (cnt-- < 1)
28829088Smarkm		return;
28929088Smarkm	switch (*data++) {
29029088Smarkm	case KRB4_ENCPWD_REJECT:
29129088Smarkm		if (cnt > 0) {
29229088Smarkm			printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n",
29329088Smarkm				cnt, data);
29429088Smarkm		} else
29529088Smarkm			printf("[ KRB4_ENCPWD refuses authentication ]\r\n");
29629088Smarkm		auth_send_retry();
29729088Smarkm		return;
29829088Smarkm	case KRB4_ENCPWD_ACCEPT:
29929088Smarkm		printf("[ KRB4_ENCPWD accepts you ]\n");
30029088Smarkm		auth_finished(ap, AUTH_USER);
30129088Smarkm		return;
30229088Smarkm	case KRB4_ENCPWD_CHALLENGE:
30329088Smarkm		/*
30429088Smarkm		 * Verify that the response to the challenge is correct.
30529088Smarkm		 */
30629088Smarkm
30729088Smarkm		gethostname(hostname, sizeof(hostname));
30829088Smarkm		realm = krb_realmofhost(hostname);
30929088Smarkm		memmove((void *)challenge, (void *)data, cnt);
31029088Smarkm		memset(user_passwd, 0, sizeof(user_passwd));
31129088Smarkm		local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
31229088Smarkm		UserPassword = user_passwd;
31329088Smarkm		Challenge = challenge;
31429088Smarkm		strcpy(instance, RemoteHostName);
31529088Smarkm		if ((cp = strchr(instance, '.')) != 0)  *cp = '\0';
31629088Smarkm
31729088Smarkm		if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) {
31829088Smarkm		  krb_token.length = 0;
31929088Smarkm		}
32029088Smarkm
32129088Smarkm		if (!Data(ap, KRB4_ENCPWD_AUTH, (void *)krb_token.dat, krb_token.length)) {
32229088Smarkm		  return;
32329088Smarkm		}
32429088Smarkm
32529088Smarkm		break;
32629088Smarkm
32729088Smarkm	default:
32829088Smarkm		return;
32929088Smarkm	}
33029088Smarkm}
33129088Smarkm
33229088Smarkm	int
33329088Smarkmkrb4encpwd_status(ap, name, level)
33429088Smarkm	Authenticator *ap;
33529088Smarkm	char *name;
33629088Smarkm	int level;
33729088Smarkm{
33829088Smarkm
33929088Smarkm	if (level < AUTH_USER)
34029088Smarkm		return(level);
34129088Smarkm
34229088Smarkm	if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) {
34329088Smarkm		strcpy(name, UserNameRequested);
34429088Smarkm		return(AUTH_VALID);
34529088Smarkm	} else {
34629088Smarkm		return(AUTH_USER);
34729088Smarkm	}
34829088Smarkm}
34929088Smarkm
35029088Smarkm#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
35129088Smarkm#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
35229088Smarkm
35329088Smarkm	void
35429088Smarkmkrb4encpwd_printsub(data, cnt, buf, buflen)
35529088Smarkm	unsigned char *data, *buf;
35629088Smarkm	int cnt, buflen;
35729088Smarkm{
35829088Smarkm	char lbuf[32];
35929088Smarkm	register int i;
36029088Smarkm
36129088Smarkm	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
36229088Smarkm	buflen -= 1;
36329088Smarkm
36429088Smarkm	switch(data[3]) {
36529088Smarkm	case KRB4_ENCPWD_REJECT:	/* Rejected (reason might follow) */
36629088Smarkm		strncpy((char *)buf, " REJECT ", buflen);
36729088Smarkm		goto common;
36829088Smarkm
36929088Smarkm	case KRB4_ENCPWD_ACCEPT:	/* Accepted (name might follow) */
37029088Smarkm		strncpy((char *)buf, " ACCEPT ", buflen);
37129088Smarkm	common:
37229088Smarkm		BUMP(buf, buflen);
37329088Smarkm		if (cnt <= 4)
37429088Smarkm			break;
37529088Smarkm		ADDC(buf, buflen, '"');
37629088Smarkm		for (i = 4; i < cnt; i++)
37729088Smarkm			ADDC(buf, buflen, data[i]);
37829088Smarkm		ADDC(buf, buflen, '"');
37929088Smarkm		ADDC(buf, buflen, '\0');
38029088Smarkm		break;
38129088Smarkm
38229088Smarkm	case KRB4_ENCPWD_AUTH:		/* Authentication data follows */
38329088Smarkm		strncpy((char *)buf, " AUTH", buflen);
38429088Smarkm		goto common2;
38529088Smarkm
38629088Smarkm	case KRB4_ENCPWD_CHALLENGE:
38729088Smarkm		strncpy((char *)buf, " CHALLENGE", buflen);
38829088Smarkm		goto common2;
38929088Smarkm
39029088Smarkm	case KRB4_ENCPWD_ACK:
39129088Smarkm		strncpy((char *)buf, " ACK", buflen);
39229088Smarkm		goto common2;
39329088Smarkm
39429088Smarkm	default:
39529088Smarkm		sprintf(lbuf, " %d (unknown)", data[3]);
39629088Smarkm		strncpy((char *)buf, lbuf, buflen);
39729088Smarkm	common2:
39829088Smarkm		BUMP(buf, buflen);
39929088Smarkm		for (i = 4; i < cnt; i++) {
40029088Smarkm			sprintf(lbuf, " %d", data[i]);
40129088Smarkm			strncpy((char *)buf, lbuf, buflen);
40229088Smarkm			BUMP(buf, buflen);
40329088Smarkm		}
40429088Smarkm		break;
40529088Smarkm	}
40629088Smarkm}
40729088Smarkm
40829088Smarkmint passwdok(name, passwd)
40929088Smarkmchar *name, *passwd;
41029088Smarkm{
41129088Smarkm  char *crypt();
41229088Smarkm  char *salt, *p;
41329088Smarkm  struct passwd *pwd;
41429088Smarkm  int   passwdok_status = 0;
41529088Smarkm
41629088Smarkm  if (pwd = getpwnam(name))
41729088Smarkm    salt = pwd->pw_passwd;
41829088Smarkm  else salt = "xx";
41929088Smarkm
42029088Smarkm  p = crypt(passwd, salt);
42129088Smarkm
42229088Smarkm  if (pwd && !strcmp(p, pwd->pw_passwd)) {
42329088Smarkm    passwdok_status = 1;
42429088Smarkm  } else passwdok_status = 0;
42529088Smarkm  return(passwdok_status);
42629088Smarkm}
42729088Smarkm
42829088Smarkm#endif
429