167910Sbrian/*-
267910Sbrian * Copyright (c) 2000 Semen Ustimenko <semenu@FreeBSD.org>
367910Sbrian * All rights reserved.
467910Sbrian *
567910Sbrian * Redistribution and use in source and binary forms, with or without
667910Sbrian * modification, are permitted provided that the following conditions
767910Sbrian * are met:
867910Sbrian * 1. Redistributions of source code must retain the above copyright
967910Sbrian *    notice, this list of conditions and the following disclaimer.
1067910Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1167910Sbrian *    notice, this list of conditions and the following disclaimer in the
1267910Sbrian *    documentation and/or other materials provided with the distribution.
1367910Sbrian *
1467910Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1567910Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1667910Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1767910Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1867910Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1967910Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2067910Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2167910Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2267910Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2367910Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2467910Sbrian * SUCH DAMAGE.
2567910Sbrian *
2667910Sbrian * $FreeBSD$
2767910Sbrian */
2867910Sbrian
2998132Sbrian#include <sys/param.h>
3067910Sbrian
3198132Sbrian#include <sys/socket.h>
3298132Sbrian#include <netinet/in_systm.h>
3396402Sbrian#include <netinet/in.h>
3498132Sbrian#include <netinet/ip.h>
3598132Sbrian#include <sys/un.h>
3693462Sbrian
3767910Sbrian#include <stdio.h>
3867910Sbrian#include <stdlib.h>
3996768Sbrian#include <string.h>
4067910Sbrian#include <termios.h>
4167910Sbrian#include <openssl/rc4.h>
4267910Sbrian
4367910Sbrian#include "defs.h"
4467910Sbrian#include "mbuf.h"
4567910Sbrian#include "log.h"
4667910Sbrian#include "timer.h"
4767910Sbrian#include "fsm.h"
4867910Sbrian#include "lqr.h"
4967910Sbrian#include "hdlc.h"
5067910Sbrian#include "lcp.h"
5167910Sbrian#include "ccp.h"
5272025Sbrian#include "throughput.h"
5372025Sbrian#include "layer.h"
5472025Sbrian#include "link.h"
5567910Sbrian#include "chap_ms.h"
5672025Sbrian#include "proto.h"
5767910Sbrian#include "mppe.h"
5883403Sbrian#include "ua.h"
5998132Sbrian#include "descriptor.h"
6098132Sbrian#ifndef NORADIUS
6198132Sbrian#include "radius.h"
6298132Sbrian#endif
6398132Sbrian#include "ncpaddr.h"
6498132Sbrian#include "iplist.h"
6598132Sbrian#include "slcompress.h"
6698132Sbrian#include "ipcp.h"
6798132Sbrian#include "ipv6cp.h"
6898132Sbrian#include "filter.h"
6998132Sbrian#include "mp.h"
7098132Sbrian#include "ncp.h"
7198132Sbrian#include "bundle.h"
7267910Sbrian
7367910Sbrian/*
7467910Sbrian * Documentation:
7567910Sbrian *
7667910Sbrian * draft-ietf-pppext-mppe-04.txt
7767910Sbrian * draft-ietf-pppext-mppe-keys-02.txt
7867910Sbrian */
7967910Sbrian
8078411Sbrian#define	MPPE_OPT_STATELESS	0x1000000
8178411Sbrian#define	MPPE_OPT_COMPRESSED	0x01
8278411Sbrian#define	MPPE_OPT_40BIT		0x20
8378411Sbrian#define	MPPE_OPT_56BIT		0x80
8478411Sbrian#define	MPPE_OPT_128BIT		0x40
8578411Sbrian#define	MPPE_OPT_BITMASK	0xe0
8678411Sbrian#define	MPPE_OPT_MASK		(MPPE_OPT_STATELESS | MPPE_OPT_BITMASK)
8778411Sbrian
8879376Sbrian#define	MPPE_FLUSHED			0x8000
8979376Sbrian#define	MPPE_ENCRYPTED			0x1000
9079376Sbrian#define	MPPE_HEADER_BITMASK		0xf000
9179376Sbrian#define	MPPE_HEADER_FLAG		0x00ff
9279376Sbrian#define	MPPE_HEADER_FLAGMASK		0x00ff
9379376Sbrian#define	MPPE_HEADER_FLAGSHIFT		8
9479376Sbrian#define	MPPE_HEADER_STATEFUL_KEYCHANGES	16
9578411Sbrian
9667910Sbrianstruct mppe_state {
9778411Sbrian  unsigned	stateless : 1;
9878411Sbrian  unsigned	flushnext : 1;
9978411Sbrian  unsigned	flushrequired : 1;
10078411Sbrian  int		cohnum;
101134789Sbrian  unsigned	keylen;			/* 8 or 16 bytes */
10278411Sbrian  int 		keybits;		/* 40, 56 or 128 bits */
10378411Sbrian  char		sesskey[MPPE_KEY_LEN];
10478411Sbrian  char		mastkey[MPPE_KEY_LEN];
10578411Sbrian  RC4_KEY	rc4key;
10667910Sbrian};
10767910Sbrian
10867910Sbrianint MPPE_MasterKeyValid = 0;
10968461Sbrianint MPPE_IsServer = 0;
11067910Sbrianchar MPPE_MasterKey[MPPE_KEY_LEN];
11167910Sbrian
11278411Sbrian/*
11378411Sbrian * The peer has missed a packet.  Mark the next output frame to be FLUSHED
11478411Sbrian */
11578411Sbrianstatic int
11667910SbrianMPPEResetOutput(void *v)
11767910Sbrian{
11878411Sbrian  struct mppe_state *mop = (struct mppe_state *)v;
11978411Sbrian
12078411Sbrian  if (mop->stateless)
12178411Sbrian    log_Printf(LogCCP, "MPPE: Unexpected output channel reset\n");
12278411Sbrian  else {
12378411Sbrian    log_Printf(LogCCP, "MPPE: Output channel reset\n");
12478411Sbrian    mop->flushnext = 1;
12578411Sbrian  }
12678411Sbrian
12778411Sbrian  return 0;		/* Ask FSM not to ACK */
12867910Sbrian}
12967910Sbrian
13067912Sbrianstatic void
13167912SbrianMPPEReduceSessionKey(struct mppe_state *mp)
13267912Sbrian{
13367910Sbrian  switch(mp->keybits) {
13467910Sbrian  case 40:
13567910Sbrian    mp->sesskey[2] = 0x9e;
13667910Sbrian    mp->sesskey[1] = 0x26;
13767910Sbrian  case 56:
13867910Sbrian    mp->sesskey[0] = 0xd1;
13967910Sbrian  case 128:
14096544Sbrian    break;
14167910Sbrian  }
14267910Sbrian}
14367910Sbrian
14467912Sbrianstatic void
14567912SbrianMPPEKeyChange(struct mppe_state *mp)
14667912Sbrian{
14767910Sbrian  char InterimKey[MPPE_KEY_LEN];
14867910Sbrian  RC4_KEY RC4Key;
14967910Sbrian
15067910Sbrian  GetNewKeyFromSHA(mp->mastkey, mp->sesskey, mp->keylen, InterimKey);
15167910Sbrian  RC4_set_key(&RC4Key, mp->keylen, InterimKey);
15267910Sbrian  RC4(&RC4Key, mp->keylen, InterimKey, mp->sesskey);
15367910Sbrian
15467910Sbrian  MPPEReduceSessionKey(mp);
15567910Sbrian}
15667910Sbrian
15767910Sbrianstatic struct mbuf *
158134789SbrianMPPEOutput(void *v, struct ccp *ccp, struct link *l __unused, int pri __unused,
159134789Sbrian	   u_short *proto, struct mbuf *mp)
16067910Sbrian{
16167910Sbrian  struct mppe_state *mop = (struct mppe_state *)v;
16267910Sbrian  struct mbuf *mo;
16378411Sbrian  u_short nproto, prefix;
16478411Sbrian  int dictinit, ilen, len;
16567910Sbrian  char *rp;
16667910Sbrian
16767910Sbrian  ilen = m_length(mp);
16878411Sbrian  dictinit = 0;
16967910Sbrian
17067910Sbrian  log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen);
17167910Sbrian  if (*proto < 0x21 && *proto > 0xFA) {
17267910Sbrian    log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n");
17378411Sbrian    ccp->compout += ilen;
17478411Sbrian    ccp->uncompout += ilen;
17567910Sbrian    return mp;
17667910Sbrian  }
17767910Sbrian
17867910Sbrian  log_DumpBp(LogDEBUG, "MPPE: Output: Encrypt packet:", mp);
17967910Sbrian
18067910Sbrian  /* Get mbuf for prefixes */
18167910Sbrian  mo = m_get(4, MB_CCPOUT);
18267910Sbrian  mo->m_next = mp;
18367910Sbrian
18478411Sbrian  rp = MBUF_CTOP(mo);
18578411Sbrian  prefix = MPPE_ENCRYPTED | mop->cohnum;
18667910Sbrian
18778411Sbrian  if (mop->stateless ||
18878411Sbrian      (mop->cohnum & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) {
18978411Sbrian    /* Change our key */
19078411Sbrian    log_Printf(LogDEBUG, "MPPEOutput: Key changed [%d]\n", mop->cohnum);
19178411Sbrian    MPPEKeyChange(mop);
19278411Sbrian    dictinit = 1;
19378411Sbrian  }
19478411Sbrian
19578411Sbrian  if (mop->stateless || mop->flushnext) {
19678411Sbrian    prefix |= MPPE_FLUSHED;
19778411Sbrian    dictinit = 1;
19878411Sbrian    mop->flushnext = 0;
19978411Sbrian  }
20078411Sbrian
20178411Sbrian  if (dictinit) {
20278411Sbrian    /* Initialise our dictionary */
20378411Sbrian    log_Printf(LogDEBUG, "MPPEOutput: Dictionary initialised [%d]\n",
20478411Sbrian               mop->cohnum);
20578411Sbrian    RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey);
20678411Sbrian  }
20778411Sbrian
20867910Sbrian  /* Set MPPE packet prefix */
20983403Sbrian  ua_htons(&prefix, rp);
21067910Sbrian
21167910Sbrian  /* Save encrypted protocol number */
21267910Sbrian  nproto = htons(*proto);
21367910Sbrian  RC4(&mop->rc4key, 2, (char *)&nproto, rp + 2);
21467910Sbrian
21567910Sbrian  /* Encrypt main packet */
21667910Sbrian  rp = MBUF_CTOP(mp);
21767910Sbrian  RC4(&mop->rc4key, ilen, rp, rp);
21867910Sbrian
21978411Sbrian  mop->cohnum++;
22078411Sbrian  mop->cohnum &= ~MPPE_HEADER_BITMASK;
22167910Sbrian
22278411Sbrian  /* Set the protocol number */
22367910Sbrian  *proto = ccp_Proto(ccp);
22478411Sbrian  len = m_length(mo);
22578411Sbrian  ccp->uncompout += ilen;
22678411Sbrian  ccp->compout += len;
22767910Sbrian
22867912Sbrian  log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n",
22978411Sbrian             *proto, len);
23067910Sbrian
23167910Sbrian  return mo;
23267910Sbrian}
23367910Sbrian
23467910Sbrianstatic void
235134789SbrianMPPEResetInput(void *v __unused)
23667910Sbrian{
23778411Sbrian  log_Printf(LogCCP, "MPPE: Unexpected input channel ack\n");
23867910Sbrian}
23967910Sbrian
24067910Sbrianstatic struct mbuf *
24167910SbrianMPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp)
24267910Sbrian{
24367910Sbrian  struct mppe_state *mip = (struct mppe_state *)v;
24467910Sbrian  u_short prefix;
24567910Sbrian  char *rp;
24678411Sbrian  int dictinit, flushed, ilen, len, n;
24767910Sbrian
24867910Sbrian  ilen = m_length(mp);
24978411Sbrian  dictinit = 0;
25078411Sbrian  ccp->compin += ilen;
25167910Sbrian
25267910Sbrian  log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen);
25367910Sbrian  log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp);
25467910Sbrian
25567910Sbrian  mp = mbuf_Read(mp, &prefix, 2);
25667910Sbrian  prefix = ntohs(prefix);
25778411Sbrian  flushed = prefix & MPPE_FLUSHED;
25878411Sbrian  prefix &= ~flushed;
25978411Sbrian  if ((prefix & MPPE_HEADER_BITMASK) != MPPE_ENCRYPTED) {
26078411Sbrian    log_Printf(LogERROR, "MPPE: Input: Invalid packet (flags = 0x%x)\n",
26178411Sbrian               (prefix & MPPE_HEADER_BITMASK) | flushed);
26267910Sbrian    m_freem(mp);
26367910Sbrian    return NULL;
26467910Sbrian  }
26567910Sbrian
26678411Sbrian  prefix &= ~MPPE_HEADER_BITMASK;
26778411Sbrian
26878411Sbrian  if (!flushed && mip->stateless) {
26978411Sbrian    log_Printf(LogCCP, "MPPEInput: Packet without MPPE_FLUSHED set"
27078411Sbrian               " in stateless mode\n");
27178411Sbrian    flushed = MPPE_FLUSHED;
27278411Sbrian    /* Should we really continue ? */
27367910Sbrian  }
27467910Sbrian
27578411Sbrian  if (mip->stateless) {
27678411Sbrian    /* Change our key for each missed packet in stateless mode */
27778411Sbrian    while (prefix != mip->cohnum) {
27878411Sbrian      log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix);
27978411Sbrian      MPPEKeyChange(mip);
28078411Sbrian      /*
28178411Sbrian       * mip->cohnum contains what we received last time in stateless
28278411Sbrian       * mode.
28378411Sbrian       */
28478411Sbrian      mip->cohnum++;
28578411Sbrian      mip->cohnum &= ~MPPE_HEADER_BITMASK;
28678411Sbrian    }
28778411Sbrian    dictinit = 1;
28878411Sbrian  } else {
28978411Sbrian    if (flushed) {
29078411Sbrian      /*
29178411Sbrian       * We can always process a flushed packet.
29278411Sbrian       * Catch up on any outstanding key changes.
29378411Sbrian       */
29478411Sbrian      n = (prefix >> MPPE_HEADER_FLAGSHIFT) -
29578411Sbrian          (mip->cohnum >> MPPE_HEADER_FLAGSHIFT);
29679376Sbrian      if (n < 0)
29779376Sbrian        n += MPPE_HEADER_STATEFUL_KEYCHANGES;
29878411Sbrian      while (n--) {
29978411Sbrian        log_Printf(LogDEBUG, "MPPEInput: Key changed during catchup [%u]\n",
30078411Sbrian                   prefix);
30178411Sbrian        MPPEKeyChange(mip);
30278411Sbrian      }
30378411Sbrian      mip->flushrequired = 0;
30478411Sbrian      mip->cohnum = prefix;
30578411Sbrian      dictinit = 1;
30678411Sbrian    }
30767910Sbrian
30878411Sbrian    if (mip->flushrequired) {
30978411Sbrian      /*
31078411Sbrian       * Perhaps we should be lenient if
31178411Sbrian       * (prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG
31278411Sbrian       * The spec says that we shouldn't be though....
31378411Sbrian       */
31478411Sbrian      log_Printf(LogDEBUG, "MPPE: Not flushed - discarded\n");
31582411Sbrian      fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0,
31682411Sbrian                 MB_CCPOUT);
31778411Sbrian      m_freem(mp);
31878411Sbrian      return NULL;
31978411Sbrian    }
32078411Sbrian
32178411Sbrian    if (prefix != mip->cohnum) {
32278411Sbrian      /*
32378411Sbrian       * We're in stateful mode and didn't receive the expected
32478411Sbrian       * packet.  Send a reset request, but don't tell the CCP layer
32578411Sbrian       * about it as we don't expect to receive a Reset ACK !
32678411Sbrian       * Guess what... M$ invented this !
32778411Sbrian       */
32878411Sbrian      log_Printf(LogCCP, "MPPE: Input: Got seq %u, not %u\n",
32978411Sbrian                 prefix, mip->cohnum);
33078411Sbrian      fsm_Output(&ccp->fsm, CODE_RESETREQ, ccp->fsm.reqid++, NULL, 0,
33178411Sbrian                 MB_CCPOUT);
33278411Sbrian      mip->flushrequired = 1;
33378411Sbrian      m_freem(mp);
33478411Sbrian      return NULL;
33578411Sbrian    }
33678411Sbrian
33778411Sbrian    if ((prefix & MPPE_HEADER_FLAGMASK) == MPPE_HEADER_FLAG) {
33878411Sbrian      log_Printf(LogDEBUG, "MPPEInput: Key changed [%u]\n", prefix);
33978411Sbrian      MPPEKeyChange(mip);
34078411Sbrian      dictinit = 1;
34178411Sbrian    } else if (flushed)
34278411Sbrian      dictinit = 1;
34378411Sbrian
34478411Sbrian    /*
34578411Sbrian     * mip->cohnum contains what we expect to receive next time in stateful
34678411Sbrian     * mode.
34778411Sbrian     */
34878411Sbrian    mip->cohnum++;
34978411Sbrian    mip->cohnum &= ~MPPE_HEADER_BITMASK;
35078411Sbrian  }
35178411Sbrian
35278411Sbrian  if (dictinit) {
35378411Sbrian    log_Printf(LogDEBUG, "MPPEInput: Dictionary initialised [%u]\n", prefix);
35478411Sbrian    RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey);
35578411Sbrian  }
35678411Sbrian
35767910Sbrian  mp = mbuf_Read(mp, proto, 2);
35867910Sbrian  RC4(&mip->rc4key, 2, (char *)proto, (char *)proto);
35967910Sbrian  *proto = ntohs(*proto);
36067910Sbrian
36167910Sbrian  rp = MBUF_CTOP(mp);
36278411Sbrian  len = m_length(mp);
36378411Sbrian  RC4(&mip->rc4key, len, rp, rp);
36467910Sbrian
36578411Sbrian  log_Printf(LogDEBUG, "MPPEInput: Decrypted: Proto %02x (%d bytes)\n",
36678411Sbrian             *proto, len);
36778411Sbrian  log_DumpBp(LogDEBUG, "MPPEInput: Decrypted: Packet:", mp);
36867910Sbrian
36978411Sbrian  ccp->uncompin += len;
37067910Sbrian
37167910Sbrian  return mp;
37267910Sbrian}
37367910Sbrian
37467910Sbrianstatic void
375134789SbrianMPPEDictSetup(void *v __unused, struct ccp *ccp __unused,
376134789Sbrian	      u_short proto __unused, struct mbuf *mp __unused)
37767910Sbrian{
378134789Sbrian  /* Nothing to see here */
37967910Sbrian}
38067910Sbrian
38167910Sbrianstatic const char *
38294894SbrianMPPEDispOpts(struct fsm_opt *o)
38367910Sbrian{
38478411Sbrian  static char buf[70];
38583403Sbrian  u_int32_t val;
38678411Sbrian  char ch;
38792221Sbrian  int len, n;
38878411Sbrian
38983403Sbrian  ua_ntohl(o->data, &val);
39092221Sbrian  len = 0;
39192221Sbrian  if ((n = snprintf(buf, sizeof buf, "value 0x%08x ", (unsigned)val)) > 0)
39292221Sbrian    len += n;
39378411Sbrian  if (!(val & MPPE_OPT_BITMASK)) {
39492221Sbrian    if ((n = snprintf(buf + len, sizeof buf - len, "(0")) > 0)
39592221Sbrian      len += n;
39678411Sbrian  } else {
39778411Sbrian    ch = '(';
39878411Sbrian    if (val & MPPE_OPT_128BIT) {
39992221Sbrian      if ((n = snprintf(buf + len, sizeof buf - len, "%c128", ch)) > 0)
40092221Sbrian        len += n;
40178411Sbrian      ch = '/';
40278411Sbrian    }
40378411Sbrian    if (val & MPPE_OPT_56BIT) {
40492221Sbrian      if ((n = snprintf(buf + len, sizeof buf - len, "%c56", ch)) > 0)
40592221Sbrian        len += n;
40678411Sbrian      ch = '/';
40778411Sbrian    }
40878411Sbrian    if (val & MPPE_OPT_40BIT) {
40992221Sbrian      if ((n = snprintf(buf + len, sizeof buf - len, "%c40", ch)) > 0)
41092221Sbrian        len += n;
41178411Sbrian      ch = '/';
41278411Sbrian    }
41378411Sbrian  }
41478411Sbrian
41592221Sbrian  if ((n = snprintf(buf + len, sizeof buf - len, " bits, state%s",
41692221Sbrian                    (val & MPPE_OPT_STATELESS) ? "less" : "ful")) > 0)
41792221Sbrian    len += n;
41878411Sbrian
41978411Sbrian  if (val & MPPE_OPT_COMPRESSED) {
42092221Sbrian    if ((n = snprintf(buf + len, sizeof buf - len, ", compressed")) > 0)
42192221Sbrian      len += n;
42278411Sbrian  }
42378411Sbrian
42478411Sbrian  snprintf(buf + len, sizeof buf - len, ")");
42578411Sbrian
42667910Sbrian  return buf;
42767910Sbrian}
42867910Sbrian
42972025Sbrianstatic int
43072025SbrianMPPEUsable(struct fsm *fp)
43172025Sbrian{
43272025Sbrian  int ok;
43398966Sbrian#ifndef NORADIUS
43498966Sbrian  struct radius *r = &fp->bundle->radius;
43572025Sbrian
43698966Sbrian  /*
43798966Sbrian   * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES,
43898966Sbrian   * use that instead of our configuration value.
43998966Sbrian   */
44098966Sbrian  if (*r->cfg.file) {
44198966Sbrian    ok = r->mppe.sendkeylen && r->mppe.recvkeylen;
44298966Sbrian    if (!ok)
44398966Sbrian      log_Printf(LogCCP, "MPPE: Not permitted by RADIUS server\n");
44498966Sbrian  } else
44598966Sbrian#endif
44698966Sbrian  {
44798966Sbrian    struct lcp *lcp = &fp->link->lcp;
44898966Sbrian    ok = (lcp->want_auth == PROTO_CHAP && lcp->want_authtype == 0x81) ||
44998966Sbrian         (lcp->his_auth == PROTO_CHAP && lcp->his_authtype == 0x81);
45098966Sbrian    if (!ok)
45198966Sbrian      log_Printf(LogCCP, "MPPE: Not usable without CHAP81\n");
45298966Sbrian  }
45372025Sbrian
45472025Sbrian  return ok;
45572025Sbrian}
45672025Sbrian
45778411Sbrianstatic int
45878411SbrianMPPERequired(struct fsm *fp)
45978411Sbrian{
46098132Sbrian#ifndef NORADIUS
46198132Sbrian  /*
46298132Sbrian   * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY,
46398132Sbrian   * use that instead of our configuration value.
46498132Sbrian   */
46598132Sbrian  if (*fp->bundle->radius.cfg.file && fp->bundle->radius.mppe.policy)
46698132Sbrian    return fp->bundle->radius.mppe.policy == MPPE_POLICY_REQUIRED ? 1 : 0;
46798132Sbrian#endif
46898132Sbrian
46978411Sbrian  return fp->link->ccp.cfg.mppe.required;
47078411Sbrian}
47178411Sbrian
47278411Sbrianstatic u_int32_t
473134906SphkMPPE_ConfigVal(struct bundle *bundle __unused, const struct ccp_config *cfg)
47478411Sbrian{
47578411Sbrian  u_int32_t val;
47678411Sbrian
47778411Sbrian  val = cfg->mppe.state == MPPE_STATELESS ? MPPE_OPT_STATELESS : 0;
47898132Sbrian#ifndef NORADIUS
47998132Sbrian  /*
48098132Sbrian   * If the radius server gave us RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES,
48198132Sbrian   * use that instead of our configuration value.
48298132Sbrian   */
48398132Sbrian  if (*bundle->radius.cfg.file && bundle->radius.mppe.types) {
48498132Sbrian    if (bundle->radius.mppe.types & MPPE_TYPE_40BIT)
48598132Sbrian      val |= MPPE_OPT_40BIT;
48698132Sbrian    if (bundle->radius.mppe.types & MPPE_TYPE_128BIT)
48798132Sbrian      val |= MPPE_OPT_128BIT;
48898132Sbrian  } else
48998132Sbrian#endif
49098132Sbrian    switch(cfg->mppe.keybits) {
49198132Sbrian    case 128:
49298132Sbrian      val |= MPPE_OPT_128BIT;
49398132Sbrian      break;
49498132Sbrian    case 56:
49598132Sbrian      val |= MPPE_OPT_56BIT;
49698132Sbrian      break;
49798132Sbrian    case 40:
49898132Sbrian      val |= MPPE_OPT_40BIT;
49998132Sbrian      break;
50098132Sbrian    case 0:
50198132Sbrian      val |= MPPE_OPT_128BIT | MPPE_OPT_56BIT | MPPE_OPT_40BIT;
50298132Sbrian      break;
50398132Sbrian    }
50478411Sbrian
50578411Sbrian  return val;
50678411Sbrian}
50778411Sbrian
50878411Sbrian/*
50978411Sbrian * What options should we use for our first configure request
51078411Sbrian */
51167910Sbrianstatic void
51298132SbrianMPPEInitOptsOutput(struct bundle *bundle, struct fsm_opt *o,
51398132Sbrian                   const struct ccp_config *cfg)
51467910Sbrian{
51583403Sbrian  u_int32_t mval;
51667910Sbrian
51794894Sbrian  o->hdr.len = 6;
51867910Sbrian
51967910Sbrian  if (!MPPE_MasterKeyValid) {
52070498Sbrian    log_Printf(LogCCP, "MPPE: MasterKey is invalid,"
52171971Sbrian               " MPPE is available only with CHAP81 authentication\n");
522134809Sbrian    mval = 0;
523134809Sbrian    ua_htonl(&mval, o->data);
52467910Sbrian    return;
52567910Sbrian  }
52667910Sbrian
52798132Sbrian
52898132Sbrian  mval = MPPE_ConfigVal(bundle, cfg);
52983403Sbrian  ua_htonl(&mval, o->data);
53067910Sbrian}
53167910Sbrian
53278411Sbrian/*
53378411Sbrian * Our CCP request was NAK'd with the given options
53478411Sbrian */
53567910Sbrianstatic int
53698132SbrianMPPESetOptsOutput(struct bundle *bundle, struct fsm_opt *o,
53798132Sbrian                  const struct ccp_config *cfg)
53867910Sbrian{
53983403Sbrian  u_int32_t mval, peer;
54067910Sbrian
54183403Sbrian  ua_ntohl(o->data, &peer);
54283403Sbrian
54378411Sbrian  if (!MPPE_MasterKeyValid)
54478411Sbrian    /* Treat their NAK as a REJ */
54578411Sbrian    return MODE_NAK;
54667910Sbrian
54798132Sbrian  mval = MPPE_ConfigVal(bundle, cfg);
54878411Sbrian
54978411Sbrian  /*
55078411Sbrian   * If we haven't been configured with a specific number of keybits, allow
55178411Sbrian   * whatever the peer asks for.
55278411Sbrian   */
55378411Sbrian  if (!cfg->mppe.keybits) {
55478411Sbrian    mval &= ~MPPE_OPT_BITMASK;
55578411Sbrian    mval |= (peer & MPPE_OPT_BITMASK);
55678411Sbrian    if (!(mval & MPPE_OPT_BITMASK))
55778411Sbrian      mval |= MPPE_OPT_128BIT;
55867910Sbrian  }
55967910Sbrian
56078411Sbrian  /* Adjust our statelessness */
56178411Sbrian  if (cfg->mppe.state == MPPE_ANYSTATE) {
56278411Sbrian    mval &= ~MPPE_OPT_STATELESS;
56378411Sbrian    mval |= (peer & MPPE_OPT_STATELESS);
56478411Sbrian  }
56567910Sbrian
56683403Sbrian  ua_htonl(&mval, o->data);
56778411Sbrian
56878411Sbrian  return MODE_ACK;
56967910Sbrian}
57067910Sbrian
57178411Sbrian/*
57278411Sbrian * The peer has requested the given options
57378411Sbrian */
57467910Sbrianstatic int
57598132SbrianMPPESetOptsInput(struct bundle *bundle, struct fsm_opt *o,
57698132Sbrian                 const struct ccp_config *cfg)
57767910Sbrian{
57883403Sbrian  u_int32_t mval, peer;
57978411Sbrian  int res = MODE_ACK;
58067910Sbrian
58183403Sbrian  ua_ntohl(o->data, &peer);
58267910Sbrian  if (!MPPE_MasterKeyValid) {
58383403Sbrian    if (peer != 0) {
58483403Sbrian      peer = 0;
58583403Sbrian      ua_htonl(&peer, o->data);
58667910Sbrian      return MODE_NAK;
58778411Sbrian    } else
58867910Sbrian      return MODE_ACK;
58967910Sbrian  }
59067910Sbrian
59198132Sbrian  mval = MPPE_ConfigVal(bundle, cfg);
59278411Sbrian
59378411Sbrian  if (peer & ~MPPE_OPT_MASK)
59478411Sbrian    /* He's asking for bits we don't know about */
59578411Sbrian    res = MODE_NAK;
59678411Sbrian
59778411Sbrian  if (peer & MPPE_OPT_STATELESS) {
59878411Sbrian    if (cfg->mppe.state == MPPE_STATEFUL)
59978411Sbrian      /* Peer can't have stateless */
60078411Sbrian      res = MODE_NAK;
60178411Sbrian    else
60278411Sbrian      /* Peer wants stateless, that's ok */
60378411Sbrian      mval |= MPPE_OPT_STATELESS;
60478411Sbrian  } else {
60578411Sbrian    if (cfg->mppe.state == MPPE_STATELESS)
60678411Sbrian      /* Peer must have stateless */
60778411Sbrian      res = MODE_NAK;
60878411Sbrian    else
60978411Sbrian      /* Peer doesn't want stateless, that's ok */
61078411Sbrian      mval &= ~MPPE_OPT_STATELESS;
61167910Sbrian  }
61267910Sbrian
61378411Sbrian  /* If we've got a configured number of keybits - the peer must use that */
61478411Sbrian  if (cfg->mppe.keybits) {
61583403Sbrian    ua_htonl(&mval, o->data);
61678411Sbrian    return peer == mval ? res : MODE_NAK;
61778411Sbrian  }
61867910Sbrian
61978411Sbrian  /* If a specific number of bits hasn't been requested, we'll need to NAK */
62078411Sbrian  switch (peer & MPPE_OPT_BITMASK) {
62178411Sbrian  case MPPE_OPT_128BIT:
62278411Sbrian  case MPPE_OPT_56BIT:
62378411Sbrian  case MPPE_OPT_40BIT:
62478411Sbrian    break;
62578411Sbrian  default:
62678411Sbrian    res = MODE_NAK;
62778411Sbrian  }
62878411Sbrian
62978411Sbrian  /* Suggest the best number of bits */
63078411Sbrian  mval &= ~MPPE_OPT_BITMASK;
63178411Sbrian  if (peer & MPPE_OPT_128BIT)
63278411Sbrian    mval |= MPPE_OPT_128BIT;
63378411Sbrian  else if (peer & MPPE_OPT_56BIT)
63478411Sbrian    mval |= MPPE_OPT_56BIT;
63578411Sbrian  else if (peer & MPPE_OPT_40BIT)
63678411Sbrian    mval |= MPPE_OPT_40BIT;
63778411Sbrian  else
63878411Sbrian    mval |= MPPE_OPT_128BIT;
63983403Sbrian  ua_htonl(&mval, o->data);
64067910Sbrian
64178411Sbrian  return res;
64267910Sbrian}
64367910Sbrian
64478411Sbrianstatic struct mppe_state *
64594894SbrianMPPE_InitState(struct fsm_opt *o)
64678411Sbrian{
64778411Sbrian  struct mppe_state *mp;
64878411Sbrian  u_int32_t val;
64978411Sbrian
65078411Sbrian  if ((mp = calloc(1, sizeof *mp)) != NULL) {
65183403Sbrian    ua_ntohl(o->data, &val);
65278411Sbrian
65378411Sbrian    switch (val & MPPE_OPT_BITMASK) {
65478411Sbrian    case MPPE_OPT_128BIT:
65578411Sbrian      mp->keylen = 16;
65678411Sbrian      mp->keybits = 128;
65778411Sbrian      break;
65878411Sbrian    case MPPE_OPT_56BIT:
65978411Sbrian      mp->keylen = 8;
66078411Sbrian      mp->keybits = 56;
66178411Sbrian      break;
66278411Sbrian    case MPPE_OPT_40BIT:
66378411Sbrian      mp->keylen = 8;
66478411Sbrian      mp->keybits = 40;
66578411Sbrian      break;
66678411Sbrian    default:
66778411Sbrian      log_Printf(LogWARN, "Unexpected MPPE options 0x%08x\n", val);
66878411Sbrian      free(mp);
66978411Sbrian      return NULL;
67078411Sbrian    }
67178411Sbrian
67278411Sbrian    mp->stateless = !!(val & MPPE_OPT_STATELESS);
67378411Sbrian  }
67478411Sbrian
67578411Sbrian  return mp;
67678411Sbrian}
67778411Sbrian
67867910Sbrianstatic void *
679134906SphkMPPEInitInput(struct bundle *bundle __unused, struct fsm_opt *o)
68067910Sbrian{
68167910Sbrian  struct mppe_state *mip;
68267910Sbrian
68367910Sbrian  if (!MPPE_MasterKeyValid) {
68471971Sbrian    log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n");
68567910Sbrian    return NULL;
68667910Sbrian  }
68767910Sbrian
68878411Sbrian  if ((mip = MPPE_InitState(o)) == NULL) {
68978411Sbrian    log_Printf(LogWARN, "MPPEInput: Cannot initialise - unexpected options\n");
69078411Sbrian    return NULL;
69167910Sbrian  }
69267910Sbrian
69367910Sbrian  log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits);
69467910Sbrian
69598132Sbrian#ifndef NORADIUS
69698132Sbrian  if (*bundle->radius.cfg.file && bundle->radius.mppe.recvkey) {
69799235Sbrian    if (mip->keylen > bundle->radius.mppe.recvkeylen)
69899235Sbrian      mip->keylen = bundle->radius.mppe.recvkeylen;
69998132Sbrian    if (mip->keylen > sizeof mip->mastkey)
70098132Sbrian      mip->keylen = sizeof mip->mastkey;
70198132Sbrian    memcpy(mip->mastkey, bundle->radius.mppe.recvkey, mip->keylen);
70298132Sbrian  } else
70398132Sbrian#endif
70498132Sbrian    GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0,
70598132Sbrian                         MPPE_IsServer);
70698132Sbrian
70767910Sbrian  GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey);
70867910Sbrian
70967910Sbrian  MPPEReduceSessionKey(mip);
71067910Sbrian
71178411Sbrian  log_Printf(LogCCP, "MPPE: Input channel initiated\n");
71267910Sbrian
71378411Sbrian  if (!mip->stateless) {
71478411Sbrian    /*
71578411Sbrian     * We need to initialise our dictionary here as the first packet we
71678411Sbrian     * receive is unlikely to have the FLUSHED bit set.
71778411Sbrian     */
71878411Sbrian    log_Printf(LogDEBUG, "MPPEInitInput: Dictionary initialised [%d]\n",
71978411Sbrian               mip->cohnum);
72078411Sbrian    RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey);
72178411Sbrian  } else {
72278411Sbrian    /*
72378411Sbrian     * We do the first key change here as the first packet is expected
72478411Sbrian     * to have a sequence number of 0 and we'll therefore not expect
72578411Sbrian     * to have to change the key at that point.
72678411Sbrian     */
72778411Sbrian    log_Printf(LogDEBUG, "MPPEInitInput: Key changed [%d]\n", mip->cohnum);
72878411Sbrian    MPPEKeyChange(mip);
72978411Sbrian  }
73067910Sbrian
73167910Sbrian  return mip;
73267910Sbrian}
73367910Sbrian
73467910Sbrianstatic void *
735134906SphkMPPEInitOutput(struct bundle *bundle __unused, struct fsm_opt *o)
73667910Sbrian{
73767910Sbrian  struct mppe_state *mop;
73867910Sbrian
73967910Sbrian  if (!MPPE_MasterKeyValid) {
74071971Sbrian    log_Printf(LogWARN, "MPPE: Cannot initialise without CHAP81\n");
74167910Sbrian    return NULL;
74267910Sbrian  }
74367910Sbrian
74478411Sbrian  if ((mop = MPPE_InitState(o)) == NULL) {
74578411Sbrian    log_Printf(LogWARN, "MPPEOutput: Cannot initialise - unexpected options\n");
74678411Sbrian    return NULL;
74767910Sbrian  }
74867910Sbrian
74967910Sbrian  log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits);
75067910Sbrian
75198132Sbrian#ifndef NORADIUS
75298132Sbrian  if (*bundle->radius.cfg.file && bundle->radius.mppe.sendkey) {
75399235Sbrian    if (mop->keylen > bundle->radius.mppe.sendkeylen)
75499235Sbrian      mop->keylen = bundle->radius.mppe.sendkeylen;
75598132Sbrian    if (mop->keylen > sizeof mop->mastkey)
75698132Sbrian      mop->keylen = sizeof mop->mastkey;
75798132Sbrian    memcpy(mop->mastkey, bundle->radius.mppe.sendkey, mop->keylen);
75898132Sbrian  } else
75998132Sbrian#endif
76098132Sbrian    GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1,
76198132Sbrian                         MPPE_IsServer);
76298132Sbrian
76367910Sbrian  GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey);
76467910Sbrian
76567910Sbrian  MPPEReduceSessionKey(mop);
76667910Sbrian
76778411Sbrian  log_Printf(LogCCP, "MPPE: Output channel initiated\n");
76867910Sbrian
76978411Sbrian  if (!mop->stateless) {
77078411Sbrian    /*
77178411Sbrian     * We need to initialise our dictionary now as the first packet we
77278411Sbrian     * send won't have the FLUSHED bit set.
77378411Sbrian     */
77478411Sbrian    log_Printf(LogDEBUG, "MPPEInitOutput: Dictionary initialised [%d]\n",
77578411Sbrian               mop->cohnum);
77678411Sbrian    RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey);
77778411Sbrian  }
77867910Sbrian
77967910Sbrian  return mop;
78067910Sbrian}
78167910Sbrian
78267910Sbrianstatic void
78367910SbrianMPPETermInput(void *v)
78467910Sbrian{
78567910Sbrian  free(v);
78667910Sbrian}
78767910Sbrian
78867910Sbrianstatic void
78967910SbrianMPPETermOutput(void *v)
79067910Sbrian{
79167910Sbrian  free(v);
79267910Sbrian}
79367910Sbrian
79467910Sbrianconst struct ccp_algorithm MPPEAlgorithm = {
79567910Sbrian  TY_MPPE,
79667910Sbrian  CCP_NEG_MPPE,
79767910Sbrian  MPPEDispOpts,
79872025Sbrian  MPPEUsable,
79978411Sbrian  MPPERequired,
80067910Sbrian  {
80167910Sbrian    MPPESetOptsInput,
80267910Sbrian    MPPEInitInput,
80367910Sbrian    MPPETermInput,
80467910Sbrian    MPPEResetInput,
80567910Sbrian    MPPEInput,
80667910Sbrian    MPPEDictSetup
80767910Sbrian  },
80867910Sbrian  {
80979165Sbrian    2,
81067910Sbrian    MPPEInitOptsOutput,
81167910Sbrian    MPPESetOptsOutput,
81267910Sbrian    MPPEInitOutput,
81367910Sbrian    MPPETermOutput,
81467910Sbrian    MPPEResetOutput,
81567910Sbrian    MPPEOutput
81667910Sbrian  },
81767910Sbrian};
818