X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=contrib%2Fsslinfo%2Fsslinfo.c;h=641c3f0c845641f3dcc31e0bf4b9b7f765d97b96;hb=6a605cd6bd9f689b35676623add0de9b90978bf1;hp=c843303ff0d4020f9c88ca6d9035a5c0a8b5d844;hpb=a86e70b8f8bbacbba3d9e5b8a3adf22c01b19d2b;p=postgresql diff --git a/contrib/sslinfo/sslinfo.c b/contrib/sslinfo/sslinfo.c index c843303ff0..641c3f0c84 100644 --- a/contrib/sslinfo/sslinfo.c +++ b/contrib/sslinfo/sslinfo.c @@ -3,6 +3,8 @@ * * Written by Victor B. Wagner , Cryptocom LTD * This file is distributed under BSD-style license. + * + * contrib/sslinfo/sslinfo.c */ #include "postgres.h" @@ -16,43 +18,62 @@ #include #include - 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