PostgreSQL Source Code  git master
sslinfo.c File Reference
#include "postgres.h"
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/asn1.h>
#include "access/htup_details.h"
#include "funcapi.h"
#include "libpq/libpq-be.h"
#include "miscadmin.h"
#include "utils/builtins.h"
Include dependency graph for sslinfo.c:

Go to the source code of this file.

Data Structures

struct  SSLExtensionInfoContext
 

Functions

static Datum X509_NAME_field_to_text (X509_NAME *name, text *fieldName)
 
static Datum ASN1_STRING_to_text (ASN1_STRING *str)
 
 PG_FUNCTION_INFO_V1 (ssl_is_used)
 
Datum ssl_is_used (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (ssl_version)
 
Datum ssl_version (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (ssl_cipher)
 
Datum ssl_cipher (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (ssl_client_cert_present)
 
Datum ssl_client_cert_present (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (ssl_client_serial)
 
Datum ssl_client_serial (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (ssl_client_dn_field)
 
Datum ssl_client_dn_field (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (ssl_issuer_field)
 
Datum ssl_issuer_field (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (ssl_client_dn)
 
Datum ssl_client_dn (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (ssl_issuer_dn)
 
Datum ssl_issuer_dn (PG_FUNCTION_ARGS)
 
 PG_FUNCTION_INFO_V1 (ssl_extension_info)
 
Datum ssl_extension_info (PG_FUNCTION_ARGS)
 

Variables

 PG_MODULE_MAGIC
 

Function Documentation

◆ ASN1_STRING_to_text()

static Datum ASN1_STRING_to_text ( ASN1_STRING *  str)
static

Definition at line 148 of file sslinfo.c.

References cstring_to_text(), elog, ereport, errcode(), errmsg(), ERROR, pfree(), pg_any_to_server(), PG_RETURN_TEXT_P, and PG_UTF8.

Referenced by X509_NAME_field_to_text().

149 {
150  BIO *membuf;
151  size_t size;
152  char nullterm;
153  char *sp;
154  char *dp;
155  text *result;
156 
157  membuf = BIO_new(BIO_s_mem());
158  if (membuf == NULL)
159  ereport(ERROR,
160  (errcode(ERRCODE_OUT_OF_MEMORY),
161  errmsg("could not create OpenSSL BIO structure")));
162  (void) BIO_set_close(membuf, BIO_CLOSE);
163  ASN1_STRING_print_ex(membuf, str,
164  ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB)
165  | ASN1_STRFLGS_UTF8_CONVERT));
166  /* ensure null termination of the BIO's content */
167  nullterm = '\0';
168  BIO_write(membuf, &nullterm, 1);
169  size = BIO_get_mem_data(membuf, &sp);
170  dp = pg_any_to_server(sp, size - 1, PG_UTF8);
171  result = cstring_to_text(dp);
172  if (dp != sp)
173  pfree(dp);
174  if (BIO_free(membuf) != 1)
175  elog(ERROR, "could not free OpenSSL BIO structure");
176 
177  PG_RETURN_TEXT_P(result);
178 }
int errcode(int sqlerrcode)
Definition: elog.c:694
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:45
#define ereport(elevel,...)
Definition: elog.h:155
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:189
int errmsg(const char *fmt,...)
Definition: elog.c:905
#define elog(elevel,...)
Definition: elog.h:227
Definition: c.h:621
char * pg_any_to_server(const char *s, int len, int encoding)
Definition: mbutils.c:619

◆ PG_FUNCTION_INFO_V1() [1/10]

◆ PG_FUNCTION_INFO_V1() [2/10]

PG_FUNCTION_INFO_V1 ( ssl_version  )

◆ PG_FUNCTION_INFO_V1() [3/10]

PG_FUNCTION_INFO_V1 ( ssl_cipher  )

◆ PG_FUNCTION_INFO_V1() [4/10]

PG_FUNCTION_INFO_V1 ( ssl_client_cert_present  )

◆ PG_FUNCTION_INFO_V1() [5/10]

PG_FUNCTION_INFO_V1 ( ssl_client_serial  )

◆ PG_FUNCTION_INFO_V1() [6/10]

PG_FUNCTION_INFO_V1 ( ssl_client_dn_field  )

◆ PG_FUNCTION_INFO_V1() [7/10]

PG_FUNCTION_INFO_V1 ( ssl_issuer_field  )

◆ PG_FUNCTION_INFO_V1() [8/10]

PG_FUNCTION_INFO_V1 ( ssl_client_dn  )

◆ PG_FUNCTION_INFO_V1() [9/10]

PG_FUNCTION_INFO_V1 ( ssl_issuer_dn  )

◆ PG_FUNCTION_INFO_V1() [10/10]

PG_FUNCTION_INFO_V1 ( ssl_extension_info  )

◆ ssl_cipher()

Datum ssl_cipher ( PG_FUNCTION_ARGS  )

Definition at line 74 of file sslinfo.c.

References be_tls_get_cipher(), cstring_to_text(), MyProcPort, PG_FUNCTION_INFO_V1(), PG_RETURN_NULL, PG_RETURN_TEXT_P, ssl_client_cert_present(), and Port::ssl_in_use.

Referenced by ssl_version().

75 {
76  const char *cipher;
77 
78  if (!MyProcPort->ssl_in_use)
80 
81  cipher = be_tls_get_cipher(MyProcPort);
82  if (cipher == NULL)
84 
86 }
struct Port * MyProcPort
Definition: globals.c:44
bool ssl_in_use
Definition: libpq-be.h:191
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:189
const char * be_tls_get_cipher(Port *port)
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ ssl_client_cert_present()

Datum ssl_client_cert_present ( PG_FUNCTION_ARGS  )

Definition at line 97 of file sslinfo.c.

References MyProcPort, Port::peer_cert_valid, PG_FUNCTION_INFO_V1(), PG_RETURN_BOOL, and ssl_client_serial().

Referenced by ssl_cipher().

98 {
100 }
struct Port * MyProcPort
Definition: globals.c:44
bool peer_cert_valid
Definition: libpq-be.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

◆ ssl_client_dn()

Datum ssl_client_dn ( PG_FUNCTION_ARGS  )

Definition at line 298 of file sslinfo.c.

References be_tls_get_peer_subject_name(), cstring_to_text(), MyProcPort, NAMEDATALEN, Port::peer_cert_valid, PG_FUNCTION_INFO_V1(), PG_RETURN_NULL, PG_RETURN_TEXT_P, Port::ssl_in_use, and ssl_issuer_dn().

Referenced by ssl_issuer_field().

299 {
300  char subject[NAMEDATALEN];
301 
303  PG_RETURN_NULL();
304 
306 
307  if (!*subject)
308  PG_RETURN_NULL();
309 
311 }
struct Port * MyProcPort
Definition: globals.c:44
bool peer_cert_valid
Definition: libpq-be.h:193
bool ssl_in_use
Definition: libpq-be.h:191
#define NAMEDATALEN
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:189
void be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len)
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ ssl_client_dn_field()

Datum ssl_client_dn_field ( PG_FUNCTION_ARGS  )

Definition at line 235 of file sslinfo.c.

References MyProcPort, Port::peer_cert_valid, PG_FUNCTION_INFO_V1(), PG_GETARG_TEXT_PP, PG_RETURN_NULL, Port::ssl_in_use, ssl_issuer_field(), and X509_NAME_field_to_text().

Referenced by X509_NAME_field_to_text().

236 {
237  text *fieldname = PG_GETARG_TEXT_PP(0);
238  Datum result;
239 
241  PG_RETURN_NULL();
242 
243  result = X509_NAME_field_to_text(X509_get_subject_name(MyProcPort->peer), fieldname);
244 
245  if (!result)
246  PG_RETURN_NULL();
247  else
248  return result;
249 }
struct Port * MyProcPort
Definition: globals.c:44
static Datum X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
Definition: sslinfo.c:194
bool peer_cert_valid
Definition: libpq-be.h:193
bool ssl_in_use
Definition: libpq-be.h:191
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
uintptr_t Datum
Definition: postgres.h:367
Definition: c.h:621
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ ssl_client_serial()

Datum ssl_client_serial ( PG_FUNCTION_ARGS  )

Definition at line 113 of file sslinfo.c.

References be_tls_get_peer_serial(), CStringGetDatum, DirectFunctionCall3, Int32GetDatum, MyProcPort, NAMEDATALEN, numeric_in(), ObjectIdGetDatum, Port::peer_cert_valid, PG_RETURN_NULL, and Port::ssl_in_use.

Referenced by ssl_client_cert_present().

114 {
115  char decimal[NAMEDATALEN];
116  Datum result;
117 
119  PG_RETURN_NULL();
120 
122 
123  if (!*decimal)
124  PG_RETURN_NULL();
125 
127  CStringGetDatum(decimal),
128  ObjectIdGetDatum(0),
129  Int32GetDatum(-1));
130  return result;
131 }
struct Port * MyProcPort
Definition: globals.c:44
bool peer_cert_valid
Definition: libpq-be.h:193
bool ssl_in_use
Definition: libpq-be.h:191
#define NAMEDATALEN
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define CStringGetDatum(X)
Definition: postgres.h:578
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:621
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:630
uintptr_t Datum
Definition: postgres.h:367
#define Int32GetDatum(X)
Definition: postgres.h:479
void be_tls_get_peer_serial(Port *port, char *ptr, size_t len)
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ ssl_extension_info()

Datum ssl_extension_info ( PG_FUNCTION_ARGS  )

Definition at line 351 of file sslinfo.c.

References BlessTupleDesc(), BoolGetDatum, buf, FuncCallContext::call_cntr, cstring_to_text_with_len(), CStringGetTextDatum, elog, ereport, errcode(), errmsg(), ERROR, get_call_result_type(), heap_form_tuple(), HeapTupleGetDatum, FuncCallContext::max_calls, MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, MyProcPort, palloc(), PointerGetDatum, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, SSLExtensionInfoContext::tupdesc, TYPEFUNC_COMPOSITE, FuncCallContext::user_fctx, and values.

Referenced by ssl_issuer_dn().

352 {
353  X509 *cert = MyProcPort->peer;
354  FuncCallContext *funcctx;
355  int call_cntr;
356  int max_calls;
357  MemoryContext oldcontext;
359 
360  if (SRF_IS_FIRSTCALL())
361  {
362 
363  TupleDesc tupdesc;
364 
365  /* create a function context for cross-call persistence */
366  funcctx = SRF_FIRSTCALL_INIT();
367 
368  /*
369  * Switch to memory context appropriate for multiple function calls
370  */
371  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
372 
373  /* Create a user function context for cross-call persistence */
375 
376  /* Construct tuple descriptor */
377  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
378  ereport(ERROR,
379  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
380  errmsg("function returning record called in context that cannot accept type record")));
381  fctx->tupdesc = BlessTupleDesc(tupdesc);
382 
383  /* Set max_calls as a count of extensions in certificate */
384  max_calls = cert != NULL ? X509_get_ext_count(cert) : 0;
385 
386  if (max_calls > 0)
387  {
388  /* got results, keep track of them */
389  funcctx->max_calls = max_calls;
390  funcctx->user_fctx = fctx;
391  }
392  else
393  {
394  /* fast track when no results */
395  MemoryContextSwitchTo(oldcontext);
396  SRF_RETURN_DONE(funcctx);
397  }
398 
399  MemoryContextSwitchTo(oldcontext);
400  }
401 
402  /* stuff done on every call of the function */
403  funcctx = SRF_PERCALL_SETUP();
404 
405  /*
406  * Initialize per-call variables.
407  */
408  call_cntr = funcctx->call_cntr;
409  max_calls = funcctx->max_calls;
410  fctx = funcctx->user_fctx;
411 
412  /* do while there are more left to send */
413  if (call_cntr < max_calls)
414  {
415  Datum values[3];
416  bool nulls[3];
417  char *buf;
418  HeapTuple tuple;
419  Datum result;
420  BIO *membuf;
421  X509_EXTENSION *ext;
422  ASN1_OBJECT *obj;
423  int nid;
424  int len;
425 
426  /* need a BIO for this */
427  membuf = BIO_new(BIO_s_mem());
428  if (membuf == NULL)
429  ereport(ERROR,
430  (errcode(ERRCODE_OUT_OF_MEMORY),
431  errmsg("could not create OpenSSL BIO structure")));
432 
433  /* Get the extension from the certificate */
434  ext = X509_get_ext(cert, call_cntr);
435  obj = X509_EXTENSION_get_object(ext);
436 
437  /* Get the extension name */
438  nid = OBJ_obj2nid(obj);
439  if (nid == NID_undef)
440  ereport(ERROR,
441  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
442  errmsg("unknown OpenSSL extension in certificate at position %d",
443  call_cntr)));
444  values[0] = CStringGetTextDatum(OBJ_nid2sn(nid));
445  nulls[0] = false;
446 
447  /* Get the extension value */
448  if (X509V3_EXT_print(membuf, ext, 0, 0) <= 0)
449  ereport(ERROR,
450  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
451  errmsg("could not print extension value in certificate at position %d",
452  call_cntr)));
453  len = BIO_get_mem_data(membuf, &buf);
454  values[1] = PointerGetDatum(cstring_to_text_with_len(buf, len));
455  nulls[1] = false;
456 
457  /* Get critical status */
458  values[2] = BoolGetDatum(X509_EXTENSION_get_critical(ext));
459  nulls[2] = false;
460 
461  /* Build tuple */
462  tuple = heap_form_tuple(fctx->tupdesc, values, nulls);
463  result = HeapTupleGetDatum(tuple);
464 
465  if (BIO_free(membuf) != 1)
466  elog(ERROR, "could not free OpenSSL BIO structure");
467 
468  SRF_RETURN_NEXT(funcctx, result);
469  }
470 
471  /* All done */
472  SRF_RETURN_DONE(funcctx);
473 }
uint64 call_cntr
Definition: funcapi.h:65
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:207
struct Port * MyProcPort
Definition: globals.c:44
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:294
#define PointerGetDatum(X)
Definition: postgres.h:556
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:694
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:298
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:300
#define ERROR
Definition: elog.h:45
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2052
static char * buf
Definition: pg_test_fsync.c:68
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:201
uintptr_t Datum
Definition: postgres.h:367
#define BoolGetDatum(X)
Definition: postgres.h:402
#define ereport(elevel,...)
Definition: elog.h:155
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221
static Datum values[MAXATTR]
Definition: bootstrap.c:165
void * user_fctx
Definition: funcapi.h:82
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:905
#define elog(elevel,...)
Definition: elog.h:227
#define CStringGetTextDatum(s)
Definition: builtins.h:82
uint64 max_calls
Definition: funcapi.h:74
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:318
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:296

◆ ssl_is_used()

Datum ssl_is_used ( PG_FUNCTION_ARGS  )

Definition at line 43 of file sslinfo.c.

References MyProcPort, PG_FUNCTION_INFO_V1(), PG_RETURN_BOOL, Port::ssl_in_use, and ssl_version().

44 {
46 }
struct Port * MyProcPort
Definition: globals.c:44
bool ssl_in_use
Definition: libpq-be.h:191
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

◆ ssl_issuer_dn()

Datum ssl_issuer_dn ( PG_FUNCTION_ARGS  )

Definition at line 325 of file sslinfo.c.

References be_tls_get_peer_issuer_name(), cstring_to_text(), MyProcPort, NAMEDATALEN, Port::peer_cert_valid, PG_FUNCTION_INFO_V1(), PG_RETURN_NULL, PG_RETURN_TEXT_P, ssl_extension_info(), and Port::ssl_in_use.

Referenced by ssl_client_dn().

326 {
327  char issuer[NAMEDATALEN];
328 
330  PG_RETURN_NULL();
331 
333 
334  if (!*issuer)
335  PG_RETURN_NULL();
336 
338 }
struct Port * MyProcPort
Definition: globals.c:44
bool peer_cert_valid
Definition: libpq-be.h:193
bool ssl_in_use
Definition: libpq-be.h:191
#define NAMEDATALEN
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:189
void be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len)
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ ssl_issuer_field()

Datum ssl_issuer_field ( PG_FUNCTION_ARGS  )

Definition at line 270 of file sslinfo.c.

References MyProcPort, PG_FUNCTION_INFO_V1(), PG_GETARG_TEXT_PP, PG_RETURN_NULL, ssl_client_dn(), and X509_NAME_field_to_text().

Referenced by ssl_client_dn_field().

271 {
272  text *fieldname = PG_GETARG_TEXT_PP(0);
273  Datum result;
274 
275  if (!(MyProcPort->peer))
276  PG_RETURN_NULL();
277 
278  result = X509_NAME_field_to_text(X509_get_issuer_name(MyProcPort->peer), fieldname);
279 
280  if (!result)
281  PG_RETURN_NULL();
282  else
283  return result;
284 }
struct Port * MyProcPort
Definition: globals.c:44
static Datum X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
Definition: sslinfo.c:194
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
uintptr_t Datum
Definition: postgres.h:367
Definition: c.h:621
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ ssl_version()

Datum ssl_version ( PG_FUNCTION_ARGS  )

Definition at line 54 of file sslinfo.c.

References be_tls_get_version(), cstring_to_text(), MyProcPort, PG_FUNCTION_INFO_V1(), PG_RETURN_NULL, PG_RETURN_TEXT_P, ssl_cipher(), and Port::ssl_in_use.

Referenced by ssl_is_used().

55 {
56  const char *version;
57 
58  if (!MyProcPort->ssl_in_use)
60 
61  version = be_tls_get_version(MyProcPort);
62  if (version == NULL)
64 
66 }
struct Port * MyProcPort
Definition: globals.c:44
bool ssl_in_use
Definition: libpq-be.h:191
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:189
const char * be_tls_get_version(Port *port)
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ X509_NAME_field_to_text()

static Datum X509_NAME_field_to_text ( X509_NAME *  name,
text fieldName 
)
static

Definition at line 194 of file sslinfo.c.

References ASN1_STRING_to_text(), ereport, errcode(), errmsg(), ERROR, pfree(), PG_FUNCTION_INFO_V1(), ssl_client_dn_field(), and text_to_cstring().

Referenced by ssl_client_dn_field(), and ssl_issuer_field().

195 {
196  char *string_fieldname;
197  int nid,
198  index;
199  ASN1_STRING *data;
200 
201  string_fieldname = text_to_cstring(fieldName);
202  nid = OBJ_txt2nid(string_fieldname);
203  if (nid == NID_undef)
204  ereport(ERROR,
205  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
206  errmsg("invalid X.509 field name: \"%s\"",
207  string_fieldname)));
208  pfree(string_fieldname);
209  index = X509_NAME_get_index_by_NID(name, nid, -1);
210  if (index < 0)
211  return (Datum) 0;
212  data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, index));
213  return ASN1_STRING_to_text(data);
214 }
int errcode(int sqlerrcode)
Definition: elog.c:694
Definition: type.h:89
static Datum ASN1_STRING_to_text(ASN1_STRING *str)
Definition: sslinfo.c:148
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:45
uintptr_t Datum
Definition: postgres.h:367
#define ereport(elevel,...)
Definition: elog.h:155
const char * name
Definition: encode.c:515
char * text_to_cstring(const text *t)
Definition: varlena.c:222
int errmsg(const char *fmt,...)
Definition: elog.c:905

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 22 of file sslinfo.c.