summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2003-02-07 09:06:51 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2003-02-07 09:06:51 +0000
commit31f922d91c510ba6c7560751309d279c0531f64e (patch)
treef91a322f9958c6abe47d7a6ed42a193065c8b406
parent383d3b421c8dec95a48bcd0638601aaad4ff7b5c (diff)
downloadgnutls-31f922d91c510ba6c7560751309d279c0531f64e.tar.gz
More improvements in the CRL support, and the X.509 backend. Added a function to get some parts of the DN using an OID.
-rw-r--r--THANKS1
-rw-r--r--includes/gnutls/x509.h17
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/gnutls_x509.c423
-rw-r--r--lib/gnutls_x509.h17
-rw-r--r--lib/x509/Makefile.am4
-rw-r--r--lib/x509/common.c459
-rw-r--r--lib/x509/common.h18
-rw-r--r--lib/x509/crl.c40
-rw-r--r--lib/x509/dn.c192
-rw-r--r--lib/x509/dn.h4
-rw-r--r--lib/x509_extensions.c1
-rw-r--r--lib/x509_xml.c1
13 files changed, 728 insertions, 451 deletions
diff --git a/THANKS b/THANKS
index 910f8b371d..ff85d7fc2d 100644
--- a/THANKS
+++ b/THANKS
@@ -11,7 +11,6 @@ Marco d'Itri <md@linux.it>
Mike Siers <mikes@poliac.com>
Marc Huber <Marc.Huber@web.de>
Guillaume Morin <guillaume@morinfr.org>
-Andrew McDonald <andrew@mcdonald.org.uk>
Jeff Johnson <jbj@redhat.com>
David Taylor <dtaylo11@bigpond.net.au>
Ivo Timmermans <ivo@o2w.nl>
diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h
index bc01cc6f55..89b96fa9f3 100644
--- a/includes/gnutls/x509.h
+++ b/includes/gnutls/x509.h
@@ -32,6 +32,19 @@ extern "C" {
#include <gnutls/gnutls.h>
+/* Some OIDs usually found in Distinguished names
+ */
+#define X520_COUNTRY_NAME "2 5 4 6"
+#define X520_ORGANIZATION_NAME "2 5 4 10"
+#define X520_ORGANIZATIONAL_UNIT_NAME "2 5 4 11"
+#define X520_COMMON_NAME "2 5 4 3"
+#define X520_LOCALITY_NAME "2 5 4 7"
+#define X520_STATE_OR_PROVINCE_NAME "2 5 4 8"
+#define LDAP_DC "0 9 2342 19200300 100 1 25"
+#define LDAP_UID "0 9 2342 19200300 100 1 1"
+#define PKCS9_EMAIL "1 2 840 113549 1 9 1"
+
+
struct gnutls_crl_int;
typedef struct gnutls_crl_int* gnutls_crl;
@@ -43,6 +56,10 @@ int gnutls_x509_crl_import(gnutls_crl crl, const gnutls_datum * data,
int gnutls_x509_crl_get_issuer_dn(const gnutls_crl crl,
char *buf, int *sizeof_buf);
+int gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_crl crl, const char* oid,
+ char *buf, int *sizeof_buf);
+
+
int gnutls_x509_crl_get_signed_data(gnutls_crl crl, gnutls_datum *data);
int gnutls_x509_crl_get_signature(gnutls_crl crl, gnutls_datum *data);
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 926db3205d..01531be70b 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -46,7 +46,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c \
libgnutls_la_SOURCES = $(COBJECTS)
-libgnutls_la_LIBADD = $(MINITASN1_OBJECTS) x509/dn.lo x509/crl.lo
+libgnutls_la_LIBADD = $(MINITASN1_OBJECTS) x509/dn.lo x509/crl.lo x509/common.lo
libgnutls_la_LDFLAGS = $(LIBASN1_LINK) $(LIBGCRYPT_LIBS) \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index db092cd791..00c00342d2 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -43,6 +43,7 @@
#include <x509_b64.h>
#include <gnutls_privkey.h>
#include <gnutls_x509.h>
+#include "x509/common.h"
/*
* some x509 certificate parsing functions.
@@ -51,168 +52,6 @@
int gnutls_x509_pkcs7_extract_certificate(const gnutls_datum * pkcs7_struct, int indx, char* certificate, int* certificate_size);
int gnutls_x509_pkcs7_extract_certificate_count(const gnutls_datum * pkcs7_struct);
-typedef struct _oid2string {
- const char * OID;
- const char * DESC;
- const char * ldap_desc;
- int choice;
- int printable;
-} oid2string;
-
-static const oid2string OID2STR[] = {
- {"2 5 4 6", "X520countryName", "C", 0, 1},
- {"2 5 4 10", "X520OrganizationName", "O", 1, 1},
- {"2 5 4 11", "X520OrganizationalUnitName", "OU", 1, 1},
- {"2 5 4 3", "X520CommonName", "CN", 1, 1},
- {"2 5 4 7", "X520LocalityName", "L", 1, 1},
- {"2 5 4 8", "X520StateOrProvinceName", "ST", 1, 1},
- {"0 9 2342 19200300 100 1 25", "dc", "DC", 1, 1}, /* FIXME: CHOICE? */
- {"0 9 2342 19200300 100 1 1", "uid", "UID", 1, 1}, /* FIXME: CHOICE? */
- {"1 2 840 113549 1 9 1", "Pkcs9email", NULL, 0, 1},
- {"1 2 840 113549 1 1 1", "rsaEncryption", NULL, 0, 0},
- {"1 2 840 113549 1 1 2", "md2WithRSAEncryption", NULL, 0, 0},
- {"1 2 840 113549 1 1 4", "md5WithRSAEncryption", NULL, 0, 0},
- {"1 2 840 113549 1 1 5", "sha1WithRSAEncryption", NULL, 0, 0},
- {"1 2 840 10040 4 3", "id-dsa-with-sha1", NULL, 0, 0},
- {"1 2 840 10040 4 1", "id-dsa", NULL, 0, 0},
- {NULL, NULL, NULL, 0, 0}
-};
-
-/* Returns 1 if the data defined by the OID are printable.
- */
-int _gnutls_x509_oid_data_printable( const char* OID) {
-int i = 0;
-
- do {
- if ( strcmp(OID2STR[i].OID, OID)==0)
- return OID2STR[i].printable;
- i++;
- } while( OID2STR[i].OID != NULL);
-
- return 0;
-}
-
-/* Returns 1 if the data defined by the OID are of a choice
- * type.
- */
-int _gnutls_x509_oid_data_choice( const char* OID) {
-int i = 0;
-
- do {
- if ( strcmp(OID2STR[i].OID, OID)==0)
- return OID2STR[i].choice;
- i++;
- } while( OID2STR[i].OID != NULL);
-
- return 0;
-}
-
-const char* _gnutls_x509_oid2string( const char* OID) {
-int i = 0;
-
- do {
- if ( strcmp(OID2STR[i].OID, OID)==0)
- return OID2STR[i].DESC;
- i++;
- } while( OID2STR[i].OID != NULL);
-
- return NULL;
-}
-
-const char* _gnutls_x509_oid2ldap_string( const char* OID) {
-int i = 0;
-
- do {
- if ( strcmp(OID2STR[i].OID, OID)==0)
- return OID2STR[i].ldap_desc;
- i++;
- } while( OID2STR[i].OID != NULL);
-
- return NULL;
-}
-
-/* This function will convert an attribute value, specified by the OID,
- * to a string. The result will be a null terminated string.
- */
-int _gnutls_x509_oid_data2string( const char* OID, void* value,
- int value_size, char * res, int res_size) {
-
-int result;
-char str[1024], tmpname[1024];
-const char* ANAME = NULL;
-int CHOICE = -1, len = -1;
-ASN1_TYPE tmpasn;
-
- if (value==NULL || value_size <=0 || res==NULL || res_size <=0) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- res[0] = 0;
-
- if ( _gnutls_x509_oid_data_printable( OID) == 0) {
- gnutls_assert();
- return GNUTLS_E_INTERNAL_ERROR;
- }
-
- ANAME = _gnutls_x509_oid2string( OID);
- CHOICE = _gnutls_x509_oid_data_choice( OID);
-
- if (ANAME==NULL) {
- gnutls_assert();
- return GNUTLS_E_INTERNAL_ERROR;
- }
-
- _gnutls_str_cpy(str, sizeof(str), "PKIX1.");
- _gnutls_str_cat(str, sizeof(str), ANAME);
- _gnutls_str_cpy( tmpname, sizeof(tmpname), "temp-structure-");
- _gnutls_str_cat( tmpname, sizeof(tmpname), ANAME);
-
- if ((result =
- _gnutls_asn1_create_element(_gnutls_get_pkix(), str,
- &tmpasn, tmpname)) != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- if ((result = asn1_der_decoding(&tmpasn, value, value_size, NULL)) != ASN1_SUCCESS) {
- asn1_delete_structure(&tmpasn);
- return _gnutls_asn2err(result);
- }
-
- /* If this is a choice then we read the choice. Otherwise it
- * is the value;
- */
- len = sizeof( str) - 1;
- if ((result = asn1_read_value(tmpasn, tmpname, str, &len)) != ASN1_SUCCESS) { /* CHOICE */
- asn1_delete_structure(&tmpasn);
- return _gnutls_asn2err(result);
- }
-
- if (CHOICE == 0) {
- str[len] = 0;
- _gnutls_str_cpy(res, res_size, str);
-
- } else { /* CHOICE */
- str[len] = 0;
- _gnutls_str_cat( tmpname, sizeof(tmpname), ".");
- _gnutls_str_cat( tmpname, sizeof(tmpname), str);
-
- len = sizeof(str) - 1;
- if ((result =
- asn1_read_value(tmpasn, tmpname, str,
- &len)) != ASN1_SUCCESS) {
- asn1_delete_structure(&tmpasn);
- return _gnutls_asn2err(result);
- }
- str[len] = 0;
- _gnutls_str_cpy(res, res_size, str);
- }
- asn1_delete_structure(&tmpasn);
-
- return 0;
-
-}
static int _IREAD(ASN1_TYPE rasn, char* name, const char *OID,
gnutls_x509_dn *dn)
@@ -256,22 +95,11 @@ static int _IREAD(ASN1_TYPE rasn, char* name, const char *OID,
return 1;
}
- result = _gnutls_x509_oid_data2string( OID, str, len, res, res_size);
+ result = _gnutls_x509_oid_data2string( OID, str, len, res, &res_size);
if (result < 0) return 1;
else return 0;
}
-/* this function will convert up to 3 digit
- * numbers to characters. Use a character string of MAX_INT_DIGITS, in
- * order to have enough space for it.
- */
-void _gnutls_int2str(unsigned int k, char *data)
-{
- if (k > 999)
- sprintf(data, "%d", 999);
- else
- sprintf(data, "%d", k);
-}
/* This function will attempt to read a Name
* ASN.1 structure. (Taken from Fabio's samples!)
@@ -362,52 +190,6 @@ int _gnutls_x509_get_name_type(ASN1_TYPE rasn, const char *root, gnutls_x509_dn
}
-/* Extracts the time in time_t from the ASN1_TYPE given. When should
- * be something like "crl2.tbsCertList.thisUpdate".
- */
-#define MAX_TIME 1024
-time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *when)
-{
- opaque ttime[MAX_TIME];
- char name[1024];
- time_t ctime = (time_t)-1;
- int len, result;
-
- _gnutls_str_cpy(name, sizeof(name), when);
-
- len = sizeof(ttime) - 1;
- if ((result = asn1_read_value(c2, name, ttime, &len)) < 0) {
- gnutls_assert();
- return (time_t) (-1);
- }
-
- /* CHOICE */
- if (strcmp(ttime, "GeneralizedTime") == 0) {
-
- _gnutls_str_cat(name, sizeof(name), ".generalTime");
- len = sizeof(ttime) - 1;
- result = asn1_read_value(c2, name, ttime, &len);
- if (result == ASN1_SUCCESS)
- ctime = _gnutls_x509_generalTime2gtime(ttime);
- } else { /* UTCTIME */
-
- _gnutls_str_cat(name, sizeof(name), ".utcTime");
- len = sizeof(ttime) - 1;
- result = asn1_read_value(c2, name, ttime, &len);
- if (result == ASN1_SUCCESS)
- ctime = _gnutls_x509_utcTime2gtime(ttime);
- }
-
- /* We cannot handle dates after 2031 in 32 bit machines.
- * a time_t of 64bits has to be used.
- */
-
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return (time_t) (-1);
- }
- return ctime;
-}
int _gnutls_x509_get_version(ASN1_TYPE c2, const char *root)
{
@@ -2014,18 +1796,6 @@ static int _read_dsa_pubkey(opaque * der, int dersize, GNUTLS_MPI * params)
}
-#define PKIX1_RSA_OID "1 2 840 113549 1 1 1"
-#define DSA_OID "1 2 840 10040 4 1"
-
-gnutls_pk_algorithm _gnutls_x509_oid2pk_algorithm( const char* oid)
-{
- if (strcmp( oid, PKIX1_RSA_OID) == 0) /* pkix-1 1 - RSA */
- return GNUTLS_PK_RSA;
- else if (strcmp( oid, DSA_OID) == 0)
- return GNUTLS_PK_DSA;
-
- return GNUTLS_PK_UNKNOWN;
-}
/* Extracts DSA and RSA parameters from a certificate.
*/
@@ -2570,13 +2340,7 @@ int gnutls_x509_extract_certificate_pk_algorithm( const gnutls_datum * cert, int
return _gnutls_asn2err(result);
}
- algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM;
-
- if ( strcmp( str, PKIX1_RSA_OID)==0)
- algo = GNUTLS_PK_RSA;
-
- if ( strcmp( str, DSA_OID)==0)
- algo = GNUTLS_PK_DSA;
+ algo = _gnutls_x509_oid2pk_algorithm( str);
if ( bits==NULL) {
asn1_delete_structure(&c2);
@@ -2745,187 +2509,6 @@ int gnutls_x509_pkcs7_extract_certificate_count(const gnutls_datum * pkcs7_struc
return count;
}
-/* TIME functions
- * Convertions between generalized or UTC time to time_t
- *
- */
-
-/* This is an emulations of the struct tm.
- * Since we do not use libc's functions, we don't need to
- * depend on the libc structure.
- */
-typedef struct fake_tm {
- int tm_mon;
- int tm_year; /* FULL year - ie 1971 */
- int tm_mday;
- int tm_hour;
- int tm_min;
- int tm_sec;
-} fake_tm;
-
-/* The mktime_utc function is due to Russ Allbery (rra@stanford.edu),
- * who placed it under public domain:
- */
-
-/* The number of days in each month.
- */
-static const int MONTHDAYS[] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
- /* Whether a given year is a leap year. */
-#define ISLEAP(year) \
- (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0))
-
-/*
- ** Given a struct tm representing a calendar time in UTC, convert it to
- ** seconds since epoch. Returns (time_t) -1 if the time is not
- ** convertable. Note that this function does not canonicalize the provided
- ** struct tm, nor does it allow out of range values or years before 1970.
- */
-static time_t mktime_utc(const struct fake_tm *tm)
-{
- time_t result = 0;
- int i;
-
-/* We do allow some ill-formed dates, but we don't do anything special
- * with them and our callers really shouldn't pass them to us. Do
- * explicitly disallow the ones that would cause invalid array accesses
- * or other algorithm problems.
- */
- if (tm->tm_mon < 0 || tm->tm_mon > 11 || tm->tm_year < 1970)
- return (time_t) - 1;
-
-/* Convert to a time_t.
- */
- for (i = 1970; i < tm->tm_year; i++)
- result += 365 + ISLEAP(i);
- for (i = 0; i < tm->tm_mon; i++)
- result += MONTHDAYS[i];
- if (tm->tm_mon > 1 && ISLEAP(tm->tm_year))
- result++;
- result = 24 * (result + tm->tm_mday - 1) + tm->tm_hour;
- result = 60 * result + tm->tm_min;
- result = 60 * result + tm->tm_sec;
- return result;
-}
-
-
-/* this one will parse dates of the form:
- * month|day|hour|minute (2 chars each)
- * and year is given. Returns a time_t date.
- */
-static time_t _gnutls_x509_time2gtime(char *ttime, int year)
-{
- char xx[3];
- struct fake_tm etime;
- time_t ret;
-
- if (strlen( ttime) < 8) {
- gnutls_assert();
- return (time_t) -1;
- }
-
- etime.tm_year = year;
-
- /* In order to work with 32 bit
- * time_t.
- */
- if (sizeof (time_t) <= 4 && etime.tm_year >= 2038)
- return (time_t)2145914603; /* 2037-12-31 23:23:23 */
-
- xx[2] = 0;
-
-/* get the month
- */
- memcpy(xx, ttime, 2); /* month */
- etime.tm_mon = atoi(xx) - 1;
- ttime += 2;
-
-/* get the day
- */
- memcpy(xx, ttime, 2); /* day */
- etime.tm_mday = atoi(xx);
- ttime += 2;
-
-/* get the hour
- */
- memcpy(xx, ttime, 2); /* hour */
- etime.tm_hour = atoi(xx);
- ttime += 2;
-
-/* get the minutes
- */
- memcpy(xx, ttime, 2); /* minutes */
- etime.tm_min = atoi(xx);
- ttime += 2;
-
- etime.tm_sec = 0;
-
- ret = mktime_utc(&etime);
-
- return ret;
-}
-
-/* returns a time_t value that contains the given time.
- * The given time is expressed as:
- * YEAR(2)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)
- */
-time_t _gnutls_x509_utcTime2gtime(char *ttime)
-{
- char xx[3];
- int year;
-
- if (strlen( ttime) < 10) {
- gnutls_assert();
- return (time_t) -1;
- }
- xx[2] = 0;
-/* get the year
- */
- memcpy(xx, ttime, 2); /* year */
- year = atoi(xx);
- ttime += 2;
-
- if (year > 49)
- year += 1900;
- else
- year += 2000;
-
- return _gnutls_x509_time2gtime( ttime, year);
-}
-
-/* returns a time_t value that contains the given time.
- * The given time is expressed as:
- * YEAR(4)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)
- */
-time_t _gnutls_x509_generalTime2gtime(char *ttime)
-{
- char xx[5];
- int year;
-
- if (strlen( ttime) < 12) {
- gnutls_assert();
- return (time_t) -1;
- }
-
- if (strchr(ttime, 'Z') == 0) {
- gnutls_assert();
- /* sorry we don't support it yet
- */
- return (time_t)-1;
- }
- xx[4] = 0;
-
-/* get the year
- */
- memcpy(xx, ttime, 4); /* year */
- year = atoi(xx);
- ttime += 4;
-
- return _gnutls_x509_time2gtime( ttime, year);
-
-}
static char* str_escape( char* str, char* buffer, unsigned int buffer_size)
{
diff --git a/lib/gnutls_x509.h b/lib/gnutls_x509.h
index 99309aac81..3a6cf9ee1d 100644
--- a/lib/gnutls_x509.h
+++ b/lib/gnutls_x509.h
@@ -10,10 +10,6 @@ typedef enum ConvFlags {
int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert, ConvFlags flags);
-/* for int2str */
-#define MAX_INT_DIGITS 4
-void _gnutls_int2str(unsigned int k, char *data);
-
#define PEM_CERT_SEP2 "-----BEGIN X509 CERTIFICATE"
#define PEM_CERT_SEP "-----BEGIN CERTIFICATE"
#define PEM_PKCS7_SEP "-----BEGIN PKCS7"
@@ -25,19 +21,6 @@ int _gnutls_check_x509_key_usage( const gnutls_cert * cert, gnutls_kx_algorithm
time_t gnutls_x509_extract_certificate_activation_time( const gnutls_datum*);
time_t gnutls_x509_extract_certificate_expiration_time( const gnutls_datum*);
-time_t _gnutls_x509_utcTime2gtime(char *ttime);
-time_t _gnutls_x509_generalTime2gtime(char *ttime);
-
-int _gnutls_x509_oid_data2string( const char* OID, void* value,
- int value_size, char * res, int res_size);
-
-const char* _gnutls_x509_oid2string( const char* OID);
-const char* _gnutls_x509_oid2ldap_string( const char* OID);
-
-int _gnutls_x509_oid_data_printable( const char* OID);
-gnutls_pk_algorithm _gnutls_x509_oid2pk_algorithm( const char* oid);
-
-time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *when);
int gnutls_x509_extract_certificate_subject_alt_name( const gnutls_datum*, int seq, char*, int*);
int gnutls_x509_extract_certificate_dn( const gnutls_datum*, gnutls_x509_dn*);
diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am
index d6fbd8eea8..3c126a866a 100644
--- a/lib/x509/Makefile.am
+++ b/lib/x509/Makefile.am
@@ -1,8 +1,8 @@
INCLUDES = -I../ -I../minitasn1/
-EXTRA_DIST = crl.h dn.h
+EXTRA_DIST = crl.h dn.h common.h
noinst_LTLIBRARIES = libx509.la
-libx509_la_SOURCES = crl.c dn.c
+libx509_la_SOURCES = crl.c dn.c common.c
diff --git a/lib/x509/common.c b/lib/x509/common.c
new file mode 100644
index 0000000000..06ecf9ad67
--- /dev/null
+++ b/lib/x509/common.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2003 Nikos Mavroyanopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library 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 2.1 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 library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <libtasn1.h>
+#include <gnutls_int.h>
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <gnutls_str.h>
+#include <gnutls_x509.h>
+#include <gnutls_num.h>
+#include <common.h>
+
+typedef struct _oid2string {
+ const char * OID;
+ const char * DESC;
+ const char * ldap_desc;
+ int choice;
+ int printable;
+} oid2string;
+
+static const oid2string OID2STR[] = {
+ {"2 5 4 6", "X520countryName", "C", 0, 1},
+ {"2 5 4 10", "X520OrganizationName", "O", 1, 1},
+ {"2 5 4 11", "X520OrganizationalUnitName", "OU", 1, 1},
+ {"2 5 4 3", "X520CommonName", "CN", 1, 1},
+ {"2 5 4 7", "X520LocalityName", "L", 1, 1},
+ {"2 5 4 8", "X520StateOrProvinceName", "ST", 1, 1},
+ {"0 9 2342 19200300 100 1 25", "dc", "DC", 1, 1}, /* FIXME: CHOICE? */
+ {"0 9 2342 19200300 100 1 1", "uid", "UID", 1, 1}, /* FIXME: CHOICE? */
+ {"1 2 840 113549 1 9 1", "Pkcs9email", NULL, 0, 1},
+ {"1 2 840 113549 1 1 1", "rsaEncryption", NULL, 0, 0},
+ {"1 2 840 113549 1 1 2", "md2WithRSAEncryption", NULL, 0, 0},
+ {"1 2 840 113549 1 1 4", "md5WithRSAEncryption", NULL, 0, 0},
+ {"1 2 840 113549 1 1 5", "sha1WithRSAEncryption", NULL, 0, 0},
+ {"1 2 840 10040 4 3", "id-dsa-with-sha1", NULL, 0, 0},
+ {"1 2 840 10040 4 1", "id-dsa", NULL, 0, 0},
+ {NULL, NULL, NULL, 0, 0}
+};
+
+/* Returns 1 if the data defined by the OID are printable.
+ */
+int _gnutls_x509_oid_data_printable( const char* OID) {
+int i = 0;
+
+ do {
+ if ( strcmp(OID2STR[i].OID, OID)==0)
+ return OID2STR[i].printable;
+ i++;
+ } while( OID2STR[i].OID != NULL);
+
+ return 0;
+}
+
+/* Returns 1 if the data defined by the OID are of a choice
+ * type.
+ */
+int _gnutls_x509_oid_data_choice( const char* OID) {
+int i = 0;
+
+ do {
+ if ( strcmp(OID2STR[i].OID, OID)==0)
+ return OID2STR[i].choice;
+ i++;
+ } while( OID2STR[i].OID != NULL);
+
+ return 0;
+}
+
+const char* _gnutls_x509_oid2string( const char* OID) {
+int i = 0;
+
+ do {
+ if ( strcmp(OID2STR[i].OID, OID)==0)
+ return OID2STR[i].DESC;
+ i++;
+ } while( OID2STR[i].OID != NULL);
+
+ return NULL;
+}
+
+const char* _gnutls_x509_oid2ldap_string( const char* OID) {
+int i = 0;
+
+ do {
+ if ( strcmp(OID2STR[i].OID, OID)==0)
+ return OID2STR[i].ldap_desc;
+ i++;
+ } while( OID2STR[i].OID != NULL);
+
+ return NULL;
+}
+
+/* This function will convert an attribute value, specified by the OID,
+ * to a string. The result will be a null terminated string.
+ *
+ * res may be null. This will just return the res_size, needed to
+ * hold the string.
+ */
+int _gnutls_x509_oid_data2string( const char* OID, void* value,
+ int value_size, char * res, int *res_size) {
+
+int result;
+char str[1024], tmpname[1024];
+const char* ANAME = NULL;
+int CHOICE = -1, len = -1;
+ASN1_TYPE tmpasn;
+
+ if (value==NULL || value_size <=0 || res_size == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ res[0] = 0;
+
+ if ( _gnutls_x509_oid_data_printable( OID) == 0) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ ANAME = _gnutls_x509_oid2string( OID);
+ CHOICE = _gnutls_x509_oid_data_choice( OID);
+
+ if (ANAME==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ _gnutls_str_cpy(str, sizeof(str), "PKIX1.");
+ _gnutls_str_cat(str, sizeof(str), ANAME);
+ _gnutls_str_cpy( tmpname, sizeof(tmpname), "temp-structure-");
+ _gnutls_str_cat( tmpname, sizeof(tmpname), ANAME);
+
+ if ((result =
+ _gnutls_asn1_create_element(_gnutls_get_pkix(), str,
+ &tmpasn, tmpname)) != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ if ((result = asn1_der_decoding(&tmpasn, value, value_size, NULL)) != ASN1_SUCCESS) {
+ asn1_delete_structure(&tmpasn);
+ return _gnutls_asn2err(result);
+ }
+
+ /* If this is a choice then we read the choice. Otherwise it
+ * is the value;
+ */
+ len = sizeof( str) - 1;
+ if ((result = asn1_read_value(tmpasn, tmpname, str, &len)) != ASN1_SUCCESS) { /* CHOICE */
+ asn1_delete_structure(&tmpasn);
+ return _gnutls_asn2err(result);
+ }
+
+ if (CHOICE == 0) {
+ str[len] = 0;
+ if (res)
+ _gnutls_str_cpy(res, *res_size, str);
+ *res_size = len;
+
+ } else { /* CHOICE */
+ str[len] = 0;
+ _gnutls_str_cat( tmpname, sizeof(tmpname), ".");
+ _gnutls_str_cat( tmpname, sizeof(tmpname), str);
+
+ len = sizeof(str) - 1;
+ if ((result =
+ asn1_read_value(tmpasn, tmpname, str,
+ &len)) != ASN1_SUCCESS) {
+ asn1_delete_structure(&tmpasn);
+ return _gnutls_asn2err(result);
+ }
+ str[len] = 0;
+
+ if (res)
+ _gnutls_str_cpy(res, *res_size, str);
+ *res_size = len;
+ }
+ asn1_delete_structure(&tmpasn);
+
+ return 0;
+
+}
+
+
+/* this function will convert up to 3 digit
+ * numbers to characters. Use a character string of MAX_INT_DIGITS, in
+ * order to have enough space for it.
+ */
+void _gnutls_int2str(unsigned int k, char *data)
+{
+ if (k > 999)
+ sprintf(data, "%d", 999);
+ else
+ sprintf(data, "%d", k);
+}
+
+
+#define PKIX1_RSA_OID "1 2 840 113549 1 1 1"
+#define DSA_OID "1 2 840 10040 4 1"
+
+gnutls_pk_algorithm _gnutls_x509_oid2pk_algorithm( const char* oid)
+{
+ if (strcmp( oid, PKIX1_RSA_OID) == 0) /* pkix-1 1 - RSA */
+ return GNUTLS_PK_RSA;
+ else if (strcmp( oid, DSA_OID) == 0)
+ return GNUTLS_PK_DSA;
+
+ return GNUTLS_PK_UNKNOWN;
+}
+
+
+/* TIME functions
+ * Convertions between generalized or UTC time to time_t
+ *
+ */
+
+/* This is an emulations of the struct tm.
+ * Since we do not use libc's functions, we don't need to
+ * depend on the libc structure.
+ */
+typedef struct fake_tm {
+ int tm_mon;
+ int tm_year; /* FULL year - ie 1971 */
+ int tm_mday;
+ int tm_hour;
+ int tm_min;
+ int tm_sec;
+} fake_tm;
+
+/* The mktime_utc function is due to Russ Allbery (rra@stanford.edu),
+ * who placed it under public domain:
+ */
+
+/* The number of days in each month.
+ */
+static const int MONTHDAYS[] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+ /* Whether a given year is a leap year. */
+#define ISLEAP(year) \
+ (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0))
+
+/*
+ ** Given a struct tm representing a calendar time in UTC, convert it to
+ ** seconds since epoch. Returns (time_t) -1 if the time is not
+ ** convertable. Note that this function does not canonicalize the provided
+ ** struct tm, nor does it allow out of range values or years before 1970.
+ */
+static time_t mktime_utc(const struct fake_tm *tm)
+{
+ time_t result = 0;
+ int i;
+
+/* We do allow some ill-formed dates, but we don't do anything special
+ * with them and our callers really shouldn't pass them to us. Do
+ * explicitly disallow the ones that would cause invalid array accesses
+ * or other algorithm problems.
+ */
+ if (tm->tm_mon < 0 || tm->tm_mon > 11 || tm->tm_year < 1970)
+ return (time_t) - 1;
+
+/* Convert to a time_t.
+ */
+ for (i = 1970; i < tm->tm_year; i++)
+ result += 365 + ISLEAP(i);
+ for (i = 0; i < tm->tm_mon; i++)
+ result += MONTHDAYS[i];
+ if (tm->tm_mon > 1 && ISLEAP(tm->tm_year))
+ result++;
+ result = 24 * (result + tm->tm_mday - 1) + tm->tm_hour;
+ result = 60 * result + tm->tm_min;
+ result = 60 * result + tm->tm_sec;
+ return result;
+}
+
+
+/* this one will parse dates of the form:
+ * month|day|hour|minute (2 chars each)
+ * and year is given. Returns a time_t date.
+ */
+static time_t _gnutls_x509_time2gtime(char *ttime, int year)
+{
+ char xx[3];
+ struct fake_tm etime;
+ time_t ret;
+
+ if (strlen( ttime) < 8) {
+ gnutls_assert();
+ return (time_t) -1;
+ }
+
+ etime.tm_year = year;
+
+ /* In order to work with 32 bit
+ * time_t.
+ */
+ if (sizeof (time_t) <= 4 && etime.tm_year >= 2038)
+ return (time_t)2145914603; /* 2037-12-31 23:23:23 */
+
+ xx[2] = 0;
+
+/* get the month
+ */
+ memcpy(xx, ttime, 2); /* month */
+ etime.tm_mon = atoi(xx) - 1;
+ ttime += 2;
+
+/* get the day
+ */
+ memcpy(xx, ttime, 2); /* day */
+ etime.tm_mday = atoi(xx);
+ ttime += 2;
+
+/* get the hour
+ */
+ memcpy(xx, ttime, 2); /* hour */
+ etime.tm_hour = atoi(xx);
+ ttime += 2;
+
+/* get the minutes
+ */
+ memcpy(xx, ttime, 2); /* minutes */
+ etime.tm_min = atoi(xx);
+ ttime += 2;
+
+ etime.tm_sec = 0;
+
+ ret = mktime_utc(&etime);
+
+ return ret;
+}
+
+
+/* returns a time_t value that contains the given time.
+ * The given time is expressed as:
+ * YEAR(2)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)
+ */
+time_t _gnutls_x509_utcTime2gtime(char *ttime)
+{
+ char xx[3];
+ int year;
+
+ if (strlen( ttime) < 10) {
+ gnutls_assert();
+ return (time_t) -1;
+ }
+ xx[2] = 0;
+/* get the year
+ */
+ memcpy(xx, ttime, 2); /* year */
+ year = atoi(xx);
+ ttime += 2;
+
+ if (year > 49)
+ year += 1900;
+ else
+ year += 2000;
+
+ return _gnutls_x509_time2gtime( ttime, year);
+}
+
+/* returns a time_t value that contains the given time.
+ * The given time is expressed as:
+ * YEAR(4)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)
+ */
+time_t _gnutls_x509_generalTime2gtime(char *ttime)
+{
+ char xx[5];
+ int year;
+
+ if (strlen( ttime) < 12) {
+ gnutls_assert();
+ return (time_t) -1;
+ }
+
+ if (strchr(ttime, 'Z') == 0) {
+ gnutls_assert();
+ /* sorry we don't support it yet
+ */
+ return (time_t)-1;
+ }
+ xx[4] = 0;
+
+/* get the year
+ */
+ memcpy(xx, ttime, 4); /* year */
+ year = atoi(xx);
+ ttime += 4;
+
+ return _gnutls_x509_time2gtime( ttime, year);
+
+}
+
+/* Extracts the time in time_t from the ASN1_TYPE given. When should
+ * be something like "crl2.tbsCertList.thisUpdate".
+ */
+#define MAX_TIME 1024
+time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *when)
+{
+ opaque ttime[MAX_TIME];
+ char name[1024];
+ time_t ctime = (time_t)-1;
+ int len, result;
+
+ _gnutls_str_cpy(name, sizeof(name), when);
+
+ len = sizeof(ttime) - 1;
+ if ((result = asn1_read_value(c2, name, ttime, &len)) < 0) {
+ gnutls_assert();
+ return (time_t) (-1);
+ }
+
+ /* CHOICE */
+ if (strcmp(ttime, "GeneralizedTime") == 0) {
+
+ _gnutls_str_cat(name, sizeof(name), ".generalTime");
+ len = sizeof(ttime) - 1;
+ result = asn1_read_value(c2, name, ttime, &len);
+ if (result == ASN1_SUCCESS)
+ ctime = _gnutls_x509_generalTime2gtime(ttime);
+ } else { /* UTCTIME */
+
+ _gnutls_str_cat(name, sizeof(name), ".utcTime");
+ len = sizeof(ttime) - 1;
+ result = asn1_read_value(c2, name, ttime, &len);
+ if (result == ASN1_SUCCESS)
+ ctime = _gnutls_x509_utcTime2gtime(ttime);
+ }
+
+ /* We cannot handle dates after 2031 in 32 bit machines.
+ * a time_t of 64bits has to be used.
+ */
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return (time_t) (-1);
+ }
+ return ctime;
+}
diff --git a/lib/x509/common.h b/lib/x509/common.h
new file mode 100644
index 0000000000..7da7d2e372
--- /dev/null
+++ b/lib/x509/common.h
@@ -0,0 +1,18 @@
+/* for int2str */
+#define MAX_INT_DIGITS 4
+void _gnutls_int2str(unsigned int k, char *data);
+
+time_t _gnutls_x509_utcTime2gtime(char *ttime);
+time_t _gnutls_x509_generalTime2gtime(char *ttime);
+
+int _gnutls_x509_oid_data2string( const char* OID, void* value,
+ int value_size, char * res, int *res_size);
+
+const char* _gnutls_x509_oid2string( const char* OID);
+const char* _gnutls_x509_oid2ldap_string( const char* OID);
+
+int _gnutls_x509_oid_data_choice( const char* OID);
+int _gnutls_x509_oid_data_printable( const char* OID);
+gnutls_pk_algorithm _gnutls_x509_oid2pk_algorithm( const char* oid);
+
+time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *when);
diff --git a/lib/x509/crl.c b/lib/x509/crl.c
index 8daf1feb01..aeb08ab441 100644
--- a/lib/x509/crl.c
+++ b/lib/x509/crl.c
@@ -24,7 +24,7 @@
#include <gnutls_datum.h>
#include <gnutls_global.h>
#include <gnutls_errors.h>
-#include <gnutls_x509.h>
+#include <common.h>
#include <x509_b64.h>
#include <crl.h>
#include <dn.h>
@@ -203,12 +203,14 @@ int gnutls_x509_crl_import(gnutls_crl crl, const gnutls_datum * data,
/**
* gnutls_x509_crl_get_issuer_dn - This function returns the CRL's issuer distinguished name
* @crl: should contain a gnutls_crl structure
- * @buf: a pointer to a structure to hold the peer's name
+ * @buf: a pointer to a structure to hold the peer's name (may be null)
* @sizeof_buf: initialy holds the size of 'buf'
*
* This function will copy the name of the CRL issuer in the provided buffer. The name
* will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253.
*
+ * If buf is null then only the size will be filled.
+ *
* Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not long enough, and
* in that case the sizeof_buf will be updated with the required size.
* On success zero is returned.
@@ -217,7 +219,7 @@ int gnutls_x509_crl_import(gnutls_crl crl, const gnutls_datum * data,
int gnutls_x509_crl_get_issuer_dn(gnutls_crl crl, char *buf,
int *sizeof_buf)
{
- if (buf == NULL || sizeof_buf == 0 || crl == NULL) {
+ if (sizeof_buf == 0 || crl == NULL) {
return GNUTLS_E_INVALID_REQUEST;
}
@@ -228,6 +230,38 @@ int gnutls_x509_crl_get_issuer_dn(gnutls_crl crl, char *buf,
}
/**
+ * gnutls_x509_crl_get_issuer_dn_by_oid - This function returns the CRL's issuer distinguished name
+ * @crl: should contain a gnutls_crl structure
+ * @oid: holds an Object Identified in null terminated string
+ * @buf: a pointer to a structure to hold the peer's name (may be null)
+ * @sizeof_buf: initialy holds the size of 'buf'
+ *
+ * This function will extract the part of the name of the CRL issuer specified
+ * by the given OID. The output will be encoded as described in RFC2253.
+ *
+ * Some helper macros with popular OIDs can be found in gnutls/x509.h
+ *
+ * If buf is null then only the size will be filled.
+ *
+ * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the provided buffer is not long enough, and
+ * in that case the sizeof_buf will be updated with the required size.
+ * On success zero is returned.
+ *
+ **/
+int gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_crl crl, const char* oid, char *buf,
+ int *sizeof_buf)
+{
+ if (sizeof_buf == 0 || crl == NULL) {
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ return _gnutls_x509_parse_dn_oid( crl->crl, "crl2.tbsCertList.issuer.rdnSequence", oid,
+ buf, sizeof_buf);
+
+
+}
+
+/**
* gnutls_x509_crl_get_signed_data - This function returns the CRL's signed portion
* @crl: should contain a gnutls_crl structure
* @data: a datum which points to the signed data
diff --git a/lib/x509/dn.c b/lib/x509/dn.c
index bfe2d9ab6f..779229cd5c 100644
--- a/lib/x509/dn.c
+++ b/lib/x509/dn.c
@@ -25,10 +25,14 @@
#include <gnutls_global.h>
#include <gnutls_errors.h>
#include <gnutls_str.h>
-#include <gnutls_x509.h>
+#include <common.h>
#include <gnutls_num.h>
#include <dn.h>
+/* This file includes all the required to parse an X.509 Distriguished
+ * Name (you need a parser just to read a name in the X.509 protoocols!!!)
+ */
+
/* converts all spaces to dots. Used to convert the
* OIDs returned by libtasn1 to the dotted OID format.
*/
@@ -107,7 +111,7 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
int first = 0;
int len, printable;
- if (buf == NULL || *sizeof_buf == 0) {
+ if (*sizeof_buf == 0) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
@@ -231,10 +235,11 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
if (printable==1) {
char string[256];
+ int sizeof_string = sizeof(string);
STR_APPEND(ldap_desc);
STR_APPEND("=");
- if ( (result=_gnutls_x509_oid_data2string( oid, value, len, string, sizeof(string))) < 0) {
+ if ( (result=_gnutls_x509_oid_data2string( oid, value, len, string, &sizeof_string)) < 0) {
gnutls_assert();
goto cleanup;
}
@@ -253,19 +258,192 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
} while (1);
- if (out_str.length >= *sizeof_buf) {
+ if (out_str.length >= (unsigned int)*sizeof_buf) {
gnutls_assert();
*sizeof_buf = out_str.length;
result = GNUTLS_E_SHORT_MEMORY_BUFFER;
goto cleanup;
}
- memcpy(buf, out_str.data, out_str.length);
- buf[out_str.length] = 0;
+ if (buf) {
+ memcpy(buf, out_str.data, out_str.length);
+ buf[out_str.length] = 0;
+ }
+ *sizeof_buf = out_str.length;
- return 0;
+ result = 0;
cleanup:
_gnutls_string_clear(&out_str);
return result;
}
+
+/* Parses an X509 DN in the asn1_struct, and searches for the
+ * given OID in the DN.
+ * The output will be encoded in the LDAP way. (#hex for non printable).
+ *
+ * asn1_rdn_name must be a string in the form "crl2.tbsCertificate.issuer.rdnSequence".
+ * That is to point in the rndSequence.
+ */
+int _gnutls_x509_parse_dn_oid(ASN1_TYPE asn1_struct,
+ const char *asn1_rdn_name, const char * given_oid,
+ char *buf,
+ int *sizeof_buf)
+{
+ int k2, k1, result;
+ char tmpbuffer1[64];
+ char tmpbuffer2[64];
+ char tmpbuffer3[64];
+ char counter[MAX_INT_DIGITS];
+ char value[200];
+ char escaped[256];
+ char oid[128];
+ int len, printable;
+
+ if (*sizeof_buf == 0) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ buf[0] = 0;
+
+ k1 = 0;
+ do {
+
+ k1++;
+ /* create a string like "crl2.tbsCertList.issuer.rdnSequence.?1"
+ */
+ _gnutls_int2str(k1, counter);
+ _gnutls_str_cpy(tmpbuffer1, sizeof(tmpbuffer1),
+ asn1_rdn_name);
+ _gnutls_str_cat(tmpbuffer1, sizeof(tmpbuffer1), ".?");
+ _gnutls_str_cat(tmpbuffer1, sizeof(tmpbuffer1), counter);
+
+ len = sizeof(value) - 1;
+ result =
+ asn1_read_value(asn1_struct, tmpbuffer1, value, &len);
+
+ if (result == ASN1_ELEMENT_NOT_FOUND) {
+ gnutls_assert();
+ break;
+ }
+
+ if (result != ASN1_VALUE_NOT_FOUND) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ k2 = 0;
+
+ do { /* Move to the attibute type and values
+ */
+ k2++;
+
+ _gnutls_int2str(k2, counter);
+ _gnutls_str_cpy(tmpbuffer2, sizeof(tmpbuffer2),
+ tmpbuffer1);
+ _gnutls_str_cat(tmpbuffer2, sizeof(tmpbuffer2),
+ ".?");
+ _gnutls_str_cat(tmpbuffer2, sizeof(tmpbuffer2),
+ counter);
+
+ /* Try to read the RelativeDistinguishedName attributes.
+ */
+
+ len = sizeof(value) - 1;
+ result =
+ asn1_read_value(asn1_struct, tmpbuffer2, value,
+ &len);
+
+ if (result == ASN1_ELEMENT_NOT_FOUND) {
+ gnutls_assert();
+ break;
+ }
+ if (result != ASN1_VALUE_NOT_FOUND) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ /* Read the OID
+ */
+ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
+ tmpbuffer2);
+ _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
+ ".type");
+
+ len = sizeof(oid) - 1;
+ result =
+ asn1_read_value(asn1_struct, tmpbuffer3, oid,
+ &len);
+
+ if (result == ASN1_ELEMENT_NOT_FOUND)
+ break;
+ else if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if (strcmp( oid, given_oid) == 0) {
+
+ /* Read the Value
+ */
+ _gnutls_str_cpy(tmpbuffer3, sizeof(tmpbuffer3),
+ tmpbuffer2);
+ _gnutls_str_cat(tmpbuffer3, sizeof(tmpbuffer3),
+ ".value");
+
+ len = sizeof(value) - 1;
+ result =
+ asn1_read_value(asn1_struct, tmpbuffer3, value,
+ &len);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+
+ printable = _gnutls_x509_oid_data_printable(oid);
+
+ if (printable==1) {
+ if ( (result=_gnutls_x509_oid_data2string( oid, value, len, buf, sizeof_buf)) < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ return 0;
+ } else {
+ char * res;
+
+ res = _gnutls_bin2hex( value, len, escaped, sizeof(escaped));
+ if (res) {
+ int size = strlen(res) + 1;
+ if ( size > *sizeof_buf) {
+ *sizeof_buf = size;
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+ *sizeof_buf = size - 1;
+ strcpy( buf, res);
+
+ return 0;
+ } else {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+ }
+ }
+ } while (1);
+
+ } while (1);
+
+ gnutls_assert();
+
+ result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+
+ cleanup:
+ return result;
+}
diff --git a/lib/x509/dn.h b/lib/x509/dn.h
index 894b2e90c7..aa48aab0f2 100644
--- a/lib/x509/dn.h
+++ b/lib/x509/dn.h
@@ -1,3 +1,7 @@
int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
const char* asn1_rdn_name, char *buf,
int* sizeof_buf);
+
+int _gnutls_x509_parse_dn_oid(ASN1_TYPE asn1_struct,
+ const char* asn1_rdn_name, const char* oid, char *buf,
+ int* sizeof_buf);
diff --git a/lib/x509_extensions.c b/lib/x509_extensions.c
index 9232a5e741..70bb6fd5f0 100644
--- a/lib/x509_extensions.c
+++ b/lib/x509_extensions.c
@@ -31,6 +31,7 @@
#include "debug.h"
#include <gnutls_str.h>
#include <gnutls_x509.h>
+#include "x509/common.h"
/* This file contains code to parse the X.509 certificate
* extensions. Not all the PKIX extensions are supported.
diff --git a/lib/x509_xml.c b/lib/x509_xml.c
index d7e8cec4e7..4ab99d837d 100644
--- a/lib/x509_xml.c
+++ b/lib/x509_xml.c
@@ -38,6 +38,7 @@
#include <gnutls_errors.h>
#include <gnutls_str.h>
#include <gnutls_x509.h>
+#include "x509/common.h"
static int _gnutls_x509_expand_extensions(ASN1_TYPE* rasn, const char *root);