return _gnutls_asn2err(result);
}
+ result = gnutls_subject_alt_names_init(&tmp->san);
+ if (result < 0) {
+ gnutls_assert();
+ asn1_delete_structure(&tmp->cert);
+ gnutls_free(tmp);
+ return result;
+ }
+ result = gnutls_subject_alt_names_init(&tmp->ian);
+ if (result < 0) {
+ gnutls_assert();
+ asn1_delete_structure(&tmp->cert);
+ gnutls_free(tmp);
+ gnutls_subject_alt_names_deinit(tmp->san);
+ return result;
+ }
+
/* If you add anything here, be sure to check if it has to be added
to gnutls_x509_crt_import as well. */
asn1_delete_structure(&cert->cert);
gnutls_free(cert->raw_dn.data);
gnutls_free(cert->raw_issuer_dn.data);
+ gnutls_subject_alt_names_deinit(cert->san);
+ gnutls_subject_alt_names_deinit(cert->ian);
gnutls_free(cert);
}
+static int cache_alt_names(gnutls_x509_crt_t cert)
+{
+ gnutls_datum_t tmpder = {NULL, 0};
+ int ret;
+
+ /* pre-parse subject alt name */
+ ret = _gnutls_x509_crt_get_extension(cert, "2.5.29.17", 0, &tmpder, NULL);
+ if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ gnutls_free(tmpder.data);
+ return gnutls_assert_val(ret);
+ }
+
+ if (ret >= 0) {
+ ret = gnutls_x509_ext_import_subject_alt_names(&tmpder, cert->san, 0);
+ gnutls_free(tmpder.data);
+ tmpder.data = NULL;
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ }
+
+ ret = _gnutls_x509_crt_get_extension(cert, "2.5.29.18", 0, &tmpder, NULL);
+ if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+ return gnutls_assert_val(ret);
+
+ if (ret >= 0) {
+ ret = gnutls_x509_ext_import_subject_alt_names(&tmpder, cert->ian, 0);
+ gnutls_free(tmpder.data);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ }
+
+ return 0;
+}
+
/**
* gnutls_x509_crt_import:
* @cert: The structure to store the parsed certificate.
cert->expanded = 1;
+ result = cache_alt_names(cert);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
/* Since we do not want to disable any extension
*/
cert->use_extensions = 1;
}
static int
-get_alt_name(gnutls_x509_crt_t cert, const char *extension_id,
+get_alt_name(gnutls_subject_alt_names_t san,
unsigned int seq, uint8_t *alt,
size_t * alt_size, unsigned int *alt_type,
unsigned int *critical, int othername_oid)
{
int ret;
- gnutls_datum_t dnsname = {NULL, 0};
gnutls_datum_t ooid = {NULL, 0};
- gnutls_datum_t res;
- gnutls_subject_alt_names_t sans = NULL;
+ gnutls_datum_t oname;
+ gnutls_datum_t virt = {NULL, 0};
unsigned int type;
- if (cert == NULL) {
+ if (san == NULL) {
gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
if (alt == NULL)
*alt_size = 0;
- if ((ret =
- _gnutls_x509_crt_get_extension(cert, extension_id, 0,
- &dnsname, critical)) < 0) {
- return ret;
- }
-
- if (dnsname.size == 0 || dnsname.data == NULL) {
- gnutls_assert();
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- ret = gnutls_subject_alt_names_init(&sans);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- ret = gnutls_x509_ext_import_subject_alt_names(&dnsname, sans, 0);
- if (ret < 0) {
- gnutls_assert();
- goto cleanup;
- }
-
- ret = gnutls_subject_alt_names_get(sans, seq, &type, &res, &ooid);
+ ret = gnutls_subject_alt_names_get(san, seq, &type, &oname, &ooid);
if (ret < 0) {
gnutls_assert();
goto cleanup;
ret = _gnutls_copy_string(&ooid, alt, alt_size);
} else {
if (is_type_printable(type)) {
- ret = _gnutls_copy_string(&res, alt, alt_size);
+ ret = _gnutls_copy_string(&oname, alt, alt_size);
} else {
- ret = _gnutls_copy_data(&res, alt, alt_size);
+ ret = _gnutls_copy_data(&oname, alt, alt_size);
}
}
ret = type;
cleanup:
- gnutls_free(dnsname.data);
- if (sans != NULL)
- gnutls_subject_alt_names_deinit(sans);
+ gnutls_free(virt.data);
return ret;
}
size_t * san_size,
unsigned int *critical)
{
- return get_alt_name(cert, "2.5.29.17", seq, san, san_size, NULL,
+ return get_alt_name(cert->san, seq, san, san_size, NULL,
critical, 0);
}
size_t * ian_size,
unsigned int *critical)
{
- return get_alt_name(cert, "2.5.29.18", seq, ian, ian_size, NULL,
+ return get_alt_name(cert->ian, seq, ian, ian_size, NULL,
critical, 0);
}
unsigned int *san_type,
unsigned int *critical)
{
- return get_alt_name(cert, "2.5.29.17", seq, san, san_size,
+ return get_alt_name(cert->san, seq, san, san_size,
san_type, critical, 0);
}
unsigned int *ian_type,
unsigned int *critical)
{
- return get_alt_name(cert, "2.5.29.18", seq, ian, ian_size,
+ return get_alt_name(cert->ian, seq, ian, ian_size,
ian_type, critical, 0);
}
unsigned int seq,
void *oid, size_t * oid_size)
{
- return get_alt_name(cert, "2.5.29.17", seq, oid, oid_size, NULL,
+ return get_alt_name(cert->san, seq, oid, oid_size, NULL,
NULL, 1);
}
unsigned int seq,
void *ret, size_t * ret_size)
{
- return get_alt_name(cert, "2.5.29.18", seq, ret, ret_size, NULL,
+ return get_alt_name(cert->ian, seq, ret, ret_size, NULL,
NULL, 1);
}