[glib/glib-2-28] Rework PEM parsing to not be order dependent
- From: Nicolas Dufresne <nicolasd src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/glib-2-28] Rework PEM parsing to not be order dependent
- Date: Wed, 27 Jul 2011 20:22:37 +0000 (UTC)
commit 3a7fad03137dccf54069b0b27a368f2982a614f9
Author: Nicolas Dufresne <nicolas dufresne collabora com>
Date: Wed Jul 27 16:10:12 2011 -0400
Rework PEM parsing to not be order dependent
Some valid PEM file would not work because the private key was put
before the certificate.
gio/gtlscertificate.c | 150 +++++++++++++++++++++++++++++++------------------
1 files changed, 96 insertions(+), 54 deletions(-)
---
diff --git a/gio/gtlscertificate.c b/gio/gtlscertificate.c
index 84a0c4e..6e8eaf7 100644
--- a/gio/gtlscertificate.c
+++ b/gio/gtlscertificate.c
@@ -209,70 +209,73 @@ g_tls_certificate_new_internal (const gchar *certificate_pem,
#define PEM_PRIVKEY_HEADER "-----BEGIN RSA PRIVATE KEY-----"
#define PEM_PRIVKEY_FOOTER "-----END RSA PRIVATE KEY-----"
-static GTlsCertificate *
-parse_next_pem_certificate (const gchar **data,
- const gchar *data_end,
- gboolean required,
- GError **error)
+gchar *
+parse_private_key (const gchar *data,
+ gsize data_len,
+ gboolean required,
+ GError **error)
{
- const gchar *start, *end, *next;
- gchar *cert_pem, *privkey_pem = NULL;
- GTlsCertificate *cert;
+ const gchar *start, *end;
- start = g_strstr_len (*data, data_end - *data, PEM_CERTIFICATE_HEADER);
+ start = g_strstr_len (data, data_len, PEM_PRIVKEY_HEADER);
if (!start)
{
if (required)
{
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
- _("No PEM-encoded certificate found"));
+ _("No PEM-encoded private key found"));
}
return NULL;
}
- end = g_strstr_len (start, data_end - start, PEM_CERTIFICATE_FOOTER);
+ end = g_strstr_len (start, data_len - (data - start), PEM_PRIVKEY_FOOTER);
if (!end)
{
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
- _("Could not parse PEM-encoded certificate"));
+ _("Could not parse PEM-encoded private key"));
return NULL;
}
- end += strlen (PEM_CERTIFICATE_FOOTER);
+ end += strlen (PEM_PRIVKEY_FOOTER);
while (*end == '\r' || *end == '\n')
end++;
- cert_pem = g_strndup (start, end - start);
+ return g_strndup (start, end - start);
+}
- *data = end;
- next = g_strstr_len (*data, data_end - *data, PEM_CERTIFICATE_HEADER);
- start = g_strstr_len (*data, data_end - *data, PEM_PRIVKEY_HEADER);
- if (start)
- end = g_strstr_len (start, data_end - start, PEM_PRIVKEY_FOOTER);
+gchar *
+parse_next_pem_certificate (const gchar **data,
+ const gchar *data_end,
+ gboolean required,
+ GError **error)
+{
+ const gchar *start, *end;
- if (start && (!next || start < next))
+ start = g_strstr_len (*data, data_end - *data, PEM_CERTIFICATE_HEADER);
+ if (!start)
{
- if (!end || (next && end > next))
+ if (required)
{
g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
- _("Could not parse PEM-encoded private key"));
- return NULL;
+ _("No PEM-encoded certificate found"));
}
+ return NULL;
+ }
- end += strlen (PEM_PRIVKEY_FOOTER);
- while (*end == '\r' || *end == '\n')
- end++;
-
- privkey_pem = g_strndup (start, end - start);
-
- *data = end + strlen (PEM_PRIVKEY_FOOTER);
+ end = g_strstr_len (start, data_end - start, PEM_CERTIFICATE_FOOTER);
+ if (!end)
+ {
+ g_set_error_literal (error, G_TLS_ERROR, G_TLS_ERROR_BAD_CERTIFICATE,
+ _("Could not parse PEM-encoded certificate"));
+ return NULL;
}
+ end += strlen (PEM_CERTIFICATE_FOOTER);
+ while (*end == '\r' || *end == '\n')
+ end++;
- cert = g_tls_certificate_new_internal (cert_pem, privkey_pem, error);
- g_free (cert_pem);
- g_free (privkey_pem);
+ *data = end;
- return cert;
+ return g_strndup (start, end - start);
}
/**
@@ -298,14 +301,32 @@ g_tls_certificate_new_from_pem (const gchar *data,
GError **error)
{
const gchar *data_end;
+ gchar *key_pem, *cert_pem;
+ GTlsCertificate *cert;
g_return_val_if_fail (data != NULL, NULL);
if (length == -1)
- data_end = data + strlen (data);
- else
- data_end = data + length;
- return parse_next_pem_certificate (&data, data_end, TRUE, error);
+ length = strlen (data);
+
+ data_end = data + length;
+
+ key_pem = parse_private_key (data, length, FALSE, error);
+ if (error && *error)
+ return NULL;
+
+ cert_pem = parse_next_pem_certificate (&data, data_end, TRUE, error);
+ if (error && *error)
+ {
+ g_free (key_pem);
+ return NULL;
+ }
+
+ cert = g_tls_certificate_new_internal (cert_pem, key_pem, error);
+ g_free (key_pem);
+ g_free (cert_pem);
+
+ return cert;
}
/**
@@ -359,18 +380,34 @@ g_tls_certificate_new_from_files (const gchar *cert_file,
{
GTlsCertificate *cert;
gchar *cert_data, *key_data;
+ gsize cert_len, key_len;
+ gchar *cert_pem, *key_pem;
+ const gchar *p;
- if (!g_file_get_contents (cert_file, &cert_data, NULL, error))
+ if (!g_file_get_contents (cert_file, &cert_data, &cert_len, error))
+ return NULL;
+ p = cert_data;
+ cert_pem = parse_next_pem_certificate (&p, p + cert_len, TRUE, error);
+ g_free (cert_data);
+ if (error && *error)
return NULL;
- if (!g_file_get_contents (key_file, &key_data, NULL, error))
+
+ if (!g_file_get_contents (key_file, &key_data, &key_len, error))
{
- g_free (cert_data);
+ g_free (cert_pem);
return NULL;
}
-
- cert = g_tls_certificate_new_internal (cert_data, key_data, error);
- g_free (cert_data);
+ key_pem = parse_private_key (key_data, key_len, TRUE, error);
g_free (key_data);
+ if (error && *error)
+ {
+ g_free (cert_pem);
+ return NULL;
+ }
+
+ cert = g_tls_certificate_new_internal (cert_pem, key_pem, error);
+ g_free (cert_pem);
+ g_free (key_pem);
return cert;
}
@@ -395,8 +432,7 @@ GList *
g_tls_certificate_list_new_from_file (const gchar *file,
GError **error)
{
- GTlsCertificate *cert;
- GList *list, *l;
+ GQueue queue = G_QUEUE_INIT;
gchar *contents, *end;
const gchar *p;
gsize length;
@@ -404,24 +440,30 @@ g_tls_certificate_list_new_from_file (const gchar *file,
if (!g_file_get_contents (file, &contents, &length, error))
return NULL;
- list = NULL;
end = contents + length;
p = contents;
while (p && *p)
{
- cert = parse_next_pem_certificate (&p, end, FALSE, error);
+ gchar *cert_pem;
+ GTlsCertificate *cert = NULL;
+
+ cert_pem = parse_next_pem_certificate (&p, end, FALSE, error);
+ if (cert_pem)
+ {
+ cert = g_tls_certificate_new_internal (cert_pem, NULL, error);
+ g_free (cert_pem);
+ }
if (!cert)
{
- for (l = list; l; l = l->next)
- g_object_unref (l->data);
- g_list_free (list);
- list = NULL;
+ g_list_free_full (queue.head, g_object_unref);
+ queue.head = NULL;
break;
}
- list = g_list_prepend (list, cert);
+ g_queue_push_tail (&queue, cert);
}
- return g_list_reverse (list);
+ g_free (contents);
+ return queue.head;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]