1 /*- 2 * Copyright (c) 2000 Semen Ustimenko <semenu@FreeBSD.org> 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 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include <sys/types.h> 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <termios.h> 35 #ifdef __FreeBSD__ 36 #include <sha.h> 37 #else 38 #include <openssl/sha.h> 39 #endif 40 #include <openssl/rc4.h> 41 42 #include "defs.h" 43 #include "mbuf.h" 44 #include "log.h" 45 #include "timer.h" 46 #include "fsm.h" 47 #include "lqr.h" 48 #include "hdlc.h" 49 #include "lcp.h" 50 #include "ccp.h" 51 #include "throughput.h" 52 #include "layer.h" 53 #include "link.h" 54 #include "chap_ms.h" 55 #include "proto.h" 56 #include "mppe.h" 57 58 /* 59 * Documentation: 60 * 61 * draft-ietf-pppext-mppe-04.txt 62 * draft-ietf-pppext-mppe-keys-02.txt 63 */ 64 65 #define MPPE_OPT_STATELESS 0x1000000 66 #define MPPE_OPT_COMPRESSED 0x01 67 #define MPPE_OPT_40BIT 0x20 68 #define MPPE_OPT_56BIT 0x80 69 #define MPPE_OPT_128BIT 0x40 70 #define MPPE_OPT_BITMASK 0xe0 71 #define MPPE_OPT_MASK (MPPE_OPT_STATELESS | MPPE_OPT_BITMASK) 72 73 #define MPPE_FLUSHED 0x8000 74 #define MPPE_ENCRYPTED 0x1000 75 #define MPPE_HEADER_BITMASK 0xf000 76 #define MPPE_HEADER_FLAG 0x00ff 77 #define MPPE_HEADER_FLAGMASK 0x00ff 78 #define MPPE_HEADER_FLAGSHIFT 8 79 80 struct mppe_state { 81 unsigned stateless : 1; 82 unsigned flushnext : 1; 83 unsigned flushrequired : 1; 84 int cohnum; 85 int keylen; /* 8 or 16 bytes */ 86 int keybits; /* 40, 56 or 128 bits */ 87 char sesskey[MPPE_KEY_LEN]; 88 char mastkey[MPPE_KEY_LEN]; 89 RC4_KEY rc4key; 90 }; 91 92 int MPPE_MasterKeyValid = 0; 93 int MPPE_IsServer = 0; 94 char MPPE_MasterKey[MPPE_KEY_LEN]; 95 96 /* 97 * The peer has missed a packet. Mark the next output frame to be FLUSHED 98 */ 99 static int 100 MPPEResetOutput(void *v) 101 { 102 struct mppe_state *mop = (struct mppe_state *)v; 103 104 if (mop->stateless) 105 log_Printf(LogCCP, "MPPE: Unexpected output channel reset\n"); 106 else { 107 log_Printf(LogCCP, "MPPE: Output channel reset\n"); 108 mop->flushnext = 1; 109 } 110 111 return 0; /* Ask FSM not to ACK */ 112 } 113 114 static void 115 MPPEReduceSessionKey(struct mppe_state *mp) 116 { 117 switch(mp->keybits) { 118 case 40: 119 mp->sesskey[2] = 0x9e; 120 mp->sesskey[1] = 0x26; 121 case 56: 122 mp->sesskey[0] = 0xd1; 123 case 128: 124 } 125 } 126 127 static void 128 MPPEKeyChange(struct mppe_state *mp) 129 { 130 char InterimKey[MPPE_KEY_LEN]; 131 RC4_KEY RC4Key; 132 133 GetNewKeyFromSHA(mp->mastkey, mp->sesskey, mp->keylen, InterimKey); 134 RC4_set_key(&RC4Key, mp->keylen, InterimKey); 135 RC4(&RC4Key, mp->keylen, InterimKey, mp->sesskey); 136 137 MPPEReduceSessionKey(mp); 138 } 139 140 static struct mbuf * 141 MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto, 142 struct mbuf *mp) 143 { 144 struct mppe_state *mop = (struct mppe_state *)v; 145 struct mbuf *mo; 146 u_short nproto, prefix; 147 int dictinit, ilen, len; 148 char *rp; 149 150 ilen = m_length(mp); 151 dictinit = 0; 152 153 log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen); 154 if (*proto < 0x21 && *proto > 0xFA) { 155 log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n"); 156 ccp->compout += ilen; 157 ccp->uncompout += ilen; 158 return mp; 159 } 160 161 log_DumpBp(LogDEBUG, "MPPE: Output: Encrypt packet:", mp); 162 163 /* Get mbuf for prefixes */ 164 mo = m_get(4, MB_CCPOUT); 165 mo->m_next = mp; 166 167 rp = MBUF_CTOP(mo); 168 prefix = MPPE_ENCRYPTED | mop->cohnum; 169 170 if (mop->stateless || 171 (mop->cohnum & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) { 172 /* Change our key */ 173 log_Printf(LogDEBUG, "MPPEOutput: Key changed [%d]\n", mop->cohnum); 174 MPPEKeyChange(mop); 175 dictinit = 1; 176 } 177 178 if (mop->stateless || mop->flushnext) { 179 prefix |= MPPE_FLUSHED; 180 dictinit = 1; 181 mop->flushnext = 0; 182 } 183 184 if (dictinit) { 185 /* Initialise our dictionary */ 186 log_Printf(LogDEBUG, "MPPEOutput: Dictionary initialised [%d]\n", 187 mop->cohnum); 188 RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); 189 } 190 191 /* Set MPPE packet prefix */ 192 *(u_short *)rp = htons(prefix); 193 194 /* Save encrypted protocol number */ 195 nproto = htons(*proto); 196 RC4(&mop->rc4key, 2, (char *)&nproto, rp + 2); 197 198 /* Encrypt main packet */ 199 rp = MBUF_CTOP(mp); 200 RC4(&mop->rc4key, ilen, rp, rp); 201 202 mop->cohnum++; 203 mop->cohnum &= ~MPPE_HEADER_BITMASK; 204 205 /* Set the protocol number */ 206 *proto = ccp_Proto(ccp); 207 len = m_length(mo); 208 ccp->uncompout += ilen; 209 ccp->compout += len; 210 211 log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n", 212 *proto, len); 213 214 return mo; 215 } 216 217 static void 218 MPPEResetInput(void *v) 219 { 220 log_Printf(LogCCP, "MPPE: Unexpected input channel ack\n"); 221 } 222 223 static struct mbuf * 224 MPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp) 225 { 226 struct mppe_state *mip = (struct mppe_state *)v; 227 u_short prefix; 228 char *rp; 229 int dictinit, flushed, ilen, len, n; 230 231 ilen = m_length(mp); 232 dictinit = 0; 233 ccp->compin += ilen; 234 235 log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen); 236 log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp); 237 238 mp = mbuf_Read(mp, &prefix, 2); 239 prefix = ntohs(prefix); 240 flushed = prefix & MPPE_FLUSHED; 241 prefix &= ~flushed; 242 if ((prefix & MPPE_HEADER_BITMASK) != MPPE_ENCRYPTED) { 243 log_Printf(LogERROR, "MPPE: Input: Invalid packet (flags = 0x%x)\n", 244 (prefix & MPPE_HEADER_BITMASK) | flushed); 245 m_freem(mp); 246 return NULL; 247 } 248 249 prefix &= ~MPPE_HEADER_BITMASK; 250 251 if (!flushed && mip->stateless) { 252 log_Printf(LogCCP, "MPPEInput: Packet without MPPE_FLUSHED set" 253 " in stateless mode\n"); 254 flushed = MPPE_FLUSHED; 255 /* Should we really continue ? */ 256 } 257 258 if (mip->stateless) { 259 /* Change our key for each missed packet in stateless mode */ 260 while (prefix != mip->cohnum) { 261 log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix); 262 MPPEKeyChange(mip); 263 /* 264 * mip->cohnum contains what we received last time in stateless 265 * mode. 266 */ 267 mip->cohnum++; 268 mip->cohnum &= ~MPPE_HEADER_BITMASK; 269 } 270 dictinit = 1; 271 } else { 272 if (flushed) { 273 /* 274 * We can always process a flushed packet. 275 * Catch up on any outstanding key changes. 276 */ 277 n = (prefix >> MPPE_HEADER_FLAGSHIFT) - 278 (mip->cohnum >> MPPE_HEADER_FLAGSHIFT); 279 while (n--) { 280 log_Printf(LogDEBUG, "MPPEInput: Key changed during catchup [%u]\n", 281 prefix); 282 MPPEKeyChange(mip); 283 } 284 mip->flushrequired = 0; 285 mip->cohnum = prefix; 286 dictinit = 1; 287 } 288 289 if (mip->flushrequired) { 290 /* 291 * Perhaps we should be lenient if 292 * (prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG 293 * The spec says that we shouldn't be though.... 294 */ 295 log_Printf(LogDEBUG, "MPPE: Not flushed - discarded\n"); 296 m_freem(mp); 297 return NULL; 298 } 299 300 if (prefix != mip->cohnum) { 301 /* 302 * We're in stateful mode and didn't receive the expected 303 * packet. Send a reset request, but don't tell the CCP layer 304 * about it as we don't expect to receive a Reset ACK ! 305 * Guess what... M$ invented this ! 306 */ 307 log_Printf(LogCCP, "MPPE: Input: Got seq %u, not %u\n", 308 prefix, mip->cohnum); 309 fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0, 310 MB_CCPOUT); 311 mip->flushrequired = 1; 312 m_freem(mp); 313 return NULL; 314 } 315 316 if ((prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) { 317 log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix); 318 MPPEKeyChange(mip); 319 dictinit = 1; 320 } else if (flushed) 321 dictinit = 1; 322 323 /* 324 * mip->cohnum contains what we expect to receive next time in stateful 325 * mode. 326 */ 327 mip->cohnum++; 328 mip->cohnum &= ~MPPE_HEADER_BITMASK; 329 } 330 331 if (dictinit) { 332 log_Printf(LogDEBUG, "MPPEInput: Dictionary initialised [%u]\n", prefix); 333 RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); 334 } 335 336 mp = mbuf_Read(mp, proto, 2); 337 RC4(&mip->rc4key, 2, (char *)proto, (char *)proto); 338 *proto = ntohs(*proto); 339 340 rp = MBUF_CTOP(mp); 341 len = m_length(mp); 342 RC4(&mip->rc4key, len, rp, rp); 343 344 log_Printf(LogDEBUG, "MPPEInput: Decrypted: Proto %02x (%d bytes)\n", 345 *proto, len); 346 log_DumpBp(LogDEBUG, "MPPEInput: Decrypted: Packet:", mp); 347 348 ccp->uncompin += len; 349 350 return mp; 351 } 352 353 static void 354 MPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi) 355 { 356 } 357 358 static const char * 359 MPPEDispOpts(struct lcp_opt *o) 360 { 361 static char buf[70]; 362 u_int32_t val = ntohl(*(u_int32_t *)o->data); 363 char ch; 364 int len; 365 366 snprintf(buf, sizeof buf, "value 0x%08x ", (unsigned)val); 367 len = strlen(buf); 368 if (!(val & MPPE_OPT_BITMASK)) { 369 snprintf(buf + len, sizeof buf - len, "(0"); 370 len++; 371 } else { 372 ch = '('; 373 if (val & MPPE_OPT_128BIT) { 374 snprintf(buf + len, sizeof buf - len, "%c128", ch); 375 len += strlen(buf + len); 376 ch = '/'; 377 } 378 if (val & MPPE_OPT_56BIT) { 379 snprintf(buf + len, sizeof buf - len, "%c56", ch); 380 len += strlen(buf + len); 381 ch = '/'; 382 } 383 if (val & MPPE_OPT_40BIT) { 384 snprintf(buf + len, sizeof buf - len, "%c40", ch); 385 len += strlen(buf + len); 386 ch = '/'; 387 } 388 } 389 390 snprintf(buf + len, sizeof buf - len, " bits, state%s", 391 (val & MPPE_OPT_STATELESS) ? "less" : "full"); 392 len += strlen(buf + len); 393 394 if (val & MPPE_OPT_COMPRESSED) { 395 snprintf(buf + len, sizeof buf - len, ", compressed"); 396 len += strlen(buf + len); 397 } 398 399 snprintf(buf + len, sizeof buf - len, ")"); 400 401 return buf; 402 } 403 404 static int 405 MPPEUsable(struct fsm *fp) 406 { 407 struct lcp *lcp; 408 int ok; 409 410 lcp = &fp->link->lcp; 411 ok = (lcp->want_auth == PROTO_CHAP && lcp->want_authtype == 0x81) || 412 (lcp->his_auth == PROTO_CHAP && lcp->his_authtype == 0x81); 413 if (!ok) 414 log_Printf(LogCCP, "MPPE: Not usable without CHAP81\n"); 415 416 return ok; 417 } 418 419 static int 420 MPPERequired(struct fsm *fp) 421 { 422 return fp->link->ccp.cfg.mppe.required; 423 } 424 425 static u_int32_t 426 MPPE_ConfigVal(const struct ccp_config *cfg) 427 { 428 u_int32_t val; 429 430 val = cfg->mppe.state == MPPE_STATELESS ? MPPE_OPT_STATELESS : 0; 431 switch(cfg->mppe.keybits) { 432 case 128: 433 val |= MPPE_OPT_128BIT; 434 break; 435 case 56: 436 val |= MPPE_OPT_56BIT; 437 break; 438 case 40: 439 val |= MPPE_OPT_40BIT; 440 break; 441 case 0: 442 val |= MPPE_OPT_128BIT | MPPE_OPT_56BIT | MPPE_OPT_40BIT; 443 break; 444 } 445 446 return val; 447 } 448 449 /* 450 * What options should we use for our first configure request 451 */ 452 static void 453 MPPEInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) 454 { 455 u_int32_t *p = (u_int32_t *)o->data; 456 457 o->len = 6; 458 459 if (!MPPE_MasterKeyValid) { 460 log_Printf(LogCCP, "MPPE: MasterKey is invalid," 461 " MPPE is available only with CHAP81 authentication\n"); 462 *p = htonl(0x0); 463 return; 464 } 465 466 *p = htonl(MPPE_ConfigVal(cfg)); 467 } 468 469 /* 470 * Our CCP request was NAK'd with the given options 471 */ 472 static int 473 MPPESetOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg) 474 { 475 u_int32_t *p = (u_int32_t *)o->data; 476 u_int32_t peer = ntohl(*p); 477 u_int32_t mval; 478 479 if (!MPPE_MasterKeyValid) 480 /* Treat their NAK as a REJ */ 481 return MODE_NAK; 482 483 mval = MPPE_ConfigVal(cfg); 484 485 /* 486 * If we haven't been configured with a specific number of keybits, allow 487 * whatever the peer asks for. 488 */ 489 if (!cfg->mppe.keybits) { 490 mval &= ~MPPE_OPT_BITMASK; 491 mval |= (peer & MPPE_OPT_BITMASK); 492 if (!(mval & MPPE_OPT_BITMASK)) 493 mval |= MPPE_OPT_128BIT; 494 } 495 496 /* Adjust our statelessness */ 497 if (cfg->mppe.state == MPPE_ANYSTATE) { 498 mval &= ~MPPE_OPT_STATELESS; 499 mval |= (peer & MPPE_OPT_STATELESS); 500 } 501 502 *p = htonl(mval); 503 504 return MODE_ACK; 505 } 506 507 /* 508 * The peer has requested the given options 509 */ 510 static int 511 MPPESetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg) 512 { 513 u_int32_t *p = (u_int32_t *)(o->data); 514 u_int32_t peer = ntohl(*p); 515 u_int32_t mval; 516 int res = MODE_ACK; 517 518 if (!MPPE_MasterKeyValid) { 519 if (*p != 0x0) { 520 *p = 0x0; 521 return MODE_NAK; 522 } else 523 return MODE_ACK; 524 } 525 526 mval = MPPE_ConfigVal(cfg); 527 528 if (peer & ~MPPE_OPT_MASK) 529 /* He's asking for bits we don't know about */ 530 res = MODE_NAK; 531 532 if (peer & MPPE_OPT_STATELESS) { 533 if (cfg->mppe.state == MPPE_STATEFUL) 534 /* Peer can't have stateless */ 535 res = MODE_NAK; 536 else 537 /* Peer wants stateless, that's ok */ 538 mval |= MPPE_OPT_STATELESS; 539 } else { 540 if (cfg->mppe.state == MPPE_STATELESS) 541 /* Peer must have stateless */ 542 res = MODE_NAK; 543 else 544 /* Peer doesn't want stateless, that's ok */ 545 mval &= ~MPPE_OPT_STATELESS; 546 } 547 548 /* If we've got a configured number of keybits - the peer must use that */ 549 if (cfg->mppe.keybits) { 550 *p = htonl(mval); 551 return peer == mval ? res : MODE_NAK; 552 } 553 554 /* If a specific number of bits hasn't been requested, we'll need to NAK */ 555 switch (peer & MPPE_OPT_BITMASK) { 556 case MPPE_OPT_128BIT: 557 case MPPE_OPT_56BIT: 558 case MPPE_OPT_40BIT: 559 break; 560 default: 561 res = MODE_NAK; 562 } 563 564 /* Suggest the best number of bits */ 565 mval &= ~MPPE_OPT_BITMASK; 566 if (peer & MPPE_OPT_128BIT) 567 mval |= MPPE_OPT_128BIT; 568 else if (peer & MPPE_OPT_56BIT) 569 mval |= MPPE_OPT_56BIT; 570 else if (peer & MPPE_OPT_40BIT) 571 mval |= MPPE_OPT_40BIT; 572 else 573 mval |= MPPE_OPT_128BIT; 574 *p = htonl(mval); 575 576 return res; 577 } 578 579 static struct mppe_state * 580 MPPE_InitState(struct lcp_opt *o) 581 { 582 struct mppe_state *mp; 583 u_int32_t val; 584 585 if ((mp = calloc(1, sizeof *mp)) != NULL) { 586 val = ntohl(*(u_int32_t *)o->data); 587 588 switch (val & MPPE_OPT_BITMASK) { 589 case MPPE_OPT_128BIT: 590 mp->keylen = 16; 591 mp->keybits = 128; 592 break; 593 case MPPE_OPT_56BIT: 594 mp->keylen = 8; 595 mp->keybits = 56; 596 break; 597 case MPPE_OPT_40BIT: 598 mp->keylen = 8; 599 mp->keybits = 40; 600 break; 601 default: 602 log_Printf(LogWARN, "Unexpected MPPE options 0x%08x\n", val); 603 free(mp); 604 return NULL; 605 } 606 607 mp->stateless = !!(val & MPPE_OPT_STATELESS); 608 } 609 610 return mp; 611 } 612 613 static void * 614 MPPEInitInput(struct lcp_opt *o) 615 { 616 struct mppe_state *mip; 617 618 if (!MPPE_MasterKeyValid) { 619 log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n"); 620 return NULL; 621 } 622 623 if ((mip = MPPE_InitState(o)) == NULL) { 624 log_Printf(LogWARN, "MPPEInput: Cannot initialise - unexpected options\n"); 625 return NULL; 626 } 627 628 log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits); 629 630 GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0, 631 MPPE_IsServer); 632 GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey); 633 634 MPPEReduceSessionKey(mip); 635 636 log_Printf(LogCCP, "MPPE: Input channel initiated\n"); 637 638 if (!mip->stateless) { 639 /* 640 * We need to initialise our dictionary here as the first packet we 641 * receive is unlikely to have the FLUSHED bit set. 642 */ 643 log_Printf(LogDEBUG, "MPPEInitInput: Dictionary initialised [%d]\n", 644 mip->cohnum); 645 RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey); 646 } else { 647 /* 648 * We do the first key change here as the first packet is expected 649 * to have a sequence number of 0 and we'll therefore not expect 650 * to have to change the key at that point. 651 */ 652 log_Printf(LogDEBUG, "MPPEInitInput: Key changed [%d]\n", mip->cohnum); 653 MPPEKeyChange(mip); 654 } 655 656 return mip; 657 } 658 659 static void * 660 MPPEInitOutput(struct lcp_opt *o) 661 { 662 struct mppe_state *mop; 663 664 if (!MPPE_MasterKeyValid) { 665 log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n"); 666 return NULL; 667 } 668 669 if ((mop = MPPE_InitState(o)) == NULL) { 670 log_Printf(LogWARN, "MPPEOutput: Cannot initialise - unexpected options\n"); 671 return NULL; 672 } 673 674 log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits); 675 676 GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1, 677 MPPE_IsServer); 678 GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey); 679 680 MPPEReduceSessionKey(mop); 681 682 log_Printf(LogCCP, "MPPE: Output channel initiated\n"); 683 684 if (!mop->stateless) { 685 /* 686 * We need to initialise our dictionary now as the first packet we 687 * send won't have the FLUSHED bit set. 688 */ 689 log_Printf(LogDEBUG, "MPPEInitOutput: Dictionary initialised [%d]\n", 690 mop->cohnum); 691 RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey); 692 } 693 694 return mop; 695 } 696 697 static void 698 MPPETermInput(void *v) 699 { 700 free(v); 701 } 702 703 static void 704 MPPETermOutput(void *v) 705 { 706 free(v); 707 } 708 709 const struct ccp_algorithm MPPEAlgorithm = { 710 TY_MPPE, 711 CCP_NEG_MPPE, 712 MPPEDispOpts, 713 MPPEUsable, 714 MPPERequired, 715 { 716 MPPESetOptsInput, 717 MPPEInitInput, 718 MPPETermInput, 719 MPPEResetInput, 720 MPPEInput, 721 MPPEDictSetup 722 }, 723 { 724 MPPEInitOptsOutput, 725 MPPESetOptsOutput, 726 MPPEInitOutput, 727 MPPETermOutput, 728 MPPEResetOutput, 729 MPPEOutput 730 }, 731 }; 732