@@ -45,6 +45,11 @@ def parse(cls, sslmode):
4545 return  getattr (cls , sslmode .replace ('-' , '_' ))
4646
4747
48+ class  SSLNegotiation (compat .StrEnum ):
49+  postgres  =  "postgres" 
50+  direct  =  "direct" 
51+ 
52+ 
4853_ConnectionParameters  =  collections .namedtuple (
4954 'ConnectionParameters' ,
5055 [
@@ -53,7 +58,7 @@ def parse(cls, sslmode):
5358 'database' ,
5459 'ssl' ,
5560 'sslmode' ,
56-  'direct_tls ' ,
61+  'ssl_negotiation ' ,
5762 'server_settings' ,
5863 'target_session_attrs' ,
5964 'krbsrvname' ,
@@ -269,6 +274,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user,
269274 auth_hosts  =  None 
270275 sslcert  =  sslkey  =  sslrootcert  =  sslcrl  =  sslpassword  =  None 
271276 ssl_min_protocol_version  =  ssl_max_protocol_version  =  None 
277+  sslnegotiation  =  None 
272278
273279 if  dsn :
274280 parsed  =  urllib .parse .urlparse (dsn )
@@ -362,6 +368,9 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user,
362368 if  'sslrootcert'  in  query :
363369 sslrootcert  =  query .pop ('sslrootcert' )
364370
371+  if  'sslnegotiation'  in  query :
372+  sslnegotiation  =  query .pop ('sslnegotiation' )
373+ 
365374 if  'sslcrl'  in  query :
366375 sslcrl  =  query .pop ('sslcrl' )
367376
@@ -503,13 +512,36 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user,
503512 if  ssl  is  None  and  have_tcp_addrs :
504513 ssl  =  'prefer' 
505514
515+  if  direct_tls  is  not None :
516+  sslneg  =  (
517+  SSLNegotiation .direct  if  direct_tls  else  SSLNegotiation .postgres 
518+  )
519+  else :
520+  if  sslnegotiation  is  None :
521+  sslnegotiation  =  os .environ .get ("PGSSLNEGOTIATION" )
522+ 
523+  if  sslnegotiation  is  not None :
524+  try :
525+  sslneg  =  SSLNegotiation (sslnegotiation )
526+  except  ValueError :
527+  modes  =  ', ' .join (
528+  m .name .replace ('_' , '-' )
529+  for  m  in  SSLNegotiation 
530+  )
531+  raise  exceptions .ClientConfigurationError (
532+  f'`sslnegotiation` parameter must be one of: { modes }  
533+  ) from  None 
534+  else :
535+  sslneg  =  SSLNegotiation .postgres 
536+ 
506537 if  isinstance (ssl , (str , SSLMode )):
507538 try :
508539 sslmode  =  SSLMode .parse (ssl )
509540 except  AttributeError :
510541 modes  =  ', ' .join (m .name .replace ('_' , '-' ) for  m  in  SSLMode )
511542 raise  exceptions .ClientConfigurationError (
512-  '`sslmode` parameter must be one of: {}' .format (modes ))
543+  '`sslmode` parameter must be one of: {}' .format (modes )
544+  ) from  None 
513545
514546 # docs at https://www.postgresql.org/docs/10/static/libpq-connect.html 
515547 if  sslmode  <  SSLMode .allow :
@@ -676,7 +708,7 @@ def _parse_connect_dsn_and_args(*, dsn, host, port, user,
676708
677709 params  =  _ConnectionParameters (
678710 user = user , password = password , database = database , ssl = ssl ,
679-  sslmode = sslmode , direct_tls = direct_tls ,
711+  sslmode = sslmode , ssl_negotiation = sslneg ,
680712 server_settings = server_settings ,
681713 target_session_attrs = target_session_attrs ,
682714 krbsrvname = krbsrvname , gsslib = gsslib )
@@ -882,9 +914,9 @@ async def __connect_addr(
882914 # UNIX socket 
883915 connector  =  loop .create_unix_connection (proto_factory , addr )
884916
885-  elif  params .ssl  and  params .direct_tls :
886-  # if ssl and direct_tls are given , skip STARTTLS and perform direct  
887-  # SSL connection 
917+  elif  params .ssl  and  params .ssl_negotiation   is   SSLNegotiation . direct :
918+  # if ssl and ssl_negotiation is `direct` , skip STARTTLS and perform 
919+  # direct  SSL connection 
888920 connector  =  loop .create_connection (
889921 proto_factory , * addr , ssl = params .ssl 
890922 )
0 commit comments