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 org.apache.harmony.auth.tests.javax.security.auth.kerberos;
019:
020: import java.net.InetAddress;
021: import java.net.UnknownHostException;
022: import java.util.Arrays;
023: import java.util.Date;
024:
025: import javax.crypto.SecretKey;
026: import javax.security.auth.RefreshFailedException;
027: import javax.security.auth.kerberos.KerberosKey;
028: import javax.security.auth.kerberos.KerberosPrincipal;
029: import javax.security.auth.kerberos.KerberosTicket;
030:
031: import junit.framework.TestCase;
032:
033: import org.apache.harmony.auth.tests.support.TestUtils;
034:
035: public class KerberosTicketTest extends TestCase {
036:
037: private static final String ENV_KDC = "java.security.krb5.kdc";
038:
039: private static final String ENV_REALM = "java.security.krb5.realm";
040:
041: // ticket's ASN.1 encoding
042: private static final byte[] ticket = { 0x01, 0x02, 0x03, 0x04 };
043:
044: // client's principal
045: private static final KerberosPrincipal pClient = new KerberosPrincipal(
046: "client@apache.org");
047:
048: // server's principal
049: private static final KerberosPrincipal pServer = new KerberosPrincipal(
050: "server@apache.org");
051:
052: // session key
053: private static final byte[] sessionKey = { 0x01, 0x04, 0x03, 0x02 };
054:
055: private static final int KEY_TYPE = 1;
056:
057: // number of flags used by Kerberos protocol
058: private static final int FLAGS_NUM = 32;
059:
060: private static final boolean[] flags = { true, false, true, false,
061: true, false, true, false, true, false, true, false, };
062:
063: private static final int AUTH_TIME = 0;
064:
065: private static final Date authTime = new Date(AUTH_TIME);
066:
067: private static final int START_TIME = 1;
068:
069: private static final Date startTime = new Date(START_TIME);
070:
071: private static final int END_TIME = 2;
072:
073: private static final Date endTime = new Date(END_TIME);
074:
075: private static final Date renewTill = new Date(3);
076:
077: private static final InetAddress[] addesses;
078:
079: static {
080: try {
081: addesses = new InetAddress[] { InetAddress.getLocalHost() };
082: } catch (UnknownHostException e) {
083: throw new RuntimeException(e);
084: }
085: }
086:
087: /**
088: * @tests javax.security.auth.kerberos.KerberosTicket#getAuthTime()
089: */
090: public void test_getAuthTime() throws Exception {
091:
092: Date newAuthTime = new Date(AUTH_TIME);
093:
094: KerberosTicket krbTicket = new KerberosTicket(ticket, pClient,
095: pServer, sessionKey, KEY_TYPE, flags, newAuthTime,
096: startTime, endTime, renewTill, addesses);
097:
098: // initial value is not copied
099: newAuthTime.setTime(AUTH_TIME + 1);
100: assertEquals(AUTH_TIME + 1, krbTicket.getAuthTime().getTime());
101:
102: // returned value is copied
103: assertNotSame(krbTicket.getAuthTime(), krbTicket.getAuthTime());
104:
105: // auth time: null value is illegal for constructor
106: try {
107: new KerberosTicket(ticket, pClient, pServer, sessionKey,
108: KEY_TYPE, flags, null, startTime, endTime,
109: renewTill, addesses);
110: fail("No expected IllegalArgumentException");
111: } catch (IllegalArgumentException e) {
112: }
113: }
114:
115: /**
116: * @tests javax.security.auth.kerberos.KerberosTicket#getClient()
117: */
118: public void test_getClient() throws Exception {
119:
120: KerberosTicket krbTicket = new KerberosTicket(ticket, pClient,
121: pServer, sessionKey, KEY_TYPE, flags, authTime,
122: startTime, endTime, renewTill, addesses);
123:
124: assertSame(pClient, krbTicket.getClient());
125:
126: // client principal: null value is illegal for constructor
127: try {
128: new KerberosTicket(ticket, null, pServer, sessionKey,
129: KEY_TYPE, flags, authTime, startTime, endTime,
130: renewTill, addesses);
131: fail("No expected IllegalArgumentException");
132: } catch (IllegalArgumentException e) {
133: }
134: }
135:
136: /**
137: * @tests javax.security.auth.kerberos.KerberosTicket#getClientAddresses()
138: */
139: public void test_getClientAddresses() throws Exception {
140:
141: KerberosTicket krbTicket = new KerberosTicket(ticket, pClient,
142: pServer, sessionKey, KEY_TYPE, flags, authTime,
143: startTime, endTime, renewTill, addesses);
144:
145: assertTrue(Arrays.equals(addesses, krbTicket
146: .getClientAddresses()));
147:
148: // initial value is copied
149: assertNotSame(addesses, krbTicket.getClientAddresses());
150:
151: // KerberosTicket instance is immutable
152: assertNotSame(krbTicket.getClientAddresses(), krbTicket
153: .getClientAddresses());
154:
155: // addesses: null value is OK for constructor
156: krbTicket = new KerberosTicket(ticket, pClient, pServer,
157: sessionKey, KEY_TYPE, flags, authTime, startTime,
158: endTime, renewTill, null);
159: assertNull(krbTicket.getClientAddresses());
160: }
161:
162: /**
163: * @tests javax.security.auth.kerberos.KerberosTicket#getEncoded()
164: */
165: public void test_getEncoded() throws Exception {
166:
167: KerberosTicket krbTicket = new KerberosTicket(ticket, pClient,
168: pServer, sessionKey, KEY_TYPE, flags, authTime,
169: startTime, endTime, renewTill, addesses);
170:
171: assertTrue(Arrays.equals(ticket, krbTicket.getEncoded()));
172:
173: // initial byte array is copied
174: assertNotSame(ticket, krbTicket.getEncoded());
175:
176: // KerberosTicket instance is immutable
177: assertNotSame(krbTicket.getEncoded(), krbTicket.getEncoded());
178:
179: // ticket: null value is illegal for constructor
180: try {
181: new KerberosTicket(null, pClient, pServer, sessionKey,
182: KEY_TYPE, flags, authTime, startTime, endTime,
183: renewTill, addesses);
184: fail("No expected IllegalArgumentException");
185: } catch (IllegalArgumentException e) {
186: }
187: }
188:
189: /**
190: * @tests javax.security.auth.kerberos.KerberosTicket#getEndTime()
191: */
192: public void test_getEndTime() throws Exception {
193:
194: Date newEndTime = new Date(END_TIME);
195:
196: KerberosTicket krbTicket = new KerberosTicket(ticket, pClient,
197: pServer, sessionKey, KEY_TYPE, flags, authTime,
198: startTime, newEndTime, renewTill, addesses);
199:
200: // initial value is not copied
201: newEndTime.setTime(END_TIME + 1);
202: assertEquals(END_TIME + 1, krbTicket.getEndTime().getTime());
203:
204: // returned value is copied
205: assertNotSame(krbTicket.getEndTime(), krbTicket.getEndTime());
206:
207: // end time: null value is illegal for constructor
208: try {
209: new KerberosTicket(ticket, pClient, pServer, sessionKey,
210: KEY_TYPE, flags, authTime, startTime, null,
211: renewTill, addesses);
212: fail("No expected IllegalArgumentException");
213: } catch (IllegalArgumentException e) {
214: }
215: }
216:
217: /**
218: * @tests javax.security.auth.kerberos.KerberosTicket#getFlags()
219: */
220: public void test_getFlags() {
221:
222: boolean[] myFlags = new boolean[] { true, //reserved
223: true, // forwardable
224: true, // forwarded
225: true, // proxiable
226: true, // proxy
227: true, // may-postdate
228: true, // postdated
229: true, // invalid
230: true, // renewable
231: true, // initial
232: true, // pre-authent
233: true // hw-authent
234: };
235:
236: KerberosTicket krbTicket = new KerberosTicket(ticket, pClient,
237: pServer, sessionKey, KEY_TYPE, myFlags, // <=== we test this
238: authTime, startTime, endTime, renewTill, addesses);
239:
240: // test: returned value is copied
241: assertNotSame(krbTicket.getFlags(), krbTicket.getFlags());
242:
243: // test: flags values
244: assertTrue(krbTicket.isForwardable());
245: assertTrue(krbTicket.isForwarded());
246: assertTrue(krbTicket.isInitial());
247: assertTrue(krbTicket.isPostdated());
248: assertTrue(krbTicket.isProxiable());
249: assertTrue(krbTicket.isProxy());
250: assertTrue(krbTicket.isRenewable());
251:
252: //
253: // test: number of flags less the in Kerberos protocol (<32)
254: //
255: boolean[] ktFlags = krbTicket.getFlags();
256: assertEquals("flags length", FLAGS_NUM, ktFlags.length);
257: int index = 0;
258: // must match to initial array
259: for (; index < flags.length; index++) {
260: assertEquals("Index: " + index, myFlags[index],
261: ktFlags[index]);
262: }
263: // the rest is expected to be false
264: for (; index < FLAGS_NUM; index++) {
265: assertEquals("Index: " + index, false, ktFlags[index]);
266: }
267:
268: //
269: // test: flags array is greater then 32
270: //
271: myFlags = new boolean[50];
272:
273: krbTicket = new KerberosTicket(ticket, pClient, pServer,
274: sessionKey, KEY_TYPE, myFlags, // <=== we test this
275: authTime, startTime, endTime, renewTill, addesses);
276:
277: ktFlags = krbTicket.getFlags();
278:
279: assertEquals(myFlags.length, ktFlags.length);
280: for (index = 0; index < ktFlags.length; index++) {
281: assertEquals(false, ktFlags[index]);
282: }
283:
284: // initial array is copied
285: assertFalse(krbTicket.isForwardable());
286: myFlags[1] = true;
287: assertFalse(krbTicket.isForwardable());
288:
289: //
290: // test: Null value
291: //
292: krbTicket = new KerberosTicket(ticket, pClient, pServer,
293: sessionKey, KEY_TYPE, null, // <=== we test this
294: authTime, startTime, endTime, renewTill, addesses);
295: assertTrue(Arrays.equals(new boolean[FLAGS_NUM], krbTicket
296: .getFlags()));
297: }
298:
299: /**
300: * @tests javax.security.auth.kerberos.KerberosTicket#getServer()
301: */
302: public void test_getServer() throws Exception {
303:
304: KerberosTicket krbTicket = new KerberosTicket(ticket, pClient,
305: pServer, sessionKey, KEY_TYPE, flags, authTime,
306: startTime, endTime, renewTill, addesses);
307:
308: assertSame(pServer, krbTicket.getServer());
309:
310: // server principal: null value is illegal for constructor
311: try {
312: new KerberosTicket(ticket, pClient, null, sessionKey,
313: KEY_TYPE, flags, authTime, startTime, endTime,
314: renewTill, addesses);
315: fail("No expected IllegalArgumentException");
316: } catch (IllegalArgumentException e) {
317: }
318: }
319:
320: /**
321: * @tests javax.security.auth.kerberos.KerberosTicket#getSessionKey()
322: */
323: public void test_getSessionKey() throws Exception {
324:
325: KerberosTicket krbTicket = new KerberosTicket(ticket, pClient,
326: pServer, sessionKey, KEY_TYPE, flags, authTime,
327: startTime, endTime, renewTill, addesses);
328:
329: assertSame(krbTicket.getSessionKey(), krbTicket.getSessionKey());
330:
331: // test returned SecretKey object
332: SecretKey sKey = krbTicket.getSessionKey();
333: byte[] keyBytes = sKey.getEncoded();
334:
335: assertTrue(Arrays.equals(sessionKey, keyBytes));
336: // initial byte array is copied
337: assertNotSame(sessionKey, sKey.getEncoded());
338: // key instance is immutable
339: assertNotSame(sKey.getEncoded(), sKey.getEncoded());
340:
341: assertEquals("algorithm", "DES", sKey.getAlgorithm());
342: assertEquals("format", "RAW", sKey.getFormat());
343:
344: // sessionKey: null value is illegal for constructor
345: try {
346: new KerberosTicket(ticket, pClient, pServer, null,
347: KEY_TYPE, flags, authTime, startTime, endTime,
348: renewTill, addesses);
349: fail("No expected IllegalArgumentException");
350: } catch (IllegalArgumentException e) {
351: }
352: }
353:
354: /**
355: * @tests javax.security.auth.kerberos.KerberosTicket#getSessionKeyType()
356: */
357: public void test_getSessionKeyType() throws Exception {
358:
359: KerberosTicket krbTicket = new KerberosTicket(ticket, pClient,
360: pServer, sessionKey, KEY_TYPE, flags, authTime,
361: startTime, endTime, renewTill, addesses);
362:
363: assertEquals(KEY_TYPE, krbTicket.getSessionKeyType());
364: }
365:
366: /**
367: * @tests javax.security.auth.kerberos.KerberosTicket#getStartTime()
368: */
369: public void test_getStartTime() throws Exception {
370:
371: Date newStartTime = new Date(START_TIME);
372:
373: KerberosTicket krbTicket = new KerberosTicket(ticket, pClient,
374: pServer, sessionKey, KEY_TYPE, flags, authTime,
375: newStartTime, endTime, renewTill, addesses);
376:
377: // initial value is copied
378: newStartTime.setTime(START_TIME + 1);
379: assertEquals(START_TIME + 1, krbTicket.getStartTime().getTime());
380:
381: // returned value is copied
382: assertNotSame(krbTicket.getStartTime(), krbTicket
383: .getStartTime());
384:
385: // start time: null value is valid for constructor
386: krbTicket = new KerberosTicket(ticket, pClient, pServer,
387: sessionKey, KEY_TYPE, flags, authTime, null, endTime,
388: renewTill, addesses);
389: assertEquals(authTime, krbTicket.getStartTime());
390: assertNotSame(authTime, krbTicket.getStartTime());
391: }
392:
393: /**
394: * @tests javax.security.auth.kerberos.KerberosTicket#destroy()
395: * @tests javax.security.auth.kerberos.KerberosTicket#isDestroyed()
396: */
397: public void test_Destroyable() throws Exception {
398:
399: KerberosTicket kt = new KerberosTicket(ticket, pClient,
400: pServer, sessionKey, KEY_TYPE, flags, authTime,
401: startTime, endTime, renewTill, addesses);
402:
403: assertFalse(kt.isDestroyed());
404:
405: kt.destroy();
406: assertTrue(kt.isDestroyed());
407:
408: // no exceptions for second destroy
409: kt.destroy();
410:
411: assertNull(kt.getAuthTime());
412: assertNull(kt.getClient());
413: assertNull(kt.getClientAddresses());
414:
415: try {
416: kt.getEncoded();
417: fail("No expected IllegalStateException");
418: } catch (IllegalStateException e) {
419: }
420:
421: assertNull(kt.getEndTime());
422: assertNull(kt.getFlags());
423: assertNull(kt.getRenewTill());
424: assertNull(kt.getServer());
425:
426: try {
427: kt.getSessionKey();
428: fail("No expected IllegalStateException");
429: } catch (IllegalStateException e) {
430: }
431:
432: try {
433: kt.getSessionKeyType();
434: fail("No expected IllegalStateException");
435: } catch (IllegalStateException e) {
436: }
437:
438: try {
439: kt.toString();
440: fail("No expected IllegalStateException");
441: } catch (IllegalStateException e) {
442: }
443: }
444:
445: /**
446: * @tests javax.security.auth.kerberos.KerberosTicket#refresh()
447: */
448: public void test_refresh() throws Exception {
449:
450: boolean[] myFlags = new boolean[] { true, //reserved
451: true, // forwardable
452: true, // forwarded
453: true, // proxiable
454: true, // proxy
455: true, // may-postdate
456: true, // postdated
457: true, // invalid
458: true, // renewable: <=== we test this
459: true, // initial
460: true, // pre-authent
461: true // hw-authent
462: };
463:
464: //
465: // test: should not renew ticket because renewTill < current time
466: //
467: Date newRenewTill = new Date((new Date()).getTime() - 3600000);
468:
469: KerberosTicket krbTicket = new KerberosTicket(ticket, pClient,
470: pServer, sessionKey, KEY_TYPE, myFlags, authTime,
471: startTime, endTime, newRenewTill, // <=== we test this: it is less then current time
472: addesses);
473:
474: try {
475: krbTicket.refresh();
476: fail("No expected RefreshFailedException");
477: } catch (RefreshFailedException e) {
478: }
479:
480: //
481: // test: should not renew ticket because renewable flag is false
482: //
483: newRenewTill = new Date((new Date()).getTime() + 3600000);
484: myFlags[8] = false;
485:
486: krbTicket = new KerberosTicket(encTicket, pClient, pServer,
487: sessionKey, KEY_TYPE, myFlags, // <=== we test this: it is not renewable
488: authTime, startTime, endTime, newRenewTill, addesses);
489:
490: try {
491: krbTicket.refresh();
492: fail("No expected RefreshFailedException");
493: } catch (RefreshFailedException e) {
494: }
495:
496: //
497: // test: dependency on system props 'kdc' and 'realm'
498: //
499:
500: // verify that env. is clean
501: assertNull(System.getProperty(ENV_KDC));
502: assertNull(System.getProperty(ENV_REALM));
503:
504: // create real DES key
505: byte[] newSessionKey = new KerberosKey(new KerberosPrincipal(
506: "me@MY.REALM"), "pwd".toCharArray(), "DES")
507: .getEncoded();
508:
509: myFlags[8] = true;
510: krbTicket = new KerberosTicket(encTicket, pClient, pServer,
511: newSessionKey, KEY_TYPE, myFlags, authTime, startTime,
512: endTime, newRenewTill, addesses);
513:
514: // case 1: unset 'kdc' and set 'realm'
515: TestUtils.setSystemProperty(ENV_KDC, "some_value");
516: try {
517: krbTicket.refresh();
518: fail("No expected RefreshFailedException");
519: } catch (RefreshFailedException e) {
520: } finally {
521: TestUtils.setSystemProperty(ENV_KDC, null);
522: }
523:
524: // case 2: set 'kdc' and unset 'realm' sys.props
525: TestUtils.setSystemProperty(ENV_REALM, "some_value");
526: try {
527: krbTicket.refresh();
528: fail("No expected RefreshFailedException");
529: } catch (RefreshFailedException e) {
530: } finally {
531: TestUtils.setSystemProperty(ENV_REALM, null);
532: }
533:
534: // TODO test: ticket refreshing
535: }
536:
537: // Hands-created ticket encoding:
538: // - tkt-vno: 5
539: // - realm: 'MY.REALM'
540: // - sname: {type=0, string=krbtgt/MY.REALM}
541: // - enc-part: {etype=3,kvno=1,cipher=0} (i.e. it is empty)
542: private static final byte[] encTicket = {
543: // [APPLICATION 1]
544: (byte) 0x61,
545: (byte) 0x45,
546: // SEQUENCE
547: (byte) 0x30,
548: (byte) 0x43,
549:
550: // tkt-vno [0] INTEGER (5)
551: (byte) 0xa0,
552: (byte) 0x03,
553: (byte) 0x02,
554: (byte) 0x01,
555: (byte) 0x05,
556:
557: // realm [1] Realm = 'MY.REALM'
558: (byte) 0xa1,
559: (byte) 0x0a,
560: (byte) 0x1b,
561: (byte) 0x08,
562: (byte) 0x4d,
563: (byte) 0x59,
564: (byte) 0x2e,
565: (byte) 0x52,
566: (byte) 0x45,
567: (byte) 0x41,
568: (byte) 0x4c,
569: (byte) 0x4d,
570:
571: // sname [2] PrincipalName
572: (byte) 0xa2,
573: (byte) 0x1d,
574: (byte) 0x30,
575: (byte) 0x1b,
576: // name-type
577: (byte) 0xa0,
578: (byte) 0x03,
579: (byte) 0x02,
580: (byte) 0x01,
581: (byte) 0x00,
582: // name-string: SEQUENCE OF krbtgt/MY.REALM
583: (byte) 0xa1, (byte) 0x14, (byte) 0x30, (byte) 0x12,
584: (byte) 0x1b, (byte) 0x06, (byte) 0x6b, (byte) 0x72,
585: (byte) 0x62, (byte) 0x74, (byte) 0x67, (byte) 0x74,
586: (byte) 0x1b, (byte) 0x08, (byte) 0x4d, (byte) 0x59,
587: (byte) 0x2e,
588: (byte) 0x52,
589: (byte) 0x45,
590: (byte) 0x41,
591: (byte) 0x4c,
592: (byte) 0x4d,
593:
594: // enc-part [3] EncryptedData
595: (byte) 0xa3,
596: (byte) 0x11,
597: // SEQUENCE
598: (byte) 0x30,
599: (byte) 0x0F,
600: // etype
601: (byte) 0xa0, (byte) 0x03, (byte) 0x02,
602: (byte) 0x01,
603: (byte) 0x03,
604: // kvno
605: (byte) 0xa1, (byte) 0x03, (byte) 0x02, (byte) 0x01,
606: (byte) 0x01,
607: // cipher
608: (byte) 0xa2, (byte) 0x03, (byte) 0x04, (byte) 0x01,
609: (byte) 0x00 };
610: }
|