Line data Source code
1 : /* 2 : * Copyright (C) 2015-2016 Red Hat, Inc. 3 : * 4 : * Author: Nikos Mavrogiannopoulos 5 : * 6 : * This file is part of GnuTLS. 7 : * 8 : * The GnuTLS is free software; you can redistribute it and/or 9 : * modify it under the terms of the GNU Lesser General Public License 10 : * as published by the Free Software Foundation; either version 2.1 of 11 : * the License, or (at your option) any later version. 12 : * 13 : * This library is distributed in the hope that it will be useful, but 14 : * WITHOUT ANY WARRANTY; without even the implied warranty of 15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 : * Lesser General Public License for more details. 17 : * 18 : * You should have received a copy of the GNU Lesser General Public License 19 : * along with this program. If not, see <https://www.gnu.org/licenses/> 20 : * 21 : */ 22 : 23 : /* Functions that relate to the TLS handshake procedure. 24 : */ 25 : 26 : #include "gnutls_int.h" 27 : #include "errors.h" 28 : #include "debug.h" 29 : #include "handshake.h" 30 : #include <auth/cert.h> 31 : #include "constate.h" 32 : #include <record.h> 33 : #include <state.h> 34 : #include <ext/safe_renegotiation.h> 35 : #include <auth/anon.h> /* for gnutls_anon_server_credentials_t */ 36 : #include <auth/psk.h> /* for gnutls_psk_server_credentials_t */ 37 : #ifdef ENABLE_SRP 38 : # include <auth/srp_kx.h> 39 : #endif 40 : 41 7427 : int _gnutls_check_id_for_change(gnutls_session_t session) 42 : { 43 7427 : int cred_type; 44 : 45 : /* This checks in PSK and SRP ciphersuites that the username remained the 46 : * same on a rehandshake. */ 47 7427 : if (session->internals.flags & GNUTLS_ALLOW_ID_CHANGE) 48 : return 0; 49 : 50 7415 : cred_type = gnutls_auth_get_type(session); 51 7415 : if (cred_type == GNUTLS_CRD_PSK || cred_type == GNUTLS_CRD_SRP) { 52 1685 : const char *username = NULL; 53 1685 : int username_length; 54 : 55 1685 : if (cred_type == GNUTLS_CRD_PSK) { 56 1660 : psk_auth_info_t ai; 57 : 58 1660 : ai = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); 59 1660 : if (ai == NULL) 60 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); 61 : 62 1660 : username = ai->username; 63 1660 : username_length = ai->username_len; 64 : #ifdef ENABLE_SRP 65 : } else { 66 25 : srp_server_auth_info_t ai = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP); 67 25 : if (ai == NULL) 68 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); 69 : 70 25 : username = ai->username; 71 25 : username_length = strlen(ai->username); 72 : #endif 73 : } 74 : 75 1685 : if (username == NULL) 76 0 : return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); 77 : 78 1685 : if (session->internals.saved_username_size != -1) { 79 5 : if (session->internals.saved_username_size == username_length && 80 5 : strncmp(session->internals.saved_username, username, username_length) != 0) { 81 5 : _gnutls_debug_log("Session's PSK username changed during rehandshake; aborting!\n"); 82 5 : return gnutls_assert_val(GNUTLS_E_SESSION_USER_ID_CHANGED); 83 : } 84 : } else { 85 1680 : memcpy(session->internals.saved_username, username, username_length); 86 1680 : session->internals.saved_username[username_length] = 0; 87 1680 : session->internals.saved_username_size = username_length; 88 : } 89 : } 90 : 91 : return 0; 92 : } 93 : 94 10281 : int _gnutls_check_if_cert_hash_is_same(gnutls_session_t session, gnutls_certificate_credentials_t cred) 95 : { 96 10281 : cert_auth_info_t ai; 97 10281 : char tmp[32]; 98 10281 : int ret; 99 : 100 10281 : if (session->internals.flags & GNUTLS_ALLOW_ID_CHANGE) 101 : return 0; 102 : 103 10277 : ai = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); 104 5390 : if (ai == NULL || ai->ncerts == 0) 105 : return 0; 106 : 107 4994 : ret = gnutls_hash_fast(GNUTLS_DIG_SHA256, 108 2497 : ai->raw_certificate_list[0].data, 109 2497 : ai->raw_certificate_list[0].size, 110 : tmp); 111 2497 : if (ret < 0) 112 0 : return gnutls_assert_val(ret); 113 : 114 2497 : if (session->internals.cert_hash_set) { 115 94 : if (memcmp(tmp, session->internals.cert_hash, 32) != 0) { 116 2 : _gnutls_debug_log("Session certificate changed during rehandshake; aborting!\n"); 117 2 : return gnutls_assert_val(GNUTLS_E_SESSION_USER_ID_CHANGED); 118 : } 119 : } else { 120 2403 : memcpy(session->internals.cert_hash, tmp, 32); 121 2403 : session->internals.cert_hash_set = 1; 122 : } 123 : 124 : return 0; 125 : }