Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Robert Dubner
OpenLDAP
Commits
56b0429c
Commit
56b0429c
authored
Oct 07, 2021
by
Robert Dubner
Browse files
Start implementing multi-packet TLS logic; got single-packet working again
parent
a0756b42
Changes
5
Hide whitespace changes
Inline
Side-by-side
contrib/slapd-modules/radiusov/radius.c
View file @
56b0429c
...
...
@@ -755,7 +755,7 @@ static int
encrypt_and_send_response
(
STATE
*
state
,
uint8_t
eap_message_type
)
{
// There is a message in state->c
iphe
rtext_
in
that needs to be encrypted,
// There is a message in state->c
lea
rtext_
out
that needs to be encrypted,
// packaged in an EAP-Message, and sent to our peer:
int
rc
;
...
...
@@ -2346,45 +2346,65 @@ process_eap_message_peap_or_ttls( RADIUS_INFO *radius_info,
return
FAIL_SILENTLY
;
}
uint8_t
flags
=
*
peap
++
;
int
length_bytes
;
int
length_bytes
=
0
;
state
->
tls_record_in_total_len
=
eap_message_length
-
6
;
state
->
tls_record_in_recvd_len
=
0
;
// At this point in the transfer process, we are receiving one or
// more RADIUS packets with encrypted data being carried in their
// outer_eap[] buffers, which are each reassembled from the
// often multiple-per-packet RATV_EAP_Message attributes
if
(
flags
&
EAP_TLS_FLAG_LENGTH_INCLUDED
)
// We build the composite encrypted data in state->ciphertext_in
if
(
state
->
tls_record_in_recvd_len
==
0
)
{
length_bytes
=
4
;
Debug
(
LDAP_DEBUG_ARGS
,
DPREFIX
"%s(): Got explicit length
\n
"
,
__func__
);
state
->
tls_record_in_total_len
=
0
;
if
(
(
char
*
)
peap
-
(
char
*
)
eap_message
+
4
>=
eap_message_length
)
// This is the length we've received so far. Because it
// is zero, we know that this is the first chunk of
// encrypted data.
// Either the four-byte length explicitly follows the flag
// byte, or else we imply it from the length of the EAP-Message
if
(
flags
&
EAP_TLS_FLAG_LENGTH_INCLUDED
)
{
Debug
(
LDAP_DEBUG_ANY
,
DPREFIX
"%s(): eap_message doesn't have enough bytes(B)
\n
"
,
__func__
);
return
FAIL_SILENTLY
;
length_bytes
=
4
;
state
->
tls_record_expected_length
=
0
;
if
(
(
char
*
)
peap
-
(
char
*
)
eap_message
+
4
>=
eap_message_length
)
{
Debug
(
LDAP_DEBUG_ANY
,
DPREFIX
"%s(): eap_message doesn't have enough bytes(B)
\n
"
,
__func__
);
return
FAIL_SILENTLY
;
}
// Pick up four-byte big-endian length
state
->
tls_record_expected_length
*=
256
;
state
->
tls_record_expected_length
+=
*
peap
++
;
state
->
tls_record_expected_length
*=
256
;
state
->
tls_record_expected_length
+=
*
peap
++
;
state
->
tls_record_expected_length
*=
256
;
state
->
tls_record_expected_length
+=
*
peap
++
;
state
->
tls_record_expected_length
*=
256
;
state
->
tls_record_expected_length
+=
*
peap
++
;
Debug
(
LDAP_DEBUG_ARGS
,
DPREFIX
"%s(): Got explicit expected length of %ld bytes
\n
"
,
__func__
,
state
->
tls_record_expected_length
);
}
// Pick up four-byte big-endian length
state
->
tls_record_in_total_len
*=
256
;
state
->
tls_record_in_total_len
+=
*
peap
++
;
state
->
tls_record_in_total_len
*=
256
;
state
->
tls_record_in_total_len
+=
*
peap
++
;
state
->
tls_record_in_total_len
*=
256
;
state
->
tls_record_in_total_len
+=
*
peap
++
;
state
->
tls_record_in_total_len
*=
256
;
state
->
tls_record_in_total_len
+=
*
peap
++
;
else
{
// We are inferring the length from the eap_message length
state
->
tls_record_expected_length
=
eap_message_length
-
6
;
length_bytes
=
0
;
Debug
(
LDAP_DEBUG_ARGS
,
DPREFIX
"%s(): We are using the implicit expected length of %ld bytes
\n
"
,
__func__
,
state
->
tls_record_expected_length
);
}
state
->
ciphertext_in
.
used
=
0
;
}
// We've been told to expect state->tls_record_in_total_len bytes.
size_t
fragment_length
=
eap_message_length
-
6
-
length_bytes
;
//
//
// I am forcing ciphertext_in.used to simply be the length
// of the data we are working with. I have not yet seen a
// case where the authenticating peer (the WiFi Access Point,
// or equivalent) has to send me multiple RADIUS packets
// each with EAP-Message fragments. When we do encounter
// that situation we will have to update this code:
state
->
ciphertext_in
.
used
=
0
;
// We calculate the fragment length from the length of the EAP message:
size_t
fragment_length
=
eap_message_length
-
6
-
length_bytes
;
//
// We copy that many encrypted bytes from the EAP-Message payload to the ciphertext buffer
memcpy
(
state
->
ciphertext_in
.
data
+
state
->
ciphertext_in
.
used
,
peap
,
fragment_length
);
...
...
@@ -2394,26 +2414,29 @@ process_eap_message_peap_or_ttls( RADIUS_INFO *radius_info,
state
->
tls_record_in_recvd_len
+=
fragment_length
;
Debug
(
LDAP_DEBUG_ARGS
,
DPREFIX
"%s() With this %ld-byte fragment, we've received %ld bytes; we are expecting %ld
\n
"
,
DPREFIX
"%s() With this %ld-byte fragment, we've received %ld bytes; we are expecting
a total of
%ld
\n
"
,
__func__
,
fragment_length
,
state
->
tls_record_in_recvd_len
,
state
->
tls_record_
in_total
_len
);
state
->
tls_record_
expected
_len
gth
);
if
(
state
->
tls_record_in_recvd_len
>
state
->
tls_record_
in_total
_len
)
if
(
state
->
tls_record_in_recvd_len
>
state
->
tls_record_
expected
_len
gth
)
{
Debug
(
LDAP_DEBUG_ANY
,
DPREFIX
"%s() We received more bytes (%ld) than we "
"were told we were going to receive (%ld)
\n
"
,
__func__
,
state
->
tls_record_in_recvd_len
,
state
->
tls_record_
in_total
_len
);
state
->
tls_record_
expected
_len
gth
);
return
FAIL_SILENTLY
;
}
if
(
state
->
tls_record_in_recvd_len
==
state
->
tls_record_
in_total
_len
)
if
(
state
->
tls_record_in_recvd_len
==
state
->
tls_record_
expected
_len
gth
)
{
// Reset this counter for next time:
state
->
tls_record_in_recvd_len
=
0
;
// We have an entire TLS message. Send it to BIO_write
int
err
=
BIO_write
(
state
->
into_ssl
,
state
->
ciphertext_in
.
data
,
...
...
@@ -2573,9 +2596,9 @@ process_access_request( RADIUS_INFO *radius_info,
int
we_got_message_authenticator
=
0
;
RADIUS_ATTRIBUTE
*
ra
=
fetch_attribute_from_packet
(
request
,
RATV_Message_Authenticator
);
if
(
ra
)
RADIUS_ATTRIBUTE
*
ra
MsgAuth
=
fetch_attribute_from_packet
(
request
,
RATV_Message_Authenticator
);
if
(
ra
MsgAuth
)
{
Debug
(
LDAP_DEBUG_ARGS
,
DPREFIX
"%s(): RADIUS packet has a RATV_Message_Authenticator
\n
"
,
...
...
@@ -2583,8 +2606,8 @@ process_access_request( RADIUS_INFO *radius_info,
// Per RFC2869, we perform an HMAC-MD5 on the whole packet, but with the
// signature bytes set to zero:
uint8_t
save_the_signature
[
AUTHENTICATOR_LENGTH
];
memcpy
(
save_the_signature
,
ra
->
Data
,
AUTHENTICATOR_LENGTH
);
memset
(
ra
->
Data
,
0
,
AUTHENTICATOR_LENGTH
);
memcpy
(
save_the_signature
,
ra
MsgAuth
->
Data
,
AUTHENTICATOR_LENGTH
);
memset
(
ra
MsgAuth
->
Data
,
0
,
AUTHENTICATOR_LENGTH
);
// Calculate the digest
uint8_t
digest
[
MD5_DIGEST_LENGTH
];
...
...
@@ -2595,7 +2618,7 @@ process_access_request( RADIUS_INFO *radius_info,
strlen
(
shared_secret
)
);
// Restore the original packet:
memcpy
(
ra
->
Data
,
save_the_signature
,
AUTHENTICATOR_LENGTH
);
memcpy
(
ra
MsgAuth
->
Data
,
save_the_signature
,
AUTHENTICATOR_LENGTH
);
// Check to see if the calculated and provided digests are the same:
if
(
memcmp
(
digest
,
save_the_signature
,
AUTHENTICATOR_LENGTH
)
)
...
...
@@ -2621,9 +2644,10 @@ process_access_request( RADIUS_INFO *radius_info,
}
// Let's check for an EAP-message. (RFC3748)
ra
=
fetch_attribute_from_packet
(
request
,
RATV_EAP_Message
);
EAP_MESSAGE
*
eap_message
=
get_outer_eap_message
(
request
);
size_t
eap_message_length
=
get_eap_length
(
eap_message
);
if
(
ra
)
if
(
eap_message
)
{
Debug
(
LDAP_DEBUG_ARGS
,
DPREFIX
"%s(): The RADIUS packet has an EAP-Message:
\n
"
,
...
...
@@ -2643,45 +2667,28 @@ process_access_request( RADIUS_INFO *radius_info,
}
Debug
(
LDAP_DEBUG_ARGS
,
DPREFIX
"%s(): Incoming EAP-message of %d bytes.
\n
"
,
DPREFIX
"%s(): Incoming EAP-message of %
l
d bytes.
\n
"
,
__func__
,
ra
->
DataL
ength
);
eap_message_l
ength
);
// Your best first bet for looking at the bytes of an EAP-Message is to
// look at a Wireshark capture. But you can activate the following
// code if you want.
#if
0
#if
1
ber_log_bprint
(
LDAP_DEBUG_ANY
,
LDAP_DEBUG_ANY
,
(const char *)
ra->Data
,
ra->DataL
ength);
(
const
char
*
)
eap_message
,
eap_message_l
ength
);
#endif
// Make sure the EAP-message payload is long enough:
if
(
ra
->
DataL
ength
<
5
)
if
(
eap_message_l
ength
<
5
)
{
Debug
(
LDAP_DEBUG_ANY
,
DPREFIX
"%s(): RADIUS packet has an EAP-Message that's poorly "
"formed; at %d bytes, it is too short
\n
"
,
__func__
,
ra
->
DataLength
);
return
FAIL_SILENTLY
;
}
EAP_MESSAGE
*
eap_message
=
(
EAP_MESSAGE
*
)(
ra
->
Data
);
// Make sure that the EAP-Message's data length fits inside the
// the RADIUS_ATTRIBUTE:
size_t
eap_message_length
=
get_eap_length
(
eap_message
);
if
(
eap_message_length
>
ra
->
DataLength
)
{
Debug
(
LDAP_DEBUG_ANY
,
DPREFIX
"%s(): The EAP-Message length is %ld bytes, which is too long"
"to fit in the %d bytes of the RADIUS_ATTRIBUTE
\n
"
,
"formed; at %ld bytes, it is too short
\n
"
,
__func__
,
eap_message_length
,
ra
->
DataLength
);
eap_message_length
);
return
FAIL_SILENTLY
;
}
...
...
@@ -2769,9 +2776,9 @@ radiusov_protocol( RADIUS_INFO *radius_info,
RADIUS_PACKET
request_
;
RADIUS_PACKET
*
request
=
&
request_
;
rc
=
radiusov_ge
t_packet_from_
request
(
request
,
incoming_request
,
recv_len
);
rc
=
extrac
t_packet_from_
buffer
(
request
,
incoming_request
,
recv_len
);
if
(
rc
==
0
)
{
debugging_display_of
(
request
);
...
...
contrib/slapd-modules/radiusov/radiusov.h
View file @
56b0429c
...
...
@@ -98,7 +98,7 @@ typedef struct _STATE
size_t
mtu
;
// Current fragment size
size_t
tls_record_
in_total
_len
;
// peer value for total length of TLS record
size_t
tls_record_
expected
_len
gth
;
// peer value for total length of TLS record
size_t
tls_record_in_recvd_len
;
// how much of that we've already read in
char
const
*
keying_material_label
;
...
...
contrib/slapd-modules/radiusov/rpacket.c
View file @
56b0429c
...
...
@@ -18,6 +18,7 @@
#include
"radiusov.h"
#include
"lber-int.h"
#include
"rpacket.h"
#include
"reap.h"
const
RADIUS_ATTRIBUTE_TYPE
radius_attribute_types
[]
=
{
...
...
@@ -352,9 +353,9 @@ radius_attribute_to_text(RADIUS_ATTRIBUTE *ra, char *buffer, size_t buf_len)
}
int
radiusov_ge
t_packet_from_
request
(
RADIUS_PACKET
*
radius_packet
,
uint8_t
*
incoming_request
,
ssize_t
recv_len
)
extrac
t_packet_from_
buffer
(
RADIUS_PACKET
*
radius_packet
,
uint8_t
*
incoming_request
,
ssize_t
recv_len
)
{
DENTER
;
// This routine dissects the raw incoming_request (which is recv_len bytes
...
...
@@ -417,6 +418,7 @@ radiusov_get_packet_from_request( RADIUS_PACKET *radius_packet,
// an attribute falls off the end of the radius packet, we silently fail,
// discarding the entire incoming packet.
radius_packet
->
outer_eap_length
=
0
;
radius_packet
->
number_of_attributes
=
0
;
uint8_t
*
attributes
;
...
...
@@ -455,10 +457,24 @@ radiusov_get_packet_from_request( RADIUS_PACKET *radius_packet,
radius_packet
->
attributes
[
radius_packet
->
number_of_attributes
].
DataLength
=
alength
-
2
;
radius_packet
->
attributes
[
radius_packet
->
number_of_attributes
].
Data
=
attributes
+
2
;
if
(
atype
==
RATV_EAP_Message
)
{
// Special processing for EAP-Message, which can arrive as several
// fragments:
memcpy
(
radius_packet
->
outer_eap
+
radius_packet
->
outer_eap_length
,
radius_packet
->
attributes
[
radius_packet
->
number_of_attributes
].
Data
,
radius_packet
->
attributes
[
radius_packet
->
number_of_attributes
].
DataLength
);
radius_packet
->
outer_eap_length
+=
radius_packet
->
attributes
[
radius_packet
->
number_of_attributes
].
DataLength
;
radius_packet
->
outer_eap
[
2
]
=
radius_packet
->
outer_eap_length
>>
8
;
radius_packet
->
outer_eap
[
3
]
=
radius_packet
->
outer_eap_length
;
}
// Make an entry in the speed_fetch array, to make it easy
// to find this attribute.
radius_packet
->
speed_fetch
[
atype
]
=
radius_packet
->
number_of_attributes
;
radius_packet
->
number_of_attributes
+=
1
;
}
else
...
...
@@ -484,6 +500,13 @@ fetch_attribute_from_packet(RADIUS_PACKET *radius_packet, uint8_t Type)
return
&
radius_packet
->
attributes
[
index
];
}
EAP_MESSAGE
*
get_outer_eap_message
(
RADIUS_PACKET
*
radius_packet
)
{
return
(
EAP_MESSAGE
*
)
radius_packet
->
outer_eap
;
}
void
add_attribute_to_radius_packet
(
RADIUS_PACKET
*
radius_packet
,
uint8_t
Type
,
...
...
contrib/slapd-modules/radiusov/rpacket.h
View file @
56b0429c
...
...
@@ -16,6 +16,8 @@
#ifndef RPACKET_H
#define RPACKET_H
#include
"reap.h"
typedef
enum
RADIUS_PACKET_DATA_TYPE
{
RDP_NONE
,
...
...
@@ -282,6 +284,14 @@ typedef struct _RADIUS_PACKET
RADIUS_ATTRIBUTE
attributes
[
STUPID_NUMBER_OF_ATTRIBUTES
];
uint8_t
speed_fetch
[
256
];
// This is a map of radius_attribute type to its
// index in attributes[]
// The RADIUS packet EAP message can be longer than the 253-byte payload
// of an RADIUS_ATTRIBUTE. When a message with one or more EAP-Message
// attributes comes in, the reconstructed EAP message is placed here:
// This is the data as received.
int
outer_eap_length
;
uint8_t
outer_eap
[
MAXIMUM_POSSIBLE_LENGTH_OF_PACKET
];
}
RADIUS_PACKET
;
#define RADIUS_ATTRIBUTE_TYPE_MAX 191
...
...
@@ -306,12 +316,12 @@ void build_packet_postamble( RADIUS_PACKET *response,
RADIUS_PACKET
*
request
,
const
char
*
state_string
,
const
char
*
shared_secret
);
int
radiusov_get_packet_from_request
(
RADIUS_PACKET
*
radius_packet
,
uint8_t
*
incoming_request
,
ssize_t
recv_len
);
RADIUS_ATTRIBUTE
*
fetch_attribute_from_packet
(
RADIUS_PACKET
*
radius_packet
,
int
extract_packet_from_buffer
(
RADIUS_PACKET
*
radius_packet
,
uint8_t
*
incoming_request
,
ssize_t
recv_len
);
RADIUS_ATTRIBUTE
*
fetch_attribute_from_packet
(
RADIUS_PACKET
*
radius_packet
,
uint8_t
Type
);
EAP_MESSAGE
*
get_outer_eap_message
(
RADIUS_PACKET
*
radius_packet
);
void
add_attribute_to_radius_packet
(
RADIUS_PACKET
*
radius_packet
,
uint8_t
Type
,
uint8_t
DataLength
,
...
...
contrib/slapd-modules/radiusov/tls.c
View file @
56b0429c
...
...
@@ -858,34 +858,32 @@ tls_init_ctx(SSL_CONFIGURATION *conf)
/* Set Info callback */
SSL_CTX_set_info_callback
(
ctx
,
cbtls_info
);
int
verify_mode
=
SSL_VERIFY_NONE
;
// This is what we use for client mode
int
verify_mode
=
SSL_VERIFY_NONE
;
if
(
conf
->
is_server
)
// It's time to set the verification mode. See SSL_CTX_set_verify()
switch
(
conf
->
verify_mode
)
{
// It's time to set the verification mode. See SSL_CTX_set_verify()
switch
(
conf
->
verify_mode
)
{
case
VM_NEVER
:
verify_mode
=
SSL_VERIFY_NONE
;
break
;
case
VM_ALLOW
:
verify_mode
=
SSL_VERIFY_PEER
;
break
;
case
VM_TRY
:
verify_mode
=
SSL_VERIFY_PEER
;
break
;
case
VM_DEMAND
:
verify_mode
=
SSL_VERIFY_PEER
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
;
break
;
default:
Debug
(
LDAP_DEBUG_ANY
,
"%s(): conf->verify_mode has an unknown value of %d
\n
"
,
__func__
,
conf
->
verify_mode
);
return
NULL
;
break
;
}
case
VM_NEVER
:
verify_mode
=
SSL_VERIFY_NONE
;
break
;
case
VM_ALLOW
:
verify_mode
=
SSL_VERIFY_PEER
;
break
;
case
VM_TRY
:
verify_mode
=
SSL_VERIFY_PEER
;
break
;
case
VM_DEMAND
:
verify_mode
=
SSL_VERIFY_PEER
|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT
;
break
;
default:
Debug
(
LDAP_DEBUG_ANY
,
"%s(): conf->verify_mode has an unknown value of %d
\n
"
,
__func__
,
conf
->
verify_mode
);
return
NULL
;
break
;
}
SSL_CTX_set_verify
(
ctx
,
verify_mode
,
verify_callback
);
SSL_CTX_set_verify_depth
(
ctx
,
conf
->
verify_depth
);
...
...
@@ -1416,7 +1414,6 @@ tls_new_session(SSL_CTX *ctx,
// Create a new TLS session
STATE
*
state
=
NULL
;
SSL
*
new_tls
=
NULL
;
// int verify_mode = 0;
Debug
(
LDAP_DEBUG_TRACE
,
"=> %s()
\n
"
,
__func__
);
...
...
@@ -1532,7 +1529,7 @@ CONFIG_ELEMENT configuration_elements[] =
MAKE_CONFIG_ELEMENT
(
"private_key_password"
,
CT_STRING
,
private_key_password
,
"whatever"
),
MAKE_CONFIG_ELEMENT
(
"cipher_list"
,
CT_STRING
,
cipher_list
,
""
),
MAKE_CONFIG_ELEMENT
(
"auto_chain"
,
CT_BOOLEAN
,
auto_chain
,
"yes"
),
MAKE_CONFIG_ELEMENT
(
"
tls
verify
client
"
,
CT_VERIFICATION
,
verify_mode
,
"never"
),
// allow|try|demand
MAKE_CONFIG_ELEMENT
(
"verify
_mode
"
,
CT_VERIFICATION
,
verify_mode
,
"never"
),
//
never|
allow|try|demand
MAKE_CONFIG_ELEMENT
(
"verify_depth"
,
CT_INTEGER
,
verify_depth
,
"100"
),
};
#define NUMBER_OF_ELEMENTS (sizeof(configuration_elements)/sizeof(configuration_elements[0]))
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment