| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.jgss.krb5;  | 
 | 
 | 
 | 
import javax.security.auth.kerberos.KerberosTicket;  | 
 | 
import javax.security.auth.kerberos.KerberosKey;  | 
 | 
import javax.security.auth.kerberos.KerberosPrincipal;  | 
 | 
import javax.security.auth.kerberos.KeyTab;  | 
 | 
import javax.security.auth.Subject;  | 
 | 
 | 
 | 
import sun.security.krb5.Credentials;  | 
 | 
import sun.security.krb5.EncryptionKey;  | 
 | 
import sun.security.krb5.KrbException;  | 
 | 
import java.io.IOException;  | 
 | 
import java.util.ArrayList;  | 
 | 
import java.util.List;  | 
 | 
import java.util.Set;  | 
 | 
import sun.security.krb5.*;  | 
 | 
import sun.security.krb5.internal.Krb5;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public final class ServiceCreds { | 
 | 
      | 
 | 
    private KerberosPrincipal kp;  | 
 | 
 | 
 | 
      | 
 | 
    private Set<KerberosPrincipal> allPrincs;  | 
 | 
 | 
 | 
      | 
 | 
    private List<KeyTab> ktabs;  | 
 | 
    private List<KerberosKey> kk;  | 
 | 
    private KerberosTicket tgt;  | 
 | 
 | 
 | 
    private boolean destroyed;  | 
 | 
 | 
 | 
    private ServiceCreds() { | 
 | 
        // Make sure this class cannot be instantiated externally.  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public static ServiceCreds getInstance(  | 
 | 
            Subject subj, String serverPrincipal) { | 
 | 
 | 
 | 
        ServiceCreds sc = new ServiceCreds();  | 
 | 
 | 
 | 
        sc.allPrincs =  | 
 | 
                subj.getPrincipals(KerberosPrincipal.class);  | 
 | 
 | 
 | 
          | 
 | 
        for (KerberosKey key: SubjectComber.findMany(  | 
 | 
                subj, serverPrincipal, null, KerberosKey.class)) { | 
 | 
            sc.allPrincs.add(key.getPrincipal());  | 
 | 
        }  | 
 | 
 | 
 | 
        if (serverPrincipal != null) {       | 
 | 
            sc.kp = new KerberosPrincipal(serverPrincipal);  | 
 | 
        } else { | 
 | 
            // For compatibility reason, we set the name of default principal  | 
 | 
            // to the "only possible" name it can take, which means there is  | 
 | 
              | 
 | 
            if (sc.allPrincs.size() == 1) { | 
 | 
                boolean hasUnbound = false;  | 
 | 
                for (KeyTab ktab: SubjectComber.findMany(  | 
 | 
                        subj, null, null, KeyTab.class)) { | 
 | 
                    if (!ktab.isBound()) { | 
 | 
                        hasUnbound = true;  | 
 | 
                        break;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                if (!hasUnbound) { | 
 | 
                    sc.kp = sc.allPrincs.iterator().next();  | 
 | 
                    serverPrincipal = sc.kp.getName();  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        sc.ktabs = SubjectComber.findMany(  | 
 | 
                    subj, serverPrincipal, null, KeyTab.class);  | 
 | 
        sc.kk = SubjectComber.findMany(  | 
 | 
                    subj, serverPrincipal, null, KerberosKey.class);  | 
 | 
        sc.tgt = SubjectComber.find(  | 
 | 
                subj, null, serverPrincipal, KerberosTicket.class);  | 
 | 
        if (sc.ktabs.isEmpty() && sc.kk.isEmpty() && sc.tgt == null) { | 
 | 
            return null;  | 
 | 
        }  | 
 | 
 | 
 | 
        sc.destroyed = false;  | 
 | 
 | 
 | 
        return sc;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    public String getName() { | 
 | 
        if (destroyed) { | 
 | 
            throw new IllegalStateException("This object is destroyed"); | 
 | 
        }  | 
 | 
        return kp == null ? null : kp.getName();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public KerberosKey[] getKKeys() { | 
 | 
        if (destroyed) { | 
 | 
            throw new IllegalStateException("This object is destroyed"); | 
 | 
        }  | 
 | 
        KerberosPrincipal one = kp;                   | 
 | 
        if (one == null && !allPrincs.isEmpty()) {   | 
 | 
            one = allPrincs.iterator().next();  | 
 | 
        }  | 
 | 
        if (one == null) {                           | 
 | 
            for (KeyTab ktab: ktabs) { | 
 | 
                  | 
 | 
                PrincipalName pn =  | 
 | 
                        Krb5Util.snapshotFromJavaxKeyTab(ktab).getOneName();  | 
 | 
                if (pn != null) { | 
 | 
                    one = new KerberosPrincipal(pn.getName());  | 
 | 
                    break;  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        if (one != null) { | 
 | 
            return getKKeys(one);  | 
 | 
        } else { | 
 | 
            return new KerberosKey[0];  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public KerberosKey[] getKKeys(KerberosPrincipal princ) { | 
 | 
        if (destroyed) { | 
 | 
            throw new IllegalStateException("This object is destroyed"); | 
 | 
        }  | 
 | 
        ArrayList<KerberosKey> keys = new ArrayList<>();  | 
 | 
        if (kp != null && !princ.equals(kp)) {       | 
 | 
            return new KerberosKey[0];  | 
 | 
        }  | 
 | 
        for (KerberosKey k: kk) { | 
 | 
            if (k.getPrincipal().equals(princ)) { | 
 | 
                keys.add(k);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        for (KeyTab ktab: ktabs) { | 
 | 
            if (ktab.getPrincipal() == null && ktab.isBound()) { | 
 | 
                // legacy bound keytab. although we don't know who  | 
 | 
                  | 
 | 
                if (!allPrincs.contains(princ)) { | 
 | 
                    continue;     | 
 | 
                }  | 
 | 
            }  | 
 | 
            for (KerberosKey k: ktab.getKeys(princ)) { | 
 | 
                keys.add(k);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return keys.toArray(new KerberosKey[keys.size()]);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public EncryptionKey[] getEKeys(PrincipalName princ) { | 
 | 
        if (destroyed) { | 
 | 
            throw new IllegalStateException("This object is destroyed"); | 
 | 
        }  | 
 | 
        KerberosKey[] kkeys = getKKeys(new KerberosPrincipal(princ.getName()));  | 
 | 
        if (kkeys.length == 0) { | 
 | 
            // Fallback: old JDK does not perform real name checking. If the  | 
 | 
            // acceptor has host.sun.com but initiator requests for host,  | 
 | 
            // as long as their keys match (i.e. keys for one can decrypt  | 
 | 
            // the other's service ticket), the authentication is OK.  | 
 | 
            // There are real customers depending on this to use different  | 
 | 
              | 
 | 
            kkeys = getKKeys();  | 
 | 
        }  | 
 | 
        EncryptionKey[] ekeys = new EncryptionKey[kkeys.length];  | 
 | 
        for (int i=0; i<ekeys.length; i++) { | 
 | 
            ekeys[i] =  new EncryptionKey(  | 
 | 
                        kkeys[i].getEncoded(), kkeys[i].getKeyType(),  | 
 | 
                        new Integer(kkeys[i].getVersionNumber()));  | 
 | 
        }  | 
 | 
        return ekeys;  | 
 | 
    }  | 
 | 
 | 
 | 
    public Credentials getInitCred() { | 
 | 
        if (destroyed) { | 
 | 
            throw new IllegalStateException("This object is destroyed"); | 
 | 
        }  | 
 | 
        if (tgt == null) { | 
 | 
            return null;  | 
 | 
        }  | 
 | 
        try { | 
 | 
            return Krb5Util.ticketToCreds(tgt);  | 
 | 
        } catch (KrbException | IOException e) { | 
 | 
            return null;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    public void destroy() { | 
 | 
        // Do not wipe out real keys because they are references to the  | 
 | 
          | 
 | 
        destroyed = true;  | 
 | 
        kp = null;  | 
 | 
        ktabs.clear();  | 
 | 
        kk.clear();  | 
 | 
        tgt = null;  | 
 | 
    }  | 
 | 
}  |