129088Smarkm/*-
229088Smarkm * Copyright (c) 1991, 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
3929181Smarkmstatic const char sccsid[] = "@(#)kerberos.c	8.3 (Berkeley) 5/30/95";
4029088Smarkm#endif /* not lint */
4129088Smarkm
4229088Smarkm/*
4329088Smarkm * Copyright (C) 1990 by the Massachusetts Institute of Technology
4429088Smarkm *
4529088Smarkm * Export of this software from the United States of America is assumed
4629088Smarkm * to require a specific license from the United States Government.
4729088Smarkm * It is the responsibility of any person or organization contemplating
4829088Smarkm * export to obtain such a license before exporting.
4929088Smarkm *
5029088Smarkm * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
5129088Smarkm * distribute this software and its documentation for any purpose and
5229088Smarkm * without fee is hereby granted, provided that the above copyright
5329088Smarkm * notice appear in all copies and that both that copyright notice and
5429088Smarkm * this permission notice appear in supporting documentation, and that
5529088Smarkm * the name of M.I.T. not be used in advertising or publicity pertaining
5629088Smarkm * to distribution of the software without specific, written prior
5729088Smarkm * permission.  M.I.T. makes no representations about the suitability of
5829088Smarkm * this software for any purpose.  It is provided "as is" without express
5929088Smarkm * or implied warranty.
6029088Smarkm */
6129088Smarkm
6229088Smarkm#ifdef	KRB4
6329088Smarkm#include <sys/types.h>
6429088Smarkm#include <arpa/telnet.h>
6557442Smarkm#include <openssl/des.h>	/* BSD wont include this in krb.h, so we do it here */
6629088Smarkm#include <krb.h>
6787139Smarkm#include <stdio.h>
6829088Smarkm#include <stdlib.h>
6929088Smarkm#include <string.h>
7029088Smarkm
7129088Smarkm#include "encrypt.h"
7229088Smarkm#include "auth.h"
7329088Smarkm#include "misc.h"
7429088Smarkm
7587155Smarkmint kerberos4_cksum(unsigned char *, int);
7687155Smarkmint kuserok(AUTH_DAT *, char *);
7729088Smarkm
7887139Smarkmextern int auth_debug_mode;
7929088Smarkm
8029088Smarkmstatic unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
8129088Smarkm			  		AUTHTYPE_KERBEROS_V4, };
8229088Smarkm
8329088Smarkm#define	KRB_AUTH	0		/* Authentication data follows */
8429088Smarkm#define	KRB_REJECT	1		/* Rejected (reason might follow) */
8529088Smarkm#define	KRB_ACCEPT	2		/* Accepted */
8629088Smarkm#define	KRB_CHALLENGE	3		/* Challenge for mutual auth. */
8729088Smarkm#define	KRB_RESPONSE	4		/* Response for mutual auth. */
8829088Smarkm
8929088Smarkmstatic	KTEXT_ST auth;
9029088Smarkmstatic	char name[ANAME_SZ];
9187139Smarkmstatic	AUTH_DAT adat = { 0, "", "", "", 0, {}, 0, 0, 0, { 0, "", 0 } };
9229088Smarkm#ifdef	ENCRYPTION
9329088Smarkmstatic Block	session_key	= { 0 };
9429181Smarkmstatic des_key_schedule sched;
9529088Smarkmstatic Block	challenge	= { 0 };
9629088Smarkm#endif	/* ENCRYPTION */
9729088Smarkm
9887139Smarkmstatic char krb_service_name[] = "rcmd";
9987139Smarkmstatic char empty[] = "";
10087139Smarkm
10187139Smarkmstatic int
10287139SmarkmData(Authenticator *ap, int type, const unsigned char *d, int c)
10329088Smarkm{
10429088Smarkm	unsigned char *p = str_data + 4;
10587139Smarkm	const unsigned char *cd = d;
10629088Smarkm
10729088Smarkm	if (c == -1)
10887139Smarkm		c = strlen(cd);
10929088Smarkm
11029088Smarkm	if (auth_debug_mode) {
11129088Smarkm		printf("%s:%d: [%d] (%d)",
11229088Smarkm			str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
11329088Smarkm			str_data[3],
11429088Smarkm			type, c);
11529088Smarkm		printd(d, c);
11629088Smarkm		printf("\r\n");
11729088Smarkm	}
11829088Smarkm	*p++ = ap->type;
11929088Smarkm	*p++ = ap->way;
12029088Smarkm	*p++ = type;
12129088Smarkm	while (c-- > 0) {
12229088Smarkm		if ((*p++ = *cd++) == IAC)
12329088Smarkm			*p++ = IAC;
12429088Smarkm	}
12529088Smarkm	*p++ = IAC;
12629088Smarkm	*p++ = SE;
12729088Smarkm	if (str_data[3] == TELQUAL_IS)
12829088Smarkm		printsub('>', &str_data[2], p - (&str_data[2]));
12929088Smarkm	return(net_write(str_data, p - str_data));
13029088Smarkm}
13129088Smarkm
13287139Smarkmint
13387139Smarkmkerberos4_init(Authenticator *ap __unused, int server)
13429088Smarkm{
13529088Smarkm	FILE *fp;
13629088Smarkm
13729088Smarkm	if (server) {
13829088Smarkm		str_data[3] = TELQUAL_REPLY;
13929088Smarkm		if ((fp = fopen(KEYFILE, "r")) == NULL)
14029088Smarkm			return(0);
14129088Smarkm		fclose(fp);
14229088Smarkm	} else {
14329088Smarkm		str_data[3] = TELQUAL_IS;
14429088Smarkm	}
14529088Smarkm	return(1);
14629088Smarkm}
14729088Smarkm
14829088Smarkmchar dst_realm_buf[REALM_SZ], *dest_realm = NULL;
14929088Smarkmint dst_realm_sz = REALM_SZ;
15029088Smarkm
15187139Smarkmint
15287139Smarkmkerberos4_send(Authenticator *ap)
15329088Smarkm{
15487139Smarkm	KTEXT_ST lauth;
15529088Smarkm	char instance[INST_SZ];
15629088Smarkm	char *realm;
15729088Smarkm	CREDENTIALS cred;
15829088Smarkm	int r;
15929088Smarkm
16029088Smarkm	printf("[ Trying KERBEROS4 ... ]\n");
16129088Smarkm	if (!UserNameRequested) {
16229088Smarkm		if (auth_debug_mode) {
16329088Smarkm			printf("Kerberos V4: no user name supplied\r\n");
16429088Smarkm		}
16529088Smarkm		return(0);
16629088Smarkm	}
16729088Smarkm
16829088Smarkm	memset(instance, 0, sizeof(instance));
16929088Smarkm
17029181Smarkm	if ((realm = krb_get_phost(RemoteHostName)))
17129088Smarkm		strncpy(instance, realm, sizeof(instance));
17229088Smarkm
17329088Smarkm	instance[sizeof(instance)-1] = '\0';
17429088Smarkm
17529088Smarkm	realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName);
17629088Smarkm
17729088Smarkm	if (!realm) {
17829088Smarkm		printf("Kerberos V4: no realm for %s\r\n", RemoteHostName);
17929088Smarkm		return(0);
18029088Smarkm	}
18187139Smarkm	if ((r = krb_mk_req(&lauth, krb_service_name, instance, realm, 0L))) {
18229088Smarkm		printf("mk_req failed: %s\r\n", krb_err_txt[r]);
18329088Smarkm		return(0);
18429088Smarkm	}
18587139Smarkm	if ((r = krb_get_cred(krb_service_name, instance, realm, &cred))) {
18629088Smarkm		printf("get_cred failed: %s\r\n", krb_err_txt[r]);
18729088Smarkm		return(0);
18829088Smarkm	}
18929088Smarkm	if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
19029088Smarkm		if (auth_debug_mode)
19129088Smarkm			printf("Not enough room for user name\r\n");
19229088Smarkm		return(0);
19329088Smarkm	}
19429088Smarkm	if (auth_debug_mode)
19587139Smarkm		printf("Sent %d bytes of authentication data\r\n", lauth.length);
19687139Smarkm	if (!Data(ap, KRB_AUTH, (void *)lauth.dat, lauth.length)) {
19729088Smarkm		if (auth_debug_mode)
19829088Smarkm			printf("Not enough room for authentication data\r\n");
19929088Smarkm		return(0);
20029088Smarkm	}
20129088Smarkm#ifdef	ENCRYPTION
20229088Smarkm	/*
20329088Smarkm	 * If we are doing mutual authentication, get set up to send
20429088Smarkm	 * the challenge, and verify it when the response comes back.
20529088Smarkm	 */
20629088Smarkm	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
20729088Smarkm		register int i;
20829088Smarkm
20929181Smarkm		des_key_sched(&cred.session, sched);
210110049Snectar		des_random_key(&session_key);
21129181Smarkm		des_ecb_encrypt(&session_key, &session_key, sched, 0);
21229181Smarkm		des_ecb_encrypt(&session_key, &challenge, sched, 0);
21329088Smarkm		/*
21429088Smarkm		 * Increment the challenge by 1, and encrypt it for
21529088Smarkm		 * later comparison.
21629088Smarkm		 */
21729088Smarkm		for (i = 7; i >= 0; --i) {
21829088Smarkm			register int x;
21929088Smarkm			x = (unsigned int)challenge[i] + 1;
22029088Smarkm			challenge[i] = x;	/* ignore overflow */
22129088Smarkm			if (x < 256)		/* if no overflow, all done */
22229088Smarkm				break;
22329088Smarkm		}
22429181Smarkm		des_ecb_encrypt(&challenge, &challenge, sched, 1);
22529088Smarkm	}
22629088Smarkm#endif	/* ENCRYPTION */
22729088Smarkm
22829088Smarkm	if (auth_debug_mode) {
22987139Smarkm		printf("CK: %d:", kerberos4_cksum(lauth.dat, lauth.length));
23087139Smarkm		printd(lauth.dat, lauth.length);
23129088Smarkm		printf("\r\n");
23229088Smarkm		printf("Sent Kerberos V4 credentials to server\r\n");
23329088Smarkm	}
23429088Smarkm	return(1);
23529088Smarkm}
23629088Smarkm
23787139Smarkmvoid
23887139Smarkmkerberos4_is(Authenticator *ap, unsigned char *data, int cnt)
23929088Smarkm{
24029088Smarkm#ifdef	ENCRYPTION
24129088Smarkm	Session_Key skey;
24229088Smarkm	Block datablock;
24329088Smarkm#endif	/* ENCRYPTION */
24429088Smarkm	char realm[REALM_SZ];
24529088Smarkm	char instance[INST_SZ];
24629088Smarkm	int r;
24729088Smarkm
24829088Smarkm	if (cnt-- < 1)
24929088Smarkm		return;
25029088Smarkm	switch (*data++) {
25129088Smarkm	case KRB_AUTH:
25229088Smarkm		if (krb_get_lrealm(realm, 1) != KSUCCESS) {
25387139Smarkm			Data(ap, KRB_REJECT, "No local V4 Realm.", -1);
25429088Smarkm			auth_finished(ap, AUTH_REJECT);
25529088Smarkm			if (auth_debug_mode)
25629088Smarkm				printf("No local realm\r\n");
25729088Smarkm			return;
25829088Smarkm		}
25929088Smarkm		memmove((void *)auth.dat, (void *)data, auth.length = cnt);
26029088Smarkm		if (auth_debug_mode) {
26129088Smarkm			printf("Got %d bytes of authentication data\r\n", cnt);
26229088Smarkm			printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
26329088Smarkm			printd(auth.dat, auth.length);
26429088Smarkm			printf("\r\n");
26529088Smarkm		}
26629088Smarkm		instance[0] = '*'; instance[1] = 0;
26787139Smarkm		if ((r = krb_rd_req(&auth, krb_service_name,
26887139Smarkm				   instance, 0, &adat, empty))) {
26929088Smarkm			if (auth_debug_mode)
27029088Smarkm				printf("Kerberos failed him as %s\r\n", name);
27187139Smarkm			Data(ap, KRB_REJECT, krb_err_txt[r], -1);
27229088Smarkm			auth_finished(ap, AUTH_REJECT);
27329088Smarkm			return;
27429088Smarkm		}
27529088Smarkm#ifdef	ENCRYPTION
27629088Smarkm		memmove((void *)session_key, (void *)adat.session, sizeof(Block));
27729088Smarkm#endif	/* ENCRYPTION */
27829088Smarkm		krb_kntoln(&adat, name);
27929088Smarkm
28029088Smarkm		if (UserNameRequested && !kuserok(&adat, UserNameRequested))
28187139Smarkm			Data(ap, KRB_ACCEPT, NULL, 0);
28229088Smarkm		else
28387139Smarkm			Data(ap, KRB_REJECT, "user is not authorized", -1);
28429088Smarkm		auth_finished(ap, AUTH_USER);
28529088Smarkm		break;
28629088Smarkm
28729088Smarkm	case KRB_CHALLENGE:
28829088Smarkm#ifndef	ENCRYPTION
28987139Smarkm		Data(ap, KRB_RESPONSE, NULL, 0);
29029088Smarkm#else	/* ENCRYPTION */
29129088Smarkm		if (!VALIDKEY(session_key)) {
29229088Smarkm			/*
29329088Smarkm			 * We don't have a valid session key, so just
29429088Smarkm			 * send back a response with an empty session
29529088Smarkm			 * key.
29629088Smarkm			 */
29787139Smarkm			Data(ap, KRB_RESPONSE, NULL, 0);
29829088Smarkm			break;
29929088Smarkm		}
30029088Smarkm
30129181Smarkm		des_key_sched(&session_key, sched);
30229088Smarkm		memmove((void *)datablock, (void *)data, sizeof(Block));
30329088Smarkm		/*
30429088Smarkm		 * Take the received encrypted challenge, and encrypt
30529088Smarkm		 * it again to get a unique session_key for the
30629088Smarkm		 * ENCRYPT option.
30729088Smarkm		 */
30829181Smarkm		des_ecb_encrypt(&datablock, &session_key, sched, 1);
30929088Smarkm		skey.type = SK_DES;
31029088Smarkm		skey.length = 8;
31129088Smarkm		skey.data = session_key;
31229088Smarkm		encrypt_session_key(&skey, 1);
31329088Smarkm		/*
31429088Smarkm		 * Now decrypt the received encrypted challenge,
31529088Smarkm		 * increment by one, re-encrypt it and send it back.
31629088Smarkm		 */
31729181Smarkm		des_ecb_encrypt(&datablock, &challenge, sched, 0);
31829088Smarkm		for (r = 7; r >= 0; r--) {
31929088Smarkm			register int t;
32029088Smarkm			t = (unsigned int)challenge[r] + 1;
32129088Smarkm			challenge[r] = t;	/* ignore overflow */
32229088Smarkm			if (t < 256)		/* if no overflow, all done */
32329088Smarkm				break;
32429088Smarkm		}
32529181Smarkm		des_ecb_encrypt(&challenge, &challenge, sched, 1);
32687139Smarkm		Data(ap, KRB_RESPONSE, challenge, sizeof(challenge));
32729088Smarkm#endif	/* ENCRYPTION */
32829088Smarkm		break;
32929088Smarkm
33029088Smarkm	default:
33129088Smarkm		if (auth_debug_mode)
33229088Smarkm			printf("Unknown Kerberos option %d\r\n", data[-1]);
33387139Smarkm		Data(ap, KRB_REJECT, NULL, 0);
33429088Smarkm		break;
33529088Smarkm	}
33629088Smarkm}
33729088Smarkm
33887139Smarkmvoid
33987139Smarkmkerberos4_reply(Authenticator *ap, unsigned char *data, int cnt)
34029088Smarkm{
34129088Smarkm#ifdef	ENCRYPTION
34229088Smarkm	Session_Key skey;
34329088Smarkm#endif	/* ENCRYPTION */
34429088Smarkm
34529088Smarkm	if (cnt-- < 1)
34629088Smarkm		return;
34729088Smarkm	switch (*data++) {
34829088Smarkm	case KRB_REJECT:
34929088Smarkm		if (cnt > 0) {
35029088Smarkm			printf("[ Kerberos V4 refuses authentication because %.*s ]\r\n",
35129088Smarkm				cnt, data);
35229088Smarkm		} else
35329088Smarkm			printf("[ Kerberos V4 refuses authentication ]\r\n");
35429088Smarkm		auth_send_retry();
35529088Smarkm		return;
35629088Smarkm	case KRB_ACCEPT:
35729088Smarkm		printf("[ Kerberos V4 accepts you ]\n");
35829088Smarkm		if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
35929088Smarkm			/*
36029088Smarkm			 * Send over the encrypted challenge.
36129088Smarkm		 	 */
36229088Smarkm#ifndef	ENCRYPTION
36387139Smarkm			Data(ap, KRB_CHALLENGE, NULL, 0);
36429088Smarkm#else	/* ENCRYPTION */
36587139Smarkm			Data(ap, KRB_CHALLENGE, session_key,
36629088Smarkm						sizeof(session_key));
36729181Smarkm			des_ecb_encrypt(&session_key, &session_key, sched, 1);
36829088Smarkm			skey.type = SK_DES;
36929088Smarkm			skey.length = 8;
37029088Smarkm			skey.data = session_key;
37129088Smarkm			encrypt_session_key(&skey, 0);
37229088Smarkm#endif	/* ENCRYPTION */
37329088Smarkm			return;
37429088Smarkm		}
37529088Smarkm		auth_finished(ap, AUTH_USER);
37629088Smarkm		return;
37729088Smarkm	case KRB_RESPONSE:
37829088Smarkm#ifdef	ENCRYPTION
37929088Smarkm		/*
38029088Smarkm		 * Verify that the response to the challenge is correct.
38129088Smarkm		 */
38229088Smarkm		if ((cnt != sizeof(Block)) ||
38329088Smarkm		    (0 != memcmp((void *)data, (void *)challenge,
38429088Smarkm						sizeof(challenge))))
38529088Smarkm		{
38629088Smarkm#endif	/* ENCRYPTION */
38729088Smarkm			printf("[ Kerberos V4 challenge failed!!! ]\r\n");
38829088Smarkm			auth_send_retry();
38929088Smarkm			return;
39029088Smarkm#ifdef	ENCRYPTION
39129088Smarkm		}
39229088Smarkm		printf("[ Kerberos V4 challenge successful ]\r\n");
39329088Smarkm		auth_finished(ap, AUTH_USER);
39429088Smarkm#endif	/* ENCRYPTION */
39529088Smarkm		break;
39629088Smarkm	default:
39729088Smarkm		if (auth_debug_mode)
39829088Smarkm			printf("Unknown Kerberos option %d\r\n", data[-1]);
39929088Smarkm		return;
40029088Smarkm	}
40129088Smarkm}
40229088Smarkm
40387139Smarkmint
40487139Smarkmkerberos4_status(Authenticator *ap __unused, char *nam, int level)
40529088Smarkm{
40629088Smarkm	if (level < AUTH_USER)
40729088Smarkm		return(level);
40829088Smarkm
40929088Smarkm	if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
41087139Smarkm		strcpy(nam, UserNameRequested);
41129088Smarkm		return(AUTH_VALID);
41229088Smarkm	} else
41329088Smarkm		return(AUTH_USER);
41429088Smarkm}
41529088Smarkm
41629088Smarkm#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
41729088Smarkm#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
41829088Smarkm
41987139Smarkmvoid
42087139Smarkmkerberos4_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
42129088Smarkm{
42229088Smarkm	char lbuf[32];
42329088Smarkm	register int i;
42429088Smarkm
42529088Smarkm	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
42629088Smarkm	buflen -= 1;
42729088Smarkm
42829088Smarkm	switch(data[3]) {
42929088Smarkm	case KRB_REJECT:		/* Rejected (reason might follow) */
43029088Smarkm		strncpy((char *)buf, " REJECT ", buflen);
43129088Smarkm		goto common;
43229088Smarkm
43329088Smarkm	case KRB_ACCEPT:		/* Accepted (name might follow) */
43429088Smarkm		strncpy((char *)buf, " ACCEPT ", buflen);
43529088Smarkm	common:
43629088Smarkm		BUMP(buf, buflen);
43729088Smarkm		if (cnt <= 4)
43829088Smarkm			break;
43929088Smarkm		ADDC(buf, buflen, '"');
44029088Smarkm		for (i = 4; i < cnt; i++)
44129088Smarkm			ADDC(buf, buflen, data[i]);
44229088Smarkm		ADDC(buf, buflen, '"');
44329088Smarkm		ADDC(buf, buflen, '\0');
44429088Smarkm		break;
44529088Smarkm
44629088Smarkm	case KRB_AUTH:			/* Authentication data follows */
44729088Smarkm		strncpy((char *)buf, " AUTH", buflen);
44829088Smarkm		goto common2;
44929088Smarkm
45029088Smarkm	case KRB_CHALLENGE:
45129088Smarkm		strncpy((char *)buf, " CHALLENGE", buflen);
45229088Smarkm		goto common2;
45329088Smarkm
45429088Smarkm	case KRB_RESPONSE:
45529088Smarkm		strncpy((char *)buf, " RESPONSE", buflen);
45629088Smarkm		goto common2;
45729088Smarkm
45829088Smarkm	default:
45929088Smarkm		sprintf(lbuf, " %d (unknown)", data[3]);
46029088Smarkm		strncpy((char *)buf, lbuf, buflen);
46129088Smarkm	common2:
46229088Smarkm		BUMP(buf, buflen);
46329088Smarkm		for (i = 4; i < cnt; i++) {
46429088Smarkm			sprintf(lbuf, " %d", data[i]);
46529088Smarkm			strncpy((char *)buf, lbuf, buflen);
46629088Smarkm			BUMP(buf, buflen);
46729088Smarkm		}
46829088Smarkm		break;
46929088Smarkm	}
47029088Smarkm}
47129088Smarkm
47287139Smarkmint
47387139Smarkmkerberos4_cksum(unsigned char *d, int n)
47429088Smarkm{
47529088Smarkm	int ck = 0;
47629088Smarkm
47729088Smarkm	/*
47829088Smarkm	 * A comment is probably needed here for those not
47929088Smarkm	 * well versed in the "C" language.  Yes, this is
48029088Smarkm	 * supposed to be a "switch" with the body of the
48129088Smarkm	 * "switch" being a "while" statement.  The whole
48229088Smarkm	 * purpose of the switch is to allow us to jump into
48329088Smarkm	 * the middle of the while() loop, and then not have
48429088Smarkm	 * to do any more switch()s.
48529088Smarkm	 *
48629088Smarkm	 * Some compilers will spit out a warning message
48729088Smarkm	 * about the loop not being entered at the top.
48829088Smarkm	 */
48929088Smarkm	switch (n&03)
49029088Smarkm	while (n > 0) {
49129088Smarkm	case 0:
49229088Smarkm		ck ^= (int)*d++ << 24;
49329088Smarkm		--n;
49429088Smarkm	case 3:
49529088Smarkm		ck ^= (int)*d++ << 16;
49629088Smarkm		--n;
49729088Smarkm	case 2:
49829088Smarkm		ck ^= (int)*d++ << 8;
49929088Smarkm		--n;
50029088Smarkm	case 1:
50129088Smarkm		ck ^= (int)*d++;
50229088Smarkm		--n;
50329088Smarkm	}
50429088Smarkm	return(ck);
50529088Smarkm}
50629088Smarkm#endif
507