146801Sdab /*- 246801Sdab * Copyright (c) 1991 The Regents of the University of California. 346801Sdab * All rights reserved. 446801Sdab * 546801Sdab * %sccs.include.redist.c% 646801Sdab */ 746801Sdab 846801Sdab #ifndef lint 9*57214Sdab static char sccsid[] = "@(#)encrypt.c 5.3 (Berkeley) 12/18/92"; 1046801Sdab #endif /* not lint */ 1146801Sdab 1246801Sdab /* 1346801Sdab * Copyright (C) 1990 by the Massachusetts Institute of Technology 1446801Sdab * 1546801Sdab * Export of this software from the United States of America is assumed 1646801Sdab * to require a specific license from the United States Government. 1746801Sdab * It is the responsibility of any person or organization contemplating 1846801Sdab * export to obtain such a license before exporting. 1946801Sdab * 2046801Sdab * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 2146801Sdab * distribute this software and its documentation for any purpose and 2246801Sdab * without fee is hereby granted, provided that the above copyright 2346801Sdab * notice appear in all copies and that both that copyright notice and 2446801Sdab * this permission notice appear in supporting documentation, and that 2546801Sdab * the name of M.I.T. not be used in advertising or publicity pertaining 2646801Sdab * to distribution of the software without specific, written prior 2746801Sdab * permission. M.I.T. makes no representations about the suitability of 2846801Sdab * this software for any purpose. It is provided "as is" without express 2946801Sdab * or implied warranty. 3046801Sdab */ 3146801Sdab 32*57214Sdab #if defined(ENCRYPTION) 3346801Sdab 3446801Sdab #define ENCRYPT_NAMES 3546801Sdab #include <arpa/telnet.h> 3646801Sdab 3746801Sdab #include "encrypt.h" 3846801Sdab #include "misc.h" 3946801Sdab 4046801Sdab #ifdef __STDC__ 4146801Sdab #include <stdlib.h> 4246801Sdab #endif 4346801Sdab #ifdef NO_STRING_H 4446801Sdab #include <strings.h> 4546801Sdab #else 4646801Sdab #include <string.h> 4746801Sdab #endif 4846801Sdab 4946801Sdab /* 5046801Sdab * These functions pointers point to the current routines 5146801Sdab * for encrypting and decrypting data. 5246801Sdab */ 5346801Sdab void (*encrypt_output) P((unsigned char *, int)); 5446801Sdab int (*decrypt_input) P((int)); 5546801Sdab 5646801Sdab int encrypt_debug_mode = 0; 5746801Sdab static int decrypt_mode = 0; 5846801Sdab static int encrypt_mode = 0; 5946801Sdab static int encrypt_verbose = 0; 6046801Sdab static int autoencrypt = 0; 6146801Sdab static int autodecrypt = 0; 6246801Sdab static int havesessionkey = 0; 6346801Sdab static int Server = 0; 6446801Sdab static char *Name = "Noname"; 6546801Sdab 6646801Sdab #define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) 6746801Sdab 6847612Sdab static long i_support_encrypt = typemask(ENCTYPE_DES_CFB64) 6947612Sdab | typemask(ENCTYPE_DES_OFB64); 7047612Sdab static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64) 7147612Sdab | typemask(ENCTYPE_DES_OFB64); 7247612Sdab static long i_wont_support_encrypt = 0; 7347612Sdab static long i_wont_support_decrypt = 0; 7447612Sdab #define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt) 7547612Sdab #define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt) 7647612Sdab 7746801Sdab static long remote_supports_encrypt = 0; 7846801Sdab static long remote_supports_decrypt = 0; 7946801Sdab 8046801Sdab static Encryptions encryptions[] = { 81*57214Sdab #if defined(DES_ENCRYPTION) 8247612Sdab { "DES_CFB64", ENCTYPE_DES_CFB64, 8347612Sdab cfb64_encrypt, 8447612Sdab cfb64_decrypt, 8547612Sdab cfb64_init, 8647612Sdab cfb64_start, 8747612Sdab cfb64_is, 8847612Sdab cfb64_reply, 8947612Sdab cfb64_session, 9047612Sdab cfb64_keyid, 9147612Sdab cfb64_printsub }, 9247612Sdab { "DES_OFB64", ENCTYPE_DES_OFB64, 9347612Sdab ofb64_encrypt, 9447612Sdab ofb64_decrypt, 9547612Sdab ofb64_init, 9647612Sdab ofb64_start, 9747612Sdab ofb64_is, 9847612Sdab ofb64_reply, 9947612Sdab ofb64_session, 10047612Sdab ofb64_keyid, 10147612Sdab ofb64_printsub }, 10246801Sdab #endif 10346801Sdab { 0, }, 10446801Sdab }; 10546801Sdab 10646801Sdab static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT, 10747612Sdab ENCRYPT_SUPPORT }; 10846801Sdab static unsigned char str_suplen = 0; 10947612Sdab static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT }; 11046801Sdab static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE }; 11146801Sdab 11246801Sdab Encryptions * 11346801Sdab findencryption(type) 11446801Sdab int type; 11546801Sdab { 11646801Sdab Encryptions *ep = encryptions; 11746801Sdab 11847612Sdab if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type))) 11946801Sdab return(0); 12046801Sdab while (ep->type && ep->type != type) 12146801Sdab ++ep; 12246801Sdab return(ep->type ? ep : 0); 12346801Sdab } 12446801Sdab 12546801Sdab Encryptions * 12646801Sdab finddecryption(type) 12746801Sdab int type; 12846801Sdab { 12946801Sdab Encryptions *ep = encryptions; 13046801Sdab 13147612Sdab if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type))) 13246801Sdab return(0); 13346801Sdab while (ep->type && ep->type != type) 13446801Sdab ++ep; 13546801Sdab return(ep->type ? ep : 0); 13646801Sdab } 13746801Sdab 13847612Sdab #define MAXKEYLEN 64 13947612Sdab 14047612Sdab static struct key_info { 14147612Sdab unsigned char keyid[MAXKEYLEN]; 14247612Sdab int keylen; 14347612Sdab int dir; 14447612Sdab int *modep; 14547612Sdab Encryptions *(*getcrypt)(); 14647612Sdab } ki[2] = { 14747612Sdab { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption }, 14847612Sdab { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption }, 14947612Sdab }; 15047612Sdab 15146801Sdab void 15246801Sdab encrypt_init(name, server) 15346801Sdab char *name; 15446801Sdab int server; 15546801Sdab { 15646801Sdab Encryptions *ep = encryptions; 15746801Sdab 15846801Sdab Name = name; 15946801Sdab Server = server; 16046801Sdab i_support_encrypt = i_support_decrypt = 0; 16146801Sdab remote_supports_encrypt = remote_supports_decrypt = 0; 16246801Sdab encrypt_mode = 0; 16346801Sdab decrypt_mode = 0; 16446801Sdab encrypt_output = 0; 16546801Sdab decrypt_input = 0; 16646801Sdab #ifdef notdef 16746801Sdab encrypt_verbose = !server; 16846801Sdab #endif 16946801Sdab 17046801Sdab str_suplen = 4; 17146801Sdab 17246801Sdab while (ep->type) { 17346801Sdab if (encrypt_debug_mode) 17446801Sdab printf(">>>%s: I will support %s\r\n", 17546801Sdab Name, ENCTYPE_NAME(ep->type)); 17646801Sdab i_support_encrypt |= typemask(ep->type); 17746801Sdab i_support_decrypt |= typemask(ep->type); 17847612Sdab if ((i_wont_support_decrypt & typemask(ep->type)) == 0) 17947612Sdab if ((str_send[str_suplen++] = ep->type) == IAC) 18047612Sdab str_send[str_suplen++] = IAC; 18146801Sdab if (ep->init) 18246801Sdab (*ep->init)(Server); 18346801Sdab ++ep; 18446801Sdab } 18546801Sdab str_send[str_suplen++] = IAC; 18646801Sdab str_send[str_suplen++] = SE; 18746801Sdab } 18846801Sdab 18946801Sdab void 19046801Sdab encrypt_list_types() 19146801Sdab { 19246801Sdab Encryptions *ep = encryptions; 19346801Sdab 19446801Sdab printf("Valid encryption types:\n"); 19546801Sdab while (ep->type) { 19647612Sdab printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type); 19746801Sdab ++ep; 19846801Sdab } 19946801Sdab } 20046801Sdab 20146801Sdab int 20246801Sdab EncryptEnable(type, mode) 20346801Sdab char *type, *mode; 20446801Sdab { 20546801Sdab if (isprefix(type, "help") || isprefix(type, "?")) { 20646801Sdab printf("Usage: encrypt enable <type> [input|output]\n"); 20746801Sdab encrypt_list_types(); 20846801Sdab return(0); 20946801Sdab } 21046801Sdab if (EncryptType(type, mode)) 21146801Sdab return(EncryptStart(mode)); 21246801Sdab return(0); 21346801Sdab } 21446801Sdab 21546801Sdab int 21647612Sdab EncryptDisable(type, mode) 21747612Sdab char *type, *mode; 21847612Sdab { 21947612Sdab register Encryptions *ep; 22047612Sdab int ret = 0; 22147612Sdab 22247612Sdab if (isprefix(type, "help") || isprefix(type, "?")) { 22347612Sdab printf("Usage: encrypt disable <type> [input|output]\n"); 22447612Sdab encrypt_list_types(); 22547612Sdab } else if ((ep = (Encryptions *)genget(type, encryptions, 22647612Sdab sizeof(Encryptions))) == 0) { 22747612Sdab printf("%s: invalid encryption type\n", type); 22847612Sdab } else if (Ambiguous(ep)) { 22947612Sdab printf("Ambiguous type '%s'\n", type); 23047612Sdab } else { 23147612Sdab if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) { 23247612Sdab if (decrypt_mode == ep->type) 23347612Sdab EncryptStopInput(); 23447612Sdab i_wont_support_decrypt |= typemask(ep->type); 23547612Sdab ret = 1; 23647612Sdab } 23747612Sdab if ((mode == 0) || (isprefix(mode, "output"))) { 23847612Sdab if (encrypt_mode == ep->type) 23947612Sdab EncryptStopOutput(); 24047612Sdab i_wont_support_encrypt |= typemask(ep->type); 24147612Sdab ret = 1; 24247612Sdab } 24347612Sdab if (ret == 0) 24447612Sdab printf("%s: invalid encryption mode\n", mode); 24547612Sdab } 24647612Sdab return(ret); 24747612Sdab } 24847612Sdab 24947612Sdab int 25046801Sdab EncryptType(type, mode) 25146801Sdab char *type; 25246801Sdab char *mode; 25346801Sdab { 25446801Sdab register Encryptions *ep; 25547612Sdab int ret = 0; 25646801Sdab 25746801Sdab if (isprefix(type, "help") || isprefix(type, "?")) { 25846801Sdab printf("Usage: encrypt type <type> [input|output]\n"); 25946801Sdab encrypt_list_types(); 26047612Sdab } else if ((ep = (Encryptions *)genget(type, encryptions, 26147612Sdab sizeof(Encryptions))) == 0) { 26246801Sdab printf("%s: invalid encryption type\n", type); 26347612Sdab } else if (Ambiguous(ep)) { 26446801Sdab printf("Ambiguous type '%s'\n", type); 26547612Sdab } else { 26647612Sdab if ((mode == 0) || isprefix(mode, "input")) { 26746801Sdab decrypt_mode = ep->type; 26847612Sdab i_wont_support_decrypt &= ~typemask(ep->type); 26947612Sdab ret = 1; 27047612Sdab } 27147612Sdab if ((mode == 0) || isprefix(mode, "output")) { 27246801Sdab encrypt_mode = ep->type; 27347612Sdab i_wont_support_encrypt &= ~typemask(ep->type); 27447612Sdab ret = 1; 27547612Sdab } 27647612Sdab if (ret == 0) 27746801Sdab printf("%s: invalid encryption mode\n", mode); 27847612Sdab } 27947612Sdab return(ret); 28046801Sdab } 28146801Sdab 28246801Sdab int 28346801Sdab EncryptStart(mode) 28446801Sdab char *mode; 28546801Sdab { 28646801Sdab register int ret = 0; 28746801Sdab if (mode) { 28846801Sdab if (isprefix(mode, "input")) 28946801Sdab return(EncryptStartInput()); 29046801Sdab if (isprefix(mode, "output")) 29146801Sdab return(EncryptStartOutput()); 29246801Sdab if (isprefix(mode, "help") || isprefix(mode, "?")) { 29346801Sdab printf("Usage: encrypt start [input|output]\n"); 29446801Sdab return(0); 29546801Sdab } 29646801Sdab printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode); 29746801Sdab return(0); 29846801Sdab } 29946801Sdab ret += EncryptStartInput(); 30046801Sdab ret += EncryptStartOutput(); 30146801Sdab return(ret); 30246801Sdab } 30346801Sdab 30446801Sdab int 30546801Sdab EncryptStartInput() 30646801Sdab { 30746801Sdab if (decrypt_mode) { 30846801Sdab encrypt_send_request_start(); 30946801Sdab return(1); 31046801Sdab } 31146801Sdab printf("No previous decryption mode, decryption not enabled\r\n"); 31246801Sdab return(0); 31346801Sdab } 31446801Sdab 31546801Sdab int 31646801Sdab EncryptStartOutput() 31746801Sdab { 31846801Sdab if (encrypt_mode) { 31946801Sdab encrypt_start_output(encrypt_mode); 32046801Sdab return(1); 32146801Sdab } 32246801Sdab printf("No previous encryption mode, encryption not enabled\r\n"); 32346801Sdab return(0); 32446801Sdab } 32546801Sdab 32646801Sdab int 32746801Sdab EncryptStop(mode) 32846801Sdab char *mode; 32946801Sdab { 33046801Sdab int ret = 0; 33146801Sdab if (mode) { 33246801Sdab if (isprefix(mode, "input")) 33346801Sdab return(EncryptStopInput()); 33446801Sdab if (isprefix(mode, "output")) 33546801Sdab return(EncryptStopOutput()); 33646801Sdab if (isprefix(mode, "help") || isprefix(mode, "?")) { 33746801Sdab printf("Usage: encrypt stop [input|output]\n"); 33846801Sdab return(0); 33946801Sdab } 34046801Sdab printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode); 34146801Sdab return(0); 34246801Sdab } 34346801Sdab ret += EncryptStopInput(); 34446801Sdab ret += EncryptStopOutput(); 34546801Sdab return(ret); 34646801Sdab } 34746801Sdab 34846801Sdab int 34946801Sdab EncryptStopInput() 35046801Sdab { 35146801Sdab encrypt_send_request_end(); 35246801Sdab return(1); 35346801Sdab } 35446801Sdab 35546801Sdab int 35646801Sdab EncryptStopOutput() 35746801Sdab { 35846801Sdab encrypt_send_end(); 35946801Sdab return(1); 36046801Sdab } 36146801Sdab 36246801Sdab void 36346801Sdab encrypt_display() 36446801Sdab { 36546801Sdab if (encrypt_output) 36646801Sdab printf("Currently encrypting output with %s\r\n", 36746801Sdab ENCTYPE_NAME(encrypt_mode)); 36846801Sdab if (decrypt_input) 36946801Sdab printf("Currently decrypting input with %s\r\n", 37046801Sdab ENCTYPE_NAME(decrypt_mode)); 37146801Sdab } 37246801Sdab 37346801Sdab int 37446801Sdab EncryptStatus() 37546801Sdab { 37646801Sdab if (encrypt_output) 37746801Sdab printf("Currently encrypting output with %s\r\n", 37846801Sdab ENCTYPE_NAME(encrypt_mode)); 37946801Sdab else if (encrypt_mode) { 38046801Sdab printf("Currently output is clear text.\r\n"); 38146801Sdab printf("Last encryption mode was %s\r\n", 38246801Sdab ENCTYPE_NAME(encrypt_mode)); 38346801Sdab } 38446801Sdab if (decrypt_input) { 38546801Sdab printf("Currently decrypting input with %s\r\n", 38646801Sdab ENCTYPE_NAME(decrypt_mode)); 38746801Sdab } else if (decrypt_mode) { 38846801Sdab printf("Currently input is clear text.\r\n"); 38946801Sdab printf("Last decryption mode was %s\r\n", 39046801Sdab ENCTYPE_NAME(decrypt_mode)); 39146801Sdab } 39246801Sdab return 1; 39346801Sdab } 39446801Sdab 39546801Sdab void 39646801Sdab encrypt_send_support() 39746801Sdab { 39846801Sdab if (str_suplen) { 39946801Sdab /* 40046801Sdab * If the user has requested that decryption start 40146801Sdab * immediatly, then send a "REQUEST START" before 40246801Sdab * we negotiate the type. 40346801Sdab */ 40446801Sdab if (!Server && autodecrypt) 40546801Sdab encrypt_send_request_start(); 40646801Sdab net_write(str_send, str_suplen); 40746801Sdab printsub('>', &str_send[2], str_suplen - 2); 40846801Sdab str_suplen = 0; 40946801Sdab } 41046801Sdab } 41146801Sdab 41246801Sdab int 41347612Sdab EncryptDebug(on) 41447612Sdab int on; 41546801Sdab { 41647612Sdab if (on < 0) 41747612Sdab encrypt_debug_mode ^= 1; 41847612Sdab else 41947612Sdab encrypt_debug_mode = on; 42046801Sdab printf("Encryption debugging %s\r\n", 42146801Sdab encrypt_debug_mode ? "enabled" : "disabled"); 42246801Sdab return(1); 42346801Sdab } 42446801Sdab 42546801Sdab int 42647612Sdab EncryptVerbose(on) 42747612Sdab int on; 42846801Sdab { 42947612Sdab if (on < 0) 43047612Sdab encrypt_verbose ^= 1; 43147612Sdab else 43247612Sdab encrypt_verbose = on; 43346801Sdab printf("Encryption %s verbose\r\n", 43446801Sdab encrypt_verbose ? "is" : "is not"); 43546801Sdab return(1); 43646801Sdab } 43746801Sdab 43846801Sdab int 43947612Sdab EncryptAutoEnc(on) 44047612Sdab int on; 44146801Sdab { 44247612Sdab encrypt_auto(on); 44347612Sdab printf("Automatic encryption of output is %s\r\n", 44446801Sdab autoencrypt ? "enabled" : "disabled"); 44546801Sdab return(1); 44646801Sdab } 44746801Sdab 44847612Sdab int 44947612Sdab EncryptAutoDec(on) 45047612Sdab int on; 45147612Sdab { 45247612Sdab decrypt_auto(on); 45347612Sdab printf("Automatic decryption of input is %s\r\n", 45447612Sdab autodecrypt ? "enabled" : "disabled"); 45547612Sdab return(1); 45647612Sdab } 45746801Sdab 45846801Sdab /* 45946801Sdab * Called when ENCRYPT SUPPORT is received. 46046801Sdab */ 46146801Sdab void 46246801Sdab encrypt_support(typelist, cnt) 46346801Sdab unsigned char *typelist; 46446801Sdab int cnt; 46546801Sdab { 46646801Sdab register int type, use_type = 0; 46746801Sdab Encryptions *ep; 46846801Sdab 46946801Sdab /* 47046801Sdab * Forget anything the other side has previously told us. 47146801Sdab */ 47246801Sdab remote_supports_decrypt = 0; 47346801Sdab 47446801Sdab while (cnt-- > 0) { 47546801Sdab type = *typelist++; 47646801Sdab if (encrypt_debug_mode) 47746801Sdab printf(">>>%s: He is supporting %s (%d)\r\n", 47846801Sdab Name, 47946801Sdab ENCTYPE_NAME(type), type); 48046801Sdab if ((type < ENCTYPE_CNT) && 48147612Sdab (I_SUPPORT_ENCRYPT & typemask(type))) { 48246801Sdab remote_supports_decrypt |= typemask(type); 48346801Sdab if (use_type == 0) 48446801Sdab use_type = type; 48546801Sdab } 48646801Sdab } 48746801Sdab if (use_type) { 48846801Sdab ep = findencryption(use_type); 48946801Sdab if (!ep) 49046801Sdab return; 49146801Sdab type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0; 49246801Sdab if (encrypt_debug_mode) 49346801Sdab printf(">>>%s: (*ep->start)() returned %d\r\n", 49446801Sdab Name, type); 49546801Sdab if (type < 0) 49646801Sdab return; 49747612Sdab encrypt_mode = use_type; 49846801Sdab if (type == 0) 49946801Sdab encrypt_start_output(use_type); 50046801Sdab } 50146801Sdab } 50246801Sdab 50346801Sdab void 50446801Sdab encrypt_is(data, cnt) 50546801Sdab unsigned char *data; 50646801Sdab int cnt; 50746801Sdab { 50846801Sdab Encryptions *ep; 50946801Sdab register int type, ret; 51046801Sdab 51146801Sdab if (--cnt < 0) 51246801Sdab return; 51346801Sdab type = *data++; 51446801Sdab if (type < ENCTYPE_CNT) 51546801Sdab remote_supports_encrypt |= typemask(type); 51646801Sdab if (!(ep = finddecryption(type))) { 51746801Sdab if (encrypt_debug_mode) 51846801Sdab printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", 51946801Sdab Name, 52047612Sdab ENCTYPE_NAME_OK(type) 52147612Sdab ? ENCTYPE_NAME(type) : "(unknown)", 52247612Sdab type); 52346801Sdab return; 52446801Sdab } 52546801Sdab if (!ep->is) { 52646801Sdab if (encrypt_debug_mode) 52746801Sdab printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", 52846801Sdab Name, 52947612Sdab ENCTYPE_NAME_OK(type) 53047612Sdab ? ENCTYPE_NAME(type) : "(unknown)", 53147612Sdab type); 53246801Sdab ret = 0; 53346801Sdab } else { 53446801Sdab ret = (*ep->is)(data, cnt); 53547612Sdab if (encrypt_debug_mode) 53647612Sdab printf("(*ep->is)(%x, %d) returned %s(%d)\n", data, cnt, 53747612Sdab (ret < 0) ? "FAIL " : 53847612Sdab (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); 53946801Sdab } 54046801Sdab if (ret < 0) { 54146801Sdab autodecrypt = 0; 54246801Sdab } else { 54346801Sdab decrypt_mode = type; 54446801Sdab if (ret == 0 && autodecrypt) 54546801Sdab encrypt_send_request_start(); 54646801Sdab } 54746801Sdab } 54846801Sdab 54946801Sdab void 55046801Sdab encrypt_reply(data, cnt) 55146801Sdab unsigned char *data; 55246801Sdab int cnt; 55346801Sdab { 55446801Sdab Encryptions *ep; 55546801Sdab register int ret, type; 55646801Sdab 55746801Sdab if (--cnt < 0) 55846801Sdab return; 55946801Sdab type = *data++; 56046801Sdab if (!(ep = findencryption(type))) { 56146801Sdab if (encrypt_debug_mode) 56246801Sdab printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", 56346801Sdab Name, 56447612Sdab ENCTYPE_NAME_OK(type) 56547612Sdab ? ENCTYPE_NAME(type) : "(unknown)", 56647612Sdab type); 56746801Sdab return; 56846801Sdab } 56946801Sdab if (!ep->reply) { 57046801Sdab if (encrypt_debug_mode) 57146801Sdab printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", 57246801Sdab Name, 57347612Sdab ENCTYPE_NAME_OK(type) 57447612Sdab ? ENCTYPE_NAME(type) : "(unknown)", 57547612Sdab type); 57646801Sdab ret = 0; 57746801Sdab } else { 57846801Sdab ret = (*ep->reply)(data, cnt); 57947612Sdab if (encrypt_debug_mode) 58047612Sdab printf("(*ep->reply)(%x, %d) returned %s(%d)\n", 58147612Sdab data, cnt, 58247612Sdab (ret < 0) ? "FAIL " : 58347612Sdab (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); 58446801Sdab } 58546801Sdab if (encrypt_debug_mode) 58646801Sdab printf(">>>%s: encrypt_reply returned %d\n", Name, ret); 58746801Sdab if (ret < 0) { 58846801Sdab autoencrypt = 0; 58946801Sdab } else { 59046801Sdab encrypt_mode = type; 59146801Sdab if (ret == 0 && autoencrypt) 59246801Sdab encrypt_start_output(type); 59346801Sdab } 59446801Sdab } 59546801Sdab 59646801Sdab /* 59746801Sdab * Called when a ENCRYPT START command is received. 59846801Sdab */ 59946801Sdab void 60047612Sdab encrypt_start(data, cnt) 60147612Sdab unsigned char *data; 60247612Sdab int cnt; 60346801Sdab { 60446801Sdab Encryptions *ep; 60546801Sdab 60646801Sdab if (!decrypt_mode) { 60746801Sdab /* 60846801Sdab * Something is wrong. We should not get a START 60946801Sdab * command without having already picked our 61046801Sdab * decryption scheme. Send a REQUEST-END to 61146801Sdab * attempt to clear the channel... 61246801Sdab */ 61346801Sdab printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name); 61446801Sdab encrypt_send_request_end(); 61546801Sdab return; 61646801Sdab } 61746801Sdab 61846801Sdab if (ep = finddecryption(decrypt_mode)) { 61946801Sdab decrypt_input = ep->input; 62046801Sdab if (encrypt_verbose) 62146801Sdab printf("[ Input is now decrypted with type %s ]\r\n", 62246801Sdab ENCTYPE_NAME(decrypt_mode)); 62346801Sdab if (encrypt_debug_mode) 62446801Sdab printf(">>>%s: Start to decrypt input with type %s\r\n", 62546801Sdab Name, ENCTYPE_NAME(decrypt_mode)); 62646801Sdab } else { 62746801Sdab printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n", 62847612Sdab Name, 62947612Sdab ENCTYPE_NAME_OK(decrypt_mode) 63047612Sdab ? ENCTYPE_NAME(decrypt_mode) 63147612Sdab : "(unknown)", 63247612Sdab decrypt_mode); 63346801Sdab encrypt_send_request_end(); 63446801Sdab } 63546801Sdab } 63646801Sdab 63746801Sdab void 63846801Sdab encrypt_session_key(key, server) 63946801Sdab Session_Key *key; 64046801Sdab int server; 64146801Sdab { 64246801Sdab Encryptions *ep = encryptions; 64346801Sdab 64446801Sdab havesessionkey = 1; 64546801Sdab 64646801Sdab while (ep->type) { 64746801Sdab if (ep->session) 64846801Sdab (*ep->session)(key, server); 649*57214Sdab #ifdef notdef 650*57214Sdab if (!encrypt_output && autoencrypt && !server) 651*57214Sdab encrypt_start_output(ep->type); 652*57214Sdab if (!decrypt_input && autodecrypt && !server) 653*57214Sdab encrypt_send_request_start(); 654*57214Sdab #endif 65546801Sdab ++ep; 65646801Sdab } 65746801Sdab } 65846801Sdab 65946801Sdab /* 66046801Sdab * Called when ENCRYPT END is received. 66146801Sdab */ 66246801Sdab void 66346801Sdab encrypt_end() 66446801Sdab { 66546801Sdab decrypt_input = 0; 66646801Sdab if (encrypt_debug_mode) 66746801Sdab printf(">>>%s: Input is back to clear text\r\n", Name); 66846801Sdab if (encrypt_verbose) 66946801Sdab printf("[ Input is now clear text ]\r\n"); 67046801Sdab } 67146801Sdab 67246801Sdab /* 67346801Sdab * Called when ENCRYPT REQUEST-END is received. 67446801Sdab */ 67546801Sdab void 67646801Sdab encrypt_request_end() 67746801Sdab { 67846801Sdab encrypt_send_end(); 67946801Sdab } 68046801Sdab 68146801Sdab /* 68246801Sdab * Called when ENCRYPT REQUEST-START is received. If we receive 68346801Sdab * this before a type is picked, then that indicates that the 68446801Sdab * other side wants us to start encrypting data as soon as we 68546801Sdab * can. 68646801Sdab */ 68746801Sdab void 68847612Sdab encrypt_request_start(data, cnt) 68947612Sdab unsigned char *data; 69047612Sdab int cnt; 69146801Sdab { 69247612Sdab if (encrypt_mode == 0) { 69347612Sdab if (Server) 69447612Sdab autoencrypt = 1; 69546801Sdab return; 69646801Sdab } 69746801Sdab encrypt_start_output(encrypt_mode); 69846801Sdab } 69946801Sdab 70047612Sdab static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT }; 70147612Sdab 70247612Sdab encrypt_enc_keyid(keyid, len) 70347612Sdab unsigned char *keyid; 70447612Sdab int len; 70547612Sdab { 70647612Sdab encrypt_keyid(&ki[1], keyid, len); 70747612Sdab } 70847612Sdab 70947612Sdab encrypt_dec_keyid(keyid, len) 71047612Sdab unsigned char *keyid; 71147612Sdab int len; 71247612Sdab { 71347612Sdab encrypt_keyid(&ki[0], keyid, len); 71447612Sdab } 71547612Sdab 71647612Sdab encrypt_keyid(kp, keyid, len) 71747612Sdab struct key_info *kp; 71847612Sdab unsigned char *keyid; 71947612Sdab int len; 72047612Sdab { 72147612Sdab Encryptions *ep; 72247612Sdab unsigned char *strp, *cp; 72347612Sdab int dir = kp->dir; 72447612Sdab register int ret = 0; 72547612Sdab 72647612Sdab if (!(ep = (*kp->getcrypt)(*kp->modep))) { 72747612Sdab if (len == 0) 72847612Sdab return; 72947612Sdab kp->keylen = 0; 73047612Sdab } else if (len == 0) { 73147612Sdab /* 73247612Sdab * Empty option, indicates a failure. 73347612Sdab */ 73447612Sdab if (kp->keylen == 0) 73547612Sdab return; 73647612Sdab kp->keylen = 0; 73747612Sdab if (ep->keyid) 73847612Sdab (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); 73947612Sdab 74047612Sdab } else if ((len != kp->keylen) || (bcmp(keyid, kp->keyid, len) != 0)) { 74147612Sdab /* 74247612Sdab * Length or contents are different 74347612Sdab */ 74447612Sdab kp->keylen = len; 74547612Sdab bcopy(keyid, kp->keyid, len); 74647612Sdab if (ep->keyid) 74747612Sdab (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); 74847612Sdab } else { 74947612Sdab if (ep->keyid) 75047612Sdab ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen); 75147612Sdab if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt) 75247612Sdab encrypt_start_output(*kp->modep); 75347612Sdab return; 75447612Sdab } 75547612Sdab 75647612Sdab encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0); 75747612Sdab } 75847612Sdab 75946801Sdab void 76047612Sdab encrypt_send_keyid(dir, keyid, keylen, saveit) 76147612Sdab int dir; 76247612Sdab unsigned char *keyid; 76347612Sdab int keylen; 76447612Sdab int saveit; 76546801Sdab { 76647612Sdab unsigned char *strp; 76747612Sdab 76847612Sdab str_keyid[3] = (dir == DIR_ENCRYPT) 76947612Sdab ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID; 77047612Sdab if (saveit) { 77147612Sdab struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1]; 77247612Sdab bcopy(keyid, kp->keyid, keylen); 77347612Sdab kp->keylen = keylen; 77447612Sdab } 77547612Sdab 77647612Sdab for (strp = &str_keyid[4]; keylen > 0; --keylen) { 77747612Sdab if ((*strp++ = *keyid++) == IAC) 77847612Sdab *strp++ = IAC; 77947612Sdab } 78047612Sdab *strp++ = IAC; 78147612Sdab *strp++ = SE; 78247612Sdab net_write(str_keyid, strp - str_keyid); 78347612Sdab printsub('>', &str_keyid[2], strp - str_keyid - 2); 78446801Sdab } 78546801Sdab 78646801Sdab void 78747612Sdab encrypt_auto(on) 78847612Sdab int on; 78947612Sdab { 79047612Sdab if (on < 0) 79147612Sdab autoencrypt ^= 1; 79247612Sdab else 79347612Sdab autoencrypt = on ? 1 : 0; 79447612Sdab } 79547612Sdab 79647612Sdab void 79747612Sdab decrypt_auto(on) 79847612Sdab int on; 79947612Sdab { 80047612Sdab if (on < 0) 80147612Sdab autodecrypt ^= 1; 80247612Sdab else 80347612Sdab autodecrypt = on ? 1 : 0; 80447612Sdab } 80547612Sdab 80647612Sdab void 80746801Sdab encrypt_start_output(type) 80846801Sdab int type; 80946801Sdab { 81046801Sdab Encryptions *ep; 81147612Sdab register unsigned char *p; 81247612Sdab register int i; 81346801Sdab 81446801Sdab if (!(ep = findencryption(type))) { 81546801Sdab if (encrypt_debug_mode) { 81647612Sdab printf(">>>%s: Can't encrypt with type %s (%d)\r\n", 81746801Sdab Name, 81847612Sdab ENCTYPE_NAME_OK(type) 81947612Sdab ? ENCTYPE_NAME(type) : "(unknown)", 82047612Sdab type); 82146801Sdab } 82246801Sdab return; 82346801Sdab } 82446801Sdab if (ep->start) { 82547612Sdab i = (*ep->start)(DIR_ENCRYPT, Server); 82647612Sdab if (encrypt_debug_mode) { 82747612Sdab printf(">>>%s: Encrypt start: %s (%d) %s\r\n", 82847612Sdab Name, 82947612Sdab (i < 0) ? "failed" : 83047612Sdab "initial negotiation in progress", 83147612Sdab i, ENCTYPE_NAME(type)); 83247612Sdab } 83347612Sdab if (i) 83446801Sdab return; 83546801Sdab } 83647612Sdab p = str_start + 3; 83747612Sdab *p++ = ENCRYPT_START; 83847612Sdab for (i = 0; i < ki[0].keylen; ++i) { 83947612Sdab if ((*p++ = ki[0].keyid[i]) == IAC) 84047612Sdab *p++ = IAC; 84147612Sdab } 84247612Sdab *p++ = IAC; 84347612Sdab *p++ = SE; 84447612Sdab net_write(str_start, p - str_start); 84546801Sdab net_encrypt(); 84647612Sdab printsub('>', &str_start[2], p - &str_start[2]); 84746801Sdab /* 84846801Sdab * If we are already encrypting in some mode, then 84946801Sdab * encrypt the ring (which includes our request) in 85046801Sdab * the old mode, mark it all as "clear text" and then 85146801Sdab * switch to the new mode. 85246801Sdab */ 85346801Sdab encrypt_output = ep->output; 85446801Sdab encrypt_mode = type; 85546801Sdab if (encrypt_debug_mode) 85646801Sdab printf(">>>%s: Started to encrypt output with type %s\r\n", 85746801Sdab Name, ENCTYPE_NAME(type)); 85846801Sdab if (encrypt_verbose) 85946801Sdab printf("[ Output is now encrypted with type %s ]\r\n", 86046801Sdab ENCTYPE_NAME(type)); 86146801Sdab } 86246801Sdab 86346801Sdab void 86446801Sdab encrypt_send_end() 86546801Sdab { 86646801Sdab if (!encrypt_output) 86746801Sdab return; 86846801Sdab 86946801Sdab str_end[3] = ENCRYPT_END; 87046801Sdab net_write(str_end, sizeof(str_end)); 87146801Sdab net_encrypt(); 87246801Sdab printsub('>', &str_end[2], sizeof(str_end) - 2); 87346801Sdab /* 87446801Sdab * Encrypt the output buffer now because it will not be done by 87546801Sdab * netflush... 87646801Sdab */ 87746801Sdab encrypt_output = 0; 87846801Sdab if (encrypt_debug_mode) 87946801Sdab printf(">>>%s: Output is back to clear text\r\n", Name); 88046801Sdab if (encrypt_verbose) 88146801Sdab printf("[ Output is now clear text ]\r\n"); 88246801Sdab } 88346801Sdab 88446801Sdab void 88546801Sdab encrypt_send_request_start() 88646801Sdab { 88747612Sdab register unsigned char *p; 88847612Sdab register int i; 88946801Sdab 89047612Sdab p = &str_start[3]; 89147612Sdab *p++ = ENCRYPT_REQSTART; 89247612Sdab for (i = 0; i < ki[1].keylen; ++i) { 89347612Sdab if ((*p++ = ki[1].keyid[i]) == IAC) 89447612Sdab *p++ = IAC; 89546801Sdab } 89647612Sdab *p++ = IAC; 89747612Sdab *p++ = SE; 89847612Sdab net_write(str_start, p - str_start); 89947612Sdab printsub('>', &str_start[2], p - &str_start[2]); 90046801Sdab if (encrypt_debug_mode) 90146801Sdab printf(">>>%s: Request input to be encrypted\r\n", Name); 90246801Sdab } 90346801Sdab 90446801Sdab void 90546801Sdab encrypt_send_request_end() 90646801Sdab { 90746801Sdab str_end[3] = ENCRYPT_REQEND; 90846801Sdab net_write(str_end, sizeof(str_end)); 90946801Sdab printsub('>', &str_end[2], sizeof(str_end) - 2); 91046801Sdab 91146801Sdab if (encrypt_debug_mode) 91246801Sdab printf(">>>%s: Request input to be clear text\r\n", Name); 91346801Sdab } 91446801Sdab 91546801Sdab void 91646801Sdab encrypt_wait() 91746801Sdab { 91846801Sdab register int encrypt, decrypt; 91946801Sdab if (encrypt_debug_mode) 92046801Sdab printf(">>>%s: in encrypt_wait\r\n", Name); 92147612Sdab if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt)) 92246801Sdab return; 92346801Sdab while (autoencrypt && !encrypt_output) 92446801Sdab if (telnet_spin()) 92546801Sdab return; 92646801Sdab } 92746801Sdab 92846801Sdab void 92946801Sdab encrypt_debug(mode) 93046801Sdab int mode; 93146801Sdab { 93246801Sdab encrypt_debug_mode = mode; 93346801Sdab } 93446801Sdab 93546801Sdab void 93646801Sdab encrypt_gen_printsub(data, cnt, buf, buflen) 93746801Sdab unsigned char *data, *buf; 93846801Sdab int cnt, buflen; 93946801Sdab { 94046801Sdab char tbuf[16], *cp; 94146801Sdab 94246801Sdab cnt -= 2; 94346801Sdab data += 2; 94446801Sdab buf[buflen-1] = '\0'; 94546801Sdab buf[buflen-2] = '*'; 94646801Sdab buflen -= 2;; 94746801Sdab for (; cnt > 0; cnt--, data++) { 94846801Sdab sprintf(tbuf, " %d", *data); 94946801Sdab for (cp = tbuf; *cp && buflen > 0; --buflen) 95046801Sdab *buf++ = *cp++; 95146801Sdab if (buflen <= 0) 95246801Sdab return; 95346801Sdab } 95446801Sdab *buf = '\0'; 95546801Sdab } 95646801Sdab 95746801Sdab void 95846801Sdab encrypt_printsub(data, cnt, buf, buflen) 95946801Sdab unsigned char *data, *buf; 96046801Sdab int cnt, buflen; 96146801Sdab { 96246801Sdab Encryptions *ep; 96346801Sdab register int type = data[1]; 96446801Sdab 96546801Sdab for (ep = encryptions; ep->type && ep->type != type; ep++) 96646801Sdab ; 96746801Sdab 96846801Sdab if (ep->printsub) 96946801Sdab (*ep->printsub)(data, cnt, buf, buflen); 97046801Sdab else 97146801Sdab encrypt_gen_printsub(data, cnt, buf, buflen); 97246801Sdab } 97346801Sdab #endif 974