Lines 19-25
Link Here
|
19 |
|
19 |
|
20 |
import org.postgresql.PGProperty; |
20 |
import org.postgresql.PGProperty; |
21 |
import org.postgresql.core.*; |
21 |
import org.postgresql.core.*; |
22 |
import org.postgresql.sspi.SSPIClient; |
|
|
23 |
import org.postgresql.hostchooser.GlobalHostStatusTracker; |
22 |
import org.postgresql.hostchooser.GlobalHostStatusTracker; |
24 |
import org.postgresql.hostchooser.HostChooser; |
23 |
import org.postgresql.hostchooser.HostChooser; |
25 |
import org.postgresql.hostchooser.HostChooserFactory; |
24 |
import org.postgresql.hostchooser.HostChooserFactory; |
Lines 387-397
Link Here
|
387 |
// or an authentication request |
386 |
// or an authentication request |
388 |
|
387 |
|
389 |
String password = PGProperty.PASSWORD.get(info); |
388 |
String password = PGProperty.PASSWORD.get(info); |
390 |
|
|
|
391 |
/* SSPI negotiation state, if used */ |
392 |
SSPIClient sspiClient = null; |
393 |
|
389 |
|
394 |
try { |
|
|
395 |
authloop: |
390 |
authloop: |
396 |
while (true) |
391 |
while (true) |
397 |
{ |
392 |
{ |
Lines 507-594
Link Here
|
507 |
case AUTH_REQ_SSPI: |
502 |
case AUTH_REQ_SSPI: |
508 |
/* |
503 |
/* |
509 |
* Use GSSAPI if requested on all platforms, via JSSE. |
504 |
* Use GSSAPI if requested on all platforms, via JSSE. |
510 |
* |
|
|
511 |
* For SSPI auth requests, if we're on Windows attempt native SSPI |
512 |
* authentication if available, and if not disabled by setting a |
513 |
* kerberosServerName. On other platforms, attempt JSSE GSSAPI |
514 |
* negotiation with the SSPI server. |
515 |
* |
516 |
* Note that this is slightly different to libpq, which uses SSPI |
517 |
* for GSSAPI where supported. We prefer to use the existing Java |
518 |
* JSSE Kerberos support rather than going to native (via JNA) calls |
519 |
* where possible, so that JSSE system properties etc continue |
520 |
* to work normally. |
521 |
* |
522 |
* Note that while SSPI is often Kerberos-based there's no guarantee |
523 |
* it will be; it may be NTLM or anything else. If the client responds |
524 |
* to an SSPI request via GSSAPI and the other end isn't using Kerberos |
525 |
* for SSPI then authentication will fail. |
526 |
*/ |
505 |
*/ |
527 |
final String gsslib = PGProperty.GSS_LIB.get(info); |
506 |
org.postgresql.gss.MakeGSS.authenticate(pgStream, host, |
528 |
final boolean usespnego = PGProperty.USE_SPNEGO.getBoolean(info); |
507 |
user, password, |
529 |
|
508 |
PGProperty.JAAS_APPLICATION_NAME.get(info), |
530 |
boolean useSSPI = false; |
509 |
PGProperty.KERBEROS_SERVER_NAME.get(info), |
|
|
510 |
logger, |
511 |
PGProperty.USE_SPNEGO.getBoolean(info)); |
512 |
|
513 |
break; |
531 |
|
514 |
|
532 |
/* |
|
|
533 |
* Use SSPI if we're in auto mode on windows and have a |
534 |
* request for SSPI auth, or if it's forced. Otherwise |
535 |
* use gssapi. If the user has specified a Kerberos server |
536 |
* name we'll always use JSSE GSSAPI. |
537 |
*/ |
538 |
if (gsslib.equals("gssapi")) |
539 |
logger.debug("Using JSSE GSSAPI, param gsslib=gssapi"); |
540 |
else if (areq == AUTH_REQ_GSS && !gsslib.equals("sspi")) |
541 |
logger.debug("Using JSSE GSSAPI, gssapi requested by server and gsslib=sspi not forced"); |
542 |
else |
543 |
{ |
544 |
/* Determine if SSPI is supported by the client */ |
545 |
sspiClient = new SSPIClient(pgStream, |
546 |
PGProperty.SSPI_SERVICE_CLASS.get(info), |
547 |
/* Use negotiation for SSPI, or if explicitly requested for GSS */ |
548 |
areq == AUTH_REQ_SSPI || (areq == AUTH_REQ_GSS && usespnego), |
549 |
logger); |
550 |
|
551 |
useSSPI = sspiClient.isSSPISupported(); |
552 |
logger.debug("SSPI support detected: " + useSSPI); |
553 |
|
554 |
if (!useSSPI) { |
555 |
/* No need to dispose() if no SSPI used */ |
556 |
sspiClient = null; |
557 |
|
558 |
if (gsslib.equals("sspi")) |
559 |
throw new PSQLException("SSPI forced with gsslib=sspi, but SSPI not available; set loglevel=2 for details", |
560 |
PSQLState.CONNECTION_UNABLE_TO_CONNECT); |
561 |
} |
562 |
|
563 |
logger.debug("Using SSPI: " + useSSPI + ", gsslib="+gsslib+" and SSPI support detected"); |
564 |
} |
565 |
|
566 |
if (useSSPI) |
567 |
{ |
568 |
/* SSPI requested and detected as available */ |
569 |
sspiClient.startSSPI(); |
570 |
} |
571 |
else |
572 |
{ |
573 |
/* Use JGSS's GSSAPI for this request */ |
574 |
org.postgresql.gss.MakeGSS.authenticate(pgStream, host, |
575 |
user, password, |
576 |
PGProperty.JAAS_APPLICATION_NAME.get(info), |
577 |
PGProperty.KERBEROS_SERVER_NAME.get(info), |
578 |
logger, |
579 |
usespnego); |
580 |
} |
581 |
|
582 |
break; |
583 |
|
584 |
case AUTH_REQ_GSS_CONTINUE: |
585 |
/* |
586 |
* Only called for SSPI, as GSS is handled by an inner loop |
587 |
* in MakeGSS. |
588 |
*/ |
589 |
sspiClient.continueSSPI(l_msgLen - 8); |
590 |
break; |
591 |
|
592 |
case AUTH_REQ_OK: |
515 |
case AUTH_REQ_OK: |
593 |
/* Cleanup after successful authentication */ |
516 |
/* Cleanup after successful authentication */ |
594 |
if (logger.logDebug()) |
517 |
if (logger.logDebug()) |
Lines 609-626
Link Here
|
609 |
throw new PSQLException(GT.tr("Protocol error. Session setup failed."), PSQLState.PROTOCOL_VIOLATION); |
532 |
throw new PSQLException(GT.tr("Protocol error. Session setup failed."), PSQLState.PROTOCOL_VIOLATION); |
610 |
} |
533 |
} |
611 |
} |
534 |
} |
612 |
} finally { |
|
|
613 |
/* Cleanup after successful or failed authentication attempts */ |
614 |
if (sspiClient != null) |
615 |
{ |
616 |
try { |
617 |
sspiClient.dispose(); |
618 |
} catch (RuntimeException ex) { |
619 |
logger.log("Unexpected error during SSPI context disposal", ex); |
620 |
} |
621 |
|
622 |
} |
623 |
} |
624 |
|
535 |
|
625 |
} |
536 |
} |
626 |
|
537 |
|