xref: /freebsd/contrib/telnet/libtelnet/kerberos.c (revision a3c85800)
181cb6ddcSMark Murray /*-
281cb6ddcSMark Murray  * Copyright (c) 1991, 1993
381cb6ddcSMark Murray  *	The Regents of the University of California.  All rights reserved.
481cb6ddcSMark Murray  *
581cb6ddcSMark Murray  * Redistribution and use in source and binary forms, with or without
681cb6ddcSMark Murray  * modification, are permitted provided that the following conditions
781cb6ddcSMark Murray  * are met:
881cb6ddcSMark Murray  * 1. Redistributions of source code must retain the above copyright
981cb6ddcSMark Murray  *    notice, this list of conditions and the following disclaimer.
1081cb6ddcSMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
1181cb6ddcSMark Murray  *    notice, this list of conditions and the following disclaimer in the
1281cb6ddcSMark Murray  *    documentation and/or other materials provided with the distribution.
1383129c0bSEd Maste  * 3. Neither the name of the University nor the names of its contributors
1481cb6ddcSMark Murray  *    may be used to endorse or promote products derived from this software
1581cb6ddcSMark Murray  *    without specific prior written permission.
1681cb6ddcSMark Murray  *
1781cb6ddcSMark Murray  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1881cb6ddcSMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1981cb6ddcSMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2081cb6ddcSMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2181cb6ddcSMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2281cb6ddcSMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2381cb6ddcSMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2481cb6ddcSMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2581cb6ddcSMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2681cb6ddcSMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2781cb6ddcSMark Murray  * SUCH DAMAGE.
2881cb6ddcSMark Murray  */
2981cb6ddcSMark Murray 
3081cb6ddcSMark Murray #ifndef lint
3104c426ccSMark Murray static const char sccsid[] = "@(#)kerberos.c	8.3 (Berkeley) 5/30/95";
3281cb6ddcSMark Murray #endif /* not lint */
3381cb6ddcSMark Murray 
3481cb6ddcSMark Murray /*
3581cb6ddcSMark Murray  * Copyright (C) 1990 by the Massachusetts Institute of Technology
3681cb6ddcSMark Murray  *
3781cb6ddcSMark Murray  * Export of this software from the United States of America is assumed
3881cb6ddcSMark Murray  * to require a specific license from the United States Government.
3981cb6ddcSMark Murray  * It is the responsibility of any person or organization contemplating
4081cb6ddcSMark Murray  * export to obtain such a license before exporting.
4181cb6ddcSMark Murray  *
4281cb6ddcSMark Murray  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
4381cb6ddcSMark Murray  * distribute this software and its documentation for any purpose and
4481cb6ddcSMark Murray  * without fee is hereby granted, provided that the above copyright
4581cb6ddcSMark Murray  * notice appear in all copies and that both that copyright notice and
4681cb6ddcSMark Murray  * this permission notice appear in supporting documentation, and that
4781cb6ddcSMark Murray  * the name of M.I.T. not be used in advertising or publicity pertaining
4881cb6ddcSMark Murray  * to distribution of the software without specific, written prior
4981cb6ddcSMark Murray  * permission.  M.I.T. makes no representations about the suitability of
5081cb6ddcSMark Murray  * this software for any purpose.  It is provided "as is" without express
5181cb6ddcSMark Murray  * or implied warranty.
5281cb6ddcSMark Murray  */
5381cb6ddcSMark Murray 
5481cb6ddcSMark Murray #ifdef	KRB4
5581cb6ddcSMark Murray #include <sys/types.h>
5681cb6ddcSMark Murray #include <arpa/telnet.h>
57bf4f84d4SMark Murray #include <openssl/des.h>	/* BSD wont include this in krb.h, so we do it here */
5881cb6ddcSMark Murray #include <krb.h>
598fa113e5SMark Murray #include <stdio.h>
6081cb6ddcSMark Murray #include <stdlib.h>
6181cb6ddcSMark Murray #include <string.h>
6281cb6ddcSMark Murray 
6381cb6ddcSMark Murray #include "encrypt.h"
6481cb6ddcSMark Murray #include "auth.h"
6581cb6ddcSMark Murray #include "misc.h"
6681cb6ddcSMark Murray 
673138440aSMark Murray int kerberos4_cksum(unsigned char *, int);
683138440aSMark Murray int kuserok(AUTH_DAT *, char *);
6981cb6ddcSMark Murray 
708fa113e5SMark Murray extern int auth_debug_mode;
7181cb6ddcSMark Murray 
7281cb6ddcSMark Murray static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
7381cb6ddcSMark Murray 			  		AUTHTYPE_KERBEROS_V4, };
7481cb6ddcSMark Murray 
7581cb6ddcSMark Murray #define	KRB_AUTH	0		/* Authentication data follows */
7681cb6ddcSMark Murray #define	KRB_REJECT	1		/* Rejected (reason might follow) */
7781cb6ddcSMark Murray #define	KRB_ACCEPT	2		/* Accepted */
7881cb6ddcSMark Murray #define	KRB_CHALLENGE	3		/* Challenge for mutual auth. */
7981cb6ddcSMark Murray #define	KRB_RESPONSE	4		/* Response for mutual auth. */
8081cb6ddcSMark Murray 
8181cb6ddcSMark Murray static	KTEXT_ST auth;
8281cb6ddcSMark Murray static	char name[ANAME_SZ];
838fa113e5SMark Murray static	AUTH_DAT adat = { 0, "", "", "", 0, {}, 0, 0, 0, { 0, "", 0 } };
8481cb6ddcSMark Murray #ifdef	ENCRYPTION
8581cb6ddcSMark Murray static Block	session_key	= { 0 };
86b285c5dfSJung-uk Kim static DES_key_schedule sched;
8781cb6ddcSMark Murray static Block	challenge	= { 0 };
8881cb6ddcSMark Murray #endif	/* ENCRYPTION */
8981cb6ddcSMark Murray 
908fa113e5SMark Murray static char krb_service_name[] = "rcmd";
918fa113e5SMark Murray static char empty[] = "";
928fa113e5SMark Murray 
9381cb6ddcSMark Murray static int
Data(Authenticator * ap,int type,const unsigned char * d,int c)948fa113e5SMark Murray Data(Authenticator *ap, int type, const unsigned char *d, int c)
9581cb6ddcSMark Murray {
9681cb6ddcSMark Murray 	unsigned char *p = str_data + 4;
978fa113e5SMark Murray 	const unsigned char *cd = d;
9881cb6ddcSMark Murray 
9981cb6ddcSMark Murray 	if (c == -1)
1008fa113e5SMark Murray 		c = strlen(cd);
10181cb6ddcSMark Murray 
10281cb6ddcSMark Murray 	if (auth_debug_mode) {
10381cb6ddcSMark Murray 		printf("%s:%d: [%d] (%d)",
10481cb6ddcSMark Murray 			str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
10581cb6ddcSMark Murray 			str_data[3],
10681cb6ddcSMark Murray 			type, c);
10781cb6ddcSMark Murray 		printd(d, c);
10881cb6ddcSMark Murray 		printf("\r\n");
10981cb6ddcSMark Murray 	}
11081cb6ddcSMark Murray 	*p++ = ap->type;
11181cb6ddcSMark Murray 	*p++ = ap->way;
11281cb6ddcSMark Murray 	*p++ = type;
11381cb6ddcSMark Murray 	while (c-- > 0) {
11481cb6ddcSMark Murray 		if ((*p++ = *cd++) == IAC)
11581cb6ddcSMark Murray 			*p++ = IAC;
11681cb6ddcSMark Murray 	}
11781cb6ddcSMark Murray 	*p++ = IAC;
11881cb6ddcSMark Murray 	*p++ = SE;
11981cb6ddcSMark Murray 	if (str_data[3] == TELQUAL_IS)
12081cb6ddcSMark Murray 		printsub('>', &str_data[2], p - (&str_data[2]));
12181cb6ddcSMark Murray 	return(net_write(str_data, p - str_data));
12281cb6ddcSMark Murray }
12381cb6ddcSMark Murray 
12481cb6ddcSMark Murray int
kerberos4_init(Authenticator * ap __unused,int server)1258fa113e5SMark Murray kerberos4_init(Authenticator *ap __unused, int server)
12681cb6ddcSMark Murray {
12781cb6ddcSMark Murray 	FILE *fp;
12881cb6ddcSMark Murray 
12981cb6ddcSMark Murray 	if (server) {
13081cb6ddcSMark Murray 		str_data[3] = TELQUAL_REPLY;
13181cb6ddcSMark Murray 		if ((fp = fopen(KEYFILE, "r")) == NULL)
13281cb6ddcSMark Murray 			return(0);
13381cb6ddcSMark Murray 		fclose(fp);
13481cb6ddcSMark Murray 	} else {
13581cb6ddcSMark Murray 		str_data[3] = TELQUAL_IS;
13681cb6ddcSMark Murray 	}
13781cb6ddcSMark Murray 	return(1);
13881cb6ddcSMark Murray }
13981cb6ddcSMark Murray 
14081cb6ddcSMark Murray char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
14181cb6ddcSMark Murray int dst_realm_sz = REALM_SZ;
14281cb6ddcSMark Murray 
14381cb6ddcSMark Murray int
kerberos4_send(Authenticator * ap)1448fa113e5SMark Murray kerberos4_send(Authenticator *ap)
14581cb6ddcSMark Murray {
1468fa113e5SMark Murray 	KTEXT_ST lauth;
14781cb6ddcSMark Murray 	char instance[INST_SZ];
14881cb6ddcSMark Murray 	char *realm;
14981cb6ddcSMark Murray 	CREDENTIALS cred;
15081cb6ddcSMark Murray 	int r;
15181cb6ddcSMark Murray 
15281cb6ddcSMark Murray 	printf("[ Trying KERBEROS4 ... ]\n");
15381cb6ddcSMark Murray 	if (!UserNameRequested) {
15481cb6ddcSMark Murray 		if (auth_debug_mode) {
15581cb6ddcSMark Murray 			printf("Kerberos V4: no user name supplied\r\n");
15681cb6ddcSMark Murray 		}
15781cb6ddcSMark Murray 		return(0);
15881cb6ddcSMark Murray 	}
15981cb6ddcSMark Murray 
16081cb6ddcSMark Murray 	memset(instance, 0, sizeof(instance));
16181cb6ddcSMark Murray 
16204c426ccSMark Murray 	if ((realm = krb_get_phost(RemoteHostName)))
16381cb6ddcSMark Murray 		strncpy(instance, realm, sizeof(instance));
16481cb6ddcSMark Murray 
16581cb6ddcSMark Murray 	instance[sizeof(instance)-1] = '\0';
16681cb6ddcSMark Murray 
16781cb6ddcSMark Murray 	realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName);
16881cb6ddcSMark Murray 
16981cb6ddcSMark Murray 	if (!realm) {
17081cb6ddcSMark Murray 		printf("Kerberos V4: no realm for %s\r\n", RemoteHostName);
17181cb6ddcSMark Murray 		return(0);
17281cb6ddcSMark Murray 	}
1738fa113e5SMark Murray 	if ((r = krb_mk_req(&lauth, krb_service_name, instance, realm, 0L))) {
17481cb6ddcSMark Murray 		printf("mk_req failed: %s\r\n", krb_err_txt[r]);
17581cb6ddcSMark Murray 		return(0);
17681cb6ddcSMark Murray 	}
1778fa113e5SMark Murray 	if ((r = krb_get_cred(krb_service_name, instance, realm, &cred))) {
17881cb6ddcSMark Murray 		printf("get_cred failed: %s\r\n", krb_err_txt[r]);
17981cb6ddcSMark Murray 		return(0);
18081cb6ddcSMark Murray 	}
18181cb6ddcSMark Murray 	if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
18281cb6ddcSMark Murray 		if (auth_debug_mode)
18381cb6ddcSMark Murray 			printf("Not enough room for user name\r\n");
18481cb6ddcSMark Murray 		return(0);
18581cb6ddcSMark Murray 	}
18681cb6ddcSMark Murray 	if (auth_debug_mode)
1878fa113e5SMark Murray 		printf("Sent %d bytes of authentication data\r\n", lauth.length);
1888fa113e5SMark Murray 	if (!Data(ap, KRB_AUTH, (void *)lauth.dat, lauth.length)) {
18981cb6ddcSMark Murray 		if (auth_debug_mode)
19081cb6ddcSMark Murray 			printf("Not enough room for authentication data\r\n");
19181cb6ddcSMark Murray 		return(0);
19281cb6ddcSMark Murray 	}
19381cb6ddcSMark Murray #ifdef	ENCRYPTION
19481cb6ddcSMark Murray 	/*
19581cb6ddcSMark Murray 	 * If we are doing mutual authentication, get set up to send
19681cb6ddcSMark Murray 	 * the challenge, and verify it when the response comes back.
19781cb6ddcSMark Murray 	 */
19881cb6ddcSMark Murray 	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
19981cb6ddcSMark Murray 		register int i;
20081cb6ddcSMark Murray 
201b285c5dfSJung-uk Kim 		DES_key_sched(&cred.session, sched);
202b285c5dfSJung-uk Kim 		DES_random_key(&session_key);
203b285c5dfSJung-uk Kim 		DES_ecb_encrypt(&session_key, &session_key, sched, 0);
204b285c5dfSJung-uk Kim 		DES_ecb_encrypt(&session_key, &challenge, sched, 0);
20581cb6ddcSMark Murray 		/*
20681cb6ddcSMark Murray 		 * Increment the challenge by 1, and encrypt it for
20781cb6ddcSMark Murray 		 * later comparison.
20881cb6ddcSMark Murray 		 */
20981cb6ddcSMark Murray 		for (i = 7; i >= 0; --i) {
21081cb6ddcSMark Murray 			register int x;
21181cb6ddcSMark Murray 			x = (unsigned int)challenge[i] + 1;
21281cb6ddcSMark Murray 			challenge[i] = x;	/* ignore overflow */
21381cb6ddcSMark Murray 			if (x < 256)		/* if no overflow, all done */
21481cb6ddcSMark Murray 				break;
21581cb6ddcSMark Murray 		}
216b285c5dfSJung-uk Kim 		DES_ecb_encrypt(&challenge, &challenge, sched, 1);
21781cb6ddcSMark Murray 	}
21881cb6ddcSMark Murray #endif	/* ENCRYPTION */
21981cb6ddcSMark Murray 
22081cb6ddcSMark Murray 	if (auth_debug_mode) {
2218fa113e5SMark Murray 		printf("CK: %d:", kerberos4_cksum(lauth.dat, lauth.length));
2228fa113e5SMark Murray 		printd(lauth.dat, lauth.length);
22381cb6ddcSMark Murray 		printf("\r\n");
22481cb6ddcSMark Murray 		printf("Sent Kerberos V4 credentials to server\r\n");
22581cb6ddcSMark Murray 	}
22681cb6ddcSMark Murray 	return(1);
22781cb6ddcSMark Murray }
22881cb6ddcSMark Murray 
22981cb6ddcSMark Murray void
kerberos4_is(Authenticator * ap,unsigned char * data,int cnt)2308fa113e5SMark Murray kerberos4_is(Authenticator *ap, unsigned char *data, int cnt)
23181cb6ddcSMark Murray {
23281cb6ddcSMark Murray #ifdef	ENCRYPTION
23381cb6ddcSMark Murray 	Session_Key skey;
23481cb6ddcSMark Murray 	Block datablock;
23581cb6ddcSMark Murray #endif	/* ENCRYPTION */
23681cb6ddcSMark Murray 	char realm[REALM_SZ];
23781cb6ddcSMark Murray 	char instance[INST_SZ];
23881cb6ddcSMark Murray 	int r;
23981cb6ddcSMark Murray 
24081cb6ddcSMark Murray 	if (cnt-- < 1)
24181cb6ddcSMark Murray 		return;
24281cb6ddcSMark Murray 	switch (*data++) {
24381cb6ddcSMark Murray 	case KRB_AUTH:
24481cb6ddcSMark Murray 		if (krb_get_lrealm(realm, 1) != KSUCCESS) {
2458fa113e5SMark Murray 			Data(ap, KRB_REJECT, "No local V4 Realm.", -1);
24681cb6ddcSMark Murray 			auth_finished(ap, AUTH_REJECT);
24781cb6ddcSMark Murray 			if (auth_debug_mode)
24881cb6ddcSMark Murray 				printf("No local realm\r\n");
24981cb6ddcSMark Murray 			return;
25081cb6ddcSMark Murray 		}
25181cb6ddcSMark Murray 		memmove((void *)auth.dat, (void *)data, auth.length = cnt);
25281cb6ddcSMark Murray 		if (auth_debug_mode) {
25381cb6ddcSMark Murray 			printf("Got %d bytes of authentication data\r\n", cnt);
25481cb6ddcSMark Murray 			printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
25581cb6ddcSMark Murray 			printd(auth.dat, auth.length);
25681cb6ddcSMark Murray 			printf("\r\n");
25781cb6ddcSMark Murray 		}
25881cb6ddcSMark Murray 		instance[0] = '*'; instance[1] = 0;
2598fa113e5SMark Murray 		if ((r = krb_rd_req(&auth, krb_service_name,
2608fa113e5SMark Murray 				   instance, 0, &adat, empty))) {
26181cb6ddcSMark Murray 			if (auth_debug_mode)
26281cb6ddcSMark Murray 				printf("Kerberos failed him as %s\r\n", name);
2638fa113e5SMark Murray 			Data(ap, KRB_REJECT, krb_err_txt[r], -1);
26481cb6ddcSMark Murray 			auth_finished(ap, AUTH_REJECT);
26581cb6ddcSMark Murray 			return;
26681cb6ddcSMark Murray 		}
26781cb6ddcSMark Murray #ifdef	ENCRYPTION
26881cb6ddcSMark Murray 		memmove((void *)session_key, (void *)adat.session, sizeof(Block));
26981cb6ddcSMark Murray #endif	/* ENCRYPTION */
27081cb6ddcSMark Murray 		krb_kntoln(&adat, name);
27181cb6ddcSMark Murray 
27281cb6ddcSMark Murray 		if (UserNameRequested && !kuserok(&adat, UserNameRequested))
2738fa113e5SMark Murray 			Data(ap, KRB_ACCEPT, NULL, 0);
27481cb6ddcSMark Murray 		else
2758fa113e5SMark Murray 			Data(ap, KRB_REJECT, "user is not authorized", -1);
27681cb6ddcSMark Murray 		auth_finished(ap, AUTH_USER);
27781cb6ddcSMark Murray 		break;
27881cb6ddcSMark Murray 
27981cb6ddcSMark Murray 	case KRB_CHALLENGE:
28081cb6ddcSMark Murray #ifndef	ENCRYPTION
2818fa113e5SMark Murray 		Data(ap, KRB_RESPONSE, NULL, 0);
28281cb6ddcSMark Murray #else	/* ENCRYPTION */
28381cb6ddcSMark Murray 		if (!VALIDKEY(session_key)) {
28481cb6ddcSMark Murray 			/*
28581cb6ddcSMark Murray 			 * We don't have a valid session key, so just
28681cb6ddcSMark Murray 			 * send back a response with an empty session
28781cb6ddcSMark Murray 			 * key.
28881cb6ddcSMark Murray 			 */
2898fa113e5SMark Murray 			Data(ap, KRB_RESPONSE, NULL, 0);
29081cb6ddcSMark Murray 			break;
29181cb6ddcSMark Murray 		}
29281cb6ddcSMark Murray 
293b285c5dfSJung-uk Kim 		DES_key_sched(&session_key, sched);
29481cb6ddcSMark Murray 		memmove((void *)datablock, (void *)data, sizeof(Block));
29581cb6ddcSMark Murray 		/*
29681cb6ddcSMark Murray 		 * Take the received encrypted challenge, and encrypt
29781cb6ddcSMark Murray 		 * it again to get a unique session_key for the
29881cb6ddcSMark Murray 		 * ENCRYPT option.
29981cb6ddcSMark Murray 		 */
300b285c5dfSJung-uk Kim 		DES_ecb_encrypt(&datablock, &session_key, sched, 1);
30181cb6ddcSMark Murray 		skey.type = SK_DES;
30281cb6ddcSMark Murray 		skey.length = 8;
30381cb6ddcSMark Murray 		skey.data = session_key;
30481cb6ddcSMark Murray 		encrypt_session_key(&skey, 1);
30581cb6ddcSMark Murray 		/*
30681cb6ddcSMark Murray 		 * Now decrypt the received encrypted challenge,
30781cb6ddcSMark Murray 		 * increment by one, re-encrypt it and send it back.
30881cb6ddcSMark Murray 		 */
309b285c5dfSJung-uk Kim 		DES_ecb_encrypt(&datablock, &challenge, sched, 0);
31081cb6ddcSMark Murray 		for (r = 7; r >= 0; r--) {
31181cb6ddcSMark Murray 			register int t;
31281cb6ddcSMark Murray 			t = (unsigned int)challenge[r] + 1;
31381cb6ddcSMark Murray 			challenge[r] = t;	/* ignore overflow */
31481cb6ddcSMark Murray 			if (t < 256)		/* if no overflow, all done */
31581cb6ddcSMark Murray 				break;
31681cb6ddcSMark Murray 		}
317b285c5dfSJung-uk Kim 		DES_ecb_encrypt(&challenge, &challenge, sched, 1);
3188fa113e5SMark Murray 		Data(ap, KRB_RESPONSE, challenge, sizeof(challenge));
31981cb6ddcSMark Murray #endif	/* ENCRYPTION */
32081cb6ddcSMark Murray 		break;
32181cb6ddcSMark Murray 
32281cb6ddcSMark Murray 	default:
32381cb6ddcSMark Murray 		if (auth_debug_mode)
32481cb6ddcSMark Murray 			printf("Unknown Kerberos option %d\r\n", data[-1]);
3258fa113e5SMark Murray 		Data(ap, KRB_REJECT, NULL, 0);
32681cb6ddcSMark Murray 		break;
32781cb6ddcSMark Murray 	}
32881cb6ddcSMark Murray }
32981cb6ddcSMark Murray 
33081cb6ddcSMark Murray void
kerberos4_reply(Authenticator * ap,unsigned char * data,int cnt)3318fa113e5SMark Murray kerberos4_reply(Authenticator *ap, unsigned char *data, int cnt)
33281cb6ddcSMark Murray {
33381cb6ddcSMark Murray #ifdef	ENCRYPTION
33481cb6ddcSMark Murray 	Session_Key skey;
33581cb6ddcSMark Murray #endif	/* ENCRYPTION */
33681cb6ddcSMark Murray 
33781cb6ddcSMark Murray 	if (cnt-- < 1)
33881cb6ddcSMark Murray 		return;
33981cb6ddcSMark Murray 	switch (*data++) {
34081cb6ddcSMark Murray 	case KRB_REJECT:
34181cb6ddcSMark Murray 		if (cnt > 0) {
34281cb6ddcSMark Murray 			printf("[ Kerberos V4 refuses authentication because %.*s ]\r\n",
34381cb6ddcSMark Murray 				cnt, data);
34481cb6ddcSMark Murray 		} else
34581cb6ddcSMark Murray 			printf("[ Kerberos V4 refuses authentication ]\r\n");
34681cb6ddcSMark Murray 		auth_send_retry();
34781cb6ddcSMark Murray 		return;
34881cb6ddcSMark Murray 	case KRB_ACCEPT:
34981cb6ddcSMark Murray 		printf("[ Kerberos V4 accepts you ]\n");
35081cb6ddcSMark Murray 		if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
35181cb6ddcSMark Murray 			/*
35281cb6ddcSMark Murray 			 * Send over the encrypted challenge.
35381cb6ddcSMark Murray 		 	 */
35481cb6ddcSMark Murray #ifndef	ENCRYPTION
3558fa113e5SMark Murray 			Data(ap, KRB_CHALLENGE, NULL, 0);
35681cb6ddcSMark Murray #else	/* ENCRYPTION */
3578fa113e5SMark Murray 			Data(ap, KRB_CHALLENGE, session_key,
35881cb6ddcSMark Murray 						sizeof(session_key));
359b285c5dfSJung-uk Kim 			DES_ecb_encrypt(&session_key, &session_key, sched, 1);
36081cb6ddcSMark Murray 			skey.type = SK_DES;
36181cb6ddcSMark Murray 			skey.length = 8;
36281cb6ddcSMark Murray 			skey.data = session_key;
36381cb6ddcSMark Murray 			encrypt_session_key(&skey, 0);
36481cb6ddcSMark Murray #endif	/* ENCRYPTION */
36581cb6ddcSMark Murray 			return;
36681cb6ddcSMark Murray 		}
36781cb6ddcSMark Murray 		auth_finished(ap, AUTH_USER);
36881cb6ddcSMark Murray 		return;
36981cb6ddcSMark Murray 	case KRB_RESPONSE:
37081cb6ddcSMark Murray #ifdef	ENCRYPTION
37181cb6ddcSMark Murray 		/*
37281cb6ddcSMark Murray 		 * Verify that the response to the challenge is correct.
37381cb6ddcSMark Murray 		 */
37481cb6ddcSMark Murray 		if ((cnt != sizeof(Block)) ||
37581cb6ddcSMark Murray 		    (0 != memcmp((void *)data, (void *)challenge,
37681cb6ddcSMark Murray 						sizeof(challenge))))
37781cb6ddcSMark Murray 		{
37881cb6ddcSMark Murray #endif	/* ENCRYPTION */
37981cb6ddcSMark Murray 			printf("[ Kerberos V4 challenge failed!!! ]\r\n");
38081cb6ddcSMark Murray 			auth_send_retry();
38181cb6ddcSMark Murray 			return;
38281cb6ddcSMark Murray #ifdef	ENCRYPTION
38381cb6ddcSMark Murray 		}
38481cb6ddcSMark Murray 		printf("[ Kerberos V4 challenge successful ]\r\n");
38581cb6ddcSMark Murray 		auth_finished(ap, AUTH_USER);
38681cb6ddcSMark Murray #endif	/* ENCRYPTION */
38781cb6ddcSMark Murray 		break;
38881cb6ddcSMark Murray 	default:
38981cb6ddcSMark Murray 		if (auth_debug_mode)
39081cb6ddcSMark Murray 			printf("Unknown Kerberos option %d\r\n", data[-1]);
39181cb6ddcSMark Murray 		return;
39281cb6ddcSMark Murray 	}
39381cb6ddcSMark Murray }
39481cb6ddcSMark Murray 
39581cb6ddcSMark Murray int
kerberos4_status(Authenticator * ap __unused,char * nam,int level)3968fa113e5SMark Murray kerberos4_status(Authenticator *ap __unused, char *nam, int level)
39781cb6ddcSMark Murray {
39881cb6ddcSMark Murray 	if (level < AUTH_USER)
39981cb6ddcSMark Murray 		return(level);
40081cb6ddcSMark Murray 
40181cb6ddcSMark Murray 	if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
4028fa113e5SMark Murray 		strcpy(nam, UserNameRequested);
40381cb6ddcSMark Murray 		return(AUTH_VALID);
40481cb6ddcSMark Murray 	} else
40581cb6ddcSMark Murray 		return(AUTH_USER);
40681cb6ddcSMark Murray }
40781cb6ddcSMark Murray 
40881cb6ddcSMark Murray #define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
40981cb6ddcSMark Murray #define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
41081cb6ddcSMark Murray 
41181cb6ddcSMark Murray void
kerberos4_printsub(unsigned char * data,int cnt,unsigned char * buf,int buflen)4128fa113e5SMark Murray kerberos4_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
41381cb6ddcSMark Murray {
41481cb6ddcSMark Murray 	char lbuf[32];
41581cb6ddcSMark Murray 	register int i;
41681cb6ddcSMark Murray 
41781cb6ddcSMark Murray 	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
41881cb6ddcSMark Murray 	buflen -= 1;
41981cb6ddcSMark Murray 
42081cb6ddcSMark Murray 	switch(data[3]) {
42181cb6ddcSMark Murray 	case KRB_REJECT:		/* Rejected (reason might follow) */
42281cb6ddcSMark Murray 		strncpy((char *)buf, " REJECT ", buflen);
42381cb6ddcSMark Murray 		goto common;
42481cb6ddcSMark Murray 
42581cb6ddcSMark Murray 	case KRB_ACCEPT:		/* Accepted (name might follow) */
42681cb6ddcSMark Murray 		strncpy((char *)buf, " ACCEPT ", buflen);
42781cb6ddcSMark Murray 	common:
42881cb6ddcSMark Murray 		BUMP(buf, buflen);
42981cb6ddcSMark Murray 		if (cnt <= 4)
43081cb6ddcSMark Murray 			break;
43181cb6ddcSMark Murray 		ADDC(buf, buflen, '"');
43281cb6ddcSMark Murray 		for (i = 4; i < cnt; i++)
43381cb6ddcSMark Murray 			ADDC(buf, buflen, data[i]);
43481cb6ddcSMark Murray 		ADDC(buf, buflen, '"');
43581cb6ddcSMark Murray 		ADDC(buf, buflen, '\0');
43681cb6ddcSMark Murray 		break;
43781cb6ddcSMark Murray 
43881cb6ddcSMark Murray 	case KRB_AUTH:			/* Authentication data follows */
43981cb6ddcSMark Murray 		strncpy((char *)buf, " AUTH", buflen);
44081cb6ddcSMark Murray 		goto common2;
44181cb6ddcSMark Murray 
44281cb6ddcSMark Murray 	case KRB_CHALLENGE:
44381cb6ddcSMark Murray 		strncpy((char *)buf, " CHALLENGE", buflen);
44481cb6ddcSMark Murray 		goto common2;
44581cb6ddcSMark Murray 
44681cb6ddcSMark Murray 	case KRB_RESPONSE:
44781cb6ddcSMark Murray 		strncpy((char *)buf, " RESPONSE", buflen);
44881cb6ddcSMark Murray 		goto common2;
44981cb6ddcSMark Murray 
45081cb6ddcSMark Murray 	default:
45181cb6ddcSMark Murray 		sprintf(lbuf, " %d (unknown)", data[3]);
45281cb6ddcSMark Murray 		strncpy((char *)buf, lbuf, buflen);
45381cb6ddcSMark Murray 	common2:
45481cb6ddcSMark Murray 		BUMP(buf, buflen);
45581cb6ddcSMark Murray 		for (i = 4; i < cnt; i++) {
45681cb6ddcSMark Murray 			sprintf(lbuf, " %d", data[i]);
45781cb6ddcSMark Murray 			strncpy((char *)buf, lbuf, buflen);
45881cb6ddcSMark Murray 			BUMP(buf, buflen);
45981cb6ddcSMark Murray 		}
46081cb6ddcSMark Murray 		break;
46181cb6ddcSMark Murray 	}
46281cb6ddcSMark Murray }
46381cb6ddcSMark Murray 
46481cb6ddcSMark Murray int
kerberos4_cksum(unsigned char * d,int n)4658fa113e5SMark Murray kerberos4_cksum(unsigned char *d, int n)
46681cb6ddcSMark Murray {
46781cb6ddcSMark Murray 	int ck = 0;
46881cb6ddcSMark Murray 
46981cb6ddcSMark Murray 	/*
47081cb6ddcSMark Murray 	 * A comment is probably needed here for those not
47181cb6ddcSMark Murray 	 * well versed in the "C" language.  Yes, this is
47281cb6ddcSMark Murray 	 * supposed to be a "switch" with the body of the
47381cb6ddcSMark Murray 	 * "switch" being a "while" statement.  The whole
47481cb6ddcSMark Murray 	 * purpose of the switch is to allow us to jump into
47581cb6ddcSMark Murray 	 * the middle of the while() loop, and then not have
47681cb6ddcSMark Murray 	 * to do any more switch()s.
47781cb6ddcSMark Murray 	 *
47881cb6ddcSMark Murray 	 * Some compilers will spit out a warning message
47981cb6ddcSMark Murray 	 * about the loop not being entered at the top.
48081cb6ddcSMark Murray 	 */
48181cb6ddcSMark Murray 	switch (n&03)
48281cb6ddcSMark Murray 	while (n > 0) {
48381cb6ddcSMark Murray 	case 0:
48481cb6ddcSMark Murray 		ck ^= (int)*d++ << 24;
48581cb6ddcSMark Murray 		--n;
48681cb6ddcSMark Murray 	case 3:
48781cb6ddcSMark Murray 		ck ^= (int)*d++ << 16;
48881cb6ddcSMark Murray 		--n;
48981cb6ddcSMark Murray 	case 2:
49081cb6ddcSMark Murray 		ck ^= (int)*d++ << 8;
49181cb6ddcSMark Murray 		--n;
49281cb6ddcSMark Murray 	case 1:
49381cb6ddcSMark Murray 		ck ^= (int)*d++;
49481cb6ddcSMark Murray 		--n;
49581cb6ddcSMark Murray 	}
49681cb6ddcSMark Murray 	return(ck);
49781cb6ddcSMark Murray }
49881cb6ddcSMark Murray #endif
499