I put patch generated on git diffs to this letter. I make an a thread in postgresql commit fest: https://commitfest.postgresql.org/action/patch_view?id=1438
 
21.04.2014, 09:12, "Michael Paquier" <michael.paqu...@gmail.com>:


On Mon, Apr 21, 2014 at 1:48 PM, Воронин Дмитрий <carriingfat...@yandex.ru> wrote:
> Hello,
>  
> I make an a patch, which adds 4 functions to sslinfo extension module:
> 1) ssl_get_count_of_extensions() --- get count of X509v3 extensions from
> client certificate;
> 2) ssl_get_extension_names() --- get short names of X509v3 extensions from
> client certificate;
> 3) ssl_get_extension_value(text) --- get value of extension from certificate
> (argument --- short name of extension);
> 4) ssl_is_critical_extension(text) --- returns true, if extension is
> critical and false, if is not (argument --- short name of extension).
>  
> You can view some information of certificate's extensions via those
> functions.
> I want, that my functions will be included in PostgreSQL release.
>  
> What do you think about it?
Please avoid creating a new thread each time you send a new version of the same patch. Previous message was here:
http://www.postgresql.org/message-id/1135491397673...@web9m.yandex.ru
With my previous answer here:
http://www.postgresql.org/message-id/CAB7nPqRVFhnPnQL9ND+K=WA-YF_N1fAirx=s6fawk9f6anl...@mail.gmail.com

As I already mentioned last time, please register this patch to the upcoming commit fest beginning in June:
https://commitfest.postgresql.org/action/commitfest_view?id=22
This way, you will be sure that your patch will get at least one fair review and that progress will be made on the feature you are proposing.

The development cycle of 9.4 is over, but your patch could get into 9.5. You seem as well to have developed this patch using a tarball of 9.3.4 code by generating diffs from it, you will need a development environment with git. Here are some guidelines you can refer to (those are the same URLs as in my previous email btw...):
https://wiki.postgresql.org/wiki/Submitting_a_Patch
https://wiki.postgresql.org/wiki/Working_with_Git
https://wiki.postgresql.org/wiki/Creating_Clean_Patches
Regards,
--
Michael
 
Best regrads, Dmitry Voronin
 
 
*** a/contrib/sslinfo/sslinfo--1.0.sql
--- b/contrib/sslinfo/sslinfo--1.0.sql
***************
*** 38,40 **** LANGUAGE C STRICT;
--- 38,56 ----
  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;
\ No newline at end of file
\ No newline at end of file
*** a/contrib/sslinfo/sslinfo--unpackaged--1.0.sql
--- b/contrib/sslinfo/sslinfo--unpackaged--1.0.sql
***************
*** 11,16 **** ALTER EXTENSION sslinfo ADD function ssl_issuer_field(text);
--- 11,21 ----
  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
*** a/contrib/sslinfo/sslinfo.c
--- b/contrib/sslinfo/sslinfo.c
***************
*** 5,10 ****
--- 5,12 ----
   * 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,31 ****
  #include "miscadmin.h"
  #include "utils/builtins.h"
  #include "mb/pg_wchar.h"
  
  #include <openssl/x509.h>
  #include <openssl/asn1.h>
  
  
  PG_MODULE_MAGIC;
  
  
! static Datum X509_NAME_field_to_text(X509_NAME *name, text *fieldName);
! static Datum X509_NAME_to_text(X509_NAME *name);
! static Datum ASN1_STRING_to_text(ASN1_STRING *str);
  
  
  /*
   * Indicates whether current session uses SSL
--- 16,49 ----
  #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;
  
  
! Datum		ssl_is_used(PG_FUNCTION_ARGS);
! Datum		ssl_version(PG_FUNCTION_ARGS);
! Datum		ssl_cipher(PG_FUNCTION_ARGS);
! Datum		ssl_client_cert_present(PG_FUNCTION_ARGS);
! Datum		ssl_client_serial(PG_FUNCTION_ARGS);
! Datum		ssl_client_dn_field(PG_FUNCTION_ARGS);
! Datum		ssl_issuer_field(PG_FUNCTION_ARGS);
! Datum		ssl_client_dn(PG_FUNCTION_ARGS);
! Datum		ssl_issuer_dn(PG_FUNCTION_ARGS);
! Datum		X509_NAME_field_to_text(X509_NAME *name, text *fieldName);
! 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
***************
*** 42,48 **** ssl_is_used(PG_FUNCTION_ARGS)
  
  
  /*
!  * Returns SSL version currently in use.
   */
  PG_FUNCTION_INFO_V1(ssl_version);
  Datum
--- 60,66 ----
  
  
  /*
!  * Returns SSL cipher currently in use.
   */
  PG_FUNCTION_INFO_V1(ssl_version);
  Datum
***************
*** 68,74 **** ssl_cipher(PG_FUNCTION_ARGS)
  
  
  /*
!  * Indicates whether current client provided a certificate
   *
   * Function has no arguments.  Returns bool.  True if current session
   * is SSL session and client certificate is verified, otherwise false.
--- 86,92 ----
  
  
  /*
!  * Indicates whether current client have provided a certificate
   *
   * Function has no arguments.  Returns bool.  True if current session
   * is SSL session and client certificate is verified, otherwise false.
***************
*** 129,135 **** ssl_client_serial(PG_FUNCTION_ARGS)
   * Returns Datum, which can be directly returned from a C language SQL
   * function.
   */
! static Datum
  ASN1_STRING_to_text(ASN1_STRING *str)
  {
  	BIO		   *membuf;
--- 147,153 ----
   * Returns Datum, which can be directly returned from a C language SQL
   * function.
   */
! Datum
  ASN1_STRING_to_text(ASN1_STRING *str)
  {
  	BIO		   *membuf;
***************
*** 148,154 **** ASN1_STRING_to_text(ASN1_STRING *str)
  	nullterm = '\0';
  	BIO_write(membuf, &nullterm, 1);
  	size = BIO_get_mem_data(membuf, &sp);
! 	dp = pg_any_to_server(sp, size - 1, PG_UTF8);
  	result = cstring_to_text(dp);
  	if (dp != sp)
  		pfree(dp);
--- 166,175 ----
  	nullterm = '\0';
  	BIO_write(membuf, &nullterm, 1);
  	size = BIO_get_mem_data(membuf, &sp);
! 	dp = (char *) pg_do_encoding_conversion((unsigned char *) sp,
! 											size - 1,
! 											PG_UTF8,
! 											GetDatabaseEncoding());
  	result = cstring_to_text(dp);
  	if (dp != sp)
  		pfree(dp);
***************
*** 170,176 **** ASN1_STRING_to_text(ASN1_STRING *str)
   * Returns result of ASN1_STRING_to_text applied to appropriate
   * part of name
   */
! static Datum
  X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
  {
  	char	   *string_fieldname;
--- 191,197 ----
   * Returns result of ASN1_STRING_to_text applied to appropriate
   * part of name
   */
! Datum
  X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
  {
  	char	   *string_fieldname;
***************
*** 275,281 **** ssl_issuer_field(PG_FUNCTION_ARGS)
   * Returns: text datum which contains string representation of
   * X509_NAME
   */
! static Datum
  X509_NAME_to_text(X509_NAME *name)
  {
  	BIO		   *membuf = BIO_new(BIO_s_mem());
--- 296,302 ----
   * Returns: text datum which contains string representation of
   * X509_NAME
   */
! Datum
  X509_NAME_to_text(X509_NAME *name)
  {
  	BIO		   *membuf = BIO_new(BIO_s_mem());
***************
*** 310,316 **** X509_NAME_to_text(X509_NAME *name)
  	nullterm = '\0';
  	BIO_write(membuf, &nullterm, 1);
  	size = BIO_get_mem_data(membuf, &sp);
! 	dp = pg_any_to_server(sp, size - 1, PG_UTF8);
  	result = cstring_to_text(dp);
  	if (dp != sp)
  		pfree(dp);
--- 331,340 ----
  	nullterm = '\0';
  	BIO_write(membuf, &nullterm, 1);
  	size = BIO_get_mem_data(membuf, &sp);
! 	dp = (char *) pg_do_encoding_conversion((unsigned char *) sp,
! 											size - 1,
! 											PG_UTF8,
! 											GetDatabaseEncoding());
  	result = cstring_to_text(dp);
  	if (dp != sp)
  		pfree(dp);
***************
*** 356,358 **** ssl_issuer_dn(PG_FUNCTION_ARGS)
--- 380,525 ----
  		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);
+ }
+ 

-- 
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