24 RCSID(
"$Id: f37ba0e59ee4634d97d2c95375d138cb3cdba6bf $")
51 unsigned int remaining = data_len;
53 while (remaining > 0) {
56 if (remaining < hdr_len) {
57 RDEBUG2(
"Diameter attribute is too small (%u) to contain a Diameter header", remaining);
61 memcpy(&attr, data,
sizeof(attr));
63 memcpy(&length, data + 4,
sizeof(length));
64 length = ntohl(length);
66 if ((data[4] & 0x80) != 0) {
68 RDEBUG2(
"Diameter attribute is too small to contain a Diameter header with Vendor-Id");
83 if (length <= (hdr_len - 4)) {
84 RDEBUG2(
"Tunneled attribute %u is too short (%u < %u) to contain anything useful.", attr,
89 if (length > remaining) {
90 RDEBUG2(
"Tunneled attribute %u is longer than room remaining in the packet (%u > %u).", attr,
99 if (remaining == length)
break;
116 if (remaining < length) {
117 REDEBUG2(
"Diameter attribute overflows packet!");
139 uint8_t
const *
data,
size_t data_len)
146 size_t data_left = data_len;
154 while (data_left > 0) {
156 memcpy(&attr, data,
sizeof(attr));
161 memcpy(&length, data,
sizeof(length));
163 length = ntohl(length);
170 if ((length & ((uint32_t)1 << 31)) != 0) {
171 memcpy(&vendor, data,
sizeof(vendor));
172 vendor = ntohl(vendor);
177 if (attr > 65535)
goto next_attr;
189 length &= 0x00ffffff;
195 size = length - offset;
201 if ((attr > 255) && (vendor == 0)) {
202 RWDEBUG2(
"Skipping Diameter attribute %u", attr);
215 if ((size > 253) && !((vendor == 0) && (attr == PW_EAP_MESSAGE))) {
216 RWDEBUG2(
"diameter2vp skipping long attribute %u", attr);
227 if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
232 buffer[0] = PW_VENDOR_SPECIFIC;
233 buffer[1] = size + 2;
234 memcpy(buffer + 2, data, size);
238 buffer, size + 2, NULL);
240 REDEBUG2(
"diameter2vp failed decoding attr: %s",
245 if ((
size_t) decoded != size + 2) {
246 REDEBUG2(
"diameter2vp failed to entirely decode VSA");
262 RDEBUG2(
"Failure in creating VP");
276 if (size != vp->vp_length) {
286 if (!da)
return NULL;
288 if (!vp)
return NULL;
292 memcpy(&vp->vp_integer, data, vp->vp_length);
297 vp->vp_integer = ntohl(vp->vp_integer);
301 if (size != vp->vp_length)
goto raw;
302 memcpy(&vp->vp_integer64, data, vp->vp_length);
307 vp->vp_integer64 = ntohll(vp->vp_integer64);
311 if (size != vp->vp_length) {
312 RDEBUG2(
"Invalid length attribute %d",
318 memcpy(&vp->vp_ipaddr, data, vp->vp_length);
326 if (size != vp->vp_length)
goto raw;
327 vp->vp_byte = data[0];
331 if (size != vp->vp_length)
goto raw;
332 vp->vp_short = (data[0] * 256) + data[1];
336 if (size != vp->vp_length)
goto raw;
337 memcpy(&vp->vp_signed, data, vp->vp_length);
338 vp->vp_signed = ntohl(vp->vp_signed);
342 if (size != vp->vp_length)
goto raw;
343 memcpy(&vp->vp_ipv6addr, data, vp->vp_length);
347 if (size != vp->vp_length)
goto raw;
348 memcpy(vp->vp_ipv6prefix, data, vp->vp_length);
353 vp->vp_length = strlen(vp->vp_strvalue);
387 if (((vp->
da->
vendor == 0) && (vp->
da->
attr == PW_CHAP_CHALLENGE)) ||
389 uint8_t challenge[16];
391 if ((vp->vp_length < 8) ||
392 (vp->vp_length > 16)) {
393 RDEBUG(
"Tunneled challenge has invalid length");
402 if (memcmp(challenge, vp->vp_octets,
403 vp->vp_length) != 0) {
404 RDEBUG(
"Tunneled challenge is incorrect");
420 if (data_left == length)
break;
432 data += length - offset;
456 uint8_t buffer[4096];
473 if ((total + vp->vp_length + 12) >=
sizeof(buffer)) {
474 RDEBUG2(
"output buffer is full!");
483 length = vp->vp_length;
486 attr = vp->
da->
attr & 0xffff;
487 length |= ((uint32_t)1 << 31);
499 memcpy(p, &attr,
sizeof(attr));
508 length = ntohl(length);
509 memcpy(p, &length,
sizeof(length));
513 vendor = ntohl(vendor);
514 memcpy(p, &vendor,
sizeof(vendor));
518 length = ntohl(length);
519 memcpy(p, &length,
sizeof(length));
527 attr = htonl(vp->vp_integer);
528 memcpy(p, &attr,
sizeof(attr));
533 attr64 = htonll(vp->vp_integer64);
534 memcpy(p, &attr64,
sizeof(attr64));
539 memcpy(p, &vp->vp_ipaddr, 4);
546 memcpy(p, vp->vp_strvalue, vp->vp_length);
547 length = vp->vp_length;
560 if ((total & 0x03) != 0) {
563 length = 4 - (total & 0x03);
564 for (i = 0; i <
length; i++) {
580 for (i = 0; i < total; i++) {
581 if ((i & 0x0f) == 0) fprintf(
fr_log_fp,
" TTLS tunnel data out %04x: ", (
int) i);
585 if ((i & 0x0f) == 0x0f) fprintf(
fr_log_fp,
"\n");
587 if ((total & 0x0f) != 0) fprintf(
fr_log_fp,
"\n");
591 (tls_session->record_from_buff)(&tls_session->clean_in, buffer, total);
596 tls_handshake_send(request, tls_session);
638 switch (reply->code) {
640 RDEBUG(
"Got tunneled Access-Accept");
666 RDEBUG(
"Got MS-CHAP2-Success, tunneling it to the client in a challenge");
713 RDEBUG(
"Sending tunneled reply attributes");
735 RDEBUG(
"Got tunneled Access-Reject");
746 RDEBUG(
"Got tunneled Access-Challenge");
791 RDEBUG(
"Unknown RADIUS packet type %d: rejecting tunneled user", reply->code);
807 tls_session_t *tls_session = (tls_session_t *) data;
810 RDEBUG(
"Passing reply from proxy back into the tunnel");
817 eap_session->request->proxy,
830 request->
proxy = NULL;
847 RDEBUG2(
"post-auth returns %d", rcode);
853 RDEBUG(
"Final reply from tunneled session code %d", fake->
reply->
code);
860 request->
proxy = talloc_steal(request, fake->
packet);
886 rcode = process_reply(eap_session, tls_session, eap_session->request, eap_session->request->proxy_reply);
897 RDEBUG(
"Reply was rejected");
901 RDEBUG(
"Reply was handled");
916 RDEBUG(
"Reply was unknown");
945 data_len = tls_session->clean_out.used;
946 tls_session->clean_out.used = 0;
947 data = tls_session->clean_out.
data;
957 RDEBUG(
"Got ACK, and the user was already authenticated");
973 for (i = 0; i < data_len; i++) {
974 if ((i & 0x0f) == 0) fprintf(
fr_log_fp,
" TTLS tunnel data in %04x: ", (
int) i);
978 if ((i & 0x0f) == 0x0f) fprintf(
fr_log_fp,
"\n");
980 if ((data_len & 0x0f) != 0) fprintf(
fr_log_fp,
"\n");
1009 RDEBUG(
"Got tunneled request");
1041 RDEBUG(
"Got tunneled identity of %s",
1049 RDEBUG(
"Setting default EAP type for tunneled EAP session");
1062 RWDEBUG2(
"No EAP-Identity found to start EAP conversation");
1097 if ((vp->
da->
attr > 255) &&
1125 case PW_USER_PASSWORD:
1126 case PW_CHAP_PASSWORD:
1127 case PW_CHAP_CHALLENGE:
1128 case PW_PROXY_STATE:
1129 case PW_MESSAGE_AUTHENTICATOR:
1130 case PW_EAP_MESSAGE:
1158 RDEBUG(
"received chbind request");
1169 RDEBUG(
"sending chbind response");
1173 RDEBUG(
"no chbind response");
1199 RDEBUG(
"Tunneled authentication will be proxied to %s", vp->vp_strvalue);
1213 request->
proxy = talloc_steal(request, fake->
packet);
1229 tunnel->
callback = eap_ttls_postproxy;
1235 tunnel,
false,
false,
false);
1246 fake,
true,
false,
false);
1259 RDEBUG(
"No tunneled reply was found for request %d , and the request was not proxied: rejecting the user.",
1269 rcode = process_reply(eap_session, tls_session, request, fake->
reply);
#define PW_MSCHAP_CHALLENGE
bool copy_request_to_tunnel
void fr_pair_list_free(VALUE_PAIR **)
Free memory used by a valuepair list.
static rlm_rcode_t CC_HINT(nonnull)
rlm_rcode_t eap_virtual_server(REQUEST *request, REQUEST *fake, eap_session_t *eap_session, char const *virtual_server)
Send a fake request to a virtual server, managing the eap_session_t of the child. ...
VALUE_PAIR * config
VALUE_PAIR (s) used to set per request parameters for modules and the server core at runtime...
VALUE_PAIR * eap_chbind_packet2vp(REQUEST *request, chbind_packet_t *packet)
fr_dict_attr_t * fr_dict_unknown_afrom_fields(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int vendor, unsigned int attr) CC_HINT(nonnull)
Allocates an unknown attribute.
RFC2865 - Access-Challenge.
RADIUS_PACKET * proxy_reply
Incoming response from proxy server.
The module is OK, continue.
VALUE_PAIR * fr_pair_afrom_num(TALLOC_CTX *ctx, unsigned int vendor, unsigned int attr)
Create a new valuepair.
#define RAD_REQUEST_OPTION_PROXY_EAP
int rad_postauth(REQUEST *)
void fr_pair_list_mcopy_by_num(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from, unsigned int vendor, unsigned int attr, int8_t tag)
Copy / delete matching pairs between VALUE_PAIR lists.
char const * virtual_server
fr_ipaddr_t src_ipaddr
Src IP address of packet.
static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR *first)
VALUE_PAIR * username
Cached username VALUE_PAIR from request RADIUS_PACKET.
#define REQUEST_DATA_EAP_TUNNEL_CALLBACK
#define REDEBUG2(fmt,...)
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
#define pair_make_request(_a, _b, _c)
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
VALUE_PAIR * password
Cached password VALUE_PAIR from request RADIUS_PACKET.
The module considers the request invalid.
unsigned int number
Monotonically increasing request number. Reset on server restart.
VALUE_PAIR * fr_pair_list_copy_by_num(TALLOC_CTX *ctx, VALUE_PAIR *from, unsigned int vendor, unsigned int attr, int8_t tag)
Copy matching pairs.
uint16_t dst_port
DST Port of packet.
uint16_t src_port
Src port of packet.
REQUEST * request_alloc_fake(REQUEST *oldreq)
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
REQUEST * request
Request that contains the response we're processing.
#define VENDORPEC_MICROSOFT
RADIUS_PACKET * proxy
Outgoing request to proxy server.
static VALUE_PAIR * diameter2vp(REQUEST *request, REQUEST *fake, SSL *ssl, uint8_t const *data, size_t data_len)
PW_CODE eap_ttls_process(eap_session_t *eap_session, tls_session_t *tls_session)
Highest priority debug messages (-x).
VALUE_PAIR * fr_pair_list_copy(TALLOC_CTX *ctx, VALUE_PAIR *from)
Copy a pairlist.
void fr_cursor_merge(vp_cursor_t *cursor, VALUE_PAIR *vp)
Merges multiple VALUE_PAIR into the cursor.
void fr_cursor_insert(vp_cursor_t *cursor, VALUE_PAIR *vp)
Insert a single VALUE_PAIR at the end of the list.
PW_CODE chbind_process(REQUEST *request, CHBIND_REQ *chbind)
void fr_pair_add(VALUE_PAIR **head, VALUE_PAIR *vp)
Add a VP to the end of the list.
int eap_tls_success(eap_session_t *eap_session)
Send an EAP-TLS success.
Tracks the progress of a single session of any EAP method.
unsigned int attr
Attribute number.
Immediately reject the request.
unsigned int code
Packet code (type).
void * request_data_get(REQUEST *request, void *unique_ptr, int unique_int)
Get opaque data from a request.
unsigned int vendor
Vendor that defines this attribute.
Stores an attribute, a value and various bits of other data.
eap_tunnel_callback_t callback
RADIUS_PACKET * reply
Outgoing response.
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
char const * fr_strerror(void)
Get the last library error.
#define RWDEBUG2(fmt,...)
chbind_packet_t * request
void rdebug_pair_list(log_lvl_t level, REQUEST *, VALUE_PAIR *, char const *)
Print a list of VALUE_PAIRs.
void fr_pair_delete_by_num(VALUE_PAIR **head, unsigned int vendor, unsigned int attr, int8_t tag)
Delete matching pairs.
chbind_packet_t * response
VALUE_PAIR * fr_pair_find_by_da(VALUE_PAIR *head, fr_dict_attr_t const *da, int8_t tag)
Find the pair with the matching DAs.
void eap_ttls_gen_challenge(SSL *s, uint8_t *buffer, size_t size)
chbind_packet_t * eap_chbind_vp2packet(TALLOC_CTX *ctx, VALUE_PAIR *vps)
Module failed, don't reply.
ssize_t fr_radius_decode_pair(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len, void *decoder_ctx)
Create a "normal" VALUE_PAIR from the given data.
log_lvl_t rad_debug_lvl
Global debugging level.
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
void fr_radius_free(RADIUS_PACKET **)
Free a RADIUS_PACKET.
RADIUS_PACKET * packet
Incoming request.
RFC2865/RFC5997 - Status Server (response)
int request_data_add(REQUEST *request, void *unique_ptr, int unique_int, void *opaque, bool free_on_replace, bool free_on_parent, bool persist)
Add opaque data to a REQUEST.
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.
int eap_tls_fail(eap_session_t *eap_session)
Send an EAP-TLS failure.
VALUE_PAIR * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute.
PW_CODE
RADIUS packet codes.
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
void fr_pair_value_bstrncpy(VALUE_PAIR *vp, void const *src, size_t len)
Copy data into an "string" data type.
String of printable characters.
#define PW_MSCHAP2_SUCCESS
static int diameter_verify(REQUEST *request, uint8_t const *data, unsigned int data_len)
int eap_tls_request(eap_session_t *eap_session)
Frames the OpenSSL data that needs to be sent to the client in an EAP-Request.
The module handled the request, so stop.
fr_dict_t * fr_dict_internal
Internal server dictionary.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
VALUE_PAIR * fr_pair_make(TALLOC_CTX *ctx, VALUE_PAIR **vps, char const *attribute, char const *value, FR_TOKEN op)
Create a VALUE_PAIR from ASCII strings.
uint32_t options
mainly for proxying EAP-MSCHAPv2.
void fr_pair_value_memcpy(VALUE_PAIR *vp, uint8_t const *src, size_t len)
Copy data into an "octets" data type.
#define REQUEST_DATA_EAP_MSCHAP_TUNNEL_CALLBACK