1 /* 2 * Copyright (c) 2000, 2011, 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 26 package com.sun.security.auth.module; 27 28 import java.util.*; 29 import java.io.IOException; 30 import javax.security.auth.*; 31 import javax.security.auth.callback.*; 32 import javax.security.auth.login.*; 33 import javax.security.auth.spi.*; 34 import com.sun.security.auth.SolarisPrincipal; 35 import com.sun.security.auth.SolarisNumericUserPrincipal; 36 import com.sun.security.auth.SolarisNumericGroupPrincipal; 37 38 /** 39 * <p> This <code>LoginModule</code> imports a user's Solaris 40 * <code>Principal</code> information (<code>SolarisPrincipal</code>, 41 * <code>SolarisNumericUserPrincipal</code>, 42 * and <code>SolarisNumericGroupPrincipal</code>) 43 * and associates them with the current <code>Subject</code>. 44 * 45 * <p> This LoginModule recognizes the debug option. 46 * If set to true in the login Configuration, 47 * debug messages will be output to the output stream, System.out. 48 * @deprecated As of JDK1.4, replaced by 49 * <code>com.sun.security.auth.module.UnixLoginModule</code>. 50 * This LoginModule is entirely deprecated and 51 * is here to allow for a smooth transition to the new 52 * UnixLoginModule. 53 * 54 */ 55 @jdk.Supported 56 @Deprecated 57 public class SolarisLoginModule implements LoginModule { 58 59 // initial state 60 private Subject subject; 61 private CallbackHandler callbackHandler; 62 private Map<String, ?> sharedState; 63 private Map<String, ?> options; 64 65 // configurable option 66 private boolean debug = true; 67 68 // SolarisSystem to retrieve underlying system info 69 private SolarisSystem ss; 70 71 // the authentication status 72 private boolean succeeded = false; 73 private boolean commitSucceeded = false; 74 75 // Underlying system info 76 private SolarisPrincipal userPrincipal; 77 private SolarisNumericUserPrincipal UIDPrincipal; 78 private SolarisNumericGroupPrincipal GIDPrincipal; 79 private LinkedList<SolarisNumericGroupPrincipal> supplementaryGroups = 80 new LinkedList<>(); 81 82 /** 83 * Initialize this <code>LoginModule</code>. 84 * 85 * <p> 86 * 87 * @param subject the <code>Subject</code> to be authenticated. <p> 88 * 89 * @param callbackHandler a <code>CallbackHandler</code> for communicating 90 * with the end user (prompting for usernames and 91 * passwords, for example). <p> 92 * 93 * @param sharedState shared <code>LoginModule</code> state. <p> 94 * 95 * @param options options specified in the login 96 * <code>Configuration</code> for this particular 97 * <code>LoginModule</code>. 98 */ 99 public void initialize(Subject subject, CallbackHandler callbackHandler, 100 Map<String,?> sharedState, 101 Map<String,?> options) 102 { 103 104 this.subject = subject; 105 this.callbackHandler = callbackHandler; 106 this.sharedState = sharedState; 107 this.options = options; 108 109 // initialize any configured options 110 debug = "true".equalsIgnoreCase((String)options.get("debug")); 111 } 112 113 /** 114 * Authenticate the user (first phase). 115 * 116 * <p> The implementation of this method attempts to retrieve the user's 117 * Solaris <code>Subject</code> information by making a native Solaris 118 * system call. 119 * 120 * <p> 121 * 122 * @exception FailedLoginException if attempts to retrieve the underlying 123 * system information fail. 124 * 125 * @return true in all cases (this <code>LoginModule</code> 126 * should not be ignored). 127 */ 128 public boolean login() throws LoginException { 129 130 long[] solarisGroups = null; 131 132 ss = new SolarisSystem(); 133 134 if (ss == null) { 135 succeeded = false; 136 throw new FailedLoginException 137 ("Failed in attempt to import " + 138 "the underlying system identity information"); 139 } else { 140 userPrincipal = new SolarisPrincipal(ss.getUsername()); 141 UIDPrincipal = new SolarisNumericUserPrincipal(ss.getUid()); 142 GIDPrincipal = new SolarisNumericGroupPrincipal(ss.getGid(), true); 143 if (ss.getGroups() != null && ss.getGroups().length > 0) 144 solarisGroups = ss.getGroups(); 145 for (int i = 0; i < solarisGroups.length; i++) { 146 SolarisNumericGroupPrincipal ngp = 147 new SolarisNumericGroupPrincipal 148 (solarisGroups[i], false); 149 if (!ngp.getName().equals(GIDPrincipal.getName())) 150 supplementaryGroups.add(ngp); 151 } 152 if (debug) { 153 System.out.println("\t\t[SolarisLoginModule]: " + 154 "succeeded importing info: "); 155 System.out.println("\t\t\tuid = " + ss.getUid()); 156 System.out.println("\t\t\tgid = " + ss.getGid()); 157 solarisGroups = ss.getGroups(); 158 for (int i = 0; i < solarisGroups.length; i++) { 159 System.out.println("\t\t\tsupp gid = " + solarisGroups[i]); 160 } 161 } 162 succeeded = true; 163 return true; 164 } 165 } 166 167 /** 168 * Commit the authentication (second phase). 169 * 170 * <p> This method is called if the LoginContext's 171 * overall authentication succeeded 172 * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules 173 * succeeded). 174 * 175 * <p> If this LoginModule's own authentication attempt 176 * succeeded (the importing of the Solaris authentication information 177 * succeeded), then this method associates the Solaris Principals 178 * with the <code>Subject</code> currently tied to the 179 * <code>LoginModule</code>. If this LoginModule's 180 * authentication attempted failed, then this method removes 181 * any state that was originally saved. 182 * 183 * <p> 184 * 185 * @exception LoginException if the commit fails 186 * 187 * @return true if this LoginModule's own login and commit attempts 188 * succeeded, or false otherwise. 189 */ 190 public boolean commit() throws LoginException { 191 if (succeeded == false) { 192 if (debug) { 193 System.out.println("\t\t[SolarisLoginModule]: " + 194 "did not add any Principals to Subject " + 195 "because own authentication failed."); 196 } 197 return false; 198 } 199 if (subject.isReadOnly()) { 200 throw new LoginException ("Subject is Readonly"); 201 } 202 if (!subject.getPrincipals().contains(userPrincipal)) 203 subject.getPrincipals().add(userPrincipal); 204 if (!subject.getPrincipals().contains(UIDPrincipal)) 205 subject.getPrincipals().add(UIDPrincipal); 206 if (!subject.getPrincipals().contains(GIDPrincipal)) 207 subject.getPrincipals().add(GIDPrincipal); 208 for (int i = 0; i < supplementaryGroups.size(); i++) { 209 if (!subject.getPrincipals().contains(supplementaryGroups.get(i))) 210 subject.getPrincipals().add(supplementaryGroups.get(i)); 211 } 212 213 if (debug) { 214 System.out.println("\t\t[SolarisLoginModule]: " + 215 "added SolarisPrincipal,"); 216 System.out.println("\t\t\t\tSolarisNumericUserPrincipal,"); 217 System.out.println("\t\t\t\tSolarisNumericGroupPrincipal(s),"); 218 System.out.println("\t\t\t to Subject"); 219 } 220 221 commitSucceeded = true; 222 return true; 223 } 224 225 226 /** 227 * Abort the authentication (second phase). 228 * 229 * <p> This method is called if the LoginContext's 230 * overall authentication failed. 231 * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules 232 * did not succeed). 233 * 234 * <p> This method cleans up any state that was originally saved 235 * as part of the authentication attempt from the <code>login</code> 236 * and <code>commit</code> methods. 237 * 238 * <p> 239 * 240 * @exception LoginException if the abort fails 241 * 242 * @return false if this LoginModule's own login and/or commit attempts 243 * failed, and true otherwise. 244 */ 245 public boolean abort() throws LoginException { 246 if (debug) { 247 System.out.println("\t\t[SolarisLoginModule]: " + 248 "aborted authentication attempt"); 249 } 250 251 if (succeeded == false) { 252 return false; 253 } else if (succeeded == true && commitSucceeded == false) { 254 255 // Clean out state 256 succeeded = false; 257 ss = null; 258 userPrincipal = null; 259 UIDPrincipal = null; 260 GIDPrincipal = null; 261 supplementaryGroups = 262 new LinkedList<SolarisNumericGroupPrincipal>(); 263 } else { 264 // overall authentication succeeded and commit succeeded, 265 // but someone else's commit failed 266 logout(); 267 } 268 return true; 269 } 270 271 /** 272 * Logout the user 273 * 274 * <p> This method removes the Principals associated 275 * with the <code>Subject</code>. 276 * 277 * <p> 278 * 279 * @exception LoginException if the logout fails 280 * 281 * @return true in all cases (this <code>LoginModule</code> 282 * should not be ignored). 283 */ 284 public boolean logout() throws LoginException { 285 if (debug) { 286 System.out.println("\t\t[SolarisLoginModule]: " + 287 "Entering logout"); 288 } 289 if (subject.isReadOnly()) { 290 throw new LoginException ("Subject is Readonly"); 291 } 292 // remove the added Principals from the Subject 293 subject.getPrincipals().remove(userPrincipal); 294 subject.getPrincipals().remove(UIDPrincipal); 295 subject.getPrincipals().remove(GIDPrincipal); 296 for (int i = 0; i < supplementaryGroups.size(); i++) { 297 subject.getPrincipals().remove(supplementaryGroups.get(i)); 298 } 299 300 // clean out state 301 ss = null; 302 succeeded = false; 303 commitSucceeded = false; 304 userPrincipal = null; 305 UIDPrincipal = null; 306 GIDPrincipal = null; 307 supplementaryGroups = new LinkedList<SolarisNumericGroupPrincipal>(); 308 309 if (debug) { 310 System.out.println("\t\t[SolarisLoginModule]: " + 311 "logged out Subject"); 312 } 313 return true; 314 } 315 }