diff -r d0e8c9361bc0 src/share/classes/javax/security/auth/kerberos/KerberosTicket.java --- a/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java Tue Apr 03 11:52:06 2012 +0900 +++ b/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java Wed Apr 18 15:24:45 2012 -0600 @@ -37,6 +37,8 @@ import sun.misc.HexDumpEncoder; import sun.security.krb5.EncryptionKey; import sun.security.krb5.Asn1Exception; +import sun.security.krb5.internal.LastReq; +import sun.security.jgss.krb5.Krb5Util; import sun.security.util.*; /** @@ -164,6 +166,8 @@ private Date renewTill; + private LastRequest[] lastRequest; + /** * * Client that owns the service ticket @@ -242,6 +246,55 @@ authTime, startTime, endTime, renewTill, clientAddresses); } + /** + * Constructs a KerberosTicket using credentials information that a + * client either receives from a KDC or reads from a cache. + * + * @param asn1Encoding the ASN.1 encoding of the ticket as defined by + * the Kerberos protocol specification. + * @param client the client that owns this service + * ticket + * @param server the service that this ticket is for + * @param sessionKey the raw bytes for the session key that must be + * used to encrypt the authenticator that will be sent to the server + * @param keyType the key type for the session key as defined by the + * Kerberos protocol specification. + * @param flags the ticket flags. Each element in this array indicates + * the value for the corresponding bit in the ASN.1 BitString that + * represents the ticket flags. If the number of elements in this array + * is less than the number of flags used by the Kerberos protocol, + * then the missing flags will be filled in with false. + * @param authTime the time of initial authentication for the client + * @param startTime the time after which the ticket will be valid. This + * may be null in which case the value of authTime is treated as the + * startTime. + * @param endTime the time after which the ticket will no longer be + * valid + * @param renewTill an absolute expiration time for the ticket, + * including all renewal that might be possible. This field may be null + * for tickets that are not renewable. + * @param lastRequest the time(s) a request can be made, + * @param clientAddresses the addresses from where the ticket may be + * used by the client. This field may be null when the ticket is usable + * from any address. + */ + public KerberosTicket(byte[] asn1Encoding, + KerberosPrincipal client, + KerberosPrincipal server, + byte[] sessionKey, + int keyType, + boolean[] flags, + Date authTime, + Date startTime, + Date endTime, + Date renewTill, + LastRequest[] lastRequest, + InetAddress[] clientAddresses) { + init(asn1Encoding, client, server, sessionKey, keyType, flags, + authTime, startTime, endTime, renewTill, clientAddresses); + this.lastRequest = lastRequest; + } + private void init(byte[] asn1Encoding, KerberosPrincipal client, KerberosPrincipal server, @@ -493,6 +546,15 @@ } /** + * Returns an array of the the last request time(s). + * + * @return an array of the last request time(s). + */ + public final LastRequest[] getLastRequest() { + return (lastRequest); + } + + /** * Returns a list of addresses from where the ticket can be used. * * @return ths list of addresses or null, if the field was not @@ -552,6 +614,14 @@ Throwable e = null; sun.security.krb5.Credentials krb5Creds = null; + LastReq lastReq = null; + try { + lastReq = Krb5Util.LastRequestToLastReq(lastRequest); + } catch (java.io.IOException ioException) { + e = ioException; + + } + try { krb5Creds = new sun.security.krb5.Credentials(asn1Encoding, client.toString(), @@ -563,6 +633,7 @@ startTime, endTime, renewTill, + lastReq, clientAddresses); krb5Creds = krb5Creds.renew(); } catch (sun.security.krb5.KrbException krbException) { @@ -603,6 +674,7 @@ krb5Creds.getRenewTill(), krb5Creds.getClientAddresses()); destroyed = false; + lastReq = krb5Creds.getLastReq(); } } @@ -621,6 +693,7 @@ startTime = null; endTime = null; renewTill = null; + lastRequest = null; clientAddresses = null; destroyed = true; } @@ -643,6 +716,13 @@ clientAddresses[i].toString()); } } + String lastRequests = "null"; + if (lastRequest != null) { + lastRequests = ""; + for (int i = 0; i < lastRequest.length; i++) { + lastRequests += lastRequest[i].toString(); + } + } return ("Ticket (hex) = " + "\n" + (new HexDumpEncoder()).encodeBuffer(asn1Encoding) + "\n" + "Client Principal = " + client.toString() + "\n" + @@ -659,6 +739,7 @@ "Start Time = " + String.valueOf(startTime) + "\n" + "End Time = " + endTime.toString() + "\n" + "Renew Till = " + String.valueOf(renewTill) + "\n" + + "Last Request = " + lastRequests + "\n" + "Client Addresses " + (clientAddresses == null ? " Null " : caddrBuf.toString() + "\n")); @@ -696,6 +777,11 @@ result = result * 37 + renewTill.hashCode(); } + // lastRequest may be null + if (lastRequest != null) { + result = result * 37 + lastRequest.hashCode(); + } + // clientAddress may be null, the array's hashCode is 0 result = result * 37 + Arrays.hashCode(clientAddresses); return result * 37 + Arrays.hashCode(flags); diff -r d0e8c9361bc0 src/share/classes/sun/security/jgss/krb5/Krb5Util.java --- a/src/share/classes/sun/security/jgss/krb5/Krb5Util.java Tue Apr 03 11:52:06 2012 +0900 +++ b/src/share/classes/sun/security/jgss/krb5/Krb5Util.java Wed Apr 18 15:24:45 2012 -0600 @@ -28,6 +28,7 @@ import javax.security.auth.kerberos.KerberosTicket; import javax.security.auth.kerberos.KerberosKey; import javax.security.auth.kerberos.KerberosPrincipal; +import javax.security.auth.kerberos.LastRequest; import javax.security.auth.kerberos.KeyTab; import javax.security.auth.Subject; import javax.security.auth.login.LoginException; @@ -38,6 +39,9 @@ import sun.security.krb5.Credentials; import sun.security.krb5.EncryptionKey; import sun.security.krb5.KrbException; +import sun.security.krb5.internal.LastReq; +import sun.security.krb5.internal.LastReqEntry; +import sun.security.krb5.internal.KerberosTime; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; @@ -339,6 +343,26 @@ return sc; } + public static LastRequest[] LastReqToLastRequest(LastReq lastReq) { + if (lastReq == null) { + return null; + } + + LastReqEntry[] lastReqEntry = lastReq.getEntry(); + if (lastReqEntry == null) { + return null; + } + + LastRequest[] lastRequest = new LastRequest[lastReqEntry.length]; + + for (int i = 0; i < lastReqEntry.length; i++) { + lastRequest[i] = new LastRequest (lastReqEntry[i].getLrType(), + lastReqEntry[i].getLrValue().toDate()); + } + + return lastRequest; + } + public static KerberosTicket credsToTicket(Credentials serviceCreds) { EncryptionKey sessionKey = serviceCreds.getSessionKey(); return new KerberosTicket( @@ -353,9 +377,26 @@ serviceCreds.getStartTime(), serviceCreds.getEndTime(), serviceCreds.getRenewTill(), + LastReqToLastRequest(serviceCreds.getLastReq()), serviceCreds.getClientAddresses()); }; + public static LastReq LastRequestToLastReq(LastRequest[] lastRequest) + throws IOException { + + if (lastRequest == null) { + return null; + } + + LastReqEntry[] lastReqEntry = new LastReqEntry[lastRequest.length]; + + for (int i = 0; i < lastRequest.length; i++) { + KerberosTime t = new KerberosTime (lastRequest[i].getLrValue()); + lastReqEntry[i] = new LastReqEntry (lastRequest[i].getLrType(), t); + } + return (new LastReq(lastReqEntry)); + } + public static Credentials ticketToCreds(KerberosTicket kerbTicket) throws KrbException, IOException { return new Credentials( @@ -369,6 +410,7 @@ kerbTicket.getStartTime(), kerbTicket.getEndTime(), kerbTicket.getRenewTill(), + LastRequestToLastReq(kerbTicket.getLastRequest()), kerbTicket.getClientAddresses()); } diff -r d0e8c9361bc0 src/share/classes/sun/security/krb5/Credentials.java --- a/src/share/classes/sun/security/krb5/Credentials.java Tue Apr 03 11:52:06 2012 +0900 +++ b/src/share/classes/sun/security/krb5/Credentials.java Wed Apr 18 15:24:45 2012 -0600 @@ -55,6 +55,7 @@ KerberosTime startTime; KerberosTime endTime; KerberosTime renewTill; + LastReq lastReq; HostAddresses cAddr; EncryptionKey serviceKey; AuthorizationData authzData; @@ -99,9 +100,26 @@ startTime = new_startTime; endTime = new_endTime; this.renewTill = renewTill; + this.lastReq = null; this.cAddr = cAddr; } + public Credentials(Ticket new_ticket, + PrincipalName new_client, + PrincipalName new_server, + EncryptionKey new_key, + TicketFlags new_flags, + KerberosTime authTime, + KerberosTime new_startTime, + KerberosTime new_endTime, + KerberosTime renewTill, + LastReq lastReq, + HostAddresses cAddr) { + this(new_ticket, new_client, new_server, new_key, new_flags, + authTime, new_startTime, new_endTime, renewTill, cAddr); + this.lastReq = lastReq; + } + public Credentials(byte[] encoding, String client, String server, @@ -125,6 +143,31 @@ null); // caddrs are in the encoding at this point } + public Credentials(byte[] encoding, + String client, + String server, + byte[] keyBytes, + int keyType, + boolean[] flags, + Date authTime, + Date startTime, + Date endTime, + Date renewTill, + LastReq lastReq, + InetAddress[] cAddrs) throws KrbException, IOException { + this(new Ticket(encoding), + new PrincipalName(client, PrincipalName.KRB_NT_PRINCIPAL), + new PrincipalName(server, PrincipalName.KRB_NT_SRV_INST), + new EncryptionKey(keyType, keyBytes), + (flags == null? null: new TicketFlags(flags)), + (authTime == null? null: new KerberosTime(authTime)), + (startTime == null? null: new KerberosTime(startTime)), + (endTime == null? null: new KerberosTime(endTime)), + (renewTill == null? null: new KerberosTime(renewTill)), + (lastReq == null? null: new LastReq(lastReq.getEntry())), + null); // caddrs are in the encoding at this point + } + /** * Acquires a service ticket for the specified service * principal. If the service ticket is not already available, it @@ -180,6 +223,14 @@ return null; } + public final LastReq getLastReq() { + if (lastReq != null) + { + return lastReq; + } + return null; + } + public final boolean[] getFlags() { if (flags == null) // Can be in a KRB-CRED return null; @@ -494,6 +545,7 @@ } buffer.append("\nendTime=").append(endTime); buffer.append("\nrenewTill=").append(renewTill); + buffer.append("\nlastReq=").append(lastReq); buffer.append("\nflags: ").append(flags); buffer.append("\nEType (int): ").append(key.getEType()); return buffer.toString(); diff -r d0e8c9361bc0 src/share/classes/sun/security/krb5/KrbAsRep.java --- a/src/share/classes/sun/security/krb5/KrbAsRep.java Tue Apr 03 11:52:06 2012 +0900 +++ b/src/share/classes/sun/security/krb5/KrbAsRep.java Wed Apr 18 15:24:45 2012 -0600 @@ -168,6 +168,7 @@ enc_part.starttime, enc_part.endtime, enc_part.renewTill, + enc_part.lastReq, enc_part.caddr); if (DEBUG) { System.out.println(">>> KrbAsRep cons in KrbAsReq.getReply " + diff -r d0e8c9361bc0 src/share/classes/sun/security/krb5/internal/LastReq.java --- a/src/share/classes/sun/security/krb5/internal/LastReq.java Tue Apr 03 11:52:06 2012 +0900 +++ b/src/share/classes/sun/security/krb5/internal/LastReq.java Wed Apr 18 15:24:45 2012 -0600 @@ -33,6 +33,7 @@ import sun.security.util.*; import sun.security.krb5.Asn1Exception; import java.util.Vector; +import java.util.Arrays; import java.io.IOException; /** @@ -55,6 +56,8 @@ public class LastReq { private LastReqEntry[] entry = null; + public LastReqEntry[] getEntry() { return (entry); } + public LastReq(LastReqEntry[] entries) throws IOException { if (entries != null) { entry = new LastReqEntry[entries.length]; @@ -134,4 +137,50 @@ } } + public Object clone() { + LastReq ret = null; + try { + ret = new LastReq(entry); + } + catch (java.io.IOException e) { + return null; + } + + return ret; + } + + public String toString() { + String ret = ""; + + for (int i = 0; i < entry.length; i++) { + ret += entry[i].toString(); + } + + return (ret); + } + + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof LastReq)) { + return false; + } + + LastReq l = (LastReq) obj; + + return (Arrays.equals (entry, l.getEntry())); + } + + public int hashCode() { + int ret = 0; + + for (int i = 0; i < entry.length; i++) { + ret += entry[i].hashCode(); + } + + return (ret); + + } } diff -r d0e8c9361bc0 src/share/classes/sun/security/krb5/internal/LastReqEntry.java --- a/src/share/classes/sun/security/krb5/internal/LastReqEntry.java Tue Apr 03 11:52:06 2012 +0900 +++ b/src/share/classes/sun/security/krb5/internal/LastReqEntry.java Wed Apr 18 15:24:45 2012 -0600 @@ -38,6 +38,9 @@ private int lrType; private KerberosTime lrValue; + public int getLrType() { return (lrType); } + public KerberosTime getLrValue() { return (lrValue); } + private LastReqEntry() { } @@ -93,4 +96,26 @@ newEntry.lrValue = (KerberosTime)lrValue.clone(); return newEntry; } + + public String toString() { + return ("lrType = " + lrType + ", lrValue = " + lrValue); + } + + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (!(obj instanceof LastReqEntry)) { + return false; + } + + LastReqEntry l = (LastReqEntry) obj; + + return (lrType == l.getLrType() && lrValue == l.getLrValue()); + } + + public int hashCode() { + return (lrType + lrValue.hashCode()); + } } diff -r d0e8c9361bc0 src/share/classes/sun/security/krb5/internal/ccache/Credentials.java --- a/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java Tue Apr 03 11:52:06 2012 +0900 +++ b/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java Wed Apr 18 15:24:45 2012 -0600 @@ -43,6 +43,8 @@ KerberosTime authtime; KerberosTime starttime;//optional KerberosTime endtime; + LastReq lastReq; + KerberosTime keyExpiration; //optional KerberosTime renewTill; //optional HostAddresses caddr; //optional; for proxied tickets only AuthorizationData authorizationData; //optional, not being actually used @@ -123,6 +125,10 @@ if (kdcRep.encKDCRepPart.renewTill != null) { renewTill = (KerberosTime) kdcRep.encKDCRepPart.renewTill.clone(); } + + keyExpiration = (KerberosTime)kdcRep.encKDCRepPart.keyExpiration.clone(); + lastReq = (LastReq)kdcRep.encKDCRepPart.lastReq.clone(); + srealm = (Realm) kdcRep.encKDCRepPart.srealm.clone(); sname = (PrincipalName) kdcRep.encKDCRepPart.sname.clone(); caddr = (HostAddresses) kdcRep.encKDCRepPart.caddr.clone(); @@ -162,6 +168,16 @@ } else { renewTill = null; } + if (kdcRep.encKDCRepPart.keyExpiration != null) { + keyExpiration = (KerberosTime)kdcRep.encKDCRepPart.keyExpiration.clone(); + } else { + keyExpiration = null; + } + if (kdcRep.encKDCRepPart.lastReq != null) { + lastReq = (LastReq)kdcRep.encKDCRepPart.lastReq.clone(); + } else { + lastReq = null; + } // if (kdcRep.msgType == Krb5.KRB_AS_REP) { // isEncInSKey = false; // secondTicket = null; @@ -250,4 +266,12 @@ public int getTktEType() { return ticket.encPart.getEType(); } + + public LastReq getLastReq() { + return lastReq; + } + + public KerberosTime getKeyExpiration() { + return keyExpiration; + } }