Add MPPE and MSChap v2 support (denied and disabled by default)

Submitted by: Ustimenko Semen <semen@iclub.nsu.ru>
This commit is contained in:
Brian Somers 2000-10-30 00:15:04 +00:00
parent fa99586d3a
commit a8d604ab74
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=67910
15 changed files with 1003 additions and 26 deletions

View File

@ -58,7 +58,7 @@ SRCS+= id.c
.if exists(${.CURDIR}/../../secure) && !defined(NOCRYPT) && !defined(NOSECURE) && !defined(NO_OPENSSL) && !defined(RELEASE_CRUNCH)
DISTRIBUTION=crypto
CFLAGS+=-DHAVE_DES
SRCS+= chap_ms.c
SRCS+= chap_ms.c mppe.c
LDADD+= -lcrypto
DPADD+= ${LIBCRYPTO}
.endif

View File

@ -61,6 +61,9 @@
#ifndef NORADIUS
#include "radius.h"
#endif
#ifdef HAVE_DES
#include "mppe.h"
#endif
#include "bundle.h"
static void CcpSendConfigReq(struct fsm *);
@ -106,7 +109,8 @@ protoname(int proto)
NULL, NULL, NULL, NULL, NULL, NULL,
"HWPPC", /* 16: Hewlett-Packard PPC */
"STAC", /* 17: Stac Electronics LZS (rfc1974) */
"MPPC", /* 18: Microsoft PPC (rfc2118) */
"MPPE", /* 18: Microsoft PPC (rfc2118) and */
/* Microsoft PPE (draft-ietf-pppext-mppe) */
"GAND", /* 19: Gandalf FZA (rfc1993) */
"V42BIS", /* 20: ARG->DATA.42bis compression */
"BSD", /* 21: BSD LZW Compress */
@ -130,6 +134,9 @@ static const struct ccp_algorithm * const algorithm[] = {
&DeflateAlgorithm,
&Pred1Algorithm,
&PppdDeflateAlgorithm
#ifdef HAVE_DES
, &MPPEAlgorithm
#endif
};
#define NALGORITHMS (sizeof algorithm/sizeof algorithm[0])
@ -167,6 +174,11 @@ ccp_ReportStatus(struct cmdargs const *arg)
command_ShowNegval(ccp->cfg.neg[CCP_NEG_PRED1]));
prompt_Printf(arg->prompt, " DEFLATE24: %s\n",
command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE24]));
#ifdef HAVE_DES
prompt_Printf(arg->prompt, " MPPE: %s\n",
command_ShowNegval(ccp->cfg.neg[CCP_NEG_MPPE]));
prompt_Printf(arg->prompt, "Key Size = %d-bits\n", ccp->cfg.mppe.keybits);
#endif
return 0;
}
@ -196,6 +208,10 @@ ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l,
ccp->cfg.neg[CCP_NEG_DEFLATE] = NEG_ENABLED|NEG_ACCEPTED;
ccp->cfg.neg[CCP_NEG_PRED1] = NEG_ENABLED|NEG_ACCEPTED;
ccp->cfg.neg[CCP_NEG_DEFLATE24] = 0;
#ifdef HAVE_DES
ccp->cfg.mppe.keybits = 128;
ccp->cfg.neg[CCP_NEG_MPPE] = 0;
#endif
ccp_Setup(ccp);
}

View File

@ -29,6 +29,7 @@
#define TY_HWPPC 16 /* Hewlett-Packard PPC */
#define TY_STAC 17 /* Stac Electronics LZS */
#define TY_MSPPC 18 /* Microsoft PPC */
#define TY_MPPE 18 /* Microsoft PPE */
#define TY_GAND 19 /* Gandalf FZA */
#define TY_V42BIS 20 /* V.42bis compression */
#define TY_BSD 21 /* BSD LZW Compress */
@ -38,7 +39,12 @@
#define CCP_NEG_DEFLATE 0
#define CCP_NEG_PRED1 1
#define CCP_NEG_DEFLATE24 2
#ifdef HAVE_DES
#define CCP_NEG_MPPE 3
#define CCP_NEG_TOTAL 4
#else
#define CCP_NEG_TOTAL 3
#endif
struct mbuf;
struct link;
@ -49,6 +55,11 @@ struct ccp_config {
int winsize;
} in, out;
} deflate;
#ifdef HAVE_DES
struct {
int keybits;
} mppe;
#endif
struct fsm_retry fsm; /* How often/frequently to resend requests */
unsigned neg[CCP_NEG_TOTAL];
};

View File

@ -75,6 +75,7 @@
#include "datalink.h"
#ifdef HAVE_DES
#include "chap_ms.h"
#include "mppe.h"
#endif
#include "id.h"
@ -111,7 +112,7 @@ ChapOutput(struct physical *physical, u_int code, u_int id,
static char *
chap_BuildAnswer(char *name, char *key, u_char id, char *challenge, u_char type
#ifdef HAVE_DES
, int lanman
, char *peerchallenge, char *authresponse, int lanman
#endif
)
{
@ -167,6 +168,51 @@ chap_BuildAnswer(char *name, char *key, u_char id, char *challenge, u_char type
* ---- -------- ------------- ----- ------
* where only one of LANMan & NT digest are set.
*/
} else if (type == 0x81) {
char expkey[AUTHLEN << 2];
char pwdhash[CHAP81_HASH_LEN];
char pwdhashhash[CHAP81_HASH_LEN];
char *ntresponse;
int f;
if ((result = malloc(1 + nlen + CHAP81_RESPONSE_LEN)) == NULL)
return result;
memset(result, 0, 1 + nlen + CHAP81_RESPONSE_LEN);
digest = result;
*digest++ = CHAP81_RESPONSE_LEN; /* value size */
/* Copy our challenge */
memcpy(digest, peerchallenge + 1, CHAP81_CHALLENGE_LEN);
/* Expand password to Unicode XXX */
for (f = 0; f < klen; f++) {
expkey[2*f] = key[f];
expkey[2*f+1] = '\0';
}
ntresponse = digest + CHAP81_NTRESPONSE_OFF;
/* Get some needed hashes */
NtPasswordHash(expkey, klen * 2, pwdhash);
HashNtPasswordHash(pwdhash, pwdhashhash);
/* Generate NTRESPONSE to respond on challenge call */
GenerateNTResponse(challenge + 1, peerchallenge + 1, name, nlen,
expkey, klen * 2, ntresponse);
/* Generate MPPE MASTERKEY */
GetMasterKey(pwdhashhash, ntresponse, MPPE_MasterKey);
/* Generate AUTHRESPONSE to verify on auth success */
GenerateAuthenticatorResponse(expkey, klen * 2, ntresponse,
peerchallenge + 1, challenge + 1, name, nlen,
authresponse);
authresponse[CHAP81_AUTHRESPONSE_LEN] = 0;
memcpy(digest + CHAP81_RESPONSE_LEN, name, nlen);
} else
#endif
if ((result = malloc(nlen + 17)) != NULL) {
@ -316,7 +362,7 @@ chap_Respond(struct chap *chap, char *name, char *key, u_char type
ans = chap_BuildAnswer(name, key, chap->auth.id, chap->challenge.peer, type
#ifdef HAVE_DES
, lm
, chap->challenge.local, chap->authresponse, lm
#endif
);
@ -421,7 +467,7 @@ chap_Write(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset)
}
static void
chap_Challenge(struct authinfo *authp)
chap_ChallengeInit(struct authinfo *authp)
{
struct chap *chap = auth2chap(authp);
int len, i;
@ -445,6 +491,8 @@ chap_Challenge(struct authinfo *authp)
#ifdef HAVE_DES
if (authp->physical->link.lcp.want_authtype == 0x80)
*cp++ = 8; /* MS does 8 byte callenges :-/ */
else if (authp->physical->link.lcp.want_authtype == 0x81)
*cp++ = 16; /* MS-CHAP-V2 does 16 bytes challenges */
else
#endif
*cp++ = random() % (CHAPCHALLENGELEN-16) + 16;
@ -453,15 +501,48 @@ chap_Challenge(struct authinfo *authp)
}
memcpy(cp, authp->physical->dl->bundle->cfg.auth.name, len);
}
ChapOutput(authp->physical, CHAP_CHALLENGE, authp->id, chap->challenge.local,
1 + *chap->challenge.local + len, NULL);
}
static void
chap_Challenge(struct authinfo *authp)
{
struct chap *chap = auth2chap(authp);
int len;
log_Printf(LogDEBUG, "CHAP%02X: Challenge\n", authp->physical->link.lcp.want_authtype);
len = strlen(authp->physical->dl->bundle->cfg.auth.name);
/* Generate new local challenge value */
if (!*chap->challenge.local)
chap_ChallengeInit(authp);
#ifdef HAVE_DES
if (authp->physical->link.lcp.want_authtype == 0x81)
ChapOutput(authp->physical, CHAP_CHALLENGE, authp->id,
chap->challenge.local, 1 + *chap->challenge.local, NULL);
else
#endif
ChapOutput(authp->physical, CHAP_CHALLENGE, authp->id,
chap->challenge.local, 1 + *chap->challenge.local + len, NULL);
}
static void
chap_Success(struct authinfo *authp)
{
char *msg;
datalink_GotAuthname(authp->physical->dl, authp->in.name);
ChapOutput(authp->physical, CHAP_SUCCESS, authp->id, "Welcome!!", 10, NULL);
#ifdef HAVE_DES
if (authp->physical->link.lcp.want_authtype == 0x81) {
msg = auth2chap(authp)->authresponse;
MPPE_MasterKeyValid = 1;
} else
#endif
msg = "Welcome!!";
ChapOutput(authp->physical, CHAP_SUCCESS, authp->id, msg, strlen(msg) + 1,
NULL);
authp->physical->link.lcp.auth_ineed = 0;
if (Enabled(authp->physical->dl->bundle, OPT_UTMP))
physical_Login(authp->physical, authp->in.name);
@ -477,7 +558,28 @@ chap_Success(struct authinfo *authp)
static void
chap_Failure(struct authinfo *authp)
{
ChapOutput(authp->physical, CHAP_FAILURE, authp->id, "Invalid!!", 9, NULL);
#ifdef HAVE_DES
char buf[1024];
#endif
char *msg;
#ifdef HAVE_DES
if (authp->physical->link.lcp.want_authtype == 0x81) {
int i;
msg = buf;
msg += sprintf(buf, "E=691 R=0 C=");
for (i=0; i<16; i++)
msg += sprintf(msg, "%02X", *(auth2chap(authp)->challenge.local+1+i));
sprintf(msg, " V=3 M=Invalid!");
msg = buf;
} else
#endif
msg = "Invalid!!";
ChapOutput(authp->physical, CHAP_FAILURE, authp->id, msg, strlen(msg) + 1,
NULL);
datalink_AuthNotOk(authp->physical->dl);
}
@ -610,6 +712,9 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
lanman = p->link.lcp.his_authtype == 0x80 &&
((chap->NTRespSent && IsAccepted(p->link.lcp.cfg.chap80lm)) ||
!IsAccepted(p->link.lcp.cfg.chap80nt));
/* Generate local challenge value */
chap_ChallengeInit(&chap->auth);
#endif
break;
@ -632,7 +737,8 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
ans[alen+1] = '\0';
bp = auth_ReadName(&chap->auth, bp, len);
#ifdef HAVE_DES
lanman = alen == 49 && ans[alen] == 0;
lanman = p->link.lcp.want_authtype == 0x80 &&
alen == 49 && ans[alen] == 0;
#endif
break;
@ -717,25 +823,39 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
if (key) {
char *myans;
#ifdef HAVE_DES
if (lanman && !IsEnabled(p->link.lcp.cfg.chap80lm)) {
if (p->link.lcp.want_authtype == 0x80 &&
lanman && !IsEnabled(p->link.lcp.cfg.chap80lm)) {
log_Printf(LogPHASE, "Auth failure: LANMan not enabled\n");
if (chap_HaveAnotherGo(chap))
break;
key = NULL;
} else if (!lanman && !IsEnabled(p->link.lcp.cfg.chap80nt) &&
p->link.lcp.want_authtype == 0x80) {
} else if (p->link.lcp.want_authtype == 0x80 &&
!lanman && !IsEnabled(p->link.lcp.cfg.chap80nt)) {
log_Printf(LogPHASE, "Auth failure: mschap not enabled\n");
if (chap_HaveAnotherGo(chap))
break;
key = NULL;
} else if (p->link.lcp.want_authtype == 0x81 &&
!IsEnabled(p->link.lcp.cfg.chap81)) {
log_Printf(LogPHASE, "Auth failure: CHAP81 not enabled\n");
key = NULL;
} else
#endif
{
#ifdef HAVE_DES
/* Get peer's challenge */
if (p->link.lcp.want_authtype == 0x81) {
chap->challenge.peer[0] = CHAP81_CHALLENGE_LEN;
memcpy(chap->challenge.peer + 1, ans + 1, CHAP81_CHALLENGE_LEN);
}
#endif
myans = chap_BuildAnswer(name, key, chap->auth.id,
chap->challenge.local,
p->link.lcp.want_authtype
#ifdef HAVE_DES
, lanman
, chap->challenge.peer,
chap->authresponse, lanman
#endif
);
if (myans == NULL)
@ -764,13 +884,27 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
case CHAP_SUCCESS:
if (p->link.lcp.auth_iwait == PROTO_CHAP) {
p->link.lcp.auth_iwait = 0;
if (p->link.lcp.auth_ineed == 0)
if (p->link.lcp.auth_ineed == 0) {
#ifdef HAVE_DES
if (p->link.lcp.his_authtype == 0x81) {
if (strncmp(ans, chap->authresponse, 42)) {
datalink_AuthNotOk(p->dl);
log_Printf(LogDEBUG, "CHAP81: AuthenticatorResponse: (%s) != ans: (%s)\n", chap->authresponse, ans);
} else {
/* Successful login */
MPPE_MasterKeyValid = 1;
datalink_AuthOk(p->dl);
}
} else
#endif
/*
* We've succeeded in our ``login''
* If we're not expecting the peer to authenticate (or he already
* has), proceed to network phase.
*/
datalink_AuthOk(p->dl);
}
}
break;

View File

@ -46,12 +46,14 @@ struct chap {
#ifdef HAVE_DES
unsigned NTRespSent : 1; /* Our last response */
int peertries;
u_char authresponse[CHAPAUTHRESPONSELEN]; /* CHAP 81 response */
#endif
};
#define descriptor2chap(d) \
((d)->type == CHAP_DESCRIPTOR ? (struct chap *)(d) : NULL)
#define auth2chap(a) (struct chap *)((char *)a - (int)&((struct chap *)0)->auth)
#define auth2chap(a) \
((struct chap *)((char *)a - (int)&((struct chap *)0)->auth))
extern void chap_Init(struct chap *, struct physical *);
extern void chap_ReInit(struct chap *);

View File

@ -31,10 +31,32 @@
#else
#include <des.h>
#endif
#include <sha.h>
#include <md4.h>
#include <string.h>
#include "chap_ms.h"
/*
* Documentation & specifications:
*
* MS-CHAP (CHAP80) rfc2433
* MS-CHAP-V2 (CHAP81) rfc2759
* MPPE key management draft-ietf-pppext-mppe-keys-02.txt
*/
static char SHA1_Pad1[40] =
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static char SHA1_Pad2[40] =
{0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2};
/* unused, for documentation only */
/* only NTResp is filled in for FreeBSD */
struct MS_ChapResponse {
@ -95,6 +117,217 @@ ChallengeResponse(u_char *challenge, u_char *pwHash, u_char *response)
DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
}
void
NtPasswordHash(char *key, int keylen, char *hash) {
MD4_CTX MD4context;
MD4Init(&MD4context);
MD4Update(&MD4context, key, keylen);
MD4Final(hash, &MD4context);
}
void
HashNtPasswordHash(char *hash, char *hashhash) {
MD4_CTX MD4context;
MD4Init(&MD4context);
MD4Update(&MD4context, hash, 16);
MD4Final(hashhash, &MD4context);
}
void
ChallengeHash(char *PeerChallenge, char *AuthenticatorChallenge, char *UserName, int UserNameLen, char *Challenge) {
SHA_CTX Context;
char Digest[SHA_DIGEST_LENGTH];
char *Name;
Name = strrchr(UserName, '\\');
if(NULL == Name)
Name = UserName;
else
Name++;
SHA1_Init(&Context);
SHA1_Update(&Context, PeerChallenge, 16);
SHA1_Update(&Context, AuthenticatorChallenge, 16);
SHA1_Update(&Context, UserName, UserNameLen);
SHA1_Final(Digest, &Context);
memcpy(Challenge, Digest, 8);
}
void
GenerateNTResponse(char *AuthenticatorChallenge, char *PeerChallenge, char *UserName, int UserNameLen, char *Password, int PasswordLen, char *Response) {
char Challenge[8];
char PasswordHash[16];
ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName, UserNameLen,
Challenge);
NtPasswordHash(Password, PasswordLen, PasswordHash);
ChallengeResponse(Challenge, PasswordHash, Response);
}
void
GenerateAuthenticatorResponse(char *Password, int PasswordLen, char *NTResponse, char *PeerChallenge, char *AuthenticatorChallenge, char *UserName, int UserNameLen, char *AuthenticatorResponse) {
SHA_CTX Context;
char PasswordHash[16];
char PasswordHashHash[16];
char Challenge[8];
u_char Digest[SHA_DIGEST_LENGTH];
int i;
/*
* "Magic" constants used in response generation
*/
char Magic1[39] =
{0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74};
char Magic2[41] =
{0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
0x6E};
/*
* Hash the password with MD4
*/
NtPasswordHash(Password, PasswordLen, PasswordHash);
/*
* Now hash the hash
*/
HashNtPasswordHash(PasswordHash, PasswordHashHash);
SHA1_Init(&Context);
SHA1_Update(&Context, PasswordHashHash, 16);
SHA1_Update(&Context, NTResponse, 24);
SHA1_Update(&Context, Magic1, 39);
SHA1_Final(Digest, &Context);
ChallengeHash(PeerChallenge, AuthenticatorChallenge, UserName, UserNameLen,
Challenge);
SHA1_Init(&Context);
SHA1_Update(&Context, Digest, 20);
SHA1_Update(&Context, Challenge, 8);
SHA1_Update(&Context, Magic2, 41);
/*
* Encode the value of 'Digest' as "S=" followed by
* 40 ASCII hexadecimal digits and return it in
* AuthenticatorResponse.
* For example,
* "S=0123456789ABCDEF0123456789ABCDEF01234567"
*/
AuthenticatorResponse[0] = 'S';
AuthenticatorResponse[1] = '=';
SHA1_End(&Context, AuthenticatorResponse + 2);
for (i=2; i<42; i++)
AuthenticatorResponse[i] = toupper(AuthenticatorResponse[i]);
}
void
GetMasterKey(char *PasswordHashHash, char *NTResponse, char *MasterKey) {
char Digest[SHA_DIGEST_LENGTH];
SHA_CTX Context;
static char Magic1[27] =
{0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79};
SHA1_Init(&Context);
SHA1_Update(&Context, PasswordHashHash, 16);
SHA1_Update(&Context, NTResponse, 24);
SHA1_Update(&Context, Magic1, 27);
SHA1_Final(Digest, &Context);
memcpy(MasterKey, Digest, 16);
}
void
GetAsymetricStartKey(char *MasterKey, char *SessionKey, int SessionKeyLength, int IsSend, int IsServer) {
char Digest[SHA_DIGEST_LENGTH];
SHA_CTX Context;
char *s;
static char Magic2[84] =
{0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
0x6b, 0x65, 0x79, 0x2e};
static char Magic3[84] =
{0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
0x6b, 0x65, 0x79, 0x2e};
if (IsSend) {
if (IsServer) {
s = Magic3;
} else {
s = Magic2;
}
} else {
if (IsServer) {
s = Magic2;
} else {
s = Magic3;
}
}
SHA1_Init(&Context);
SHA1_Update(&Context, MasterKey, 16);
SHA1_Update(&Context, SHA1_Pad1, 40);
SHA1_Update(&Context, s, 84);
SHA1_Update(&Context, SHA1_Pad2, 40);
SHA1_Final(Digest, &Context);
memcpy(SessionKey, Digest, SessionKeyLength);
}
void
GetNewKeyFromSHA(char *StartKey, char *SessionKey, long SessionKeyLength, char *InterimKey) {
SHA_CTX Context;
char Digest[SHA_DIGEST_LENGTH];
SHA1_Init(&Context);
SHA1_Update(&Context, StartKey, SessionKeyLength);
SHA1_Update(&Context, SHA1_Pad1, 40);
SHA1_Update(&Context, SessionKey, SessionKeyLength);
SHA1_Update(&Context, SHA1_Pad2, 40);
SHA1_Final(Digest, &Context);
memcpy(InterimKey, Digest, SessionKeyLength);
}
void
Get_Key(char *InitialSessionKey, char *CurrentSessionKey, int LengthOfDesiredKey) {
SHA_CTX Context;
char Digest[SHA_DIGEST_LENGTH];
SHA1_Init(&Context);
SHA1_Update(&Context, InitialSessionKey, LengthOfDesiredKey);
SHA1_Update(&Context, SHA1_Pad1, 40);
SHA1_Update(&Context, CurrentSessionKey, LengthOfDesiredKey);
SHA1_Update(&Context, SHA1_Pad2, 40);
SHA1_Final(Digest, &Context);
memcpy(CurrentSessionKey, Digest, LengthOfDesiredKey);
}
/* passwordHash 16-bytes MD4 hashed password
challenge 8-bytes peer CHAP challenge
since passwordHash is in a 24-byte buffer, response is written in there */

View File

@ -26,7 +26,21 @@
#define MAX_NT_PASSWORD 256
/* Don't rely on sizeof(MS_ChapResponse) in case of struct padding */
#define MS_CHAP_RESPONSE_LEN 49
#define MS_CHAP_RESPONSE_LEN 49
#define CHAP81_RESPONSE_LEN 49
#define CHAP81_NTRESPONSE_LEN 24
#define CHAP81_NTRESPONSE_OFF 24
#define CHAP81_HASH_LEN 16
#define CHAP81_AUTHRESPONSE_LEN 42
#define CHAP81_CHALLENGE_LEN 16
extern void mschap_NT(char *, char *);
extern void mschap_LANMan(char *, char *, char *);
extern void GenerateNTResponse(char *, char *, char *, int, char *, int , char *);
extern void HashNtPasswordHash(char *, char *);
extern void NtPasswordHash(char *, int, char *);
extern void ChallengeHash(char *, char *, char *UserName, int, char *);
extern void GenerateAuthenticatorResponse(char *, int, char *, char *, char *, char *, int, char *);
extern void GetAsymetricStartKey(char *, char *, int, int, int);
extern void GetMasterKey(char *, char *, char *);
extern void GetNewKeyFromSHA(char *, char *, long, char *);

View File

@ -127,6 +127,7 @@
#define VAR_URGENTPORTS 33
#define VAR_LOGOUT 34
#define VAR_IFQUEUE 35
#define VAR_KEYBITS 36
/* ``accept|deny|disable|enable'' masks */
#define NEG_HISMASK (1)
@ -147,6 +148,8 @@
#define NEG_PROTOCOMP 51
#define NEG_SHORTSEQ 52
#define NEG_VJCOMP 53
#define NEG_MPPE 54
#define NEG_CHAP81 55
const char Version[] = "2.27";
@ -1574,6 +1577,24 @@ SetVariable(struct cmdargs const *arg)
}
break;
#ifdef HAVE_DES
case VAR_KEYBITS:
if (arg->argc > arg->argn) {
l->ccp.cfg.mppe.keybits = atoi(arg->argv[arg->argn]);
if (l->ccp.cfg.mppe.keybits != 40 &&
l->ccp.cfg.mppe.keybits != 56 &&
l->ccp.cfg.mppe.keybits != 128 ) {
log_Printf(LogWARN, "%d: Invalid bits number\n",
l->ccp.cfg.mppe.keybits);
l->ccp.cfg.mppe.keybits = 40;
}
} else {
err = "No bits number pecified\n";
log_Printf(LogWARN, err);
}
break;
#endif
case VAR_DEVICE:
physical_SetDeviceList(cx->physical, arg->argc - arg->argn,
arg->argv + arg->argn);
@ -1968,6 +1989,11 @@ static struct cmdtab const SetCommands[] = {
{"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT,
"deflate window sizes", "set deflate out-winsize in-winsize",
(const void *) VAR_WINSIZE},
#ifdef HAVE_DES
{"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT,
"MPPE key size", "set mppe {40|56|128}",
(const void *) VAR_KEYBITS},
#endif
{"device", "line", SetVariable, LOCAL_AUTH | LOCAL_CX,
"physical device name", "set device|line device-name[,device-name]",
(const void *) VAR_DEVICE},
@ -2414,6 +2440,14 @@ NegotiateSet(struct cmdargs const *arg)
cx->physical->link.lcp.cfg.chap80lm &= keep;
cx->physical->link.lcp.cfg.chap80lm |= add;
break;
case NEG_CHAP81:
cx->physical->link.lcp.cfg.chap81 &= keep;
cx->physical->link.lcp.cfg.chap81 |= add;
break;
case NEG_MPPE:
l->ccp.cfg.neg[CCP_NEG_MPPE] &= keep;
l->ccp.cfg.neg[CCP_NEG_MPPE] |= add;
break;
#endif
case NEG_DEFLATE:
l->ccp.cfg.neg[CCP_NEG_DEFLATE] &= keep;
@ -2517,6 +2551,12 @@ static struct cmdtab const NegotiateCommands[] = {
{"LANMan", "chap80lm", NegotiateSet, LOCAL_AUTH | LOCAL_CX,
"Microsoft (NT) CHAP", "accept|deny|disable|enable",
(const void *)NEG_CHAP80LM},
{"mschapv2", "chap81", NegotiateSet, LOCAL_AUTH | LOCAL_CX,
"Microsoft CHAP v2", "accept|deny|disable|enable",
(const void *)NEG_CHAP81},
{"mppe", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT,
"MPPE encryption", "accept|deny|disable|enable",
(const void *)NEG_MPPE},
#endif
{"deflate", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX_OPT,
"Deflate compression", "accept|deny|disable|enable",

View File

@ -49,6 +49,7 @@
#define AUTHLEN 100 /* Size of authname/authkey */
#define CHAPDIGESTLEN 100 /* Maximum chap digest */
#define CHAPCHALLENGELEN 48 /* Maximum chap challenge */
#define CHAPAUTHRESPONSELEN 48 /* Maximum chap authresponse (chap81) */
#define MAXARGS 40 /* How many args per config line */
#define NCP_IDLE_TIMEOUT 180 /* Drop all links */
#define CHOKED_TIMEOUT 120 /* Delete queued packets w/ blocked tun */

View File

@ -193,6 +193,8 @@ lcp_ReportStatus(struct cmdargs const *arg)
command_ShowNegval(lcp->cfg.chap80nt));
prompt_Printf(arg->prompt, " LANMan = %s\n",
command_ShowNegval(lcp->cfg.chap80lm));
prompt_Printf(arg->prompt, " CHAP81 = %s\n",
command_ShowNegval(lcp->cfg.chap81));
#endif
prompt_Printf(arg->prompt, " LQR = %s\n",
command_ShowNegval(lcp->cfg.lqr));
@ -244,6 +246,7 @@ lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l,
#ifdef HAVE_DES
lcp->cfg.chap80nt = NEG_ACCEPTED;
lcp->cfg.chap80lm = NEG_ACCEPTED;
lcp->cfg.chap81 = 0;
#endif
lcp->cfg.lqr = NEG_ACCEPTED;
lcp->cfg.pap = NEG_ACCEPTED;
@ -292,6 +295,9 @@ lcp_Setup(struct lcp *lcp, int openmode)
IsEnabled(lcp->cfg.chap80lm)) {
lcp->want_auth = PROTO_CHAP;
lcp->want_authtype = 0x80;
} else if (IsEnabled(lcp->cfg.chap81)) {
lcp->want_auth = PROTO_CHAP;
lcp->want_authtype = 0x81;
#endif
} else if (IsEnabled(lcp->cfg.pap)) {
lcp->want_auth = PROTO_PAP;
@ -733,6 +739,12 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
*dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
*dec->nakend++ = (unsigned char) PROTO_CHAP;
*dec->nakend++ = 0x80;
} else if (IsAccepted(lcp->cfg.chap81)) {
*dec->nakend++ = *cp;
*dec->nakend++ = 5;
*dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
*dec->nakend++ = (unsigned char) PROTO_CHAP;
*dec->nakend++ = 0x81;
#endif
} else
goto reqreject;
@ -747,6 +759,7 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
#ifdef HAVE_DES
|| (cp[4] == 0x80 && (IsAccepted(lcp->cfg.chap80nt) ||
(IsAccepted(lcp->cfg.chap80lm))))
|| (cp[4] == 0x81 && IsAccepted(lcp->cfg.chap81))
#endif
) {
lcp->his_auth = proto;
@ -755,9 +768,11 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
dec->ackend += length;
} else {
#ifndef HAVE_DES
if (cp[4] == 0x80)
if (cp[4] == 0x80) {
log_Printf(LogWARN, "CHAP 0x80 not available without DES\n");
else
} else if (cp[4] == 0x81) {
log_Printf(LogWARN, "CHAP 0x81 not available without DES\n");
} else
#endif
if (cp[4] != 0x05)
log_Printf(LogWARN, "%s not supported\n",
@ -777,6 +792,12 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
*dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
*dec->nakend++ = (unsigned char) PROTO_CHAP;
*dec->nakend++ = 0x80;
} else if (IsAccepted(lcp->cfg.chap81)) {
*dec->nakend++ = *cp;
*dec->nakend++ = 5;
*dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8);
*dec->nakend++ = (unsigned char) PROTO_CHAP;
*dec->nakend++ = 0x81;
#endif
} else if (IsAccepted(lcp->cfg.pap)) {
*dec->nakend++ = *cp;
@ -816,18 +837,24 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
IsEnabled(lcp->cfg.chap80lm))) {
lcp->want_auth = PROTO_CHAP;
lcp->want_authtype = 0x80;
} else if (cp[4] == 0x81 && IsEnabled(lcp->cfg.chap81)) {
lcp->want_auth = PROTO_CHAP;
lcp->want_authtype = 0x81;
#endif
} else {
#ifndef HAVE_DES
if (cp[4] == 0x80)
if (cp[4] == 0x80) {
log_Printf(LogLCP, "Peer will only send MSCHAP (not available"
" without DES)\n");
else
} else if (cp[4] == 0x81) {
log_Printf(LogLCP, "Peer will only send MSCHAPV2 (not available"
" without DES)\n");
} else
#endif
log_Printf(LogLCP, "Peer will only send %s (not %s)\n",
Auth2Nam(PROTO_CHAP, cp[4]),
#ifdef HAVE_DES
cp[4] == 0x80 ? "configured" :
(cp[4] == 0x80 || cp[4] == 0x81) ? "configured" :
#endif
"supported");
lcp->his_reject |= (1 << type);

View File

@ -83,6 +83,7 @@ struct lcp {
#ifdef HAVE_DES
unsigned chap80nt : 2; /* Microsoft (NT) CHAP */
unsigned chap80lm : 2; /* Microsoft (LANMan) CHAP */
unsigned chap81 : 2; /* Microsoft CHAP v2 */
#endif
unsigned lqr : 2; /* Link Quality Report */
unsigned pap : 2; /* Password Authentication protocol */

422
usr.sbin/ppp/mppe.c Normal file
View File

@ -0,0 +1,422 @@
/*-
* Copyright (c) 2000 Semen Ustimenko <semenu@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <sha.h>
#include <openssl/rc4.h>
#include "defs.h"
#include "mbuf.h"
#include "log.h"
#include "timer.h"
#include "fsm.h"
#include "lqr.h"
#include "hdlc.h"
#include "lcp.h"
#include "ccp.h"
#include "chap_ms.h"
#include "mppe.h"
/*
* Documentation:
*
* draft-ietf-pppext-mppe-04.txt
* draft-ietf-pppext-mppe-keys-02.txt
*/
struct mppe_state {
int cohnum;
int keylen; /* 8 or 16 bytes */
int keybits; /* 40, 56 or 128 bits */
char sesskey[MPPE_KEY_LEN];
char mastkey[MPPE_KEY_LEN];
RC4_KEY rc4key;
};
int MPPE_MasterKeyValid = 0;
char MPPE_MasterKey[MPPE_KEY_LEN];
static void
MPPEResetOutput(void *v)
{
log_Printf(LogCCP, "MPPE: Output channel reset\n");
}
void
MPPEReduceSessionKey(struct mppe_state *mp) {
switch(mp->keybits) {
case 40:
mp->sesskey[2] = 0x9e;
mp->sesskey[1] = 0x26;
case 56:
mp->sesskey[0] = 0xd1;
case 128:
}
}
void
MPPEKeyChange(struct mppe_state *mp) {
char InterimKey[MPPE_KEY_LEN];
RC4_KEY RC4Key;
GetNewKeyFromSHA(mp->mastkey, mp->sesskey, mp->keylen, InterimKey);
RC4_set_key(&RC4Key, mp->keylen, InterimKey);
RC4(&RC4Key, mp->keylen, InterimKey, mp->sesskey);
MPPEReduceSessionKey(mp);
}
static struct mbuf *
MPPEOutput(void *v, struct ccp *ccp, struct link *l, int pri, u_short *proto,
struct mbuf *mp)
{
struct mppe_state *mop = (struct mppe_state *)v;
struct mbuf *mo;
u_short nproto;
int ilen;
char *rp;
log_Printf(LogCCP, "MPPE: Output\n");
ilen = m_length(mp);
log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen);
if (*proto < 0x21 && *proto > 0xFA) {
log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n");
return mp;
}
log_DumpBp(LogDEBUG, "MPPE: Output: Encrypt packet:", mp);
/* Get mbuf for prefixes */
mo = m_get(4, MB_CCPOUT);
mo->m_next = mp;
/* Init RC4 keys */
RC4_set_key(&mop->rc4key, mop->keylen, mop->sesskey);
/* Set MPPE packet prefix */
rp = MBUF_CTOP(mo);
*(u_short *)rp = htons(0x9000 | mop->cohnum);
/* Save encrypted protocol number */
nproto = htons(*proto);
RC4(&mop->rc4key, 2, (char *)&nproto, rp + 2);
/* Encrypt main packet */
rp = MBUF_CTOP(mp);
RC4(&mop->rc4key, ilen, rp, rp);
/* Rotate keys */
MPPEKeyChange(mop);
mop->cohnum ++; mop->cohnum &= 0xFFF;
/* Chage protocol number */
*proto = ccp_Proto(ccp);
log_Printf(LogDEBUG, "MPPE: Output: Encrypted: Proto %02x (%d bytes)\n", *proto, m_length(mo));
return mo;
}
static void
MPPEResetInput(void *v)
{
log_Printf(LogCCP, "MPPE: Input channel reset\n");
}
static struct mbuf *
MPPEInput(void *v, struct ccp *ccp, u_short *proto, struct mbuf *mp)
{
struct mppe_state *mip = (struct mppe_state *)v;
u_short prefix;
char *rp;
int ilen;
log_Printf(LogCCP, "MPPE: Input\n");
ilen = m_length(mp);
log_Printf(LogDEBUG, "MPPE: Input: Proto %02x (%d bytes)\n", *proto, ilen);
log_DumpBp(LogDEBUG, "MPPE: Input: Packet:", mp);
mp = mbuf_Read(mp, &prefix, 2);
prefix = ntohs(prefix);
if ((prefix & 0xF000) != 0x9000) {
log_Printf(LogERROR, "MPPE: Input: Invalid packet\n");
m_freem(mp);
return NULL;
}
prefix &= 0xFFF;
while (prefix != mip->cohnum) {
MPPEKeyChange(mip);
mip->cohnum ++; mip->cohnum &= 0xFFF;
}
RC4_set_key(&mip->rc4key, mip->keylen, mip->sesskey);
mp = mbuf_Read(mp, proto, 2);
RC4(&mip->rc4key, 2, (char *)proto, (char *)proto);
*proto = ntohs(*proto);
rp = MBUF_CTOP(mp);
RC4(&mip->rc4key, m_length(mp), rp, rp);
log_Printf(LogDEBUG, "MPPE: Input: Decrypted: Proto %02x (%d bytes)\n", *proto, m_length(mp));
log_DumpBp(LogDEBUG, "MPPE: Input: Decrypted: Packet:", mp);
return mp;
}
static void
MPPEDictSetup(void *v, struct ccp *ccp, u_short proto, struct mbuf *mi)
{
log_Printf(LogCCP, "MPPE: DictSetup\n");
}
static const char *
MPPEDispOpts(struct lcp_opt *o)
{
static char buf[32];
sprintf(buf, "value 0x%08x", (int)ntohl(*(u_int32_t *)(o->data)));
return buf;
}
static void
MPPEInitOptsOutput(struct lcp_opt *o, const struct ccp_config *cfg)
{
u_long val;
o->len = 6;
log_Printf(LogCCP, "MPPE: InitOptsOutput\n");
if (!MPPE_MasterKeyValid) {
log_Printf(LogWARN, "MPPE: MasterKey is invalid, MPPE is capable only with CHAP81 authentication\n");
*(u_int32_t *)o->data = htonl(0x0);
return;
}
val = 0x1000000;
switch(cfg->mppe.keybits) {
case 128:
val |= 0x40; break;
case 56:
val |= 0x80; break;
case 40:
val |= 0x20; break;
}
*(u_int32_t *)o->data = htonl(val);
}
static int
MPPESetOptsOutput(struct lcp_opt *o)
{
u_long *p = (u_long *)(o->data);
u_long val = ntohl(*p);
log_Printf(LogCCP, "MPPE: SetOptsOutput\n");
if (!MPPE_MasterKeyValid) {
if (*p != 0x0) {
*p = 0x0;
return MODE_NAK;
} else {
return MODE_ACK;
}
}
if (val == 0x01000020 ||
val == 0x01000040 ||
val == 0x01000080)
return MODE_ACK;
return MODE_NAK;
}
static int
MPPESetOptsInput(struct lcp_opt *o, const struct ccp_config *cfg)
{
u_long *p = (u_long *)(o->data);
u_long val = ntohl(*p);
u_long mval;
log_Printf(LogCCP, "MPPE: SetOptsInput\n");
if (!MPPE_MasterKeyValid) {
if (*p != 0x0) {
*p = 0x0;
return MODE_NAK;
} else {
return MODE_ACK;
}
}
mval = 0x01000000;
switch(cfg->mppe.keybits) {
case 128:
mval |= 0x40; break;
case 56:
mval |= 0x80; break;
case 40:
mval |= 0x20; break;
}
if (val == mval)
return MODE_ACK;
*p = htonl(mval);
return MODE_NAK;
}
static void *
MPPEInitInput(struct lcp_opt *o)
{
struct mppe_state *mip;
u_int32_t val = ntohl(*(unsigned long *)o->data);
log_Printf(LogCCP, "MPPE: InitInput\n");
if (!MPPE_MasterKeyValid) {
log_Printf(LogERROR, "MPPE: InitInput: MasterKey is invalid!!!!\n");
return NULL;
}
mip = malloc(sizeof(*mip));
memset(mip, 0, sizeof(*mip));
if (val & 0x20) { /* 40-bits */
mip->keylen = 8;
mip->keybits = 40;
} else if (val & 0x80) { /* 56-bits */
mip->keylen = 8;
mip->keybits = 56;
} else { /* 128-bits */
mip->keylen = 16;
mip->keybits = 128;
}
log_Printf(LogDEBUG, "MPPE: InitInput: %d-bits\n", mip->keybits);
GetAsymetricStartKey(MPPE_MasterKey, mip->mastkey, mip->keylen, 0, 0);
GetNewKeyFromSHA(mip->mastkey, mip->mastkey, mip->keylen, mip->sesskey);
MPPEReduceSessionKey(mip);
MPPEKeyChange(mip);
mip->cohnum = 0;
return mip;
}
static void *
MPPEInitOutput(struct lcp_opt *o)
{
struct mppe_state *mop;
u_int32_t val = ntohl(*(unsigned long *)o->data);
log_Printf(LogCCP, "MPPE: InitOutput\n");
if (!MPPE_MasterKeyValid) {
log_Printf(LogERROR, "MPPE: InitOutput: MasterKey is invalid!!!!\n");
return NULL;
}
mop = malloc(sizeof(*mop));
memset(mop, 0, sizeof(*mop));
if (val & 0x20) { /* 40-bits */
mop->keylen = 8;
mop->keybits = 40;
} else if (val & 0x80) { /* 56-bits */
mop->keylen = 8;
mop->keybits = 56;
} else { /* 128-bits */
mop->keylen = 16;
mop->keybits = 128;
}
log_Printf(LogDEBUG, "MPPE: InitOutput: %d-bits\n", mop->keybits);
GetAsymetricStartKey(MPPE_MasterKey, mop->mastkey, mop->keylen, 1, 0);
GetNewKeyFromSHA(mop->mastkey, mop->mastkey, mop->keylen, mop->sesskey);
MPPEReduceSessionKey(mop);
MPPEKeyChange(mop);
mop->cohnum = 0;
return mop;
}
static void
MPPETermInput(void *v)
{
log_Printf(LogCCP, "MPPE: TermInput\n");
free(v);
}
static void
MPPETermOutput(void *v)
{
log_Printf(LogCCP, "MPPE: TermOutput\n");
free(v);
}
const struct ccp_algorithm MPPEAlgorithm = {
TY_MPPE,
CCP_NEG_MPPE,
MPPEDispOpts,
{
MPPESetOptsInput,
MPPEInitInput,
MPPETermInput,
MPPEResetInput,
MPPEInput,
MPPEDictSetup
},
{
MPPEInitOptsOutput,
MPPESetOptsOutput,
MPPEInitOutput,
MPPETermOutput,
MPPEResetOutput,
MPPEOutput
},
};

32
usr.sbin/ppp/mppe.h Normal file
View File

@ -0,0 +1,32 @@
/*-
* Copyright (c) 2000 Semen Ustimenko <semenu@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#define MPPE_KEY_LEN 16
extern const struct ccp_algorithm MPPEAlgorithm;
extern int MPPE_MasterKeyValid;
extern char MPPE_MasterKey[];

View File

@ -243,7 +243,7 @@ In direct mode,
acts as server which accepts incoming
.Em PPP
connections on stdin/stdout.
.It Supports PAP and CHAP (rfc 1994) authentication.
.It Supports PAP and CHAP (rfc 1994, 2433 and 2759) authentication.
With PAP or CHAP, it is possible to skip the Unix style
.Xr login 1
procedure, and use the
@ -353,6 +353,14 @@ It is possible to configure
.Nm
to open more than one physical connection to the peer, combining the
bandwidth of all links for better throughput.
.It Supports MPPE (draft-ietf-pppext-mppe)
MPPE is Microsoft Point to Point Encryption scheme. It is possible to configure
.Nm
to participate in Microsoft's Windows VPN. For now,
.Nm
can only get encryption keys from CHAP 81 authentication.
.Nm
must be compiled with DES for MPPE to operate.
.El
.Sh PERMISSIONS
.Nm
@ -2654,8 +2662,20 @@ level, and any appropriate
.Dq reconnect
values are honoured as if the peer were responsible for dropping the
connection.
.It mppe
Default: Disabled and Denied.
This is Microsoft Point to Point Encryption scheme. MPPE key size can be
40-, 56- and 128-bits. Refer to
.Dq set mppe
command.
.It MSChapV2|chap81
Default: Disabled and Denied.
It is very similar to standard CHAP (type 0x05)
except that it issues challenges of a fixed 16 bytes in length and uses a
combination of MD4, SHA-1 and DES to encrypt the challenge rather than using the
standard MD5 mechanism.
.It MSChap|chap80nt
Default: Disabled and Accepted.
Default: Disabled and Denied.
The use of this authentication protocol
is discouraged as it partially violates the authentication protocol by
implementing two different mechanisms (LANMan & NT) under the guise of
@ -4738,6 +4758,8 @@ This will allow
to do the necessary address translations to enable the process that
triggers the connection to connect once the link is up despite the
peer assigning us a new (dynamic) IP address.
.It set mppe {40|56|128}
This option selects particular key length. Default is 128.
.It set mrru Op Ar value
Setting this option enables Multi-link PPP negotiations, also known as
Multi-link Protocol or MP.

View File

@ -243,7 +243,7 @@ In direct mode,
acts as server which accepts incoming
.Em PPP
connections on stdin/stdout.
.It Supports PAP and CHAP (rfc 1994) authentication.
.It Supports PAP and CHAP (rfc 1994, 2433 and 2759) authentication.
With PAP or CHAP, it is possible to skip the Unix style
.Xr login 1
procedure, and use the
@ -353,6 +353,14 @@ It is possible to configure
.Nm
to open more than one physical connection to the peer, combining the
bandwidth of all links for better throughput.
.It Supports MPPE (draft-ietf-pppext-mppe)
MPPE is Microsoft Point to Point Encryption scheme. It is possible to configure
.Nm
to participate in Microsoft's Windows VPN. For now,
.Nm
can only get encryption keys from CHAP 81 authentication.
.Nm
must be compiled with DES for MPPE to operate.
.El
.Sh PERMISSIONS
.Nm
@ -2654,8 +2662,20 @@ level, and any appropriate
.Dq reconnect
values are honoured as if the peer were responsible for dropping the
connection.
.It mppe
Default: Disabled and Denied.
This is Microsoft Point to Point Encryption scheme. MPPE key size can be
40-, 56- and 128-bits. Refer to
.Dq set mppe
command.
.It MSChapV2|chap81
Default: Disabled and Denied.
It is very similar to standard CHAP (type 0x05)
except that it issues challenges of a fixed 16 bytes in length and uses a
combination of MD4, SHA-1 and DES to encrypt the challenge rather than using the
standard MD5 mechanism.
.It MSChap|chap80nt
Default: Disabled and Accepted.
Default: Disabled and Denied.
The use of this authentication protocol
is discouraged as it partially violates the authentication protocol by
implementing two different mechanisms (LANMan & NT) under the guise of
@ -4738,6 +4758,8 @@ This will allow
to do the necessary address translations to enable the process that
triggers the connection to connect once the link is up despite the
peer assigning us a new (dynamic) IP address.
.It set mppe {40|56|128}
This option selects particular key length. Default is 128.
.It set mrru Op Ar value
Setting this option enables Multi-link PPP negotiations, also known as
Multi-link Protocol or MP.