Author: nico
Date: 2009-05-20 17:14:29 +0200 (Wed, 20 May 2009)
New Revision: 35329

Added:
   
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/VisitorFilter.java
Removed:
   
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmVisitor.java
Modified:
   
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmKnownVisitorModule.java
   
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmVisitorFilter.java
   
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/KnownVisitorModule.java
   
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/Visitor.java
Log:
CMSC-1408 Make Basic and NTLM authentication optional for knownvisitors 

Modified: 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/KnownVisitorModule.java
===================================================================
--- 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/KnownVisitorModule.java
        2009-05-20 15:14:26 UTC (rev 35328)
+++ 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/KnownVisitorModule.java
        2009-05-20 15:14:29 UTC (rev 35329)
@@ -1,23 +1,175 @@
-package com.finalist.cmsc.knownvisitor;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.mmbase.module.Module;
-
-public abstract class KnownVisitorModule extends Module {
-
-   private static KnownVisitorModule instance;
-
-
-   public abstract Visitor getVisitor(HttpServletRequest request);
-
-
-   public static KnownVisitorModule getInstance() {
-      return instance;
-   }
-
-
-   public static void setInstance(KnownVisitorModule module) {
-      instance = module;
-   }
-}
+package com.finalist.cmsc.knownvisitor;
+
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.mmbase.module.Module;
+
+import com.finalist.cmsc.mmbase.PropertiesUtil;
+
+public abstract class KnownVisitorModule extends Module {
+
+   private static final Log log = LogFactory.getLog(KnownVisitorModule.class);
+
+   private static final String SESSION_ATTRIBUTE = "knownVisitor";
+   
+   private static final String PROPERTY_ENABLED = "knownvisitor.enabled";
+   private static final String PROPERTY_IPEXCEPTIONS = 
"knownvisitor.ipexceptions";
+   private static final String PROPERTY_BASIC_AUTH = 
"knownvisitor.basic-authentication";
+
+   private static final String PROPERTY_LDAP_SERVER = 
"knownvisitor.ldapserver";
+   private static final String PROPERTY_REALM = "knownvisitor.realm";
+   private static final String PROPERTY_LOGONNAME = "knownvisitor.logonname";
+   private static final String PROPERTY_LOGONPASSWORD = 
"knownvisitor.logonpassword";
+   private static final String PROPERTY_BASEDN = "knownvisitor.baseDN";
+
+   private static final String PROPERTY_FIELD_EMAIL = 
"knownvisitor.field.email";
+   private static final String PROPERTY_FIELD_REALNAME = 
"knownvisitor.field.realname";
+   private static final String PROPERTY_FIELD_USERNAME = 
"knownvisitor.field.username";
+
+   
+   private static KnownVisitorModule instance;
+
+   public static KnownVisitorModule getInstance() {
+      return instance;
+   }
+
+   public static void setInstance(KnownVisitorModule module) {
+      instance = module;
+   }
+   
+
+   public Visitor getVisitor(HttpServletRequest request) {
+      HttpSession ssn = request.getSession(false);
+      return (ssn != null ? (Visitor) ssn.getAttribute(SESSION_ATTRIBUTE) : 
null);
+   }
+
+   public void setVisitor(HttpServletRequest request, Visitor visitor) {
+      request.getSession().setAttribute(SESSION_ATTRIBUTE, visitor);
+   }
+
+   public void readLdapInfo(Visitor visitor) {
+      // Assemble a hash with data to use when connecting...
+      String ldapPrincipal = getLdapPrincipal();
+      String ldapPassword = getLdapPassword();
+
+
+      // Make a directory context by connecting with the above details.
+      try {
+         DirContext ctx = ldapLogin(ldapPrincipal, ldapPassword);
+
+         String baseDN = getLdapBaseDN();
+         String query = "(" + getLdapUsernameField() + "=" + 
visitor.getIdentifier() + ")";
+         
+         NamingEnumeration<SearchResult> answer = ctx.search(baseDN, query, 
null);
+         if (answer.hasMoreElements()) {
+            SearchResult result = answer.next();
+            Attribute values = 
result.getAttributes().get(getLdapRealnameField());
+            if (values.size() > 0) {
+               visitor.setDisplayName((String) values.get(0));
+            }
+
+            values = result.getAttributes().get(getLdapEmailField());
+            if (values.size() > 0) {
+               visitor.setEmail((String) values.get(0));
+            }
+         }
+      }
+      catch (NamingException e) {
+         log.error("problem reading user from LDAP: ", e);
+         visitor.setDisplayName("LDAP failed");
+      }
+   }
+
+   public DirContext ldapLogin(String ldapPrincipal, String ldapPassword) 
throws NamingException {
+      String server = getLdapServer();
+      if (server.indexOf("://") < 0) {
+         // no protocol, fallback to ldap
+         server = "ldap://"; + server;
+      }
+      
+      Hashtable<String, String> env = new Hashtable<String, String>();
+      env.put(Context.INITIAL_CONTEXT_FACTORY, 
"com.sun.jndi.ldap.LdapCtxFactory");
+      env.put(Context.PROVIDER_URL, server);
+
+      env.put(Context.SECURITY_AUTHENTICATION, "simple");
+      env.put(Context.SECURITY_PRINCIPAL, ldapPrincipal);
+      env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
+      
+      DirContext ctx = new InitialDirContext(env);
+      return ctx;
+   }
+
+   public boolean offerBasic(HttpServletRequest req) {
+      boolean offerBasic = req.isSecure();
+      if (!offerBasic) {
+         String basic = getBasicAuth();
+         if (StringUtils.isBlank(basic) || "secure".equalsIgnoreCase(basic)) {
+            return false;
+         }
+         else {
+            // basic authentication is not forced to be on secured urls and 
the current request is not secured
+            // This does not mean that the url arrived at the webserver was 
not secured. The webserver could
+            // proxy the request without using the secured flag.
+            return true;
+         }
+      }
+      return offerBasic;
+   }
+
+   public String getBasicAuth() {
+      return PropertiesUtil.getProperty(PROPERTY_BASIC_AUTH);
+   }
+
+   public boolean isEnabled() {
+      return 
Boolean.parseBoolean(PropertiesUtil.getProperty(PROPERTY_ENABLED));
+   }
+
+   public List<String> getIpExceptions() {
+       return PropertiesUtil.getPropertyAsList(PROPERTY_IPEXCEPTIONS);
+   }
+
+   public String getProperty(String key) {
+      return PropertiesUtil.getProperty(key);
+   }
+
+   public String getLdapPassword() {
+      return getProperty(PROPERTY_LOGONPASSWORD);
+   }
+
+   public String getLdapPrincipal() {
+      return getProperty(PROPERTY_LOGONNAME);
+   }
+
+   public String getLdapServer() {
+      return getProperty(PROPERTY_LDAP_SERVER);
+   }
+
+   public String getLdapBaseDN() {
+      return getProperty(PROPERTY_BASEDN);
+   }
+
+   public String getLdapUsernameField() {
+      return getProperty(PROPERTY_FIELD_USERNAME);
+   }
+
+   public String getLdapEmailField() {
+      return getProperty(PROPERTY_FIELD_EMAIL);
+   }
+
+   public String getLdapRealnameField() {
+      return getProperty(PROPERTY_FIELD_REALNAME);
+   }
+
+   public String getRealm() {
+      return getProperty(PROPERTY_REALM);
+   }
+}

Modified: 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/Visitor.java
===================================================================
--- 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/Visitor.java
   2009-05-20 15:14:26 UTC (rev 35328)
+++ 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/Visitor.java
   2009-05-20 15:14:29 UTC (rev 35329)
@@ -1,12 +1,37 @@
-package com.finalist.cmsc.knownvisitor;
-
-public abstract class Visitor {
-
-   public abstract Object getIdentifier();
-
-
-   public abstract String getDisplayName();
-
-
-   public abstract String getEmail();
-}
+package com.finalist.cmsc.knownvisitor;
+
+public class Visitor {
+
+   private String identifier;
+   private String displayName;
+   private String email;
+
+   public String getIdentifier() {
+      return identifier;
+   }
+
+
+   public String getDisplayName() {
+      return displayName;
+   }
+
+
+   public void setDisplayName(String displayName) {
+      this.displayName = displayName;
+   }
+
+
+   public void setIdentifier(String identifier) {
+      this.identifier = identifier;
+   }
+
+
+   public String getEmail() {
+      return email;
+   }
+
+
+   public void setEmail(String email) {
+      this.email = email;
+   }
+}

Added: 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/VisitorFilter.java
===================================================================
--- 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/VisitorFilter.java
                             (rev 0)
+++ 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor/src/java/com/finalist/cmsc/knownvisitor/VisitorFilter.java
     2009-05-20 15:14:29 UTC (rev 35329)
@@ -0,0 +1,164 @@
+/*
+
+This software is OSI Certified Open Source Software.
+OSI Certified is a certification mark of the Open Source Initiative.
+
+The license (Mozilla version 1.0) can be read at the MMBase site.
+See http://www.MMBase.org/license
+
+*/
+package com.finalist.cmsc.knownvisitor;
+
+import java.io.IOException;
+
+import java.util.*;
+
+import javax.naming.NamingException;
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.mmbase.util.Encode;
+
+public class VisitorFilter implements Filter {
+
+   private static final Log log = LogFactory.getLog(VisitorFilter.class);
+   
+   public void init(FilterConfig filterConfig) {
+      // nothing
+   }
+
+   public void destroy() {
+      // nothing
+   }
+
+   /**
+    * This method simply calls <tt>negotiate( req, resp, false )</tt> and then
+    * <tt>chain.doFilter</tt>. You can override and call negotiate manually
+    * to achive a variety of different behavior.
+    */
+   public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException,
+         ServletException {
+      final HttpServletRequest req = (HttpServletRequest) request;
+      final HttpServletResponse resp = (HttpServletResponse) response;
+
+      if (KnownVisitorModule.getInstance().isEnabled() && 
!alreadyLoggedIn(req)) {
+         List<String> exceptions = 
KnownVisitorModule.getInstance().getIpExceptions();
+         if (!exceptions.isEmpty()) {
+            
+            List<String> ips = resolveRemoteAddresses(request);
+
+            for (Iterator<String> iterator = ips.iterator(); 
iterator.hasNext();) {
+               String addr = iterator.next();
+               if (exceptions.contains(addr)) {
+                  log.debug("Ip " + addr + " allowed.");
+                  chain.doFilter(request, response);
+                  return;
+               }
+            }
+         }
+
+         if (!negotiate(req, resp)) {
+            return;
+         }
+      }
+      chain.doFilter(req, resp);
+   }
+
+   private List<String> resolveRemoteAddresses(ServletRequest request) {
+      List<String> ips = new ArrayList<String>();
+      ips.add(request.getRemoteAddr());
+      
+      String ip = ((HttpServletRequest) request).getHeader("X-Forwarded-For");
+      if (StringUtils.isBlank(ip)) {
+         // not behind a proxy or mod_proxy
+         log.debug("Incoming ip, remote address = " + request.getRemoteAddr());
+      }
+      else {
+         log.debug("Incoming ip, remote address = " + request.getRemoteAddr() 
+ " X-Forwarded-For =" + ip);
+         StringTokenizer token = new StringTokenizer(ip, ",");
+         while(token.hasMoreTokens()) {
+            ips.add(token.nextToken().trim());
+         }
+      }
+      return ips;
+   }
+
+   /**
+    * Negotiate password hashes with MSIE clients using NTLM SSP
+    * 
+    * @param req The servlet request
+    * @param resp The servlet response
+    * @return True if the negotiation is complete, otherwise false
+    */
+   protected boolean negotiate(HttpServletRequest req, HttpServletResponse 
resp)
+         throws IOException, ServletException {
+      String msg = req.getHeader("Authorization");
+      boolean offerBasic = KnownVisitorModule.getInstance().offerBasic(req);
+      log.debug("Message: " + msg);
+      if (msg != null && offerBasic && msg.startsWith("Basic ")) {
+         log.debug("Message starts with Basic.");
+         String base64str = msg.substring(6);
+         String auth = Encode.decode("BASE64", base64str);
+         int index = auth.indexOf(':');
+         String user = (index != -1) ? auth.substring(0, index) : auth;
+         String password = (index != -1) ? auth.substring(index + 1) : "";
+         index = user.indexOf('\\');
+         if (index == -1)
+            index = user.indexOf('/');
+         
+         String domain;
+         if (index == -1) {
+             domain = KnownVisitorModule.getInstance().getRealm();
+         } else {
+             domain = user.substring(0, index);
+         }
+
+         user = (index != -1) ? user.substring(index + 1) : user;
+         
+         
+         try {
+            log.debug("user " + user + " domain " + domain + " password " + 
password);
+            KnownVisitorModule.getInstance().ldapLogin(user, password);
+         }
+         catch (NamingException e) {
+            log.debug("" + e.getMessage(), e);
+            // lets try mmbase authentication now
+            return true;
+         }
+         
+         req.getSession().setAttribute("NtlmHttpAuth", user);
+         justLoggedIn(req, user);
+
+         return true;
+      }
+      else {
+         HttpSession ssn = req.getSession(false);
+         if (offerBasic && (ssn == null || ssn.getAttribute("NtlmHttpAuth") == 
null)) {
+            log.debug("Not BASIO authenticated, starting authentication.");
+            String realm = KnownVisitorModule.getInstance().getRealm();
+            if (realm == null) {
+               realm = "CMS Container";
+            }
+            resp.addHeader("WWW-Authenticate", "Basic realm=\"" + realm + 
"\"");
+         }
+         resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+         resp.setContentLength(0);
+         resp.flushBuffer();
+         return false;
+      }
+   }
+
+   protected boolean alreadyLoggedIn(HttpServletRequest req) {
+      return KnownVisitorModule.getInstance().getVisitor(req) != null;
+   }
+
+   public void justLoggedIn(HttpServletRequest request, String username) {
+      Visitor visitor = new Visitor();
+      visitor.setIdentifier(username);
+      KnownVisitorModule.getInstance().readLdapInfo(visitor);
+      KnownVisitorModule.getInstance().setVisitor(request, visitor);
+   }
+}

Modified: 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmKnownVisitorModule.java
===================================================================
--- 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmKnownVisitorModule.java
  2009-05-20 15:14:26 UTC (rev 35328)
+++ 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmKnownVisitorModule.java
  2009-05-20 15:14:29 UTC (rev 35329)
@@ -1,101 +1,137 @@
-package com.finalist.cmsc.knownvisitor.ntlm;
-
-import java.util.Hashtable;
-
-import javax.naming.*;
-import javax.naming.directory.*;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import jcifs.smb.NtlmPasswordAuthentication;
-
-import com.finalist.cmsc.knownvisitor.KnownVisitorModule;
-import com.finalist.cmsc.mmbase.PropertiesUtil;
-
-public class NtlmKnownVisitorModule extends KnownVisitorModule {
-   static Log log = LogFactory.getLog(NtlmKnownVisitorModule.class);
-
-   private static final String SESSION_ATTRIBUTE = "NtlmVisitor";
-
-   public static final String PROPERTY_ENABLED = "knownvisitor-ntlm.enabled";
-   public static final String PROPERTY_DOMAIN_CONTROLLER = 
"knownvisitor-ntlm.domaincontroller";
-   public static final String PROPERTY_DOMAIN = "knownvisitor-ntlm.domain";
-   public static final String PROPERTY_IPEXCEPTIONS = 
"knownvisitor-ntlm.ipexceptions";
-   public static final String PROPERTY_BASIC_AUTH = "basic-authentication";
-
-   public static final String PROPERTY_FIELD_EMAIL = 
"knownvisitor-ntlm.field.email";
-   public static final String PROPERTY_FIELD_REALNAME = 
"knownvisitor-ntlm.field.realname";
-   public static final String PROPERTY_FIELD_USERNAME = 
"knownvisitor-ntlm.field.username";
-   public static final String PROPERTY_LOGONNAME = 
"knownvisitor-ntlm.logonname";
-   public static final String PROPERTY_LOGONPASSWORD = 
"knownvisitor-ntlm.logonpassword";
-   public static final String PROPERTY_SEARCHDN = "knownvisitor-ntlm.searchDN";
-
-
-   public NtlmKnownVisitorModule() {
-      // nothing
-   }
-
-
-   @Override
-   public NtlmVisitor getVisitor(HttpServletRequest request) {
-      return (NtlmVisitor) 
request.getSession().getAttribute(NtlmKnownVisitorModule.SESSION_ATTRIBUTE);
-   }
-
-
-   @Override
-   public void init() {
-      KnownVisitorModule.setInstance(this);
-   }
-
-
-   public void justLoggedIn(HttpServletRequest request, 
NtlmPasswordAuthentication ntlm) {
-      NtlmVisitor visitor = new NtlmVisitor();
-      visitor.setIdentifier(ntlm.getUsername());
-      readLdapInfo(visitor);
-      
request.getSession().setAttribute(NtlmKnownVisitorModule.SESSION_ATTRIBUTE, 
visitor);
-   }
-
-
-   public void readLdapInfo(NtlmVisitor visitor) {
-      DirContext ctx;
-      String query = "(" + getProperty(PROPERTY_FIELD_USERNAME) + "=" + 
visitor.getIdentifier() + ")";
-      String searchDN = getProperty(PROPERTY_SEARCHDN);
-      String server = getProperty(PROPERTY_DOMAIN_CONTROLLER);
-
-      // Assemble a hash with data to use when connecting...
-      Hashtable<String, String> env = new Hashtable<String, String>();
-      env.put(Context.SECURITY_AUTHENTICATION, "simple");
-      env.put(Context.SECURITY_PRINCIPAL, "cn=" + 
getProperty(PROPERTY_LOGONNAME) + "," + searchDN);
-      env.put(Context.SECURITY_CREDENTIALS, 
getProperty(PROPERTY_LOGONPASSWORD));
-
-      // Make a directory context by connecting with the above details.
-      try {
-         ctx = new InitialDirContext(env);
-         NamingEnumeration<SearchResult> answer = ctx.search("ldap://"; + 
server + "/" + searchDN, query, null);
-         if (answer.hasMoreElements()) {
-            SearchResult result = answer.next();
-            Attribute values = 
result.getAttributes().get(getProperty(PROPERTY_FIELD_REALNAME));
-            if (values.size() > 0) {
-               visitor.setDisplayName((String) values.get(0));
-            }
-
-            values = 
result.getAttributes().get(getProperty(PROPERTY_FIELD_EMAIL));
-            if (values.size() > 0) {
-               visitor.setEmail((String) values.get(0));
-            }
-         }
-      }
-      catch (NamingException e) {
-         log.error("problem reading user from LDAP: ", e);
-         visitor.setDisplayName("LDAP failed");
-      }
-   }
-
-
-   private String getProperty(String key) {
-      return PropertiesUtil.getProperty(key);
-   }
-
-}
+package com.finalist.cmsc.knownvisitor.ntlm;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.finalist.cmsc.knownvisitor.KnownVisitorModule;
+import com.finalist.cmsc.mmbase.PropertiesUtil;
+
+public class NtlmKnownVisitorModule extends KnownVisitorModule {
+   static Log log = LogFactory.getLog(NtlmKnownVisitorModule.class);
+
+   private static final String PROPERTY_ENABLED = "knownvisitor-ntlm.enabled";
+   private static final String PROPERTY_IPEXCEPTIONS = 
"knownvisitor-ntlm.ipexceptions";
+
+   private static final String PROPERTY_DOMAIN_CONTROLLER = 
"knownvisitor-ntlm.domaincontroller";
+   private static final String PROPERTY_DOMAIN = "knownvisitor-ntlm.domain";
+
+   private static final String PROPERTY_FIELD_EMAIL = 
"knownvisitor-ntlm.field.email";
+   private static final String PROPERTY_FIELD_REALNAME = 
"knownvisitor-ntlm.field.realname";
+   private static final String PROPERTY_FIELD_USERNAME = 
"knownvisitor-ntlm.field.username";
+   private static final String PROPERTY_LOGONNAME = 
"knownvisitor-ntlm.logonname";
+   private static final String PROPERTY_LOGONPASSWORD = 
"knownvisitor-ntlm.logonpassword";
+   private static final String PROPERTY_SEARCHDN = 
"knownvisitor-ntlm.searchDN";
+
+   private static final String PROPERTY_BASIC_AUTH = 
"knownvisitor-ntlm.basic-authentication";
+   private static final String PROPERTY_NTLM_AUTH = 
"knownvisitor-ntlm.ntlm-authentication";
+
+   public NtlmKnownVisitorModule() {
+      // nothing
+   }
+
+   @Override
+   public void init() {
+      KnownVisitorModule.setInstance(this);
+   }
+
+   public String getDomainController() {
+      return getProperty(PROPERTY_DOMAIN_CONTROLLER);
+   }
+
+   public String getDomain() {
+      return getProperty(PROPERTY_DOMAIN);
+   }
+   
+   public boolean isEnabled() {
+      String property = PropertiesUtil.getProperty(PROPERTY_ENABLED);
+      if (property != null) {
+         return Boolean.parseBoolean(property);
+      }
+      return super.isEnabled();
+   }
+   
+   public boolean offerNtlm(HttpServletRequest req) {
+      String property = PropertiesUtil.getProperty(PROPERTY_NTLM_AUTH);
+      if (StringUtils.isNotBlank(property)) {
+         return Boolean.parseBoolean(property);
+      }
+      return false;
+   }
+
+   
+   public List<String> getIpExceptions() {
+      List<String> property = 
PropertiesUtil.getPropertyAsList(PROPERTY_IPEXCEPTIONS);
+      if (property != null && !property.isEmpty()) {
+         return property;
+      }
+      return super.getIpExceptions();
+   }
+   
+   @Override
+   public String getBasicAuth() {
+      return PropertiesUtil.getProperty(PROPERTY_BASIC_AUTH);
+   }
+   
+   @Override
+   public String getLdapServer() {
+      String ldapServer = super.getLdapServer();
+      if (StringUtils.isNotBlank(ldapServer)) {
+         return ldapServer;
+      }
+      return getDomainController();
+   }
+   
+   public String getLdapPassword() {
+      String property = getProperty(PROPERTY_LOGONPASSWORD);
+      if (StringUtils.isNotBlank(property)) {
+         return property;
+      }
+      return super.getLdapPassword();
+   }
+
+   public String getLdapPrincipal() {
+      String property = getProperty(PROPERTY_LOGONNAME);
+      if (StringUtils.isNotBlank(property)) {
+         return "cn=" + property + "," + getLdapBaseDN();
+      }
+      return super.getLdapPrincipal();
+   }
+
+   public String getLdapBaseDN() {
+      String property = getProperty(PROPERTY_SEARCHDN);
+      if (StringUtils.isNotBlank(property)) {
+         return property;
+      }
+      return super.getLdapBaseDN();
+   }
+
+   public String getLdapUsernameField() {
+      String property = getProperty(PROPERTY_FIELD_USERNAME);
+      if (StringUtils.isNotBlank(property)) {
+         return property;
+      }
+      return super.getLdapUsernameField();
+   }
+
+   public String getLdapEmailField() {
+      String property = getProperty(PROPERTY_FIELD_EMAIL);
+      if (StringUtils.isNotBlank(property)) {
+         return property;
+      }
+      return super.getLdapEmailField();
+   }
+
+   public String getLdapRealnameField() {
+      String property = getProperty(PROPERTY_FIELD_REALNAME);
+      if (StringUtils.isNotBlank(property)) {
+         return property;
+      }
+      return super.getLdapRealnameField();
+   }
+   
+}

Deleted: 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmVisitor.java
===================================================================
--- 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmVisitor.java
     2009-05-20 15:14:26 UTC (rev 35328)
+++ 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmVisitor.java
     2009-05-20 15:14:29 UTC (rev 35329)
@@ -1,41 +0,0 @@
-package com.finalist.cmsc.knownvisitor.ntlm;
-
-import com.finalist.cmsc.knownvisitor.Visitor;
-
-public class NtlmVisitor extends Visitor {
-
-   private String identifier;
-   private String displayName;
-   private String email;
-
-
-   public String getIdentifier() {
-      return identifier;
-   }
-
-
-   public String getDisplayName() {
-      return displayName;
-   }
-
-
-   public void setDisplayName(String displayName) {
-      this.displayName = displayName;
-   }
-
-
-   public void setIdentifier(String identifier) {
-      this.identifier = identifier;
-   }
-
-
-   public String getEmail() {
-      return email;
-   }
-
-
-   public void setEmail(String email) {
-      this.email = email;
-   }
-
-}

Modified: 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmVisitorFilter.java
===================================================================
--- 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmVisitorFilter.java
       2009-05-20 15:14:26 UTC (rev 35328)
+++ 
CMSContainer/branches/b1_6/CMSContainer_Modules/knownvisitor-ntlm/src/java/com/finalist/cmsc/knownvisitor/ntlm/NtlmVisitorFilter.java
       2009-05-20 15:14:29 UTC (rev 35329)
@@ -1,223 +1,170 @@
-package com.finalist.cmsc.knownvisitor.ntlm;
-
-import java.io.IOException;
-import java.util.List;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
-
-import jcifs.Config;
-import jcifs.UniAddress;
-import jcifs.http.NtlmSsp;
-import jcifs.smb.*;
-import jcifs.util.Base64;
-
-import org.apache.commons.lang.StringUtils;
-import org.mmbase.util.logging.Logger;
-import org.mmbase.util.logging.Logging;
-
-import com.finalist.cmsc.knownvisitor.KnownVisitorModule;
-import com.finalist.cmsc.mmbase.PropertiesUtil;
-
-/**
- * @author Freek Punt, Finalist IT Group
- * @author Jeoffrey Bakker, Finalist IT Group
- */
-public class NtlmVisitorFilter implements Filter {
-   private static final String realm = "jCIFS";
-
-   private static final Logger log = 
Logging.getLoggerInstance(NtlmVisitorFilter.class);
-
-
-   public void init(FilterConfig filterConfig) {
-
-      /*
-       * Set jcifs properties we know we want; soTimeout and cachePolicy to
-       * 10min.
-       */
-      Config.setProperty("jcifs.smb.client.soTimeout", "300000");
-      Config.setProperty("jcifs.netbios.cachePolicy", "1200");
-   }
-
-
-   public void destroy() {
-      // nothing
-   }
-
-
-   /**
-    * This method simply calls <tt>negotiate( req, resp, false )</tt> and then
-    * <tt>chain.doFilter</tt>. You can override and call negotiate manually
-    * to achive a variety of different behavior.
-    */
-   public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException,
-         ServletException {
-      final HttpServletRequest req = (HttpServletRequest) request;
-      final HttpServletResponse resp = (HttpServletResponse) response;
-
-      if (isEnabled()) {
-         List<String> exceptions = getIpExceptions();
-         if (!exceptions.isEmpty()) {
-            String clientIp = req.getHeader("X-Forwarded-For");
-            if (StringUtils.isBlank(clientIp)) {
-               // not behind a proxy or mod_proxy
-               clientIp = request.getRemoteAddr();
-            }
-            if (exceptions.contains(clientIp)) {
-               chain.doFilter(req, resp);
-               return;
-            }
-         }
-
-         if (!negotiate(req, resp, false)) {
-            return;
-         }
-      }
-      chain.doFilter(req, resp);
-   }
-
-
-   /**
-    * Negotiate password hashes with MSIE clients using NTLM SSP
-    * 
-    * @param req
-    *           The servlet request
-    * @param resp
-    *           The servlet response
-    * @param skipAuthentication
-    *           If true the negotiation is only done if it is initiated by the
-    *           client (MSIE post requests after successful NTLM SSP
-    *           authentication). If false and the user has not been
-    *           authenticated yet the client will be forced to send an
-    *           authentication (server sends
-    *           HttpServletResponse.SC_UNAUTHORIZED).
-    * @return True if the negotiation is complete, otherwise false
-    */
-   protected boolean negotiate(HttpServletRequest req, HttpServletResponse 
resp, boolean skipAuthentication)
-         throws IOException, ServletException {
-      UniAddress dc;
-      String msg;
-      NtlmPasswordAuthentication ntlm = null;
-      msg = req.getHeader("Authorization");
-      boolean offerBasic = offerBasic(req);
-
-      log.debug("Message: " + msg);
-      if (msg != null && (msg.startsWith("NTLM ") || (offerBasic && 
msg.startsWith("Basic ")))) {
-         if (msg.startsWith("NTLM ")) {
-            log.debug("Message starts with NTLM.");
-            HttpSession ssn = req.getSession();
-            byte[] challenge;
-
-            dc = UniAddress.getByName(getDomainController(), true);
-            challenge = SmbSession.getChallenge(dc);
-
-            if ((ntlm = NtlmSsp.authenticate(req, resp, challenge)) == null) {
-               return false;
-            }
-            /* negotiation complete, remove the challenge object */
-            log.debug("negotiation complete, remove the challenge object.");
-            ssn.removeAttribute("NtlmHttpChal");
-         }
-         else {
-            log.debug("Message starts with Basic.");
-            String auth = new String(Base64.decode(msg.substring(6)), 
"US-ASCII");
-            int index = auth.indexOf(':');
-            String user = (index != -1) ? auth.substring(0, index) : auth;
-            String password = (index != -1) ? auth.substring(index + 1) : "";
-            index = user.indexOf('\\');
-            if (index == -1)
-               index = user.indexOf('/');
-            
-            String domain;
-            if (index == -1) {
-                domain = 
PropertiesUtil.getProperty(NtlmKnownVisitorModule.PROPERTY_DOMAIN);
-            } else {
-                domain = user.substring(0, index);
-            }
-
-            user = (index != -1) ? user.substring(index + 1) : user;
-            ntlm = new NtlmPasswordAuthentication(domain, user, password);
-            dc = UniAddress.getByName(getDomainController(), true);
-         }
-         try {
-
-            SmbSession.logon(dc, ntlm);
-
-            if (log.isDebugEnabled()) {
-               log.debug("NtlmHttpFilter: " + ntlm + " successfully 
authenticated against " + dc);
-            }
-         }
-         catch (SmbAuthException sae) {
-            if (log.isServiceEnabled()) {
-               log.service("NtlmHttpFilter: " + ntlm.getName() + ": 0x"
-                     + jcifs.util.Hexdump.toHexString(sae.getNtStatus(), 8) + 
": " + sae);
-            }
-            if (sae.getNtStatus() == NtStatus.NT_STATUS_ACCESS_VIOLATION) {
-               /*
-                * Server challenge no longer valid for externally supplied
-                * password hashes.
-                */
-               HttpSession ssn = req.getSession(false);
-               if (ssn != null) {
-                  ssn.removeAttribute("NtlmHttpAuth");
-               }
-            }
-            // lets try mmbase authentication now
-            return true;
-         }
-         req.getSession().setAttribute("NtlmHttpAuth", ntlm);
-         ((NtlmKnownVisitorModule) 
KnownVisitorModule.getInstance()).justLoggedIn(req, ntlm);
-      }
-      else {
-         if (!skipAuthentication) {
-            HttpSession ssn = req.getSession(false);
-            if (ssn == null || (ntlm = (NtlmPasswordAuthentication) 
ssn.getAttribute("NtlmHttpAuth")) == null) {
-               log.debug("Not NTLM authenticated, starting authentication.");
-               resp.setHeader("WWW-Authenticate", "NTLM");
-               if (offerBasic) {
-                  resp.addHeader("WWW-Authenticate", "Basic realm=\"" + realm 
+ "\"");
-               }
-               resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
-               resp.setContentLength(0);
-               resp.flushBuffer();
-               return false;
-            }
-         }
-      }
-
-      return ntlm != null;
-   }
-
-
-   private boolean offerBasic(HttpServletRequest req) {
-      boolean offerBasic = req.isSecure();
-      if (!offerBasic) {
-         String basic = 
PropertiesUtil.getProperty(NtlmKnownVisitorModule.PROPERTY_BASIC_AUTH);
-         if (StringUtils.isBlank(basic) || "secure".equalsIgnoreCase(basic)) {
-            return false;
-         }
-         else {
-            // basic authentication is not forced to be on secured urls and 
the current request is not secured
-            // This does not mean that the url arrived at the webserver was 
not secured. The webserver could
-            // proxy the request without using the secured flag.
-            return true;
-         }
-      }
-      return offerBasic;
-   }
-
-
-   private boolean isEnabled() {
-      return 
Boolean.parseBoolean(PropertiesUtil.getProperty(NtlmKnownVisitorModule.PROPERTY_ENABLED));
-   }
-
-
-   private String getDomainController() {
-      return 
PropertiesUtil.getProperty(NtlmKnownVisitorModule.PROPERTY_DOMAIN_CONTROLLER);
-   }
-
-   private List<String> getIpExceptions() {
-       return 
PropertiesUtil.getPropertyAsList(NtlmKnownVisitorModule.PROPERTY_IPEXCEPTIONS);
-   }
-
-}
+package com.finalist.cmsc.knownvisitor.ntlm;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import jcifs.Config;
+import jcifs.UniAddress;
+import jcifs.http.NtlmSsp;
+import jcifs.smb.*;
+import jcifs.util.Base64;
+
+import org.apache.commons.lang.StringUtils;
+import org.mmbase.util.logging.Logger;
+import org.mmbase.util.logging.Logging;
+
+import com.finalist.cmsc.knownvisitor.*;
+
+/**
+ * @author Freek Punt, Finalist IT Group
+ * @author Jeoffrey Bakker, Finalist IT Group
+ */
+public class NtlmVisitorFilter extends VisitorFilter {
+
+   private static final Logger log = 
Logging.getLoggerInstance(NtlmVisitorFilter.class);
+
+   private static final String NTLM_HTTP_AUTH = "NtlmHttpAuth";
+
+
+   public void init(FilterConfig filterConfig) {
+      super.init(filterConfig);
+      /*
+       * Set jcifs properties we know we want; soTimeout and cachePolicy to
+       * 10min.
+       */
+      Config.setProperty("jcifs.smb.client.soTimeout", "300000");
+      Config.setProperty("jcifs.netbios.cachePolicy", "1200");
+   }
+
+   /**
+    * Negotiate password hashes with MSIE clients using NTLM SSP
+    * 
+    * @param req The servlet request
+    * @param resp The servlet response
+    * @return True if the negotiation is complete, otherwise false
+    */
+   protected boolean negotiate(HttpServletRequest req, HttpServletResponse 
resp)
+         throws IOException, ServletException {
+      String msg = req.getHeader("Authorization");
+      NtlmKnownVisitorModule module = (NtlmKnownVisitorModule) 
KnownVisitorModule.getInstance();
+      boolean offerBasic = module.offerBasic(req);
+      boolean offerNtlm = module.offerNtlm(req);
+      log.debug("Message: " + msg);
+      
+      NtlmPasswordAuthentication ntlm = null;
+      
+      if (msg != null && (offerNtlm && msg.startsWith("NTLM ") || (offerBasic 
&& msg.startsWith("Basic ")))) {
+         String domainController = getDomainController();
+         UniAddress dc = UniAddress.getByName(domainController, true);
+         if (msg.startsWith("NTLM ")) {
+            log.debug("Message starts with NTLM.");
+            HttpSession ssn = req.getSession();
+            byte[] challenge = SmbSession.getChallenge(dc);
+
+            if ((ntlm = NtlmSsp.authenticate(req, resp, challenge)) == null) {
+               return false;
+            }
+            /* negotiation complete,*/
+            log.debug("negotiation complete");
+         }
+         else {
+            ntlm = createBasicAuthToken(msg);
+         }
+         try {
+            SmbSession.logon(dc, ntlm);
+            if (log.isDebugEnabled()) {
+               log.debug("NtlmHttpFilter: " + ntlm + " successfully 
authenticated against " + dc);
+            }
+         }
+         catch (SmbAuthException sae) {
+            if (log.isServiceEnabled()) {
+               log.service("NtlmHttpFilter: " + ntlm.getName() + ": 0x"
+                     + jcifs.util.Hexdump.toHexString(sae.getNtStatus(), 8) + 
": " + sae);
+            }
+            if (sae.getNtStatus() == NtStatus.NT_STATUS_ACCESS_VIOLATION) {
+               /*
+                * Server challenge no longer valid for externally supplied
+                * password hashes.
+                */
+               HttpSession ssn = req.getSession(false);
+               if (ssn != null) {
+                  ssn.removeAttribute(NTLM_HTTP_AUTH);
+               }
+            }
+            else{
+               if (sae.getNtStatus() != NtStatus.NT_STATUS_LOGON_FAILURE) {
+                  log.info("SmbAuthException" + sae.getNtStatus() + " : " + 
sae.getMessage());
+               }
+            }
+            sendChallenge(resp, module, offerBasic, offerNtlm);
+            return false;
+         }
+         req.getSession().setAttribute(NTLM_HTTP_AUTH, ntlm);
+         String username = ntlm.getUsername();
+         justLoggedIn(req, username);
+      }
+      else {
+         HttpSession ssn = req.getSession(false);
+         if (ssn == null || (ntlm = (NtlmPasswordAuthentication) 
ssn.getAttribute(NTLM_HTTP_AUTH)) == null) {
+            log.debug("Not NTLM authenticated, starting authentication.");
+            sendChallenge(resp, module, offerBasic, offerNtlm);
+            return false;
+         }
+      }
+
+      return ntlm != null;
+   }
+
+   private void sendChallenge(HttpServletResponse resp, NtlmKnownVisitorModule 
module,
+         boolean offerBasic, boolean offerNtlm) throws IOException {
+      if (offerNtlm) {
+         resp.setHeader("WWW-Authenticate", "NTLM");
+      }
+      if (offerBasic) {
+         String realm = module.getRealm();
+         if (StringUtils.isBlank(realm)) {
+            realm = "CMS Container";
+         }
+         resp.addHeader("WWW-Authenticate", "Basic realm=\"" + realm + "\"");
+      }
+      resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+      resp.setContentLength(0);
+      resp.flushBuffer();
+   }
+
+   private NtlmPasswordAuthentication createBasicAuthToken(String msg)
+         throws UnsupportedEncodingException {
+      NtlmPasswordAuthentication ntlm;
+      log.debug("Message starts with Basic.");
+      String auth = new String(Base64.decode(msg.substring(6)), "US-ASCII");
+      int index = auth.indexOf(':');
+      String user = (index != -1) ? auth.substring(0, index) : auth;
+      String password = (index != -1) ? auth.substring(index + 1) : "";
+      index = user.indexOf('\\');
+      if (index == -1)
+         index = user.indexOf('/');
+      
+      String domain;
+      if (index == -1) {
+          domain = getDomain();
+      } else {
+          domain = user.substring(0, index);
+      }
+
+      user = (index != -1) ? user.substring(index + 1) : user;
+      ntlm = new NtlmPasswordAuthentication(domain, user, password);
+      return ntlm;
+   }
+
+   private String getDomainController() {
+      return ((NtlmKnownVisitorModule) 
KnownVisitorModule.getInstance()).getDomainController();
+   }
+
+   private String getDomain() {
+      return ((NtlmKnownVisitorModule) 
KnownVisitorModule.getInstance()).getDomain();
+   }
+
+}

_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs

Reply via email to