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