]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
encode and decode passwords automatically
authorAlan T. DeKok <aland@freeradius.org>
Sat, 11 Feb 2023 16:27:48 +0000 (11:27 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sat, 11 Feb 2023 17:05:11 +0000 (12:05 -0500)
src/protocols/tacacs/encode.c
src/tests/unit/protocols/tacacs/base.txt

index c9ec8f88ceb36ffc1e092f58f34e18541a8e382e..ba810d339239d00bc841721fab31231c53dbcaa4 100644 (file)
@@ -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;
 
index 7e269fb169678119dd38e46d220724e3ba7adcfd..ad505253d1aa2557ccd6331080ecc1282e38f3b7 100644 (file)
@@ -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