]> granicus.if.org Git - postgresql/blobdiff - contrib/sslinfo/sslinfo.c
Adjust blank lines around PG_MODULE_MAGIC defines, for consistency
[postgresql] / contrib / sslinfo / sslinfo.c
index c843303ff0d4020f9c88ca6d9035a5c0a8b5d844..641c3f0c845641f3dcc31e0bf4b9b7f765d97b96 100644 (file)
@@ -3,6 +3,8 @@
  *
  * Written by Victor B. Wagner <vitus@cryptocom.ru>, Cryptocom LTD
  * This file is distributed under BSD-style license.
+ *
+ * contrib/sslinfo/sslinfo.c
  */
 
 #include "postgres.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);
 
-Datum ssl_is_used(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);
 
-
-/* 
+/*
  * Indicates whether current session uses SSL
  *
  * Function has no arguments.  Returns bool.  True if current session
  * is SSL session and false if it is local or non-ssl session.
  */
 PG_FUNCTION_INFO_V1(ssl_is_used);
-Datum ssl_is_used(PG_FUNCTION_ARGS)
+Datum
+ssl_is_used(PG_FUNCTION_ARGS)
 {
-       PG_RETURN_BOOL(MyProcPort->ssl !=NULL);
+       PG_RETURN_BOOL(MyProcPort->ssl != NULL);
 }
 
 
 /*
- * Indicates whether current client have provided a certificate
+ * Returns SSL version currently in use.
+ */
+PG_FUNCTION_INFO_V1(ssl_version);
+Datum
+ssl_version(PG_FUNCTION_ARGS)
+{
+       if (MyProcPort->ssl == NULL)
+               PG_RETURN_NULL();
+       PG_RETURN_TEXT_P(cstring_to_text(SSL_get_version(MyProcPort->ssl)));
+}
+
+
+/*
+ * Returns SSL cipher currently in use.
+ */
+PG_FUNCTION_INFO_V1(ssl_cipher);
+Datum
+ssl_cipher(PG_FUNCTION_ARGS)
+{
+       if (MyProcPort->ssl == NULL)
+               PG_RETURN_NULL();
+       PG_RETURN_TEXT_P(cstring_to_text(SSL_get_cipher(MyProcPort->ssl)));
+}
+
+
+/*
+ * 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.
  */
 PG_FUNCTION_INFO_V1(ssl_client_cert_present);
-Datum ssl_client_cert_present(PG_FUNCTION_ARGS)
+Datum
+ssl_client_cert_present(PG_FUNCTION_ARGS)
 {
        PG_RETURN_BOOL(MyProcPort->peer != NULL);
 }
@@ -67,20 +88,22 @@ Datum ssl_client_cert_present(PG_FUNCTION_ARGS)
  * SSL connection is established without sending client certificate.
  */
 PG_FUNCTION_INFO_V1(ssl_client_serial);
-Datum ssl_client_serial(PG_FUNCTION_ARGS)
+Datum
+ssl_client_serial(PG_FUNCTION_ARGS)
 {
-       Datum result;
-       Port *port = MyProcPort;
-       X509 *peer = port->peer;
+       Datum           result;
+       Port       *port = MyProcPort;
+       X509       *peer = port->peer;
        ASN1_INTEGER *serial = NULL;
-       BIGNUM *b;
-       char *decimal;
+       BIGNUM     *b;
+       char       *decimal;
 
        if (!peer)
                PG_RETURN_NULL();
        serial = X509_get_serialNumber(peer);
        b = ASN1_INTEGER_to_BN(serial, NULL);
        decimal = BN_bn2dec(b);
+
        BN_free(b);
        result = DirectFunctionCall3(numeric_in,
                                                                 CStringGetDatum(decimal),
@@ -98,41 +121,37 @@ Datum ssl_client_serial(PG_FUNCTION_ARGS)
  * current database encoding if possible.  Any invalid characters are
  * replaced by question marks.
  *
- * Parameter: str - OpenSSL ASN1_STRING structure.  Memory managment
+ * Parameter: str - OpenSSL ASN1_STRING structure.  Memory management
  * of this structure is responsibility of caller.
  *
  * Returns Datum, which can be directly returned from a C language SQL
  * function.
  */
-Datum ASN1_STRING_to_text(ASN1_STRING *str)
+static Datum
+ASN1_STRING_to_text(ASN1_STRING *str)
 {
-       BIO *membuf = NULL;
-       size_t size, outlen;
-       char *sp;
-       char *dp;
-       text *result;
+       BIO                *membuf;
+       size_t          size;
+       char            nullterm;
+       char       *sp;
+       char       *dp;
+       text       *result;
 
        membuf = BIO_new(BIO_s_mem());
-       BIO_set_close(membuf, BIO_CLOSE);
-       ASN1_STRING_print_ex(membuf,str,
+       (void) BIO_set_close(membuf, BIO_CLOSE);
+       ASN1_STRING_print_ex(membuf, str,
                                                 ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB)
                                                  | ASN1_STRFLGS_UTF8_CONVERT));
-
-       outlen = 0;
-       BIO_write(membuf, &outlen, 1);
+       /* ensure null termination of the BIO's content */
+       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());
-       outlen = strlen(dp);
-       result = palloc(VARHDRSZ + outlen);
-       memcpy(VARDATA(result), dp, outlen);
+       dp = pg_any_to_server(sp, size - 1, PG_UTF8);
+       result = cstring_to_text(dp);
        if (dp != sp)
                pfree(dp);
-
        BIO_free(membuf);
-       VARATT_SIZEP(result) = outlen + VARHDRSZ;
+
        PG_RETURN_TEXT_P(result);
 }
 
@@ -144,26 +163,20 @@ Datum ASN1_STRING_to_text(ASN1_STRING *str)
  *
  * Parameter: X509_NAME *name - either subject or issuer of certificate
  * Parameter: text fieldName  - field name string like 'CN' or commonName
- *            to be looked up in the OpenSSL ASN1 OID database
+ *                       to be looked up in the OpenSSL ASN1 OID database
  *
  * Returns result of ASN1_STRING_to_text applied to appropriate
  * part of name
  */
-Datum X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
+static Datum
+X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
 {
-       char *sp;
-       char *string_fieldname;
-       char *dp;
-       size_t name_len = VARSIZE(fieldName) - VARHDRSZ;
-       int nid, index, i;
+       char       *string_fieldname;
+       int                     nid,
+                               index;
        ASN1_STRING *data;
 
-       string_fieldname = palloc(name_len + 1);
-       sp = VARDATA(fieldName);
-       dp = string_fieldname;
-       for (i = 0; i < name_len; i++)
-               *dp++ = *sp++;
-       *dp = '\0';
+       string_fieldname = text_to_cstring(fieldName);
        nid = OBJ_txt2nid(string_fieldname);
        if (nid == NID_undef)
                ereport(ERROR,
@@ -173,7 +186,7 @@ Datum X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
        pfree(string_fieldname);
        index = X509_NAME_get_index_by_NID(name, nid, -1);
        if (index < 0)
-               return (Datum)0;
+               return (Datum) 0;
        data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, index));
        return ASN1_STRING_to_text(data);
 }
@@ -196,10 +209,11 @@ Datum X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
  * there is no field with such name in the certificate.
  */
 PG_FUNCTION_INFO_V1(ssl_client_dn_field);
-Datum ssl_client_dn_field(PG_FUNCTION_ARGS)
+Datum
+ssl_client_dn_field(PG_FUNCTION_ARGS)
 {
-       text *fieldname = PG_GETARG_TEXT_P(0);
-       Datum result;
+       text       *fieldname = PG_GETARG_TEXT_P(0);
+       Datum           result;
 
        if (!(MyProcPort->peer))
                PG_RETURN_NULL();
@@ -230,10 +244,11 @@ Datum ssl_client_dn_field(PG_FUNCTION_ARGS)
  * there is no field with such name in the certificate.
  */
 PG_FUNCTION_INFO_V1(ssl_issuer_field);
-Datum ssl_issuer_field(PG_FUNCTION_ARGS)
+Datum
+ssl_issuer_field(PG_FUNCTION_ARGS)
 {
-       text *fieldname = PG_GETARG_TEXT_P(0);
-       Datum result;
+       text       *fieldname = PG_GETARG_TEXT_P(0);
+       Datum           result;
 
        if (!(MyProcPort->peer))
                PG_RETURN_NULL();
@@ -258,21 +273,24 @@ Datum ssl_issuer_field(PG_FUNCTION_ARGS)
  * Returns: text datum which contains string representation of
  * X509_NAME
  */
-Datum X509_NAME_to_text(X509_NAME *name)
+static Datum
+X509_NAME_to_text(X509_NAME *name)
 {
-       BIO *membuf = BIO_new(BIO_s_mem());
-       int i,nid,count = X509_NAME_entry_count(name);
+       BIO                *membuf = BIO_new(BIO_s_mem());
+       int                     i,
+                               nid,
+                               count = X509_NAME_entry_count(name);
        X509_NAME_ENTRY *e;
        ASN1_STRING *v;
-
        const char *field_name;
-       size_t size,outlen;
-       char *sp;
-       char *dp;
-       text *result;
-
-       BIO_set_close(membuf, BIO_CLOSE);
-       for (i=0; i<count; i++)
+       size_t          size;
+       char            nullterm;
+       char       *sp;
+       char       *dp;
+       text       *result;
+
+       (void) BIO_set_close(membuf, BIO_CLOSE);
+       for (i = 0; i < count; i++)
        {
                e = X509_NAME_get_entry(name, i);
                nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e));
@@ -281,29 +299,21 @@ Datum X509_NAME_to_text(X509_NAME *name)
                if (!field_name)
                        field_name = OBJ_nid2ln(nid);
                BIO_printf(membuf, "/%s=", field_name);
-               ASN1_STRING_print_ex(membuf,v,
+               ASN1_STRING_print_ex(membuf, v,
                                                         ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB)
                                                          | ASN1_STRFLGS_UTF8_CONVERT));
        }
 
-       i=0;
-       BIO_write(membuf, &i, 1);
+       /* ensure null termination of the BIO's content */
+       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());
-       BIO_free(membuf);
-       outlen = strlen(dp);
-       result = palloc(VARHDRSZ + outlen);
-       memcpy(VARDATA(result), dp, outlen);
-
-       /* pg_do_encoding_conversion has annoying habit of returning
-        * source pointer */
+       dp = pg_any_to_server(sp, size - 1, PG_UTF8);
+       result = cstring_to_text(dp);
        if (dp != sp)
                pfree(dp);
-       VARATT_SIZEP(result) = outlen + VARHDRSZ;
+       BIO_free(membuf);
+
        PG_RETURN_TEXT_P(result);
 }
 
@@ -318,7 +328,8 @@ Datum X509_NAME_to_text(X509_NAME *name)
  * Returns text datum.
  */
 PG_FUNCTION_INFO_V1(ssl_client_dn);
-Datum ssl_client_dn(PG_FUNCTION_ARGS)
+Datum
+ssl_client_dn(PG_FUNCTION_ARGS)
 {
        if (!(MyProcPort->peer))
                PG_RETURN_NULL();
@@ -336,7 +347,8 @@ Datum ssl_client_dn(PG_FUNCTION_ARGS)
  * Returns text datum.
  */
 PG_FUNCTION_INFO_V1(ssl_issuer_dn);
-Datum ssl_issuer_dn(PG_FUNCTION_ARGS)
+Datum
+ssl_issuer_dn(PG_FUNCTION_ARGS)
 {
        if (!(MyProcPort->peer))
                PG_RETURN_NULL();