diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 307b805..6b53e37 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -181,6 +181,19 @@ static const PQconninfoOption PQconninfoOptions[] = { {"sslmode", "PGSSLMODE", DefaultSSLMode, NULL, "SSL-Mode", "", 8}, /* sizeof("disable") == 8 */ + {"sslcert", "PGSSLCERT", NULL, NULL, + "SSL-Client-Cert", "", 64}, + + {"sslkey", "PGSSLKEY", NULL, NULL, + "SSL-Client-Key", "", 64}, + + {"sslrootcert", "PGROOTCERT", NULL, NULL, + "SSL-Root-Certificate", "", 64}, + + {"sslcrl", "PGSSLCRL", NULL, NULL, + "SSL-Revocation-List", "", 64}, + + #if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI) /* Kerberos and GSSAPI authentication support specifying the service name */ {"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL, @@ -413,6 +426,14 @@ connectOptions1(PGconn *conn, const char *conninfo) conn->connect_timeout = tmp ? strdup(tmp) : NULL; tmp = conninfo_getval(connOptions, "sslmode"); conn->sslmode = tmp ? strdup(tmp) : NULL; + tmp = conninfo_getval(connOptions, "sslkey"); + conn->sslkey = tmp ? strdup(tmp) : NULL; + tmp = conninfo_getval(connOptions, "sslcert"); + conn->sslcert = tmp ? strdup(tmp) : NULL; + tmp = conninfo_getval(connOptions, "sslrootcert"); + conn->sslrootcert = tmp ? strdup(tmp) : NULL; + tmp = conninfo_getval(connOptions, "sslcrl"); + conn->sslcrl = tmp ? strdup(tmp) : NULL; #ifdef USE_SSL tmp = conninfo_getval(connOptions, "requiressl"); if (tmp && tmp[0] == '1') diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c index a61dbfb..a4fdba1 100644 --- a/src/interfaces/libpq/fe-secure.c +++ b/src/interfaces/libpq/fe-secure.c @@ -599,7 +599,11 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) } /* read the user certificate */ - snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE); + + if (conn->sslcert) + strncpy(fnbuf, conn->sslcert, sizeof(fnbuf)); + else + snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE); /* * OpenSSL <= 0.9.8 lacks error stack handling, which means it's likely to @@ -650,7 +654,7 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) BIO_free(bio); #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) - if (getenv("PGSSLKEY")) + if (getenv("PGSSLKEY") && !conn->sslkey) { /* read the user key from engine */ char *engine_env = getenv("PGSSLKEY"); @@ -702,7 +706,11 @@ client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey) #endif /* use PGSSLKEY */ { /* read the user key from file */ - snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE); + if (conn->sslkey) + strncpy(fnbuf, conn->sslkey, sizeof(fnbuf)); + else + snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE); + if (stat(fnbuf, &buf) != 0) { printfPQExpBuffer(&conn->errorMessage, @@ -904,7 +912,11 @@ initialize_SSL(PGconn *conn) /* Set up to verify server cert, if root.crt is present */ if (pqGetHomeDirectory(homedir, sizeof(homedir))) { - snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE); + if (conn->ssltrustcrt) + strncpy(fnbuf, conn->ssltrustcrt, sizeof(fnbuf)); + else + snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE); + if (stat(fnbuf, &buf) == 0) { X509_STORE *cvstore; @@ -922,8 +934,13 @@ initialize_SSL(PGconn *conn) if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL) { + if (conn->sslcrl) + strncpy(fnbuf, conn->sslcrl, sizeof(fnbuf)); + else + snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CRL_FILE); + /* setting the flags to check against the complete CRL chain */ - if (X509_STORE_load_locations(cvstore, ROOT_CRL_FILE, NULL) != 0) + if (X509_STORE_load_locations(cvstore, fnbuf, NULL) != 0) /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */ #ifdef X509_V_FLAG_CRL_CHECK X509_STORE_set_flags(cvstore, diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index 4af1388..f47e50e 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -293,6 +293,11 @@ struct pg_conn char *pgpass; bool pgpass_from_client; /* did password come from connect args? */ char *sslmode; /* SSL mode (require,prefer,allow,disable) */ + char *sslkey; /* client key filename */ + char *sslcert; /* client certificate filename */ + char *sslrootcert; /* root certificate filename */ + char *sslcrl; /* certificate revocation list filename */ + #if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI) char *krbsrvname; /* Kerberos service name */ #endif