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 * 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 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 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 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 24513e3f4d6SMark Murray auth_enable(char *type) 24613e3f4d6SMark Murray { 24713e3f4d6SMark Murray return(auth_onoff(type, 1)); 24813e3f4d6SMark Murray } 24913e3f4d6SMark Murray 25013e3f4d6SMark Murray int 25113e3f4d6SMark Murray auth_disable(char *type) 25213e3f4d6SMark Murray { 25313e3f4d6SMark Murray return(auth_onoff(type, 0)); 25413e3f4d6SMark Murray } 25513e3f4d6SMark Murray 25613e3f4d6SMark Murray int 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 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 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 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 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 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 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 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 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 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 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 55113e3f4d6SMark Murray auth_intr(int sig) 55213e3f4d6SMark Murray { 55313e3f4d6SMark Murray auth_finished(0, AUTH_REJECT); 55413e3f4d6SMark Murray } 55513e3f4d6SMark Murray 55613e3f4d6SMark Murray int 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 59013e3f4d6SMark Murray auth_debug(int mode) 59113e3f4d6SMark Murray { 59213e3f4d6SMark Murray auth_debug_mode = mode; 59313e3f4d6SMark Murray } 59413e3f4d6SMark Murray 59513e3f4d6SMark Murray void 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 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