]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/telnet/libtelnet/encrypt.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / telnet / libtelnet / encrypt.c
1 /*-
2  * Copyright (c) 1991, 1993
3  *      The Regents of the University of California.  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 #include <sys/cdefs.h>
35
36 __FBSDID("$FreeBSD$");
37
38 #ifndef lint
39 #if 0
40 static const char sccsid[] = "@(#)encrypt.c     8.2 (Berkeley) 5/30/95";
41 #endif
42 #endif /* not lint */
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 #ifdef  ENCRYPTION
65
66 #include <sys/types.h>
67 #define ENCRYPT_NAMES
68 #include <arpa/telnet.h>
69 #include <stdio.h>
70 #include <stdlib.h>
71 #include <string.h>
72
73 #include "encrypt.h"
74 #include "misc.h"
75
76 /*
77  * These functions pointers point to the current routines
78  * for encrypting and decrypting data.
79  */
80 void    (*encrypt_output)(unsigned char *, int);
81 int     (*decrypt_input)(int);
82
83 int EncryptType(char *type, char *mode);
84 int EncryptStart(char *mode);
85 int EncryptStop(char *mode);
86 int EncryptStartInput(void);
87 int EncryptStartOutput(void);
88 int EncryptStopInput(void);
89 int EncryptStopOutput(void);
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 u_long i_support_encrypt = 0
104  | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64)
105  |0;
106 static u_long i_support_decrypt = 0
107  | typemask(ENCTYPE_DES_CFB64) | typemask(ENCTYPE_DES_OFB64)
108  |0;
109
110 static u_long i_wont_support_encrypt = 0;
111 static u_long i_wont_support_decrypt = 0;
112 #define I_SUPPORT_ENCRYPT       (i_support_encrypt & ~i_wont_support_encrypt)
113 #define I_SUPPORT_DECRYPT       (i_support_decrypt & ~i_wont_support_decrypt)
114
115 static u_long remote_supports_encrypt = 0;
116 static u_long remote_supports_decrypt = 0;
117
118 static Encryptions encryptions[] = {
119     { "DES_CFB64",      ENCTYPE_DES_CFB64,
120                         cfb64_encrypt,
121                         cfb64_decrypt,
122                         cfb64_init,
123                         cfb64_start,
124                         cfb64_is,
125                         cfb64_reply,
126                         cfb64_session,
127                         cfb64_keyid,
128                         cfb64_printsub },
129     { "DES_OFB64",      ENCTYPE_DES_OFB64,
130                         ofb64_encrypt,
131                         ofb64_decrypt,
132                         ofb64_init,
133                         ofb64_start,
134                         ofb64_is,
135                         ofb64_reply,
136                         ofb64_session,
137                         ofb64_keyid,
138                         ofb64_printsub },
139     { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
140 };
141
142 static unsigned char str_send[64] = { IAC, SB, TELOPT_ENCRYPT,
143                                          ENCRYPT_SUPPORT };
144 static unsigned char str_suplen = 0;
145 static unsigned char str_start[72] = { IAC, SB, TELOPT_ENCRYPT };
146 static unsigned char str_end[] = { IAC, SB, TELOPT_ENCRYPT, 0, IAC, SE };
147
148 Encryptions *
149 findencryption(int type)
150 {
151         Encryptions *ep = encryptions;
152
153         if (!(I_SUPPORT_ENCRYPT & remote_supports_decrypt & (unsigned)typemask(type)))
154                 return(0);
155         while (ep->type && ep->type != type)
156                 ++ep;
157         return(ep->type ? ep : 0);
158 }
159
160 static Encryptions *
161 finddecryption(int type)
162 {
163         Encryptions *ep = encryptions;
164
165         if (!(I_SUPPORT_DECRYPT & remote_supports_encrypt & (unsigned)typemask(type)))
166                 return(0);
167         while (ep->type && ep->type != type)
168                 ++ep;
169         return(ep->type ? ep : 0);
170 }
171
172 #define MAXKEYLEN 64
173
174 static struct key_info {
175         unsigned char keyid[MAXKEYLEN];
176         int keylen;
177         int dir;
178         int *modep;
179         Encryptions *(*getcrypt)(int);
180 } ki[2] = {
181         { { 0 }, 0, DIR_ENCRYPT, &encrypt_mode, findencryption },
182         { { 0 }, 0, DIR_DECRYPT, &decrypt_mode, finddecryption },
183 };
184
185 static void encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len);
186
187 void
188 encrypt_init(const char *name, int server)
189 {
190         Encryptions *ep = encryptions;
191
192         Name = name;
193         Server = server;
194         i_support_encrypt = i_support_decrypt = 0;
195         remote_supports_encrypt = remote_supports_decrypt = 0;
196         encrypt_mode = 0;
197         decrypt_mode = 0;
198         encrypt_output = 0;
199         decrypt_input = 0;
200
201         str_suplen = 4;
202
203         while (ep->type) {
204                 if (encrypt_debug_mode)
205                         printf(">>>%s: I will support %s\r\n",
206                                 Name, ENCTYPE_NAME(ep->type));
207                 i_support_encrypt |= typemask(ep->type);
208                 i_support_decrypt |= typemask(ep->type);
209                 if ((i_wont_support_decrypt & typemask(ep->type)) == 0)
210                         if ((str_send[str_suplen++] = ep->type) == IAC)
211                                 str_send[str_suplen++] = IAC;
212                 if (ep->init)
213                         (*ep->init)(Server);
214                 ++ep;
215         }
216         str_send[str_suplen++] = IAC;
217         str_send[str_suplen++] = SE;
218 }
219
220 static void
221 encrypt_list_types(void)
222 {
223         Encryptions *ep = encryptions;
224
225         printf("Valid encryption types:\n");
226         while (ep->type) {
227                 printf("\t%s (%d)\r\n", ENCTYPE_NAME(ep->type), ep->type);
228                 ++ep;
229         }
230 }
231
232 int
233 EncryptEnable(char *type, char *mode)
234 {
235         if (isprefix(type, "help") || isprefix(type, "?")) {
236                 printf("Usage: encrypt enable <type> [input|output]\n");
237                 encrypt_list_types();
238                 return(0);
239         }
240         if (EncryptType(type, mode))
241                 return(EncryptStart(mode));
242         return(0);
243 }
244
245 int
246 EncryptDisable(char *type, char *mode)
247 {
248         Encryptions *ep;
249         int ret = 0;
250
251         if (isprefix(type, "help") || isprefix(type, "?")) {
252                 printf("Usage: encrypt disable <type> [input|output]\n");
253                 encrypt_list_types();
254         } else if ((ep = (Encryptions *)genget(type, (char **)encryptions,
255                                                 sizeof(Encryptions))) == 0) {
256                 printf("%s: invalid encryption type\n", type);
257         } else if (Ambiguous((char **)ep)) {
258                 printf("Ambiguous type '%s'\n", type);
259         } else {
260                 if ((mode == 0) || (isprefix(mode, "input") ? 1 : 0)) {
261                         if (decrypt_mode == ep->type)
262                                 EncryptStopInput();
263                         i_wont_support_decrypt |= typemask(ep->type);
264                         ret = 1;
265                 }
266                 if ((mode == 0) || (isprefix(mode, "output"))) {
267                         if (encrypt_mode == ep->type)
268                                 EncryptStopOutput();
269                         i_wont_support_encrypt |= typemask(ep->type);
270                         ret = 1;
271                 }
272                 if (ret == 0)
273                         printf("%s: invalid encryption mode\n", mode);
274         }
275         return(ret);
276 }
277
278 int
279 EncryptType(char *type, char *mode)
280 {
281         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, (char **)encryptions,
288                                                 sizeof(Encryptions))) == 0) {
289                 printf("%s: invalid encryption type\n", type);
290         } else if (Ambiguous((char **)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(char *mode)
311 {
312         int ret = 0;
313         if (mode) {
314                 if (isprefix(mode, "input"))
315                         return(EncryptStartInput());
316                 if (isprefix(mode, "output"))
317                         return(EncryptStartOutput());
318                 if (isprefix(mode, "help") || isprefix(mode, "?")) {
319                         printf("Usage: encrypt start [input|output]\n");
320                         return(0);
321                 }
322                 printf("%s: invalid encryption mode 'encrypt start ?' for help\n", mode);
323                 return(0);
324         }
325         ret += EncryptStartInput();
326         ret += EncryptStartOutput();
327         return(ret);
328 }
329
330 int
331 EncryptStartInput(void)
332 {
333         if (decrypt_mode) {
334                 encrypt_send_request_start();
335                 return(1);
336         }
337         printf("No previous decryption mode, decryption not enabled\r\n");
338         return(0);
339 }
340
341 int
342 EncryptStartOutput(void)
343 {
344         if (encrypt_mode) {
345                 encrypt_start_output(encrypt_mode);
346                 return(1);
347         }
348         printf("No previous encryption mode, encryption not enabled\r\n");
349         return(0);
350 }
351
352 int
353 EncryptStop(char *mode)
354 {
355         int ret = 0;
356         if (mode) {
357                 if (isprefix(mode, "input"))
358                         return(EncryptStopInput());
359                 if (isprefix(mode, "output"))
360                         return(EncryptStopOutput());
361                 if (isprefix(mode, "help") || isprefix(mode, "?")) {
362                         printf("Usage: encrypt stop [input|output]\n");
363                         return(0);
364                 }
365                 printf("%s: invalid encryption mode 'encrypt stop ?' for help\n", mode);
366                 return(0);
367         }
368         ret += EncryptStopInput();
369         ret += EncryptStopOutput();
370         return(ret);
371 }
372
373 int
374 EncryptStopInput(void)
375 {
376         encrypt_send_request_end();
377         return(1);
378 }
379
380 int
381 EncryptStopOutput(void)
382 {
383         encrypt_send_end();
384         return(1);
385 }
386
387 void
388 encrypt_display(void)
389 {
390         if (encrypt_output)
391                 printf("Currently encrypting output with %s\r\n",
392                         ENCTYPE_NAME(encrypt_mode));
393         if (decrypt_input)
394                 printf("Currently decrypting input with %s\r\n",
395                         ENCTYPE_NAME(decrypt_mode));
396 }
397
398 int
399 EncryptStatus(void)
400 {
401         if (encrypt_output)
402                 printf("Currently encrypting output with %s\r\n",
403                         ENCTYPE_NAME(encrypt_mode));
404         else if (encrypt_mode) {
405                 printf("Currently output is clear text.\r\n");
406                 printf("Last encryption mode was %s\r\n",
407                         ENCTYPE_NAME(encrypt_mode));
408         }
409         if (decrypt_input) {
410                 printf("Currently decrypting input with %s\r\n",
411                         ENCTYPE_NAME(decrypt_mode));
412         } else if (decrypt_mode) {
413                 printf("Currently input is clear text.\r\n");
414                 printf("Last decryption mode was %s\r\n",
415                         ENCTYPE_NAME(decrypt_mode));
416         }
417         return 1;
418 }
419
420 void
421 encrypt_send_support(void)
422 {
423         if (str_suplen) {
424                 /*
425                  * If the user has requested that decryption start
426                  * immediatly, then send a "REQUEST START" before
427                  * we negotiate the type.
428                  */
429                 if (!Server && autodecrypt)
430                         encrypt_send_request_start();
431                 net_write(str_send, str_suplen);
432                 printsub('>', &str_send[2], str_suplen - 2);
433                 str_suplen = 0;
434         }
435 }
436
437 int
438 EncryptDebug(int on)
439 {
440         if (on < 0)
441                 encrypt_debug_mode ^= 1;
442         else
443                 encrypt_debug_mode = on;
444         printf("Encryption debugging %s\r\n",
445                 encrypt_debug_mode ? "enabled" : "disabled");
446         return(1);
447 }
448
449 int
450 EncryptVerbose(int on)
451 {
452         if (on < 0)
453                 encrypt_verbose ^= 1;
454         else
455                 encrypt_verbose = on;
456         printf("Encryption %s verbose\r\n",
457                 encrypt_verbose ? "is" : "is not");
458         return(1);
459 }
460
461 int
462 EncryptAutoEnc(int on)
463 {
464         encrypt_auto(on);
465         printf("Automatic encryption of output is %s\r\n",
466                 autoencrypt ? "enabled" : "disabled");
467         return(1);
468 }
469
470 int
471 EncryptAutoDec(int on)
472 {
473         decrypt_auto(on);
474         printf("Automatic decryption of input is %s\r\n",
475                 autodecrypt ? "enabled" : "disabled");
476         return(1);
477 }
478
479 /*
480  * Called when ENCRYPT SUPPORT is received.
481  */
482 void
483 encrypt_support(unsigned char *typelist, int cnt)
484 {
485         int type, use_type = 0;
486         Encryptions *ep;
487
488         /*
489          * Forget anything the other side has previously told us.
490          */
491         remote_supports_decrypt = 0;
492
493         while (cnt-- > 0) {
494                 type = *typelist++;
495                 if (encrypt_debug_mode)
496                         printf(">>>%s: He is supporting %s (%d)\r\n",
497                                 Name,
498                                 ENCTYPE_NAME(type), type);
499                 if ((type < ENCTYPE_CNT) &&
500                     (I_SUPPORT_ENCRYPT & typemask(type))) {
501                         remote_supports_decrypt |= typemask(type);
502                         if (use_type == 0)
503                                 use_type = type;
504                 }
505         }
506         if (use_type) {
507                 ep = findencryption(use_type);
508                 if (!ep)
509                         return;
510                 type = ep->start ? (*ep->start)(DIR_ENCRYPT, Server) : 0;
511                 if (encrypt_debug_mode)
512                         printf(">>>%s: (*ep->start)() returned %d\r\n",
513                                         Name, type);
514                 if (type < 0)
515                         return;
516                 encrypt_mode = use_type;
517                 if (type == 0)
518                         encrypt_start_output(use_type);
519         }
520 }
521
522 void
523 encrypt_is(unsigned char *data, int cnt)
524 {
525         Encryptions *ep;
526         int type, ret;
527
528         if (--cnt < 0)
529                 return;
530         type = *data++;
531         if (type < ENCTYPE_CNT)
532                 remote_supports_encrypt |= typemask(type);
533         if (!(ep = finddecryption(type))) {
534                 if (encrypt_debug_mode)
535                         printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
536                                 Name,
537                                 ENCTYPE_NAME_OK(type)
538                                         ? ENCTYPE_NAME(type) : "(unknown)",
539                                 type);
540                 return;
541         }
542         if (!ep->is) {
543                 if (encrypt_debug_mode)
544                         printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
545                                 Name,
546                                 ENCTYPE_NAME_OK(type)
547                                         ? ENCTYPE_NAME(type) : "(unknown)",
548                                 type);
549                 ret = 0;
550         } else {
551                 ret = (*ep->is)(data, cnt);
552                 if (encrypt_debug_mode)
553                         printf("(*ep->is)(%p, %d) returned %s(%d)\n", data, cnt,
554                                 (ret < 0) ? "FAIL " :
555                                 (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
556         }
557         if (ret < 0) {
558                 autodecrypt = 0;
559         } else {
560                 decrypt_mode = type;
561                 if (ret == 0 && autodecrypt)
562                         encrypt_send_request_start();
563         }
564 }
565
566 void
567 encrypt_reply(unsigned char *data, int cnt)
568 {
569         Encryptions *ep;
570         int ret, type;
571
572         if (--cnt < 0)
573                 return;
574         type = *data++;
575         if (!(ep = findencryption(type))) {
576                 if (encrypt_debug_mode)
577                         printf(">>>%s: Can't find type %s (%d) for initial negotiation\r\n",
578                                 Name,
579                                 ENCTYPE_NAME_OK(type)
580                                         ? ENCTYPE_NAME(type) : "(unknown)",
581                                 type);
582                 return;
583         }
584         if (!ep->reply) {
585                 if (encrypt_debug_mode)
586                         printf(">>>%s: No initial negotiation needed for type %s (%d)\r\n",
587                                 Name,
588                                 ENCTYPE_NAME_OK(type)
589                                         ? ENCTYPE_NAME(type) : "(unknown)",
590                                 type);
591                 ret = 0;
592         } else {
593                 ret = (*ep->reply)(data, cnt);
594                 if (encrypt_debug_mode)
595                         printf("(*ep->reply)(%p, %d) returned %s(%d)\n",
596                                 data, cnt,
597                                 (ret < 0) ? "FAIL " :
598                                 (ret == 0) ? "SUCCESS " : "MORE_TO_DO ", ret);
599         }
600         if (encrypt_debug_mode)
601                 printf(">>>%s: encrypt_reply returned %d\n", Name, ret);
602         if (ret < 0) {
603                 autoencrypt = 0;
604         } else {
605                 encrypt_mode = type;
606                 if (ret == 0 && autoencrypt)
607                         encrypt_start_output(type);
608         }
609 }
610
611 /*
612  * Called when a ENCRYPT START command is received.
613  */
614 void
615 encrypt_start(unsigned char *data __unused, int cnt __unused)
616 {
617         Encryptions *ep;
618
619         if (!decrypt_mode) {
620                 /*
621                  * Something is wrong.  We should not get a START
622                  * command without having already picked our
623                  * decryption scheme.  Send a REQUEST-END to
624                  * attempt to clear the channel...
625                  */
626                 printf("%s: Warning, Cannot decrypt input stream!!!\r\n", Name);
627                 encrypt_send_request_end();
628                 return;
629         }
630
631         if ((ep = finddecryption(decrypt_mode))) {
632                 decrypt_input = ep->input;
633                 if (encrypt_verbose)
634                         printf("[ Input is now decrypted with type %s ]\r\n",
635                                 ENCTYPE_NAME(decrypt_mode));
636                 if (encrypt_debug_mode)
637                         printf(">>>%s: Start to decrypt input with type %s\r\n",
638                                 Name, ENCTYPE_NAME(decrypt_mode));
639         } else {
640                 printf("%s: Warning, Cannot decrypt type %s (%d)!!!\r\n",
641                                 Name,
642                                 ENCTYPE_NAME_OK(decrypt_mode)
643                                         ? ENCTYPE_NAME(decrypt_mode)
644                                         : "(unknown)",
645                                 decrypt_mode);
646                 encrypt_send_request_end();
647         }
648 }
649
650 void
651 encrypt_session_key( Session_Key *key, int server)
652 {
653         Encryptions *ep = encryptions;
654
655         havesessionkey = 1;
656
657         while (ep->type) {
658                 if (ep->session)
659                         (*ep->session)(key, server);
660                 ++ep;
661         }
662 }
663
664 /*
665  * Called when ENCRYPT END is received.
666  */
667 void
668 encrypt_end(void)
669 {
670         decrypt_input = 0;
671         if (encrypt_debug_mode)
672                 printf(">>>%s: Input is back to clear text\r\n", Name);
673         if (encrypt_verbose)
674                 printf("[ Input is now clear text ]\r\n");
675 }
676
677 /*
678  * Called when ENCRYPT REQUEST-END is received.
679  */
680 void
681 encrypt_request_end(void)
682 {
683         encrypt_send_end();
684 }
685
686 /*
687  * Called when ENCRYPT REQUEST-START is received.  If we receive
688  * this before a type is picked, then that indicates that the
689  * other side wants us to start encrypting data as soon as we
690  * can.
691  */
692 void
693 encrypt_request_start(unsigned char *data __unused, int cnt __unused)
694 {
695         if (encrypt_mode == 0)  {
696                 if (Server)
697                         autoencrypt = 1;
698                 return;
699         }
700         encrypt_start_output(encrypt_mode);
701 }
702
703 static unsigned char str_keyid[(MAXKEYLEN*2)+5] = { IAC, SB, TELOPT_ENCRYPT };
704
705 void
706 encrypt_enc_keyid(unsigned char *keyid, int len)
707 {
708         encrypt_keyid(&ki[1], keyid, len);
709 }
710
711 void
712 encrypt_dec_keyid(unsigned char *keyid, int len)
713 {
714         encrypt_keyid(&ki[0], keyid, len);
715 }
716
717 void
718 encrypt_keyid(struct key_info *kp, unsigned char *keyid, int len)
719 {
720         Encryptions *ep;
721         int dir = kp->dir;
722         int ret = 0;
723
724         if (len > MAXKEYLEN)
725                 len = MAXKEYLEN;
726
727         if (!(ep = (*kp->getcrypt)(*kp->modep))) {
728                 if (len == 0)
729                         return;
730                 kp->keylen = 0;
731         } else if (len == 0) {
732                 /*
733                  * Empty option, indicates a failure.
734                  */
735                 if (kp->keylen == 0)
736                         return;
737                 kp->keylen = 0;
738                 if (ep->keyid)
739                         (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
740
741         } else if ((len != kp->keylen) ||
742                    (memcmp(keyid, kp->keyid, len) != 0)) {
743                 /*
744                  * Length or contents are different
745                  */
746                 kp->keylen = len;
747                 memmove(kp->keyid, keyid, len);
748                 if (ep->keyid)
749                         (void)(*ep->keyid)(dir, kp->keyid, &kp->keylen);
750         } else {
751                 if (ep->keyid)
752                         ret = (*ep->keyid)(dir, kp->keyid, &kp->keylen);
753                 if ((ret == 0) && (dir == DIR_ENCRYPT) && autoencrypt)
754                         encrypt_start_output(*kp->modep);
755                 return;
756         }
757
758         encrypt_send_keyid(dir, kp->keyid, kp->keylen, 0);
759 }
760
761 void
762 encrypt_send_keyid(int dir, const char *keyid, int keylen, int saveit)
763 {
764         unsigned char *strp;
765
766         str_keyid[3] = (dir == DIR_ENCRYPT)
767                         ? ENCRYPT_ENC_KEYID : ENCRYPT_DEC_KEYID;
768         if (saveit) {
769                 struct key_info *kp = &ki[(dir == DIR_ENCRYPT) ? 0 : 1];
770                 memmove(kp->keyid, keyid, keylen);
771                 kp->keylen = keylen;
772         }
773
774         for (strp = &str_keyid[4]; keylen > 0; --keylen) {
775                 if ((*strp++ = *keyid++) == IAC)
776                         *strp++ = IAC;
777         }
778         *strp++ = IAC;
779         *strp++ = SE;
780         net_write(str_keyid, strp - str_keyid);
781         printsub('>', &str_keyid[2], strp - str_keyid - 2);
782 }
783
784 void
785 encrypt_auto(int on)
786 {
787         if (on < 0)
788                 autoencrypt ^= 1;
789         else
790                 autoencrypt = on ? 1 : 0;
791 }
792
793 void
794 decrypt_auto(int on)
795 {
796         if (on < 0)
797                 autodecrypt ^= 1;
798         else
799                 autodecrypt = on ? 1 : 0;
800 }
801
802 void
803 encrypt_start_output(int type)
804 {
805         Encryptions *ep;
806         unsigned char *p;
807         int i;
808
809         if (!(ep = findencryption(type))) {
810                 if (encrypt_debug_mode) {
811                         printf(">>>%s: Can't encrypt with type %s (%d)\r\n",
812                                 Name,
813                                 ENCTYPE_NAME_OK(type)
814                                         ? ENCTYPE_NAME(type) : "(unknown)",
815                                 type);
816                 }
817                 return;
818         }
819         if (ep->start) {
820                 i = (*ep->start)(DIR_ENCRYPT, Server);
821                 if (encrypt_debug_mode) {
822                         printf(">>>%s: Encrypt start: %s (%d) %s\r\n",
823                                 Name,
824                                 (i < 0) ? "failed" :
825                                         "initial negotiation in progress",
826                                 i, ENCTYPE_NAME(type));
827                 }
828                 if (i)
829                         return;
830         }
831         p = str_start + 3;
832         *p++ = ENCRYPT_START;
833         for (i = 0; i < ki[0].keylen; ++i) {
834                 if ((*p++ = ki[0].keyid[i]) == IAC)
835                         *p++ = IAC;
836         }
837         *p++ = IAC;
838         *p++ = SE;
839         net_write(str_start, p - str_start);
840         net_encrypt();
841         printsub('>', &str_start[2], p - &str_start[2]);
842         /*
843          * If we are already encrypting in some mode, then
844          * encrypt the ring (which includes our request) in
845          * the old mode, mark it all as "clear text" and then
846          * switch to the new mode.
847          */
848         encrypt_output = ep->output;
849         encrypt_mode = type;
850         if (encrypt_debug_mode)
851                 printf(">>>%s: Started to encrypt output with type %s\r\n",
852                         Name, ENCTYPE_NAME(type));
853         if (encrypt_verbose)
854                 printf("[ Output is now encrypted with type %s ]\r\n",
855                         ENCTYPE_NAME(type));
856 }
857
858 void
859 encrypt_send_end(void)
860 {
861         if (!encrypt_output)
862                 return;
863
864         str_end[3] = ENCRYPT_END;
865         net_write(str_end, sizeof(str_end));
866         net_encrypt();
867         printsub('>', &str_end[2], sizeof(str_end) - 2);
868         /*
869          * Encrypt the output buffer now because it will not be done by
870          * netflush...
871          */
872         encrypt_output = 0;
873         if (encrypt_debug_mode)
874                 printf(">>>%s: Output is back to clear text\r\n", Name);
875         if (encrypt_verbose)
876                 printf("[ Output is now clear text ]\r\n");
877 }
878
879 void
880 encrypt_send_request_start(void)
881 {
882         unsigned char *p;
883         int i;
884
885         p = &str_start[3];
886         *p++ = ENCRYPT_REQSTART;
887         for (i = 0; i < ki[1].keylen; ++i) {
888                 if ((*p++ = ki[1].keyid[i]) == IAC)
889                         *p++ = IAC;
890         }
891         *p++ = IAC;
892         *p++ = SE;
893         net_write(str_start, p - str_start);
894         printsub('>', &str_start[2], p - &str_start[2]);
895         if (encrypt_debug_mode)
896                 printf(">>>%s: Request input to be encrypted\r\n", Name);
897 }
898
899 void
900 encrypt_send_request_end(void)
901 {
902         str_end[3] = ENCRYPT_REQEND;
903         net_write(str_end, sizeof(str_end));
904         printsub('>', &str_end[2], sizeof(str_end) - 2);
905
906         if (encrypt_debug_mode)
907                 printf(">>>%s: Request input to be clear text\r\n", Name);
908 }
909
910 void
911 encrypt_wait(void)
912 {
913         if (encrypt_debug_mode)
914                 printf(">>>%s: in encrypt_wait\r\n", Name);
915         if (!havesessionkey || !(I_SUPPORT_ENCRYPT & remote_supports_decrypt))
916                 return;
917         while (autoencrypt && !encrypt_output)
918                 if (telnet_spin())
919                         return;
920 }
921
922 void
923 encrypt_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
924 {
925         char tbuf[16], *cp;
926
927         cnt -= 2;
928         data += 2;
929         buf[buflen-1] = '\0';
930         buf[buflen-2] = '*';
931         buflen -= 2;;
932         for (; cnt > 0; cnt--, data++) {
933                 sprintf(tbuf, " %d", *data);
934                 for (cp = tbuf; *cp && buflen > 0; --buflen)
935                         *buf++ = *cp++;
936                 if (buflen <= 0)
937                         return;
938         }
939         *buf = '\0';
940 }
941
942 void
943 encrypt_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
944 {
945         Encryptions *ep;
946         int type = data[1];
947
948         for (ep = encryptions; ep->type && ep->type != type; ep++)
949                 ;
950
951         if (ep->printsub)
952                 (*ep->printsub)(data, cnt, buf, buflen);
953         else
954                 encrypt_gen_printsub(data, cnt, buf, buflen);
955 }
956 #endif  /* ENCRYPTION */