]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
v4: Convert %(mschap: ) to new xlat API (#4082)
authorNick Porter <nick@portercomputing.co.uk>
Fri, 21 May 2021 13:05:48 +0000 (14:05 +0100)
committerGitHub <noreply@github.com>
Fri, 21 May 2021 13:05:48 +0000 (15:05 +0200)
* Convert %(mschap: ) to new xlat API

* Add extra safety checks to %(mschap: ) attribute parsing

* Add tests for %(mschap: ) xlat

* Update docs for new syntax of %(mschap: )

* Update other code use of %(mschap: )

doc/antora/modules/howto/pages/modules/mschap/index.adoc
doc/antora/modules/raddb/pages/mods-available/mschap.adoc
doc/antora/modules/raddb/pages/mods-available/ntlm_auth.adoc
raddb/mods-available/mschap
raddb/mods-available/ntlm_auth
src/modules/rlm_mschap/rlm_mschap.c
src/modules/rlm_pap/rlm_pap.c
src/tests/keywords/mschap [new file with mode: 0644]
src/tests/keywords/radius.conf

index 180eb000dca0d9f56260829999ab4c09f1244980..192d8ae34de11454d97f354c9072efdf247ba5d0 100644 (file)
@@ -43,7 +43,7 @@ several options for the arguments, in particular username and domain:
 
 * `–username=%{User-Name}` - this will fail if you’re using realms or
 host-based auth
-* `–username=%{mschap:User-Name}` - this will fail if using using suffix
+* `–username=%(mschap:User-Name)` - this will fail if using using suffix
 i.e. user@domain
 
 You’ll need to fit this to your local needs.
@@ -81,8 +81,8 @@ mschap {
 
     # initial data to send
     # this MUST be supplied
-    ntlm_auth_username = "username: %{mschap:User-Name}"
-    ntlm_auth_domain = "nt-domain: %{%{mschap:NT-Domain}:-YOURDOMAIN}"
+    ntlm_auth_username = "username: %(mschap:User-Name)"
+    ntlm_auth_domain = "nt-domain: %{%(mschap:NT-Domain):-YOURDOMAIN}"
 
     # Or, you could try:
     ntlm_auth_username = "full-username: %{User-Name}"
index 5b5fd3fa4ff29052051ee7bbda5433be6a507366..af5ddc37bccbe0e74eb990f3de347215a7dda951 100644 (file)
@@ -102,7 +102,7 @@ module will do the authentication itself, without calling `ntlm_auth`.
 
 You can also try setting the user name as:
 
-`... --username=%{mschap:User-Name} ...`
+`... --username=%(mschap:User-Name) ...`
 
 In that case, the `mschap` module will look at the `link:https://freeradius.org/rfc/rfc2865.html#User-Name[User-Name]`
 attribute, and do prefix/suffix checks in order to obtain the _best_
@@ -320,11 +320,11 @@ mschap {
 #      require_encryption = yes
 #      require_strong = yes
 #      with_ntdomain_hack = no
-#      ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%{mschap:Challenge}:-00} --nt-response=%{%{mschap:NT-Response}:-00}"
+#      ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%(mschap:Challenge):-00} --nt-response=%{%(mschap:NT-Response):-00}"
 #      ntlm_auth_timeout = 10
        winbind {
-#              username = "%{mschap:User-Name}"
-#              domain = "%{mschap:NT-Domain}"
+#              username = "%(mschap:User-Name)"
+#              domain = "%(mschap:NT-Domain)"
 #              retry_with_normalised_username = no
        }
        pool {
@@ -340,9 +340,9 @@ mschap {
        }
        passchange {
 #              ntlm_auth = "/usr/bin/ntlm_auth --helper-protocol=ntlm-change-password-1"
-#              ntlm_auth_username = "username: %{mschap:User-Name}"
-#              ntlm_auth_domain = "nt-domain: %{mschap:NT-Domain}"
-#              local_cpw = "%{exec:/path/to/script %{mschap:User-Name} %{MS-CHAP-New-Password.Cleartext}}"
+#              ntlm_auth_username = "username: %(mschap:User-Name)"
+#              ntlm_auth_domain = "nt-domain: %(mschap:NT-Domain)"
+#              local_cpw = "%{exec:/path/to/script %(mschap:User-Name) %{MS-CHAP-New-Password.Cleartext}}"
 #              local_cpw = "%{sql:UPDATE radcheck set value='%{MS-CHAP-New-NT-Password}' where username='%{User-Name}' and attribute='NT-Password'}"
        }
 #      use_open_directory = yes
index be978d9bfb18aba2c9167a34169cedc71b3cae31..a7bc565cf93ca31fe90872c69c83cae981e026ea 100644 (file)
@@ -39,6 +39,6 @@ local system.  The other fields can be left alone.
 #      http://deployingradius.com/documents/configuration/active_directory.html
 exec ntlm_auth {
        wait = yes
-       program = "/path/to/ntlm_auth --request-nt-key --domain=MYDOMAIN --username=%{mschap:User-Name} --password=%{User-Password}"
+       program = "/path/to/ntlm_auth --request-nt-key --domain=MYDOMAIN --username=%(mschap:User-Name) --password=%{User-Password}"
 }
 ```
index f1764a3e698eddbfdf0b4d274cdde6dedbffb47c..905bfa59777d09fc89406b28200bda2d207fb0cf 100644 (file)
@@ -111,7 +111,7 @@ mschap {
        #
        #  You can also try setting the user name as:
        #
-       #  `... --username=%{mschap:User-Name} ...`
+       #  `... --username=%(mschap:User-Name) ...`
        #
        #  In that case, the `mschap` module will look at the `User-Name`
        #  attribute, and do prefix/suffix checks in order to obtain the _best_
@@ -126,7 +126,7 @@ mschap {
        #  WARNING: Be VERY careful when editing the following line!
        #  Change the path, and ideally nothing else.
        #
-#      ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%{mschap:Challenge}:-00} --nt-response=%{%{mschap:NT-Response}:-00}"
+#      ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%(mschap:Challenge):-00} --nt-response=%{%(mschap:NT-Response):-00}"
 
        #
        #  ntlm_auth_timeout:: Time to wait for `ntlm_auth` to run.
@@ -163,8 +163,8 @@ mschap {
                #  later to be installed. Make sure that `ntlm_auth` above is
                #  commented out.
                #
-#              username = "%{mschap:User-Name}"
-#              domain = "%{mschap:NT-Domain}"
+#              username = "%(mschap:User-Name)"
+#              domain = "%(mschap:NT-Domain)"
 
                #
                #  retry_with_normalised_username::
@@ -309,8 +309,8 @@ mschap {
                #  Uncomment the three lines below, and change the path to `ntlm_auth.
                #
 #              ntlm_auth = "/usr/bin/ntlm_auth --helper-protocol=ntlm-change-password-1"
-#              ntlm_auth_username = "username: %{mschap:User-Name}"
-#              ntlm_auth_domain = "nt-domain: %{mschap:NT-Domain}"
+#              ntlm_auth_username = "username: %(mschap:User-Name)"
+#              ntlm_auth_domain = "nt-domain: %(mschap:NT-Domain)"
 
                #
                #  local_cpw::
@@ -322,7 +322,7 @@ mschap {
                #
                #  TIP: We give both examples here, but *only one should be used*.
                #
-#              local_cpw = "%{exec:/path/to/script %{mschap:User-Name} %{MS-CHAP-New-Password.Cleartext}}"
+#              local_cpw = "%{exec:/path/to/script %(mschap:User-Name) %{MS-CHAP-New-Password.Cleartext}}"
 #              local_cpw = "%{sql:UPDATE radcheck set value='%{MS-CHAP-New-NT-Password}' where username='%{User-Name}' and attribute='NT-Password'}"
        }
 
index 7e0ada9ba4e4cdd701bef9949ed8e6cee5ef803d..3806a5e46fc50f8d17416963efc83cd12e8a49a5 100644 (file)
@@ -38,5 +38,5 @@ exec ntlm_auth {
        #  You will need to edit the path and domain to match your
        #  local system.  The other fields can be left alone.
        #
-       program = "/path/to/ntlm_auth --request-nt-key --domain=MYDOMAIN --username=%{mschap:User-Name} --password=%{User-Password}"
+       program = "/path/to/ntlm_auth --request-nt-key --domain=MYDOMAIN --username=%(mschap:User-Name) --password=%{User-Password}"
 }
index f5ea4e2f659c7c93fe607ecf978524da5068f38e..252a365d71923f09fdd2f22e91045ebbbddd9b58 100644 (file)
@@ -286,6 +286,17 @@ static int pdb_decode_acct_ctrl(char const *p)
        return acct_ctrl;
 }
 
+static int mod_xlat_instantiate(void *xlat_inst, UNUSED xlat_exp_t const *exp, void *uctx)
+{
+       *((void **)xlat_inst) = talloc_get_type_abort(uctx, rlm_mschap_t);
+       return 0;
+}
+
+static xlat_arg_parser_t const mschap_xlat_args[] = {
+       { .required = true, .single = true, .type = FR_TYPE_STRING },
+       { .concat = true, .type = FR_TYPE_STRING },
+       XLAT_ARG_PARSER_TERMINATOR
+};
 
 /** Get data from MSCHAP attributes
  *
@@ -294,16 +305,23 @@ static int pdb_decode_acct_ctrl(char const *p)
  *
  * @ingroup xlat_functions
  */
-static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
-                          void const *mod_inst, UNUSED void const *xlat_inst,
-                          request_t *request, char const *fmt)
+static xlat_action_t mschap_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request,
+                                void const *xlat_inst, UNUSED void *xlat_thread_inst,
+                                fr_value_box_list_t *in)
 {
-       size_t                  i, data_len;
+       size_t                  data_len;
        uint8_t const           *data = NULL;
        uint8_t                 buffer[32];
        fr_pair_t               *user_name;
        fr_pair_t               *chap_challenge, *response;
-       rlm_mschap_t const      *inst = mod_inst;
+       rlm_mschap_t const      *inst;
+       void                    *instance;
+       fr_value_box_t          *arg = fr_dlist_head(in);
+       fr_value_box_t          *vb;
+       bool                    tainted = false;
+
+       memcpy(&instance, xlat_inst, sizeof(instance));
+       inst = talloc_get_type_abort(instance, rlm_mschap_t);
 
        response = NULL;
 
@@ -311,12 +329,13 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
         *      Challenge means MS-CHAPv1 challenge, or
         *      hash of MS-CHAPv2 challenge, and peer challenge.
         */
-       if (strncasecmp(fmt, "Challenge", 9) == 0) {
+       if (strncasecmp(arg->vb_strvalue, "Challenge", 9) == 0) {
                chap_challenge = fr_pair_find_by_da(&request->request_pairs, attr_ms_chap_challenge, 0);
                if (!chap_challenge) {
                        REDEBUG("No MS-CHAP-Challenge in the request");
-                       return -1;
+                       return XLAT_ACTION_FAIL;
                }
+               tainted = chap_challenge->vp_tainted;
 
                /*
                 *      MS-CHAP-Challenges are 8 octets,
@@ -340,7 +359,7 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                        response = fr_pair_find_by_da(&request->request_pairs, attr_ms_chap2_response, 0);
                        if (!response) {
                                REDEBUG("Vendor-Specific.Microsoft.CHAP2-Response is required to calculate MS-CHAPv1 challenge");
-                               return -1;
+                               return XLAT_ACTION_FAIL;
                        }
 
                        /*
@@ -354,11 +373,11 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                         */
                        if (response->vp_length < 50) {
                                REDEBUG("Vendor-Specific.Microsoft.CHAP-Response has the wrong format");
-                               return -1;
+                               return XLAT_ACTION_FAIL;
                        }
 
                        user_name = mschap_identity_find(request);
-                       if (!user_name) return -1;
+                       if (!user_name) return XLAT_ACTION_FAIL;
 
                        /*
                         *      Check for MS-CHAP-User-Name and if found, use it
@@ -370,11 +389,7 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                         *      packet.
                         */
                        response_name = fr_pair_find_by_da(&request->request_pairs, attr_ms_chap_user_name, 0);
-                       if (response_name) {
-                               name_vp = response_name;
-                       } else {
-                               name_vp = user_name;
-                       }
+                       name_vp = response_name ? response_name : user_name;
 
                        /*
                         *      with_ntdomain_hack moved here, too.
@@ -411,20 +426,21 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                        data_len = 8;
                } else {
                        REDEBUG("Invalid MS-CHAP challenge length");
-                       return -1;
+                       return XLAT_ACTION_FAIL;
                }
 
        /*
         *      Get the MS-CHAPv1 response, or the MS-CHAPv2
         *      response.
         */
-       } else if (strncasecmp(fmt, "NT-Response", 11) == 0) {
+       } else if (strncasecmp(arg->vb_strvalue, "NT-Response", 11) == 0) {
                response = fr_pair_find_by_da(&request->request_pairs, attr_ms_chap_response, 0);
                if (!response) response = fr_pair_find_by_da(&request->request_pairs, attr_ms_chap2_response, 0);
                if (!response) {
                        REDEBUG("No MS-CHAP-Response or MS-CHAP2-Response was found in the request");
-                       return -1;
+                       return XLAT_ACTION_FAIL;
                }
+               tainted = response->vp_tainted;
 
                /*
                 *      For MS-CHAPv1, the NT-Response exists only
@@ -432,7 +448,12 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                 */
                if ((response->da == attr_ms_chap_response) && ((response->vp_octets[1] & 0x01) == 0)) {
                        REDEBUG("No NT-Response in MS-CHAP-Response");
-                       return -1;
+                       return XLAT_ACTION_FAIL;
+               }
+
+               if (response->vp_length < 50) {
+                       REDEBUG("Vendor-Specific.Microsoft.CHAP-Response has the wrong format");
+                       return XLAT_ACTION_FAIL;
                }
 
                /*
@@ -447,20 +468,25 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
         *      LM-Response is deprecated, and exists only
         *      in MS-CHAPv1, and not often there.
         */
-       } else if (strncasecmp(fmt, "LM-Response", 11) == 0) {
+       } else if (strncasecmp(arg->vb_strvalue, "LM-Response", 11) == 0) {
                response = fr_pair_find_by_da(&request->request_pairs, attr_ms_chap_response, 0);
                if (!response) {
                        REDEBUG("No MS-CHAP-Response was found in the request");
-                       return -1;
+                       return XLAT_ACTION_FAIL;
                }
+               tainted = response->vp_tainted;
 
+               if (response->vp_length < 50) {
+                       REDEBUG("Vendor-Specific.Microsoft.CHAP-Response has the wrong format");
+                       return XLAT_ACTION_FAIL;
+               }
                /*
                 *      For MS-CHAPv1, the LM-Response exists only
                 *      if the second octet says so.
                 */
                if ((response->vp_octets[1] & 0x01) != 0) {
                        REDEBUG("No LM-Response in MS-CHAP-Response");
-                       return -1;
+                       return XLAT_ACTION_FAIL;
                }
                data = response->vp_octets + 2;
                data_len = 24;
@@ -468,11 +494,13 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
        /*
         *      Pull the NT-Domain out of the User-Name, if it exists.
         */
-       } else if (strncasecmp(fmt, "NT-Domain", 9) == 0) {
+       } else if (strncasecmp(arg->vb_strvalue, "NT-Domain", 9) == 0) {
                char *p, *q;
 
+               vb = fr_value_box_alloc_null(ctx);
+
                user_name = mschap_identity_find(request);
-               if (!user_name) return -1;
+               if (!user_name) return XLAT_ACTION_FAIL;
 
                /*
                 *      First check to see if this is a host/ style User-Name
@@ -488,7 +516,7 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                        p = strchr(user_name->vp_strvalue, '.');
                        if (!p) {
                                RDEBUG2("setting NT-Domain to same as machine name");
-                               strlcpy(*out, user_name->vp_strvalue + 5, outlen);
+                               fr_value_box_strdup(ctx, vb, NULL, user_name->vp_strvalue + 5, user_name->vp_tainted);
                        } else {
                                p++;    /* skip the period */
                                q = strchr(p, '.');
@@ -497,34 +525,38 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                                 * only if another period was found
                                 */
                                if (q) *q = '\0';
-                               strlcpy(*out, p, outlen);
+                               fr_value_box_strdup(ctx, vb, NULL, p, user_name->vp_tainted);
                                if (q) *q = '.';
                        }
                } else {
                        p = strchr(user_name->vp_strvalue, '\\');
                        if (!p) {
                                REDEBUG("No NT-Domain was found in the User-Name");
-                               return -1;
+                               talloc_free(vb);
+                               return XLAT_ACTION_FAIL;
                        }
 
                        /*
                         *      Hack.  This is simpler than the alternatives.
                         */
                        *p = '\0';
-                       strlcpy(*out, user_name->vp_strvalue, outlen);
+                       fr_value_box_strdup(ctx, vb, NULL, user_name->vp_strvalue, user_name->vp_tainted);
                        *p = '\\';
                }
 
-               return strlen(*out);
+               fr_dcursor_append(out, vb);
+               return XLAT_ACTION_DONE;
 
        /*
         *      Pull the User-Name out of the User-Name...
         */
-       } else if (strncasecmp(fmt, "User-Name", 9) == 0) {
+       } else if (strncasecmp(arg->vb_strvalue, "User-Name", 9) == 0) {
                char const *p, *q;
 
                user_name = mschap_identity_find(request);
-               if (!user_name) return -1;
+               if (!user_name) return XLAT_ACTION_FAIL;
+
+               vb = fr_value_box_alloc_null(ctx);
 
                /*
                 *      First check to see if this is a host/ style User-Name
@@ -549,9 +581,9 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                         * only if a period was found
                         */
                        if (q) {
-                               snprintf(*out, outlen, "%.*s$", (int) (q - p), p);
+                               fr_value_box_asprintf(ctx, vb, NULL, true, "%.*s$", (int) (q - p), p);
                        } else {
-                               snprintf(*out, outlen, "%s$", p);
+                               fr_value_box_asprintf(ctx, vb, NULL, true, "%s$", p);
                        }
                } else {
                        p = strchr(user_name->vp_strvalue, '\\');
@@ -560,82 +592,65 @@ static ssize_t mschap_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                        } else {
                                p = user_name->vp_strvalue; /* use the whole User-Name */
                        }
-                       strlcpy(*out, p, outlen);
+                       fr_value_box_strdup(ctx, vb, NULL, p, user_name->vp_tainted);
                }
 
-               return strlen(*out);
+               fr_dcursor_append(out, vb);
+               return XLAT_ACTION_DONE;
 
        /*
         * Return the NT-Hash of the passed string
         */
-       } else if (strncasecmp(fmt, "NT-Hash ", 8) == 0) {
-               char const *p;
-
-               p = fmt + 8;    /* 7 is the length of 'NT-Hash' */
-               if ((*p == '\0') || (outlen <= 32))
-                       return 0;
-
-               fr_skip_whitespace(p);
+       } else if (strncasecmp(arg->vb_strvalue, "NT-Hash", 7) == 0) {
+               arg = fr_dlist_next(in, arg);
+               if ((!arg) || (arg->length == 0))
+                       return XLAT_ACTION_FAIL;
 
-               if (mschap_nt_password_hash(buffer, p) < 0) {
+               if (mschap_nt_password_hash(buffer, arg->vb_strvalue) < 0) {
                        REDEBUG("Failed generating NT-Password");
                        *buffer = '\0';
-                       return -1;
+                       return XLAT_ACTION_FAIL;
                }
 
-               fr_bin2hex(&FR_SBUFF_OUT(*out, (NT_DIGEST_LENGTH * 2) + 1), &FR_DBUFF_TMP(buffer, NT_DIGEST_LENGTH), SIZE_MAX);
-               (*out)[32] = '\0';
-               RDEBUG2("NT-Hash of \"known-good\" password: %s", *out);
-               return 32;
+               vb = fr_value_box_alloc_null(ctx);
+               fr_value_box_memdup(ctx, vb, NULL, buffer, NT_DIGEST_LENGTH, false);
+               RDEBUG2("NT-Hash of \"known-good\" password: %pV", vb);
+               fr_dcursor_append(out, vb);
+               return XLAT_ACTION_DONE;
 
        /*
         * Return the LM-Hash of the passed string
         */
-       } else if (strncasecmp(fmt, "LM-Hash ", 8) == 0) {
-               char const *p;
-
-               p = fmt + 8;    /* 7 is the length of 'LM-Hash' */
-               if ((*p == '\0') || (outlen <= 32))
-                       return 0;
-
-               fr_skip_whitespace(p);
-
-               smbdes_lmpwdhash(p, buffer);
-               fr_bin2hex(&FR_SBUFF_OUT(*out, (LM_DIGEST_LENGTH * 2) + 1), &FR_DBUFF_TMP(buffer, LM_DIGEST_LENGTH), SIZE_MAX);
-               (*out)[32] = '\0';
-               RDEBUG2("LM-Hash of %s = %s", p, *out);
-               return 32;
+       } else if (strncasecmp(arg->vb_strvalue, "LM-Hash", 7) == 0) {
+               arg = fr_dlist_next(in, arg);
+               if ((!arg) || (arg->length == 0))
+                       return XLAT_ACTION_FAIL;
+
+               smbdes_lmpwdhash(arg->vb_strvalue, buffer);
+
+               vb = fr_value_box_alloc_null(ctx);
+               fr_value_box_memdup(ctx, vb, NULL, buffer, LM_DIGEST_LENGTH, false);
+               RDEBUG2("LM-Hash of %s = %pV", arg->vb_strvalue, vb);
+               fr_dcursor_append(out, vb);
+               return XLAT_ACTION_DONE;
        } else {
-               REDEBUG("Unknown expansion string '%s'", fmt);
-               return -1;
+               REDEBUG("Unknown expansion string '%pV'", arg);
+               return XLAT_ACTION_FAIL;
        }
 
-       if (outlen == 0) return 0; /* nowhere to go, don't do anything */
-
        /*
         *      Didn't set anything: this is bad.
         */
        if (!data) {
                RWDEBUG2("Failed to do anything intelligent");
-               return 0;
-       }
-
-       /*
-        *      Check the output length.
-        */
-       if (outlen < ((data_len * 2) + 1)) {
-               data_len = (outlen - 1) / 2;
+               return XLAT_ACTION_FAIL;
        }
 
-       /*
-        *
-        */
-       for (i = 0; i < data_len; i++) {
-               sprintf((*out) + (2 * i), "%02x", data[i]);
-       }
-       (*out)[data_len * 2] = '\0';
+       vb = fr_value_box_alloc_null(ctx);
+       fr_value_box_memdup(ctx, vb, NULL, data, data_len, tainted);
 
-       return data_len * 2;
+       fr_dcursor_append(out, vb);
+       return XLAT_ACTION_DONE;
 }
 
 
@@ -721,8 +736,8 @@ static int CC_HINT(nonnull (1, 2, 4, 5)) do_mschap_cpw(rlm_mschap_t const *inst,
                 * we're expecting to use the ntlm-change-password-1 protocol
                 * which needs the following on stdin:
                 *
-                * username: %{mschap:User-Name}
-                * nt-domain: %{mschap:NT-Domain}
+                * username: %(mschap:User-Name)
+                * nt-domain: %(mschap:NT-Domain)
                 * new-nt-password-blob: bin2hex(new_nt_password) - 1032 bytes encoded
                 * old-nt-hash-blob: bin2hex(old_nt_hash) - 32 bytes encoded
                 * new-lm-password-blob: 00000...0000 - 1032 bytes null
@@ -896,7 +911,7 @@ ntlm_auth_err:
                 *
                 *  ...or...
                 *
-                *  %{exec:/path/to %{mschap:User-Name} %{MS-CHAP-New-Password}}"
+                *  %{exec:/path/to %(mschap:User-Name) %{MS-CHAP-New-Password}}"
                 *
                 */
                fr_pair_t *new_pass, *new_hash;
@@ -2198,6 +2213,7 @@ static int mod_bootstrap(void *instance, CONF_SECTION *conf)
 {
        char const              *name;
        rlm_mschap_t            *inst = instance;
+       xlat_t                  *xlat;
 
        /*
         *      Create the dynamic translation.
@@ -2206,7 +2222,9 @@ static int mod_bootstrap(void *instance, CONF_SECTION *conf)
        if (!name) name = cf_section_name1(conf);
        inst->name = name;
 
-       xlat_register_legacy(inst, inst->name, mschap_xlat, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN);
+       xlat = xlat_register(inst, inst->name, mschap_xlat, false);
+       xlat_func_args(xlat, mschap_xlat_args);
+       xlat_async_instantiate_set(xlat, mod_xlat_instantiate, rlm_mschap_t *, NULL, inst);
 
        return 0;
 }
index d6fa65e6683d99ed00e2fcefcca308acc1104710..838cbca516addfdc1829431f4ad93cf1531ba62c 100644 (file)
@@ -735,7 +735,7 @@ static unlang_action_t CC_HINT(nonnull) pap_auth_lm(rlm_rcode_t *p_result,
                RETURN_MODULE_INVALID;
        }
 
-       len = xlat_eval(charbuf, sizeof(charbuf), request, "%{mschap:LM-Hash %{User-Password}}", NULL, NULL);
+       len = xlat_eval(charbuf, sizeof(charbuf), request, "%(mschap:LM-Hash %{User-Password})", NULL, NULL);
        if (len < 0) RETURN_MODULE_FAIL;
 
        if ((fr_hex2bin(NULL, &FR_DBUFF_TMP(digest, sizeof(digest)), &FR_SBUFF_IN(charbuf, len), false) !=
diff --git a/src/tests/keywords/mschap b/src/tests/keywords/mschap
new file mode 100644 (file)
index 0000000..bcceaf6
--- /dev/null
@@ -0,0 +1,98 @@
+#
+#  PRE: update
+#
+
+# MS CHAPv1
+update request {
+        &User-Name := 'EXAMPLE\bob'
+       &Vendor-Specific.Microsoft.CHAP-Challenge := 0xe96e4fff2955c4f1
+       &Vendor-Specific.Microsoft.CHAP-Response := 0x00010000000000000000000000000000000000000000000000008860bbaac0cd3960b4ce5dc6f0f7a462b897ef530484e80f
+}
+
+update request {
+        &Tmp-Octets-0 := "%(mschap:Challenge)"
+        &Tmp-Octets-1 := "%(mschap:NT-Response)"
+        &Tmp-String-0 := "%(mschap:NT-Domain)"
+        &Tmp-String-1 := "%(mschap:User-Name)"
+}
+
+if (&Tmp-Octets-0 != 0xe96e4fff2955c4f1) {
+        test_fail
+}
+
+if (&Tmp-Octets-1 != 0x8860bbaac0cd3960b4ce5dc6f0f7a462b897ef530484e80f) {
+        test_fail
+}
+
+if (&Tmp-String-0 != 'EXAMPLE') {
+        test_fail
+}
+
+if (&Tmp-String-1 != 'bob') {
+        test_fail
+}
+
+update request {
+       &Vendor-Specific.Microsoft.CHAP-Response := 0x00006937d7935bb28a4c1dafe6a193bdea7a853a74d8bcf6db158860bbaac0cd3960b4ce5dc6f0f7a462b897ef530484e80f
+}
+
+update request {
+        &Tmp-Octets-0 := "%(mschap:LM-Response)"
+}
+
+if (&Tmp-Octets-0 != 0x6937d7935bb28a4c1dafe6a193bdea7a853a74d8bcf6db15) {
+        test_fail
+}
+
+# Hashing
+update request {
+        &Tmp-Octets-0 := "%(mschap:NT-Hash testing_123)"
+        &Tmp-Octets-1 := "%(mschap:LM-Hash testing_123)"
+}
+
+if (&Tmp-Octets-0 != 0xfa782604f85eb3564f555648341b53e4) {
+        test_fail
+}
+
+if (&Tmp-Octets-1 != 0x2d5545077d7b7d2ae4343f96ab15c596) {
+        test_fail
+}
+
+# MS CHAPv2
+update request {
+        &Vendor-Specific.Microsoft.CHAP-Response !* ANY
+        &Vendor-Specific.Microsoft.CHAP-Challenge := 0x04408dc2a98dae1ce351dfc53f57d08e
+        &Vendor-Specific.Microsoft.CHAP2-Response := 0x00010e93cfbfcef8d5b6af42d2b2ca5b43180000000000000000bc068d1e8c54de5e9db78e6736d686eb88a999dd7fa239b200
+}
+
+update request {
+        &Tmp-Octets-0 := "%(mschap:Challenge)"
+        &Tmp-Octets-1 := "%(mschap:NT-Response)"
+}
+
+if (&Tmp-Octets-0 != 0xad18b6b8e1478b4c) {
+        test_fail
+}
+
+if (&Tmp-Octets-1 != 0xbc068d1e8c54de5e9db78e6736d686eb88a999dd7fa239b2) {
+        test_fail
+}
+
+# Invalid
+update request {
+        &Vendor-Specific.Microsoft.CHAP-Challenge := 0xf0eac4151d5346662ba8c5e428
+}
+
+update request {
+        &Tmp-String-0 := "%(mschap:Challenge)"
+}
+
+if (&Tmp-String-0 != "") {
+        test_fail
+}
+
+if (&Module-Failure-Message != "Invalid MS-CHAP challenge length") {
+        test_fail
+}
+
+success
\ No newline at end of file
index bbdb5579f6bab502b718971eb0472d1e5c91e0f5..336d3753d792fe2fe173901e185368addb391ff1 100644 (file)
@@ -51,12 +51,17 @@ modules {
        date sqldate {
                format = "%Y-%m-%d %H:%M:%S"
                utc = yes
-  }
+       }
   
        idn {
                allow_unassigned = no
                use_std3_ascii_rules = yes
        }
+
+       mschap {
+
+       }
+
 }
 
 policy {