summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2005-03-28 20:45:13 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2005-03-28 20:45:13 +0000
commitd02e7a1d22f73ce589508394390d0d1493952820 (patch)
tree0abe3ffb6e7fda09112abe380822f1912122e13a
parenta4fa1abebdd9b2310005972befa2a81d0e82ff8e (diff)
downloadgnutls-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--NEWS1
-rw-r--r--includes/gnutls/x509.h2
-rw-r--r--lib/x509/x509.c91
-rw-r--r--src/cli.c13
4 files changed, 102 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index 9abc70d923..897c6eb540 100644
--- a/NEWS
+++ b/NEWS
@@ -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;
+}
+
diff --git a/src/cli.c b/src/cli.c
index ca167f1a42..b524245182 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -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;