From c8008cae74231ac83b08a2dc995415f2fea497fc Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Tue, 30 Oct 2012 18:51:50 +0100 Subject: [PATCH] Simplified certificate verification by adding gnutls_certificate_verify_peers3(). This function combines the RFC2818 hostname check and chain verification check. --- NEWS | 4 ++ doc/cha-cert-auth.texi | 16 ++---- doc/cha-cert-auth2.texi | 2 +- doc/cha-gtls-app.texi | 17 +++--- doc/examples/ex-client-x509.c | 41 +-------------- doc/examples/ex-verify-ssh.c | 41 ++------------- doc/examples/verify.c | 44 +--------------- lib/gnutls_cert.c | 64 +++++++++++++++++++++-- lib/gnutls_x509.c | 13 ++++- lib/gnutls_x509.h | 1 + lib/includes/gnutls/gnutls.h.in | 5 ++ lib/libgnutls.map | 1 + lib/openpgp/compat.c | 9 ++++ lib/openpgp/gnutls_openpgp.h | 1 + lib/openpgp/pgp.c | 2 +- lib/x509/rfc2818_hostname.c | 2 +- src/common.c | 111 +--------------------------------------- 17 files changed, 117 insertions(+), 257 deletions(-) diff --git a/NEWS b/NEWS index 1363fc965..eabc76aef 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,9 @@ the available revocation data validity. ** libgnutls: Added priority string %VERIFY_DISABLE_CRL_CHECKS. +** libgnutls: Simplified certificate verification by adding +gnutls_certificate_verify_peers3(). + ** gnutls-cli: Added --local-dns option. ** danetool: Corrected bug that prevented loading PEM files. @@ -18,6 +21,7 @@ the available revocation data validity. ** API and ABI modifications: gnutls_session_get_id2: Added gnutls_certificate_update_verify_flags: Added +gnutls_certificate_verify_peers3: Added GNUTLS_CERT_REVOCATION_DATA_TOO_OLD: Added. GNUTLS_CERT_REVOCATION_DATA_INVALID: Added. diff --git a/doc/cha-cert-auth.texi b/doc/cha-cert-auth.texi index eeb1f7334..3f66b61c2 100644 --- a/doc/cha-cert-auth.texi +++ b/doc/cha-cert-auth.texi @@ -281,26 +281,20 @@ authority list may also be set using: @showfuncC{gnutls_certificate_set_x509_trust_file,gnutls_certificate_set_x509_crl_file,gnutls_certificate_set_x509_system_trust} Then it is not required to setup a trusted list as above. -The function @funcref{gnutls_certificate_verify_peers2} -may then be used to verify the peer's certificate chain. The flags +The function @funcref{gnutls_certificate_verify_peers3} +may then be used to verify the peer's certificate chain and identity. The flags are set similarly to the verification functions in the previous section. There is also the possibility to pass some input to the verification functions in the form of flags. For @funcref{gnutls_x509_trust_list_verify_crt} the flags are passed straightforward, but -@funcref{gnutls_certificate_verify_peers2} depends on the flags set by +@funcref{gnutls_certificate_verify_peers3} depends on the flags set by calling @funcref{gnutls_certificate_set_verify_flags}. All the available flags are part of the enumeration @code{gnutls_@-certificate_@-verify_@-flags} shown in @ref{gnutls_certificate_verify_flags}. @showenumdesc{gnutls_certificate_verify_flags,The @code{gnutls_@-certificate_@-verify_@-flags} enumeration.} -Although the verification of a certificate path indicates that the -certificate is signed by trusted authority, does not reveal anything -about the peer's identity. It is required to verify if the -certificate's owner is the one you expect. For more information -consult @funcref{gnutls_x509_crt_check_hostname}, section @ref{ex:verify} for an example, and @xcite{RFC2818}. - @node OpenPGP certificates @section @acronym{OpenPGP} certificates @@ -433,7 +427,7 @@ of verification status flags is the same as in the @acronym{X.509} certificates Similarly with X.509 certificates, one needs to specify the OpenPGP keyring file in the credentials structure. The certificates -in this file will be used by @funcref{gnutls_certificate_verify_peers2} +in this file will be used by @funcref{gnutls_certificate_verify_peers3} to verify the signatures in the certificate sent by the peer. @showfuncdesc{gnutls_certificate_set_openpgp_keyring_file} @@ -578,7 +572,7 @@ certificates self-signed using @code{RSA-MD2} or @code{RSA-MD5}. The certificates in the trusted list are considered trusted irrespective of the signature. -If you are using @funcref{gnutls_certificate_verify_peers2} to verify the +If you are using @funcref{gnutls_certificate_verify_peers3} to verify the certificate chain, you can call @funcref{gnutls_certificate_update_verify_flags} or @funcref{gnutls_certificate_set_verify_flags} with the flags: diff --git a/doc/cha-cert-auth2.texi b/doc/cha-cert-auth2.texi index e34f0a4b3..da00a4014 100644 --- a/doc/cha-cert-auth2.texi +++ b/doc/cha-cert-auth2.texi @@ -155,7 +155,7 @@ in a CRL and/or perform an OCSP check for the certificate. Note that in the context of a TLS session the server may provide an OCSP response that will used during the TLS certificate verification -(see @funcref{gnutls_certificate_verify_peers2}). +(see @funcref{gnutls_certificate_verify_peers3}). You may obtain this response using @funcref{gnutls_ocsp_status_request_get}. Before performing the OCSP query, the application will need to figure diff --git a/doc/cha-gtls-app.texi b/doc/cha-gtls-app.texi index baa316af9..56f387046 100644 --- a/doc/cha-gtls-app.texi +++ b/doc/cha-gtls-app.texi @@ -494,25 +494,26 @@ Certificate verification is possible by loading the trusted authorities into the credentials structure by using the following functions, applicable to X.509 and OpenPGP certificates. -@showfuncB{gnutls_certificate_set_x509_trust_file,gnutls_certificate_set_openpgp_keyring_file} +@showfuncC{gnutls_certificate_set_x509_system_trust,gnutls_certificate_set_x509_trust_file,gnutls_certificate_set_openpgp_keyring_file} The peer's certificate is not automatically verified and one -should call @funcref{gnutls_certificate_verify_peers2} -after a successful handshake to verify the certificate's signature. -Alternative the verification can occur during the handshake +must call @funcref{gnutls_certificate_verify_peers3} +after a successful handshake to verify the certificate's signature and the owner +of the certificate. + +Alternatively the verification can occur during the handshake by using @funcref{gnutls_certificate_set_verify_function}. -In order to report a detailed verification output, an alternative -way has to be used. For that, one should call @funcref{gnutls_certificate_get_peers} +The functions above provide a brief verification output. If a +detailed output is required one should call @funcref{gnutls_certificate_get_peers} to obtain the raw certificate of the peer and verify it using the functions discussed in @ref{X.509 certificates}. -@showfuncdesc{gnutls_certificate_verify_peers2} +@showfuncdesc{gnutls_certificate_verify_peers3} @showfuncdesc{gnutls_certificate_set_verify_function} - @node SRP credentials @subsection SRP diff --git a/doc/examples/ex-client-x509.c b/doc/examples/ex-client-x509.c index 6939ba36a..3c90e952a 100644 --- a/doc/examples/ex-client-x509.c +++ b/doc/examples/ex-client-x509.c @@ -142,10 +142,7 @@ static int _verify_certificate_callback (gnutls_session_t session) { unsigned int status; - const gnutls_datum_t *cert_list; - unsigned int cert_list_size; int ret; - gnutls_x509_crt_t cert; const char *hostname; /* read hostname */ @@ -154,7 +151,7 @@ _verify_certificate_callback (gnutls_session_t session) /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ - ret = gnutls_certificate_verify_peers2 (session, &status); + ret = gnutls_certificate_verify_peers3 (session, hostname, &status); if (ret < 0) { printf ("Error\n"); @@ -179,42 +176,6 @@ _verify_certificate_callback (gnutls_session_t session) return GNUTLS_E_CERTIFICATE_ERROR; } - /* Up to here the process is the same for X.509 certificates and - * OpenPGP keys. From now on X.509 certificates are assumed. This can - * be easily extended to work with openpgp keys as well. - */ - if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) - return GNUTLS_E_CERTIFICATE_ERROR; - - if (gnutls_x509_crt_init (&cert) < 0) - { - printf ("error in initialization\n"); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - cert_list = gnutls_certificate_get_peers (session, &cert_list_size); - if (cert_list == NULL) - { - printf ("No certificate was found!\n"); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) - { - printf ("error parsing certificate\n"); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - - if (!gnutls_x509_crt_check_hostname (cert, hostname)) - { - printf ("The certificate's owner does not match hostname '%s'\n", - hostname); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - gnutls_x509_crt_deinit (cert); - /* notify gnutls to continue handshake normally */ return 0; } diff --git a/doc/examples/ex-verify-ssh.c b/doc/examples/ex-verify-ssh.c index a748516a0..28e09ac97 100644 --- a/doc/examples/ex-verify-ssh.c +++ b/doc/examples/ex-verify-ssh.c @@ -23,7 +23,6 @@ _ssh_verify_certificate_callback (gnutls_session_t session) const gnutls_datum_t *cert_list; unsigned int cert_list_size; int ret; - gnutls_x509_crt_t cert; const char *hostname; /* read hostname */ @@ -32,7 +31,7 @@ _ssh_verify_certificate_callback (gnutls_session_t session) /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ - ret = gnutls_certificate_verify_peers2 (session, &status); + ret = gnutls_certificate_verify_peers3 (session, hostname, &status); if (ret < 0) { printf ("Error\n"); @@ -54,19 +53,6 @@ _ssh_verify_certificate_callback (gnutls_session_t session) if (status & GNUTLS_CERT_NOT_ACTIVATED) printf ("The certificate is not yet activated\n"); - /* Up to here the process is the same for X.509 certificates and - * OpenPGP keys. From now on X.509 certificates are assumed. This can - * be easily extended to work with openpgp keys as well. - */ - if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) - return GNUTLS_E_CERTIFICATE_ERROR; - - if (gnutls_x509_crt_init (&cert) < 0) - { - printf ("error in initialization\n"); - return GNUTLS_E_CERTIFICATE_ERROR; - } - cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list == NULL) { @@ -74,27 +60,10 @@ _ssh_verify_certificate_callback (gnutls_session_t session) return GNUTLS_E_CERTIFICATE_ERROR; } - /* This is not a real world example, since we only check the first - * certificate in the given chain. - */ - if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) - { - printf ("error parsing certificate\n"); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - if (!gnutls_x509_crt_check_hostname (cert, hostname)) - { - printf ("The certificate's owner does not match hostname '%s'\n", - hostname); - status |= GNUTLS_CERT_INVALID; - } - - gnutls_x509_crt_deinit (cert); - /* service may be obtained alternatively using getservbyport() */ ret = gnutls_verify_stored_pubkey(NULL, NULL, hostname, "https", - GNUTLS_CRT_X509, &cert_list[0], 0); + gnutls_certificate_type_get (session), + &cert_list[0], 0); if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND) { printf("Host %s is not known.", hostname); @@ -130,8 +99,8 @@ _ssh_verify_certificate_callback (gnutls_session_t session) if (ret != 0) { ret = gnutls_store_pubkey(NULL, NULL, hostname, "https", - GNUTLS_CRT_X509, &cert_list[0], - 0, 0); + gnutls_certificate_type_get (session), + &cert_list[0], 0, 0); if (ret < 0) printf("gnutls_store_pubkey: %s\n", gnutls_strerror(ret)); } diff --git a/doc/examples/verify.c b/doc/examples/verify.c index d02440a5c..10aed207b 100644 --- a/doc/examples/verify.c +++ b/doc/examples/verify.c @@ -13,10 +13,7 @@ int verify_certificate_callback (gnutls_session_t session) { unsigned int status; - const gnutls_datum_t *cert_list; - unsigned int cert_list_size; int ret; - gnutls_x509_crt_t cert; const char *hostname; /* read hostname */ @@ -25,7 +22,7 @@ int verify_certificate_callback (gnutls_session_t session) /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ - ret = gnutls_certificate_verify_peers2 (session, &status); + ret = gnutls_certificate_verify_peers3 (session, hostname, &status); if (ret < 0) { printf ("Error\n"); @@ -47,45 +44,6 @@ int verify_certificate_callback (gnutls_session_t session) if (status & GNUTLS_CERT_NOT_ACTIVATED) printf ("The certificate is not yet activated\n"); - /* Up to here the process is the same for X.509 certificates and - * OpenPGP keys. From now on X.509 certificates are assumed. This can - * be easily extended to work with openpgp keys as well. - */ - if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) - return GNUTLS_E_CERTIFICATE_ERROR; - - if (gnutls_x509_crt_init (&cert) < 0) - { - printf ("error in initialization\n"); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - cert_list = gnutls_certificate_get_peers (session, &cert_list_size); - if (cert_list == NULL) - { - printf ("No certificate was found!\n"); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - /* This is not a real world example, since we only check the first - * certificate in the given chain. - */ - if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) - { - printf ("error parsing certificate\n"); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - - if (!gnutls_x509_crt_check_hostname (cert, hostname)) - { - printf ("The certificate's owner does not match hostname '%s'\n", - hostname); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - gnutls_x509_crt_deinit (cert); - /* notify gnutls to continue handshake normally */ return 0; } diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index d8d437a8d..ef1a3dcc0 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -581,6 +581,7 @@ _gnutls_x509_get_raw_crt_expiration_time (const gnutls_datum_t * cert) -*/ static int _gnutls_openpgp_crt_verify_peers (gnutls_session_t session, + const char* hostname, unsigned int *status) { cert_auth_info_t info; @@ -621,7 +622,7 @@ _gnutls_openpgp_crt_verify_peers (gnutls_session_t session, /* Verify certificate */ ret = - _gnutls_openpgp_verify_key (cred, &info->raw_certificate_list[0], + _gnutls_openpgp_verify_key (cred, hostname, &info->raw_certificate_list[0], peer_certificate_list_size, status); if (ret < 0) @@ -629,7 +630,7 @@ _gnutls_openpgp_crt_verify_peers (gnutls_session_t session, gnutls_assert (); return ret; } - + return 0; } #endif @@ -677,10 +678,65 @@ gnutls_certificate_verify_peers2 (gnutls_session_t session, switch (gnutls_certificate_type_get (session)) { case GNUTLS_CRT_X509: - return _gnutls_x509_cert_verify_peers (session, status); + return _gnutls_x509_cert_verify_peers (session, NULL, status); +#ifdef ENABLE_OPENPGP + case GNUTLS_CRT_OPENPGP: + return _gnutls_openpgp_crt_verify_peers (session, NULL, status); +#endif + default: + return GNUTLS_E_INVALID_REQUEST; + } +} + +/** + * gnutls_certificate_verify_peers3: + * @session: is a gnutls session + * @hostname: is the expected name of the peer + * @status: is the output of the verification + * + * This function will verify the peer's certificate and its name and + * return its status (trusted, invalid etc.). The value of @status will + * be one or more of the gnutls_certificate_status_t flags + * bitwise or'd. Note that verification failure does not imply a + * negative return value. Only the @status is updated. + * + * In case the @hostname does not match the %GNUTLS_CERT_UNEXPECTED_OWNER + * status flag will be set. + * + * If available the OCSP Certificate Status extension will be + * utilized by this function. + * + * To avoid denial of service attacks some + * default upper limits regarding the certificate key size and chain + * size are set. To override them use gnutls_certificate_set_verify_limits(). + * + * Returns: a negative error code on error and %GNUTLS_E_SUCCESS (0) on success. + **/ +int +gnutls_certificate_verify_peers3 (gnutls_session_t session, + const char* hostname, + unsigned int *status) +{ + cert_auth_info_t info; + + CHECK_AUTH (GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST); + + info = _gnutls_get_auth_info (session); + if (info == NULL) + { + return GNUTLS_E_NO_CERTIFICATE_FOUND; + } + + if (info->raw_certificate_list == NULL || info->ncerts == 0) + return GNUTLS_E_NO_CERTIFICATE_FOUND; + + switch (gnutls_certificate_type_get (session)) + { + case GNUTLS_CRT_X509: + return _gnutls_x509_cert_verify_peers (session, hostname, status); #ifdef ENABLE_OPENPGP case GNUTLS_CRT_OPENPGP: - return _gnutls_openpgp_crt_verify_peers (session, status); + return _gnutls_openpgp_crt_verify_peers (session, hostname, status); #endif default: return GNUTLS_E_INVALID_REQUEST; diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index 19e6c7357..cf8dee55f 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -191,6 +191,7 @@ cleanup: -*/ int _gnutls_x509_cert_verify_peers (gnutls_session_t session, + const char* hostname, unsigned int *status) { cert_auth_info_t info; @@ -306,14 +307,22 @@ skip_ocsp: peer_certificate_list_size, verify_flags, status, NULL); - CLEAR_CERTS; - if (ret < 0) { gnutls_assert (); + CLEAR_CERTS; return ret; } + if (hostname) + { + ret = gnutls_x509_crt_check_hostname( peer_certificate_list[0], hostname); + if (ret == 0) + *status |= GNUTLS_CERT_UNEXPECTED_OWNER; + } + + CLEAR_CERTS; + *status |= ocsp_status; return 0; diff --git a/lib/gnutls_x509.h b/lib/gnutls_x509.h index 55340dc3c..a082cfcfc 100644 --- a/lib/gnutls_x509.h +++ b/lib/gnutls_x509.h @@ -24,6 +24,7 @@ #include int _gnutls_x509_cert_verify_peers (gnutls_session_t session, + const char* hostname, unsigned int *status); #define PEM_CERT_SEP2 "-----BEGIN X509 CERTIFICATE" diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 1b8c1d8f7..8a4847996 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -446,6 +446,7 @@ extern "C" * @GNUTLS_CERT_EXPIRED: The certificate has expired. * @GNUTLS_CERT_REVOCATION_DATA_TOO_OLD: The OCSP revocation data are too old. * @GNUTLS_CERT_REVOCATION_DATA_INVALID: The OCSP revocation data are invalid. + * @GNUTLS_CERT_UNEXPECTED_OWNER: The owner is not the expected one. * * Enumeration of certificate status codes. Note that the status * bits may have different meanings in OpenPGP keys and X.509 @@ -463,6 +464,7 @@ extern "C" GNUTLS_CERT_SIGNATURE_FAILURE = 2048, GNUTLS_CERT_REVOCATION_DATA_TOO_OLD = 4096, GNUTLS_CERT_REVOCATION_DATA_INVALID = 8192, + GNUTLS_CERT_UNEXPECTED_OWNER = 16384, } gnutls_certificate_status_t; /** @@ -1699,6 +1701,9 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session); int gnutls_certificate_client_get_request_status (gnutls_session_t session); int gnutls_certificate_verify_peers2 (gnutls_session_t session, unsigned int *status); + int gnutls_certificate_verify_peers3 (gnutls_session_t session, + const char* hostname, + unsigned int *status); int gnutls_pem_base64_encode (const char *msg, const gnutls_datum_t * data, char *result, size_t * result_size); diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 3cee073e5..278524b98 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -859,6 +859,7 @@ GNUTLS_3_1_0 { gnutls_certificate_get_peers_subkey_id; gnutls_session_get_id2; gnutls_certificate_update_verify_flags; + gnutls_certificate_verify_peers3; } GNUTLS_3_0_0; GNUTLS_PRIVATE { diff --git a/lib/openpgp/compat.c b/lib/openpgp/compat.c index 7612d3f4c..ebcb3afb8 100644 --- a/lib/openpgp/compat.c +++ b/lib/openpgp/compat.c @@ -30,6 +30,7 @@ /*- * gnutls_openpgp_verify_key: + * @hostname: the name of the certificate holder * @cert_list: the structure that holds the certificates. * @cert_list_lenght: the items in the cert_list. * @status: the output of the verification function @@ -44,6 +45,7 @@ -*/ int _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred, + const char* hostname, const gnutls_datum_t * cert_list, int cert_list_length, unsigned int *status) { @@ -95,6 +97,13 @@ _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t cred, /* If we only checked the self signature. */ if (!cred->keyring) *status |= GNUTLS_CERT_SIGNER_NOT_FOUND; + + if (hostname) + { + ret = gnutls_openpgp_crt_check_hostname(key, hostname); + if (ret == 0) + *status |= GNUTLS_CERT_UNEXPECTED_OWNER; + } ret = 0; diff --git a/lib/openpgp/gnutls_openpgp.h b/lib/openpgp/gnutls_openpgp.h index 8af869b9a..4949624fa 100644 --- a/lib/openpgp/gnutls_openpgp.h +++ b/lib/openpgp/gnutls_openpgp.h @@ -57,6 +57,7 @@ _gnutls_openpgp_request_key (gnutls_session_t, uint8_t * key_fpr, int key_fpr_size); int _gnutls_openpgp_verify_key (const gnutls_certificate_credentials_t, + const char* hostname, const gnutls_datum_t * cert_list, int cert_list_length, unsigned int *status); int _gnutls_openpgp_fingerprint (const gnutls_datum_t * cert, diff --git a/lib/openpgp/pgp.c b/lib/openpgp/pgp.c index 9dc9cc763..e100155f3 100644 --- a/lib/openpgp/pgp.c +++ b/lib/openpgp/pgp.c @@ -603,7 +603,7 @@ gnutls_openpgp_crt_get_revoked_status (gnutls_openpgp_crt_t key) * given hostname. This is a basic implementation of the matching * described in RFC2818 (HTTPS), which takes into account wildcards. * - * Returns: %GNUTLS_E_SUCCESS on success, or an error code. + * Returns: non-zero for a successful match, and zero on failure. **/ int gnutls_openpgp_crt_check_hostname (gnutls_openpgp_crt_t key, diff --git a/lib/x509/rfc2818_hostname.c b/lib/x509/rfc2818_hostname.c index 7d099f3e5..c53476f57 100644 --- a/lib/x509/rfc2818_hostname.c +++ b/lib/x509/rfc2818_hostname.c @@ -35,7 +35,7 @@ * described in RFC2818 (HTTPS), which takes into account wildcards, * and the DNSName/IPAddress subject alternative name PKIX extension. * - * Returns: non (0) for a successful match, and (0) on failure. + * Returns: non-zero for a successful match, and zero on failure. **/ int gnutls_x509_crt_check_hostname (gnutls_x509_crt_t cert, const char *hostname) diff --git a/src/common.c b/src/common.c index 9ef83b6f8..4f3c9d895 100644 --- a/src/common.c +++ b/src/common.c @@ -192,110 +192,7 @@ print_x509_info (gnutls_session_t session, int flag, int print_cert) } } -/* returns true or false, depending on whether the hostname - * matches to certificate */ -static int -verify_x509_hostname (gnutls_session_t session, const char *hostname) -{ - gnutls_x509_crt_t crt; - const gnutls_datum_t *cert_list; - unsigned int cert_list_size = 0; - int ret; - - cert_list = gnutls_certificate_get_peers (session, &cert_list_size); - if (cert_list_size == 0) - { - fprintf (stderr, "No certificates found!\n"); - return 0; - } - - gnutls_x509_crt_init (&crt); - ret = - gnutls_x509_crt_import (crt, &cert_list[0], - GNUTLS_X509_FMT_DER); - if (ret < 0) - { - fprintf (stderr, "Decoding error: %s\n", - gnutls_strerror (ret)); - return 0; - } - - /* Check the hostname of the first certificate if it matches - * the name of the host we connected to. - */ - if (hostname != NULL) - { - if (gnutls_x509_crt_check_hostname (crt, hostname) == 0) - { - printf - ("- The hostname in the certificate does NOT match '%s'\n", - hostname); - ret = 0; - } - else - { - printf ("- The hostname in the certificate matches '%s'.\n", - hostname); - ret = 1; - } - } - - gnutls_x509_crt_deinit (crt); - - return ret; -} - #ifdef ENABLE_OPENPGP -/* returns true or false, depending on whether the hostname - * matches to certificate */ -static int -verify_openpgp_hostname (gnutls_session_t session, const char *hostname) -{ - gnutls_openpgp_crt_t crt; - const gnutls_datum_t *cert_list; - unsigned int cert_list_size = 0; - int ret; - - cert_list = gnutls_certificate_get_peers (session, &cert_list_size); - if (cert_list_size == 0) - { - fprintf (stderr, "No certificates found!\n"); - return 0; - } - - gnutls_openpgp_crt_init (&crt); - ret = - gnutls_openpgp_crt_import (crt, &cert_list[0], - GNUTLS_OPENPGP_FMT_RAW); - if (ret < 0) - { - fprintf (stderr, "Decoding error: %s\n", - gnutls_strerror (ret)); - return 0; - } - - /* Check the hostname of the first certificate if it matches - * the name of the host we connected to. - */ - if (gnutls_openpgp_crt_check_hostname (crt, hostname) == 0) - { - printf - ("- The hostname in the certificate does NOT match '%s'\n", - hostname); - ret = 0; - } - else - { - printf ("- The hostname in the certificate matches '%s'.\n", - hostname); - ret = 1; - } - - gnutls_openpgp_crt_deinit (crt); - - return ret; -} - static void print_openpgp_info_compact (gnutls_session_t session) { @@ -419,7 +316,7 @@ cert_verify (gnutls_session_t session, const char* hostname) unsigned int status = 0; int type; - rc = gnutls_certificate_verify_peers2 (session, &status); + rc = gnutls_certificate_verify_peers3 (session, hostname, &status); if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND) { printf ("- Peer did not send any certificate.\n"); @@ -460,9 +357,6 @@ cert_verify (gnutls_session_t session, const char* hostname) printf ("- Peer's certificate is NOT trusted\n"); else printf ("- Peer's certificate is trusted\n"); - - rc = verify_x509_hostname (session, hostname); - if (rc == 0) status |= GNUTLS_CERT_INVALID; } else if (type == GNUTLS_CRT_OPENPGP) { @@ -472,9 +366,6 @@ cert_verify (gnutls_session_t session, const char* hostname) printf ("- Peer's key is valid\n"); if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) printf ("- Could not find a signer of the peer's key\n"); - - rc = verify_openpgp_hostname (session, hostname); - if (rc == 0) status |= GNUTLS_CERT_INVALID; } else { -- 2.11.4.GIT