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