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 : : #include <sys/param.h> 20 : : 21 : : #include "tls/s2n_tls.h" 22 : : #include "tls/s2n_tls_parameters.h" 23 : : #include "utils/s2n_safety.h" 24 : : 25 : : #define S2N_NAME_TYPE_HOST_NAME 0 26 : : 27 : : static bool s2n_client_server_name_should_send(struct s2n_connection *conn); 28 : : static int s2n_client_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out); 29 : : static int s2n_client_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension); 30 : : 31 : : const s2n_extension_type s2n_client_server_name_extension = { 32 : : .iana_value = TLS_EXTENSION_SERVER_NAME, 33 : : .is_response = false, 34 : : .send = s2n_client_server_name_send, 35 : : .recv = s2n_client_server_name_recv, 36 : : .should_send = s2n_client_server_name_should_send, 37 : : .if_missing = s2n_extension_noop_if_missing, 38 : : }; 39 : : 40 : : static bool s2n_client_server_name_should_send(struct s2n_connection *conn) 41 : 7355 : { 42 [ + - ][ + + ]: 7355 : return conn && conn->server_name[0] != '\0'; 43 : 7355 : } 44 : : 45 : : static int s2n_client_server_name_send(struct s2n_connection *conn, struct s2n_stuffer *out) 46 : 79 : { 47 : 79 : struct s2n_stuffer_reservation server_name_list_size = { 0 }; 48 [ - + ]: 79 : POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &server_name_list_size)); 49 : : 50 : : /* NameType, as described by RFC6066. 51 : : * host_name is currently the only possible NameType defined. */ 52 [ - + ]: 79 : POSIX_GUARD(s2n_stuffer_write_uint8(out, S2N_NAME_TYPE_HOST_NAME)); 53 : : 54 [ - + ]: 79 : POSIX_GUARD(s2n_stuffer_write_uint16(out, strlen(conn->server_name))); 55 [ - + ]: 79 : POSIX_GUARD(s2n_stuffer_write_bytes(out, (const uint8_t *) conn->server_name, strlen(conn->server_name))); 56 : : 57 [ - + ]: 79 : POSIX_GUARD(s2n_stuffer_write_vector_size(&server_name_list_size)); 58 : 79 : return S2N_SUCCESS; 59 : 79 : } 60 : : 61 : : /* Read the extension up to the first item in ServerNameList. Instantiates the server_name blob to 62 : : * point to the first entry. For now s2n ignores all subsequent items in ServerNameList. 63 : : */ 64 : : S2N_RESULT s2n_client_server_name_parse(struct s2n_stuffer *extension, struct s2n_blob *server_name) 65 : 113 : { 66 : 113 : uint16_t list_size = 0; 67 [ - + ]: 113 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(extension, &list_size)); 68 [ + + ][ + - ]: 113 : RESULT_ENSURE_LTE(list_size, s2n_stuffer_data_available(extension)); 69 : : 70 : 111 : uint8_t server_name_type = 0; 71 [ - + ]: 111 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(extension, &server_name_type)); 72 [ + - ][ + + ]: 111 : RESULT_ENSURE_EQ(server_name_type, S2N_NAME_TYPE_HOST_NAME); 73 : : 74 : 110 : uint16_t length = 0; 75 [ - + ]: 110 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(extension, &length)); 76 [ + + ][ + - ]: 110 : RESULT_ENSURE_LTE(length, s2n_stuffer_data_available(extension)); 77 : : 78 : 108 : uint8_t *data = s2n_stuffer_raw_read(extension, length); 79 [ # # ][ - + ]: 108 : RESULT_ENSURE_REF(data); 80 [ - + ]: 108 : RESULT_GUARD_POSIX(s2n_blob_init(server_name, data, length)); 81 : : 82 : 108 : return S2N_RESULT_OK; 83 : 108 : } 84 : : 85 : : static int s2n_client_server_name_recv(struct s2n_connection *conn, struct s2n_stuffer *extension) 86 : 114 : { 87 [ # # ][ - + ]: 114 : POSIX_ENSURE_REF(conn); 88 : : 89 : : /* Exit early if we've already parsed the server name */ 90 [ + + ]: 114 : if (conn->server_name[0]) { 91 : 4 : return S2N_SUCCESS; 92 : 4 : } 93 : : 94 : : /* Ignore if malformed or we don't have enough space to store it. We just won't use the server name. */ 95 : 110 : struct s2n_blob server_name = { 0 }; 96 [ + + ][ - + ]: 110 : if (!s2n_result_is_ok(s2n_client_server_name_parse(extension, &server_name)) || server_name.size > S2N_MAX_SERVER_NAME) { 97 : 5 : return S2N_SUCCESS; 98 : 5 : } 99 : : 100 [ - + ][ # # ]: 105 : POSIX_CHECKED_MEMCPY(conn->server_name, server_name.data, server_name.size); [ + - ] 101 : : 102 : 105 : return S2N_SUCCESS; 103 : 105 : }