implement radiusd::xlat in rlm_perl
authorBoris Lytochkin <lytboris@yandex-team.ru>
Fri, 4 Nov 2016 14:29:12 +0000 (17:29 +0300)
committerBoris Lytochkin <lytboris@yandex-team.ru>
Tue, 8 Nov 2016 13:49:07 +0000 (16:49 +0300)
Sponsored by: Yandex LLC

doc/ChangeLog
raddb/mods-config/perl/example.pl
src/modules/rlm_perl/rlm_perl.c

index 3a18747..aeb51cf 100644 (file)
@@ -5,6 +5,8 @@ FreeRADIUS 3.0.13 Thur 29 Sep 2016 13:00:00 EDT urgency=medium
        * Added 'cipher_server_preference' to mods-available/eap
          Patch from #1797.
        * OpenSSL 1.1.0 compatibility fixes.
+       * rlm_perl: radiusd::xlat to evaluate xlat string
+         within perl script
 
        Bug fixes
        * Minor typos.  Fixes #1763
index 1216e9f..1fffd44 100644 (file)
@@ -126,7 +126,12 @@ sub authenticate {
                return RLM_MODULE_REJECT;
        } else {
                # Accept user and set some attribute
-               $RAD_REPLY{'h323-credit-amount'} = "100";
+               if (&radiusd::xlat("%{client:group}") eq 'UltraAllInclusive') {
+                       # User called from NAS with unlim plan set, set higher limits
+                       $RAD_REPLY{'h323-credit-amount'} = "1000000";
+               } else {
+                       $RAD_REPLY{'h323-credit-amount'} = "100";
+               }
                return RLM_MODULE_OK;
        }
 }
index 5ec63cb..b1191ab 100644 (file)
@@ -297,6 +297,44 @@ static XS(XS_radiusd_radlog)
        XSRETURN_NO;
 }
 
+/*
+ *     This is a wraper for radius_axlat
+ *     Now users are able to get data that is accessible only via xlat
+ *     e.g. %{client:...}
+ *     Call syntax is radiusd::xlat(string), string will be handled the
+ *     same way it is described in EXPANSIONS section of man unlang
+ */
+static XS(XS_radiusd_xlat)
+{
+       dXSARGS;
+       char *in_str;
+       char *expanded;
+       ssize_t slen;
+       SV *rad_requestp_sv;
+       REQUEST *request;
+
+       if (items != 1) croak("Usage: radiusd::xlat(string)");
+
+       rad_requestp_sv = get_sv("RAD___REQUESTP", 0);
+       if (rad_requestp_sv == NULL) croak("Can not evalue xlat, RAD___REQUESTP is not set!");
+
+       request = INT2PTR(REQUEST *, SvIV(rad_requestp_sv));
+
+       in_str = (char *) SvPV(ST(0), PL_na);
+       expanded = NULL;
+       slen = radius_axlat(&expanded, request, in_str, NULL, NULL);
+
+       if (slen < 0) {
+               REDEBUG("Error parsing xlat '%s'", in_str);
+               XSRETURN_UNDEF;
+       }
+
+
+       XST_mPV(0, expanded);
+       talloc_free(expanded);
+       XSRETURN(1);
+}
+
 static void xs_init(pTHX)
 {
        char const *file = __FILE__;
@@ -305,6 +343,7 @@ static void xs_init(pTHX)
        newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
 
        newXS("radiusd::radlog",XS_radiusd_radlog, "rlm_perl");
+       newXS("radiusd::xlat",XS_radiusd_xlat, "rlm_perl");
 }
 
 /*
@@ -782,6 +821,7 @@ static int do_perl(void *instance, REQUEST *request, char const *function_name)
        HV              *rad_request_proxy_hv;
        HV              *rad_request_proxy_reply_hv;
 #endif
+       SV              *rad_requestp_sv;
 
        /*
         *      Radius has told us to call this function, but none
@@ -816,6 +856,7 @@ static int do_perl(void *instance, REQUEST *request, char const *function_name)
                rad_config_hv = get_hv("RAD_CONFIG", 1);
                rad_request_hv = get_hv("RAD_REQUEST", 1);
                rad_state_hv = get_hv("RAD_STATE", 1);
+               rad_requestp_sv = get_sv("RAD___REQUESTP", 1);
 
                perl_store_vps(request->packet, request, &request->packet->vps, rad_request_hv, "RAD_REQUEST", "request");
                perl_store_vps(request->reply, request, &request->reply->vps, rad_reply_hv, "RAD_REPLY", "reply");
@@ -842,6 +883,15 @@ static int do_perl(void *instance, REQUEST *request, char const *function_name)
                }
 #endif
 
+               /*
+                * Store pointer to request structure globally so xlat works
+                * We mark it read-only for interpreter so end users will not be
+                * in posession to change it and crash radiusd with bogus pointer
+                */
+               SvREADONLY_off(rad_requestp_sv);
+               sv_setiv(rad_requestp_sv, PTR2IV(request));
+               SvREADONLY_on(rad_requestp_sv);
+
                PUSHMARK(SP);
                /*
                 * This way %RAD_xx can be pushed onto stack as sub parameters.