diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2016-04-24 15:22:55 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2016-04-24 15:24:58 +0200 |
commit | c3c3e44d5dfe33407f2372753f6a1a9ecee7bc19 (patch) | |
tree | 60f9d0006a5d86b268a60c4c2ced9efdf6c08af0 /doc | |
parent | 4f6cb81345a2b15a476f911432c4d19976ac766b (diff) | |
download | gnutls-c3c3e44d5dfe33407f2372753f6a1a9ecee7bc19.tar.gz |
doc: added example client application utilizing the 3.1.x APIs
Diffstat (limited to 'doc')
-rw-r--r-- | doc/cha-gtls-examples.texi | 25 | ||||
-rw-r--r-- | doc/examples/Makefile.am | 1 | ||||
-rw-r--r-- | doc/examples/ex-client-x509-3.1.c | 193 |
3 files changed, 214 insertions, 5 deletions
diff --git a/doc/cha-gtls-examples.texi b/doc/cha-gtls-examples.texi index 7615f92041..fb951cc43e 100644 --- a/doc/cha-gtls-examples.texi +++ b/doc/cha-gtls-examples.texi @@ -33,6 +33,7 @@ implemented by another example. * Client using a smart card with TLS:: * Client with Resume capability example:: * Simple client example with SRP authentication:: +* Legacy client example with X.509 certificate support:: * Simple client example in C++:: * Helper functions for TCP connections:: * Helper functions for UDP connections:: @@ -43,11 +44,13 @@ implemented by another example. @anchor{ex-verify} Let's assume now that we want to create a TCP client which -communicates with servers that use @acronym{X.509} or -@acronym{OpenPGP} certificate authentication. The following client is -a very simple @acronym{TLS} client, which uses the high level verification -functions for certificates, but does not support session -resumption. +communicates with servers that use @acronym{X.509} certificate authentication. +The following client is a very simple @acronym{TLS} client, which uses +the high level verification functions for certificates, but does not support session +resumption. + +Note that this client utilizes functionality present in the latest GnuTLS +version. For a reasonably portable version see @ref{Legacy client example with X.509 certificate support}. @verbatiminclude examples/ex-client-x509.c @@ -151,6 +154,18 @@ itself using a certificate, and in that case it has to be verified. @verbatiminclude examples/ex-client-srp.c + +@node Legacy client example with X.509 certificate support +@subsection Legacy client example with @acronym{X.509} certificate support +@anchor{ex-verify-legacy} + +For applications that need to maintain compatibility with the GnuTLS 3.1.x +library, this client example is identical to @ref{Simple client example with X.509 certificate support} +but utilizes APIs that were available in GnuTLS 3.1.4. + +@verbatiminclude examples/ex-client-x509-3.1.c + + @node Simple client example in C++ @subsection Simple client example using the C++ API diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am index bcfa0a3c6a..ffafd22e97 100644 --- a/doc/examples/Makefile.am +++ b/doc/examples/Makefile.am @@ -88,4 +88,5 @@ endif libexamples_la_SOURCES = examples.h ex-alert.c ex-pkcs12.c \ ex-session-info.c ex-x509-info.c ex-verify.c \ + ex-client-x509-3.1.c \ tcp.c udp.c ex-pkcs11-list.c verify.c ex-verify-ssh.c diff --git a/doc/examples/ex-client-x509-3.1.c b/doc/examples/ex-client-x509-3.1.c new file mode 100644 index 0000000000..c60d1d4689 --- /dev/null +++ b/doc/examples/ex-client-x509-3.1.c @@ -0,0 +1,193 @@ +/* This example code is placed in the public domain. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> +#include "examples.h" + +/* A very basic TLS client, with X.509 authentication and server certificate + * verification. Note that error checking for missing files etc. is omitted + * for simplicity. + */ + +#define MAX_BUF 1024 +#define CAFILE "/etc/ssl/certs/ca-certificates.crt" +#define MSG "GET / HTTP/1.0\r\n\r\n" + +extern int tcp_connect(void); +extern void tcp_close(int sd); +static int _verify_certificate_callback(gnutls_session_t session); + +int main(void) +{ + int ret, sd, ii; + gnutls_session_t session; + char buffer[MAX_BUF + 1]; + const char *err; + gnutls_certificate_credentials_t xcred; + + if (gnutls_check_version("3.1.4") == NULL) { + fprintf(stderr, "GnuTLS 3.1.4 or later is required for this example\n"); + exit(1); + } + + /* for backwards compatibility with gnutls < 3.3.0 */ + gnutls_global_init(); + + /* X509 stuff */ + gnutls_certificate_allocate_credentials(&xcred); + + /* sets the trusted cas file + */ + gnutls_certificate_set_x509_trust_file(xcred, CAFILE, + GNUTLS_X509_FMT_PEM); + gnutls_certificate_set_verify_function(xcred, + _verify_certificate_callback); + + /* If client holds a certificate it can be set using the following: + * + gnutls_certificate_set_x509_key_file (xcred, + "cert.pem", "key.pem", + GNUTLS_X509_FMT_PEM); + */ + + /* Initialize TLS session + */ + gnutls_init(&session, GNUTLS_CLIENT); + + gnutls_session_set_ptr(session, (void *) "my_host_name"); + + gnutls_server_name_set(session, GNUTLS_NAME_DNS, "my_host_name", + strlen("my_host_name")); + + /* use default priorities */ + gnutls_set_default_priority(session); +#if 0 + /* if more fine-graned control is required */ + ret = gnutls_priority_set_direct(session, + "NORMAL", &err); + if (ret < 0) { + if (ret == GNUTLS_E_INVALID_REQUEST) { + fprintf(stderr, "Syntax error at: %s\n", err); + } + exit(1); + } +#endif + + /* put the x509 credentials to the current session + */ + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); + + /* connect to the peer + */ + sd = tcp_connect(); + + gnutls_transport_set_int(session, sd); + gnutls_handshake_set_timeout(session, + GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); + + /* Perform the TLS handshake + */ + do { + ret = gnutls_handshake(session); + } + while (ret < 0 && gnutls_error_is_fatal(ret) == 0); + + if (ret < 0) { + fprintf(stderr, "*** Handshake failed\n"); + gnutls_perror(ret); + goto end; + } else { + char *desc; + + desc = gnutls_session_get_desc(session); + printf("- Session info: %s\n", desc); + gnutls_free(desc); + } + + gnutls_record_send(session, MSG, strlen(MSG)); + + ret = gnutls_record_recv(session, buffer, MAX_BUF); + if (ret == 0) { + printf("- Peer has closed the TLS connection\n"); + goto end; + } else if (ret < 0 && gnutls_error_is_fatal(ret) == 0) { + fprintf(stderr, "*** Warning: %s\n", gnutls_strerror(ret)); + } else if (ret < 0) { + fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret)); + goto end; + } + + if (ret > 0) { + printf("- Received %d bytes: ", ret); + for (ii = 0; ii < ret; ii++) { + fputc(buffer[ii], stdout); + } + fputs("\n", stdout); + } + + gnutls_bye(session, GNUTLS_SHUT_RDWR); + + end: + + tcp_close(sd); + + gnutls_deinit(session); + + gnutls_certificate_free_credentials(xcred); + + gnutls_global_deinit(); + + return 0; +} + +/* This function will verify the peer's certificate, and check + * if the hostname matches, as well as the activation, expiration dates. + */ +static int _verify_certificate_callback(gnutls_session_t session) +{ + unsigned int status; + int ret, type; + const char *hostname; + gnutls_datum_t out; + + /* read hostname */ + hostname = gnutls_session_get_ptr(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_peers3(session, hostname, + &status); + if (ret < 0) { + printf("Error\n"); + return GNUTLS_E_CERTIFICATE_ERROR; + } + + type = gnutls_certificate_type_get(session); + + ret = + gnutls_certificate_verification_status_print(status, type, + &out, 0); + if (ret < 0) { + printf("Error\n"); + return GNUTLS_E_CERTIFICATE_ERROR; + } + + printf("%s", out.data); + + gnutls_free(out.data); + + if (status != 0) /* Certificate is not trusted */ + return GNUTLS_E_CERTIFICATE_ERROR; + + /* notify gnutls to continue handshake normally */ + return 0; +} |