@@ -274,7 +274,7 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
274
274
offsetof(struct pg_conn , sslmode )},
275
275
276
276
{"sslnegotiation" , "PGSSLNEGOTIATION" , DefaultSSLNegotiation , NULL ,
277
- "SSL-Negotiation" , "" , 14 , /* sizeof("requiredirect ") == 14 */
277
+ "SSL-Negotiation" , "" , 9 , /* sizeof("postgres ") == 9 */
278
278
offsetof(struct pg_conn , sslnegotiation )},
279
279
280
280
{"sslcompression" , "PGSSLCOMPRESSION" , "0" , NULL ,
@@ -1590,8 +1590,7 @@ pqConnectOptions2(PGconn *conn)
1590
1590
if (conn -> sslnegotiation )
1591
1591
{
1592
1592
if (strcmp (conn -> sslnegotiation , "postgres" ) != 0
1593
- && strcmp (conn -> sslnegotiation , "direct" ) != 0
1594
- && strcmp (conn -> sslnegotiation , "requiredirect" ) != 0 )
1593
+ && strcmp (conn -> sslnegotiation , "direct" ) != 0 )
1595
1594
{
1596
1595
conn -> status = CONNECTION_BAD ;
1597
1596
libpq_append_conn_error (conn , "invalid %s value: \"%s\"" ,
@@ -1608,6 +1607,25 @@ pqConnectOptions2(PGconn *conn)
1608
1607
return false;
1609
1608
}
1610
1609
#endif
1610
+
1611
+ /*
1612
+ * Don't allow direct SSL negotiation with sslmode='prefer', because
1613
+ * that poses a risk of unintentional fallback to plaintext connection
1614
+ * when connecting to a pre-v17 server that does not support direct
1615
+ * SSL connections. To keep things simple, don't allow it with
1616
+ * sslmode='allow' or sslmode='disable' either. If a user goes through
1617
+ * the trouble of setting sslnegotiation='direct', they probably
1618
+ * intend to use SSL, and sslmode=disable or allow is probably a user
1619
+ * user mistake anyway.
1620
+ */
1621
+ if (conn -> sslnegotiation [0 ] == 'd' &&
1622
+ conn -> sslmode [0 ] != 'r' && conn -> sslmode [0 ] != 'v' )
1623
+ {
1624
+ conn -> status = CONNECTION_BAD ;
1625
+ libpq_append_conn_error (conn , "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")" ,
1626
+ conn -> sslmode );
1627
+ return false;
1628
+ }
1611
1629
}
1612
1630
else
1613
1631
{
@@ -3347,42 +3365,45 @@ PQconnectPoll(PGconn *conn)
3347
3365
goto error_return ;
3348
3366
3349
3367
/*
3350
- * If direct SSL is enabled, jump right into SSL handshake . We
3351
- * will come back here after SSL encryption has been
3352
- * established, with ssl_in_use set.
3368
+ * If SSL is enabled, start the SSL negotiation . We will come
3369
+ * back here after SSL encryption has been established, with
3370
+ * ssl_in_use set.
3353
3371
*/
3354
- if (conn -> current_enc_method == ENC_DIRECT_SSL && !conn -> ssl_in_use )
3372
+ if (conn -> current_enc_method == ENC_SSL && !conn -> ssl_in_use )
3355
3373
{
3356
- conn -> status = CONNECTION_SSL_STARTUP ;
3357
- return PGRES_POLLING_WRITING ;
3358
- }
3359
-
3360
- /*
3361
- * If negotiated SSL is enabled, request SSL and proceed with
3362
- * SSL handshake. We will come back here after SSL encryption
3363
- * has been established, with ssl_in_use set.
3364
- */
3365
- if (conn -> current_enc_method == ENC_NEGOTIATED_SSL && !conn -> ssl_in_use )
3366
- {
3367
- ProtocolVersion pv ;
3368
-
3369
3374
/*
3370
- * Send the SSL request packet.
3371
- *
3372
- * Theoretically, this could block, but it really
3373
- * shouldn't since we only got here if the socket is
3374
- * write-ready.
3375
+ * If traditional postgres SSL negotiation is used, send
3376
+ * the SSL request. In direct negotiation, jump straight
3377
+ * into the SSL handshake.
3375
3378
*/
3376
- pv = pg_hton32 (NEGOTIATE_SSL_CODE );
3377
- if (pqPacketSend (conn , 0 , & pv , sizeof (pv )) != STATUS_OK )
3379
+ if (conn -> sslnegotiation [0 ] == 'p' )
3378
3380
{
3379
- libpq_append_conn_error (conn , "could not send SSL negotiation packet: %s" ,
3380
- SOCK_STRERROR (SOCK_ERRNO , sebuf , sizeof (sebuf )));
3381
- goto error_return ;
3381
+ ProtocolVersion pv ;
3382
+
3383
+ /*
3384
+ * Send the SSL request packet.
3385
+ *
3386
+ * Theoretically, this could block, but it really
3387
+ * shouldn't since we only got here if the socket is
3388
+ * write-ready.
3389
+ */
3390
+ pv = pg_hton32 (NEGOTIATE_SSL_CODE );
3391
+ if (pqPacketSend (conn , 0 , & pv , sizeof (pv )) != STATUS_OK )
3392
+ {
3393
+ libpq_append_conn_error (conn , "could not send SSL negotiation packet: %s" ,
3394
+ SOCK_STRERROR (SOCK_ERRNO , sebuf , sizeof (sebuf )));
3395
+ goto error_return ;
3396
+ }
3397
+ /* Ok, wait for response */
3398
+ conn -> status = CONNECTION_SSL_STARTUP ;
3399
+ return PGRES_POLLING_READING ;
3400
+ }
3401
+ else
3402
+ {
3403
+ Assert (conn -> sslnegotiation [0 ] == 'd' );
3404
+ conn -> status = CONNECTION_SSL_STARTUP ;
3405
+ return PGRES_POLLING_WRITING ;
3382
3406
}
3383
- /* Ok, wait for response */
3384
- conn -> status = CONNECTION_SSL_STARTUP ;
3385
- return PGRES_POLLING_READING ;
3386
3407
}
3387
3408
#endif /* USE_SSL */
3388
3409
@@ -3453,11 +3474,11 @@ PQconnectPoll(PGconn *conn)
3453
3474
PostgresPollingStatusType pollres ;
3454
3475
3455
3476
/*
3456
- * On first time through, get the postmaster's response to our
3457
- * SSL negotiation packet. If we are trying a direct ssl
3458
- * connection , go straight to initiating ssl .
3477
+ * On first time through with traditional SSL negotiation, get
3478
+ * the postmaster's response to our SSLRequest packet. With
3479
+ * sslnegotiation='direct' , go straight to initiating SSL .
3459
3480
*/
3460
- if (!conn -> ssl_in_use && conn -> current_enc_method == ENC_NEGOTIATED_SSL )
3481
+ if (!conn -> ssl_in_use && conn -> sslnegotiation [ 0 ] == 'p' )
3461
3482
{
3462
3483
/*
3463
3484
* We use pqReadData here since it has the logic to
@@ -4282,7 +4303,7 @@ init_allowed_encryption_methods(PGconn *conn)
4282
4303
if (conn -> raddr .addr .ss_family == AF_UNIX )
4283
4304
{
4284
4305
/* Don't request SSL or GSSAPI over Unix sockets */
4285
- conn -> allowed_enc_methods &= ~(ENC_DIRECT_SSL | ENC_NEGOTIATED_SSL | ENC_GSSAPI );
4306
+ conn -> allowed_enc_methods &= ~(ENC_SSL | ENC_GSSAPI );
4286
4307
4287
4308
/*
4288
4309
* XXX: we probably should not do this. sslmode=require works
@@ -4309,12 +4330,7 @@ init_allowed_encryption_methods(PGconn *conn)
4309
4330
/* sslmode anything but 'disable', and GSSAPI not required */
4310
4331
if (conn -> sslmode [0 ] != 'd' && conn -> gssencmode [0 ] != 'r' )
4311
4332
{
4312
- if (conn -> sslnegotiation [0 ] == 'p' )
4313
- conn -> allowed_enc_methods |= ENC_NEGOTIATED_SSL ;
4314
- else if (conn -> sslnegotiation [0 ] == 'd' )
4315
- conn -> allowed_enc_methods |= ENC_DIRECT_SSL | ENC_NEGOTIATED_SSL ;
4316
- else if (conn -> sslnegotiation [0 ] == 'r' )
4317
- conn -> allowed_enc_methods |= ENC_DIRECT_SSL ;
4333
+ conn -> allowed_enc_methods |= ENC_SSL ;
4318
4334
}
4319
4335
#endif
4320
4336
@@ -4354,7 +4370,8 @@ encryption_negotiation_failed(PGconn *conn)
4354
4370
4355
4371
if (select_next_encryption_method (conn , true))
4356
4372
{
4357
- if (conn -> current_enc_method == ENC_DIRECT_SSL )
4373
+ /* An existing connection cannot be reused for direct SSL */
4374
+ if (conn -> current_enc_method == ENC_SSL && conn -> sslnegotiation [0 ] == 'd' )
4358
4375
return 2 ;
4359
4376
else
4360
4377
return 1 ;
@@ -4376,18 +4393,6 @@ connection_failed(PGconn *conn)
4376
4393
Assert ((conn -> failed_enc_methods & conn -> current_enc_method ) == 0 );
4377
4394
conn -> failed_enc_methods |= conn -> current_enc_method ;
4378
4395
4379
- /*
4380
- * If the server reported an error after the SSL handshake, no point in
4381
- * retrying with negotiated vs direct SSL.
4382
- */
4383
- if ((conn -> current_enc_method & (ENC_DIRECT_SSL | ENC_NEGOTIATED_SSL )) != 0 &&
4384
- conn -> ssl_handshake_started )
4385
- {
4386
- conn -> failed_enc_methods |= (ENC_DIRECT_SSL | ENC_NEGOTIATED_SSL ) & conn -> allowed_enc_methods ;
4387
- }
4388
- else
4389
- conn -> failed_enc_methods |= conn -> current_enc_method ;
4390
-
4391
4396
return select_next_encryption_method (conn , false);
4392
4397
}
4393
4398
@@ -4445,24 +4450,17 @@ select_next_encryption_method(PGconn *conn, bool have_valid_connection)
4445
4450
SELECT_NEXT_METHOD (ENC_GSSAPI );
4446
4451
#endif
4447
4452
4448
- /* With sslmode=allow, try plaintext connection before SSL. */
4449
- if (conn -> sslmode [0 ] == 'a' )
4450
- SELECT_NEXT_METHOD (ENC_PLAINTEXT );
4451
-
4452
4453
/*
4453
- * If enabled, try direct SSL. Unless we have a valid TCP connection that
4454
- * failed negotiating GSSAPI encryption; in that case we prefer to reuse
4455
- * the connection with negotiated SSL, instead of reconnecting to do
4456
- * direct SSL. The point of sslnegotiation=direct is to avoid the
4457
- * roundtrip from the negotiation, but reconnecting would also incur a
4458
- * roundtrip. (In sslnegotiation=requiredirect mode, negotiated SSL is not
4459
- * in the list of allowed methods and we will reconnect.)
4454
+ * The order between SSL encryption and plaintext depends on sslmode. With
4455
+ * sslmode=allow, try plaintext connection before SSL. With
4456
+ * sslmode=prefer, it's the other way round. With other modes, we only try
4457
+ * plaintext or SSL connections so the order they're listed here doesn't
4458
+ * matter.
4460
4459
*/
4461
- if (have_valid_connection )
4462
- SELECT_NEXT_METHOD (ENC_NEGOTIATED_SSL );
4460
+ if (conn -> sslmode [ 0 ] == 'a' )
4461
+ SELECT_NEXT_METHOD (ENC_PLAINTEXT );
4463
4462
4464
- SELECT_NEXT_METHOD (ENC_DIRECT_SSL );
4465
- SELECT_NEXT_METHOD (ENC_NEGOTIATED_SSL );
4463
+ SELECT_NEXT_METHOD (ENC_SSL );
4466
4464
4467
4465
if (conn -> sslmode [0 ] != 'a' )
4468
4466
SELECT_NEXT_METHOD (ENC_PLAINTEXT );
0 commit comments