Line data Source code
1 : /* 2 : * Copyright (C) 2015 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 : #include "gnutls_int.h" 24 : #include "errors.h" 25 : #include <auth/cert.h> 26 : #include <gnutls/gnutls.h> 27 : 28 : /* This file implements the client certificate auto verification functionality. 29 : */ 30 : 31 : /* The actual verification callback. */ 32 6 : static int auto_verify_cb(gnutls_session_t session) 33 : { 34 6 : unsigned int status; 35 6 : int ret; 36 : 37 6 : if (session->internals.vc_elements == 0) { 38 0 : ret = gnutls_certificate_verify_peers2(session, &status); 39 : } else { 40 6 : ret = gnutls_certificate_verify_peers(session, session->internals.vc_data, 41 : session->internals.vc_elements, &status); 42 : } 43 6 : if (ret < 0) { 44 0 : return gnutls_assert_val(GNUTLS_E_CERTIFICATE_ERROR); 45 : } 46 : 47 6 : session->internals.vc_status = status; 48 : 49 6 : if (status != 0) /* Certificate is not trusted */ 50 2 : return gnutls_assert_val(GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR); 51 : 52 : /* notify gnutls to continue handshake normally */ 53 : return 0; 54 : } 55 : 56 : /** 57 : * gnutls_session_set_verify_cert: 58 : * @session: is a gnutls session 59 : * @hostname: is the expected name of the peer; may be %NULL 60 : * @flags: flags for certificate verification -- #gnutls_certificate_verify_flags 61 : * 62 : * This function instructs GnuTLS to verify the peer's certificate 63 : * using the provided hostname. If the verification fails the handshake 64 : * will also fail with %GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR. In that 65 : * case the verification result can be obtained using gnutls_session_get_verify_cert_status(). 66 : * 67 : * The @hostname pointer provided must remain valid for the lifetime 68 : * of the session. More precisely it should be available during any subsequent 69 : * handshakes. If no hostname is provided, no hostname verification 70 : * will be performed. For a more advanced verification function check 71 : * gnutls_session_set_verify_cert2(). 72 : * 73 : * If @flags is provided which contain a profile, this function should be 74 : * called after any session priority setting functions. 75 : * 76 : * The gnutls_session_set_verify_cert() function is intended to be used by TLS 77 : * clients to verify the server's certificate. 78 : * 79 : * Since: 3.4.6 80 : **/ 81 2 : void gnutls_session_set_verify_cert(gnutls_session_t session, 82 : const char *hostname, unsigned flags) 83 : { 84 2 : if (hostname) { 85 2 : session->internals.vc_sdata.type = GNUTLS_DT_DNS_HOSTNAME; 86 2 : session->internals.vc_sdata.data = (void*)hostname; 87 2 : session->internals.vc_sdata.size = 0; 88 2 : session->internals.vc_elements = 1; 89 2 : session->internals.vc_data = &session->internals.vc_sdata; 90 : } else { 91 0 : session->internals.vc_elements = 0; 92 : } 93 : 94 2 : if (flags) { 95 0 : ADD_PROFILE_VFLAGS(session, flags); 96 : } 97 : 98 2 : gnutls_session_set_verify_function(session, auto_verify_cb); 99 2 : } 100 : 101 : /** 102 : * gnutls_session_set_verify_cert2: 103 : * @session: is a gnutls session 104 : * @data: an array of typed data 105 : * @elements: the number of data elements 106 : * @flags: flags for certificate verification -- #gnutls_certificate_verify_flags 107 : * 108 : * This function instructs GnuTLS to verify the peer's certificate 109 : * using the provided typed data information. If the verification fails the handshake 110 : * will also fail with %GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR. In that 111 : * case the verification result can be obtained using gnutls_session_get_verify_cert_status(). 112 : * 113 : * The acceptable typed data are the same as in gnutls_certificate_verify_peers(), 114 : * and once set must remain valid for the lifetime of the session. More precisely 115 : * they should be available during any subsequent handshakes. 116 : * 117 : * If @flags is provided which contain a profile, this function should be 118 : * called after any session priority setting functions. 119 : * 120 : * Since: 3.4.6 121 : **/ 122 4 : void gnutls_session_set_verify_cert2(gnutls_session_t session, 123 : gnutls_typed_vdata_st * data, 124 : unsigned elements, 125 : unsigned flags) 126 : { 127 4 : session->internals.vc_data = data; 128 4 : session->internals.vc_elements = elements; 129 : 130 4 : if (flags) 131 0 : session->internals.additional_verify_flags |= flags; 132 : 133 4 : gnutls_session_set_verify_function(session, auto_verify_cb); 134 4 : } 135 : 136 : /** 137 : * gnutls_session_get_verify_cert_status: 138 : * @session: is a gnutls session 139 : * 140 : * This function returns the status of the verification when initiated 141 : * via auto-verification, i.e., by gnutls_session_set_verify_cert2() or 142 : * gnutls_session_set_verify_cert(). If no certificate verification 143 : * was occurred then the return value would be set to ((unsigned int)-1). 144 : * 145 : * The certificate verification status is the same as in gnutls_certificate_verify_peers(). 146 : * 147 : * Returns: the certificate verification status. 148 : * 149 : * Since: 3.4.6 150 : **/ 151 6 : unsigned int gnutls_session_get_verify_cert_status(gnutls_session_t session) 152 : { 153 6 : return session->internals.vc_status; 154 : }