It checks whether the list to be imported is properly sorted.
using gnutls_certificate_set_x509_key*(), is sorted
according to TLS specification (from subject to issuer).
+** libgnutls: Added GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED flag for
+gnutls_x509_crt_list_import. It checks whether the list to be
+imported is properly sorted.
+
** API and ABI modifications:
-No changes since last version.
+GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED: New element in gnutls_certificate_import_flags
* Version 3.0.0 (released 2011-07-29)
int _gnutls_hostname_compare (const char *certname, size_t certnamesize,
const char *hostname, int level);
#define MAX_CN 256
+#define MAX_DN 1024
#define BUFFER_APPEND(b, x, s) { \
ret = _gnutls_buffer_append_data(b, x, s); \
static int check_if_sorted(gnutls_pcert_st * crt, int nr)
{
gnutls_x509_crt_t x509;
-char prev_dn[MAX_CN];
-char dn[MAX_CN];
+char prev_dn[MAX_DN];
+char dn[MAX_DN];
size_t prev_dn_size, dn_size;
int i, ret;
* @GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED: Fail if the
* certificates in the buffer are more than the space allocated for
* certificates. The error code will be %GNUTLS_E_SHORT_MEMORY_BUFFER.
+ * @GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED: Fail if the certificates
+ * in the buffer are not ordered starting from subject to issuer.
+ * The error code will be %GNUTLS_E_CERTIFICATE_LIST_UNSORTED.
*
* Enumeration of different certificate import flags.
*/
typedef enum gnutls_certificate_import_flags
{
- GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED = 1
+ GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED = 1,
+ GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED = 2
} gnutls_certificate_import_flags;
int gnutls_x509_crt_init (gnutls_x509_crt_t * cert);
return 0;
}
+static int check_if_sorted(gnutls_x509_crt_t * crt, int nr)
+{
+char prev_dn[MAX_DN];
+char dn[MAX_DN];
+size_t prev_dn_size, dn_size;
+int i, ret;
+
+ /* check if the X.509 list is ordered */
+ if (nr > 1)
+ {
+
+ for (i=0;i<nr;i++)
+ {
+ if (i>0)
+ {
+ dn_size = sizeof(dn);
+ ret = gnutls_x509_crt_get_dn(crt[i], dn, &dn_size);
+ if (ret < 0)
+ {
+ ret = gnutls_assert_val(ret);
+ goto cleanup;
+ }
+
+ if (dn_size != prev_dn_size || memcmp(dn, prev_dn, dn_size) != 0)
+ {
+ ret = gnutls_assert_val(GNUTLS_E_CERTIFICATE_LIST_UNSORTED);
+ goto cleanup;
+ }
+ }
+
+ prev_dn_size = sizeof(prev_dn);
+ ret = gnutls_x509_crt_get_issuer_dn(crt[i], prev_dn, &prev_dn_size);
+ if (ret < 0)
+ {
+ ret = gnutls_assert_val(ret);
+ goto cleanup;
+ }
+ }
+ }
+
+ ret = 0;
+
+cleanup:
+ return ret;
+}
+
/**
* gnutls_x509_crt_list_import:
* to the native gnutls_x509_crt_t format. The output will be stored
* in @certs. They will be automatically initialized.
*
+ * The flag %GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED will cause
+ * import to fail if the certificates in the provided buffer are more
+ * than the available structures. The %GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED
+ * flag will cause the function to fail if the provided list is not
+ * sorted from subject to issuer.
+ *
* If the Certificate is PEM encoded it should have a header of "X509
* CERTIFICATE", or "CERTIFICATE".
*
*cert_max = count;
+ if (flags & GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED)
+ {
+ ret = check_if_sorted(certs, *cert_max);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto error;
+ }
+ }
+
if (nocopy == 0)
return count;
else
"+62SbuYGpFYsouHAUyfI8pUwCwYJKoZIhvcNAQEFA4GBALujmBJVZnvaTXr9cFRJ\n"
"jpfc/3X7sLUsMvumcDE01ls/cG5mIatmiyEU9qI3jbgUf82z23ON/acwJf875D3/\n"
"U7jyOsBJ44SEQITbin2yUeJMIm1tievvdNXBDfW95AM507ShzP12sfiJkJfjjdhy\n"
- "dc8Siq5JojruiMizAf0pA7in\n" "-----END CERTIFICATE-----\n";
+ "dc8Siq5JojruiMizAf0pA7in\n" "-----END CERTIFICATE-----\n"
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIB5zCCAVKgAwIBAgIERiYdJzALBgkqhkiG9w0BAQUwGTEXMBUGA1UEAxMOR251\n"
+ "VExTIHRlc3QgQ0EwHhcNMDcwNDE4MTMyOTExWhcNMDgwNDE3MTMyOTExWjAZMRcw\n"
+ "FQYDVQQDEw5HbnVUTFMgdGVzdCBDQTCBnDALBgkqhkiG9w0BAQEDgYwAMIGIAoGA\n"
+ "vuyYeh1vfmslnuggeEKgZAVmQ5ltSdUY7H25WGSygKMUYZ0KT74v8C780qtcNt9T\n"
+ "7EPH/N6RvB4BprdssgcQLsthR3XKA84jbjjxNCcaGs33lvOz8A1nf8p3hD+cKfRi\n"
+ "kfYSW2JazLrtCC4yRCas/SPOUxu78of+3HiTfFm/oXUCAwEAAaNDMEEwDwYDVR0T\n"
+ "AQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwQAMB0GA1UdDgQWBBTpPBz7rZJu5gak\n"
+ "Viyi4cBTJ8jylTALBgkqhkiG9w0BAQUDgYEAiaIRqGfp1jPpNeVhABK60SU0KIAy\n"
+ "njuu7kHq5peUgYn8Jd9zNzExBOEp1VOipGsf6G66oQAhDFp2o8zkz7ZH71zR4HEW\n"
+ "KoX6n5Emn6DvcEH/9pAhnGxNHJAoS7czTKv/JDZJhkqHxyrE1fuLsg5Qv25DTw7+\n"
+ "PfqUpIhz5Bbm7J4=\n" "-----END CERTIFICATE-----\n";
const gnutls_datum_t cert = { cert_pem, sizeof (cert_pem) };
static unsigned char key_pem[] =
sizeof (server_key_pem)
};
-
+#define LIST_SIZE 3
void
doit (void)
{
gnutls_certificate_credentials_t x509_cred;
- int ret;
- gnutls_x509_crt_t crt, issuer;
+ int ret, i;
+ gnutls_x509_crt_t issuer;
+ gnutls_x509_crt_t list[LIST_SIZE];
char dn[128];
size_t dn_size;
+ unsigned int list_size;
/* this must be called once in the program
*/
GNUTLS_X509_FMT_PEM);
/* test for gnutls_certificate_get_issuer() */
- gnutls_x509_crt_init(&crt);
- ret = gnutls_x509_crt_import(crt, &cert, GNUTLS_X509_FMT_PEM);
- if (ret < 0)
- fail("gnutls_x509_crt_import");
- ret = gnutls_certificate_get_issuer(x509_cred, crt, &issuer, 0);
+ list_size = LIST_SIZE;
+ ret = gnutls_x509_crt_list_import(list, &list_size, &cert, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
+ if (ret < 0)
+ fail("gnutls_x509_crt_list_import");
+
+ ret = gnutls_certificate_get_issuer(x509_cred, list[0], &issuer, 0);
if (ret < 0)
fail("gnutls_certificate_get_isser");
fail("gnutls_certificate_get_isser");
fprintf(stderr, "Issuer's DN: %s\n", dn);
- gnutls_x509_crt_deinit(crt);
+ for (i=0;i<list_size;i++)
+ gnutls_x509_crt_deinit(list[i]);
gnutls_certificate_free_credentials(x509_cred);
success("success");