uint8_t const *p = attrs;
fr_pair_t *vp;
fr_pair_t *vendor = NULL;
+ fr_dict_attr_t const *root;
/*
* No one? Just get out!
}
}
+ root = fr_dict_root(dict_tacacs);
+
/*
* Then, do the dirty job of creating attributes.
*/
for (i = 0; i < arg_cnt; i++) {
uint8_t const *value, *name_end, *arg_end;
fr_dict_attr_t const *da;
+ fr_pair_list_t *dst;
uint8_t buffer[256];
fr_assert((p + argv[i]) <= end);
if (!name_end) goto next;
/*
- * Dupe the whole thing so that we have:
- *
- * Argument-List += "name=value"
+ * Prefer to decode from the attribute root, first.
+ */
+ da = fr_dict_attr_by_name(NULL, root, (char *) buffer);
+ if (da) {
+ vp = fr_pair_afrom_da(ctx, da);
+ if (!vp) goto oom;
+
+ dst = out;
+ goto decode;
+ }
+
+ /*
+ * If the attribute isn't in the main dictionary,
+ * maybe it's in the vendor dictionary?
*/
if (vendor) {
da = fr_dict_attr_by_name(NULL, parent, (char *) buffer);
vp = fr_pair_afrom_da(vendor, da);
if (!vp) goto oom;
+ dst = &vendor->vp_group;
+
+ decode:
/*
* If it's OCTETS or STRING type, then just copy the value verbatim, as the
* contents are (should be?) binary-safe. But if it's zero length, then don't need to
*/
}
- fr_pair_append(&vendor->vp_group, vp);
+ fr_pair_append(dst, vp);
} else {
raw:
fr_assert(fr_dict_by_da(vp->da) == dict_tacacs);
+ /*
+ * RFC 8907 attributes.
+ */
+ if (vp->da->parent->flags.is_root) {
+ arg_cnt++;
+ continue;
+ }
+
/*
* Recurse into children.
*/
if (vp->da->type == FR_TYPE_VENDOR) {
arg_cnt += tacacs_encode_body_arg_cnt(&vp->vp_group, NULL);
+ continue;
}
if (vp->da->parent->type != FR_TYPE_VENDOR) continue;
i += child_argc;
continue;
- } else if (!vp->da->parent || (vp->da->parent->type != FR_TYPE_VENDOR)) {
+ } else if (!vp->da->parent || (!vp->da->parent->flags.is_root && (vp->da->parent->type != FR_TYPE_VENDOR))) {
continue;
} else {
ssize_t slen;
fr_sbuff_t sbuff;
fr_dbuff_t arg_dbuff = FR_DBUFF_MAX(&work_dbuff, 255);
+ fr_value_box_t box;
char buffer[256];
/*
FR_DBUFF_IN_BYTES_RETURN(&arg_dbuff, (uint8_t) '=');
sbuff = FR_SBUFF_OUT(buffer, sizeof(buffer));
- slen = fr_pair_print_value_quoted(&sbuff, vp, 0);
- if (slen <= 0) return -1;
+
+ switch (vp->vp_type) {
+ /*
+ * For now, we always print time deltas and dates as integers.
+ *
+ * Because everyone else's date formats are insane.
+ */
+ case FR_TYPE_DATE:
+ case FR_TYPE_TIME_DELTA:
+ fr_value_box_init(&box, FR_TYPE_UINT64, vp->data.enumv, vp->vp_tainted);
+ if (fr_value_box_cast(NULL, &box, FR_TYPE_UINT64, NULL, &vp->data) < 0) {
+ buffer[0] = '\0';
+ slen = 0;
+ break;
+ }
+
+ slen = fr_sbuff_in_sprintf(&sbuff, "%lu", box.vb_uint64);
+ if (slen <= 0) return -1;
+ break;
+
+ default:
+ slen = fr_pair_print_value_quoted(&sbuff, vp, T_BARE_WORD);
+ if (slen <= 0) return -1;
+ }
FR_DBUFF_IN_MEMCPY_RETURN(&arg_dbuff, buffer, (size_t) slen);
fr_dbuff_set(&work_dbuff, &arg_dbuff);
}
+ fr_assert(len <= UINT8_MAX);
+
FR_PROTO_TRACE("len(arg[%d]) = %d", i, len);
arg_len[i++] = len;
}
}
#ifndef NDEBUG
- if (fr_debug_lvl >= L_DBG_LVL_4) {
+// if (fr_debug_lvl >= L_DBG_LVL_4) {
+ if (1) {
uint8_t flags = packet->hdr.flags;
packet->hdr.flags |= FR_TAC_PLUS_UNENCRYPTED_FLAG;
# Authorization - Request: (Client -> Server)
#
decode-proto c0 02 01 00 e1 66 78 e6 00 00 00 35 4b c5 ea 62 13 cc ca a6 6a 03 3c 8e 3f c0 5a aa 46 da 12 cd ee 48 62 69 67 9a b8 b4 db 70 98 30 b7 fc f6 93 09 d4 3f 2c a9 58 9e 3c 6a 0e d5 50 20 e6 a5 39 46
-match Packet.Version-Major = Plus, Packet.Version-Minor = 0, Packet.Packet-Type = Authorization, Packet.Sequence-Number = 1, Packet.Flags = None, Packet.Session-Id = 3781589222, Packet.Length = 53, Packet-Body-Type = Request, Authentication-Method = TACACSPLUS, Privilege-Level = Minimum, Authentication-Type = PAP, Authentication-Service = PPP, User-Name = "bob", Client-Port = "tapioca/0", Remote-Address = "localhost", Argument-List = "service=ppp", Argument-List = "protocol=ip"
+match Packet.Version-Major = Plus, Packet.Version-Minor = 0, Packet.Packet-Type = Authorization, Packet.Sequence-Number = 1, Packet.Flags = None, Packet.Session-Id = 3781589222, Packet.Length = 53, Packet-Body-Type = Request, Authentication-Method = TACACSPLUS, Privilege-Level = Minimum, Authentication-Type = PAP, Authentication-Service = PPP, User-Name = "bob", Client-Port = "tapioca/0", Remote-Address = "localhost", service = "ppp", protocol = "ip"
encode-proto -
match c0 02 01 00 e1 66 78 e6 00 00 00 35 4b c5 ea 62 13 cc ca a6 6a 03 3c 8e 3f c0 5a aa 46 da 12 cd ee 48 62 69 67 9a b8 b4 db 70 98 30 b7 fc f6 93 09 d4 3f 2c a9 58 9e 3c 6a 0e d5 50 20 e6 a5 39 46
# Authorization - Response: (Client <- Server)
#
decode-proto c0 02 02 00 e1 66 78 e6 00 00 00 13 02 59 f9 90 38 81 e1 bb 9d a6 13 93 fc 86 7e 4a 14 1c 24
-match Packet.Version-Major = Plus, Packet.Version-Minor = 0, Packet.Packet-Type = Authorization, Packet.Sequence-Number = 2, Packet.Flags = None, Packet.Session-Id = 3781589222, Packet.Length = 19, Packet-Body-Type = Response, Authorization-Status = Pass-Add, Server-Message = "", Data = 0x, Argument-List = "addr=1.2.3.4"
+match Packet.Version-Major = Plus, Packet.Version-Minor = 0, Packet.Packet-Type = Authorization, Packet.Sequence-Number = 2, Packet.Flags = None, Packet.Session-Id = 3781589222, Packet.Length = 19, Packet-Body-Type = Response, Authorization-Status = Pass-Add, Server-Message = "", Data = 0x, addr = 1.2.3.4
encode-proto -
match c0 02 02 00 e1 66 78 e6 00 00 00 13 02 59 f9 90 38 81 e1 bb 9d a6 13 93 fc 86 7e 4a 14 1c 24
# Accounting - Request: (Client -> Server)
#
decode-proto c0 03 01 00 07 9b 35 d9 00 00 00 5b 7c 8a 99 d6 88 f9 32 3c ec 34 6d 23 89 71 72 dd 89 46 75 df 9c 00 a5 96 28 05 fc 57 88 02 0c 11 a3 60 9a 05 8b 71 6d 27 ca 83 b0 ab 2f 00 27 c8 da 58 d3 1a f1 3f 07 17 8d f6 35 c5 7b e2 07 be 29 86 d4 93 16 99 04 01 ef 03 6c 1c 2b ad 3a fb 5b 11 06 61 dc d9 09 1d 6a 08 1e
-match Packet.Version-Major = Plus, Packet.Version-Minor = 0, Packet.Packet-Type = Accounting, Packet.Sequence-Number = 1, Packet.Flags = None, Packet.Session-Id = 127612377, Packet.Length = 91, Packet-Body-Type = Request, Accounting-Flags = Start, Authentication-Method = TACACSPLUS, Privilege-Level = Minimum, Authentication-Type = PAP, Authentication-Service = PPP, User-Name = "bob", Client-Port = "tapioca/0", Remote-Address = "localhost", Argument-List = "start_time=1596565644", Argument-List = "task_id=17558", Argument-List = "service=ppp", Argument-List = "protocol=ip"
+match Packet.Version-Major = Plus, Packet.Version-Minor = 0, Packet.Packet-Type = Accounting, Packet.Sequence-Number = 1, Packet.Flags = None, Packet.Session-Id = 127612377, Packet.Length = 91, Packet-Body-Type = Request, Accounting-Flags = Start, Authentication-Method = TACACSPLUS, Privilege-Level = Minimum, Authentication-Type = PAP, Authentication-Service = PPP, User-Name = "bob", Client-Port = "tapioca/0", Remote-Address = "localhost", start_time = "Aug 4 2020 18:27:24 UTC", task_id = "17558", service = "ppp", protocol = "ip"
encode-proto -
match c0 03 01 00 07 9b 35 d9 00 00 00 5a 7c 8a 99 d6 88 f9 32 3c ed 21 75 25 89 18 7f d0 9f 53 64 c6 9a 0c a7 d8 37 59 ff 5b 8a 0f 08 16 bf 67 9d 02 9e 62 6b 0c e1 9e b4 a3 77 0c 23 c4 d5 5b d0 19 f2 3d 07 57 98 e4 2d f1 4d ef 5e b2 2f 84 d4 9e 5d 8f 13 05 f0 09 6a 44 66 ad 3a fb 59 0c 1d 7a d0 d5 0a 4c 3e 11