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: releng/11.0/usr.sbin/ppp/mppe.c 256574 2013-10-16 02:55:31Z kevlo $ 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); 171256574Skevlo 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