[SCM] GNU gnutls branch, master, updated. gnutls_3_1_3-30-gacca614
"Nikos Mavrogiannopoulos" <[email protected]> Tue, 30 Oct 2012 18:46:23 +0000
| Newsgroups | gmane.comp.encryption.gpg.gnutls.cvs |
|---|---|
| Message-ID | <[email protected]> |
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".
http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=acca614b0f77ec74d403c1de67d69befa4242b5b
The branch, master has been updated
via acca614b0f77ec74d403c1de67d69befa4242b5b (commit)
via 4ecbf335793e040c74e1e45dd51269c544bb7605 (commit)
via c8008cae74231ac83b08a2dc995415f2fea497fc (commit)
via 1566caaa8063a5b4cd544c97a60cbfedcf6c7a5c (commit)
via c1e846124968412b168d43613fdd81a037c762e6 (commit)
via 3632cb3eaf778507070b8613684586e4e00af68b (commit)
from 0d19c895785ebbd68e607b92dbc80d70ca06632c (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit acca614b0f77ec74d403c1de67d69befa4242b5b
Author: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue Oct 30 19:35:53 2012 +0100
Documented gnutls_certificate_verification_status_print().
commit 4ecbf335793e040c74e1e45dd51269c544bb7605
Author: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue Oct 30 19:18:24 2012 +0100
Added gnutls_certificate_verification_status_print().
This function simplifies printing the certificate verification status.
commit c8008cae74231ac83b08a2dc995415f2fea497fc
Author: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue Oct 30 18:51:50 2012 +0100
Simplified certificate verification by adding gnutls_certificate_verify_peers3().
This function combines the RFC2818 hostname check and chain verification check.
commit 1566caaa8063a5b4cd544c97a60cbfedcf6c7a5c
Author: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue Oct 30 18:16:40 2012 +0100
fix compilation when DANE is disabled.
commit c1e846124968412b168d43613fdd81a037c762e6
Author: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue Oct 30 18:15:18 2012 +0100
updated documentation.
commit 3632cb3eaf778507070b8613684586e4e00af68b
Author: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue Oct 30 15:49:44 2012 +0100
Added gnutls_certificate_update_verify_flags() to allow setting new flags without overriding any defaults.
-----------------------------------------------------------------------
Summary of changes:
NEWS | 12 ++-
doc/Makefile.am | 1 +
doc/cha-cert-auth.texi | 86 +++++-----------------
doc/cha-cert-auth2.texi | 2 +-
doc/cha-gtls-app.texi | 98 +++++++++++++++++++++---
doc/examples/ex-client-x509.c | 65 +++-------------
doc/examples/ex-verify-ssh.c | 63 ++++------------
doc/examples/verify.c | 65 +++-------------
lib/gnutls_cert.c | 149 +++++++++++++++++++++++++++++++++++-
lib/gnutls_ui.c | 25 +++++-
lib/gnutls_x509.c | 13 +++-
lib/gnutls_x509.h | 1 +
lib/includes/gnutls/gnutls.h.in | 11 +++
lib/libgnutls.map | 3 +
lib/openpgp/compat.c | 9 ++
lib/openpgp/gnutls_openpgp.h | 1 +
lib/openpgp/pgp.c | 2 +-
lib/x509/output.c | 6 +-
lib/x509/rfc2818_hostname.c | 2 +-
src/cli.c | 2 +
src/common.c | 160 +++------------------------------------
21 files changed, 373 insertions(+), 403 deletions(-)
diff --git a/NEWS b/NEWS
index b7301b3..20eb366 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.
@@ -17,9 +20,12 @@ the available revocation data validity.
** API and ABI modifications:
gnutls_session_get_id2: Added
-GNUTLS_CERT_REVOCATION_DATA_TOO_OLD: Added.
-GNUTLS_CERT_REVOCATION_DATA_INVALID: Added.
-
+gnutls_certificate_update_verify_flags: Added
+gnutls_certificate_verify_peers3: Added
+gnutls_certificate_verification_status_print: Added
+GNUTLS_CERT_REVOCATION_DATA_TOO_OLD: Added
+GNUTLS_CERT_REVOCATION_DATA_INVALID: Added
+GNUTLS_CERT_UNEXPECTED_OWNER: Added
* Version 3.1.3 (released 2012-10-12)
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 7f4a8a6..13e4454 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -396,6 +396,7 @@ DISTCLEANFILES += $(ENUMS) stamp_enums stamp_functions
stamp_functions: gnutls-api.texi x509-api.texi pgp-api.texi pkcs12-api.texi tpm-api.texi pkcs11-api.texi abstract-api.texi compat-api.texi dtls-api.texi crypto-api.texi ocsp-api.texi tpm-api.texi dane-api.texi
-mkdir functions
+ -rm -f functions/*.short
for i in $^; do \
$(srcdir)/scripts/split-texi.pl functions < $$i; \
done
diff --git a/doc/cha-cert-auth.texi b/doc/cha-cert-auth.texi
index cb395cb..3f66b61 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}
@@ -442,6 +436,13 @@ to verify the signatures in the certificate sent by the peer.
@section Advanced certificate verification
@cindex Certificate verification
+The verification of X.509 certificates in the HTTPS and other Internet protocols is typically
+done by loading a trusted list of commercial Certificate Authorities
+(see @funcref{gnutls_certificate_set_x509_system_trust}), and using them as trusted anchors.
+However, there are several examples (eg. the Diginotar incident) where one of these
+authorities was compromised. This risk can be mitigated by using in addition to CA certificate verification,
+other verification methods. In this section we list the available in GnuTLS methods.
+
@menu
* Verifying a certificate using trust on first use authentication::
* Verifying a certificate using DANE (DNSSEC)::
@@ -453,7 +454,6 @@ to verify the signatures in the certificate sent by the peer.
@cindex SSH-style authentication
@cindex Trust on first use
@cindex Key pinning
-@tindex gnutls_certificate_verify_flags
It is possible to use a trust on first use (TOFU) authentication
method in GnuTLS. That is the concept used by the SSH programs, where the
@@ -468,76 +468,25 @@ the trust on first use method.
Such a hybrid system with X.509 and trust on first use authentication is
shown in @ref{Simple client example with SSH-style certificate verification}.
-@showfuncdesc{gnutls_verify_stored_pubkey}
-@showfuncdesc{gnutls_store_pubkey}
-
-In addition to the above the @funcref{gnutls_store_commitment} can be
-used to implement a key-pinning architecture as in @xcite{KEYPIN}.
-This provides a way for web server to commit on a public key that is
-not yet active.
-
-@showfuncdesc{gnutls_store_commitment}
-
-The storage and verification functions may be used with the default
-text file based back-end, or another back-end may be specified. That
-should contain storage and retrieval functions and specified as below.
-
-@showfuncE{gnutls_tdb_init,gnutls_tdb_deinit,gnutls_tdb_set_verify_func,gnutls_tdb_set_store_func,gnutls_tdb_set_store_commitment_func}
+See @ref{Certificate verification} on how to use the available functionality.
@node Verifying a certificate using DANE (DNSSEC)
@subsection Verifying a certificate using DANE (DNSSEC)
@cindex verifying certificate paths
@cindex DANE
@cindex DNSSEC
-@tindex gnutls_certificate_verify_flags
The DANE protocol is a protocol that can be used to verify TLS certificates
using the DNS (or better DNSSEC) protocols. The DNS security extensions (DNSSEC)
provide an alternative public key infrastructure to the commercial CAs that
are typically used to sign TLS certificates. The DANE protocol takes advantage
of the DNSSEC infrastructure to verify TLS certificates. This can be
-in addition to the verification by commercial CA infrastructure or
+in addition to the verification by CA infrastructure or
could even replace it where DNSSEC is deployed.
The DANE functionality is provided by the @code{libgnutls-dane} library that is shipped
with GnuTLS and the function prototypes are in @code{gnutls/dane.h}.
-
-@subsubheading Using the DANE library
-Since the DANE library is not included in GnuTLS it requires programs
-to be linked against it. This can be achieved with the following commands.
-
-@example
-gcc -o foo foo.c `pkg-config gnutls-dane --cflags --libs`
-@end example
-
-When a program uses the GNU autoconf system, then the following
-line or similar can be used to detect the presence of the library.
-
-@example
-PKG_CHECK_MODULES([LIBDANE], [gnutls-dane >= 3.0.0])
-
-AC_SUBST([LIBDANE_CFLAGS])
-AC_SUBST([LIBDANE_LIBS])
-@end example
-
-@subsubheading DANE library functionality
-
-The library provides high level verification functions which are shown below.
-
-@showfuncdesc{dane_verify_crt}
-
-@showfuncB{dane_verify_session_crt,dane_strerror}
-
-Note that the @code{dane_state_t} structure that is accepted by both
-verification functions is optional. It is required when many queries
-are performed to facilitate caching.
-The following flags are returned by the verify functions to
-indicate the status of the verification.
-
-@showenumdesc{dane_verify_status_t,The DANE verification status flags.}
-
-In order to generate a DANE TLSA entry to use in a DNS server
-you may use danetool (see @ref{danetool Invocation}).
+See @ref{Certificate verification} for information on how to use the library.
@node Digital signatures
@section Digital signatures
@@ -623,8 +572,9 @@ 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:
@itemize
@item @code{GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2}
@@ -633,11 +583,11 @@ certificate chain, you can call
as in the following example:
@example
- gnutls_certificate_set_verify_flags (x509cred,
+ gnutls_certificate_update_verify_flags (x509cred,
GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
@end example
-This will tell the verifier algorithm to enable @code{RSA-MD5} when
+This will signal the verifier algorithm to enable @code{RSA-MD5} when
verifying the certificates.
If you are using @funcref{gnutls_x509_crt_verify} or
diff --git a/doc/cha-cert-auth2.texi b/doc/cha-cert-auth2.texi
index e34f0a4..da00a40 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 7b5150b..c853398 100644
--- a/doc/cha-gtls-app.texi
+++ b/doc/cha-gtls-app.texi
@@ -11,7 +11,7 @@
* Data transfer and termination::
* Handling alerts::
* Priority Strings::
-* Advanced and other topics::
+* Advanced topics::
* Using the cryptographic library::
* Selecting cryptographic key sizes::
@end menu
@@ -494,25 +494,27 @@ 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. The verification status returned can be printed using
+@funcref{gnutls_certificate_verification_status_print}.
+
+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
@@ -1067,11 +1069,12 @@ except TLS 1.2:
"SECURE128:+SECURE192:-VERS-TLS-ALL:+VERS-TLS1.2"
@end example
-@node Advanced and other topics
-@section Advanced and other topics
+@node Advanced topics
+@section Advanced topics
@menu
* Session resumption::
+* Certificate verification::
* Parameter generation::
* Keying Material Exporters::
* Channel Bindings::
@@ -1130,6 +1133,77 @@ Those keys should be associated with the GnuTLS session using
A server enabling both session tickets and a storage for session data
would use session tickets when clients support it and the storage otherwise.
+@node Certificate verification
+@subsection Certificate verification
+@cindex DANE
+@cindex DNSSEC
+@cindex SSH-style authentication
+@cindex Trust on first use
+@cindex Key pinning
+@tindex gnutls_certificate_verify_flags
+
+In this section the functionality for additional certificate verification methods is listed.
+These methods are intended to be used in addition to normal PKI verification, in order to reduce
+the risk of a compromised CA being undetected.
+
+@subsubsection Trust on first use
+
+The GnuTLS library includes functionlity to use an SSH-like trust on first use authentication.
+The available functions to store and verify public keys are listed below.
+
+@showfuncdesc{gnutls_verify_stored_pubkey}
+@showfuncdesc{gnutls_store_pubkey}
+
+In addition to the above the @funcref{gnutls_store_commitment} can be
+used to implement a key-pinning architecture as in @xcite{KEYPIN}.
+This provides a way for web server to commit on a public key that is
+not yet active.
+
+@showfuncdesc{gnutls_store_commitment}
+
+The storage and verification functions may be used with the default
+text file based back-end, or another back-end may be specified. That
+should contain storage and retrieval functions and specified as below.
+
+@showfuncE{gnutls_tdb_init,gnutls_tdb_deinit,gnutls_tdb_set_verify_func,gnutls_tdb_set_store_func,gnutls_tdb_set_store_commitment_func}
+
+@subsubsection DANE verification
+Since the DANE library is not included in GnuTLS it requires programs
+to be linked against it. This can be achieved with the following commands.
+
+@example
+gcc -o foo foo.c `pkg-config gnutls-dane --cflags --libs`
+@end example
+
+When a program uses the GNU autoconf system, then the following
+line or similar can be used to detect the presence of the library.
+
+@example
+PKG_CHECK_MODULES([LIBDANE], [gnutls-dane >= 3.0.0])
+
+AC_SUBST([LIBDANE_CFLAGS])
+AC_SUBST([LIBDANE_LIBS])
+@end example
+
+The high level functionality provided by the DANE library is shown below.
+
+@showfuncdesc{dane_verify_crt}
+
+@showfuncB{dane_verify_session_crt,dane_strerror}
+
+Note that the @code{dane_state_t} structure that is accepted by both
+verification functions is optional. It is required when many queries
+are performed to facilitate caching.
+The following flags are returned by the verify functions to
+indicate the status of the verification.
+
+@showenumdesc{dane_verify_status_t,The DANE verification status flags.}
+
+In order to generate a DANE TLSA entry to use in a DNS server
+you may use danetool (see @ref{danetool Invocation}).
+
+
+
@node Parameter generation
@subsection Parameter generation
@cindex parameter generation
@@ -1283,6 +1357,8 @@ that only allows the stream cipher ARCFOUR is below.
NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:+VERS-SSL3.0:-CIPHER-ALL:+ARCFOUR-128:%COMPAT
@end verbatim
+
+
@node Compatibility with the OpenSSL library
@subsection Compatibility with the OpenSSL library
@cindex OpenSSL
diff --git a/doc/examples/ex-client-x509.c b/doc/examples/ex-client-x509.c
index 6939ba3..6e38a15 100644
--- a/doc/examples/ex-client-x509.c
+++ b/doc/examples/ex-client-x509.c
@@ -142,11 +142,9 @@ 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;
+ int ret, type;
const char *hostname;
+ gnutls_datum_t out;
/* read hostname */
hostname = gnutls_session_get_ptr (session);
@@ -154,66 +152,25 @@ _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");
return GNUTLS_E_CERTIFICATE_ERROR;
}
- if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
- printf ("The certificate hasn't got a known issuer.\n");
+ type = gnutls_certificate_type_get (session);
- if (status & GNUTLS_CERT_REVOKED)
- printf ("The certificate has been revoked.\n");
-
- if (status & GNUTLS_CERT_EXPIRED)
- printf ("The certificate has expired\n");
-
- if (status & GNUTLS_CERT_NOT_ACTIVATED)
- printf ("The certificate is not yet activated\n");
-
- if (status & GNUTLS_CERT_INVALID)
- {
- printf ("The certificate is not trusted.\n");
- 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))
+ ret = gnutls_certificate_verification_status_print( status, type, &out, 0);
+ if (ret < 0)
{
- printf ("The certificate's owner does not match hostname '%s'\n",
- hostname);
+ printf ("Error\n");
return GNUTLS_E_CERTIFICATE_ERROR;
}
-
- gnutls_x509_crt_deinit (cert);
+
+ printf ("%s", out.data);
+
+ gnutls_free(out.data);
/* 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 a748516..9251b78 100644
--- a/doc/examples/ex-verify-ssh.c
+++ b/doc/examples/ex-verify-ssh.c
@@ -22,8 +22,8 @@ _ssh_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;
+ int ret, type;
+ gnutls_datum_t out;
const char *hostname;
/* read hostname */
@@ -32,41 +32,27 @@ _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");
return GNUTLS_E_CERTIFICATE_ERROR;
}
+
+ type = gnutls_certificate_type_get (session);
- if (status & GNUTLS_CERT_INVALID)
- printf ("The certificate is not trusted.\n");
-
- if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
- printf ("The certificate hasn't got a known issuer.\n");
-
- if (status & GNUTLS_CERT_REVOKED)
- printf ("The certificate has been revoked.\n");
-
- if (status & GNUTLS_CERT_EXPIRED)
- printf ("The certificate has expired\n");
-
- 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)
+ ret = gnutls_certificate_verification_status_print( status, type, &out, 0);
+ if (ret < 0)
{
- printf ("error in initialization\n");
+ printf ("Error\n");
return GNUTLS_E_CERTIFICATE_ERROR;
}
+
+ printf ("%s", out.data);
+
+ gnutls_free(out.data);
+ /* Do SSH verification */
cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
if (cert_list == NULL)
{
@@ -74,27 +60,9 @@ _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);
+ type, &cert_list[0], 0);
if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND)
{
printf("Host %s is not known.", hostname);
@@ -130,8 +98,7 @@ _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);
+ type, &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 d02440a..8fd5931 100644
--- a/doc/examples/verify.c
+++ b/doc/examples/verify.c
@@ -13,11 +13,9 @@
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;
+ int ret, type;
const char *hostname;
+ gnutls_datum_t out;
/* read hostname */
hostname = gnutls_session_get_ptr (session);
@@ -25,66 +23,25 @@ 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");
return GNUTLS_E_CERTIFICATE_ERROR;
}
- if (status & GNUTLS_CERT_INVALID)
- printf ("The certificate is not trusted.\n");
+ type = gnutls_certificate_type_get (session);
- if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
- printf ("The certificate hasn't got a known issuer.\n");
-
- if (status & GNUTLS_CERT_REVOKED)
- printf ("The certificate has been revoked.\n");
-
- if (status & GNUTLS_CERT_EXPIRED)
- printf ("The certificate has expired\n");
-
- 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))
+ ret = gnutls_certificate_verification_status_print( status, type, &out, 0);
+ if (ret < 0)
{
- printf ("The certificate's owner does not match hostname '%s'\n",
- hostname);
+ printf ("Error\n");
return GNUTLS_E_CERTIFICATE_ERROR;
}
-
- gnutls_x509_crt_deinit (cert);
+
+ printf ("%s", out.data);
+
+ gnutls_free(out.data);
/* notify gnutls to continue handshake normally */
return 0;
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index d8d437a..f803a65 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -41,6 +41,8 @@
#ifdef ENABLE_OPENPGP
#include "openpgp/gnutls_openpgp.h"
#endif
+#include "gettext.h"
+#define _(String) dgettext (PACKAGE, String)
/**
* gnutls_certificate_free_keys:
@@ -581,6 +583,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 +624,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 +632,7 @@ _gnutls_openpgp_crt_verify_peers (gnutls_session_t session,
gnutls_assert ();
return ret;
}
-
+
return 0;
}
#endif
@@ -677,10 +680,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;
@@ -846,3 +904,86 @@ _gnutls_check_key_cert_match (gnutls_certificate_credentials_t res)
return 0;
}
+
+/**
+ * gnutls_certificate_verification_status_print:
+ * @status: The status flags to be printed
+ * @type: The certificate type
+ * @out: Newly allocated datum with (0) terminated string.
+ * @flags: should be zero
+ *
+ * This function will pretty print the status of a verification
+ * process -- eg. the one obtained by gnutls_certificate_verify_peers3().
+ *
+ * The output @out needs to be deallocated using gnutls_free().
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ **/
+int
+gnutls_certificate_verification_status_print (unsigned int status,
+ gnutls_certificate_type_t type,
+ gnutls_datum_t * out, unsigned int flags)
+{
+ gnutls_buffer_st str;
+ int ret;
+
+ _gnutls_buffer_init (&str);
+
+ if (type == GNUTLS_CRT_X509)
+ {
+ if (status == 0)
+ _gnutls_buffer_append_str (&str, _("- Peer's certificate is trusted\n"));
+ else
+ {
+ if (status & GNUTLS_CERT_INVALID)
+ _gnutls_buffer_append_str (&str, _("- Peer's certificate is NOT trusted\n"));
+
+ if (status & GNUTLS_CERT_REVOKED)
+ _gnutls_buffer_append_str (&str, _("- Peer's certificate chain revoked\n"));
+
+ if (status & GNUTLS_CERT_REVOCATION_DATA_TOO_OLD)
+ _gnutls_buffer_append_str (&str, _("- The revocation data provided by the peer are too old\n"));
+
+ if (status & GNUTLS_CERT_REVOCATION_DATA_INVALID)
+ _gnutls_buffer_append_str (&str, _("- The revocation data provided by the peer are invalid\n"));
+
+ if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
+ _gnutls_buffer_append_str (&str, _("- Peer's certificate issuer is unknown\n"));
+
+ if (status & GNUTLS_CERT_SIGNER_NOT_CA)
+ _gnutls_buffer_append_str (&str, _("- Peer's certificate issuer is not a CA\n"));
+ }
+ }
+ else if (type == GNUTLS_CRT_OPENPGP)
+ {
+ if (status == 0)
+ _gnutls_buffer_append_str (&str, _("- Peer's key is valid\n"));
+
+ if (status & GNUTLS_CERT_INVALID)
+ _gnutls_buffer_append_str (&str, _("- Peer's certificate is invalid\n"));
+
+ if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
+ _gnutls_buffer_append_str (&str, _("- Could not find a signer of the peer's certificate\n"));
+
+ if (status & GNUTLS_CERT_REVOKED)
+ _gnutls_buffer_append_str (&str, _("- Peer's certificate is revoked\n"));
+ }
+
+ if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
+ _gnutls_buffer_append_str (&str, _("- Peer's certificate chain uses insecure algorithm\n"));
+
+ if (status & GNUTLS_CERT_NOT_ACTIVATED)
+ _gnutls_buffer_append_str (&str, _("- Peer's certificate chain uses not yet valid certificate\n"));
+
+ if (status & GNUTLS_CERT_EXPIRED)
+ _gnutls_buffer_append_str (&str, _("- Peer's certificate chain uses expired certificate\n"));
+
+ if (status & GNUTLS_CERT_UNEXPECTED_OWNER)
+ _gnutls_buffer_append_str (&str, _("- The name in the certificate does not match the expected\n"));
+
+ ret = _gnutls_buffer_to_datum( &str, out);
+ if (out->size > 0) out->size--;
+
+ return ret;
+}
diff --git a/lib/gnutls_ui.c b/lib/gnutls_ui.c
index 1cd53f2..8b157e7 100644
--- a/lib/gnutls_ui.c
+++ b/lib/gnutls_ui.c
@@ -684,10 +684,9 @@ gnutls_certificate_set_params_function (gnutls_certificate_credentials_t res,
* @res: is a gnutls_certificate_credentials_t structure
* @flags: are the flags
*
- * This function will set the flags to be used at verification of the
- * certificates. Flags must be OR of the
- * #gnutls_certificate_verify_flags enumerations. The default
- * for TLS sessions is GNUTLS_VERIFY_ALLOW_UNSORTED_CHAIN.
+ * This function will set the flags to be used for verification
+ * of certificates and override any defaults. The provided flags must be an OR of the
+ * #gnutls_certificate_verify_flags enumerations.
*
**/
void
@@ -698,6 +697,24 @@ gnutls_certificate_set_verify_flags (gnutls_certificate_credentials_t
}
/**
+ * gnutls_certificate_update_verify_flags:
+ * @res: is a gnutls_certificate_credentials_t structure
+ * @flags: are the new flags
+ *
+ * This function will update the default flags to be used for verification
+ * of certificates. The provided flags must be an OR of the
+ * #gnutls_certificate_verify_flags enumerations. The default
+ * for TLS sessions is GNUTLS_VERIFY_ALLOW_UNSORTED_CHAIN.
+ *
+ **/
+void
+gnutls_certificate_update_verify_flags (gnutls_certificate_credentials_t
+ res, unsigned int flags)
+{
+ res->verify_flags |= flags;
+}
+
+/**
* gnutls_certificate_set_verify_limits:
* @res: is a gnutls_certificate_credentials structure
* @max_bits: is the number of bits of an acceptable certificate (default 8200)
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index 19e6c73..cf8dee5 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 55340dc..a082cfc 100644
--- a/lib/gnutls_x509.h
+++ b/lib/gnutls_x509.h
@@ -24,6 +24,7 @@
#include <gnutls/abstract.h>
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 e60914e..98a86fb 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;
/**
@@ -1152,6 +1154,8 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session);
gnutls_dh_params_t dh_params);
void gnutls_certificate_set_verify_flags (gnutls_certificate_credentials_t
res, unsigned int flags);
+ void gnutls_certificate_update_verify_flags (gnutls_certificate_credentials_t
+ res, unsigned int flags);
void gnutls_certificate_set_verify_limits (gnutls_certificate_credentials_t
res, unsigned int max_bits,
unsigned int max_depth);
@@ -1697,6 +1701,13 @@ 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_certificate_verification_status_print (unsigned int status,
+ gnutls_certificate_type_t type,
+ gnutls_datum_t * out, unsigned int flags);
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 751e49b..e20597c 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -858,6 +858,9 @@ GNUTLS_3_1_0 {
gnutls_pubkey_import_x509_raw;
gnutls_certificate_get_peers_subkey_id;
gnutls_session_get_id2;
+ gnutls_certificate_update_verify_flags;
+ gnutls_certificate_verify_peers3;
+ gnutls_certificate_verification_status_print;
} GNUTLS_3_0_0;
GNUTLS_PRIVATE {
diff --git a/lib/openpgp/compat.c b/lib/openpgp/compat.c
index 7612d3f..ebcb3af 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 8af869b..4949624 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 9dc9cc7..e100155 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/output.c b/lib/x509/output.c
index 1797b26..ec1a6f2 100644
--- a/lib/x509/output.c
+++ b/lib/x509/output.c
@@ -1711,7 +1711,7 @@ print_oneline (gnutls_buffer_st * str, gnutls_x509_crt_t cert)
* %GNUTLS_CRT_PRINT_ONELINE format will generate one line with some
* selected fields, which is useful for logging purposes.
*
- * The output @out needs to be deallocate using gnutls_free().
+ * The output @out needs to be deallocated using gnutls_free().
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
* negative error value.
@@ -2086,7 +2086,7 @@ print_crl (gnutls_buffer_st * str, gnutls_x509_crl_t crl, int notsigned)
* This function will pretty print a X.509 certificate revocation
* list, suitable for display to a human.
*
- * The output @out needs to be deallocate using gnutls_free().
+ * The output @out needs to be deallocated using gnutls_free().
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
* negative error value.
@@ -2400,7 +2400,7 @@ print_crq_other (gnutls_buffer_st * str, gnutls_x509_crq_t crq)
* This function will pretty print a certificate request, suitable for
* display to a human.
*
- * The output @out needs to be deallocate using gnutls_free().
+ * The output @out needs to be deallocated using gnutls_free().
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
* negative error value.
diff --git a/lib/x509/rfc2818_hostname.c b/lib/x509/rfc2818_hostname.c
index 7d099f3..c53476f 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/cli.c b/src/cli.c
index 2cf50d4..a454606 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -399,7 +399,9 @@ cert_verify_callback (gnutls_session_t session)
int rc;
unsigned int status = 0;
int ssh = ENABLED_OPT(TOFU);
+#ifdef HAVE_DANE
int dane = ENABLED_OPT(DANE);
+#endif
int ca_verify = ENABLED_OPT(CA_VERIFICATION);
const char* txt_service;
diff --git a/src/common.c b/src/common.c
index 9ef83b6..3e8932a 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)
{
@@ -417,9 +314,10 @@ cert_verify (gnutls_session_t session, const char* hostname)
{
int rc;
unsigned int status = 0;
+ gnutls_datum_t out;
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");
@@ -434,53 +332,17 @@ cert_verify (gnutls_session_t session, const char* hostname)
}
type = gnutls_certificate_type_get (session);
- if (type == GNUTLS_CRT_X509)
+ rc = gnutls_certificate_verification_status_print( status, type, &out, 0);
+ if (rc < 0)
{
-
- if (status & GNUTLS_CERT_REVOKED)
- printf ("- Peer's certificate chain revoked\n");
- if (status & GNUTLS_CERT_REVOCATION_DATA_TOO_OLD)
- printf ("- The revocation data provided by the peer are too old\n");
- if (status & GNUTLS_CERT_REVOCATION_DATA_INVALID)
- printf ("- The revocation data provided by the peer are invalid\n");
- if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
- printf ("- Peer's certificate issuer is unknown\n");
- if (status & GNUTLS_CERT_SIGNER_NOT_CA)
- printf ("- Peer's certificate issuer is not a CA\n");
- if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
- printf
- ("- Peer's certificate chain uses insecure algorithm\n");
- if (status & GNUTLS_CERT_NOT_ACTIVATED)
- printf
- ("- Peer's certificate chain uses not yet valid certificate\n");
- if (status & GNUTLS_CERT_EXPIRED)
- printf
- ("- Peer's certificate chain uses expired certificate\n");
- if (status & GNUTLS_CERT_INVALID)
- 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;
+ printf ("- Could not print verification flags (err: %s)\n",
+ gnutls_strerror (rc));
+ return 0;
}
- else if (type == GNUTLS_CRT_OPENPGP)
- {
- if (status & GNUTLS_CERT_INVALID)
- printf ("- Peer's key is invalid\n");
- else
- 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
- {
- fprintf(stderr, "Unknown certificate type\n");
- status |= GNUTLS_CERT_INVALID;
- }
+ printf ("%s", out.data);
+
+ gnutls_free(out.data);
if (status)
return 0;
hooks/post-receive
--
GNU gnutls