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