summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2004-06-12 08:56:19 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2004-06-12 08:56:19 +0000
commit929c2be43d85501a74d8eb8c91b8e60c0a245b31 (patch)
treeefe393cf87dd31fe3e1e5278f9f8d9a8808024b5
parent67b883c8c66d09734264b53f1aaad91aff3aa257 (diff)
downloadgnutls-929c2be43d85501a74d8eb8c91b8e60c0a245b31.tar.gz
added an improved verification example.
-rw-r--r--doc/examples/Makefile.am2
-rw-r--r--doc/tex/Makefile.am2
-rw-r--r--doc/tex/ex-rfc2818.tex88
-rw-r--r--doc/tex/ex-verify.tex192
-rw-r--r--doc/tex/examples.tex5
5 files changed, 196 insertions, 93 deletions
diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am
index c463d15043..1cfd5912d6 100644
--- a/doc/examples/Makefile.am
+++ b/doc/examples/Makefile.am
@@ -1,4 +1,4 @@
EXTRA_DIST = ex-alert.c ex-client-resume.c ex-client-srp.c ex-client1.c \
- ex-client2.c ex-x509-info.c ex-rfc2818.c ex-serv-export.c ex-serv-pgp.c \
+ ex-client2.c ex-x509-info.c ex-verify.c ex-serv-export.c ex-serv-pgp.c \
ex-serv-srp.c ex-serv1.c ex-cert-select.c \
ex-crq.c ex-session-info.c ex-pkcs12.c
diff --git a/doc/tex/Makefile.am b/doc/tex/Makefile.am
index 1d4f56dbf0..e4bda2064e 100644
--- a/doc/tex/Makefile.am
+++ b/doc/tex/Makefile.am
@@ -5,7 +5,7 @@ EXTRA_DIST = gnutls.tex gnutls.ps \
# If you add any examples here, also change the ../examples/Makefile.am
# to include the C source.
EXAMPLE_OBJECTS = ex-alert.tex ex-client-srp.tex ex-serv-export.tex \
- ex-client2.tex ex-x509-info.tex ex-rfc2818.tex \
+ ex-client2.tex ex-x509-info.tex ex-verify.tex \
ex-serv1.tex ex-client-resume.tex ex-serv-srp.tex \
ex-serv-pgp.tex ex-cert-select.tex cert_auth.tex \
ex-crq.tex ex-session-info.tex ex-pkcs12.tex
diff --git a/doc/tex/ex-rfc2818.tex b/doc/tex/ex-rfc2818.tex
deleted file mode 100644
index f0a904a391..0000000000
--- a/doc/tex/ex-rfc2818.tex
+++ /dev/null
@@ -1,88 +0,0 @@
-\index{Verifying certificate paths}
-\label{ex:rfc2818}
-
-\begin{verbatim}
-
-#include <gnutls/gnutls.h>
-#include <gnutls/x509.h>
-
-/* This function will try to verify the peer's certificate, and
- * also check if the hostname matches, and the activation, expiration dates.
- */
-void verify_certificate( gnutls_session session, const char* hostname)
-{
- int status;
- const gnutls_datum* cert_list;
- int cert_list_size;
- gnutls_x509_crt cert;
-
-
- /* This verification function uses the trusted CAs in the credentials
- * structure. So you must have installed one or more CA certificates.
- */
- status = gnutls_certificate_verify_peers(session);
-
- if (status == GNUTLS_E_NO_CERTIFICATE_FOUND) {
- printf("No certificate was sent\n");
- return;
- }
-
- if (status & GNUTLS_CERT_INVALID)
- printf("The certificate is not trusted.\n");
-
- if (status & GNUTLS_CERT_ISSUER_NOT_FOUND)
- printf("The certificate hasn't got a known issuer.\n");
-
- if (status & GNUTLS_CERT_REVOKED)
- printf("The certificate has been revoked.\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;
-
- if ( gnutls_x509_crt_init( &cert) < 0) {
- printf("error in initialization\n");
- return;
- }
-
- cert_list = gnutls_certificate_get_peers( session, &cert_list_size);
- if ( cert_list == NULL) {
- printf("No certificate was found!\n");
- return;
- }
-
- /* 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;
- }
-
- /* Beware here we do not check for errors.
- */
- if ( gnutls_x509_crt_get_expiration_time( cert) < time(0)) {
- printf("The certificate has expired\n");
- return;
- }
-
- if ( gnutls_x509_crt_get_activation_time( cert) > time(0)) {
- printf("The certificate is not yet activated\n");
- return;
- }
-
- if ( !gnutls_x509_crt_check_hostname( cert, hostname)) {
- printf("The certificate's owner does not match hostname '%s'\n", hostname);
- return;
- }
-
- gnutls_x509_crt_deinit( cert);
-
- return;
-}
-
-\end{verbatim}
diff --git a/doc/tex/ex-verify.tex b/doc/tex/ex-verify.tex
new file mode 100644
index 0000000000..39d8a7b573
--- /dev/null
+++ b/doc/tex/ex-verify.tex
@@ -0,0 +1,192 @@
+\index{Verifying certificate chains}
+\label{ex:verify-chain}
+
+\begin{verbatim}
+
+#include <stdio.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+/* All the available CRLs
+ */
+extern gnutls_x509_crl* crl_list;
+extern int crl_list_size;
+
+/* All the available trusted CAs
+ */
+extern gnutls_x509_crt* ca_list;
+extern int ca_list_size;
+
+static void verify_cert2(gnutls_x509_crt crt,
+ gnutls_x509_crt issuer, gnutls_x509_crl * crl_list, int crl_list_size);
+static void verify_last_cert(gnutls_x509_crt crt,
+ gnutls_x509_crt *ca_list, int ca_list_size,
+ gnutls_x509_crl * crl_list, int crl_list_size);
+
+
+/* This function will try to verify the peer's certificate chain, and
+ * also check if the hostname matches, and the activation, expiration dates.
+ */
+void verify_certificate_chain( gnutls_session session, const char* hostname,
+ const gnutls_datum* cert_chain, int cert_chain_length)
+{
+ int i, ret;
+ gnutls_x509_crt cert[cert_chain_length];
+
+ /* Import all the certificates in the chain to
+ * native certificate format.
+ */
+ for (i=0;i<cert_chain_length;i++) {
+ gnutls_x509_crt_init(&cert[i]);
+ gnutls_x509_crt_import( cert[i], &cert_chain[i], GNUTLS_X509_FMT_DER);
+ }
+
+ /* Now verify the certificates against their issuers
+ * in the chain.
+ */
+ for (i=1;i<cert_chain_length;i++) {
+ verify_cert2( cert[i-1], cert[i], crl_list, crl_list_size);
+ }
+
+ /* Here we must verify the last certificate in the chain against
+ * our trusted CA list.
+ */
+ verify_last_cert( cert[cert_chain_length-1],
+ ca_list, ca_list_size, crl_list, crl_list_size);
+
+ /* Check if the name in the first certificate matches our destination!
+ */
+ if ( !gnutls_x509_crt_check_hostname( cert[0], hostname)) {
+ printf("The certificate's owner does not match hostname '%s'\n", hostname);
+ }
+
+ for (i=0;i<cert_chain_length;i++)
+ gnutls_x509_crt_deinit( cert[i]);
+
+ return;
+}
+
+
+/* Verifies a certificate against an other certificate
+ * which is supposed to be it's issuer. Also checks the
+ * crl_list if the certificate is revoked.
+ */
+static void verify_cert2(gnutls_x509_crt crt,
+ gnutls_x509_crt issuer, gnutls_x509_crl * crl_list, int crl_list_size)
+{
+ unsigned int output;
+ int ret;
+ time_t now = time(0);
+ size_t name_size;
+ char name[64];
+
+ /* Print information about the certificates to
+ * be checked.
+ */
+ name_size = sizeof(name);
+ gnutls_x509_crt_get_dn( crt, name, &name_size);
+
+ fprintf(stderr, "\nCertificate: %s\n", name);
+
+ name_size = sizeof(name);
+ gnutls_x509_crt_get_issuer_dn(crt, name, &name_size);
+
+ fprintf(stderr, "Issued by: %s\n", name);
+
+ /* Get the DN of the issuer cert.
+ */
+ name_size = sizeof(name);
+ gnutls_x509_crt_get_dn(issuer, name, &name_size);
+
+ fprintf(stderr, "Checking against: %s\n", name);
+
+ /* Do the actual verification.
+ */
+ gnutls_x509_crt_verify(crt, &issuer, 1, 0, &output);
+
+ if (output & GNUTLS_CERT_INVALID) {
+ fprintf(stderr, "Not trusted");
+
+ if (output & GNUTLS_CERT_SIGNER_NOT_CA)
+ fprintf(stderr, ": Issuer is not a CA\n");
+ else
+ fprintf(stderr, "\n");
+ } else
+ fprintf(stderr, "Trusted\n");
+
+
+ /* Now check the expiration dates.
+ */
+ if (gnutls_x509_crt_get_activation_time(crt) > now)
+ fprintf(stderr, "Not yet activated\n");
+
+ if (gnutls_x509_crt_get_expiration_time(crt) < now)
+ fprintf(stderr, "Expired\n");
+
+ /* Check if the certificate is revoked.
+ */
+ ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size);
+ if (ret == 1) { /* revoked */
+ fprintf(stderr, "Revoked\n");
+ }
+}
+
+
+/* Verifies a certificate against the trusted CA list.
+ * Also checks the crl_list if the certificate is revoked.
+ */
+static void verify_last_cert(gnutls_x509_crt crt,
+ gnutls_x509_crt *ca_list, int ca_list_size,
+ gnutls_x509_crl * crl_list, int crl_list_size)
+{
+ unsigned int output;
+ int ret;
+ time_t now = time(0);
+ size_t name_size;
+ char name[64];
+
+ /* Print information about the certificates to
+ * be checked.
+ */
+ name_size = sizeof(name);
+ gnutls_x509_crt_get_dn( crt, name, &name_size);
+
+ fprintf(stderr, "\nCertificate: %s\n", name);
+
+ name_size = sizeof(name);
+ gnutls_x509_crt_get_issuer_dn(crt, name, &name_size);
+
+ fprintf(stderr, "Issued by: %s\n", name);
+
+ /* Do the actual verification.
+ */
+ gnutls_x509_crt_verify(crt, ca_list, ca_list_size, 0, &output);
+
+ if (output & GNUTLS_CERT_INVALID) {
+ fprintf(stderr, "Not trusted");
+
+ if (output & GNUTLS_CERT_SIGNER_NOT_CA)
+ fprintf(stderr, ": Issuer is not a CA\n");
+ else
+ fprintf(stderr, "\n");
+ } else
+ fprintf(stderr, "Trusted\n");
+
+
+ /* Now check the expiration dates.
+ */
+ if (gnutls_x509_crt_get_activation_time(crt) > now)
+ fprintf(stderr, "Not yet activated\n");
+
+ if (gnutls_x509_crt_get_expiration_time(crt) < now)
+ fprintf(stderr, "Expired\n");
+
+ /* Check if the certificate is revoked.
+ */
+ ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size);
+ if (ret == 1) { /* revoked */
+ fprintf(stderr, "Revoked\n");
+ }
+}
+
+\end{verbatim}
diff --git a/doc/tex/examples.tex b/doc/tex/examples.tex
index 863fa7fd24..3c1152e00e 100644
--- a/doc/tex/examples.tex
+++ b/doc/tex/examples.tex
@@ -30,10 +30,9 @@ It must be considered secure, only after the peer's certificate and identity hav
verified. That is, you have to verify the signature in peer's
certificate, the hostname in the certificate, and expiration dates.
Just after this step you should treat the connection as being a secure one.
-The following function is a simple example on how to verify a single certificate.
-Real world programs should be able to handle certificate chains as well.
+The following function is an example on how to verify the peer's certificate chain.
-\input{ex-rfc2818}
+\input{ex-verify}
\subsection{Using a callback to select the certificate to use}
There are cases where a client holds several certificate and key pairs,