Branch data Line data Source code
1 : : /* 2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 : : * 4 : : * Licensed under the Apache License, Version 2.0 (the "License"). 5 : : * You may not use this file except in compliance with the License. 6 : : * A copy of the License is located at 7 : : * 8 : : * http://aws.amazon.com/apache2.0 9 : : * 10 : : * or in the "license" file accompanying this file. This file is distributed 11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 : : * express or implied. See the License for the specific language governing 13 : : * permissions and limitations under the License. 14 : : */ 15 : : 16 : : #include "tls/extensions/s2n_client_server_name.h" 17 : : 18 : : #include <stdint.h> 19 : : 20 : : #include "tls/s2n_tls.h" 21 : : #include "tls/s2n_tls_parameters.h" 22 : : #include "utils/s2n_safety.h" 23 : : 24 : : #define S2N_NAME_TYPE_HOST_NAME 0 25 : : 26 : : static bool s2n_client_server_name_should_send(struct s2n_connection *conn); 27 : : static int s2n_client_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out); 28 : : static int s2n_client_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); 29 : : 30 : : const s2n_extension_type s2n_client_server_name_extension = { 31 : : .iana_value = TLS_EXTENSION_SERVER_NAME, 32 : : .is_response = false, 33 : : .send = s2n_client_server_name_send, 34 : : .recv = s2n_client_server_name_recv, 35 : : .should_send = s2n_client_server_name_should_send, 36 : : .if_missing = s2n_extension_noop_if_missing, 37 : : }; 38 : : 39 : : static bool s2n_client_server_name_should_send(struct s2n_connection *conn) 40 : 7724 : { 41 [ + - ][ + + ]: 7724 : return conn && conn->server_name[0] != '\0'; 42 : 7724 : } 43 : : 44 : : static int s2n_client_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out) 45 : 194 : { 46 : 194 : struct s2n_stuffer_reservation server_name_list_size = { 0 }; 47 [ - + ]: 194 : POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &server_name_list_size)); 48 : : 49 : : /* NameType, as described by RFC6066. 50 : : * host_name is currently the only possible NameType defined. */ 51 [ - + ]: 194 : POSIX_GUARD(s2n_stuffer_write_uint8(out, S2N_NAME_TYPE_HOST_NAME)); 52 : : 53 [ - + ]: 194 : POSIX_GUARD(s2n_stuffer_write_uint16(out, strlen(conn->server_name))); 54 [ - + ]: 194 : POSIX_GUARD(s2n_stuffer_write_bytes(out, (const uint8_t *) conn->server_name, strlen(conn->server_name))); 55 : : 56 [ - + ]: 194 : POSIX_GUARD(s2n_stuffer_write_vector_size(&server_name_list_size)); 57 : 194 : return S2N_SUCCESS; 58 : 194 : } 59 : : 60 : : /* Read the extension up to the first item in ServerNameList. Instantiates the server_name blob to 61 : : * point to the first entry. For now s2n ignores all subsequent items in ServerNameList. 62 : : */ 63 : : S2N_RESULT s2n_client_server_name_parse(struct s2n_stuffer *extension, struct s2n_blob *server_name) 64 : 228 : { 65 : 228 : uint16_t list_size = 0; 66 [ - + ]: 228 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(extension, &list_size)); 67 [ + + ][ + - ]: 228 : RESULT_ENSURE_LTE(list_size, s2n_stuffer_data_available(extension)); 68 : : 69 : 226 : uint8_t server_name_type = 0; 70 [ - + ]: 226 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(extension, &server_name_type)); 71 [ + - ][ + + ]: 226 : RESULT_ENSURE_EQ(server_name_type, S2N_NAME_TYPE_HOST_NAME); 72 : : 73 : 225 : uint16_t length = 0; 74 [ - + ]: 225 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(extension, &length)); 75 [ + + ][ + - ]: 225 : RESULT_ENSURE_LTE(length, s2n_stuffer_data_available(extension)); 76 : : 77 : 223 : uint8_t *data = s2n_stuffer_raw_read(extension, length); 78 [ # # ][ - + ]: 223 : RESULT_ENSURE_REF(data); 79 [ - + ]: 223 : RESULT_GUARD_POSIX(s2n_blob_init(server_name, data, length)); 80 : : 81 : 223 : return S2N_RESULT_OK; 82 : 223 : } 83 : : 84 : : static int s2n_client_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) 85 : 229 : { 86 [ # # ][ - + ]: 229 : POSIX_ENSURE_REF(conn); 87 : : 88 : : /* Exit early if we've already parsed the server name */ 89 [ + + ]: 229 : if (conn->server_name[0]) { 90 : 4 : return S2N_SUCCESS; 91 : 4 : } 92 : : 93 : : /* Ignore if malformed or we don't have enough space to store it. We just won't use the server name. */ 94 : 225 : struct s2n_blob server_name = { 0 }; 95 [ + + ][ - + ]: 225 : if (!s2n_result_is_ok(s2n_client_server_name_parse(extension, &server_name)) || server_name.size > S2N_MAX_SERVER_NAME) { 96 : 5 : return S2N_SUCCESS; 97 : 5 : } 98 : : 99 [ - + ][ # # ]: 220 : POSIX_CHECKED_MEMCPY(conn->server_name, server_name.data, server_name.size); [ + - ] 100 : : 101 : 220 : return S2N_SUCCESS; 102 : 220 : }