diff --git a/doc/src/sgml/ssl.sgml b/doc/src/sgml/ssl.sgml index fa4ecbc..d78568c 100644 --- a/doc/src/sgml/ssl.sgml +++ b/doc/src/sgml/ssl.sgml @@ -48,9 +48,9 @@ - Specifies the path to the private key file to be used for - incoming frontend connections. If specifies relative path, it is based - on the directory where pgpool is starting up. + Specifies the private key file to be used for + incoming frontend connections. Relative paths are relative to + Pgpool-II configuration directory. There is no default value for this option, and if left unset SSL will be disabled for incoming frontend connections. @@ -68,9 +68,9 @@ - Specifies the path to the public x509 certificate file to be used - for the incoming frontend connections. If specifies relative path, based - path is Pgpool-II is run directory. + Specifies the public x509 certificate file to be used + for the incoming frontend connections. Relative paths are relative to + Pgpool-II configuration directory. There is no default value for this option, and if left unset SSL will be disabled for incoming frontend connections. @@ -89,10 +89,11 @@ - Specifies the path to a PEM - format CA certificate files, which can be used - to verify the backend server certificates. This is analogous to - the -CApath option of the + Specifies a PEM format CA + certificate file, which can be used to verify the backend server + certificates. Relative paths are relative to + Pgpool-II configuration directory. This is + analogous to the -CApath option of the OpenSSL verify(1) command. @@ -136,9 +137,10 @@ - Specifies the path to the file containing the SSL server - certificate revocation list (CRL). The default is empty, - meaning no CRL file is loaded. + Specifies the file containing the SSL server certificate + revocation list (CRL). Relative paths are relative to + Pgpool-II configuration directory. + The default is empty, meaning no CRL file is loaded. diff --git a/src/config/pool_config_variables.c b/src/config/pool_config_variables.c index a4b446b..da9aa3a 100644 --- a/src/config/pool_config_variables.c +++ b/src/config/pool_config_variables.c @@ -1032,7 +1032,7 @@ static struct config_string ConfigureNamesString[] = { {"ssl_cert", CFGCXT_INIT, SSL_CONFIG, - "Path to the SSL public certificate file.", + "SSL public certificate file.", CONFIG_VAR_TYPE_STRING, false, 0 }, &g_pool_config.ssl_cert, @@ -1042,7 +1042,7 @@ static struct config_string ConfigureNamesString[] = { {"ssl_key", CFGCXT_INIT, SSL_CONFIG, - "Path to the SSL private key file.", + "SSL private key file.", CONFIG_VAR_TYPE_STRING, false, 0 }, &g_pool_config.ssl_key, @@ -1052,7 +1052,7 @@ static struct config_string ConfigureNamesString[] = { {"ssl_ca_cert", CFGCXT_INIT, SSL_CONFIG, - "Path to a single PEM format file.", + "Single PEM format file containing CA root certificate(s).", CONFIG_VAR_TYPE_STRING, false, 0 }, &g_pool_config.ssl_ca_cert, @@ -1072,7 +1072,7 @@ static struct config_string ConfigureNamesString[] = { {"ssl_crl_file", CFGCXT_INIT, SSL_CONFIG, - "Path to the SSL certificate revocation list file", + "SSL certificate revocation list file", CONFIG_VAR_TYPE_STRING, false, 0 }, &g_pool_config.ssl_crl_file, diff --git a/src/sample/pgpool.conf.sample-logical b/src/sample/pgpool.conf.sample-logical index 6eb146b..2f5faf7 100644 --- a/src/sample/pgpool.conf.sample-logical +++ b/src/sample/pgpool.conf.sample-logical @@ -115,21 +115,21 @@ allow_clear_text_frontend_auth = off ssl = off # Enable SSL support # (change requires restart) -#ssl_key = './server.key' - # Path to the SSL private key file +#ssl_key = 'server.key' + # SSL private key file # (change requires restart) -#ssl_cert = './server.cert' - # Path to the SSL public certificate file +#ssl_cert = 'server.crt' + # SSL public certificate file # (change requires restart) #ssl_ca_cert = '' - # Path to a single PEM format file - # containing CA root certificate(s) + # Single PEM format file containing + # CA root certificate(s) # (change requires restart) #ssl_ca_cert_dir = '' # Directory containing CA root certificate(s) # (change requires restart) #ssl_crl_file = '' - # Path to the SSL certificate revocation list file + # SSL certificate revocation list file # (change requires restart) ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' diff --git a/src/sample/pgpool.conf.sample-raw b/src/sample/pgpool.conf.sample-raw index 16cca78..ee53bff 100644 --- a/src/sample/pgpool.conf.sample-raw +++ b/src/sample/pgpool.conf.sample-raw @@ -116,21 +116,21 @@ allow_clear_text_frontend_auth = off ssl = off # Enable SSL support # (change requires restart) -#ssl_key = './server.key' - # Path to the SSL private key file +#ssl_key = 'server.key' + # SSL private key file # (change requires restart) -#ssl_cert = './server.cert' - # Path to the SSL public certificate file +#ssl_cert = 'server.crt' + # SSL public certificate file # (change requires restart) #ssl_ca_cert = '' - # Path to a single PEM format file - # containing CA root certificate(s) + # Single PEM format file containing + # CA root certificate(s) # (change requires restart) #ssl_ca_cert_dir = '' # Directory containing CA root certificate(s) # (change requires restart) #ssl_crl_file = '' - # Path to the SSL certificate revocation list file + # SSL certificate revocation list file # (change requires restart) ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' diff --git a/src/sample/pgpool.conf.sample-replication b/src/sample/pgpool.conf.sample-replication index 0fc0ee2..12ffc0f 100644 --- a/src/sample/pgpool.conf.sample-replication +++ b/src/sample/pgpool.conf.sample-replication @@ -111,21 +111,21 @@ allow_clear_text_frontend_auth = off ssl = off # Enable SSL support # (change requires restart) -#ssl_key = './server.key' - # Path to the SSL private key file +#ssl_key = 'server.key' + # SSL private key file # (change requires restart) -#ssl_cert = './server.cert' - # Path to the SSL public certificate file +#ssl_cert = 'server.crt' + # SSL public certificate file # (change requires restart) #ssl_ca_cert = '' - # Path to a single PEM format file - # containing CA root certificate(s) + # Single PEM format file containing + # CA root certificate(s) # (change requires restart) #ssl_ca_cert_dir = '' # Directory containing CA root certificate(s) # (change requires restart) #ssl_crl_file = '' - # Path to the SSL certificate revocation list file + # SSL certificate revocation list file # (change requires restart) ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' diff --git a/src/sample/pgpool.conf.sample-slony b/src/sample/pgpool.conf.sample-slony index 7abc58d..8226ebc 100644 --- a/src/sample/pgpool.conf.sample-slony +++ b/src/sample/pgpool.conf.sample-slony @@ -112,21 +112,21 @@ allow_clear_text_frontend_auth = off ssl = off # Enable SSL support # (change requires restart) -#ssl_key = './server.key' - # Path to the SSL private key file +#ssl_key = 'server.key' + # SSL private key file # (change requires restart) -#ssl_cert = './server.cert' - # Path to the SSL public certificate file +#ssl_cert = 'server.crt' + # SSL public certificate file # (change requires restart) #ssl_ca_cert = '' - # Path to a single PEM format file - # containing CA root certificate(s) + # Single PEM format file containing + # CA root certificate(s) # (change requires restart) #ssl_ca_cert_dir = '' # Directory containing CA root certificate(s) # (change requires restart) #ssl_crl_file = '' - # Path to the SSL certificate revocation list file + # SSL certificate revocation list file # (change requires restart) ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' diff --git a/src/sample/pgpool.conf.sample-stream b/src/sample/pgpool.conf.sample-stream index 26a9ff2..7490ed2 100644 --- a/src/sample/pgpool.conf.sample-stream +++ b/src/sample/pgpool.conf.sample-stream @@ -116,21 +116,21 @@ allow_clear_text_frontend_auth = off ssl = off # Enable SSL support # (change requires restart) -#ssl_key = './server.key' - # Path to the SSL private key file +#ssl_key = 'server.key' + # SSL private key file # (change requires restart) -#ssl_cert = './server.cert' - # Path to the SSL public certificate file +#ssl_cert = 'server.crt' + # SSL public certificate file # (change requires restart) #ssl_ca_cert = '' - # Path to a single PEM format file - # containing CA root certificate(s) + # Single PEM format file containing + # CA root certificate(s) # (change requires restart) #ssl_ca_cert_dir = '' # Directory containing CA root certificate(s) # (change requires restart) #ssl_crl_file = '' - # Path to the SSL certificate revocation list file + # SSL certificate revocation list file # (change requires restart) ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL' diff --git a/src/test/regression/tests/023.ssl_connection/test.sh b/src/test/regression/tests/023.ssl_connection/test.sh index 1d479c8..5c65a33 100755 --- a/src/test/regression/tests/023.ssl_connection/test.sh +++ b/src/test/regression/tests/023.ssl_connection/test.sh @@ -31,8 +31,8 @@ cp -p ../$SSL_CRT data0/ dir=`pwd` echo "ssl = on" >> etc/pgpool.conf -echo "ssl_key = '$dir/etc/$SSL_KEY'" >> etc/pgpool.conf -echo "ssl_cert = '$dir/etc/$SSL_CRT'" >> etc/pgpool.conf +echo "ssl_key = '$SSL_KEY'" >> etc/pgpool.conf +echo "ssl_cert = '$SSL_CRT'" >> etc/pgpool.conf echo "ssl_prefer_server_ciphers = on" >> etc/pgpool.conf echo "ssl_ciphers = 'EECDH:HIGH:MEDIUM:+3DES:!aNULL'" >> etc/pgpool.conf diff --git a/src/test/regression/tests/024.cert_auth/test.sh b/src/test/regression/tests/024.cert_auth/test.sh index 01a2789..c434b2b 100755 --- a/src/test/regression/tests/024.cert_auth/test.sh +++ b/src/test/regression/tests/024.cert_auth/test.sh @@ -7,18 +7,19 @@ TESTDIR=testdir PSQL=$PGBIN/psql PG_CTL=$PGBIN/pg_ctl export PGDATABASE=test +SSL_KEY=server.key +SSL_CRT=server.crt +SSL_CRL=server.crl +SSL_CRL2=server_revoked.crl +ROOT_CRT=root.crt # Generate certifications ./cert.sh +chmod 600 *.key dir=`pwd` -SSL_KEY=$dir/server.key -SSL_CRT=$dir/server.crt -SSL_CRL=$dir/server.crl -ROOT_CRT=$dir/root.crt FRONTEND_KEY=$dir/frontend.key FRONTEND_CRT=$dir/frontend.crt -chmod 600 *.key rm -fr $TESTDIR mkdir $TESTDIR @@ -29,7 +30,13 @@ echo -n "creating test environment..." $PGPOOL_SETUP -m s -n 1 || exit 1 echo "done." -dir=`pwd` +# setup SSL key and crt file +cp -p ../$SSL_KEY etc/ +chmod og-rwx etc/$SSL_KEY +cp -p ../$SSL_CRT etc/ +cp -p ../$SSL_CRL etc/ +cp -p ../$SSL_CRL2 etc/ +cp -p ../$ROOT_CRT etc/ echo "ssl = on" >> etc/pgpool.conf echo "ssl_key = '$SSL_KEY'" >> etc/pgpool.conf @@ -53,7 +60,7 @@ wait_for_pgpool_startup export PGSSLCERT=$FRONTEND_CRT export PGSSLKEY=$FRONTEND_KEY -export PGSSLROOTCERT=$ROOT_CRT +export PGSSLROOTCERT=$dir/$ROOT_CRT $PSQL -h localhost -c "select 1" test @@ -90,7 +97,7 @@ wait_for_pgpool_startup export PGSSLCERT=$FRONTEND_CRT export PGSSLKEY=$FRONTEND_KEY -export PGSSLROOTCERT=$ROOT_CRT +export PGSSLROOTCERT=$dir/$ROOT_CRT $PSQL -h localhost -c "select 1" test @@ -128,7 +135,7 @@ wait_for_pgpool_startup export PGSSLCERT=$FRONTEND_CRT export PGSSLKEY=$FRONTEND_KEY -export PGSSLROOTCERT=$ROOT_CRT +export PGSSLROOTCERT=$dir/$ROOT_CRT $PSQL -h localhost -c "select 1" test > $dir/crl_session.log 2>&1 diff --git a/src/utils/pool_process_reporting.c b/src/utils/pool_process_reporting.c index 412367d..3fc9d6a 100644 --- a/src/utils/pool_process_reporting.c +++ b/src/utils/pool_process_reporting.c @@ -236,17 +236,17 @@ get_config(int *nrows) StrNCpy(status[i].name, "ssl_key", POOLCONFIG_MAXNAMELEN); snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_key); - StrNCpy(status[i].desc, "path to the SSL private key file", POOLCONFIG_MAXDESCLEN); + StrNCpy(status[i].desc, "SSL private key file", POOLCONFIG_MAXDESCLEN); i++; StrNCpy(status[i].name, "ssl_cert", POOLCONFIG_MAXNAMELEN); snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_cert); - StrNCpy(status[i].desc, "path to the SSL public certificate file", POOLCONFIG_MAXDESCLEN); + StrNCpy(status[i].desc, "SSL public certificate file", POOLCONFIG_MAXDESCLEN); i++; StrNCpy(status[i].name, "ssl_ca_cert", POOLCONFIG_MAXNAMELEN); snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_ca_cert); - StrNCpy(status[i].desc, "path to a single PEM format file", POOLCONFIG_MAXDESCLEN); + StrNCpy(status[i].desc, "single PEM format file containing CA root certificate(s)", POOLCONFIG_MAXDESCLEN); i++; StrNCpy(status[i].name, "ssl_ca_cert_dir", POOLCONFIG_MAXNAMELEN); @@ -256,7 +256,7 @@ get_config(int *nrows) StrNCpy(status[i].name, "ssl_crl_file", POOLCONFIG_MAXNAMELEN); snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->ssl_crl_file); - StrNCpy(status[i].desc, "path to the SSL certificate revocation list file", POOLCONFIG_MAXDESCLEN); + StrNCpy(status[i].desc, "SSL certificate revocation list file", POOLCONFIG_MAXDESCLEN); i++; StrNCpy(status[i].name, "ssl_ciphers", POOLCONFIG_MAXNAMELEN); diff --git a/src/utils/pool_ssl.c b/src/utils/pool_ssl.c index 3792b85..783c6ae 100644 --- a/src/utils/pool_ssl.c +++ b/src/utils/pool_ssl.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "pool.h" #include "config.h" @@ -35,6 +36,7 @@ #include "utils/palloc.h" #include "utils/memutils.h" #include "utils/pool_stream.h" +#include "utils/pool_path.h" #include "main/pool_internal_comms.h" @@ -53,6 +55,7 @@ static DH *load_dh_buffer(const char *, size_t); static bool initialize_dh(SSL_CTX *context); static bool initialize_ecdh(SSL_CTX *context); static int run_ssl_passphrase_command(const char *prompt, char *buf, int size); +static void pool_ssl_make_absolute_path(char *artifact_path, char *config_dir, char *absolute_path); #define SSL_RETURN_VOID_IF(cond, msg) \ do { \ @@ -302,6 +305,17 @@ init_ssl_ctx(POOL_CONNECTION * cp, enum ssl_conn_type conntype) char *cacert = NULL, *cacert_dir = NULL; + char ssl_cert_path[POOLMAXPATHLEN + 1]; + char ssl_key_path[POOLMAXPATHLEN + 1]; + char ssl_ca_cert_path[POOLMAXPATHLEN + 1]; + + char *conf_file_copy = pstrdup(get_config_file_name()); + char *conf_dir = dirname(conf_file_copy); + + pool_ssl_make_absolute_path(pool_config->ssl_cert, conf_dir, ssl_cert_path); + pool_ssl_make_absolute_path(pool_config->ssl_key, conf_dir, ssl_key_path); + pool_ssl_make_absolute_path(pool_config->ssl_ca_cert, conf_dir, ssl_ca_cert_path); + /* initialize SSL members */ #if (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined (LIBRESSL_VERSION_NUMBER)) cp->ssl_ctx = SSL_CTX_new(TLS_method()); @@ -321,11 +335,11 @@ init_ssl_ctx(POOL_CONNECTION * cp, enum ssl_conn_type conntype) { /* between frontend and pgpool */ error = SSL_CTX_use_certificate_chain_file(cp->ssl_ctx, - pool_config->ssl_cert); + ssl_cert_path); SSL_RETURN_ERROR_IF((error != 1), "Loading SSL certificate"); error = SSL_CTX_use_PrivateKey_file(cp->ssl_ctx, - pool_config->ssl_key, + ssl_key_path, SSL_FILETYPE_PEM); SSL_RETURN_ERROR_IF((error != 1), "Loading SSL private key"); } @@ -333,8 +347,8 @@ init_ssl_ctx(POOL_CONNECTION * cp, enum ssl_conn_type conntype) { /* between pgpool and backend */ /* set extra verification if ssl_ca_cert or ssl_ca_cert_dir are set */ - if (strlen(pool_config->ssl_ca_cert)) - cacert = pool_config->ssl_ca_cert; + if (strlen(ssl_ca_cert_path)) + cacert = ssl_ca_cert_path; if (strlen(pool_config->ssl_ca_cert_dir)) cacert_dir = pool_config->ssl_ca_cert_dir; @@ -351,6 +365,7 @@ init_ssl_ctx(POOL_CONNECTION * cp, enum ssl_conn_type conntype) cp->ssl = SSL_new(cp->ssl_ctx); SSL_RETURN_ERROR_IF((!cp->ssl), "SSL_new"); + pfree(conf_file_copy); return 0; } @@ -521,6 +536,16 @@ SSL_ServerSide_init(void) STACK_OF(X509_NAME) *root_cert_list = NULL; SSL_CTX *context; struct stat buf; + char ssl_cert_path[POOLMAXPATHLEN + 1] = ""; + char ssl_key_path[POOLMAXPATHLEN + 1] = ""; + char ssl_ca_cert_path[POOLMAXPATHLEN + 1] = ""; + + char *conf_file_copy = pstrdup(get_config_file_name()); + char *conf_dir = dirname(conf_file_copy); + + pool_ssl_make_absolute_path(pool_config->ssl_cert, conf_dir, ssl_cert_path); + pool_ssl_make_absolute_path(pool_config->ssl_key, conf_dir, ssl_key_path); + pool_ssl_make_absolute_path(pool_config->ssl_ca_cert, conf_dir, ssl_ca_cert_path); /* This stuff need be done only once. */ if (!SSL_initialized) @@ -572,19 +597,19 @@ SSL_ServerSide_init(void) /* * Load and verify server's certificate and private key */ - if (SSL_CTX_use_certificate_chain_file(context, pool_config->ssl_cert) != 1) + if (SSL_CTX_use_certificate_chain_file(context, ssl_cert_path) != 1) { ereport(WARNING, (errmsg("could not load server certificate file \"%s\": %s", - pool_config->ssl_cert, SSLerrmessage(ERR_get_error())))); + ssl_cert_path, SSLerrmessage(ERR_get_error())))); goto error; } - if (stat(pool_config->ssl_key, &buf) != 0) + if (stat(ssl_key_path, &buf) != 0) { ereport(WARNING, (errmsg("could not access private key file \"%s\": %m", - pool_config->ssl_key))); + ssl_key_path))); goto error; } @@ -592,7 +617,7 @@ SSL_ServerSide_init(void) { ereport(WARNING, (errmsg("private key file \"%s\" is not a regular file", - pool_config->ssl_key))); + ssl_key_path))); goto error; } @@ -613,7 +638,7 @@ SSL_ServerSide_init(void) { ereport(WARNING, (errmsg("private key file \"%s\" has group or world access", - pool_config->ssl_key), + ssl_key_path), errdetail("File must have permissions u=rw (0600) or less if owned by the Pgpool-II user, or permissions u=rw,g=r (0640) or less if owned by root."))); } #endif @@ -624,17 +649,17 @@ SSL_ServerSide_init(void) dummy_ssl_passwd_cb_called = false; if (SSL_CTX_use_PrivateKey_file(context, - pool_config->ssl_key, + ssl_key_path, SSL_FILETYPE_PEM) != 1) { if (dummy_ssl_passwd_cb_called) ereport(WARNING, (errmsg("private key file \"%s\" cannot be reloaded because it requires a passphrase", - pool_config->ssl_key))); + ssl_key_path))); else ereport(WARNING, (errmsg("could not load private key file \"%s\": %s", - pool_config->ssl_key, SSLerrmessage(ERR_get_error())))); + ssl_key_path, SSLerrmessage(ERR_get_error())))); goto error; } @@ -675,13 +700,11 @@ SSL_ServerSide_init(void) /* * Load CA store, so we can verify client certificates if needed. */ - if (pool_config->ssl_ca_cert && strlen(pool_config->ssl_ca_cert)) + if (strlen(ssl_ca_cert_path)) { - char *cacert = NULL, + char *cacert = ssl_ca_cert_path, *cacert_dir = NULL; - if (strlen(pool_config->ssl_ca_cert)) - cacert = pool_config->ssl_ca_cert; if (strlen(pool_config->ssl_ca_cert_dir)) cacert_dir = pool_config->ssl_ca_cert_dir; @@ -690,7 +713,7 @@ SSL_ServerSide_init(void) { ereport(WARNING, (errmsg("could not load root certificate file \"%s\": %s", - pool_config->ssl_ca_cert, SSLerrmessage(ERR_get_error())))); + cacert, SSLerrmessage(ERR_get_error())))); goto error; } } @@ -702,12 +725,15 @@ SSL_ServerSide_init(void) */ if (pool_config->ssl_crl_file && strlen(pool_config->ssl_crl_file)) { + char ssl_crl_path[POOLMAXPATHLEN + 1] = ""; + pool_ssl_make_absolute_path(pool_config->ssl_crl_file, conf_dir, ssl_crl_path); + X509_STORE *cvstore = SSL_CTX_get_cert_store(context); if (cvstore) { /* Set the flags to check against the complete CRL chain */ - if (X509_STORE_load_locations(cvstore, pool_config->ssl_crl_file, NULL) == 1) + if (X509_STORE_load_locations(cvstore, ssl_crl_path, NULL) == 1) { /* OpenSSL 0.9.6 does not support X509_V_FLAG_CRL_CHECK */ #ifdef X509_V_FLAG_CRL_CHECK @@ -717,7 +743,7 @@ SSL_ServerSide_init(void) ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("SSL certificate revocation list file \"%s\" ignored", - pool_config->ssl_crl_file), + ssl_crl_path), errdetail("SSL library does not support certificate revocation lists."))); #endif } @@ -726,13 +752,13 @@ SSL_ServerSide_init(void) ereport(WARNING, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not load SSL certificate revocation list file \"%s\": %s", - pool_config->ssl_crl_file, SSLerrmessage(ERR_get_error())))); + ssl_crl_path, SSLerrmessage(ERR_get_error())))); goto error; } } } - if (pool_config->ssl_ca_cert && strlen(pool_config->ssl_ca_cert)) + if (strlen(ssl_ca_cert_path)) { /* * Always ask for SSL client cert, but don't fail if it's not @@ -763,6 +789,7 @@ SSL_ServerSide_init(void) return 0; error: + pfree(conf_file_copy); if (context) SSL_CTX_free(context); return -1; @@ -1012,6 +1039,18 @@ error: return len; } +void +pool_ssl_make_absolute_path(char *artifact_path, char *config_dir, char *absolute_path) +{ + if (artifact_path && strlen(artifact_path)) + { + if(is_absolute_path(artifact_path)) + strncpy(absolute_path, artifact_path, POOLMAXPATHLEN); + else + snprintf(absolute_path, POOLMAXPATHLEN, "%s/%s", config_dir, artifact_path); + } +} + #else /* USE_SSL: wrap / no-op ssl functionality if * it's not available */