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