18
18
#include "libpq/libpq-be.h"
19
19
#include "miscadmin.h"
20
20
#include "utils/builtins.h"
21
+ #include "utils/timestamp.h"
21
22
22
23
/*
23
24
* On Windows, <wincrypt.h> includes a #define for X509_NAME, which breaks our
@@ -34,6 +35,7 @@ PG_MODULE_MAGIC;
34
35
35
36
static Datum X509_NAME_field_to_text (X509_NAME * name ,text * fieldName );
36
37
static Datum ASN1_STRING_to_text (ASN1_STRING * str );
38
+ static Datum ASN1_TIME_to_timestamp (ASN1_TIME * time );
37
39
38
40
/*
39
41
* Function context for data persisting over repeated calls.
@@ -225,6 +227,39 @@ X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
225
227
}
226
228
227
229
230
+ /*
231
+ * Converts OpenSSL ASN1_TIME structure into timestamp
232
+ *
233
+ * Parameter: time - OpenSSL ASN1_TIME structure.
234
+ *
235
+ * Returns Datum, which can be directly returned from a C language SQL
236
+ * function.
237
+ */
238
+ static Datum
239
+ ASN1_TIME_to_timestamp (ASN1_TIME * time )
240
+ {
241
+ struct tm tm_time ;
242
+ struct pg_tm pgtm_time ;
243
+ Timestamp ts ;
244
+
245
+ ASN1_TIME_to_tm (time ,& tm_time );
246
+
247
+ pgtm_time .tm_sec = tm_time .tm_sec ;
248
+ pgtm_time .tm_min = tm_time .tm_min ;
249
+ pgtm_time .tm_hour = tm_time .tm_hour ;
250
+ pgtm_time .tm_mday = tm_time .tm_mday ;
251
+ pgtm_time .tm_mon = tm_time .tm_mon + 1 ;
252
+ pgtm_time .tm_year = tm_time .tm_year + 1900 ;
253
+
254
+ if (tm2timestamp (& pgtm_time ,0 ,NULL ,& ts ))
255
+ ereport (ERROR ,
256
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
257
+ errmsg ("failed to convert tm to timestamp" )));
258
+
259
+ PG_RETURN_TIMESTAMP (ts );
260
+ }
261
+
262
+
228
263
/*
229
264
* Returns specified field of client certificate distinguished name
230
265
*
@@ -482,3 +517,35 @@ ssl_extension_info(PG_FUNCTION_ARGS)
482
517
/* All done */
483
518
SRF_RETURN_DONE (funcctx );
484
519
}
520
+
521
+ /*
522
+ * Returns current client certificate notBefore timestamp in
523
+ * timestamp data type
524
+ */
525
+ PG_FUNCTION_INFO_V1 (ssl_client_get_notbefore );
526
+ Datum
527
+ ssl_client_get_notbefore (PG_FUNCTION_ARGS )
528
+ {
529
+ X509 * cert = MyProcPort -> peer ;
530
+
531
+ if (!MyProcPort -> ssl_in_use || !MyProcPort -> peer_cert_valid )
532
+ PG_RETURN_NULL ();
533
+
534
+ return ASN1_TIME_to_timestamp (X509_get_notBefore (cert ));
535
+ }
536
+
537
+ /*
538
+ * Returns current client certificate notAfter timestamp in
539
+ * timestamp data type
540
+ */
541
+ PG_FUNCTION_INFO_V1 (ssl_client_get_notafter );
542
+ Datum
543
+ ssl_client_get_notafter (PG_FUNCTION_ARGS )
544
+ {
545
+ X509 * cert = MyProcPort -> peer ;
546
+
547
+ if (!MyProcPort -> ssl_in_use || !MyProcPort -> peer_cert_valid )
548
+ PG_RETURN_NULL ();
549
+
550
+ return ASN1_TIME_to_timestamp (X509_get_notAfter (cert ));
551
+ }