Path: blob/main/crypto/heimdal/appl/telnet/libtelnet/encrypt.c
34889 views
/*-1* Copyright (c) 1991, 19932* The Regents of the University of California. All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12* 3. All advertising materials mentioning features or use of this software13* must display the following acknowledgement:14* This product includes software developed by the University of15* California, Berkeley and its contributors.16* 4. Neither the name of the University nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233/*34* Copyright (C) 1990 by the Massachusetts Institute of Technology35*36* Export of this software from the United States of America is assumed37* to require a specific license from the United States Government.38* It is the responsibility of any person or organization contemplating39* export to obtain such a license before exporting.40*41* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and42* distribute this software and its documentation for any purpose and43* without fee is hereby granted, provided that the above copyright44* notice appear in all copies and that both that copyright notice and45* this permission notice appear in supporting documentation, and that46* the name of M.I.T. not be used in advertising or publicity pertaining47* to distribution of the software without specific, written prior48* permission. M.I.T. makes no representations about the suitability of49* this software for any purpose. It is provided "as is" without express50* or implied warranty.51*/525354#include <config.h>5556RCSID("$Id$");5758#if defined(ENCRYPTION)5960#define ENCRYPT_NAMES61#include <arpa/telnet.h>6263#include <stdio.h>64#include <stdlib.h>65#include <string.h>66#include <roken.h>67#ifdef SOCKS68#include <socks.h>69#endif7071#include "encrypt.h"72#include "misc.h"737475/*76* These functions pointers point to the current routines77* for encrypting and decrypting data.78*/79void (*encrypt_output) (unsigned char *, int);80int (*decrypt_input) (int);81char *nclearto;8283int encrypt_debug_mode = 0;84static int decrypt_mode = 0;85static int encrypt_mode = 0;86static int encrypt_verbose = 0;87static int autoencrypt = 0;88static int autodecrypt = 0;89static int havesessionkey = 0;90static int Server = 0;91static const char *Name = "Noname";9293#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0)9495static long i_support_encrypt = typemask(ENCTYPE_DES_CFB64)96| typemask(ENCTYPE_DES_OFB64);97static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64)98| typemask(ENCTYPE_DES_OFB64);99static long i_wont_support_encrypt = 0;100static long i_wont_support_decrypt = 0;101#define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt)102#define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt)103104static long remote_supports_encrypt = 0;105static long remote_supports_decrypt = 0;106107static Encryptions encryptions[] = {108#if defined(DES_ENCRYPTION)109{ "DES_CFB64", ENCTYPE_DES_CFB64,110cfb64_encrypt,111cfb64_decrypt,112cfb64_init,113cfb64_start,114cfb64_is,115cfb64_reply,116cfb64_session,117cfb64_keyid,118cfb64_printsub },119{ "DES_OFB64", ENCTYPE_DES_OFB64,120ofb64_encrypt,121ofb64_decrypt,122ofb64_init,123ofb64_start,124ofb64_is,125ofb64_reply,126ofb64_session,127ofb64_keyid,128ofb64_printsub },129#endif130{ 0, },131};132133static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT,134ENCRYPT_SUPPORT };135static unsigned char str_suplen = 0;136static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT };137static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };138139Encryptions *140findencryption(int type)141{142Encryptions *ep = encryptions;143144if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type)))145return(0);146while (ep->type && ep->type != type)147++ep;148return(ep->type ? ep : 0);149}150151Encryptions *152finddecryption(int type)153{154Encryptions *ep = encryptions;155156if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type)))157return(0);158while (ep->type && ep->type != type)159++ep;160return(ep->type ? ep : 0);161}162163#define MAXKEYLEN 64164165static struct key_info {166unsigned char keyid[MAXKEYLEN];167int keylen;168int dir;169int *modep;170Encryptions *(*getcrypt)();171} ki[2] = {172{ { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption },173{ { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption },174};175176void177encrypt_init(const char *name, int server)178{179Encryptions *ep = encryptions;180181Name = name;182Server = server;183i_support_encrypt = i_support_decrypt = 0;184remote_supports_encrypt = remote_supports_decrypt = 0;185encrypt_mode = 0;186decrypt_mode = 0;187encrypt_output = 0;188decrypt_input = 0;189#ifdef notdef190encrypt_verbose = !server;191#endif192193str_suplen = 4;194195while (ep->type) {196if (encrypt_debug_mode)197printf(">>>%s: I will support %s\r\n",198Name, ENCTYPE_NAME(ep->type));199i_support_encrypt |= typemask(ep->type);200i_support_decrypt |= typemask(ep->type);201if ((i_wont_support_decrypt & typemask(ep->type)) == 0)202if ((str_send[str_suplen++] = ep->type) == IAC)203str_send[str_suplen++] = IAC;204if (ep->init)205(*ep->init)(Server);206++ep;207}208str_send[str_suplen++] = IAC;209str_send[str_suplen++] = SE;210}211212void213encrypt_list_types(void)214{215Encryptions *ep = encryptions;216217printf("Valid encryption types:\n");218while (ep->type) {219printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type);220++ep;221}222}223224int225EncryptEnable(char *type, char *mode)226{227if (isprefix(type, "help") || isprefix(type, "?")) {228printf("Usage: encrypt enable <type> [input|output]\n");229encrypt_list_types();230return(0);231}232if (EncryptType(type, mode))233return(EncryptStart(mode));234return(0);235}236237int238EncryptDisable(char *type, char *mode)239{240Encryptions *ep;241int ret = 0;242243if (isprefix(type, "help") || isprefix(type, "?")) {244printf("Usage: encrypt disable <type> [input|output]\n");245encrypt_list_types();246} else if ((ep = (Encryptions *)genget(type, (char**)encryptions,247sizeof(Encryptions))) == 0) {248printf("%s: invalid encryption type\n", type);249} else if (Ambiguous(ep)) {250printf("Ambiguous type '%s'\n", type);251} else {252if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) {253if (decrypt_mode == ep->type)254EncryptStopInput();255i_wont_support_decrypt |= typemask(ep->type);256ret = 1;257}258if ((mode == 0) || (isprefix(mode, "output"))) {259if (encrypt_mode == ep->type)260EncryptStopOutput();261i_wont_support_encrypt |= typemask(ep->type);262ret = 1;263}264if (ret == 0)265printf("%s: invalid encryption mode\n", mode);266}267return(ret);268}269270int271EncryptType(char *type, char *mode)272{273Encryptions *ep;274int ret = 0;275276if (isprefix(type, "help") || isprefix(type, "?")) {277printf("Usage: encrypt type <type> [input|output]\n");278encrypt_list_types();279} else if ((ep = (Encryptions *)genget(type, (char**)encryptions,280sizeof(Encryptions))) == 0) {281printf("%s: invalid encryption type\n", type);282} else if (Ambiguous(ep)) {283printf("Ambiguous type '%s'\n", type);284} else {285if ((mode == 0) || isprefix(mode, "input")) {286decrypt_mode = ep->type;287i_wont_support_decrypt &= ~typemask(ep->type);288ret = 1;289}290if ((mode == 0) || isprefix(mode, "output")) {291encrypt_mode = ep->type;292i_wont_support_encrypt &= ~typemask(ep->type);293ret = 1;294}295if (ret == 0)296printf("%s: invalid encryption mode\n", mode);297}298return(ret);299}300301int302EncryptStart(char *mode)303{304int ret = 0;305if (mode) {306if (isprefix(mode, "input"))307return(EncryptStartInput());308if (isprefix(mode, "output"))309return(EncryptStartOutput());310if (isprefix(mode, "help") || isprefix(mode, "?")) {311printf("Usage: encrypt start [input|output]\n");312return(0);313}314printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);315return(0);316}317ret += EncryptStartInput();318ret += EncryptStartOutput();319return(ret);320}321322int323EncryptStartInput(void)324{325if (decrypt_mode) {326encrypt_send_request_start();327return(1);328}329printf("No previous decryption mode, decryption not enabled\r\n");330return(0);331}332333int334EncryptStartOutput(void)335{336if (encrypt_mode) {337encrypt_start_output(encrypt_mode);338return(1);339}340printf("No previous encryption mode, encryption not enabled\r\n");341return(0);342}343344int345EncryptStop(char *mode)346{347int ret = 0;348if (mode) {349if (isprefix(mode, "input"))350return(EncryptStopInput());351if (isprefix(mode, "output"))352return(EncryptStopOutput());353if (isprefix(mode, "help") || isprefix(mode, "?")) {354printf("Usage: encrypt stop [input|output]\n");355return(0);356}357printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);358return(0);359}360ret += EncryptStopInput();361ret += EncryptStopOutput();362return(ret);363}364365int366EncryptStopInput(void)367{368encrypt_send_request_end();369return(1);370}371372int373EncryptStopOutput(void)374{375encrypt_send_end();376return(1);377}378379void380encrypt_display(void)381{382printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n",383autoencrypt?"on":"off", autodecrypt?"on":"off");384385if (encrypt_output)386printf("Currently encrypting output with %s\r\n",387ENCTYPE_NAME(encrypt_mode));388else389printf("Currently not encrypting output\r\n");390391if (decrypt_input)392printf("Currently decrypting input with %s\r\n",393ENCTYPE_NAME(decrypt_mode));394else395printf("Currently not decrypting input\r\n");396}397398int399EncryptStatus(void)400{401printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n",402autoencrypt?"on":"off", autodecrypt?"on":"off");403404if (encrypt_output)405printf("Currently encrypting output with %s\r\n",406ENCTYPE_NAME(encrypt_mode));407else if (encrypt_mode) {408printf("Currently output is clear text.\r\n");409printf("Last encryption mode was %s\r\n",410ENCTYPE_NAME(encrypt_mode));411} else412printf("Currently not encrypting output\r\n");413414if (decrypt_input) {415printf("Currently decrypting input with %s\r\n",416ENCTYPE_NAME(decrypt_mode));417} else if (decrypt_mode) {418printf("Currently input is clear text.\r\n");419printf("Last decryption mode was %s\r\n",420ENCTYPE_NAME(decrypt_mode));421} else422printf("Currently not decrypting input\r\n");423424return 1;425}426427void428encrypt_send_support(void)429{430if (str_suplen) {431/*432* If the user has requested that decryption start433* immediatly, then send a "REQUEST START" before434* we negotiate the type.435*/436if (!Server && autodecrypt)437encrypt_send_request_start();438telnet_net_write(str_send, str_suplen);439printsub('>', &str_send[2], str_suplen - 2);440str_suplen = 0;441}442}443444int445EncryptDebug(int on)446{447if (on < 0)448encrypt_debug_mode ^= 1;449else450encrypt_debug_mode = on;451printf("Encryption debugging %s\r\n",452encrypt_debug_mode ? "enabled" : "disabled");453return(1);454}455456/* turn on verbose encryption, but dont keep telling the whole world457*/458void encrypt_verbose_quiet(int on)459{460if(on < 0)461encrypt_verbose ^= 1;462else463encrypt_verbose = on ? 1 : 0;464}465466int467EncryptVerbose(int on)468{469encrypt_verbose_quiet(on);470printf("Encryption %s verbose\r\n",471encrypt_verbose ? "is" : "is not");472return(1);473}474475int476EncryptAutoEnc(int on)477{478encrypt_auto(on);479printf("Automatic encryption of output is %s\r\n",480autoencrypt ? "enabled" : "disabled");481return(1);482}483484int485EncryptAutoDec(int on)486{487decrypt_auto(on);488printf("Automatic decryption of input is %s\r\n",489autodecrypt ? "enabled" : "disabled");490return(1);491}492493/* Called when we receive a WONT or a DONT ENCRYPT after we sent a DO494encrypt */495void496encrypt_not(void)497{498if (encrypt_verbose)499printf("[ Connection is NOT encrypted ]\r\n");500else501printf("\r\n*** Connection not encrypted! "502"Communication may be eavesdropped. ***\r\n");503}504505/*506* Called when ENCRYPT SUPPORT is received.507*/508void509encrypt_support(unsigned char *typelist, int cnt)510{511int type, use_type = 0;512Encryptions *ep;513514/*515* Forget anything the other side has previously told us.516*/517remote_supports_decrypt = 0;518519while (cnt-- > 0) {520type = *typelist++;521if (encrypt_debug_mode)522printf(">>>%s: He is supporting %s (%d)\r\n",523Name,524ENCTYPE_NAME(type), type);525if ((type < ENCTYPE_CNT) &&526(I_SUPPORT_ENCRYPT & typemask(type))) {527remote_supports_decrypt |= typemask(type);528if (use_type == 0)529use_type = type;530}531}532if (use_type) {533ep = findencryption(use_type);534if (!ep)535return;536type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;537if (encrypt_debug_mode)538printf(">>>%s: (*ep->start)() returned %d\r\n",539Name, type);540if (type < 0)541return;542encrypt_mode = use_type;543if (type == 0)544encrypt_start_output(use_type);545}546}547548void549encrypt_is(unsigned char *data, int cnt)550{551Encryptions *ep;552int type, ret;553554if (--cnt < 0)555return;556type = *data++;557if (type < ENCTYPE_CNT)558remote_supports_encrypt |= typemask(type);559if (!(ep = finddecryption(type))) {560if (encrypt_debug_mode)561printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",562Name,563ENCTYPE_NAME_OK(type)564? ENCTYPE_NAME(type) : "(unknown)",565type);566return;567}568if (!ep->is) {569if (encrypt_debug_mode)570printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",571Name,572ENCTYPE_NAME_OK(type)573? ENCTYPE_NAME(type) : "(unknown)",574type);575ret = 0;576} else {577ret = (*ep->is)(data, cnt);578if (encrypt_debug_mode)579printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt,580(ret < 0) ? "FAIL " :581(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);582}583if (ret < 0) {584autodecrypt = 0;585} else {586decrypt_mode = type;587if (ret == 0 && autodecrypt)588encrypt_send_request_start();589}590}591592void593encrypt_reply(unsigned char *data, int cnt)594{595Encryptions *ep;596int ret, type;597598if (--cnt < 0)599return;600type = *data++;601if (!(ep = findencryption(type))) {602if (encrypt_debug_mode)603printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",604Name,605ENCTYPE_NAME_OK(type)606? ENCTYPE_NAME(type) : "(unknown)",607type);608return;609}610if (!ep->reply) {611if (encrypt_debug_mode)612printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",613Name,614ENCTYPE_NAME_OK(type)615? ENCTYPE_NAME(type) : "(unknown)",616type);617ret = 0;618} else {619ret = (*ep->reply)(data, cnt);620if (encrypt_debug_mode)621printf("(*ep->reply)(%p, %d) returned %s(%d)\n",622data, cnt,623(ret < 0) ? "FAIL " :624(ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);625}626if (encrypt_debug_mode)627printf(">>>%s: encrypt_reply returned %d\n", Name, ret);628if (ret < 0) {629autoencrypt = 0;630} else {631encrypt_mode = type;632if (ret == 0 && autoencrypt)633encrypt_start_output(type);634}635}636637/*638* Called when ENCRYPT START is received.639*/640void641encrypt_start(unsigned char *data, int cnt)642{643Encryptions *ep;644645if (!decrypt_mode) {646/*647* Something is wrong. We should not get a START648* command without having already picked our649* decryption scheme. Send a REQUEST-END to650* attempt to clear the channel...651*/652printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);653encrypt_send_request_end();654return;655}656657if ((ep = finddecryption(decrypt_mode))) {658decrypt_input = ep->input;659if (encrypt_verbose)660printf("[ Input is now decrypted with type %s ]\r\n",661ENCTYPE_NAME(decrypt_mode));662if (encrypt_debug_mode)663printf(">>>%s: Start to decrypt input with type %s\r\n",664Name, ENCTYPE_NAME(decrypt_mode));665} else {666printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",667Name,668ENCTYPE_NAME_OK(decrypt_mode)669? ENCTYPE_NAME(decrypt_mode)670: "(unknown)",671decrypt_mode);672encrypt_send_request_end();673}674}675676void677encrypt_session_key(Session_Key *key, int server)678{679Encryptions *ep = encryptions;680681havesessionkey = 1;682683while (ep->type) {684if (ep->session)685(*ep->session)(key, server);686++ep;687}688}689690/*691* Called when ENCRYPT END is received.692*/693void694encrypt_end(void)695{696decrypt_input = 0;697if (encrypt_debug_mode)698printf(">>>%s: Input is back to clear text\r\n", Name);699if (encrypt_verbose)700printf("[ Input is now clear text ]\r\n");701}702703/*704* Called when ENCRYPT REQUEST-END is received.705*/706void707encrypt_request_end(void)708{709encrypt_send_end();710}711712/*713* Called when ENCRYPT REQUEST-START is received. If we receive714* this before a type is picked, then that indicates that the715* other side wants us to start encrypting data as soon as we716* can.717*/718void719encrypt_request_start(unsigned char *data, int cnt)720{721if (encrypt_mode == 0) {722if (Server)723autoencrypt = 1;724return;725}726encrypt_start_output(encrypt_mode);727}728729static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };730731static void732encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len)733{734Encryptions *ep;735int dir = kp->dir;736int ret = 0;737738if (len > MAXKEYLEN)739len = MAXKEYLEN;740741if (!(ep = (*kp->getcrypt)(*kp->modep))) {742if (len == 0)743return;744kp->keylen = 0;745} else if (len == 0) {746/*747* Empty option, indicates a failure.748*/749if (kp->keylen == 0)750return;751kp->keylen = 0;752if (ep->keyid)753(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);754755} else if ((len != kp->keylen) || (memcmp(keyid,kp->keyid,len) != 0)) {756/*757* Length or contents are different758*/759kp->keylen = len;760memcpy(kp->keyid,keyid, len);761if (ep->keyid)762(void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);763} else {764if (ep->keyid)765ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);766if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt)767encrypt_start_output(*kp->modep);768return;769}770771encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0);772}773774void encrypt_enc_keyid(unsigned char *keyid, int len)775{776encrypt_keyid(&ki[1], keyid, len);777}778779void encrypt_dec_keyid(unsigned char *keyid, int len)780{781encrypt_keyid(&ki[0], keyid, len);782}783784785void encrypt_send_keyid(int dir, unsigned char *keyid, int keylen, int saveit)786{787unsigned char *strp;788789str_keyid[3] = (dir == DIR_ENCRYPT)790? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;791if (saveit) {792struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1];793memcpy(kp->keyid,keyid, keylen);794kp->keylen = keylen;795}796797for (strp = &str_keyid[4]; keylen > 0; --keylen) {798if ((*strp++ = *keyid++) == IAC)799*strp++ = IAC;800}801*strp++ = IAC;802*strp++ = SE;803telnet_net_write(str_keyid, strp - str_keyid);804printsub('>', &str_keyid[2], strp - str_keyid - 2);805}806807void808encrypt_auto(int on)809{810if (on < 0)811autoencrypt ^= 1;812else813autoencrypt = on ? 1 : 0;814}815816void817decrypt_auto(int on)818{819if (on < 0)820autodecrypt ^= 1;821else822autodecrypt = on ? 1 : 0;823}824825void826encrypt_start_output(int type)827{828Encryptions *ep;829unsigned char *p;830int i;831832if (!(ep = findencryption(type))) {833if (encrypt_debug_mode) {834printf(">>>%s: Can't encrypt with type %s (%d)\r\n",835Name,836ENCTYPE_NAME_OK(type)837? ENCTYPE_NAME(type) : "(unknown)",838type);839}840return;841}842if (ep->start) {843i = (*ep->start)(DIR_ENCRYPT, Server);844if (encrypt_debug_mode) {845printf(">>>%s: Encrypt start: %s (%d) %s\r\n",846Name,847(i < 0) ? "failed" :848"initial negotiation in progress",849i, ENCTYPE_NAME(type));850}851if (i)852return;853}854p = str_start + 3;855*p++ = ENCRYPT_START;856for (i = 0; i < ki[0].keylen; ++i) {857if ((*p++ = ki[0].keyid[i]) == IAC)858*p++ = IAC;859}860*p++ = IAC;861*p++ = SE;862telnet_net_write(str_start, p - str_start);863net_encrypt();864printsub('>', &str_start[2], p - &str_start[2]);865/*866* If we are already encrypting in some mode, then867* encrypt the ring (which includes our request) in868* the old mode, mark it all as "clear text" and then869* switch to the new mode.870*/871encrypt_output = ep->output;872encrypt_mode = type;873if (encrypt_debug_mode)874printf(">>>%s: Started to encrypt output with type %s\r\n",875Name, ENCTYPE_NAME(type));876if (encrypt_verbose)877printf("[ Output is now encrypted with type %s ]\r\n",878ENCTYPE_NAME(type));879}880881void882encrypt_send_end(void)883{884if (!encrypt_output)885return;886887str_end[3] = ENCRYPT_END;888telnet_net_write(str_end, sizeof(str_end));889net_encrypt();890printsub('>', &str_end[2], sizeof(str_end) - 2);891/*892* Encrypt the output buffer now because it will not be done by893* netflush...894*/895encrypt_output = 0;896if (encrypt_debug_mode)897printf(">>>%s: Output is back to clear text\r\n", Name);898if (encrypt_verbose)899printf("[ Output is now clear text ]\r\n");900}901902void903encrypt_send_request_start(void)904{905unsigned char *p;906int i;907908p = &str_start[3];909*p++ = ENCRYPT_REQSTART;910for (i = 0; i < ki[1].keylen; ++i) {911if ((*p++ = ki[1].keyid[i]) == IAC)912*p++ = IAC;913}914*p++ = IAC;915*p++ = SE;916telnet_net_write(str_start, p - str_start);917printsub('>', &str_start[2], p - &str_start[2]);918if (encrypt_debug_mode)919printf(">>>%s: Request input to be encrypted\r\n", Name);920}921922void923encrypt_send_request_end(void)924{925str_end[3] = ENCRYPT_REQEND;926telnet_net_write(str_end, sizeof(str_end));927printsub('>', &str_end[2], sizeof(str_end) - 2);928929if (encrypt_debug_mode)930printf(">>>%s: Request input to be clear text\r\n", Name);931}932933934void encrypt_wait(void)935{936if (encrypt_debug_mode)937printf(">>>%s: in encrypt_wait\r\n", Name);938if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))939return;940while (autoencrypt && !encrypt_output)941if (telnet_spin())942return;943}944945int946encrypt_delay(void)947{948if(!havesessionkey ||949(I_SUPPORT_ENCRYPT & remote_supports_decrypt) == 0 ||950(I_SUPPORT_DECRYPT & remote_supports_encrypt) == 0)951return 0;952if(!(encrypt_output && decrypt_input))953return 1;954return 0;955}956957int encrypt_is_encrypting()958{959if (encrypt_output && decrypt_input)960return 1;961return 0;962}963964void965encrypt_debug(int mode)966{967encrypt_debug_mode = mode;968}969970void encrypt_gen_printsub(unsigned char *data, size_t cnt,971unsigned char *buf, size_t buflen)972{973char tbuf[16], *cp;974975cnt -= 2;976data += 2;977buf[buflen-1] = '\0';978buf[buflen-2] = '*';979buflen -= 2;;980for (; cnt > 0; cnt--, data++) {981snprintf(tbuf, sizeof(tbuf), " %d", *data);982for (cp = tbuf; *cp && buflen > 0; --buflen)983*buf++ = *cp++;984if (buflen <= 0)985return;986}987*buf = '\0';988}989990void991encrypt_printsub(unsigned char *data, size_t cnt,992unsigned char *buf, size_t buflen)993{994Encryptions *ep;995int type = data[1];996997for (ep = encryptions; ep->type && ep->type != type; ep++)998;9991000if (ep->printsub)1001(*ep->printsub)(data, cnt, buf, buflen);1002else1003encrypt_gen_printsub(data, cnt, buf, buflen);1004}1005#endif100610071008