001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package javax.security.auth.kerberos;
019:
020: import java.io.Serializable;
021: import java.net.InetAddress;
022: import java.util.Arrays;
023: import java.util.Date;
024:
025: import javax.crypto.SecretKey;
026: import javax.security.auth.DestroyFailedException;
027: import javax.security.auth.Destroyable;
028: import javax.security.auth.RefreshFailedException;
029: import javax.security.auth.Refreshable;
030:
031: import org.apache.harmony.auth.internal.kerberos.v5.KerberosException;
032: import org.apache.harmony.auth.internal.kerberos.v5.KrbClient;
033: import org.apache.harmony.auth.internal.nls.Messages;
034: import org.apache.harmony.security.utils.Array;
035:
036: public class KerberosTicket implements Destroyable, Refreshable,
037: Serializable {
038:
039: private static final long serialVersionUID = 7395334370157380539L;
040:
041: // The description of these flags defines in the Kerberos Protocol Specification (RFC 1510).
042:
043: // FORWARDABLE flag
044: private static final int FORWARDABLE = 1;
045:
046: // FORWARDED flag
047: private static final int FORWARDED = 2;
048:
049: // PROXIABLE flag
050: private static final int PROXIABLE = 3;
051:
052: // PROXY flag
053: private static final int PROXY = 4;
054:
055: // POSTDATED flag
056: private static final int POSTDATED = 6;
057:
058: // RENEWABLE flag
059: private static final int RENEWABLE = 8;
060:
061: // INITIAL flag
062: private static final int INITIAL = 9;
063:
064: // number of flags used by Kerberos protocol
065: private static final int FLAGS_NUM = 32;
066:
067: // line feed
068: private static final String LF = "\n"; //$NON-NLS-1$
069:
070: //ASN.1 encoding of the ticket
071: private byte[] asn1Encoding;
072:
073: //raw bytes for the session key
074: private KeyImpl sessionKey;
075:
076: //ticket flags
077: private boolean[] flags;
078:
079: //time of initial authentication for the client
080: private Date authTime;
081:
082: //time after which the ticket will be valid
083: private Date startTime;
084:
085: // time after which the ticket will be invalid
086: private Date endTime;
087:
088: // expiration time for the ticket
089: private Date renewTill;
090:
091: // client that owns this ticket
092: private KerberosPrincipal client;
093:
094: //service that owns this ticket
095: private KerberosPrincipal server;
096:
097: //addresses from where the ticket may be used by the client
098: private InetAddress[] clientAddresses;
099:
100: // indicates the ticket state
101: private transient boolean destroyed;
102:
103: public KerberosTicket(byte[] asn1Encoding,
104: KerberosPrincipal client, KerberosPrincipal server,
105: byte[] keyBytes, int keyType, boolean[] flags,
106: Date authTime, Date startTime, Date endTime,
107: Date renewTill, InetAddress[] clientAddresses) {
108:
109: if (asn1Encoding == null) {
110: throw new IllegalArgumentException(Messages
111: .getString("auth.3B")); //$NON-NLS-1$
112: }
113: if (client == null) {
114: throw new IllegalArgumentException(Messages
115: .getString("auth.3C")); //$NON-NLS-1$
116: }
117:
118: if (server == null) {
119: throw new IllegalArgumentException(Messages
120: .getString("auth.3D")); //$NON-NLS-1$
121: }
122:
123: if (keyBytes == null) {
124: throw new IllegalArgumentException(Messages
125: .getString("auth.3E")); //$NON-NLS-1$
126: }
127:
128: if (authTime == null) {
129: throw new IllegalArgumentException(Messages
130: .getString("auth.3F")); //$NON-NLS-1$
131: }
132:
133: if (endTime == null) {
134: throw new IllegalArgumentException(Messages
135: .getString("auth.40")); //$NON-NLS-1$
136: }
137:
138: this .asn1Encoding = new byte[asn1Encoding.length];
139: System.arraycopy(asn1Encoding, 0, this .asn1Encoding, 0,
140: this .asn1Encoding.length);
141:
142: this .client = client;
143: this .server = server;
144: this .sessionKey = new KeyImpl(keyBytes, keyType);
145:
146: if (flags == null) {
147: this .flags = new boolean[FLAGS_NUM];
148: } else if (flags.length > FLAGS_NUM) {
149: this .flags = new boolean[flags.length];
150: System
151: .arraycopy(flags, 0, this .flags, 0,
152: this .flags.length);
153: } else {
154: this .flags = new boolean[FLAGS_NUM];
155: System.arraycopy(flags, 0, this .flags, 0, flags.length);
156: }
157:
158: if (this .flags[RENEWABLE] && renewTill == null) {
159: throw new IllegalArgumentException(Messages
160: .getString("auth.41")); //$NON-NLS-1$
161: }
162:
163: this .renewTill = renewTill;
164:
165: if (startTime != null) {
166: this .startTime = startTime;
167: } else {
168: this .startTime = authTime;
169: }
170:
171: if (this .startTime.getTime() > endTime.getTime()) {
172: // TODO: make correct description of the exception
173: throw new IllegalArgumentException(Messages
174: .getString("auth.42")); //$NON-NLS-1$
175: }
176:
177: this .authTime = authTime;
178: this .endTime = endTime;
179:
180: if (clientAddresses != null) {
181: this .clientAddresses = new InetAddress[clientAddresses.length];
182: System.arraycopy(clientAddresses, 0, this .clientAddresses,
183: 0, this .clientAddresses.length);
184: }
185:
186: }
187:
188: public final KerberosPrincipal getClient() {
189: return client;
190: }
191:
192: public final KerberosPrincipal getServer() {
193: return server;
194: }
195:
196: public final SecretKey getSessionKey() {
197: checkState();
198: return sessionKey;
199: }
200:
201: public final int getSessionKeyType() {
202: checkState();
203: return sessionKey.getKeyType();
204: }
205:
206: public final byte[] getEncoded() {
207: checkState();
208: byte[] tmp = new byte[this .asn1Encoding.length];
209: System.arraycopy(this .asn1Encoding, 0, tmp, 0, tmp.length);
210: return tmp;
211: }
212:
213: public final boolean isForwardable() {
214: checkState();
215: return flags[FORWARDABLE];
216: }
217:
218: public final boolean isForwarded() {
219: checkState();
220: //TODO: was based on authentication involving a forwarded TGT ?
221: return flags[FORWARDED];
222: }
223:
224: public final boolean isProxiable() {
225: checkState();
226: return flags[PROXIABLE];
227: }
228:
229: public final boolean isProxy() {
230: checkState();
231: return flags[PROXY];
232: }
233:
234: public final boolean isPostdated() {
235: checkState();
236: return flags[POSTDATED];
237: }
238:
239: public final boolean isRenewable() {
240: checkState();
241: return flags[RENEWABLE];
242: }
243:
244: public final boolean isInitial() {
245: checkState();
246: return flags[INITIAL];
247: }
248:
249: public final boolean[] getFlags() {
250: if (destroyed) {
251: return null;
252: }
253: boolean[] tmp = new boolean[flags.length];
254: System.arraycopy(flags, 0, tmp, 0, tmp.length);
255: return tmp;
256:
257: }
258:
259: public final Date getAuthTime() {
260: if (destroyed) {
261: return null;
262: }
263: return new Date(authTime.getTime());
264: }
265:
266: public final Date getStartTime() {
267: checkState();
268: return new Date(startTime.getTime());
269: }
270:
271: public final Date getEndTime() {
272: if (destroyed) {
273: return null;
274: }
275: return new Date(endTime.getTime());
276: }
277:
278: public final Date getRenewTill() {
279: if (destroyed) {
280: return null;
281: }
282: return renewTill;
283: }
284:
285: public final InetAddress[] getClientAddresses() {
286: if (this .clientAddresses != null) {
287: InetAddress[] tmp = new InetAddress[this .clientAddresses.length];
288: System.arraycopy(clientAddresses, 0, tmp, 0, tmp.length);
289: return tmp;
290: }
291: return null;
292: }
293:
294: public void destroy() throws DestroyFailedException {
295: if (destroyed) {
296: return;
297: }
298: Arrays.fill(this .asn1Encoding, (byte) 0);
299: this .client = null;
300: this .server = null;
301: this .sessionKey.destroy();
302: this .flags = null;
303: this .authTime = null;
304: this .startTime = null;
305: this .endTime = null;
306: this .renewTill = null;
307: this .clientAddresses = null;
308: destroyed = true;
309: }
310:
311: public boolean isDestroyed() {
312: return destroyed;
313: }
314:
315: public void refresh() throws RefreshFailedException {
316:
317: checkState();
318:
319: if (!flags[RENEWABLE]) {
320: throw new RefreshFailedException(Messages
321: .getString("auth.44")); //$NON-NLS-1$
322: }
323:
324: if (System.currentTimeMillis() > this .renewTill.getTime()) {
325: throw new RefreshFailedException(Messages
326: .getString("auth.45")); //$NON-NLS-1$
327: }
328:
329: try {
330: KrbClient.doTGS();
331: } catch (KerberosException e) {
332: throw new RefreshFailedException(e.getMessage());
333: }
334: }
335:
336: public boolean isCurrent() {
337: checkState();
338: if (this .getStartTime().getTime() <= System.currentTimeMillis()
339: && System.currentTimeMillis() <= this .getEndTime()
340: .getTime()) {
341: return true;
342: }
343: return false;
344: }
345:
346: @Override
347: public String toString() {
348: checkState();
349: StringBuilder sb = new StringBuilder();
350: sb
351: .append("Ticket = ").append(Array.toString(asn1Encoding, "(hex) ") + LF); //$NON-NLS-1$ //$NON-NLS-2$
352: sb.append("Client Principal = ").append(client.getName() + LF); //$NON-NLS-1$
353: sb.append("Server Principal = ").append(server.getName() + LF); //$NON-NLS-1$
354: //TODO: append session key
355: sb.append("Session Key = ").append(sessionKey.toString() + LF); //$NON-NLS-1$
356: sb
357: .append("Forwardable Ticket = ").append(flags[FORWARDABLE] + LF); //$NON-NLS-1$
358: sb.append("Forwarded Ticket = ").append(flags[FORWARDED] + LF); //$NON-NLS-1$
359: sb.append("Proxiable Ticket = ").append(flags[PROXIABLE] + LF); //$NON-NLS-1$
360: sb.append("Proxy Ticket = ").append(flags[PROXY] + LF); //$NON-NLS-1$
361: sb.append("Postdated Ticket = ").append(flags[POSTDATED] + LF); //$NON-NLS-1$
362: sb.append("Renewable Ticket = ").append(flags[RENEWABLE] + LF); //$NON-NLS-1$
363: sb.append("Initial Ticket = ").append(flags[INITIAL] + LF); //$NON-NLS-1$
364: sb.append("Auth Time = ").append(this .authTime.toString() + LF); //$NON-NLS-1$
365: sb
366: .append("Start Time = ").append(this .startTime.toString() + LF); //$NON-NLS-1$
367: sb.append("End Time = ").append(this .endTime.toString() + LF); //$NON-NLS-1$
368: sb
369: .append("Renew Till = ").append(this .renewTill.toString() + LF); //$NON-NLS-1$
370: sb.append("Client Addresses "); //$NON-NLS-1$
371: if (clientAddresses != null) {
372: for (int i = 0; i < clientAddresses.length; i++) {
373: if (clientAddresses[i] == null) {
374: throw new NullPointerException(Messages
375: .getString("auth.46")); //$NON-NLS-1$
376: }
377: sb
378: .append("clientAddresses[" + i + "] = ").append(clientAddresses[i].toString() + LF + "\t\t"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
379: }
380: } else {
381: sb.append("null"); //$NON-NLS-1$
382: }
383:
384: return sb.toString();
385: }
386:
387: /**
388: * if a key is destroyed then IllegalStateException must be thrown
389: */
390: private void checkState() {
391: if (destroyed) {
392: throw new IllegalStateException(Messages
393: .getString("auth.43")); //$NON-NLS-1$
394: }
395: }
396: }
|