Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "postgres.h"
00011 #include "fmgr.h"
00012 #include "utils/numeric.h"
00013 #include "libpq/libpq-be.h"
00014 #include "miscadmin.h"
00015 #include "utils/builtins.h"
00016 #include "mb/pg_wchar.h"
00017
00018 #include <openssl/x509.h>
00019 #include <openssl/asn1.h>
00020
00021
00022 PG_MODULE_MAGIC;
00023
00024
00025 Datum ssl_is_used(PG_FUNCTION_ARGS);
00026 Datum ssl_version(PG_FUNCTION_ARGS);
00027 Datum ssl_cipher(PG_FUNCTION_ARGS);
00028 Datum ssl_client_cert_present(PG_FUNCTION_ARGS);
00029 Datum ssl_client_serial(PG_FUNCTION_ARGS);
00030 Datum ssl_client_dn_field(PG_FUNCTION_ARGS);
00031 Datum ssl_issuer_field(PG_FUNCTION_ARGS);
00032 Datum ssl_client_dn(PG_FUNCTION_ARGS);
00033 Datum ssl_issuer_dn(PG_FUNCTION_ARGS);
00034 Datum X509_NAME_field_to_text(X509_NAME *name, text *fieldName);
00035 Datum X509_NAME_to_text(X509_NAME *name);
00036 Datum ASN1_STRING_to_text(ASN1_STRING *str);
00037
00038
00039
00040
00041
00042
00043
00044
00045 PG_FUNCTION_INFO_V1(ssl_is_used);
00046 Datum
00047 ssl_is_used(PG_FUNCTION_ARGS)
00048 {
00049 PG_RETURN_BOOL(MyProcPort->ssl != NULL);
00050 }
00051
00052
00053
00054
00055
00056 PG_FUNCTION_INFO_V1(ssl_version);
00057 Datum
00058 ssl_version(PG_FUNCTION_ARGS)
00059 {
00060 if (MyProcPort->ssl == NULL)
00061 PG_RETURN_NULL();
00062 PG_RETURN_TEXT_P(cstring_to_text(SSL_get_version(MyProcPort->ssl)));
00063 }
00064
00065
00066
00067
00068
00069 PG_FUNCTION_INFO_V1(ssl_cipher);
00070 Datum
00071 ssl_cipher(PG_FUNCTION_ARGS)
00072 {
00073 if (MyProcPort->ssl == NULL)
00074 PG_RETURN_NULL();
00075 PG_RETURN_TEXT_P(cstring_to_text(SSL_get_cipher(MyProcPort->ssl)));
00076 }
00077
00078
00079
00080
00081
00082
00083
00084
00085 PG_FUNCTION_INFO_V1(ssl_client_cert_present);
00086 Datum
00087 ssl_client_cert_present(PG_FUNCTION_ARGS)
00088 {
00089 PG_RETURN_BOOL(MyProcPort->peer != NULL);
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 PG_FUNCTION_INFO_V1(ssl_client_serial);
00102 Datum
00103 ssl_client_serial(PG_FUNCTION_ARGS)
00104 {
00105 Datum result;
00106 Port *port = MyProcPort;
00107 X509 *peer = port->peer;
00108 ASN1_INTEGER *serial = NULL;
00109 BIGNUM *b;
00110 char *decimal;
00111
00112 if (!peer)
00113 PG_RETURN_NULL();
00114 serial = X509_get_serialNumber(peer);
00115 b = ASN1_INTEGER_to_BN(serial, NULL);
00116 decimal = BN_bn2dec(b);
00117
00118 BN_free(b);
00119 result = DirectFunctionCall3(numeric_in,
00120 CStringGetDatum(decimal),
00121 ObjectIdGetDatum(0),
00122 Int32GetDatum(-1));
00123 OPENSSL_free(decimal);
00124 return result;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 Datum
00142 ASN1_STRING_to_text(ASN1_STRING *str)
00143 {
00144 BIO *membuf;
00145 size_t size;
00146 char nullterm;
00147 char *sp;
00148 char *dp;
00149 text *result;
00150
00151 membuf = BIO_new(BIO_s_mem());
00152 (void) BIO_set_close(membuf, BIO_CLOSE);
00153 ASN1_STRING_print_ex(membuf, str,
00154 ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB)
00155 | ASN1_STRFLGS_UTF8_CONVERT));
00156
00157 nullterm = '\0';
00158 BIO_write(membuf, &nullterm, 1);
00159 size = BIO_get_mem_data(membuf, &sp);
00160 dp = (char *) pg_do_encoding_conversion((unsigned char *) sp,
00161 size - 1,
00162 PG_UTF8,
00163 GetDatabaseEncoding());
00164 result = cstring_to_text(dp);
00165 if (dp != sp)
00166 pfree(dp);
00167 BIO_free(membuf);
00168
00169 PG_RETURN_TEXT_P(result);
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 Datum
00186 X509_NAME_field_to_text(X509_NAME *name, text *fieldName)
00187 {
00188 char *string_fieldname;
00189 int nid,
00190 index;
00191 ASN1_STRING *data;
00192
00193 string_fieldname = text_to_cstring(fieldName);
00194 nid = OBJ_txt2nid(string_fieldname);
00195 if (nid == NID_undef)
00196 ereport(ERROR,
00197 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00198 errmsg("invalid X.509 field name: \"%s\"",
00199 string_fieldname)));
00200 pfree(string_fieldname);
00201 index = X509_NAME_get_index_by_NID(name, nid, -1);
00202 if (index < 0)
00203 return (Datum) 0;
00204 data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, index));
00205 return ASN1_STRING_to_text(data);
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 PG_FUNCTION_INFO_V1(ssl_client_dn_field);
00226 Datum
00227 ssl_client_dn_field(PG_FUNCTION_ARGS)
00228 {
00229 text *fieldname = PG_GETARG_TEXT_P(0);
00230 Datum result;
00231
00232 if (!(MyProcPort->peer))
00233 PG_RETURN_NULL();
00234
00235 result = X509_NAME_field_to_text(X509_get_subject_name(MyProcPort->peer), fieldname);
00236
00237 if (!result)
00238 PG_RETURN_NULL();
00239 else
00240 return result;
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 PG_FUNCTION_INFO_V1(ssl_issuer_field);
00261 Datum
00262 ssl_issuer_field(PG_FUNCTION_ARGS)
00263 {
00264 text *fieldname = PG_GETARG_TEXT_P(0);
00265 Datum result;
00266
00267 if (!(MyProcPort->peer))
00268 PG_RETURN_NULL();
00269
00270 result = X509_NAME_field_to_text(X509_get_issuer_name(MyProcPort->peer), fieldname);
00271
00272 if (!result)
00273 PG_RETURN_NULL();
00274 else
00275 return result;
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 Datum
00291 X509_NAME_to_text(X509_NAME *name)
00292 {
00293 BIO *membuf = BIO_new(BIO_s_mem());
00294 int i,
00295 nid,
00296 count = X509_NAME_entry_count(name);
00297 X509_NAME_ENTRY *e;
00298 ASN1_STRING *v;
00299 const char *field_name;
00300 size_t size;
00301 char nullterm;
00302 char *sp;
00303 char *dp;
00304 text *result;
00305
00306 (void) BIO_set_close(membuf, BIO_CLOSE);
00307 for (i = 0; i < count; i++)
00308 {
00309 e = X509_NAME_get_entry(name, i);
00310 nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e));
00311 v = X509_NAME_ENTRY_get_data(e);
00312 field_name = OBJ_nid2sn(nid);
00313 if (!field_name)
00314 field_name = OBJ_nid2ln(nid);
00315 BIO_printf(membuf, "/%s=", field_name);
00316 ASN1_STRING_print_ex(membuf, v,
00317 ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB)
00318 | ASN1_STRFLGS_UTF8_CONVERT));
00319 }
00320
00321
00322 nullterm = '\0';
00323 BIO_write(membuf, &nullterm, 1);
00324 size = BIO_get_mem_data(membuf, &sp);
00325 dp = (char *) pg_do_encoding_conversion((unsigned char *) sp,
00326 size - 1,
00327 PG_UTF8,
00328 GetDatabaseEncoding());
00329 result = cstring_to_text(dp);
00330 if (dp != sp)
00331 pfree(dp);
00332 BIO_free(membuf);
00333
00334 PG_RETURN_TEXT_P(result);
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 PG_FUNCTION_INFO_V1(ssl_client_dn);
00348 Datum
00349 ssl_client_dn(PG_FUNCTION_ARGS)
00350 {
00351 if (!(MyProcPort->peer))
00352 PG_RETURN_NULL();
00353 return X509_NAME_to_text(X509_get_subject_name(MyProcPort->peer));
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 PG_FUNCTION_INFO_V1(ssl_issuer_dn);
00367 Datum
00368 ssl_issuer_dn(PG_FUNCTION_ARGS)
00369 {
00370 if (!(MyProcPort->peer))
00371 PG_RETURN_NULL();
00372 return X509_NAME_to_text(X509_get_issuer_name(MyProcPort->peer));
00373 }