From: Alan T. DeKok Date: Sat, 11 Feb 2023 16:27:48 +0000 (-0500) Subject: encode and decode passwords automatically X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=115f89f6fbdfac196d4cf5033bbbb3ed953d9083;p=thirdparty%2Ffreeradius-server.git encode and decode passwords automatically --- diff --git a/src/protocols/tacacs/encode.c b/src/protocols/tacacs/encode.c index c9ec8f88ceb..ba810d33923 100644 --- a/src/protocols/tacacs/encode.c +++ b/src/protocols/tacacs/encode.c @@ -252,6 +252,42 @@ static ssize_t tacacs_encode_field(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_di return fr_dbuff_set(dbuff, &work_dbuff); } +static ssize_t tacacs_encode_chap(fr_dbuff_t *dbuff, fr_tacacs_packet_t *packet, fr_pair_list_t *vps, fr_dict_attr_t const *da_chap, fr_dict_attr_t const *da_challenge) +{ + fr_pair_t *chap, *challenge; + fr_dbuff_t work_dbuff = FR_DBUFF(dbuff); + + chap = fr_pair_find_by_da(vps, NULL, da_chap); + if (!chap) { + packet->authen_start.data_len = 0; + return 0; + } + + challenge = fr_pair_find_by_da(vps, NULL, da_challenge); + if (!challenge) { + fr_strerror_printf("Packet contains %s but no %s", da_chap->name, da_challenge->name); + return -1; + } + + if (!challenge->vp_length) { + fr_strerror_printf("%s is empty", da_challenge->name); + return -1; + } + + if ((chap->vp_length + challenge->vp_length) > 255) { + fr_strerror_printf("%s and %s are longer than 255 octets", da_chap->name, da_challenge->name); + return -1; + } + + FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, chap->vp_octets, 1); + FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, challenge->vp_octets, challenge->vp_length); + FR_DBUFF_IN_MEMCPY_RETURN(&work_dbuff, chap->vp_octets + 1, chap->vp_length - 1); + + packet->authen_start.data_len = chap->vp_length + challenge->vp_length; + + return fr_dbuff_set(dbuff, &work_dbuff); +} + /* * Magic macros to keep things happy. * @@ -433,7 +469,36 @@ ssize_t fr_tacacs_encode(fr_dbuff_t *dbuff, uint8_t const *original_packet, char ENCODE_FIELD_STRING8(packet->authen_start.user_len, attr_tacacs_user_name); ENCODE_FIELD_STRING8(packet->authen_start.port_len, attr_tacacs_client_port); ENCODE_FIELD_STRING8(packet->authen_start.rem_addr_len, attr_tacacs_remote_address); - ENCODE_FIELD_STRING8(packet->authen_start.data_len, attr_tacacs_data); + + /* + * No explicit "Data" attribute, try to automatically determine what to do. + */ + if (fr_pair_find_by_da_nested(vps, NULL, attr_tacacs_data)) { + ENCODE_FIELD_STRING8(packet->authen_start.data_len, attr_tacacs_data); + + } else switch (packet->authen_start.authen_type) { + int rcode; + + default: + break; + + case FR_AUTHENTICATION_TYPE_VALUE_PAP: + ENCODE_FIELD_STRING8(packet->authen_start.data_len, attr_tacacs_user_password); + break; + + case FR_AUTHENTICATION_TYPE_VALUE_CHAP: + if (tacacs_encode_chap(&work_dbuff, packet, vps, attr_tacacs_chap_password, attr_tacacs_chap_challenge) < 0) return -1; + break; + + case FR_AUTHENTICATION_TYPE_VALUE_MSCHAP: + rcode = tacacs_encode_chap(&work_dbuff, packet, vps, attr_tacacs_mschap_response, attr_tacacs_mschap_challenge); + if (rcode < 0) return rcode; + + if (rcode > 0) break; + + if (tacacs_encode_chap(&work_dbuff, packet, vps, attr_tacacs_mschap2_response, attr_tacacs_mschap_challenge) < 0) return -1; + break; + } goto check_request; diff --git a/src/tests/unit/protocols/tacacs/base.txt b/src/tests/unit/protocols/tacacs/base.txt index 7e269fb1696..ad505253d1a 100644 --- a/src/tests/unit/protocols/tacacs/base.txt +++ b/src/tests/unit/protocols/tacacs/base.txt @@ -17,7 +17,7 @@ fuzzer-out tacacs # Authentication: Start Request: (Client -> Server) # decode-proto c1 01 01 00 b7 0f c8 0e 00 00 00 22 79 d2 9a 66 67 fe fe 87 04 af 61 7e cb 79 20 bb ca 61 cf 8b 25 ab 70 9e 68 af 9f d5 ae de c5 5d 5e 73 -match Packet.Version-Major = Plus, Packet.Version-Minor = 1, Packet.Packet-Type = Authentication, Packet.Sequence-Number = 1, Packet.Flags = None, Packet.Session-Id = 3071264782, Packet.Length = 34, Packet-Body-Type = Start, Action = LOGIN, Privilege-Level = Minimum, Authentication-Type = PAP, Authentication-Service = PPP, User-Name = "bob", Client-Port = "tapioca/0", Remote-Address = "localhost", Data = 0x68656c6c6f +match Packet.Version-Major = Plus, Packet.Version-Minor = 1, Packet.Packet-Type = Authentication, Packet.Sequence-Number = 1, Packet.Flags = None, Packet.Session-Id = 3071264782, Packet.Length = 34, Packet-Body-Type = Start, Action = LOGIN, Privilege-Level = Minimum, Authentication-Type = PAP, Authentication-Service = PPP, User-Name = "bob", Client-Port = "tapioca/0", Remote-Address = "localhost", User-Password = "hello" encode-proto - match c1 01 01 00 b7 0f c8 0e 00 00 00 22 79 d2 9a 66 67 fe fe 87 04 af 61 7e cb 79 20 bb ca 61 cf 8b 25 ab 70 9e 68 af 9f d5 ae de c5 5d 5e 73