diff -rcN ../pgsql-20060830/doc/src/sgml/config.sgml ./doc/src/sgml/config.sgml *** ../pgsql-20060830/doc/src/sgml/config.sgml 2006-08-30 16:01:12.000000000 +0400 --- ./doc/src/sgml/config.sgml 2006-09-01 11:13:34.000000000 +0400 *************** *** 555,561 **** ! password_encryption (boolean) --- 555,575 ---- ! ! ssl_ciphers> (string) ! ! ssl_ciphers configuration parameter ! ! ! ! Specifies list of SSL ciphers, which can be used to ! establish secure connection. See manual page for ! openssl ciphers ! command to find list of allowed values and their semantics. ! ! ! ! password_encryption (boolean) diff -rcN ../pgsql-20060830/doc/src/sgml/libpq.sgml ./doc/src/sgml/libpq.sgml *** ../pgsql-20060830/doc/src/sgml/libpq.sgml 2006-08-30 16:01:12.000000000 +0400 --- ./doc/src/sgml/libpq.sgml 2006-09-01 12:30:33.000000000 +0400 *************** *** 3942,3947 **** --- 3942,3959 ---- + PGSSLKEY + + PGSSLKEY + specifies hardware token which store secret key of the client + certificate, instead of file. Value of this variable should consist of + colon separated engine name (engines are loadable modules of + OpenSSL) and engine-specific key identifier. + + + + + PGKRBSRVNAME PGKRBSRVNAME sets the Kerberos service name to use when *************** *** 4139,4158 **** for increased security. See for details about the server-side SSL functionality. ! If the server demands a client certificate, libpq will send the certificate stored in file ~/.postgresql/postgresql.crt within the user's home directory. A matching private key file ~/.postgresql/postgresql.key ! must also be present, and must not be world-readable. (On Microsoft Windows these files are named %APPDATA%\postgresql\postgresql.crt and %APPDATA%\postgresql\postgresql.key.) If the file ~/.postgresql/root.crt is present in the user's home directory, libpq will use the certificate list stored --- 4151,4194 ---- for increased security. See for details about the server-side SSL functionality. ! ! libpq reads system-wide ! OpenSSL configuration file. By default this ! file is named openssl.cnf and located in the ! directory, which is reported by command: ! ! openssl version -d ! ! This default can be overriden by setting environment variable ! OPENSSL_CONF to the name of desired configuration file. ! If the server demands a client certificate, libpq will send the certificate stored in file ~/.postgresql/postgresql.crt within the user's home directory. A matching private key file ~/.postgresql/postgresql.key ! must also be present, and must not be world-readable, unless secret ! key is stored on hardware token, specified by ! PGSSLKEY. (On Microsoft Windows these files are named %APPDATA%\postgresql\postgresql.crt and %APPDATA%\postgresql\postgresql.key.) + If environment variable PGSSLKEY is set, its value + should consist of colon separated engine name and key identifier. In this + case, libpq would load specified engine, + i.e. OpenSSL module which supports special hardware + and obtain reference to key with specified identifier. Identifiers + are engine-specific. Typically, cryptography hardware tokens do not + reveal secret keys to the application. Instead, application delegates + all cryptography operations which require secret key, to the + hardware token. + + + If the file ~/.postgresql/root.crt is present in the user's home directory, libpq will use the certificate list stored diff -rcN ../pgsql-20060830/doc/src/sgml/runtime.sgml ./doc/src/sgml/runtime.sgml *** ../pgsql-20060830/doc/src/sgml/runtime.sgml 2006-08-30 16:01:12.000000000 +0400 --- ./doc/src/sgml/runtime.sgml 2006-09-01 12:30:34.000000000 +0400 *************** *** 1516,1521 **** --- 1516,1540 ---- + OpenSSL supports wide range of ciphers + and authentication algorithms, which strength varies significantly. + You can restrict list of ciphers which can be used to connect to + your server using parameter. + + + PostgreSQL reads system-wide + OpenSSL configuration file. By default this + file is named openssl.cnf and located in the + directory, which is reported by command: + + openssl version -d + + + This default can be overriden by setting environment variable + OPENSSL_CONF to the name of desired configuration file. + + + For details on how to create your server private key and certificate, refer to the OpenSSL documentation. A self-signed certificate can be used for testing, but a diff -rcN ../pgsql-20060830/src/backend/libpq/be-secure.c ./src/backend/libpq/be-secure.c *** ../pgsql-20060830/src/backend/libpq/be-secure.c 2006-08-30 16:01:28.000000000 +0400 --- ./src/backend/libpq/be-secure.c 2006-09-01 11:59:16.000000000 +0400 *************** *** 92,97 **** --- 92,101 ---- #ifdef USE_SSL #include #include + #if SSLEAY_VERSION_NUMBER >= 0x0907000L + #include + #endif + #endif #include "libpq/libpq.h" *************** *** 125,130 **** --- 129,138 ---- #define RENEGOTIATION_LIMIT (512 * 1024 * 1024) static SSL_CTX *SSL_context = NULL; + + /* GUC variable controlling SSL cipher list*/ + extern char *SSLCipherSuites; + #endif /* ------------------------------------------------------------ */ *************** *** 717,722 **** --- 725,733 ---- if (!SSL_context) { + #if SSLEAY_VERSION_NUMBER >= 0x0907000L + OPENSSL_config(NULL); + #endif SSL_library_init(); SSL_load_error_strings(); SSL_context = SSL_CTX_new(SSLv23_method()); *************** *** 778,784 **** SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2); /* setup the allowed cipher list */ ! if (SSL_CTX_set_cipher_list(SSL_context, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH") != 1) elog(FATAL, "could not set the cipher list (no valid ciphers available)"); /* --- 789,795 ---- SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2); /* setup the allowed cipher list */ ! if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1) elog(FATAL, "could not set the cipher list (no valid ciphers available)"); /* diff -rcN ../pgsql-20060830/src/backend/postmaster/postmaster.c ./src/backend/postmaster/postmaster.c *** ../pgsql-20060830/src/backend/postmaster/postmaster.c 2006-08-30 16:01:32.000000000 +0400 --- ./src/backend/postmaster/postmaster.c 2006-09-01 11:16:03.000000000 +0400 *************** *** 186,191 **** --- 186,192 ---- /* still more option variables */ bool EnableSSL = false; + char * SSLCipherSuites; bool SilentMode = false; /* silent mode (-S) */ int PreAuthDelay = 0; diff -rcN ../pgsql-20060830/src/backend/utils/misc/guc.c ./src/backend/utils/misc/guc.c *** ../pgsql-20060830/src/backend/utils/misc/guc.c 2006-08-30 16:01:36.000000000 +0400 --- ./src/backend/utils/misc/guc.c 2006-09-01 11:17:04.000000000 +0400 *************** *** 2233,2239 **** &external_pid_file, NULL, assign_canonical_path, NULL }, ! /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL --- 2233,2248 ---- &external_pid_file, NULL, assign_canonical_path, NULL }, ! { ! {"ssl_ciphers", PGC_POSTMASTER, CONN_AUTH_SECURITY, ! gettext_noop("List of allowed SSL ciphersuites"), ! NULL, ! GUC_SUPERUSER_ONLY ! }, ! &SSLCipherSuites, ! "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH",NULL,NULL ! }, ! /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL diff -rcN ../pgsql-20060830/src/backend/utils/misc/postgresql.conf.sample ./src/backend/utils/misc/postgresql.conf.sample *** ../pgsql-20060830/src/backend/utils/misc/postgresql.conf.sample 2006-08-30 16:01:36.000000000 +0400 --- ./src/backend/utils/misc/postgresql.conf.sample 2006-09-01 11:17:04.000000000 +0400 *************** *** 71,76 **** --- 71,77 ---- #authentication_timeout = 60 # 1-600, in seconds #ssl = off # (change requires restart) + #ssl_ciphers = 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH' # List of ciphers to use #password_encryption = on #db_user_namespace = off diff -rcN ../pgsql-20060830/src/include/postmaster/postmaster.h ./src/include/postmaster/postmaster.h *** ../pgsql-20060830/src/include/postmaster/postmaster.h 2006-08-30 16:01:42.000000000 +0400 --- ./src/include/postmaster/postmaster.h 2006-09-01 11:17:04.000000000 +0400 *************** *** 15,20 **** --- 15,21 ---- /* GUC options */ extern bool EnableSSL; + extern char *SSLCipherSuites; extern bool SilentMode; extern int ReservedBackends; extern int PostPortNumber; diff -rcN ../pgsql-20060830/src/interfaces/libpq/fe-secure.c ./src/interfaces/libpq/fe-secure.c *** ../pgsql-20060830/src/interfaces/libpq/fe-secure.c 2006-08-30 16:01:45.000000000 +0400 --- ./src/interfaces/libpq/fe-secure.c 2006-08-30 21:03:28.000000000 +0400 *************** *** 115,120 **** --- 115,126 ---- #ifdef USE_SSL #include + #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) + #include + #endif + #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) + #include + #endif #endif /* USE_SSL */ *************** *** 611,664 **** } fclose(fp); ! /* read the user key */ ! snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE); ! if (stat(fnbuf, &buf) == -1) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("certificate present, but not private key file \"%s\"\n"), ! fnbuf); ! return 0; ! } ! #ifndef WIN32 ! if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) || ! buf.st_uid != geteuid()) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("private key file \"%s\" has wrong permissions\n"), ! fnbuf); ! return 0; ! } ! #endif ! if ((fp = fopen(fnbuf, "r")) == NULL) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("could not open private key file \"%s\": %s\n"), ! fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf))); ! return 0; ! } ! #ifndef WIN32 ! if (fstat(fileno(fp), &buf2) == -1 || ! buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf); ! return 0; ! } ! #endif ! if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL) ! { ! char *err = SSLerrmessage(); ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("could not read private key file \"%s\": %s\n"), ! fnbuf, err); ! SSLerrfree(err); fclose(fp); - return 0; } - fclose(fp); - /* verify that the cert and key go together */ if (!X509_check_private_key(*x509, *pkey)) { --- 617,707 ---- } fclose(fp); ! #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) ! if (getenv("PGSSLKEY")) { ! /* read the user key from engine */ ! ENGINE *e = NULL; ! char *engine_id; ! char *l = getenv("PGSSLKEY"); ! char *p = strchr(l,':'); ! if (!p) { ! printfPQExpBuffer(&conn->errorMessage,libpq_gettext("Invalid value of PGSSLKEY environment variable\n")); ! return 0; ! } ! engine_id = malloc(p-l+1); ! strncpy(engine_id,l,p-l); ! engine_id[p-l]=0; ! e = ENGINE_by_id(engine_id); ! if (!e) { ! char *err = SSLerrmessage(); ! printfPQExpBuffer(&conn->errorMessage,libpq_gettext("Couldn't load engine \"%s\":%s\n"),engine_id,err); ! free(engine_id); ! SSLerrfree(err); ! return 0; ! } ! *pkey = ENGINE_load_private_key(e,p+1,NULL,NULL); ! if (!*pkey) { ! char *err = SSLerrmessage(); ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("could not read prevate key %s from engine \"%s\": %s\n"), ! p+1,engine_id, err); ! SSLerrfree(err); ! free(engine_id); ! return 0; ! } ! free(engine_id); ! } else { ! #else ! { ! #endif ! /* read the user key from file*/ ! snprintf(fnbuf, sizeof(fnbuf), "%s/%s", homedir, USER_KEY_FILE); ! if (stat(fnbuf, &buf) == -1) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("certificate present, but not private key file \"%s\"\n"), ! fnbuf); ! return 0; ! } ! #ifndef WIN32 ! if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0077) || ! buf.st_uid != geteuid()) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("private key file \"%s\" has wrong permissions\n"), ! fnbuf); ! return 0; ! } ! #endif ! if ((fp = fopen(fnbuf, "r")) == NULL) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("could not open private key file \"%s\": %s\n"), ! fnbuf, pqStrerror(errno, sebuf, sizeof(sebuf))); ! return 0; ! } ! #ifndef WIN32 ! if (fstat(fileno(fp), &buf2) == -1 || ! buf.st_dev != buf2.st_dev || buf.st_ino != buf2.st_ino) ! { ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("private key file \"%s\" changed during execution\n"), fnbuf); ! return 0; ! } ! #endif ! if (PEM_read_PrivateKey(fp, pkey, cb, NULL) == NULL) ! { ! char *err = SSLerrmessage(); ! printfPQExpBuffer(&conn->errorMessage, ! libpq_gettext("could not read private key file \"%s\": %s\n"), ! fnbuf, err); ! SSLerrfree(err); ! fclose(fp); ! return 0; ! } fclose(fp); } /* verify that the cert and key go together */ if (!X509_check_private_key(*x509, *pkey)) { *************** *** 742,747 **** --- 785,793 ---- { if (pq_initssllib) { + #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) + OPENSSL_config(NULL); + #endif SSL_library_init(); SSL_load_error_strings(); }