Source Code Cross Referenced for X500Name.java in  » 6.0-JDK-Modules » j2me » sun » security » x509 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » sun.security.x509 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * @(#)X500Name.java	1.54 06/10/10
0003:         *
0004:         * Copyright  1990-2006 Sun Microsystems, Inc. All Rights Reserved.  
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER  
0006:         *   
0007:         * This program is free software; you can redistribute it and/or  
0008:         * modify it under the terms of the GNU General Public License version  
0009:         * 2 only, as published by the Free Software Foundation.   
0010:         *   
0011:         * This program is distributed in the hope that it will be useful, but  
0012:         * WITHOUT ANY WARRANTY; without even the implied warranty of  
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
0014:         * General Public License version 2 for more details (a copy is  
0015:         * included at /legal/license.txt).   
0016:         *   
0017:         * You should have received a copy of the GNU General Public License  
0018:         * version 2 along with this work; if not, write to the Free Software  
0019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  
0020:         * 02110-1301 USA   
0021:         *   
0022:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa  
0023:         * Clara, CA 95054 or visit www.sun.com if you need additional  
0024:         * information or have any questions. 
0025:         *
0026:         */
0027:
0028:        package sun.security.x509;
0029:
0030:        import java.lang.reflect.*;
0031:        import java.io.IOException;
0032:        import java.io.StringReader;
0033:        import java.security.PrivilegedExceptionAction;
0034:        import java.security.AccessController;
0035:        import java.security.Principal;
0036:        import java.util.*;
0037:
0038:        import sun.security.util.*;
0039:        import sun.security.pkcs.PKCS9Attribute;
0040:        import javax.security.auth.x500.X500Principal;
0041:
0042:        /**
0043:         * Note:  As of 1.4, the public class,
0044:         * javax.security.auth.x500.X500Principal,
0045:         * should be used when parsing, generating, and comparing X.500 DNs.
0046:         * This class contains other useful methods for checking name constraints
0047:         * and retrieving DNs by keyword.
0048:         *
0049:         * <p> X.500 names are used to identify entities, such as those which are
0050:         * identified by X.509 certificates.  They are world-wide, hierarchical,
0051:         * and descriptive.  Entities can be identified by attributes, and in
0052:         * some systems can be searched for according to those attributes.
0053:         * <p>
0054:         * The ASN.1 for this is:
0055:         * <pre>
0056:         * GeneralName ::= CHOICE {
0057:         * ....
0058:         *     directoryName                   [4]     Name,
0059:         * ....
0060:         * Name ::= CHOICE {
0061:         *   RDNSequence }
0062:         *
0063:         * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
0064:         *
0065:         * RelativeDistinguishedName ::=
0066:         *   SET OF AttributeTypeAndValue
0067:         *
0068:         * AttributeTypeAndValue ::= SEQUENCE {
0069:         *   type     AttributeType,
0070:         *   value    AttributeValue }
0071:         *
0072:         * AttributeType ::= OBJECT IDENTIFIER
0073:         *
0074:         * AttributeValue ::= ANY DEFINED BY AttributeType
0075:         * ....
0076:         * DirectoryString ::= CHOICE {
0077:         *       teletexString           TeletexString (SIZE (1..MAX)),
0078:         *       printableString         PrintableString (SIZE (1..MAX)),
0079:         *       universalString         UniversalString (SIZE (1..MAX)),
0080:         *       utf8String              UTF8String (SIZE (1.. MAX)),
0081:         *       bmpString               BMPString (SIZE (1..MAX)) }
0082:         * </pre>
0083:         * <p>
0084:         * This specification requires only a subset of the name comparison
0085:         * functionality specified in the X.500 series of specifications.  The
0086:         * requirements for conforming implementations are as follows:
0087:         * <ol TYPE=a>
0088:         * <li>attribute values encoded in different types (e.g.,
0089:         *    PrintableString and BMPString) may be assumed to represent
0090:         *    different strings;
0091:         * <p>
0092:         * <li>attribute values in types other than PrintableString are case
0093:         *    sensitive (this permits matching of attribute values as binary
0094:         *    objects);
0095:         * <p>
0096:         * <li>attribute values in PrintableString are not case sensitive
0097:         *    (e.g., "Marianne Swanson" is the same as "MARIANNE SWANSON"); and
0098:         * <p>
0099:         * <li>attribute values in PrintableString are compared after
0100:         *    removing leading and trailing white space and converting internal
0101:         *    substrings of one or more consecutive white space characters to a
0102:         *    single space.
0103:         * </ol>
0104:         * <p>
0105:         * These name comparison rules permit a certificate user to validate
0106:         * certificates issued using languages or encodings unfamiliar to the
0107:         * certificate user.
0108:         * <p>
0109:         * In addition, implementations of this specification MAY use these
0110:         * comparison rules to process unfamiliar attribute types for name
0111:         * chaining. This allows implementations to process certificates with
0112:         * unfamiliar attributes in the issuer name.
0113:         * <p>
0114:         * Note that the comparison rules defined in the X.500 series of
0115:         * specifications indicate that the character sets used to encode data
0116:         * in distinguished names are irrelevant.  The characters themselves are
0117:         * compared without regard to encoding. Implementations of the profile
0118:         * are permitted to use the comparison algorithm defined in the X.500
0119:         * series.  Such an implementation will recognize a superset of name
0120:         * matches recognized by the algorithm specified above.
0121:         * <p>
0122:         * Note that instances of this class are immutable.
0123:         *
0124:         * @author David Brownell
0125:         * @author Amit Kapoor
0126:         * @author Hemma Prafullchandra
0127:         * @version 1.47
0128:         * @see GeneralName
0129:         * @see GeneralNames
0130:         * @see GeneralNameInterface
0131:         */
0132:
0133:        public class X500Name implements  GeneralNameInterface, Principal {
0134:
0135:            private String dn; // roughly RFC 1779 DN, or null
0136:            private String rfc1779Dn; // RFC 1779 compliant DN, or null
0137:            private String rfc2253Dn; // RFC 2253 DN, or null
0138:            private String canonicalDn; // canonical RFC 2253 DN or null
0139:            private RDN[] names; // RDNs (never null)
0140:            private X500Principal x500Principal;
0141:            private byte[] encoded;
0142:
0143:            // cached immutable list of the RDNs and all the AVAs
0144:            private volatile List rdnList, allAvaList;
0145:
0146:            /**
0147:             * Constructs a name from a conventionally formatted string, such
0148:             * as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US".
0149:             * (RFC 1779 or RFC 2253 style).
0150:             *
0151:             * @param DN X.500 Distinguished Name
0152:             */
0153:            public X500Name(String dname) throws IOException {
0154:                parseDN(dname);
0155:            }
0156:
0157:            /**
0158:             * Constructs a name from a string formatted according to format.
0159:             * Currently, the formats DEFAULT and RFC2253 are supported.
0160:             * DEFAULT is the default format used by the X500Name(String)
0161:             * constructor. RFC2253 is format strictly according to RFC2253
0162:             * without extensions.
0163:             *
0164:             * @param DN X.500 Distinguished Name
0165:             */
0166:            public X500Name(String dname, String format) throws IOException {
0167:                if (dname == null) {
0168:                    throw new NullPointerException("Name must not be null");
0169:                }
0170:                if (format.equalsIgnoreCase("RFC2253")) {
0171:                    parseRFC2253DN(dname);
0172:                } else if (format.equalsIgnoreCase("DEFAULT")) {
0173:                    parseDN(dname);
0174:                } else {
0175:                    throw new IOException("Unsupported format " + format);
0176:                }
0177:            }
0178:
0179:            /**
0180:             * Constructs a name from fields common in enterprise application
0181:             * environments.
0182:             *
0183:             * <P><EM><STRONG>NOTE:</STRONG>  The behaviour when any of
0184:             * these strings contain characters outside the ASCII range
0185:             * is unspecified in currently relevant standards.</EM>
0186:             *
0187:             * @param commonName common name of a person, e.g. "Vivette Davis"
0188:             * @param organizationUnit small organization name, e.g. "Purchasing"
0189:             * @param organizationName large organization name, e.g. "Onizuka, Inc."
0190:             * @param country two letter country code, e.g. "CH"
0191:             */
0192:            public X500Name(String commonName, String organizationUnit,
0193:                    String organizationName, String country) throws IOException {
0194:                names = new RDN[4];
0195:                /*
0196:                 * NOTE:  it's only on output that little-endian
0197:                 * ordering is used.
0198:                 */
0199:                names[3] = new RDN(1);
0200:                names[3].assertion[0] = new AVA(commonName_oid, new DerValue(
0201:                        commonName));
0202:                names[2] = new RDN(1);
0203:                names[2].assertion[0] = new AVA(orgUnitName_oid, new DerValue(
0204:                        organizationUnit));
0205:                names[1] = new RDN(1);
0206:                names[1].assertion[0] = new AVA(orgName_oid, new DerValue(
0207:                        organizationName));
0208:                names[0] = new RDN(1);
0209:                names[0].assertion[0] = new AVA(countryName_oid, new DerValue(
0210:                        country));
0211:            }
0212:
0213:            /**
0214:             * Constructs a name from fields common in Internet application
0215:             * environments.
0216:             *
0217:             * <P><EM><STRONG>NOTE:</STRONG>  The behaviour when any of
0218:             * these strings contain characters outside the ASCII range
0219:             * is unspecified in currently relevant standards.</EM>
0220:             *
0221:             * @param commonName common name of a person, e.g. "Vivette Davis"
0222:             * @param organizationUnit small organization name, e.g. "Purchasing"
0223:             * @param organizationName large organization name, e.g. "Onizuka, Inc."
0224:             * @param localityName locality (city) name, e.g. "Palo Alto"
0225:             * @param stateName state name, e.g. "California"
0226:             * @param country two letter country code, e.g. "CH"
0227:             */
0228:            public X500Name(String commonName, String organizationUnit,
0229:                    String organizationName, String localityName,
0230:                    String stateName, String country) throws IOException {
0231:                names = new RDN[6];
0232:                /*
0233:                 * NOTE:  it's only on output that little-endian
0234:                 * ordering is used.
0235:                 */
0236:                names[5] = new RDN(1);
0237:                names[5].assertion[0] = new AVA(commonName_oid, new DerValue(
0238:                        commonName));
0239:                names[4] = new RDN(1);
0240:                names[4].assertion[0] = new AVA(orgUnitName_oid, new DerValue(
0241:                        organizationUnit));
0242:                names[3] = new RDN(1);
0243:                names[3].assertion[0] = new AVA(orgName_oid, new DerValue(
0244:                        organizationName));
0245:                names[2] = new RDN(1);
0246:                names[2].assertion[0] = new AVA(localityName_oid, new DerValue(
0247:                        localityName));
0248:                names[1] = new RDN(1);
0249:                names[1].assertion[0] = new AVA(stateName_oid, new DerValue(
0250:                        stateName));
0251:                names[0] = new RDN(1);
0252:                names[0].assertion[0] = new AVA(countryName_oid, new DerValue(
0253:                        country));
0254:            }
0255:
0256:            /**
0257:             * Constructs a name from an array of relative distinguished names
0258:             *
0259:             * @param rdnArray array of relative distinguished names
0260:             * @throws IOException on error
0261:             */
0262:            public X500Name(RDN[] rdnArray) throws IOException {
0263:                if (rdnArray == null) {
0264:                    names = new RDN[0];
0265:                } else {
0266:                    names = (RDN[]) rdnArray.clone();
0267:                    for (int i = 0; i < names.length; i++) {
0268:                        if (names[i] == null) {
0269:                            throw new IOException("Cannot create an X500Name");
0270:                        }
0271:                    }
0272:                }
0273:            }
0274:
0275:            /**
0276:             * Constructs a name from an ASN.1 encoded value.  The encoding
0277:             * of the name in the stream uses DER (a BER/1 subset).
0278:             *
0279:             * @param value a DER-encoded value holding an X.500 name.
0280:             */
0281:            public X500Name(DerValue value) throws IOException {
0282:                //Note that toDerInputStream uses only the buffer (data) and not
0283:                //the tag, so an empty SEQUENCE (OF) will yield an empty DerInputStream
0284:                this (value.toDerInputStream());
0285:            }
0286:
0287:            /**
0288:             * Constructs a name from an ASN.1 encoded input stream.  The encoding
0289:             * of the name in the stream uses DER (a BER/1 subset).
0290:             *
0291:             * @param in DER-encoded data holding an X.500 name.
0292:             */
0293:            public X500Name(DerInputStream in) throws IOException {
0294:                parseDER(in);
0295:            }
0296:
0297:            /**
0298:             *  Constructs a name from an ASN.1 encoded byte array.
0299:             *
0300:             * @param name DER-encoded byte array holding an X.500 name.
0301:             */
0302:            public X500Name(byte[] name) throws IOException {
0303:                DerInputStream in = new DerInputStream(name);
0304:                parseDER(in);
0305:            }
0306:
0307:            /**
0308:             * Return an immutable List of all RDNs in this X500Name.
0309:             */
0310:            public List rdns() {
0311:                List list = rdnList;
0312:                if (list == null) {
0313:                    list = Collections.unmodifiableList(Arrays.asList(names));
0314:                    rdnList = list;
0315:                }
0316:                return list;
0317:            }
0318:
0319:            /**
0320:             * Return the number of RDNs in this X500Name.
0321:             */
0322:            public int size() {
0323:                return names.length;
0324:            }
0325:
0326:            /**
0327:             * Return an immutable List of the the AVAs contained in all the
0328:             * RDNs of this X500Name.
0329:             */
0330:            public List allAvas() {
0331:                List list = allAvaList;
0332:                if (list == null) {
0333:                    list = new ArrayList();
0334:                    for (int i = 0; i < names.length; i++) {
0335:                        list.addAll(names[i].avas());
0336:                    }
0337:                }
0338:                return list;
0339:            }
0340:
0341:            /**
0342:             * Return the total number of AVAs contained in all the RDNs of
0343:             * this X500Name.
0344:             */
0345:            public int avaSize() {
0346:                return allAvas().size();
0347:            }
0348:
0349:            /**
0350:             * Return whether this X500Name is empty. An X500Name is not empty
0351:             * if it has at least one RDN containing at least one AVA.
0352:             */
0353:            public boolean isEmpty() {
0354:                int n = names.length;
0355:                if (n == 0) {
0356:                    return true;
0357:                }
0358:                for (int i = 0; i < n; i++) {
0359:                    if (names[i].assertion.length != 0) {
0360:                        return false;
0361:                    }
0362:                }
0363:                return true;
0364:            }
0365:
0366:            /**
0367:             * Calculates a hash code value for the object.  Objects
0368:             * which are equal will also have the same hashcode.
0369:             */
0370:            public int hashCode() {
0371:                return getRFC2253CanonicalName().hashCode();
0372:            }
0373:
0374:            /**
0375:             * Compares this name with another, for equality.
0376:             *
0377:             * @return true iff the names are identical.
0378:             */
0379:            public boolean equals(Object obj) {
0380:                if (this  == obj) {
0381:                    return true;
0382:                }
0383:                if (obj instanceof  X500Name == false) {
0384:                    return false;
0385:                }
0386:                X500Name other = (X500Name) obj;
0387:                // if we already have the canonical forms, compare now
0388:                if ((this .canonicalDn != null) && (other.canonicalDn != null)) {
0389:                    return this .canonicalDn.equals(other.canonicalDn);
0390:                }
0391:                // quick check that number of RDNs and AVAs match before canonicalizing
0392:                int n = this .names.length;
0393:                if (n != other.names.length) {
0394:                    return false;
0395:                }
0396:                for (int i = 0; i < n; i++) {
0397:                    RDN r1 = this .names[i];
0398:                    RDN r2 = other.names[i];
0399:                    if (r1.assertion.length != r2.assertion.length) {
0400:                        return false;
0401:                    }
0402:                }
0403:                // definite check via canonical form
0404:                String this Canonical = this .getRFC2253CanonicalName();
0405:                String otherCanonical = other.getRFC2253CanonicalName();
0406:                return this Canonical.equals(otherCanonical);
0407:            }
0408:
0409:            /*
0410:             * Returns the name component as a Java string, regardless of its
0411:             * encoding restrictions.
0412:             */
0413:            private String getString(DerValue attribute) throws IOException {
0414:                if (attribute == null)
0415:                    return null;
0416:                String value = attribute.getAsString();
0417:
0418:                if (value == null)
0419:                    throw new IOException("not a DER string encoding, "
0420:                            + attribute.tag);
0421:                else
0422:                    return value;
0423:            }
0424:
0425:            /**
0426:             * Return type of GeneralName.
0427:             */
0428:            public int getType() {
0429:                return (GeneralNameInterface.NAME_DIRECTORY);
0430:            }
0431:
0432:            /**
0433:             * Returns a "Country" name component.  If more than one
0434:             * such attribute exists, the topmost one is returned.
0435:             *
0436:             * @return "C=" component of the name, if any.
0437:             */
0438:            public String getCountry() throws IOException {
0439:                DerValue attr = findAttribute(countryName_oid);
0440:
0441:                return getString(attr);
0442:            }
0443:
0444:            /**
0445:             * Returns an "Organization" name component.  If more than
0446:             * one such attribute exists, the topmost one is returned.
0447:             *
0448:             * @return "O=" component of the name, if any.
0449:             */
0450:            public String getOrganization() throws IOException {
0451:                DerValue attr = findAttribute(orgName_oid);
0452:
0453:                return getString(attr);
0454:            }
0455:
0456:            /**
0457:             * Returns an "Organizational Unit" name component.  If more
0458:             * than one such attribute exists, the topmost one is returned.
0459:             *
0460:             * @return "OU=" component of the name, if any.
0461:             */
0462:            public String getOrganizationalUnit() throws IOException {
0463:                DerValue attr = findAttribute(orgUnitName_oid);
0464:
0465:                return getString(attr);
0466:            }
0467:
0468:            /**
0469:             * Returns a "Common Name" component.  If more than one such
0470:             * attribute exists, the topmost one is returned.
0471:             *
0472:             * @return "CN=" component of the name, if any.
0473:             */
0474:            public String getCommonName() throws IOException {
0475:                DerValue attr = findAttribute(commonName_oid);
0476:
0477:                return getString(attr);
0478:            }
0479:
0480:            /**
0481:             * Returns a "Locality" name component.  If more than one
0482:             * such component exists, the topmost one is returned.
0483:             *
0484:             * @return "L=" component of the name, if any.
0485:             */
0486:            public String getLocality() throws IOException {
0487:                DerValue attr = findAttribute(localityName_oid);
0488:
0489:                return getString(attr);
0490:            }
0491:
0492:            /**
0493:             * Returns a "State" name component.  If more than one
0494:             * such component exists, the topmost one is returned.
0495:             *
0496:             * @return "S=" component of the name, if any.
0497:             */
0498:            public String getState() throws IOException {
0499:                DerValue attr = findAttribute(stateName_oid);
0500:
0501:                return getString(attr);
0502:            }
0503:
0504:            /**
0505:             * Returns a "Domain" name component.  If more than one
0506:             * such component exists, the topmost one is returned.
0507:             *
0508:             * @return "DC=" component of the name, if any.
0509:             */
0510:            public String getDomain() throws IOException {
0511:                DerValue attr = findAttribute(DOMAIN_COMPONENT_OID);
0512:
0513:                return getString(attr);
0514:            }
0515:
0516:            /**
0517:             * Returns a "DN Qualifier" name component.  If more than one
0518:             * such component exists, the topmost one is returned.
0519:             *
0520:             * @return "DNQ=" component of the name, if any.
0521:             */
0522:            public String getDNQualifier() throws IOException {
0523:                DerValue attr = findAttribute(DNQUALIFIER_OID);
0524:
0525:                return getString(attr);
0526:            }
0527:
0528:            /**
0529:             * Returns a "Surname" name component.  If more than one
0530:             * such component exists, the topmost one is returned.
0531:             *
0532:             * @return "SURNAME=" component of the name, if any.
0533:             */
0534:            public String getSurname() throws IOException {
0535:                DerValue attr = findAttribute(SURNAME_OID);
0536:
0537:                return getString(attr);
0538:            }
0539:
0540:            /**
0541:             * Returns a "Given Name" name component.  If more than one
0542:             * such component exists, the topmost one is returned.
0543:             *
0544:             * @return "GIVENNAME=" component of the name, if any.
0545:             */
0546:            public String getGivenName() throws IOException {
0547:                DerValue attr = findAttribute(GIVENNAME_OID);
0548:
0549:                return getString(attr);
0550:            }
0551:
0552:            /**
0553:             * Returns an "Initials" name component.  If more than one
0554:             * such component exists, the topmost one is returned.
0555:             *
0556:             * @return "INITIALS=" component of the name, if any.
0557:             */
0558:            public String getInitials() throws IOException {
0559:                DerValue attr = findAttribute(INITIALS_OID);
0560:
0561:                return getString(attr);
0562:            }
0563:
0564:            /**
0565:             * Returns a "Generation Qualifier" name component.  If more than one
0566:             * such component exists, the topmost one is returned.
0567:             *
0568:             * @return "GENERATION=" component of the name, if any.
0569:             */
0570:            public String getGeneration() throws IOException {
0571:                DerValue attr = findAttribute(GENERATIONQUALIFIER_OID);
0572:
0573:                return getString(attr);
0574:            }
0575:
0576:            /**
0577:             * Returns an "IP address" name component.  If more than one
0578:             * such component exists, the topmost one is returned.
0579:             *
0580:             * @return "IP=" component of the name, if any.
0581:             */
0582:            public String getIP() throws IOException {
0583:                DerValue attr = findAttribute(ipAddress_oid);
0584:
0585:                return getString(attr);
0586:            }
0587:
0588:            /**
0589:             * Returns a string form of the X.500 distinguished name.
0590:             * The format of the string is from RFC 1779. The returned string
0591:             * may contain non-standardised keywords for more readability
0592:             * (keywords from 1779, 2253, and 2459).
0593:             */
0594:            public String toString() {
0595:                if (dn == null) {
0596:                    generateDN();
0597:                }
0598:                return dn;
0599:            }
0600:
0601:            /**
0602:             * Returns a string form of the X.500 distinguished name
0603:             * using the algorithm defined in RFC 1779. Only standard attribute type 
0604:             * keywords defined in RFC 1779 are emitted.
0605:             */
0606:            public String getRFC1779Name() {
0607:                if (rfc1779Dn == null) {
0608:                    generateRFC1779DN();
0609:                }
0610:                return rfc1779Dn;
0611:            }
0612:
0613:            /**
0614:             * Returns a string form of the X.500 distinguished name
0615:             * using the algorithm defined in RFC 2253. Only standard attribute type 
0616:             * keywords defined in RFC 2253 are emitted.
0617:             */
0618:            public String getRFC2253Name() {
0619:                /* check for and return cached name */
0620:                if (rfc2253Dn != null) {
0621:                    return rfc2253Dn;
0622:                }
0623:                /* 
0624:                 * Section 2.1 : if the RDNSequence is an empty sequence
0625:                 * the result is the empty or zero length string.
0626:                 */
0627:                if (names.length == 0) {
0628:                    rfc2253Dn = "";
0629:                    return rfc2253Dn;
0630:                }
0631:
0632:                /*
0633:                 * 2.1 (continued) : Otherwise, the output consists of the string 
0634:                 * encodings of each RelativeDistinguishedName in the RDNSequence 
0635:                 * (according to 2.2), starting with the last element of the sequence 
0636:                 * and moving backwards toward the first.
0637:                 *
0638:                 * The encodings of adjoining RelativeDistinguishedNames are separated
0639:                 * by a comma character (',' ASCII 44).
0640:                 */
0641:                StringBuffer fullname = new StringBuffer(48);
0642:                for (int i = names.length - 1; i >= 0; i--) {
0643:                    if (i < names.length - 1) {
0644:                        fullname.append(',');
0645:                    }
0646:                    fullname.append(names[i].toRFC2253String());
0647:                }
0648:                rfc2253Dn = new String(fullname);
0649:                return rfc2253Dn;
0650:            }
0651:
0652:            public String getRFC2253CanonicalName() {
0653:                /* check for and return cached name */
0654:                if (canonicalDn != null) {
0655:                    return canonicalDn;
0656:                }
0657:                /* 
0658:                 * Section 2.1 : if the RDNSequence is an empty sequence
0659:                 * the result is the empty or zero length string.
0660:                 */
0661:                if (names.length == 0) {
0662:                    canonicalDn = "";
0663:                    return canonicalDn;
0664:                }
0665:
0666:                /*
0667:                 * 2.1 (continued) : Otherwise, the output consists of the string 
0668:                 * encodings of each RelativeDistinguishedName in the RDNSequence 
0669:                 * (according to 2.2), starting with the last element of the sequence 
0670:                 * and moving backwards toward the first.
0671:                 *
0672:                 * The encodings of adjoining RelativeDistinguishedNames are separated
0673:                 * by a comma character (',' ASCII 44).
0674:                 */
0675:                StringBuffer fullname = new StringBuffer(48);
0676:                for (int i = names.length - 1; i >= 0; i--) {
0677:                    if (i < names.length - 1) {
0678:                        fullname.append(',');
0679:                    }
0680:                    fullname.append(names[i].toRFC2253String(true));
0681:                }
0682:                canonicalDn = new String(fullname);
0683:                return canonicalDn;
0684:            }
0685:
0686:            /**
0687:             * Returns the value of toString().  This call is needed to
0688:             * implement the java.security.Principal interface.
0689:             */
0690:            public String getName() {
0691:                return toString();
0692:            }
0693:
0694:            /**
0695:             * Find the first instance of this attribute in a "top down"
0696:             * search of all the attributes in the name.
0697:             */
0698:            private DerValue findAttribute(ObjectIdentifier attribute) {
0699:                if (names != null) {
0700:                    for (int i = 0; i < names.length; i++) {
0701:                        DerValue value = names[i].findAttribute(attribute);
0702:                        if (value != null) {
0703:                            return value;
0704:                        }
0705:                    }
0706:                }
0707:                return null;
0708:            }
0709:
0710:            /**
0711:             * Find the most specific ("last") attribute of the given
0712:             * type.
0713:             */
0714:            public DerValue findMostSpecificAttribute(ObjectIdentifier attribute) {
0715:                if (names != null) {
0716:                    for (int i = names.length - 1; i >= 0; i--) {
0717:                        DerValue value = names[i].findAttribute(attribute);
0718:                        if (value != null) {
0719:                            return value;
0720:                        }
0721:                    }
0722:                }
0723:                return null;
0724:            }
0725:
0726:            /****************************************************************/
0727:
0728:            private void parseDER(DerInputStream in) throws IOException {
0729:                //
0730:                // X.500 names are a "SEQUENCE OF" RDNs, which means zero or
0731:                // more and order matters.  We scan them in order, which
0732:                // conventionally is big-endian.
0733:                //
0734:                DerValue[] nameseq = null;
0735:                byte[] derBytes = in.toByteArray();
0736:
0737:                try {
0738:                    nameseq = in.getSequence(5);
0739:                } catch (IOException ioe) {
0740:                    if (derBytes == null) {
0741:                        nameseq = null;
0742:                    } else {
0743:                        DerValue derVal = new DerValue(DerValue.tag_Sequence,
0744:                                derBytes);
0745:                        derBytes = derVal.toByteArray();
0746:                        nameseq = new DerInputStream(derBytes).getSequence(5);
0747:                    }
0748:                }
0749:
0750:                if (nameseq == null) {
0751:                    names = new RDN[0];
0752:                } else {
0753:                    names = new RDN[nameseq.length];
0754:                    for (int i = 0; i < nameseq.length; i++) {
0755:                        names[i] = new RDN(nameseq[i]);
0756:                    }
0757:                }
0758:            }
0759:
0760:            /**
0761:             * Encodes the name in DER-encoded form.
0762:             *
0763:             * @deprecated Use encode() instead
0764:             * @param out where to put the DER-encoded X.500 name
0765:             */
0766:            public void emit(DerOutputStream out) throws IOException {
0767:                encode(out);
0768:            }
0769:
0770:            /**
0771:             * Encodes the name in DER-encoded form.
0772:             *
0773:             * @param out where to put the DER-encoded X.500 name
0774:             */
0775:            public void encode(DerOutputStream out) throws IOException {
0776:                DerOutputStream tmp = new DerOutputStream();
0777:                for (int i = 0; i < names.length; i++) {
0778:                    names[i].encode(tmp);
0779:                }
0780:                out.write(DerValue.tag_Sequence, tmp);
0781:            }
0782:
0783:            /**
0784:             * Returned the encoding as an uncloned byte array. Callers must
0785:             * guarantee that they neither modify it not expose it to untrusted
0786:             * code.
0787:             */
0788:            public byte[] getEncodedInternal() throws IOException {
0789:                if (encoded == null) {
0790:                    DerOutputStream out = new DerOutputStream();
0791:                    DerOutputStream tmp = new DerOutputStream();
0792:                    for (int i = 0; i < names.length; i++) {
0793:                        names[i].encode(tmp);
0794:                    }
0795:                    out.write(DerValue.tag_Sequence, tmp);
0796:                    encoded = out.toByteArray();
0797:                }
0798:                return encoded;
0799:            }
0800:
0801:            /**
0802:             * Gets the name in DER-encoded form.
0803:             *
0804:             * @return the DER encoded byte array of this name.
0805:             */
0806:            public byte[] getEncoded() throws IOException {
0807:                return (byte[]) getEncodedInternal().clone();
0808:            }
0809:
0810:            /*
0811:             * Parses a Distinguished Name (DN) in printable representation.
0812:             *
0813:             * According to RFC 1779, RDNs in a DN are separated by comma.
0814:             * The following examples show both methods of quoting a comma, so that it
0815:             * is not considered a separator:
0816:             *
0817:             *     O="Sue, Grabbit and Runn" or
0818:             *     O=Sue\, Grabbit and Runn
0819:             *
0820:             * This method can parse 1779 or 2253 DNs and non-standard 2459 keywords.
0821:             */
0822:            private void parseDN(String input) throws IOException {
0823:                if (input == null || input.length() == 0) {
0824:                    names = new RDN[0];
0825:                    return;
0826:                }
0827:
0828:                Vector dnVector = new Vector();
0829:                int dnOffset = 0;
0830:                int rdnEnd;
0831:                String rdnString;
0832:                int quoteCount = 0;
0833:
0834:                String dnString = input;
0835:
0836:                int searchOffset = 0;
0837:                int nextComma = dnString.indexOf(',');
0838:                int nextSemiColon = dnString.indexOf(';');
0839:                while (nextComma >= 0 || nextSemiColon >= 0) {
0840:
0841:                    if (nextSemiColon < 0) {
0842:                        rdnEnd = nextComma;
0843:                    } else if (nextComma < 0) {
0844:                        rdnEnd = nextSemiColon;
0845:                    } else {
0846:                        rdnEnd = Math.min(nextComma, nextSemiColon);
0847:                    }
0848:                    quoteCount += countQuotes(dnString, searchOffset, rdnEnd);
0849:
0850:                    /*
0851:                     * We have encountered an RDN delimiter (comma or a semicolon).
0852:                     * If the comma or semicolon in the RDN under consideration is 
0853:                     * preceded by a backslash (escape), or by a double quote, it
0854:                     * is part of the RDN. Otherwise, it is used as a separator, to 
0855:                     * delimit the RDN under consideration from any subsequent RDNs.
0856:                     */
0857:                    if (rdnEnd >= 0 && quoteCount != 1
0858:                            && !escaped(rdnEnd, searchOffset, dnString)) {
0859:
0860:                        /*
0861:                         * Comma/semicolon is a separator
0862:                         */
0863:                        rdnString = dnString.substring(dnOffset, rdnEnd);
0864:
0865:                        // Parse RDN, and store it in vector
0866:                        RDN rdn = new RDN(rdnString);
0867:                        dnVector.addElement(rdn);
0868:
0869:                        // Increase the offset
0870:                        dnOffset = rdnEnd + 1;
0871:
0872:                        // Set quote counter back to zero
0873:                        quoteCount = 0;
0874:                    }
0875:
0876:                    searchOffset = rdnEnd + 1;
0877:                    nextComma = dnString.indexOf(',', searchOffset);
0878:                    nextSemiColon = dnString.indexOf(';', searchOffset);
0879:                }
0880:
0881:                // Parse last or only RDN, and store it in vector
0882:                rdnString = dnString.substring(dnOffset);
0883:                RDN rdn = new RDN(rdnString);
0884:                dnVector.addElement(rdn);
0885:
0886:                /*
0887:                 * Store the vector elements as an array of RDNs
0888:                 * NOTE: It's only on output that little-endian ordering is used.
0889:                 */
0890:                int numElem = dnVector.size();
0891:                names = new RDN[numElem];
0892:                Enumeration e = dnVector.elements();
0893:                int i = numElem - 1;
0894:
0895:                while (e.hasMoreElements()) {
0896:                    names[i--] = (RDN) e.nextElement();
0897:                }
0898:            }
0899:
0900:            private void parseRFC2253DN(String dnString) throws IOException {
0901:                if (dnString.length() == 0) {
0902:                    names = new RDN[0];
0903:                    return;
0904:                }
0905:
0906:                Vector dnVector = new Vector();
0907:                int dnOffset = 0;
0908:                String rdnString;
0909:
0910:                int searchOffset = 0;
0911:                int rdnEnd = dnString.indexOf(',');
0912:                while (rdnEnd >= 0) {
0913:                    /*
0914:                     * We have encountered an RDN delimiter (comma).
0915:                     * If the comma in the RDN under consideration is 
0916:                     * preceded by a backslash (escape), it
0917:                     * is part of the RDN. Otherwise, it is used as a separator, to 
0918:                     * delimit the RDN under consideration from any subsequent RDNs.
0919:                     */
0920:                    if (rdnEnd > 0 && !escaped(rdnEnd, searchOffset, dnString)) {
0921:
0922:                        /*
0923:                         * Comma is a separator
0924:                         */
0925:                        rdnString = dnString.substring(dnOffset, rdnEnd);
0926:
0927:                        // Parse RDN, and store it in vector
0928:                        RDN rdn = new RDN(rdnString, "RFC2253");
0929:                        dnVector.addElement(rdn);
0930:
0931:                        // Increase the offset
0932:                        dnOffset = rdnEnd + 1;
0933:                    }
0934:
0935:                    searchOffset = rdnEnd + 1;
0936:                    rdnEnd = dnString.indexOf(',', searchOffset);
0937:                }
0938:
0939:                // Parse last or only RDN, and store it in vector
0940:                rdnString = dnString.substring(dnOffset);
0941:                RDN rdn = new RDN(rdnString, "RFC2253");
0942:                dnVector.addElement(rdn);
0943:
0944:                /*
0945:                 * Store the vector elements as an array of RDNs
0946:                 * NOTE: It's only on output that little-endian ordering is used.
0947:                 */
0948:                int numElem = dnVector.size();
0949:                names = new RDN[numElem];
0950:                Enumeration e = dnVector.elements();
0951:                int i = numElem - 1;
0952:
0953:                while (e.hasMoreElements()) {
0954:                    names[i--] = (RDN) e.nextElement();
0955:                }
0956:            }
0957:
0958:            /*
0959:             * Counts double quotes in string.
0960:             * Escaped quotes are ignored.
0961:             */
0962:            static int countQuotes(String string, int from, int to) {
0963:                int count = 0;
0964:
0965:                for (int i = from; i < to; i++) {
0966:                    if ((string.charAt(i) == '"' && i == from)
0967:                            || (string.charAt(i) == '"' && string.charAt(i - 1) != '\\')) {
0968:                        count++;
0969:                    }
0970:                }
0971:
0972:                return count;
0973:            }
0974:
0975:            private static boolean escaped(int rdnEnd, int searchOffset,
0976:                    String dnString) {
0977:
0978:                if (rdnEnd == 1 && dnString.charAt(rdnEnd - 1) == '\\') {
0979:
0980:                    //	case 1:
0981:                    //	\,
0982:
0983:                    return true;
0984:
0985:                } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\'
0986:                        && dnString.charAt(rdnEnd - 2) != '\\') {
0987:
0988:                    //	case 2:
0989:                    //	foo\,
0990:
0991:                    return true;
0992:
0993:                } else if (rdnEnd > 1 && dnString.charAt(rdnEnd - 1) == '\\'
0994:                        && dnString.charAt(rdnEnd - 2) == '\\') {
0995:
0996:                    //	case 3:
0997:                    //	foo\\\\\,
0998:
0999:                    int count = 0;
1000:                    rdnEnd--; // back up to last backSlash
1001:                    while (rdnEnd >= searchOffset) {
1002:                        if (dnString.charAt(rdnEnd) == '\\') {
1003:                            count++; // count consecutive backslashes
1004:                        }
1005:                        rdnEnd--;
1006:                    }
1007:
1008:                    // if count is odd, then rdnEnd is escaped
1009:                    return (count % 2) != 0 ? true : false;
1010:
1011:                } else {
1012:                    return false;
1013:                }
1014:            }
1015:
1016:            /*
1017:             * Dump the printable form of a distinguished name.  Each relative
1018:             * name is separated from the next by a ",", and assertions in the
1019:             * relative names have "label=value" syntax.
1020:             *
1021:             * Uses RFC 1779 syntax (i.e. little-endian, comma separators)
1022:             */
1023:            private void generateDN() {
1024:                if (names.length == 1) {
1025:                    dn = names[0].toString();
1026:                    return;
1027:                }
1028:
1029:                StringBuffer sb = new StringBuffer(48);
1030:                if (names != null) {
1031:                    for (int i = names.length - 1; i >= 0; i--) {
1032:                        if (i != names.length - 1) {
1033:                            sb.append(", ");
1034:                        }
1035:                        sb.append(names[i].toString());
1036:                    }
1037:                }
1038:                dn = sb.toString();
1039:            }
1040:
1041:            /*
1042:             * Dump the printable form of a distinguished name.  Each relative
1043:             * name is separated from the next by a ",", and assertions in the
1044:             * relative names have "label=value" syntax.
1045:             *
1046:             * Uses RFC 1779 syntax (i.e. little-endian, comma separators)
1047:             * Only valid keywords from RFC 1779 are used.
1048:             */
1049:            private void generateRFC1779DN() {
1050:                if (names.length == 1) {
1051:                    rfc1779Dn = names[0].toRFC1779String();
1052:                    return;
1053:                }
1054:
1055:                StringBuffer sb = new StringBuffer(48);
1056:                if (names != null) {
1057:                    for (int i = names.length - 1; i >= 0; i--) {
1058:                        if (i != names.length - 1) {
1059:                            sb.append(", ");
1060:                        }
1061:                        sb.append(names[i].toRFC1779String());
1062:                    }
1063:                }
1064:                rfc1779Dn = sb.toString();
1065:            }
1066:
1067:            /****************************************************************/
1068:
1069:            /*
1070:             * Maybe return a preallocated OID, to reduce storage costs
1071:             * and speed recognition of common X.500 attributes.
1072:             */
1073:            static ObjectIdentifier intern(ObjectIdentifier oid) {
1074:                ObjectIdentifier interned = (ObjectIdentifier) internedOIDs
1075:                        .get(oid);
1076:                if (interned != null) {
1077:                    return interned;
1078:                }
1079:                internedOIDs.put(oid, oid);
1080:                return oid;
1081:            }
1082:
1083:            private static final Map internedOIDs = new HashMap();
1084:
1085:            /*
1086:             * Selected OIDs from X.520
1087:             * Includes all those specified in RFC2459 as MUST or SHOULD
1088:             * be recognized
1089:             */
1090:            private static final int commonName_data[] = { 2, 5, 4, 3 };
1091:            private static final int SURNAME_DATA[] = { 2, 5, 4, 4 };
1092:            private static final int SERIALNUMBER_DATA[] = { 2, 5, 4, 5 };
1093:            private static final int countryName_data[] = { 2, 5, 4, 6 };
1094:            private static final int localityName_data[] = { 2, 5, 4, 7 };
1095:            private static final int stateName_data[] = { 2, 5, 4, 8 };
1096:            private static final int streetAddress_data[] = { 2, 5, 4, 9 };
1097:            private static final int orgName_data[] = { 2, 5, 4, 10 };
1098:            private static final int orgUnitName_data[] = { 2, 5, 4, 11 };
1099:            private static final int title_data[] = { 2, 5, 4, 12 };
1100:            private static final int GIVENNAME_DATA[] = { 2, 5, 4, 42 };
1101:            private static final int INITIALS_DATA[] = { 2, 5, 4, 43 };
1102:            private static final int GENERATIONQUALIFIER_DATA[] = { 2, 5, 4, 44 };
1103:            private static final int DNQUALIFIER_DATA[] = { 2, 5, 4, 46 };
1104:
1105:            private static final int ipAddress_data[] = { 1, 3, 6, 1, 4, 1, 42,
1106:                    2, 11, 2, 1 };
1107:            private static final int DOMAIN_COMPONENT_DATA[] = { 0, 9, 2342,
1108:                    19200300, 100, 1, 25 };
1109:            private static final int userid_data[] = { 0, 9, 2342, 19200300,
1110:                    100, 1, 1 };
1111:
1112:            public static final ObjectIdentifier commonName_oid;
1113:            public static final ObjectIdentifier countryName_oid;
1114:            public static final ObjectIdentifier localityName_oid;
1115:            public static final ObjectIdentifier orgName_oid;
1116:            public static final ObjectIdentifier orgUnitName_oid;
1117:            public static final ObjectIdentifier stateName_oid;
1118:            public static final ObjectIdentifier streetAddress_oid;
1119:            public static final ObjectIdentifier title_oid;
1120:            public static final ObjectIdentifier DNQUALIFIER_OID;
1121:            public static final ObjectIdentifier SURNAME_OID;
1122:            public static final ObjectIdentifier GIVENNAME_OID;
1123:            public static final ObjectIdentifier INITIALS_OID;
1124:            public static final ObjectIdentifier GENERATIONQUALIFIER_OID;
1125:            public static final ObjectIdentifier ipAddress_oid;
1126:            public static final ObjectIdentifier DOMAIN_COMPONENT_OID;
1127:            public static final ObjectIdentifier userid_oid;
1128:            public static final ObjectIdentifier SERIALNUMBER_OID;
1129:
1130:            static {
1131:                /** OID for the "CN=" attribute, denoting a person's common name. */
1132:                commonName_oid = intern(ObjectIdentifier
1133:                        .newInternal(commonName_data));
1134:
1135:                /** OID for the "SERIALNUMBER=" attribute, denoting a serial number for. 
1136:                    a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the
1137:                certificate serial number. */
1138:                SERIALNUMBER_OID = intern(ObjectIdentifier
1139:                        .newInternal(SERIALNUMBER_DATA));
1140:
1141:                /** OID for the "C=" attribute, denoting a country. */
1142:                countryName_oid = intern(ObjectIdentifier
1143:                        .newInternal(countryName_data));
1144:
1145:                /** OID for the "L=" attribute, denoting a locality (such as a city) */
1146:                localityName_oid = intern(ObjectIdentifier
1147:                        .newInternal(localityName_data));
1148:
1149:                /** OID for the "O=" attribute, denoting an organization name */
1150:                orgName_oid = intern(ObjectIdentifier.newInternal(orgName_data));
1151:
1152:                /** OID for the "OU=" attribute, denoting an organizational unit name */
1153:                orgUnitName_oid = intern(ObjectIdentifier
1154:                        .newInternal(orgUnitName_data));
1155:
1156:                /** OID for the "S=" attribute, denoting a state (such as Delaware) */
1157:                stateName_oid = intern(ObjectIdentifier
1158:                        .newInternal(stateName_data));
1159:
1160:                /** OID for the "STREET=" attribute, denoting a street address. */
1161:                streetAddress_oid = intern(ObjectIdentifier
1162:                        .newInternal(streetAddress_data));
1163:
1164:                /** OID for the "T=" attribute, denoting a person's title. */
1165:                title_oid = intern(ObjectIdentifier.newInternal(title_data));
1166:
1167:                /** OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN
1168:                disambiguating information.*/
1169:                DNQUALIFIER_OID = intern(ObjectIdentifier
1170:                        .newInternal(DNQUALIFIER_DATA));
1171:
1172:                /** OID for the "SURNAME=" attribute, denoting a person's surname.*/
1173:                SURNAME_OID = intern(ObjectIdentifier.newInternal(SURNAME_DATA));
1174:
1175:                /** OID for the "GIVENNAME=" attribute, denoting a person's given name.*/
1176:                GIVENNAME_OID = intern(ObjectIdentifier
1177:                        .newInternal(GIVENNAME_DATA));
1178:
1179:                /** OID for the "INITIALS=" attribute, denoting a person's initials.*/
1180:                INITIALS_OID = intern(ObjectIdentifier
1181:                        .newInternal(INITIALS_DATA));
1182:
1183:                /** OID for the "GENERATION=" attribute, denoting Jr., II, etc.*/
1184:                GENERATIONQUALIFIER_OID = intern(ObjectIdentifier
1185:                        .newInternal(GENERATIONQUALIFIER_DATA));
1186:
1187:                /*
1188:                 * OIDs from other sources which show up in X.500 names we
1189:                 * expect to deal with often
1190:                 */
1191:                /** OID for "IP=" IP address attributes, used with SKIP. */
1192:                ipAddress_oid = intern(ObjectIdentifier
1193:                        .newInternal(ipAddress_data));
1194:
1195:                /*
1196:                 * Domain component OID from RFC 1274, RFC 2247, RFC 2459
1197:                 */
1198:
1199:                /*
1200:                 * OID for "DC=" domain component attributes, used with DNS names in DN
1201:                 * format
1202:                 */
1203:                DOMAIN_COMPONENT_OID = intern(ObjectIdentifier
1204:                        .newInternal(DOMAIN_COMPONENT_DATA));
1205:
1206:                /** OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798. */
1207:                userid_oid = intern(ObjectIdentifier.newInternal(userid_data));
1208:            }
1209:
1210:            /**
1211:             * Return constraint type:<ul>
1212:             *   <li>NAME_DIFF_TYPE = -1: input name is different type from this name
1213:             *	     (i.e. does not constrain)
1214:             *   <li>NAME_MATCH = 0: input name matches this name
1215:             *   <li>NAME_NARROWS = 1: input name narrows this name
1216:             *   <li>NAME_WIDENS = 2: input name widens this name
1217:             *   <li>NAME_SAME_TYPE = 3: input name does not match or narrow this name,
1218:             &       but is same type
1219:             * </ul>.  These results are used in checking NameConstraints during
1220:             * certification path verification.
1221:             *
1222:             * @param inputName to be checked for being constrained
1223:             * @returns constraint type above
1224:             * @throws UnsupportedOperationException if name is not exact match, but 
1225:             *         narrowing and widening are not supported for this name type.
1226:             */
1227:            public int constrains(GeneralNameInterface inputName)
1228:                    throws UnsupportedOperationException {
1229:                int constraintType;
1230:                if (inputName == null) {
1231:                    constraintType = NAME_DIFF_TYPE;
1232:                } else if (inputName.getType() != NAME_DIRECTORY) {
1233:                    constraintType = NAME_DIFF_TYPE;
1234:                } else { // type == NAME_DIRECTORY
1235:                    X500Name inputX500 = (X500Name) inputName;
1236:                    if (inputX500.equals(this )) {
1237:                        constraintType = NAME_MATCH;
1238:                    } else if (inputX500.names.length == 0) {
1239:                        constraintType = NAME_WIDENS;
1240:                    } else if (this .names.length == 0) {
1241:                        constraintType = NAME_NARROWS;
1242:                    } else if (inputX500.isWithinSubtree(this )) {
1243:                        constraintType = NAME_NARROWS;
1244:                    } else if (isWithinSubtree(inputX500)) {
1245:                        constraintType = NAME_WIDENS;
1246:                    } else {
1247:                        constraintType = NAME_SAME_TYPE;
1248:                    }
1249:                }
1250:                return constraintType;
1251:            }
1252:
1253:            /**
1254:             * Compares this name with another and determines if
1255:             * it is within the subtree of the other. Useful for
1256:             * checking against the name constraints extension.
1257:             *
1258:             * @return true iff this name is within the subtree of other.
1259:             */
1260:            private boolean isWithinSubtree(X500Name other) {
1261:                if (this  == other) {
1262:                    return true;
1263:                }
1264:                if (other == null) {
1265:                    return false;
1266:                }
1267:                if (other.names.length == 0) {
1268:                    return true;
1269:                }
1270:                if (this .names.length == 0) {
1271:                    return false;
1272:                }
1273:                if (names.length < other.names.length) {
1274:                    return false;
1275:                }
1276:                for (int i = 0; i < other.names.length; i++) {
1277:                    if (!names[i].equals(other.names[i])) {
1278:                        return false;
1279:                    }
1280:                }
1281:                return true;
1282:            }
1283:
1284:            /**
1285:             * Return subtree depth of this name for purposes of determining
1286:             * NameConstraints minimum and maximum bounds and for calculating
1287:             * path lengths in name subtrees.
1288:             *
1289:             * @returns distance of name from root
1290:             * @throws UnsupportedOperationException if not supported for this name type
1291:             */
1292:            public int subtreeDepth() throws UnsupportedOperationException {
1293:                return names.length;
1294:            }
1295:
1296:            /**
1297:             * Return lowest common ancestor of this name and other name
1298:             *
1299:             * @param other another X500Name
1300:             * @return X500Name of lowest common ancestor; null if none
1301:             */
1302:            public X500Name commonAncestor(X500Name other) {
1303:
1304:                if (other == null) {
1305:                    return null;
1306:                }
1307:                int otherLen = other.names.length;
1308:                int this Len = this .names.length;
1309:                if (this Len == 0 || otherLen == 0) {
1310:                    return null;
1311:                }
1312:                int minLen = (this Len < otherLen) ? this Len : otherLen;
1313:
1314:                //Compare names from highest RDN down the naming tree
1315:                //Note that these are stored in RDN[0]...
1316:                int i = 0;
1317:                for (; i < minLen; i++) {
1318:                    if (!names[i].equals(other.names[i])) {
1319:                        if (i == 0) {
1320:                            return null;
1321:                        } else {
1322:                            break;
1323:                        }
1324:                    }
1325:                }
1326:
1327:                //Copy matching RDNs into new RDN array
1328:                RDN[] ancestor = new RDN[i];
1329:                for (int j = 0; j < i; j++) {
1330:                    ancestor[j] = names[j];
1331:                }
1332:
1333:                X500Name commonAncestor = null;
1334:                try {
1335:                    commonAncestor = new X500Name(ancestor);
1336:                } catch (IOException ioe) {
1337:                    return null;
1338:                }
1339:                return commonAncestor;
1340:            }
1341:
1342:            /**
1343:             * Constructor object for use by asX500Principal().
1344:             */
1345:            private static final Constructor principalConstructor;
1346:
1347:            /**
1348:             * Field object for use by asX500Name().
1349:             */
1350:            private static final Field principalField;
1351:
1352:            /**
1353:             * Retrieve the Constructor and Field we need for reflective access
1354:             * and make them accessible.
1355:             */
1356:            static {
1357:                PrivilegedExceptionAction pa = new PrivilegedExceptionAction() {
1358:                    public Object run() throws Exception {
1359:                        Class pClass = X500Principal.class;
1360:                        Class[] args = new Class[] { X500Name.class };
1361:                        Constructor cons = pClass.getDeclaredConstructor(args);
1362:                        cons.setAccessible(true);
1363:                        Field field = pClass.getDeclaredField("thisX500Name");
1364:                        field.setAccessible(true);
1365:                        return new Object[] { cons, field };
1366:                    }
1367:                };
1368:                try {
1369:                    Object[] result = (Object[]) AccessController
1370:                            .doPrivileged(pa);
1371:                    principalConstructor = (Constructor) result[0];
1372:                    principalField = (Field) result[1];
1373:                } catch (Exception e) {
1374:                    throw (InternalError) new InternalError("Could not obtain "
1375:                            + "X500Principal access").initCause(e);
1376:                }
1377:            }
1378:
1379:            /**
1380:             * Get an X500Principal backed by this X500Name.
1381:             *
1382:             * Note that we are using privileged reflection to access the hidden 
1383:             * package private constructor in X500Principal.
1384:             */
1385:            public X500Principal asX500Principal() {
1386:                if (x500Principal == null) {
1387:                    try {
1388:                        Object[] args = new Object[] { this  };
1389:                        x500Principal = (X500Principal) principalConstructor
1390:                                .newInstance(args);
1391:                    } catch (Exception e) {
1392:                        throw new RuntimeException("Unexpected exception", e);
1393:                    }
1394:                }
1395:                return x500Principal;
1396:            }
1397:
1398:            /**
1399:             * Get the X500Name contained in the given X500Principal.
1400:             *
1401:             * Note that the X500Name is retrieved using reflection.
1402:             */
1403:            public static X500Name asX500Name(X500Principal p) {
1404:                try {
1405:                    X500Name name = (X500Name) principalField.get(p);
1406:                    name.x500Principal = p;
1407:                    return name;
1408:                } catch (Exception e) {
1409:                    throw new RuntimeException("Unexpected exception", e);
1410:                }
1411:            }
1412:
1413:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.