129088Smarkm/*- 229088Smarkm * Copyright (c) 1991, 1993 329088Smarkm * The Regents of the University of California. All rights reserved. 429088Smarkm * 529088Smarkm * Redistribution and use in source and binary forms, with or without 629088Smarkm * modification, are permitted provided that the following conditions 729088Smarkm * are met: 829088Smarkm * 1. Redistributions of source code must retain the above copyright 929088Smarkm * notice, this list of conditions and the following disclaimer. 1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1129088Smarkm * notice, this list of conditions and the following disclaimer in the 1229088Smarkm * documentation and/or other materials provided with the distribution. 1329088Smarkm * 3. All advertising materials mentioning features or use of this software 1429088Smarkm * must display the following acknowledgement: 1529088Smarkm * This product includes software developed by the University of 1629088Smarkm * California, Berkeley and its contributors. 1729088Smarkm * 4. Neither the name of the University nor the names of its contributors 1829088Smarkm * may be used to endorse or promote products derived from this software 1929088Smarkm * without specific prior written permission. 2029088Smarkm * 2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2429088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3129088Smarkm * SUCH DAMAGE. 3229088Smarkm */ 3329088Smarkm 3484305Smarkm#include <sys/cdefs.h> 3587139Smarkm 3684305Smarkm__FBSDID("$FreeBSD$"); 3784305Smarkm 3829088Smarkm#ifndef lint 3963248Speter#if 0 4029181Smarkmstatic const char sccsid[] = "@(#)encrypt.c 8.2 (Berkeley) 5/30/95"; 4163248Speter#endif 4229088Smarkm#endif /* not lint */ 4329088Smarkm 4429088Smarkm/* 4529088Smarkm * Copyright (C) 1990 by the Massachusetts Institute of Technology 4629088Smarkm * 4729088Smarkm * Export of this software from the United States of America is assumed 4829088Smarkm * to require a specific license from the United States Government. 4929088Smarkm * It is the responsibility of any person or organization contemplating 5029088Smarkm * export to obtain such a license before exporting. 5129088Smarkm * 5229088Smarkm * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 5329088Smarkm * distribute this software and its documentation for any purpose and 5429088Smarkm * without fee is hereby granted, provided that the above copyright 5529088Smarkm * notice appear in all copies and that both that copyright notice and 5629088Smarkm * this permission notice appear in supporting documentation, and that 5729088Smarkm * the name of M.I.T. not be used in advertising or publicity pertaining 5829088Smarkm * to distribution of the software without specific, written prior 5929088Smarkm * permission. M.I.T. makes no representations about the suitability of 6029088Smarkm * this software for any purpose. It is provided "as is" without express 6129088Smarkm * or implied warranty. 6229088Smarkm */ 6329088Smarkm 6429088Smarkm#ifdef ENCRYPTION 6529088Smarkm 6698884Smarkm#include <sys/types.h> 6729088Smarkm#define ENCRYPT_NAMES 6887139Smarkm#include <arpa/telnet.h> 6929181Smarkm#include <stdio.h> 7087139Smarkm#include <stdlib.h> 7187139Smarkm#include <string.h> 7229088Smarkm 7329088Smarkm#include "encrypt.h" 7429088Smarkm#include "misc.h" 7529088Smarkm 7629088Smarkm/* 7729088Smarkm * These functions pointers point to the current routines 7829088Smarkm * for encrypting and decrypting data. 7929088Smarkm */ 8087155Smarkmvoid (*encrypt_output)(unsigned char *, int); 8187155Smarkmint (*decrypt_input)(int); 8229088Smarkm 8329181Smarkmint EncryptType(char *type, char *mode); 8429181Smarkmint EncryptStart(char *mode); 8529181Smarkmint EncryptStop(char *mode); 8629181Smarkmint EncryptStartInput(void); 8729181Smarkmint EncryptStartOutput(void); 8829181Smarkmint EncryptStopInput(void); 8929181Smarkmint EncryptStopOutput(void); 9029181Smarkm 9129088Smarkmint encrypt_debug_mode = 0; 9229088Smarkmstatic int decrypt_mode = 0; 9329088Smarkmstatic int encrypt_mode = 0; 9429088Smarkmstatic int encrypt_verbose = 0; 9529088Smarkmstatic int autoencrypt = 0; 9629088Smarkmstatic int autodecrypt = 0; 9729088Smarkmstatic int havesessionkey = 0; 9829088Smarkmstatic int Server = 0; 9987139Smarkmstatic const char *Name = "Noname"; 10029088Smarkm 10129088Smarkm#define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0) 10229088Smarkm 10398884Smarkmstatic u_long i_support_encrypt = 0 10449887Snsayer | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64) 10549887Snsayer |0; 10698884Smarkmstatic u_long i_support_decrypt = 0 10749887Snsayer | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64) 10849887Snsayer |0; 10949887Snsayer 11098884Smarkmstatic u_long i_wont_support_encrypt = 0; 11198884Smarkmstatic u_long i_wont_support_decrypt = 0; 11229088Smarkm#define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt) 11329088Smarkm#define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt) 11429088Smarkm 11598884Smarkmstatic u_long remote_supports_encrypt = 0; 11698884Smarkmstatic u_long remote_supports_decrypt = 0; 11729088Smarkm 11829088Smarkmstatic Encryptions encryptions[] = { 11929088Smarkm { "DES_CFB64", ENCTYPE_DES_CFB64, 12029088Smarkm cfb64_encrypt, 12129088Smarkm cfb64_decrypt, 12229088Smarkm cfb64_init, 12329088Smarkm cfb64_start, 12429088Smarkm cfb64_is, 12529088Smarkm cfb64_reply, 12629088Smarkm cfb64_session, 12729088Smarkm cfb64_keyid, 12829088Smarkm cfb64_printsub }, 12929088Smarkm { "DES_OFB64", ENCTYPE_DES_OFB64, 13029088Smarkm ofb64_encrypt, 13129088Smarkm ofb64_decrypt, 13229088Smarkm ofb64_init, 13329088Smarkm ofb64_start, 13429088Smarkm ofb64_is, 13529088Smarkm ofb64_reply, 13629088Smarkm ofb64_session, 13729088Smarkm ofb64_keyid, 13829088Smarkm ofb64_printsub }, 13987139Smarkm { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 14029088Smarkm}; 14129088Smarkm 14229088Smarkmstatic unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT, 14329088Smarkm ENCRYPT_SUPPORT }; 14429088Smarkmstatic unsigned char str_suplen = 0; 14529088Smarkmstatic unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT }; 14629088Smarkmstatic unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE }; 14729088Smarkm 14887139SmarkmEncryptions * 14987139Smarkmfindencryption(int type) 15029088Smarkm{ 15129088Smarkm Encryptions *ep = encryptions; 15229088Smarkm 15387139Smarkm if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & (unsigned)typemask(type))) 15429088Smarkm return(0); 15529088Smarkm while (ep->type && ep->type != type) 15629088Smarkm ++ep; 15729088Smarkm return(ep->type ? ep : 0); 15829088Smarkm} 15929088Smarkm 16087139Smarkmstatic Encryptions * 16187139Smarkmfinddecryption(int type) 16229088Smarkm{ 16329088Smarkm Encryptions *ep = encryptions; 16429088Smarkm 16587139Smarkm if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & (unsigned)typemask(type))) 16629088Smarkm return(0); 16729088Smarkm while (ep->type && ep->type != type) 16829088Smarkm ++ep; 16929088Smarkm return(ep->type ? ep : 0); 17029088Smarkm} 17129088Smarkm 17229088Smarkm#define MAXKEYLEN 64 17329088Smarkm 17429088Smarkmstatic struct key_info { 17529088Smarkm unsigned char keyid[MAXKEYLEN]; 17629088Smarkm int keylen; 17729088Smarkm int dir; 17829088Smarkm int *modep; 17987139Smarkm Encryptions *(*getcrypt)(int); 18029088Smarkm} ki[2] = { 18129088Smarkm { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption }, 18229088Smarkm { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption }, 18329088Smarkm}; 18429088Smarkm 18529181Smarkmstatic void encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len); 18629181Smarkm 18787139Smarkmvoid 18887139Smarkmencrypt_init(const char *name, int server) 18929088Smarkm{ 19029088Smarkm Encryptions *ep = encryptions; 19129088Smarkm 19229088Smarkm Name = name; 19329088Smarkm Server = server; 19429088Smarkm i_support_encrypt = i_support_decrypt = 0; 19529088Smarkm remote_supports_encrypt = remote_supports_decrypt = 0; 19629088Smarkm encrypt_mode = 0; 19729088Smarkm decrypt_mode = 0; 19829088Smarkm encrypt_output = 0; 19929088Smarkm decrypt_input = 0; 20029088Smarkm 20129088Smarkm str_suplen = 4; 20229088Smarkm 20329088Smarkm while (ep->type) { 20429088Smarkm if (encrypt_debug_mode) 20529088Smarkm printf(">>>%s: I will support %s\r\n", 20629088Smarkm Name, ENCTYPE_NAME(ep->type)); 20729088Smarkm i_support_encrypt |= typemask(ep->type); 20829088Smarkm i_support_decrypt |= typemask(ep->type); 20929088Smarkm if ((i_wont_support_decrypt & typemask(ep->type)) == 0) 21029088Smarkm if ((str_send[str_suplen++] = ep->type) == IAC) 21129088Smarkm str_send[str_suplen++] = IAC; 21229088Smarkm if (ep->init) 21329088Smarkm (*ep->init)(Server); 21429088Smarkm ++ep; 21529088Smarkm } 21629088Smarkm str_send[str_suplen++] = IAC; 21729088Smarkm str_send[str_suplen++] = SE; 21829088Smarkm} 21929088Smarkm 22087139Smarkmstatic void 22187139Smarkmencrypt_list_types(void) 22229088Smarkm{ 22329088Smarkm Encryptions *ep = encryptions; 22429088Smarkm 22529088Smarkm printf("Valid encryption types:\n"); 22629088Smarkm while (ep->type) { 22729088Smarkm printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type); 22829088Smarkm ++ep; 22929088Smarkm } 23029088Smarkm} 23129088Smarkm 23287139Smarkmint 23387139SmarkmEncryptEnable(char *type, char *mode) 23429088Smarkm{ 23529088Smarkm if (isprefix(type, "help") || isprefix(type, "?")) { 23629088Smarkm printf("Usage: encrypt enable <type> [input|output]\n"); 23729088Smarkm encrypt_list_types(); 23829088Smarkm return(0); 23929088Smarkm } 24029088Smarkm if (EncryptType(type, mode)) 24129088Smarkm return(EncryptStart(mode)); 24229088Smarkm return(0); 24329088Smarkm} 24429088Smarkm 24587139Smarkmint 24687139SmarkmEncryptDisable(char *type, char *mode) 24729088Smarkm{ 24887139Smarkm Encryptions *ep; 24929088Smarkm int ret = 0; 25029088Smarkm 25129088Smarkm if (isprefix(type, "help") || isprefix(type, "?")) { 25229088Smarkm printf("Usage: encrypt disable <type> [input|output]\n"); 25329088Smarkm encrypt_list_types(); 25429181Smarkm } else if ((ep = (Encryptions *)genget(type, (char **)encryptions, 25529088Smarkm sizeof(Encryptions))) == 0) { 25629088Smarkm printf("%s: invalid encryption type\n", type); 25729181Smarkm } else if (Ambiguous((char **)ep)) { 25829088Smarkm printf("Ambiguous type '%s'\n", type); 25929088Smarkm } else { 26029088Smarkm if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) { 26129088Smarkm if (decrypt_mode == ep->type) 26229088Smarkm EncryptStopInput(); 26329088Smarkm i_wont_support_decrypt |= typemask(ep->type); 26429088Smarkm ret = 1; 26529088Smarkm } 26629088Smarkm if ((mode == 0) || (isprefix(mode, "output"))) { 26729088Smarkm if (encrypt_mode == ep->type) 26829088Smarkm EncryptStopOutput(); 26929088Smarkm i_wont_support_encrypt |= typemask(ep->type); 27029088Smarkm ret = 1; 27129088Smarkm } 27229088Smarkm if (ret == 0) 27329088Smarkm printf("%s: invalid encryption mode\n", mode); 27429088Smarkm } 27529088Smarkm return(ret); 27629088Smarkm} 27729088Smarkm 27887139Smarkmint 27987139SmarkmEncryptType(char *type, char *mode) 28029088Smarkm{ 28187139Smarkm Encryptions *ep; 28229088Smarkm int ret = 0; 28329088Smarkm 28429088Smarkm if (isprefix(type, "help") || isprefix(type, "?")) { 28529088Smarkm printf("Usage: encrypt type <type> [input|output]\n"); 28629088Smarkm encrypt_list_types(); 28729181Smarkm } else if ((ep = (Encryptions *)genget(type, (char **)encryptions, 28829088Smarkm sizeof(Encryptions))) == 0) { 28929088Smarkm printf("%s: invalid encryption type\n", type); 29029181Smarkm } else if (Ambiguous((char **)ep)) { 29129088Smarkm printf("Ambiguous type '%s'\n", type); 29229088Smarkm } else { 29329088Smarkm if ((mode == 0) || isprefix(mode, "input")) { 29429088Smarkm decrypt_mode = ep->type; 29529088Smarkm i_wont_support_decrypt &= ~typemask(ep->type); 29629088Smarkm ret = 1; 29729088Smarkm } 29829088Smarkm if ((mode == 0) || isprefix(mode, "output")) { 29929088Smarkm encrypt_mode = ep->type; 30029088Smarkm i_wont_support_encrypt &= ~typemask(ep->type); 30129088Smarkm ret = 1; 30229088Smarkm } 30329088Smarkm if (ret == 0) 30429088Smarkm printf("%s: invalid encryption mode\n", mode); 30529088Smarkm } 30629088Smarkm return(ret); 30729088Smarkm} 30829088Smarkm 30987139Smarkmint 31087139SmarkmEncryptStart(char *mode) 31129088Smarkm{ 31287139Smarkm int ret = 0; 31329088Smarkm if (mode) { 31429088Smarkm if (isprefix(mode, "input")) 31529088Smarkm return(EncryptStartInput()); 31629088Smarkm if (isprefix(mode, "output")) 31729088Smarkm return(EncryptStartOutput()); 31829088Smarkm if (isprefix(mode, "help") || isprefix(mode, "?")) { 31929088Smarkm printf("Usage: encrypt start [input|output]\n"); 32029088Smarkm return(0); 32129088Smarkm } 32229088Smarkm printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode); 32329088Smarkm return(0); 32429088Smarkm } 32529088Smarkm ret += EncryptStartInput(); 32629088Smarkm ret += EncryptStartOutput(); 32729088Smarkm return(ret); 32829088Smarkm} 32929088Smarkm 33087139Smarkmint 33187139SmarkmEncryptStartInput(void) 33229088Smarkm{ 33329088Smarkm if (decrypt_mode) { 33429088Smarkm encrypt_send_request_start(); 33529088Smarkm return(1); 33629088Smarkm } 33729088Smarkm printf("No previous decryption mode, decryption not enabled\r\n"); 33829088Smarkm return(0); 33929088Smarkm} 34029088Smarkm 34187139Smarkmint 34287139SmarkmEncryptStartOutput(void) 34329088Smarkm{ 34429088Smarkm if (encrypt_mode) { 34529088Smarkm encrypt_start_output(encrypt_mode); 34629088Smarkm return(1); 34729088Smarkm } 34829088Smarkm printf("No previous encryption mode, encryption not enabled\r\n"); 34929088Smarkm return(0); 35029088Smarkm} 35129088Smarkm 35287139Smarkmint 35387139SmarkmEncryptStop(char *mode) 35429088Smarkm{ 35529088Smarkm int ret = 0; 35629088Smarkm if (mode) { 35729088Smarkm if (isprefix(mode, "input")) 35829088Smarkm return(EncryptStopInput()); 35929088Smarkm if (isprefix(mode, "output")) 36029088Smarkm return(EncryptStopOutput()); 36129088Smarkm if (isprefix(mode, "help") || isprefix(mode, "?")) { 36229088Smarkm printf("Usage: encrypt stop [input|output]\n"); 36329088Smarkm return(0); 36429088Smarkm } 36529088Smarkm printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode); 36629088Smarkm return(0); 36729088Smarkm } 36829088Smarkm ret += EncryptStopInput(); 36929088Smarkm ret += EncryptStopOutput(); 37029088Smarkm return(ret); 37129088Smarkm} 37229088Smarkm 37387139Smarkmint 37487139SmarkmEncryptStopInput(void) 37529088Smarkm{ 37629088Smarkm encrypt_send_request_end(); 37729088Smarkm return(1); 37829088Smarkm} 37929088Smarkm 38087139Smarkmint 38187139SmarkmEncryptStopOutput(void) 38229088Smarkm{ 38329088Smarkm encrypt_send_end(); 38429088Smarkm return(1); 38529088Smarkm} 38629088Smarkm 38787139Smarkmvoid 38887139Smarkmencrypt_display(void) 38929088Smarkm{ 39029088Smarkm if (encrypt_output) 39129088Smarkm printf("Currently encrypting output with %s\r\n", 39229088Smarkm ENCTYPE_NAME(encrypt_mode)); 39329088Smarkm if (decrypt_input) 39429088Smarkm printf("Currently decrypting input with %s\r\n", 39529088Smarkm ENCTYPE_NAME(decrypt_mode)); 39629088Smarkm} 39729088Smarkm 39887139Smarkmint 39987139SmarkmEncryptStatus(void) 40029088Smarkm{ 40129088Smarkm if (encrypt_output) 40229088Smarkm printf("Currently encrypting output with %s\r\n", 40329088Smarkm ENCTYPE_NAME(encrypt_mode)); 40429088Smarkm else if (encrypt_mode) { 40529088Smarkm printf("Currently output is clear text.\r\n"); 40629088Smarkm printf("Last encryption mode was %s\r\n", 40729088Smarkm ENCTYPE_NAME(encrypt_mode)); 40829088Smarkm } 40929088Smarkm if (decrypt_input) { 41029088Smarkm printf("Currently decrypting input with %s\r\n", 41129088Smarkm ENCTYPE_NAME(decrypt_mode)); 41229088Smarkm } else if (decrypt_mode) { 41329088Smarkm printf("Currently input is clear text.\r\n"); 41429088Smarkm printf("Last decryption mode was %s\r\n", 41529088Smarkm ENCTYPE_NAME(decrypt_mode)); 41629088Smarkm } 41729088Smarkm return 1; 41829088Smarkm} 41929088Smarkm 42087139Smarkmvoid 42187139Smarkmencrypt_send_support(void) 42229088Smarkm{ 42329088Smarkm if (str_suplen) { 42429088Smarkm /* 42529088Smarkm * If the user has requested that decryption start 42629088Smarkm * immediatly, then send a "REQUEST START" before 42729088Smarkm * we negotiate the type. 42829088Smarkm */ 42929088Smarkm if (!Server && autodecrypt) 43029088Smarkm encrypt_send_request_start(); 43129088Smarkm net_write(str_send, str_suplen); 43229088Smarkm printsub('>', &str_send[2], str_suplen - 2); 43329088Smarkm str_suplen = 0; 43429088Smarkm } 43529088Smarkm} 43629088Smarkm 43787139Smarkmint 43887139SmarkmEncryptDebug(int on) 43929088Smarkm{ 44029088Smarkm if (on < 0) 44129088Smarkm encrypt_debug_mode ^= 1; 44229088Smarkm else 44329088Smarkm encrypt_debug_mode = on; 44429088Smarkm printf("Encryption debugging %s\r\n", 44529088Smarkm encrypt_debug_mode ? "enabled" : "disabled"); 44629088Smarkm return(1); 44729088Smarkm} 44829088Smarkm 44987139Smarkmint 45087139SmarkmEncryptVerbose(int on) 45129088Smarkm{ 45229088Smarkm if (on < 0) 45329088Smarkm encrypt_verbose ^= 1; 45429088Smarkm else 45529088Smarkm encrypt_verbose = on; 45629088Smarkm printf("Encryption %s verbose\r\n", 45729088Smarkm encrypt_verbose ? "is" : "is not"); 45829088Smarkm return(1); 45929088Smarkm} 46029088Smarkm 46187139Smarkmint 46287139SmarkmEncryptAutoEnc(int on) 46329088Smarkm{ 46429088Smarkm encrypt_auto(on); 46529088Smarkm printf("Automatic encryption of output is %s\r\n", 46629088Smarkm autoencrypt ? "enabled" : "disabled"); 46729088Smarkm return(1); 46829088Smarkm} 46929088Smarkm 47087139Smarkmint 47187139SmarkmEncryptAutoDec(int on) 47229088Smarkm{ 47329088Smarkm decrypt_auto(on); 47429088Smarkm printf("Automatic decryption of input is %s\r\n", 47529088Smarkm autodecrypt ? "enabled" : "disabled"); 47629088Smarkm return(1); 47729088Smarkm} 47829088Smarkm 47929088Smarkm/* 48029088Smarkm * Called when ENCRYPT SUPPORT is received. 48129088Smarkm */ 48287139Smarkmvoid 48387139Smarkmencrypt_support(unsigned char *typelist, int cnt) 48429088Smarkm{ 48587139Smarkm int type, use_type = 0; 48629088Smarkm Encryptions *ep; 48729088Smarkm 48829088Smarkm /* 48929088Smarkm * Forget anything the other side has previously told us. 49029088Smarkm */ 49129088Smarkm remote_supports_decrypt = 0; 49229088Smarkm 49329088Smarkm while (cnt-- > 0) { 49429088Smarkm type = *typelist++; 49529088Smarkm if (encrypt_debug_mode) 49629088Smarkm printf(">>>%s: He is supporting %s (%d)\r\n", 49729088Smarkm Name, 49829088Smarkm ENCTYPE_NAME(type), type); 49929088Smarkm if ((type < ENCTYPE_CNT) && 50029088Smarkm (I_SUPPORT_ENCRYPT & typemask(type))) { 50129088Smarkm remote_supports_decrypt |= typemask(type); 50229088Smarkm if (use_type == 0) 50329088Smarkm use_type = type; 50429088Smarkm } 50529088Smarkm } 50629088Smarkm if (use_type) { 50729088Smarkm ep = findencryption(use_type); 50829088Smarkm if (!ep) 50929088Smarkm return; 51029088Smarkm type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0; 51129088Smarkm if (encrypt_debug_mode) 51229088Smarkm printf(">>>%s: (*ep->start)() returned %d\r\n", 51329088Smarkm Name, type); 51429088Smarkm if (type < 0) 51529088Smarkm return; 51629088Smarkm encrypt_mode = use_type; 51729088Smarkm if (type == 0) 51829088Smarkm encrypt_start_output(use_type); 51929088Smarkm } 52029088Smarkm} 52129088Smarkm 52287139Smarkmvoid 52387139Smarkmencrypt_is(unsigned char *data, int cnt) 52429088Smarkm{ 52529088Smarkm Encryptions *ep; 52687139Smarkm int type, ret; 52729088Smarkm 52829088Smarkm if (--cnt < 0) 52929088Smarkm return; 53029088Smarkm type = *data++; 53129088Smarkm if (type < ENCTYPE_CNT) 53229088Smarkm remote_supports_encrypt |= typemask(type); 53329088Smarkm if (!(ep = finddecryption(type))) { 53429088Smarkm if (encrypt_debug_mode) 53529088Smarkm printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", 53629088Smarkm Name, 53729088Smarkm ENCTYPE_NAME_OK(type) 53829088Smarkm ? ENCTYPE_NAME(type) : "(unknown)", 53929088Smarkm type); 54029088Smarkm return; 54129088Smarkm } 54229088Smarkm if (!ep->is) { 54329088Smarkm if (encrypt_debug_mode) 54429088Smarkm printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", 54529088Smarkm Name, 54629088Smarkm ENCTYPE_NAME_OK(type) 54729088Smarkm ? ENCTYPE_NAME(type) : "(unknown)", 54829088Smarkm type); 54929088Smarkm ret = 0; 55029088Smarkm } else { 55129088Smarkm ret = (*ep->is)(data, cnt); 55229088Smarkm if (encrypt_debug_mode) 55329181Smarkm printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt, 55429088Smarkm (ret < 0) ? "FAIL " : 55529088Smarkm (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); 55629088Smarkm } 55729088Smarkm if (ret < 0) { 55829088Smarkm autodecrypt = 0; 55929088Smarkm } else { 56029088Smarkm decrypt_mode = type; 56129088Smarkm if (ret == 0 && autodecrypt) 56229088Smarkm encrypt_send_request_start(); 56329088Smarkm } 56429088Smarkm} 56529088Smarkm 56687139Smarkmvoid 56787139Smarkmencrypt_reply(unsigned char *data, int cnt) 56829088Smarkm{ 56929088Smarkm Encryptions *ep; 57087139Smarkm int ret, type; 57129088Smarkm 57229088Smarkm if (--cnt < 0) 57329088Smarkm return; 57429088Smarkm type = *data++; 57529088Smarkm if (!(ep = findencryption(type))) { 57629088Smarkm if (encrypt_debug_mode) 57729088Smarkm printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n", 57829088Smarkm Name, 57929088Smarkm ENCTYPE_NAME_OK(type) 58029088Smarkm ? ENCTYPE_NAME(type) : "(unknown)", 58129088Smarkm type); 58229088Smarkm return; 58329088Smarkm } 58429088Smarkm if (!ep->reply) { 58529088Smarkm if (encrypt_debug_mode) 58629088Smarkm printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n", 58729088Smarkm Name, 58829088Smarkm ENCTYPE_NAME_OK(type) 58929088Smarkm ? ENCTYPE_NAME(type) : "(unknown)", 59029088Smarkm type); 59129088Smarkm ret = 0; 59229088Smarkm } else { 59329088Smarkm ret = (*ep->reply)(data, cnt); 59429088Smarkm if (encrypt_debug_mode) 59529181Smarkm printf("(*ep->reply)(%p, %d) returned %s(%d)\n", 59629088Smarkm data, cnt, 59729088Smarkm (ret < 0) ? "FAIL " : 59829088Smarkm (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret); 59929088Smarkm } 60029088Smarkm if (encrypt_debug_mode) 60129088Smarkm printf(">>>%s: encrypt_reply returned %d\n", Name, ret); 60229088Smarkm if (ret < 0) { 60329088Smarkm autoencrypt = 0; 60429088Smarkm } else { 60529088Smarkm encrypt_mode = type; 60629088Smarkm if (ret == 0 && autoencrypt) 60729088Smarkm encrypt_start_output(type); 60829088Smarkm } 60929088Smarkm} 61029088Smarkm 61129088Smarkm/* 61229088Smarkm * Called when a ENCRYPT START command is received. 61329088Smarkm */ 61487139Smarkmvoid 61587139Smarkmencrypt_start(unsigned char *data __unused, int cnt __unused) 61629088Smarkm{ 61729088Smarkm Encryptions *ep; 61829088Smarkm 61929088Smarkm if (!decrypt_mode) { 62029088Smarkm /* 62129088Smarkm * Something is wrong. We should not get a START 62229088Smarkm * command without having already picked our 62329088Smarkm * decryption scheme. Send a REQUEST-END to 62429088Smarkm * attempt to clear the channel... 62529088Smarkm */ 62629088Smarkm printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name); 62729088Smarkm encrypt_send_request_end(); 62829088Smarkm return; 62929088Smarkm } 63029088Smarkm 63129181Smarkm if ((ep = finddecryption(decrypt_mode))) { 63229088Smarkm decrypt_input = ep->input; 63329088Smarkm if (encrypt_verbose) 63429088Smarkm printf("[ Input is now decrypted with type %s ]\r\n", 63529088Smarkm ENCTYPE_NAME(decrypt_mode)); 63629088Smarkm if (encrypt_debug_mode) 63729088Smarkm printf(">>>%s: Start to decrypt input with type %s\r\n", 63829088Smarkm Name, ENCTYPE_NAME(decrypt_mode)); 63929088Smarkm } else { 64029088Smarkm printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n", 64129088Smarkm Name, 64229088Smarkm ENCTYPE_NAME_OK(decrypt_mode) 64329088Smarkm ? ENCTYPE_NAME(decrypt_mode) 64429088Smarkm : "(unknown)", 64529088Smarkm decrypt_mode); 64629088Smarkm encrypt_send_request_end(); 64729088Smarkm } 64829088Smarkm} 64929088Smarkm 65087139Smarkmvoid 65187139Smarkmencrypt_session_key( Session_Key *key, int server) 65229088Smarkm{ 65329088Smarkm Encryptions *ep = encryptions; 65429088Smarkm 65529088Smarkm havesessionkey = 1; 65629088Smarkm 65729088Smarkm while (ep->type) { 65829088Smarkm if (ep->session) 65929088Smarkm (*ep->session)(key, server); 66029088Smarkm ++ep; 66129088Smarkm } 66229088Smarkm} 66329088Smarkm 66429088Smarkm/* 66529088Smarkm * Called when ENCRYPT END is received. 66629088Smarkm */ 66787139Smarkmvoid 66887139Smarkmencrypt_end(void) 66929088Smarkm{ 67029088Smarkm decrypt_input = 0; 67129088Smarkm if (encrypt_debug_mode) 67229088Smarkm printf(">>>%s: Input is back to clear text\r\n", Name); 67329088Smarkm if (encrypt_verbose) 67429088Smarkm printf("[ Input is now clear text ]\r\n"); 67529088Smarkm} 67629088Smarkm 67729088Smarkm/* 67829088Smarkm * Called when ENCRYPT REQUEST-END is received. 67929088Smarkm */ 68087139Smarkmvoid 68187139Smarkmencrypt_request_end(void) 68229088Smarkm{ 68329088Smarkm encrypt_send_end(); 68429088Smarkm} 68529088Smarkm 68629088Smarkm/* 68729088Smarkm * Called when ENCRYPT REQUEST-START is received. If we receive 68829088Smarkm * this before a type is picked, then that indicates that the 68929088Smarkm * other side wants us to start encrypting data as soon as we 69029088Smarkm * can. 69129088Smarkm */ 69287139Smarkmvoid 69387139Smarkmencrypt_request_start(unsigned char *data __unused, int cnt __unused) 69429088Smarkm{ 69529088Smarkm if (encrypt_mode == 0) { 69629088Smarkm if (Server) 69729088Smarkm autoencrypt = 1; 69829088Smarkm return; 69929088Smarkm } 70029088Smarkm encrypt_start_output(encrypt_mode); 70129088Smarkm} 70229088Smarkm 70329088Smarkmstatic unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT }; 70429088Smarkm 70587139Smarkmvoid 70687139Smarkmencrypt_enc_keyid(unsigned char *keyid, int len) 70729088Smarkm{ 70829088Smarkm encrypt_keyid(&ki[1], keyid, len); 70929088Smarkm} 71029088Smarkm 71187139Smarkmvoid 71287139Smarkmencrypt_dec_keyid(unsigned char *keyid, int len) 71329088Smarkm{ 71429088Smarkm encrypt_keyid(&ki[0], keyid, len); 71529088Smarkm} 71629088Smarkm 71787139Smarkmvoid 71887139Smarkmencrypt_keyid(struct key_info *kp, unsigned char *keyid, int len) 71929088Smarkm{ 72029088Smarkm Encryptions *ep; 72129088Smarkm int dir = kp->dir; 72287139Smarkm int ret = 0; 72329088Smarkm 724228843Scperciva if (len > MAXKEYLEN) 725228843Scperciva len = MAXKEYLEN; 726228843Scperciva 72729088Smarkm if (!(ep = (*kp->getcrypt)(*kp->modep))) { 72829088Smarkm if (len == 0) 72929088Smarkm return; 73029088Smarkm kp->keylen = 0; 73129088Smarkm } else if (len == 0) { 73229088Smarkm /* 73329088Smarkm * Empty option, indicates a failure. 73429088Smarkm */ 73529088Smarkm if (kp->keylen == 0) 73629088Smarkm return; 73729088Smarkm kp->keylen = 0; 73829088Smarkm if (ep->keyid) 73929088Smarkm (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); 74029088Smarkm 74129088Smarkm } else if ((len != kp->keylen) || 74229088Smarkm (memcmp(keyid, kp->keyid, len) != 0)) { 74329088Smarkm /* 74429088Smarkm * Length or contents are different 74529088Smarkm */ 74629088Smarkm kp->keylen = len; 74729088Smarkm memmove(kp->keyid, keyid, len); 74829088Smarkm if (ep->keyid) 74929088Smarkm (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen); 75029088Smarkm } else { 75129088Smarkm if (ep->keyid) 75229088Smarkm ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen); 75329088Smarkm if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt) 75429088Smarkm encrypt_start_output(*kp->modep); 75529088Smarkm return; 75629088Smarkm } 75729088Smarkm 75829088Smarkm encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0); 75929088Smarkm} 76029088Smarkm 76187139Smarkmvoid 76287139Smarkmencrypt_send_keyid(int dir, const char *keyid, int keylen, int saveit) 76329088Smarkm{ 76429088Smarkm unsigned char *strp; 76529088Smarkm 76629088Smarkm str_keyid[3] = (dir == DIR_ENCRYPT) 76729088Smarkm ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID; 76829088Smarkm if (saveit) { 76929088Smarkm struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1]; 77029088Smarkm memmove(kp->keyid, keyid, keylen); 77129088Smarkm kp->keylen = keylen; 77229088Smarkm } 77329088Smarkm 77429088Smarkm for (strp = &str_keyid[4]; keylen > 0; --keylen) { 77529088Smarkm if ((*strp++ = *keyid++) == IAC) 77629088Smarkm *strp++ = IAC; 77729088Smarkm } 77829088Smarkm *strp++ = IAC; 77929088Smarkm *strp++ = SE; 78029088Smarkm net_write(str_keyid, strp - str_keyid); 78129088Smarkm printsub('>', &str_keyid[2], strp - str_keyid - 2); 78229088Smarkm} 78329088Smarkm 78487139Smarkmvoid 78587139Smarkmencrypt_auto(int on) 78629088Smarkm{ 78729088Smarkm if (on < 0) 78829088Smarkm autoencrypt ^= 1; 78929088Smarkm else 79029088Smarkm autoencrypt = on ? 1 : 0; 79129088Smarkm} 79229088Smarkm 79387139Smarkmvoid 79487139Smarkmdecrypt_auto(int on) 79529088Smarkm{ 79629088Smarkm if (on < 0) 79729088Smarkm autodecrypt ^= 1; 79829088Smarkm else 79929088Smarkm autodecrypt = on ? 1 : 0; 80029088Smarkm} 80129088Smarkm 80287139Smarkmvoid 80387139Smarkmencrypt_start_output(int type) 80429088Smarkm{ 80529088Smarkm Encryptions *ep; 80687139Smarkm unsigned char *p; 80787139Smarkm int i; 80829088Smarkm 80929088Smarkm if (!(ep = findencryption(type))) { 81029088Smarkm if (encrypt_debug_mode) { 81129088Smarkm printf(">>>%s: Can't encrypt with type %s (%d)\r\n", 81229088Smarkm Name, 81329088Smarkm ENCTYPE_NAME_OK(type) 81429088Smarkm ? ENCTYPE_NAME(type) : "(unknown)", 81529088Smarkm type); 81629088Smarkm } 81729088Smarkm return; 81829088Smarkm } 81929088Smarkm if (ep->start) { 82029088Smarkm i = (*ep->start)(DIR_ENCRYPT, Server); 82129088Smarkm if (encrypt_debug_mode) { 82229088Smarkm printf(">>>%s: Encrypt start: %s (%d) %s\r\n", 82329088Smarkm Name, 82429088Smarkm (i < 0) ? "failed" : 82529088Smarkm "initial negotiation in progress", 82629088Smarkm i, ENCTYPE_NAME(type)); 82729088Smarkm } 82829088Smarkm if (i) 82929088Smarkm return; 83029088Smarkm } 83129088Smarkm p = str_start + 3; 83229088Smarkm *p++ = ENCRYPT_START; 83329088Smarkm for (i = 0; i < ki[0].keylen; ++i) { 83429088Smarkm if ((*p++ = ki[0].keyid[i]) == IAC) 83529088Smarkm *p++ = IAC; 83629088Smarkm } 83729088Smarkm *p++ = IAC; 83829088Smarkm *p++ = SE; 83929088Smarkm net_write(str_start, p - str_start); 84029088Smarkm net_encrypt(); 84129088Smarkm printsub('>', &str_start[2], p - &str_start[2]); 84229088Smarkm /* 84329088Smarkm * If we are already encrypting in some mode, then 84429088Smarkm * encrypt the ring (which includes our request) in 84529088Smarkm * the old mode, mark it all as "clear text" and then 84629088Smarkm * switch to the new mode. 84729088Smarkm */ 84829088Smarkm encrypt_output = ep->output; 84929088Smarkm encrypt_mode = type; 85029088Smarkm if (encrypt_debug_mode) 85129088Smarkm printf(">>>%s: Started to encrypt output with type %s\r\n", 85229088Smarkm Name, ENCTYPE_NAME(type)); 85329088Smarkm if (encrypt_verbose) 85429088Smarkm printf("[ Output is now encrypted with type %s ]\r\n", 85529088Smarkm ENCTYPE_NAME(type)); 85629088Smarkm} 85729088Smarkm 85887139Smarkmvoid 85987139Smarkmencrypt_send_end(void) 86029088Smarkm{ 86129088Smarkm if (!encrypt_output) 86229088Smarkm return; 86329088Smarkm 86429088Smarkm str_end[3] = ENCRYPT_END; 86529088Smarkm net_write(str_end, sizeof(str_end)); 86629088Smarkm net_encrypt(); 86729088Smarkm printsub('>', &str_end[2], sizeof(str_end) - 2); 86829088Smarkm /* 86929088Smarkm * Encrypt the output buffer now because it will not be done by 87029088Smarkm * netflush... 87129088Smarkm */ 87229088Smarkm encrypt_output = 0; 87329088Smarkm if (encrypt_debug_mode) 87429088Smarkm printf(">>>%s: Output is back to clear text\r\n", Name); 87529088Smarkm if (encrypt_verbose) 87629088Smarkm printf("[ Output is now clear text ]\r\n"); 87729088Smarkm} 87829088Smarkm 87987139Smarkmvoid 88087139Smarkmencrypt_send_request_start(void) 88129088Smarkm{ 88287139Smarkm unsigned char *p; 88387139Smarkm int i; 88429088Smarkm 88529088Smarkm p = &str_start[3]; 88629088Smarkm *p++ = ENCRYPT_REQSTART; 88729088Smarkm for (i = 0; i < ki[1].keylen; ++i) { 88829088Smarkm if ((*p++ = ki[1].keyid[i]) == IAC) 88929088Smarkm *p++ = IAC; 89029088Smarkm } 89129088Smarkm *p++ = IAC; 89229088Smarkm *p++ = SE; 89329088Smarkm net_write(str_start, p - str_start); 89429088Smarkm printsub('>', &str_start[2], p - &str_start[2]); 89529088Smarkm if (encrypt_debug_mode) 89629088Smarkm printf(">>>%s: Request input to be encrypted\r\n", Name); 89729088Smarkm} 89829088Smarkm 89987139Smarkmvoid 90087139Smarkmencrypt_send_request_end(void) 90129088Smarkm{ 90229088Smarkm str_end[3] = ENCRYPT_REQEND; 90329088Smarkm net_write(str_end, sizeof(str_end)); 90429088Smarkm printsub('>', &str_end[2], sizeof(str_end) - 2); 90529088Smarkm 90629088Smarkm if (encrypt_debug_mode) 90729088Smarkm printf(">>>%s: Request input to be clear text\r\n", Name); 90829088Smarkm} 90929088Smarkm 91087139Smarkmvoid 91187139Smarkmencrypt_wait(void) 91229088Smarkm{ 91329088Smarkm if (encrypt_debug_mode) 91429088Smarkm printf(">>>%s: in encrypt_wait\r\n", Name); 91529088Smarkm if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt)) 91629088Smarkm return; 91729088Smarkm while (autoencrypt && !encrypt_output) 91829088Smarkm if (telnet_spin()) 91929088Smarkm return; 92029088Smarkm} 92129088Smarkm 92287139Smarkmvoid 92387139Smarkmencrypt_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) 92429088Smarkm{ 92529088Smarkm char tbuf[16], *cp; 92629088Smarkm 92729088Smarkm cnt -= 2; 92829088Smarkm data += 2; 92929088Smarkm buf[buflen-1] = '\0'; 93029088Smarkm buf[buflen-2] = '*'; 93129088Smarkm buflen -= 2;; 93229088Smarkm for (; cnt > 0; cnt--, data++) { 93329088Smarkm sprintf(tbuf, " %d", *data); 93429088Smarkm for (cp = tbuf; *cp && buflen > 0; --buflen) 93529088Smarkm *buf++ = *cp++; 93629088Smarkm if (buflen <= 0) 93729088Smarkm return; 93829088Smarkm } 93929088Smarkm *buf = '\0'; 94029088Smarkm} 94129088Smarkm 94287139Smarkmvoid 94387139Smarkmencrypt_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) 94429088Smarkm{ 94529088Smarkm Encryptions *ep; 94687139Smarkm int type = data[1]; 94729088Smarkm 94829088Smarkm for (ep = encryptions; ep->type && ep->type != type; ep++) 94929088Smarkm ; 95029088Smarkm 95129088Smarkm if (ep->printsub) 95229088Smarkm (*ep->printsub)(data, cnt, buf, buflen); 95329088Smarkm else 95429088Smarkm encrypt_gen_printsub(data, cnt, buf, buflen); 95529088Smarkm} 95629088Smarkm#endif /* ENCRYPTION */ 957