Re: [HACKERS] New functions for sslinfo extension
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.0 +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 =
[HACKERS] New functions for sslinfo extension
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? -- Best regards, Dmitry Voronin
[HACKERS] New functions for sslinfo extension
Hello all, postgresmen! I want to present some 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). I write those functions with libpq on C. I put code of module and sql-file for loading with this letter. Best regards,Dmitry Voronin #include postgres.h #include fmgr.h #include utils/numeric.h #include libpq/libpq-be.h #include miscadmin.h #include utils/builtins.h #include mb/pg_wchar.h #include funcapi.h #include openssl/x509.h #include openssl/x509v3.h PG_MODULE_MAGIC; 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); X509_EXTENSION *get_extension(X509* certificate, char *name) { int extension_nid = 0; int locate = 0; extension_nid = OBJ_sn2nid(name); if (0 == extension_nid) { extension_nid = OBJ_ln2nid(name); if (0 == extension_nid) return NULL; } locate = X509_get_ext_by_NID(certificate, extension_nid, -1); return X509_get_ext(certificate, locate); } 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; text *result = NULL; if (NULL == certificate) PG_RETURN_NULL(); extension = get_extension(certificate, extension_name); if (NULL == extension) elog(ERROR, Extension by name \%s\ is not found in certificate, extension_name); bio = BIO_new(BIO_s_mem()); char nullterm = '\0'; 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); } 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 (NULL == certificate) PG_RETURN_NULL(); extension = get_extension(certificate, extension_name); if (NULL == extension) elog(ERROR, Extension name \%s\ is not found in certificate, extension_name); critical = X509_EXTENSION_get_critical(extension); PG_RETURN_BOOL(critical); } PG_FUNCTION_INFO_V1(ssl_get_count_of_extensions); Datum ssl_get_count_of_extensions(PG_FUNCTION_ARGS) { X509 *certificate = MyProcPort - peer; if (NULL == certificate) PG_RETURN_NULL(); PG_RETURN_INT32(X509_get_ext_count(certificate)); } 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 (NULL == certificate) PG_RETURN_NULL(); extension_stack = certificate - cert_info - extensions; if (NULL == extension_stack) 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 (0 == extension_nid) elog(ERROR, Unknown extension in certificate); result = cstring_to_text(OBJ_nid2sn(extension_nid)); SRF_RETURN_NEXT(funcctx, (Datum) result); } sk_X509_EXTENSION_free(extension); SRF_RETURN_DONE(funcctx); } sslextensions.control Description: Binary data sslextensions--1.0.sql Description: application/sql -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
Re: [HACKERS] New functions for sslinfo extension
Hi, On Thu, Apr 17, 2014 at 3:30 AM, Воронин Дмитрий carriingfat...@yandex.ru wrote: I want to present some 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). I write those functions with libpq on C. This looks interesting. This is unfortunately too late for 9.4, but you can submit it for 9.5 in the next commit fest but registering a new patch: https://commitfest.postgresql.org/action/commitfest_view?id=22 Here are as well some guidelines that will help you submitting nicely-formatted patches: https://wiki.postgresql.org/wiki/Submitting_a_Patch https://wiki.postgresql.org/wiki/Working_with_Git https://wiki.postgresql.org/wiki/Creating_Clean_Patches You should not send a patch in the shape of each file sent individually, but something that is generated based on diffs on the Postgres code. Also, I looked at your code, you should avoid the following things, that are not conform to the code format of the project: - Some tabs of your code are made of 4 spaces, and are not tabs - Postgres avoids conditions like (constant == variable) and it is preferable to use (variable == constant). Here is the documentation explaining the coding convention: http://www.postgresql.org/docs/devel/static/source.html Regards, -- Michael -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers