summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/examples/Makefile.am2
-rw-r--r--doc/manpages/certtool.12
-rw-r--r--doc/tex/ex-cert-select.tex205
-rw-r--r--doc/tex/examples.tex5
4 files changed, 204 insertions, 10 deletions
diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am
index 9b365b0f9f..d8e6e4b297 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 \
+EXTRA_DIST = ex-alert.c ex-client-resume.c ex-client-srp.c \
ex-client2.c ex-x509-info.c ex-rfc2818.c ex-serv-export.c ex-serv-pgp.c \
ex-serv-srp.c ex-serv1.c ex-pgp-keyserver.c ex-cert-select.c \
ex-crq.c ex-session-info.c ex-pkcs12.c
diff --git a/doc/manpages/certtool.1 b/doc/manpages/certtool.1
index 35a9de17ed..8921256683 100644
--- a/doc/manpages/certtool.1
+++ b/doc/manpages/certtool.1
@@ -55,6 +55,8 @@ Update a signed certificate.
.SS Controlling output
.IP "\-8, \-\-pkcs8"
Use PKCS #8 format for private keys.
+.IP "\-\-dsa"
+Generate a DSA key.
.IP "\-\-bits BITS"
Specify the number of bits for key generation.
.IP "\-\-export\-ciphers"
diff --git a/doc/tex/ex-cert-select.tex b/doc/tex/ex-cert-select.tex
index 796f2e568f..2137bebb92 100644
--- a/doc/tex/ex-cert-select.tex
+++ b/doc/tex/ex-cert-select.tex
@@ -2,21 +2,202 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
+/* A TLS client that loads the certificate and key.
+ */
+
+#define MAX_BUF 1024
+#define SA struct sockaddr
+#define MSG "GET / HTTP/1.0\r\n\r\n"
+
+#define CERT_FILE "cert.pem"
+#define KEY_FILE "key.pem"
+#define CAFILE "ca.pem"
+
+static int cert_callback(gnutls_session session,
+ const gnutls_datum* req_ca_rdn, int nreqs,
+ gnutls_retr_st * st);
+
+gnutls_x509_crt crt;
+gnutls_x509_privkey key;
+
+/* Helper functions to load a certificate and key
+ * files into memory. They use mmap for simplicity.
+ */
+static gnutls_datum mmap_file( const char* file)
+{
+int fd;
+gnutls_datum mmaped_file = { NULL, 0 };
+struct stat stat_st;
+void* ptr;
+
+ fd = open( file, 0);
+ if (fd==-1) return mmaped_file;
+
+ fstat( fd, &stat_st);
+
+ if ((ptr=mmap( NULL, stat_st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED)
+ return mmaped_file;
+
+ mmaped_file.data = ptr;
+ mmaped_file.size = stat_st.st_size;
+
+ return mmaped_file;
+}
+
+static void munmap_file( gnutls_datum data)
+{
+ munmap( data.data, data.size);
+}
+
+/* Load the certificate and the private key.
+ */
+static void load_keys( void)
+{
+int ret;
+gnutls_datum data;
+
+ data = mmap_file( CERT_FILE);
+ if (data.data == NULL) {
+ fprintf(stderr, "*** Error loading cert file.\n");
+ exit(1);
+ }
+ gnutls_x509_crt_init( &crt);
+
+ ret = gnutls_x509_crt_import( crt, &data, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "*** Error loading key file: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ munmap_file( data);
+
+ data = mmap_file( KEY_FILE);
+ if (data.data == NULL) {
+ fprintf(stderr, "*** Error loading key file.\n");
+ exit(1);
+ }
+
+ gnutls_x509_privkey_init( &key);
+
+ ret = gnutls_x509_privkey_import( key, &data, GNUTLS_X509_FMT_PEM);
+ if (ret < 0) {
+ fprintf(stderr, "*** Error loading key file: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ munmap_file( data);
+
+}
+
+int main()
+{
+ int ret, sd, ii;
+ gnutls_session session;
+ char buffer[MAX_BUF + 1];
+ gnutls_certificate_credentials xcred;
+ /* Allow connections to servers that have OpenPGP keys as well.
+ */
+
+ gnutls_global_init();
+
+ load_keys();
+
+ /* 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_client_set_retrieve_function( xcred, cert_callback);
+
+ /* Initialize TLS session
+ */
+ gnutls_init(&session, GNUTLS_CLIENT);
+
+ /* Use default priorities */
+ gnutls_set_default_priority(session);
+
+ /* 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_ptr( session, (gnutls_transport_ptr)sd);
+
+ /* Perform the TLS handshake
+ */
+ ret = gnutls_handshake( session);
+
+ if (ret < 0) {
+ fprintf(stderr, "*** Handshake failed\n");
+ gnutls_perror(ret);
+ goto end;
+ } else {
+ printf("- Handshake was completed\n");
+ }
+
+ 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) {
+ fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret));
+ goto end;
+ }
+
+ 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 callback should be associated with a session by calling
- * gnutls_certificate_client_set_select_function( session, cert_callback),
+ * gnutls_certificate_client_set_retrieve_function( session, cert_callback),
* before a handshake.
*/
static int cert_callback(gnutls_session session,
- const gnutls_datum * client_certs, int client_certs_num,
- const gnutls_datum * req_ca_rdn, int nreqs)
+ const gnutls_datum* req_ca_rdn, int nreqs,
+ gnutls_retr_st * st)
{
char issuer_dn[256];
int i, ret;
size_t len;
+ gnutls_certificate_type type;
/* Print the server's trusted CAs
*/
@@ -35,11 +216,23 @@ static int cert_callback(gnutls_session session,
}
}
- /* Select a certificate from the client_certs and return its
- * index.
+ /* Select a certificate and return it.
*/
- return -1;
+ type = gnutls_certificate_type_get( session);
+ if (type == GNUTLS_CRT_X509) {
+ st->type = type;
+ st->ncerts = 1;
+
+ st->cert.x509 = &crt;
+ st->key.x509 = key;
+
+ st->deinit_all = 0;
+ } else {
+ return -1;
+ }
+
+ return 0;
}
diff --git a/doc/tex/examples.tex b/doc/tex/examples.tex
index 31a38c972d..544b502616 100644
--- a/doc/tex/examples.tex
+++ b/doc/tex/examples.tex
@@ -37,9 +37,8 @@ Real world programs should be able to handle certificate chains as well.
\subsection{Using a callback to select the certificate to use}
There are cases where a client holds several certificate and key pairs,
-and may want to choose the appropriate to send in the current session.
-The following example demonstrates the use of the certificate selection callback
-to assist in this purpose.
+and may not want to load all of them in the credentials structure.
+The following example demonstrates the use of the certificate selection callback.
\par
\input{ex-cert-select}