diff options
-rw-r--r-- | lib/auth_cert.c | 4 | ||||
-rw-r--r-- | lib/gnutls.h.in.in | 1 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 12 | ||||
-rw-r--r-- | lib/gnutls_ui.h | 12 | ||||
-rw-r--r-- | lib/x509/dn.c | 25 | ||||
-rw-r--r-- | lib/x509/rfc2818_hostname.c | 4 | ||||
-rw-r--r-- | src/cli.c | 42 | ||||
-rw-r--r-- | src/common.c | 97 | ||||
-rw-r--r-- | src/tests.c | 59 | ||||
-rw-r--r-- | src/tests.h | 1 | ||||
-rw-r--r-- | src/tls_test.c | 1 |
11 files changed, 172 insertions, 86 deletions
diff --git a/lib/auth_cert.c b/lib/auth_cert.c index e6fe3054cc..f254b4966b 100644 --- a/lib/auth_cert.c +++ b/lib/auth_cert.c @@ -286,7 +286,9 @@ static int _gnutls_find_acceptable_client_cert(gnutls_session session, /* use the callback */ - if (indx == -1 && session->internals.client_cert_callback != NULL && cred->ncerts > 0) { /* use a callback to get certificate */ + if (indx == -1 && session->internals.client_cert_callback != NULL && try == -1) { + /* use a callback to get certificate + */ gnutls_datum *my_certs = NULL; gnutls_datum *issuers_dn = NULL; uint issuers_dn_len = 0; diff --git a/lib/gnutls.h.in.in b/lib/gnutls.h.in.in index 6b6bf74192..a54a9e35e6 100644 --- a/lib/gnutls.h.in.in +++ b/lib/gnutls.h.in.in @@ -388,3 +388,4 @@ void gnutls_openpgp_send_key(gnutls_session session, gnutls_openpgp_key_status s /* fingerprint */ int gnutls_fingerprint(gnutls_digest_algorithm algo, const gnutls_datum* data, char* result, size_t* result_size); + diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index 4f17c8c787..5e0638a51b 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -178,7 +178,7 @@ void gnutls_certificate_server_set_request(gnutls_session session, * @func: is the callback function * * The callback's function form is: - * int (*callback)(gnutls_session, gnutls_datum *client_cert, int ncerts, gnutls_datum* req_ca_cert, int nreqs); + * int (*callback)(gnutls_session, gnutls_datum *client_cert, int ncerts, gnutls_datum* req_ca_dn, int nreqs); * * 'client_cert' contains 'ncerts' gnutls_datum structures which hold * the raw certificates (DER for X.509 or binary for OpenPGP), of the @@ -198,10 +198,10 @@ void gnutls_certificate_server_set_request(gnutls_session session, * public key algorithms. * * If the callback function is provided then gnutls will call it - * once with NULL parameters. If the callback function returns + * once with NULL parameters (except for the sesion). If the callback function returns * a positive or zero number then gnutls will attempt to automaticaly * choose the appropriate certificate. If gnutls fails to find an appropriate - * certificate, then it will call the callback function again with the + * certificate, then it will call the callback function again with the * appropriate parameters. * * In case the callback returned a negative number then gnutls will @@ -210,7 +210,8 @@ void gnutls_certificate_server_set_request(gnutls_session session, * only to the return value of the callback function. * * The callback function should return the index of the certificate - * choosen by the user. -1 indicates that the user + * choosen by the user. The index is relative to the certificates in the + * callback's parameter. The value (-1) indicates that the user * does not want to use client authentication. * * This function returns 0 on success. @@ -342,7 +343,6 @@ int gnutls_certificate_verify_peers(gnutls_session session) info = _gnutls_get_auth_info(session); if (info == NULL) { - gnutls_assert(); return GNUTLS_E_NO_CERTIFICATE_FOUND; } @@ -376,7 +376,6 @@ time_t gnutls_certificate_expiration_time_peers(gnutls_session session) info = _gnutls_get_auth_info(session); if (info == NULL) { - gnutls_assert(); return (time_t) -1; } @@ -417,7 +416,6 @@ time_t gnutls_certificate_activation_time_peers(gnutls_session session) info = _gnutls_get_auth_info(session); if (info == NULL) { - gnutls_assert(); return (time_t) -1; } diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h index 38c14bd001..53c8136207 100644 --- a/lib/gnutls_ui.h +++ b/lib/gnutls_ui.h @@ -8,10 +8,14 @@ typedef enum gnutls_x509_subject_alt_name { # ifdef LIBGNUTLS_VERSION /* These are defined only in gnutls.h */ -typedef int gnutls_certificate_client_select_function(gnutls_session, - const gnutls_datum *, unsigned int, const gnutls_datum *, unsigned int); -typedef int gnutls_certificate_server_select_function(gnutls_session, - const gnutls_datum *, unsigned int); +/* Callback prototypes for the certificate authentication + * callbacks. + */ +typedef int gnutls_certificate_client_select_function( + gnutls_session, const gnutls_datum *client_cert, int ncerts, + const gnutls_datum* req_ca_cert, int nreqs); +typedef int gnutls_certificate_server_select_function( + gnutls_session, const gnutls_datum *server_certs, int ncerts); /* Functions that allow AUTH_INFO structures handling */ diff --git a/lib/x509/dn.c b/lib/x509/dn.c index e9bcf10016..47fbca4416 100644 --- a/lib/x509/dn.c +++ b/lib/x509/dn.c @@ -116,7 +116,9 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct, _gnutls_int2str(k1, counter); _gnutls_str_cpy(tmpbuffer1, sizeof(tmpbuffer1), asn1_rdn_name); - _gnutls_str_cat(tmpbuffer1, sizeof(tmpbuffer1), ".?"); + if (strlen(tmpbuffer1) > 0) + _gnutls_str_cat(tmpbuffer1, sizeof(tmpbuffer1), "."); + _gnutls_str_cat(tmpbuffer1, sizeof(tmpbuffer1), "?"); _gnutls_str_cat(tmpbuffer1, sizeof(tmpbuffer1), counter); len = sizeof(value) - 1; @@ -142,8 +144,10 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct, _gnutls_int2str(k2, counter); _gnutls_str_cpy(tmpbuffer2, sizeof(tmpbuffer2), tmpbuffer1); - _gnutls_str_cat(tmpbuffer2, sizeof(tmpbuffer2), - ".?"); + if (strlen( tmpbuffer2) > 0) + _gnutls_str_cat(tmpbuffer2, sizeof(tmpbuffer2), + "."); + _gnutls_str_cat(tmpbuffer2, sizeof(tmpbuffer2), "?"); _gnutls_str_cat(tmpbuffer2, sizeof(tmpbuffer2), counter); @@ -323,7 +327,10 @@ int _gnutls_x509_parse_dn_oid(ASN1_TYPE asn1_struct, _gnutls_int2str(k1, counter); _gnutls_str_cpy(tmpbuffer1, sizeof(tmpbuffer1), asn1_rdn_name); - _gnutls_str_cat(tmpbuffer1, sizeof(tmpbuffer1), ".?"); + + if (strlen( tmpbuffer1) > 0) + _gnutls_str_cat(tmpbuffer1, sizeof(tmpbuffer1), "."); + _gnutls_str_cat(tmpbuffer1, sizeof(tmpbuffer1), "?"); _gnutls_str_cat(tmpbuffer1, sizeof(tmpbuffer1), counter); len = sizeof(value) - 1; @@ -350,8 +357,11 @@ int _gnutls_x509_parse_dn_oid(ASN1_TYPE asn1_struct, _gnutls_int2str(k2, counter); _gnutls_str_cpy(tmpbuffer2, sizeof(tmpbuffer2), tmpbuffer1); + + if (strlen( tmpbuffer2) > 0) + _gnutls_str_cat(tmpbuffer2, sizeof(tmpbuffer2), "."); _gnutls_str_cat(tmpbuffer2, sizeof(tmpbuffer2), - ".?"); + "?"); _gnutls_str_cat(tmpbuffer2, sizeof(tmpbuffer2), counter); @@ -490,6 +500,7 @@ int gnutls_x509_rdn_get(const gnutls_datum * idn, ASN1_TYPE dn = ASN1_TYPE_EMPTY; if (sizeof_buf == 0) { + gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } @@ -513,7 +524,7 @@ int gnutls_x509_rdn_get(const gnutls_datum * idn, return _gnutls_asn2err(result); } - result = _gnutls_x509_parse_dn(dn, "", buf, sizeof_buf); + result = _gnutls_x509_parse_dn(dn, "rdnSequence", buf, sizeof_buf); asn1_delete_structure(&dn); return result; @@ -566,7 +577,7 @@ int gnutls_x509_rdn_get_by_oid(const gnutls_datum * idn, const char* oid, int in return _gnutls_asn2err(result); } - result = _gnutls_x509_parse_dn_oid(dn, "", oid, indx, buf, sizeof_buf); + result = _gnutls_x509_parse_dn_oid(dn, "rdnSequence", oid, indx, buf, sizeof_buf); asn1_delete_structure(&dn); return result; diff --git a/lib/x509/rfc2818_hostname.c b/lib/x509/rfc2818_hostname.c index a8856bc378..e538684adc 100644 --- a/lib/x509/rfc2818_hostname.c +++ b/lib/x509/rfc2818_hostname.c @@ -29,7 +29,7 @@ static int hostname_compare(const char *certname, const char *hostname); -/** +/*- * gnutls_x509_check_certificates_hostname - This function compares the given hostname with the hostname in the certificate * @cert: should contain a DER encoded certificate * @hostname: A null terminated string that contains a DNS name @@ -40,7 +40,7 @@ static int hostname_compare(const char *certname, const char *hostname); * * Returns non zero on success, and zero on failure. * - **/ + -*/ int gnutls_x509_check_certificates_hostname(const gnutls_datum * cert, const char *hostname) { @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000,2001,2002 Nikos Mavroyanopoulos + * Copyright (C) 2000,2001,2002,2003 Nikos Mavroyanopoulos * * This file is part of GNUTLS. * @@ -29,6 +29,7 @@ #include <unistd.h> #include <gnutls/gnutls.h> #include <gnutls/extra.h> +#include <gnutls/x509.h> #include <sys/time.h> #include <signal.h> #include <netdb.h> @@ -109,6 +110,38 @@ void init_global_tls_stuff(void); #define MAX(X,Y) (X >= Y ? X : Y); +/* A callback function to be used at the certificate selection time. + */ +static int cert_callback( gnutls_session session, const gnutls_datum* client_certs, + int client_certs_num, const gnutls_datum * req_ca_rdn, int nreqs) +{ +char issuer_dn[256]; +int len, i, ret; + + if (client_certs == NULL && req_ca_rdn == NULL) return -1; + + /* Print the server's trusted CAs + */ + if (nreqs > 0) + printf("- Server's trusted authorities:\n"); + else + printf("- Server did not send us any trusted authorities names.\n"); + + /* print the names (if any) */ + for (i=0;i<nreqs;i++) { + len = sizeof(issuer_dn); + ret = gnutls_x509_rdn_get( &req_ca_rdn[i], issuer_dn, &len); + if ( ret >= 0) { + printf(" [%d]: ", i); + printf("%s\n", issuer_dn); + } + } + + return -1; + +} + + /* initializes a gnutls_session with some defaults. */ static gnutls_session init_tls_session( const char* hostname) @@ -136,6 +169,8 @@ static gnutls_session init_tls_session( const char* hostname) gnutls_credentials_set(session, GNUTLS_CRD_SRP, srp_cred); gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); + gnutls_certificate_client_set_select_function( session, cert_callback); + /* send the fingerprint */ if (fingerprint != 0) gnutls_openpgp_send_key(session, GNUTLS_OPENPGP_KEY_FINGERPRINT); @@ -363,8 +398,6 @@ int main(int argc, char **argv) static gaainfo info; void gaa_parser(int argc, char **argv) { - int i, j; - if (gaa(argc, argv, &info) != -1) { fprintf(stderr, "Error in the arguments. Use the --help or -h parameters to get more information.\n"); @@ -523,6 +556,7 @@ int do_handshake(socket_st* socket) return ret; } + static void tls_log_func( const char* str) { fprintf(stderr, "|** %s", str); @@ -609,7 +643,7 @@ int ret; fprintf(stderr, "Error setting the OpenPGP trustdb file\n"); } } -/* gnutls_certificate_client_callback_func( xcred, cert_callback); */ + /* SRP stuff */ if (gnutls_srp_allocate_client_credentials(&srp_cred) < 0) { diff --git a/src/common.c b/src/common.c index d80ecabf1f..467c63601e 100644 --- a/src/common.c +++ b/src/common.c @@ -3,6 +3,7 @@ #include <string.h> #include <gnutls/gnutls.h> #include <gnutls/extra.h> +#include <gnutls/x509.h> #include <time.h> #define TEST_STRING @@ -11,13 +12,6 @@ int xml = 0; void print_cert_info(gnutls_session session); #define PRINTX(x,y) if (y[0]!=0) printf(" # %s %s\n", x, y) -#define PRINT_DN(X) PRINTX( "CN:", X.common_name); \ - PRINTX( "OU:", X.organizational_unit_name); \ - PRINTX( "O:", X.organization); \ - PRINTX( "L:", X.locality_name); \ - PRINTX( "S:", X.state_or_province_name); \ - PRINTX( "C:", X.country); \ - PRINTX( "E:", X.email) #define PRINT_PGP_NAME(X) PRINTX( "NAME:", X.name); \ PRINTX( "EMAIL:", X.email) @@ -35,80 +29,75 @@ static const char *my_ctime(time_t * tv) void print_x509_info(gnutls_session session) { - - gnutls_x509_dn dn; + gnutls_x509_crt crt; const gnutls_datum *cert_list; - int cert_list_size = 0; + int cert_list_size = 0, ret; char digest[20]; char serial[40]; + char dn[128]; + int dn_size; size_t digest_size = sizeof(digest); int i; int serial_size = sizeof(serial); char printable[120]; char *print; int bits, algo; - time_t expiret = gnutls_certificate_expiration_time_peers(session); - time_t activet = gnutls_certificate_activation_time_peers(session); + time_t expiret, activet; cert_list = gnutls_certificate_get_peers(session, &cert_list_size); + if (cert_list_size <= 0) return; -#if 0 /* FIXME */ - if (xml) { - gnutls_datum res; - - gnutls_x509_certificate_to_xml(&cert_list[0], &res, 0); - puts(res.data); - - free(res.data); - + gnutls_x509_crt_init( &crt); + ret = gnutls_x509_crt_import( crt, &cert_list[0], GNUTLS_X509_FMT_DER); + if (ret < 0) { + fprintf(stderr, "Decoding error: %s\n", gnutls_strerror(ret)); return; } -#endif - printf(" - Certificate info:\n"); + printf(" - Got a certificate list of %d certificates.\n", cert_list_size); + printf(" - Certificate[0] info:\n"); + + expiret = gnutls_x509_crt_get_expiration_time( crt); + activet = gnutls_x509_crt_get_activation_time( crt); - printf(" # Certificate is valid since: %s", my_ctime(&activet)); - printf(" # Certificate expires: %s", my_ctime(&expiret)); + printf(" # valid since: %s", my_ctime(&activet)); + printf(" # expires at: %s", my_ctime(&expiret)); /* Print the fingerprint of the certificate */ - if (gnutls_x509_fingerprint + if (gnutls_fingerprint (GNUTLS_DIG_MD5, &cert_list[0], digest, &digest_size) >= 0) { print = printable; for (i = 0; i < digest_size; i++) { sprintf(print, "%.2x ", (unsigned char) digest[i]); print += 3; } - printf(" # Certificate fingerprint: %s\n", printable); + printf(" # fingerprint: %s\n", printable); } /* Print the serial number of the certificate. */ - if (gnutls_x509_extract_certificate_serial - (&cert_list[0], serial, &serial_size) >= 0) { + if (gnutls_x509_crt_get_serial(crt, serial, &serial_size) >= 0) { print = printable; for (i = 0; i < serial_size; i++) { sprintf(print, "%.2x ", (unsigned char) serial[i]); print += 3; } - printf(" # Certificate serial number: %s\n", printable); + printf(" # serial number: %s\n", printable); } /* Print the version of the X.509 * certificate. */ - printf(" # Certificate version: #%d\n", - gnutls_x509_extract_certificate_version(&cert_list[0])); + printf(" # version: #%d\n", gnutls_x509_crt_get_version(crt)); algo = - gnutls_x509_extract_certificate_pk_algorithm(&cert_list[0], - &bits); - printf(" # Certificate public key algorithm: "); - + gnutls_x509_crt_get_pk_algorithm( crt, &bits); + printf(" # public key algorithm: "); if (algo == GNUTLS_PK_RSA) { printf("RSA\n"); printf(" # Modulus: %d bits\n", bits); @@ -119,31 +108,17 @@ void print_x509_info(gnutls_session session) printf("UNKNOWN\n"); } -#ifndef TEST_STRING - gnutls_x509_extract_certificate_dn(&cert_list[0], &dn); - PRINT_DN(dn); - - gnutls_x509_extract_certificate_issuer_dn(&cert_list[0], &dn); - printf(" # Certificate Issuer's info:\n"); - PRINT_DN(dn); -#else - { char buf[256]; - int buf_size = sizeof(buf); - int ret; - - ret = gnutls_x509_extract_certificate_dn_string( buf, buf_size, &cert_list[0], 0); - if (ret == 0) - printf( " # %s\n", buf); - else printf("gnutls_x509_extract_certificate_dn_string() returned %d\n", ret); - - ret = gnutls_x509_extract_certificate_dn_string( buf, buf_size, &cert_list[0], 1); - if (ret == 0) { - printf(" # Certificate Issuer's info:\n"); - printf( " # %s\n", buf); - } else printf("gnutls_x509_extract_certificate_dn_string() returned %d\n", ret); - - } -#endif + dn_size = sizeof(dn); + ret = gnutls_x509_crt_get_dn( crt, dn, &dn_size); + if (ret >= 0) + printf( " # Subject's DN: %s\n", dn); + + dn_size = sizeof(dn); + ret = gnutls_x509_crt_get_issuer_dn( crt, dn, &dn_size); + if (ret >= 0) + printf(" # Issuer's DN: %s\n", dn); + + gnutls_x509_crt_deinit( crt); } diff --git a/src/tests.c b/src/tests.c index 5208f069b2..f305592882 100644 --- a/src/tests.c +++ b/src/tests.c @@ -20,6 +20,7 @@ #include <gnutls/gnutls.h> #include <gnutls/extra.h> +#include <gnutls/x509.h> #include <tests.h> #include <unistd.h> #include <signal.h> @@ -587,3 +588,61 @@ int ret; return SUCCEED; } + +/* A callback function to be used at the certificate selection time. + */ +static int cert_callback( gnutls_session session, const gnutls_datum* client_certs, + int client_certs_num, const gnutls_datum * req_ca_rdn, int nreqs) +{ +char issuer_dn[256]; +int len, i, ret; + + if (client_certs == NULL && req_ca_rdn == NULL) return -1; + + /* Print the server's trusted CAs + */ + printf("\n"); + if (nreqs > 0) + printf("- Server's trusted authorities:\n"); + else + printf("- Server did not send us any trusted authorities names.\n"); + + /* print the names (if any) */ + for (i=0;i<nreqs;i++) { + len = sizeof(issuer_dn); + ret = gnutls_x509_rdn_get( &req_ca_rdn[i], issuer_dn, &len); + if ( ret >= 0) { + printf(" [%d]: ", i); + printf("%s\n", issuer_dn); + } + } + + return -1; + +} + +/* Prints the trusted server's CAs. This is only + * if the server sends a certificate request packet. + */ +int test_server_cas( gnutls_session session) +{ +int ret; + + ADD_ALL_CIPHERS(session); + ADD_ALL_COMP(session); + ADD_ALL_CERTTYPES(session); + ADD_ALL_PROTOCOLS(session); + ADD_ALL_MACS(session); + ADD_ALL_KX(session); + + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred); + gnutls_certificate_client_set_select_function( session, cert_callback); + + ret = do_handshake( session); + if (ret < 0) return FAILED; + + return SUCCEED; +} + + + diff --git a/src/tests.h b/src/tests.h index 0f7083a036..7ae0b24ea7 100644 --- a/src/tests.h +++ b/src/tests.h @@ -25,6 +25,7 @@ int test_unknown_ciphersuites( gnutls_session state); int test_openpgp1( gnutls_session state); int test_bye( gnutls_session state); int test_certificate( gnutls_session state); +int test_server_cas( gnutls_session state); int test_session_resume2( gnutls_session state); #define GERR(ret) fprintf(stderr, "*** Error: %s\n", gnutls_strerror(ret)) diff --git a/src/tls_test.c b/src/tls_test.c index 2adf86d3c4..b37e722da6 100644 --- a/src/tls_test.c +++ b/src/tls_test.c @@ -80,6 +80,7 @@ static const TLS_TEST tls_tests[] = { { "for TLS 1.0 support", test_tls1, "yes", "no", "dunno" }, { "for SSL 3.0 support", test_ssl3, "yes", "no", "dunno" }, { "for certificate information", test_certificate, "", "", "" }, + { "for trusted CAs", test_server_cas, "", "", "" }, { "for version rollback bug in RSA PMS", test_rsa_pms, "no", "yes", "dunno" }, { "for version rollback bug in Client Hello", test_version_rollback, "no", "yes", "dunno" }, /* this test will disable TLS 1.0 if the server is |