summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-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
-rw-r--r--lib/auth_cert.c24
-rw-r--r--lib/auth_cert.h27
-rw-r--r--lib/gnutls_cert.c12
-rw-r--r--lib/gnutls_int.h30
-rw-r--r--lib/gnutls_ui.h12
-rw-r--r--lib/x509/compat.c1
-rw-r--r--libextra/gnutls_openssl.c1
12 files changed, 262 insertions, 61 deletions
diff --git a/NEWS b/NEWS
index f90321fdae..fc81466b34 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-Version 1.1.0
+Version 1.1.0 (21/12/2003)
- The error codes GNUTLS_E_NO_TEMPORARY_DH_PARAMS and GNUTLS_E_NO_TEMPORARY_RSA_PARAMS
are no longer returned by the handshake function. Ciphersuites that
require temporary parameters are removed when such parameters do not exist.
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}
diff --git a/lib/auth_cert.c b/lib/auth_cert.c
index cbc4401b80..e76ece4bfc 100644
--- a/lib/auth_cert.c
+++ b/lib/auth_cert.c
@@ -412,15 +412,23 @@ retr_st st;
int ret;
gnutls_certificate_type type =
gnutls_certificate_type_get(session);
+const gnutls_certificate_credentials cred;
+
+ cred =
+ _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL);
+ if (cred == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
memset( &st, 0, sizeof(st));
if (session->security_parameters.entity == GNUTLS_SERVER) {
ret =
- session->internals.server_get_cert_callback(session, &st);
+ cred->server_get_cert_callback(session, &st);
} else { /* CLIENT */
ret =
- session->internals.client_get_cert_callback(session,
+ cred->client_get_cert_callback(session,
issuers_dn, issuers_dn_length,
&st);
}
@@ -454,7 +462,7 @@ gnutls_certificate_type type =
}
- _gnutls_selected_certs_set(session, local_certs, st.ncerts,
+ _gnutls_selected_certs_set(session, local_certs, (local_certs!=NULL)?st.ncerts:0,
local_key, 1);
ret = 0;
@@ -462,7 +470,7 @@ gnutls_certificate_type type =
cleanup:
if (st.type == GNUTLS_CRT_X509) {
- if (st.deinit_all_keys) {
+ if (st.deinit_all) {
for (i = 0; i < st.ncerts; i++) {
gnutls_x509_crt_deinit(st.cert.x509[i]);
}
@@ -470,7 +478,7 @@ cleanup:
gnutls_x509_privkey_deinit(st.key.x509);
}
} else {
- if (st.deinit_all_keys) {
+ if (st.deinit_all) {
if (_E_gnutls_openpgp_key_deinit == NULL ||
_E_gnutls_openpgp_privkey_deinit == NULL) {
gnutls_assert();
@@ -512,7 +520,7 @@ static int _select_client_cert(gnutls_session session,
return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
}
- if (session->internals.client_get_cert_callback != NULL ||
+ if (cred->client_get_cert_callback != NULL ||
session->internals.client_cert_callback != NULL) {
/* use a callback to get certificate
@@ -537,7 +545,7 @@ static int _select_client_cert(gnutls_session session,
}
}
- if (session->internals.client_get_cert_callback) {
+ if (cred->client_get_cert_callback) {
result = call_get_cert_callback( session, issuers_dn, issuers_dn_length);
goto cleanup;
}
@@ -1610,7 +1618,7 @@ int _gnutls_server_select_cert(gnutls_session session,
/* If the callback which retrieves certificate has been
* set use it.
*/
- if (session->internals.server_get_cert_callback != NULL) {
+ if (cred->server_get_cert_callback != NULL) {
return call_get_cert_callback( session, NULL, 0);
diff --git a/lib/auth_cert.h b/lib/auth_cert.h
index 94085ca53d..3e26c21207 100644
--- a/lib/auth_cert.h
+++ b/lib/auth_cert.h
@@ -3,6 +3,30 @@
# include "gnutls_cert.h"
# include "gnutls_auth.h"
# include "x509/x509.h"
+#include "../libextra/openpgp/openpgp.h"
+
+typedef struct retr_st {
+ gnutls_certificate_type type;
+ union cert {
+ gnutls_x509_crt* x509;
+ gnutls_openpgp_key pgp;
+ } cert;
+ uint ncerts;
+
+ union key {
+ gnutls_x509_privkey x509;
+ gnutls_openpgp_privkey pgp;
+ } key;
+
+ uint deinit_all;
+} retr_st;
+
+typedef int gnutls_certificate_client_retrieve_function(
+ struct gnutls_session_int*, const gnutls_datum* req_ca_cert, int nreqs,
+ retr_st*);
+
+typedef int gnutls_certificate_server_retrieve_function(
+ struct gnutls_session_int*, retr_st*);
/* This structure may be complex, but it's the only way to
* support a server that has multiple certificates
@@ -59,6 +83,9 @@ typedef struct {
* generating on every handshake.
*/
gnutls_datum x509_rdn_sequence;
+
+ gnutls_certificate_client_retrieve_function* client_get_cert_callback;
+ gnutls_certificate_server_retrieve_function* server_get_cert_callback;
} CERTIFICATE_CREDENTIALS_INT;
/* typedef CERTIFICATE_CREDENTIALS_INT * CERTIFICATE_CREDENTIALS; */
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index 16162b1be0..8366a5c392 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -319,7 +319,7 @@ void gnutls_certificate_server_set_select_function(gnutls_session session,
/**
* gnutls_certificate_client_set_retrieve_function - Used to set a callback to retrieve the certificate
- * @session: is a &gnutls_session structure.
+ * @cred: is a &gnutls_certificate_credentials structure.
* @func: is the callback function
*
* This function sets a callback to be called in order to retrieve the certificate
@@ -348,15 +348,15 @@ void gnutls_certificate_server_set_select_function(gnutls_session session,
* return 0 on success. The value (-1) indicates error and the handshake
* will be terminated.
**/
-void gnutls_certificate_client_set_retrieve_function(gnutls_session session,
+void gnutls_certificate_client_set_retrieve_function(gnutls_certificate_credentials cred,
gnutls_certificate_client_retrieve_function * func)
{
- session->internals.client_get_cert_callback = func;
+ cred->client_get_cert_callback = func;
}
/**
* gnutls_certificate_server_set_retrieve_function - Used to set a callback to retrieve the certificate
- * @session: is a &gnutls_session structure.
+ * @cred: is a &gnutls_certificate_credentials structure.
* @func: is the callback function
*
* This function sets a callback to be called in order to retrieve the certificate
@@ -379,10 +379,10 @@ void gnutls_certificate_client_set_retrieve_function(gnutls_session session,
* return 0 on success. The value (-1) indicates error and the handshake
* will be terminated.
**/
-void gnutls_certificate_server_set_retrieve_function(gnutls_session session,
+void gnutls_certificate_server_set_retrieve_function(gnutls_certificate_credentials cred,
gnutls_certificate_server_retrieve_function * func)
{
- session->internals.server_get_cert_callback = func;
+ cred->server_get_cert_callback = func;
}
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index cb396180fe..7eb254f64a 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -420,33 +420,6 @@ typedef int certificate_server_select_func(struct gnutls_session_int*,
typedef int srp_server_select_func(struct gnutls_session_int*,
const char**, const char**, unsigned int);
-/* authentication function definitions:
- */
-#include "../libextra/openpgp/openpgp.h"
-
-typedef struct retr_st {
- gnutls_certificate_type type;
- union cert {
- gnutls_x509_crt* x509;
- gnutls_openpgp_key pgp;
- } cert;
- uint ncerts;
-
- union key {
- gnutls_x509_privkey x509;
- gnutls_openpgp_privkey pgp;
- } key;
-
- uint deinit_all_keys;
-} retr_st;
-
-typedef int gnutls_certificate_client_retrieve_function(
- struct gnutls_session_int*, const gnutls_datum* req_ca_cert, int nreqs,
- retr_st*);
-
-typedef int gnutls_certificate_server_retrieve_function(
- struct gnutls_session_int*, retr_st*);
-
typedef struct {
opaque header[HANDSHAKE_HEADER_SIZE];
/* this holds the number of bytes in the handshake_header[] */
@@ -566,9 +539,6 @@ typedef struct {
certificate_client_select_func* client_cert_callback;
certificate_server_select_func* server_cert_callback;
- gnutls_certificate_client_retrieve_function* client_get_cert_callback;
- gnutls_certificate_server_retrieve_function* server_get_cert_callback;
-
/* Callback to select the proper password file
*/
srp_server_select_func* server_srp_callback;
diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h
index 6c2dbabdd3..fbca386228 100644
--- a/lib/gnutls_ui.h
+++ b/lib/gnutls_ui.h
@@ -43,12 +43,12 @@ typedef struct gnutls_retr_st {
gnutls_openpgp_privkey pgp;
} key;
- uint deinit_all_keys; /* if non zero all keys will be deinited */
+ uint deinit_all; /* if non zero all keys will be deinited */
} gnutls_retr_st;
typedef int gnutls_certificate_client_retrieve_function(gnutls_session,
const gnutls_datum
- * req_ca_cert,
+ * req_ca_rdn,
int nreqs,
gnutls_retr_st *);
typedef int gnutls_certificate_server_retrieve_function(gnutls_session,
@@ -72,8 +72,6 @@ int gnutls_rsa_export_get_modulus_bits(gnutls_session session);
/* X509PKI */
-#include <gnutls/compat8.h>
-
void gnutls_certificate_client_set_select_function(gnutls_session,
gnutls_certificate_client_select_function
*);
@@ -81,10 +79,12 @@ void gnutls_certificate_server_set_select_function(gnutls_session,
gnutls_certificate_server_select_function
*);
-void gnutls_certificate_client_set_retrieve_function(gnutls_session,
+/* These are set on the credentials structure.
+ */
+void gnutls_certificate_client_set_retrieve_function(gnutls_certificate_client_credentials,
gnutls_certificate_client_retrieve_function
*);
-void gnutls_certificate_server_set_retrieve_function(gnutls_session,
+void gnutls_certificate_server_set_retrieve_function(gnutls_certificate_server_credentials,
gnutls_certificate_server_retrieve_function
*);
diff --git a/lib/x509/compat.c b/lib/x509/compat.c
index 95b0ae6877..77c21d4da4 100644
--- a/lib/x509/compat.c
+++ b/lib/x509/compat.c
@@ -30,6 +30,7 @@
#include <dn.h>
#include <libtasn1.h>
#include <gnutls/x509.h>
+#include <gnutls/compat8.h>
/**
* gnutls_x509_extract_dn - This function parses an RDN sequence
diff --git a/libextra/gnutls_openssl.c b/libextra/gnutls_openssl.c
index 558502bae6..b7ecaebb9e 100644
--- a/libextra/gnutls_openssl.c
+++ b/libextra/gnutls_openssl.c
@@ -19,6 +19,7 @@
#include <config.h>
#include <gnutls/gnutls.h>
+#include <gnutls/compat8.h>
#include <gcrypt.h>
#include <stdio.h>
#include <stdlib.h>