Tom Lane wrote: > BTW, doesn't this patch leak memory at freePGconn() time?
Doh -- right, fixed. > I also think that more of it should be inside #ifdef USE_SSL --- ie, > the options should be treated like requiressl not sslmode, and not > exist in a non-SSL build. I wondered about that too, and couldn't make up my mind about it. This patch does things that way. Something that's bothering me is that PGSSLKEY is inconsistent with the sslkey conninfo parameter. PGSSLKEY specifies an engine (basically a driver for specialized hardware AFAICT) from which the key is to be loaded, but sslkey is a simple filename. This means that there's no way to load a key from hardware if you want to specify it per connection. Not that I have any such hardware, but it looks bogus. Obviously one still wants to be able to specify a different file name from the default; I tried to see if there's any way to load an engine that would load the key from a file, but could not extract any sense from the man page: http://www.openssl.org/docs/crypto/engine.html Maybe this means that we should provide separate parameters, say "sslkey" and "sslkeyfile", and a new env var PGSSLKEYFILE. Thoughts? Am I overengineering this stuff? -- Alvaro Herrera http://www.CommandPrompt.com/ PostgreSQL Replication, Consulting, Custom Development, 24x7 support
Index: doc/src/sgml/libpq.sgml =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/doc/src/sgml/libpq.sgml,v retrieving revision 1.260 diff -c -p -r1.260 libpq.sgml *** doc/src/sgml/libpq.sgml 27 Jun 2008 02:44:31 -0000 1.260 --- doc/src/sgml/libpq.sgml 1 Aug 2008 20:29:04 -0000 *************** *** 281,286 **** --- 281,330 ---- </varlistentry> <varlistentry> + <term><literal>sslcert</literal></term> + <listitem> + <para> + This parameter specifies the file name of the client SSL + certificate. This option is only available if + <productname>PostgreSQL</> is compiled with SSL support. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>sslkey</literal></term> + <listitem> + <para> + This parameter specifies the file name of the client SSL key. + This option is only available if <productname>PostgreSQL</> is + compiled with SSL support. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>sslrootcert</literal></term> + <listitem> + <para> + This parameter specifies the file name of the root SSL certificate. + This option is only available if <productname>PostgreSQL</> is + compiled with SSL support. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>sslcrl</literal></term> + <listitem> + <para> + This parameter specifies the file name of the SSL certificate + revocation list (CRL). This option is only available if + <productname>PostgreSQL</> is compiled with SSL support. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><literal>krbsrvname</literal></term> <listitem> <para> *************** defaultNoticeProcessor(void *arg, const *** 4911,4916 **** --- 4955,4982 ---- <listitem> <para> <indexterm> + <primary><envar>PGROOTCERT</envar></primary> + </indexterm> + <envar>PGROOTCERT</envar> specifies the file name where the SSL + root certificate is stored. This can be overridden by the + <literal>sslrootcert</literal> connection parameter. + </para> + </listitem> + + <listitem> + <para> + <indexterm> + <primary><envar>PGSSLCRL</envar></primary> + </indexterm> + <envar>PGSSLCRL</envar> specifies the file name where the SSL certificate + revocation list is stored. This can be overridden by the + <literal>sslcrl</literal> connection parameter. + </para> + </listitem> + + <listitem> + <para> + <indexterm> <primary><envar>PGKRBSRVNAME</envar></primary> </indexterm> <envar>PGKRBSRVNAME</envar> sets the Kerberos service name to use Index: src/interfaces/libpq/fe-connect.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/interfaces/libpq/fe-connect.c,v retrieving revision 1.359 diff -c -p -r1.359 fe-connect.c *** src/interfaces/libpq/fe-connect.c 29 May 2008 22:02:44 -0000 1.359 --- src/interfaces/libpq/fe-connect.c 1 Aug 2008 20:13:49 -0000 *************** static const PQconninfoOption PQconninfo *** 181,186 **** --- 181,201 ---- {"sslmode", "PGSSLMODE", DefaultSSLMode, NULL, "SSL-Mode", "", 8}, /* sizeof("disable") == 8 */ + /* These parameters are only present in an SSL-enabled build. */ + #ifdef USE_SSL + {"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}, + #endif + #if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI) /* Kerberos and GSSAPI authentication support specifying the service name */ {"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL, *************** connectOptions1(PGconn *conn, const char *** 414,419 **** --- 429,442 ---- tmp = conninfo_getval(connOptions, "sslmode"); conn->sslmode = tmp ? strdup(tmp) : NULL; #ifdef USE_SSL + 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; tmp = conninfo_getval(connOptions, "requiressl"); if (tmp && tmp[0] == '1') { *************** freePGconn(PGconn *conn) *** 1996,2001 **** --- 2019,2034 ---- free(conn->pgpass); if (conn->sslmode) free(conn->sslmode); + #ifdef USE_SSL + if (conn->sslcert) + free(conn->sslcert); + if (conn->sslkey) + free(conn->sslkey); + if (conn->sslrootcert) + free(conn->sslrootcert); + if (conn->sslcrl) + free(conn->sslcrl); + #endif #if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI) if (conn->krbsrvname) free(conn->krbsrvname); Index: src/interfaces/libpq/fe-secure.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/interfaces/libpq/fe-secure.c,v retrieving revision 1.105 diff -c -p -r1.105 fe-secure.c *** src/interfaces/libpq/fe-secure.c 16 May 2008 18:30:53 -0000 1.105 --- src/interfaces/libpq/fe-secure.c 1 Aug 2008 20:31:25 -0000 *************** client_cert_cb(SSL *ssl, X509 **x509, EV *** 599,605 **** } /* read the user certificate */ ! snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_CERT_FILE); /* * OpenSSL <= 0.9.8 lacks error stack handling, which means it's likely to --- 599,608 ---- } /* read the user certificate */ ! 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 *************** client_cert_cb(SSL *ssl, X509 **x509, EV *** 650,656 **** BIO_free(bio); #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) ! if (getenv("PGSSLKEY")) { /* read the user key from engine */ char *engine_env = getenv("PGSSLKEY"); --- 653,659 ---- BIO_free(bio); #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) ! if (getenv("PGSSLKEY") && !conn->sslkey) { /* read the user key from engine */ char *engine_env = getenv("PGSSLKEY"); *************** client_cert_cb(SSL *ssl, X509 **x509, EV *** 702,708 **** #endif /* use PGSSLKEY */ { /* read the user key from file */ ! snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE); if (stat(fnbuf, &buf) != 0) { printfPQExpBuffer(&conn->errorMessage, --- 705,715 ---- #endif /* use PGSSLKEY */ { /* read the user key from 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, *************** initialize_SSL(PGconn *conn) *** 904,910 **** /* 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 (stat(fnbuf, &buf) == 0) { X509_STORE *cvstore; --- 911,921 ---- /* Set up to verify server cert, if root.crt is present */ if (pqGetHomeDirectory(homedir, sizeof(homedir))) { ! if (conn->sslrootcert) ! strncpy(fnbuf, conn->sslrootcert, sizeof(fnbuf)); ! else ! snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, ROOT_CERT_FILE); ! if (stat(fnbuf, &buf) == 0) { X509_STORE *cvstore; *************** initialize_SSL(PGconn *conn) *** 922,929 **** if ((cvstore = SSL_CTX_get_cert_store(SSL_context)) != NULL) { /* setting the flags to check against the complete CRL chain */ ! if (X509_STORE_load_locations(cvstore, ROOT_CRL_FILE, NULL) != 0) /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */ #ifdef X509_V_FLAG_CRL_CHECK X509_STORE_set_flags(cvstore, --- 933,945 ---- 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, 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, Index: src/interfaces/libpq/libpq-int.h =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/interfaces/libpq/libpq-int.h,v retrieving revision 1.131 diff -c -p -r1.131 libpq-int.h *** src/interfaces/libpq/libpq-int.h 29 May 2008 22:02:44 -0000 1.131 --- src/interfaces/libpq/libpq-int.h 1 Aug 2008 20:30:24 -0000 *************** struct pg_conn *** 293,298 **** --- 293,305 ---- char *pgpass; bool pgpass_from_client; /* did password come from connect args? */ char *sslmode; /* SSL mode (require,prefer,allow,disable) */ + #ifdef USE_SSL + char *sslkey; /* client key filename */ + char *sslcert; /* client certificate filename */ + char *sslrootcert; /* root certificate filename */ + char *sslcrl; /* certificate revocation list filename */ + #endif + #if defined(KRB5) || defined(ENABLE_GSS) || defined(ENABLE_SSPI) char *krbsrvname; /* Kerberos service name */ #endif
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers