3

I have a FreeRADIUS C language module that implements MOD_AUTHENTICATE and MOD_AUTHORIZE methods for custom auth purpose. I need the ability to programmatically add VSAs to the Access-Accept reply.

I have toyed a bit with radius_pair_create() and fr_pair_add() methods (see snippet below) but that didn’t yield any change to the reply content, possibly because I specified ad-hoc values that don’t exist in a vendor-specific dictionary. Or because I didn’t use them correctly.

My FreeRADIUS version is 3_0_19

Any information, pointers and, especially, syntax samples will be highly appreciated.

void test_vsa(REQUEST *request)
{
    VALUE_PAIR *vp = NULL;

    vp = radius_pair_create(request->reply, NULL, 18, 0);

    if (vp)
    {
        log("Created VALUE_PAIR");
        vp->vp_integer = 96;
        fr_pair_add(&request->reply->vps, vp);
    } 
    else
    {
        log("Failed to create VALUE_PAIR");
    }
}
my3ika
  • 65
  • 6

1 Answers1

2

So first off you're writing an integer value to a string attribute, which is wrong. The only reason why the server isn't SEGVing is because the length of the VP has been left at zero, so the RADIUS encoder doesn't bother dereferencing the char * inside the pair that's meant to contain the pair's value.

fr_pair_make is the easier function to use here, as it takes both the attribute name and value as strings, so you don't need to worry about the C types.

The code snippet below should do what you want.

void test_avp(REQUEST *request)
{
    VALUE_PAIR *vp = NULL;

    vp = fr_pair_make(request->reply, &request->reply->vps, "Reply-Message", "Hello from FreeRADIUS", T_OP_SET);
    if (vp)
    {
        log("Created VALUE_PAIR");
    } 
    else
    {
        log("Failed to create VALUE_PAIR");
    }
}

For a bit more of an explanation, lets look at the doxygen header:

/** Create a VALUE_PAIR from ASCII strings
 *
 * Converts an attribute string identifier (with an optional tag qualifier)
 * and value string into a VALUE_PAIR.
 *
 * The string value is parsed according to the type of VALUE_PAIR being created.
 *
 * @param[in] ctx for talloc
 * @param[in] vps list where the attribute will be added (optional)
 * @param[in] attribute name.
 * @param[in] value attribute value (may be NULL if value will be set later).
 * @param[in] op to assign to new VALUE_PAIR.
 * @return a new VALUE_PAIR.
 */
VALUE_PAIR *fr_pair_make(TALLOC_CTX *ctx, VALUE_PAIR **vps,
            char const *attribute, char const *value, FR_TOKEN op)
  • ctx - This is the packet or request that the vps will belong to. If you're adding attributes to the request it should be request->packet, reply would be request->reply, control would be request.
  • vps - If specified, this will be which list to insert the new VP into. If this is NULL fr_pair_make will just return the pair and let you insert it into a list.
  • attribute - The name of the attribute as a string.
  • value - The value of the attribute as a string. For non-string types, fr_pair_make will attempt to perform a conversion. So, for example, passing "12345" for an integer type, will result in the integer value 12345 being written to an int field in the attribute.
  • op - You'll usually want to us T_OP_SET which means overwrite existing instances of the same attribute. See the T_OP_* values of FR_TOKEN and the code that uses them, if you want to understand the different operators and what they do.
Arran Cudbard-Bell
  • 5,912
  • 2
  • 26
  • 48
  • Arran, thank you for the correction and detailed explanation of fr_pair_make usage. Unfortunately, this doesn’t quite resolve my issue of adding a VSA to Access-Accept message: I still need to know how to use fr_pair_make to add a VSA (aka PW_VENDOR_SPECIFIC  aka Vendor-Specific aka attr-26). For example: VENDOR: Meraki (29671) ATTRIBUTE: Meraki-Network-Name (2) string – my3ika Nov 22 '19 at 19:52
  • 1
    You pass "Meraki-Network-Name" as the attribute string. VSAs are not a special case. – Arran Cudbard-Bell Nov 22 '19 at 23:03
  • I finally realized that the reason I don't see the VSAs I'm adding (using WireShark) is because I'm running EAP requests, and my attributes must be part of inner tunnel, while I can only see outer tunnel data. Is there a simple method to also add my VSAs to outer tunnel AVPs for testing purpose? – my3ika Nov 27 '19 at 22:34
  • 1
    Yes, and if mark this answer as accepted and ask your new question formerly, posting a link here, I'd be glad to answer it. – Arran Cudbard-Bell Nov 28 '19 at 15:15
  • Of course. Here you go: https://stackoverflow.com/questions/59146280/how-to-add-copy-vsas-vendor-specific-attributes-to-outer-channel-of-eap-reply – my3ika Dec 02 '19 at 20:34