27 #include <freeradius-devel/io/test_point.h>
28 #include <freeradius-devel/protocol/tacacs/tacacs.h>
29 #include <freeradius-devel/util/dbuff.h>
30 #include <freeradius-devel/util/rand.h>
31 #include <freeradius-devel/util/struct.h>
39 case FR_PACKET_TYPE_VALUE_AUTHENTICATION_START:
44 case FR_PACKET_TYPE_VALUE_AUTHENTICATION_PASS:
49 case FR_PACKET_TYPE_VALUE_AUTHENTICATION_FAIL:
54 case FR_PACKET_TYPE_VALUE_AUTHENTICATION_GETDATA:
59 case FR_PACKET_TYPE_VALUE_AUTHENTICATION_GETUSER:
64 case FR_PACKET_TYPE_VALUE_AUTHENTICATION_GETPASS:
69 case FR_PACKET_TYPE_VALUE_AUTHENTICATION_RESTART:
74 case FR_PACKET_TYPE_VALUE_AUTHENTICATION_ERROR:
79 case FR_PACKET_TYPE_VALUE_AUTHENTICATION_CONTINUE:
84 case FR_PACKET_TYPE_VALUE_AUTHENTICATION_CONTINUE_ABORT:
89 case FR_PACKET_TYPE_VALUE_AUTHORIZATION_REQUEST:
93 case FR_PACKET_TYPE_VALUE_AUTHORIZATION_PASS_ADD:
98 case FR_PACKET_TYPE_VALUE_AUTHORIZATION_PASS_REPLACE:
103 case FR_PACKET_TYPE_VALUE_AUTHORIZATION_FAIL:
108 case FR_PACKET_TYPE_VALUE_ACCOUNTING_REQUEST:
112 case FR_PACKET_TYPE_VALUE_ACCOUNTING_SUCCESS:
117 case FR_PACKET_TYPE_VALUE_ACCOUNTING_ERROR:
141 if (arg_cnt == 255)
break;
143 if (
vp->
da->flags.internal)
continue;
151 if (
vp->vp_length > 0xff)
continue;
161 if (
vp->
da->parent->flags.is_root) {
194 if (i > arg_cnt)
break;
196 if (
vp->
da->flags.internal)
continue;
204 if (
vp->vp_length > 0xff)
continue;
220 if (child_argc > (arg_cnt - i)) child_argc = arg_cnt = i;
246 switch (
vp->vp_type) {
262 if (slen <= 0)
return -1;
267 if (slen <= 0)
return -1;
297 if (!
vp || !
vp->vp_length || (
vp->vp_length > max_len))
return 0;
317 packet->authen_start.data_len = 0;
323 fr_strerror_printf(
"Packet contains %s but no %s", da_chap->name, da_challenge->name);
327 if (!challenge->vp_length) {
332 if ((chap->vp_length + challenge->vp_length) > 255) {
333 fr_strerror_printf(
"%s and %s are longer than 255 octets", da_chap->name, da_challenge->name);
341 packet->authen_start.data_len = chap->vp_length + challenge->vp_length;
352 #define ENCODE_FIELD_UINT8(_field, _da) do { \
353 vp = fr_pair_find_by_da(vps, NULL, _da); \
354 _field = (vp) ? vp->vp_uint8 : 0; \
357 #define ENCODE_FIELD_STRING8(_field, _da) _field = tacacs_encode_field(&work_dbuff, vps, _da, 0xff)
358 #define ENCODE_FIELD_STRING16(_field, _da) _field = htons(tacacs_encode_field(&work_dbuff, vps, _da, 0xffff))
371 size_t body_len, packet_len;
493 packet->
hdr.version = original->version;
572 }
else switch (packet->authen_start.authen_type) {
576 case FR_AUTHENTICATION_TYPE_VALUE_PAP:
580 case FR_AUTHENTICATION_TYPE_VALUE_CHAP:
584 case FR_AUTHENTICATION_TYPE_VALUE_MSCHAP: {
588 if (rcode < 0)
return rcode;
590 if (rcode > 0)
break;
726 if (packet->author_req.arg_cnt > 0) {
780 if (!((packet->author_reply.status == FR_AUTHORIZATION_STATUS_VALUE_ERROR) ||
781 (packet->author_reply.status == FR_AUTHORIZATION_STATUS_VALUE_FOLLOW))) {
785 packet->author_reply.arg_cnt = 0;
797 if (packet->author_reply.arg_cnt > 0) {
867 if (packet->acct_req.arg_cnt > 0) {
939 packet->
hdr.version = original->version;
1018 fr_strerror_const(
"Packet should be decrypted, but the secret has zero length");
1067 if (!test_ctx)
return -1;
static int const char char buffer[256]
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
#define FR_DBUFF_ADVANCE_RETURN(_dbuff_or_marker, _len)
Advance the 'current' position in dbuff or marker by _len bytes returning if _len is out of range.
struct fr_dbuff_marker_s fr_dbuff_marker_t
A position marker associated with a dbuff.
#define fr_dbuff_current(_dbuff_or_marker)
Return the 'current' position of a dbuff or marker.
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
#define FR_DBUFF_MEMSET_RETURN(_dbuff_or_marker, _c, _inlen)
Set _inlen bytes of a dbuff or marker to _c returning if there is insufficient space.
#define FR_DBUFF_IN_MEMCPY_RETURN(_dbuff_or_marker, _in, _inlen)
Copy exactly _inlen bytes into dbuff or marker returning if there's insufficient space.
#define FR_DBUFF_REMAINING_RETURN(_dbuff_or_marker, _len)
Check if _len bytes are available in the dbuff and if not return the number of bytes we'd need.
#define FR_DBUFF_IN_RETURN(_dbuff_or_marker, _in)
Copy data from a fixed sized C type into a dbuff returning if there is insufficient space.
#define FR_DBUFF(_dbuff_or_marker)
Create a new dbuff pointing to the same underlying buffer.
#define FR_DBUFF_MAX(_dbuff_or_marker, _max)
Limit the maximum number of bytes available in the dbuff when passing it to another function.
static uint8_t * fr_dbuff_marker(fr_dbuff_marker_t *m, fr_dbuff_t *dbuff)
Initialises a new marker pointing to the 'current' position of the dbuff.
#define fr_dbuff_out(_out, _dbuff_or_marker)
Copy data from a dbuff or marker to a fixed sized C type.
#define FR_DBUFF_IN_BYTES_RETURN(_dbuff_or_marker,...)
Copy a byte sequence into a dbuff or marker returning if there's insufficient space.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_t const * fr_dict_by_da(fr_dict_attr_t const *da)
Attempt to locate the protocol dictionary containing an attribute.
@ L_DBG_LVL_4
4th highest priority debug messages (-xxxx | -Xxx).
@ FR_TYPE_TIME_DELTA
A period of time measured in nanoseconds.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_VENDOR
Attribute that represents a vendor in the attribute tree.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
static fr_dict_attr_t const * attr_tacacs_authentication_flags
static fr_dict_attr_t const * attr_tacacs_user_message
static fr_dict_attr_t const * attr_tacacs_session_id
static fr_dict_attr_t const * attr_tacacs_server_message
static fr_dict_attr_t const * attr_tacacs_privilege_level
static fr_dict_attr_t const * attr_tacacs_authentication_type
static fr_dict_attr_t const * attr_tacacs_accounting_status
static fr_dict_attr_t const * attr_tacacs_authentication_service
static fr_dict_attr_t const * attr_tacacs_authentication_status
static fr_dict_attr_t const * attr_tacacs_client_port
static fr_dict_attr_t const * attr_tacacs_remote_address
static fr_dict_attr_t const * attr_tacacs_action
static fr_dict_attr_t const * attr_tacacs_authorization_status
static fr_dict_attr_t const * attr_tacacs_accounting_flags
static fr_dict_attr_t const * attr_tacacs_data
void fr_proto_da_stack_build(fr_da_stack_t *stack, fr_dict_attr_t const *da)
Build a complete DA stack from the da back to the root.
static fr_dict_t const * dict_tacacs
static fr_dict_attr_t const * attr_tacacs_user_name
HIDDEN fr_dict_attr_t const * attr_tacacs_argument_list
HIDDEN fr_dict_attr_t const * attr_tacacs_chap_password
HIDDEN fr_dict_attr_t const * attr_tacacs_mschap_challenge
HIDDEN fr_dict_attr_t const * attr_tacacs_packet
HIDDEN fr_dict_attr_t const * attr_tacacs_mschap2_response
HIDDEN fr_dict_attr_t const * attr_tacacs_authentication_continue_flags
HIDDEN fr_dict_attr_t const * attr_tacacs_user_password
HIDDEN fr_dict_attr_t const * attr_tacacs_chap_challenge
HIDDEN fr_dict_attr_t const * attr_tacacs_mschap_response
HIDDEN fr_dict_attr_t const * attr_tacacs_authentication_method
HIDDEN fr_dict_attr_t const * attr_tacacs_flags
int fr_tacacs_body_xor(fr_tacacs_packet_t const *pkt, uint8_t *body, size_t body_len, char const *secret, size_t secret_len)
XOR the body based on the secret key.
void fr_tacacs_global_free(void)
int fr_tacacs_global_init(void)
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)
int fr_tacacs_code_to_packet(fr_tacacs_packet_t *pkt, uint32_t code)
static ssize_t tacacs_encode_field(fr_dbuff_t *dbuff, fr_pair_list_t *vps, fr_dict_attr_t const *da, size_t max_len)
#define ENCODE_FIELD_UINT8(_field, _da)
ssize_t fr_tacacs_encode(fr_dbuff_t *dbuff, uint8_t const *original_packet, char const *secret, size_t secret_len, unsigned int code, fr_pair_list_t *vps)
Encode VPS into a raw TACACS packet.
static uint8_t tacacs_encode_body_arg_cnt(fr_pair_list_t *vps, fr_dict_attr_t const *da)
Encode a TACACS+ 'arg_N' fields.
static ssize_t fr_tacacs_encode_proto(UNUSED TALLOC_CTX *ctx, fr_pair_list_t *vps, uint8_t *data, size_t data_len, void *proto_ctx)
static int _encode_test_ctx(fr_tacacs_ctx_t *proto_ctx)
#define ENCODE_FIELD_STRING8(_field, _da)
fr_test_point_proto_encode_t tacacs_tp_encode_proto
#define ENCODE_FIELD_STRING16(_field, _da)
static ssize_t tacacs_encode_body_arg_n(fr_dbuff_t *dbuff, uint8_t arg_cnt, uint8_t *arg_len, fr_pair_list_t *vps, fr_dict_attr_t const *da)
static int encode_test_ctx(void **out, TALLOC_CTX *ctx)
uint32_t fr_rand(void)
Return a 32-bit random number.
ssize_t fr_sbuff_in_sprintf(fr_sbuff_t *sbuff, char const *fmt,...)
Print using a fmt string to an sbuff.
#define FR_SBUFF_OUT(_start, _len_or_end)
ssize_t fr_struct_to_network(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *parent_cursor, void *encode_ctx, fr_encode_dbuff_t encode_value, fr_encode_dbuff_t encode_pair)
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
#define packet_is_authen_reply(p)
#define packet_is_authen_continue(p)
@ FR_TAC_PLUS_CONTINUE_FLAG_UNSET
@ FR_TAC_PLUS_CONTINUE_FLAG_ABORT
@ FR_TAC_PLUS_SINGLE_CONNECT_FLAG
@ FR_TAC_PLUS_UNENCRYPTED_FLAG
#define fr_tacacs_packet_log_hex(_log, _packet, _size)
fr_dict_attr_t const * root
@ FR_TAC_PLUS_AUTHOR_STATUS_PASS_ADD
@ FR_TAC_PLUS_AUTHOR_STATUS_FAIL
@ FR_TAC_PLUS_AUTHOR_STATUS_PASS_REPL
#define packet_is_acct_reply(p)
#define packet_is_author_request(p)
#define packet_is_acct_request(p)
#define packet_is_authen_start_request(p)
3.4.
fr_tacacs_packet_hdr_t hdr
#define FR_MAX_PACKET_SIZE
@ FR_TAC_PLUS_ACCT_STATUS_SUCCESS
@ FR_TAC_PLUS_ACCT_STATUS_ERROR
@ FR_TAC_PLUS_AUTHEN_STATUS_PASS
@ FR_TAC_PLUS_AUTHEN_STATUS_GETDATA
@ FR_TAC_PLUS_AUTHEN_STATUS_ERROR
@ FR_TAC_PLUS_AUTHEN_STATUS_GETUSER
@ FR_TAC_PLUS_AUTHEN_STATUS_FAIL
@ FR_TAC_PLUS_AUTHEN_STATUS_RESTART
@ FR_TAC_PLUS_AUTHEN_STATUS_GETPASS
#define packet_is_author_reply(p)
static int talloc_const_free(void const *ptr)
Free const'd memory.
fr_test_point_ctx_alloc_t test_ctx
Allocate a test ctx for the encoder.
Entry point for protocol encoders.
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
ssize_t fr_pair_print_value_quoted(fr_sbuff_t *out, fr_pair_t const *vp, fr_token_t quote)
Print the value of an attribute to a string.
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
#define FR_PROTO_HEX_DUMP(_data, _data_len, _fmt,...)
#define FR_PROTO_TRACE(_fmt,...)
#define FR_PROTO_STACK_PRINT(_stack, _depth)
Structure for holding the stack of dictionary attributes being encoded.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
return fr_dbuff_set(dbuff, &our_dbuff)
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
static size_t char ** out