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.
3262958Snsayer *
3329088Smarkm */
3429088Smarkm
35114630Sobrien#if 0
3629088Smarkm#ifndef lint
3729181Smarkmstatic const char sccsid[] = "@(#)auth.c	8.3 (Berkeley) 5/30/95";
3829088Smarkm#endif /* not lint */
39114630Sobrien#endif
40114630Sobrien#include <sys/cdefs.h>
41114630Sobrien__FBSDID("$FreeBSD$");
4229088Smarkm
43114630Sobrien
4429088Smarkm/*
4529088Smarkm * Copyright (C) 1990 by the Massachusetts Institute of Technology
4629088Smarkm *
4729088Smarkm * Export of this software from the United States of America is assumed
4829088Smarkm * to require a specific license from the United States Government.
4929088Smarkm * It is the responsibility of any person or organization contemplating
5029088Smarkm * export to obtain such a license before exporting.
5129088Smarkm *
5229088Smarkm * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
5329088Smarkm * distribute this software and its documentation for any purpose and
5429088Smarkm * without fee is hereby granted, provided that the above copyright
5529088Smarkm * notice appear in all copies and that both that copyright notice and
5629088Smarkm * this permission notice appear in supporting documentation, and that
5729088Smarkm * the name of M.I.T. not be used in advertising or publicity pertaining
5829088Smarkm * to distribution of the software without specific, written prior
5929088Smarkm * permission.  M.I.T. makes no representations about the suitability of
6029088Smarkm * this software for any purpose.  It is provided "as is" without express
6129088Smarkm * or implied warranty.
6229088Smarkm */
6329088Smarkm
6429088Smarkm
6587139Smarkm#ifdef	AUTHENTICATION
6687139Smarkm#define	AUTH_NAMES
6729088Smarkm#include <sys/types.h>
6829088Smarkm#include <signal.h>
6987139Smarkm#include <stdio.h>
7029088Smarkm#include <stdlib.h>
7187139Smarkm#include <string.h>
7229181Smarkm#include <unistd.h>
7387139Smarkm#include <arpa/telnet.h>
7429088Smarkm
7529088Smarkm#include "encrypt.h"
7629088Smarkm#include "auth.h"
7729088Smarkm#include "misc-proto.h"
7829088Smarkm#include "auth-proto.h"
7929088Smarkm
8087139Smarkm#define	typemask(x)	((x) > 0 ? 1 << ((x)-1) : 0)
8129088Smarkm
8229088Smarkm#ifdef	KRB4_ENCPWD
8329088Smarkmextern krb4encpwd_init();
8429088Smarkmextern krb4encpwd_send();
8529088Smarkmextern krb4encpwd_is();
8629088Smarkmextern krb4encpwd_reply();
8729088Smarkmextern krb4encpwd_status();
8829088Smarkmextern krb4encpwd_printsub();
8929088Smarkm#endif
9029088Smarkm
9129088Smarkm#ifdef	RSA_ENCPWD
9229088Smarkmextern rsaencpwd_init();
9329088Smarkmextern rsaencpwd_send();
9429088Smarkmextern rsaencpwd_is();
9529088Smarkmextern rsaencpwd_reply();
9629088Smarkmextern rsaencpwd_status();
9729088Smarkmextern rsaencpwd_printsub();
9829088Smarkm#endif
9929088Smarkm
10029088Smarkmint auth_debug_mode = 0;
10187139Smarkmstatic 	const char	*Name = "Noname";
10229088Smarkmstatic	int	Server = 0;
10329088Smarkmstatic	Authenticator	*authenticated = 0;
10429088Smarkmstatic	int	authenticating = 0;
10529088Smarkmstatic	int	validuser = 0;
10629088Smarkmstatic	unsigned char	_auth_send_data[256];
10729088Smarkmstatic	unsigned char	*auth_send_data;
10829088Smarkmstatic	int	auth_send_cnt = 0;
10929088Smarkm
11029181Smarkmint auth_onoff(char *type, int on);
11129181Smarkmvoid auth_encrypt_user(char *name);
11229181Smarkm
11329088Smarkm/*
11429088Smarkm * Authentication types supported.  Plese note that these are stored
11529088Smarkm * in priority order, i.e. try the first one first.
11629088Smarkm */
11729088SmarkmAuthenticator authenticators[] = {
11829088Smarkm#ifdef	KRB5
11929088Smarkm# ifdef	ENCRYPTION
12029088Smarkm	{ AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
12129088Smarkm				kerberos5_init,
12287139Smarkm				kerberos5_send_mutual,
12329088Smarkm				kerberos5_is,
12429088Smarkm				kerberos5_reply,
12529088Smarkm				kerberos5_status,
12629088Smarkm				kerberos5_printsub },
12729088Smarkm# endif	/* ENCRYPTION */
12829088Smarkm	{ AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
12929088Smarkm				kerberos5_init,
13087139Smarkm				kerberos5_send_oneway,
13129088Smarkm				kerberos5_is,
13229088Smarkm				kerberos5_reply,
13329088Smarkm				kerberos5_status,
13429088Smarkm				kerberos5_printsub },
13529088Smarkm#endif
13629088Smarkm#ifdef	KRB4
13729088Smarkm# ifdef ENCRYPTION
13829088Smarkm	{ AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
13929088Smarkm				kerberos4_init,
14029088Smarkm				kerberos4_send,
14129088Smarkm				kerberos4_is,
14229088Smarkm				kerberos4_reply,
14329088Smarkm				kerberos4_status,
14429088Smarkm				kerberos4_printsub },
14529088Smarkm# endif	/* ENCRYPTION */
14629088Smarkm	{ AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
14729088Smarkm				kerberos4_init,
14829088Smarkm				kerberos4_send,
14929088Smarkm				kerberos4_is,
15029088Smarkm				kerberos4_reply,
15129088Smarkm				kerberos4_status,
15229088Smarkm				kerberos4_printsub },
15329088Smarkm#endif
15429088Smarkm#ifdef	KRB4_ENCPWD
15529088Smarkm	{ AUTHTYPE_KRB4_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
15629088Smarkm				krb4encpwd_init,
15729088Smarkm				krb4encpwd_send,
15829088Smarkm				krb4encpwd_is,
15929088Smarkm				krb4encpwd_reply,
16029088Smarkm				krb4encpwd_status,
16129088Smarkm				krb4encpwd_printsub },
16229088Smarkm#endif
16329088Smarkm#ifdef	RSA_ENCPWD
16429088Smarkm	{ AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
16529088Smarkm				rsaencpwd_init,
16629088Smarkm				rsaencpwd_send,
16729088Smarkm				rsaencpwd_is,
16829088Smarkm				rsaencpwd_reply,
16929088Smarkm				rsaencpwd_status,
17029088Smarkm				rsaencpwd_printsub },
17129088Smarkm#endif
17249887Snsayer#ifdef SRA
17349887Snsayer	{ AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
17449887Snsayer				sra_init,
17549887Snsayer				sra_send,
17649887Snsayer				sra_is,
17749887Snsayer				sra_reply,
17849887Snsayer				sra_status,
17949887Snsayer				sra_printsub },
18049887Snsayer
18149887Snsayer#endif
18287139Smarkm	{ 0, 0, 0, 0, 0, 0, 0, 0 },
18329088Smarkm};
18429088Smarkm
18587139Smarkmstatic Authenticator NoAuth = { 0, 0, 0, 0, 0, 0, 0, 0 };
18629088Smarkm
18729088Smarkmstatic int	i_support = 0;
18829088Smarkmstatic int	i_wont_support = 0;
18929088Smarkm
19087139SmarkmAuthenticator *
19187139Smarkmfindauthenticator(int type, int way)
19229088Smarkm{
19329088Smarkm	Authenticator *ap = authenticators;
19429088Smarkm
19529088Smarkm	while (ap->type && (ap->type != type || ap->way != way))
19629088Smarkm		++ap;
19729088Smarkm	return(ap->type ? ap : 0);
19829088Smarkm}
19929088Smarkm
20087139Smarkmvoid
20187139Smarkmauth_init(const char *name, int server)
20229088Smarkm{
20329088Smarkm	Authenticator *ap = authenticators;
20429088Smarkm
20529088Smarkm	Server = server;
20629088Smarkm	Name = name;
20729088Smarkm
20829088Smarkm	i_support = 0;
20929088Smarkm	authenticated = 0;
21029088Smarkm	authenticating = 0;
21129088Smarkm	while (ap->type) {
21229088Smarkm		if (!ap->init || (*ap->init)(ap, server)) {
21329088Smarkm			i_support |= typemask(ap->type);
21429088Smarkm			if (auth_debug_mode)
21529088Smarkm				printf(">>>%s: I support auth type %d %d\r\n",
21629088Smarkm					Name,
21729088Smarkm					ap->type, ap->way);
21829088Smarkm		}
21929088Smarkm		else if (auth_debug_mode)
22029088Smarkm			printf(">>>%s: Init failed: auth type %d %d\r\n",
22129088Smarkm				Name, ap->type, ap->way);
22229088Smarkm		++ap;
22329088Smarkm	}
22429088Smarkm}
22529088Smarkm
22687139Smarkmvoid
22787139Smarkmauth_disable_name(char *name)
22829088Smarkm{
22929088Smarkm	int x;
23029088Smarkm	for (x = 0; x < AUTHTYPE_CNT; ++x) {
23162958Snsayer		if (AUTHTYPE_NAME(x) && !strcasecmp(name, AUTHTYPE_NAME(x))) {
23229088Smarkm			i_wont_support |= typemask(x);
23329088Smarkm			break;
23429088Smarkm		}
23529088Smarkm	}
23629088Smarkm}
23729088Smarkm
23887139Smarkmint
23987139Smarkmgetauthmask(char *type, int *maskp)
24029088Smarkm{
24187139Smarkm	int x;
24229088Smarkm
24374411Snsayer	if (AUTHTYPE_NAME(0) && !strcasecmp(type, AUTHTYPE_NAME(0))) {
24429088Smarkm		*maskp = -1;
24529088Smarkm		return(1);
24629088Smarkm	}
24729088Smarkm
24829088Smarkm	for (x = 1; x < AUTHTYPE_CNT; ++x) {
24974411Snsayer		if (AUTHTYPE_NAME(x) && !strcasecmp(type, AUTHTYPE_NAME(x))) {
25029088Smarkm			*maskp = typemask(x);
25129088Smarkm			return(1);
25229088Smarkm		}
25329088Smarkm	}
25429088Smarkm	return(0);
25529088Smarkm}
25629088Smarkm
25787139Smarkmint
25887139Smarkmauth_enable(char *type)
25929088Smarkm{
26029088Smarkm	return(auth_onoff(type, 1));
26129088Smarkm}
26229088Smarkm
26387139Smarkmint
26487139Smarkmauth_disable(char *type)
26529088Smarkm{
26629088Smarkm	return(auth_onoff(type, 0));
26729088Smarkm}
26829088Smarkm
26987139Smarkmint
27087139Smarkmauth_onoff(char *type, int on)
27129088Smarkm{
27229088Smarkm	int i, mask = -1;
27329088Smarkm	Authenticator *ap;
27429088Smarkm
27529088Smarkm	if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) {
27629088Smarkm		printf("auth %s 'type'\n", on ? "enable" : "disable");
27729088Smarkm		printf("Where 'type' is one of:\n");
27829088Smarkm		printf("\t%s\n", AUTHTYPE_NAME(0));
27929088Smarkm		mask = 0;
28029088Smarkm		for (ap = authenticators; ap->type; ap++) {
28129088Smarkm			if ((mask & (i = typemask(ap->type))) != 0)
28229088Smarkm				continue;
28329088Smarkm			mask |= i;
28429088Smarkm			printf("\t%s\n", AUTHTYPE_NAME(ap->type));
28529088Smarkm		}
28629088Smarkm		return(0);
28729088Smarkm	}
28829088Smarkm
28929088Smarkm	if (!getauthmask(type, &mask)) {
29029088Smarkm		printf("%s: invalid authentication type\n", type);
29129088Smarkm		return(0);
29229088Smarkm	}
29329088Smarkm	if (on)
29429088Smarkm		i_wont_support &= ~mask;
29529088Smarkm	else
29629088Smarkm		i_wont_support |= mask;
29729088Smarkm	return(1);
29829088Smarkm}
29929088Smarkm
30087139Smarkmint
30187139Smarkmauth_togdebug(int on)
30229088Smarkm{
30329088Smarkm	if (on < 0)
30429088Smarkm		auth_debug_mode ^= 1;
30529088Smarkm	else
30629088Smarkm		auth_debug_mode = on;
30729088Smarkm	printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled");
30829088Smarkm	return(1);
30929088Smarkm}
31029088Smarkm
31187139Smarkmint
31287139Smarkmauth_status(void)
31329088Smarkm{
31429088Smarkm	Authenticator *ap;
31529088Smarkm	int i, mask;
31629088Smarkm
31729088Smarkm	if (i_wont_support == -1)
31829088Smarkm		printf("Authentication disabled\n");
31929088Smarkm	else
32029088Smarkm		printf("Authentication enabled\n");
32129088Smarkm
32229088Smarkm	mask = 0;
32329088Smarkm	for (ap = authenticators; ap->type; ap++) {
32429088Smarkm		if ((mask & (i = typemask(ap->type))) != 0)
32529088Smarkm			continue;
32629088Smarkm		mask |= i;
32729088Smarkm		printf("%s: %s\n", AUTHTYPE_NAME(ap->type),
32829088Smarkm			(i_wont_support & typemask(ap->type)) ?
32929088Smarkm					"disabled" : "enabled");
33029088Smarkm	}
33129088Smarkm	return(1);
33229088Smarkm}
33329088Smarkm
33429088Smarkm/*
33529088Smarkm * This routine is called by the server to start authentication
33629088Smarkm * negotiation.
33729088Smarkm */
33887139Smarkmvoid
33987139Smarkmauth_request(void)
34029088Smarkm{
34129088Smarkm	static unsigned char str_request[64] = { IAC, SB,
34229088Smarkm						 TELOPT_AUTHENTICATION,
34329088Smarkm						 TELQUAL_SEND, };
34429088Smarkm	Authenticator *ap = authenticators;
34529088Smarkm	unsigned char *e = str_request + 4;
34629088Smarkm
34729088Smarkm	if (!authenticating) {
34829088Smarkm		authenticating = 1;
34929088Smarkm		while (ap->type) {
35029088Smarkm			if (i_support & ~i_wont_support & typemask(ap->type)) {
35129088Smarkm				if (auth_debug_mode) {
35229088Smarkm					printf(">>>%s: Sending type %d %d\r\n",
35329088Smarkm						Name, ap->type, ap->way);
35429088Smarkm				}
35529088Smarkm				*e++ = ap->type;
35629088Smarkm				*e++ = ap->way;
35729088Smarkm			}
35829088Smarkm			++ap;
35929088Smarkm		}
36029088Smarkm		*e++ = IAC;
36129088Smarkm		*e++ = SE;
36229088Smarkm		net_write(str_request, e - str_request);
36329088Smarkm		printsub('>', &str_request[2], e - str_request - 2);
36429088Smarkm	}
36529088Smarkm}
36629088Smarkm
36729088Smarkm/*
36829088Smarkm * This is called when an AUTH SEND is received.
36929088Smarkm * It should never arrive on the server side (as only the server can
37029088Smarkm * send an AUTH SEND).
37129088Smarkm * You should probably respond to it if you can...
37229088Smarkm *
37329088Smarkm * If you want to respond to the types out of order (i.e. even
37429088Smarkm * if he sends  LOGIN KERBEROS and you support both, you respond
37529088Smarkm * with KERBEROS instead of LOGIN (which is against what the
37629088Smarkm * protocol says)) you will have to hack this code...
37729088Smarkm */
37887139Smarkmvoid
37987139Smarkmauth_send(unsigned char *data, int cnt)
38029088Smarkm{
38129088Smarkm	Authenticator *ap;
38229088Smarkm	static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
38329088Smarkm					    TELQUAL_IS, AUTHTYPE_NULL, 0,
38429088Smarkm					    IAC, SE };
38529088Smarkm	if (Server) {
38629088Smarkm		if (auth_debug_mode) {
38729088Smarkm			printf(">>>%s: auth_send called!\r\n", Name);
38829088Smarkm		}
38929088Smarkm		return;
39029088Smarkm	}
39129088Smarkm
39229088Smarkm	if (auth_debug_mode) {
39329088Smarkm		printf(">>>%s: auth_send got:", Name);
39429088Smarkm		printd(data, cnt); printf("\r\n");
39529088Smarkm	}
39629088Smarkm
39729088Smarkm	/*
39829088Smarkm	 * Save the data, if it is new, so that we can continue looking
39929088Smarkm	 * at it if the authorization we try doesn't work
40029088Smarkm	 */
40129088Smarkm	if (data < _auth_send_data ||
40229088Smarkm	    data > _auth_send_data + sizeof(_auth_send_data)) {
40387139Smarkm		auth_send_cnt = (size_t)cnt > sizeof(_auth_send_data)
40429088Smarkm					? sizeof(_auth_send_data)
40529088Smarkm					: cnt;
40629088Smarkm		memmove((void *)_auth_send_data, (void *)data, auth_send_cnt);
40729088Smarkm		auth_send_data = _auth_send_data;
40829088Smarkm	} else {
40929088Smarkm		/*
41029088Smarkm		 * This is probably a no-op, but we just make sure
41129088Smarkm		 */
41229088Smarkm		auth_send_data = data;
41329088Smarkm		auth_send_cnt = cnt;
41429088Smarkm	}
41529088Smarkm	while ((auth_send_cnt -= 2) >= 0) {
41629088Smarkm		if (auth_debug_mode)
41729088Smarkm			printf(">>>%s: He supports %d\r\n",
41829088Smarkm				Name, *auth_send_data);
41929088Smarkm		if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
42029088Smarkm			ap = findauthenticator(auth_send_data[0],
42129088Smarkm					       auth_send_data[1]);
42229088Smarkm			if (ap && ap->send) {
42329088Smarkm				if (auth_debug_mode)
42429088Smarkm					printf(">>>%s: Trying %d %d\r\n",
42529088Smarkm						Name, auth_send_data[0],
42629088Smarkm							auth_send_data[1]);
42729088Smarkm				if ((*ap->send)(ap)) {
42829088Smarkm					/*
42929088Smarkm					 * Okay, we found one we like
43029088Smarkm					 * and did it.
43129088Smarkm					 * we can go home now.
43229088Smarkm					 */
43329088Smarkm					if (auth_debug_mode)
43429088Smarkm						printf(">>>%s: Using type %d\r\n",
43529088Smarkm							Name, *auth_send_data);
43629088Smarkm					auth_send_data += 2;
43729088Smarkm					return;
43829088Smarkm				}
43929088Smarkm			}
44029088Smarkm			/* else
44129088Smarkm			 *	just continue on and look for the
44229088Smarkm			 *	next one if we didn't do anything.
44329088Smarkm			 */
44429088Smarkm		}
44529088Smarkm		auth_send_data += 2;
44629088Smarkm	}
44729088Smarkm	net_write(str_none, sizeof(str_none));
44829088Smarkm	printsub('>', &str_none[2], sizeof(str_none) - 2);
44929088Smarkm	if (auth_debug_mode)
45029088Smarkm		printf(">>>%s: Sent failure message\r\n", Name);
45129088Smarkm	auth_finished(0, AUTH_REJECT);
45229088Smarkm}
45329088Smarkm
45487139Smarkmvoid
45587139Smarkmauth_send_retry(void)
45629088Smarkm{
45729088Smarkm	/*
45829088Smarkm	 * if auth_send_cnt <= 0 then auth_send will end up rejecting
45929088Smarkm	 * the authentication and informing the other side of this.
46029088Smarkm	 */
46129088Smarkm	auth_send(auth_send_data, auth_send_cnt);
46229088Smarkm}
46329088Smarkm
46487139Smarkmvoid
46587139Smarkmauth_is(unsigned char *data, int cnt)
46629088Smarkm{
46729088Smarkm	Authenticator *ap;
46829088Smarkm
46929088Smarkm	if (cnt < 2)
47029088Smarkm		return;
47129088Smarkm
47229088Smarkm	if (data[0] == AUTHTYPE_NULL) {
47329088Smarkm		auth_finished(0, AUTH_REJECT);
47429088Smarkm		return;
47529088Smarkm	}
47629088Smarkm
47729181Smarkm	if ((ap = findauthenticator(data[0], data[1]))) {
47829088Smarkm		if (ap->is)
47929088Smarkm			(*ap->is)(ap, data+2, cnt-2);
48029088Smarkm	} else if (auth_debug_mode)
48129088Smarkm		printf(">>>%s: Invalid authentication in IS: %d\r\n",
48229088Smarkm			Name, *data);
48329088Smarkm}
48429088Smarkm
48587139Smarkmvoid
48687139Smarkmauth_reply(unsigned char *data, int cnt)
48729088Smarkm{
48829088Smarkm	Authenticator *ap;
48929088Smarkm
49029088Smarkm	if (cnt < 2)
49129088Smarkm		return;
49229088Smarkm
49329181Smarkm	if ((ap = findauthenticator(data[0], data[1]))) {
49429088Smarkm		if (ap->reply)
49529088Smarkm			(*ap->reply)(ap, data+2, cnt-2);
49629088Smarkm	} else if (auth_debug_mode)
49729088Smarkm		printf(">>>%s: Invalid authentication in SEND: %d\r\n",
49829088Smarkm			Name, *data);
49929088Smarkm}
50029088Smarkm
50187139Smarkmvoid
50287139Smarkmauth_name(unsigned char *data, int cnt)
50329088Smarkm{
50429088Smarkm	unsigned char savename[256];
50529088Smarkm
50629088Smarkm	if (cnt < 1) {
50729088Smarkm		if (auth_debug_mode)
50829088Smarkm			printf(">>>%s: Empty name in NAME\r\n", Name);
50929088Smarkm		return;
51029088Smarkm	}
51187139Smarkm	if ((size_t)cnt > sizeof(savename) - 1) {
51229088Smarkm		if (auth_debug_mode)
51329088Smarkm			printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n",
51487266Smarkm					Name, cnt, (u_int)sizeof(savename)-1);
51529088Smarkm		return;
51629088Smarkm	}
51729088Smarkm	memmove((void *)savename, (void *)data, cnt);
51829088Smarkm	savename[cnt] = '\0';	/* Null terminate */
51929088Smarkm	if (auth_debug_mode)
52029088Smarkm		printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
52129088Smarkm	auth_encrypt_user(savename);
52229088Smarkm}
52329088Smarkm
52487139Smarkmint
52587139Smarkmauth_sendname(unsigned char *cp, int len)
52629088Smarkm{
52729088Smarkm	static unsigned char str_request[256+6]
52829088Smarkm			= { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, };
52987139Smarkm	unsigned char *e = str_request + 4;
53087139Smarkm	unsigned char *ee = &str_request[sizeof(str_request)-2];
53129088Smarkm
53229088Smarkm	while (--len >= 0) {
53329088Smarkm		if ((*e++ = *cp++) == IAC)
53429088Smarkm			*e++ = IAC;
53529088Smarkm		if (e >= ee)
53629088Smarkm			return(0);
53729088Smarkm	}
53829088Smarkm	*e++ = IAC;
53929088Smarkm	*e++ = SE;
54029088Smarkm	net_write(str_request, e - str_request);
54129088Smarkm	printsub('>', &str_request[2], e - &str_request[2]);
54229088Smarkm	return(1);
54329088Smarkm}
54429088Smarkm
54587139Smarkmvoid
54687139Smarkmauth_finished(Authenticator *ap, int result)
54729088Smarkm{
54829088Smarkm	if (!(authenticated = ap))
54929088Smarkm		authenticated = &NoAuth;
55029088Smarkm	validuser = result;
55129088Smarkm}
55229088Smarkm
55387139Smarkm/* ARGSUSED */
55487139Smarkmstatic void
55587139Smarkmauth_intr(int sig __unused)
55629088Smarkm{
55729088Smarkm	auth_finished(0, AUTH_REJECT);
55829088Smarkm}
55929088Smarkm
56087139Smarkmint
56187139Smarkmauth_wait(char *name)
56229088Smarkm{
56329088Smarkm	if (auth_debug_mode)
56429088Smarkm		printf(">>>%s: in auth_wait.\r\n", Name);
56529088Smarkm
56629088Smarkm	if (Server && !authenticating)
56729088Smarkm		return(0);
56829088Smarkm
56929088Smarkm	(void) signal(SIGALRM, auth_intr);
57029088Smarkm	alarm(30);
57129088Smarkm	while (!authenticated)
57229088Smarkm		if (telnet_spin())
57329088Smarkm			break;
57429088Smarkm	alarm(0);
57529088Smarkm	(void) signal(SIGALRM, SIG_DFL);
57629088Smarkm
57729088Smarkm	/*
57829088Smarkm	 * Now check to see if the user is valid or not
57929088Smarkm	 */
58029088Smarkm	if (!authenticated || authenticated == &NoAuth)
58129088Smarkm		return(AUTH_REJECT);
58229088Smarkm
58329088Smarkm	if (validuser == AUTH_VALID)
58429088Smarkm		validuser = AUTH_USER;
58529088Smarkm
58629088Smarkm	if (authenticated->status)
58729088Smarkm		validuser = (*authenticated->status)(authenticated,
58829088Smarkm						     name, validuser);
58929088Smarkm	return(validuser);
59029088Smarkm}
59129088Smarkm
59287139Smarkmvoid
59387139Smarkmauth_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
59429088Smarkm{
59529088Smarkm	Authenticator *ap;
59629088Smarkm
59729088Smarkm	if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
59829088Smarkm		(*ap->printsub)(data, cnt, buf, buflen);
59929088Smarkm	else
60029088Smarkm		auth_gen_printsub(data, cnt, buf, buflen);
60129088Smarkm}
60229088Smarkm
60387139Smarkmvoid
60487139Smarkmauth_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
60529088Smarkm{
60687139Smarkm	unsigned char *cp;
60729088Smarkm	unsigned char tbuf[16];
60829088Smarkm
60929088Smarkm	cnt -= 3;
61029088Smarkm	data += 3;
61129088Smarkm	buf[buflen-1] = '\0';
61229088Smarkm	buf[buflen-2] = '*';
61329088Smarkm	buflen -= 2;
61429088Smarkm	for (; cnt > 0; cnt--, data++) {
61529088Smarkm		sprintf((char *)tbuf, " %d", *data);
61629088Smarkm		for (cp = tbuf; *cp && buflen > 0; --buflen)
61729088Smarkm			*buf++ = *cp++;
61829088Smarkm		if (buflen <= 0)
61929088Smarkm			return;
62029088Smarkm	}
62129088Smarkm	*buf = '\0';
62229088Smarkm}
62329088Smarkm#endif
624