Package org.apache.ws.security.kerberos

Source Code of org.apache.ws.security.kerberos.KrbTicketDecoder

package org.apache.ws.security.kerberos;

import java.util.Iterator;
import java.util.Set;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosKey;
import sun.security.krb5.EncryptionKey;
import sun.security.krb5.internal.EncTicketPart;
import sun.security.krb5.internal.Ticket;
import sun.security.krb5.internal.crypto.KeyUsage;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;

/**
* Kerberos Ticket Decoder provides the ability to decode a Kerberos v5 service
* ticket, so the session key and client principal name can be accessed.
* Reference : http://thejavamonkey.blogspot.com/2008/05/how-to-decrypt-kerberos-gss-ap-req.html
*/
public class KrbTicketDecoder {

  private byte[] serviceTicket;
  private Subject subject;

  /**
   * Construct a Kerberos Ticket Decoder. This takes the service ticket that
   * is to be decoded and the JAAS subject that contains the secret key for
   * the target service.
   *
   * @param serviceTicket
   *            the AP-REQ service ticket that is to be decode
   * @param subject
   *            the JAAS subject containing the secret key for the server
   *            principal
   */
  public KrbTicketDecoder(byte[] serviceTicket, Subject subject) {
    this.serviceTicket = serviceTicket;
    this.subject = subject;
  }

  /**
   * Get the session key from the decoded service ticket.
   *
   * @return the session key
   * @throws Exception
   */
  public SecretKey getSessionKey() throws Exception {
    EncryptionKey encKey = parseServiceTicket(serviceTicket);
    //TODO : Remove DES dependency
    SecretKeySpec keySpec = new SecretKeySpec(encKey.getBytes(), "DES");
    return (SecretKey) keySpec;
  }

  // Parses the service ticket (GSS AP-REQ token)
  private EncryptionKey parseServiceTicket(byte[] ticket) throws Exception {
    DerInputStream ticketStream = new DerInputStream(ticket);
    DerValue[] values = ticketStream.getSet(ticket.length, true);

    // Look for the AP_REQ.
    // AP-REQ ::= [APPLICATION 14] SEQUENCE
    for (int i = 0; i < values.length; i++) {
      DerValue value = values[i];
      if (value.isConstructed((byte) 14)) {
        value.resetTag(DerValue.tag_Set);
        return parseApReq(value.toDerInputStream(), value.length());
      }
    }
    throw new Exception("Could not find AP-REQ in service ticket.");
  }

  // Parse the GSS AP-REQ token.
  private EncryptionKey parseApReq(DerInputStream reqStream, int len)
      throws Exception {
    DerValue ticket = null;

    DerValue[] values = reqStream.getSet(len, true);

    for (int i = 0; i < values.length; i++) {
      DerValue value = values[i];
      if (value.isContextSpecific((byte) 3)) {
        ticket = value.getData().getDerValue();
      }
    }

    if (ticket == null) {
      throw new Exception("No Ticket found in AP-REQ PDU");
    }
    return decryptTicket(new Ticket(ticket), subject);
  }

  private EncryptionKey decryptTicket(Ticket ticket, Subject svrSub)
      throws Exception {

    // Get the private key that matches the encryption type of the ticket.
    EncryptionKey key = getPrivateKey(svrSub, ticket.encPart.getEType());
    // Decrypt the service ticket and get the cleartext bytes.
    byte[] ticketBytes = ticket.encPart.decrypt(key, KeyUsage.KU_TICKET);
    if (ticketBytes.length <= 0) {
      throw new Exception("Key is empty.");
    }
    // EncTicketPart provides access to the decrypted attributes of the
    // service ticket.
    byte[] temp = ticket.encPart.reset(ticketBytes, true);
    EncTicketPart encPart = new EncTicketPart(temp);
    return encPart.key;
  }

  // Get the private server key.
  private EncryptionKey getPrivateKey(Subject sub, int keyType)
      throws Exception {
    KerberosKey key = getKrbKey(sub, keyType);
    return new EncryptionKey(key.getEncoded(), key.getKeyType(),
        new Integer(keyType));
  }

  // Get the Kerberos Key from the subject that matches the given key type.
  private KerberosKey getKrbKey(Subject sub, int keyType) {
    Set<Object> creds = sub.getPrivateCredentials(Object.class);
    for (Iterator<Object> i = creds.iterator(); i.hasNext();) {
      Object cred = i.next();
      if (cred instanceof KerberosKey) {
        KerberosKey key = (KerberosKey) cred;
        if (key.getKeyType() == keyType) {
          return (KerberosKey) cred;
        }
      }
    }
    return null;
  }

}
TOP

Related Classes of org.apache.ws.security.kerberos.KrbTicketDecoder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.