diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2005-03-28 20:45:13 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2005-03-28 20:45:13 +0000 |
commit | d02e7a1d22f73ce589508394390d0d1493952820 (patch) | |
tree | 0abe3ffb6e7fda09112abe380822f1912122e13a | |
parent | a4fa1abebdd9b2310005972befa2a81d0e82ff8e (diff) | |
download | gnutls-d02e7a1d22f73ce589508394390d0d1493952820.tar.gz |
Added the function gnutls_x509_crt_list_import(). This is a convinience function to import many certificates with a single call.
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | includes/gnutls/x509.h | 2 | ||||
-rw-r--r-- | lib/x509/x509.c | 91 | ||||
-rw-r--r-- | src/cli.c | 13 |
4 files changed, 102 insertions, 5 deletions
@@ -23,6 +23,7 @@ See the end for copying conditions. - Eliminated some memory leaks in DHE and RSA-EXPORT cipher suites. Reported by Yoann Vandoorselaere <yoann@prelude-ids.org>. - Added the functions: + gnutls_x509_crt_list_import(), gnutls_x509_crq_get_attribute_by_oid(), gnutls_x509_crq_set_attribute_by_oid() and gnutls_x509_crt_set_extension_by_oid(). diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h index a082e753b3..b89a44ef64 100644 --- a/includes/gnutls/x509.h +++ b/includes/gnutls/x509.h @@ -83,6 +83,8 @@ int gnutls_x509_crt_init(gnutls_x509_crt_t * cert); void gnutls_x509_crt_deinit(gnutls_x509_crt_t cert); int gnutls_x509_crt_import(gnutls_x509_crt_t cert, const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format); +int gnutls_x509_crt_list_import(gnutls_x509_crt_t *certs, unsigned int cert_max, + const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format, unsigned int flags); int gnutls_x509_crt_export( gnutls_x509_crt_t cert, gnutls_x509_crt_fmt_t format, void* output_data, size_t* output_data_size); int gnutls_x509_crt_get_issuer_dn(gnutls_x509_crt_t cert, char *buf, diff --git a/lib/x509/x509.c b/lib/x509/x509.c index f42c356bca..d4fb8a921b 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -1906,3 +1906,94 @@ int gnutls_x509_crt_get_pk_dsa_raw(gnutls_x509_crt_t crt, } #endif + +#define CLEAR_CERTS \ + for(j=0;j<count;j++) gnutls_x509_crt_deinit( certs[j]) +/** + * gnutls_x509_crt_list_import - This function will import a PEM encoded certificate list + * @certs: The structures to store the parsed certificate. Must not be initialized. + * @cert_max: The number of certs. + * @data: The PEM encoded certificate. + * @format: One of DER or PEM. Only PEM is supported for now. + * @flags: must be zero. + * + * This function will convert the given PEM encoded certificate list + * to the native gnutls_x509_crt_t format. The output will be stored in @certs. + * + * If the Certificate is PEM encoded it should have a header of "X509 CERTIFICATE", or + * "CERTIFICATE". + * + * Returns the number of certificates read or a negative error value. + * + **/ +int gnutls_x509_crt_list_import(gnutls_x509_crt_t *certs, unsigned int cert_max, + const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format, unsigned int flags) +{ + int size; + const char *ptr; + gnutls_datum_t tmp; + int ret; + unsigned int count=0,j; + + /* move to the certificate + */ + ptr = memmem(data->data, data->size, + PEM_CERT_SEP, sizeof(PEM_CERT_SEP) - 1); + if (ptr == NULL) + ptr = memmem(data->data, data->size, + PEM_CERT_SEP2, sizeof(PEM_CERT_SEP2) - 1); + + if (ptr == NULL) { + gnutls_assert(); + return GNUTLS_E_BASE64_DECODING_ERROR; + } + size = data->size - (ptr - (char*)data->data); + + count = 0; + + do { + ret = gnutls_x509_crt_init( &certs[count]); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + tmp.data = (void*)ptr; + tmp.size = size; + + ret = gnutls_x509_crt_import( certs[count], &tmp, GNUTLS_X509_FMT_PEM); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + /* now we move ptr after the pem header + */ + ptr++; + /* find the next certificate (if any) + */ + size = data->size - (ptr - (char*)data->data); + + if (size > 0) { + char *ptr2; + + ptr2 = + memmem(ptr, size, PEM_CERT_SEP, sizeof(PEM_CERT_SEP) - 1); + if (ptr2 == NULL) + ptr2 = memmem(ptr, size, PEM_CERT_SEP2, + sizeof(PEM_CERT_SEP2) - 1); + + ptr = ptr2; + } else + ptr = NULL; + + count++; + } while (cert_max > count && ptr != NULL); + + return count; + +error: + CLEAR_CERTS; + return ret; +} + @@ -155,7 +155,9 @@ static void munmap_file(gnutls_datum data) munmap(data.data, data.size); } -static gnutls_x509_crt x509_crt = NULL; +#define MAX_CRT 6 +static unsigned int x509_crt_size; +static gnutls_x509_crt x509_crt[MAX_CRT]; static gnutls_x509_privkey x509_key = NULL; static gnutls_openpgp_key pgp_crt = NULL; @@ -174,15 +176,16 @@ static void load_keys(void) fprintf(stderr, "*** Error loading cert file.\n"); exit(1); } - gnutls_x509_crt_init(&x509_crt); - ret = gnutls_x509_crt_import(x509_crt, &data, GNUTLS_X509_FMT_PEM); + ret = gnutls_x509_crt_list_import(x509_crt, MAX_CRT, &data, GNUTLS_X509_FMT_PEM, 0); if (ret < 0) { fprintf(stderr, "*** Error loading cert file: %s\n", gnutls_strerror(ret)); exit(1); } + x509_crt_size = ret; + fprintf(stderr, "Processed %d client certificates...\n", ret); munmap_file(data); @@ -299,9 +302,9 @@ static int cert_callback(gnutls_session session, if (st->type == GNUTLS_CRT_X509) { if (x509_crt != NULL && x509_key != NULL) { - st->ncerts = 1; + st->ncerts = x509_crt_size; - st->cert.x509 = &x509_crt; + st->cert.x509 = x509_crt; st->key.x509 = x509_key; st->deinit_all = 0; |