Search in sources :

Example 1 with EncTicketPart

use of sun.security.krb5.internal.EncTicketPart in project jdk8u_jdk by JetBrains.

the class KrbApReq method authenticate.

private void authenticate(Krb5AcceptCredential cred, InetAddress initiator) throws KrbException, IOException {
    int encPartKeyType = apReqMessg.ticket.encPart.getEType();
    Integer kvno = apReqMessg.ticket.encPart.getKeyVersionNumber();
    EncryptionKey[] keys = cred.getKrb5EncryptionKeys(apReqMessg.ticket.sname);
    EncryptionKey dkey = EncryptionKey.findKey(encPartKeyType, kvno, keys);
    if (dkey == null) {
        throw new KrbException(Krb5.API_INVALID_ARG, "Cannot find key of appropriate type to decrypt AP REP - " + EType.toString(encPartKeyType));
    }
    byte[] bytes = apReqMessg.ticket.encPart.decrypt(dkey, KeyUsage.KU_TICKET);
    byte[] temp = apReqMessg.ticket.encPart.reset(bytes);
    EncTicketPart enc_ticketPart = new EncTicketPart(temp);
    checkPermittedEType(enc_ticketPart.key.getEType());
    byte[] bytes2 = apReqMessg.authenticator.decrypt(enc_ticketPart.key, KeyUsage.KU_AP_REQ_AUTHENTICATOR);
    byte[] temp2 = apReqMessg.authenticator.reset(bytes2);
    authenticator = new Authenticator(temp2);
    ctime = authenticator.ctime;
    cusec = authenticator.cusec;
    authenticator.ctime = authenticator.ctime.withMicroSeconds(authenticator.cusec);
    if (!authenticator.cname.equals(enc_ticketPart.cname)) {
        throw new KrbApErrException(Krb5.KRB_AP_ERR_BADMATCH);
    }
    if (!authenticator.ctime.inClockSkew())
        throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
    byte[] hash;
    try {
        hash = MessageDigest.getInstance("MD5").digest(apReqMessg.authenticator.cipher);
    } catch (NoSuchAlgorithmException ex) {
        throw new AssertionError("Impossible");
    }
    char[] h = new char[hash.length * 2];
    for (int i = 0; i < hash.length; i++) {
        h[2 * i] = hexConst[(hash[i] & 0xff) >> 4];
        h[2 * i + 1] = hexConst[hash[i] & 0xf];
    }
    AuthTimeWithHash time = new AuthTimeWithHash(authenticator.cname.toString(), apReqMessg.ticket.sname.toString(), authenticator.ctime.getSeconds(), authenticator.cusec, new String(h));
    rcache.checkAndStore(KerberosTime.now(), time);
    if (initiator != null) {
        // sender host address
        HostAddress sender = new HostAddress(initiator);
        if (enc_ticketPart.caddr != null && !enc_ticketPart.caddr.inList(sender)) {
            if (DEBUG) {
                System.out.println(">>> KrbApReq: initiator is " + sender.getInetAddress() + ", but caddr is " + Arrays.toString(enc_ticketPart.caddr.getInetAddresses()));
            }
            throw new KrbApErrException(Krb5.KRB_AP_ERR_BADADDR);
        }
    }
    // XXX check for repeated authenticator
    // if found
    //    throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
    // else
    //    save authenticator to check for later
    KerberosTime now = KerberosTime.now();
    if ((enc_ticketPart.starttime != null && enc_ticketPart.starttime.greaterThanWRTClockSkew(now)) || enc_ticketPart.flags.get(Krb5.TKT_OPTS_INVALID))
        throw new KrbApErrException(Krb5.KRB_AP_ERR_TKT_NYV);
    // than the allowable clock skew, throws ticket expired exception.
    if (enc_ticketPart.endtime != null && now.greaterThanWRTClockSkew(enc_ticketPart.endtime)) {
        throw new KrbApErrException(Krb5.KRB_AP_ERR_TKT_EXPIRED);
    }
    creds = new Credentials(apReqMessg.ticket, authenticator.cname, apReqMessg.ticket.sname, enc_ticketPart.key, enc_ticketPart.flags, enc_ticketPart.authtime, enc_ticketPart.starttime, enc_ticketPart.endtime, enc_ticketPart.renewTill, enc_ticketPart.caddr, enc_ticketPart.authorizationData);
    if (DEBUG) {
        System.out.println(">>> KrbApReq: authenticate succeed.");
    }
}
Also used : AuthTimeWithHash(sun.security.krb5.internal.rcache.AuthTimeWithHash) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException)

Example 2 with EncTicketPart

use of sun.security.krb5.internal.EncTicketPart in project jdk8u_jdk by JetBrains.

the class KerberosClientKeyExchangeImpl method init.

/**
     * Creates an instance of KerberosClientKeyExchange from its ASN.1 encoding.
     * Used by ServerHandshaker to verify and obtain premaster secret.
     *
     * @param protocolVersion current protocol version
     * @param clientVersion version requested by client in its ClientHello;
     *          used by premaster secret version check
     * @param rand random number generator used for generating random
     *          premaster secret if ticket and/or premaster verification fails
     * @param input inputstream from which to get ASN.1-encoded KerberosWrapper
     * @param acc the AccessControlContext of the handshaker
     * @param serviceCreds server's creds
     */
@Override
public void init(ProtocolVersion protocolVersion, ProtocolVersion clientVersion, SecureRandom rand, HandshakeInStream input, AccessControlContext acc, Object serviceCreds) throws IOException {
    // Read ticket
    encodedTicket = input.getBytes16();
    if (debug != null && Debug.isOn("verbose")) {
        Debug.println(System.out, "encoded Kerberos service ticket", encodedTicket);
    }
    EncryptionKey sessionKey = null;
    try {
        Ticket t = new Ticket(encodedTicket);
        EncryptedData encPart = t.encPart;
        PrincipalName ticketSname = t.sname;
        final ServiceCreds creds = (ServiceCreds) serviceCreds;
        final KerberosPrincipal princ = new KerberosPrincipal(ticketSname.toString());
        // For bound service, permission already checked at setup
        if (creds.getName() == null) {
            SecurityManager sm = System.getSecurityManager();
            try {
                if (sm != null) {
                    // Eliminate dependency on ServicePermission
                    sm.checkPermission(Krb5Helper.getServicePermission(ticketSname.toString(), "accept"), acc);
                }
            } catch (SecurityException se) {
                serviceCreds = null;
                // Do not destroy keys. Will affect Subject
                if (debug != null && Debug.isOn("handshake")) {
                    System.out.println("Permission to access Kerberos" + " secret key denied");
                }
                throw new IOException("Kerberos service not allowedy");
            }
        }
        KerberosKey[] serverKeys = AccessController.doPrivileged(new PrivilegedAction<KerberosKey[]>() {

            @Override
            public KerberosKey[] run() {
                return creds.getKKeys(princ);
            }
        });
        if (serverKeys.length == 0) {
            throw new IOException("Found no key for " + princ + (creds.getName() == null ? "" : (", this keytab is for " + creds.getName() + " only")));
        }
        /*
             * permission to access and use the secret key of the Kerberized
             * "host" service is done in ServerHandshaker.getKerberosKeys()
             * to ensure server has the permission to use the secret key
             * before promising the client
             */
        // See if we have the right key to decrypt the ticket to get
        // the session key.
        int encPartKeyType = encPart.getEType();
        Integer encPartKeyVersion = encPart.getKeyVersionNumber();
        KerberosKey dkey = null;
        try {
            dkey = findKey(encPartKeyType, encPartKeyVersion, serverKeys);
        } catch (KrbException ke) {
            // a kvno mismatch
            throw new IOException("Cannot find key matching version number", ke);
        }
        if (dkey == null) {
            // %%% Should print string repr of etype
            throw new IOException("Cannot find key of appropriate type" + " to decrypt ticket - need etype " + encPartKeyType);
        }
        EncryptionKey secretKey = new EncryptionKey(encPartKeyType, dkey.getEncoded());
        // Decrypt encPart using server's secret key
        byte[] bytes = encPart.decrypt(secretKey, KeyUsage.KU_TICKET);
        // Reset data stream after decryption, remove redundant bytes
        byte[] temp = encPart.reset(bytes);
        EncTicketPart encTicketPart = new EncTicketPart(temp);
        // Record the Kerberos Principals
        peerPrincipal = new KerberosPrincipal(encTicketPart.cname.getName());
        localPrincipal = new KerberosPrincipal(ticketSname.getName());
        sessionKey = encTicketPart.key;
        if (debug != null && Debug.isOn("handshake")) {
            System.out.println("server principal: " + ticketSname);
            System.out.println("cname: " + encTicketPart.cname.toString());
        }
    } catch (IOException e) {
        throw e;
    } catch (Exception e) {
        if (debug != null && Debug.isOn("handshake")) {
            System.out.println("KerberosWrapper error getting session key," + " generating random secret (" + e.getMessage() + ")");
        }
        sessionKey = null;
    }
    // XXX Read and ignore authenticator
    input.getBytes16();
    if (sessionKey != null) {
        preMaster = new KerberosPreMasterSecret(protocolVersion, clientVersion, rand, input, sessionKey);
    } else {
        // Generate bogus premaster secret
        preMaster = new KerberosPreMasterSecret(clientVersion, rand);
    }
}
Also used : Ticket(sun.security.krb5.internal.Ticket) KerberosTicket(javax.security.auth.kerberos.KerberosTicket) KerberosPrincipal(javax.security.auth.kerberos.KerberosPrincipal) ServiceCreds(sun.security.jgss.krb5.ServiceCreds) EncryptionKey(sun.security.krb5.EncryptionKey) PrincipalName(sun.security.krb5.PrincipalName) IOException(java.io.IOException) EncTicketPart(sun.security.krb5.internal.EncTicketPart) KrbException(sun.security.krb5.KrbException) PrivilegedActionException(java.security.PrivilegedActionException) IOException(java.io.IOException) KerberosKey(javax.security.auth.kerberos.KerberosKey) KrbException(sun.security.krb5.KrbException) EncryptedData(sun.security.krb5.EncryptedData)

Example 3 with EncTicketPart

use of sun.security.krb5.internal.EncTicketPart in project jdk8u_jdk by JetBrains.

the class KDC method processAsReq.

/**
     * Processes a AS_REQ and generates a AS_REP (or KRB_ERROR)
     * @param in the request
     * @return the response
     * @throws java.lang.Exception for various errors
     */
protected byte[] processAsReq(byte[] in) throws Exception {
    ASReq asReq = new ASReq(in);
    int[] eTypes = null;
    List<PAData> outPAs = new ArrayList<>();
    PrincipalName service = asReq.reqBody.sname;
    if (options.containsKey(KDC.Option.RESP_NT)) {
        service = new PrincipalName((int) options.get(KDC.Option.RESP_NT), service.getNameStrings(), Realm.getDefault());
    }
    try {
        System.out.println(realm + "> " + asReq.reqBody.cname + " sends AS-REQ for " + service + ", " + asReq.reqBody.kdcOptions);
        KDCReqBody body = asReq.reqBody;
        eTypes = KDCReqBodyDotEType(body);
        int eType = eTypes[0];
        EncryptionKey ckey = keyForUser(body.cname, eType, false);
        EncryptionKey skey = keyForUser(service, eType, true);
        if (options.containsKey(KDC.Option.ONLY_RC4_TGT)) {
            int tgtEType = EncryptedData.ETYPE_ARCFOUR_HMAC;
            boolean found = false;
            for (int i = 0; i < eTypes.length; i++) {
                if (eTypes[i] == tgtEType) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                throw new KrbException(Krb5.KDC_ERR_ETYPE_NOSUPP);
            }
            skey = keyForUser(service, tgtEType, true);
        }
        if (ckey == null) {
            throw new KrbException(Krb5.KDC_ERR_ETYPE_NOSUPP);
        }
        if (skey == null) {
            // TODO
            throw new KrbException(Krb5.KDC_ERR_SUMTYPE_NOSUPP);
        }
        // Session key
        EncryptionKey key = generateRandomKey(eType);
        // Check time, TODO
        KerberosTime till = body.till;
        if (till == null) {
            // TODO
            throw new KrbException(Krb5.KDC_ERR_NEVER_VALID);
        } else if (till.isZero()) {
            till = new KerberosTime(new Date().getTime() + 1000 * 3600 * 11);
        }
        //body.from
        boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX + 1];
        if (body.kdcOptions.get(KDCOptions.FORWARDABLE)) {
            List<String> sensitives = (List<String>) options.get(Option.SENSITIVE_ACCOUNTS);
            if (sensitives != null && sensitives.contains(body.cname.toString())) {
            // Cannot make FORWARDABLE
            } else {
                bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true;
            }
        }
        if (body.kdcOptions.get(KDCOptions.RENEWABLE)) {
            bFlags[Krb5.TKT_OPTS_RENEWABLE] = true;
        //renew = new KerberosTime(new Date().getTime() + 1000 * 3600 * 24 * 7);
        }
        if (body.kdcOptions.get(KDCOptions.PROXIABLE)) {
            bFlags[Krb5.TKT_OPTS_PROXIABLE] = true;
        }
        if (body.kdcOptions.get(KDCOptions.POSTDATED)) {
            bFlags[Krb5.TKT_OPTS_POSTDATED] = true;
        }
        if (body.kdcOptions.get(KDCOptions.ALLOW_POSTDATE)) {
            bFlags[Krb5.TKT_OPTS_MAY_POSTDATE] = true;
        }
        bFlags[Krb5.TKT_OPTS_INITIAL] = true;
        // Creating PA-DATA
        DerValue[] pas2 = null, pas = null;
        if (options.containsKey(KDC.Option.DUP_ETYPE)) {
            int n = (Integer) options.get(KDC.Option.DUP_ETYPE);
            switch(n) {
                case // customer's case in 7067974
                1:
                    pas2 = new DerValue[] { new DerValue(new ETypeInfo2(1, null, null).asn1Encode()), new DerValue(new ETypeInfo2(1, "", null).asn1Encode()), new DerValue(new ETypeInfo2(1, realm, new byte[] { 1 }).asn1Encode()) };
                    pas = new DerValue[] { new DerValue(new ETypeInfo(1, null).asn1Encode()), new DerValue(new ETypeInfo(1, "").asn1Encode()), new DerValue(new ETypeInfo(1, realm).asn1Encode()) };
                    break;
                case // we still reject non-null s2kparams and prefer E2 over E
                2:
                    pas2 = new DerValue[] { new DerValue(new ETypeInfo2(1, realm, new byte[] { 1 }).asn1Encode()), new DerValue(new ETypeInfo2(1, null, null).asn1Encode()), new DerValue(new ETypeInfo2(1, "", null).asn1Encode()) };
                    pas = new DerValue[] { new DerValue(new ETypeInfo(1, realm).asn1Encode()), new DerValue(new ETypeInfo(1, null).asn1Encode()), new DerValue(new ETypeInfo(1, "").asn1Encode()) };
                    break;
                case // but only E is wrong
                3:
                    pas = new DerValue[] { new DerValue(new ETypeInfo(1, realm).asn1Encode()), new DerValue(new ETypeInfo(1, null).asn1Encode()), new DerValue(new ETypeInfo(1, "").asn1Encode()) };
                    break;
                case // we also ignore rc4-hmac
                4:
                    pas = new DerValue[] { new DerValue(new ETypeInfo(23, "ANYTHING").asn1Encode()), new DerValue(new ETypeInfo(1, null).asn1Encode()), new DerValue(new ETypeInfo(1, "").asn1Encode()) };
                    break;
                case // "" should be wrong, but we accept it now
                5:
                    // See s.s.k.internal.PAData$SaltAndParams
                    pas = new DerValue[] { new DerValue(new ETypeInfo(1, "").asn1Encode()), new DerValue(new ETypeInfo(1, null).asn1Encode()) };
                    break;
            }
        } else {
            int[] epas = eTypes;
            if (options.containsKey(KDC.Option.RC4_FIRST_PREAUTH)) {
                for (int i = 1; i < epas.length; i++) {
                    if (epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC) {
                        epas[i] = epas[0];
                        epas[0] = EncryptedData.ETYPE_ARCFOUR_HMAC;
                        break;
                    }
                }
                ;
            } else if (options.containsKey(KDC.Option.ONLY_ONE_PREAUTH)) {
                epas = new int[] { eTypes[0] };
            }
            pas2 = new DerValue[epas.length];
            for (int i = 0; i < epas.length; i++) {
                pas2[i] = new DerValue(new ETypeInfo2(epas[i], epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC ? null : getSalt(body.cname), null).asn1Encode());
            }
            boolean allOld = true;
            for (int i : eTypes) {
                if (i == EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96 || i == EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96) {
                    allOld = false;
                    break;
                }
            }
            if (allOld) {
                pas = new DerValue[epas.length];
                for (int i = 0; i < epas.length; i++) {
                    pas[i] = new DerValue(new ETypeInfo(epas[i], epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC ? null : getSalt(body.cname)).asn1Encode());
                }
            }
        }
        DerOutputStream eid;
        if (pas2 != null) {
            eid = new DerOutputStream();
            eid.putSequence(pas2);
            outPAs.add(new PAData(Krb5.PA_ETYPE_INFO2, eid.toByteArray()));
        }
        if (pas != null) {
            eid = new DerOutputStream();
            eid.putSequence(pas);
            outPAs.add(new PAData(Krb5.PA_ETYPE_INFO, eid.toByteArray()));
        }
        PAData[] inPAs = KDCReqDotPAData(asReq);
        if (inPAs == null || inPAs.length == 0) {
            Object preauth = options.get(Option.PREAUTH_REQUIRED);
            if (preauth == null || preauth.equals(Boolean.TRUE)) {
                throw new KrbException(Krb5.KDC_ERR_PREAUTH_REQUIRED);
            }
        } else {
            try {
                EncryptedData data = newEncryptedData(new DerValue(inPAs[0].getValue()));
                EncryptionKey pakey = keyForUser(body.cname, data.getEType(), false);
                data.decrypt(pakey, KeyUsage.KU_PA_ENC_TS);
            } catch (Exception e) {
                throw new KrbException(Krb5.KDC_ERR_PREAUTH_FAILED);
            }
            bFlags[Krb5.TKT_OPTS_PRE_AUTHENT] = true;
        }
        TicketFlags tFlags = new TicketFlags(bFlags);
        EncTicketPart enc = new EncTicketPart(tFlags, key, body.cname, new TransitedEncoding(1, new byte[0]), new KerberosTime(new Date()), body.from, till, body.rtime, body.addresses, null);
        Ticket t = new Ticket(service, new EncryptedData(skey, enc.asn1Encode(), KeyUsage.KU_TICKET));
        EncASRepPart enc_part = new EncASRepPart(key, new LastReq(new LastReqEntry[] { new LastReqEntry(0, new KerberosTime(new Date().getTime() - 10000)) }), // TODO: detect replay?
        body.getNonce(), new KerberosTime(new Date().getTime() + 1000 * 3600 * 24), // Next 5 and last MUST be same with ticket
        tFlags, new KerberosTime(new Date()), body.from, till, body.rtime, service, body.addresses);
        EncryptedData edata = new EncryptedData(ckey, enc_part.asn1Encode(), KeyUsage.KU_ENC_AS_REP_PART);
        ASRep asRep = new ASRep(outPAs.toArray(new PAData[outPAs.size()]), body.cname, t, edata);
        System.out.println("     Return " + asRep.cname + " ticket for " + asRep.ticket.sname + ", flags " + tFlags);
        DerOutputStream out = new DerOutputStream();
        out.write(DerValue.createTag(DerValue.TAG_APPLICATION, true, (byte) Krb5.KRB_AS_REP), asRep.asn1Encode());
        byte[] result = out.toByteArray();
        // Added feature:
        // Write the current issuing TGT into a ccache file specified
        // by the system property below.
        String ccache = System.getProperty("test.kdc.save.ccache");
        if (ccache != null) {
            asRep.encKDCRepPart = enc_part;
            sun.security.krb5.internal.ccache.Credentials credentials = new sun.security.krb5.internal.ccache.Credentials(asRep);
            CredentialsCache cache = CredentialsCache.create(asReq.reqBody.cname, ccache);
            if (cache == null) {
                throw new IOException("Unable to create the cache file " + ccache);
            }
            cache.update(credentials);
            cache.save();
        }
        return result;
    } catch (KrbException ke) {
        ke.printStackTrace(System.out);
        KRBError kerr = ke.getError();
        KDCReqBody body = asReq.reqBody;
        System.out.println("     Error " + ke.returnCode() + " " + ke.returnCodeMessage());
        byte[] eData = null;
        if (kerr == null) {
            if (ke.returnCode() == Krb5.KDC_ERR_PREAUTH_REQUIRED || ke.returnCode() == Krb5.KDC_ERR_PREAUTH_FAILED) {
                DerOutputStream bytes = new DerOutputStream();
                bytes.write(new PAData(Krb5.PA_ENC_TIMESTAMP, new byte[0]).asn1Encode());
                for (PAData p : outPAs) {
                    bytes.write(p.asn1Encode());
                }
                DerOutputStream temp = new DerOutputStream();
                temp.write(DerValue.tag_Sequence, bytes);
                eData = temp.toByteArray();
            }
            kerr = new KRBError(null, null, null, new KerberosTime(new Date()), 0, ke.returnCode(), body.cname, service, KrbException.errorMessage(ke.returnCode()), eData);
        }
        return kerr.asn1Encode();
    }
}
Also used : sun.security.krb5.internal(sun.security.krb5.internal) sun.security.krb5(sun.security.krb5) DerOutputStream(sun.security.util.DerOutputStream) CredentialsCache(sun.security.krb5.internal.ccache.CredentialsCache) DerValue(sun.security.util.DerValue) InvocationTargetException(java.lang.reflect.InvocationTargetException)

Aggregations

IOException (java.io.IOException)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 PrivilegedActionException (java.security.PrivilegedActionException)1 KerberosKey (javax.security.auth.kerberos.KerberosKey)1 KerberosPrincipal (javax.security.auth.kerberos.KerberosPrincipal)1 KerberosTicket (javax.security.auth.kerberos.KerberosTicket)1 ServiceCreds (sun.security.jgss.krb5.ServiceCreds)1 sun.security.krb5 (sun.security.krb5)1 EncryptedData (sun.security.krb5.EncryptedData)1 EncryptionKey (sun.security.krb5.EncryptionKey)1 KrbException (sun.security.krb5.KrbException)1 PrincipalName (sun.security.krb5.PrincipalName)1 sun.security.krb5.internal (sun.security.krb5.internal)1 EncTicketPart (sun.security.krb5.internal.EncTicketPart)1 Ticket (sun.security.krb5.internal.Ticket)1 CredentialsCache (sun.security.krb5.internal.ccache.CredentialsCache)1 AuthTimeWithHash (sun.security.krb5.internal.rcache.AuthTimeWithHash)1 DerOutputStream (sun.security.util.DerOutputStream)1 DerValue (sun.security.util.DerValue)1