diff options
Diffstat (limited to 'src/backend/libpq/be-secure-openssl.c')
| -rw-r--r-- | src/backend/libpq/be-secure-openssl.c | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c index 5ce3f27855..40deab13c7 100644 --- a/src/backend/libpq/be-secure-openssl.c +++ b/src/backend/libpq/be-secure-openssl.c @@ -551,22 +551,26 @@ aloop: /* Get client certificate, if available. */ port->peer = SSL_get_peer_certificate(port->ssl); - /* and extract the Common Name from it. */ + /* and extract the Common Name and Distinguished Name from it. */ port->peer_cn = NULL; + port->peer_dn = NULL; port->peer_cert_valid = false; if (port->peer != NULL) { int len; + X509_NAME *x509name = X509_get_subject_name(port->peer); + char *peer_dn; + BIO *bio = NULL; + BUF_MEM *bio_buf = NULL; - len = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer), - NID_commonName, NULL, 0); + len = X509_NAME_get_text_by_NID(x509name, NID_commonName, NULL, 0); if (len != -1) { char *peer_cn; peer_cn = MemoryContextAlloc(TopMemoryContext, len + 1); - r = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer), - NID_commonName, peer_cn, len + 1); + r = X509_NAME_get_text_by_NID(x509name, NID_commonName, peer_cn, + len + 1); peer_cn[len] = '\0'; if (r != len) { @@ -590,6 +594,47 @@ aloop: port->peer_cn = peer_cn; } + + bio = BIO_new(BIO_s_mem()); + if (!bio) + { + pfree(port->peer_cn); + port->peer_cn = NULL; + return -1; + } + /* + * RFC2253 is the closest thing to an accepted standard format for + * DNs. We have documented how to produce this format from a + * certificate. It uses commas instead of slashes for delimiters, + * which make regular expression matching a bit easier. Also note that + * it prints the Subject fields in reverse order. + */ + X509_NAME_print_ex(bio, x509name, 0, XN_FLAG_RFC2253); + if (BIO_get_mem_ptr(bio, &bio_buf) <= 0) + { + BIO_free(bio); + pfree(port->peer_cn); + port->peer_cn = NULL; + return -1; + } + peer_dn = MemoryContextAlloc(TopMemoryContext, bio_buf->length + 1); + memcpy(peer_dn, bio_buf->data, bio_buf->length); + len = bio_buf->length; + BIO_free(bio); + peer_dn[len] = '\0'; + if (len != strlen(peer_dn)) + { + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("SSL certificate's distinguished name contains embedded null"))); + pfree(peer_dn); + pfree(port->peer_cn); + port->peer_cn = NULL; + return -1; + } + + port->peer_dn = peer_dn; + port->peer_cert_valid = true; } @@ -618,6 +663,12 @@ be_tls_close(Port *port) pfree(port->peer_cn); port->peer_cn = NULL; } + + if (port->peer_dn) + { + pfree(port->peer_dn); + port->peer_dn = NULL; + } } ssize_t |
