Annotation of src/usr.bin/telnet/encrypt.c, Revision 1.1
1.1 ! deraadt 1: /* $OpenBSD: encrypt.c,v 1.3 2003/06/26 07:53:27 deraadt Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 1991, 1993
! 5: * The Regents of the University of California. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. Neither the name of the University nor the names of its contributors
! 16: * may be used to endorse or promote products derived from this software
! 17: * without specific prior written permission.
! 18: *
! 19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 29: * SUCH DAMAGE.
! 30: */
! 31:
! 32: /*
! 33: * This source code is no longer held under any constraint of USA
! 34: * `cryptographic laws' since it was exported legally. The cryptographic
! 35: * functions were removed from the code and a "Bones" distribution was
! 36: * made. A Commodity Jurisdiction Request #012-94 was filed with the
! 37: * USA State Department, who handed it to the Commerce department. The
! 38: * code was determined to fall under General License GTDA under ECCN 5D96G,
! 39: * and hence exportable. The cryptographic interfaces were re-added by Eric
! 40: * Young, and then KTH proceeded to maintain the code in the free world.
! 41: *
! 42: */
! 43:
! 44: /*
! 45: * Copyright (C) 1990 by the Massachusetts Institute of Technology
! 46: *
! 47: * Export of this software from the United States of America is assumed
! 48: * to require a specific license from the United States Government.
! 49: * It is the responsibility of any person or organization contemplating
! 50: * export to obtain such a license before exporting.
! 51: *
! 52: * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
! 53: * distribute this software and its documentation for any purpose and
! 54: * without fee is hereby granted, provided that the above copyright
! 55: * notice appear in all copies and that both that copyright notice and
! 56: * this permission notice appear in supporting documentation, and that
! 57: * the name of M.I.T. not be used in advertising or publicity pertaining
! 58: * to distribution of the software without specific, written prior
! 59: * permission. M.I.T. makes no representations about the suitability of
! 60: * this software for any purpose. It is provided "as is" without express
! 61: * or implied warranty.
! 62: */
! 63:
! 64: /*
! 65: RCSID("$KTH: encrypt.c,v 1.22.8.1 2002/02/06 03:39:13 assar Exp $");
! 66: */
! 67:
! 68: #if defined(ENCRYPTION)
! 69:
! 70: #define ENCRYPT_NAMES
! 71: #include <stdio.h>
! 72: #include <stdlib.h>
! 73: #include <string.h>
! 74: #include <sys/types.h>
! 75: #include <arpa/telnet.h>
! 76:
! 77: #include "encrypt.h"
! 78: #include "misc.h"
! 79:
! 80:
! 81:
! 82: /*
! 83: * These functions pointers point to the current routines
! 84: * for encrypting and decrypting data.
! 85: */
! 86: void (*encrypt_output) (unsigned char *, int);
! 87: int (*decrypt_input) (int);
! 88: char *nclearto;
! 89:
! 90: int encrypt_debug_mode = 0;
! 91: static int decrypt_mode = 0;
! 92: static int encrypt_mode = 0;
! 93: static int encrypt_verbose = 0;
! 94: static int autoencrypt = 0;
! 95: static int autodecrypt = 0;
! 96: static int havesessionkey = 0;
! 97: static int Server = 0;
! 98: static const char *Name = "Noname";
! 99:
! 100: #define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0)
! 101:
! 102: static long i_support_encrypt = typemask(ENCTYPE_DES_CFB64)
! 103: | typemask(ENCTYPE_DES_OFB64);
! 104: static long i_support_decrypt = typemask(ENCTYPE_DES_CFB64)
! 105: | typemask(ENCTYPE_DES_OFB64);
! 106: static long i_wont_support_encrypt = 0;
! 107: static long i_wont_support_decrypt = 0;
! 108: #define I_SUPPORT_ENCRYPT (i_support_encrypt & ~i_wont_support_encrypt)
! 109: #define I_SUPPORT_DECRYPT (i_support_decrypt & ~i_wont_support_decrypt)
! 110:
! 111: static long remote_supports_encrypt = 0;
! 112: static long remote_supports_decrypt = 0;
! 113:
! 114: static Encryptions encryptions[] = {
! 115: #if defined(DES_ENCRYPTION)
! 116: { "DES_CFB64", ENCTYPE_DES_CFB64,
! 117: cfb64_encrypt,
! 118: cfb64_decrypt,
! 119: cfb64_init,
! 120: cfb64_start,
! 121: cfb64_is,
! 122: cfb64_reply,
! 123: cfb64_session,
! 124: cfb64_keyid,
! 125: cfb64_printsub },
! 126: { "DES_OFB64", ENCTYPE_DES_OFB64,
! 127: ofb64_encrypt,
! 128: ofb64_decrypt,
! 129: ofb64_init,
! 130: ofb64_start,
! 131: ofb64_is,
! 132: ofb64_reply,
! 133: ofb64_session,
! 134: ofb64_keyid,
! 135: ofb64_printsub },
! 136: #endif
! 137: { 0, },
! 138: };
! 139:
! 140: static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT,
! 141: ENCRYPT_SUPPORT };
! 142: static unsigned char str_suplen = 0;
! 143: static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT };
! 144: static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
! 145:
! 146: Encryptions *
! 147: findencryption(int type)
! 148: {
! 149: Encryptions *ep = encryptions;
! 150:
! 151: if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & typemask(type)))
! 152: return(0);
! 153: while (ep->type && ep->type != type)
! 154: ++ep;
! 155: return(ep->type ? ep : 0);
! 156: }
! 157:
! 158: Encryptions *
! 159: finddecryption(int type)
! 160: {
! 161: Encryptions *ep = encryptions;
! 162:
! 163: if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & typemask(type)))
! 164: return(0);
! 165: while (ep->type && ep->type != type)
! 166: ++ep;
! 167: return(ep->type ? ep : 0);
! 168: }
! 169:
! 170: #define MAXKEYLEN 64
! 171:
! 172: static struct key_info {
! 173: unsigned char keyid[MAXKEYLEN];
! 174: int keylen;
! 175: int dir;
! 176: int *modep;
! 177: Encryptions *(*getcrypt)(int);
! 178: } ki[2] = {
! 179: { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption },
! 180: { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption },
! 181: };
! 182:
! 183: void
! 184: encrypt_init(const char *name, int server)
! 185: {
! 186: Encryptions *ep = encryptions;
! 187:
! 188: Name = name;
! 189: Server = server;
! 190: i_support_encrypt = i_support_decrypt = 0;
! 191: remote_supports_encrypt = remote_supports_decrypt = 0;
! 192: encrypt_mode = 0;
! 193: decrypt_mode = 0;
! 194: encrypt_output = 0;
! 195: decrypt_input = 0;
! 196: #ifdef notdef
! 197: encrypt_verbose = !server;
! 198: #endif
! 199:
! 200: str_suplen = 4;
! 201:
! 202: while (ep->type) {
! 203: if (encrypt_debug_mode)
! 204: printf(">>>%s: I will support %s\r\n",
! 205: Name, ENCTYPE_NAME(ep->type));
! 206: i_support_encrypt |= typemask(ep->type);
! 207: i_support_decrypt |= typemask(ep->type);
! 208: if ((i_wont_support_decrypt & typemask(ep->type)) == 0)
! 209: if ((str_send[str_suplen++] = ep->type) == IAC)
! 210: str_send[str_suplen++] = IAC;
! 211: if (ep->init)
! 212: (*ep->init)(Server);
! 213: ++ep;
! 214: }
! 215: str_send[str_suplen++] = IAC;
! 216: str_send[str_suplen++] = SE;
! 217: }
! 218:
! 219: void
! 220: encrypt_list_types(void)
! 221: {
! 222: Encryptions *ep = encryptions;
! 223:
! 224: printf("Valid encryption types:\n");
! 225: while (ep->type) {
! 226: printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type);
! 227: ++ep;
! 228: }
! 229: }
! 230:
! 231: int
! 232: EncryptEnable(char *type, char *mode)
! 233: {
! 234: if (isprefix(type, "help") || isprefix(type, "?")) {
! 235: printf("Usage: encrypt enable <type> [input|output]\n");
! 236: encrypt_list_types();
! 237: return(0);
! 238: }
! 239: if (EncryptType(type, mode))
! 240: return(EncryptStart(mode));
! 241: return(0);
! 242: }
! 243:
! 244: int
! 245: EncryptDisable(char *type, char *mode)
! 246: {
! 247: Encryptions *ep;
! 248: int ret = 0;
! 249:
! 250: if (isprefix(type, "help") || isprefix(type, "?")) {
! 251: printf("Usage: encrypt disable <type> [input|output]\n");
! 252: encrypt_list_types();
! 253: } else if ((ep = (Encryptions *)genget(type, (char**)encryptions,
! 254: sizeof(Encryptions))) == 0) {
! 255: printf("%s: invalid encryption type\n", type);
! 256: } else if (Ambiguous(ep)) {
! 257: printf("Ambiguous type '%s'\n", type);
! 258: } else {
! 259: if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) {
! 260: if (decrypt_mode == ep->type)
! 261: EncryptStopInput();
! 262: i_wont_support_decrypt |= typemask(ep->type);
! 263: ret = 1;
! 264: }
! 265: if ((mode == 0) || (isprefix(mode, "output"))) {
! 266: if (encrypt_mode == ep->type)
! 267: EncryptStopOutput();
! 268: i_wont_support_encrypt |= typemask(ep->type);
! 269: ret = 1;
! 270: }
! 271: if (ret == 0)
! 272: printf("%s: invalid encryption mode\n", mode);
! 273: }
! 274: return(ret);
! 275: }
! 276:
! 277: int
! 278: EncryptType(char *type, char *mode)
! 279: {
! 280: Encryptions *ep;
! 281: int ret = 0;
! 282:
! 283: if (isprefix(type, "help") || isprefix(type, "?")) {
! 284: printf("Usage: encrypt type <type> [input|output]\n");
! 285: encrypt_list_types();
! 286: } else if ((ep = (Encryptions *)genget(type, (char**)encryptions,
! 287: sizeof(Encryptions))) == 0) {
! 288: printf("%s: invalid encryption type\n", type);
! 289: } else if (Ambiguous(ep)) {
! 290: printf("Ambiguous type '%s'\n", type);
! 291: } else {
! 292: if ((mode == 0) || isprefix(mode, "input")) {
! 293: decrypt_mode = ep->type;
! 294: i_wont_support_decrypt &= ~typemask(ep->type);
! 295: ret = 1;
! 296: }
! 297: if ((mode == 0) || isprefix(mode, "output")) {
! 298: encrypt_mode = ep->type;
! 299: i_wont_support_encrypt &= ~typemask(ep->type);
! 300: ret = 1;
! 301: }
! 302: if (ret == 0)
! 303: printf("%s: invalid encryption mode\n", mode);
! 304: }
! 305: return(ret);
! 306: }
! 307:
! 308: int
! 309: EncryptStart(char *mode)
! 310: {
! 311: int ret = 0;
! 312: if (mode) {
! 313: if (isprefix(mode, "input"))
! 314: return(EncryptStartInput());
! 315: if (isprefix(mode, "output"))
! 316: return(EncryptStartOutput());
! 317: if (isprefix(mode, "help") || isprefix(mode, "?")) {
! 318: printf("Usage: encrypt start [input|output]\n");
! 319: return(0);
! 320: }
! 321: printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);
! 322: return(0);
! 323: }
! 324: ret += EncryptStartInput();
! 325: ret += EncryptStartOutput();
! 326: return(ret);
! 327: }
! 328:
! 329: int
! 330: EncryptStartInput(void)
! 331: {
! 332: if (decrypt_mode) {
! 333: encrypt_send_request_start();
! 334: return(1);
! 335: }
! 336: printf("No previous decryption mode, decryption not enabled\r\n");
! 337: return(0);
! 338: }
! 339:
! 340: int
! 341: EncryptStartOutput(void)
! 342: {
! 343: if (encrypt_mode) {
! 344: encrypt_start_output(encrypt_mode);
! 345: return(1);
! 346: }
! 347: printf("No previous encryption mode, encryption not enabled\r\n");
! 348: return(0);
! 349: }
! 350:
! 351: int
! 352: EncryptStop(char *mode)
! 353: {
! 354: int ret = 0;
! 355: if (mode) {
! 356: if (isprefix(mode, "input"))
! 357: return(EncryptStopInput());
! 358: if (isprefix(mode, "output"))
! 359: return(EncryptStopOutput());
! 360: if (isprefix(mode, "help") || isprefix(mode, "?")) {
! 361: printf("Usage: encrypt stop [input|output]\n");
! 362: return(0);
! 363: }
! 364: printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);
! 365: return(0);
! 366: }
! 367: ret += EncryptStopInput();
! 368: ret += EncryptStopOutput();
! 369: return(ret);
! 370: }
! 371:
! 372: int
! 373: EncryptStopInput(void)
! 374: {
! 375: encrypt_send_request_end();
! 376: return(1);
! 377: }
! 378:
! 379: int
! 380: EncryptStopOutput(void)
! 381: {
! 382: encrypt_send_end();
! 383: return(1);
! 384: }
! 385:
! 386: void
! 387: encrypt_display(void)
! 388: {
! 389: printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n",
! 390: autoencrypt?"on":"off", autodecrypt?"on":"off");
! 391:
! 392: if (encrypt_output)
! 393: printf("Currently encrypting output with %s\r\n",
! 394: ENCTYPE_NAME(encrypt_mode));
! 395: else
! 396: printf("Currently not encrypting output\r\n");
! 397:
! 398: if (decrypt_input)
! 399: printf("Currently decrypting input with %s\r\n",
! 400: ENCTYPE_NAME(decrypt_mode));
! 401: else
! 402: printf("Currently not decrypting input\r\n");
! 403: }
! 404:
! 405: int
! 406: EncryptStatus(void)
! 407: {
! 408: printf("Autoencrypt for output is %s. Autodecrypt for input is %s.\r\n",
! 409: autoencrypt?"on":"off", autodecrypt?"on":"off");
! 410:
! 411: if (encrypt_output)
! 412: printf("Currently encrypting output with %s\r\n",
! 413: ENCTYPE_NAME(encrypt_mode));
! 414: else if (encrypt_mode) {
! 415: printf("Currently output is clear text.\r\n");
! 416: printf("Last encryption mode was %s\r\n",
! 417: ENCTYPE_NAME(encrypt_mode));
! 418: } else
! 419: printf("Currently not encrypting output\r\n");
! 420:
! 421: if (decrypt_input) {
! 422: printf("Currently decrypting input with %s\r\n",
! 423: ENCTYPE_NAME(decrypt_mode));
! 424: } else if (decrypt_mode) {
! 425: printf("Currently input is clear text.\r\n");
! 426: printf("Last decryption mode was %s\r\n",
! 427: ENCTYPE_NAME(decrypt_mode));
! 428: } else
! 429: printf("Currently not decrypting input\r\n");
! 430:
! 431: return 1;
! 432: }
! 433:
! 434: void
! 435: encrypt_send_support(void)
! 436: {
! 437: if (str_suplen) {
! 438: /*
! 439: * If the user has requested that decryption start
! 440: * immediatly, then send a "REQUEST START" before
! 441: * we negotiate the type.
! 442: */
! 443: if (!Server && autodecrypt)
! 444: encrypt_send_request_start();
! 445: telnet_net_write(str_send, str_suplen);
! 446: printsub('>', &str_send[2], str_suplen - 2);
! 447: str_suplen = 0;
! 448: }
! 449: }
! 450:
! 451: int
! 452: EncryptDebug(int on)
! 453: {
! 454: if (on < 0)
! 455: encrypt_debug_mode ^= 1;
! 456: else
! 457: encrypt_debug_mode = on;
! 458: printf("Encryption debugging %s\r\n",
! 459: encrypt_debug_mode ? "enabled" : "disabled");
! 460: return(1);
! 461: }
! 462:
! 463: /* turn on verbose encryption, but dont keep telling the whole world
! 464: */
! 465: void encrypt_verbose_quiet(int on)
! 466: {
! 467: if(on < 0)
! 468: encrypt_verbose ^= 1;
! 469: else
! 470: encrypt_verbose = on ? 1 : 0;
! 471: }
! 472:
! 473: int
! 474: EncryptVerbose(int on)
! 475: {
! 476: encrypt_verbose_quiet(on);
! 477: printf("Encryption %s verbose\r\n",
! 478: encrypt_verbose ? "is" : "is not");
! 479: return(1);
! 480: }
! 481:
! 482: int
! 483: EncryptAutoEnc(int on)
! 484: {
! 485: encrypt_auto(on);
! 486: printf("Automatic encryption of output is %s\r\n",
! 487: autoencrypt ? "enabled" : "disabled");
! 488: return(1);
! 489: }
! 490:
! 491: int
! 492: EncryptAutoDec(int on)
! 493: {
! 494: decrypt_auto(on);
! 495: printf("Automatic decryption of input is %s\r\n",
! 496: autodecrypt ? "enabled" : "disabled");
! 497: return(1);
! 498: }
! 499:
! 500: /* Called when we receive a WONT or a DONT ENCRYPT after we sent a DO
! 501: encrypt */
! 502: void
! 503: encrypt_not(void)
! 504: {
! 505: if (encrypt_verbose)
! 506: printf("[ Connection is NOT encrypted ]\r\n");
! 507: }
! 508:
! 509: /*
! 510: * Called when ENCRYPT SUPPORT is received.
! 511: */
! 512: void
! 513: encrypt_support(unsigned char *typelist, int cnt)
! 514: {
! 515: int type, use_type = 0;
! 516: Encryptions *ep;
! 517:
! 518: /*
! 519: * Forget anything the other side has previously told us.
! 520: */
! 521: remote_supports_decrypt = 0;
! 522:
! 523: while (cnt-- > 0) {
! 524: type = *typelist++;
! 525: if (encrypt_debug_mode)
! 526: printf(">>>%s: He is supporting %s (%d)\r\n",
! 527: Name,
! 528: ENCTYPE_NAME(type), type);
! 529: if ((type < ENCTYPE_CNT) &&
! 530: (I_SUPPORT_ENCRYPT & typemask(type))) {
! 531: remote_supports_decrypt |= typemask(type);
! 532: if (use_type == 0)
! 533: use_type = type;
! 534: }
! 535: }
! 536: if (use_type) {
! 537: ep = findencryption(use_type);
! 538: if (!ep)
! 539: return;
! 540: type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;
! 541: if (encrypt_debug_mode)
! 542: printf(">>>%s: (*ep->start)() returned %d\r\n",
! 543: Name, type);
! 544: if (type < 0)
! 545: return;
! 546: encrypt_mode = use_type;
! 547: if (type == 0)
! 548: encrypt_start_output(use_type);
! 549: }
! 550: }
! 551:
! 552: void
! 553: encrypt_is(unsigned char *data, int cnt)
! 554: {
! 555: Encryptions *ep;
! 556: int type, ret;
! 557:
! 558: if (--cnt < 0)
! 559: return;
! 560: type = *data++;
! 561: if (type < ENCTYPE_CNT)
! 562: remote_supports_encrypt |= typemask(type);
! 563: if (!(ep = finddecryption(type))) {
! 564: if (encrypt_debug_mode)
! 565: printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
! 566: Name,
! 567: ENCTYPE_NAME_OK(type)
! 568: ? ENCTYPE_NAME(type) : "(unknown)",
! 569: type);
! 570: return;
! 571: }
! 572: if (!ep->is) {
! 573: if (encrypt_debug_mode)
! 574: printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
! 575: Name,
! 576: ENCTYPE_NAME_OK(type)
! 577: ? ENCTYPE_NAME(type) : "(unknown)",
! 578: type);
! 579: ret = 0;
! 580: } else {
! 581: ret = (*ep->is)(data, cnt);
! 582: if (encrypt_debug_mode)
! 583: printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt,
! 584: (ret < 0) ? "FAIL " :
! 585: (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
! 586: }
! 587: if (ret < 0) {
! 588: autodecrypt = 0;
! 589: } else {
! 590: decrypt_mode = type;
! 591: if (ret == 0 && autodecrypt)
! 592: encrypt_send_request_start();
! 593: }
! 594: }
! 595:
! 596: void
! 597: encrypt_reply(unsigned char *data, int cnt)
! 598: {
! 599: Encryptions *ep;
! 600: int ret, type;
! 601:
! 602: if (--cnt < 0)
! 603: return;
! 604: type = *data++;
! 605: if (!(ep = findencryption(type))) {
! 606: if (encrypt_debug_mode)
! 607: printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
! 608: Name,
! 609: ENCTYPE_NAME_OK(type)
! 610: ? ENCTYPE_NAME(type) : "(unknown)",
! 611: type);
! 612: return;
! 613: }
! 614: if (!ep->reply) {
! 615: if (encrypt_debug_mode)
! 616: printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
! 617: Name,
! 618: ENCTYPE_NAME_OK(type)
! 619: ? ENCTYPE_NAME(type) : "(unknown)",
! 620: type);
! 621: ret = 0;
! 622: } else {
! 623: ret = (*ep->reply)(data, cnt);
! 624: if (encrypt_debug_mode)
! 625: printf("(*ep->reply)(%p, %d) returned %s(%d)\n",
! 626: data, cnt,
! 627: (ret < 0) ? "FAIL " :
! 628: (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
! 629: }
! 630: if (encrypt_debug_mode)
! 631: printf(">>>%s: encrypt_reply returned %d\n", Name, ret);
! 632: if (ret < 0) {
! 633: autoencrypt = 0;
! 634: } else {
! 635: encrypt_mode = type;
! 636: if (ret == 0 && autoencrypt)
! 637: encrypt_start_output(type);
! 638: }
! 639: }
! 640:
! 641: /*
! 642: * Called when a ENCRYPT START command is received.
! 643: */
! 644: void
! 645: encrypt_start(unsigned char *data, int cnt)
! 646: {
! 647: Encryptions *ep;
! 648:
! 649: if (!decrypt_mode) {
! 650: /*
! 651: * Something is wrong. We should not get a START
! 652: * command without having already picked our
! 653: * decryption scheme. Send a REQUEST-END to
! 654: * attempt to clear the channel...
! 655: */
! 656: printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);
! 657: encrypt_send_request_end();
! 658: return;
! 659: }
! 660:
! 661: if ((ep = finddecryption(decrypt_mode))) {
! 662: decrypt_input = ep->input;
! 663: if (encrypt_verbose)
! 664: printf("[ Input is now decrypted with type %s ]\r\n",
! 665: ENCTYPE_NAME(decrypt_mode));
! 666: if (encrypt_debug_mode)
! 667: printf(">>>%s: Start to decrypt input with type %s\r\n",
! 668: Name, ENCTYPE_NAME(decrypt_mode));
! 669: } else {
! 670: printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",
! 671: Name,
! 672: ENCTYPE_NAME_OK(decrypt_mode)
! 673: ? ENCTYPE_NAME(decrypt_mode)
! 674: : "(unknown)",
! 675: decrypt_mode);
! 676: encrypt_send_request_end();
! 677: }
! 678: }
! 679:
! 680: void
! 681: encrypt_session_key(Session_Key *key, int server)
! 682: {
! 683: Encryptions *ep = encryptions;
! 684:
! 685: havesessionkey = 1;
! 686:
! 687: while (ep->type) {
! 688: if (ep->session)
! 689: (*ep->session)(key, server);
! 690: ++ep;
! 691: }
! 692: }
! 693:
! 694: /*
! 695: * Called when ENCRYPT END is received.
! 696: */
! 697: void
! 698: encrypt_end(void)
! 699: {
! 700: decrypt_input = 0;
! 701: if (encrypt_debug_mode)
! 702: printf(">>>%s: Input is back to clear text\r\n", Name);
! 703: if (encrypt_verbose)
! 704: printf("[ Input is now clear text ]\r\n");
! 705: }
! 706:
! 707: /*
! 708: * Called when ENCRYPT REQUEST-END is received.
! 709: */
! 710: void
! 711: encrypt_request_end(void)
! 712: {
! 713: encrypt_send_end();
! 714: }
! 715:
! 716: /*
! 717: * Called when ENCRYPT REQUEST-START is received. If we receive
! 718: * this before a type is picked, then that indicates that the
! 719: * other side wants us to start encrypting data as soon as we
! 720: * can.
! 721: */
! 722: void
! 723: encrypt_request_start(unsigned char *data, int cnt)
! 724: {
! 725: if (encrypt_mode == 0) {
! 726: if (Server)
! 727: autoencrypt = 1;
! 728: return;
! 729: }
! 730: encrypt_start_output(encrypt_mode);
! 731: }
! 732:
! 733: static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
! 734:
! 735: static void
! 736: encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len)
! 737: {
! 738: Encryptions *ep;
! 739: int dir = kp->dir;
! 740: int ret = 0;
! 741:
! 742: if (!(ep = (*kp->getcrypt)(*kp->modep))) {
! 743: if (len == 0)
! 744: return;
! 745: kp->keylen = 0;
! 746: } else if (len == 0) {
! 747: /*
! 748: * Empty option, indicates a failure.
! 749: */
! 750: if (kp->keylen == 0)
! 751: return;
! 752: kp->keylen = 0;
! 753: if (ep->keyid)
! 754: (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
! 755:
! 756: } else if ((len != kp->keylen) || (memcmp(keyid,kp->keyid,len) != 0)) {
! 757: /*
! 758: * Length or contents are different
! 759: */
! 760: kp->keylen = len;
! 761: memcpy(kp->keyid,keyid, len);
! 762: if (ep->keyid)
! 763: (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
! 764: } else {
! 765: if (ep->keyid)
! 766: ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);
! 767: if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt)
! 768: encrypt_start_output(*kp->modep);
! 769: return;
! 770: }
! 771:
! 772: encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0);
! 773: }
! 774:
! 775: void encrypt_enc_keyid(unsigned char *keyid, int len)
! 776: {
! 777: encrypt_keyid(&ki[1], keyid, len);
! 778: }
! 779:
! 780: void encrypt_dec_keyid(unsigned char *keyid, int len)
! 781: {
! 782: encrypt_keyid(&ki[0], keyid, len);
! 783: }
! 784:
! 785:
! 786: void encrypt_send_keyid(int dir, unsigned char *keyid, int keylen, int saveit)
! 787: {
! 788: unsigned char *strp;
! 789:
! 790: str_keyid[3] = (dir == DIR_ENCRYPT)
! 791: ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;
! 792: if (saveit) {
! 793: struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1];
! 794: memcpy(kp->keyid,keyid, keylen);
! 795: kp->keylen = keylen;
! 796: }
! 797:
! 798: for (strp = &str_keyid[4]; keylen > 0; --keylen) {
! 799: if ((*strp++ = *keyid++) == IAC)
! 800: *strp++ = IAC;
! 801: }
! 802: *strp++ = IAC;
! 803: *strp++ = SE;
! 804: telnet_net_write(str_keyid, strp - str_keyid);
! 805: printsub('>', &str_keyid[2], strp - str_keyid - 2);
! 806: }
! 807:
! 808: void
! 809: encrypt_auto(int on)
! 810: {
! 811: if (on < 0)
! 812: autoencrypt ^= 1;
! 813: else
! 814: autoencrypt = on ? 1 : 0;
! 815: }
! 816:
! 817: void
! 818: decrypt_auto(int on)
! 819: {
! 820: if (on < 0)
! 821: autodecrypt ^= 1;
! 822: else
! 823: autodecrypt = on ? 1 : 0;
! 824: }
! 825:
! 826: void
! 827: encrypt_start_output(int type)
! 828: {
! 829: Encryptions *ep;
! 830: unsigned char *p;
! 831: int i;
! 832:
! 833: if (!(ep = findencryption(type))) {
! 834: if (encrypt_debug_mode) {
! 835: printf(">>>%s: Can't encrypt with type %s (%d)\r\n",
! 836: Name,
! 837: ENCTYPE_NAME_OK(type)
! 838: ? ENCTYPE_NAME(type) : "(unknown)",
! 839: type);
! 840: }
! 841: return;
! 842: }
! 843: if (ep->start) {
! 844: i = (*ep->start)(DIR_ENCRYPT, Server);
! 845: if (encrypt_debug_mode) {
! 846: printf(">>>%s: Encrypt start: %s (%d) %s\r\n",
! 847: Name,
! 848: (i < 0) ? "failed" :
! 849: "initial negotiation in progress",
! 850: i, ENCTYPE_NAME(type));
! 851: }
! 852: if (i)
! 853: return;
! 854: }
! 855: p = str_start + 3;
! 856: *p++ = ENCRYPT_START;
! 857: for (i = 0; i < ki[0].keylen; ++i) {
! 858: if ((*p++ = ki[0].keyid[i]) == IAC)
! 859: *p++ = IAC;
! 860: }
! 861: *p++ = IAC;
! 862: *p++ = SE;
! 863: telnet_net_write(str_start, p - str_start);
! 864: net_encrypt();
! 865: printsub('>', &str_start[2], p - &str_start[2]);
! 866: /*
! 867: * If we are already encrypting in some mode, then
! 868: * encrypt the ring (which includes our request) in
! 869: * the old mode, mark it all as "clear text" and then
! 870: * switch to the new mode.
! 871: */
! 872: encrypt_output = ep->output;
! 873: encrypt_mode = type;
! 874: if (encrypt_debug_mode)
! 875: printf(">>>%s: Started to encrypt output with type %s\r\n",
! 876: Name, ENCTYPE_NAME(type));
! 877: if (encrypt_verbose)
! 878: printf("[ Output is now encrypted with type %s ]\r\n",
! 879: ENCTYPE_NAME(type));
! 880: }
! 881:
! 882: void
! 883: encrypt_send_end(void)
! 884: {
! 885: if (!encrypt_output)
! 886: return;
! 887:
! 888: str_end[3] = ENCRYPT_END;
! 889: telnet_net_write(str_end, sizeof(str_end));
! 890: net_encrypt();
! 891: printsub('>', &str_end[2], sizeof(str_end) - 2);
! 892: /*
! 893: * Encrypt the output buffer now because it will not be done by
! 894: * netflush...
! 895: */
! 896: encrypt_output = 0;
! 897: if (encrypt_debug_mode)
! 898: printf(">>>%s: Output is back to clear text\r\n", Name);
! 899: if (encrypt_verbose)
! 900: printf("[ Output is now clear text ]\r\n");
! 901: }
! 902:
! 903: void
! 904: encrypt_send_request_start(void)
! 905: {
! 906: unsigned char *p;
! 907: int i;
! 908:
! 909: p = &str_start[3];
! 910: *p++ = ENCRYPT_REQSTART;
! 911: for (i = 0; i < ki[1].keylen; ++i) {
! 912: if ((*p++ = ki[1].keyid[i]) == IAC)
! 913: *p++ = IAC;
! 914: }
! 915: *p++ = IAC;
! 916: *p++ = SE;
! 917: telnet_net_write(str_start, p - str_start);
! 918: printsub('>', &str_start[2], p - &str_start[2]);
! 919: if (encrypt_debug_mode)
! 920: printf(">>>%s: Request input to be encrypted\r\n", Name);
! 921: }
! 922:
! 923: void
! 924: encrypt_send_request_end(void)
! 925: {
! 926: str_end[3] = ENCRYPT_REQEND;
! 927: telnet_net_write(str_end, sizeof(str_end));
! 928: printsub('>', &str_end[2], sizeof(str_end) - 2);
! 929:
! 930: if (encrypt_debug_mode)
! 931: printf(">>>%s: Request input to be clear text\r\n", Name);
! 932: }
! 933:
! 934:
! 935: void encrypt_wait(void)
! 936: {
! 937: if (encrypt_debug_mode)
! 938: printf(">>>%s: in encrypt_wait\r\n", Name);
! 939: if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))
! 940: return;
! 941: while (autoencrypt && !encrypt_output)
! 942: if (telnet_spin())
! 943: return;
! 944: }
! 945:
! 946: int
! 947: encrypt_delay(void)
! 948: {
! 949: if(!havesessionkey ||
! 950: (I_SUPPORT_ENCRYPT & remote_supports_decrypt) == 0 ||
! 951: (I_SUPPORT_DECRYPT & remote_supports_encrypt) == 0)
! 952: return 0;
! 953: if(!(encrypt_output && decrypt_input))
! 954: return 1;
! 955: return 0;
! 956: }
! 957:
! 958: int encrypt_is_encrypting()
! 959: {
! 960: if (encrypt_output && decrypt_input)
! 961: return 1;
! 962: return 0;
! 963: }
! 964:
! 965: void
! 966: encrypt_debug(int mode)
! 967: {
! 968: encrypt_debug_mode = mode;
! 969: }
! 970:
! 971: void encrypt_gen_printsub(unsigned char *data, int cnt,
! 972: unsigned char *buf, int buflen)
! 973: {
! 974: char tbuf[16], *cp;
! 975:
! 976: cnt -= 2;
! 977: data += 2;
! 978: buf[buflen-1] = '\0';
! 979: buf[buflen-2] = '*';
! 980: buflen -= 2;;
! 981: for (; cnt > 0; cnt--, data++) {
! 982: snprintf(tbuf, sizeof(tbuf), " %d", *data);
! 983: for (cp = tbuf; *cp && buflen > 0; --buflen)
! 984: *buf++ = *cp++;
! 985: if (buflen <= 0)
! 986: return;
! 987: }
! 988: *buf = '\0';
! 989: }
! 990:
! 991: void
! 992: encrypt_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
! 993: {
! 994: Encryptions *ep;
! 995: int type = data[1];
! 996:
! 997: for (ep = encryptions; ep->type && ep->type != type; ep++)
! 998: ;
! 999:
! 1000: if (ep->printsub)
! 1001: (*ep->printsub)(data, cnt, buf, buflen);
! 1002: else
! 1003: encrypt_gen_printsub(data, cnt, buf, buflen);
! 1004: }
! 1005: #endif