JAAS-无法持久保留Kerberos票证以缓存文件,并且无法从头开始创建缓存..和其他详细信息

法比亚诺·塔劳(Fabiano Tarlao)

我正在开发一个使用JAAS执行身份验证的Java应用程序,它应按以下方式工作:(i)当用户的票证uclient已经在本地缓存中时,它应该在不询问凭据的情况下对用户进行身份验证;(ii)当没有“ uclient”的票证时在缓存中,它应该询问用户名/密码并将获取的票证保存到本地缓存中。

我的应用程序可以执行“ i”,但不能执行“ ii”,它可以正确验证用户身份(创建主题/主体),但是不能将Krb票证持久化到缓存中。

问题

  1. 我该如何实现/实现?
  2. 并且..这将在空/不存在时创建Kerberos缓存文件吗?-如何从Java中以编程方式实现缓存文件的创建/初始化?
  3. 出于好奇,Java JaaS能够管理linux KEYRING吗?(目前Jaas无法自动管理它们)
  4. Java JaaS是否只能管理/持久化缓存中Default主体的票证?-或者在JaaS中如何处理单个缓存文件中有很多委托人票证的情况?

请注意,我的应用程序必须同时在Windows AD和Linux Realms中运行。

有关我的环境和当前代码的更多数据

我正在用FreeIPA客户端和服务器配置的Linux Kerberos Realm中测试客户端应用程序。我有一个Linux VM,它为AUTHDEMO.IT领域提供KDC,还有一个Linux VM,该Linux VM被认可为AUTHDEMO.IT领域。krb5.conf组态:

includedir /var/lib/sss/pubconf/krb5.include.d/

[libdefaults]
  default_realm = AUTHDEMO.IT
  dns_lookup_realm = true
  dns_lookup_kdc = true
  rdns = false
  ticket_lifetime = 24h
  forwardable = true
  udp_preference_limit = 0
  default_ccache_name = KEYRING:persistent:%{uid}


[realms]
  AUTHDEMO.IT = {
    pkinit_anchors = FILE:/etc/ipa/ca.crt

  }


[domain_realm]
  .authdemo.it = AUTHDEMO.IT
  authdemo.it = AUTHDEMO.IT

这是jaas.conf针对应用程序的:

JaasDemo {
   com.sun.security.auth.module.Krb5LoginModule required 
   useTicketCache=true
   principal=uclient
   debug=true; 
};

我没有指定默认的缓存文件名,我在调试中验证了它的默认值:/tmp/krb5cc_1000其中1000是运行用户的uid。

在JaasDemo类实例中,我使用以下login方法执行身份验证

public LoginContext login(){
        LoginContext lc = null;
        try {
            System.out.println("Initialize logincontext");
            lc = new LoginContext("JaasLogin",
                    new TextCallbackHandler());
        } catch (LoginException | SecurityException le) {
            System.err.println("Cannot create LoginContext."
                    + le.getMessage());
            return lc;
        }

        try {
            // attempt authentication
            System.out.println("Attempt login");
            lc.login();
        } catch (LoginException le) {
            System.err.println("Authentication failed:");
            System.err.println("  " + le.getMessage());
            return lc;
        }

        System.out.println("Authentication succeeded!");
        return lc;
    }

我已经使用以下命令执行了我的应用程序(请注意详细的kerberos日志记录选项):

java  -Dsun.security.krb5.debug=true -Dsun.security.jgss.debug=true -Djava.security.auth.login.config=jaas.conf -jar myapp.jar

以下是在不同情况下应用程序的输出,请注意,当系统询问时,用户以交互方式提供正确的凭据。第一种情况不存在的/tmp/krb5cc_1000文件:

Initialize logincontext
Attempt login
Debug is  true storeKey false useTicketCache true useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is uclient tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Acquire TGT from Cache
>>>KinitOptions cache name is /tmp/krb5cc_1000
Principal is [email protected]
null credentials from Ticket Cache
**Login Handler invoked, providing username and password to login manager..**
        [Krb5LoginModule] user entered username: uclient

Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
>>> KrbAsReq creating message
getKDCFromDNS using UDP
>>> KrbKdcReq send: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000, number of retries =3, #bytes=143
>>> KDCCommunication: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000,Attempt =1, #bytes=143
>>> KrbKdcReq send: #bytes read=283
>>>Pre-Authentication Data:
     PA-DATA type = 136

>>>Pre-Authentication Data:
     PA-DATA type = 19
     PA-ETYPE-INFO2 etype = 18, salt = REMOVED 3@, s2kparams = null
     PA-ETYPE-INFO2 etype = 17, salt = REMOVED, s2kparams = null

>>>Pre-Authentication Data:
     PA-DATA type = 2
     PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
     PA-DATA type = 133

>>> KdcAccessibility: remove authdemo2.authdemo.it.:88
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
     cTime is Wed Jun 29 17:12:49 CEST 1988 583600369000
     sTime is Wed Aug 02 15:53:28 CEST 2017 1501682008000
     suSec is 981130
     error code is 25
     error Message is Additional pre-authentication required
     cname is [email protected]
     sname is krbtgt/[email protected]
     eData provided.
     msgType is 30
>>>Pre-Authentication Data:
     PA-DATA type = 136

>>>Pre-Authentication Data:
     PA-DATA type = 19
     PA-ETYPE-INFO2 etype = 18, salt = REMOVED 3@, s2kparams = null
     PA-ETYPE-INFO2 etype = 17, salt = REMOVED, s2kparams = null

>>>Pre-Authentication Data:
     PA-DATA type = 2
     PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
     PA-DATA type = 133

KRBError received: NEEDED_PREAUTH
KrbAsReqBuilder: PREAUTH FAILED/REQ, re-send AS-REQ
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> KrbAsReq creating message
getKDCFromDNS using UDP
>>> KrbKdcReq send: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000, number of retries =3, #bytes=225
>>> KDCCommunication: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000,Attempt =1, #bytes=225
>>> KrbKdcReq send: #bytes read=674
>>> KdcAccessibility: remove authdemo2.authdemo.it.:88
>>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
>>> KrbAsRep cons in KrbAsReq.getReply uclient
principal is [email protected]
Commit Succeeded 

Authentication succeeded!


Subject.toString:
    Principal: [email protected]
    Private Credential: Ticket (hex) = 
REMOVED TICKET DETAILS                                             K.

Client Principal = [email protected]
Server Principal = krbtgt/[email protected]
Session Key = EncryptionKey: keyType=18 keyBytes (hex dump)=
REMOVED

Forwardable Ticket true
Forwarded Ticket false
Proxiable Ticket false
Proxy Ticket false
Postdated Ticket false
Renewable Ticket false
Initial Ticket false
Auth Time = Wed Aug 02 15:53:28 CEST 2017
Start Time = Wed Aug 02 15:53:28 CEST 2017
End Time = Thu Aug 03 15:53:28 CEST 2017
Renew Till = null
Client Addresses  Null 

/tmp/krb5cc_1000存在第二个案例文件,其中包含另一个用户的票证(使用kinit -c创建);应用程序正确进行身份验证,但是获取的票证不会持久保存到缓存文件中。

klist状态优先于应用程序执行:

klist -c /tmp/krb5cc_1000 

Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: [email protected]

Valid starting       Expires              Service principal
08/02/2017 16:05:19  08/03/2017 16:05:13  krbtgt/[email protected]

应用程序输出:

Initialize logincontext
Attempt login
Debug is  true storeKey false useTicketCache true useKeyTab false doNotPrompt false ticketCache is null isInitiator true KeyTab is null refreshKrb5Config is false principal is uclient tryFirstPass is false useFirstPass is false storePass is false clearPass is false
Acquire TGT from Cache
>>>KinitOptions cache name is /tmp/krb5cc_1000
java.io.IOException: Primary principals don't match.
    at sun.security.krb5.internal.ccache.FileCredentialsCache.load(FileCredentialsCache.java:179)
    at sun.security.krb5.internal.ccache.FileCredentialsCache.acquireInstance(FileCredentialsCache.java:82)
    at sun.security.krb5.internal.ccache.CredentialsCache.getInstance(CredentialsCache.java:83)
    at sun.security.krb5.Credentials.acquireTGTFromCache(Credentials.java:333)
    at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:665)
    at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:617)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:755)
    at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195)
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682)
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:680)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
    at javax.security.auth.login.LoginContext.login(LoginContext.java:587)
    at it.kerberosdemo.login.JaasDemo.login(JaasDemo.java:45)
    at it.kerberosdemo.login.JaasDemo.login(JaasDemo.java:27)
    at it.male.kerberosdemo.client.ClientMain.main(ClientMain.java:29)
Principal is [email protected]
null credentials from Ticket Cache
Login Handler invokerd, providing username and password to login manager..
        [Krb5LoginModule] user entered username: uclient

Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
>>> KrbAsReq creating message
getKDCFromDNS using UDP
>>> KrbKdcReq send: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000, number of retries =3, #bytes=143
>>> KDCCommunication: kdc=authdemo2.authdemo.it. UDP:88, timeout=30000,Attempt =1, #bytes=143
>>> KrbKdcReq send: #bytes read=283
>>>Pre-Authentication Data:
     PA-DATA type = 136

>>>Pre-Authentication Data:
     PA-DATA type = 19
     PA-ETYPE-INFO2 etype = 18, salt = REMOVED, s2kparams = null
     PA-ETYPE-INFO2 etype = 17, salt = REMOVED, s2kparams = null

>>>Pre-Authentication Data:
     PA-DATA type = 2
     PA-ENC-TIMESTAMP
>>>Pre-Authentication Data:
     PA-DATA type = 133

>>> KdcAccessibility: remove authdemo2.authdemo.it.:88
>>> KDCRep: init() encoding tag is 126 req type is 11
>>>KRBError:
     cTime is Mon Sep 22 16:38:56 CEST 2031 1947854336000
     sTime is Wed Aug 02 16:07:05 CEST 2017 1501682825000
     suSec is 803283
     error code is 25
     error Message is Additional pre-authentication required
     cname is [email protected]
     sname is krbtgt/[email protected]
     eData provided.
     msgType is 30
>>>Pre-Authentication Data:
     PA-DATA type = 136
...OMITTED IDENTICAL

klist确认没有为“ uclient”添加任何票证到高速缓存文件中。

问候

法比亚诺·塔劳(Fabiano Tarlao)

最后我找到了问题1 + 2的答案

kinit与Java发行版捆绑在一起命令是一个Java应用程序,该应用程序对用户进行身份验证进入领域/域,并将获取的票证保存在ccache文件中。kinit命令代码sun.security.krb5.internal.tools在OpenJDK软件包中可用主要的课程是sun.security.krb5.internal.tools.Kinit为了获取(认证)并保留Kerberos票证,您可以将所有tool复制到应用程序中,并通过提供cli参数Kinit类中调用该方法main(String[] arv)您也可以像我一样更改Kinit类,以便更好地与您的代码集成。

Kinit代码对于理解内部专用Kerberos代码的内部工作方式以及对其进行自定义非常有用。例如,有一个KDCOptions您可以手动配置实例,以索取可再生票证等等。让我们学习吧!;-)

请考虑:

  • 不保证内部代码的接口在将来的JDK版本中将保持不变
  • 不保证不同JDK供应商之间内部代码的接口相同。

我可以确认我的代码在OpenJDK和Oracle JDK上都能正常工作。

大图

目前,我的应用程序使用Jaas来通过查看本地ccache文件中的Krb凭证进行身份验证,如果失败,它将执行上述kinit代码。然后,它使用更新ccache文件中的Jaas进行身份验证

下一步

我目前正在尝试将Kerberos票证直接从主题对象中的凭据持久保存到ccache。
我将尝试使用sun.security.krb5.internal.ccache.FileCredentialCache该类,但它看起来很底层。让我们看看在CredentialCachekinit代码中使用抽象类,可能有用。如果成功,我将更新线程。

谢谢

谢谢Michael-O向我展示了sun.security.krb5.internal最终找到kinit代码软件包

问候

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Firefox-无法选择保存地址,信用卡和其他详细信息

如何通过迭代存储从文件读取的数据的列表的索引值来获取名称和其他详细信息?

当以ASCII格式转储时,CAP文件包含主小程序类和所有其他类文件的详细信息

JAAS和Wildfly10

如何从标题和详细信息类创建Json

使用 Windows API 检索和设置文件详细信息?

当我在身份页面(配置文件详细信息或密码重置)时,ASP.NET MVC 无法返回主页或其他页面

pdf文件的详细信息

JAAS Realm加载内部配置文件

无法显示项目的详细信息

无法获取订阅详细信息

无法打印GC详细信息

无法在angular2和firebase中获取登录用户详细信息?

如何获取Windows文件详细信息?

从文件中读取详细信息

如何获取Java文件的“详细信息”

“禁止”,无法使用JAAS(WildFly)进行身份验证

使用flipkart API获取特定单个产品的价格,标题和其他详细信息

Woocommerce电子邮件订单详细信息中的其他列和项目值

如何确定已编译的本机模块的ABI版本(和其他详细信息)?

如何向Spring Security用户详细信息添加其他详细信息

如何在颤动中创建带有文本和分隔线的详细信息框

如何使用Firebase身份验证创建用户名,地址和详细信息

如何使用 React Router DOM 创建列表和详细信息视图?

Paypal 购物车自定义创建订单对象和用户详细信息

在运行时获取配置文件和证书的详细信息

如何在Node.js中读取和更改文件的详细信息?

如何自定义检查页面和订单详细信息页面的液体文件

Snakemake:如何在config.yml文件中保存和访问示例详细信息?