summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2014-04-09 09:44:01 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2014-04-09 10:20:44 +0200
commite665044f1c8894993665fcc1030dc4344326797a (patch)
tree47475cf83c789016a6153bdfd76b6f8ab62c66d0
parentf7ad44f1b587e057070f57ceee521b8eecf060db (diff)
downloadgnutls-e665044f1c8894993665fcc1030dc4344326797a.tar.gz
Replaced gnutls_certificate_verify_peers3() with the extendable gnutls_certificate_verify_peers().
That will allow adding new functionality to verification without the need to add new functions.
-rw-r--r--NEWS2
-rw-r--r--doc/cha-cert-auth.texi2
-rw-r--r--doc/examples/ex-client-x509.c24
-rw-r--r--doc/examples/verify.c17
-rw-r--r--lib/gnutls_cert.c49
-rw-r--r--lib/includes/gnutls/gnutls.h.in29
-rw-r--r--lib/libgnutls.map2
-rw-r--r--src/cli.c2
-rw-r--r--src/common.c20
-rw-r--r--src/common.h2
-rw-r--r--src/serv.c4
-rw-r--r--tests/mini-x509-2.c234
-rw-r--r--tests/mini-x509.c17
13 files changed, 327 insertions, 77 deletions
diff --git a/NEWS b/NEWS
index 78ee7e914a..6c4c5388f4 100644
--- a/NEWS
+++ b/NEWS
@@ -103,7 +103,7 @@ That option enables (when running on FIPS140-enabled system):
** API and ABI modifications:
GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS: Added
-gnutls_certificate_verify_peers4: Added
+gnutls_certificate_verify_peers: Added
gnutls_privkey_generate: Added
gnutls_pkcs11_crt_is_known: Added
gnutls_fips140_mode_enabled: Added
diff --git a/doc/cha-cert-auth.texi b/doc/cha-cert-auth.texi
index dfd4f8c9ec..00bc5427d0 100644
--- a/doc/cha-cert-auth.texi
+++ b/doc/cha-cert-auth.texi
@@ -355,7 +355,7 @@ may be used to verify the peer's certificate chain and identity. The flags
are set similarly to the verification functions in the previous section.
Note that in certain cases it is required to check the marked purpose of
the end certificate (e.g. @code{GNUTLS_KP_TLS_WWW_SERVER}); in these case
-@funcref{gnutls_certificate_verify_peers4} should be used instead.
+@funcref{gnutls_certificate_verify_peers} should be used instead.
There is also the possibility to pass some input to the verification
functions in the form of flags. For @funcref{gnutls_x509_trust_list_verify_crt} the
diff --git a/doc/examples/ex-client-x509.c b/doc/examples/ex-client-x509.c
index dc6b2985e0..ff90ad0bec 100644
--- a/doc/examples/ex-client-x509.c
+++ b/doc/examples/ex-client-x509.c
@@ -158,9 +158,29 @@ static int _verify_certificate_callback(gnutls_session_t session)
/* This verification function uses the trusted CAs in the credentials
* structure. So you must have installed one or more CA certificates.
*/
- ret = gnutls_certificate_verify_peers4(session, hostname,
- GNUTLS_KP_TLS_WWW_SERVER,
+
+ /* The following demonstrate two different verification functions,
+ * the more flexible gnutls_certificate_verify_peers(), as well
+ * as the old gnutls_certificate_verify_peers3(). */
+#if 1
+ {
+ gnutls_typed_vdata_st data[2];
+
+ memset(data, 0, sizeof(data));
+
+ data[0].type = GNUTLS_DT_DNS_HOSTNAME;
+ data[0].data = (void*)hostname;
+
+ data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
+ data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER;
+
+ ret = gnutls_certificate_verify_peers(session, data, 2,
+ &status);
+ }
+#else
+ ret = gnutls_certificate_verify_peers3(session, hostname,
&status);
+#endif
if (ret < 0) {
printf("Error\n");
return GNUTLS_E_CERTIFICATE_ERROR;
diff --git a/doc/examples/verify.c b/doc/examples/verify.c
index 86d35808fc..2b5fa7a9c5 100644
--- a/doc/examples/verify.c
+++ b/doc/examples/verify.c
@@ -10,12 +10,17 @@
#include "examples.h"
+/* The example below demonstrates the usage of the more powerful
+ * gnutls_certificate_verify_peers() which can be used to check
+ * the hostname, as well as the key purpose OID of the peer's
+ * certificate. */
int verify_certificate_callback(gnutls_session_t session)
{
unsigned int status;
int ret, type;
const char *hostname;
gnutls_datum_t out;
+ gnutls_typed_vdata_st data[2];
/* read hostname */
hostname = gnutls_session_get_ptr(session);
@@ -23,9 +28,15 @@ int verify_certificate_callback(gnutls_session_t session)
/* This verification function uses the trusted CAs in the credentials
* structure. So you must have installed one or more CA certificates.
*/
- ret = gnutls_certificate_verify_peers4(session, hostname,
- GNUTLS_KP_TLS_WWW_SERVER,
- &status);
+ data[0].type = GNUTLS_DT_DNS_HOSTNAME;
+ data[0].data = (void*)hostname;
+ data[0].size = 0;
+
+ data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
+ data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER;
+ data[1].size = 0;
+ ret = gnutls_certificate_verify_peers(session, data, 2,
+ &status);
if (ret < 0) {
printf("Error\n");
return GNUTLS_E_CERTIFICATE_ERROR;
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index 557ee6b71a..5d755c3004 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -656,7 +656,7 @@ int
gnutls_certificate_verify_peers2(gnutls_session_t session,
unsigned int *status)
{
- return gnutls_certificate_verify_peers4(session, NULL, NULL, status);
+ return gnutls_certificate_verify_peers(session, NULL, 0, status);
}
/**
@@ -680,7 +680,7 @@ gnutls_certificate_verify_peers2(gnutls_session_t session,
* If names do not match the %GNUTLS_CERT_UNEXPECTED_OWNER status flag will be set.
*
* In order to verify the purpose of the end-certificate (by checking the extended
- * key usage), use gnutls_certificate_verify_peers4().
+ * key usage), use gnutls_certificate_verify_peers().
*
* Returns: a negative error code on error and %GNUTLS_E_SUCCESS (0) on success.
*
@@ -691,14 +691,20 @@ gnutls_certificate_verify_peers3(gnutls_session_t session,
const char *hostname,
unsigned int *status)
{
- return gnutls_certificate_verify_peers4(session, hostname, NULL, status);
+gnutls_typed_vdata_st data;
+
+ data.type = GNUTLS_DT_DNS_HOSTNAME;
+ data.size = 0;
+ data.data = (void*)hostname;
+
+ return gnutls_certificate_verify_peers(session, &data, 1, status);
}
/**
- * gnutls_certificate_verify_peers4:
+ * gnutls_certificate_verify_peers:
* @session: is a gnutls session
- * @hostname: is the expected name of the peer; may be %NULL
- * @purpose: is the expected key purpose OID, see the %GNUTLS_KP definitions
+ * @data: an array of typed data
+ * @elements: the number of data elements
* @status: is the output of the verification
*
* This function will verify the peer's certificate and store the
@@ -710,26 +716,31 @@ gnutls_certificate_verify_peers3(gnutls_session_t session,
* using gnutls_certificate_set_verify_flags(). See the documentation
* of gnutls_certificate_verify_peers2() for details in the verification process.
*
- * If the @hostname provided is non-NULL then this function will compare
+ * The acceptable data types are %GNUTLS_DT_DNS_HOSTNAME and %GNUTLS_DT_KEY_PURPOSE_OID.
+ * If a DNS hostname is provided then this function will compare
* the hostname in the certificate against the given. The comparison will
* be accurate for ascii names; non-ascii names are compared byte-by-byte.
* If names do not match the %GNUTLS_CERT_UNEXPECTED_OWNER status flag will be set.
*
- * If @purpose is non-NULL and the end-certificate contains the extended key usage
- * PKIX extension, it will be required to be have the provided key purpose (e.g., %GNUTLS_KP_TLS_WWW_SERVER),
- * or verification will fail with %GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE status.
+ * If a key purpose OID is provided and the end-certificate contains the extended key
+ * usage PKIX extension, it will be required to be have the provided key purpose
+ * (e.g., %GNUTLS_KP_TLS_WWW_SERVER), or be marked for any purpose, otherwise
+ * verification will fail with %GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE status.
*
* Returns: a negative error code on error and %GNUTLS_E_SUCCESS (0) on success.
*
* Since: 3.3.0
**/
int
-gnutls_certificate_verify_peers4(gnutls_session_t session,
- const char *hostname,
- const char *purpose,
- unsigned int *status)
+gnutls_certificate_verify_peers(gnutls_session_t session,
+ gnutls_typed_vdata_st * data,
+ unsigned int elements,
+ unsigned int *status)
{
cert_auth_info_t info;
+ const char *hostname = NULL;
+ const char *purpose = NULL;
+ unsigned i;
CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
@@ -741,6 +752,16 @@ gnutls_certificate_verify_peers4(gnutls_session_t session,
if (info->raw_certificate_list == NULL || info->ncerts == 0)
return GNUTLS_E_NO_CERTIFICATE_FOUND;
+ for (i=0;i<elements;i++) {
+ if (data[i].type == GNUTLS_DT_DNS_HOSTNAME) {
+ hostname = (void*)data[i].data;
+ } else if (data[i].type == GNUTLS_DT_KEY_PURPOSE_OID) {
+ purpose = (void*)data[i].data;
+ } else {
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ }
+
switch (gnutls_certificate_type_get(session)) {
case GNUTLS_CRT_X509:
return _gnutls_x509_cert_verify_peers(session, hostname,
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 71244da554..67419e9e64 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -1911,11 +1911,32 @@ int gnutls_certificate_verify_peers2(gnutls_session_t session,
int gnutls_certificate_verify_peers3(gnutls_session_t session,
const char *hostname,
unsigned int *status);
+
+/**
+ * gnutls_vdata_types_t:
+ * @GNUTLS_DT_UNKNOWN: Unknown data type.
+ * @GNUTLS_DT_DNS_HOSTNAME: The data contain a null-terminated DNS hostname.
+ * @GNUTLS_DT_KEY_PURPOSE_OID: The data contain a null-terminated key purpose OID.
+ *
+ * Enumeration of different key exchange algorithms.
+ */
+typedef enum {
+ GNUTLS_DT_UNKNOWN = 0,
+ GNUTLS_DT_DNS_HOSTNAME = 1,
+ GNUTLS_DT_KEY_PURPOSE_OID = 2,
+} gnutls_vdata_types_t;
+
+typedef struct {
+ gnutls_vdata_types_t type;
+ unsigned char *data;
+ unsigned int size;
+} gnutls_typed_vdata_st;
+
int
-gnutls_certificate_verify_peers4(gnutls_session_t session,
- const char *hostname,
- const char *purpose,
- unsigned int *status);
+gnutls_certificate_verify_peers(gnutls_session_t session,
+ gnutls_typed_vdata_st * data,
+ unsigned int elements,
+ unsigned int *status);
int gnutls_certificate_verification_status_print(unsigned int status,
gnutls_certificate_type_t
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 38b76caec6..303e77dde9 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1010,7 +1010,7 @@ GNUTLS_3_1_0 {
gnutls_x509_ext_export_key_purposes;
gnutls_x509_crt_check_hostname2;
gnutls_openpgp_crt_check_hostname2;
- gnutls_certificate_verify_peers4;
+ gnutls_certificate_verify_peers;
} GNUTLS_3_0_0;
GNUTLS_PRIVATE {
diff --git a/src/cli.c b/src/cli.c
index a4ed4aac44..6837777d22 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -436,7 +436,7 @@ static int cert_verify_callback(gnutls_session_t session)
print_cert_info(session, verbose, print_cert);
if (ca_verify) {
- rc = cert_verify(session, hostname);
+ rc = cert_verify(session, hostname, GNUTLS_KP_TLS_WWW_SERVER);
if (rc == 0) {
printf
("*** Verifying server certificate failed...\n");
diff --git a/src/common.c b/src/common.c
index 81fea5f254..d878ecf29d 100644
--- a/src/common.c
+++ b/src/common.c
@@ -285,14 +285,30 @@ print_openpgp_info(gnutls_session_t session, int flag, int print_cert)
/* returns false (0) if not verified, or true (1) otherwise
*/
-int cert_verify(gnutls_session_t session, const char *hostname)
+int cert_verify(gnutls_session_t session, const char *hostname, const char *purpose)
{
int rc;
unsigned int status = 0;
gnutls_datum_t out;
int type;
+ gnutls_typed_vdata_st data[2];
+ unsigned elements = 0;
- rc = gnutls_certificate_verify_peers3(session, hostname, &status);
+ memset(data, 0, sizeof(data));
+
+ if (hostname) {
+ data[elements].type = GNUTLS_DT_DNS_HOSTNAME;
+ data[elements].data = (void*)hostname;
+ elements++;
+ }
+
+ if (purpose) {
+ data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
+ data[elements].data = (void*)purpose;
+ elements++;
+ }
+
+ rc = gnutls_certificate_verify_peers(session, data, elements, &status);
if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND) {
printf("- Peer did not send any certificate.\n");
return 0;
diff --git a/src/common.h b/src/common.h
index 37912ecc43..9d786ce95c 100644
--- a/src/common.h
+++ b/src/common.h
@@ -55,7 +55,7 @@ void print_cert_info(gnutls_session_t, int flag, int print_cert);
void print_cert_info_compact(gnutls_session_t session);
void print_list(const char *priorities, int verbose);
-int cert_verify(gnutls_session_t session, const char *hostname);
+int cert_verify(gnutls_session_t session, const char *hostname, const char *purpose);
const char *raw_to_string(const unsigned char *raw, size_t raw_size);
void pkcs11_common(void);
diff --git a/src/serv.c b/src/serv.c
index 3f65605994..46dcbfd74f 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -1356,7 +1356,7 @@ static void tcp_server(const char *name, int port)
cert_verify
(j->
tls_session,
- NULL);
+ NULL, NULL);
}
j->handshake_ok = 1;
}
@@ -1536,7 +1536,7 @@ static void tcp_server(const char *name, int port)
cert_verify
(j->
tls_session,
- NULL);
+ NULL, NULL);
}
j->handshake_ok = 1;
}
diff --git a/tests/mini-x509-2.c b/tests/mini-x509-2.c
index 3e0b42231f..74fca4ac1f 100644
--- a/tests/mini-x509-2.c
+++ b/tests/mini-x509-2.c
@@ -42,42 +42,103 @@ static void tls_log_func(int level, const char *str)
fprintf(stderr, "%s|<%d>| %s", side, level, str);
}
+static unsigned char ca_cert_pem[] =
+"-----BEGIN CERTIFICATE-----\n"
+"MIIC4DCCAcigAwIBAgIBADANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRDQS0w\n"
+"MCIYDzIwMTQwNDA5MDgwMjM0WhgPOTk5OTEyMzEyMzU5NTlaMA8xDTALBgNVBAMT\n"
+"BENBLTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCuLSye8pe3yWKZ\n"
+"Yp7tLQ4ImwLqqh1aN7x9pc5spLDj6krVArzkyyYDcWvtQNDjErEfLUrZZrCc4aIl\n"
+"oU1Ghb92kI8ofZnHFbj3z5zdcWqiPppj5Y+hRdc4LszTWb+itrD9Ht/D67EK+m7W\n"
+"ev6xxUdyiBYUmb2O3CnPZpUVshMRtEe45EDGI5hUgL2n4Msj41htTq8hATYPXgoq\n"
+"gQUyXFpKAX5XDCyOG+FC6jmEys7UCRYv3SCl7TPWJ4cm+lHcFI2/OTOCBvMlKN2J\n"
+"mWCdfnudZldqthin+8fR9l4nbuutOfPNt1Dj9InDzWZ1W/o4LrjKa7fsvszj2Z5A\n"
+"Fn+xN/4zAgMBAAGjQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcE\n"
+"ADAdBgNVHQ4EFgQUwRHwbXyPosKNNkBiZduEwL5ZCwswDQYJKoZIhvcNAQELBQAD\n"
+"ggEBAEKr0b7WoJL+L8St/LEITU/i7FwFrCP6DkbaNo0kgzPmwnvNmw88MLI6UKwE\n"
+"JecnjFhurRBBZ4FA85ucNyizeBnuXqFcyJ20+XziaXGPKV/ugKyYv9KBoTYkQOCh\n"
+"nbOthmDqjvy2UYQj0BU2dOywkjUKWhYHEZLBpZYck0Orynxydwil5Ncsz4t3smJw\n"
+"ahzCW8SzBFTiO99qQBCH2RH1PbUYzfAnJxZS2VScpcqlu9pr+Qv7r8E3p9qHxnQM\n"
+"gO5laWO6lc13rNsbZRrtlCvacsiDSuDnS8EVXm0ih4fAntpRHacPbXZbOPQqJ/+1\n"
+"G7/qJ6cDC/9aW+fU80ogTkAoFg4=\n"
+"-----END CERTIFICATE-----\n";
+
+const gnutls_datum_t ca_cert = { ca_cert_pem,
+ sizeof(ca_cert_pem)
+};
+
static unsigned char server_cert_pem[] =
- "-----BEGIN CERTIFICATE-----\n"
- "MIICVjCCAcGgAwIBAgIERiYdMTALBgkqhkiG9w0BAQUwGTEXMBUGA1UEAxMOR251\n"
- "VExTIHRlc3QgQ0EwHhcNMDcwNDE4MTMyOTIxWhcNMDgwNDE3MTMyOTIxWjA3MRsw\n"
- "GQYDVQQKExJHbnVUTFMgdGVzdCBzZXJ2ZXIxGDAWBgNVBAMTD3Rlc3QuZ251dGxz\n"
- "Lm9yZzCBnDALBgkqhkiG9w0BAQEDgYwAMIGIAoGA17pcr6MM8C6pJ1aqU46o63+B\n"
- "dUxrmL5K6rce+EvDasTaDQC46kwTHzYWk95y78akXrJutsoKiFV1kJbtple8DDt2\n"
- "DZcevensf9Op7PuFZKBroEjOd35znDET/z3IrqVgbtm2jFqab7a+n2q9p/CgMyf1\n"
- "tx2S5Zacc1LWn9bIjrECAwEAAaOBkzCBkDAMBgNVHRMBAf8EAjAAMBoGA1UdEQQT\n"
- "MBGCD3Rlc3QuZ251dGxzLm9yZzATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHQ8B\n"
- "Af8EBQMDB6AAMB0GA1UdDgQWBBTrx0Vu5fglyoyNgw106YbU3VW0dTAfBgNVHSME\n"
- "GDAWgBTpPBz7rZJu5gakViyi4cBTJ8jylTALBgkqhkiG9w0BAQUDgYEAaFEPTt+7\n"
- "bzvBuOf7+QmeQcn29kT6Bsyh1RHJXf8KTk5QRfwp6ogbp94JQWcNQ/S7YDFHglD1\n"
- "AwUNBRXwd3riUsMnsxgeSDxYBfJYbDLeohNBsqaPDJb7XailWbMQKfAbFQ8cnOxg\n"
- "rOKLUQRWJ0K3HyXRMhbqjdLIaQiCvQLuizo=\n" "-----END CERTIFICATE-----\n";
+"-----BEGIN CERTIFICATE-----\n"
+"MIIDOjCCAiKgAwIBAgIMU0T+mwoDu5uVLKeeMA0GCSqGSIb3DQEBCwUAMA8xDTAL\n"
+"BgNVBAMTBENBLTEwIhgPMjAxNDA0MDkwODAyMzVaGA85OTk5MTIzMTIzNTk1OVow\n"
+"EzERMA8GA1UEAxMIc2VydmVyLTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\n"
+"AoIBAQDXfvgsMWXHNf3iUaEoZSNztZZr6+UdBkoUhbdWJDR+GwR+GHfnYaYHsuqb\n"
+"bNEl/QFI+8Jeth0SmG7TNB+b/AlHFoBm8TwBt7H+Mn6AQIdo872Vs262UkHgbZN6\n"
+"dEQeRCgiXmlsOVe+MVpf79Xi32MYz1FZ/ueS6tr8sIDhECThIZkq2eulVjAV86N2\n"
+"zQ72Ml1k8rPw4SdK5OFhcXNdXr6CsAol8MmiORKDF0iAZxwtFVc00nBGqQC5rwrN\n"
+"3A8czH5TsvyvrcW0mwV2XOVvZM5kFM1T/X0jF6RQHiGGFBYK4s6JZxSSOhJMFYYh\n"
+"koPEKsuVZdmBJ2yTTdGumHZfG9LDAgMBAAGjgY0wgYowDAYDVR0TAQH/BAIwADAU\n"
+"BgNVHREEDTALgglsb2NhbGhvc3QwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0P\n"
+"AQH/BAUDAwegADAdBgNVHQ4EFgQURXiN5VD5vgqAprhd/37ldGKv4/4wHwYDVR0j\n"
+"BBgwFoAU8MUzmkotjSmVa5r1ejMkMQ6BiZYwDQYJKoZIhvcNAQELBQADggEBABSU\n"
+"cmMX0nGeg43itPnLjSTIUuYEamRhfsFDwgRYQn5w+BcFG1p0scBRxLAShUEb9A2A\n"
+"oEJV4rQDpCn9bcMrMHhTCR5sOlLh/2o9BROjK0+DjQLDkooQK5xa+1GYEiy6QYCx\n"
+"QjdCCnMhHh24oP2/vUggRKhevvD2QQFKcCDT6n13RFYm+HX82gIh6SAtRs0oahY5\n"
+"k9CM9TYRPzXy+tQqhZisJzc8BLTW/XA97kAJW6+hUhPir7AYR6BKJhNeIxcN/yMy\n"
+"jsHzWDLezip/8q+kzw658V5e40hne7ZaJycGUaUdLVnJcpNtBgGE82TRS/XZSQKF\n"
+"fpy8FLGcJynqlIOzdKs=\n"
+"-----END CERTIFICATE-----\n"
+"-----BEGIN CERTIFICATE-----\n"
+"MIIDATCCAemgAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDEwRDQS0w\n"
+"MCIYDzIwMTQwNDA5MDgwMjM0WhgPOTk5OTEyMzEyMzU5NTlaMA8xDTALBgNVBAMT\n"
+"BENBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZq3sA+mjFadII\n"
+"EMDHfj1fYh+UOUSa8c814E9NfCdYZ9Z11BmPpBeR5mXV12j1DKjkTlqTUL7s4lVR\n"
+"RKfyAdCpQIfeXHDeTYYUq2uBnbi5YMG5Y+WbCiYacgRU3IypYrSzaeh1mY7GiEFe\n"
+"U/NaImHLCf+TdAvTJ3Fo0QPe5QN2Lrv6l//cqOv7enZ91KRWxClDMM6EAr+C/7dk\n"
+"rOTXRrCuH/e/KVBXEJ/YeSYPmBIwolGktRrGdsVagdqYArr4dhJ7VThIVRUX1Ijl\n"
+"THCLstI/LuD8WkDccU3ZSdm47f2U43p/+rSO0MiNOXiaskeK56G/9DbJEeETUbzm\n"
+"/B2712MVAgMBAAGjZDBiMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcE\n"
+"ADAdBgNVHQ4EFgQU8MUzmkotjSmVa5r1ejMkMQ6BiZYwHwYDVR0jBBgwFoAUwRHw\n"
+"bXyPosKNNkBiZduEwL5ZCwswDQYJKoZIhvcNAQELBQADggEBACKxBPj9u1t52uIF\n"
+"eQ2JPb8/u+MBttvSLo0qPKXwpc4q8hNclh66dpqGWiF0iSumsKyKU54r6CIF9Ikm\n"
+"t1V1GR9Ll4iTnz3NdIt1w3ns8rSlU5O/dgKysK/1C/5xJWEUYtEO5mnyi4Zaf8FB\n"
+"hKmQ1aWF5dTB81PVAQxyCiFEnH7YumK7pJeIpnCOPIqLZLUHfrTUeL8zONF4i5Sb\n"
+"7taZ8SQ6b7IaioU+NJ50uT2wy34lsyvCWf76Azezv9bggkdNDo/7ktMgsfRrSyM8\n"
+"+MVob5ePGTjKx5yMy/sy2vUkkefwW3RiEss/y2JRb8Hw7nDlA9ttilYKFwGFwRvw\n"
+"KRsXqo8=\n"
+"-----END CERTIFICATE-----\n";
const gnutls_datum_t server_cert = { server_cert_pem,
sizeof(server_cert_pem)
};
static unsigned char server_key_pem[] =
- "-----BEGIN RSA PRIVATE KEY-----\n"
- "MIICXAIBAAKBgQDXulyvowzwLqknVqpTjqjrf4F1TGuYvkrqtx74S8NqxNoNALjq\n"
- "TBMfNhaT3nLvxqResm62ygqIVXWQlu2mV7wMO3YNlx696ex/06ns+4VkoGugSM53\n"
- "fnOcMRP/PciupWBu2baMWppvtr6far2n8KAzJ/W3HZLllpxzUtaf1siOsQIDAQAB\n"
- "AoGAYAFyKkAYC/PYF8e7+X+tsVCHXppp8AoP8TEZuUqOZz/AArVlle/ROrypg5kl\n"
- "8YunrvUdzH9R/KZ7saNZlAPLjZyFG9beL/am6Ai7q7Ma5HMqjGU8kTEGwD7K+lbG\n"
- "iomokKMOl+kkbY/2sI5Czmbm+/PqLXOjtVc5RAsdbgvtmvkCQQDdV5QuU8jap8Hs\n"
- "Eodv/tLJ2z4+SKCV2k/7FXSKWe0vlrq0cl2qZfoTUYRnKRBcWxc9o92DxK44wgPi\n"
- "oMQS+O7fAkEA+YG+K9e60sj1K4NYbMPAbYILbZxORDecvP8lcphvwkOVUqbmxOGh\n"
- "XRmTZUuhBrJhJKKf6u7gf3KWlPl6ShKEbwJASC118cF6nurTjuLf7YKARDjNTEws\n"
- "qZEeQbdWYINAmCMj0RH2P0mvybrsXSOD5UoDAyO7aWuqkHGcCLv6FGG+qwJAOVqq\n"
- "tXdUucl6GjOKKw5geIvRRrQMhb/m5scb+5iw8A4LEEHPgGiBaF5NtJZLALgWfo5n\n"
- "hmC8+G8F0F78znQtPwJBANexu+Tg5KfOnzSILJMo3oXiXhf5PqXIDmbN0BKyCKAQ\n"
- "LfkcEcUbVfmDaHpvzwY9VEaoMOKVLitETXdNSxVpvWM=\n"
- "-----END RSA PRIVATE KEY-----\n";
+"-----BEGIN RSA PRIVATE KEY-----\n"
+"MIIEpAIBAAKCAQEA1374LDFlxzX94lGhKGUjc7WWa+vlHQZKFIW3ViQ0fhsEfhh3\n"
+"52GmB7Lqm2zRJf0BSPvCXrYdEphu0zQfm/wJRxaAZvE8Abex/jJ+gECHaPO9lbNu\n"
+"tlJB4G2TenREHkQoIl5pbDlXvjFaX+/V4t9jGM9RWf7nkura/LCA4RAk4SGZKtnr\n"
+"pVYwFfOjds0O9jJdZPKz8OEnSuThYXFzXV6+grAKJfDJojkSgxdIgGccLRVXNNJw\n"
+"RqkAua8KzdwPHMx+U7L8r63FtJsFdlzlb2TOZBTNU/19IxekUB4hhhQWCuLOiWcU\n"
+"kjoSTBWGIZKDxCrLlWXZgSdsk03Rrph2XxvSwwIDAQABAoIBAB7trDS7ij4DM8MN\n"
+"sDGaAnKS91nZ63I0+uDjKCMG4znOKuDmJh9hVnD4bs+L2KC5JTwSVh09ygJnOlC5\n"
+"xGegzrwTMK6VpOUiNjujh6BkooqfoPAhZpxoReguEeKbWUN2yMPWBQ9xU3SKpMvs\n"
+"IiiDozdmWeiuuxHM/00REA49QO3Gnx2logeB+fcvXXD1UiZV3x0xxSApiJt1sr2r\n"
+"NmqSyGdNUgpmnTP8zbKnDaRe5Wj4tj1TCTLE/HZ0tzdRuwlkIqvcpGg1LMtKm5N8\n"
+"xIWjTGMFwGjG+OF8LGqHLH+28pI3iMB6QqO2YLwOp+WZKImKP3+Dp3s8lCw8t8cm\n"
+"q5/Qc9ECgYEA2xwxm+pFkrFmZNLCakP/6S5AZqpfSBRUlF/uX2pBKO7o6I6aOV9o\n"
+"zq2QWYIZfdyD+9MvAFUQ36sWfTVWpGA34WGtsGtcRRygKKTigpJHvBldaPxiuYuk\n"
+"xbS54nWUdix/JzyQAy22xJXlp4XJvtFJjHhA2td0XA7tfng9n8jmvEUCgYEA+8cA\n"
+"uFIQFbaZ2y6pnOvlVj8OH0f1hZa9M+3q01fWy1rnDAsLrIzJy8TZnBtpDwy9lAun\n"
+"Sa6wzu6qeHmF17xwk5U7BCyK2Qj/9KhRLg1mnDebQ/CiLSAaJVnrYFp9Du96fTkN\n"
+"ollvbFiGF92QwPTDf2f1gHZQEPwa+f/ox37ad2cCgYEAwMgXpfUD7cOEMeV2BQV7\n"
+"XnDBXRM97i9lE38sPmtAlYFPD36Yly4pCt+PCBH9181zmtf+nK47wG/Jw7RwXQQD\n"
+"ZpwItBZiArTi/Z/FY9jMoOU4WKznOBVzjjgq7ONDEo6n+Z/BnepUyraQb0q5bNi7\n"
+"e4o6ldHHoU/JCeNFZRbgXHkCgYA6vJU9at+XwS6phHxLQHkTIsivoYD0tlLTX4it\n"
+"30sby8wk8hq6GWomYHkHwxlCSo2bkRBozxkuXV1ll6wSxUJaG7FV6vJFaaUUtYOi\n"
+"w7uRbCOLuQKMlnWjCxQvOUz9g/7GYd39ZvHoi8pUnPrdGPzWpzEN1AwfukCs2/e5\n"
+"Oq3KtwKBgQCkHmDU8h0kOfN28f8ZiyjJemQMNoOGiJqnGexaKvsRd+bt4H+7DsWQ\n"
+"OnyKm/oR0wCCSmFM5aQc6GgzPD7orueKVYHChbY7HLTWKRHNs6Rlk+6hXJvOld0i\n"
+"Cl7KqL2x2ibGMtt4LtSntdzWqa87N7vCWMSTmvd8uLgflBs33xUIiQ==\n"
+"-----END RSA PRIVATE KEY-----\n";
const gnutls_datum_t server_key = { server_key_pem,
sizeof(server_key_pem)
@@ -95,7 +156,9 @@ void doit(void)
gnutls_certificate_credentials_t clientx509cred;
gnutls_session_t client;
int cret = GNUTLS_E_AGAIN;
- gnutls_x509_crt_t crt;
+ gnutls_x509_crt_t *crts;
+ unsigned int crts_size;
+ unsigned i;
gnutls_x509_privkey_t pkey;
/* General init. */
@@ -104,7 +167,8 @@ void doit(void)
if (debug)
gnutls_global_set_log_level(2);
- ret = gnutls_x509_crt_init(&crt);
+ ret = gnutls_x509_crt_list_import2(&crts, &crts_size, &server_cert, GNUTLS_X509_FMT_PEM,
+ GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
if (ret < 0) {
fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
exit(1);
@@ -117,13 +181,6 @@ void doit(void)
}
ret =
- gnutls_x509_crt_import(crt, &server_cert, GNUTLS_X509_FMT_PEM);
- if (ret < 0) {
- fprintf(stderr, "error: %s\n", gnutls_strerror(ret));
- exit(1);
- }
-
- ret =
gnutls_x509_privkey_import(pkey, &server_key,
GNUTLS_X509_FMT_PEM);
if (ret < 0) {
@@ -133,9 +190,11 @@ void doit(void)
/* Init server */
gnutls_certificate_allocate_credentials(&serverx509cred);
- gnutls_certificate_set_x509_key(serverx509cred, &crt, 1, pkey);
+ gnutls_certificate_set_x509_key(serverx509cred, crts, crts_size, pkey);
gnutls_x509_privkey_deinit(pkey);
- gnutls_x509_crt_deinit(crt);
+ for (i=0;i<crts_size;i++)
+ gnutls_x509_crt_deinit(crts[i]);
+ gnutls_free(crts);
gnutls_init(&server, GNUTLS_SERVER);
gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
@@ -148,10 +207,24 @@ void doit(void)
gnutls_transport_set_ptr(server, server);
/* Init client */
- gnutls_certificate_allocate_credentials(&clientx509cred);
- gnutls_init(&client, GNUTLS_CLIENT);
- gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
+ /* Init client */
+ ret = gnutls_certificate_allocate_credentials(&clientx509cred);
+ if (ret < 0)
+ exit(1);
+
+ ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM);
+ if (ret < 0)
+ exit(1);
+
+ ret = gnutls_init(&client, GNUTLS_CLIENT);
+ if (ret < 0)
+ exit(1);
+
+ ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
clientx509cred);
+ if (ret < 0)
+ exit(1);
+
gnutls_priority_set_direct(client, "NORMAL", NULL);
gnutls_transport_set_push_function(client, client_push);
gnutls_transport_set_pull_function(client, client_pull);
@@ -159,6 +232,81 @@ void doit(void)
HANDSHAKE(client, server);
+ /* check the number of certificates received */
+ {
+ unsigned cert_list_size = 0;
+ gnutls_typed_vdata_st data[2];
+ unsigned status;
+
+ memset(data, 0, sizeof(data));
+
+ /* check with wrong hostname */
+ data[0].type = GNUTLS_DT_DNS_HOSTNAME;
+ data[0].data = (void*)"localhost1";
+
+ data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
+ data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER;
+
+ gnutls_certificate_get_peers(client, &cert_list_size);
+ if (cert_list_size < 2) {
+ fprintf(stderr, "received a certificate list of %d!\n", cert_list_size);
+ exit(1);
+ }
+
+ ret = gnutls_certificate_verify_peers(client, data, 2, &status);
+ if (ret < 0) {
+ fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (status == 0) {
+ fprintf(stderr, "should not have accepted!\n");
+ exit(1);
+ }
+
+ /* check with wrong purpose */
+ data[0].type = GNUTLS_DT_DNS_HOSTNAME;
+ data[0].data = (void*)"localhost";
+
+ data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
+ data[1].data = (void*)GNUTLS_KP_TLS_WWW_CLIENT;
+
+ gnutls_certificate_get_peers(client, &cert_list_size);
+ if (cert_list_size < 2) {
+ fprintf(stderr, "received a certificate list of %d!\n", cert_list_size);
+ exit(1);
+ }
+
+ ret = gnutls_certificate_verify_peers(client, data, 2, &status);
+ if (ret < 0) {
+ fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (status == 0) {
+ fprintf(stderr, "should not have accepted!\n");
+ exit(1);
+ }
+
+ /* check with correct purpose */
+ data[0].type = GNUTLS_DT_DNS_HOSTNAME;
+ data[0].data = (void*)"localhost";
+
+ data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
+ data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER;
+
+ ret = gnutls_certificate_verify_peers(client, data, 2, &status);
+ if (ret < 0) {
+ fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret));
+ exit(1);
+ }
+
+ if (status != 0) {
+ fprintf(stderr, "could not verify certificate: %.4x\n", status);
+ exit(1);
+ }
+ }
+
gnutls_bye(client, GNUTLS_SHUT_RDWR);
gnutls_bye(server, GNUTLS_SHUT_RDWR);
diff --git a/tests/mini-x509.c b/tests/mini-x509.c
index 3bb3908b4b..c4240fdb7c 100644
--- a/tests/mini-x509.c
+++ b/tests/mini-x509.c
@@ -164,6 +164,7 @@ void doit(void)
gnutls_certificate_set_x509_key_mem(serverx509cred,
&server_cert, &server_key,
GNUTLS_X509_FMT_PEM);
+
gnutls_init(&server, GNUTLS_SERVER);
gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
serverx509cred);
@@ -206,15 +207,24 @@ void doit(void)
/* check the number of certificates received */
{
unsigned cert_list_size = 0;
+ gnutls_typed_vdata_st data[2];
unsigned status;
+ memset(data, 0, sizeof(data));
+
+ data[0].type = GNUTLS_DT_DNS_HOSTNAME;
+ data[0].data = (void*)"localhost1";
+
+ data[1].type = GNUTLS_DT_KEY_PURPOSE_OID;
+ data[1].data = (void*)GNUTLS_KP_TLS_WWW_SERVER;
+
gnutls_certificate_get_peers(client, &cert_list_size);
if (cert_list_size < 2) {
fprintf(stderr, "received a certificate list of %d!\n", cert_list_size);
exit(1);
}
- ret = gnutls_certificate_verify_peers4(client, "localhost1", GNUTLS_KP_TLS_WWW_SERVER, &status);
+ ret = gnutls_certificate_verify_peers(client, data, 2, &status);
if (ret < 0) {
fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret));
exit(1);
@@ -225,7 +235,10 @@ void doit(void)
exit(1);
}
- ret = gnutls_certificate_verify_peers4(client, "localhost", GNUTLS_KP_TLS_WWW_SERVER, &status);
+ data[0].type = GNUTLS_DT_DNS_HOSTNAME;
+ data[0].data = (void*)"localhost";
+
+ ret = gnutls_certificate_verify_peers(client, data, 2, &status);
if (ret < 0) {
fprintf(stderr, "could not verify certificate: %s\n", gnutls_strerror(ret));
exit(1);