Settings of SSL context for PGserver and for libpq
От | Dmitrij K |
---|---|
Тема | Settings of SSL context for PGserver and for libpq |
Дата | |
Msg-id | DUB116-W11959D17D7B0131C5AF6E62C1620@phx.gbl обсуждение исходный текст |
Список | pgsql-hackers |
Dear Developers.
Could you do things written in this message ?
/// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
Target auditorium of this doc are: developers the Postgresql, developers apps c/c++, paranoiacs .
A hosting(dedicted/virtual) is not safe place for storing the private key/cert.
Here is presented a concept secured way to initialize context SSL for PGserver.
This doc has three parts:
1) module, that will load dynamically by the PGserver for initializing the context SSL, and import this into the PGserver address space.
2) some server actions (checking cert & pkey), and adding new variable into `pg_config'.
3) and some recomendations for adding new procs into API libpq.
PS: this way is not panacea, but is protecting from fools.
PSS: sorry for my english.
Thanks for your attention.
--
The best regards.
*/
/// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
1) Part first:
Module side: module is a shared library written on `C' - for get symbol `PGimportSSLCTX' by `dlsym' from the PGserver.
*/
// [SOURCEFILE=pg_import_sslctx.c]
// for compile it by GCC: gcc -shared -fPIC -c pg_import_sslctx.c && ld -shared -export-dynamic pg_import_sslctx.o -o libpg_import_sslctx.so -ldl -lc
#include <stdint.h>
#include <sys/types.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
// function for export SSL_CTX into the PGserver address space
extern int PGimportSSLCTX ( SSL_CTX **pp_ctx );
void *h_ssl; // handle of `libssl'
// cert and private key in a encrypted form (simulation)
uint8_t pkey [] = {'s', 'u', 'p', 'e', 'r', ' ', 'e', 'n', 'c', 'r', 'y', 'p', 't', 'e', 'd', ' ', 'k', 'e', 'y', 0};
uint8_t cert [] = {'s', 'u', 'p', 'e', 'r', ' ', 'e', 'n', 'c', 'r', 'y', 'p', 't', 'e', 'd', ' ', 'c', 'e', 'r', 't', 0};
// blank proc decrypting the cert/pkey (simulation)
void decrypt (uint8_t *data) { return ; }
// simulation of trusted certs
uint8_t trusted_cert1 [] = {0, 5, 7, 12, 76, 4, 9};
uint8_t trusted_cert2 [] = {89, 5, 4, 12, 56, 11, 0};
// NOTE : for windows, you can use the `dlfcn-win32' , or you can use code below:
#ifdef _WIN32
#include <windows.h>
#define RTLD_LAZY 0x00001
#define RTLD_NOW 0x00002
#define RTLD_BINDING_MASK 0x3
#define RTLD_NOLOAD 0x00004
#define RTLD_GLOBAL 0x00100
#define RTLD_LOCAL 0
#define RTLD_NODELETE 0x01000
inline void* dlopen ( const char *f, int m ){
HMODULE *hdll;
DWORD flags;
flags = LOAD_WITH_ALTERED_SEARCH_PATH;
if( (m & RTLD_LAZY) ){ flags |= DONT_RESOLVE_DLL_REFERENCES; }
if(f == NULL){ hdll = (HMODULE *) GetModuleHandle ( NULL ); }
else { hdll = (HMODULE *) LoadLibraryEx ( f, NULL, flags ); }
return (void *) hdll;
}
inline int dlclose ( void* h ) {
if ( !FreeLibrary ((HMODULE)h) ){ return -1; }
return 0;
}
inline void* dlsym ( void* h, const char *name ) {
return (void *) GetProcAddress ( (HMODULE)h, name );
}
#else
#include <dlfcn.h>
#include <sys/mman.h>
#endif
// this procedure will be called after loading the shared lib
void _init () {
#if defined (_WIN32)
// I don't know how to off swapping on Windows, sorry :(...
const char *filedll = "libssl.dll";
#else
mlockall ( MCL_CURRENT ); // swap off
const char *filedll = "libssl.so"; // `libssl.so' is link to `libssl.so.1.0.0' usually
#endif
// We are trying load `libssl'
h_ssl = dlopen ( filedll, RTLD_NOW | RTLD_NOLOAD );
if ( !h_ssl ) { h_ssl = dlopen ( filedll, RTLD_NOW | RTLD_LOCAL ); }
}
// this procedure will be called before unloading the shared lib
void _fini () {
if ( h_ssl ) { dlclose ( h_ssl ); } // unload `libssl'
#ifndef _WIN32
munlockall ();
#endif
}
// pointers to procedures SSL, imported form shared `libssl'
const SSL_METHOD* (*p_TLSv1_server_method)(void);
SSL_CTX* (*p_SSL_CTX_new)(const SSL_METHOD*);
void (*p_SSL_CTX_free)(SSL_CTX*);
int (*p_SSL_CTX_use_PrivateKey)(SSL_CTX*,EVP_PKEY*);
int (*p_SSL_CTX_use_certificate)(SSL_CTX*,X509*);
void (*p_SSL_CTX_set_verify)(SSL_CTX*,int ,int(*)(int,X509_STORE_CTX*));
long (*p_SSL_CTX_ctrl)(SSL_CTX*,int,long,void*);
// realisation:
int PGimportSSLCTX ( SSL_CTX **pp_ctx ) {
int ret;
SSL_CTX *ctx;
const SSL_METHOD *meth;
ret = 0;
if ( !h_ssl ) { goto end; } // libssl was not loaded
if ( !( p_TLSv1_server_method = dlsym ( h_ssl, "TLSv1_server_method" ) ) ) { goto end; } // fails get symbol
if ( !( meth = p_TLSv1_server_method () ) ) { goto end; } // fails get TLSv1_server_method
if ( !( p_SSL_CTX_new = dlsym ( h_ssl, "SSL_CTX_new" ) ) ) { goto end; } // fails get symbol
if ( !( ctx = p_SSL_CTX_new ( meth) ) ) { goto end; } // fails create new context
// decrypt ours the private key and the cert
decrypt ( pkey );
decrypt ( cert );
if ( !( p_SSL_CTX_use_PrivateKey = dlsym ( h_ssl, "SSL_CTX_use_PrivateKey" ) ) ) { goto end; } // fails get symbol
if ( !( p_SSL_CTX_use_certificate = dlsym ( h_ssl, "SSL_CTX_use_certificate" ) ) ) { goto end; } // fails get symbol
// maybe we need do `d2i_PrivateKey' before setup pkey/cert into the context ? ..
if ( p_SSL_CTX_use_PrivateKey ( ctx, (EVP_PKEY*) pkey ) <= 0 ) { goto end; } // fails set the private key into the context
if ( p_SSL_CTX_use_certificate ( ctx, (X509*) cert ) <= 0 ) { goto end; } // fails set the cert into the context
if ( !( p_SSL_CTX_set_verify = dlsym ( h_ssl, "SSL_CTX_set_verify" ) ) ) { goto end; } // fails get symbol
// set up rules of verifyng
p_SSL_CTX_set_verify ( ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL );
if ( !( p_SSL_CTX_ctrl = dlsym ( h_ssl, "SSL_CTX_ctrl" ) ) ) { goto end; } // fails get symbol
// making our own trusted chain of certs:
p_SSL_CTX_ctrl ( ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, (char *)trusted_cert1 );
p_SSL_CTX_ctrl ( ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, (char *)trusted_cert2 );
// set up options to the context
p_SSL_CTX_ctrl ( ctx, SSL_CTRL_OPTIONS, SSL_OP_NO_SSLv2 |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION, NULL );
// set up modes to the context
p_SSL_CTX_ctrl ( ctx,
SSL_CTRL_MODE, SSL_MODE_ENABLE_PARTIAL_WRITE |
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
SSL_MODE_AUTO_RETRY, NULL );
ret = 1;
end:
if ( ret ) { *pp_ctx = ctx; }
else if ( ctx ){
if ( ( p_SSL_CTX_free = dlsym ( h_ssl, "SSL_CTX_free" ) ) ) {
p_SSL_CTX_free ( ctx );
}
}
return ret;
}
// [/SOURCEFILE]
/// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
2) Part second:
Server side:
[CONFIGFILE]
PG_IMPORT_SSLCTX="/usr/lib/postgresql/libpg_import_sslctx.so"
[/CONFIGFILE]
*/
// NOTE : imported from a module the SSL context MUST BE freed by server side !!!
// a some place in the PGserver source code ...
const char *path2mod; // path to a module
SSL_CTX *ctx; // the context
ctx = NULL;
// trying to get path to module import ssl context from config file
if ( ( path2mod = get_PG_IMPORT_SSLCTX_from_ConfigFile() ) ) {
// we have a path to module, needs to load it
int ret;
void *h_mod; // handle of `libpg_import_sslctx.so'
int (*p_PGimportSSLCTX) ( SSL_CTX ** ); // pointer to `PGimportSSLCTX' proc
ret = 0;
if ( !( h_mod = dlopen (path2mod, RTLD_NOW | RTLD_LOCAL) ) ) { goto end; } // can't load the module
if ( !( p_PGimportSSLCTX = dlsym (h_mod, "PGimportSSLCTX") ) ) { goto end; } // can't get the symbol of importing the SSL context
if ( !p_PGimportSSLCTX ( &ctx ) ) { goto end; } // can't get the SSL context for accepting SSL/TLS connections
if ( SSL_CTX_check_private_key(ctx) <= 0 ) { goto end; } // private key and cert are not match ! fails !
// and other actions, that needed for starting accepting SSL/TLS connections ...
ret = 1;
end:
if ( h_mod ) { dlclose ( h_mod ); } // unload the module
if ( !ret && ctx ) { SSL_CTX_free ( ctx ); ctx = NULL; } // fails, needs to free the context
}
/// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/*
3) Part third:
client side (libpq):
*/
// will be very good thing to add into libpq API something like:
extern PGconn *PQconnectStart(const char *conninfo, SSL_CTX *ctx);
extern PGconn *PQconnectdb(const char *conninfo, SSL_CTX *ctx);
В списке pgsql-hackers по дате отправления:
Предыдущее
От: Josh BerkusДата:
Сообщение: Re: Proposal/design feedback needed: WITHIN GROUP (sql standard ordered set aggregate functions)
Следующее
От: Alvaro HerreraДата:
Сообщение: Re: ALTER SYSTEM SET command to change postgresql.conf parameters (RE: Proposal for Allow postgresql.conf values to be changed via SQL [review])