]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
v4: Convert %(soh: ) to new xlat api (#4062)
authorNick Porter <nick@portercomputing.co.uk>
Fri, 16 Apr 2021 18:33:05 +0000 (19:33 +0100)
committerGitHub <noreply@github.com>
Fri, 16 Apr 2021 18:33:05 +0000 (13:33 -0500)
* Convert %(soh: ) to new xlat api

* Correct interpretation of windows version numbers

* Add test for %(soh: ) xlat

doc/antora/modules/howto/pages/modules/soh/index.adoc
src/modules/rlm_soh/rlm_soh.c
src/tests/keywords/radius.conf
src/tests/keywords/xlat-soh [new file with mode: 0644]

index 4c431232db4fff291901c832fcd53a8ec0365d78..1a4dc538a1699d4b8fff2e157631ab209bd85a7e 100644 (file)
@@ -129,13 +129,13 @@ some dynamic variables available, for example:
 ```
 recv Access-Request {
        soh update request {
-               Tmp-String-0 = %{soh:OS}
+               Tmp-String-0 = %(soh:OS)
        }
 }
 ```
 
-…will give you a string like ``Windows Vista 6.1.100 sp 1.0'' or
-``Windows XP 5.x.x sp 3.0''
+…will give you a string like ``Windows Vista / Server 2008 6.0.100 sp 1.0''
+or ``Windows XP 5.x.x sp 3.0''
 
 At the moment, this is the only dynamic expansion; in future, we will
 make various bits of info available, for example non-Microsoft SoH
index e3b527f751b3ec13ab2243dab031f7b43cf4190c..d828e5b09cfaf6ee0ad96b2e3530838cae77c17d 100644 (file)
@@ -70,28 +70,36 @@ fr_dict_attr_autoload_t rlm_soh_dict_attr[] = {
        { NULL }
 };
 
+static xlat_arg_parser_t const soh_xlat_args[] = {
+       { .required = true, .single = true, .type = FR_TYPE_STRING },
+       XLAT_ARG_PARSER_TERMINATOR
+};
+
 /** SoH xlat
  *
  * Not sure how to make this useful yet...
  *
  * @ingroup xlat_functions
  */
-static ssize_t soh_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
-                       UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
-                       request_t *request, char const *fmt)
+static xlat_action_t soh_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request,
+                             UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
+                             fr_value_box_list_t *in)
 {
-       fr_pair_t* vp[6];
-       char const *osname;
+       fr_value_box_t  *in_head = fr_dlist_head(in);
+       fr_value_box_t  *vb;
+       fr_pair_t*      vp[6];
+       char const      *osname;
+       char            buff[128];
 
        /*
         * There will be no point unless SoH-Supported = yes
         */
        vp[0] = fr_pair_find_by_da(&request->request_pairs, attr_soh_supported);
        if (!vp[0])
-               return 0;
+               return XLAT_ACTION_FAIL;
 
 
-       if (strncasecmp(fmt, "OS", 2) == 0) {
+       if (strncasecmp(in_head->vb_strvalue, "OS", 2) == 0) {
                /* OS vendor */
                vp[0] = fr_pair_find_by_da(&request->request_pairs, attr_soh_ms_machine_os_vendor);
                vp[1] = fr_pair_find_by_da(&request->request_pairs, attr_soh_ms_machine_os_version);
@@ -101,37 +109,70 @@ static ssize_t soh_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen,
                vp[5] = fr_pair_find_by_da(&request->request_pairs, attr_soh_ms_machine_sp_release);
 
                if (vp[0] && vp[0]->vp_uint32 == attr_ms_vendor->attr) {
+                       MEM(vb=fr_value_box_alloc_null(ctx));
+
                        if (!vp[1]) {
-                               snprintf(*out, outlen, "Windows unknown");
+                               fr_value_box_bstrndup(ctx, vb, NULL, "Windows unknown", 15, false);
                        } else {
                                switch (vp[1]->vp_uint32) {
-                               case 7:
-                                       osname = "7";
+                               case 10:
+                                       osname = "10";
                                        break;
 
                                case 6:
-                                       osname = "Vista";
+                                       switch (vp[2]->vp_uint32) {
+                                       case 0:
+                                               osname = "Vista / Server 2008";
+                                               break;
+                                       case 1:
+                                               osname = "7 / Server 2008 R2";
+                                               break;
+                                       case 2:
+                                               osname = "8 / Server 2012";
+                                               break;
+                                       case 3:
+                                               osname = "8.1 / Server 2012 R2";
+                                               break;
+                                       default:
+                                               osname = "Other";
+                                               break;
+                                       }
                                        break;
 
                                case 5:
-                                       osname = "XP";
+                                       switch (vp[2]->vp_uint32) {
+                                       case 0:
+                                               osname = "2000";
+                                               break;
+                                       case 1:
+                                               osname = "XP";
+                                               break;
+                                       case 2:
+                                               osname = "Server 2003";
+                                               break;
+                                       default:
+                                               osname = "Other";
+                                               break;
+                                       }
                                        break;
 
                                default:
                                        osname = "Other";
                                        break;
                                }
-                               snprintf(*out, outlen, "Windows %s %d.%d.%d sp %d.%d", osname, vp[1]->vp_uint32,
+                               snprintf(buff, 127, "Windows %s %d.%d.%d sp %d.%d", osname, vp[1]->vp_uint32,
                                         vp[2] ? vp[2]->vp_uint32 : 0,
                                         vp[3] ? vp[3]->vp_uint32 : 0,
                                         vp[4] ? vp[4]->vp_uint32 : 0,
                                         vp[5] ? vp[5]->vp_uint32 : 0);
+                               fr_value_box_bstrndup(ctx, vb, NULL, buff, strlen(buff), false);
                        }
-                       return strlen(*out);
+                       fr_dcursor_append(out, vb);
+                       return XLAT_ACTION_DONE;
                }
        }
 
-       return 0;
+       return XLAT_ACTION_FAIL;
 }
 
 
@@ -232,13 +273,15 @@ static int mod_bootstrap(void *instance, CONF_SECTION *conf)
 {
        char const      *name;
        rlm_soh_t       *inst = instance;
+       xlat_t          *xlat;
 
        name = cf_section_name2(conf);
        if (!name) name = cf_section_name1(conf);
        inst->xlat_name = name;
        if (!inst->xlat_name) return -1;
 
-       xlat_register_legacy(inst, inst->xlat_name, soh_xlat, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN);
+       xlat = xlat_register(inst, inst->xlat_name, soh_xlat, false);
+       xlat_func_args(xlat, soh_xlat_args);
 
        return 0;
 }
index 45cccbf96b9585399869e96c2307c08beba33b7a..b2d8f0dd00a008df1a65e197139657b4be18bbcd 100644 (file)
@@ -34,6 +34,10 @@ modules {
 
        }
 
+       soh {
+
+       }
+
 }
 
 policy {
diff --git a/src/tests/keywords/xlat-soh b/src/tests/keywords/xlat-soh
new file mode 100644 (file)
index 0000000..7e85dff
--- /dev/null
@@ -0,0 +1,86 @@
+#
+# PRE: update
+#
+
+update control {
+        &Tmp-String-0 := %(soh:OS)
+}
+
+# SoH-Supported not set - should be no response
+if ("%{control.Tmp-String-0}" != "") {
+        test_fail
+}
+
+update request {
+        &SoH-Supported := yes
+        &SoH-MS-Machine-OS-release := 0
+        &SoH-MS-Machine-OS-build := 6001
+        &SoH-MS-Machine-SP-version := 1
+        &SoH-MS-Machine-SP-release := 0
+}
+
+update control {
+        &Tmp-String-0 := %(soh:OS)
+}
+
+# SoH-MS-Machine-OS-vendor not set - should be no response
+if ("%{control.Tmp-String-0}" != "") {
+        test_fail
+}
+
+update request {
+        &SoH-Supported := yes
+        &SoH-MS-Machine-OS-vendor := Microsoft
+}
+
+update control {
+        &Tmp-String-0 := %(soh:OS)
+}
+
+# OS version not set
+if ("%{control.Tmp-String-0}" != "Windows unknown") {
+        test_fail
+}
+
+update request {
+        &SoH-MS-Machine-OS-version := 6
+}
+
+update control {
+        &Tmp-String-0 := %(soh:OS)
+}
+
+# Complete set of data should match a real version of Windows
+if ("%{control.Tmp-String-0}" != "Windows Vista / Server 2008 6.0.6001 sp 1.0" ) {
+        test_fail
+}
+
+update request {
+        &SoH-MS-Machine-OS-release := 5
+}
+
+update control {
+        &Tmp-String-0 := %(soh:OS)
+}
+
+# Version and Release combination that does not exist
+if ("%{control.Tmp-String-0}" != "Windows Other 6.5.6001 sp 1.0") {
+        test_fail
+}
+
+update request {
+        &SoH-MS-Machine-OS-version := 8
+        &SoH-MS-Machine-OS-release := 0
+}
+
+update control {
+        &Tmp-String-0 := %(soh:OS)
+}
+
+# Version that does not exist
+if ("%{control.Tmp-String-0}" != "Windows Other 8.0.6001 sp 1.0") {
+        test_fail
+}
+
+debug_control
+success