and add a common context with secret, etc.
};
ssize_t fr_radius_encode_dbuff(fr_dbuff_t *dbuff, uint8_t const *original,
- char const *secret, UNUSED size_t secret_len, int code, int id, fr_pair_list_t *vps)
+ char const *secret, size_t secret_len, int code, int id, fr_pair_list_t *vps)
{
ssize_t slen;
fr_pair_t const *vp;
fr_dcursor_t cursor;
- fr_radius_ctx_t packet_ctx;
+ fr_radius_ctx_t common_ctx = {};
+ fr_radius_encode_ctx_t packet_ctx = {};
fr_dbuff_t work_dbuff, length_dbuff;
- memset(&packet_ctx, 0, sizeof(packet_ctx));
- packet_ctx.secret = secret;
+ common_ctx.secret = secret;
+ common_ctx.secret_length = secret_len;
+
+ packet_ctx.common = &common_ctx;
packet_ctx.rand_ctx.a = fr_rand();
packet_ctx.rand_ctx.b = fr_rand();
packet_ctx.disallow_tunnel_passwords = disallow_tunnel_passwords[code];
/*
* Callers in these cases have preloaded the buffer with the authentication vector.
*/
- FR_DBUFF_OUT_MEMCPY_RETURN(packet_ctx.vector, &work_dbuff, sizeof(packet_ctx.vector));
+ FR_DBUFF_OUT_MEMCPY_RETURN(common_ctx.vector, &work_dbuff, sizeof(common_ctx.vector));
break;
case FR_RADIUS_CODE_ACCESS_REJECT:
fr_strerror_const("Cannot encode response without request");
return -1;
}
- memcpy(packet_ctx.vector, original + 4, sizeof(packet_ctx.vector));
- FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, packet_ctx.vector, RADIUS_AUTH_VECTOR_LENGTH);
+ memcpy(common_ctx.vector, original + 4, sizeof(common_ctx.vector));
+ FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, common_ctx.vector, RADIUS_AUTH_VECTOR_LENGTH);
break;
case FR_RADIUS_CODE_ACCOUNTING_REQUEST:
* to say "don't do that!"
*/
case FR_RADIUS_CODE_COA_REQUEST:
- memset(packet_ctx.vector, 0, sizeof(packet_ctx.vector));
+ memset(common_ctx.vector, 0, sizeof(common_ctx.vector));
FR_DBUFF_MEMSET_RETURN(&work_dbuff, 0, RADIUS_AUTH_VECTOR_LENGTH);
break;
*/
ssize_t fr_radius_decode(TALLOC_CTX *ctx, fr_pair_list_t *out,
uint8_t const *packet, size_t packet_len, uint8_t const *original,
- char const *secret, UNUSED size_t secret_len)
+ char const *secret, size_t secret_len)
{
ssize_t slen;
uint8_t const *attr, *end;
- fr_radius_ctx_t packet_ctx;
+ fr_radius_ctx_t common_ctx = {};
+ fr_radius_decode_ctx_t packet_ctx = {};
+
+ common_ctx.secret = secret;
+ common_ctx.secret_length = secret_len;
+ memcpy(common_ctx.vector, original ? original + 4 : packet + 4, sizeof(common_ctx.vector));
- memset(&packet_ctx, 0, sizeof(packet_ctx));
+ packet_ctx.common = &common_ctx;
packet_ctx.tmp_ctx = talloc_init_const("tmp");
- packet_ctx.secret = secret;
packet_ctx.end = packet + packet_len;
- memcpy(packet_ctx.vector, original ? original + 4 : packet + 4, sizeof(packet_ctx.vector));
attr = packet + 20;
end = packet + packet_len;
size_t len;
ssize_t slen;
fr_dict_attr_t const *da;
- fr_radius_ctx_t *packet_ctx = decode_ctx;
+ fr_radius_decode_ctx_t *packet_ctx = decode_ctx;
#ifdef STATIC_ANALYZER
if (!packet_ctx || !packet_ctx->tmp_ctx) return PAIR_DECODE_FATAL_ERROR;
*/
static ssize_t decode_nas_filter_rule(TALLOC_CTX *ctx, fr_pair_list_t *out,
fr_dict_attr_t const *parent, uint8_t const *data,
- size_t const data_len, fr_radius_ctx_t *packet_ctx)
+ size_t const data_len, fr_radius_decode_ctx_t *packet_ctx)
{
uint8_t const *ptr = data;
uint8_t const *end = data + data_len;
*/
static ssize_t decode_digest_attributes(TALLOC_CTX *ctx, fr_pair_list_t *out,
fr_dict_attr_t const *parent, uint8_t const *data,
- size_t const data_len, fr_radius_ctx_t *packet_ctx)
+ size_t const data_len, fr_radius_decode_ctx_t *packet_ctx)
{
ssize_t slen;
fr_pair_t *vp;
*/
ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *out,
fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len,
- fr_radius_ctx_t *packet_ctx)
+ fr_radius_decode_ctx_t *packet_ctx)
{
uint8_t const *p = data, *end = data + data_len;
fr_dict_attr_t const *child;
static ssize_t decode_vsa_internal(TALLOC_CTX *ctx, fr_pair_list_t *out,
fr_dict_attr_t const *parent,
uint8_t const *data, size_t data_len,
- fr_radius_ctx_t *packet_ctx, fr_dict_vendor_t const *dv)
+ fr_radius_decode_ctx_t *packet_ctx, fr_dict_vendor_t const *dv)
{
unsigned int attribute;
ssize_t attrlen, my_len;
static ssize_t decode_extended_fragments(TALLOC_CTX *ctx, fr_pair_list_t *out,
fr_dict_attr_t const *parent,
uint8_t const *data, size_t attr_len,
- fr_radius_ctx_t *packet_ctx)
+ fr_radius_decode_ctx_t *packet_ctx)
{
ssize_t ret;
size_t fraglen;
static ssize_t decode_extended(TALLOC_CTX *ctx, fr_pair_list_t *out,
fr_dict_attr_t const *da,
uint8_t const *data, UNUSED size_t data_len,
- fr_radius_ctx_t *packet_ctx)
+ fr_radius_decode_ctx_t *packet_ctx)
{
ssize_t slen;
fr_dict_attr_t const *child;
static ssize_t decode_wimax(TALLOC_CTX *ctx, fr_pair_list_t *out,
fr_dict_attr_t const *parent,
uint8_t const *data, size_t attr_len,
- fr_radius_ctx_t *packet_ctx)
+ fr_radius_decode_ctx_t *packet_ctx)
{
ssize_t ret;
size_t wimax_len;
static ssize_t CC_HINT(nonnull) decode_vsa(TALLOC_CTX *ctx, fr_pair_list_t *out,
fr_dict_attr_t const *parent,
uint8_t const *data, size_t attr_len,
- fr_radius_ctx_t *packet_ctx)
+ fr_radius_decode_ctx_t *packet_ctx)
{
size_t total;
ssize_t ret;
fr_pair_t *vp = NULL;
uint8_t const *p = data;
uint8_t buffer[256];
- fr_radius_ctx_t *packet_ctx = decode_ctx;
+ fr_radius_decode_ctx_t *packet_ctx = decode_ctx;
if (attr_len > 128 * 1024) {
fr_strerror_printf("%s: packet is too large to be RADIUS", __FUNCTION__);
*/
case FLAG_ENCRYPT_USER_PASSWORD:
fr_radius_decode_password((char *)buffer, attr_len,
- packet_ctx->secret, packet_ctx->vector);
+ packet_ctx->common->secret, packet_ctx->common->vector);
buffer[253] = '\0';
/*
case FLAG_TAGGED_TUNNEL_PASSWORD:
case FLAG_ENCRYPT_TUNNEL_PASSWORD:
if (fr_radius_decode_tunnel_password(buffer, &data_len,
- packet_ctx->secret, packet_ctx->vector,
+ packet_ctx->common->secret, packet_ctx->common->vector,
packet_ctx->tunnel_password_zeros) < 0) {
goto raw;
}
*/
case FLAG_ENCRYPT_ASCEND_SECRET:
fr_radius_ascend_secret(&FR_DBUFF_TMP(buffer, sizeof(buffer)), p, data_len,
- packet_ctx->secret, packet_ctx->vector);
+ packet_ctx->common->secret, packet_ctx->common->vector);
buffer[RADIUS_AUTH_VECTOR_LENGTH] = '\0';
data_len = strlen((char *) buffer);
break;
*
*/
ssize_t fr_radius_decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out,
- uint8_t const *data, size_t data_len, fr_radius_ctx_t *packet_ctx)
+ uint8_t const *data, size_t data_len, fr_radius_decode_ctx_t *packet_ctx)
{
ssize_t ret;
fr_dict_attr_t const *da;
return 2 + ret;
}
-static int _test_ctx_free(fr_radius_ctx_t *ctx)
+static int _test_ctx_free(fr_radius_decode_ctx_t *ctx)
{
TALLOC_FREE(ctx->tags);
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
- fr_radius_ctx_t *test_ctx;
+ fr_radius_decode_ctx_t *test_ctx;
if (fr_radius_init() < 0) return -1;
- test_ctx = talloc_zero(ctx, fr_radius_ctx_t);
- test_ctx->secret = talloc_strdup(test_ctx, "testing123");
- memcpy(test_ctx->vector, vector, sizeof(test_ctx->vector));
+ test_ctx = talloc_zero(ctx, fr_radius_decode_ctx_t);
+ test_ctx->common = talloc_zero(test_ctx, fr_radius_ctx_t);
+
+ test_ctx->common->secret = talloc_strdup(test_ctx->common, "testing123");
+ test_ctx->common->secret_length = talloc_array_length(test_ctx->common->secret);
+
+ memcpy(test_ctx->common->vector, vector, sizeof(test_ctx->common->vector));
test_ctx->tmp_ctx = talloc_zero(test_ctx, uint8_t);
talloc_set_destructor(test_ctx, _test_ctx_free);
static ssize_t fr_radius_decode_proto(TALLOC_CTX *ctx, fr_pair_list_t *out,
uint8_t const *data, size_t data_len, void *proto_ctx)
{
- fr_radius_ctx_t *test_ctx = talloc_get_type_abort(proto_ctx, fr_radius_ctx_t);
+ fr_radius_decode_ctx_t *test_ctx = talloc_get_type_abort(proto_ctx, fr_radius_decode_ctx_t);
decode_fail_t reason;
fr_pair_t *vp;
size_t packet_len = data_len;
fr_pair_append(out, vp);
memset(original, 0, 4);
- memcpy(original + 4, test_ctx->vector, sizeof(test_ctx->vector));
+ memcpy(original + 4, test_ctx->common->vector, sizeof(test_ctx->common->vector));
test_ctx->end = data + packet_len;
return fr_radius_decode(ctx, out, data, packet_len, original,
- test_ctx->secret, talloc_array_length(test_ctx->secret) - 1);
+ test_ctx->common->secret, talloc_array_length(test_ctx->common->secret) - 1);
}
static ssize_t decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *out, NDEBUG_UNUSED fr_dict_attr_t const *parent,
- uint8_t const *data, size_t data_len, fr_radius_ctx_t *packet_ctx)
+ uint8_t const *data, size_t data_len, fr_radius_decode_ctx_t *packet_ctx)
{
fr_assert(parent == fr_dict_root(dict_radius));
uint8_t digest[RADIUS_AUTH_VECTOR_LENGTH];
uint8_t tpasswd[RADIUS_MAX_STRING_LENGTH];
size_t i, n;
- fr_radius_ctx_t *packet_ctx = encode_ctx;
+ fr_radius_encode_ctx_t *packet_ctx = encode_ctx;
uint32_t r;
size_t output_len, encrypted_len, padding;
ssize_t slen;
md5_ctx = fr_md5_ctx_alloc_from_list();
md5_ctx_old = fr_md5_ctx_alloc_from_list();
- fr_md5_update(md5_ctx, (uint8_t const *) packet_ctx->secret, talloc_array_length(packet_ctx->secret) - 1);
+ fr_md5_update(md5_ctx, (uint8_t const *) packet_ctx->common->secret, talloc_array_length(packet_ctx->common->secret) - 1);
fr_md5_ctx_copy(md5_ctx_old, md5_ctx);
- fr_md5_update(md5_ctx, packet_ctx->vector, RADIUS_AUTH_VECTOR_LENGTH);
+ fr_md5_update(md5_ctx, packet_ctx->common->vector, RADIUS_AUTH_VECTOR_LENGTH);
fr_md5_update(md5_ctx, &tpasswd[0], 2);
/*
size_t len;
fr_pair_t const *vp = fr_dcursor_current(cursor);
fr_dict_attr_t const *da = da_stack->da[depth];
- fr_radius_ctx_t *packet_ctx = encode_ctx;
+ fr_radius_encode_ctx_t *packet_ctx = encode_ctx;
fr_dbuff_t work_dbuff = FR_DBUFF(dbuff);
fr_dbuff_t value_dbuff;
fr_dbuff_marker_t value_start, src, dest;
* Encode the password in place
*/
slen = encode_password(&work_dbuff, &value_start, fr_dbuff_used(&value_dbuff),
- packet_ctx->secret, packet_ctx->vector);
+ packet_ctx->common->secret, packet_ctx->common->vector);
if (slen < 0) return slen;
encrypted = true;
break;
* there can pass a marker so we can use it here, too.
*/
slen = fr_radius_ascend_secret(&work_dbuff, fr_dbuff_current(&value_start), fr_dbuff_used(&value_dbuff),
- packet_ctx->secret, packet_ctx->vector);
+ packet_ctx->common->secret, packet_ctx->common->vector);
if (slen < 0) return slen;
encrypted = true;
break;
* Tags are *top-level*, and are never nested.
*/
if (vp->vp_type == FR_TYPE_GROUP) {
- fr_radius_ctx_t *packet_ctx = encode_ctx;
+ fr_radius_encode_ctx_t *packet_ctx = encode_ctx;
if (!vp->da->flags.internal ||
!((vp->da->attr > FR_TAG_BASE) && (vp->da->attr < (FR_TAG_BASE + 0x20)))) {
return fr_dbuff_set(dbuff, &work_dbuff);
}
-static int _test_ctx_free(UNUSED fr_radius_ctx_t *ctx)
+static int _test_ctx_free(UNUSED fr_radius_encode_ctx_t *ctx)
{
fr_radius_free();
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
- fr_radius_ctx_t *test_ctx;
+ fr_radius_encode_ctx_t *test_ctx;
if (fr_radius_init() < 0) return -1;
- test_ctx = talloc_zero(ctx, fr_radius_ctx_t);
+ test_ctx = talloc_zero(ctx, fr_radius_encode_ctx_t);
if (!test_ctx) return -1;
- test_ctx->secret = talloc_strdup(test_ctx, "testing123");
- memcpy(test_ctx->vector, vector, sizeof(test_ctx->vector));
+ test_ctx->common = talloc_zero(test_ctx, fr_radius_ctx_t);
+
+ test_ctx->common->secret = talloc_strdup(test_ctx->common, "testing123");
+ test_ctx->common->secret_length = talloc_array_length(test_ctx->common->secret);
+
+ memcpy(test_ctx->common->vector, vector, sizeof(test_ctx->common->vector));
test_ctx->rand_ctx.a = 6809;
test_ctx->rand_ctx.b = 2112;
talloc_set_destructor(test_ctx, _test_ctx_free);
static ssize_t fr_radius_encode_proto(UNUSED TALLOC_CTX *ctx, fr_pair_list_t *vps, uint8_t *data, size_t data_len, void *proto_ctx)
{
- fr_radius_ctx_t *test_ctx = talloc_get_type_abort(proto_ctx, fr_radius_ctx_t);
+ fr_radius_encode_ctx_t *packet_ctx = talloc_get_type_abort(proto_ctx, fr_radius_encode_ctx_t);
int packet_type = FR_RADIUS_CODE_ACCESS_REQUEST;
fr_pair_t *vp;
ssize_t slen;
int i;
for (i = 0; i < RADIUS_AUTH_VECTOR_LENGTH; i++) {
- data[4 + i] = fr_fast_rand(&test_ctx->rand_ctx);
+ data[4 + i] = fr_fast_rand(&packet_ctx->rand_ctx);
}
}
}
/*
- * @todo - pass in test_ctx to this function, so that we
+ * @todo - pass in packet_ctx to this function, so that we
* can leverage a consistent random number generator.
*/
- slen = fr_radius_encode(data, data_len, NULL, test_ctx->secret, talloc_array_length(test_ctx->secret) - 1,
+ slen = fr_radius_encode(data, data_len, NULL, packet_ctx->common->secret, talloc_array_length(packet_ctx->common->secret) - 1,
packet_type, 0, vps);
if (slen <= 0) return slen;
- if (fr_radius_sign(data, NULL, (uint8_t const *) test_ctx->secret, talloc_array_length(test_ctx->secret) - 1) < 0) {
+ if (fr_radius_sign(data, NULL, (uint8_t const *) packet_ctx->common->secret, talloc_array_length(packet_ctx->common->secret) - 1) < 0) {
return -1;
}
uint8_t *ptr;
radius_packet_t *hdr;
fr_pair_list_t tmp_list;
- fr_radius_ctx_t packet_ctx = {
- .secret = secret,
- .tunnel_password_zeros = tunnel_password_zeros
- };
+ fr_radius_ctx_t common_ctx = {};
+ fr_radius_decode_ctx_t packet_ctx = {};
+
+ common_ctx.secret = secret;
+ common_ctx.secret_length = strlen(secret);
+
+ packet_ctx.common = &common_ctx;
+ packet_ctx.tunnel_password_zeros = tunnel_password_zeros;
#ifndef NDEBUG
if (fr_debug_lvl >= L_DBG_LVL_4) fr_radius_packet_log_hex(&default_log, packet);
switch (packet->code) {
case FR_RADIUS_CODE_ACCESS_REQUEST:
case FR_RADIUS_CODE_STATUS_SERVER:
- memcpy(packet_ctx.vector, packet->vector, sizeof(packet_ctx.vector));
+ memcpy(common_ctx.vector, packet->vector, sizeof(common_ctx.vector));
break;
case FR_RADIUS_CODE_ACCESS_ACCEPT:
* radsniff doesn't always have a response
*/
if (original) {
- memcpy(packet_ctx.vector, original->vector, sizeof(packet_ctx.vector));
+ memcpy(common_ctx.vector, original->vector, sizeof(common_ctx.vector));
} else {
memset(packet->vector, 0, sizeof(packet->vector));
- memset(packet_ctx.vector, 0, sizeof(packet_ctx.vector));
+ memset(common_ctx.vector, 0, sizeof(common_ctx.vector));
}
break;
case FR_RADIUS_CODE_COA_REQUEST:
case FR_RADIUS_CODE_DISCONNECT_REQUEST:
memset(packet->vector, 0, sizeof(packet->vector));
- memset(packet_ctx.vector, 0, sizeof(packet_ctx.vector));
+ memset(common_ctx.vector, 0, sizeof(common_ctx.vector));
break;
default:
} fr_radius_tag_ctx_t;
typedef struct {
- TALLOC_CTX *tmp_ctx; //!< for temporary things cleaned up during decoding
- uint8_t vector[RADIUS_AUTH_VECTOR_LENGTH]; //!< vector for encryption / decryption of data
- char const *secret; //!< shared secret. MUST be talloc'd
+ char const *secret;
+ size_t secret_length;
+
+ bool add_proxy_state; //!< do we add a Proxy-State?
+ uint64_t my_proxy_state; //!< if so, this is its value
+
+ uint32_t acct_delay_time; //!< additional time to add to acct_delay_time
+
+ uint8_t vector[RADIUS_AUTH_VECTOR_LENGTH]; //!< vector for authenticating the reply
+} fr_radius_ctx_t;
+
+typedef struct {
+ fr_radius_ctx_t *common;
+
fr_fast_rand_t rand_ctx; //!< for tunnel passwords
- uint8_t const *end; //!< end of the packet
int salt_offset; //!< for tunnel passwords
- bool tunnel_password_zeros; //!< check for trailing zeros on decode
- bool disallow_tunnel_passwords; //!< not all packets can have tunnel passwords
uint8_t tag; //!< current tag for encoding
+ bool disallow_tunnel_passwords; //!< not all packets can have tunnel passwords
+ bool seen_message_authenticator;
+} fr_radius_encode_ctx_t;
+
+typedef struct {
+ fr_radius_ctx_t *common;
+
+ TALLOC_CTX *tmp_ctx; //!< for temporary things cleaned up during decoding
+ uint8_t const *end; //!< end of the packet
+
+ bool tunnel_password_zeros; //!< check for trailing zeros on decode
+
fr_radius_tag_ctx_t **tags; //!< for decoding tagged attributes
fr_pair_list_t *tag_root; //!< Where to insert tag attributes.
TALLOC_CTX *tag_root_ctx; //!< Where to allocate new tag attributes.
-} fr_radius_ctx_t;
+} fr_radius_decode_ctx_t;
/*
* protocols/radius/abinary.c
ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_pair_list_t *list,
fr_dict_attr_t const *parent,
uint8_t const *data, size_t data_len,
- fr_radius_ctx_t *packet_ctx) CC_HINT(nonnull);
+ fr_radius_decode_ctx_t *packet_ctx) CC_HINT(nonnull);
ssize_t fr_radius_decode_pair(TALLOC_CTX *ctx, fr_pair_list_t *list,
- uint8_t const *data, size_t data_len, fr_radius_ctx_t *packet_ctx) CC_HINT(nonnull);
+ uint8_t const *data, size_t data_len, fr_radius_decode_ctx_t *packet_ctx) CC_HINT(nonnull);