summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2003-02-14 15:48:33 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2003-02-14 15:48:33 +0000
commit3da54547a9a85c8cf07e2b9505dfa62363b7e37f (patch)
tree6e024ecf3812c877516f51d4d51136c9d043004c
parent9af3251fd14b6c96f8ba08bcbc5847795fa35c06 (diff)
downloadgnutls-3da54547a9a85c8cf07e2b9505dfa62363b7e37f.tar.gz
Corrected bugs in gnutls_x509_rdn_get(). Added a test to print the server's trusted CAs in gnutls-cli-debug, and in gnutls-cli.
-rw-r--r--lib/auth_cert.c4
-rw-r--r--lib/gnutls.h.in.in1
-rw-r--r--lib/gnutls_cert.c12
-rw-r--r--lib/gnutls_ui.h12
-rw-r--r--lib/x509/dn.c25
-rw-r--r--lib/x509/rfc2818_hostname.c4
-rw-r--r--src/cli.c42
-rw-r--r--src/common.c97
-rw-r--r--src/tests.c59
-rw-r--r--src/tests.h1
-rw-r--r--src/tls_test.c1
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)
{
diff --git a/src/cli.c b/src/cli.c
index bbc99d50fa..3c2407dafb 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -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