From: Nick Porter Date: Fri, 16 Apr 2021 18:33:05 +0000 (+0100) Subject: v4: Convert %(soh: ) to new xlat api (#4062) X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e0924d5e761b24045352e988d660e9ceb2e455f1;p=thirdparty%2Ffreeradius-server.git v4: Convert %(soh: ) to new xlat api (#4062) * Convert %(soh: ) to new xlat api * Correct interpretation of windows version numbers * Add test for %(soh: ) xlat --- diff --git a/doc/antora/modules/howto/pages/modules/soh/index.adoc b/doc/antora/modules/howto/pages/modules/soh/index.adoc index 4c431232db4..1a4dc538a16 100644 --- a/doc/antora/modules/howto/pages/modules/soh/index.adoc +++ b/doc/antora/modules/howto/pages/modules/soh/index.adoc @@ -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 diff --git a/src/modules/rlm_soh/rlm_soh.c b/src/modules/rlm_soh/rlm_soh.c index e3b527f751b..d828e5b09cf 100644 --- a/src/modules/rlm_soh/rlm_soh.c +++ b/src/modules/rlm_soh/rlm_soh.c @@ -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; } diff --git a/src/tests/keywords/radius.conf b/src/tests/keywords/radius.conf index 45cccbf96b9..b2d8f0dd00a 100644 --- a/src/tests/keywords/radius.conf +++ b/src/tests/keywords/radius.conf @@ -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 index 00000000000..7e85dff6554 --- /dev/null +++ b/src/tests/keywords/xlat-soh @@ -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