Source Code Cross Referenced for Config.java in  » 6.0-JDK-Modules-sun » security » sun » security » krb5 » 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 sun » security » sun.security.krb5 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Portions Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        /*
0027:         * @(#)Config.java	1.38 07/07/18
0028:         *
0029:         *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
0030:         *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
0031:         */
0032:        package sun.security.krb5;
0033:
0034:        import java.io.File;
0035:        import java.io.FileInputStream;
0036:        import java.util.Hashtable;
0037:        import java.util.Vector;
0038:        import java.util.ArrayList;
0039:        import java.io.BufferedReader;
0040:        import java.io.InputStreamReader;
0041:        import java.io.IOException;
0042:        import java.util.Enumeration;
0043:        import java.util.List;
0044:        import java.util.StringTokenizer;
0045:        import java.net.InetAddress;
0046:        import java.net.UnknownHostException;
0047:        import sun.security.krb5.internal.crypto.EType;
0048:        import sun.security.krb5.internal.ktab.*;
0049:        import sun.security.krb5.internal.Krb5;
0050:
0051:        /**
0052:         * This class maintains key-value pairs of Kerberos configurable constants
0053:         * from configuration file or from user specified system properties.
0054:         */
0055:
0056:        public class Config {
0057:
0058:            /*
0059:             * Only allow a single instance of Config.
0060:             */
0061:            private static Config singleton = null;
0062:
0063:            /* 
0064:             * Hashtable used to store configuration infomation.
0065:             */
0066:            private Hashtable<String, Object> stanzaTable;
0067:
0068:            private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
0069:
0070:            // these are used for hexdecimal calculation.
0071:            private static final int BASE16_0 = 1;
0072:            private static final int BASE16_1 = 16;
0073:            private static final int BASE16_2 = 16 * 16;
0074:            private static final int BASE16_3 = 16 * 16 * 16;
0075:            private String defaultRealm; // default kdc realm.
0076:
0077:            // used for native interface
0078:            private static native String getWindowsDirectory();
0079:
0080:            /**
0081:             * Gets an instance of Config class. One and only one instance (the
0082:             * singleton) is returned.
0083:             *
0084:             * @exception KrbException if error occurs when constructing a Config
0085:             * instance. Possible causes would be configuration file not
0086:             * found, either of java.security.krb5.realm or java.security.krb5.kdc
0087:             * not specified, error reading configuration file. 
0088:             */
0089:            public static synchronized Config getInstance() throws KrbException {
0090:                if (singleton == null) {
0091:                    singleton = new Config();
0092:                }
0093:                return singleton;
0094:            }
0095:
0096:            /**
0097:             * Refresh and reload the Configuration. This could involve,
0098:             * for example reading the Configuration file again or getting 
0099:             * the java.security.krb5.* system properties again.
0100:             *
0101:             * @exception KrbException if error occurs when constructing a Config
0102:             * instance. Possible causes would be configuration file not
0103:             * found, either of java.security.krb5.realm or java.security.krb5.kdc
0104:             * not specified, error reading configuration file. 
0105:             */
0106:
0107:            public static synchronized void refresh() throws KrbException {
0108:                singleton = new Config();
0109:                KeyTab.refresh();
0110:            }
0111:
0112:            /**
0113:             * Private constructor - can not be instantiated externally.
0114:             */
0115:            private Config() throws KrbException {
0116:                /*
0117:                 * If these two system properties are being specified by the user,
0118:                 * we ignore configuration file. If either one system property is
0119:                 * specified, we throw exception. If neither of them are specified,
0120:                 * we load the information from configuration file.
0121:                 */
0122:                String kdchost = java.security.AccessController
0123:                        .doPrivileged(new sun.security.action.GetPropertyAction(
0124:                                "java.security.krb5.kdc"));
0125:                defaultRealm = java.security.AccessController
0126:                        .doPrivileged(new sun.security.action.GetPropertyAction(
0127:                                "java.security.krb5.realm"));
0128:                if ((kdchost == null && defaultRealm != null)
0129:                        || (defaultRealm == null && kdchost != null)) {
0130:                    throw new KrbException(
0131:                            "System property java.security.krb5.kdc and "
0132:                                    + "java.security.krb5.realm both must be set or "
0133:                                    + "neither must be set.");
0134:                }
0135:                if (kdchost != null) {
0136:                    /*
0137:                     * If configuration information is only specified by
0138:                     * properties java.security.krb5.kdc and
0139:                     * java.security.krb5.realm, we put both in the hashtable
0140:                     * under [libdefaults].
0141:                     */
0142:                    Hashtable<String, String> kdcs = new Hashtable<String, String>();
0143:                    kdcs.put("default_realm", defaultRealm);
0144:                    // The user can specify a list of kdc hosts separated by ":"
0145:                    kdchost = kdchost.replace(':', ' ');
0146:                    kdcs.put("kdc", kdchost);
0147:                    stanzaTable = new Hashtable<String, Object>();
0148:                    stanzaTable.put("libdefaults", kdcs);
0149:                } else {
0150:                    // Read the Kerberos configuration file
0151:                    try {
0152:                        Vector<String> configFile;
0153:                        configFile = loadConfigFile();
0154:                        stanzaTable = parseStanzaTable(configFile);
0155:                    } catch (IOException ioe) {
0156:                        KrbException ke = new KrbException("Could not load "
0157:                                + "configuration file " + ioe.getMessage());
0158:                        ke.initCause(ioe);
0159:                        throw (ke);
0160:                    }
0161:                }
0162:            }
0163:
0164:            /**
0165:             * Gets the default int value for the specified name.
0166:             * @param name the name.
0167:             * @return the default Integer, null is returned if no such name and
0168:             * value are found in configuration file, or error occurs when parsing
0169:             * string to integer. 
0170:             */
0171:            public int getDefaultIntValue(String name) {
0172:                String result = null;
0173:                int value = Integer.MIN_VALUE;
0174:                result = getDefault(name);
0175:                if (result != null) {
0176:                    try {
0177:                        value = parseIntValue(result);
0178:                    } catch (NumberFormatException e) {
0179:                        if (DEBUG) {
0180:                            System.out.println("Exception in getting value of "
0181:                                    + name + " " + e.getMessage());
0182:                            System.out.println("Setting " + name
0183:                                    + " to minimum value");
0184:                        }
0185:                        value = Integer.MIN_VALUE;
0186:                    }
0187:                }
0188:                return value;
0189:            }
0190:
0191:            /**
0192:             * Gets the default int value for the specified name in the specified
0193:             * section. <br>This method is quicker by using section name as the
0194:             * search key. 
0195:             * @param name the name.
0196:             * @param sectio the name string of the section.
0197:             * @return the default Integer, null is returned if no such name and
0198:             * value are found in configuration file, or error occurs when parsing
0199:             * string to integer. 
0200:             */
0201:            public int getDefaultIntValue(String name, String section) {
0202:                String result = null;
0203:                int value = Integer.MIN_VALUE;
0204:                result = getDefault(name, section);
0205:                if (result != null) {
0206:                    try {
0207:                        value = parseIntValue(result);
0208:                    } catch (NumberFormatException e) {
0209:                        if (DEBUG) {
0210:                            System.out.println("Exception in getting value of "
0211:                                    + name + " in section " + section + " "
0212:                                    + e.getMessage());
0213:                            System.out.println("Setting " + name
0214:                                    + " to minimum value");
0215:                        }
0216:                        value = Integer.MIN_VALUE;
0217:                    }
0218:                }
0219:                return value;
0220:            }
0221:
0222:            /**
0223:             * Gets the default string value for the specified name.
0224:             * @param name the name.
0225:             * @return the default value, null is returned if it cannot be found.
0226:             */
0227:            public String getDefault(String name) {
0228:                if (stanzaTable == null) {
0229:                    return null;
0230:                } else {
0231:                    return getDefault(name, stanzaTable);
0232:                }
0233:            }
0234:
0235:            /**
0236:             * This method does the real job to recursively search through the
0237:             * stanzaTable. 
0238:             * @param k the key string.
0239:             * @param t stanzaTable or sub hashtable within it.
0240:             * @return the value found in config file, returns null if no value
0241:             * matched with the key is found. 
0242:             */
0243:            private String getDefault(String k, Hashtable t) {
0244:                String result = null;
0245:                String key;
0246:                if (stanzaTable != null) {
0247:                    for (Enumeration e = t.keys(); e.hasMoreElements();) {
0248:                        key = (String) e.nextElement();
0249:                        Object ob = t.get(key);
0250:                        if (ob instanceof  Hashtable) {
0251:                            result = getDefault(k, (Hashtable) ob);
0252:                            if (result != null) {
0253:                                return result;
0254:                            }
0255:                        } else if (key.equalsIgnoreCase(k)) {
0256:                            if (ob instanceof  String) {
0257:                                return (String) (t.get(key));
0258:                            } else if (ob instanceof  Vector) {
0259:                                result = "";
0260:                                int length = ((Vector) ob).size();
0261:                                for (int i = 0; i < length; i++) {
0262:                                    if (i == length - 1) {
0263:                                        result += (String) (((Vector) ob)
0264:                                                .elementAt(i));
0265:                                    } else {
0266:                                        result += (String) (((Vector) ob)
0267:                                                .elementAt(i))
0268:                                                + " ";
0269:                                    }
0270:                                }
0271:                                return result;
0272:                            }
0273:                        }
0274:                    }
0275:                }
0276:                return result;
0277:            }
0278:
0279:            /**
0280:             * Gets the default string value for the specified name in the
0281:             * specified section.
0282:             * <br>This method is quicker by using the section name as the search key. 
0283:             * @param name the name.
0284:             * @param section the name of the section. 
0285:             * @return the default value, null is returned if it cannot be found.
0286:             */
0287:            public String getDefault(String name, String section) {
0288:                String stanzaName;
0289:                String result = null;
0290:                Hashtable subTable;
0291:
0292:                /*
0293:                 * In the situation when kdc is specified by
0294:                 * java.security.krb5.kdc, we get the kdc from [libdefaults] in
0295:                 * hashtable.
0296:                 */
0297:                if (name.equalsIgnoreCase("kdc")
0298:                        && (!section.equalsIgnoreCase("libdefaults"))
0299:                        && (java.security.AccessController
0300:                                .doPrivileged(new sun.security.action.GetPropertyAction(
0301:                                        "java.security.krb5.kdc")) != null)) {
0302:                    result = getDefault("kdc", "libdefaults");
0303:                    return result;
0304:                }
0305:                if (stanzaTable != null) {
0306:                    for (Enumeration e = stanzaTable.keys(); e
0307:                            .hasMoreElements();) {
0308:                        stanzaName = (String) e.nextElement();
0309:                        subTable = (Hashtable) stanzaTable.get(stanzaName);
0310:                        if (stanzaName.equalsIgnoreCase(section)) {
0311:                            if (subTable.containsKey(name)) {
0312:                                return (String) (subTable.get(name));
0313:                            }
0314:                        } else if (subTable.containsKey(section)) {
0315:                            Object ob = subTable.get(section);
0316:                            if (ob instanceof  Hashtable) {
0317:                                Hashtable temp = (Hashtable) ob;
0318:                                if (temp.containsKey(name)) {
0319:                                    Object object = temp.get(name);
0320:                                    if (object instanceof  Vector) {
0321:                                        result = "";
0322:                                        int length = ((Vector) object).size();
0323:                                        for (int i = 0; i < length; i++) {
0324:                                            if (i == length - 1) {
0325:                                                result += (String) (((Vector) object)
0326:                                                        .elementAt(i));
0327:                                            } else {
0328:                                                result += (String) (((Vector) object)
0329:                                                        .elementAt(i))
0330:                                                        + " ";
0331:                                            }
0332:                                        }
0333:                                    } else {
0334:                                        result = (String) object;
0335:                                    }
0336:                                }
0337:                            }
0338:                        }
0339:                    }
0340:                }
0341:                return result;
0342:            }
0343:
0344:            /**
0345:             * Gets the default boolean value for the specified name.
0346:             * @param name the name.
0347:             * @return the default boolean value, false is returned if it cannot be
0348:             * found.
0349:             */
0350:            public boolean getDefaultBooleanValue(String name) {
0351:                String val = null;
0352:                if (stanzaTable == null) {
0353:                    val = null;
0354:                } else {
0355:                    val = getDefault(name, stanzaTable);
0356:                }
0357:                if (val != null && val.equalsIgnoreCase("true")) {
0358:                    return true;
0359:                } else {
0360:                    return false;
0361:                }
0362:            }
0363:
0364:            /**
0365:             * Gets the default boolean value for the specified name in the
0366:             * specified section.
0367:             * <br>This method is quicker by using the section name as the search key. 
0368:             * @param name the name.
0369:             * @param section the name of the section. 
0370:             * @return the default boolean value, false is returned if it cannot be
0371:             * found.
0372:             */
0373:            public boolean getDefaultBooleanValue(String name, String section) {
0374:                String val = getDefault(name, section);
0375:                if (val != null && val.equalsIgnoreCase("true")) {
0376:                    return true;
0377:                } else {
0378:                    return false;
0379:                }
0380:            }
0381:
0382:            /**
0383:             * Parses a string to an integer. The convertible strings include the
0384:             * string representations of positive integers, negative integers, and
0385:             * hex decimal integers.  Valid inputs are, e.g., -1234, +1234,
0386:             * 0x40000. 
0387:             * 
0388:             * @param input the String to be converted to an Integer.
0389:             * @return an numeric value represented by the string
0390:             * @exception NumberFormationException if the String does not contain a
0391:             * parsable integer. 
0392:             */
0393:            private int parseIntValue(String input)
0394:                    throws NumberFormatException {
0395:                int value = 0;
0396:                if (input.startsWith("+")) {
0397:                    String temp = input.substring(1);
0398:                    return Integer.parseInt(temp);
0399:                } else if (input.startsWith("0x")) {
0400:                    String temp = input.substring(2);
0401:                    char[] chars = temp.toCharArray();
0402:                    if (chars.length > 8) {
0403:                        throw new NumberFormatException();
0404:                    } else {
0405:                        for (int i = 0; i < chars.length; i++) {
0406:                            int index = chars.length - i - 1;
0407:                            switch (chars[i]) {
0408:                            case '0':
0409:                                value += 0;
0410:                                break;
0411:                            case '1':
0412:                                value += 1 * getBase(index);
0413:                                break;
0414:                            case '2':
0415:                                value += 2 * getBase(index);
0416:                                break;
0417:                            case '3':
0418:                                value += 3 * getBase(index);
0419:                                break;
0420:                            case '4':
0421:                                value += 4 * getBase(index);
0422:                                break;
0423:                            case '5':
0424:                                value += 5 * getBase(index);
0425:                                break;
0426:                            case '6':
0427:                                value += 6 * getBase(index);
0428:                                break;
0429:                            case '7':
0430:                                value += 7 * getBase(index);
0431:                                break;
0432:                            case '8':
0433:                                value += 8 * getBase(index);
0434:                                break;
0435:                            case '9':
0436:                                value += 9 * getBase(index);
0437:                                break;
0438:                            case 'a':
0439:                            case 'A':
0440:                                value += 10 * getBase(index);
0441:                                break;
0442:                            case 'b':
0443:                            case 'B':
0444:                                value += 11 * getBase(index);
0445:                                break;
0446:                            case 'c':
0447:                            case 'C':
0448:                                value += 12 * getBase(index);
0449:                                break;
0450:                            case 'd':
0451:                            case 'D':
0452:                                value += 13 * getBase(index);
0453:                                break;
0454:                            case 'e':
0455:                            case 'E':
0456:                                value += 14 * getBase(index);
0457:                                break;
0458:                            case 'f':
0459:                            case 'F':
0460:                                value += 15 * getBase(index);
0461:                                break;
0462:                            default:
0463:                                throw new NumberFormatException(
0464:                                        "Invalid numerical format");
0465:                            }
0466:                        }
0467:                    }
0468:                    if (value < 0) {
0469:                        throw new NumberFormatException("Data overflow.");
0470:                    }
0471:                } else {
0472:                    value = Integer.parseInt(input);
0473:                }
0474:                return value;
0475:            }
0476:
0477:            private int getBase(int i) {
0478:                int result = 16;
0479:                switch (i) {
0480:                case 0:
0481:                    result = BASE16_0;
0482:                    break;
0483:                case 1:
0484:                    result = BASE16_1;
0485:                    break;
0486:                case 2:
0487:                    result = BASE16_2;
0488:                    break;
0489:                case 3:
0490:                    result = BASE16_3;
0491:                    break;
0492:                default:
0493:                    for (int j = 1; j < i; j++) {
0494:                        result *= 16;
0495:                    }
0496:                }
0497:                return result;
0498:            }
0499:
0500:            /**
0501:             * Finds the matching value in the hashtable.
0502:             */
0503:            private String find(String key1, String key2) {
0504:                String result;
0505:                if ((stanzaTable != null)
0506:                        && ((result = (String) (((Hashtable) (stanzaTable
0507:                                .get(key1))).get(key2))) != null)) {
0508:                    return result;
0509:                } else {
0510:                    return "";
0511:                }
0512:            }
0513:
0514:            /**
0515:             * Reads name/value pairs to the memory from the configuration
0516:             * file. The default location of the configuration file is in java home
0517:             * directory. 
0518:             *
0519:             * Configuration file contains information about the default realm,
0520:             * ticket parameters, location of the KDC and the admin server for
0521:             * known realms, etc. The file is divided into sections. Each section
0522:             * contains one or more name/value pairs with one pair per line. A
0523:             * typical file would be: 
0524:             * [libdefaults]
0525:             *		default_realm = EXAMPLE.COM
0526:             *		default_tgs_enctypes = des-cbc-md5
0527:             * 		default_tkt_enctypes = des-cbc-md5
0528:             * [realms]
0529:             *		EXAMPLE.COM = {
0530:             *			kdc = kerberos.example.com
0531:             *			kdc = kerberos-1.example.com
0532:             *			admin_server = kerberos.example.com
0533:             *			}
0534:             * 		SAMPLE_COM = {
0535:             *			kdc = orange.sample.com
0536:             *			admin_server = orange.sample.com
0537:             *			}
0538:             * [domain_realm]
0539:             *		blue.sample.com = TEST.SAMPLE.COM
0540:             *		.backup.com	= EXAMPLE.COM
0541:             */
0542:            private Vector<String> loadConfigFile() throws IOException {
0543:                try {
0544:                    final String fileName = getFileName();
0545:                    if (!fileName.equals("")) {
0546:                        BufferedReader br = new BufferedReader(
0547:                                new InputStreamReader(
0548:                                        java.security.AccessController
0549:                                                .doPrivileged(new java.security.PrivilegedExceptionAction<FileInputStream>() {
0550:                                                    public FileInputStream run()
0551:                                                            throws IOException {
0552:                                                        return new FileInputStream(
0553:                                                                fileName);
0554:                                                    }
0555:                                                })));
0556:                        String Line;
0557:                        Vector<String> v = new Vector<String>();
0558:                        String previous = null;
0559:                        while ((Line = br.readLine()) != null) {
0560:                            // ignore comments and blank line in the configuration file.
0561:                            // Comments start with #.
0562:                            if (!(Line.startsWith("#") || Line.trim().isEmpty())) {
0563:                                String current = Line.trim();
0564:                                // In practice, a subsection might look like:
0565:                                //	EXAMPLE.COM =
0566:                                // 	{
0567:                                //		kdc = kerberos.example.com
0568:                                //		...
0569:                                //	}
0570:                                // Before parsed into stanza table, it needs to be
0571:                                // converted into formal style:
0572:                                //	EXAMPLE.COM = {
0573:                                //		kdc = kerberos.example.com
0574:                                //		...
0575:                                //	}
0576:                                //
0577:                                // So, if a line is "{", adhere to the previous line.
0578:                                if (current.equals("{")) {
0579:                                    if (previous == null) {
0580:                                        throw new IOException(
0581:                                                "Config file should not start with \"{\"");
0582:                                    }
0583:                                    previous += " " + current;
0584:                                } else {
0585:                                    if (previous != null) {
0586:                                        v.addElement(previous);
0587:                                    }
0588:                                    previous = current;
0589:                                }
0590:                            }
0591:                        }
0592:                        if (previous != null) {
0593:                            v.addElement(previous);
0594:                        }
0595:
0596:                        br.close();
0597:                        return v;
0598:                    }
0599:                    return null;
0600:                } catch (java.security.PrivilegedActionException pe) {
0601:                    throw (IOException) pe.getException();
0602:                }
0603:            }
0604:
0605:            /**
0606:             * Parses stanza names and values from configuration file to
0607:             * stanzaTable (Hashtable). Hashtable key would be stanza names,
0608:             * (libdefaults, realms, domain_realms, etc), and the hashtable value
0609:             * would be another hashtable which contains the key-value pairs under
0610:             * a stanza name.
0611:             */
0612:            private Hashtable<String, Object> parseStanzaTable(Vector<String> v)
0613:                    throws KrbException {
0614:                if (v == null) {
0615:                    throw new KrbException("I/O error while reading"
0616:                            + " configuration file.");
0617:                }
0618:                Hashtable<String, Object> table = new Hashtable<String, Object>();
0619:                for (int i = 0; i < v.size(); i++) {
0620:                    String line = v.elementAt(i).trim();
0621:                    if (line.equalsIgnoreCase("[realms]")) {
0622:                        for (int count = i + 1; count < v.size() + 1; count++) {
0623:                            // find the next stanza name
0624:                            if ((count == v.size())
0625:                                    || (v.elementAt(count).startsWith("["))) {
0626:                                Hashtable<String, Hashtable<String, Vector<String>>> temp = new Hashtable<String, Hashtable<String, Vector<String>>>();
0627:                                temp = parseRealmField(v, i + 1, count);
0628:                                table.put("realms", temp);
0629:                                i = count - 1;
0630:                                break;
0631:                            }
0632:                        }
0633:                    } else if (line.equalsIgnoreCase("[capaths]")) {
0634:                        for (int count = i + 1; count < v.size() + 1; count++) {
0635:                            // find the next stanza name
0636:                            if ((count == v.size())
0637:                                    || (v.elementAt(count).startsWith("["))) {
0638:                                Hashtable<String, Hashtable<String, Vector<String>>> temp = new Hashtable<String, Hashtable<String, Vector<String>>>();
0639:                                temp = parseRealmField(v, i + 1, count);
0640:                                table.put("capaths", temp);
0641:                                i = count - 1;
0642:                                break;
0643:                            }
0644:                        }
0645:                    } else if (line.startsWith("[") && line.endsWith("]")) {
0646:                        String key = line.substring(1, line.length() - 1);
0647:                        for (int count = i + 1; count < v.size() + 1; count++) {
0648:                            // find the next stanza name
0649:                            if ((count == v.size())
0650:                                    || (v.elementAt(count).startsWith("["))) {
0651:                                Hashtable<String, String> temp = parseField(v,
0652:                                        i + 1, count);
0653:                                table.put(key, temp);
0654:                                i = count - 1;
0655:                                break;
0656:                            }
0657:                        }
0658:                    }
0659:                }
0660:                return table;
0661:            }
0662:
0663:            /**
0664:             * Gets the default configuration file name. The file will be searched
0665:             * in a list of possible loations in the following order: 
0666:             * 1. the location and file name defined by system property
0667:             * "java.security.krb5.conf", 
0668:             * 2. at Java home lib\security directory with "krb5.conf" name, 
0669:             * 3. "krb5.ini" at Java home,
0670:             * 4. at windows directory with the name of "krb5.ini" for Windows,
0671:             * /etc/krb5/krb5.conf for Solaris, /etc/krb5.conf for Linux.
0672:             */
0673:            private String getFileName() {
0674:                String name = java.security.AccessController
0675:                        .doPrivileged(new sun.security.action.GetPropertyAction(
0676:                                "java.security.krb5.conf"));
0677:                if (name != null) {
0678:                    boolean temp = java.security.AccessController
0679:                            .doPrivileged(new FileExistsAction(name));
0680:                    if (temp)
0681:                        return name;
0682:                } else {
0683:                    name = java.security.AccessController
0684:                            .doPrivileged(new sun.security.action.GetPropertyAction(
0685:                                    "java.home"))
0686:                            + File.separator
0687:                            + "lib"
0688:                            + File.separator
0689:                            + "security" + File.separator + "krb5.conf";
0690:                    boolean temp = java.security.AccessController
0691:                            .doPrivileged(new FileExistsAction(name));
0692:                    if (temp) {
0693:                        return name;
0694:                    } else {
0695:                        String osname = java.security.AccessController
0696:                                .doPrivileged(new sun.security.action.GetPropertyAction(
0697:                                        "os.name"));
0698:                        if (osname.startsWith("Windows")) {
0699:                            try {
0700:                                Credentials.ensureLoaded();
0701:                            } catch (Exception e) {
0702:                                // ignore exceptions
0703:                            }
0704:                            if (Credentials.alreadyLoaded) {
0705:                                if ((name = getWindowsDirectory()) == null) {
0706:                                    name = "c:\\winnt\\krb5.ini";
0707:                                } else if (name.endsWith("\\")) {
0708:                                    name += "krb5.ini";
0709:                                } else {
0710:                                    name += "\\krb5.ini";
0711:                                }
0712:                            } else {
0713:                                name = "c:\\winnt\\krb5.ini";
0714:                            }
0715:                        } else if (osname.startsWith("SunOS")) {
0716:                            name = "/etc/krb5/krb5.conf";
0717:                        } else if (osname.startsWith("Linux")) {
0718:                            name = "/etc/krb5.conf";
0719:                        }
0720:                    }
0721:                }
0722:                if (DEBUG) {
0723:                    System.out.println("Config name: " + name);
0724:                }
0725:                return name;
0726:            }
0727:
0728:            /**
0729:             * Parses key-value pairs under a stanza name.	 
0730:             */
0731:            private Hashtable<String, String> parseField(Vector<String> v,
0732:                    int start, int end) {
0733:                Hashtable<String, String> table = new Hashtable<String, String>();
0734:                String line;
0735:                for (int i = start; i < end; i++) {
0736:                    line = v.elementAt(i);
0737:                    for (int j = 0; j < line.length(); j++) {
0738:                        if (line.charAt(j) == '=') {
0739:                            String key = (line.substring(0, j)).trim();
0740:                            String value = (line.substring(j + 1)).trim();
0741:                            table.put(key, value);
0742:                            break;
0743:                        }
0744:                    }
0745:                }
0746:                return table;
0747:            }
0748:
0749:            /**
0750:             * Parses key-value pairs under [realms].  The key would be the realm
0751:             * name, the value would be another hashtable which contains
0752:             * information for the realm given within a pair of braces.
0753:             */
0754:            private Hashtable<String, Hashtable<String, Vector<String>>> parseRealmField(
0755:                    Vector<String> v, int start, int end) {
0756:                Hashtable<String, Hashtable<String, Vector<String>>> table = new Hashtable<String, Hashtable<String, Vector<String>>>();
0757:                String line;
0758:                for (int i = start; i < end; i++) {
0759:                    line = v.elementAt(i).trim();
0760:                    if (line.endsWith("{")) {
0761:                        String key = "";
0762:                        for (int j = 0; j < line.length(); j++) {
0763:                            if (line.charAt(j) == '=') {
0764:                                key = line.substring(0, j).trim();
0765:                                // get the key
0766:                                break;
0767:                            }
0768:                        }
0769:                        for (int k = i + 1; k < end; k++) {
0770:                            boolean found = false;
0771:                            line = v.elementAt(k).trim();
0772:                            for (int l = 0; l < line.length(); l++) {
0773:                                if (line.charAt(l) == '}') {
0774:                                    found = true;
0775:                                    break;
0776:                                }
0777:                            }
0778:                            if (found == true) {
0779:                                Hashtable<String, Vector<String>> temp = parseRealmFieldEx(
0780:                                        v, i + 1, k);
0781:                                table.put(key, temp);
0782:                                i = k;
0783:                                found = false;
0784:                                break;
0785:                            }
0786:
0787:                        }
0788:                    }
0789:                }
0790:                return table;
0791:            }
0792:
0793:            /**
0794:             * Parses key-value pairs within each braces under [realms].
0795:             */
0796:            private Hashtable<String, Vector<String>> parseRealmFieldEx(
0797:                    Vector<String> v, int start, int end) {
0798:                Hashtable<String, Vector<String>> table = new Hashtable<String, Vector<String>>();
0799:                Vector<String> keyVector = new Vector<String>();
0800:                Vector<String> nameVector = new Vector<String>();
0801:                String line = "";
0802:                String key;
0803:                for (int i = start; i < end; i++) {
0804:                    line = v.elementAt(i);
0805:                    for (int j = 0; j < line.length(); j++) {
0806:                        if (line.charAt(j) == '=') {
0807:                            int index;
0808:                            key = line.substring(0, j - 1).trim();
0809:                            if (!exists(key, keyVector)) {
0810:                                keyVector.addElement(key);
0811:                                nameVector = new Vector<String>();
0812:                            } else {
0813:                                nameVector = table.get(key);
0814:                            }
0815:                            nameVector.addElement((line.substring(j + 1))
0816:                                    .trim());
0817:                            table.put(key, nameVector);
0818:                            break;
0819:                        }
0820:                    }
0821:                }
0822:                return table;
0823:            }
0824:
0825:            /**
0826:             * Compares the key with the known keys to see if it exists.
0827:             */
0828:            private boolean exists(String key, Vector v) {
0829:                boolean exists = false;
0830:                for (int i = 0; i < v.size(); i++) {
0831:                    if (((String) (v.elementAt(i))).equals(key)) {
0832:                        exists = true;
0833:                    }
0834:                }
0835:                return exists;
0836:            }
0837:
0838:            /**
0839:             * For testing purpose. This method lists all information being parsed from
0840:             * the configuration file to the hashtable.
0841:             */
0842:            public void listTable() {
0843:                listTable(stanzaTable);
0844:            }
0845:
0846:            private void listTable(Hashtable table) {
0847:                Vector v = new Vector();
0848:                String key;
0849:                if (stanzaTable != null) {
0850:                    for (Enumeration e = table.keys(); e.hasMoreElements();) {
0851:                        key = (String) e.nextElement();
0852:                        Object object = table.get(key);
0853:                        if (table == stanzaTable) {
0854:                            System.out.println("[" + key + "]");
0855:                        }
0856:                        if (object instanceof  Hashtable) {
0857:                            if (table != stanzaTable)
0858:                                System.out.println("\t" + key + " = {");
0859:                            listTable((Hashtable) object);
0860:                            if (table != stanzaTable)
0861:                                System.out.println("\t}");
0862:
0863:                        } else if (object instanceof  String) {
0864:                            System.out.println("\t" + key + " = "
0865:                                    + (String) table.get(key));
0866:                        } else if (object instanceof  Vector) {
0867:                            v = (Vector) object;
0868:                            for (int i = 0; i < v.size(); i++) {
0869:                                System.out.println("\t" + key + " = "
0870:                                        + (String) v.elementAt(i));
0871:                            }
0872:                        }
0873:                    }
0874:                } else {
0875:                    System.out.println("Configuration file not found.");
0876:                }
0877:            }
0878:
0879:            /**
0880:             * Returns the default encryption types.
0881:             * 
0882:             */
0883:            public int[] defaultEtype(String enctypes) {
0884:                String default_enctypes;
0885:                default_enctypes = getDefault(enctypes, "libdefaults");
0886:                String delim = " ";
0887:                StringTokenizer st;
0888:                int[] etype;
0889:                if (default_enctypes == null) {
0890:                    if (DEBUG) {
0891:                        System.out.println("Using builtin default etypes for "
0892:                                + enctypes);
0893:                    }
0894:                    etype = EType.getBuiltInDefaults();
0895:                } else {
0896:                    for (int j = 0; j < default_enctypes.length(); j++) {
0897:                        if (default_enctypes.substring(j, j + 1).equals(",")) {
0898:                            // only two delimiters are allowed to use 
0899:                            // according to Kerberos DCE doc.
0900:                            delim = ",";
0901:                            break;
0902:                        }
0903:                    }
0904:                    st = new StringTokenizer(default_enctypes, delim);
0905:                    int len = st.countTokens();
0906:                    ArrayList<Integer> ls = new ArrayList<Integer>(len);
0907:                    int type;
0908:                    for (int i = 0; i < len; i++) {
0909:                        type = getType(st.nextToken());
0910:                        if ((type != -1) && (EType.isSupported(type))) {
0911:                            ls.add(type);
0912:                        }
0913:                    }
0914:                    if (ls.size() == 0) {
0915:                        if (DEBUG) {
0916:                            System.out
0917:                                    .println("no supported default etypes for "
0918:                                            + enctypes);
0919:                        }
0920:                        return null;
0921:                    } else {
0922:                        etype = new int[ls.size()];
0923:                        for (int i = 0; i < etype.length; i++) {
0924:                            etype[i] = ls.get(i);
0925:                        }
0926:                    }
0927:                }
0928:
0929:                if (DEBUG) {
0930:                    System.out.print("default etypes for " + enctypes + ":");
0931:                    for (int i = 0; i < etype.length; i++) {
0932:                        System.out.print(" " + etype[i]);
0933:                    }
0934:                    System.out.println(".");
0935:                }
0936:                return etype;
0937:            }
0938:
0939:            /**
0940:             * Get the etype and checksum value for the specified encryption and
0941:             * checksum type.
0942:             * 
0943:             */
0944:            /*
0945:             * This method converts the string representation of encryption type and
0946:             * checksum type to int value that can be later used by EType and
0947:             * Checksum classes.
0948:             */
0949:            public int getType(String input) {
0950:                int result = -1;
0951:                if (input == null) {
0952:                    return result;
0953:                }
0954:                if (input.startsWith("d") || (input.startsWith("D"))) {
0955:                    if (input.equalsIgnoreCase("des-cbc-crc")) {
0956:                        result = EncryptedData.ETYPE_DES_CBC_CRC;
0957:                    } else if (input.equalsIgnoreCase("des-cbc-md5")) {
0958:                        result = EncryptedData.ETYPE_DES_CBC_MD5;
0959:                    } else if (input.equalsIgnoreCase("des-mac")) {
0960:                        result = Checksum.CKSUMTYPE_DES_MAC;
0961:                    } else if (input.equalsIgnoreCase("des-mac-k")) {
0962:                        result = Checksum.CKSUMTYPE_DES_MAC_K;
0963:                    } else if (input.equalsIgnoreCase("des-cbc-md4")) {
0964:                        result = EncryptedData.ETYPE_DES_CBC_MD4;
0965:                    } else if (input.equalsIgnoreCase("des3-cbc-sha1")
0966:                            || input.equalsIgnoreCase("des3-hmac-sha1")
0967:                            || input.equalsIgnoreCase("des3-cbc-sha1-kd")
0968:                            || input.equalsIgnoreCase("des3-cbc-hmac-sha1-kd")) {
0969:                        result = EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD;
0970:                    }
0971:                } else if (input.startsWith("a") || (input.startsWith("A"))) {
0972:                    // AES
0973:                    if (input.equalsIgnoreCase("aes128-cts")
0974:                            || input
0975:                                    .equalsIgnoreCase("aes128-cts-hmac-sha1-96")) {
0976:                        result = EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96;
0977:                    } else if (input.equalsIgnoreCase("aes256-cts")
0978:                            || input
0979:                                    .equalsIgnoreCase("aes256-cts-hmac-sha1-96")) {
0980:                        result = EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96;
0981:                        // ARCFOUR-HMAC
0982:                    } else if (input.equalsIgnoreCase("arcfour-hmac")
0983:                            || input.equalsIgnoreCase("arcfour-hmac-md5")) {
0984:                        result = EncryptedData.ETYPE_ARCFOUR_HMAC;
0985:                    }
0986:                    // RC4-HMAC
0987:                } else if (input.equalsIgnoreCase("rc4-hmac")) {
0988:                    result = EncryptedData.ETYPE_ARCFOUR_HMAC;
0989:                } else if (input.equalsIgnoreCase("CRC32")) {
0990:                    result = Checksum.CKSUMTYPE_CRC32;
0991:                } else if (input.startsWith("r") || (input.startsWith("R"))) {
0992:                    if (input.equalsIgnoreCase("rsa-md5")) {
0993:                        result = Checksum.CKSUMTYPE_RSA_MD5;
0994:                    } else if (input.equalsIgnoreCase("rsa-md5-des")) {
0995:                        result = Checksum.CKSUMTYPE_RSA_MD5_DES;
0996:                    }
0997:                } else if (input.equalsIgnoreCase("hmac-sha1-des3-kd")) {
0998:                    result = Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD;
0999:                } else if (input.equalsIgnoreCase("hmac-sha1-96-aes128")) {
1000:                    result = Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128;
1001:                } else if (input.equalsIgnoreCase("hmac-sha1-96-aes256")) {
1002:                    result = Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256;
1003:                } else if (input.equalsIgnoreCase("hmac-md5-rc4")
1004:                        || input.equalsIgnoreCase("hmac-md5-arcfour")
1005:                        || input.equalsIgnoreCase("hmac-md5-enc")) {
1006:                    result = Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR;
1007:                } else if (input.equalsIgnoreCase("NULL")) {
1008:                    result = EncryptedData.ETYPE_NULL;
1009:                }
1010:
1011:                return result;
1012:            }
1013:
1014:            /**
1015:             * Resets the default kdc realm.
1016:             * We do not need to synchronize these methods since assignments are atomic
1017:             */
1018:            public void resetDefaultRealm(String realm) {
1019:                defaultRealm = realm;
1020:                if (DEBUG) {
1021:                    System.out.println(">>> Config reset default kdc "
1022:                            + defaultRealm);
1023:                }
1024:
1025:            }
1026:
1027:            /**
1028:             * Check to use addresses in tickets
1029:             * use addresses if "no_addresses" or "noaddresses" is set to false
1030:             */
1031:            public boolean useAddresses() {
1032:                boolean useAddr = false;
1033:                // use addresses if "no_addresses" is set to false
1034:                String value = getDefault("no_addresses", "libdefaults");
1035:                useAddr = (value != null && value.equalsIgnoreCase("false"));
1036:                if (useAddr == false) {
1037:                    // use addresses if "noaddresses" is set to false
1038:                    value = getDefault("noaddresses", "libdefaults");
1039:                    useAddr = (value != null && value.equalsIgnoreCase("false"));
1040:                }
1041:                return useAddr;
1042:            }
1043:
1044:            /**
1045:             * Check if need to use DNS to locate Kerberos services
1046:             */
1047:            public boolean useDNS(String name) {
1048:                boolean value = getDefaultBooleanValue(name, "libdefaults");
1049:                if (value == false) {
1050:                    value = getDefaultBooleanValue("dns_fallback",
1051:                            "libdefaults");
1052:                }
1053:                return value;
1054:            }
1055:
1056:            /**
1057:             * Check if need to use DNS to locate the KDC
1058:             */
1059:            public boolean useDNS_KDC() {
1060:                return useDNS("dns_lookup_kdc");
1061:            }
1062:
1063:            /*
1064:             * Check if need to use DNS to locate the Realm
1065:             */
1066:            public boolean useDNS_Realm() {
1067:                return useDNS("dns_lookup_realm");
1068:            }
1069:
1070:            /**
1071:             * Gets default realm.
1072:             */
1073:            public String getDefaultRealm() throws KrbException {
1074:                String realm = getDefault("default_realm", "libdefaults");
1075:                if ((realm == null) && useDNS_Realm()) {
1076:                    // use DNS to locate Kerberos realm
1077:                    realm = getRealmFromDNS();
1078:                }
1079:                return realm;
1080:            }
1081:
1082:            /**
1083:             * Returns a list of KDC's with each KDC separated by a space
1084:             *
1085:             * @param realm the realm for which the master KDC is desired
1086:             * @return the list of KDCs
1087:             */
1088:            public String getKDCList(String realm) throws KrbException {
1089:                if (realm == null) {
1090:                    realm = getDefaultRealm();
1091:                }
1092:                String kdcs = getDefault("kdc", realm);
1093:                if ((kdcs == null) && useDNS_KDC()) {
1094:                    // use DNS to locate KDC
1095:                    kdcs = getKDCFromDNS(realm);
1096:                }
1097:                return kdcs;
1098:            }
1099:
1100:            /**
1101:             * Locate Kerberos realm using DNS
1102:             *
1103:             * @return the Kerberos realm
1104:             */
1105:            private String getRealmFromDNS() throws KrbException {
1106:                // use DNS to locate Kerberos realm
1107:                String realm = null;
1108:                String hostName = null;
1109:                try {
1110:                    hostName = InetAddress.getLocalHost().getHostName();
1111:                } catch (UnknownHostException e) {
1112:                    KrbException ke = new KrbException(Krb5.KRB_ERR_GENERIC,
1113:                            "Unable to locate Kerberos realm: "
1114:                                    + e.getMessage());
1115:                    ke.initCause(e);
1116:                    throw (ke);
1117:                }
1118:                // get the domain realm mapping from the configuration
1119:                String mapRealm = PrincipalName.mapHostToRealm(hostName);
1120:                String[] records = null;
1121:                String newRealm = mapRealm;
1122:                while ((records == null) && (newRealm != null)) {
1123:                    // locate DNS TXT record
1124:                    records = KrbServiceLocator.getKerberosService(newRealm);
1125:                    newRealm = Realm.parseRealmComponent(newRealm);
1126:                    // if no DNS TXT records found, try again using sub-realm
1127:                }
1128:                if (records == null) {
1129:                    // no DNS TXT records
1130:                    throw new KrbException(Krb5.KRB_ERR_GENERIC,
1131:                            "Unable to locate Kerberos realm");
1132:                }
1133:                boolean found = false;
1134:                for (int i = 0; i < records.length; i++) {
1135:                    if (records[i].equals(mapRealm)) {
1136:                        found = true;
1137:                        realm = records[i];
1138:                    }
1139:                }
1140:                if (found == false) {
1141:                    throw new KrbException(Krb5.KRB_ERR_GENERIC,
1142:                            "Unable to locate Kerberos realm");
1143:                }
1144:                return realm;
1145:            }
1146:
1147:            /**
1148:             * Locate KDC using DNS
1149:             *
1150:             * @param realm the realm for which the master KDC is desired
1151:             * @return the KDC
1152:             */
1153:            private String getKDCFromDNS(String realm) throws KrbException {
1154:                // use DNS to locate KDC
1155:                String kdcs = null;
1156:                String[] srvs = null;
1157:                // locate DNS SRV record using UDP
1158:                srvs = KrbServiceLocator.getKerberosService(realm, "_udp.");
1159:                if (srvs == null) {
1160:                    // locate DNS SRV record using TCP
1161:                    srvs = KrbServiceLocator.getKerberosService(realm, "_tcp.");
1162:                }
1163:                if (srvs == null) {
1164:                    // no DNS SRV records
1165:                    throw new KrbException(Krb5.KRB_ERR_GENERIC,
1166:                            "Unable to locate KDC for realm " + realm);
1167:                }
1168:                for (int i = 0; i < srvs.length; i++) {
1169:                    String value = srvs[i];
1170:                    for (int j = 0; j < srvs[i].length(); j++) {
1171:                        // filter the KDC name
1172:                        if (value.charAt(j) == ':') {
1173:                            kdcs = (value.substring(0, j)).trim();
1174:                        }
1175:                    }
1176:                }
1177:                return kdcs;
1178:            }
1179:
1180:            static class FileExistsAction implements 
1181:                    java.security.PrivilegedAction<Boolean> {
1182:
1183:                private String fileName;
1184:
1185:                public FileExistsAction(String fileName) {
1186:                    this .fileName = fileName;
1187:                }
1188:
1189:                public Boolean run() {
1190:                    return new File(fileName).exists();
1191:                }
1192:            }
1193:
1194:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.