26 #include <freeradius-devel/libradius.h>
27 #include <freeradius-devel/md5.h>
61 if ((packet == NULL) || (password == NULL))
return -1;
75 memcpy(ptr, password->vp_strvalue, password->vp_length);
76 ptr += password->vp_length;
77 i += password->vp_length;
85 memcpy(ptr, challenge->vp_strvalue, challenge->vp_length);
86 i += challenge->vp_length;
93 fr_md5_calc((uint8_t *)output + 1, (uint8_t *)
string, i);
116 if (len > 127) len = 127;
122 for (n = len ; n >= 0 ; n--) passwd[n + 3] = passwd[n];
151 for (; n > 0; n--, len++) passwd[len] = 0;
159 secretlen = strlen(secret);
160 memcpy(buffer, secret, secretlen);
171 for (i = 0; i <
AUTH_PASS_LEN; i++) passwd[i + n2] ^= digest[i];
204 if (len > 128) len = 128;
210 memset(&passwd[len], 0, AUTH_PASS_LEN - (len % AUTH_PASS_LEN));
218 secretlen = strlen(secret);
221 fr_md5_update(&context, (uint8_t
const *) secret, secretlen);
234 fr_md5_update(&context, (uint8_t *) passwd + n - AUTH_PASS_LEN, AUTH_PASS_LEN);
238 for (i = 0; i <
AUTH_PASS_LEN; i++) passwd[i + n] ^= digest[i];
244 static void encode_password(uint8_t *out, ssize_t *outlen, uint8_t
const *input,
size_t inlen,
245 char const *
secret, uint8_t
const *vector)
260 memcpy(passwd, input, len);
261 if (len <
sizeof(passwd)) memset(passwd + len, 0,
sizeof(passwd) - len);
264 else if ((len & 0x0f) != 0) {
271 fr_md5_update(&context, (uint8_t
const *) secret, strlen(secret));
286 for (i = 0; i <
AUTH_PASS_LEN; i++) passwd[i + n] ^= digest[i];
289 memcpy(out, passwd, len);
294 uint8_t
const *input,
size_t inlen,
size_t freespace,
295 char const *
secret, uint8_t
const *vector)
300 size_t encrypted_len;
306 if (freespace > 253) freespace = 253;
314 if (inlen > (freespace - 3)) inlen = freespace - 3;
323 encrypted_len = inlen + 1;
324 if ((encrypted_len & 0x0f) != 0) {
325 encrypted_len += 0x0f;
326 encrypted_len &= ~0x0f;
333 if (encrypted_len > (freespace - 2)) encrypted_len = freespace - 2;
335 *outlen = encrypted_len + 2;
340 memcpy(out + 3, input, inlen);
341 memset(out + 3 + inlen, 0, *outlen - 3 - inlen);
357 fr_md5_update(&context, (uint8_t
const *) secret, strlen(secret));
375 block_len = freespace - 2 - n;
378 for (i = 0; i < block_len; i++) out[i + 2 + n] ^= digest[i];
404 buffer = fr_thread_local_init(fr_radius_encode_value_hton_buff, free);
408 buffer = malloc(
sizeof(uint8_t) *
sizeof(
value_data_t));
410 fr_strerror_printf(
"Failed allocating memory for fr_radius_encode_value_hton buffer");
414 ret = fr_thread_local_set(fr_radius_encode_value_hton_buff, buffer);
416 fr_strerror_printf(
"Failed setting up TLS for fr_radius_encode_value_hton buffer: %s", strerror(errno));
427 memcpy(out, &vp->
data.ptr,
sizeof(*out));
442 void const *p = &vp->
data;
443 memcpy(out, &p,
sizeof(*out));
448 buffer[0] = vp->vp_byte & 0x01;
453 buffer[0] = vp->vp_byte & 0xff;
458 buffer[0] = (vp->vp_short >> 8) & 0xff;
459 buffer[1] = vp->vp_short & 0xff;
464 lvalue = htonl(vp->vp_integer);
465 memcpy(buffer, &lvalue,
sizeof(lvalue));
470 lvalue64 = htonll(vp->vp_integer64);
471 memcpy(buffer, &lvalue64,
sizeof(lvalue64));
476 lvalue = htonl(vp->vp_date);
477 memcpy(buffer, &lvalue,
sizeof(lvalue));
483 int32_t slvalue = htonl(vp->vp_signed);
484 memcpy(buffer, &slvalue,
sizeof(slvalue));
506 return vp->vp_length;
518 while (outlen >= 5) {
525 len =
encode_tlv_hdr(p, outlen, tlv_stack, depth + 1, cursor, encoder_ctx);
530 if (len < 0)
return len;
531 if (len == 0)
return out[1];
546 if (da != tlv_stack[depth])
break;
570 if (!tlv_stack[depth + 1]) {
575 if (outlen < 5)
return 0;
580 out[0] = tlv_stack[depth]->
attr & 0xff;
584 if (len <= 0)
return len;
585 if (len > 253)
return 0;
620 return encode_tlv_hdr(out, outlen, tlv_stack, depth, cursor, encoder_ctx);
627 if (tlv_stack[depth + 1] != NULL) {
678 data = (uint8_t
const *) &vp->
data;
683 array[0] = vp->vp_byte;
689 array[0] = (vp->vp_short >> 8) & 0xff;
690 array[1] = vp->vp_short & 0xff;
696 lvalue = htonl(vp->vp_integer);
697 memcpy(array, &lvalue,
sizeof(lvalue));
703 lvalue64 = htonll(vp->vp_integer64);
704 data = (uint8_t *) &lvalue64;
711 lvalue = htonl(vp->vp_date);
712 data = (uint8_t
const *) &lvalue;
721 slvalue = htonl(vp->vp_signed);
722 memcpy(array, &slvalue,
sizeof(slvalue));
744 if (len > (ssize_t)outlen) len = outlen;
758 case FLAG_ENCRYPT_USER_PASSWORD:
762 case FLAG_ENCRYPT_TUNNEL_PASSWORD:
773 if (outlen < (18 + lvalue))
return 0;
780 if (!ctx->
original)
goto no_ctx_error;
801 case FLAG_ENCRYPT_ASCEND_SECRET:
802 if (len != 16)
return 0;
810 if (len > ((ssize_t) (outlen - 1))) len = outlen - 1;
817 memcpy(ptr, data, len);
827 return len + (ptr - out);
830 static ssize_t
attr_shift(uint8_t
const *start, uint8_t
const *end,
831 uint8_t *ptr,
int hdr_len, ssize_t len,
832 int flag_offset,
int vsa_offset)
834 int check_len = len - ptr[1];
835 int total = len + hdr_len;
843 while (check_len > (255 - hdr_len)) {
845 check_len -= (255 - hdr_len);
855 if ((ptr + ptr[1] + total) > end)
return (ptr + ptr[1]) - start;
863 int sublen = 255 - ptr[1];
865 if (len <= sublen)
break;
868 memmove(ptr + 255 + hdr_len, ptr + 255, sublen);
869 memmove(ptr + 255, ptr, hdr_len);
871 if (vsa_offset) ptr[vsa_offset] += sublen;
872 ptr[flag_offset] |= 0x80;
876 if (vsa_offset) ptr[vsa_offset] = 3;
880 if (vsa_offset) ptr[vsa_offset] += len;
882 return (ptr + ptr[1]) - start;
894 uint8_t *start = out;
909 out[0] = tlv_stack[depth++]->
attr & 0xff;
915 if (outlen < 3)
return 0;
918 out[2] = tlv_stack[depth]->
attr & 0xff;
921 if (outlen < 4)
return 0;
924 out[2] = tlv_stack[depth]->
attr & 0xff;
935 uint8_t *evs = out + out[1];
938 if (outlen < (
size_t) (out[1] + 5))
return 0;
942 lvalue = htonl(tlv_stack[depth++]->attr);
943 memcpy(evs, &lvalue, 4);
945 evs[4] = tlv_stack[depth]->
attr & 0xff;
959 len =
encode_value(out + out[1], outlen - hdr_len, tlv_stack, depth, cursor, encoder_ctx);
961 if (len <= 0)
return len;
969 if (len > (255 - out[1])) {
971 return attr_shift(start, start + outlen, out, 4, len, 3, 0);
974 len = (255 - out[1]);
983 fprintf(
fr_log_fp,
"\t\t%02x %02x ", out[0], out[1]);
988 fprintf(
fr_log_fp,
"%02x %02x ", out[2], out[3]);
993 fprintf(
fr_log_fp,
"%02x%02x%02x%02x (%u) %02x ",
994 out[jump], out[jump + 1],
995 out[jump + 2], out[jump + 3],
996 ((out[jump + 1] << 16) |
997 (out[jump + 2] << 8) |
1007 return (out + out[1]) - start;
1027 len = vp->vp_length;
1030 if (outlen <= 2)
break;
1032 ptr[0] = tlv_stack[depth]->
attr & 0xff;
1038 if (left > 253) left = 253;
1041 if (outlen < (left + 2)) left = outlen - 2;
1043 memcpy(ptr + 2, p, left);
1047 fprintf(
fr_log_fp,
"\t\t%02x %02x ", ptr[0], ptr[1]);
1083 switch (tlv_stack[depth]->type) {
1090 if (((tlv_stack[depth]->vendor == 0) && (tlv_stack[depth]->attr == 0)) ||
1091 (tlv_stack[depth]->attr > 255)) {
1093 tlv_stack[depth]->attr);
1099 if (outlen <= 2)
return 0;
1101 out[0] = tlv_stack[depth]->
attr & 0xff;
1104 if (outlen > ((
unsigned) 255 - out[1])) outlen = 255 - out[1];
1106 len =
encode_value(out + out[1], outlen, tlv_stack, depth, cursor, encoder_ctx);
1107 if (len <= 0)
return len;
1113 fprintf(
fr_log_fp,
"\t\t%02x %02x ", out[0], out[1]);
1136 dv = tlv_stack[depth++];
1143 da = tlv_stack[depth];
1162 out[1] = (da->
attr >> 16) & 0xff;
1163 out[2] = (da->
attr >> 8) & 0xff;
1164 out[3] = da->
attr & 0xff;
1168 out[0] = (da->
attr >> 8) & 0xff;
1169 out[1] = da->
attr & 0xff;
1173 out[0] = da->
attr & 0xff;
1196 if (outlen > ((
unsigned) 255 - hdr_len)) outlen = 255 - hdr_len;
1206 len =
encode_value(out + hdr_len, outlen, tlv_stack, depth, cursor, encoder_ctx);
1209 if (len <= 0)
return len;
1221 fprintf(
fr_log_fp,
"\t\t%02x%02x%02x%02x ", out[0], out[1], out[2], out[3]);
1254 return hdr_len + len;
1267 uint8_t *start = out;
1277 if (outlen < 9)
return 0;
1279 if (tlv_stack[depth++]->attr != PW_VENDOR_SPECIFIC) {
1280 fr_strerror_printf(
"%s: level[1] of tlv_stack is incorrect, must be Vendor-Specific (26)",
1287 fr_strerror_printf(
"%s: level[2] of tlv_stack is incorrect, must be Wimax vendor %i", __FUNCTION__,
1297 out[0] = PW_VENDOR_SPECIFIC;
1300 memcpy(out + 2, &lvalue, 4);
1305 out[6] = tlv_stack[depth]->
attr;
1312 if (len <= 0)
return len;
1314 len =
encode_value(out + out[1], outlen - hdr_len, tlv_stack, depth, cursor, encoder_ctx);
1315 if (len <= 0)
return len;
1324 if (len > (255 - out[1])) {
1325 return attr_shift(start, start + outlen, out, hdr_len, len, 8, 7);
1333 fprintf(
fr_log_fp,
"\t\t%02x %02x %02x%02x%02x%02x (%u) %02x %02x %02x ",
1335 out[2], out[3], out[4], out[5],
1336 (out[3] << 16) | (out[4] << 8) | out[5],
1337 out[6], out[7], out[8]);
1342 return (out + out[1]) - start;
1372 if (outlen < 6)
return 0;
1377 out[0] = PW_VENDOR_SPECIFIC;
1383 da = tlv_stack[++depth];
1392 lvalue = htonl(da->
attr);
1393 memcpy(out + 2, &lvalue, 4);
1395 if (outlen > ((
unsigned) 255 - out[1])) outlen = 255 - out[1];
1398 if (len < 0)
return len;
1402 fprintf(
fr_log_fp,
"\t\t%02x %02x %02x%02x%02x%02x (%u) ",
1404 out[2], out[3], out[4], out[5],
1405 (out[3] << 16) | (out[4] << 8) | out[5]);
1428 switch (tlv_stack[depth]->type) {
1439 if (((tlv_stack[depth]->vendor == 0) && (tlv_stack[depth]->attr == 0)) ||
1440 (tlv_stack[depth]->attr > 255)) {
1451 if ((vp->vp_length == 0) && (vp->
da->
attr == PW_CHARGEABLE_USER_IDENTITY)) {
1452 out[0] = PW_CHARGEABLE_USER_IDENTITY;
1463 if (!vp->
da->
vendor && (vp->
da->
attr == PW_MESSAGE_AUTHENTICATOR)) {
1464 if (outlen < 18)
return -1;
1466 out[0] = PW_MESSAGE_AUTHENTICATOR;
1468 memset(out + 2, 0, 16);
1497 if (!cursor || !out || (outlen <= 2))
return -1;
1519 attr_len = (outlen > UINT8_MAX) ? UINT8_MAX : outlen;
1525 tlv_stack[0] = vp->
da;
1526 tlv_stack[1] = NULL;
1528 return encode_rfc_hdr(out, attr_len, tlv_stack, 0, cursor, encoder_ctx);
1541 ret =
encode_rfc_hdr(out, attr_len, tlv_stack, 0, cursor, encoder_ctx);
1549 ret =
encode_concat(out, outlen, tlv_stack, 0, cursor, encoder_ctx);
1555 ret =
encode_vsa_hdr(out, attr_len, tlv_stack, 0, cursor, encoder_ctx);
1569 ret =
encode_tlv_hdr(out, attr_len, tlv_stack, 0, cursor, encoder_ctx);
1595 if (ret < 0)
return ret;
1601 fr_strerror_printf(
"%s: Nested attribute structure too large to encode", __FUNCTION__);
static void encode_tunnel_password(uint8_t *out, ssize_t *outlen, uint8_t const *input, size_t inlen, size_t freespace, char const *secret, uint8_t const *vector)
static int encode_vsa_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, unsigned int depth, vp_cursor_t *cursor, void *encoder_ctx)
Encode a Vendor-Specific attribute.
void fr_md5_calc(uint8_t *out, uint8_t const *in, size_t inlen)
Calculate the MD5 hash of the contents of a buffer.
static int encode_extended_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, unsigned int depth, vp_cursor_t *cursor, void *encoder_ctx)
Encode an "extended" attribute.
static ssize_t encode_value(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, int depth, vp_cursor_t *cursor, void *encoder_ctx)
Encodes the data portion of an attribute.
static ssize_t encode_concat(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, unsigned int depth, vp_cursor_t *cursor, UNUSED void *encoder_ctx)
Encode an RFC format attribute, with the "concat" flag set.
Time value (struct timeval), only for config items.
static unsigned int salt_offset
RFC2865 - Access-Challenge.
#define PW_TYPE_STRUCTURAL
Match all non value types in case statements.
ssize_t fr_radius_encode_value_hton(uint8_t const **out, VALUE_PAIR const *vp)
Converts vp_data to network byte order.
uint32_t fr_rand(void)
Return a 32-bit random number.
Ascend binary format a packed data structure.
WiMAX IPv4 or IPv6 address depending on length.
uint8_t length
length of the attribute
void fr_radius_make_secret(uint8_t *digest, uint8_t const *vector, char const *secret, uint8_t const *value)
Build an encrypted secret value to return in a reply packet.
int fr_radius_encode_pair(uint8_t *out, size_t outlen, vp_cursor_t *cursor, void *encoder_ctx)
Encode a data structure into a RADIUS attribute.
int8_t tag
Tag value used to group valuepairs.
void fr_md5_init(FR_MD5_CTX *ctx)
Initialise a new MD5 context.
#define FR_DICT_MAX_TLV_STACK
Maximum TLV stack size.
Number of defined data types.
fr_thread_local_setup(uint8_t *, fr_radius_encode_value_hton_buff)
Long extended attribute space attribute.
unsigned int depth
Depth of nesting for this attribute.
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
fr_dict_attr_flags_t flags
Flags.
WiMAX IPv4 or IPv6 address prefix depending on length.
void fr_md5_update(FR_MD5_CTX *ctx, uint8_t const *in, size_t inlen) CC_BOUNDED(__string__
static int encode_wimax_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, unsigned int depth, vp_cursor_t *cursor, void *encoder_ctx)
Encode a WiMAX attribute.
static ssize_t attr_shift(uint8_t const *start, uint8_t const *end, uint8_t *ptr, int hdr_len, ssize_t len, int flag_offset, int vsa_offset)
const FR_NAME_NUMBER dict_attr_types[]
Map data types to names representing those types.
RFC2866 - Accounting-Request.
Double precision floating point.
unsigned int attr
Attribute number.
int fr_radius_encode_chap_password(uint8_t *output, RADIUS_PACKET *packet, int id, VALUE_PAIR *password)
unsigned int code
Packet code (type).
unsigned int vendor
Vendor that defines this attribute.
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const * parent
Immediate parent of this attribute.
VALUE_PAIR * fr_cursor_current(vp_cursor_t *cursor)
Return the VALUE_PAIR the cursor current points to.
enum attr_flags::@0 encrypt
Attribute that represents a vendor in the attribute tree.
unsigned int is_root
Is root of a dictionary.
unsigned int concat
concatenate multiple instances
Invalid (uninitialised) attribute type.
RFC3575/RFC5176 - CoA-Request.
uint8_t vector[AUTH_VECTOR_LEN]
RADIUS authentication vector.
static int encode_rfc_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, unsigned int depth, vp_cursor_t *cursor, void *encoder_ctx)
Encode an RFC standard attribute 1..255.
#define FR_PROTO_HEX_DUMP(_x, _y, _z)
static ssize_t encode_tlv_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, unsigned int depth, vp_cursor_t *cursor, void *encoder_ctx)
#define FR_PROTO_STACK_PRINT(_x, _y)
RADIUS_PACKET const * original
Vendor-Specific, for RADIUS attribute 26.
char name[1]
Attribute name.
Extended attribute space attribute.
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
#define fr_md5_copy(_out, _in)
static ssize_t encode_rfc_hdr_internal(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, unsigned int depth, vp_cursor_t *cursor, void *encoder_ctx)
Encode an RFC format TLV.
static ssize_t encode_tlv_hdr_internal(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, unsigned int depth, vp_cursor_t *cursor, void *encoder_ctx)
static char const * secret
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
unsigned int has_tag
Tagged attribute.
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
void void fr_md5_final(uint8_t out[MD5_DIGEST_LENGTH], FR_MD5_CTX *ctx) CC_BOUNDED(__minbytes__
int fr_radius_encode_password(char *passwd, size_t *pwlen, char const *secret, uint8_t const *vector)
Encode password.
char const * fr_int2str(FR_NAME_NUMBER const *table, int number, char const *def)
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
RADIUS_PACKET const * packet
uint8_t type_size
for TLV2, size of the type
String of printable characters.
Contains nested attributes.
void fr_proto_tlv_stack_build(fr_dict_attr_t const **tlv_stack, fr_dict_attr_t const *da)
static ssize_t encode_vendor_attr_hdr(uint8_t *out, size_t outlen, fr_dict_attr_t const **tlv_stack, unsigned int depth, vp_cursor_t *cursor, void *encoder_ctx)
Encode a VSA which is a TLV.
int fr_radius_encode_tunnel_password(char *passwd, size_t *pwlen, char const *secret, uint8_t const *vector)
Encode Tunnel-Password attributes when sending them out on the wire.
static void encode_password(uint8_t *out, ssize_t *outlen, uint8_t const *input, size_t inlen, char const *secret, uint8_t const *vector)
Extended attribute, vendor specific.
RFC3575/RFC5176 - Disconnect-Request.