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