mppe.c revision 330449
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: stable/11/usr.sbin/ppp/mppe.c 330449 2018-03-05 07:26:05Z eadler $
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
98struct 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
110int MPPE_MasterKeyValid = 0;
111int MPPE_IsServer = 0;
112char MPPE_MasterKey[MPPE_KEY_LEN];
113
114/*
115 * The peer has missed a packet.  Mark the next output frame to be FLUSHED
116 */
117static int
118MPPEResetOutput(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
132static void
133MPPEReduceSessionKey(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
146static void
147MPPEKeyChange(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
159static struct mbuf *
160MPPEOutput(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
236static void
237MPPEResetInput(void *v __unused)
238{
239  log_Printf(LogCCP, "MPPE: Unexpected input channel ack\n");
240}
241
242static struct mbuf *
243MPPEInput(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
376static void
377MPPEDictSetup(void *v __unused, struct ccp *ccp __unused,
378	      u_short proto __unused, struct mbuf *mp __unused)
379{
380  /* Nothing to see here */
381}
382
383static const char *
384MPPEDispOpts(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
431static int
432MPPEUsable(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
459static int
460MPPERequired(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
474static u_int32_t
475MPPE_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 */
513static void
514MPPEInitOptsOutput(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 */
537static int
538MPPESetOptsOutput(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 */
576static int
577MPPESetOptsInput(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
646static struct mppe_state *
647MPPE_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
680static void *
681MPPEInitInput(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
736static void *
737MPPEInitOutput(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
784static void
785MPPETermInput(void *v)
786{
787  free(v);
788}
789
790static void
791MPPETermOutput(void *v)
792{
793  free(v);
794}
795
796const 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