SSO с Java настольным клиентом - в LSA не найдено TGT - PullRequest
0 голосов
/ 13 февраля 2020

Мне нужно создать настольное приложение Java, которое выполняет единый вход (SSO) на сервере Active Directory. Приложению не удалось пройти первый шаг - получить кэшированный билет TGT для текущего пользователя Windows. Я получаю следующий вывод (с параметрами отладки безопасности, включенными в командной строке):

Java config name: null
Native config name: C:\Windows\krb5.ini
Search Subject for Kerberos V5 INIT cred (<<DEF>>, sun.security.jgss.krb5.Krb5InitCredential)
No Subject
configfile: reading file:/C:/Develoment/SSO_Testing/etc/login.conf
configparser:   Reading next config entry: com.sun.security.jgss.krb5.initiate
configparser:       com.sun.security.auth.module.Krb5LoginModule, REQUIRED
configparser:           debug=true
configparser:           renewTGT=true
configparser:           doNotPrompt=true
configparser:           storeKey=false
configparser:           useKeyTab=false
configparser:           useTicketCache=true
    [GSS LoginConfigImpl]: Trying com.sun.security.jgss.krb5.initiate: Found!
Debug is  true storeKey false useTicketCache true useKeyTab false doNotPrompt true ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is null tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Acquire TGT from Cache
>>>KinitOptions cache name is C:\Users\myusername\krb5cc_myusername
>> Acquire default native Credentials
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
>>> Found no TGT's in LSA
Principal is null
null credentials from Ticket Cache
        [Krb5LoginModule] authentication failed 
Unable to obtain Principal Name for authentication 
    [LoginContext]: login REQUIRED failure
    [LoginContext]: abort ignored
GSSException: No valid credentials provided (Mechanism level: Attempt to obtain new INITIATE credentials failed! (null))
    at sun.security.jgss.krb5.Krb5InitCredential.getTgt(Unknown Source)
    at sun.security.jgss.krb5.Krb5InitCredential.getInstance(Unknown Source)
    at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Unknown Source)
    at sun.security.jgss.krb5.Krb5MechFactory.getMechanismContext(Unknown Source)
    at sun.security.jgss.GSSManagerImpl.getMechanismContext(Unknown Source)
    at sun.security.jgss.GSSContextImpl.initSecContext(Unknown Source)
    at sun.security.jgss.GSSContextImpl.initSecContext(Unknown Source)
    at main.java.TestGetTicket2.main(TestGetTicket2.java:22)
Caused by: javax.security.auth.login.LoginException: Unable to obtain Principal Name for authentication 
    at com.sun.security.auth.module.Krb5LoginModule.promptForName(Unknown Source)
    at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Unknown Source)
    at com.sun.security.auth.module.Krb5LoginModule.login(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at javax.security.auth.login.LoginContext.invoke(Unknown Source)
    at javax.security.auth.login.LoginContext.access$000(Unknown Source)
    at javax.security.auth.login.LoginContext$4.run(Unknown Source)
    at javax.security.auth.login.LoginContext$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.login.LoginContext.invokePriv(Unknown Source)
    at javax.security.auth.login.LoginContext.login(Unknown Source)
    at sun.security.jgss.GSSUtil.login(Unknown Source)
    at sun.security.jgss.krb5.Krb5Util.getTicket(Unknown Source)
    at sun.security.jgss.krb5.Krb5InitCredential$1.run(Unknown Source)
    at sun.security.jgss.krb5.Krb5InitCredential$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    ... 8 more
LSA: Found Ticket
LSA: Made NewWeakGlobalRef
LSA: Found PrincipalName
LSA: Made NewWeakGlobalRef
LSA: Found DerValue
LSA: Made NewWeakGlobalRef
LSA: Found EncryptionKey
LSA: Made NewWeakGlobalRef
LSA: Found TicketFlags
LSA: Made NewWeakGlobalRef
LSA: Found KerberosTime
LSA: Made NewWeakGlobalRef
LSA: Found String
LSA: Made NewWeakGlobalRef
LSA: Found DerValue constructor
LSA: Found Ticket constructor
LSA: Found PrincipalName constructor
LSA: Found EncryptionKey constructor
LSA: Found TicketFlags constructor
LSA: Found KerberosTime constructor
LSA: Finished OnLoad processing
LSA: Found KrbCreds constructor
LSA: Got handle to Kerberos package
LSA: Response size is 0
LSA: Error calling function Protocol status: 1312
LSA: A specified logon session does not exist. It may already have been terminated.

Вот код, который воспроизводит проблему, уменьшенную до этого первого шага (для простоты код не go дальше ошибки и, следовательно, не включает дополнительный код, который был бы необходим для дальнейшего согласования с сервером).

package main.java;

import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;

public class TestGetTicket2 {

    public static void main( String[] args ) {
        System.setProperty( "javax.security.auth.useSubjectCredsOnly", "false" );
        GSSManager manager = GSSManager.getInstance();
        try {
            GSSName serverName = manager.createName( "HTTP/testws2.sso.internal", null );
            Oid krb5Oid = new Oid("1.2.840.113554.1.2.2");
            GSSContext clientContext = manager.createContext( serverName, krb5Oid, (GSSCredential) null,
                    GSSContext.DEFAULT_LIFETIME );
            clientContext.requestMutualAuth(true);
            clientContext.requestConf(true);
            clientContext.requestInteg(true);
            byte[] clientToken = clientContext.initSecContext( new byte[0], 0, 0 );
            System.out.println( "Success so far" );
        } catch( Exception e ) {
            e.printStackTrace();
            System.exit( 1 );
        }

    }

}

Моя конфигурация JAAS:

com.sun.security.jgss.krb5.initiate  {
  com.sun.security.auth.module.Krb5LoginModule required
  useKeyTab=false
  debug=true
  useTicketCache=true
  doNotPrompt=true
  renewTGT=true
  storeKey=false;
};

Моя среда: Windows 10 Pro в виртуальной машине VirtualBox (Windows 10 Pro host), Java 8 (сборка 1.8.0_66-b18). У меня есть экземпляр виртуальной машины Windows 2016 R2 на том же хосте, который работает как сервер Active Directory
Я уже предпринял следующие шаги:

  • Добавлен раздел реестра allowtgtsessionkey со значением 1
  • «Защита учетных данных» не используется (защита на основе виртуализации = «Не включена»)
  • Пользователь не входит в локальную группу администрирования
  • UA C отключен для user
  • JAVA_HOME \ jre \ lib \ security jars заменены JAR jars
  • Нет файлов krb5 cc* в домашней папке пользователя

Я не могу использовать WAFFLE, потому что мой сервер, с которым клиент будет связываться, будет работать Linux.
Почему первый вызов initSecContext не удался? Должна ли Java по умолчанию (и, насколько мне известно, только в версии 8) реализация GSS-API иметь возможность выполнять SSO с использованием аутентификации Windows? Соответствует ли ошибка отладки «TGT в LSA не найдено»?

...