Frames | No Frames |
1: /* KerberosTicket.java -- a kerberos ticket 2: Copyright (C) 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.security.auth.kerberos; 40: 41: import gnu.classpath.NotImplementedException; 42: 43: import java.io.Serializable; 44: import java.net.InetAddress; 45: import java.util.Date; 46: 47: import javax.crypto.SecretKey; 48: import javax.security.auth.DestroyFailedException; 49: import javax.security.auth.Destroyable; 50: import javax.security.auth.RefreshFailedException; 51: import javax.security.auth.Refreshable; 52: 53: /** 54: * This class represents a Kerberos ticket. See the Kerberos 55: * authentication RFC for more information: 56: * <a href="http://www.ietf.org/rfc/rfc1510.txt">RFC 1510</a>. 57: * 58: * @since 1.4 59: */ 60: public class KerberosTicket 61: implements Destroyable, Serializable, Refreshable 62: { 63: private static final long serialVersionUID = 7395334370157380539L; 64: 65: // Indices of the various flags. From the kerberos spec. 66: // We only list the ones we use. 67: private static final int FORWARDABLE = 1; 68: private static final int FORWARDED = 2; 69: private static final int PROXIABLE = 3; 70: private static final int PROXY = 4; 71: private static final int POSTDATED = 6; 72: private static final int RENEWABLE = 8; 73: private static final int INITIAL = 9; 74: private static final int NUM_FLAGS = 12; 75: 76: private byte[] asn1Encoding; 77: private KeyImpl sessionKey; 78: private boolean[] flags; 79: private Date authTime; 80: private Date startTime; 81: private Date endTime; 82: private Date renewTill; 83: private KerberosPrincipal client; 84: private KerberosPrincipal server; 85: private InetAddress[] clientAddresses; 86: 87: /** 88: * Create a new ticket given all the facts about it. 89: * 90: * Note that flags may be null or "short"; any flags not specified 91: * will be taken to be false. 92: * 93: * If the key is not renewable, then renewTill may be null. 94: * 95: * If authTime is null, then it is taken to be the same as startTime. 96: * 97: * If clientAddresses is null, then the ticket can be used anywhere. 98: * 99: * @param asn1Encoding the contents of the ticket, as ASN1 100: * @param client the client principal 101: * @param server the server principal 102: * @param key the contents of the session key 103: * @param type the type of the key 104: * @param flags an array of flags, as specified by the RFC 105: * @param authTime when the client was authenticated 106: * @param startTime starting time at which the ticket is valid 107: * @param endTime ending time, after which the ticket is invalid 108: * @param renewTill for a rewewable ticket, the time before which it must 109: * be renewed 110: * @param clientAddresses a possibly-null array of addresses where this 111: * ticket may be used 112: */ 113: public KerberosTicket(byte[] asn1Encoding, KerberosPrincipal client, 114: KerberosPrincipal server, byte[] key, int type, 115: boolean[] flags, Date authTime, Date startTime, 116: Date endTime, Date renewTill, 117: InetAddress[] clientAddresses) 118: { 119: this.asn1Encoding = (byte[]) asn1Encoding.clone(); 120: this.sessionKey = new KeyImpl(key, type); 121: this.flags = new boolean[NUM_FLAGS]; 122: if (flags != null) 123: System.arraycopy(flags, 0, this.flags, 0, 124: Math.min(flags.length, NUM_FLAGS)); 125: this.flags = (boolean[]) flags.clone(); 126: this.authTime = (Date) authTime.clone(); 127: this.startTime = (Date) ((startTime == null) 128: ? authTime : startTime).clone(); 129: this.endTime = (Date) endTime.clone(); 130: this.renewTill = (Date) renewTill.clone(); 131: this.client = client; 132: this.server = server; 133: this.clientAddresses = (clientAddresses == null 134: ? null 135: : (InetAddress[]) clientAddresses.clone()); 136: } 137: 138: /** 139: * Destroy this ticket. This discards secret information. After this 140: * method is called, other methods will throw IllegalStateException. 141: */ 142: public void destroy() throws DestroyFailedException 143: { 144: if (sessionKey == null) 145: throw new DestroyFailedException("already destroyed"); 146: sessionKey = null; 147: asn1Encoding = null; 148: } 149: 150: /** 151: * Return true if this ticket has been destroyed. 152: */ 153: public boolean isDestroyed() 154: { 155: return sessionKey == null; 156: } 157: 158: /** 159: * Return true if the ticket is currently valid. This is true if 160: * the system time is between the ticket's start and end times. 161: */ 162: public boolean isCurrent() 163: { 164: long now = System.currentTimeMillis(); 165: return startTime.getTime() <= now && now <= endTime.getTime(); 166: } 167: 168: /** 169: * If the ticket is renewable, and the renewal time has not yet elapsed, 170: * attempt to renew the ticket. 171: * @throws RefreshFailedException if the renewal fails for any reason 172: */ 173: public void refresh() throws RefreshFailedException, NotImplementedException 174: { 175: if (! isRenewable()) 176: throw new RefreshFailedException("not renewable"); 177: if (renewTill != null 178: && System.currentTimeMillis() >= renewTill.getTime()) 179: throw new RefreshFailedException("renewal time elapsed"); 180: // FIXME: must contact the KDC. 181: // Use the java.security.krb5.kdc property... 182: throw new RefreshFailedException("not implemented"); 183: } 184: 185: /** 186: * Return the client principal for this ticket. 187: */ 188: public final KerberosPrincipal getClient() 189: { 190: return client; 191: } 192: 193: /** 194: * Return the server principal for this ticket. 195: */ 196: public final KerberosPrincipal getServer() 197: { 198: return server; 199: } 200: 201: /** 202: * Return true if this ticket is forwardable. 203: */ 204: public final boolean isForwardable() 205: { 206: return flags[FORWARDABLE]; 207: } 208: 209: /** 210: * Return true if this ticket has been forwarded. 211: */ 212: public final boolean isForwarded() 213: { 214: return flags[FORWARDED]; 215: } 216: 217: /** 218: * Return true if this ticket is proxiable. 219: */ 220: public final boolean isProxiable() 221: { 222: return flags[PROXIABLE]; 223: } 224: 225: /** 226: * Return true if this ticket is a proxy ticket. 227: */ 228: public final boolean isProxy() 229: { 230: return flags[PROXY]; 231: } 232: 233: /** 234: * Return true if this ticket was post-dated. 235: */ 236: public final boolean isPostdated() 237: { 238: return flags[POSTDATED]; 239: } 240: 241: /** 242: * Return true if this ticket is renewable. 243: */ 244: public final boolean isRenewable() 245: { 246: return flags[RENEWABLE]; 247: } 248: 249: /** 250: * Return true if this ticket was granted by an application 251: * server, and not via a ticket-granting ticket. 252: */ 253: public final boolean isInitial() 254: { 255: return flags[INITIAL]; 256: } 257: 258: /** 259: * Return the flags for this ticket as a boolean array. 260: * See the RFC to understand what the different entries mean. 261: */ 262: public final boolean[] getFlags() 263: { 264: return (boolean[]) flags.clone(); 265: } 266: 267: /** 268: * Return the authentication time for this ticket. 269: */ 270: public final Date getAuthTime() 271: { 272: return (Date) authTime.clone(); 273: } 274: 275: /** 276: * Return the start time for this ticket. 277: */ 278: public final Date getStartTime() 279: { 280: return (Date) startTime.clone(); 281: } 282: 283: /** 284: * Return the end time for this ticket. 285: */ 286: public final Date getEndTime() 287: { 288: return (Date) endTime.clone(); 289: } 290: 291: /** 292: * Return the renewal time for this ticket. For a non-renewable 293: * ticket, this will return null. 294: */ 295: public final Date getRenewTill() 296: { 297: return flags[RENEWABLE] ? ((Date) renewTill.clone()) : null; 298: } 299: 300: /** 301: * Return the allowable client addresses for this ticket. This will 302: * return null if the ticket can be used anywhere. 303: */ 304: public final InetAddress[] getClientAddresses() 305: { 306: return (clientAddresses == null 307: ? null 308: : (InetAddress[]) clientAddresses.clone()); 309: } 310: 311: /** 312: * Return the encoded form of this ticket. 313: */ 314: public final byte[] getEncoded() 315: { 316: checkDestroyed(); 317: return (byte[]) sessionKey.key.clone(); 318: } 319: 320: /** 321: * Return the secret key associated with this ticket. 322: */ 323: public final SecretKey getSessionKey() 324: { 325: checkDestroyed(); 326: return sessionKey; 327: } 328: 329: private void checkDestroyed() 330: { 331: if (sessionKey == null) 332: throw new IllegalStateException("key is destroyed"); 333: } 334: 335: public String toString() 336: { 337: return getClass().getName() + 338: "[client=" + client + 339: ",server=" + server + 340: ",sessionKey=" + sessionKey + 341: ",flags=" + flags + 342: ",authTime=" + authTime + 343: ",startTime= " + startTime + 344: ",endTime=" + endTime + 345: ",renewTill=" + renewTill + 346: ",clientAddresses=" + clientAddresses + 347: "]"; 348: } 349: 350: /** 351: * <p> 352: * Returns the type of the session key in accordance with 353: * RFC1510. This usually corresponds to the encryption 354: * algorithm used by the key, though more than one algorithm 355: * may use the same key type (e.g. DES with different checksum 356: * mechanisms and chaining modes). Negative values are reserved 357: * for local use. Non-negative values are for officially assigned 358: * type fields. The RFC defines: 359: * </p> 360: * <ul> 361: * <li>0 — null</li> 362: * <li>1 — DES (in CBC mode with either MD4 or MD5 checksums)</li> 363: * </ul> 364: * 365: * @return the type of session key used by this ticket. 366: */ 367: public final int getSessionKeyType() 368: { 369: return sessionKey.type; 370: } 371: 372: }