On ons, 2012-02-08 at 09:16 +0100, Magnus Hagander wrote:
> > My best idea at the moment is that we should set these parameters to
> > empty by default, and make users point them to existing files if they
> > want to use that functionality.  Comments?
> >
> 
> +1. Anybody who actually cares about setting up security is likely not
> going to rely on defaults anyway - and is certainly going to review
> whatever they are. So there should be no big problem there. 

Updated patch to reflect this.
*** i/doc/src/sgml/config.sgml
--- w/doc/src/sgml/config.sgml
***************
*** 668,673 **** SET ENABLE_SEQSCAN TO OFF;
--- 668,737 ----
        </listitem>
       </varlistentry>
  
+      <varlistentry id="guc-ssl-ca-file" xreflabel="ssl_ca_file">
+       <term><varname>ssl_ca_file</varname> (<type>string</type>)</term>
+       <indexterm>
+        <primary><varname>ssl_ca_file</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+         Specifies the name of the file containing the SSL server certificate
+         authority (CA).  The default is empty, meaning no CA file is loaded,
+         and client certificate verification is not performed.  (In previous
+         releases of PostgreSQL, the name of this file was hard-coded
+         as <filename>root.crt</filename>.)  Relative paths are relative to the
+         data directory.  This parameter can only be set at server start.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry id="guc-ssl-cert-file" xreflabel="ssl_cert_file">
+       <term><varname>ssl_cert_file</varname> (<type>string</type>)</term>
+       <indexterm>
+        <primary><varname>ssl_cert_file</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+         Specifies the name of the file containing the SSL server certificate.
+         The default is <filename>server.crt</filename>.  Relative paths are
+         relative to the data directory.  This parameter can only be set at
+         server start.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry id="guc-ssl-crl-file" xreflabel="ssl_crl_file">
+       <term><varname>ssl_crl_file</varname> (<type>string</type>)</term>
+       <indexterm>
+        <primary><varname>ssl_crl_file</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+         Specifies the name of the file containing the SSL server certificate
+         revocation list (CRL).  The default is empty, meaning no CRL file is
+         loaded.  (In previous releases of PostgreSQL, the name of this file was
+         hard-coded as <filename>root.crl</filename>.)  Relative paths are
+         relative to the data directory.  This parameter can only be set at
+         server start.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry id="guc-ssl-key-file" xreflabel="ssl_key_file">
+       <term><varname>ssl_key_file</varname> (<type>string</type>)</term>
+       <indexterm>
+        <primary><varname>ssl_key_file</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+         Specifies the name of the file containing the SSL server private key.
+         The default is <filename>server.key</filename>.  Relative paths are
+         relative to the data directory.  This parameter can only be set at
+         server start.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
       <varlistentry id="guc-ssl-renegotiation-limit" xreflabel="ssl_renegotiation_limit">
        <term><varname>ssl_renegotiation_limit</varname> (<type>integer</type>)</term>
        <indexterm>
*** i/doc/src/sgml/runtime.sgml
--- w/doc/src/sgml/runtime.sgml
***************
*** 1831,1840 **** pg_dumpall -p 5432 | psql -d postgres -p 5433
     SSL certificates and make sure that clients check the server's certificate.
     To do that, the server
     must be configured to accept only <literal>hostssl</> connections (<xref
!    linkend="auth-pg-hba-conf">) and have SSL
!    <filename>server.key</filename> (key) and
!    <filename>server.crt</filename> (certificate) files (<xref
!    linkend="ssl-tcp">). The TCP client must connect using
     <literal>sslmode=verify-ca</> or
     <literal>verify-full</> and have the appropriate root certificate
     file installed (<xref linkend="libpq-connect">).
--- 1831,1838 ----
     SSL certificates and make sure that clients check the server's certificate.
     To do that, the server
     must be configured to accept only <literal>hostssl</> connections (<xref
!    linkend="auth-pg-hba-conf">) and have SSL key and certificate files
!    (<xref linkend="ssl-tcp">). The TCP client must connect using
     <literal>sslmode=verify-ca</> or
     <literal>verify-full</> and have the appropriate root certificate
     file installed (<xref linkend="libpq-connect">).
***************
*** 2053,2062 **** pg_dumpall -p 5432 | psql -d postgres -p 5433
    </note>
  
    <para>
!    To start in <acronym>SSL</> mode, the files <filename>server.crt</>
!    and <filename>server.key</> must exist in the server's data directory.
!    These files should contain the server certificate and private key,
!    respectively.
     On Unix systems, the permissions on <filename>server.key</filename> must
     disallow any access to world or group; achieve this by the command
     <command>chmod 0600 server.key</command>.
--- 2051,2062 ----
    </note>
  
    <para>
!    To start in <acronym>SSL</> mode, files containing the server certificate
!    and private key must exist.  By default, these files are expected to be
!    named <filename>server.crt</> and <filename>server.key</>, respectively, in
!    the server's data directory, but other names and locations can be specified
!    using the configuration parameters <xref linkend="guc-ssl-cert-file">
!    and <xref linkend="guc-ssl-key-file">.
     On Unix systems, the permissions on <filename>server.key</filename> must
     disallow any access to world or group; achieve this by the command
     <command>chmod 0600 server.key</command>.
***************
*** 2144,2170 **** pg_dumpall -p 5432 | psql -d postgres -p 5433
      <tbody>
  
       <row>
!       <entry><filename>$PGDATA/server.crt</></entry>
        <entry>server certificate</entry>
        <entry>sent to client to indicate server's identity</entry>
       </row>
  
       <row>
!       <entry><filename>$PGDATA/server.key</></entry>
        <entry>server private key</entry>
        <entry>proves server certificate was sent by the owner; does not indicate
        certificate owner is trustworthy</entry>
       </row>
  
       <row>
!       <entry><filename>$PGDATA/root.crt</></entry>
        <entry>trusted certificate authorities</entry>
        <entry>checks that client certificate is
        signed by a trusted certificate authority</entry>
       </row>
  
       <row>
!       <entry><filename>$PGDATA/root.crl</></entry>
        <entry>certificates revoked by certificate authorities</entry>
        <entry>client certificate must not be on this list</entry>
       </row>
--- 2144,2170 ----
      <tbody>
  
       <row>
!       <entry><xref linkend="guc-ssl-cert-file"> (<filename>$PGDATA/server.crt</>)</entry>
        <entry>server certificate</entry>
        <entry>sent to client to indicate server's identity</entry>
       </row>
  
       <row>
!       <entry><xref linkend="guc-ssl-key-file"> (<filename>$PGDATA/server.key</>)</entry>
        <entry>server private key</entry>
        <entry>proves server certificate was sent by the owner; does not indicate
        certificate owner is trustworthy</entry>
       </row>
  
       <row>
!       <entry><xref linkend="guc-ssl-ca-file"> (<filename>$PGDATA/root.crt</>)</entry>
        <entry>trusted certificate authorities</entry>
        <entry>checks that client certificate is
        signed by a trusted certificate authority</entry>
       </row>
  
       <row>
!       <entry><xref linkend="guc-ssl-crl-file"> (<filename>$PGDATA/root.crl</>)</entry>
        <entry>certificates revoked by certificate authorities</entry>
        <entry>client certificate must not be on this list</entry>
       </row>
***************
*** 2176,2181 **** pg_dumpall -p 5432 | psql -d postgres -p 5433
--- 2176,2182 ----
     <para>
      The files <filename>server.key</>, <filename>server.crt</>,
      <filename>root.crt</filename>, and <filename>root.crl</filename>
+     (or their configured alternative names)
      are only examined during server start; so you must restart
      the server for changes in them to take effect.
     </para>
*** i/src/backend/libpq/be-secure.c
--- w/src/backend/libpq/be-secure.c
***************
*** 77,86 ****
  
  #ifdef USE_SSL
  
! #define ROOT_CERT_FILE			"root.crt"
! #define ROOT_CRL_FILE			"root.crl"
! #define SERVER_CERT_FILE		"server.crt"
! #define SERVER_PRIVATE_KEY_FILE "server.key"
  
  static DH  *load_dh_file(int keylength);
  static DH  *load_dh_buffer(const char *, size_t);
--- 77,86 ----
  
  #ifdef USE_SSL
  
! char *ssl_cert_file;
! char *ssl_key_file;
! char *ssl_ca_file;
! char *ssl_crl_file;
  
  static DH  *load_dh_file(int keylength);
  static DH  *load_dh_buffer(const char *, size_t);
***************
*** 746,762 **** initialize_SSL(void)
  		 * Load and verify server's certificate and private key
  		 */
  		if (SSL_CTX_use_certificate_chain_file(SSL_context,
! 											   SERVER_CERT_FILE) != 1)
  			ereport(FATAL,
  					(errcode(ERRCODE_CONFIG_FILE_ERROR),
  				  errmsg("could not load server certificate file \"%s\": %s",
! 						 SERVER_CERT_FILE, SSLerrmessage())));
  
! 		if (stat(SERVER_PRIVATE_KEY_FILE, &buf) != 0)
  			ereport(FATAL,
  					(errcode_for_file_access(),
  					 errmsg("could not access private key file \"%s\": %m",
! 							SERVER_PRIVATE_KEY_FILE)));
  
  		/*
  		 * Require no public access to key file.
--- 746,762 ----
  		 * Load and verify server's certificate and private key
  		 */
  		if (SSL_CTX_use_certificate_chain_file(SSL_context,
! 											   ssl_cert_file) != 1)
  			ereport(FATAL,
  					(errcode(ERRCODE_CONFIG_FILE_ERROR),
  				  errmsg("could not load server certificate file \"%s\": %s",
! 						 ssl_cert_file, SSLerrmessage())));
  
! 		if (stat(ssl_key_file, &buf) != 0)
  			ereport(FATAL,
  					(errcode_for_file_access(),
  					 errmsg("could not access private key file \"%s\": %m",
! 							ssl_key_file)));
  
  		/*
  		 * Require no public access to key file.
***************
*** 771,786 **** initialize_SSL(void)
  			ereport(FATAL,
  					(errcode(ERRCODE_CONFIG_FILE_ERROR),
  				  errmsg("private key file \"%s\" has group or world access",
! 						 SERVER_PRIVATE_KEY_FILE),
  				   errdetail("Permissions should be u=rw (0600) or less.")));
  #endif
  
  		if (SSL_CTX_use_PrivateKey_file(SSL_context,
! 										SERVER_PRIVATE_KEY_FILE,
  										SSL_FILETYPE_PEM) != 1)
  			ereport(FATAL,
  					(errmsg("could not load private key file \"%s\": %s",
! 							SERVER_PRIVATE_KEY_FILE, SSLerrmessage())));
  
  		if (SSL_CTX_check_private_key(SSL_context) != 1)
  			ereport(FATAL,
--- 771,786 ----
  			ereport(FATAL,
  					(errcode(ERRCODE_CONFIG_FILE_ERROR),
  				  errmsg("private key file \"%s\" has group or world access",
! 						 ssl_key_file),
  				   errdetail("Permissions should be u=rw (0600) or less.")));
  #endif
  
  		if (SSL_CTX_use_PrivateKey_file(SSL_context,
! 										ssl_key_file,
  										SSL_FILETYPE_PEM) != 1)
  			ereport(FATAL,
  					(errmsg("could not load private key file \"%s\": %s",
! 							ssl_key_file, SSLerrmessage())));
  
  		if (SSL_CTX_check_private_key(SSL_context) != 1)
  			ereport(FATAL,
***************
*** 797,844 **** initialize_SSL(void)
  		elog(FATAL, "could not set the cipher list (no valid ciphers available)");
  
  	/*
! 	 * Attempt to load CA store, so we can verify client certificates if
! 	 * needed.
  	 */
! 	ssl_loaded_verify_locations = false;
! 
! 	if (access(ROOT_CERT_FILE, R_OK) != 0)
  	{
! 		/*
! 		 * If root certificate file simply not found, don't log an error here,
! 		 * because it's quite likely the user isn't planning on using client
! 		 * certificates. If we can't access it for other reasons, it is an
! 		 * error.
! 		 */
! 		if (errno != ENOENT)
  			ereport(FATAL,
! 				 (errmsg("could not access root certificate file \"%s\": %m",
! 						 ROOT_CERT_FILE)));
  	}
! 	else if (SSL_CTX_load_verify_locations(SSL_context, ROOT_CERT_FILE, NULL) != 1 ||
! 		  (root_cert_list = SSL_load_client_CA_file(ROOT_CERT_FILE)) == NULL)
! 	{
! 		/*
! 		 * File was there, but we could not load it. This means the file is
! 		 * somehow broken, and we cannot do verification at all - so fail.
! 		 */
! 		ereport(FATAL,
! 				(errmsg("could not load root certificate file \"%s\": %s",
! 						ROOT_CERT_FILE, SSLerrmessage())));
! 	}
! 	else
  	{
- 		/*----------
- 		 * Load the Certificate Revocation List (CRL) if file exists.
- 		 * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html
- 		 *----------
- 		 */
  		X509_STORE *cvstore = SSL_CTX_get_cert_store(SSL_context);
  
  		if (cvstore)
  		{
  			/* Set the flags to check against the complete CRL chain */
! 			if (X509_STORE_load_locations(cvstore, ROOT_CRL_FILE, NULL) == 1)
  			{
  				/* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
  #ifdef X509_V_FLAG_CRL_CHECK
--- 797,826 ----
  		elog(FATAL, "could not set the cipher list (no valid ciphers available)");
  
  	/*
! 	 * Load CA store, so we can verify client certificates if needed.
  	 */
! 	if (ssl_ca_file[0])
  	{
! 		if (SSL_CTX_load_verify_locations(SSL_context, ssl_ca_file, NULL) != 1 ||
! 			(root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL)
  			ereport(FATAL,
! 					(errmsg("could not load root certificate file \"%s\": %s",
! 							ssl_ca_file, SSLerrmessage())));
  	}
! 
! 	/*----------
! 	 * Load the Certificate Revocation List (CRL).
! 	 * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html
! 	 *----------
! 	 */
! 	if (ssl_crl_file[0])
  	{
  		X509_STORE *cvstore = SSL_CTX_get_cert_store(SSL_context);
  
  		if (cvstore)
  		{
  			/* Set the flags to check against the complete CRL chain */
! 			if (X509_STORE_load_locations(cvstore, ssl_crl_file, NULL) == 1)
  			{
  				/* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */
  #ifdef X509_V_FLAG_CRL_CHECK
***************
*** 847,878 **** initialize_SSL(void)
  #else
  				ereport(LOG,
  				(errmsg("SSL certificate revocation list file \"%s\" ignored",
! 						ROOT_CRL_FILE),
  				 errdetail("SSL library does not support certificate revocation lists.")));
  #endif
  			}
  			else
! 			{
! 				/* Not fatal - we do not require CRL */
! 				ereport(LOG,
! 						(errmsg("SSL certificate revocation list file \"%s\" not found, skipping: %s",
! 								ROOT_CRL_FILE, SSLerrmessage()),
! 						 errdetail("Certificates will not be checked against revocation list.")));
! 			}
  
! 			/*
! 			 * Always ask for SSL client cert, but don't fail if it's not
! 			 * presented.  We might fail such connections later, depending on
! 			 * what we find in pg_hba.conf.
! 			 */
! 			SSL_CTX_set_verify(SSL_context,
! 							   (SSL_VERIFY_PEER |
! 								SSL_VERIFY_CLIENT_ONCE),
! 							   verify_cb);
  
! 			/* Set flag to remember CA store is successfully loaded */
! 			ssl_loaded_verify_locations = true;
! 		}
  
  		/*
  		 * Tell OpenSSL to send the list of root certs we trust to clients in
--- 829,859 ----
  #else
  				ereport(LOG,
  				(errmsg("SSL certificate revocation list file \"%s\" ignored",
! 						ssl_crl_file),
  				 errdetail("SSL library does not support certificate revocation lists.")));
  #endif
  			}
  			else
! 				ereport(FATAL,
! 						(errmsg("could not load SSL certificate revocation list file \"%s\": %s",
! 								ssl_crl_file, SSLerrmessage())));
! 		}
! 	}
  
! 	if (ssl_ca_file[0])
! 	{
! 		/*
! 		 * Always ask for SSL client cert, but don't fail if it's not
! 		 * presented.  We might fail such connections later, depending on
! 		 * what we find in pg_hba.conf.
! 		 */
! 		SSL_CTX_set_verify(SSL_context,
! 						   (SSL_VERIFY_PEER |
! 							SSL_VERIFY_CLIENT_ONCE),
! 						   verify_cb);
  
! 		/* Set flag to remember CA store is successfully loaded */
! 		ssl_loaded_verify_locations = true;
  
  		/*
  		 * Tell OpenSSL to send the list of root certs we trust to clients in
*** i/src/backend/utils/misc/guc.c
--- w/src/backend/utils/misc/guc.c
***************
*** 39,44 ****
--- 39,45 ----
  #include "funcapi.h"
  #include "libpq/auth.h"
  #include "libpq/be-fsstubs.h"
+ #include "libpq/libpq.h"
  #include "libpq/pqformat.h"
  #include "miscadmin.h"
  #include "optimizer/cost.h"
***************
*** 2961,2966 **** static struct config_string ConfigureNamesString[] =
--- 2962,3007 ----
  	},
  
  	{
+ 		{"ssl_cert_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
+ 			gettext_noop("Location of the SSL server certificate file."),
+ 			NULL
+ 		},
+ 		&ssl_cert_file,
+ 		"server.crt",
+ 		NULL, NULL, NULL
+ 	},
+ 
+ 	{
+ 		{"ssl_key_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
+ 			gettext_noop("Location of the SSL server private key file."),
+ 			NULL
+ 		},
+ 		&ssl_key_file,
+ 		"server.key",
+ 		NULL, NULL, NULL
+ 	},
+ 
+ 	{
+ 		{"ssl_ca_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
+ 			gettext_noop("Location of the SSL certificate authority file."),
+ 			NULL
+ 		},
+ 		&ssl_ca_file,
+ 		"",
+ 		NULL, NULL, NULL
+ 	},
+ 
+ 	{
+ 		{"ssl_crl_file", PGC_POSTMASTER, CONN_AUTH_SECURITY,
+ 			gettext_noop("Location of the SSL certificate revocation list file."),
+ 			NULL
+ 		},
+ 		&ssl_crl_file,
+ 		"",
+ 		NULL, NULL, NULL
+ 	},
+ 
+ 	{
  		{"stats_temp_directory", PGC_SIGHUP, STATS_COLLECTOR,
  			gettext_noop("Writes temporary statistics files to the specified directory."),
  			NULL,
*** i/src/backend/utils/misc/postgresql.conf.sample
--- w/src/backend/utils/misc/postgresql.conf.sample
***************
*** 81,86 ****
--- 81,90 ----
  #ssl_ciphers = 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH'	# allowed SSL ciphers
  					# (change requires restart)
  #ssl_renegotiation_limit = 512MB	# amount of data between renegotiations
+ #ssl_cert_file = 'server.crt'		# (change requires restart)
+ #ssl_key_file = 'server.key'		# (change requires restart)
+ #ssl_ca_file = ''			# (change requires restart)
+ #ssl_crl_file = ''			# (change requires restart)
  #password_encryption = on
  #db_user_namespace = off
  
*** i/src/include/libpq/libpq.h
--- w/src/include/libpq/libpq.h
***************
*** 70,75 **** extern void pq_endcopyout(bool errorAbort);
--- 70,80 ----
  /*
   * prototypes for functions in be-secure.c
   */
+ extern char *ssl_cert_file;
+ extern char *ssl_key_file;
+ extern char *ssl_ca_file;
+ extern char *ssl_crl_file;
+ 
  extern int	secure_initialize(void);
  extern bool secure_loaded_verify_locations(void);
  extern void secure_destroy(void);
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to