Skip to content

Commit

Permalink
Add support for encoding version lists
Browse files Browse the repository at this point in the history
  • Loading branch information
arr2036 committed Dec 1, 2017
1 parent 414ff83 commit 0abefd8
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 12 deletions.
2 changes: 1 addition & 1 deletion share/dictionary.eap.sim
Expand Up @@ -14,7 +14,7 @@ ATTRIBUTE EAP-SIM-Res 3 octets
ATTRIBUTE EAP-SIM-Auts 4 octets
ATTRIBUTE EAP-SIM-Nonce-MT 7 octets
ATTRIBUTE EAP-SIM-Permanent-ID-Req 10 bool
ATTRIBUTE EAP-SIM-Mac 11 octets
ATTRIBUTE EAP-SIM-Mac 11 octets[20]
ATTRIBUTE EAP-SIM-Notification 12 short

VALUE EAP-SIM-Notification General-Failure-After-Authentication 0
Expand Down
44 changes: 44 additions & 0 deletions src/modules/rlm_eap/lib/sim/base.c
Expand Up @@ -40,6 +40,50 @@ RCSID("$Id$")
fr_dict_attr_t const *dict_sim_root;
fr_dict_attr_t const *dict_aka_root;

/** SIM AT on-the-wire format attribute sizes
*
* Holds the min/max sizes of all supported SIM AT attribute values as they
* would be found in a SIM AT packet.
*
* These sizes may be different than the sizes of INTERNAL formats, PRESENTATION
* formats and generic NETWORK formats.
*/
size_t const fr_sim_attr_sizes[FR_TYPE_MAX + 1][2] = {
[FR_TYPE_INVALID] = {~0, 0},

[FR_TYPE_STRING] = {0, ~0},
[FR_TYPE_OCTETS] = {0, ~0},

[FR_TYPE_BOOL] = {2, 2},
[FR_TYPE_UINT8] = {1, 1},
[FR_TYPE_UINT16] = {2, 2},
[FR_TYPE_UINT32] = {4, 4},
[FR_TYPE_UINT64] = {8, 8},

[FR_TYPE_TLV] = {2, ~0},

[FR_TYPE_MAX] = {~0, 0} //!< Ensure array covers all types.
};

/** Return the on-the-wire length of an attribute value
*
* @param[in] vp to return the length of.
* @return the length of the attribute.
*/
size_t fr_sim_attr_len(VALUE_PAIR const *vp)
{
switch (vp->vp_type) {
case FR_TYPE_VARIABLE_SIZE:
return vp->vp_length;

default:
return fr_radius_attr_sizes[vp->vp_type][0];

case FR_TYPE_STRUCTURAL:
if (!fr_cond_assert(0)) return 0;
}
}

/*
* definitions changed to take a buffer for unknowns
* as this is more thread safe.
Expand Down
2 changes: 1 addition & 1 deletion src/modules/rlm_eap/lib/sim/decode.c
Expand Up @@ -256,7 +256,7 @@ static int fr_sim_array_members(size_t *out, size_t len, fr_dict_attr_t const *d
break;

default:
element_len = dict_attr_sizes[da->type][0];
element_len = fr_sim_attr_sizes[da->type][0];
break;
}

Expand Down
104 changes: 94 additions & 10 deletions src/modules/rlm_eap/lib/sim/encode.c
Expand Up @@ -338,6 +338,13 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
*p++ = 0; /* Reserved */
*p++ = 0; /* Reserved */

if (vp->da->flags.length && (vp->vp_length != vp->da->flags.length)) {
fr_strerror_printf("%s: Attribute \"%s\" needs a value of exactly %zu bytes, "
"but value was %zu bytes", __FUNCTION__,
vp->da->name, (size_t)vp->da->flags.length, vp->vp_length);
return -1;
}

memcpy(p, vp->vp_octets, vp->vp_length);
p += vp->vp_length;

Expand Down Expand Up @@ -376,6 +383,13 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,

if ((rounded_len + 2) > outlen) goto oos;

if (vp->da->flags.length && (vp->vp_length != vp->da->flags.length)) {
fr_strerror_printf("%s: Attribute \"%s\" needs a value of exactly %zu bytes, "
"but value was %zu bytes", __FUNCTION__,
vp->da->name, (size_t)vp->da->flags.length, vp->vp_length);
return -1;
}

memcpy(p, &actual_len, sizeof(actual_len)); /* Big endian real string length */
p += sizeof(actual_len);

Expand Down Expand Up @@ -444,6 +458,71 @@ static ssize_t encode_value(uint8_t *out, size_t outlen,
return len;
}

/** Encodes the data portion of an attribute
*
@verbatim
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| AT_VERSION_L..| Length | Actual Version List Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Supported Version 1 | Supported Version 2 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. .
. .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Supported Version N | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@endverbatim
*
*/
static ssize_t encode_array(uint8_t *out, size_t outlen,
fr_dict_attr_t const **tlv_stack, int depth,
vp_cursor_t *cursor, void *encoder_ctx)
{
uint8_t *p = out, *end = p + outlen;
uint8_t *value;
size_t pad_len;
uint16_t actual_len;
fr_dict_attr_t const *da = tlv_stack[depth];

rad_assert(da->flags.array);

p += 2;
value = p; /* Space for actual length */

/*
* Keep encoding as long as we have space to
* encode things.
*/
while (fr_sim_attr_sizes[da->type][0] <= ((size_t)(end - p))) {
VALUE_PAIR *vp;
ssize_t slen;

slen = encode_value(p, end - p, tlv_stack, depth, cursor, encoder_ctx);
if (slen < 0) return slen;

p += slen;

vp = fr_pair_cursor_current(cursor);
if (!vp || (vp->da != da)) break; /* Stop if we have an attribute of a different type */
}

actual_len = htons((p - value) & UINT16_MAX); /* Length of the elements we encoded */
memcpy(out, &actual_len, sizeof(actual_len));

/*
* Pad value a multiple of 4
*/
pad_len = (((p - value) + 3) & ~3) - (p - value);
if (pad_len) {
memset(p, 0, pad_len);
p += pad_len;
}

return p - out;
}

/** Encode an RFC format attribute header
*
* This could be a standard attribute, or a TLV data type.
Expand Down Expand Up @@ -487,9 +566,13 @@ static ssize_t encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const
* length.
*/
da = tlv_stack[depth];
slen = encode_value(out + 2, outlen - 2, tlv_stack, depth, cursor, encoder_ctx);
if (slen <= 0) return slen;

if (da->flags.array) {
slen = encode_array(out + 2, outlen - 2, tlv_stack, depth, cursor, encoder_ctx);
} else {
slen = encode_value(out + 2, outlen - 2, tlv_stack, depth, cursor, encoder_ctx);
}
if (slen <= 0) return slen;
/*
* Round attr + len + data length out to a multiple
* of four, and setup the attribute header and
Expand Down Expand Up @@ -668,10 +751,11 @@ ssize_t fr_sim_encode_pair(uint8_t *out, size_t outlen, vp_cursor_t *cursor, voi
* Fast path for the common case.
*/
if ((vp->da->parent == packet_ctx->root) && !vp->da->flags.concat && (vp->vp_type != FR_TYPE_TLV)) {
tlv_stack[0] = vp->da;
tlv_stack[1] = NULL;
tlv_stack[0] = packet_ctx->root;
tlv_stack[1] = vp->da;
tlv_stack[2] = NULL;
FR_PROTO_STACK_PRINT(tlv_stack, 0);
return encode_rfc_hdr(out, attr_len, tlv_stack, 0, cursor, encoder_ctx);
return encode_rfc_hdr(out, attr_len, tlv_stack, 1, cursor, encoder_ctx);
}

/*
Expand Down Expand Up @@ -772,8 +856,8 @@ ssize_t fr_sim_encode(REQUEST *request, fr_dict_attr_t const *parent, uint8_t ty
MEM(buff = talloc_array(eap_packet, uint8_t, 3));

buff[0] = subtype; /* SIM or AKA subtype */
buff[1] = 0; /* Reserved */
buff[2] = 0; /* Reserved */
buff[1] = 0; /* Reserved (0) */
buff[2] = 0; /* Reserved (1) */

eap_packet->type.length = 3;
eap_packet->type.data = buff;
Expand All @@ -786,9 +870,9 @@ ssize_t fr_sim_encode(REQUEST *request, fr_dict_attr_t const *parent, uint8_t ty
end = p + talloc_array_length(p);
if (do_hmac) end -= SIM_CALC_MAC_SIZE;

*p++ = subtype; /* Subtype (1) */
*p++ = 0; /* Reserved */
*p++ = 0; /* Reserved */
*p++ = subtype; /* Subtype */
*p++ = 0; /* Reserved (0) */
*p++ = 0; /* Reserved (1) */

/*
* Encode all the things...
Expand Down
3 changes: 3 additions & 0 deletions src/modules/rlm_eap/lib/sim/sim_proto.h
Expand Up @@ -163,6 +163,7 @@ typedef struct {

typedef struct _eap_session eap_session_t;

extern size_t const fr_sim_attr_sizes[FR_TYPE_MAX + 1][2];
extern fr_dict_attr_t const *dict_sim_root;
extern fr_dict_attr_t const *dict_aka_root;

Expand All @@ -186,6 +187,8 @@ ssize_t fr_sim_encode(REQUEST *request, fr_dict_attr_t const *parent, uint8_t t
/*
* base.c
*/
size_t fr_sim_attr_len(VALUE_PAIR const *vp);

char const *fr_sim_session_to_name(char *out, size_t outlen, eap_sim_client_states_t state);

int fr_sim_global_init(void);
Expand Down
13 changes: 13 additions & 0 deletions src/tests/unit/eap-sim.txt
Expand Up @@ -78,3 +78,16 @@ data 82 05 00 00 3f b8 34 1f f8 26 e0 4d 4a f3 f9 61 3c a9 84 26 0d 01 00 00 82

decode-pair.tp_decode_sim -
data EAP-SIM-Next-Pseudonym = "testing123", EAP-SIM-Any-ID-Req = yes, EAP-SIM-Counter-Too-Small = yes

# Array (one element)
encode-pair.tp_encode_sim EAP-SIM-Version-List = 1
data 0f 02 00 02 00 01 00 00

# Array (multiple elements, with padding)
encode-pair.tp_encode_sim EAP-SIM-Version-List = 1, EAP-SIM-Version-List = 2, EAP-SIM-Version-List = 3
data 0f 03 00 06 00 01 00 02 00 03 00 00

# Array (multiple elements, with no padding)
encode-pair.tp_encode_sim EAP-SIM-Version-List = 1, EAP-SIM-Version-List = 2, EAP-SIM-Version-List = 3, EAP-SIM-Version-List = 4
data 0f 03 00 08 00 01 00 02 00 03 00 04

0 comments on commit 0abefd8

Please sign in to comment.