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