KDC.java revision 2418
2418N/A * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 678N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 678N/A * This code is free software; you can redistribute it and/or modify it 678N/A * under the terms of the GNU General Public License version 2 only, as 678N/A * published by the Free Software Foundation. 678N/A * This code is distributed in the hope that it will be useful, but WITHOUT 678N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 678N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 678N/A * version 2 for more details (a copy is included in the LICENSE file that 678N/A * accompanied this code). 678N/A * You should have received a copy of the GNU General Public License version 678N/A * 2 along with this work; if not, write to the Free Software Foundation, 678N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 678N/A * <li> Supports TCP and UDP 678N/A * <li> Supports AS-REQ and TGS-REQ 678N/A * <li> Principal db and other settings hard coded in application 678N/A * <li> Options, say, request preauth or not 678N/A * singleton and initialized according to Kerberos settings (krb5.conf and 678N/A * java.security.krb5.* system properties). This means once it's initialized 678N/A * it will not automatically notice any changes to these settings (or file 678N/A * changes of krb5.conf). The KDC class normally does not touch these 678N/A * settings (except for the <code>writeKtab()</code> method). However, to make 678N/A * sure nothing ever goes wrong, if you want to make any changes to these 678N/A * settings after calling a KDC method, call <code>Config.refresh()</code> to 678N/A * make sure your changes are reflected in the <code>Config</code> object. 1941N/A * System properties recognized: 678N/A * <li> Generates krb5.conf to be used on another machine, currently the kdc is 678N/A * <li> More options to KDC, say, error output, say, response nonce != 678N/A * Note: This program uses internal krb5 classes (including reflection to 678N/A * access private fields and methods). 678N/A * 1. Init and start the KDC: 678N/A * KDC kdc = KDC.create("REALM.NAME", port, isDaemon); 678N/A * KDC kdc = KDC.create("REALM.NAME"); 678N/A * Here, <code>port</code> is the UDP and TCP port number the KDC server 678N/A * listens on. If zero, a random port is chosen, which you can use getPort() 678N/A * later to retrieve the value. 678N/A * If <code>isDaemon</code> is true, the KDC worker threads will be daemons. 678N/A * The shortcut <code>KDC.create("REALM.NAME")</code> has port=0 and 678N/A * isDaemon=false, and is commonly used in an embedded KDC. 678N/A * kdc.addPrincipal(String principal_name, char[] password); 678N/A * kdc.addPrincipalRandKey(String principal_name); 678N/A * generates a random key. To expose this key, call <code>writeKtab()</code> to 678N/A * save the keys into a keytab file. 678N/A * Note that you can safely add a principal at any time after the KDC is 678N/A * started and before a user requests info on this principal. 678N/A * 3. Other public methods: 678N/A * <li> <code>getPort</code>: Returns the port number the KDC uses 678N/A * <li> <code>getRealm</code>: Returns the realm name 678N/A * <li> <code>writeKtab</code>: Writes all principals' keys into a keytab file 678N/A * <li> <code>saveConfig</code>: Saves a krb5.conf file to access this KDC 678N/A * <li> <code>setOption</code>: Sets various options 678N/A * Read the javadoc for details. Lazy developer can use <code>OneKDC</code> 678N/A // The random generator to generate random keys (including session keys) 1300N/A // Principal db. principal -> pass 678N/A * Option names, to be expanded forever. 678N/A * Whether pre-authentication is required. Default Boolean.TRUE 678N/A * A standalone KDC server. 678N/A * Creates and starts a KDC running as a daemon on a random port. 678N/A * @param realm the realm name 678N/A * @return the running KDC instance 678N/A * @throws java.io.IOException for any socket creation error 678N/A * Creates and starts a KDC server. 678N/A * @param realm the realm name 678N/A * @param port the TCP and UDP port to listen to. A random port will to 678N/A * @param asDaemon if true, KDC threads will be daemons. Otherwise, not. 678N/A * @return the running KDC instance 678N/A * @throws java.io.IOException for any socket creation error 678N/A * @param key the option name 1266N/A * Write all principals' keys from multiple KDCsinto one keytab file. 1266N/A * Note that the keys for the krbtgt principals will not be written. 678N/A * Attention: This method references krb5.conf settings. If you need to 678N/A * setup krb5.conf later, please call <code>Config.refresh()</code> after 678N/A * the new setting. For example: 678N/A * <li> (Fatal) Generating keys: EncryptionKey.acquireSecretKeys 678N/A * <li> (Has workaround) Creating PrincipalName 678N/A * @param tab The keytab filename to write to. 678N/A * @throws java.io.IOException for any file output error 678N/A * @throws sun.security.krb5.KrbException for any realm and/or principal 1266N/A * Write a ktab for this KDC. 678N/A * Adds a new principal to this realm with a given password. 678N/A * @param user the principal's name. For a service principal, use the 678N/A * @param pass the password for the principal 678N/A * Adds a new principal to this realm with a random password 678N/A * @param user the principal's name. For a service principal, use the 678N/A * Returns the name of this realm 678N/A * @return the name of this realm 678N/A * Writes a krb5.conf for one or more KDC that includes KDC locations for 678N/A * each realm and the default realm name. You can also add extra strings 678N/A * into the file. The method should be called like: 678N/A * Here you can provide one or more kdc# and zero or more line# arguments. 678N/A * The line# will be put after [libdefaults] and before [realms]. Therefore 678N/A * you can append new lines into [libdefaults] and/or create your new 678N/A * stanzas as well. Note that a newline character will be appended to 678N/A * default_realm = REALM.NAME 678N/A * ".kdc1.com = KDC1.NAME"); 678N/A * default_realm = KDC1.NAME 678N/A * .kdc1.com = KDC1.NAME 678N/A * @param file the name of the file to write into 678N/A * @param kdc the first (and default) KDC 678N/A * @param more more KDCs or extra lines (in their appearing order) to 678N/A * insert into the krb5.conf file. This method reads each argument's type 678N/A * to determine what it's for. This argument can be empty. 678N/A * @throws java.io.IOException for any file output error 678N/A * Returns the service port of the KDC server. 678N/A * @return the KDC service port 678N/A // Private helper methods 678N/A * Private constructor, cannot be called outside. 678N/A * A constructor that starts the KDC service also. 678N/A * Generates a 32-char random password 2413N/A // The last char cannot be a number, otherwise, keyForUser() 2413N/A // believes it's a sign of kvno 678N/A * Generates a random key for the given encryption type. 678N/A * @param eType the encryption type 678N/A * @return the generated key 678N/A // Is 32 enough for AES256? I should have generated the keys directly 678N/A // but different cryptos have different rules on what keys are valid. 678N/A * Returns the password for a given principal 678N/A * @throws sun.security.krb5.KrbException when the principal is not inside 1300N/A * Returns the salt string for the principal. 678N/A * Returns the key for a given principal of the given encryption type 678N/A * @param p the principal 678N/A * @param etype the encryption type 1941N/A * @param server looking for a server principal? 678N/A // Do not call EncryptionKey.acquireSecretKeys(), otherwise 2035N/A // For service whose password ending with a number, use it as kvno. 1941N/A * A system property named test.kdc.policy.RULE will be consulted. 1941N/A * If it's unset, returns false. If its value is "", any pair is 1941N/A * matched. Otherwise, it should contains the server name matched. 1941N/A * TODO: client name is not used currently. 1941N/A * @return if a match is found 678N/A * Processes an incoming request and generates a response. 678N/A * @param in the request 678N/A * @throws java.lang.Exception for various errors 678N/A * Processes a TGS_REQ and generates a TGS_REP (or KRB_ERROR) 678N/A * @param in the request 678N/A * @throws java.lang.Exception for various errors 678N/A " sends TGS-REQ for " +
678N/A // Reflection: PAData[] pas = tgsReq.pAData; 678N/A // Session key for original ticket, TGT 678N/A // Session key for session with the service 678N/A //renew = new KerberosTime(new Date().getTime() + 1000 * 3600 * 24 * 7); 678N/A // Next 5 and last MUST be same with ticket 678N/A * Processes a AS_REQ and generates a AS_REP (or KRB_ERROR) 678N/A * @param in the request 678N/A * @throws java.lang.Exception for various errors 678N/A // Reflection: int[] eType = body.eType; 678N/A //renew = new KerberosTime(new Date().getTime() + 1000 * 3600 * 24 * 7); 678N/A // Next 5 and last MUST be same with ticket 704N/A // Write the current issuing TGT into a ccache file specified 704N/A // by the system property below. 1300N/A * @return REALM.NAME = { kdc = host:port } 678N/A * Start the KDC service. This server listens on both UDP and TCP using 678N/A * the same port number. It uses three threads to deal with requests. 678N/A * They can be set to daemon threads if requested. 678N/A * @param port the port number to listen to. If zero, a random available 678N/A * port no less than 8000 will be chosen and used. 678N/A * @param asDaemon true if the KDC threads should be daemons 678N/A * @throws java.io.IOException for any communication error 678N/A // Try to find a port number that's both TCP and UDP free 678N/A * Helper class to encapsulate a job in a KDC. 678N/A byte[]
token;
// The received request at creation time and 678N/A // the response at send time 678N/A Socket s;
// The TCP socket from where the request comes 678N/A // Creates a job object for TCP 678N/A // Creates a job object for UDP 678N/A // Sends the output back to the client 1300N/A // No reverse lookup, PrincipalName use original string