GNU Classpath (0.95) | |
Frames | No Frames |
1: /* Oid.java -- Object identifier class. 2: Copyright (C) 2004 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: The documentation comments of this class are derived from the text 39: of RFC 2853: Generic Security Service API Version 2: Java Bindings. 40: That document is covered under the following license notice: 41: 42: Copyright (C) The Internet Society (2000). All Rights Reserved. 43: 44: This document and translations of it may be copied and furnished to 45: others, and derivative works that comment on or otherwise explain it 46: or assist in its implementation may be prepared, copied, published and 47: distributed, in whole or in part, without restriction of any kind, 48: provided that the above copyright notice and this paragraph are 49: included on all such copies and derivative works. However, this 50: document itself may not be modified in any way, such as by removing 51: the copyright notice or references to the Internet Society or other 52: Internet organizations, except as needed for the purpose of developing 53: Internet standards in which case the procedures for copyrights defined 54: in the Internet Standards process must be followed, or as required to 55: translate it into languages other than English. 56: 57: The limited permissions granted above are perpetual and will not be 58: revoked by the Internet Society or its successors or assigns. 59: 60: This document and the information contained herein is provided on an 61: "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING 62: TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT 63: NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN 64: WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF 65: MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. */ 66: 67: 68: package org.ietf.jgss; 69: 70: import java.io.ByteArrayInputStream; 71: import java.io.ByteArrayOutputStream; 72: import java.io.DataInputStream; 73: import java.io.InputStream; 74: import java.io.IOException; 75: import java.io.OutputStream; 76: 77: import java.math.BigInteger; 78: 79: import java.util.Arrays; 80: import java.util.StringTokenizer; 81: 82: /** 83: * <p>This class represents Universal Object Identifiers (Oids) and their 84: * associated operations.</p> 85: * 86: * <p>Oids are hierarchically globally-interpretable identifiers used 87: * within the GSS-API framework to identify mechanisms and name formats.</p> 88: * 89: * <p>The structure and encoding of Oids is defined in ISOIEC-8824 and 90: * ISOIEC-8825. For example the Oid representation of Kerberos V5 91: * mechanism is "1.2.840.113554.1.2.2".</p> 92: * 93: * <p>The {@link GSSName} name class contains <code>public static Oid</code> 94: * objects representing the standard name types defined in GSS-API.</p> 95: */ 96: public class Oid 97: { 98: 99: // Constants and fields. 100: // ------------------------------------------------------------------------- 101: 102: private static final int OBJECT_IDENTIFIER = 0x06; 103: private static final int RELATIVE_OID = 0x0d; 104: 105: private final int[] components; 106: private byte[] derOid; 107: private String strOid; 108: private boolean relative; 109: 110: // Constructors. 111: // ------------------------------------------------------------------------- 112: 113: /** 114: * Creates an Oid object from a string representation of its integer 115: * components (e.g. "1.2.840.113554.1.2.2"). 116: * 117: * @param strOid The string representation for the oid. 118: * @throws GSSException If the argument is badly formed. 119: */ 120: public Oid(String strOid) throws GSSException 121: { 122: if (strOid == null) 123: throw new NullPointerException(); 124: this.strOid = strOid; 125: try 126: { 127: StringTokenizer tok = new StringTokenizer(strOid, "."); 128: components = new int[tok.countTokens()]; 129: int i = 0; 130: while (tok.hasMoreTokens() && i < components.length) 131: { 132: components[i++] = Integer.parseInt(tok.nextToken()); 133: } 134: } 135: catch (Exception x) 136: { 137: throw new GSSException(GSSException.FAILURE); 138: } 139: relative = false; 140: } 141: 142: /** 143: * Creates an Oid object from its DER encoding. This refers to the full 144: * encoding including tag and length. The structure and encoding of 145: * Oids is defined in ISOIEC-8824 and ISOIEC-8825. This method is 146: * identical in functionality to its byte array counterpart. 147: * 148: * @param derOid Stream containing the DER encoded oid. 149: * @throws GSSException If the DER stream is badly formed, or if the 150: * input stream throws an exception. 151: */ 152: public Oid(InputStream derOid) throws GSSException 153: { 154: DataInputStream in = new DataInputStream(derOid); 155: try 156: { 157: int tag = in.read() & 0x1F; 158: if (tag != OBJECT_IDENTIFIER && tag != RELATIVE_OID) 159: throw new IOException(); 160: int len = in.read(); 161: if ((len & ~0x7F) != 0) 162: { 163: byte[] buf = new byte[len & 0x7F]; 164: in.readFully(buf); 165: len = new BigInteger(1, buf).intValue(); 166: } 167: if (len < 0) 168: throw new IOException(); 169: byte[] enc = new byte[len]; 170: in.readFully(enc); 171: int[] comp = new int[len + 1]; 172: int count = 0; 173: int i = 0; 174: relative = tag == RELATIVE_OID; 175: if (!relative && i < len) 176: { 177: int j = (enc[i] & 0xFF); 178: comp[count++] = j / 40; 179: comp[count++] = j % 40; 180: i++; 181: } 182: while (i < len) 183: { 184: int j = 0; 185: do 186: { 187: j = enc[i++] & 0xFF; 188: comp[count] <<= 7; 189: comp[count] |= j & 0x7F; 190: if (i >= len && (j & 0x80) != 0) 191: throw new IOException(); 192: } 193: while ((j & 0x80) != 0); 194: count++; 195: } 196: if (count == len) 197: this.components = comp; 198: else 199: { 200: this.components = new int[count]; 201: System.arraycopy(comp, 0, components, 0, count); 202: } 203: } 204: catch (IOException ioe) 205: { 206: throw new GSSException(GSSException.FAILURE); 207: } 208: } 209: 210: /** 211: * Creates an Oid object from its DER encoding. This refers to the full 212: * encoding including tag and length. The structure and encoding of 213: * Oids is defined in ISOIEC-8824 and ISOIEC-8825. This method is 214: * identical in functionality to its streaming counterpart. 215: * 216: * @param derOid Byte array storing a DER encoded oid. 217: * @throws GSSException If the DER bytes are badly formed. 218: */ 219: public Oid(byte[] derOid) throws GSSException 220: { 221: this(new ByteArrayInputStream(derOid)); 222: this.derOid = (byte[]) derOid.clone(); 223: } 224: 225: Oid(int[] components) 226: { 227: this.components = components; 228: relative = false; 229: } 230: 231: // Instance methods. 232: // ------------------------------------------------------------------------- 233: 234: /** 235: * Returns a string representation of the oid's integer components in 236: * dot separated notation (e.g. "1.2.840.113554.1.2.2"). 237: * 238: * @return The string representation of this oid. 239: */ 240: public String toString() 241: { 242: if (strOid == null) 243: { 244: StringBuffer buf = new StringBuffer(); 245: for (int i = 0; i < components.length; i++) 246: { 247: buf.append(components[i]); 248: if (i < components.length - 1) 249: buf.append('.'); 250: } 251: strOid = buf.toString(); 252: } 253: return strOid; 254: } 255: 256: /** 257: * Returns the full ASN.1 DER encoding for this oid object, which 258: * includes the tag and length. 259: * 260: * @return The ASN.1 DER encoding for this oid. 261: * @throws GSSException If encoding fails. 262: */ 263: public byte[] getDER() throws GSSException 264: { 265: if (derOid == null) 266: { 267: ByteArrayOutputStream out = new ByteArrayOutputStream(256); 268: try 269: { 270: int i = 0; 271: if (!relative) 272: { 273: int b = components[i++] * 40 + (components.length > 1 274: ? components[i++] : 0); 275: encodeSubId(out, b); 276: } 277: for ( ; i < components.length; i++) 278: encodeSubId(out, components[i]); 279: byte[] oid = out.toByteArray(); 280: out.reset(); 281: if (relative) 282: out.write(RELATIVE_OID); 283: else 284: out.write(OBJECT_IDENTIFIER); 285: if (oid.length < 128) 286: out.write(oid.length); 287: else if (oid.length < 256) 288: { 289: out.write(0x81); 290: out.write(oid.length); 291: } 292: else if (oid.length < 65536) 293: { 294: out.write(0x82); 295: out.write((oid.length >>> 8) & 0xFF); 296: out.write(oid.length & 0xFF); 297: } 298: else if (oid.length < 16777216) 299: { 300: out.write(0x83); 301: out.write((oid.length >>> 16) & 0xFF); 302: out.write((oid.length >>> 8) & 0xFF); 303: out.write(oid.length & 0xFF); 304: } 305: else 306: { 307: out.write(0x84); 308: out.write((oid.length >>> 24) & 0xFF); 309: out.write((oid.length >>> 16) & 0xFF); 310: out.write((oid.length >>> 8) & 0xFF); 311: out.write(oid.length & 0xFF); 312: } 313: out.write(oid); 314: } 315: catch (IOException ioe) 316: { 317: throw new GSSException(GSSException.FAILURE); 318: } 319: derOid = out.toByteArray(); 320: } 321: return (byte[]) derOid.clone(); 322: } 323: 324: /** 325: * A utility method to test if an Oid object is contained within the 326: * supplied Oid object array. 327: * 328: * @param oids An array of oids to search. 329: * @return True if this oid is contained in the given array. 330: */ 331: public boolean containedIn(Oid[] oids) 332: { 333: for (int i = 0; i < oids.length; i++) 334: { 335: if (equals(oids[i])) 336: return true; 337: } 338: return false; 339: } 340: 341: public boolean equals(Object o) 342: { 343: if (!(o instanceof Oid)) 344: return false; 345: Oid that = (Oid) o; 346: return Arrays.equals(components, that.components); 347: } 348: 349: public int hashCode() 350: { 351: int code = 0; 352: for (int i = 0; i < components.length; i++) 353: code += components[i]; 354: return code; 355: } 356: 357: // Own methods. 358: // ------------------------------------------------------------------------- 359: 360: private static void encodeSubId(OutputStream out, int id) throws IOException 361: { 362: if (id < 128) 363: { 364: out.write(id); 365: } 366: else if (id < 16384) 367: { 368: out.write((id >>> 7) | 0x80); 369: out.write(id & 0x7F); 370: } 371: else if (id < 2097152) 372: { 373: out.write((id >>> 14) | 0x80); 374: out.write(((id >>> 7) | 0x80) & 0xFF); 375: out.write(id & 0x7F); 376: } 377: else if (id < 268435456) 378: { 379: out.write( (id >>> 21) | 0x80); 380: out.write(((id >>> 14) | 0x80) & 0xFF); 381: out.write(((id >>> 7) | 0x80) & 0xFF); 382: out.write(id & 0x7F); 383: } 384: } 385: }
GNU Classpath (0.95) |