RADIUS: add accounting request authenticator validation

validate authenticator field for Accounting-Request packets

implement RFC 2866, Request Authenticator page 7
This commit is contained in:
Emanuele Bovisio 2021-02-17 13:32:05 +01:00 committed by Wireshark GitLab Utility
parent 1965109ec7
commit b3f356efa2
1 changed files with 34 additions and 10 deletions

View File

@ -1901,14 +1901,15 @@ is_radius(tvbuff_t *tvb)
} }
/* /*
* returns true if the response authenticator is valid * returns true if the response or accounting request authenticator is valid
* input: tvb of the response, corresponding request authenticator * input: tvb of the response, corresponding request authenticator (not used for request),
* uses the shared secret to calculate the Response authenticator * uses the shared secret to calculate the authenticator
* and checks with the current. * and checks with the current.
* see RFC 2865, packet format page 16 * see RFC 2865, packet format page 16
* see RFC 2866, Request Authenticator page 7
*/ */
static gboolean static gboolean
valid_authenticator(tvbuff_t *tvb, guint8 request_authenticator[]) valid_authenticator(tvbuff_t *tvb, guint8 request_authenticator[], int request)
{ {
gcry_md_hd_t md5_handle; gcry_md_hd_t md5_handle;
guint8 *digest; guint8 *digest;
@ -1921,8 +1922,13 @@ valid_authenticator(tvbuff_t *tvb, guint8 request_authenticator[])
/* copy response into payload */ /* copy response into payload */
payload = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, tvb_length); payload = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, 0, tvb_length);
/* replace authenticator in reply with the one in request */ if (request) {
memcpy(payload+4, request_authenticator, AUTHENTICATOR_LENGTH); /* reset authenticator field */
memset(payload+4, 0, AUTHENTICATOR_LENGTH);
} else {
/* replace authenticator in reply with the one in request */
memcpy(payload+4, request_authenticator, AUTHENTICATOR_LENGTH);
}
/* calculate MD5 hash (payload+shared_secret) */ /* calculate MD5 hash (payload+shared_secret) */
if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) { if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
@ -2093,6 +2099,24 @@ dissect_radius(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
proto_item_set_generated(item); proto_item_set_generated(item);
} }
} }
/* Accounting Request Authenticator Validation */
if (rh.rh_code == RADIUS_PKT_TYPE_ACCOUNTING_REQUEST && validate_authenticator && *shared_secret != '\0') {
proto_item *authenticator_tree, *item;
int valid;
valid = valid_authenticator(tvb, radius_call->req_authenticator, 1);
proto_item_append_text(authenticator_item, " [%s]", valid? "correct" : "incorrect");
authenticator_tree = proto_item_add_subtree(authenticator_item, ett_radius_authenticator);
item = proto_tree_add_boolean(authenticator_tree, hf_radius_authenticator_valid, tvb, 4, AUTHENTICATOR_LENGTH, valid ? TRUE : FALSE);
proto_item_set_generated(item);
item = proto_tree_add_boolean(authenticator_tree, hf_radius_authenticator_invalid, tvb, 4, AUTHENTICATOR_LENGTH, valid ? FALSE : TRUE);
proto_item_set_generated(item);
if (!valid) {
col_append_fstr(pinfo->cinfo, COL_INFO, " [incorrect authenticator]");
}
}
} }
if (!PINFO_FD_VISITED(pinfo) && (radius_call == NULL || !rad_info->is_duplicate)) { if (!PINFO_FD_VISITED(pinfo) && (radius_call == NULL || !rad_info->is_duplicate)) {
@ -2214,7 +2238,7 @@ dissect_radius(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _
if (validate_authenticator && *shared_secret != '\0') { if (validate_authenticator && *shared_secret != '\0') {
proto_item *authenticator_tree; proto_item *authenticator_tree;
int valid; int valid;
valid = valid_authenticator(tvb, radius_call->req_authenticator); valid = valid_authenticator(tvb, radius_call->req_authenticator, 0);
proto_item_append_text(authenticator_item, " [%s]", valid? "correct" : "incorrect"); proto_item_append_text(authenticator_item, " [%s]", valid? "correct" : "incorrect");
authenticator_tree = proto_item_add_subtree(authenticator_item, ett_radius_authenticator); authenticator_tree = proto_item_add_subtree(authenticator_item, ett_radius_authenticator);
@ -2829,10 +2853,10 @@ proto_register_radius(void)
register_shutdown_routine(radius_shutdown); register_shutdown_routine(radius_shutdown);
radius_module = prefs_register_protocol(proto_radius, NULL); radius_module = prefs_register_protocol(proto_radius, NULL);
prefs_register_string_preference(radius_module, "shared_secret", "Shared Secret", prefs_register_string_preference(radius_module, "shared_secret", "Shared Secret",
"Shared secret used to decode User Passwords and validate Response Authenticators", "Shared secret used to decode User Passwords and validate Accounting Request and Response Authenticators",
&shared_secret); &shared_secret);
prefs_register_bool_preference(radius_module, "validate_authenticator", "Validate Response Authenticator", prefs_register_bool_preference(radius_module, "validate_authenticator", "Validate Accounting Request and Response Authenticator",
"Whether to check or not if Response Authenticator is correct. You need to define shared secret for this to work.", "Whether to check or not if Accounting Request and Response Authenticator are correct. You need to define shared secret for this to work.",
&validate_authenticator); &validate_authenticator);
prefs_register_bool_preference(radius_module, "show_length", "Show AVP Lengths", prefs_register_bool_preference(radius_module, "show_length", "Show AVP Lengths",
"Whether to add or not to the tree the AVP's payload length", "Whether to add or not to the tree the AVP's payload length",