private byte[] parseToken(byte[] rawToken) { byte[] token = rawToken; DerValue tmpToken = new DerValue(rawToken); if (debug.messageEnabled()) { debug.message("token tag:" + DerValue.printByte(tmpToken.getTag())); } if (tmpToken.getTag() != (byte) 0x60) { return null; } ByteArrayInputStream tmpInput = new ByteArrayInputStream(tmpToken.getData()); // check for SPNEGO OID byte[] oidArray = new byte[spnegoOID.length]; tmpInput.read(oidArray, 0, oidArray.length); if (Arrays.equals(oidArray, spnegoOID)) { debug.message("SPNEGO OID found in the Auth Token"); tmpToken = new DerValue(tmpInput); // 0xa0 indicates an init token(NegTokenInit); 0xa1 indicates an // response arg token(NegTokenTarg). no arg token is needed for us. if (tmpToken.getTag() == (byte) 0xa0) { debug.message("DerValue: found init token"); tmpToken = new DerValue(tmpToken.getData()); if (tmpToken.getTag() == (byte) 0x30) { debug.message("DerValue: 0x30 constructed token found"); tmpInput = new ByteArrayInputStream(tmpToken.getData()); tmpToken = new DerValue(tmpInput); // In an init token, it can contain 4 optional arguments: // a0: mechTypes // a1: contextFlags // a2: octect string(with leading char 0x04) for the token // a3: message integrity value while (tmpToken.getTag() != (byte) -1 && tmpToken.getTag() != (byte) 0xa2) { // look for next mech token DER tmpToken = new DerValue(tmpInput); } if (tmpToken.getTag() != (byte) -1) { // retrieve octet string tmpToken = new DerValue(tmpToken.getData()); token = tmpToken.getData(); } } } } else { debug.message("SPNEGO OID not found in the Auth Token"); byte[] krb5Oid = new byte[KERBEROS_V5_OID.length]; int i = 0; for (; i < oidArray.length; i++) { krb5Oid[i] = oidArray[i]; } tmpInput.read(krb5Oid, i, krb5Oid.length - i); if (!Arrays.equals(krb5Oid, KERBEROS_V5_OID)) { debug.message("Kerberos V5 OID not found in the Auth Token"); token = null; } else { debug.message("Kerberos V5 OID found in the Auth Token"); } } return token; }
/** * Processes the authentication request. * * @param callbacks * @param state * @return -1 as succeeded; 0 as failed. * @exception AuthLoginException upon any failure. */ public int process(Callback[] callbacks, int state) throws AuthLoginException { int result = ISAuthConstants.LOGIN_IGNORE; if (!getConfigParams()) { initWindowsDesktopSSOAuth(options); } // retrieve the spnego token byte[] spnegoToken = getSPNEGOTokenFromHTTPRequest(getHttpServletRequest()); if (spnegoToken == null) { spnegoToken = getSPNEGOTokenFromCallback(callbacks); } if (spnegoToken == null) { debug.message("spnego token is not valid."); throw new AuthLoginException(amAuthWindowsDesktopSSO, "token", null); } if (debug.messageEnabled()) { debug.message( "SPNEGO token: \n" + DerValue.printByteArray(spnegoToken, 0, spnegoToken.length)); } // parse the spnego token and extract the kerberos mech token from it final byte[] kerberosToken = parseToken(spnegoToken); if (kerberosToken == null) { debug.message("kerberos token is not valid."); throw new AuthLoginException(amAuthWindowsDesktopSSO, "token", null); } if (debug.messageEnabled()) { debug.message( "Kerberos token retrieved from SPNEGO token: \n" + DerValue.printByteArray(kerberosToken, 0, kerberosToken.length)); } // authenticate the user with the kerberos token try { authenticateToken(kerberosToken); debug.message("WindowsDesktopSSO authentication succeeded."); result = ISAuthConstants.LOGIN_SUCCEED; } catch (PrivilegedActionException pe) { Exception e = extractException(pe); if (e instanceof GSSException) { int major = ((GSSException) e).getMajor(); if (major == GSSException.CREDENTIALS_EXPIRED) { debug.message("Credential expired. Re-establish credential..."); serviceLogin(); try { authenticateToken(kerberosToken); debug.message("Authentication succeeded with new cred."); result = ISAuthConstants.LOGIN_SUCCEED; } catch (Exception ee) { debug.message("Authentication failed with new cred."); throw new AuthLoginException(amAuthWindowsDesktopSSO, "auth", null, ee); } } else { debug.message("Authentication failed with GSSException."); throw new AuthLoginException(amAuthWindowsDesktopSSO, "auth", null, e); } } } catch (GSSException e) { int major = e.getMajor(); if (major == GSSException.CREDENTIALS_EXPIRED) { debug.message("Credential expired. Re-establish credential..."); serviceLogin(); try { authenticateToken(kerberosToken); debug.message("Authentication succeeded with new cred."); result = ISAuthConstants.LOGIN_SUCCEED; } catch (Exception ee) { debug.message("Authentication failed with new cred."); throw new AuthLoginException(amAuthWindowsDesktopSSO, "auth", null, ee); } } else { debug.message("Authentication failed with GSSException."); throw new AuthLoginException(amAuthWindowsDesktopSSO, "auth", null, e); } } catch (AuthLoginException e) { throw e; } catch (Exception e) { debug.message("Authentication failed with generic exception."); throw new AuthLoginException(amAuthWindowsDesktopSSO, "auth", null, e); } return result; }