/pidgin/main: 4879ef4db7cf: Move Tls Certificate parsing code in...

Mike Ruprecht <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: 4879ef4db7cf4e06134f1e43fb47b3bdf758722a
Author:	 Mike Ruprecht <[email protected]>
Date:	 2016-04-07 01:29 -0500
Branch:	 purple-ssl-to-gio
URL: https://hg.pidgin.im/pidgin/main/rev/4879ef4db7cf

Description:

Move Tls Certificate parsing code into tls-certificate-info.[ch]

This patch moves the TLS certificate parsing code into a new file,
separate from the TLS trust and storage code (tls-certificate.[ch])
upon Masca's suggestion.

diffstat:

 finch/gntcertmgr.c               |    3 +-
 finch/gntrequest.c               |    2 +-
 libpurple/Makefile.am            |    2 +
 libpurple/tls-certificate-info.c |  779 +++++++++++++++++++++++++++++++++++++++
 libpurple/tls-certificate-info.h |  105 +++++
 libpurple/tls-certificate.c      |  751 -------------------------------------
 libpurple/tls-certificate.h      |   64 ---
 pidgin/gtkcertmgr.c              |    3 +-
 pidgin/gtkrequest.c              |    2 +-
 9 files changed, 892 insertions(+), 819 deletions(-)

diffs (truncated from 1808 to 300 lines):

diff --git a/finch/gntcertmgr.c b/finch/gntcertmgr.c
--- a/finch/gntcertmgr.c
+++ b/finch/gntcertmgr.c
@@ -23,10 +23,11 @@
 #include <internal.h>
 #include "finch.h"
 
-#include "tls-certificate.h"
 #include "debug.h"
 #include "notify.h"
 #include "request.h"
+#include "tls-certificate.h"
+#include "tls-certificate-info.h"
 
 #include "gntcertmgr.h"
 
diff --git a/finch/gntrequest.c b/finch/gntrequest.c
--- a/finch/gntrequest.c
+++ b/finch/gntrequest.c
@@ -34,7 +34,7 @@
 #include "finch.h"
 #include "gntrequest.h"
 #include "debug.h"
-#include "tls-certificate.h"
+#include "tls-certificate-info.h"
 #include "util.h"
 
 typedef struct
diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am
--- a/libpurple/Makefile.am
+++ b/libpurple/Makefile.am
@@ -115,6 +115,7 @@ purple_coresources = \
 	theme-loader.c \
 	theme-manager.c \
 	tls-certificate.c \
+	tls-certificate-info.c \
 	trie.c \
 	upnp.c \
 	util.c \
@@ -193,6 +194,7 @@ purple_coreheaders = \
 	theme-loader.h \
 	theme-manager.h \
 	tls-certificate.h \
+	tls-certificate-info.h \
 	trie.h \
 	upnp.h \
 	util.h \
diff --git a/libpurple/tls-certificate-info.c b/libpurple/tls-certificate-info.c
new file mode 100644
--- /dev/null
+++ b/libpurple/tls-certificate-info.c
@@ -0,0 +1,779 @@
+/*
+ *
+ * purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here.  Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
+ */
+
+#include "internal.h"
+#include "tls-certificate-info.h"
+#include "ciphers/sha1hash.h"
+#include "debug.h"
+#include "util.h"
+
+#define DER_TYPE_CLASS(type)		(type & 0xc0)
+
+#define DER_TYPE_CLASS_UNIVERSAL	0x00
+#define DER_TYPE_CLASS_APPLICATION	0x40
+#define DER_TYPE_CLASS_CONTEXT_SPECIFIC	0x80
+#define DER_TYPE_CLASS_PRIVATE		0xc0
+
+#define DER_TYPE_TAG(type) (type & 0x1f)
+
+#define DER_TYPE_IS_CONSTRUCTED(type) ((type & 0x20) ? TRUE : FALSE)
+
+#define DER_TYPE_TAG_IS_LONG_FORM(type) (DER_TYPE_TAG(type) == 0x1f)
+
+#define DER_LENGTH_IS_LONG_FORM(byte) ((byte & 0x80) ? TRUE : FALSE)
+#define DER_LENGTH_LONG_FORM_SIZE(byte) (byte & 0x7f)
+
+typedef struct {
+	guint8 type_class;
+	gboolean constructed;
+	guint type;
+	GBytes *content;
+	GSList *children;
+} DerNodeData;
+
+static void der_node_data_children_list_free(GSList *children);
+
+static void
+der_node_data_free(DerNodeData *node_data)
+{
+	g_return_if_fail(node_data != NULL);
+
+	g_clear_pointer(&node_data->content, g_bytes_unref);
+	g_clear_pointer(&node_data->children,
+			der_node_data_children_list_free);
+
+	g_free(node_data);
+}
+
+static void
+der_node_data_children_list_free(GSList *children)
+{
+	g_return_if_fail(children != NULL);
+
+	g_slist_free_full(children, (GDestroyNotify)der_node_data_free);
+}
+
+/* Parses DER encoded data into a GSList of DerNodeData instances */
+static GSList *
+der_parse(GBytes *data_bytes)
+{
+	const guint8 *data;
+	gsize size = 0;
+	gsize offset = 0;
+	GSList *nodes = NULL;
+	DerNodeData *node = NULL;
+
+	data = g_bytes_get_data(data_bytes, &size);
+
+	/* Parse data */
+	while (offset < size) {
+		guint8 byte;
+		gsize length;
+
+		/* Parse type */
+
+		byte = *(data + offset++);
+		node = g_new0(DerNodeData, 1);
+		node->type_class = DER_TYPE_CLASS(byte);
+		node->constructed = DER_TYPE_IS_CONSTRUCTED(byte);
+
+		if (DER_TYPE_TAG_IS_LONG_FORM(byte)) {
+			/* Long-form type encoding */
+			/* TODO: Handle long-form encoding.
+			 * Maiku: The certificates I tested didn't do this.
+			 */
+			g_return_val_if_reached(NULL);
+		} else {
+			/* Short-form type encoding */
+			node->type = DER_TYPE_TAG(byte);
+		}
+
+		/* Parse content length */
+
+		if (offset >= size) {
+			purple_debug_error("tls-certificate",
+					"Not enough remaining data when "
+					"parsing DER chunk length byte: "
+					"read (%" G_GSIZE_FORMAT ") "
+					"available: ""(%" G_GSIZE_FORMAT ")",
+					offset, size);
+			break;
+		}
+
+		byte = *(data + offset++);
+
+		if (DER_LENGTH_IS_LONG_FORM(byte)) {
+			/* Long-form length encoding */
+			guint num_len_bytes = DER_LENGTH_LONG_FORM_SIZE(byte);
+			guint i;
+
+			/* Guard against overflowing the integer */
+			if (num_len_bytes > sizeof(guint)) {
+				purple_debug_error("tls-certificate",
+						"Number of long-form length "
+						"bytes greater than guint "
+						"size: %u > %" G_GSIZE_FORMAT,
+						num_len_bytes, sizeof(guint));
+				break;
+			}
+
+			/* Guard against reading past the end of the buffer */
+			if (offset + num_len_bytes > size) {
+				purple_debug_error("tls-certificate",
+						"Not enough remaining data "
+						"when parsing DER chunk "
+						"long-form length bytes: "
+						"read (%" G_GSIZE_FORMAT ") "
+						"available: ""(%"
+						G_GSIZE_FORMAT ")",
+						offset, size);
+				break;
+			}
+
+			length = 0;
+
+			for (i = 0; i < num_len_bytes; ++i) {
+				length = length << 8;
+				length |= *(data + offset++);
+			}
+		} else {
+			/* Short-form length encoding */
+			length = byte;
+		}
+		
+		/* Parse content */
+
+		if (offset + length > size) {
+			purple_debug_error("tls-certificate",
+					"Not enough remaining data when "
+					"parsing DER chunk content: "
+					"content size (%" G_GSIZE_FORMAT ") "
+					"available: ""(%" G_GSIZE_FORMAT ")",
+					length, size - offset);
+			break;
+		}
+
+		node->content = g_bytes_new_from_bytes(data_bytes,
+				offset, length);
+		offset += length;
+
+		/* Maybe recurse */
+		if (node->constructed) {
+			node->children = der_parse(node->content);
+
+			if (node->children == NULL) {
+				/* No children on a constructed type
+				 * should an error. If this happens, it
+				 * outputs debug info inside der_parse().
+				 */
+				break;
+			}
+		}
+
+		nodes = g_slist_append(nodes, node);
+		node = NULL;
+	}
+
+	if (node != NULL) {
+		/* There was an error. Free parsing data. */
+		der_node_data_free(node);
+		g_clear_pointer(&nodes, der_node_data_children_list_free);
+		/* FIXME: Report error to calling function ala GError? */
+	}
+
+	return nodes;
+}
+
+static gchar *
+der_parse_string(DerNodeData *node)
+{
+	const gchar *str;
+	gsize length = 0;
+
+	g_return_val_if_fail(node != NULL, NULL);
+	g_return_val_if_fail(node->content != NULL, NULL);
+
+	str = g_bytes_get_data(node->content, &length);
+	return g_strndup(str, length);
+}
+
+typedef struct {
+	gchar *oid;
+	gchar *value;
+} DerOIDValue;
+
+static void
+der_oid_value_free(DerOIDValue *data)
+{
+	g_return_if_fail(data != NULL);
+
+	g_clear_pointer(&data->oid, g_free);
+	g_clear_pointer(&data->value, g_free);
+
+	g_free(data);
+}
+
+static void
+der_oid_value_slist_free(GSList *list)
+{
+	g_return_if_fail(list != NULL);
+
+	g_slist_free_full(list, (GDestroyNotify)der_oid_value_free);
+}
+
+static const gchar *
+der_oid_value_slist_get_value_by_oid(GSList *list, const gchar *oid)
+{
+	for (; list != NULL; list = g_slist_next(list)) {
+		DerOIDValue *value = list->data;

_______________________________________________
Commits mailing list
[email protected]
https://pidgin.im/cgi-bin/mailman/listinfo/commits
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.