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