From: Alan T. DeKok Date: Wed, 19 Aug 2020 21:29:59 +0000 (-0400) Subject: copy original header if we have it X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=64acd55a49867bb71fd489587f7f7764abc8858e;p=thirdparty%2Ffreeradius-server.git copy original header if we have it and if there's no VPs parented by TACACS-Packet. This lets us avoid some extra work, so we don't have to copy VPs from the request to the reply --- diff --git a/src/protocols/tacacs/encode.c b/src/protocols/tacacs/encode.c index 74281784f57..d8ca6d131e3 100644 --- a/src/protocols/tacacs/encode.c +++ b/src/protocols/tacacs/encode.c @@ -155,6 +155,11 @@ ssize_t fr_tacacs_encode(uint8_t *buffer, size_t buffer_len, uint8_t const *orig return -1; } + /* + * Handle directly in the allocated buffer + */ + packet = (fr_tacacs_packet_t *)buffer; + /* * Find the first attribute which is parented by TACACS-Packet. */ @@ -165,28 +170,35 @@ ssize_t fr_tacacs_encode(uint8_t *buffer, size_t buffer_len, uint8_t const *orig } if (!vp) { - fr_strerror_printf("No TACACS+ %s in the attribute list", - attr_tacacs_packet->name); - return -1; - } + if (!original) { + fr_strerror_printf("No TACACS+ %s in the attribute list", + attr_tacacs_packet->name); + return -1; + } - fr_proto_da_stack_build(&da_stack, attr_tacacs_packet); - FR_PROTO_STACK_PRINT(&da_stack, 0); + /* + * Initialize the reply from the request. + */ + memset(buffer, 0, sizeof(packet->hdr)); + packet->hdr.version = original->version; + packet->hdr.type = original->type; + packet->hdr.flags = original->flags; + packet->hdr.session_id = original->session_id; - /* - * Call the struct encoder to do the actual work. - */ - len = fr_struct_to_network(buffer, buffer_len, &da_stack, 0, &cursor, NULL, NULL); - if (len != sizeof(fr_tacacs_packet_hdr_t)) { - fr_strerror_printf("Failed encoding %s using fr_struct_to_network()", - attr_tacacs_packet->name); - return -1; - } + } else { + fr_proto_da_stack_build(&da_stack, attr_tacacs_packet); + FR_PROTO_STACK_PRINT(&da_stack, 0); - /* - * Handle directly in the allocated buffer - */ - packet = (fr_tacacs_packet_t *)buffer; + /* + * Call the struct encoder to do the actual work. + */ + len = fr_struct_to_network(buffer, buffer_len, &da_stack, 0, &cursor, NULL, NULL); + if (len != sizeof(fr_tacacs_packet_hdr_t)) { + fr_strerror_printf("Failed encoding %s using fr_struct_to_network()", + attr_tacacs_packet->name); + return -1; + } + } /* * Encode 8 octets of various fields not members of STRUCT @@ -565,6 +577,19 @@ ssize_t fr_tacacs_encode(uint8_t *buffer, size_t buffer_len, uint8_t const *orig fr_assert(packet_len < FR_TACACS_MAX_PACKET_SIZE); packet->hdr.length = htonl(packet_len - sizeof(fr_tacacs_packet_hdr_t)); + /* + * If the original packet is encrypted, then the reply + * MUST be encrypted too. + * + * On the other hand, if the request is unencrypted, + * we're OK with sending an encrypted reply. Because, + * whatever. + */ + if (original && + ((original->flags & FR_TAC_PLUS_UNENCRYPTED_FLAG) == 0)) { + packet->hdr.flags &= ~FR_TAC_PLUS_UNENCRYPTED_FLAG; + } + /* * 3.6. Encryption *