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