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.
*
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;
# 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