From 0445a3554997687e10655fd10b94d5ea16adbd5a Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sun, 21 Dec 2003 14:51:24 +0000 Subject: *** empty log message *** --- NEWS | 2 +- doc/examples/Makefile.am | 2 +- doc/manpages/certtool.1 | 2 + doc/tex/ex-cert-select.tex | 205 +++++++++++++++++++++++++++++++++++++++++++-- doc/tex/examples.tex | 5 +- lib/auth_cert.c | 24 ++++-- lib/auth_cert.h | 27 ++++++ lib/gnutls_cert.c | 12 +-- lib/gnutls_int.h | 30 ------- lib/gnutls_ui.h | 12 +-- lib/x509/compat.c | 1 + libextra/gnutls_openssl.c | 1 + 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 #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +/* 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 - 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 #include #include +#include /** * 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 #include +#include #include #include #include -- cgit v1.2.1