1/* 2 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package sun.security.jgss; 27 28import java.util.HashMap; 29import javax.security.auth.login.AppConfigurationEntry; 30import javax.security.auth.login.Configuration; 31import org.ietf.jgss.Oid; 32 33/** 34 * A Configuration implementation especially designed for JGSS. 35 * 36 * @author weijun.wang 37 * @since 1.6 38 */ 39public class LoginConfigImpl extends Configuration { 40 41 private final Configuration config; 42 private final GSSCaller caller; 43 private final String mechName; 44 private static final sun.security.util.Debug debug = 45 sun.security.util.Debug.getInstance("gssloginconfig", "\t[GSS LoginConfigImpl]"); 46 47 /** 48 * A new instance of LoginConfigImpl must be created for each login request 49 * since it's only used by a single (caller, mech) pair 50 * @param caller defined in GSSUtil as CALLER_XXX final fields 51 * @param mech defined in GSSUtil as XXX_MECH_OID final fields 52 */ 53 public LoginConfigImpl(GSSCaller caller, Oid mech) { 54 55 this.caller = caller; 56 57 if (mech.equals(GSSUtil.GSS_KRB5_MECH_OID)) { 58 mechName = "krb5"; 59 } else { 60 throw new IllegalArgumentException(mech.toString() + " not supported"); 61 } 62 config = java.security.AccessController.doPrivileged 63 (new java.security.PrivilegedAction <Configuration> () { 64 public Configuration run() { 65 return Configuration.getConfiguration(); 66 } 67 }); 68 } 69 70 /** 71 * @param name Almost useless, since the (caller, mech) is already passed 72 * into constructor. The only use will be detecting OTHER which 73 * is called in LoginContext 74 */ 75 public AppConfigurationEntry[] getAppConfigurationEntry(String name) { 76 77 AppConfigurationEntry[] entries = null; 78 79 // This is the second call from LoginContext, which we will just ignore 80 if ("OTHER".equalsIgnoreCase(name)) { 81 return null; 82 } 83 84 String[] alts = null; 85 86 // Compatibility: 87 // For the 4 old callers, old entry names will be used if the new 88 // entry name is not provided. 89 90 if ("krb5".equals(mechName)) { 91 if (caller == GSSCaller.CALLER_INITIATE) { 92 alts = new String[] { 93 "com.sun.security.jgss.krb5.initiate", 94 "com.sun.security.jgss.initiate", 95 }; 96 } else if (caller == GSSCaller.CALLER_ACCEPT) { 97 alts = new String[] { 98 "com.sun.security.jgss.krb5.accept", 99 "com.sun.security.jgss.accept", 100 }; 101 } else if (caller == GSSCaller.CALLER_SSL_CLIENT) { 102 alts = new String[] { 103 "com.sun.security.jgss.krb5.initiate", 104 "com.sun.net.ssl.client", 105 }; 106 } else if (caller == GSSCaller.CALLER_SSL_SERVER) { 107 alts = new String[] { 108 "com.sun.security.jgss.krb5.accept", 109 "com.sun.net.ssl.server", 110 }; 111 } else if (caller instanceof HttpCaller) { 112 alts = new String[] { 113 "com.sun.security.jgss.krb5.initiate", 114 }; 115 } else if (caller == GSSCaller.CALLER_UNKNOWN) { 116 throw new AssertionError("caller not defined"); 117 } 118 } else { 119 throw new IllegalArgumentException(mechName + " not supported"); 120 // No other mech at the moment, maybe -- 121 /* 122 switch (caller) { 123 case GSSUtil.CALLER_INITIATE: 124 case GSSUtil.CALLER_SSL_CLIENT: 125 case GSSUtil.CALLER_HTTP_NEGOTIATE: 126 alts = new String[] { 127 "com.sun.security.jgss." + mechName + ".initiate", 128 }; 129 break; 130 case GSSUtil.CALLER_ACCEPT: 131 case GSSUtil.CALLER_SSL_SERVER: 132 alts = new String[] { 133 "com.sun.security.jgss." + mechName + ".accept", 134 }; 135 break; 136 case GSSUtil.CALLER_UNKNOWN: 137 // should never use 138 throw new AssertionError("caller cannot be unknown"); 139 default: 140 throw new AssertionError("caller not defined"); 141 } 142 */ 143 } 144 for (String alt: alts) { 145 entries = config.getAppConfigurationEntry(alt); 146 if (debug != null) { 147 debug.println("Trying " + alt + 148 ((entries == null)?": does not exist.":": Found!")); 149 } 150 if (entries != null) { 151 break; 152 } 153 } 154 155 if (entries == null) { 156 if (debug != null) { 157 debug.println("Cannot read JGSS entry, use default values instead."); 158 } 159 entries = getDefaultConfigurationEntry(); 160 } 161 return entries; 162 } 163 164 /** 165 * Default value for a caller-mech pair when no entry is defined in 166 * the system-wide Configuration object. 167 */ 168 private AppConfigurationEntry[] getDefaultConfigurationEntry() { 169 HashMap <String, String> options = new HashMap <String, String> (2); 170 171 if (mechName == null || mechName.equals("krb5")) { 172 if (isServerSide(caller)) { 173 // Assuming the keytab file can be found through 174 // krb5 config file or under user home directory 175 options.put("useKeyTab", "true"); 176 options.put("storeKey", "true"); 177 options.put("doNotPrompt", "true"); 178 options.put("principal", "*"); 179 options.put("isInitiator", "false"); 180 } else { 181 options.put("useTicketCache", "true"); 182 options.put("doNotPrompt", "false"); 183 } 184 return new AppConfigurationEntry[] { 185 new AppConfigurationEntry( 186 "com.sun.security.auth.module.Krb5LoginModule", 187 AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, 188 options) 189 }; 190 } 191 return null; 192 } 193 194 private static boolean isServerSide (GSSCaller caller) { 195 return GSSCaller.CALLER_ACCEPT == caller || 196 GSSCaller.CALLER_SSL_SERVER == caller; 197 } 198} 199