]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/chap_ms.c
Fix include paths for plugins to use the public API of pppd
[ppp.git] / pppd / chap_ms.c
index 016b42e0c10ee9a845a3e96ad8aa55dcb2b0464c..e7e8cbadfc2ff71333c11e25e83d384a3e3f42fe 100644 (file)
@@ -76,7 +76,9 @@
 
 #define RCSID  "$Id: chap_ms.c,v 1.38 2007/12/01 20:10:51 carlsonj Exp $"
 
-#ifdef CHAPMS
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "sha1.h"
 #include "pppcrypt.h"
 #include "magic.h"
+#include "mppe.h"
 
-static const char rcsid[] = RCSID;
-
-
-static void    ascii2unicode __P((char[], int, u_char[]));
-static void    NTPasswordHash __P((u_char *, int, u_char[MD4_SIGNATURE_SIZE]));
-static void    ChallengeResponse __P((u_char *, u_char *, u_char[24]));
-static void    ChapMS_NT __P((u_char *, char *, int, u_char[24]));
-static void    ChapMS2_NT __P((u_char *, u_char[16], char *, char *, int,
-                               u_char[24]));
-static void    GenerateAuthenticatorResponsePlain
-                       __P((char*, int, u_char[24], u_char[16], u_char *,
-                            char *, u_char[41]));
-#ifdef MSLANMAN
-static void    ChapMS_LANMan __P((u_char *, char *, int, u_char *));
+#ifdef UNIT_TEST
+#undef PPP_WITH_MPPE
 #endif
 
-#ifdef MPPE
-static void    Set_Start_Key __P((u_char *, char *, int));
-static void    SetMasterKeys __P((char *, int, u_char[24], int));
+static void    ascii2unicode (char[], int, u_char[]);
+static void    NTPasswordHash (u_char *, int, u_char[MD4_SIGNATURE_SIZE]);
+static void    ChallengeResponse (u_char *, u_char *, u_char[24]);
+static void    ChapMS_NT (u_char *, char *, int, u_char[24]);
+static void    ChapMS2_NT (u_char *, u_char[16], char *, char *, int,
+                               u_char[24]);
+static void    GenerateAuthenticatorResponsePlain
+                       (char*, int, u_char[24], u_char[16], u_char *,
+                        char *, u_char[41]);
+#ifdef PPP_WITH_MSLANMAN
+static void    ChapMS_LANMan (u_char *, char *, int, u_char *);
 #endif
 
-#ifdef MSLANMAN
+#ifdef PPP_WITH_MSLANMAN
 bool   ms_lanman = 0;          /* Use LanMan password instead of NT */
                                /* Has meaning only with MS-CHAP challenges */
 #endif
 
-#ifdef MPPE
-u_char mppe_send_key[MPPE_MAX_KEY_LEN];
-u_char mppe_recv_key[MPPE_MAX_KEY_LEN];
-int mppe_keys_set = 0;         /* Have the MPPE keys been set? */
-
+#ifdef PPP_WITH_MPPE
 #ifdef DEBUGMPPEKEY
 /* For MPPE debug */
 /* Use "[]|}{?/><,`!2&&(" (sans quotes) for RFC 3079 MS-CHAPv2 test value */
@@ -142,7 +137,7 @@ static char *mschap2_peer_challenge = NULL;
  * Command-line options.
  */
 static option_t chapms_option_list[] = {
-#ifdef MSLANMAN
+#ifdef PPP_WITH_MSLANMAN
        { "ms-lanman", o_bool, &ms_lanman,
          "Use LanMan passwd when using MS-CHAP", 1 },
 #endif
@@ -200,7 +195,7 @@ chapms_verify_response(int id, char *name,
        if (response_len != MS_CHAP_RESPONSE_LEN)
                goto bad;
 
-#ifndef MSLANMAN
+#ifndef PPP_WITH_MSLANMAN
        if (!response[MS_CHAP_USENT]) {
                /* Should really propagate this into the error packet. */
                notice("Peer request for LANMAN auth not supported");
@@ -211,7 +206,7 @@ chapms_verify_response(int id, char *name,
        /* Generate the expected response. */
        ChapMS(challenge, (char *)secret, secret_len, md);
 
-#ifdef MSLANMAN
+#ifdef PPP_WITH_MSLANMAN
        /* Determine which part of response to verify against */
        if (!response[MS_CHAP_USENT])
                diff = memcmp(&response[MS_CHAP_LANMANRESP],
@@ -382,7 +377,7 @@ chapms2_make_response(unsigned char *response, int id, char *our_name,
                      unsigned char *private)
 {
        const struct chapms2_response_cache_entry *cache_entry;
-       unsigned char auth_response[MS_AUTH_RESPONSE_LENGTH];
+       unsigned char auth_response[MS_AUTH_RESPONSE_LENGTH+1];
 
        challenge++;    /* skip length, should be 16 */
        *response++ = MS_CHAP2_RESPONSE_LEN;
@@ -424,6 +419,8 @@ chapms2_check_success(int id, unsigned char *msg, int len)
        len -= MS_AUTH_RESPONSE_LENGTH;
        if ((len >= 3) && !strncmp((char *)msg, " M=", 3)) {
                msg += 3; /* Eat the delimiter */
+       } else  if ((len >= 2) && !strncmp((char *)msg, "M=", 2)) {
+               msg += 2; /* Eat the delimiter */
        } else if (len) {
                /* Packet has extra text which does not begin " M=" */
                error("MS-CHAPv2 Success packet is badly formed.");
@@ -574,7 +571,7 @@ ascii2unicode(char ascii[], int ascii_len, u_char unicode[])
 static void
 NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE])
 {
-#ifdef __NetBSD__
+#if defined(__NetBSD__) || !defined(USE_MD4)
     /* NetBSD uses the libc md4 routines which take bytes instead of bits */
     int                        mdlen = secret_len;
 #else
@@ -583,12 +580,14 @@ NTPasswordHash(u_char *secret, int secret_len, u_char hash[MD4_SIGNATURE_SIZE])
     MD4_CTX            md4Context;
 
     MD4Init(&md4Context);
-    /* MD4Update can take at most 64 bytes at a time */
+#if !defined(USE_MD4)
+    /* Internal MD4Update can take at most 64 bytes at a time */
     while (mdlen > 512) {
        MD4Update(&md4Context, secret, 512);
        secret += 64;
        mdlen -= 512;
     }
+#endif
     MD4Update(&md4Context, secret, mdlen);
     MD4Final(hash, &md4Context);
 
@@ -625,7 +624,7 @@ ChapMS2_NT(u_char *rchallenge, u_char PeerChallenge[16], char *username,
     ChallengeResponse(Challenge, PasswordHash, NTResponse);
 }
 
-#ifdef MSLANMAN
+#ifdef PPP_WITH_MSLANMAN
 static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
 
 static void
@@ -717,29 +716,7 @@ GenerateAuthenticatorResponsePlain
 }
 
 
-#ifdef MPPE
-/*
- * Set mppe_xxxx_key from the NTPasswordHashHash.
- * RFC 2548 (RADIUS support) requires us to export this function (ugh).
- */
-void
-mppe_set_keys(u_char *rchallenge, u_char PasswordHashHash[MD4_SIGNATURE_SIZE])
-{
-    SHA1_CTX   sha1Context;
-    u_char     Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
-
-    SHA1_Init(&sha1Context);
-    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
-    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
-    SHA1_Update(&sha1Context, rchallenge, 8);
-    SHA1_Final(Digest, &sha1Context);
-
-    /* Same key in both directions. */
-    BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
-    BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
-
-    mppe_keys_set = 1;
-}
+#ifdef PPP_WITH_MPPE
 
 /*
  * Set mppe_xxxx_key from MS-CHAP credentials. (see RFC 3079)
@@ -756,104 +733,7 @@ Set_Start_Key(u_char *rchallenge, char *secret, int secret_len)
     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
 
-    mppe_set_keys(rchallenge, PasswordHashHash);
-}
-
-/*
- * Set mppe_xxxx_key from MS-CHAPv2 credentials. (see RFC 3079)
- *
- * This helper function used in the Winbind module, which gets the
- * NTHashHash from the server.
- */
-void
-mppe_set_keys2(u_char PasswordHashHash[MD4_SIGNATURE_SIZE],
-              u_char NTResponse[24], int IsServer)
-{
-    SHA1_CTX   sha1Context;
-    u_char     MasterKey[SHA1_SIGNATURE_SIZE]; /* >= MPPE_MAX_KEY_LEN */
-    u_char     Digest[SHA1_SIGNATURE_SIZE];    /* >= MPPE_MAX_KEY_LEN */
-
-    u_char SHApad1[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 };
-    u_char SHApad2[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 };
-
-    /* "This is the MPPE Master Key" */
-    u_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 };
-    /* "On the client side, this is the send key; "
-       "on the server side, it is the receive key." */
-    u_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 };
-    /* "On the client side, this is the receive key; "
-       "on the server side, it is the send key." */
-    u_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 };
-    u_char *s;
-
-    SHA1_Init(&sha1Context);
-    SHA1_Update(&sha1Context, PasswordHashHash, MD4_SIGNATURE_SIZE);
-    SHA1_Update(&sha1Context, NTResponse, 24);
-    SHA1_Update(&sha1Context, Magic1, sizeof(Magic1));
-    SHA1_Final(MasterKey, &sha1Context);
-
-    /*
-     * generate send key
-     */
-    if (IsServer)
-       s = Magic3;
-    else
-       s = Magic2;
-    SHA1_Init(&sha1Context);
-    SHA1_Update(&sha1Context, MasterKey, 16);
-    SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
-    SHA1_Update(&sha1Context, s, 84);
-    SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
-    SHA1_Final(Digest, &sha1Context);
-
-    BCOPY(Digest, mppe_send_key, sizeof(mppe_send_key));
-
-    /*
-     * generate recv key
-     */
-    if (IsServer)
-       s = Magic2;
-    else
-       s = Magic3;
-    SHA1_Init(&sha1Context);
-    SHA1_Update(&sha1Context, MasterKey, 16);
-    SHA1_Update(&sha1Context, SHApad1, sizeof(SHApad1));
-    SHA1_Update(&sha1Context, s, 84);
-    SHA1_Update(&sha1Context, SHApad2, sizeof(SHApad2));
-    SHA1_Final(Digest, &sha1Context);
-
-    BCOPY(Digest, mppe_recv_key, sizeof(mppe_recv_key));
-
-    mppe_keys_set = 1;
+    mppe_set_chapv1(rchallenge, PasswordHashHash);
 }
 
 /*
@@ -869,10 +749,10 @@ SetMasterKeys(char *secret, int secret_len, u_char NTResponse[24], int IsServer)
     ascii2unicode(secret, secret_len, unicodePassword);
     NTPasswordHash(unicodePassword, secret_len * 2, PasswordHash);
     NTPasswordHash(PasswordHash, sizeof(PasswordHash), PasswordHashHash);
-    mppe_set_keys2(PasswordHashHash, NTResponse, IsServer);
+    mppe_set_chapv2(PasswordHashHash, NTResponse, IsServer);
 }
 
-#endif /* MPPE */
+#endif /* PPP_WITH_MPPE */
 
 
 void
@@ -883,7 +763,7 @@ ChapMS(u_char *rchallenge, char *secret, int secret_len,
 
     ChapMS_NT(rchallenge, secret, secret_len, &response[MS_CHAP_NTRESP]);
 
-#ifdef MSLANMAN
+#ifdef PPP_WITH_MSLANMAN
     ChapMS_LANMan(rchallenge, secret, secret_len,
                  &response[MS_CHAP_LANMANRESP]);
 
@@ -893,7 +773,7 @@ ChapMS(u_char *rchallenge, char *secret, int secret_len,
     response[MS_CHAP_USENT] = 1;
 #endif
 
-#ifdef MPPE
+#ifdef PPP_WITH_MPPE
     Set_Start_Key(rchallenge, secret, secret_len);
 #endif
 }
@@ -938,44 +818,12 @@ ChapMS2(u_char *rchallenge, u_char *PeerChallenge,
                                       &response[MS_CHAP2_PEER_CHALLENGE],
                                       rchallenge, user, authResponse);
 
-#ifdef MPPE
+#ifdef PPP_WITH_MPPE
     SetMasterKeys(secret, secret_len,
                  &response[MS_CHAP2_NTRESP], authenticator);
 #endif
 }
 
-#ifdef MPPE
-/*
- * Set MPPE options from plugins.
- */
-void
-set_mppe_enc_types(int policy, int types)
-{
-    /* Early exit for unknown policies. */
-    if (policy != MPPE_ENC_POL_ENC_ALLOWED ||
-       policy != MPPE_ENC_POL_ENC_REQUIRED)
-       return;
-
-    /* Don't modify MPPE if it's optional and wasn't already configured. */
-    if (policy == MPPE_ENC_POL_ENC_ALLOWED && !ccp_wantoptions[0].mppe)
-       return;
-
-    /*
-     * Disable undesirable encryption types.  Note that we don't ENABLE
-     * any encryption types, to avoid overriding manual configuration.
-     */
-    switch(types) {
-       case MPPE_ENC_TYPES_RC4_40:
-           ccp_wantoptions[0].mppe &= ~MPPE_OPT_128;   /* disable 128-bit */
-           break;
-       case MPPE_ENC_TYPES_RC4_128:
-           ccp_wantoptions[0].mppe &= ~MPPE_OPT_40;    /* disable 40-bit */
-           break;
-       default:
-           break;
-    }
-}
-#endif /* MPPE */
 
 static struct chap_digest_type chapms_digest = {
        CHAP_MICROSOFT,         /* code */
@@ -995,6 +843,7 @@ static struct chap_digest_type chapms2_digest = {
        chapms_handle_failure,
 };
 
+#ifndef UNIT_TEST
 void
 chapms_init(void)
 {
@@ -1002,5 +851,94 @@ chapms_init(void)
        chap_register_digest(&chapms2_digest);
        add_options(chapms_option_list);
 }
+#else
+
+#include <time.h>
+
+int debug = 1;
+int error_count = 0;
+int unsuccess = 0;
+
+void random_bytes(unsigned char *bytes, int len)
+{
+    int i = 0;
+    srand(time(NULL));
+    while (i < len) {
+        bytes[i++] = (unsigned char) rand();
+    }
+}
+
+
+int test_chap_v1(void) {
+    char *secret = "TestPassword";
+
+    unsigned char challenge[8] = {
+        0x6c, 0x8d, 0x4b, 0xa1, 0x2b, 0x5c, 0x13, 0xc3
+    };
+    unsigned char response[MS_CHAP_RESPONSE_LEN] = {
+    };
+    unsigned char result[MS_CHAP_RESPONSE_LEN] = {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+        0x91, 0x09, 0x61, 0x5a, 0x0c, 0xac, 0xac, 0x55,
+        0x1f, 0x60, 0xe2, 0x9c, 0x00, 0xac, 0x24, 0xda,
+        0x6e, 0xa5, 0x7b, 0xdb, 0x1d, 0x6a, 0x17, 0xc5,
+        0x01
+    };
+
+    ChapMS(challenge, secret, strlen(secret), response);
+    return memcmp(response, result, MS_CHAP_RESPONSE_LEN);
+}
+
+int test_chap_v2(void) {
+    char *secret = "clientPass";
+    char *name = "User";
+
+    char saresponse[MS_AUTH_RESPONSE_LENGTH+1];
+    char *saresult = "407A5589115FD0D6209F510FE9C04566932CDA56";
+
+    unsigned char authenticator[16] = {
+        0x5B, 0x5D, 0x7C, 0x7D, 0x7B, 0x3F, 0x2F, 0x3E,
+        0x3C, 0x2C, 0x60, 0x21, 0x32, 0x26, 0x26, 0x28
+    };
+    unsigned char peerchallenge[16] = {
+        0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A,
+        0x28, 0x29, 0x5F, 0x2B, 0x3A, 0x33, 0x7C, 0x7E
+    };
+    unsigned char result[MS_CHAP_NTRESP_LEN] = {
+        0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E,
+        0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54,
+        0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF
+    };
+
+    unsigned char response[MS_CHAP2_RESPONSE_LEN] = {
+    };
+
+       ChapMS2(authenticator, peerchallenge, name,
+               secret, strlen(secret), response,
+               (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR);
+
+    return memcmp(&response[MS_CHAP2_NTRESP], result, MS_CHAP2_NTRESP_LEN) ||
+        strncmp(saresponse, saresult, MS_AUTH_RESPONSE_LENGTH);
+}
+
+int main(int argc, char *argv[]) {
+
+    if (test_chap_v1()) {
+        printf("CHAPv1 failed\n");
+        return -1;
+    }
+
+    if (test_chap_v2()) {
+        printf("CHAPv2 failed\n");
+        return -1;
+    }
+
+    printf("Success\n");
+    return 0;
+}
+
+#endif  /* UNIT_TEST */
 
-#endif /* CHAPMS */