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 ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
