xref: /freebsd/usr.sbin/ppp/mppe.c (revision 8ab2f5ecc596131f6ca790d6ae35540c06ed7985)
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/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   int		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   case 56:
138     mp->sesskey[0] = 0xd1;
139   case 128:
140     break;
141   }
142 }
143 
144 static void
145 MPPEKeyChange(struct mppe_state *mp)
146 {
147   char InterimKey[MPPE_KEY_LEN];
148   RC4_KEY RC4Key;
149 
150   GetNewKeyFromSHA(mp->mastkey, mp->sesskey, mp->keylen, InterimKey);
151   RC4_set_key(&RC4Key, mp->keylen, InterimKey);
152   RC4(&RC4Key, mp->keylen, InterimKey, mp->sesskey);
153 
154   MPPEReduceSessionKey(mp);
155 }
156 
157 static struct mbuf *
158 MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto,
159            struct mbuf *mp)
160 {
161   struct mppe_state *mop = (struct mppe_state *)v;
162   struct mbuf *mo;
163   u_short nproto, prefix;
164   int dictinit, ilen, len;
165   char *rp;
166 
167   ilen = m_length(mp);
168   dictinit = 0;
169 
170   log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen);
171   if (*proto < 0x21 && *proto > 0xFA) {
172     log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n");
173     ccp->compout += ilen;
174     ccp->uncompout += ilen;
175     return mp;
176   }
177 
178   log_DumpBp(LogDEBUG, "MPPE: Output: Encrypt packet:", mp);
179 
180   /* Get mbuf for prefixes */
181   mo = m_get(4, MB_CCPOUT);
182   mo->m_next = mp;
183 
184   rp = MBUF_CTOP(mo);
185   prefix = MPPE_ENCRYPTED | mop->cohnum;
186 
187   if (mop->stateless ||
188       (mop->cohnum & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) {
189     /* Change our key */
190     log_Printf(LogDEBUG, "MPPEOutput: Key changed [%d]\n", mop->cohnum);
191     MPPEKeyChange(mop);
192     dictinit = 1;
193   }
194 
195   if (mop->stateless || mop->flushnext) {
196     prefix |= MPPE_FLUSHED;
197     dictinit = 1;
198     mop->flushnext = 0;
199   }
200 
201   if (dictinit) {
202     /* Initialise our dictionary */
203     log_Printf(LogDEBUG, "MPPEOutput: Dictionary initialised [%d]\n",
204                mop->cohnum);
205     RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey);
206   }
207 
208   /* Set MPPE packet prefix */
209   ua_htons(&prefix, rp);
210 
211   /* Save encrypted protocol number */
212   nproto = htons(*proto);
213   RC4(&mop->rc4key, 2, (char *)&nproto, rp + 2);
214 
215   /* Encrypt main packet */
216   rp = MBUF_CTOP(mp);
217   RC4(&mop->rc4key, ilen, rp, rp);
218 
219   mop->cohnum++;
220   mop->cohnum &= ~MPPE_HEADER_BITMASK;
221 
222   /* Set the protocol number */
223   *proto = ccp_Proto(ccp);
224   len = m_length(mo);
225   ccp->uncompout += ilen;
226   ccp->compout += len;
227 
228   log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n",
229              *proto, len);
230 
231   return mo;
232 }
233 
234 static void
235 MPPEResetInput(void *v)
236 {
237   log_Printf(LogCCP, "MPPE: Unexpected input channel ack\n");
238 }
239 
240 static struct mbuf *
241 MPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp)
242 {
243   struct mppe_state *mip = (struct mppe_state *)v;
244   u_short prefix;
245   char *rp;
246   int dictinit, flushed, ilen, len, n;
247 
248   ilen = m_length(mp);
249   dictinit = 0;
250   ccp->compin += ilen;
251 
252   log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen);
253   log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp);
254 
255   mp = mbuf_Read(mp, &prefix, 2);
256   prefix = ntohs(prefix);
257   flushed = prefix & MPPE_FLUSHED;
258   prefix &= ~flushed;
259   if ((prefix & MPPE_HEADER_BITMASK) != MPPE_ENCRYPTED) {
260     log_Printf(LogERROR, "MPPE: Input: Invalid packet (flags = 0x%x)\n",
261                (prefix & MPPE_HEADER_BITMASK) | flushed);
262     m_freem(mp);
263     return NULL;
264   }
265 
266   prefix &= ~MPPE_HEADER_BITMASK;
267 
268   if (!flushed && mip->stateless) {
269     log_Printf(LogCCP, "MPPEInput: Packet without MPPE_FLUSHED set"
270                " in stateless mode\n");
271     flushed = MPPE_FLUSHED;
272     /* Should we really continue ? */
273   }
274 
275   if (mip->stateless) {
276     /* Change our key for each missed packet in stateless mode */
277     while (prefix != mip->cohnum) {
278       log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix);
279       MPPEKeyChange(mip);
280       /*
281        * mip->cohnum contains what we received last time in stateless
282        * mode.
283        */
284       mip->cohnum++;
285       mip->cohnum &= ~MPPE_HEADER_BITMASK;
286     }
287     dictinit = 1;
288   } else {
289     if (flushed) {
290       /*
291        * We can always process a flushed packet.
292        * Catch up on any outstanding key changes.
293        */
294       n = (prefix >> MPPE_HEADER_FLAGSHIFT) -
295           (mip->cohnum >> MPPE_HEADER_FLAGSHIFT);
296       if (n < 0)
297         n += MPPE_HEADER_STATEFUL_KEYCHANGES;
298       while (n--) {
299         log_Printf(LogDEBUG, "MPPEInput: Key changed during catchup [%u]\n",
300                    prefix);
301         MPPEKeyChange(mip);
302       }
303       mip->flushrequired = 0;
304       mip->cohnum = prefix;
305       dictinit = 1;
306     }
307 
308     if (mip->flushrequired) {
309       /*
310        * Perhaps we should be lenient if
311        * (prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG
312        * The spec says that we shouldn't be though....
313        */
314       log_Printf(LogDEBUG, "MPPE: Not flushed - discarded\n");
315       fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0,
316                  MB_CCPOUT);
317       m_freem(mp);
318       return NULL;
319     }
320 
321     if (prefix != mip->cohnum) {
322       /*
323        * We're in stateful mode and didn't receive the expected
324        * packet.  Send a reset request, but don't tell the CCP layer
325        * about it as we don't expect to receive a Reset ACK !
326        * Guess what... M$ invented this !
327        */
328       log_Printf(LogCCP, "MPPE: Input: Got seq %u, not %u\n",
329                  prefix, mip->cohnum);
330       fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0,
331                  MB_CCPOUT);
332       mip->flushrequired = 1;
333       m_freem(mp);
334       return NULL;
335     }
336 
337     if ((prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) {
338       log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix);
339       MPPEKeyChange(mip);
340       dictinit = 1;
341     } else if (flushed)
342       dictinit = 1;
343 
344     /*
345      * mip->cohnum contains what we expect to receive next time in stateful
346      * mode.
347      */
348     mip->cohnum++;
349     mip->cohnum &= ~MPPE_HEADER_BITMASK;
350   }
351 
352   if (dictinit) {
353     log_Printf(LogDEBUG, "MPPEInput: Dictionary initialised [%u]\n", prefix);
354     RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey);
355   }
356 
357   mp = mbuf_Read(mp, proto, 2);
358   RC4(&mip->rc4key, 2, (char *)proto, (char *)proto);
359   *proto = ntohs(*proto);
360 
361   rp = MBUF_CTOP(mp);
362   len = m_length(mp);
363   RC4(&mip->rc4key, len, rp, rp);
364 
365   log_Printf(LogDEBUG, "MPPEInput: Decrypted: Proto %02x (%d bytes)\n",
366              *proto, len);
367   log_DumpBp(LogDEBUG, "MPPEInput: Decrypted: Packet:", mp);
368 
369   ccp->uncompin += len;
370 
371   return mp;
372 }
373 
374 static void
375 MPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi)
376 {
377 }
378 
379 static const char *
380 MPPEDispOpts(struct fsm_opt *o)
381 {
382   static char buf[70];
383   u_int32_t val;
384   char ch;
385   int len, n;
386 
387   ua_ntohl(o->data, &val);
388   len = 0;
389   if ((n = snprintf(buf, sizeof buf, "value 0x%08x ", (unsigned)val)) > 0)
390     len += n;
391   if (!(val & MPPE_OPT_BITMASK)) {
392     if ((n = snprintf(buf + len, sizeof buf - len, "(0")) > 0)
393       len += n;
394   } else {
395     ch = '(';
396     if (val & MPPE_OPT_128BIT) {
397       if ((n = snprintf(buf + len, sizeof buf - len, "%c128", ch)) > 0)
398         len += n;
399       ch = '/';
400     }
401     if (val & MPPE_OPT_56BIT) {
402       if ((n = snprintf(buf + len, sizeof buf - len, "%c56", ch)) > 0)
403         len += n;
404       ch = '/';
405     }
406     if (val & MPPE_OPT_40BIT) {
407       if ((n = snprintf(buf + len, sizeof buf - len, "%c40", ch)) > 0)
408         len += n;
409       ch = '/';
410     }
411   }
412 
413   if ((n = snprintf(buf + len, sizeof buf - len, " bits, state%s",
414                     (val & MPPE_OPT_STATELESS) ? "less" : "ful")) > 0)
415     len += n;
416 
417   if (val & MPPE_OPT_COMPRESSED) {
418     if ((n = snprintf(buf + len, sizeof buf - len, ", compressed")) > 0)
419       len += n;
420   }
421 
422   snprintf(buf + len, sizeof buf - len, ")");
423 
424   return buf;
425 }
426 
427 static int
428 MPPEUsable(struct fsm *fp)
429 {
430   int ok;
431 #ifndef NORADIUS
432   struct radius *r = &fp->bundle->radius;
433 
434   /*
435    * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES,
436    * use that instead of our configuration value.
437    */
438   if (*r->cfg.file) {
439     ok = r->mppe.sendkeylen && r->mppe.recvkeylen;
440     if (!ok)
441       log_Printf(LogCCP, "MPPE: Not permitted by RADIUS server\n");
442   } else
443 #endif
444   {
445     struct lcp *lcp = &fp->link->lcp;
446     ok = (lcp->want_auth == PROTO_CHAP && lcp->want_authtype == 0x81) ||
447          (lcp->his_auth == PROTO_CHAP && lcp->his_authtype == 0x81);
448     if (!ok)
449       log_Printf(LogCCP, "MPPE: Not usable without CHAP81\n");
450   }
451 
452   return ok;
453 }
454 
455 static int
456 MPPERequired(struct fsm *fp)
457 {
458 #ifndef NORADIUS
459   /*
460    * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY,
461    * use that instead of our configuration value.
462    */
463   if (*fp->bundle->radius.cfg.file && fp->bundle->radius.mppe.policy)
464     return fp->bundle->radius.mppe.policy == MPPE_POLICY_REQUIRED ? 1 : 0;
465 #endif
466 
467   return fp->link->ccp.cfg.mppe.required;
468 }
469 
470 static u_int32_t
471 MPPE_ConfigVal(struct bundle *bundle, const struct ccp_config *cfg)
472 {
473   u_int32_t val;
474 
475   val = cfg->mppe.state == MPPE_STATELESS ? MPPE_OPT_STATELESS : 0;
476 #ifndef NORADIUS
477   /*
478    * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES,
479    * use that instead of our configuration value.
480    */
481   if (*bundle->radius.cfg.file && bundle->radius.mppe.types) {
482     if (bundle->radius.mppe.types & MPPE_TYPE_40BIT)
483       val |= MPPE_OPT_40BIT;
484     if (bundle->radius.mppe.types & MPPE_TYPE_128BIT)
485       val |= MPPE_OPT_128BIT;
486   } else
487 #endif
488     switch(cfg->mppe.keybits) {
489     case 128:
490       val |= MPPE_OPT_128BIT;
491       break;
492     case 56:
493       val |= MPPE_OPT_56BIT;
494       break;
495     case 40:
496       val |= MPPE_OPT_40BIT;
497       break;
498     case 0:
499       val |= MPPE_OPT_128BIT | MPPE_OPT_56BIT | MPPE_OPT_40BIT;
500       break;
501     }
502 
503   return val;
504 }
505 
506 /*
507  * What options should we use for our first configure request
508  */
509 static void
510 MPPEInitOptsOutput(struct bundle *bundle, struct fsm_opt *o,
511                    const struct ccp_config *cfg)
512 {
513   u_int32_t mval;
514 
515   o->hdr.len = 6;
516 
517   if (!MPPE_MasterKeyValid) {
518     log_Printf(LogCCP, "MPPE: MasterKey is invalid,"
519                " MPPE is available only with CHAP81 authentication\n");
520     ua_htonl(0x0, o->data);
521     return;
522   }
523 
524 
525   mval = MPPE_ConfigVal(bundle, cfg);
526   ua_htonl(&mval, o->data);
527 }
528 
529 /*
530  * Our CCP request was NAK'd with the given options
531  */
532 static int
533 MPPESetOptsOutput(struct bundle *bundle, struct fsm_opt *o,
534                   const struct ccp_config *cfg)
535 {
536   u_int32_t mval, peer;
537 
538   ua_ntohl(o->data, &peer);
539 
540   if (!MPPE_MasterKeyValid)
541     /* Treat their NAK as a REJ */
542     return MODE_NAK;
543 
544   mval = MPPE_ConfigVal(bundle, cfg);
545 
546   /*
547    * If we haven't been configured with a specific number of keybits, allow
548    * whatever the peer asks for.
549    */
550   if (!cfg->mppe.keybits) {
551     mval &= ~MPPE_OPT_BITMASK;
552     mval |= (peer & MPPE_OPT_BITMASK);
553     if (!(mval & MPPE_OPT_BITMASK))
554       mval |= MPPE_OPT_128BIT;
555   }
556 
557   /* Adjust our statelessness */
558   if (cfg->mppe.state == MPPE_ANYSTATE) {
559     mval &= ~MPPE_OPT_STATELESS;
560     mval |= (peer & MPPE_OPT_STATELESS);
561   }
562 
563   ua_htonl(&mval, o->data);
564 
565   return MODE_ACK;
566 }
567 
568 /*
569  * The peer has requested the given options
570  */
571 static int
572 MPPESetOptsInput(struct bundle *bundle, struct fsm_opt *o,
573                  const struct ccp_config *cfg)
574 {
575   u_int32_t mval, peer;
576   int res = MODE_ACK;
577 
578   ua_ntohl(o->data, &peer);
579   if (!MPPE_MasterKeyValid) {
580     if (peer != 0) {
581       peer = 0;
582       ua_htonl(&peer, o->data);
583       return MODE_NAK;
584     } else
585       return MODE_ACK;
586   }
587 
588   mval = MPPE_ConfigVal(bundle, cfg);
589 
590   if (peer & ~MPPE_OPT_MASK)
591     /* He's asking for bits we don't know about */
592     res = MODE_NAK;
593 
594   if (peer & MPPE_OPT_STATELESS) {
595     if (cfg->mppe.state == MPPE_STATEFUL)
596       /* Peer can't have stateless */
597       res = MODE_NAK;
598     else
599       /* Peer wants stateless, that's ok */
600       mval |= MPPE_OPT_STATELESS;
601   } else {
602     if (cfg->mppe.state == MPPE_STATELESS)
603       /* Peer must have stateless */
604       res = MODE_NAK;
605     else
606       /* Peer doesn't want stateless, that's ok */
607       mval &= ~MPPE_OPT_STATELESS;
608   }
609 
610   /* If we've got a configured number of keybits - the peer must use that */
611   if (cfg->mppe.keybits) {
612     ua_htonl(&mval, o->data);
613     return peer == mval ? res : MODE_NAK;
614   }
615 
616   /* If a specific number of bits hasn't been requested, we'll need to NAK */
617   switch (peer & MPPE_OPT_BITMASK) {
618   case MPPE_OPT_128BIT:
619   case MPPE_OPT_56BIT:
620   case MPPE_OPT_40BIT:
621     break;
622   default:
623     res = MODE_NAK;
624   }
625 
626   /* Suggest the best number of bits */
627   mval &= ~MPPE_OPT_BITMASK;
628   if (peer & MPPE_OPT_128BIT)
629     mval |= MPPE_OPT_128BIT;
630   else if (peer & MPPE_OPT_56BIT)
631     mval |= MPPE_OPT_56BIT;
632   else if (peer & MPPE_OPT_40BIT)
633     mval |= MPPE_OPT_40BIT;
634   else
635     mval |= MPPE_OPT_128BIT;
636   ua_htonl(&mval, o->data);
637 
638   return res;
639 }
640 
641 static struct mppe_state *
642 MPPE_InitState(struct fsm_opt *o)
643 {
644   struct mppe_state *mp;
645   u_int32_t val;
646 
647   if ((mp = calloc(1, sizeof *mp)) != NULL) {
648     ua_ntohl(o->data, &val);
649 
650     switch (val & MPPE_OPT_BITMASK) {
651     case MPPE_OPT_128BIT:
652       mp->keylen = 16;
653       mp->keybits = 128;
654       break;
655     case MPPE_OPT_56BIT:
656       mp->keylen = 8;
657       mp->keybits = 56;
658       break;
659     case MPPE_OPT_40BIT:
660       mp->keylen = 8;
661       mp->keybits = 40;
662       break;
663     default:
664       log_Printf(LogWARN, "Unexpected MPPE options 0x%08x\n", val);
665       free(mp);
666       return NULL;
667     }
668 
669     mp->stateless = !!(val & MPPE_OPT_STATELESS);
670   }
671 
672   return mp;
673 }
674 
675 static void *
676 MPPEInitInput(struct bundle *bundle, struct fsm_opt *o)
677 {
678   struct mppe_state *mip;
679 
680   if (!MPPE_MasterKeyValid) {
681     log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n");
682     return NULL;
683   }
684 
685   if ((mip = MPPE_InitState(o)) == NULL) {
686     log_Printf(LogWARN, "MPPEInput: Cannot initialise - unexpected options\n");
687     return NULL;
688   }
689 
690   log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits);
691 
692 #ifndef NORADIUS
693   if (*bundle->radius.cfg.file && bundle->radius.mppe.recvkey) {
694     if (mip->keylen > bundle->radius.mppe.recvkeylen)
695       mip->keylen = bundle->radius.mppe.recvkeylen;
696     if (mip->keylen > sizeof mip->mastkey)
697       mip->keylen = sizeof mip->mastkey;
698     memcpy(mip->mastkey, bundle->radius.mppe.recvkey, mip->keylen);
699   } else
700 #endif
701     GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0,
702                          MPPE_IsServer);
703 
704   GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey);
705 
706   MPPEReduceSessionKey(mip);
707 
708   log_Printf(LogCCP, "MPPE: Input channel initiated\n");
709 
710   if (!mip->stateless) {
711     /*
712      * We need to initialise our dictionary here as the first packet we
713      * receive is unlikely to have the FLUSHED bit set.
714      */
715     log_Printf(LogDEBUG, "MPPEInitInput: Dictionary initialised [%d]\n",
716                mip->cohnum);
717     RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey);
718   } else {
719     /*
720      * We do the first key change here as the first packet is expected
721      * to have a sequence number of 0 and we'll therefore not expect
722      * to have to change the key at that point.
723      */
724     log_Printf(LogDEBUG, "MPPEInitInput: Key changed [%d]\n", mip->cohnum);
725     MPPEKeyChange(mip);
726   }
727 
728   return mip;
729 }
730 
731 static void *
732 MPPEInitOutput(struct bundle *bundle, struct fsm_opt *o)
733 {
734   struct mppe_state *mop;
735 
736   if (!MPPE_MasterKeyValid) {
737     log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n");
738     return NULL;
739   }
740 
741   if ((mop = MPPE_InitState(o)) == NULL) {
742     log_Printf(LogWARN, "MPPEOutput: Cannot initialise - unexpected options\n");
743     return NULL;
744   }
745 
746   log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits);
747 
748 #ifndef NORADIUS
749   if (*bundle->radius.cfg.file && bundle->radius.mppe.sendkey) {
750     if (mop->keylen > bundle->radius.mppe.sendkeylen)
751       mop->keylen = bundle->radius.mppe.sendkeylen;
752     if (mop->keylen > sizeof mop->mastkey)
753       mop->keylen = sizeof mop->mastkey;
754     memcpy(mop->mastkey, bundle->radius.mppe.sendkey, mop->keylen);
755   } else
756 #endif
757     GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1,
758                          MPPE_IsServer);
759 
760   GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey);
761 
762   MPPEReduceSessionKey(mop);
763 
764   log_Printf(LogCCP, "MPPE: Output channel initiated\n");
765 
766   if (!mop->stateless) {
767     /*
768      * We need to initialise our dictionary now as the first packet we
769      * send won't have the FLUSHED bit set.
770      */
771     log_Printf(LogDEBUG, "MPPEInitOutput: Dictionary initialised [%d]\n",
772                mop->cohnum);
773     RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey);
774   }
775 
776   return mop;
777 }
778 
779 static void
780 MPPETermInput(void *v)
781 {
782   free(v);
783 }
784 
785 static void
786 MPPETermOutput(void *v)
787 {
788   free(v);
789 }
790 
791 const struct ccp_algorithm MPPEAlgorithm = {
792   TY_MPPE,
793   CCP_NEG_MPPE,
794   MPPEDispOpts,
795   MPPEUsable,
796   MPPERequired,
797   {
798     MPPESetOptsInput,
799     MPPEInitInput,
800     MPPETermInput,
801     MPPEResetInput,
802     MPPEInput,
803     MPPEDictSetup
804   },
805   {
806     2,
807     MPPEInitOptsOutput,
808     MPPESetOptsOutput,
809     MPPEInitOutput,
810     MPPETermOutput,
811     MPPEResetOutput,
812     MPPEOutput
813   },
814 };
815