[BACK]Return to encrypt.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / telnet

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