From: Arran Cudbard-Bell Date: Wed, 16 May 2018 14:29:05 +0000 (+0600) Subject: Autoload proto_tacacs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bc1715cd16dca03210d80b6a1fb983114ea08410;p=thirdparty%2Ffreeradius-server.git Autoload proto_tacacs --- diff --git a/src/modules/proto_tacacs/proto_tacacs.c b/src/modules/proto_tacacs/proto_tacacs.c index 0b3d0319010..74c61d56f17 100644 --- a/src/modules/proto_tacacs/proto_tacacs.c +++ b/src/modules/proto_tacacs/proto_tacacs.c @@ -30,6 +30,71 @@ #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, diff --git a/src/modules/proto_tacacs/tacacs.c b/src/modules/proto_tacacs/tacacs.c index 35b0dd0fdc1..1c46f25a499 100644 --- a/src/modules/proto_tacacs/tacacs.c +++ b/src/modules/proto_tacacs/tacacs.c @@ -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); diff --git a/src/modules/proto_tacacs/tacacs.h b/src/modules/proto_tacacs/tacacs.h index c4dfde9f1d2..ed94216cae6 100644 --- a/src/modules/proto_tacacs/tacacs.h +++ b/src/modules/proto_tacacs/tacacs.h @@ -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);