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