001: /*
002: * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.security.jgss;
027:
028: import java.util.HashMap;
029: import javax.security.auth.login.AppConfigurationEntry;
030: import javax.security.auth.login.Configuration;
031: import org.ietf.jgss.Oid;
032:
033: /**
034: * A Configuration implementation especially designed for JGSS.
035: *
036: * @author weijun.wang
037: * @since 1.6
038: */
039: public class LoginConfigImpl extends Configuration {
040:
041: private final Configuration config;
042: private final int caller;
043: private final String mechName;
044: private static final sun.security.util.Debug debug = sun.security.util.Debug
045: .getInstance("gssloginconfig", "\t[GSS LoginConfigImpl]");
046:
047: /**
048: * A new instance of LoginConfigImpl must be created for each login request
049: * since it's only used by a single (caller, mech) pair
050: * @param caller defined in GSSUtil as CALLER_XXX final fields
051: * @param oid defined in GSSUtil as XXX_MECH_OID final fields
052: */
053: public LoginConfigImpl(int caller, Oid mech) {
054:
055: this .caller = caller;
056:
057: if (mech.equals(GSSUtil.GSS_KRB5_MECH_OID)) {
058: mechName = "krb5";
059: } else {
060: throw new IllegalArgumentException(mech.toString()
061: + " not supported");
062: }
063: config = java.security.AccessController
064: .doPrivileged(new java.security.PrivilegedAction<Configuration>() {
065: public Configuration run() {
066: return Configuration.getConfiguration();
067: }
068: });
069: }
070:
071: /**
072: * @param name Almost useless, since the (caller, mech) is already passed
073: * into constructor. The only use will be detecting OTHER which
074: * is called in LoginContext
075: */
076: public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
077:
078: AppConfigurationEntry[] entries = null;
079:
080: // This is the second call from LoginContext, which we will just ignore
081: if ("OTHER".equalsIgnoreCase(name)) {
082: return null;
083: }
084:
085: String[] alts = null;
086:
087: // Compatibility:
088: // For the 4 old callers, old entry names will be used if the new
089: // entry name is not provided.
090:
091: if ("krb5".equals(mechName)) {
092: switch (caller) {
093: case GSSUtil.CALLER_INITIATE:
094: alts = new String[] {
095: "com.sun.security.jgss.krb5.initiate",
096: "com.sun.security.jgss.initiate", };
097: break;
098: case GSSUtil.CALLER_ACCEPT:
099: alts = new String[] {
100: "com.sun.security.jgss.krb5.accept",
101: "com.sun.security.jgss.accept", };
102: break;
103: case GSSUtil.CALLER_SSL_CLIENT:
104: alts = new String[] {
105: "com.sun.security.jgss.krb5.initiate",
106: "com.sun.net.ssl.client", };
107: break;
108: case GSSUtil.CALLER_SSL_SERVER:
109: alts = new String[] {
110: "com.sun.security.jgss.krb5.accept",
111: "com.sun.net.ssl.server", };
112: break;
113: case GSSUtil.CALLER_HTTP_NEGOTIATE:
114: alts = new String[] { "com.sun.security.jgss.krb5.initiate", };
115: break;
116: case GSSUtil.CALLER_UNKNOWN:
117: // should never use
118: throw new AssertionError("caller cannot be unknown");
119: default:
120: throw new AssertionError("caller not defined");
121: }
122: } else {
123: throw new IllegalArgumentException(mechName
124: + " not supported");
125: // No other mech at the moment, maybe --
126: /*
127: switch (caller) {
128: case GSSUtil.CALLER_INITIATE:
129: case GSSUtil.CALLER_SSL_CLIENT:
130: case GSSUtil.CALLER_HTTP_NEGOTIATE:
131: alts = new String[] {
132: "com.sun.security.jgss." + mechName + ".initiate",
133: };
134: break;
135: case GSSUtil.CALLER_ACCEPT:
136: case GSSUtil.CALLER_SSL_SERVER:
137: alts = new String[] {
138: "com.sun.security.jgss." + mechName + ".accept",
139: };
140: break;
141: case GSSUtil.CALLER_UNKNOWN:
142: // should never use
143: throw new AssertionError("caller cannot be unknown");
144: default:
145: throw new AssertionError("caller not defined");
146: }
147: */
148: }
149: for (String alt : alts) {
150: entries = config.getAppConfigurationEntry(alt);
151: if (debug != null) {
152: debug.println("Trying "
153: + alt
154: + ((entries == null) ? ": does not exist."
155: : ": Found!"));
156: }
157: if (entries != null) {
158: break;
159: }
160: }
161:
162: if (entries == null) {
163: if (debug != null) {
164: debug
165: .println("Cannot read JGSS entry, use default values instead.");
166: }
167: entries = getDefaultConfigurationEntry();
168: }
169: return entries;
170: }
171:
172: /**
173: * Default value for a caller-mech pair when no entry is defined in
174: * the system-wide Configuration object.
175: */
176: private AppConfigurationEntry[] getDefaultConfigurationEntry() {
177: HashMap<String, String> options = new HashMap<String, String>(2);
178:
179: if (mechName == null || mechName.equals("krb5")) {
180: if (isServerSide(caller)) {
181: // Assuming the keytab file can be found through
182: // krb5 config file or under user home directory
183: options.put("useKeyTab", "true");
184: options.put("storeKey", "true");
185: options.put("doNotPrompt", "true");
186: options.put("isInitiator", "false");
187: } else {
188: options.put("useTicketCache", "true");
189: options.put("doNotPrompt", "false");
190: }
191: return new AppConfigurationEntry[] { new AppConfigurationEntry(
192: "com.sun.security.auth.module.Krb5LoginModule",
193: AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
194: options) };
195: }
196: return null;
197: }
198:
199: private static boolean isServerSide(int caller) {
200: return GSSUtil.CALLER_ACCEPT == caller
201: || GSSUtil.CALLER_SSL_SERVER == caller;
202: }
203: }
|