001: package org.tigris.scarab.pipeline;
002:
003: import java.io.IOException;
004:
005: import javax.servlet.ServletException;
006: import javax.servlet.http.HttpServletRequest;
007: import javax.servlet.http.HttpServletResponse;
008: import javax.servlet.http.HttpSession;
009:
010: import org.apache.fulcrum.security.TurbineSecurity;
011: import org.apache.fulcrum.security.util.DataBackendException;
012: import org.apache.fulcrum.security.util.UnknownEntityException;
013: import org.apache.log4j.Logger;
014: import org.apache.turbine.RunData;
015: import org.apache.turbine.Turbine;
016: import org.apache.turbine.TurbineException;
017: import org.apache.turbine.ValveContext;
018: import org.apache.turbine.pipeline.AbstractValve;
019: import org.tigris.scarab.om.ScarabUser;
020: import org.tigris.scarab.tools.ScarabLocalizationTool;
021: import org.tigris.scarab.tools.localization.L10NKeySet;
022: import org.tigris.scarab.tools.localization.L10NMessage;
023: import org.tigris.scarab.util.AnonymousUserUtil;
024: import org.tigris.scarab.util.Log;
025:
026: import jcifs.Config;
027: import jcifs.UniAddress;
028:
029: import jcifs.smb.NtlmPasswordAuthentication;
030: import jcifs.smb.SmbAuthException;
031: import jcifs.smb.SmbSession;
032:
033: import jcifs.util.Base64;
034:
035: import jcifs.http.NtlmSsp;
036:
037: /*
038: * This valve will try to automatically login a user in an NTLM domain, using
039: * the credentials provided by the browser.
040: *
041: * @author jorgeuriarte
042: */
043: public class NTLMLoginValve extends AbstractValve {
044: private boolean bNTLMActive;
045: private String domainController;
046: private static Logger log = Log.get(NTLMLoginValve.class.getName());
047:
048: /*
049: * Invoked by the Turbine's pipeline, as defined in scarab-pipeline.xml
050: * Will try to authenticate against a NTLM domain using info provided by the browser.
051: *
052: * @see org.apache.turbine.pipeline.AbstractValve#invoke(org.apache.turbine.RunData, org.apache.turbine.ValveContext)
053: */
054: public void invoke(RunData data, ValveContext context)
055: throws IOException, TurbineException {
056: if (bNTLMActive
057: && (((null == data.getUserFromSession() || data
058: .getUserFromSession().getUserName().trim()
059: .length() == 0) && null == data.getUser()) || ((ScarabUser) data
060: .getUserFromSession()).isUserAnonymous())
061: && (!data.getAction().equals("Logout")
062: && !data.getAction().equals("Login")
063: && !data.getTarget().equals("Register.vm") && !data
064: .getTarget().equals("ForgotPassword.vm"))) {
065: authenticateNtlm(data);
066: }
067: context.invokeNext(data);
068: }
069:
070: /*
071: * This method will initialize the NTLM login system if the required properties are set.
072: */
073: public void initialize() throws Exception {
074: bNTLMActive = Turbine.getConfiguration().getBoolean(
075: "scarab.login.ntlm.active", false);
076: domainController = Turbine.getConfiguration().getString(
077: "scarab.login.ntlm.domain", "<check properties>");
078: Config.setProperty("jcifs.util.loglevel",
079: log.isDebugEnabled() ? "10" : "0");
080: Config.setProperty("jcifs.smb.client.soTimeout", "300000");
081: Config.setProperty("jcifs.netbios.cachePolicy", "600");
082: Config.setProperty("jcifs.http.domainController",
083: domainController);
084: Config.setProperty("jcifs.smb.client.domain", domainController);
085: Config.setProperty("http.auth.ntlm.domain", domainController);
086:
087: if (domainController == null) {
088: bNTLMActive = false;
089: Log.get(this .getClass().getName()).debug(
090: "Domain controller must be specified.");
091: }
092: super .initialize();
093: }
094:
095: private void authenticateNtlm(RunData data) throws IOException {
096: HttpServletRequest request = data.getRequest();
097: HttpServletResponse response = data.getResponse();
098: UniAddress dc;
099: String msg = request.getHeader("Authorization");
100: if (msg != null && msg.startsWith("NTLM ")) {
101: dc = UniAddress.getByName(domainController, true);
102: NtlmPasswordAuthentication ntlm = null;
103: if (msg.startsWith("NTLM ")) {
104: byte[] challenge = SmbSession.getChallenge(dc);
105: try {
106: ntlm = NtlmSsp.authenticate(request, response,
107: challenge);
108: } catch (IOException e) {
109: log.error("authenticateNtlm: " + e);
110: } catch (ServletException e) {
111: log.error("authenticateNtlm: " + e);
112: }
113: if (ntlm == null)
114: return;
115: } else {
116: String auth = new String(Base64
117: .decode(msg.substring(6)), "US-ASCII");
118: int index = auth.indexOf(':');
119: String user = (index != -1) ? auth.substring(0, index)
120: : auth;
121: String password = (index != -1) ? auth
122: .substring(index + 1) : "";
123: index = user.indexOf('\\');
124: if (index == -1)
125: index = user.indexOf('/');
126: String domain = (index != -1) ? user
127: .substring(0, index) : domainController;
128: user = (index != -1) ? user.substring(index + 1) : user;
129: ntlm = new NtlmPasswordAuthentication(domain, user,
130: password);
131: }
132: try {
133: SmbSession.logon(dc, ntlm);
134: } catch (SmbAuthException sae) {
135: response.setHeader("WWW-Authenticate", "NTLM");
136: response.setHeader("Connection", "close");
137: response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
138: response.flushBuffer();
139: return;
140: }
141:
142: try {
143: // Once the user has been authenticated, we'll try logging in Scarab.
144: String creds[] = { ntlm.getUsername(), domainController };
145: ScarabUser user = (ScarabUser) TurbineSecurity
146: .getUser(creds[0]);
147: AnonymousUserUtil.userLogin(data, user);
148: data.setTarget("SelectModule.vm");
149:
150: // Inform the user that s/he's been logged in using NTLM credentials!
151: L10NMessage mesg = new L10NMessage(
152: L10NKeySet.AutomaticallyLoggedIn, creds);
153: ScarabLocalizationTool l10n = new ScarabLocalizationTool();
154: l10n.init(user.getLocale());
155: data.setMessage(mesg.getMessage(l10n));
156: } catch (DataBackendException e) {
157: log.error("authenticateNtlm: " + e);
158: } catch (UnknownEntityException e) {
159: log.error("authenticateNtlm: " + e);
160: }
161: } else {
162: HttpSession ssn = request.getSession(false);
163: if (ssn == null || ssn.getAttribute("NtlmHttpAuth") == null) {
164: response.setHeader("WWW-Authenticate", "NTLM");
165: // TODO: Allow a maximum number of connection attempts?
166: response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
167: response.flushBuffer();
168: return;
169: }
170: }
171: }
172:
173: }
|