** libgnutls: gnutls_certificate_set_x509_key_file() and
friends support server name indication. If multiple
certificates are set using these functions the proper one
-will be selected during a handshake, with the limitation
-of a single name per certificate.
+will be selected during a handshake.
** libgnutls: Added AES-256-GCM which was left out from
the previous release. Reported by Benjamin Hof.
x509_b64.h gnutls_v2_compat.h gnutls_datum.h \
gnutls_mpi.h gnutls_pk.h gnutls_record.h \
gnutls_constate.h gnutls_global.h gnutls_sig.h gnutls_mem.h \
- gnutls_session_pack.h gnutls_str.h \
+ gnutls_session_pack.h gnutls_str.h gnutls_str_arrary.h \
gnutls_state.h gnutls_x509.h crypto-backend.h \
gnutls_rsa_export.h gnutls_srp.h auth/srp.h auth/srp_passwd.h \
gnutls_helper.h gnutls_supplemental.h crypto.h random.h system.h\
{
for (i = 0; i < cred->ncerts; i++)
{
-fprintf(stderr, "\n*** name[i]: %s, req: %s\n\n", cred->certs[i].name, server_name);
- if (cred->certs[i].name != NULL && strcasecmp(cred->certs[i].name, server_name) == 0)
+ if (cred->certs[i].names != NULL && _gnutls_str_array_match(cred->certs[i].names, server_name) != 0)
{
/* if requested algorithms are also compatible select it */
gnutls_pk_algorithm pk =
#include "openpgp/openpgp_int.h"
#include <gnutls/abstract.h>
#include <gnutls/compat.h>
+#include <gnutls_str_array.h>
typedef struct {
gnutls_pcert_st * cert_list; /* a certificate chain */
unsigned int cert_list_length; /* its length */
- char* name; /* the name of the first certificate - only 1 allowed*/
+ gnutls_str_array_t names; /* the names in the first certificate */
} certs_st;
/* This structure may be complex, but it's the only way to
cert_auth_info_t info);
int certificate_credential_append_crt_list (gnutls_certificate_credentials_t
- res, const char* name, gnutls_pcert_st* crt, int nr);
+ res, gnutls_str_array_t names,
+ gnutls_pcert_st* crt, int nr);
int certificate_credentials_append_pkey (gnutls_certificate_credentials_t res,
gnutls_privkey_t pkey);
#include <gnutls_state.h>
#include <gnutls_auth.h>
#include <gnutls_x509.h>
+#include <gnutls_str_array.h>
#include "x509/x509_int.h"
#ifdef ENABLE_OPENPGP
#include "openpgp/gnutls_openpgp.h"
gnutls_pcert_deinit (&sc->certs[i].cert_list[j]);
}
gnutls_free (sc->certs[i].cert_list);
- gnutls_free (sc->certs[i].name);
+ _gnutls_str_array_clear (&sc->certs[i].names);
}
gnutls_free (sc->certs);
--- /dev/null
+/*
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef GNUTLS_STR_ARRAY_H
+#define GNUTLS_STR_ARRAY_H
+
+#include <gnutls_int.h>
+
+/* Functionality to allow an array of strings. Strings
+ * are allowed to be added to the list and matched against it.
+ */
+
+typedef struct gnutls_str_array_st
+{
+ char* str;
+ int len;
+ struct gnutls_str_array_st* next;
+} *gnutls_str_array_t;
+
+inline static void _gnutls_str_array_init(gnutls_str_array_t* head)
+{
+ *head = NULL;
+}
+
+inline static void _gnutls_str_array_clear (gnutls_str_array_t *head)
+{
+ gnutls_str_array_t prev, array = *head;
+
+ while(array != NULL)
+ {
+ prev = array;
+ array = prev->next;
+ gnutls_free(prev);
+ }
+ *head = NULL;
+}
+
+inline static int _gnutls_str_array_match (gnutls_str_array_t head, const char* str)
+{
+ gnutls_str_array_t array = head;
+
+ while(array != NULL)
+ {
+ if (strcmp(array->str, str) == 0) return 1;
+ array = array->next;
+ }
+
+ return 0;
+}
+
+inline static void append(gnutls_str_array_t array, const char* str, int len)
+{
+ array->str = ((uint8_t*)array) + sizeof(struct gnutls_str_array_st);
+ memcpy(array->str, str, len);
+ array->str[len] = 0;
+ array->len = len;
+ array->next = NULL;
+}
+
+inline static int _gnutls_str_array_append (gnutls_str_array_t* head, const char* str, int len)
+{
+ gnutls_str_array_t prev, array;
+ if (*head == NULL)
+ {
+ *head = gnutls_malloc(len + 1 + sizeof(struct gnutls_str_array_st));
+ if (*head == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ array = *head;
+ append(array, str, len);
+ }
+ else
+ {
+ array = *head;
+ prev = array;
+ while(array != NULL)
+ {
+ prev = array;
+ array = prev->next;
+ }
+ prev->next = gnutls_malloc(len + 1 + sizeof(struct gnutls_str_array_st));
+
+ array = prev->next;
+
+ if (array == NULL)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ append(array, str, len);
+ }
+
+ return 0;
+}
+
+#endif
#include <gnutls_x509.h>
#include "x509/common.h"
#include "x509/x509_int.h"
+#include <gnutls_str_array.h>
#include "read-file.h"
/*
/* Returns the name of the certificate of a null name
*/
-static void get_x509_name(gnutls_x509_crt_t crt, char* name, size_t max_name_size)
+static int get_x509_name(gnutls_x509_crt_t crt, gnutls_str_array_t *names)
{
size_t max_size;
-int i, ret = 0;
-
- name[0] = 0;
+int i, ret = 0, ret2;
+char name[MAX_CN];
for (i = 0; !(ret < 0); i++)
{
- max_size = max_name_size;
+ max_size = sizeof(name);
- ret = gnutls_x509_crt_get_subject_alt_name(crt, 0, name, &max_size, NULL);
+ ret = gnutls_x509_crt_get_subject_alt_name(crt, i, name, &max_size, NULL);
if (ret == GNUTLS_SAN_DNSNAME)
- return;
+ {
+ ret2 = _gnutls_str_array_append(names, name, max_size);
+ if (ret2 < 0)
+ {
+ _gnutls_str_array_clear(names);
+ return gnutls_assert_val(ret2);
+ }
+ }
}
- max_size = max_name_size;
- gnutls_x509_crt_get_dn_by_oid (crt, OID_X520_COMMON_NAME, 0, 0, name, &max_size);
+ max_size = sizeof(name);
+ ret = gnutls_x509_crt_get_dn_by_oid (crt, OID_X520_COMMON_NAME, 0, 0, name, &max_size);
+ if (ret >= 0)
+ {
+ ret = _gnutls_str_array_append(names, name, max_size);
+ if (ret < 0)
+ {
+ _gnutls_str_array_clear(names);
+ return gnutls_assert_val(ret);
+ }
+ }
+
+ return 0;
}
-static void get_x509_name_raw(gnutls_datum_t *raw, gnutls_x509_crt_fmt_t type, char* name, size_t max_name_size)
+static int get_x509_name_raw(gnutls_datum_t *raw, gnutls_x509_crt_fmt_t type, gnutls_str_array_t *names)
{
int ret;
gnutls_x509_crt_t crt;
- name[0] = 0;
-
ret = gnutls_x509_crt_init (&crt);
if (ret < 0)
{
gnutls_assert ();
- return;
+ return ret;
}
ret = gnutls_x509_crt_import (crt, raw, type);
{
gnutls_assert ();
gnutls_x509_crt_deinit (crt);
- return;
+ return ret;
}
- get_x509_name(crt, name, max_name_size);
+ ret = get_x509_name(crt, names);
gnutls_x509_crt_deinit (crt);
- return;
+ return ret;
}
/* Reads a DER encoded certificate list from memory and stores it to a
gnutls_x509_crt_t crt;
gnutls_pcert_st *ccert;
int ret;
- char name[MAX_CN];
+ gnutls_str_array_t names;
+
+ _gnutls_str_array_init(&names);
ccert = gnutls_malloc (sizeof (*ccert));
if (ccert == NULL)
goto cleanup;
}
- get_x509_name(crt, name, sizeof(name));
+ ret = get_x509_name(crt, &names);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ gnutls_x509_crt_deinit (crt);
+ goto cleanup;
+ }
ret = gnutls_pcert_import_x509 (ccert, crt, 0);
gnutls_x509_crt_deinit (crt);
goto cleanup;
}
- ret = certificate_credential_append_crt_list (res, name, ccert, 1);
+ ret = certificate_credential_append_crt_list (res, names, ccert, 1);
if (ret < 0)
{
gnutls_assert ();
return ret;
cleanup:
+ _gnutls_str_array_clear(&names);
gnutls_free (ccert);
return ret;
}
gnutls_datum_t tmp;
int ret, count, i;
gnutls_pcert_st *certs = NULL;
- char name[MAX_CN];
+ gnutls_str_array_t names;
+
+ _gnutls_str_array_init(&names);
/* move to the certificate
*/
tmp.data = (void*)ptr;
tmp.size = size;
- if (count == 0) get_x509_name_raw(&tmp, GNUTLS_X509_FMT_PEM, name, sizeof(name));
+ if (count == 0)
+ {
+ ret = get_x509_name_raw(&tmp, GNUTLS_X509_FMT_PEM, &names);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+ }
ret = gnutls_pcert_import_x509_raw (&certs[count], &tmp, GNUTLS_X509_FMT_PEM, 0);
if (ret < 0)
}
while (ptr != NULL);
- ret = certificate_credential_append_crt_list (res, name, certs, count);
+ ret = certificate_credential_append_crt_list (res, names, certs, count);
if (ret < 0)
{
gnutls_assert ();
return count;
cleanup:
+ _gnutls_str_array_clear(&names);
for (i=0;i<count;i++)
gnutls_pcert_deinit(&certs[i]);
gnutls_free(certs);
int ret;
gnutls_x509_crt_t crt;
gnutls_pcert_st *ccert;
- char name[MAX_CN];
+ gnutls_str_array_t names;
+
+ _gnutls_str_array_init(&names);
ccert = gnutls_malloc (sizeof (*ccert));
if (ccert == NULL)
if (ret < 0)
{
gnutls_assert ();
- gnutls_free (ccert);
- return ret;
+ goto cleanup;
}
ret = gnutls_x509_crt_import_pkcs11_url (crt, url, 0);
if (ret < 0)
{
gnutls_assert ();
- gnutls_free (ccert);
gnutls_x509_crt_deinit (crt);
- return ret;
+ goto cleanup;
}
- get_x509_name(crt, name, sizeof(name));
+ ret = get_x509_name(crt, &names);
+ if (ret < 0)
+ {
+ gnutls_assert ();
+ gnutls_x509_crt_deinit (crt);
+ goto cleanup;
+ }
ret = gnutls_pcert_import_x509 (ccert, crt, 0);
gnutls_x509_crt_deinit (crt);
if (ret < 0)
{
gnutls_assert ();
- gnutls_free (ccert);
- return ret;
+ goto cleanup;
}
- ret = certificate_credential_append_crt_list (res, name, ccert, 1);
+ ret = certificate_credential_append_crt_list (res, names, ccert, 1);
if (ret < 0)
{
gnutls_assert ();
- gnutls_free (ccert);
- return ret;
+ goto cleanup;
}
return 0;
+cleanup:
+ _gnutls_str_array_clear(&names);
+ gnutls_free (ccert);
+ return ret;
}
#endif /* ENABLE_PKCS11 */
int
certificate_credential_append_crt_list (gnutls_certificate_credentials_t res,
- const char* name, gnutls_pcert_st * crt, int nr)
+ gnutls_str_array_t names, gnutls_pcert_st * crt, int nr)
{
int ret;
res->certs[res->ncerts].cert_list = crt;
res->certs[res->ncerts].cert_list_length = nr;
- if (name[0] != 0)
- res->certs[res->ncerts].name = gnutls_strdup(name);
- else
- res->certs[res->ncerts].name = NULL;
+ res->certs[res->ncerts].names = names;
return 0;
int ret, i;
gnutls_privkey_t pkey;
gnutls_pcert_st *pcerts = NULL;
- char name[MAX_CN];
+ gnutls_str_array_t names;
+
+ _gnutls_str_array_init(&names);
/* this should be first
*/
return GNUTLS_E_MEMORY_ERROR;
}
- get_x509_name(cert_list[0], name, sizeof(name));
+ ret = get_x509_name(cert_list[0], &names);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
for (i = 0; i < cert_list_size; i++)
{
if (ret < 0)
{
gnutls_assert ();
- return ret;
+ goto cleanup;
}
}
- ret = certificate_credential_append_crt_list (res, name, pcerts, cert_list_size);
+ ret = certificate_credential_append_crt_list (res, names, pcerts, cert_list_size);
if (ret < 0)
{
gnutls_assert ();
- return ret;
+ goto cleanup;
}
res->ncerts++;
}
return 0;
+
+cleanup:
+ _gnutls_str_array_clear(&names);
+ return ret;
}
/**
gnutls_openpgp_crt_t crt,
gnutls_openpgp_privkey_t pkey)
{
- int ret;
+ int ret, ret2, i;
gnutls_privkey_t privkey;
- gnutls_pcert_st *ccert;
+ gnutls_pcert_st *ccert = NULL;
char name[MAX_CN];
- size_t name_size = sizeof(name);
+ size_t max_size;
+ gnutls_str_array_t names;
+ _gnutls_str_array_init(&names);
+
/* this should be first */
ret = gnutls_privkey_init (&privkey);
GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
if (ret < 0)
{
- gnutls_privkey_deinit (privkey);
gnutls_assert ();
- return ret;
+ goto cleanup;
}
- ret = gnutls_openpgp_crt_get_name(crt, 0, name, &name_size);
- if (ret < 0)
- name[0] = 0;
-
ccert = gnutls_calloc (1, sizeof (gnutls_pcert_st));
if (ccert == NULL)
{
gnutls_assert ();
- gnutls_privkey_deinit (privkey);
- return GNUTLS_E_MEMORY_ERROR;
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+
+ max_size = sizeof(name);
+ ret = 0;
+ for (i = 0; !(ret < 0); i++)
+ {
+ ret = gnutls_openpgp_crt_get_name(crt, i, name, &max_size);
+ if (ret >= 0)
+ {
+ ret2 = _gnutls_str_array_append(&names, name, max_size);
+ if (ret2 < 0)
+ {
+ gnutls_assert();
+ ret = ret2;
+ goto cleanup;
+ }
+ }
}
ret = gnutls_pcert_import_openpgp (ccert, crt, 0);
if (ret < 0)
{
gnutls_assert ();
- gnutls_free (ccert);
- gnutls_privkey_deinit (privkey);
- return ret;
+ goto cleanup;
}
ret = certificate_credentials_append_pkey (res, privkey);
if (ret >= 0)
- ret = certificate_credential_append_crt_list (res, name, ccert, 1);
+ ret = certificate_credential_append_crt_list (res, names, ccert, 1);
if (ret < 0)
{
gnutls_assert ();
- gnutls_free (ccert);
- gnutls_privkey_deinit (privkey);
- return ret;
+ goto cleanup;
}
res->ncerts++;
/* FIXME: Check if the keys match. */
return 0;
+
+cleanup:
+ gnutls_privkey_deinit (privkey);
+ gnutls_free (ccert);
+ _gnutls_str_array_clear(&names);
+ return ret;
}
/*-