1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /** 19 * @author Alexander V. Esin 20 */ 21 package org.ietf.jgss; 22 23 import java.io.ByteArrayInputStream; 24 import java.util.Arrays; 25 26 import junit.framework.TestCase; 27 28 /** 29 * Tests Oid class 30 * 31 * ASN.1 encodings and string values are base on X.690 specification. 32 * 33 * @see http://asn1.elibel.tm.fr/en/standards/index.htm 34 */ 35 public class OidTest extends TestCase { 36 37 /** 38 * Testing: Constructors, toString(), equals(), getDER() 39 */ 40 public void testValidOid() { 41 Object[][] testcase = new Object[][] { 42 // 43 new Object[] { "0.0.3", new byte[] { 0x06, 0x02, 0x00, 0x03 } }, 44 // 45 new Object[] { "0.1.3", new byte[] { 0x06, 0x02, 0x01, 0x03 } }, 46 // 47 new Object[] { "0.39.3", new byte[] { 0x06, 0x02, 0x27, 0x03 } }, 48 // 49 new Object[] { "1.0.3", new byte[] { 0x06, 0x02, 0x28, 0x03 } }, 50 // 51 new Object[] { "1.2.1.2.1", 52 new byte[] { 0x06, 0x04, 0x2A, 0x01, 0x02, 0x01 } }, 53 // 54 new Object[] { "1.39.3", new byte[] { 0x06, 0x02, 0x4F, 0x03 } }, 55 // 56 new Object[] { "2.0.3", new byte[] { 0x06, 0x02, 0x50, 0x03 } }, 57 // 58 new Object[] { "2.5.4.3", 59 new byte[] { 0x06, 0x03, 0x55, 0x04, 0x03 } }, 60 // 61 new Object[] { "2.39.3", new byte[] { 0x06, 0x02, 0x77, 0x03 } }, 62 // 63 //FIXME new Object[]{"2.40.3", new byte[]{0x06, 0x02, 0x78, 0x03}}, 64 // 65 //FIXME new Object[]{"2.100.3", new byte[]{0x06, 0x03, (byte)0x81, 0x34,0x03}}, 66 // 67 new Object[] { 68 "1.2.840.113554.1.2.2", 69 new byte[] { 0x06, 0x09, 0x2A, (byte) 0x86, 0x48, 70 (byte) 0x86, (byte) 0xF7, 0x12, 0x01, 0x02, 71 0x02 } } }; 72 73 for (int i = 0; i < testcase.length; i++) { 74 75 String strOid = (String) testcase[i][0]; 76 byte[] enc = (byte[]) testcase[i][1]; 77 78 try { 79 Oid oid1 = new Oid(strOid); 80 Oid oid2 = new Oid(enc); 81 Oid oid3 = new Oid(new ByteArrayInputStream(enc)); 82 83 // test equals 84 assertEquals(oid1, oid2); 85 assertEquals(oid1, oid3); 86 assertEquals(oid2, oid3); 87 88 // test toString() 89 assertEquals(oid1.toString(), strOid); 90 assertEquals(oid2.toString(), strOid); 91 assertEquals(oid3.toString(), strOid); 92 93 // test getDer 94 assertTrue(Arrays.equals(enc, oid1.getDER())); 95 assertTrue(Arrays.equals(enc, oid2.getDER())); 96 assertTrue(Arrays.equals(enc, oid3.getDER())); 97 98 } catch (GSSException e) { 99 fail("Testcase: " + i + "\nUnexpected exception: " + e); 100 } 101 } 102 } 103 104 /** 105 * @tests org.ieft.jgss.Oid#containedIn(org.ieft.jgss.Oid[]) 106 */ 107 public void testContainedIn() throws Exception { 108 Oid oid= new Oid("1.2.1.2.1"); 109 Oid [] oidArr= new Oid [] { 110 new Oid("1.1.1.2.1"), 111 new Oid("1.2.2.2.1"), 112 new Oid("1.2.1.2.1"), //right 113 new Oid("1.2.1.2.5") 114 }; 115 assertTrue(oid.containedIn(oidArr) ); 116 117 try { 118 oid.containedIn(null); 119 fail("No expected NullPointerException"); 120 } catch (NullPointerException e) { 121 } 122 } 123 124 /** 125 * Oid constructor Oid(String oid) is tested in case when 126 * string oid contains a subidentifier with leading zero 127 */ 128 public void testLeadingZero() throws Exception { 129 Oid oid1 = new Oid("1.0.0.0.1"); 130 Oid oid2 = new Oid("01.0.0.0.1"); // subidentifier has leading 0 131 Oid oid3 = new Oid("1.0.0.0.01"); // subidentifier has leading 0 132 133 // testing equality 134 assertEquals(oid1, oid2); 135 assertEquals(oid1, oid3); 136 137 // testing hash code 138 assertEquals(oid1.hashCode(), oid2.hashCode()); 139 assertEquals(oid1.hashCode(), oid3.hashCode()); 140 } 141 142 /** 143 * Oid constructor Oid(String oid) is tested in case when 144 * an invalid oid string is passed as a parameter 145 */ 146 public void testInvalidOIDString() { 147 148 String[] testcase = new String[] { "", // empty string 149 "1", // only one subidentifier 150 "SOME WRONG DATA", // char string 151 "0.40.3", // second subidentifier > 40 when first subidentifier = 0 152 "1.40.3", // second subidentifier > 40 when first subidentifier = 1 153 "3.2.1", // first subidentifier > 2 154 "2.2,1", // ',' is a delimiter 155 "2..2.1", // double dot 156 "2.2..1", // double dot 157 ".2.2", // leading dot 158 "2.2.", // trailing dot 159 "A.2.1", // leading char 'A' 160 "2.2.A", // trailing char 'A' 161 "OID.2.2.1", // OID prefix 162 "oid.2.2.1", // oid prefix 163 "-2.2.1", // negative first subidentifier 164 "2.-2.1", // negative second subidentifier 165 "2.2.-1", // negative third subidentifier 166 }; 167 168 for (int i = 0; i < testcase.length; i++) { 169 try { 170 new Oid(testcase[i]); 171 fail("No expected GSSException for oid string: " + testcase[i]); 172 } catch (GSSException e) { 173 assertEquals(GSSException.FAILURE, e.getMajor()); 174 assertEquals(0, e.getMinor()); 175 } 176 } 177 } 178 179 /** 180 * Oid constructors Oid(byte[] oid) and Oid(InputStream oid) 181 * are tested in case when an invalid oid encoding is passed as a parameter 182 */ 183 public void testInvalidOIDEncodings() { 184 185 byte[][] testcase = new byte[][] { 186 // incorrect tag: MUST be 0x06 187 new byte[] { 0x05, 0x03, 0x55, 0x04, 0x03 }, 188 // incorrect length: MUST be 0x03 189 new byte[] { 0x06, 0x07, 0x55, 0x04, 0x03 }, 190 // incorrect length=0 191 // FIXME new byte[] { 0x06, 0x00 }, 192 // incorrect last subidentifier(last octet): 8th bit is not 0 193 new byte[] { 0x06, 0x03, 0x55, 0x04, (byte) 0x83 } 194 }; 195 196 // Testing: Oid(byte[] oid) 197 for (int i = 0; i < testcase.length; i++) { 198 try { 199 new Oid(testcase[i]); 200 fail("Byte array: no expected GSSException for testcase: " + i); 201 } catch (GSSException e) { 202 assertEquals(GSSException.FAILURE, e.getMajor()); 203 assertEquals(0, e.getMinor()); 204 } 205 } 206 207 // Testing: Oid(InputStream oid) 208 for (int i = 0; i < testcase.length; i++) { 209 try { 210 ByteArrayInputStream in = new ByteArrayInputStream(testcase[i]); 211 new Oid(in); 212 fail("Input stream: no expected GSSException for testcase: " 213 + i); 214 } catch (GSSException e) { 215 assertEquals(GSSException.FAILURE, e.getMajor()); 216 assertEquals(0, e.getMinor()); 217 } 218 } 219 } 220 221 /** 222 * Tests 2 cases of Encoding Rules violation. 223 * Both cases should be in testInvalidOIDEncodings(). 224 */ 225 public void testEncodingRulesViolation() throws Exception { 226 227 // incorrect last subidentifier: leading octet have value 0x80 228 byte[] case1 = new byte[] { 0x06, 0x04, 0x55, 0x04, (byte) 0x80, 0x03 }; 229 // incorrect length: encoded not in minimum number of octets 230 byte[] case2 = new byte[] { 0x06, (byte) 0x84, 0x00, 0x00, 0x00, 0x03, 231 0x55, 0x04, 0x03 }; 232 233 assertEquals("2.5.4.3", new Oid(case1).toString()); 234 assertEquals("2.5.4.3", new Oid(case2).toString()); 235 } 236 237 public void testImmutability() throws Exception { 238 239 byte[] encoding = new byte[] { 0x06, 0x03, 0x55, 0x04, 0x03 }; 240 241 Oid oid = new Oid(encoding); 242 243 byte[] enc1 = oid.getDER(); 244 byte[] enc2 = oid.getDER(); 245 246 assertTrue(enc1 != encoding); 247 assertTrue(enc1 != enc2); 248 } 249 250 251 /** 252 * Oid encoding contains 2 extra bytes. 253 * Two Oid constructors are verified: 254 * - Oid(byte[] oid): GSSException is thrown 255 * - Oid(InputStream oid): oid object is created, 256 * input stream contains extra bytes 257 */ 258 public void testExtraBytes() throws Exception { 259 byte[] encoding = new byte[] { 0x06, 0x01, 0x55, 0x04, 0x03 }; 260 261 try { 262 new Oid(encoding); 263 fail("No expected GSSException"); 264 } catch (GSSException e) { 265 assertEquals(GSSException.FAILURE, e.getMajor()); 266 assertEquals(0, e.getMinor()); 267 } 268 269 ByteArrayInputStream in = new ByteArrayInputStream(encoding); 270 Oid oid = new Oid(in); 271 272 assertEquals("2.5", oid.toString()); 273 274 assertEquals(0x04, in.read()); 275 assertEquals(0x03, in.read()); 276 assertEquals(0, in.available()); 277 } 278 279 /** 280 * @tests org.ieft.jgss.Oid#Oid(byte[]) 281 */ 282 public final void test_ConstructorLbyte_array() throws GSSException { 283 284 try { 285 new Oid((byte[]) null); 286 fail("No expected NullPointerException"); 287 } catch (NullPointerException e) { 288 } 289 } 290 291 /** 292 * @tests org.ieft.jgss.Oid#Oid(java.io.InputStream) 293 */ 294 public final void test_ConstructorLjava_io_InputStream() 295 throws GSSException { 296 297 try { 298 new Oid((java.io.InputStream) null); 299 fail("No expected NullPointerException"); 300 } catch (NullPointerException e) { 301 } 302 } 303 304 /** 305 * @tests org.ieft.jgss.Oid#Oid(java.lang.String) 306 */ 307 public final void test_ConstructorLjava_lang_String() { 308 309 try { 310 new Oid((java.lang.String) null); 311 fail("No expected GSSException"); 312 } catch (GSSException e) { 313 } 314 } 315 316 public void test_KerberosV5() throws Exception { 317 Oid oid = new Oid("1.2.840.113554.1.2.2"); 318 byte[] expectedDer = new byte[] { 6, 9, 42, -122, 72, -122, -9, 18, 1, 319 2, 2 }; 320 assertTrue(Arrays.equals(expectedDer, oid.getDER())); 321 } 322 } 323