xref: /freebsd/crypto/heimdal/appl/telnet/libtelnet/auth.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
113e3f4d6SMark Murray /*-
213e3f4d6SMark Murray  * Copyright (c) 1991, 1993
313e3f4d6SMark Murray  *	The Regents of the University of California.  All rights reserved.
413e3f4d6SMark Murray  *
513e3f4d6SMark Murray  * Redistribution and use in source and binary forms, with or without
613e3f4d6SMark Murray  * modification, are permitted provided that the following conditions
713e3f4d6SMark Murray  * are met:
813e3f4d6SMark Murray  * 1. Redistributions of source code must retain the above copyright
913e3f4d6SMark Murray  *    notice, this list of conditions and the following disclaimer.
1013e3f4d6SMark Murray  * 2. Redistributions in binary form must reproduce the above copyright
1113e3f4d6SMark Murray  *    notice, this list of conditions and the following disclaimer in the
1213e3f4d6SMark Murray  *    documentation and/or other materials provided with the distribution.
1313e3f4d6SMark Murray  * 3. All advertising materials mentioning features or use of this software
1413e3f4d6SMark Murray  *    must display the following acknowledgement:
1513e3f4d6SMark Murray  *	This product includes software developed by the University of
1613e3f4d6SMark Murray  *	California, Berkeley and its contributors.
1713e3f4d6SMark Murray  * 4. Neither the name of the University nor the names of its contributors
1813e3f4d6SMark Murray  *    may be used to endorse or promote products derived from this software
1913e3f4d6SMark Murray  *    without specific prior written permission.
2013e3f4d6SMark Murray  *
2113e3f4d6SMark Murray  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2213e3f4d6SMark Murray  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2313e3f4d6SMark Murray  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2413e3f4d6SMark Murray  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2513e3f4d6SMark Murray  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2613e3f4d6SMark Murray  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2713e3f4d6SMark Murray  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2813e3f4d6SMark Murray  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2913e3f4d6SMark Murray  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3013e3f4d6SMark Murray  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3113e3f4d6SMark Murray  * SUCH DAMAGE.
3213e3f4d6SMark Murray  */
3313e3f4d6SMark Murray 
3413e3f4d6SMark Murray /*
3513e3f4d6SMark Murray  * Copyright (C) 1990 by the Massachusetts Institute of Technology
3613e3f4d6SMark Murray  *
3713e3f4d6SMark Murray  * Export of this software from the United States of America is assumed
3813e3f4d6SMark Murray  * to require a specific license from the United States Government.
3913e3f4d6SMark Murray  * It is the responsibility of any person or organization contemplating
4013e3f4d6SMark Murray  * export to obtain such a license before exporting.
4113e3f4d6SMark Murray  *
4213e3f4d6SMark Murray  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
4313e3f4d6SMark Murray  * distribute this software and its documentation for any purpose and
4413e3f4d6SMark Murray  * without fee is hereby granted, provided that the above copyright
4513e3f4d6SMark Murray  * notice appear in all copies and that both that copyright notice and
4613e3f4d6SMark Murray  * this permission notice appear in supporting documentation, and that
4713e3f4d6SMark Murray  * the name of M.I.T. not be used in advertising or publicity pertaining
4813e3f4d6SMark Murray  * to distribution of the software without specific, written prior
4913e3f4d6SMark Murray  * permission.  M.I.T. makes no representations about the suitability of
5013e3f4d6SMark Murray  * this software for any purpose.  It is provided "as is" without express
5113e3f4d6SMark Murray  * or implied warranty.
5213e3f4d6SMark Murray  */
5313e3f4d6SMark Murray 
5413e3f4d6SMark Murray #include <config.h>
5513e3f4d6SMark Murray 
56*ae771770SStanislav Sedov RCSID("$Id$");
5713e3f4d6SMark Murray 
5813e3f4d6SMark Murray #if	defined(AUTHENTICATION)
5913e3f4d6SMark Murray #include <stdio.h>
6013e3f4d6SMark Murray #ifdef HAVE_SYS_TYPES_H
6113e3f4d6SMark Murray #include <sys/types.h>
6213e3f4d6SMark Murray #endif
6313e3f4d6SMark Murray #include <signal.h>
6413e3f4d6SMark Murray #define	AUTH_NAMES
6513e3f4d6SMark Murray #ifdef HAVE_ARPA_TELNET_H
6613e3f4d6SMark Murray #include <arpa/telnet.h>
6713e3f4d6SMark Murray #endif
6813e3f4d6SMark Murray #include <stdlib.h>
6913e3f4d6SMark Murray #include <string.h>
7013e3f4d6SMark Murray 
7113e3f4d6SMark Murray #include <roken.h>
7213e3f4d6SMark Murray 
7313e3f4d6SMark Murray #ifdef SOCKS
7413e3f4d6SMark Murray #include <socks.h>
7513e3f4d6SMark Murray #endif
7613e3f4d6SMark Murray 
7713e3f4d6SMark Murray #include "encrypt.h"
7813e3f4d6SMark Murray #include "auth.h"
7913e3f4d6SMark Murray #include "misc-proto.h"
8013e3f4d6SMark Murray #include "auth-proto.h"
8113e3f4d6SMark Murray 
8213e3f4d6SMark Murray #define	typemask(x)		(1<<((x)-1))
8313e3f4d6SMark Murray 
8413e3f4d6SMark Murray #ifdef	RSA_ENCPWD
8513e3f4d6SMark Murray extern rsaencpwd_init();
8613e3f4d6SMark Murray extern rsaencpwd_send();
8713e3f4d6SMark Murray extern rsaencpwd_is();
8813e3f4d6SMark Murray extern rsaencpwd_reply();
8913e3f4d6SMark Murray extern rsaencpwd_status();
9013e3f4d6SMark Murray extern rsaencpwd_printsub();
9113e3f4d6SMark Murray #endif
9213e3f4d6SMark Murray 
9313e3f4d6SMark Murray int auth_debug_mode = 0;
944137ff4cSJacques Vidrine int auth_has_failed  = 0;
954137ff4cSJacques Vidrine int auth_enable_encrypt = 0;
9613e3f4d6SMark Murray static 	const	char	*Name = "Noname";
9713e3f4d6SMark Murray static	int	Server = 0;
9813e3f4d6SMark Murray static	Authenticator	*authenticated = 0;
9913e3f4d6SMark Murray static	int	authenticating = 0;
10013e3f4d6SMark Murray static	int	validuser = 0;
10113e3f4d6SMark Murray static	unsigned char	_auth_send_data[256];
10213e3f4d6SMark Murray static	unsigned char	*auth_send_data;
10313e3f4d6SMark Murray static	int	auth_send_cnt = 0;
10413e3f4d6SMark Murray 
10513e3f4d6SMark Murray /*
10613e3f4d6SMark Murray  * Authentication types supported.  Plese note that these are stored
10713e3f4d6SMark Murray  * in priority order, i.e. try the first one first.
10813e3f4d6SMark Murray  */
10913e3f4d6SMark Murray Authenticator authenticators[] = {
11013e3f4d6SMark Murray #ifdef UNSAFE
11113e3f4d6SMark Murray     { AUTHTYPE_UNSAFE, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
11213e3f4d6SMark Murray       unsafe_init,
11313e3f4d6SMark Murray       unsafe_send,
11413e3f4d6SMark Murray       unsafe_is,
11513e3f4d6SMark Murray       unsafe_reply,
11613e3f4d6SMark Murray       unsafe_status,
11713e3f4d6SMark Murray       unsafe_printsub },
11813e3f4d6SMark Murray #endif
11913e3f4d6SMark Murray #ifdef SRA
12013e3f4d6SMark Murray     { AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
12113e3f4d6SMark Murray       sra_init,
12213e3f4d6SMark Murray       sra_send,
12313e3f4d6SMark Murray       sra_is,
12413e3f4d6SMark Murray       sra_reply,
12513e3f4d6SMark Murray       sra_status,
12613e3f4d6SMark Murray       sra_printsub },
12713e3f4d6SMark Murray #endif
12813e3f4d6SMark Murray #ifdef	SPX
12913e3f4d6SMark Murray     { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
13013e3f4d6SMark Murray       spx_init,
13113e3f4d6SMark Murray       spx_send,
13213e3f4d6SMark Murray       spx_is,
13313e3f4d6SMark Murray       spx_reply,
13413e3f4d6SMark Murray       spx_status,
13513e3f4d6SMark Murray       spx_printsub },
13613e3f4d6SMark Murray     { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
13713e3f4d6SMark Murray       spx_init,
13813e3f4d6SMark Murray       spx_send,
13913e3f4d6SMark Murray       spx_is,
14013e3f4d6SMark Murray       spx_reply,
14113e3f4d6SMark Murray       spx_status,
14213e3f4d6SMark Murray       spx_printsub },
14313e3f4d6SMark Murray #endif
14413e3f4d6SMark Murray #ifdef	KRB5
14513e3f4d6SMark Murray     { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
14613e3f4d6SMark Murray       kerberos5_init,
14713e3f4d6SMark Murray       kerberos5_send_mutual,
14813e3f4d6SMark Murray       kerberos5_is,
14913e3f4d6SMark Murray       kerberos5_reply,
15013e3f4d6SMark Murray       kerberos5_status,
15113e3f4d6SMark Murray       kerberos5_printsub },
15213e3f4d6SMark Murray     { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
15313e3f4d6SMark Murray       kerberos5_init,
15413e3f4d6SMark Murray       kerberos5_send_oneway,
15513e3f4d6SMark Murray       kerberos5_is,
15613e3f4d6SMark Murray       kerberos5_reply,
15713e3f4d6SMark Murray       kerberos5_status,
15813e3f4d6SMark Murray       kerberos5_printsub },
15913e3f4d6SMark Murray #endif
16013e3f4d6SMark Murray #ifdef	RSA_ENCPWD
16113e3f4d6SMark Murray     { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
16213e3f4d6SMark Murray       rsaencpwd_init,
16313e3f4d6SMark Murray       rsaencpwd_send,
16413e3f4d6SMark Murray       rsaencpwd_is,
16513e3f4d6SMark Murray       rsaencpwd_reply,
16613e3f4d6SMark Murray       rsaencpwd_status,
16713e3f4d6SMark Murray       rsaencpwd_printsub },
16813e3f4d6SMark Murray #endif
16913e3f4d6SMark Murray     { 0, },
17013e3f4d6SMark Murray };
17113e3f4d6SMark Murray 
17213e3f4d6SMark Murray static Authenticator NoAuth = { 0 };
17313e3f4d6SMark Murray 
17413e3f4d6SMark Murray static int	i_support = 0;
17513e3f4d6SMark Murray static int	i_wont_support = 0;
17613e3f4d6SMark Murray 
17713e3f4d6SMark Murray Authenticator *
findauthenticator(int type,int way)17813e3f4d6SMark Murray findauthenticator(int type, int way)
17913e3f4d6SMark Murray {
18013e3f4d6SMark Murray     Authenticator *ap = authenticators;
18113e3f4d6SMark Murray 
18213e3f4d6SMark Murray     while (ap->type && (ap->type != type || ap->way != way))
18313e3f4d6SMark Murray 	++ap;
18413e3f4d6SMark Murray     return(ap->type ? ap : 0);
18513e3f4d6SMark Murray }
18613e3f4d6SMark Murray 
18713e3f4d6SMark Murray void
auth_init(const char * name,int server)18813e3f4d6SMark Murray auth_init(const char *name, int server)
18913e3f4d6SMark Murray {
19013e3f4d6SMark Murray     Authenticator *ap = authenticators;
19113e3f4d6SMark Murray 
19213e3f4d6SMark Murray     Server = server;
19313e3f4d6SMark Murray     Name = name;
19413e3f4d6SMark Murray 
19513e3f4d6SMark Murray     i_support = 0;
19613e3f4d6SMark Murray     authenticated = 0;
19713e3f4d6SMark Murray     authenticating = 0;
19813e3f4d6SMark Murray     while (ap->type) {
19913e3f4d6SMark Murray 	if (!ap->init || (*ap->init)(ap, server)) {
20013e3f4d6SMark Murray 	    i_support |= typemask(ap->type);
20113e3f4d6SMark Murray 	    if (auth_debug_mode)
20213e3f4d6SMark Murray 		printf(">>>%s: I support auth type %d %d\r\n",
20313e3f4d6SMark Murray 		       Name,
20413e3f4d6SMark Murray 		       ap->type, ap->way);
20513e3f4d6SMark Murray 	}
20613e3f4d6SMark Murray 	else if (auth_debug_mode)
20713e3f4d6SMark Murray 	    printf(">>>%s: Init failed: auth type %d %d\r\n",
20813e3f4d6SMark Murray 		   Name, ap->type, ap->way);
20913e3f4d6SMark Murray 	++ap;
21013e3f4d6SMark Murray     }
21113e3f4d6SMark Murray }
21213e3f4d6SMark Murray 
21313e3f4d6SMark Murray void
auth_disable_name(char * name)21413e3f4d6SMark Murray auth_disable_name(char *name)
21513e3f4d6SMark Murray {
21613e3f4d6SMark Murray     int x;
21713e3f4d6SMark Murray     for (x = 0; x < AUTHTYPE_CNT; ++x) {
21813e3f4d6SMark Murray 	if (!strcasecmp(name, AUTHTYPE_NAME(x))) {
21913e3f4d6SMark Murray 	    i_wont_support |= typemask(x);
22013e3f4d6SMark Murray 	    break;
22113e3f4d6SMark Murray 	}
22213e3f4d6SMark Murray     }
22313e3f4d6SMark Murray }
22413e3f4d6SMark Murray 
22513e3f4d6SMark Murray int
getauthmask(char * type,int * maskp)22613e3f4d6SMark Murray getauthmask(char *type, int *maskp)
22713e3f4d6SMark Murray {
22813e3f4d6SMark Murray     int x;
22913e3f4d6SMark Murray 
23013e3f4d6SMark Murray     if (!strcasecmp(type, AUTHTYPE_NAME(0))) {
23113e3f4d6SMark Murray 	*maskp = -1;
23213e3f4d6SMark Murray 	return(1);
23313e3f4d6SMark Murray     }
23413e3f4d6SMark Murray 
23513e3f4d6SMark Murray     for (x = 1; x < AUTHTYPE_CNT; ++x) {
23613e3f4d6SMark Murray 	if (!strcasecmp(type, AUTHTYPE_NAME(x))) {
23713e3f4d6SMark Murray 	    *maskp = typemask(x);
23813e3f4d6SMark Murray 	    return(1);
23913e3f4d6SMark Murray 	}
24013e3f4d6SMark Murray     }
24113e3f4d6SMark Murray     return(0);
24213e3f4d6SMark Murray }
24313e3f4d6SMark Murray 
24413e3f4d6SMark Murray int
auth_enable(char * type)24513e3f4d6SMark Murray auth_enable(char *type)
24613e3f4d6SMark Murray {
24713e3f4d6SMark Murray     return(auth_onoff(type, 1));
24813e3f4d6SMark Murray }
24913e3f4d6SMark Murray 
25013e3f4d6SMark Murray int
auth_disable(char * type)25113e3f4d6SMark Murray auth_disable(char *type)
25213e3f4d6SMark Murray {
25313e3f4d6SMark Murray     return(auth_onoff(type, 0));
25413e3f4d6SMark Murray }
25513e3f4d6SMark Murray 
25613e3f4d6SMark Murray int
auth_onoff(char * type,int on)25713e3f4d6SMark Murray auth_onoff(char *type, int on)
25813e3f4d6SMark Murray {
25913e3f4d6SMark Murray     int i, mask = -1;
26013e3f4d6SMark Murray     Authenticator *ap;
26113e3f4d6SMark Murray 
26213e3f4d6SMark Murray     if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) {
26313e3f4d6SMark Murray 	printf("auth %s 'type'\n", on ? "enable" : "disable");
26413e3f4d6SMark Murray 	printf("Where 'type' is one of:\n");
26513e3f4d6SMark Murray 	printf("\t%s\n", AUTHTYPE_NAME(0));
26613e3f4d6SMark Murray 	mask = 0;
26713e3f4d6SMark Murray 	for (ap = authenticators; ap->type; ap++) {
26813e3f4d6SMark Murray 	    if ((mask & (i = typemask(ap->type))) != 0)
26913e3f4d6SMark Murray 		continue;
27013e3f4d6SMark Murray 	    mask |= i;
27113e3f4d6SMark Murray 	    printf("\t%s\n", AUTHTYPE_NAME(ap->type));
27213e3f4d6SMark Murray 	}
27313e3f4d6SMark Murray 	return(0);
27413e3f4d6SMark Murray     }
27513e3f4d6SMark Murray 
27613e3f4d6SMark Murray     if (!getauthmask(type, &mask)) {
27713e3f4d6SMark Murray 	printf("%s: invalid authentication type\n", type);
27813e3f4d6SMark Murray 	return(0);
27913e3f4d6SMark Murray     }
28013e3f4d6SMark Murray     if (on)
28113e3f4d6SMark Murray 	i_wont_support &= ~mask;
28213e3f4d6SMark Murray     else
28313e3f4d6SMark Murray 	i_wont_support |= mask;
28413e3f4d6SMark Murray     return(1);
28513e3f4d6SMark Murray }
28613e3f4d6SMark Murray 
28713e3f4d6SMark Murray int
auth_togdebug(int on)28813e3f4d6SMark Murray auth_togdebug(int on)
28913e3f4d6SMark Murray {
29013e3f4d6SMark Murray     if (on < 0)
29113e3f4d6SMark Murray 	auth_debug_mode ^= 1;
29213e3f4d6SMark Murray     else
29313e3f4d6SMark Murray 	auth_debug_mode = on;
29413e3f4d6SMark Murray     printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled");
29513e3f4d6SMark Murray     return(1);
29613e3f4d6SMark Murray }
29713e3f4d6SMark Murray 
29813e3f4d6SMark Murray int
auth_status(void)29913e3f4d6SMark Murray auth_status(void)
30013e3f4d6SMark Murray {
30113e3f4d6SMark Murray     Authenticator *ap;
30213e3f4d6SMark Murray     int i, mask;
30313e3f4d6SMark Murray 
30413e3f4d6SMark Murray     if (i_wont_support == -1)
30513e3f4d6SMark Murray 	printf("Authentication disabled\n");
30613e3f4d6SMark Murray     else
30713e3f4d6SMark Murray 	printf("Authentication enabled\n");
30813e3f4d6SMark Murray 
30913e3f4d6SMark Murray     mask = 0;
31013e3f4d6SMark Murray     for (ap = authenticators; ap->type; ap++) {
31113e3f4d6SMark Murray 	if ((mask & (i = typemask(ap->type))) != 0)
31213e3f4d6SMark Murray 	    continue;
31313e3f4d6SMark Murray 	mask |= i;
31413e3f4d6SMark Murray 	printf("%s: %s\n", AUTHTYPE_NAME(ap->type),
31513e3f4d6SMark Murray 	       (i_wont_support & typemask(ap->type)) ?
31613e3f4d6SMark Murray 	       "disabled" : "enabled");
31713e3f4d6SMark Murray     }
31813e3f4d6SMark Murray     return(1);
31913e3f4d6SMark Murray }
32013e3f4d6SMark Murray 
32113e3f4d6SMark Murray /*
32213e3f4d6SMark Murray  * This routine is called by the server to start authentication
32313e3f4d6SMark Murray  * negotiation.
32413e3f4d6SMark Murray  */
32513e3f4d6SMark Murray void
auth_request(void)32613e3f4d6SMark Murray auth_request(void)
32713e3f4d6SMark Murray {
32813e3f4d6SMark Murray     static unsigned char str_request[64] = { IAC, SB,
32913e3f4d6SMark Murray 					     TELOPT_AUTHENTICATION,
33013e3f4d6SMark Murray 					     TELQUAL_SEND, };
33113e3f4d6SMark Murray     Authenticator *ap = authenticators;
33213e3f4d6SMark Murray     unsigned char *e = str_request + 4;
33313e3f4d6SMark Murray 
33413e3f4d6SMark Murray     if (!authenticating) {
33513e3f4d6SMark Murray 	authenticating = 1;
33613e3f4d6SMark Murray 	while (ap->type) {
33713e3f4d6SMark Murray 	    if (i_support & ~i_wont_support & typemask(ap->type)) {
33813e3f4d6SMark Murray 		if (auth_debug_mode) {
33913e3f4d6SMark Murray 		    printf(">>>%s: Sending type %d %d\r\n",
34013e3f4d6SMark Murray 			   Name, ap->type, ap->way);
34113e3f4d6SMark Murray 		}
34213e3f4d6SMark Murray 		*e++ = ap->type;
34313e3f4d6SMark Murray 		*e++ = ap->way;
34413e3f4d6SMark Murray 	    }
34513e3f4d6SMark Murray 	    ++ap;
34613e3f4d6SMark Murray 	}
34713e3f4d6SMark Murray 	*e++ = IAC;
34813e3f4d6SMark Murray 	*e++ = SE;
34913e3f4d6SMark Murray 	telnet_net_write(str_request, e - str_request);
35013e3f4d6SMark Murray 	printsub('>', &str_request[2], e - str_request - 2);
35113e3f4d6SMark Murray     }
35213e3f4d6SMark Murray }
35313e3f4d6SMark Murray 
35413e3f4d6SMark Murray /*
35513e3f4d6SMark Murray  * This is called when an AUTH SEND is received.
35613e3f4d6SMark Murray  * It should never arrive on the server side (as only the server can
35713e3f4d6SMark Murray  * send an AUTH SEND).
35813e3f4d6SMark Murray  * You should probably respond to it if you can...
35913e3f4d6SMark Murray  *
36013e3f4d6SMark Murray  * If you want to respond to the types out of order (i.e. even
36113e3f4d6SMark Murray  * if he sends  LOGIN KERBEROS and you support both, you respond
36213e3f4d6SMark Murray  * with KERBEROS instead of LOGIN (which is against what the
36313e3f4d6SMark Murray  * protocol says)) you will have to hack this code...
36413e3f4d6SMark Murray  */
36513e3f4d6SMark Murray void
auth_send(unsigned char * data,int cnt)36613e3f4d6SMark Murray auth_send(unsigned char *data, int cnt)
36713e3f4d6SMark Murray {
36813e3f4d6SMark Murray     Authenticator *ap;
36913e3f4d6SMark Murray     static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
37013e3f4d6SMark Murray 					TELQUAL_IS, AUTHTYPE_NULL, 0,
37113e3f4d6SMark Murray 					IAC, SE };
37213e3f4d6SMark Murray     if (Server) {
37313e3f4d6SMark Murray 	if (auth_debug_mode) {
37413e3f4d6SMark Murray 	    printf(">>>%s: auth_send called!\r\n", Name);
37513e3f4d6SMark Murray 	}
37613e3f4d6SMark Murray 	return;
37713e3f4d6SMark Murray     }
37813e3f4d6SMark Murray 
37913e3f4d6SMark Murray     if (auth_debug_mode) {
38013e3f4d6SMark Murray 	printf(">>>%s: auth_send got:", Name);
38113e3f4d6SMark Murray 	printd(data, cnt); printf("\r\n");
38213e3f4d6SMark Murray     }
38313e3f4d6SMark Murray 
38413e3f4d6SMark Murray     /*
38513e3f4d6SMark Murray      * Save the data, if it is new, so that we can continue looking
38613e3f4d6SMark Murray      * at it if the authorization we try doesn't work
38713e3f4d6SMark Murray      */
38813e3f4d6SMark Murray     if (data < _auth_send_data ||
38913e3f4d6SMark Murray 	data > _auth_send_data + sizeof(_auth_send_data)) {
39013e3f4d6SMark Murray 	auth_send_cnt = cnt > sizeof(_auth_send_data)
39113e3f4d6SMark Murray 	    ? sizeof(_auth_send_data)
39213e3f4d6SMark Murray 	    : cnt;
39313e3f4d6SMark Murray 	memmove(_auth_send_data, data, auth_send_cnt);
39413e3f4d6SMark Murray 	auth_send_data = _auth_send_data;
39513e3f4d6SMark Murray     } else {
39613e3f4d6SMark Murray 	/*
39713e3f4d6SMark Murray 	 * This is probably a no-op, but we just make sure
39813e3f4d6SMark Murray 	 */
39913e3f4d6SMark Murray 	auth_send_data = data;
40013e3f4d6SMark Murray 	auth_send_cnt = cnt;
40113e3f4d6SMark Murray     }
40213e3f4d6SMark Murray     while ((auth_send_cnt -= 2) >= 0) {
40313e3f4d6SMark Murray 	if (auth_debug_mode)
40413e3f4d6SMark Murray 	    printf(">>>%s: He supports %d\r\n",
40513e3f4d6SMark Murray 		   Name, *auth_send_data);
40613e3f4d6SMark Murray 	if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
40713e3f4d6SMark Murray 	    ap = findauthenticator(auth_send_data[0],
40813e3f4d6SMark Murray 				   auth_send_data[1]);
40913e3f4d6SMark Murray 	    if (ap && ap->send) {
41013e3f4d6SMark Murray 		if (auth_debug_mode)
41113e3f4d6SMark Murray 		    printf(">>>%s: Trying %d %d\r\n",
41213e3f4d6SMark Murray 			   Name, auth_send_data[0],
41313e3f4d6SMark Murray 			   auth_send_data[1]);
41413e3f4d6SMark Murray 		if ((*ap->send)(ap)) {
41513e3f4d6SMark Murray 		    /*
41613e3f4d6SMark Murray 		     * Okay, we found one we like
41713e3f4d6SMark Murray 		     * and did it.
41813e3f4d6SMark Murray 		     * we can go home now.
41913e3f4d6SMark Murray 		     */
42013e3f4d6SMark Murray 		    if (auth_debug_mode)
42113e3f4d6SMark Murray 			printf(">>>%s: Using type %d\r\n",
42213e3f4d6SMark Murray 			       Name, *auth_send_data);
42313e3f4d6SMark Murray 		    auth_send_data += 2;
42413e3f4d6SMark Murray 		    return;
42513e3f4d6SMark Murray 		}
42613e3f4d6SMark Murray 	    }
42713e3f4d6SMark Murray 	    /* else
42813e3f4d6SMark Murray 	     *	just continue on and look for the
42913e3f4d6SMark Murray 	     *	next one if we didn't do anything.
43013e3f4d6SMark Murray 	     */
43113e3f4d6SMark Murray 	}
43213e3f4d6SMark Murray 	auth_send_data += 2;
43313e3f4d6SMark Murray     }
43413e3f4d6SMark Murray     telnet_net_write(str_none, sizeof(str_none));
43513e3f4d6SMark Murray     printsub('>', &str_none[2], sizeof(str_none) - 2);
43613e3f4d6SMark Murray     if (auth_debug_mode)
43713e3f4d6SMark Murray 	printf(">>>%s: Sent failure message\r\n", Name);
43813e3f4d6SMark Murray     auth_finished(0, AUTH_REJECT);
4394137ff4cSJacques Vidrine     auth_has_failed = 1;
44013e3f4d6SMark Murray #ifdef KANNAN
44113e3f4d6SMark Murray     /*
44213e3f4d6SMark Murray      *  We requested strong authentication, however no mechanisms worked.
44313e3f4d6SMark Murray      *  Therefore, exit on client end.
44413e3f4d6SMark Murray      */
44513e3f4d6SMark Murray     printf("Unable to securely authenticate user ... exit\n");
44613e3f4d6SMark Murray     exit(0);
44713e3f4d6SMark Murray #endif /* KANNAN */
44813e3f4d6SMark Murray }
44913e3f4d6SMark Murray 
45013e3f4d6SMark Murray void
auth_send_retry(void)45113e3f4d6SMark Murray auth_send_retry(void)
45213e3f4d6SMark Murray {
45313e3f4d6SMark Murray     /*
45413e3f4d6SMark Murray      * if auth_send_cnt <= 0 then auth_send will end up rejecting
45513e3f4d6SMark Murray      * the authentication and informing the other side of this.
45613e3f4d6SMark Murray 	 */
45713e3f4d6SMark Murray     auth_send(auth_send_data, auth_send_cnt);
45813e3f4d6SMark Murray }
45913e3f4d6SMark Murray 
46013e3f4d6SMark Murray void
auth_is(unsigned char * data,int cnt)46113e3f4d6SMark Murray auth_is(unsigned char *data, int cnt)
46213e3f4d6SMark Murray {
46313e3f4d6SMark Murray     Authenticator *ap;
46413e3f4d6SMark Murray 
46513e3f4d6SMark Murray     if (cnt < 2)
46613e3f4d6SMark Murray 	return;
46713e3f4d6SMark Murray 
46813e3f4d6SMark Murray     if (data[0] == AUTHTYPE_NULL) {
46913e3f4d6SMark Murray 	auth_finished(0, AUTH_REJECT);
47013e3f4d6SMark Murray 	return;
47113e3f4d6SMark Murray     }
47213e3f4d6SMark Murray 
47313e3f4d6SMark Murray     if ((ap = findauthenticator(data[0], data[1]))) {
47413e3f4d6SMark Murray 	if (ap->is)
47513e3f4d6SMark Murray 	    (*ap->is)(ap, data+2, cnt-2);
47613e3f4d6SMark Murray     } else if (auth_debug_mode)
47713e3f4d6SMark Murray 	printf(">>>%s: Invalid authentication in IS: %d\r\n",
47813e3f4d6SMark Murray 	       Name, *data);
47913e3f4d6SMark Murray }
48013e3f4d6SMark Murray 
48113e3f4d6SMark Murray void
auth_reply(unsigned char * data,int cnt)48213e3f4d6SMark Murray auth_reply(unsigned char *data, int cnt)
48313e3f4d6SMark Murray {
48413e3f4d6SMark Murray     Authenticator *ap;
48513e3f4d6SMark Murray 
48613e3f4d6SMark Murray     if (cnt < 2)
48713e3f4d6SMark Murray 	return;
48813e3f4d6SMark Murray 
48913e3f4d6SMark Murray     if ((ap = findauthenticator(data[0], data[1]))) {
49013e3f4d6SMark Murray 	if (ap->reply)
49113e3f4d6SMark Murray 	    (*ap->reply)(ap, data+2, cnt-2);
49213e3f4d6SMark Murray     } else if (auth_debug_mode)
49313e3f4d6SMark Murray 	printf(">>>%s: Invalid authentication in SEND: %d\r\n",
49413e3f4d6SMark Murray 	       Name, *data);
49513e3f4d6SMark Murray }
49613e3f4d6SMark Murray 
49713e3f4d6SMark Murray void
auth_name(unsigned char * data,int cnt)49813e3f4d6SMark Murray auth_name(unsigned char *data, int cnt)
49913e3f4d6SMark Murray {
50013e3f4d6SMark Murray     char savename[256];
50113e3f4d6SMark Murray 
50213e3f4d6SMark Murray     if (cnt < 1) {
50313e3f4d6SMark Murray 	if (auth_debug_mode)
50413e3f4d6SMark Murray 	    printf(">>>%s: Empty name in NAME\r\n", Name);
50513e3f4d6SMark Murray 	return;
50613e3f4d6SMark Murray     }
50713e3f4d6SMark Murray     if (cnt > sizeof(savename) - 1) {
50813e3f4d6SMark Murray 	if (auth_debug_mode)
50913e3f4d6SMark Murray 	    printf(">>>%s: Name in NAME (%d) exceeds %lu length\r\n",
51013e3f4d6SMark Murray 		   Name, cnt, (unsigned long)(sizeof(savename)-1));
51113e3f4d6SMark Murray 	return;
51213e3f4d6SMark Murray     }
51313e3f4d6SMark Murray     memmove(savename, data, cnt);
51413e3f4d6SMark Murray     savename[cnt] = '\0';	/* Null terminate */
51513e3f4d6SMark Murray     if (auth_debug_mode)
51613e3f4d6SMark Murray 	printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
51713e3f4d6SMark Murray     auth_encrypt_user(savename);
51813e3f4d6SMark Murray }
51913e3f4d6SMark Murray 
52013e3f4d6SMark Murray int
auth_sendname(unsigned char * cp,int len)52113e3f4d6SMark Murray auth_sendname(unsigned char *cp, int len)
52213e3f4d6SMark Murray {
52313e3f4d6SMark Murray     static unsigned char str_request[256+6]
52413e3f4d6SMark Murray 	= { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, };
52513e3f4d6SMark Murray     unsigned char *e = str_request + 4;
52613e3f4d6SMark Murray     unsigned char *ee = &str_request[sizeof(str_request)-2];
52713e3f4d6SMark Murray 
52813e3f4d6SMark Murray     while (--len >= 0) {
52913e3f4d6SMark Murray 	if ((*e++ = *cp++) == IAC)
53013e3f4d6SMark Murray 	    *e++ = IAC;
53113e3f4d6SMark Murray 	if (e >= ee)
53213e3f4d6SMark Murray 	    return(0);
53313e3f4d6SMark Murray     }
53413e3f4d6SMark Murray     *e++ = IAC;
53513e3f4d6SMark Murray     *e++ = SE;
53613e3f4d6SMark Murray     telnet_net_write(str_request, e - str_request);
53713e3f4d6SMark Murray     printsub('>', &str_request[2], e - &str_request[2]);
53813e3f4d6SMark Murray     return(1);
53913e3f4d6SMark Murray }
54013e3f4d6SMark Murray 
54113e3f4d6SMark Murray void
auth_finished(Authenticator * ap,int result)54213e3f4d6SMark Murray auth_finished(Authenticator *ap, int result)
54313e3f4d6SMark Murray {
54413e3f4d6SMark Murray     if (!(authenticated = ap))
54513e3f4d6SMark Murray 	authenticated = &NoAuth;
54613e3f4d6SMark Murray     validuser = result;
54713e3f4d6SMark Murray }
54813e3f4d6SMark Murray 
54913e3f4d6SMark Murray /* ARGSUSED */
55013e3f4d6SMark Murray static void
auth_intr(int sig)55113e3f4d6SMark Murray auth_intr(int sig)
55213e3f4d6SMark Murray {
55313e3f4d6SMark Murray     auth_finished(0, AUTH_REJECT);
55413e3f4d6SMark Murray }
55513e3f4d6SMark Murray 
55613e3f4d6SMark Murray int
auth_wait(char * name,size_t name_sz)55713e3f4d6SMark Murray auth_wait(char *name, size_t name_sz)
55813e3f4d6SMark Murray {
55913e3f4d6SMark Murray     if (auth_debug_mode)
56013e3f4d6SMark Murray 	printf(">>>%s: in auth_wait.\r\n", Name);
56113e3f4d6SMark Murray 
56213e3f4d6SMark Murray     if (Server && !authenticating)
56313e3f4d6SMark Murray 	return(0);
56413e3f4d6SMark Murray 
56513e3f4d6SMark Murray     signal(SIGALRM, auth_intr);
56613e3f4d6SMark Murray     alarm(30);
56713e3f4d6SMark Murray     while (!authenticated)
56813e3f4d6SMark Murray 	if (telnet_spin())
56913e3f4d6SMark Murray 	    break;
57013e3f4d6SMark Murray     alarm(0);
57113e3f4d6SMark Murray     signal(SIGALRM, SIG_DFL);
57213e3f4d6SMark Murray 
57313e3f4d6SMark Murray     /*
57413e3f4d6SMark Murray      * Now check to see if the user is valid or not
57513e3f4d6SMark Murray      */
57613e3f4d6SMark Murray     if (!authenticated || authenticated == &NoAuth)
57713e3f4d6SMark Murray 	return(AUTH_REJECT);
57813e3f4d6SMark Murray 
57913e3f4d6SMark Murray     if (validuser == AUTH_VALID)
58013e3f4d6SMark Murray 	validuser = AUTH_USER;
58113e3f4d6SMark Murray 
58213e3f4d6SMark Murray     if (authenticated->status)
58313e3f4d6SMark Murray 	validuser = (*authenticated->status)(authenticated,
58413e3f4d6SMark Murray 					     name, name_sz,
58513e3f4d6SMark Murray 					     validuser);
58613e3f4d6SMark Murray     return(validuser);
58713e3f4d6SMark Murray }
58813e3f4d6SMark Murray 
58913e3f4d6SMark Murray void
auth_debug(int mode)59013e3f4d6SMark Murray auth_debug(int mode)
59113e3f4d6SMark Murray {
59213e3f4d6SMark Murray     auth_debug_mode = mode;
59313e3f4d6SMark Murray }
59413e3f4d6SMark Murray 
59513e3f4d6SMark Murray void
auth_printsub(unsigned char * data,size_t cnt,unsigned char * buf,size_t buflen)596*ae771770SStanislav Sedov auth_printsub(unsigned char *data, size_t cnt,
597*ae771770SStanislav Sedov 	      unsigned char *buf, size_t buflen)
59813e3f4d6SMark Murray {
59913e3f4d6SMark Murray     Authenticator *ap;
60013e3f4d6SMark Murray 
60113e3f4d6SMark Murray     if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
60213e3f4d6SMark Murray 	(*ap->printsub)(data, cnt, buf, buflen);
60313e3f4d6SMark Murray     else
60413e3f4d6SMark Murray 	auth_gen_printsub(data, cnt, buf, buflen);
60513e3f4d6SMark Murray }
60613e3f4d6SMark Murray 
60713e3f4d6SMark Murray void
auth_gen_printsub(unsigned char * data,size_t cnt,unsigned char * buf,size_t buflen)608*ae771770SStanislav Sedov auth_gen_printsub(unsigned char *data, size_t cnt,
609*ae771770SStanislav Sedov 		  unsigned char *buf, size_t buflen)
61013e3f4d6SMark Murray {
61113e3f4d6SMark Murray     unsigned char *cp;
61213e3f4d6SMark Murray     unsigned char tbuf[16];
61313e3f4d6SMark Murray 
61413e3f4d6SMark Murray     cnt -= 3;
61513e3f4d6SMark Murray     data += 3;
61613e3f4d6SMark Murray     buf[buflen-1] = '\0';
61713e3f4d6SMark Murray     buf[buflen-2] = '*';
61813e3f4d6SMark Murray     buflen -= 2;
61913e3f4d6SMark Murray     for (; cnt > 0; cnt--, data++) {
6204137ff4cSJacques Vidrine 	snprintf((char*)tbuf, sizeof(tbuf), " %d", *data);
62113e3f4d6SMark Murray 	for (cp = tbuf; *cp && buflen > 0; --buflen)
62213e3f4d6SMark Murray 	    *buf++ = *cp++;
62313e3f4d6SMark Murray 	if (buflen <= 0)
62413e3f4d6SMark Murray 	    return;
62513e3f4d6SMark Murray     }
62613e3f4d6SMark Murray     *buf = '\0';
62713e3f4d6SMark Murray }
62813e3f4d6SMark Murray #endif
629