MFC:
[dragonfly.git] / usr.sbin / ppp / mppe.c
blob632209ac18653c9d2697c1e8e6bde5f13c749661
1 /*-
2 * Copyright (c) 2000 Semen Ustimenko <semenu@FreeBSD.org>
3 * All rights reserved.
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.
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.
26 * $FreeBSD: src/usr.sbin/ppp/mppe.c,v 1.4.2.6 2002/09/01 02:12:29 brian Exp $
27 * $DragonFly: src/usr.sbin/ppp/mppe.c,v 1.2 2003/06/17 04:30:00 dillon Exp $
30 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/in.h>
35 #include <netinet/ip.h>
36 #include <sys/un.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <termios.h>
42 #include <openssl/rc4.h>
44 #include "defs.h"
45 #include "mbuf.h"
46 #include "log.h"
47 #include "timer.h"
48 #include "fsm.h"
49 #include "lqr.h"
50 #include "hdlc.h"
51 #include "lcp.h"
52 #include "ccp.h"
53 #include "throughput.h"
54 #include "layer.h"
55 #include "link.h"
56 #include "chap_ms.h"
57 #include "proto.h"
58 #include "mppe.h"
59 #include "ua.h"
60 #include "descriptor.h"
61 #ifndef NORADIUS
62 #include "radius.h"
63 #endif
64 #include "ncpaddr.h"
65 #include "iplist.h"
66 #include "slcompress.h"
67 #include "ipcp.h"
68 #include "ipv6cp.h"
69 #include "filter.h"
70 #include "mp.h"
71 #include "ncp.h"
72 #include "bundle.h"
75 * Documentation:
77 * draft-ietf-pppext-mppe-04.txt
78 * draft-ietf-pppext-mppe-keys-02.txt
81 #define MPPE_OPT_STATELESS 0x1000000
82 #define MPPE_OPT_COMPRESSED 0x01
83 #define MPPE_OPT_40BIT 0x20
84 #define MPPE_OPT_56BIT 0x80
85 #define MPPE_OPT_128BIT 0x40
86 #define MPPE_OPT_BITMASK 0xe0
87 #define MPPE_OPT_MASK (MPPE_OPT_STATELESS | MPPE_OPT_BITMASK)
89 #define MPPE_FLUSHED 0x8000
90 #define MPPE_ENCRYPTED 0x1000
91 #define MPPE_HEADER_BITMASK 0xf000
92 #define MPPE_HEADER_FLAG 0x00ff
93 #define MPPE_HEADER_FLAGMASK 0x00ff
94 #define MPPE_HEADER_FLAGSHIFT 8
95 #define MPPE_HEADER_STATEFUL_KEYCHANGES 16
97 struct mppe_state {
98 unsigned stateless : 1;
99 unsigned flushnext : 1;
100 unsigned flushrequired : 1;
101 int cohnum;
102 int keylen; /* 8 or 16 bytes */
103 int keybits; /* 40, 56 or 128 bits */
104 char sesskey[MPPE_KEY_LEN];
105 char mastkey[MPPE_KEY_LEN];
106 RC4_KEY rc4key;
109 int MPPE_MasterKeyValid = 0;
110 int MPPE_IsServer = 0;
111 char MPPE_MasterKey[MPPE_KEY_LEN];
114 * The peer has missed a packet. Mark the next output frame to be FLUSHED
116 static int
117 MPPEResetOutput(void *v)
119 struct mppe_state *mop = (struct mppe_state *)v;
121 if (mop->stateless)
122 log_Printf(LogCCP, "MPPE: Unexpected output channel reset\n");
123 else {
124 log_Printf(LogCCP, "MPPE: Output channel reset\n");
125 mop->flushnext = 1;
128 return 0; /* Ask FSM not to ACK */
131 static void
132 MPPEReduceSessionKey(struct mppe_state *mp)
134 switch(mp->keybits) {
135 case 40:
136 mp->sesskey[2] = 0x9e;
137 mp->sesskey[1] = 0x26;
138 case 56:
139 mp->sesskey[0] = 0xd1;
140 case 128:
141 break;
145 static void
146 MPPEKeyChange(struct mppe_state *mp)
148 char InterimKey[MPPE_KEY_LEN];
149 RC4_KEY RC4Key;
151 GetNewKeyFromSHA(mp->mastkey, mp->sesskey, mp->keylen, InterimKey);
152 RC4_set_key(&RC4Key, mp->keylen, InterimKey);
153 RC4(&RC4Key, mp->keylen, InterimKey, mp->sesskey);
155 MPPEReduceSessionKey(mp);
158 static struct mbuf *
159 MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto,
160 struct mbuf *mp)
162 struct mppe_state *mop = (struct mppe_state *)v;
163 struct mbuf *mo;
164 u_short nproto, prefix;
165 int dictinit, ilen, len;
166 char *rp;
168 ilen = m_length(mp);
169 dictinit = 0;
171 log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen);
172 if (*proto < 0x21 && *proto > 0xFA) {
173 log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n");
174 ccp->compout += ilen;
175 ccp->uncompout += ilen;
176 return mp;
179 log_DumpBp(LogDEBUG, "MPPE: Output: Encrypt packet:", mp);
181 /* Get mbuf for prefixes */
182 mo = m_get(4, MB_CCPOUT);
183 mo->m_next = mp;
185 rp = MBUF_CTOP(mo);
186 prefix = MPPE_ENCRYPTED | mop->cohnum;
188 if (mop->stateless ||
189 (mop->cohnum & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) {
190 /* Change our key */
191 log_Printf(LogDEBUG, "MPPEOutput: Key changed [%d]\n", mop->cohnum);
192 MPPEKeyChange(mop);
193 dictinit = 1;
196 if (mop->stateless || mop->flushnext) {
197 prefix |= MPPE_FLUSHED;
198 dictinit = 1;
199 mop->flushnext = 0;
202 if (dictinit) {
203 /* Initialise our dictionary */
204 log_Printf(LogDEBUG, "MPPEOutput: Dictionary initialised [%d]\n",
205 mop->cohnum);
206 RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey);
209 /* Set MPPE packet prefix */
210 ua_htons(&prefix, rp);
212 /* Save encrypted protocol number */
213 nproto = htons(*proto);
214 RC4(&mop->rc4key, 2, (char *)&nproto, rp + 2);
216 /* Encrypt main packet */
217 rp = MBUF_CTOP(mp);
218 RC4(&mop->rc4key, ilen, rp, rp);
220 mop->cohnum++;
221 mop->cohnum &= ~MPPE_HEADER_BITMASK;
223 /* Set the protocol number */
224 *proto = ccp_Proto(ccp);
225 len = m_length(mo);
226 ccp->uncompout += ilen;
227 ccp->compout += len;
229 log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n",
230 *proto, len);
232 return mo;
235 static void
236 MPPEResetInput(void *v)
238 log_Printf(LogCCP, "MPPE: Unexpected input channel ack\n");
241 static struct mbuf *
242 MPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp)
244 struct mppe_state *mip = (struct mppe_state *)v;
245 u_short prefix;
246 char *rp;
247 int dictinit, flushed, ilen, len, n;
249 ilen = m_length(mp);
250 dictinit = 0;
251 ccp->compin += ilen;
253 log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen);
254 log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp);
256 mp = mbuf_Read(mp, &prefix, 2);
257 prefix = ntohs(prefix);
258 flushed = prefix & MPPE_FLUSHED;
259 prefix &= ~flushed;
260 if ((prefix & MPPE_HEADER_BITMASK) != MPPE_ENCRYPTED) {
261 log_Printf(LogERROR, "MPPE: Input: Invalid packet (flags = 0x%x)\n",
262 (prefix & MPPE_HEADER_BITMASK) | flushed);
263 m_freem(mp);
264 return NULL;
267 prefix &= ~MPPE_HEADER_BITMASK;
269 if (!flushed && mip->stateless) {
270 log_Printf(LogCCP, "MPPEInput: Packet without MPPE_FLUSHED set"
271 " in stateless mode\n");
272 flushed = MPPE_FLUSHED;
273 /* Should we really continue ? */
276 if (mip->stateless) {
277 /* Change our key for each missed packet in stateless mode */
278 while (prefix != mip->cohnum) {
279 log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix);
280 MPPEKeyChange(mip);
282 * mip->cohnum contains what we received last time in stateless
283 * mode.
285 mip->cohnum++;
286 mip->cohnum &= ~MPPE_HEADER_BITMASK;
288 dictinit = 1;
289 } else {
290 if (flushed) {
292 * We can always process a flushed packet.
293 * Catch up on any outstanding key changes.
295 n = (prefix >> MPPE_HEADER_FLAGSHIFT) -
296 (mip->cohnum >> MPPE_HEADER_FLAGSHIFT);
297 if (n < 0)
298 n += MPPE_HEADER_STATEFUL_KEYCHANGES;
299 while (n--) {
300 log_Printf(LogDEBUG, "MPPEInput: Key changed during catchup [%u]\n",
301 prefix);
302 MPPEKeyChange(mip);
304 mip->flushrequired = 0;
305 mip->cohnum = prefix;
306 dictinit = 1;
309 if (mip->flushrequired) {
311 * Perhaps we should be lenient if
312 * (prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG
313 * The spec says that we shouldn't be though....
315 log_Printf(LogDEBUG, "MPPE: Not flushed - discarded\n");
316 fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0,
317 MB_CCPOUT);
318 m_freem(mp);
319 return NULL;
322 if (prefix != mip->cohnum) {
324 * We're in stateful mode and didn't receive the expected
325 * packet. Send a reset request, but don't tell the CCP layer
326 * about it as we don't expect to receive a Reset ACK !
327 * Guess what... M$ invented this !
329 log_Printf(LogCCP, "MPPE: Input: Got seq %u, not %u\n",
330 prefix, mip->cohnum);
331 fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0,
332 MB_CCPOUT);
333 mip->flushrequired = 1;
334 m_freem(mp);
335 return NULL;
338 if ((prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) {
339 log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix);
340 MPPEKeyChange(mip);
341 dictinit = 1;
342 } else if (flushed)
343 dictinit = 1;
346 * mip->cohnum contains what we expect to receive next time in stateful
347 * mode.
349 mip->cohnum++;
350 mip->cohnum &= ~MPPE_HEADER_BITMASK;
353 if (dictinit) {
354 log_Printf(LogDEBUG, "MPPEInput: Dictionary initialised [%u]\n", prefix);
355 RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey);
358 mp = mbuf_Read(mp, proto, 2);
359 RC4(&mip->rc4key, 2, (char *)proto, (char *)proto);
360 *proto = ntohs(*proto);
362 rp = MBUF_CTOP(mp);
363 len = m_length(mp);
364 RC4(&mip->rc4key, len, rp, rp);
366 log_Printf(LogDEBUG, "MPPEInput: Decrypted: Proto %02x (%d bytes)\n",
367 *proto, len);
368 log_DumpBp(LogDEBUG, "MPPEInput: Decrypted: Packet:", mp);
370 ccp->uncompin += len;
372 return mp;
375 static void
376 MPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi)
380 static const char *
381 MPPEDispOpts(struct fsm_opt *o)
383 static char buf[70];
384 u_int32_t val;
385 char ch;
386 int len, n;
388 ua_ntohl(o->data, &val);
389 len = 0;
390 if ((n = snprintf(buf, sizeof buf, "value 0x%08x ", (unsigned)val)) > 0)
391 len += n;
392 if (!(val & MPPE_OPT_BITMASK)) {
393 if ((n = snprintf(buf + len, sizeof buf - len, "(0")) > 0)
394 len += n;
395 } else {
396 ch = '(';
397 if (val & MPPE_OPT_128BIT) {
398 if ((n = snprintf(buf + len, sizeof buf - len, "%c128", ch)) > 0)
399 len += n;
400 ch = '/';
402 if (val & MPPE_OPT_56BIT) {
403 if ((n = snprintf(buf + len, sizeof buf - len, "%c56", ch)) > 0)
404 len += n;
405 ch = '/';
407 if (val & MPPE_OPT_40BIT) {
408 if ((n = snprintf(buf + len, sizeof buf - len, "%c40", ch)) > 0)
409 len += n;
410 ch = '/';
414 if ((n = snprintf(buf + len, sizeof buf - len, " bits, state%s",
415 (val & MPPE_OPT_STATELESS) ? "less" : "ful")) > 0)
416 len += n;
418 if (val & MPPE_OPT_COMPRESSED) {
419 if ((n = snprintf(buf + len, sizeof buf - len, ", compressed")) > 0)
420 len += n;
423 snprintf(buf + len, sizeof buf - len, ")");
425 return buf;
428 static int
429 MPPEUsable(struct fsm *fp)
431 int ok;
432 #ifndef NORADIUS
433 struct radius *r = &fp->bundle->radius;
436 * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES,
437 * use that instead of our configuration value.
439 if (*r->cfg.file) {
440 ok = r->mppe.sendkeylen && r->mppe.recvkeylen;
441 if (!ok)
442 log_Printf(LogCCP, "MPPE: Not permitted by RADIUS server\n");
443 } else
444 #endif
446 struct lcp *lcp = &fp->link->lcp;
447 ok = (lcp->want_auth == PROTO_CHAP && lcp->want_authtype == 0x81) ||
448 (lcp->his_auth == PROTO_CHAP && lcp->his_authtype == 0x81);
449 if (!ok)
450 log_Printf(LogCCP, "MPPE: Not usable without CHAP81\n");
453 return ok;
456 static int
457 MPPERequired(struct fsm *fp)
459 #ifndef NORADIUS
461 * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY,
462 * use that instead of our configuration value.
464 if (*fp->bundle->radius.cfg.file && fp->bundle->radius.mppe.policy)
465 return fp->bundle->radius.mppe.policy == MPPE_POLICY_REQUIRED ? 1 : 0;
466 #endif
468 return fp->link->ccp.cfg.mppe.required;
471 static u_int32_t
472 MPPE_ConfigVal(struct bundle *bundle, const struct ccp_config *cfg)
474 u_int32_t val;
476 val = cfg->mppe.state == MPPE_STATELESS ? MPPE_OPT_STATELESS : 0;
477 #ifndef NORADIUS
479 * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES,
480 * use that instead of our configuration value.
482 if (*bundle->radius.cfg.file && bundle->radius.mppe.types) {
483 if (bundle->radius.mppe.types & MPPE_TYPE_40BIT)
484 val |= MPPE_OPT_40BIT;
485 if (bundle->radius.mppe.types & MPPE_TYPE_128BIT)
486 val |= MPPE_OPT_128BIT;
487 } else
488 #endif
489 switch(cfg->mppe.keybits) {
490 case 128:
491 val |= MPPE_OPT_128BIT;
492 break;
493 case 56:
494 val |= MPPE_OPT_56BIT;
495 break;
496 case 40:
497 val |= MPPE_OPT_40BIT;
498 break;
499 case 0:
500 val |= MPPE_OPT_128BIT | MPPE_OPT_56BIT | MPPE_OPT_40BIT;
501 break;
504 return val;
508 * What options should we use for our first configure request
510 static void
511 MPPEInitOptsOutput(struct bundle *bundle, struct fsm_opt *o,
512 const struct ccp_config *cfg)
514 u_int32_t mval;
516 o->hdr.len = 6;
518 if (!MPPE_MasterKeyValid) {
519 log_Printf(LogCCP, "MPPE: MasterKey is invalid,"
520 " MPPE is available only with CHAP81 authentication\n");
521 ua_htonl(0x0, o->data);
522 return;
526 mval = MPPE_ConfigVal(bundle, cfg);
527 ua_htonl(&mval, o->data);
531 * Our CCP request was NAK'd with the given options
533 static int
534 MPPESetOptsOutput(struct bundle *bundle, struct fsm_opt *o,
535 const struct ccp_config *cfg)
537 u_int32_t mval, peer;
539 ua_ntohl(o->data, &peer);
541 if (!MPPE_MasterKeyValid)
542 /* Treat their NAK as a REJ */
543 return MODE_NAK;
545 mval = MPPE_ConfigVal(bundle, cfg);
548 * If we haven't been configured with a specific number of keybits, allow
549 * whatever the peer asks for.
551 if (!cfg->mppe.keybits) {
552 mval &= ~MPPE_OPT_BITMASK;
553 mval |= (peer & MPPE_OPT_BITMASK);
554 if (!(mval & MPPE_OPT_BITMASK))
555 mval |= MPPE_OPT_128BIT;
558 /* Adjust our statelessness */
559 if (cfg->mppe.state == MPPE_ANYSTATE) {
560 mval &= ~MPPE_OPT_STATELESS;
561 mval |= (peer & MPPE_OPT_STATELESS);
564 ua_htonl(&mval, o->data);
566 return MODE_ACK;
570 * The peer has requested the given options
572 static int
573 MPPESetOptsInput(struct bundle *bundle, struct fsm_opt *o,
574 const struct ccp_config *cfg)
576 u_int32_t mval, peer;
577 int res = MODE_ACK;
579 ua_ntohl(o->data, &peer);
580 if (!MPPE_MasterKeyValid) {
581 if (peer != 0) {
582 peer = 0;
583 ua_htonl(&peer, o->data);
584 return MODE_NAK;
585 } else
586 return MODE_ACK;
589 mval = MPPE_ConfigVal(bundle, cfg);
591 if (peer & ~MPPE_OPT_MASK)
592 /* He's asking for bits we don't know about */
593 res = MODE_NAK;
595 if (peer & MPPE_OPT_STATELESS) {
596 if (cfg->mppe.state == MPPE_STATEFUL)
597 /* Peer can't have stateless */
598 res = MODE_NAK;
599 else
600 /* Peer wants stateless, that's ok */
601 mval |= MPPE_OPT_STATELESS;
602 } else {
603 if (cfg->mppe.state == MPPE_STATELESS)
604 /* Peer must have stateless */
605 res = MODE_NAK;
606 else
607 /* Peer doesn't want stateless, that's ok */
608 mval &= ~MPPE_OPT_STATELESS;
611 /* If we've got a configured number of keybits - the peer must use that */
612 if (cfg->mppe.keybits) {
613 ua_htonl(&mval, o->data);
614 return peer == mval ? res : MODE_NAK;
617 /* If a specific number of bits hasn't been requested, we'll need to NAK */
618 switch (peer & MPPE_OPT_BITMASK) {
619 case MPPE_OPT_128BIT:
620 case MPPE_OPT_56BIT:
621 case MPPE_OPT_40BIT:
622 break;
623 default:
624 res = MODE_NAK;
627 /* Suggest the best number of bits */
628 mval &= ~MPPE_OPT_BITMASK;
629 if (peer & MPPE_OPT_128BIT)
630 mval |= MPPE_OPT_128BIT;
631 else if (peer & MPPE_OPT_56BIT)
632 mval |= MPPE_OPT_56BIT;
633 else if (peer & MPPE_OPT_40BIT)
634 mval |= MPPE_OPT_40BIT;
635 else
636 mval |= MPPE_OPT_128BIT;
637 ua_htonl(&mval, o->data);
639 return res;
642 static struct mppe_state *
643 MPPE_InitState(struct fsm_opt *o)
645 struct mppe_state *mp;
646 u_int32_t val;
648 if ((mp = calloc(1, sizeof *mp)) != NULL) {
649 ua_ntohl(o->data, &val);
651 switch (val & MPPE_OPT_BITMASK) {
652 case MPPE_OPT_128BIT:
653 mp->keylen = 16;
654 mp->keybits = 128;
655 break;
656 case MPPE_OPT_56BIT:
657 mp->keylen = 8;
658 mp->keybits = 56;
659 break;
660 case MPPE_OPT_40BIT:
661 mp->keylen = 8;
662 mp->keybits = 40;
663 break;
664 default:
665 log_Printf(LogWARN, "Unexpected MPPE options 0x%08x\n", val);
666 free(mp);
667 return NULL;
670 mp->stateless = !!(val & MPPE_OPT_STATELESS);
673 return mp;
676 static void *
677 MPPEInitInput(struct bundle *bundle, struct fsm_opt *o)
679 struct mppe_state *mip;
681 if (!MPPE_MasterKeyValid) {
682 log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n");
683 return NULL;
686 if ((mip = MPPE_InitState(o)) == NULL) {
687 log_Printf(LogWARN, "MPPEInput: Cannot initialise - unexpected options\n");
688 return NULL;
691 log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits);
693 #ifndef NORADIUS
694 if (*bundle->radius.cfg.file && bundle->radius.mppe.recvkey) {
695 if (mip->keylen > bundle->radius.mppe.recvkeylen)
696 mip->keylen = bundle->radius.mppe.recvkeylen;
697 if (mip->keylen > sizeof mip->mastkey)
698 mip->keylen = sizeof mip->mastkey;
699 memcpy(mip->mastkey, bundle->radius.mppe.recvkey, mip->keylen);
700 } else
701 #endif
702 GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0,
703 MPPE_IsServer);
705 GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey);
707 MPPEReduceSessionKey(mip);
709 log_Printf(LogCCP, "MPPE: Input channel initiated\n");
711 if (!mip->stateless) {
713 * We need to initialise our dictionary here as the first packet we
714 * receive is unlikely to have the FLUSHED bit set.
716 log_Printf(LogDEBUG, "MPPEInitInput: Dictionary initialised [%d]\n",
717 mip->cohnum);
718 RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey);
719 } else {
721 * We do the first key change here as the first packet is expected
722 * to have a sequence number of 0 and we'll therefore not expect
723 * to have to change the key at that point.
725 log_Printf(LogDEBUG, "MPPEInitInput: Key changed [%d]\n", mip->cohnum);
726 MPPEKeyChange(mip);
729 return mip;
732 static void *
733 MPPEInitOutput(struct bundle *bundle, struct fsm_opt *o)
735 struct mppe_state *mop;
737 if (!MPPE_MasterKeyValid) {
738 log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n");
739 return NULL;
742 if ((mop = MPPE_InitState(o)) == NULL) {
743 log_Printf(LogWARN, "MPPEOutput: Cannot initialise - unexpected options\n");
744 return NULL;
747 log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits);
749 #ifndef NORADIUS
750 if (*bundle->radius.cfg.file && bundle->radius.mppe.sendkey) {
751 if (mop->keylen > bundle->radius.mppe.sendkeylen)
752 mop->keylen = bundle->radius.mppe.sendkeylen;
753 if (mop->keylen > sizeof mop->mastkey)
754 mop->keylen = sizeof mop->mastkey;
755 memcpy(mop->mastkey, bundle->radius.mppe.sendkey, mop->keylen);
756 } else
757 #endif
758 GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1,
759 MPPE_IsServer);
761 GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey);
763 MPPEReduceSessionKey(mop);
765 log_Printf(LogCCP, "MPPE: Output channel initiated\n");
767 if (!mop->stateless) {
769 * We need to initialise our dictionary now as the first packet we
770 * send won't have the FLUSHED bit set.
772 log_Printf(LogDEBUG, "MPPEInitOutput: Dictionary initialised [%d]\n",
773 mop->cohnum);
774 RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey);
777 return mop;
780 static void
781 MPPETermInput(void *v)
783 free(v);
786 static void
787 MPPETermOutput(void *v)
789 free(v);
792 const struct ccp_algorithm MPPEAlgorithm = {
793 TY_MPPE,
794 CCP_NEG_MPPE,
795 MPPEDispOpts,
796 MPPEUsable,
797 MPPERequired,
799 MPPESetOptsInput,
800 MPPEInitInput,
801 MPPETermInput,
802 MPPEResetInput,
803 MPPEInput,
804 MPPEDictSetup
808 MPPEInitOptsOutput,
809 MPPESetOptsOutput,
810 MPPEInitOutput,
811 MPPETermOutput,
812 MPPEResetOutput,
813 MPPEOutput