Hello, I make an a patch, which adds 4 functions to sslinfo extension module.
 
You can view some information of certificate's extensions with those functions.
The descriptions of functions I posted in my first letter and in source code.
 
What do you think about it?
 
--
Best regards, Dmitry Voronin
 
--- contrib/sslinfo/sslinfo.c	2014-03-17 23:35:47.000000000 +0400
+++ contrib/sslinfo/sslinfo.c	2014-04-18 11:09:49.567775647 +0400
@@ -5,6 +5,8 @@
  * This file is distributed under BSD-style license.
  *
  * contrib/sslinfo/sslinfo.c
+ * 
+ * Extension functions written by Dmitry Voronin carriingfat...@yandex.ru, CNIIEISU.
  */
 
 #include "postgres.h"
@@ -14,9 +16,11 @@
 #include "miscadmin.h"
 #include "utils/builtins.h"
 #include "mb/pg_wchar.h"
+#include "funcapi.h"
 
 #include <openssl/x509.h>
 #include <openssl/asn1.h>
+#include <openssl/x509v3.h>
 
 
 PG_MODULE_MAGIC;
@@ -35,6 +39,11 @@
 Datum		X509_NAME_to_text(X509_NAME *name);
 Datum		ASN1_STRING_to_text(ASN1_STRING *str);
 
+X509_EXTENSION	*get_extension(X509* certificate, char *name);
+Datum 		ssl_get_extension_value(PG_FUNCTION_ARGS);
+Datum		ssl_is_critical_extension(PG_FUNCTION_ARGS);
+Datum 		ssl_get_count_of_extensions(PG_FUNCTION_ARGS);
+Datum		ssl_get_extension_names(PG_FUNCTION_ARGS);
 
 /*
  * Indicates whether current session uses SSL
@@ -371,3 +380,146 @@
 		PG_RETURN_NULL();
 	return X509_NAME_to_text(X509_get_issuer_name(MyProcPort->peer));
 }
+
+
+X509_EXTENSION *get_extension(X509* certificate, char *name) {
+	int 			extension_nid = 0;
+	int 			locate = 0;
+	
+	extension_nid = OBJ_sn2nid(name);
+	if (extension_nid == NID_undef) {
+		extension_nid = OBJ_ln2nid(name);
+		if (extension_nid == NID_undef) 
+			return NULL;
+	}
+	locate = X509_get_ext_by_NID(certificate, extension_nid,  -1);
+	return X509_get_ext(certificate, locate);
+}
+
+/* Returns value of extension. 
+ * 
+ * This function returns value of extension by short name in client certificate. 
+ * 
+ * Returns text datum. 
+ */
+
+PG_FUNCTION_INFO_V1(ssl_get_extension_value);
+Datum
+ssl_get_extension_value(PG_FUNCTION_ARGS) {	
+	X509 			*certificate = MyProcPort -> peer;
+	X509_EXTENSION 		*extension = NULL;
+	char 			*extension_name = text_to_cstring(PG_GETARG_TEXT_P(0));
+	BIO 			*bio = NULL;
+	char 			*value = NULL;
+	char 			nullterm = '\0';
+	text 			*result = NULL;
+
+	if (certificate == NULL)
+		PG_RETURN_NULL();
+
+	extension = get_extension(certificate, extension_name);
+	if (extension == NULL)
+		elog(ERROR, "Extension by name \"%s\" is not found in certificate", extension_name);
+
+	bio = BIO_new(BIO_s_mem());
+	X509V3_EXT_print(bio, extension, -1, -1);
+	BIO_write(bio, &nullterm, 1);
+	BIO_get_mem_data(bio, &value);
+
+	result = cstring_to_text(value);
+	BIO_free(bio);
+
+	PG_RETURN_TEXT_P(result);
+}
+
+/* Returns status of extension 
+ * 
+ * Returns true, if extension is critical and false, if it is not.
+ * 
+ * Returns bool datum
+ */
+PG_FUNCTION_INFO_V1(ssl_is_critical_extension);
+Datum
+ssl_is_critical_extension(PG_FUNCTION_ARGS) {
+	X509 			*certificate = MyProcPort -> peer;
+	X509_EXTENSION 		*extension = NULL;
+	char 			*extension_name = text_to_cstring(PG_GETARG_TEXT_P(0));
+	int 			critical = 0;
+	
+	if (certificate == NULL)
+		PG_RETURN_NULL();
+	
+	extension = get_extension(certificate, extension_name);
+	if (extension == NULL) 
+		elog(ERROR, "Extension name \"%s\" is not found in certificate", extension_name);
+	
+	critical = X509_EXTENSION_get_critical(extension);
+	PG_RETURN_BOOL(critical);
+}
+
+/* Returns count of extensions in client certificate
+ * 
+ * Returns int datum
+ */
+PG_FUNCTION_INFO_V1(ssl_get_count_of_extensions);
+Datum
+ssl_get_count_of_extensions(PG_FUNCTION_ARGS) {
+	X509 			*certificate = MyProcPort -> peer;
+	
+	if (certificate == NULL)
+		PG_RETURN_NULL();
+	
+	PG_RETURN_INT32(X509_get_ext_count(certificate));
+}
+
+/* Returns short names of extensions in client certificate
+ * 
+ * Returns setof text datum
+ */
+PG_FUNCTION_INFO_V1(ssl_get_extension_names);
+Datum
+ssl_get_extension_names(PG_FUNCTION_ARGS) {
+	X509				*certificate = MyProcPort -> peer;
+	FuncCallContext 		*funcctx;
+	STACK_OF(X509_EXTENSION) 	*extension_stack = NULL;
+	MemoryContext 			oldcontext;
+	int 				call = 0;
+	int 				max_calls = 0;
+	X509_EXTENSION			*extension = NULL;
+	ASN1_OBJECT			*object = NULL;
+	int 				extension_nid = 0;
+	text*				result = NULL;
+	
+	if (certificate == NULL)
+		PG_RETURN_NULL();
+	
+	extension_stack = certificate -> cert_info -> extensions;
+	if (extension_stack == NULL) 
+		PG_RETURN_NULL();
+	
+	if (SRF_IS_FIRSTCALL()) {
+		funcctx = SRF_FIRSTCALL_INIT();
+		oldcontext = MemoryContextSwitchTo(funcctx -> multi_call_memory_ctx);
+		funcctx -> max_calls = X509_get_ext_count(certificate);
+		MemoryContextSwitchTo(oldcontext);
+	}
+	funcctx = SRF_PERCALL_SETUP();
+	
+	call = funcctx -> call_cntr;
+	max_calls = funcctx -> max_calls;
+	
+	if (call < max_calls) {
+		extension = sk_X509_EXTENSION_value(extension_stack, call);
+		object = X509_EXTENSION_get_object(extension);
+		extension_nid = OBJ_obj2nid(object);
+	    
+		if (extension_nid == NID_undef)
+			elog(ERROR, "Unknown extension in certificate");
+	    
+		result = cstring_to_text(OBJ_nid2sn(extension_nid));
+	    
+ 		SRF_RETURN_NEXT(funcctx, (Datum) result);
+	}
+	SRF_RETURN_DONE(funcctx);
+}
+
--- contrib/sslinfo/sslinfo--1.0.sql	2014-03-17 23:35:47.000000000 +0400
+++ contrib/sslinfo/sslinfo--1.0.sql	2014-04-18 11:12:03.768470905 +0400
@@ -38,3 +38,19 @@
 CREATE FUNCTION ssl_issuer_dn() RETURNS text
 AS 'MODULE_PATHNAME', 'ssl_issuer_dn'
 LANGUAGE C STRICT;
+
+CREATE OR REPLACE FUNCTION ssl_get_extension_value(text) RETURNS text
+AS 'MODULE_PATHNAME', 'ssl_get_extension_value'
+LANGUAGE C STRICT;
+
+CREATE OR REPLACE FUNCTION ssl_is_critical_extension(text) RETURNS boolean
+AS 'MODULE_PATHNAME', 'ssl_is_critical_extension'
+LANGUAGE C STRICT;
+
+CREATE OR REPLACE FUNCTION ssl_get_count_of_extensions() RETURNS integer
+AS 'MODULE_PATHNAME', 'ssl_get_count_of_extensions'
+LANGUAGE C STRICT;
+
+CREATE OR REPLACE FUNCTION ssl_get_extension_names() RETURNS SETOF text 
+AS 'MODULE_PATHNAME', 'ssl_get_extension_names'
+LANGUAGE C STRICT;
+
--- contrib/sslinfo/sslinfo--unpackaged--1.0.sql	2014-04-18 11:17:44.937238072 +0400
+++ contrib/sslinfo/sslinfo--unpackaged--1.0.sql	2014-04-18 11:16:45.185110931 +0400
@@ -11,6 +11,11 @@
 ALTER EXTENSION sslinfo ADD function ssl_client_dn();
 ALTER EXTENSION sslinfo ADD function ssl_issuer_dn();
 
+ALTER EXTENSION sslinfo ADD function ssl_get_extension_value();
+ALTER EXTENSION sslinfo ADD function ssl_is_critical_extension();
+ALTER EXTENSION sslinfo ADD function ssl_count_of_extensions();
+ALTER EXTENSION sslinfo ADD function ssl_get_extension_names();
+
 -- These functions were not in 9.0:
 
 CREATE FUNCTION ssl_version() RETURNS text

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to