@@ -2,12 +2,17 @@ extern crate owning_ref;
2
2
extern crate sodiumoxide;
3
3
extern crate r2d2;
4
4
extern crate r2d2_postgres;
5
+ extern crate postgres_openssl;
5
6
extern crate percent_encoding;
6
7
7
8
use :: std:: sync:: RwLock ;
8
9
9
10
use postgres;
10
11
use self :: r2d2_postgres:: { TlsMode , PostgresConnectionManager } ;
12
+ use self :: postgres_openssl:: { OpenSsl } ;
13
+ use self :: postgres_openssl:: openssl:: ssl:: { SslMethod , SslConnector } ;
14
+ use postgres_storage:: postgres_openssl:: openssl:: ssl:: SslConnectorBuilder ;
15
+
11
16
use serde_json;
12
17
13
18
use self :: owning_ref:: OwningHandle ;
@@ -369,10 +374,11 @@ impl StorageIterator for PostgresStorageIterator {
369
374
}
370
375
}
371
376
372
- #[ derive( Deserialize , Debug ) ]
377
+ #[ derive( Deserialize ) ]
373
378
pub struct PostgresConfig {
374
379
url : String ,
375
380
tls : Option < String > ,
381
+ tls_ca : Option < String > ,
376
382
// default off
377
383
max_connections : Option < u32 > ,
378
384
// default 5
@@ -384,28 +390,57 @@ pub struct PostgresConfig {
384
390
// default 5
385
391
wallet_scheme : Option < WalletScheme > , // default DatabasePerWallet
386
392
database_name : Option < String > , // default _WALLET_DB
393
+
394
+ // For TLS
395
+ #[ serde( skip) ]
396
+ negotiator : Option < OpenSsl > ,
397
+
387
398
}
388
399
389
400
impl PostgresConfig {
401
+
402
+ fn init_tls ( & mut self ) {
403
+ debug ! ( "initializing postgresql builder" ) ;
404
+
405
+ let mut builder = SslConnector :: builder ( SslMethod :: tls ( ) ) . unwrap ( ) ;
406
+
407
+ if self . tls_ca . is_some ( ) {
408
+ builder. set_ca_file ( self . tls_ca . as_ref ( ) . unwrap ( ) ) ;
409
+ }
410
+
411
+ debug ! ( "initializing postgresql negotiator" ) ;
412
+ self . negotiator = Some ( OpenSsl :: from ( builder. build ( ) ) ) ;
413
+ }
414
+
390
415
fn tls ( & self ) -> postgres:: TlsMode {
416
+ debug ! ( "tls" ) ;
391
417
match & self . tls {
392
418
Some ( tls) => match tls. as_ref ( ) {
393
419
"None" => postgres:: TlsMode :: None ,
394
420
// TODO add tls support for connecting to postgres db
395
- // "Prefer" => postgres::TlsMode::Prefer(&postgres::Connection ),
396
- // "Require" => postgres::TlsMode::Require(&postgres::Connection ),
421
+ "Prefer" => postgres:: TlsMode :: Prefer ( self . negotiator . as_ref ( ) . unwrap ( ) ) ,
422
+ "Require" => postgres:: TlsMode :: Require ( self . negotiator . as_ref ( ) . unwrap ( ) ) ,
397
423
_ => postgres:: TlsMode :: None
398
424
} ,
399
425
None => postgres:: TlsMode :: None
400
426
}
401
427
}
402
428
fn r2d2_tls ( & self ) -> TlsMode {
429
+
430
+ let mut builder = SslConnector :: builder ( SslMethod :: tls ( ) ) . unwrap ( ) ;
431
+
432
+ if self . tls_ca . is_some ( ) {
433
+ builder. set_ca_file ( self . tls_ca . as_ref ( ) . unwrap ( ) ) ;
434
+ }
435
+
436
+ let negotiator = OpenSsl :: from ( builder. build ( ) ) ;
437
+
403
438
match & self . tls {
404
439
Some ( tls) => match tls. as_ref ( ) {
405
440
"None" => TlsMode :: None ,
406
441
// TODO add tls support for connecting to postgres db
407
- // "Prefer" => TlsMode::Prefer(&postgres::Connection ),
408
- // "Require" => TlsMode::Require(&postgres::Connection ),
442
+ "Prefer" => r2d2_postgres :: TlsMode :: Prefer ( Box :: new ( negotiator ) ) ,
443
+ "Require" => r2d2_postgres :: TlsMode :: Require ( Box :: new ( negotiator ) ) ,
409
444
_ => TlsMode :: None
410
445
} ,
411
446
None => TlsMode :: None
@@ -511,7 +546,7 @@ impl WalletStrategy for MultiWalletSingleTableStrategySharedPool {
511
546
let url_base = PostgresStorageType :: _admin_postgres_url ( & config, & credentials) ;
512
547
let url = PostgresStorageType :: _postgres_url ( _WALLETS_DB, & config, & credentials) ;
513
548
514
- let conn = postgres:: Connection :: connect ( & url_base[ ..] , postgres :: TlsMode :: None ) ?;
549
+ let conn = postgres:: Connection :: connect ( & url_base[ ..] , config . tls ( ) ) ?;
515
550
516
551
if let Err ( error) = conn. execute ( & _CREATE_WALLETS_DATABASE, & [ ] ) {
517
552
if error. code ( ) != Some ( & postgres:: error:: DUPLICATE_DATABASE ) {
@@ -525,7 +560,7 @@ impl WalletStrategy for MultiWalletSingleTableStrategySharedPool {
525
560
}
526
561
conn. finish ( ) ?;
527
562
528
- let conn = match postgres:: Connection :: connect ( & url[ ..] , postgres :: TlsMode :: None ) {
563
+ let conn = match postgres:: Connection :: connect ( & url[ ..] , config . tls ( ) ) {
529
564
Ok ( conn) => conn,
530
565
Err ( error) => {
531
566
return Err ( WalletStorageError :: IOError ( format ! ( "Error occurred while connecting to wallet schema: {}" , error) ) ) ;
@@ -546,7 +581,7 @@ impl WalletStrategy for MultiWalletSingleTableStrategySharedPool {
546
581
// insert metadata
547
582
let url = PostgresStorageType :: _postgres_url ( _WALLETS_DB, & config, & credentials) ;
548
583
549
- let conn = match postgres:: Connection :: connect ( & url[ ..] , postgres :: TlsMode :: None ) {
584
+ let conn = match postgres:: Connection :: connect ( & url[ ..] , config . tls ( ) ) {
550
585
Ok ( conn) => conn,
551
586
Err ( error) => {
552
587
return Err ( WalletStorageError :: IOError ( format ! ( "Error occurred while connecting to wallet schema: {}" , error) ) ) ;
@@ -606,7 +641,7 @@ impl WalletStrategy for MultiWalletSingleTableStrategySharedPool {
606
641
fn delete_wallet ( & self , id : & str , config : & PostgresConfig , credentials : & PostgresCredentials ) -> Result < ( ) , WalletStorageError > {
607
642
let url = PostgresStorageType :: _postgres_url ( & _WALLETS_DB, & config, & credentials) ;
608
643
609
- let conn = match postgres:: Connection :: connect ( & url[ ..] , postgres :: TlsMode :: None ) {
644
+ let conn = match postgres:: Connection :: connect ( & url[ ..] , config . tls ( ) ) {
610
645
Ok ( conn) => conn,
611
646
Err ( error) => {
612
647
return Err ( WalletStorageError :: IOError ( format ! ( "Error occurred while connecting to wallet schema: {}" , error) ) ) ;
@@ -1856,7 +1891,7 @@ impl WalletStorageType for PostgresStorageType {
1856
1891
. map_or ( Ok ( None ) , |v| v. map ( Some ) )
1857
1892
. map_err ( |err| CommonError :: InvalidStructure ( format ! ( "Cannot deserialize credentials: {:?}" , err) ) ) ?;
1858
1893
1859
- let config = match config {
1894
+ let mut config = match config {
1860
1895
Some ( config) => config,
1861
1896
None => return Err ( WalletStorageError :: ConfigError )
1862
1897
} ;
@@ -1865,6 +1900,8 @@ impl WalletStorageType for PostgresStorageType {
1865
1900
None => return Err ( WalletStorageError :: ConfigError )
1866
1901
} ;
1867
1902
1903
+ config. init_tls ( ) ;
1904
+
1868
1905
match config. wallet_scheme {
1869
1906
Some ( scheme) => match scheme {
1870
1907
WalletScheme :: DatabasePerWallet => {
@@ -1938,7 +1975,7 @@ impl WalletStorageType for PostgresStorageType {
1938
1975
. map_or ( Ok ( None ) , |v| v. map ( Some ) )
1939
1976
. map_err ( |err| CommonError :: InvalidStructure ( format ! ( "Cannot deserialize credentials: {:?}" , err) ) ) ?;
1940
1977
1941
- let config = match config {
1978
+ let mut config = match config {
1942
1979
Some ( config) => config,
1943
1980
None => return Err ( WalletStorageError :: ConfigError )
1944
1981
} ;
@@ -1947,6 +1984,8 @@ impl WalletStorageType for PostgresStorageType {
1947
1984
None => return Err ( WalletStorageError :: ConfigError )
1948
1985
} ;
1949
1986
1987
+ config. init_tls ( ) ;
1988
+
1950
1989
let strategy_read_lock = SELECTED_STRATEGY . read ( ) . unwrap ( ) ;
1951
1990
strategy_read_lock. as_ref ( ) . delete_wallet ( id, & config, & credentials)
1952
1991
}
@@ -1988,7 +2027,7 @@ impl WalletStorageType for PostgresStorageType {
1988
2027
. map_or ( Ok ( None ) , |v| v. map ( Some ) )
1989
2028
. map_err ( |err| CommonError :: InvalidStructure ( format ! ( "Cannot deserialize credentials: {:?}" , err) ) ) ?;
1990
2029
1991
- let config = match config {
2030
+ let mut config = match config {
1992
2031
Some ( config) => config,
1993
2032
None => return Err ( WalletStorageError :: ConfigError )
1994
2033
} ;
@@ -1997,6 +2036,8 @@ impl WalletStorageType for PostgresStorageType {
1997
2036
None => return Err ( WalletStorageError :: ConfigError )
1998
2037
} ;
1999
2038
2039
+ config. init_tls ( ) ;
2040
+
2000
2041
// initialize using the global selected_strategy object
2001
2042
let r1 = SELECTED_STRATEGY . read ( ) . unwrap ( ) ;
2002
2043
r1. as_ref ( ) . create_wallet ( id, & config, & credentials, metadata)
@@ -2039,7 +2080,7 @@ impl WalletStorageType for PostgresStorageType {
2039
2080
. map_or ( Ok ( None ) , |v| v. map ( Some ) )
2040
2081
. map_err ( |err| CommonError :: InvalidStructure ( format ! ( "Cannot deserialize credentials: {:?}" , err) ) ) ?;
2041
2082
2042
- let config = match config
2083
+ let mut config = match config
2043
2084
{
2044
2085
Some ( config) => config,
2045
2086
None => return Err ( WalletStorageError :: ConfigError )
@@ -2049,6 +2090,8 @@ impl WalletStorageType for PostgresStorageType {
2049
2090
None => return Err ( WalletStorageError :: ConfigError )
2050
2091
} ;
2051
2092
2093
+ config. init_tls ( ) ;
2094
+
2052
2095
// initialize using the global selected_strategy object
2053
2096
let r1 = SELECTED_STRATEGY . read ( ) . unwrap ( ) ;
2054
2097
r1. as_ref ( ) . open_wallet ( id, & config, & credentials)
0 commit comments