157416Smarkm/*-
257416Smarkm * Copyright (c) 1991, 1993
357416Smarkm *	The Regents of the University of California.  All rights reserved.
457416Smarkm *
557416Smarkm * Redistribution and use in source and binary forms, with or without
657416Smarkm * modification, are permitted provided that the following conditions
757416Smarkm * are met:
857416Smarkm * 1. Redistributions of source code must retain the above copyright
957416Smarkm *    notice, this list of conditions and the following disclaimer.
1057416Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1157416Smarkm *    notice, this list of conditions and the following disclaimer in the
1257416Smarkm *    documentation and/or other materials provided with the distribution.
1357416Smarkm * 3. All advertising materials mentioning features or use of this software
1457416Smarkm *    must display the following acknowledgement:
1557416Smarkm *	This product includes software developed by the University of
1657416Smarkm *	California, Berkeley and its contributors.
1757416Smarkm * 4. Neither the name of the University nor the names of its contributors
1857416Smarkm *    may be used to endorse or promote products derived from this software
1957416Smarkm *    without specific prior written permission.
2057416Smarkm *
2157416Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2257416Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2357416Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2457416Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2557416Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2657416Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2757416Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2857416Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2957416Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3057416Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3157416Smarkm * SUCH DAMAGE.
3257416Smarkm */
3357416Smarkm
3457416Smarkm/*
3557416Smarkm * Copyright (C) 1990 by the Massachusetts Institute of Technology
3657416Smarkm *
3757416Smarkm * Export of this software from the United States of America is assumed
3857416Smarkm * to require a specific license from the United States Government.
3957416Smarkm * It is the responsibility of any person or organization contemplating
4057416Smarkm * export to obtain such a license before exporting.
4157416Smarkm *
4257416Smarkm * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
4357416Smarkm * distribute this software and its documentation for any purpose and
4457416Smarkm * without fee is hereby granted, provided that the above copyright
4557416Smarkm * notice appear in all copies and that both that copyright notice and
4657416Smarkm * this permission notice appear in supporting documentation, and that
4757416Smarkm * the name of M.I.T. not be used in advertising or publicity pertaining
4857416Smarkm * to distribution of the software without specific, written prior
4957416Smarkm * permission.  M.I.T. makes no representations about the suitability of
5057416Smarkm * this software for any purpose.  It is provided "as is" without express
5157416Smarkm * or implied warranty.
5257416Smarkm */
5357416Smarkm
5457416Smarkm#include <config.h>
5557416Smarkm
56233294SstasRCSID("$Id$");
5757416Smarkm
5857416Smarkm#if	defined(AUTHENTICATION)
5957416Smarkm#include <stdio.h>
6057416Smarkm#ifdef HAVE_SYS_TYPES_H
6157416Smarkm#include <sys/types.h>
6257416Smarkm#endif
6357416Smarkm#include <signal.h>
6457416Smarkm#define	AUTH_NAMES
6557416Smarkm#ifdef HAVE_ARPA_TELNET_H
6657416Smarkm#include <arpa/telnet.h>
6757416Smarkm#endif
6857416Smarkm#include <stdlib.h>
6957416Smarkm#include <string.h>
7057416Smarkm
7157416Smarkm#include <roken.h>
7257416Smarkm
7357416Smarkm#ifdef SOCKS
7457416Smarkm#include <socks.h>
7557416Smarkm#endif
7657416Smarkm
7757416Smarkm#include "encrypt.h"
7857416Smarkm#include "auth.h"
7957416Smarkm#include "misc-proto.h"
8057416Smarkm#include "auth-proto.h"
8157416Smarkm
8257416Smarkm#define	typemask(x)		(1<<((x)-1))
8357416Smarkm
8457416Smarkm#ifdef	RSA_ENCPWD
8557416Smarkmextern rsaencpwd_init();
8657416Smarkmextern rsaencpwd_send();
8757416Smarkmextern rsaencpwd_is();
8857416Smarkmextern rsaencpwd_reply();
8957416Smarkmextern rsaencpwd_status();
9057416Smarkmextern rsaencpwd_printsub();
9157416Smarkm#endif
9257416Smarkm
9357416Smarkmint auth_debug_mode = 0;
9490926Snectarint auth_has_failed  = 0;
9590926Snectarint auth_enable_encrypt = 0;
9657416Smarkmstatic 	const	char	*Name = "Noname";
9757416Smarkmstatic	int	Server = 0;
9857416Smarkmstatic	Authenticator	*authenticated = 0;
9957416Smarkmstatic	int	authenticating = 0;
10057416Smarkmstatic	int	validuser = 0;
10157416Smarkmstatic	unsigned char	_auth_send_data[256];
10257416Smarkmstatic	unsigned char	*auth_send_data;
10357416Smarkmstatic	int	auth_send_cnt = 0;
10457416Smarkm
10557416Smarkm/*
10657416Smarkm * Authentication types supported.  Plese note that these are stored
10757416Smarkm * in priority order, i.e. try the first one first.
10857416Smarkm */
10957416SmarkmAuthenticator authenticators[] = {
11057416Smarkm#ifdef UNSAFE
11157416Smarkm    { AUTHTYPE_UNSAFE, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
11257416Smarkm      unsafe_init,
11357416Smarkm      unsafe_send,
11457416Smarkm      unsafe_is,
11557416Smarkm      unsafe_reply,
11657416Smarkm      unsafe_status,
11757416Smarkm      unsafe_printsub },
11857416Smarkm#endif
11957416Smarkm#ifdef SRA
12057416Smarkm    { AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
12157416Smarkm      sra_init,
12257416Smarkm      sra_send,
12357416Smarkm      sra_is,
12457416Smarkm      sra_reply,
12557416Smarkm      sra_status,
12657416Smarkm      sra_printsub },
12757416Smarkm#endif
12857416Smarkm#ifdef	SPX
12957416Smarkm    { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
13057416Smarkm      spx_init,
13157416Smarkm      spx_send,
13257416Smarkm      spx_is,
13357416Smarkm      spx_reply,
13457416Smarkm      spx_status,
13557416Smarkm      spx_printsub },
13657416Smarkm    { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
13757416Smarkm      spx_init,
13857416Smarkm      spx_send,
13957416Smarkm      spx_is,
14057416Smarkm      spx_reply,
14157416Smarkm      spx_status,
14257416Smarkm      spx_printsub },
14357416Smarkm#endif
14457416Smarkm#ifdef	KRB5
14557416Smarkm    { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
14657416Smarkm      kerberos5_init,
14757416Smarkm      kerberos5_send_mutual,
14857416Smarkm      kerberos5_is,
14957416Smarkm      kerberos5_reply,
15057416Smarkm      kerberos5_status,
15157416Smarkm      kerberos5_printsub },
15257416Smarkm    { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
15357416Smarkm      kerberos5_init,
15457416Smarkm      kerberos5_send_oneway,
15557416Smarkm      kerberos5_is,
15657416Smarkm      kerberos5_reply,
15757416Smarkm      kerberos5_status,
15857416Smarkm      kerberos5_printsub },
15957416Smarkm#endif
16057416Smarkm#ifdef	RSA_ENCPWD
16157416Smarkm    { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
16257416Smarkm      rsaencpwd_init,
16357416Smarkm      rsaencpwd_send,
16457416Smarkm      rsaencpwd_is,
16557416Smarkm      rsaencpwd_reply,
16657416Smarkm      rsaencpwd_status,
16757416Smarkm      rsaencpwd_printsub },
16857416Smarkm#endif
16957416Smarkm    { 0, },
17057416Smarkm};
17157416Smarkm
17257416Smarkmstatic Authenticator NoAuth = { 0 };
17357416Smarkm
17457416Smarkmstatic int	i_support = 0;
17557416Smarkmstatic int	i_wont_support = 0;
17657416Smarkm
17757416SmarkmAuthenticator *
17857416Smarkmfindauthenticator(int type, int way)
17957416Smarkm{
18057416Smarkm    Authenticator *ap = authenticators;
18157416Smarkm
18257416Smarkm    while (ap->type && (ap->type != type || ap->way != way))
18357416Smarkm	++ap;
18457416Smarkm    return(ap->type ? ap : 0);
18557416Smarkm}
18657416Smarkm
18757416Smarkmvoid
18857416Smarkmauth_init(const char *name, int server)
18957416Smarkm{
19057416Smarkm    Authenticator *ap = authenticators;
19157416Smarkm
19257416Smarkm    Server = server;
19357416Smarkm    Name = name;
19457416Smarkm
19557416Smarkm    i_support = 0;
19657416Smarkm    authenticated = 0;
19757416Smarkm    authenticating = 0;
19857416Smarkm    while (ap->type) {
19957416Smarkm	if (!ap->init || (*ap->init)(ap, server)) {
20057416Smarkm	    i_support |= typemask(ap->type);
20157416Smarkm	    if (auth_debug_mode)
20257416Smarkm		printf(">>>%s: I support auth type %d %d\r\n",
20357416Smarkm		       Name,
20457416Smarkm		       ap->type, ap->way);
20557416Smarkm	}
20657416Smarkm	else if (auth_debug_mode)
20757416Smarkm	    printf(">>>%s: Init failed: auth type %d %d\r\n",
20857416Smarkm		   Name, ap->type, ap->way);
20957416Smarkm	++ap;
21057416Smarkm    }
21157416Smarkm}
21257416Smarkm
21357416Smarkmvoid
21457416Smarkmauth_disable_name(char *name)
21557416Smarkm{
21657416Smarkm    int x;
21757416Smarkm    for (x = 0; x < AUTHTYPE_CNT; ++x) {
21857416Smarkm	if (!strcasecmp(name, AUTHTYPE_NAME(x))) {
21957416Smarkm	    i_wont_support |= typemask(x);
22057416Smarkm	    break;
22157416Smarkm	}
22257416Smarkm    }
22357416Smarkm}
22457416Smarkm
22557416Smarkmint
22657416Smarkmgetauthmask(char *type, int *maskp)
22757416Smarkm{
22857416Smarkm    int x;
22957416Smarkm
23057416Smarkm    if (!strcasecmp(type, AUTHTYPE_NAME(0))) {
23157416Smarkm	*maskp = -1;
23257416Smarkm	return(1);
23357416Smarkm    }
23457416Smarkm
23557416Smarkm    for (x = 1; x < AUTHTYPE_CNT; ++x) {
23657416Smarkm	if (!strcasecmp(type, AUTHTYPE_NAME(x))) {
23757416Smarkm	    *maskp = typemask(x);
23857416Smarkm	    return(1);
23957416Smarkm	}
24057416Smarkm    }
24157416Smarkm    return(0);
24257416Smarkm}
24357416Smarkm
24457416Smarkmint
24557416Smarkmauth_enable(char *type)
24657416Smarkm{
24757416Smarkm    return(auth_onoff(type, 1));
24857416Smarkm}
24957416Smarkm
25057416Smarkmint
25157416Smarkmauth_disable(char *type)
25257416Smarkm{
25357416Smarkm    return(auth_onoff(type, 0));
25457416Smarkm}
25557416Smarkm
25657416Smarkmint
25757416Smarkmauth_onoff(char *type, int on)
25857416Smarkm{
25957416Smarkm    int i, mask = -1;
26057416Smarkm    Authenticator *ap;
26157416Smarkm
26257416Smarkm    if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) {
26357416Smarkm	printf("auth %s 'type'\n", on ? "enable" : "disable");
26457416Smarkm	printf("Where 'type' is one of:\n");
26557416Smarkm	printf("\t%s\n", AUTHTYPE_NAME(0));
26657416Smarkm	mask = 0;
26757416Smarkm	for (ap = authenticators; ap->type; ap++) {
26857416Smarkm	    if ((mask & (i = typemask(ap->type))) != 0)
26957416Smarkm		continue;
27057416Smarkm	    mask |= i;
27157416Smarkm	    printf("\t%s\n", AUTHTYPE_NAME(ap->type));
27257416Smarkm	}
27357416Smarkm	return(0);
27457416Smarkm    }
27557416Smarkm
27657416Smarkm    if (!getauthmask(type, &mask)) {
27757416Smarkm	printf("%s: invalid authentication type\n", type);
27857416Smarkm	return(0);
27957416Smarkm    }
28057416Smarkm    if (on)
28157416Smarkm	i_wont_support &= ~mask;
28257416Smarkm    else
28357416Smarkm	i_wont_support |= mask;
28457416Smarkm    return(1);
28557416Smarkm}
28657416Smarkm
28757416Smarkmint
28857416Smarkmauth_togdebug(int on)
28957416Smarkm{
29057416Smarkm    if (on < 0)
29157416Smarkm	auth_debug_mode ^= 1;
29257416Smarkm    else
29357416Smarkm	auth_debug_mode = on;
29457416Smarkm    printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled");
29557416Smarkm    return(1);
29657416Smarkm}
29757416Smarkm
29857416Smarkmint
29957416Smarkmauth_status(void)
30057416Smarkm{
30157416Smarkm    Authenticator *ap;
30257416Smarkm    int i, mask;
30357416Smarkm
30457416Smarkm    if (i_wont_support == -1)
30557416Smarkm	printf("Authentication disabled\n");
30657416Smarkm    else
30757416Smarkm	printf("Authentication enabled\n");
30857416Smarkm
30957416Smarkm    mask = 0;
31057416Smarkm    for (ap = authenticators; ap->type; ap++) {
31157416Smarkm	if ((mask & (i = typemask(ap->type))) != 0)
31257416Smarkm	    continue;
31357416Smarkm	mask |= i;
31457416Smarkm	printf("%s: %s\n", AUTHTYPE_NAME(ap->type),
31557416Smarkm	       (i_wont_support & typemask(ap->type)) ?
31657416Smarkm	       "disabled" : "enabled");
31757416Smarkm    }
31857416Smarkm    return(1);
31957416Smarkm}
32057416Smarkm
32157416Smarkm/*
32257416Smarkm * This routine is called by the server to start authentication
32357416Smarkm * negotiation.
32457416Smarkm */
32557416Smarkmvoid
32657416Smarkmauth_request(void)
32757416Smarkm{
32857416Smarkm    static unsigned char str_request[64] = { IAC, SB,
32957416Smarkm					     TELOPT_AUTHENTICATION,
33057416Smarkm					     TELQUAL_SEND, };
33157416Smarkm    Authenticator *ap = authenticators;
33257416Smarkm    unsigned char *e = str_request + 4;
33357416Smarkm
33457416Smarkm    if (!authenticating) {
33557416Smarkm	authenticating = 1;
33657416Smarkm	while (ap->type) {
33757416Smarkm	    if (i_support & ~i_wont_support & typemask(ap->type)) {
33857416Smarkm		if (auth_debug_mode) {
33957416Smarkm		    printf(">>>%s: Sending type %d %d\r\n",
34057416Smarkm			   Name, ap->type, ap->way);
34157416Smarkm		}
34257416Smarkm		*e++ = ap->type;
34357416Smarkm		*e++ = ap->way;
34457416Smarkm	    }
34557416Smarkm	    ++ap;
34657416Smarkm	}
34757416Smarkm	*e++ = IAC;
34857416Smarkm	*e++ = SE;
34957416Smarkm	telnet_net_write(str_request, e - str_request);
35057416Smarkm	printsub('>', &str_request[2], e - str_request - 2);
35157416Smarkm    }
35257416Smarkm}
35357416Smarkm
35457416Smarkm/*
35557416Smarkm * This is called when an AUTH SEND is received.
35657416Smarkm * It should never arrive on the server side (as only the server can
35757416Smarkm * send an AUTH SEND).
35857416Smarkm * You should probably respond to it if you can...
35957416Smarkm *
36057416Smarkm * If you want to respond to the types out of order (i.e. even
36157416Smarkm * if he sends  LOGIN KERBEROS and you support both, you respond
36257416Smarkm * with KERBEROS instead of LOGIN (which is against what the
36357416Smarkm * protocol says)) you will have to hack this code...
36457416Smarkm */
36557416Smarkmvoid
36657416Smarkmauth_send(unsigned char *data, int cnt)
36757416Smarkm{
36857416Smarkm    Authenticator *ap;
36957416Smarkm    static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
37057416Smarkm					TELQUAL_IS, AUTHTYPE_NULL, 0,
37157416Smarkm					IAC, SE };
37257416Smarkm    if (Server) {
37357416Smarkm	if (auth_debug_mode) {
37457416Smarkm	    printf(">>>%s: auth_send called!\r\n", Name);
37557416Smarkm	}
37657416Smarkm	return;
37757416Smarkm    }
37857416Smarkm
37957416Smarkm    if (auth_debug_mode) {
38057416Smarkm	printf(">>>%s: auth_send got:", Name);
38157416Smarkm	printd(data, cnt); printf("\r\n");
38257416Smarkm    }
38357416Smarkm
38457416Smarkm    /*
38557416Smarkm     * Save the data, if it is new, so that we can continue looking
38657416Smarkm     * at it if the authorization we try doesn't work
38757416Smarkm     */
38857416Smarkm    if (data < _auth_send_data ||
38957416Smarkm	data > _auth_send_data + sizeof(_auth_send_data)) {
39057416Smarkm	auth_send_cnt = cnt > sizeof(_auth_send_data)
39157416Smarkm	    ? sizeof(_auth_send_data)
39257416Smarkm	    : cnt;
39357416Smarkm	memmove(_auth_send_data, data, auth_send_cnt);
39457416Smarkm	auth_send_data = _auth_send_data;
39557416Smarkm    } else {
39657416Smarkm	/*
39757416Smarkm	 * This is probably a no-op, but we just make sure
39857416Smarkm	 */
39957416Smarkm	auth_send_data = data;
40057416Smarkm	auth_send_cnt = cnt;
40157416Smarkm    }
40257416Smarkm    while ((auth_send_cnt -= 2) >= 0) {
40357416Smarkm	if (auth_debug_mode)
40457416Smarkm	    printf(">>>%s: He supports %d\r\n",
40557416Smarkm		   Name, *auth_send_data);
40657416Smarkm	if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
40757416Smarkm	    ap = findauthenticator(auth_send_data[0],
40857416Smarkm				   auth_send_data[1]);
40957416Smarkm	    if (ap && ap->send) {
41057416Smarkm		if (auth_debug_mode)
41157416Smarkm		    printf(">>>%s: Trying %d %d\r\n",
41257416Smarkm			   Name, auth_send_data[0],
41357416Smarkm			   auth_send_data[1]);
41457416Smarkm		if ((*ap->send)(ap)) {
41557416Smarkm		    /*
41657416Smarkm		     * Okay, we found one we like
41757416Smarkm		     * and did it.
41857416Smarkm		     * we can go home now.
41957416Smarkm		     */
42057416Smarkm		    if (auth_debug_mode)
42157416Smarkm			printf(">>>%s: Using type %d\r\n",
42257416Smarkm			       Name, *auth_send_data);
42357416Smarkm		    auth_send_data += 2;
42457416Smarkm		    return;
42557416Smarkm		}
42657416Smarkm	    }
42757416Smarkm	    /* else
42857416Smarkm	     *	just continue on and look for the
42957416Smarkm	     *	next one if we didn't do anything.
43057416Smarkm	     */
43157416Smarkm	}
43257416Smarkm	auth_send_data += 2;
43357416Smarkm    }
43457416Smarkm    telnet_net_write(str_none, sizeof(str_none));
43557416Smarkm    printsub('>', &str_none[2], sizeof(str_none) - 2);
43657416Smarkm    if (auth_debug_mode)
43757416Smarkm	printf(">>>%s: Sent failure message\r\n", Name);
43857416Smarkm    auth_finished(0, AUTH_REJECT);
43990926Snectar    auth_has_failed = 1;
44057416Smarkm#ifdef KANNAN
44157416Smarkm    /*
44257416Smarkm     *  We requested strong authentication, however no mechanisms worked.
44357416Smarkm     *  Therefore, exit on client end.
44457416Smarkm     */
44557416Smarkm    printf("Unable to securely authenticate user ... exit\n");
44657416Smarkm    exit(0);
44757416Smarkm#endif /* KANNAN */
44857416Smarkm}
44957416Smarkm
45057416Smarkmvoid
45157416Smarkmauth_send_retry(void)
45257416Smarkm{
45357416Smarkm    /*
45457416Smarkm     * if auth_send_cnt <= 0 then auth_send will end up rejecting
45557416Smarkm     * the authentication and informing the other side of this.
45657416Smarkm	 */
45757416Smarkm    auth_send(auth_send_data, auth_send_cnt);
45857416Smarkm}
45957416Smarkm
46057416Smarkmvoid
46157416Smarkmauth_is(unsigned char *data, int cnt)
46257416Smarkm{
46357416Smarkm    Authenticator *ap;
46457416Smarkm
46557416Smarkm    if (cnt < 2)
46657416Smarkm	return;
46757416Smarkm
46857416Smarkm    if (data[0] == AUTHTYPE_NULL) {
46957416Smarkm	auth_finished(0, AUTH_REJECT);
47057416Smarkm	return;
47157416Smarkm    }
47257416Smarkm
47357416Smarkm    if ((ap = findauthenticator(data[0], data[1]))) {
47457416Smarkm	if (ap->is)
47557416Smarkm	    (*ap->is)(ap, data+2, cnt-2);
47657416Smarkm    } else if (auth_debug_mode)
47757416Smarkm	printf(">>>%s: Invalid authentication in IS: %d\r\n",
47857416Smarkm	       Name, *data);
47957416Smarkm}
48057416Smarkm
48157416Smarkmvoid
48257416Smarkmauth_reply(unsigned char *data, int cnt)
48357416Smarkm{
48457416Smarkm    Authenticator *ap;
48557416Smarkm
48657416Smarkm    if (cnt < 2)
48757416Smarkm	return;
48857416Smarkm
48957416Smarkm    if ((ap = findauthenticator(data[0], data[1]))) {
49057416Smarkm	if (ap->reply)
49157416Smarkm	    (*ap->reply)(ap, data+2, cnt-2);
49257416Smarkm    } else if (auth_debug_mode)
49357416Smarkm	printf(">>>%s: Invalid authentication in SEND: %d\r\n",
49457416Smarkm	       Name, *data);
49557416Smarkm}
49657416Smarkm
49757416Smarkmvoid
49857416Smarkmauth_name(unsigned char *data, int cnt)
49957416Smarkm{
50057416Smarkm    char savename[256];
50157416Smarkm
50257416Smarkm    if (cnt < 1) {
50357416Smarkm	if (auth_debug_mode)
50457416Smarkm	    printf(">>>%s: Empty name in NAME\r\n", Name);
50557416Smarkm	return;
50657416Smarkm    }
50757416Smarkm    if (cnt > sizeof(savename) - 1) {
50857416Smarkm	if (auth_debug_mode)
50957416Smarkm	    printf(">>>%s: Name in NAME (%d) exceeds %lu length\r\n",
51057416Smarkm		   Name, cnt, (unsigned long)(sizeof(savename)-1));
51157416Smarkm	return;
51257416Smarkm    }
51357416Smarkm    memmove(savename, data, cnt);
51457416Smarkm    savename[cnt] = '\0';	/* Null terminate */
51557416Smarkm    if (auth_debug_mode)
51657416Smarkm	printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
51757416Smarkm    auth_encrypt_user(savename);
51857416Smarkm}
51957416Smarkm
52057416Smarkmint
52157416Smarkmauth_sendname(unsigned char *cp, int len)
52257416Smarkm{
52357416Smarkm    static unsigned char str_request[256+6]
52457416Smarkm	= { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, };
52557416Smarkm    unsigned char *e = str_request + 4;
52657416Smarkm    unsigned char *ee = &str_request[sizeof(str_request)-2];
52757416Smarkm
52857416Smarkm    while (--len >= 0) {
52957416Smarkm	if ((*e++ = *cp++) == IAC)
53057416Smarkm	    *e++ = IAC;
53157416Smarkm	if (e >= ee)
53257416Smarkm	    return(0);
53357416Smarkm    }
53457416Smarkm    *e++ = IAC;
53557416Smarkm    *e++ = SE;
53657416Smarkm    telnet_net_write(str_request, e - str_request);
53757416Smarkm    printsub('>', &str_request[2], e - &str_request[2]);
53857416Smarkm    return(1);
53957416Smarkm}
54057416Smarkm
54157416Smarkmvoid
54257416Smarkmauth_finished(Authenticator *ap, int result)
54357416Smarkm{
54457416Smarkm    if (!(authenticated = ap))
54557416Smarkm	authenticated = &NoAuth;
54657416Smarkm    validuser = result;
54757416Smarkm}
54857416Smarkm
54957416Smarkm/* ARGSUSED */
55057416Smarkmstatic void
55157416Smarkmauth_intr(int sig)
55257416Smarkm{
55357416Smarkm    auth_finished(0, AUTH_REJECT);
55457416Smarkm}
55557416Smarkm
55657416Smarkmint
55757416Smarkmauth_wait(char *name, size_t name_sz)
55857416Smarkm{
55957416Smarkm    if (auth_debug_mode)
56057416Smarkm	printf(">>>%s: in auth_wait.\r\n", Name);
56157416Smarkm
56257416Smarkm    if (Server && !authenticating)
56357416Smarkm	return(0);
56457416Smarkm
56557416Smarkm    signal(SIGALRM, auth_intr);
56657416Smarkm    alarm(30);
56757416Smarkm    while (!authenticated)
56857416Smarkm	if (telnet_spin())
56957416Smarkm	    break;
57057416Smarkm    alarm(0);
57157416Smarkm    signal(SIGALRM, SIG_DFL);
57257416Smarkm
57357416Smarkm    /*
57457416Smarkm     * Now check to see if the user is valid or not
57557416Smarkm     */
57657416Smarkm    if (!authenticated || authenticated == &NoAuth)
57757416Smarkm	return(AUTH_REJECT);
57857416Smarkm
57957416Smarkm    if (validuser == AUTH_VALID)
58057416Smarkm	validuser = AUTH_USER;
58157416Smarkm
58257416Smarkm    if (authenticated->status)
58357416Smarkm	validuser = (*authenticated->status)(authenticated,
58457416Smarkm					     name, name_sz,
58557416Smarkm					     validuser);
58657416Smarkm    return(validuser);
58757416Smarkm}
58857416Smarkm
58957416Smarkmvoid
59057416Smarkmauth_debug(int mode)
59157416Smarkm{
59257416Smarkm    auth_debug_mode = mode;
59357416Smarkm}
59457416Smarkm
59557416Smarkmvoid
596233294Sstasauth_printsub(unsigned char *data, size_t cnt,
597233294Sstas	      unsigned char *buf, size_t buflen)
59857416Smarkm{
59957416Smarkm    Authenticator *ap;
60057416Smarkm
60157416Smarkm    if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
60257416Smarkm	(*ap->printsub)(data, cnt, buf, buflen);
60357416Smarkm    else
60457416Smarkm	auth_gen_printsub(data, cnt, buf, buflen);
60557416Smarkm}
60657416Smarkm
60757416Smarkmvoid
608233294Sstasauth_gen_printsub(unsigned char *data, size_t cnt,
609233294Sstas		  unsigned char *buf, size_t buflen)
61057416Smarkm{
61157416Smarkm    unsigned char *cp;
61257416Smarkm    unsigned char tbuf[16];
61357416Smarkm
61457416Smarkm    cnt -= 3;
61557416Smarkm    data += 3;
61657416Smarkm    buf[buflen-1] = '\0';
61757416Smarkm    buf[buflen-2] = '*';
61857416Smarkm    buflen -= 2;
61957416Smarkm    for (; cnt > 0; cnt--, data++) {
62090926Snectar	snprintf((char*)tbuf, sizeof(tbuf), " %d", *data);
62157416Smarkm	for (cp = tbuf; *cp && buflen > 0; --buflen)
62257416Smarkm	    *buf++ = *cp++;
62357416Smarkm	if (buflen <= 0)
62457416Smarkm	    return;
62557416Smarkm    }
62657416Smarkm    *buf = '\0';
62757416Smarkm}
62857416Smarkm#endif
629