This discussion is archived
1 2 Previous Next 28 Replies Latest reply: Sep 18, 2009 2:58 AM by 843810 RSS

Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)

843810 Newbie
Currently Being Moderated
Hi,

FWIW, I've already file a bug report with Apple for this, but maybe you can help me. We have a program that authenticates against Active Directory using Krb5LoginModule. It's been working for years under Mac OS X, Windows, Linux and FreeBSD, but under Snow Leopard (Mac OS X 10.6), using JRE 1.6.0_15 it fails with the following stack trace:
09:16:36,451 ERROR LoginDialog:225 - Password check failed: java.lang.IllegalArgumentException: EncryptionKey: Key bytes cannot be null!
     at sun.security.krb5.EncryptionKey.<init>(EncryptionKey.java:214)
     at sun.security.krb5.EncryptionKey.acquireSecretKeys(EncryptionKey.java:191)
     at sun.security.krb5.EncryptionKey.acquireSecretKeys(EncryptionKey.java:159)
     at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:665)
     at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:542)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
     at java.lang.reflect.Method.invoke(Method.java:597)
     at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
     at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
     at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
     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:579)
     at de.unikoeln.rrz.uklanadmin.services.LoginService.checkPassword(LoginService.java:47)
I've read the source and found that pre-auth works. Actually that's all we care about, we don't need the keys at all! But this call in Krb5LoginModule fails:
              // update keys after pre-auth
              encKeys = EncryptionKey.acquireSecretKeys(
               password, principal.getSalt());
Please refer to http://openradar.appspot.com/radar?id=76405 for more details.
  • 1. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    I have found a workaround. When there is a ticket in the ticket cache (using either kinit in Terminal or Ticket Viewer.app) and the LoginContext has useTicketCache=yes set, authentication works. In that case the password that's entered isn't used at all, i.e. you can enter anything. But that's really just a workaround, not a fix.
  • 2. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    Don't know what the Apple JDK is doing here. My experience with Sun JDK is:

    1. If you already specified useTicketcache and the cache does include a proper TGT, Java will not prompt for the password at all.

    2. Otherwise, Krb5LoginModule.attemptAuthentication will prompt for username and password using your registered CallbackHandler, maybe console mode, maybe GUI. Maybe the default CallbackHanlder defined by Apple JDK cannot pass the password you input into the EncryptionKey class below?
  • 3. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    Thanks for your comment, but I don't think that's it.

    1. It's not Java itself that prompts for the password, it's our app. We never anticipated using a ticket cache, so we always prompt. I may try to fix that, but it's incidental.

    2. We've got our own callback handler. I know that it does pass the password correctly, because I see it in the debugger. What's more, EncryptionKey.acquireSecretKeys iterates through various encryption types. The first few work OK, i.e. the keys for the are acquired. Unfortunately I can't see which encryption type fails, and I haven't been successful in forcing a specific encryption type to be used, either.

    Edited by: TyrionLannister on Sep 18, 2009 12:55 AM
  • 4. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    You can add -Dsun.security.krb5.debug=true to see some debug outputs.

    As stated in http://java.sun.com/javase/6/docs/technotes/guides/security/jgss/jgss-features.html, you can re-write your krb5.conf file to determine what etype is used. Once again, I'm not familiar with Apple JDK, so maybe they're using the /Library/Preferences/edu.mit.Kerberos file.

    In Sun JDK, if I want to control the user/pass, I'll directly code with Krb5LoginModule, like this:

    Subject subject = new Subject();
    Krb5LoginModule krb5 = new Krb5LoginModule();
    Map<String, String> map = new HashMap<String, String>();
    Map<String, Object> shared = new HashMap<String, Object>();
    map.put("doNotPrompt", "true");
    map.put("useTicketCache", "false");
    map.put("useFirstPass", "true");
    shared.put("javax.security.auth.login.name", username);
    shared.put("javax.security.auth.login.password", password.toCharArray());
    krb5.initialize(subject, null, shared, map);
    krb5.login();
    krb5.commit();

    and then I can use the subject in Subject.doAs() calls.
  • 5. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    Thanks. I'd already set debug=true in the config file (and with map.put in your example). Apple does indeed use /Library/Preferences/edu.mit.Kerberos instead of /etc/krb5.conf. I can see that the settings there are picked up by programs I run in the Terminal, e.g. kinit. I'm not so sure they're picked up by the JDK. I have tried to set permitted_enctypes to just des-cbc-crc, but that didn't seem to have any effect.

    As for your code example, the result is exactly the same (as I had expected). krb5.initialize() works fine, but in login(), at exactly the same spot in the source, I get exactly the same stack trace. For reference, it's this block in attemptAuthentication():
      669                   // We can't get the key from the keytab so prompt
      670                   if (encKeys == null) {
      671                       promptForPass(getPasswdFromSharedState);
      672   
      673                       encKeys = EncryptionKey.acquireSecretKeys(
      674                           password, principal.getSalt());
      675   
      676                       if (isInitiator) {
      677                           if (debug)
      678                               System.out.println("Acquire TGT using AS Exchange");
      679                           cred = Credentials.acquireTGT(principal,
      680                                                   encKeys, password);
      681                           // update keys after pre-auth
      682                           encKeys = EncryptionKey.acquireSecretKeys(password,
      683                                                           principal.getSalt());
      684                       }
      685                   }
    The call in line 673 succeeds, but the one in line 682 fails. The reason is in this method:
        182       public static EncryptionKey[] acquireSecretKeys(char[] password,
      183           String salt, boolean pa_exists, int pa_etype, byte[] pa_s2kparams)
      184           throws KrbException
    There it's this part:
      204           EncryptionKey[] encKeys = new EncryptionKey[etypes.length];
      205           for (int i = 0; i < etypes.length; i++) {
      206               if (EType.isSupported(etypes)) {
    207 encKeys[i] = new EncryptionKey(
    208 stringToKey(password, salt, pa_s2kparams, etypes[i]),
    209 etypes[i], null);
    210 }
    For one of the values in etype[], the stringToKey method returns null. The source code is taken from OpenJDK. It's not available with Sun's JDK, so I haven't been able to step through that part in the debugger.
    
    Edited by: TyrionLannister on Sep 18, 2009 2:21 AM (corrected a few mistakes)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
  • 6. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    -Dsun.security.krb5.debug=true is totally different, it's for JGSS/krb5. debug=true in Krb5LoginModule is for JAAS.

    Do you mean that the permitted_enctypes settings in Apple's JDK has no effect at all?

    I guess the problem maybe relies on new AES cryptos. In Sun's JDK, in order to support AES-256, you need to download something called strong crypto (see last item at http://java.sun.com/javase/downloads/index.jsp). Is there any connection here?

    Also, what's the latest version of Java in Leopard, is it also 1.6.0_15?
  • 7. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    Good news! It seems the Apple JDK is not quite different from the Sun JDK, since they all contains this constructor: new EncryptionKey(char, String, String).

    Therefore, I write this small program:

    class A {
    public static void main(String[] args) throws Exception {
    for (int i: sun.security.krb5.internal.crypto.EType.getBuiltInDefaults())
    System.out.println(i);
    if (args.length > 0)
    System.out.println(new sun.security.krb5.EncryptionKey(
    args[0].toCharArray(), args[1], args[2]));
    }
    }

    Now, just run the program to see what etypes are supported. Then, you run it with

    java A pass salt etype_string

    The etype_string can be found in line 296-304 of the EncryptionKey class in OpenJDK. The number-string map can be found at the beginning of another class: EncryptedData.

    I've checked this program on my Apple JDK 1.5.0_19. My MacBook is very old and it only runs JDK 5.0.
  • 8. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    OK, with -Dsun.security.krb5.debug=true I get this:
    Using builtin default etypes for default_tkt_enctypes
    default etypes for default_tkt_enctypes: 3 1 23 16 17 18.
    Acquire TGT using AS Exchange
    Using builtin default etypes for default_tkt_enctypes
    default etypes for default_tkt_enctypes: 3 1 23 16 17 18.
    
    KrbAsReq calling createMessage
    KrbAsReq in createMessage
    KrbKdcReq send: kdc=rzkvdc2.ad.uni-koeln.de. UDP:88, timeout=30000, number of retries =3, #bytes=157
    KDCCommunication: kdc=rzkvdc2.ad.uni-koeln.de. UDP:88, timeout=30000,Attempt =1, #bytes=157
    KrbKdcReq send: #bytes read=218
    KrbKdcReq send: #bytes read=218
    KDCRep: init() encoding tag is 126 req type is 11
    KRBError:
          sTime is Fri Sep 18 12:07:41 CEST 2009 1253268461000       suSec is 326401       error code is 25       error Message is Additional pre-authentication required       realm is AD.UNI-KOELN.DE       sname is krbtgt/AD.UNI-KOELN.DE       eData provided.       msgType is 30
    Pre-Authentication Data:
          PA-DATA type = 11       PA-ETYPE-INFO etype = 23
    Pre-Authentication Data:
          PA-DATA type = 2       PA-ENC-TIMESTAMP
    Pre-Authentication Data:
          PA-DATA type = 15 AcquireTGT: PREAUTH FAILED/REQUIRED, re-send AS-REQ Using builtin default etypes for default_tkt_enctypes default etypes for default_tkt_enctypes: 3 1 23 16 17 18. Pre-Authentication: Set preferred etype = 23
    KrbAsReq salt is
    Pre-Authenticaton: find key for etype = 23 AS-REQ: Add PA_ENC_TIMESTAMP now
    EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
    KrbAsReq calling createMessage
    KrbAsReq in createMessage
    KrbKdcReq send: kdc=rzkvdc2.ad.uni-koeln.de. UDP:88, timeout=30000, number of retries =3, #bytes=218
    KDCCommunication: kdc=rzkvdc2.ad.uni-koeln.de. UDP:88, timeout=30000,Attempt =1, #bytes=218
    KrbKdcReq send: #bytes read=1295
    KrbKdcReq send: #bytes read=1295
    EType: sun.security.krb5.internal.crypto.ArcFourHmacEType
    KrbAsRep cons in KrbAsReq.getReply a0620
    Using builtin default etypes for default_tkt_enctypes default etypes for default_tkt_enctypes: 3 1 23 16 17 18. 12:07:41,290 ERROR LoginDialog:225 - EncryptionKey: Key bytes cannot be null!
    I will try your program next.

    Edited by: TyrionLannister on Sep 18, 2009 3:11 AM

    Edited by: TyrionLannister on Sep 18, 2009 3:12 AM
  • 9. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    I've made the program more simple. One shot and no need to check any string:

    class A {
    public static void main(String[] args) throws Exception {
    for (int i: sun.security.krb5.internal.crypto.EType.getBuiltInDefaults()) {
    System.out.println("EType: " + i);
    String e = null;
    switch (i) {
    case 1: case 3: e = "DES"; break;
    case 16: e = "DESede"; break;
    case 17: e = "AES128"; break;
    case 18: e = "AES256"; break;
    case 23: e = "ArcFourHmac"; break;
    }
    if (e != null)
    System.out.println(new sun.security.krb5.EncryptionKey(
    "pass".toCharArray(), "meME", e));
    }
    }
    }
  • 10. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    Thanks for your help! The supported types are:

    3
    1
    23
    16
    17
    18

    But with the revised program there is no stack trace:

    % java A
    EType: 3
    EncryptionKey: keyType=3 kvno=null keyValue (hex dump)=
    0000: B6 57 43 1F FD D0 C2 61

    EType: 1
    EncryptionKey: keyType=3 kvno=null keyValue (hex dump)=
    0000: B6 57 43 1F FD D0 C2 61

    EType: 23
    EncryptionKey: keyType=23 kvno=null keyValue (hex dump)=
    0000: 36 AA 83 BD CA B3 C9 FD AF 32 1C A4 2A 31 C3 FC 6........2..*1..


    EType: 16
    EncryptionKey: keyType=16 kvno=null keyValue (hex dump)=
    0000: 5E C1 92 EF 9B 3B B0 3D EF 67 A4 85 85 04 52 5E ^....;.=.g....R^
    0010: 6B 3B 13 B5 89 C1 D6 52

    EType: 17
    EncryptionKey: keyType=17 kvno=null keyValue (hex dump)=
    0000: E9 97 AE 23 73 A8 7E B1 ED F2 95 FA 4B 5C 23 2F ...#s.......K\#/


    EType: 18
    EncryptionKey: keyType=18 kvno=null keyValue (hex dump)=
    0000: 88 C8 33 04 59 29 D8 56 08 8A 3A B4 31 9F 58 F6 ..3.Y).V..:.1.X.
    0010: 93 76 01 43 CB 5A 6B A5 38 D5 73 C8 5B 45 4C 18 .v.C.Zk.8.s.[EL.

    But I think you're calling a different constructor, which might make a difference. I'll take a look. I will also try to add the source fro EncryptionKey.java to Apple's sources.jar.
  • 11. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    I thought I was making progress, but now I'm more confused than before. I tried to provoke the stack trace by adding this to A.java:

    sun.security.krb5.EncryptionKey.acquireSecretKeys("pass".toCharArray(), "meME", false, i , null);

    I thought that would force the encryption type i to be preferred, so that at some point in the loop I'd get the stack trace. But I don't. So something else seems to be going on. As I noted earlier, in the real app the first call to acquireSecretKeys (via Krb5LoginModule) succeeds, only the second one fails. But I don't see why ...

    I tried to debug this further by unjarring Apple's src.jar, adding OpenJDK's source of EncryptionKey.java to that directory and pointing Eclipse to it. That works to a point (the source is visible), but the lines don't match 100% and (because of that) I don't see the local variables in the debugger.
  • 12. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    Both calls looks like:

    682 encKeys = EncryptionKey.acquireSecretKeys(password,
    683 principal.getSalt());

    Here, the password does not change, so the only possibility is that salt is changed. The original salt looks like name+realm. For example, if your realm name is ME.LOCAL and your user account is "admin", the salt should be "adminME.LOCAL". In the second call, salt is updated by the server. You can use a packet sniffer (say, Wireshark) to catch the KRB-ERROR packet send back as the response to the first AS-REQ you sent. Go into the KRB-ERROR and look for the ETYPE-INFO or ETYPE-INFO2 data inside the edata, use the salt value there.

    I suggest you directly call this method with your own password and salt value.
  • 13. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    I've done as you suggested. The salt in the PA-ENCTYPE-INFO2 field reads "REALMusername", i.e. the order is inversed. That's also the original salt that is passed in the first call to acquireSecretKeys (as I can see in the debugger). The second time acquireSecretKeys is called, the salt is the empty string (""). But even when I make that call in A.java, I still don't get a stack trace!

    Does that make any sense to you?
  • 14. Re: Program fails in Krb5LoginModule on Snow Leopard (Mac OS X 10.6)
    843810 Newbie
    Currently Being Moderated
    TyrionLannister wrote:
    I've done as you suggested. The salt in the PA-ENCTYPE-INFO2 field reads "REALMusername", i.e. the order is inversed. That's also the original salt that is passed in the first call to acquireSecretKeys (as I can see in the debugger). The second time acquireSecretKeys is called, the salt is the empty string (""). But even when I make that call in A.java, I still don't get a stack trace!

    Does that make any sense to you?
    My mistake, I never get the order of username and realm correct in salt. :)

    It's quite strange that salt is "" in the 2nd call. You've said that the salt in the PA-ENCTYPE-INFO2 field is not empty. So neither the original nor the updated is empty.

    Is there any chance that the security providers got changed in the big program? I mean, with a program as simple as A.java, all default cryptos are loaded, but in your big program, for some reason, one crypto is not loaded. Just my guess.
1 2 Previous Next