]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Autoload proto_tacacs
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 16 May 2018 14:29:05 +0000 (20:29 +0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 16 May 2018 14:29:05 +0000 (20:29 +0600)
src/modules/proto_tacacs/proto_tacacs.c
src/modules/proto_tacacs/tacacs.c
src/modules/proto_tacacs/tacacs.h

index 0b3d0319010d4b8f863c5200d009eefcec90168a..74c61d56f175553e659b4979728c7f0daffc021c 100644 (file)
 
 #include "tacacs.h"
 
+static fr_dict_t const *dict_freeradius;
+static fr_dict_t const *dict_radius;
+static fr_dict_t const *dict_tacacs;
+
+extern fr_dict_autoload_t proto_tacacs_dict[];
+fr_dict_autoload_t proto_tacacs_dict[] = {
+       { .out = &dict_freeradius, .proto = "freeradius" },
+       { .out = &dict_radius, .proto = "radius" },
+       { .out = &dict_tacacs, .proto = "tacacs" },
+
+       { NULL }
+};
+
+static fr_dict_attr_t const *attr_auth_type;
+
+static fr_dict_attr_t const *attr_state;
+
+fr_dict_attr_t const *attr_tacacs_accounting_flags;
+fr_dict_attr_t const *attr_tacacs_accounting_status;
+fr_dict_attr_t const *attr_tacacs_action;
+fr_dict_attr_t const *attr_tacacs_authentication_flags;
+fr_dict_attr_t const *attr_tacacs_authentication_method;
+fr_dict_attr_t const *attr_tacacs_authentication_service;
+fr_dict_attr_t const *attr_tacacs_authentication_status;
+fr_dict_attr_t const *attr_tacacs_authentication_type;
+fr_dict_attr_t const *attr_tacacs_authorization_status;
+fr_dict_attr_t const *attr_tacacs_client_port;
+fr_dict_attr_t const *attr_tacacs_data;
+fr_dict_attr_t const *attr_tacacs_packet_type;
+fr_dict_attr_t const *attr_tacacs_privilege_level;
+fr_dict_attr_t const *attr_tacacs_remote_address;
+fr_dict_attr_t const *attr_tacacs_sequence_number;
+fr_dict_attr_t const *attr_tacacs_server_message;
+fr_dict_attr_t const *attr_tacacs_session_id;
+fr_dict_attr_t const *attr_tacacs_user_message;
+fr_dict_attr_t const *attr_tacacs_user_name;
+fr_dict_attr_t const *attr_tacacs_version_minor;
+
+extern fr_dict_attr_autoload_t proto_tacacs_dict_attr[];
+fr_dict_attr_autoload_t proto_tacacs_dict_attr[] = {
+       { .out = &attr_auth_type, .name = "Auth-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
+       { .out = &attr_state, .name = "State", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
+       { .out = &attr_tacacs_accounting_flags, .name = "TACACS-Accounting-Flags", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_accounting_status, .name = "TACACS-Accounting-Status", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_action, .name = "TACACS-Action", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_authentication_flags, .name = "TACACS-Authentication-Flags", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_authentication_method, .name = "TACACS-Authentication-Method", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_authentication_service, .name = "TACACS-Authentication-Service", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_authentication_status, .name = "TACACS-Authentication-Status", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_authentication_type, .name = "TACACS-Authentication-Type", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_authorization_status, .name = "TACACS-Authorization-Status", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_client_port, .name = "TACACS-Client-Port", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_data, .name = "TACACS-Data", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_packet_type, .name = "TACACS-Packet-Type", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_privilege_level, .name = "TACACS-Privilege-Level", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_remote_address, .name = "TACACS-Remote-Address", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_sequence_number, .name = "TACACS-Sequence-Number", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_server_message, .name = "TACACS-Server-Message", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_session_id, .name = "TACACS-Session-Id", .type = FR_TYPE_UINT32, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_user_message, .name = "TACACS-User-Message", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_user_name, .name = "TACACS-User-Name", .type = FR_TYPE_STRING, .dict = &dict_tacacs },
+       { .out = &attr_tacacs_version_minor, .name = "TACACS-Version-Minor", .type = FR_TYPE_UINT8, .dict = &dict_tacacs },
+       { NULL }
+};
+
 /*
  *     Debug the packet if requested - cribbed from common_packet_debug
  */
@@ -61,69 +126,82 @@ static void tacacs_packet_debug(REQUEST *request, RADIUS_PACKET *packet, bool re
 
 static void tacacs_status(REQUEST * const request, rlm_rcode_t rcode)
 {
-       char const *k = "Unknown";
-       char const *v = "Unknown";
+       VALUE_PAIR *vp;
 
        switch (tacacs_type(request->packet)) {
        case TAC_PLUS_AUTHEN:
-               k = "TACACS-Authentication-Status";
                switch (rcode) {
                case RLM_MODULE_OK:
-                       v = "Pass";
+                       MEM(pair_update_reply(&vp, attr_tacacs_authentication_status) >= 0);
+                       fr_pair_value_from_str(vp, "Pass", -1);
                        break;
+
                case RLM_MODULE_FAIL:
                case RLM_MODULE_REJECT:
                case RLM_MODULE_USERLOCK:
-                       v = "Fail";
+                       MEM(pair_update_reply(&vp, attr_tacacs_authentication_status) >= 0);
+                       fr_pair_value_from_str(vp, "Fail", -1);
                        break;
+
                case RLM_MODULE_INVALID:
-                       v = "Error";
+                       MEM(pair_update_reply(&vp, attr_tacacs_authentication_status) >= 0);
+                       fr_pair_value_from_str(vp, "Error", -1);
                        break;
+
                case RLM_MODULE_HANDLED:        /* unlang set status */
                        return;
+
                default:
 noop:
                        WARN("ignoring request to add TACACS status with code %d", rcode);
                        return;
                }
                break;
+
        case TAC_PLUS_AUTHOR:
-               k = "TACACS-Authorization-Status";
                switch (rcode) {
                case RLM_MODULE_OK:
-                       v = "Pass-Repl";
+                       MEM(pair_update_reply(&vp, attr_tacacs_authorization_status) >= 0);
+                       fr_pair_value_from_str(vp, "Pass-Repl", -1);
                        break;
+
                case RLM_MODULE_FAIL:
                case RLM_MODULE_REJECT:
                case RLM_MODULE_USERLOCK:
-                       v = "Fail";
+                       MEM(pair_update_reply(&vp, attr_tacacs_authorization_status) >= 0);
+                       fr_pair_value_from_str(vp, "Fail", -1);
                        break;
+
                case RLM_MODULE_INVALID:
-                       v = "Error";
+                       MEM(pair_update_reply(&vp, attr_tacacs_authorization_status) >= 0);
+                       fr_pair_value_from_str(vp, "Error", -1);
                        break;
+
                default:
                        goto noop;
                }
                break;
+
        case TAC_PLUS_ACCT:
-               k = "TACACS-Accounting-Status";
                switch (rcode) {
                case RLM_MODULE_OK:
-                       v = "Success";
+                       MEM(pair_update_reply(&vp, attr_tacacs_accounting_status) >= 0);
+                       fr_pair_value_from_str(vp, "Success", -1);
                        break;
+
                case RLM_MODULE_FAIL:
                case RLM_MODULE_REJECT:
                case RLM_MODULE_USERLOCK:
                case RLM_MODULE_INVALID:
-                       v = "Error";
+                       MEM(pair_update_reply(&vp, attr_tacacs_accounting_status) >= 0);
+                       fr_pair_value_from_str(vp, "Error", -1);
                        break;
+
                default:
                        goto noop;
                }
                break;
        }
-
-       fr_pair_make(request->reply, &request->reply->vps, k, v, T_OP_EQ);
 }
 
 static void state_add(REQUEST *request, RADIUS_PACKET *packet)
@@ -140,21 +218,19 @@ static void state_add(REQUEST *request, RADIUS_PACKET *packet)
        session_id = tacacs_session_id(request->packet);
        memcpy(&buf[sizeof(buf) - sizeof(session_id)], &session_id, sizeof(session_id));
 
-       vp = fr_pair_afrom_num(packet, 0, FR_STATE);
-       rad_assert(vp != NULL);
+       MEM(vp = fr_pair_afrom_da(packet, attr_state));
        fr_pair_value_memcpy(vp, (uint8_t const *)buf, sizeof(buf));
        fr_pair_add(&packet->vps, vp);
 }
 
 static void tacacs_running(REQUEST *request, fr_state_signal_t action)
 {
-       rlm_rcode_t rcode;
-       CONF_SECTION *unlang;
-       fr_dict_attr_t const *da;
-       fr_dict_enum_t const *dv = NULL;
-       VALUE_PAIR *vp, *auth_type;
-       vp_cursor_t cursor;
-       int rc;
+       rlm_rcode_t             rcode;
+       CONF_SECTION            *unlang;
+       fr_dict_enum_t const    *dv = NULL;
+       VALUE_PAIR *vp,         *auth_type;
+       vp_cursor_t             cursor;
+       int                     rc;
 
        REQUEST_VERIFY(request);
 
@@ -238,7 +314,7 @@ stop_processing:
                 */
                fr_pair_cursor_init(&cursor, &request->control);
                auth_type = NULL;
-               while ((vp = fr_pair_cursor_next_by_num(&cursor, 0, FR_AUTH_TYPE, TAG_ANY)) != NULL) {
+               while ((vp = fr_pair_cursor_next_by_da(&cursor, attr_auth_type, TAG_ANY)) != NULL) {
                        if (!auth_type) {
                                auth_type = vp;
                                continue;
@@ -359,12 +435,7 @@ send_reply:
                gettimeofday(&request->reply->timestamp, NULL);
 
                if (tacacs_type(request->packet) == TAC_PLUS_AUTHEN) {
-                       fr_dict_attr_t const *authda;
-
-                       authda = fr_dict_attr_by_name(NULL, "TACACS-Authentication-Status");
-                       rad_assert(authda != NULL);
-                       vp = fr_pair_find_by_da(request->reply->vps, authda, TAG_ANY);
-
+                       vp = fr_pair_find_by_da(request->reply->vps, attr_tacacs_authentication_status, TAG_ANY);
                        if (vp) {
                                switch ((tacacs_authen_reply_status_t)vp->vp_uint8) {
                                case TAC_PLUS_AUTHEN_STATUS_PASS:
@@ -375,10 +446,12 @@ send_reply:
                                        fr_state_discard(global_state, request, request->packet);
                                        break;
                                default:
-                                       da = fr_dict_attr_by_name(NULL, "TACACS-Sequence-Number");
-                                       rad_assert(da != NULL);
-                                       vp = fr_pair_find_by_da(request->packet->vps, da, TAG_ANY);
-                                       rad_assert(vp != NULL);
+                                       vp = fr_pair_find_by_da(request->packet->vps,
+                                                               attr_tacacs_sequence_number, TAG_ANY);
+                                       if (!vp) {
+                                               REDEBUG("No sequence number found");
+                                               goto done;
+                                       }
 
                                        /* authentication would continue but seq_no cannot continue */
                                        if (vp->vp_uint8 == 253) {
@@ -386,18 +459,18 @@ send_reply:
                                                fr_state_discard(global_state, request, request->packet);
                                                fr_pair_list_free(&request->reply->vps);
 
-                                               vp = fr_pair_afrom_da(request->reply, authda);
-                                               rad_assert(vp != NULL);
-                                               vp->vp_uint8 = (tacacs_authen_reply_status_t)TAC_PLUS_AUTHEN_STATUS_RESTART;
-                                               fr_pair_add(&request->reply->vps, vp);
+                                               MEM(pair_update_reply(&vp, attr_tacacs_authentication_status) >= 0);
+                                               vp->vp_uint8 = TAC_PLUS_AUTHEN_STATUS_RESTART;
                                        } else {
                                                state_add(request, request->reply);
                                                request->reply->code = 1;       /* FIXME: util.c:request_verify() */
-                                               fr_request_to_state(global_state, request, request->packet, request->reply);
+                                               fr_request_to_state(global_state, request,
+                                                                   request->packet, request->reply);
                                        }
                                }
-                       } else
+                       } else {
                                fr_state_discard(global_state, request, request->packet);
+                       }
                }
 
                if (RDEBUG_ENABLED) tacacs_packet_debug(request, request->reply, false);
@@ -575,21 +648,10 @@ static int tacacs_listen_compile(CONF_SECTION *server_cs, UNUSED CONF_SECTION *l
        return 0;
 }
 
-static int tacacs_load(void)
-{
-       dict_tacacs_root = fr_dict_attr_child_by_num(fr_dict_root(fr_dict_internal), FR_TACACS_ROOT);
-       if (!dict_tacacs_root) {
-               ERROR("Missing TACACS-Root attribute");
-               return -1;
-       }
-       return 0;
-}
-
 extern rad_protocol_t proto_tacacs;
 rad_protocol_t proto_tacacs = {
        .name           = "tacacs",
        .magic          = RLM_MODULE_INIT,
-       .load           = tacacs_load,
        .inst_size      = sizeof(listen_socket_t),
        .transports     = TRANSPORT_TCP,
        .tls            = false,
index 35b0dd0fdc1b70cc05ba2ed4b4c11112b13b9bdf..1c46f25a49985ea41a264a18a74548949290bc11 100644 (file)
@@ -37,24 +37,21 @@ tacacs_type_t tacacs_type(RADIUS_PACKET const * const packet)
 {
        VALUE_PAIR const *vp;
 
-       vp = fr_pair_find_by_child_num(packet->vps, dict_tacacs_root, FR_TACACS_PACKET_TYPE, TAG_ANY);
-       rad_assert(vp != NULL);
+       vp = fr_pair_find_by_da(packet->vps, attr_tacacs_packet_type, TAG_ANY);
+       if (!vp) return 0;
 
        return (tacacs_type_t)vp->vp_uint8;
 }
 
-char const * tacacs_lookup_packet_code(RADIUS_PACKET const * const packet)
+char const *tacacs_lookup_packet_code(RADIUS_PACKET const * const packet)
 {
-       fr_dict_attr_t const *da;
        fr_dict_enum_t const *dv;
        tacacs_type_t type;
 
        type = tacacs_type(packet);
 
-       da = fr_dict_attr_child_by_num(dict_tacacs_root, FR_TACACS_PACKET_TYPE);
-       rad_assert(da != NULL);
-       dv = fr_dict_enum_by_value(da, fr_box_uint32(type));
-       rad_assert(dv != NULL);
+       dv = fr_dict_enum_by_value(attr_tacacs_packet_type, fr_box_uint32(type));
+       if (!dv) return NULL;
 
        return dv->alias;
 }
@@ -63,8 +60,8 @@ uint32_t tacacs_session_id(RADIUS_PACKET const * const packet)
 {
        VALUE_PAIR const *vp;
 
-       vp = fr_pair_find_by_child_num(packet->vps, dict_tacacs_root, FR_TACACS_SESSION_ID, TAG_ANY);
-       rad_assert(vp != NULL);
+       vp = fr_pair_find_by_da(packet->vps, attr_tacacs_session_id, TAG_ANY);
+       if (!vp) return 0;
 
        return vp->vp_uint32;
 }
@@ -92,8 +89,8 @@ bad_seqno:
                        fr_strerror_printf("client sent seq_no set to 255");
                        return false;
                }
-
                break;
+
        case TAC_PLUS_AUTHOR:
        case TAC_PLUS_ACCT:
                if ((from_client && pkt->hdr.seq_no != 1) || (!from_client && pkt->hdr.seq_no != 2))
@@ -131,6 +128,7 @@ bad_seqno:
                        }
                }
                break;
+
        case TAC_PLUS_AUTHOR:
                if (from_client) {
                        len = pkt->author.req.user_len + pkt->author.req.port_len + pkt->author.req.rem_addr_len + pkt->author.req.arg_cnt;
@@ -150,6 +148,7 @@ bad_seqno:
                        }
                }
                break;
+
        case TAC_PLUS_ACCT:
                if (from_client) {
                        uint8_t flags;
@@ -271,43 +270,32 @@ int tacacs_encode(RADIUS_PACKET * const packet, char const * const secret)
 
                if (!vp->da->flags.internal) continue;
 
-               switch (vp->da->attr) {
-               case FR_TACACS_VERSION_MINOR:
+               if (vp->da == attr_tacacs_version_minor) {
                        pkt->hdr.ver.minor = vp->vp_uint8;
-                       break;
-               case FR_TACACS_PACKET_TYPE:
+               } else if (vp->da == attr_tacacs_packet_type) {
                        pkt->hdr.type = vp->vp_uint8;
-                       break;
-               case FR_TACACS_SEQUENCE_NUMBER:
+               } else if (vp->da == attr_tacacs_sequence_number) {
                        pkt->hdr.seq_no = vp->vp_uint8;
-                       break;
-               case FR_TACACS_SESSION_ID:
+               } else if (vp->da == attr_tacacs_session_id) {
                        pkt->hdr.session_id = htonl(vp->vp_uint32);
-                       break;
-               case FR_TACACS_AUTHENTICATION_STATUS:
+               } else if (vp->da == attr_tacacs_authentication_status) {
                        pkt->authen.reply.status = vp->vp_uint8;
                        status = vp->vp_uint8;
-                       break;
-               case FR_TACACS_AUTHENTICATION_FLAGS:
+               } else if (vp->da == attr_tacacs_authentication_status) {
                        authen_reply_flags |= vp->vp_uint8;
-                       break;
-               case FR_TACACS_AUTHORIZATION_STATUS:
+               } else if (vp->da == attr_tacacs_authorization_status) {
                        pkt->author.res.status = vp->vp_uint8;
                        status = vp->vp_uint8;
-                       break;
-               case FR_TACACS_ACCOUNTING_STATUS:
+               } else if (vp->da == attr_tacacs_accounting_status) {
                        pkt->acct.res.status = vp->vp_uint8;
                        status = vp->vp_uint8;
-                       break;
-               case FR_TACACS_SERVER_MESSAGE:
+               } else if (vp->da == attr_tacacs_server_message) {
                        length_body += vp->vp_length;
                        field.server_msg = vp;
-                       break;
-               case FR_TACACS_DATA:
+               } else if (vp->da == attr_tacacs_data) {
                        length_body += vp->vp_length;
                        field.data = vp;
-                       break;
-               default:
+               } else {
                        WARN("Unhandled %s", vp->da->name);
                }
        }
@@ -320,17 +308,20 @@ int tacacs_encode(RADIUS_PACKET * const packet, char const * const secret)
                pkt->authen.reply.server_msg_len = htons(0);
                pkt->authen.reply.data_len = htons(0);
                break;
+
        case TAC_PLUS_AUTHOR:
                length_hdr += offsetof(tacacs_packet_author_res_hdr_t, body);
                pkt->author.res.arg_cnt = 0;
                pkt->author.res.server_msg_len = htons(0);
                pkt->author.res.data_len = htons(0);
                break;
+
        case TAC_PLUS_ACCT:
                length_hdr += offsetof(tacacs_packet_acct_res_hdr_t, body);
                pkt->acct.res.server_msg_len = htons(0);
                pkt->acct.res.data_len = htons(0);
                break;
+
        /* unsupported type as per draft-ietf-opsawg-tacacs section 3.6 */
        default:
 fail:
@@ -408,8 +399,8 @@ skip_fields:
 }
 
 
-static int tacacs_decode_field(TALLOC_CTX *ctx, vp_cursor_t *cursor, unsigned int attr, char const *field_name,
-                              uint8_t **field_data, size_t field_len, size_t *remaining)
+static int tacacs_decode_field(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *da,
+                              char const *field_name, uint8_t **field_data, size_t field_len, size_t *remaining)
 {
        uint8_t *p;
        VALUE_PAIR *vp;
@@ -427,8 +418,7 @@ static int tacacs_decode_field(TALLOC_CTX *ctx, vp_cursor_t *cursor, unsigned in
                return -1;
        }
 
-       vp = fr_pair_afrom_child_num(ctx, dict_tacacs_root, attr);
-       if (!vp) return -1;
+       MEM(vp = fr_pair_afrom_da(ctx, da));
 
        fr_pair_value_bstrncpy(vp, p, field_len);
        p += field_len;
@@ -465,25 +455,21 @@ int tacacs_decode(RADIUS_PACKET * const packet)
 
        remaining = ntohl(pkt->hdr.length);
 
-       vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_VERSION_MINOR);
-       if (!vp) return -1;
+       MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_version_minor));
        vp->vp_uint8 = pkt->hdr.ver.minor;
        fr_pair_cursor_append(&cursor, vp);
 
-       vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_PACKET_TYPE);
-       if (!vp) return -1;
+       MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_packet_type));
        vp->vp_uint8 = pkt->hdr.type;
        fr_pair_cursor_append(&cursor, vp);
 
        packet->code = pkt->hdr.type;
 
-       vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_SEQUENCE_NUMBER);
-       if (!vp) return -1;
+       MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_sequence_number));
        vp->vp_uint8 = pkt->hdr.seq_no;
        fr_pair_cursor_append(&cursor, vp);
 
-       vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_SESSION_ID);
-       if (!vp) return -1;
+       MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_session_id));
        vp->vp_uint32 = ntohl(pkt->hdr.session_id);
        fr_pair_cursor_append(&cursor, vp);
        session_id = vp->vp_uint32;
@@ -502,22 +488,19 @@ int tacacs_decode(RADIUS_PACKET * const packet)
                        /*
                         *      Decode 4 octets of various flags.
                         */
-                       vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_ACTION);
-                       if (!vp) return -1;
+                       MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_action));
                        vp->vp_uint8 = pkt->authen.start.action;
                        fr_pair_cursor_append(&cursor, vp);
 
-                       vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_PRIVILEGE_LEVEL);
-                       if (!vp) return -1;
+                       MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_privilege_level));
                        vp->vp_uint8 = pkt->authen.start.priv_lvl;
                        fr_pair_cursor_append(&cursor, vp);
 
-                       vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_AUTHENTICATION_TYPE);
-                       if (!vp) return -1;
+                       MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_authentication_type));
                        vp->vp_uint8 = pkt->authen.start.authen_type;
                        fr_pair_cursor_append(&cursor, vp);
 
-                       vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_AUTHENTICATION_SERVICE);
+                       MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_authentication_service));
                        if (!vp) return -1;
                        vp->vp_uint8 = pkt->authen.start.authen_service;
                        fr_pair_cursor_append(&cursor, vp);
@@ -527,22 +510,22 @@ int tacacs_decode(RADIUS_PACKET * const packet)
                         */
                        p = pkt->authen.start.body;
 
-                       if (tacacs_decode_field(packet, &cursor, FR_TACACS_USER_NAME, "User",
+                       if (tacacs_decode_field(packet, &cursor, attr_tacacs_user_name, "User",
                                                &p, pkt->authen.start.user_len, &remaining) < 0) {
                                return -1;
                        }
 
-                       if (tacacs_decode_field(packet, &cursor, FR_TACACS_CLIENT_PORT, "Port",
+                       if (tacacs_decode_field(packet, &cursor, attr_tacacs_client_port, "Port",
                                                &p, pkt->authen.start.port_len, &remaining) < 0) {
                                return -1;
                        }
 
-                       if (tacacs_decode_field(packet, &cursor, FR_TACACS_REMOTE_ADDRESS, "Remote address",
+                       if (tacacs_decode_field(packet, &cursor, attr_tacacs_remote_address, "Remote address",
                                                &p, pkt->authen.start.rem_addr_len, &remaining) < 0) {
                                return -1;
                        }
 
-                       if (tacacs_decode_field(packet, &cursor, FR_TACACS_DATA, "Data",
+                       if (tacacs_decode_field(packet, &cursor, attr_tacacs_data, "Data",
                                                &p, pkt->authen.start.data_len, &remaining) < 0) {
                                return -1;
                        }
@@ -561,12 +544,12 @@ int tacacs_decode(RADIUS_PACKET * const packet)
                         */
                        p = pkt->authen.cont.body;
 
-                       if (tacacs_decode_field(packet, &cursor, FR_TACACS_USER_MESSAGE, "User message",
+                       if (tacacs_decode_field(packet, &cursor, attr_tacacs_user_message, "User message",
                                                &p, ntohs(pkt->authen.cont.user_msg_len), &remaining) < 0) {
                                return -1;
                        }
 
-                       if (tacacs_decode_field(packet, &cursor, FR_TACACS_DATA, "Data",
+                       if (tacacs_decode_field(packet, &cursor, attr_tacacs_data, "Data",
                                                &p, ntohs(pkt->authen.cont.data_len), &remaining) < 0) {
                                return -1;
                        }
@@ -577,12 +560,14 @@ int tacacs_decode(RADIUS_PACKET * const packet)
                        if (pkt->authen.cont.flags & TAC_PLUS_CONTINUE_FLAG_ABORT) {
                                if (!ntohs(pkt->authen.cont.data_len) ||
                                    !(vp = fr_pair_cursor_last(&cursor))) {
-                                       fr_strerror_printf("Client aborted authentication session %u with no message", session_id);
+                                       fr_strerror_printf("Client aborted authentication session %u "
+                                                          "with no message", session_id);
                                        return -2;
                                }
 
                                if (ntohs(pkt->authen.cont.data_len) > 128) {
-                                       fr_strerror_printf("Client aborted authentication session %u with too long message", session_id);
+                                       fr_strerror_printf("Client aborted authentication session %u "
+                                                          "with too long message", session_id);
                                        return -2;
                                }
 
@@ -617,40 +602,36 @@ int tacacs_decode(RADIUS_PACKET * const packet)
                /*
                 *      Decode 4 octets of various flags.
                 */
-               vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_AUTHENTICATION_METHOD);
-               if (!vp) return -1;
+               MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_authentication_method));
                vp->vp_uint8 = pkt->author.req.authen_method;
                fr_pair_cursor_append(&cursor, vp);
 
-               vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_PRIVILEGE_LEVEL);
-               if (!vp) return -1;
+               MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_privilege_level));
                vp->vp_uint8 = pkt->author.req.priv_lvl;
                fr_pair_cursor_append(&cursor, vp);
 
-               vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_AUTHENTICATION_TYPE);
-               if (!vp) return -1;
+               MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_authentication_type));
                vp->vp_uint8 = pkt->author.req.authen_type;
                fr_pair_cursor_append(&cursor, vp);
 
-               vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_AUTHENTICATION_SERVICE);
-               if (!vp) return -1;
+               MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_authentication_service));
                vp->vp_uint8 = pkt->author.req.authen_service;
                fr_pair_cursor_append(&cursor, vp);
 
                /*
                 *      Decode 3 fields, based on their "length"
                 */
-               if (tacacs_decode_field(packet, &cursor, FR_TACACS_USER_NAME, "User",
+               if (tacacs_decode_field(packet, &cursor, attr_tacacs_user_name, "User",
                                        &p, pkt->author.req.user_len, &remaining) < 0) {
                        return -1;
                }
 
-               if (tacacs_decode_field(packet, &cursor, FR_TACACS_CLIENT_PORT, "Port",
+               if (tacacs_decode_field(packet, &cursor, attr_tacacs_client_port, "Port",
                                        &p, pkt->authen.start.port_len, &remaining) < 0) {
                        return -1;
                }
 
-               if (tacacs_decode_field(packet, &cursor, FR_TACACS_REMOTE_ADDRESS, "Remote address",
+               if (tacacs_decode_field(packet, &cursor, attr_tacacs_remote_address, "Remote address",
                                        &p, pkt->authen.start.rem_addr_len, &remaining) < 0) {
                        return -1;
                }
@@ -691,48 +672,37 @@ int tacacs_decode(RADIUS_PACKET * const packet)
                /*
                 *      Decode 8 octets of various fields.
                 */
-               vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_ACCOUNTING_FLAGS);
-               if (!vp) return -1;
+               MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_accounting_flags));
                vp->vp_uint8 = pkt->acct.req.flags;
                fr_pair_cursor_append(&cursor, vp);
 
-               vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_AUTHENTICATION_METHOD);
-               if (!vp) return -1;
+               MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_authentication_method));
                vp->vp_uint8 = pkt->acct.req.authen_method;
                fr_pair_cursor_append(&cursor, vp);
 
-               vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_PRIVILEGE_LEVEL);
-               if (!vp) return -1;
+               MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_privilege_level));
                vp->vp_uint8 = pkt->acct.req.priv_lvl;
                fr_pair_cursor_append(&cursor, vp);
 
-               vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_AUTHENTICATION_TYPE);
-               if (!vp) return -1;
+               MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_authentication_type));
                vp->vp_uint8 = pkt->acct.req.authen_type;
                fr_pair_cursor_append(&cursor, vp);
 
-               vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_AUTHENTICATION_SERVICE);
-               if (!vp) return -1;
+               MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_authentication_service));
                vp->vp_uint8 = pkt->acct.req.authen_service;
                fr_pair_cursor_append(&cursor, vp);
 
                /*
                 *      Decode 3 fields, based on their "length"
                 */
-               if (tacacs_decode_field(packet, &cursor, FR_TACACS_USER_NAME, "User",
-                                       &p, pkt->acct.req.user_len, &remaining) < 0) {
-                       return -1;
-               }
+               if (tacacs_decode_field(packet, &cursor, attr_tacacs_user_name, "User",
+                                       &p, pkt->acct.req.user_len, &remaining) < 0) return -1;
 
-               if (tacacs_decode_field(packet, &cursor, FR_TACACS_CLIENT_PORT, "Port",
-                                       &p, pkt->acct.req.port_len, &remaining) < 0) {
-                       return -1;
-               }
+               if (tacacs_decode_field(packet, &cursor, attr_tacacs_client_port, "Port",
+                                       &p, pkt->acct.req.port_len, &remaining) < 0) return -1;
 
-               if (tacacs_decode_field(packet, &cursor, FR_TACACS_REMOTE_ADDRESS, "Remote address",
-                                       &p, pkt->acct.req.rem_addr_len, &remaining) < 0) {
-                       return -1;
-               }
+               if (tacacs_decode_field(packet, &cursor, attr_tacacs_remote_address, "Remote address",
+                                       &p, pkt->acct.req.rem_addr_len, &remaining) < 0) return -1;
 
                /* FIXME fully support arg */
                p =  pkt->acct.req.body;
@@ -912,32 +882,35 @@ int tacacs_send(RADIUS_PACKET * const packet, RADIUS_PACKET const * const origin
        uint8_t                 seq_no;
        VALUE_PAIR              *vp;
 
-       vp = fr_pair_find_by_child_num(original->vps, dict_tacacs_root, FR_TACACS_VERSION_MINOR, TAG_ANY);
-       rad_assert(vp != NULL);
+       vp = fr_pair_find_by_da(original->vps, attr_tacacs_version_minor, TAG_ANY);
+       if (!vp) {
+               fr_strerror_printf("Missing %s", attr_tacacs_version_minor->name);
+               return -1;
+       }
        vminor = vp->vp_uint8;
 
-       vp = fr_pair_afrom_da(packet, vp->da);
-       if (!vp) return -1;
+       vp = fr_pair_find_by_da(original->vps, attr_tacacs_sequence_number, TAG_ANY);
+       if (!vp) {
+               fr_strerror_printf("Missing %s", attr_tacacs_sequence_number->name);
+               return -1;
+       }
+       seq_no = vp->vp_uint8 + 1;      /* we catch client 255 on ingress */
+
+       MEM(vp = fr_pair_afrom_da(packet, vp->da));
        vp->vp_uint8 = vminor;
        fr_pair_add(&packet->vps, vp);
 
        type = tacacs_type(original);
 
-       vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_PACKET_TYPE);
+       MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_packet_type));
        vp->vp_uint8 = type;
        fr_pair_add(&packet->vps, vp);
 
-       vp = fr_pair_find_by_child_num(original->vps, dict_tacacs_root, FR_TACACS_SEQUENCE_NUMBER, TAG_ANY);
-       rad_assert(vp != NULL);
-       seq_no = vp->vp_uint8 + 1;      /* we catch client 255 on ingress */
-
-       vp = fr_pair_afrom_da(packet, vp->da);
-       if (!vp) return -1;
+       MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_sequence_number));
        vp->vp_uint8 = seq_no;
        fr_pair_add(&packet->vps, vp);
 
-       vp = fr_pair_afrom_child_num(packet, dict_tacacs_root, FR_TACACS_SESSION_ID);
-       if (!vp) return -1;
+       MEM(vp = fr_pair_afrom_da(packet, attr_tacacs_session_id));
        vp->vp_uint32 = tacacs_session_id(original);
        fr_pair_add(&packet->vps, vp);
 
index c4dfde9f1d2a82520134d4fc633fafa8f57ae132..ed94216cae654d67d684f6d2ea5c910fd0182e73 100644 (file)
@@ -231,12 +231,37 @@ typedef struct CC_HINT(__packed__) tacacs_packet {
        };
 } tacacs_packet_t;
 
-tacacs_type_t tacacs_type(RADIUS_PACKET const * const packet);
-char const * tacacs_lookup_packet_code(RADIUS_PACKET const * const packet);
-uint32_t tacacs_session_id(RADIUS_PACKET const * const packet);
-int tacacs_read_packet(RADIUS_PACKET * const packet, char const * const secret);
-int tacacs_decode(RADIUS_PACKET * const packet);
-int tacacs_encode(RADIUS_PACKET * const packet, char const * const secret);
-int tacacs_send(RADIUS_PACKET * const packet, RADIUS_PACKET const * const original, char const * const secret);
-
-extern fr_dict_attr_t const *dict_tacacs_root;
+fr_dict_attr_t const *attr_tacacs_accounting_flags;
+fr_dict_attr_t const *attr_tacacs_accounting_status;
+fr_dict_attr_t const *attr_tacacs_action;
+fr_dict_attr_t const *attr_tacacs_authentication_flags;
+fr_dict_attr_t const *attr_tacacs_authentication_method;
+fr_dict_attr_t const *attr_tacacs_authentication_service;
+fr_dict_attr_t const *attr_tacacs_authentication_status;
+fr_dict_attr_t const *attr_tacacs_authentication_type;
+fr_dict_attr_t const *attr_tacacs_authorization_status;
+fr_dict_attr_t const *attr_tacacs_client_port;
+fr_dict_attr_t const *attr_tacacs_data;
+fr_dict_attr_t const *attr_tacacs_packet_type;
+fr_dict_attr_t const *attr_tacacs_privilege_level;
+fr_dict_attr_t const *attr_tacacs_remote_address;
+fr_dict_attr_t const *attr_tacacs_sequence_number;
+fr_dict_attr_t const *attr_tacacs_server_message;
+fr_dict_attr_t const *attr_tacacs_session_id;
+fr_dict_attr_t const *attr_tacacs_user_message;
+fr_dict_attr_t const *attr_tacacs_user_name;
+fr_dict_attr_t const *attr_tacacs_version_minor;
+
+tacacs_type_t  tacacs_type(RADIUS_PACKET const * const packet);
+
+char const     *tacacs_lookup_packet_code(RADIUS_PACKET const * const packet);
+
+uint32_t       tacacs_session_id(RADIUS_PACKET const * const packet);
+
+int            tacacs_read_packet(RADIUS_PACKET * const packet, char const * const secret);
+
+int            tacacs_decode(RADIUS_PACKET * const packet);
+
+int            tacacs_encode(RADIUS_PACKET * const packet, char const * const secret);
+
+int            tacacs_send(RADIUS_PACKET * const packet, RADIUS_PACKET const * const original, char const * const secret);