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 5557416Smarkm#include <config.h> 5657416Smarkm 57233294SstasRCSID("$Id$"); 5857416Smarkm 5957416Smarkm#if defined(ENCRYPTION) 6057416Smarkm 6157416Smarkm#define ENCRYPT_NAMES 6257416Smarkm#include <arpa/telnet.h> 6357416Smarkm 6457416Smarkm#include <stdio.h> 6557416Smarkm#include <stdlib.h> 6657416Smarkm#include <string.h> 6757416Smarkm#include <roken.h> 6857416Smarkm#ifdef SOCKS 6957416Smarkm#include <socks.h> 7057416Smarkm#endif 7157416Smarkm 72233294Sstas#include "encrypt.h" 73233294Sstas#include "misc.h" 7457416Smarkm 75233294Sstas 7657416Smarkm/* 7757416Smarkm * These functions pointers point to the current routines 7857416Smarkm * for encrypting and decrypting data. 7957416Smarkm */ 8057416Smarkmvoid (*encrypt_output) (unsigned char *, int); 8157416Smarkmint (*decrypt_input) (int); 8257416Smarkmchar *nclearto; 8357416Smarkm 8457416Smarkmint encrypt_debug_mode = 0; 8557416Smarkmstatic int decrypt_mode = 0; 8657416Smarkmstatic int encrypt_mode = 0; 8757416Smarkmstatic int encrypt_verbose = 0; 8857416Smarkmstatic int autoencrypt = 0; 8957416Smarkmstatic int autodecrypt = 0; 9057416Smarkmstatic int havesessionkey = 0; 9157416Smarkmstatic int Server = 0; 9257416Smarkmstatic const char *Name = "Noname"; 9357416Smarkm 9457416Smarkm#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) 9557416Smarkm 9657416Smarkmstatic long i_support_encrypt = typemask(ENCTYPE_DES_CFB64) 9757416Smarkm | typemask(ENCTYPE_DES_OFB64); 9857416Smarkm static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64) 9957416Smarkm | typemask(ENCTYPE_DES_OFB64); 10057416Smarkm static long i_wont_support_encrypt = 0; 10157416Smarkm static long i_wont_support_decrypt = 0; 10257416Smarkm#define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt) 10357416Smarkm#define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt) 10457416Smarkm 10557416Smarkm static long remote_supports_encrypt = 0; 10657416Smarkm static long remote_supports_decrypt = 0; 10757416Smarkm 10857416Smarkm static Encryptions encryptions[] = { 10957416Smarkm#if defined(DES_ENCRYPTION) 11057416Smarkm { "DES_CFB64", ENCTYPE_DES_CFB64, 111233294Sstas cfb64_encrypt, 11257416Smarkm cfb64_decrypt, 11357416Smarkm cfb64_init, 11457416Smarkm cfb64_start, 11557416Smarkm cfb64_is, 11657416Smarkm cfb64_reply, 11757416Smarkm cfb64_session, 11857416Smarkm cfb64_keyid, 11957416Smarkm cfb64_printsub }, 12057416Smarkm { "DES_OFB64", ENCTYPE_DES_OFB64, 121233294Sstas ofb64_encrypt, 12257416Smarkm ofb64_decrypt, 12357416Smarkm ofb64_init, 12457416Smarkm ofb64_start, 12557416Smarkm ofb64_is, 12657416Smarkm ofb64_reply, 12757416Smarkm ofb64_session, 12857416Smarkm ofb64_keyid, 12957416Smarkm ofb64_printsub }, 13057416Smarkm#endif 13157416Smarkm { 0, }, 13257416Smarkm }; 13357416Smarkm 13457416Smarkmstatic unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT, 13557416Smarkm ENCRYPT_SUPPORT }; 13657416Smarkmstatic unsigned char str_suplen = 0; 13757416Smarkmstatic unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT }; 13857416Smarkmstatic unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE }; 13957416Smarkm 14057416SmarkmEncryptions * 14157416Smarkmfindencryption(int type) 14257416Smarkm{ 14357416Smarkm Encryptions *ep = encryptions; 14457416Smarkm 14557416Smarkm if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type))) 14657416Smarkm return(0); 14757416Smarkm while (ep->type && ep->type != type) 14857416Smarkm ++ep; 14957416Smarkm return(ep->type ? ep : 0); 15057416Smarkm} 15157416Smarkm 15257416SmarkmEncryptions * 15357416Smarkmfinddecryption(int type) 15457416Smarkm{ 15557416Smarkm Encryptions *ep = encryptions; 15657416Smarkm 15757416Smarkm if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type))) 15857416Smarkm return(0); 15957416Smarkm while (ep->type && ep->type != type) 16057416Smarkm ++ep; 16157416Smarkm return(ep->type ? ep : 0); 16257416Smarkm} 16357416Smarkm 16457416Smarkm#define MAXKEYLEN 64 16557416Smarkm 16657416Smarkmstatic struct key_info { 16757416Smarkm unsigned char keyid[MAXKEYLEN]; 16857416Smarkm int keylen; 16957416Smarkm int dir; 17057416Smarkm int *modep; 17157416Smarkm Encryptions *(*getcrypt)(); 17257416Smarkm} ki[2] = { 17357416Smarkm { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption }, 17457416Smarkm { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption }, 17557416Smarkm}; 17657416Smarkm 17757416Smarkmvoid 17857416Smarkmencrypt_init(const char *name, int server) 17957416Smarkm{ 18057416Smarkm Encryptions *ep = encryptions; 18157416Smarkm 18257416Smarkm Name = name; 18357416Smarkm Server = server; 18457416Smarkm i_support_encrypt = i_support_decrypt = 0; 18557416Smarkm remote_supports_encrypt = remote_supports_decrypt = 0; 18657416Smarkm encrypt_mode = 0; 18757416Smarkm decrypt_mode = 0; 18857416Smarkm encrypt_output = 0; 18957416Smarkm decrypt_input = 0; 19057416Smarkm#ifdef notdef 19157416Smarkm encrypt_verbose = !server; 19257416Smarkm#endif 19357416Smarkm 19457416Smarkm str_suplen = 4; 19557416Smarkm 19657416Smarkm while (ep->type) { 19757416Smarkm if (encrypt_debug_mode) 19857416Smarkm printf(">>>%s: I will support %s\r\n", 19957416Smarkm Name, ENCTYPE_NAME(ep->type)); 20057416Smarkm i_support_encrypt |= typemask(ep->type); 20157416Smarkm i_support_decrypt |= typemask(ep->type); 20257416Smarkm if ((i_wont_support_decrypt & typemask(ep->type)) == 0) 20357416Smarkm if ((str_send[str_suplen++] = ep->type) == IAC) 20457416Smarkm str_send[str_suplen++] = IAC; 20557416Smarkm if (ep->init) 20657416Smarkm (*ep->init)(Server); 20757416Smarkm ++ep; 20857416Smarkm } 20957416Smarkm str_send[str_suplen++] = IAC; 21057416Smarkm str_send[str_suplen++] = SE; 21157416Smarkm} 21257416Smarkm 21357416Smarkmvoid 21457416Smarkmencrypt_list_types(void) 21557416Smarkm{ 21657416Smarkm Encryptions *ep = encryptions; 21757416Smarkm 21857416Smarkm printf("Valid encryption types:\n"); 21957416Smarkm while (ep->type) { 22057416Smarkm printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type); 22157416Smarkm ++ep; 22257416Smarkm } 22357416Smarkm} 22457416Smarkm 22557416Smarkmint 22657416SmarkmEncryptEnable(char *type, char *mode) 22757416Smarkm{ 22857416Smarkm if (isprefix(type, "help") || isprefix(type, "?")) { 22957416Smarkm printf("Usage: encrypt enable <type> [input|output]\n"); 23057416Smarkm encrypt_list_types(); 23157416Smarkm return(0); 23257416Smarkm } 23357416Smarkm if (EncryptType(type, mode)) 23457416Smarkm return(EncryptStart(mode)); 23557416Smarkm return(0); 23657416Smarkm} 23757416Smarkm 23857416Smarkmint 23957416SmarkmEncryptDisable(char *type, char *mode) 24057416Smarkm{ 24157416Smarkm Encryptions *ep; 24257416Smarkm int ret = 0; 24357416Smarkm 24457416Smarkm if (isprefix(type, "help") || isprefix(type, "?")) { 24557416Smarkm printf("Usage: encrypt disable <type> [input|output]\n"); 24657416Smarkm encrypt_list_types(); 24757416Smarkm } else if ((ep = (Encryptions *)genget(type, (char**)encryptions, 24857416Smarkm sizeof(Encryptions))) == 0) { 24957416Smarkm printf("%s: invalid encryption type\n", type); 25057416Smarkm } else if (Ambiguous(ep)) { 25157416Smarkm printf("Ambiguous type '%s'\n", type); 25257416Smarkm } else { 25357416Smarkm if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) { 25457416Smarkm if (decrypt_mode == ep->type) 25557416Smarkm EncryptStopInput(); 25657416Smarkm i_wont_support_decrypt |= typemask(ep->type); 25757416Smarkm ret = 1; 25857416Smarkm } 25957416Smarkm if ((mode == 0) || (isprefix(mode, "output"))) { 26057416Smarkm if (encrypt_mode == ep->type) 26157416Smarkm EncryptStopOutput(); 26257416Smarkm i_wont_support_encrypt |= typemask(ep->type); 26357416Smarkm ret = 1; 26457416Smarkm } 26557416Smarkm if (ret == 0) 26657416Smarkm printf("%s: invalid encryption mode\n", mode); 26757416Smarkm } 26857416Smarkm return(ret); 26957416Smarkm} 27057416Smarkm 27157416Smarkmint 27257416SmarkmEncryptType(char *type, char *mode) 27357416Smarkm{ 27457416Smarkm Encryptions *ep; 27557416Smarkm int ret = 0; 27657416Smarkm 27757416Smarkm if (isprefix(type, "help") || isprefix(type, "?")) { 27857416Smarkm printf("Usage: encrypt type <type> [input|output]\n"); 27957416Smarkm encrypt_list_types(); 28057416Smarkm } else if ((ep = (Encryptions *)genget(type, (char**)encryptions, 28157416Smarkm sizeof(Encryptions))) == 0) { 28257416Smarkm printf("%s: invalid encryption type\n", type); 28357416Smarkm } else if (Ambiguous(ep)) { 28457416Smarkm printf("Ambiguous type '%s'\n", type); 28557416Smarkm } else { 28657416Smarkm if ((mode == 0) || isprefix(mode, "input")) { 28757416Smarkm decrypt_mode = ep->type; 28857416Smarkm i_wont_support_decrypt &= ~typemask(ep->type); 28957416Smarkm ret = 1; 29057416Smarkm } 29157416Smarkm if ((mode == 0) || isprefix(mode, "output")) { 29257416Smarkm encrypt_mode = ep->type; 29357416Smarkm i_wont_support_encrypt &= ~typemask(ep->type); 29457416Smarkm ret = 1; 29557416Smarkm } 29657416Smarkm if (ret == 0) 29757416Smarkm printf("%s: invalid encryption mode\n", mode); 29857416Smarkm } 29957416Smarkm return(ret); 30057416Smarkm} 30157416Smarkm 30257416Smarkmint 30357416SmarkmEncryptStart(char *mode) 30457416Smarkm{ 30557416Smarkm int ret = 0; 30657416Smarkm if (mode) { 30757416Smarkm if (isprefix(mode, "input")) 30857416Smarkm return(EncryptStartInput()); 30957416Smarkm if (isprefix(mode, "output")) 31057416Smarkm return(EncryptStartOutput()); 31157416Smarkm if (isprefix(mode, "help") || isprefix(mode, "?")) { 31257416Smarkm printf("Usage: encrypt start [input|output]\n"); 31357416Smarkm return(0); 31457416Smarkm } 31557416Smarkm printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode); 31657416Smarkm return(0); 31757416Smarkm } 31857416Smarkm ret += EncryptStartInput(); 31957416Smarkm ret += EncryptStartOutput(); 32057416Smarkm return(ret); 32157416Smarkm} 32257416Smarkm 32357416Smarkmint 32457416SmarkmEncryptStartInput(void) 32557416Smarkm{ 32657416Smarkm if (decrypt_mode) { 32757416Smarkm encrypt_send_request_start(); 32857416Smarkm return(1); 32957416Smarkm } 33057416Smarkm printf("No previous decryption mode, decryption not enabled\r\n"); 33157416Smarkm return(0); 33257416Smarkm} 33357416Smarkm 33457416Smarkmint 33557416SmarkmEncryptStartOutput(void) 33657416Smarkm{ 33757416Smarkm if (encrypt_mode) { 33857416Smarkm encrypt_start_output(encrypt_mode); 33957416Smarkm return(1); 34057416Smarkm } 34157416Smarkm printf("No previous encryption mode, encryption not enabled\r\n"); 34257416Smarkm return(0); 34357416Smarkm} 34457416Smarkm 34557416Smarkmint 34657416SmarkmEncryptStop(char *mode) 34757416Smarkm{ 34857416Smarkm int ret = 0; 34957416Smarkm if (mode) { 35057416Smarkm if (isprefix(mode, "input")) 35157416Smarkm return(EncryptStopInput()); 35257416Smarkm if (isprefix(mode, "output")) 35357416Smarkm return(EncryptStopOutput()); 35457416Smarkm if (isprefix(mode, "help") || isprefix(mode, "?")) { 35557416Smarkm printf("Usage: encrypt stop [input|output]\n"); 35657416Smarkm return(0); 35757416Smarkm } 35857416Smarkm printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode); 35957416Smarkm return(0); 36057416Smarkm } 36157416Smarkm ret += EncryptStopInput(); 36257416Smarkm ret += EncryptStopOutput(); 36357416Smarkm return(ret); 36457416Smarkm} 36557416Smarkm 36657416Smarkmint 36757416SmarkmEncryptStopInput(void) 36857416Smarkm{ 36957416Smarkm encrypt_send_request_end(); 37057416Smarkm return(1); 37157416Smarkm} 37257416Smarkm 37357416Smarkmint 37457416SmarkmEncryptStopOutput(void) 37557416Smarkm{ 37657416Smarkm encrypt_send_end(); 37757416Smarkm return(1); 37857416Smarkm} 37957416Smarkm 38057416Smarkmvoid 38157416Smarkmencrypt_display(void) 38257416Smarkm{ 38357416Smarkm printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n", 38457416Smarkm autoencrypt?"on":"off", autodecrypt?"on":"off"); 38557416Smarkm 38657416Smarkm if (encrypt_output) 38757416Smarkm printf("Currently encrypting output with %s\r\n", 38857416Smarkm ENCTYPE_NAME(encrypt_mode)); 38957416Smarkm else 39057416Smarkm printf("Currently not encrypting output\r\n"); 391233294Sstas 39257416Smarkm if (decrypt_input) 39357416Smarkm printf("Currently decrypting input with %s\r\n", 39457416Smarkm ENCTYPE_NAME(decrypt_mode)); 39557416Smarkm else 39657416Smarkm printf("Currently not decrypting input\r\n"); 39757416Smarkm} 39857416Smarkm 39957416Smarkmint 40057416SmarkmEncryptStatus(void) 40157416Smarkm{ 40257416Smarkm printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n", 40357416Smarkm autoencrypt?"on":"off", autodecrypt?"on":"off"); 40457416Smarkm 40557416Smarkm if (encrypt_output) 40657416Smarkm printf("Currently encrypting output with %s\r\n", 40757416Smarkm ENCTYPE_NAME(encrypt_mode)); 40857416Smarkm else if (encrypt_mode) { 40957416Smarkm printf("Currently output is clear text.\r\n"); 41057416Smarkm printf("Last encryption mode was %s\r\n", 41157416Smarkm ENCTYPE_NAME(encrypt_mode)); 41257416Smarkm } else 41357416Smarkm printf("Currently not encrypting output\r\n"); 414233294Sstas 41557416Smarkm if (decrypt_input) { 41657416Smarkm printf("Currently decrypting input with %s\r\n", 41757416Smarkm ENCTYPE_NAME(decrypt_mode)); 41857416Smarkm } else if (decrypt_mode) { 41957416Smarkm printf("Currently input is clear text.\r\n"); 42057416Smarkm printf("Last decryption mode was %s\r\n", 42157416Smarkm ENCTYPE_NAME(decrypt_mode)); 42257416Smarkm } else 42357416Smarkm printf("Currently not decrypting input\r\n"); 42457416Smarkm 42557416Smarkm return 1; 42657416Smarkm} 42757416Smarkm 42857416Smarkmvoid 42957416Smarkmencrypt_send_support(void) 43057416Smarkm{ 43157416Smarkm if (str_suplen) { 43257416Smarkm /* 43357416Smarkm * If the user has requested that decryption start 43457416Smarkm * immediatly, then send a "REQUEST START" before 43557416Smarkm * we negotiate the type. 43657416Smarkm */ 43757416Smarkm if (!Server && autodecrypt) 43857416Smarkm encrypt_send_request_start(); 43957416Smarkm telnet_net_write(str_send, str_suplen); 44057416Smarkm printsub('>', &str_send[2], str_suplen - 2); 44157416Smarkm str_suplen = 0; 44257416Smarkm } 44357416Smarkm} 44457416Smarkm 44557416Smarkmint 44657416SmarkmEncryptDebug(int on) 44757416Smarkm{ 44857416Smarkm if (on < 0) 44957416Smarkm encrypt_debug_mode ^= 1; 45057416Smarkm else 45157416Smarkm encrypt_debug_mode = on; 45257416Smarkm printf("Encryption debugging %s\r\n", 45357416Smarkm encrypt_debug_mode ? "enabled" : "disabled"); 45457416Smarkm return(1); 45557416Smarkm} 45657416Smarkm 45757416Smarkm/* turn on verbose encryption, but dont keep telling the whole world 45857416Smarkm */ 45957416Smarkmvoid encrypt_verbose_quiet(int on) 46057416Smarkm{ 46157416Smarkm if(on < 0) 46257416Smarkm encrypt_verbose ^= 1; 46357416Smarkm else 46457416Smarkm encrypt_verbose = on ? 1 : 0; 46557416Smarkm} 46657416Smarkm 46757416Smarkmint 46857416SmarkmEncryptVerbose(int on) 46957416Smarkm{ 47057416Smarkm encrypt_verbose_quiet(on); 47157416Smarkm printf("Encryption %s verbose\r\n", 47257416Smarkm encrypt_verbose ? "is" : "is not"); 47357416Smarkm return(1); 47457416Smarkm} 47557416Smarkm 47657416Smarkmint 47757416SmarkmEncryptAutoEnc(int on) 47857416Smarkm{ 47957416Smarkm encrypt_auto(on); 48057416Smarkm printf("Automatic encryption of output is %s\r\n", 48157416Smarkm autoencrypt ? "enabled" : "disabled"); 48257416Smarkm return(1); 48357416Smarkm} 48457416Smarkm 48557416Smarkmint 48657416SmarkmEncryptAutoDec(int on) 48757416Smarkm{ 48857416Smarkm decrypt_auto(on); 48957416Smarkm printf("Automatic decryption of input is %s\r\n", 49057416Smarkm autodecrypt ? "enabled" : "disabled"); 49157416Smarkm return(1); 49257416Smarkm} 49357416Smarkm 49457416Smarkm/* Called when we receive a WONT or a DONT ENCRYPT after we sent a DO 49557416Smarkm encrypt */ 49657416Smarkmvoid 49757416Smarkmencrypt_not(void) 49857416Smarkm{ 49957416Smarkm if (encrypt_verbose) 50057416Smarkm printf("[ Connection is NOT encrypted ]\r\n"); 50157416Smarkm else 50257416Smarkm printf("\r\n*** Connection not encrypted! " 50357416Smarkm "Communication may be eavesdropped. ***\r\n"); 50457416Smarkm} 50557416Smarkm 50657416Smarkm/* 50757416Smarkm * Called when ENCRYPT SUPPORT is received. 50857416Smarkm */ 50957416Smarkmvoid 51057416Smarkmencrypt_support(unsigned char *typelist, int cnt) 51157416Smarkm{ 51257416Smarkm int type, use_type = 0; 51357416Smarkm Encryptions *ep; 51457416Smarkm 51557416Smarkm /* 51657416Smarkm * Forget anything the other side has previously told us. 51757416Smarkm */ 51857416Smarkm remote_supports_decrypt = 0; 51957416Smarkm 52057416Smarkm while (cnt-- > 0) { 52157416Smarkm type = *typelist++; 52257416Smarkm if (encrypt_debug_mode) 52357416Smarkm printf(">>>%s: He is supporting %s (%d)\r\n", 52457416Smarkm Name, 52557416Smarkm ENCTYPE_NAME(type), type); 52657416Smarkm if ((type < ENCTYPE_CNT) && 52757416Smarkm (I_SUPPORT_ENCRYPT & typemask(type))) { 52857416Smarkm remote_supports_decrypt |= typemask(type); 52957416Smarkm if (use_type == 0) 53057416Smarkm use_type = type; 53157416Smarkm } 53257416Smarkm } 53357416Smarkm if (use_type) { 53457416Smarkm ep = findencryption(use_type); 53557416Smarkm if (!ep) 53657416Smarkm return; 53757416Smarkm type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0; 53857416Smarkm if (encrypt_debug_mode) 53957416Smarkm printf(">>>%s: (*ep->start)() returned %d\r\n", 54057416Smarkm Name, type); 54157416Smarkm if (type < 0) 54257416Smarkm return; 54357416Smarkm encrypt_mode = use_type; 54457416Smarkm if (type == 0) 54557416Smarkm encrypt_start_output(use_type); 54657416Smarkm } 54757416Smarkm} 54857416Smarkm 54957416Smarkmvoid 55057416Smarkmencrypt_is(unsigned char *data, int cnt) 55157416Smarkm{ 55257416Smarkm Encryptions *ep; 55357416Smarkm int type, ret; 55457416Smarkm 55557416Smarkm if (--cnt < 0) 55657416Smarkm return; 55757416Smarkm type = *data++; 55857416Smarkm if (type < ENCTYPE_CNT) 55957416Smarkm remote_supports_encrypt |= typemask(type); 56057416Smarkm if (!(ep = finddecryption(type))) { 56157416Smarkm if (encrypt_debug_mode) 56257416Smarkm printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", 56357416Smarkm Name, 56457416Smarkm ENCTYPE_NAME_OK(type) 56557416Smarkm ? ENCTYPE_NAME(type) : "(unknown)", 56657416Smarkm type); 56757416Smarkm return; 56857416Smarkm } 56957416Smarkm if (!ep->is) { 57057416Smarkm if (encrypt_debug_mode) 57157416Smarkm printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", 57257416Smarkm Name, 57357416Smarkm ENCTYPE_NAME_OK(type) 57457416Smarkm ? ENCTYPE_NAME(type) : "(unknown)", 57557416Smarkm type); 57657416Smarkm ret = 0; 57757416Smarkm } else { 57857416Smarkm ret = (*ep->is)(data, cnt); 57957416Smarkm if (encrypt_debug_mode) 58057416Smarkm printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt, 58157416Smarkm (ret < 0) ? "FAIL " : 58257416Smarkm (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); 58357416Smarkm } 58457416Smarkm if (ret < 0) { 58557416Smarkm autodecrypt = 0; 58657416Smarkm } else { 58757416Smarkm decrypt_mode = type; 58857416Smarkm if (ret == 0 && autodecrypt) 58957416Smarkm encrypt_send_request_start(); 59057416Smarkm } 59157416Smarkm} 59257416Smarkm 59357416Smarkmvoid 59457416Smarkmencrypt_reply(unsigned char *data, int cnt) 59557416Smarkm{ 59657416Smarkm Encryptions *ep; 59757416Smarkm int ret, type; 59857416Smarkm 59957416Smarkm if (--cnt < 0) 60057416Smarkm return; 60157416Smarkm type = *data++; 60257416Smarkm if (!(ep = findencryption(type))) { 60357416Smarkm if (encrypt_debug_mode) 60457416Smarkm printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", 60557416Smarkm Name, 60657416Smarkm ENCTYPE_NAME_OK(type) 60757416Smarkm ? ENCTYPE_NAME(type) : "(unknown)", 60857416Smarkm type); 60957416Smarkm return; 61057416Smarkm } 61157416Smarkm if (!ep->reply) { 61257416Smarkm if (encrypt_debug_mode) 61357416Smarkm printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", 61457416Smarkm Name, 61557416Smarkm ENCTYPE_NAME_OK(type) 61657416Smarkm ? ENCTYPE_NAME(type) : "(unknown)", 61757416Smarkm type); 61857416Smarkm ret = 0; 61957416Smarkm } else { 62057416Smarkm ret = (*ep->reply)(data, cnt); 62157416Smarkm if (encrypt_debug_mode) 62257416Smarkm printf("(*ep->reply)(%p, %d) returned %s(%d)\n", 62357416Smarkm data, cnt, 62457416Smarkm (ret < 0) ? "FAIL " : 62557416Smarkm (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); 62657416Smarkm } 62757416Smarkm if (encrypt_debug_mode) 62857416Smarkm printf(">>>%s: encrypt_reply returned %d\n", Name, ret); 62957416Smarkm if (ret < 0) { 63057416Smarkm autoencrypt = 0; 63157416Smarkm } else { 63257416Smarkm encrypt_mode = type; 63357416Smarkm if (ret == 0 && autoencrypt) 63457416Smarkm encrypt_start_output(type); 63557416Smarkm } 63657416Smarkm} 63757416Smarkm 63857416Smarkm/* 639178825Sdfr * Called when ENCRYPT START is received. 64057416Smarkm */ 64157416Smarkmvoid 64257416Smarkmencrypt_start(unsigned char *data, int cnt) 64357416Smarkm{ 64457416Smarkm Encryptions *ep; 64557416Smarkm 64657416Smarkm if (!decrypt_mode) { 64757416Smarkm /* 64857416Smarkm * Something is wrong. We should not get a START 64957416Smarkm * command without having already picked our 65057416Smarkm * decryption scheme. Send a REQUEST-END to 65157416Smarkm * attempt to clear the channel... 65257416Smarkm */ 65357416Smarkm printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name); 65457416Smarkm encrypt_send_request_end(); 65557416Smarkm return; 65657416Smarkm } 65757416Smarkm 65857416Smarkm if ((ep = finddecryption(decrypt_mode))) { 65957416Smarkm decrypt_input = ep->input; 66057416Smarkm if (encrypt_verbose) 66157416Smarkm printf("[ Input is now decrypted with type %s ]\r\n", 66257416Smarkm ENCTYPE_NAME(decrypt_mode)); 66357416Smarkm if (encrypt_debug_mode) 66457416Smarkm printf(">>>%s: Start to decrypt input with type %s\r\n", 66557416Smarkm Name, ENCTYPE_NAME(decrypt_mode)); 66657416Smarkm } else { 66757416Smarkm printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n", 66857416Smarkm Name, 66957416Smarkm ENCTYPE_NAME_OK(decrypt_mode) 67057416Smarkm ? ENCTYPE_NAME(decrypt_mode) 67157416Smarkm : "(unknown)", 67257416Smarkm decrypt_mode); 67357416Smarkm encrypt_send_request_end(); 67457416Smarkm } 67557416Smarkm} 67657416Smarkm 67757416Smarkmvoid 67857416Smarkmencrypt_session_key(Session_Key *key, int server) 67957416Smarkm{ 68057416Smarkm Encryptions *ep = encryptions; 68157416Smarkm 68257416Smarkm havesessionkey = 1; 68357416Smarkm 68457416Smarkm while (ep->type) { 68557416Smarkm if (ep->session) 68657416Smarkm (*ep->session)(key, server); 68757416Smarkm ++ep; 68857416Smarkm } 68957416Smarkm} 69057416Smarkm 69157416Smarkm/* 69257416Smarkm * Called when ENCRYPT END is received. 69357416Smarkm */ 69457416Smarkmvoid 69557416Smarkmencrypt_end(void) 69657416Smarkm{ 69757416Smarkm decrypt_input = 0; 69857416Smarkm if (encrypt_debug_mode) 69957416Smarkm printf(">>>%s: Input is back to clear text\r\n", Name); 70057416Smarkm if (encrypt_verbose) 70157416Smarkm printf("[ Input is now clear text ]\r\n"); 70257416Smarkm} 70357416Smarkm 70457416Smarkm/* 70557416Smarkm * Called when ENCRYPT REQUEST-END is received. 70657416Smarkm */ 70757416Smarkmvoid 70857416Smarkmencrypt_request_end(void) 70957416Smarkm{ 71057416Smarkm encrypt_send_end(); 71157416Smarkm} 71257416Smarkm 71357416Smarkm/* 71457416Smarkm * Called when ENCRYPT REQUEST-START is received. If we receive 71557416Smarkm * this before a type is picked, then that indicates that the 71657416Smarkm * other side wants us to start encrypting data as soon as we 717233294Sstas * can. 71857416Smarkm */ 71957416Smarkmvoid 72057416Smarkmencrypt_request_start(unsigned char *data, int cnt) 72157416Smarkm{ 72257416Smarkm if (encrypt_mode == 0) { 72357416Smarkm if (Server) 72457416Smarkm autoencrypt = 1; 72557416Smarkm return; 72657416Smarkm } 72757416Smarkm encrypt_start_output(encrypt_mode); 72857416Smarkm} 72957416Smarkm 73057416Smarkmstatic unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT }; 73157416Smarkm 73257416Smarkmstatic void 73357416Smarkmencrypt_keyid(struct key_info *kp, unsigned char *keyid, int len) 73457416Smarkm{ 73557416Smarkm Encryptions *ep; 73657416Smarkm int dir = kp->dir; 73757416Smarkm int ret = 0; 73857416Smarkm 739228843Scperciva if (len > MAXKEYLEN) 740234027Sstas len = MAXKEYLEN; 741228843Scperciva 74257416Smarkm if (!(ep = (*kp->getcrypt)(*kp->modep))) { 74357416Smarkm if (len == 0) 74457416Smarkm return; 74557416Smarkm kp->keylen = 0; 74657416Smarkm } else if (len == 0) { 74757416Smarkm /* 74857416Smarkm * Empty option, indicates a failure. 74957416Smarkm */ 75057416Smarkm if (kp->keylen == 0) 75157416Smarkm return; 75257416Smarkm kp->keylen = 0; 75357416Smarkm if (ep->keyid) 75457416Smarkm (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); 75557416Smarkm 75657416Smarkm } else if ((len != kp->keylen) || (memcmp(keyid,kp->keyid,len) != 0)) { 75757416Smarkm /* 75857416Smarkm * Length or contents are different 75957416Smarkm */ 76057416Smarkm kp->keylen = len; 76157416Smarkm memcpy(kp->keyid,keyid, len); 76257416Smarkm if (ep->keyid) 76357416Smarkm (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); 76457416Smarkm } else { 76557416Smarkm if (ep->keyid) 76657416Smarkm ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen); 76757416Smarkm if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt) 76857416Smarkm encrypt_start_output(*kp->modep); 76957416Smarkm return; 77057416Smarkm } 77157416Smarkm 77257416Smarkm encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0); 77357416Smarkm} 77457416Smarkm 77557416Smarkmvoid encrypt_enc_keyid(unsigned char *keyid, int len) 77657416Smarkm{ 77757416Smarkm encrypt_keyid(&ki[1], keyid, len); 77857416Smarkm} 77957416Smarkm 78057416Smarkmvoid encrypt_dec_keyid(unsigned char *keyid, int len) 78157416Smarkm{ 78257416Smarkm encrypt_keyid(&ki[0], keyid, len); 78357416Smarkm} 78457416Smarkm 78557416Smarkm 78657416Smarkmvoid encrypt_send_keyid(int dir, unsigned char *keyid, int keylen, int saveit) 78757416Smarkm{ 78857416Smarkm unsigned char *strp; 78957416Smarkm 79057416Smarkm str_keyid[3] = (dir == DIR_ENCRYPT) 79157416Smarkm ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID; 79257416Smarkm if (saveit) { 79357416Smarkm struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1]; 79457416Smarkm memcpy(kp->keyid,keyid, keylen); 79557416Smarkm kp->keylen = keylen; 79657416Smarkm } 79757416Smarkm 79857416Smarkm for (strp = &str_keyid[4]; keylen > 0; --keylen) { 79957416Smarkm if ((*strp++ = *keyid++) == IAC) 80057416Smarkm *strp++ = IAC; 80157416Smarkm } 80257416Smarkm *strp++ = IAC; 80357416Smarkm *strp++ = SE; 80457416Smarkm telnet_net_write(str_keyid, strp - str_keyid); 80557416Smarkm printsub('>', &str_keyid[2], strp - str_keyid - 2); 80657416Smarkm} 80757416Smarkm 80857416Smarkmvoid 80957416Smarkmencrypt_auto(int on) 81057416Smarkm{ 81157416Smarkm if (on < 0) 81257416Smarkm autoencrypt ^= 1; 81357416Smarkm else 81457416Smarkm autoencrypt = on ? 1 : 0; 81557416Smarkm} 81657416Smarkm 81757416Smarkmvoid 81857416Smarkmdecrypt_auto(int on) 81957416Smarkm{ 82057416Smarkm if (on < 0) 82157416Smarkm autodecrypt ^= 1; 82257416Smarkm else 82357416Smarkm autodecrypt = on ? 1 : 0; 82457416Smarkm} 82557416Smarkm 82657416Smarkmvoid 82757416Smarkmencrypt_start_output(int type) 82857416Smarkm{ 82957416Smarkm Encryptions *ep; 83057416Smarkm unsigned char *p; 83157416Smarkm int i; 83257416Smarkm 83357416Smarkm if (!(ep = findencryption(type))) { 83457416Smarkm if (encrypt_debug_mode) { 83557416Smarkm printf(">>>%s: Can't encrypt with type %s (%d)\r\n", 83657416Smarkm Name, 83757416Smarkm ENCTYPE_NAME_OK(type) 83857416Smarkm ? ENCTYPE_NAME(type) : "(unknown)", 83957416Smarkm type); 84057416Smarkm } 84157416Smarkm return; 84257416Smarkm } 84357416Smarkm if (ep->start) { 84457416Smarkm i = (*ep->start)(DIR_ENCRYPT, Server); 84557416Smarkm if (encrypt_debug_mode) { 84657416Smarkm printf(">>>%s: Encrypt start: %s (%d) %s\r\n", 847233294Sstas Name, 84857416Smarkm (i < 0) ? "failed" : 84957416Smarkm "initial negotiation in progress", 85057416Smarkm i, ENCTYPE_NAME(type)); 85157416Smarkm } 85257416Smarkm if (i) 85357416Smarkm return; 85457416Smarkm } 85557416Smarkm p = str_start + 3; 85657416Smarkm *p++ = ENCRYPT_START; 85757416Smarkm for (i = 0; i < ki[0].keylen; ++i) { 85857416Smarkm if ((*p++ = ki[0].keyid[i]) == IAC) 85957416Smarkm *p++ = IAC; 86057416Smarkm } 86157416Smarkm *p++ = IAC; 86257416Smarkm *p++ = SE; 86357416Smarkm telnet_net_write(str_start, p - str_start); 86457416Smarkm net_encrypt(); 86557416Smarkm printsub('>', &str_start[2], p - &str_start[2]); 86657416Smarkm /* 86757416Smarkm * If we are already encrypting in some mode, then 86857416Smarkm * encrypt the ring (which includes our request) in 86957416Smarkm * the old mode, mark it all as "clear text" and then 87057416Smarkm * switch to the new mode. 87157416Smarkm */ 87257416Smarkm encrypt_output = ep->output; 87357416Smarkm encrypt_mode = type; 87457416Smarkm if (encrypt_debug_mode) 87557416Smarkm printf(">>>%s: Started to encrypt output with type %s\r\n", 87657416Smarkm Name, ENCTYPE_NAME(type)); 87757416Smarkm if (encrypt_verbose) 87857416Smarkm printf("[ Output is now encrypted with type %s ]\r\n", 87957416Smarkm ENCTYPE_NAME(type)); 88057416Smarkm} 88157416Smarkm 88257416Smarkmvoid 88357416Smarkmencrypt_send_end(void) 88457416Smarkm{ 88557416Smarkm if (!encrypt_output) 88657416Smarkm return; 88757416Smarkm 88857416Smarkm str_end[3] = ENCRYPT_END; 88957416Smarkm telnet_net_write(str_end, sizeof(str_end)); 89057416Smarkm net_encrypt(); 89157416Smarkm printsub('>', &str_end[2], sizeof(str_end) - 2); 89257416Smarkm /* 89357416Smarkm * Encrypt the output buffer now because it will not be done by 89457416Smarkm * netflush... 89557416Smarkm */ 89657416Smarkm encrypt_output = 0; 89757416Smarkm if (encrypt_debug_mode) 89857416Smarkm printf(">>>%s: Output is back to clear text\r\n", Name); 89957416Smarkm if (encrypt_verbose) 90057416Smarkm printf("[ Output is now clear text ]\r\n"); 90157416Smarkm} 90257416Smarkm 90357416Smarkmvoid 90457416Smarkmencrypt_send_request_start(void) 90557416Smarkm{ 90657416Smarkm unsigned char *p; 90757416Smarkm int i; 90857416Smarkm 90957416Smarkm p = &str_start[3]; 91057416Smarkm *p++ = ENCRYPT_REQSTART; 91157416Smarkm for (i = 0; i < ki[1].keylen; ++i) { 91257416Smarkm if ((*p++ = ki[1].keyid[i]) == IAC) 91357416Smarkm *p++ = IAC; 91457416Smarkm } 91557416Smarkm *p++ = IAC; 91657416Smarkm *p++ = SE; 91757416Smarkm telnet_net_write(str_start, p - str_start); 91857416Smarkm printsub('>', &str_start[2], p - &str_start[2]); 91957416Smarkm if (encrypt_debug_mode) 92057416Smarkm printf(">>>%s: Request input to be encrypted\r\n", Name); 92157416Smarkm} 92257416Smarkm 92357416Smarkmvoid 92457416Smarkmencrypt_send_request_end(void) 92557416Smarkm{ 92657416Smarkm str_end[3] = ENCRYPT_REQEND; 92757416Smarkm telnet_net_write(str_end, sizeof(str_end)); 92857416Smarkm printsub('>', &str_end[2], sizeof(str_end) - 2); 92957416Smarkm 93057416Smarkm if (encrypt_debug_mode) 93157416Smarkm printf(">>>%s: Request input to be clear text\r\n", Name); 93257416Smarkm} 93357416Smarkm 93457416Smarkm 93557416Smarkmvoid encrypt_wait(void) 93657416Smarkm{ 93757416Smarkm if (encrypt_debug_mode) 93857416Smarkm printf(">>>%s: in encrypt_wait\r\n", Name); 93957416Smarkm if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt)) 94057416Smarkm return; 94157416Smarkm while (autoencrypt && !encrypt_output) 94257416Smarkm if (telnet_spin()) 94357416Smarkm return; 94457416Smarkm} 94557416Smarkm 94657416Smarkmint 94757416Smarkmencrypt_delay(void) 94857416Smarkm{ 94957416Smarkm if(!havesessionkey || 95057416Smarkm (I_SUPPORT_ENCRYPT & remote_supports_decrypt) == 0 || 95157416Smarkm (I_SUPPORT_DECRYPT & remote_supports_encrypt) == 0) 95257416Smarkm return 0; 95357416Smarkm if(!(encrypt_output && decrypt_input)) 95457416Smarkm return 1; 95557416Smarkm return 0; 95657416Smarkm} 95757416Smarkm 95890926Snectarint encrypt_is_encrypting() 95990926Snectar{ 96090926Snectar if (encrypt_output && decrypt_input) 96190926Snectar return 1; 96290926Snectar return 0; 96390926Snectar} 96490926Snectar 96557416Smarkmvoid 96657416Smarkmencrypt_debug(int mode) 96757416Smarkm{ 96857416Smarkm encrypt_debug_mode = mode; 96957416Smarkm} 97057416Smarkm 971233294Sstasvoid encrypt_gen_printsub(unsigned char *data, size_t cnt, 972233294Sstas unsigned char *buf, size_t buflen) 97357416Smarkm{ 97457416Smarkm char tbuf[16], *cp; 97557416Smarkm 97657416Smarkm cnt -= 2; 97757416Smarkm data += 2; 97857416Smarkm buf[buflen-1] = '\0'; 97957416Smarkm buf[buflen-2] = '*'; 98057416Smarkm buflen -= 2;; 98157416Smarkm for (; cnt > 0; cnt--, data++) { 98257416Smarkm snprintf(tbuf, sizeof(tbuf), " %d", *data); 98357416Smarkm for (cp = tbuf; *cp && buflen > 0; --buflen) 98457416Smarkm *buf++ = *cp++; 98557416Smarkm if (buflen <= 0) 98657416Smarkm return; 98757416Smarkm } 98857416Smarkm *buf = '\0'; 98957416Smarkm} 99057416Smarkm 99157416Smarkmvoid 992233294Sstasencrypt_printsub(unsigned char *data, size_t cnt, 993233294Sstas unsigned char *buf, size_t buflen) 99457416Smarkm{ 99557416Smarkm Encryptions *ep; 99657416Smarkm int type = data[1]; 99757416Smarkm 99857416Smarkm for (ep = encryptions; ep->type && ep->type != type; ep++) 99957416Smarkm ; 100057416Smarkm 100157416Smarkm if (ep->printsub) 100257416Smarkm (*ep->printsub)(data, cnt, buf, buflen); 100357416Smarkm else 100457416Smarkm encrypt_gen_printsub(data, cnt, buf, buflen); 100557416Smarkm} 100657416Smarkm#endif 1007