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
96struct 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
108int MPPE_MasterKeyValid = 0;
109int MPPE_IsServer = 0;
110char MPPE_MasterKey[MPPE_KEY_LEN];
111
112/*
113 * The peer has missed a packet.  Mark the next output frame to be FLUSHED
114 */
115static int
116MPPEResetOutput(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
130static void
131MPPEReduceSessionKey(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
144static void
145MPPEKeyChange(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
157static struct mbuf *
158MPPEOutput(void *v, struct ccp *ccp, struct link *l __unused, int pri __unused,
159	   u_short *proto, 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
234static void
235MPPEResetInput(void *v __unused)
236{
237  log_Printf(LogCCP, "MPPE: Unexpected input channel ack\n");
238}
239
240static struct mbuf *
241MPPEInput(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
374static void
375MPPEDictSetup(void *v __unused, struct ccp *ccp __unused,
376	      u_short proto __unused, struct mbuf *mp __unused)
377{
378  /* Nothing to see here */
379}
380
381static const char *
382MPPEDispOpts(struct fsm_opt *o)
383{
384  static char buf[70];
385  u_int32_t val;
386  char ch;
387  int len, n;
388
389  ua_ntohl(o->data, &val);
390  len = 0;
391  if ((n = snprintf(buf, sizeof buf, "value 0x%08x ", (unsigned)val)) > 0)
392    len += n;
393  if (!(val & MPPE_OPT_BITMASK)) {
394    if ((n = snprintf(buf + len, sizeof buf - len, "(0")) > 0)
395      len += n;
396  } else {
397    ch = '(';
398    if (val & MPPE_OPT_128BIT) {
399      if ((n = snprintf(buf + len, sizeof buf - len, "%c128", ch)) > 0)
400        len += n;
401      ch = '/';
402    }
403    if (val & MPPE_OPT_56BIT) {
404      if ((n = snprintf(buf + len, sizeof buf - len, "%c56", ch)) > 0)
405        len += n;
406      ch = '/';
407    }
408    if (val & MPPE_OPT_40BIT) {
409      if ((n = snprintf(buf + len, sizeof buf - len, "%c40", ch)) > 0)
410        len += n;
411      ch = '/';
412    }
413  }
414
415  if ((n = snprintf(buf + len, sizeof buf - len, " bits, state%s",
416                    (val & MPPE_OPT_STATELESS) ? "less" : "ful")) > 0)
417    len += n;
418
419  if (val & MPPE_OPT_COMPRESSED) {
420    if ((n = snprintf(buf + len, sizeof buf - len, ", compressed")) > 0)
421      len += n;
422  }
423
424  snprintf(buf + len, sizeof buf - len, ")");
425
426  return buf;
427}
428
429static int
430MPPEUsable(struct fsm *fp)
431{
432  int ok;
433#ifndef NORADIUS
434  struct radius *r = &fp->bundle->radius;
435
436  /*
437   * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES,
438   * use that instead of our configuration value.
439   */
440  if (*r->cfg.file) {
441    ok = r->mppe.sendkeylen && r->mppe.recvkeylen;
442    if (!ok)
443      log_Printf(LogCCP, "MPPE: Not permitted by RADIUS server\n");
444  } else
445#endif
446  {
447    struct lcp *lcp = &fp->link->lcp;
448    ok = (lcp->want_auth == PROTO_CHAP && lcp->want_authtype == 0x81) ||
449         (lcp->his_auth == PROTO_CHAP && lcp->his_authtype == 0x81);
450    if (!ok)
451      log_Printf(LogCCP, "MPPE: Not usable without CHAP81\n");
452  }
453
454  return ok;
455}
456
457static int
458MPPERequired(struct fsm *fp)
459{
460#ifndef NORADIUS
461  /*
462   * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY,
463   * use that instead of our configuration value.
464   */
465  if (*fp->bundle->radius.cfg.file && fp->bundle->radius.mppe.policy)
466    return fp->bundle->radius.mppe.policy == MPPE_POLICY_REQUIRED ? 1 : 0;
467#endif
468
469  return fp->link->ccp.cfg.mppe.required;
470}
471
472static u_int32_t
473MPPE_ConfigVal(struct bundle *bundle __unused, const struct ccp_config *cfg)
474{
475  u_int32_t val;
476
477  val = cfg->mppe.state == MPPE_STATELESS ? MPPE_OPT_STATELESS : 0;
478#ifndef NORADIUS
479  /*
480   * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES,
481   * use that instead of our configuration value.
482   */
483  if (*bundle->radius.cfg.file && bundle->radius.mppe.types) {
484    if (bundle->radius.mppe.types & MPPE_TYPE_40BIT)
485      val |= MPPE_OPT_40BIT;
486    if (bundle->radius.mppe.types & MPPE_TYPE_128BIT)
487      val |= MPPE_OPT_128BIT;
488  } else
489#endif
490    switch(cfg->mppe.keybits) {
491    case 128:
492      val |= MPPE_OPT_128BIT;
493      break;
494    case 56:
495      val |= MPPE_OPT_56BIT;
496      break;
497    case 40:
498      val |= MPPE_OPT_40BIT;
499      break;
500    case 0:
501      val |= MPPE_OPT_128BIT | MPPE_OPT_56BIT | MPPE_OPT_40BIT;
502      break;
503    }
504
505  return val;
506}
507
508/*
509 * What options should we use for our first configure request
510 */
511static void
512MPPEInitOptsOutput(struct bundle *bundle, struct fsm_opt *o,
513                   const struct ccp_config *cfg)
514{
515  u_int32_t mval;
516
517  o->hdr.len = 6;
518
519  if (!MPPE_MasterKeyValid) {
520    log_Printf(LogCCP, "MPPE: MasterKey is invalid,"
521               " MPPE is available only with CHAP81 authentication\n");
522    mval = 0;
523    ua_htonl(&mval, o->data);
524    return;
525  }
526
527
528  mval = MPPE_ConfigVal(bundle, cfg);
529  ua_htonl(&mval, o->data);
530}
531
532/*
533 * Our CCP request was NAK'd with the given options
534 */
535static int
536MPPESetOptsOutput(struct bundle *bundle, struct fsm_opt *o,
537                  const struct ccp_config *cfg)
538{
539  u_int32_t mval, peer;
540
541  ua_ntohl(o->data, &peer);
542
543  if (!MPPE_MasterKeyValid)
544    /* Treat their NAK as a REJ */
545    return MODE_NAK;
546
547  mval = MPPE_ConfigVal(bundle, cfg);
548
549  /*
550   * If we haven't been configured with a specific number of keybits, allow
551   * whatever the peer asks for.
552   */
553  if (!cfg->mppe.keybits) {
554    mval &= ~MPPE_OPT_BITMASK;
555    mval |= (peer & MPPE_OPT_BITMASK);
556    if (!(mval & MPPE_OPT_BITMASK))
557      mval |= MPPE_OPT_128BIT;
558  }
559
560  /* Adjust our statelessness */
561  if (cfg->mppe.state == MPPE_ANYSTATE) {
562    mval &= ~MPPE_OPT_STATELESS;
563    mval |= (peer & MPPE_OPT_STATELESS);
564  }
565
566  ua_htonl(&mval, o->data);
567
568  return MODE_ACK;
569}
570
571/*
572 * The peer has requested the given options
573 */
574static int
575MPPESetOptsInput(struct bundle *bundle, struct fsm_opt *o,
576                 const struct ccp_config *cfg)
577{
578  u_int32_t mval, peer;
579  int res = MODE_ACK;
580
581  ua_ntohl(o->data, &peer);
582  if (!MPPE_MasterKeyValid) {
583    if (peer != 0) {
584      peer = 0;
585      ua_htonl(&peer, o->data);
586      return MODE_NAK;
587    } else
588      return MODE_ACK;
589  }
590
591  mval = MPPE_ConfigVal(bundle, cfg);
592
593  if (peer & ~MPPE_OPT_MASK)
594    /* He's asking for bits we don't know about */
595    res = MODE_NAK;
596
597  if (peer & MPPE_OPT_STATELESS) {
598    if (cfg->mppe.state == MPPE_STATEFUL)
599      /* Peer can't have stateless */
600      res = MODE_NAK;
601    else
602      /* Peer wants stateless, that's ok */
603      mval |= MPPE_OPT_STATELESS;
604  } else {
605    if (cfg->mppe.state == MPPE_STATELESS)
606      /* Peer must have stateless */
607      res = MODE_NAK;
608    else
609      /* Peer doesn't want stateless, that's ok */
610      mval &= ~MPPE_OPT_STATELESS;
611  }
612
613  /* If we've got a configured number of keybits - the peer must use that */
614  if (cfg->mppe.keybits) {
615    ua_htonl(&mval, o->data);
616    return peer == mval ? res : MODE_NAK;
617  }
618
619  /* If a specific number of bits hasn't been requested, we'll need to NAK */
620  switch (peer & MPPE_OPT_BITMASK) {
621  case MPPE_OPT_128BIT:
622  case MPPE_OPT_56BIT:
623  case MPPE_OPT_40BIT:
624    break;
625  default:
626    res = MODE_NAK;
627  }
628
629  /* Suggest the best number of bits */
630  mval &= ~MPPE_OPT_BITMASK;
631  if (peer & MPPE_OPT_128BIT)
632    mval |= MPPE_OPT_128BIT;
633  else if (peer & MPPE_OPT_56BIT)
634    mval |= MPPE_OPT_56BIT;
635  else if (peer & MPPE_OPT_40BIT)
636    mval |= MPPE_OPT_40BIT;
637  else
638    mval |= MPPE_OPT_128BIT;
639  ua_htonl(&mval, o->data);
640
641  return res;
642}
643
644static struct mppe_state *
645MPPE_InitState(struct fsm_opt *o)
646{
647  struct mppe_state *mp;
648  u_int32_t val;
649
650  if ((mp = calloc(1, sizeof *mp)) != NULL) {
651    ua_ntohl(o->data, &val);
652
653    switch (val & MPPE_OPT_BITMASK) {
654    case MPPE_OPT_128BIT:
655      mp->keylen = 16;
656      mp->keybits = 128;
657      break;
658    case MPPE_OPT_56BIT:
659      mp->keylen = 8;
660      mp->keybits = 56;
661      break;
662    case MPPE_OPT_40BIT:
663      mp->keylen = 8;
664      mp->keybits = 40;
665      break;
666    default:
667      log_Printf(LogWARN, "Unexpected MPPE options 0x%08x\n", val);
668      free(mp);
669      return NULL;
670    }
671
672    mp->stateless = !!(val & MPPE_OPT_STATELESS);
673  }
674
675  return mp;
676}
677
678static void *
679MPPEInitInput(struct bundle *bundle __unused, struct fsm_opt *o)
680{
681  struct mppe_state *mip;
682
683  if (!MPPE_MasterKeyValid) {
684    log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n");
685    return NULL;
686  }
687
688  if ((mip = MPPE_InitState(o)) == NULL) {
689    log_Printf(LogWARN, "MPPEInput: Cannot initialise - unexpected options\n");
690    return NULL;
691  }
692
693  log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits);
694
695#ifndef NORADIUS
696  if (*bundle->radius.cfg.file && bundle->radius.mppe.recvkey) {
697    if (mip->keylen > bundle->radius.mppe.recvkeylen)
698      mip->keylen = bundle->radius.mppe.recvkeylen;
699    if (mip->keylen > sizeof mip->mastkey)
700      mip->keylen = sizeof mip->mastkey;
701    memcpy(mip->mastkey, bundle->radius.mppe.recvkey, mip->keylen);
702  } else
703#endif
704    GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0,
705                         MPPE_IsServer);
706
707  GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey);
708
709  MPPEReduceSessionKey(mip);
710
711  log_Printf(LogCCP, "MPPE: Input channel initiated\n");
712
713  if (!mip->stateless) {
714    /*
715     * We need to initialise our dictionary here as the first packet we
716     * receive is unlikely to have the FLUSHED bit set.
717     */
718    log_Printf(LogDEBUG, "MPPEInitInput: Dictionary initialised [%d]\n",
719               mip->cohnum);
720    RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey);
721  } else {
722    /*
723     * We do the first key change here as the first packet is expected
724     * to have a sequence number of 0 and we'll therefore not expect
725     * to have to change the key at that point.
726     */
727    log_Printf(LogDEBUG, "MPPEInitInput: Key changed [%d]\n", mip->cohnum);
728    MPPEKeyChange(mip);
729  }
730
731  return mip;
732}
733
734static void *
735MPPEInitOutput(struct bundle *bundle __unused, struct fsm_opt *o)
736{
737  struct mppe_state *mop;
738
739  if (!MPPE_MasterKeyValid) {
740    log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n");
741    return NULL;
742  }
743
744  if ((mop = MPPE_InitState(o)) == NULL) {
745    log_Printf(LogWARN, "MPPEOutput: Cannot initialise - unexpected options\n");
746    return NULL;
747  }
748
749  log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits);
750
751#ifndef NORADIUS
752  if (*bundle->radius.cfg.file && bundle->radius.mppe.sendkey) {
753    if (mop->keylen > bundle->radius.mppe.sendkeylen)
754      mop->keylen = bundle->radius.mppe.sendkeylen;
755    if (mop->keylen > sizeof mop->mastkey)
756      mop->keylen = sizeof mop->mastkey;
757    memcpy(mop->mastkey, bundle->radius.mppe.sendkey, mop->keylen);
758  } else
759#endif
760    GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1,
761                         MPPE_IsServer);
762
763  GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey);
764
765  MPPEReduceSessionKey(mop);
766
767  log_Printf(LogCCP, "MPPE: Output channel initiated\n");
768
769  if (!mop->stateless) {
770    /*
771     * We need to initialise our dictionary now as the first packet we
772     * send won't have the FLUSHED bit set.
773     */
774    log_Printf(LogDEBUG, "MPPEInitOutput: Dictionary initialised [%d]\n",
775               mop->cohnum);
776    RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey);
777  }
778
779  return mop;
780}
781
782static void
783MPPETermInput(void *v)
784{
785  free(v);
786}
787
788static void
789MPPETermOutput(void *v)
790{
791  free(v);
792}
793
794const struct ccp_algorithm MPPEAlgorithm = {
795  TY_MPPE,
796  CCP_NEG_MPPE,
797  MPPEDispOpts,
798  MPPEUsable,
799  MPPERequired,
800  {
801    MPPESetOptsInput,
802    MPPEInitInput,
803    MPPETermInput,
804    MPPEResetInput,
805    MPPEInput,
806    MPPEDictSetup
807  },
808  {
809    2,
810    MPPEInitOptsOutput,
811    MPPESetOptsOutput,
812    MPPEInitOutput,
813    MPPETermOutput,
814    MPPEResetOutput,
815    MPPEOutput
816  },
817};
818