svn commit: r669994 - in /ofbiz/trunk: applications/party/config/ applications/party/webapp/partymgr/party/ framework/common/config/ framework/common/servicedef/ framework/common/src/org/ofbiz/common/login/ framework/security/config/ framework/security...

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r669994 - in /ofbiz/trunk: applications/party/config/ applications/party/webapp/partymgr/party/ framework/common/config/ framework/common/servicedef/ framework/common/src/org/ofbiz/common/login/ framework/security/config/ framework/security...

adrianc
Author: adrianc
Date: Fri Jun 20 10:09:19 2008
New Revision: 669994

URL: http://svn.apache.org/viewvc?rev=669994&view=rev
Log:
Added LDAP user authentication, based on work contributed by Mohamed Amine Azzi and Torsten Schlabach - https://issues.apache.org/jira/browse/OFBIZ-811.

Internationalization note: this commit contains new UI labels.

Added:
    ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LdapAuthenticationServices.java   (with props)
    ofbiz/trunk/framework/security/config/jndiLdap.properties   (with props)
Modified:
    ofbiz/trunk/applications/party/config/PartyUiLabels.xml
    ofbiz/trunk/applications/party/webapp/partymgr/party/PartyForms.xml
    ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml
    ofbiz/trunk/framework/common/servicedef/services.xml
    ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java
    ofbiz/trunk/framework/security/config/security.properties
    ofbiz/trunk/framework/security/entitydef/entitymodel.xml

Modified: ofbiz/trunk/applications/party/config/PartyUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/party/config/PartyUiLabels.xml?rev=669994&r1=669993&r2=669994&view=diff
==============================================================================
--- ofbiz/trunk/applications/party/config/PartyUiLabels.xml (original)
+++ ofbiz/trunk/applications/party/config/PartyUiLabels.xml Fri Jun 20 10:09:19 2008
@@ -1043,6 +1043,9 @@
         <value xml:lang="th">ผลรวมของปีที่มีประสบการณ์การทำงาน</value>
         <value xml:lang="zh">工作经历年数合计</value>
     </property>
+    <property key="FormFieldTitle_userLdapDn">
+        <value xml:lang="en">LDAP Distinguished Name</value>
+    </property>
     <property key="FormFieldTitle_userLoginId">
         <value xml:lang="en">User Login Id</value>
         <value xml:lang="fr">Utilisateur de connexion</value>

Modified: ofbiz/trunk/applications/party/webapp/partymgr/party/PartyForms.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/party/webapp/partymgr/party/PartyForms.xml?rev=669994&r1=669993&r2=669994&view=diff
==============================================================================
--- ofbiz/trunk/applications/party/webapp/partymgr/party/PartyForms.xml (original)
+++ ofbiz/trunk/applications/party/webapp/partymgr/party/PartyForms.xml Fri Jun 20 10:09:19 2008
@@ -162,9 +162,13 @@
 
     <form name="updateUserLoginSecurity" type="single" target="updateUserLoginSecurity" default-map-name="editUserLogin"
         header-row-style="header-row" default-table-style="basic-table">
+        <actions>
+            <property-to-field field="ldapEnabled" resource="security" property="security.ldap.enable"/>
+        </actions>
         <auto-fields-service service-name="updateUserLoginSecurity"/>
         <field name="partyId"><hidden/></field>
         <field name="userLoginId"><hidden/></field>
+        <field name="userLdapDn" use-when="&quot;true&quot;.equals(ldapEnabled)"><text/></field>
         <field name="submitButton" title="${uiLabelMap.CommonSave}" widget-style="smallSubmit"><submit button-type="text-link"/></field>
         <field name="cancelLink" title="${uiLabelMap.CommonEmptyHeader}" widget-style="smallSubmit"><hyperlink target="${donePage}?partyId=${partyId}" also-hidden="false" description="${uiLabelMap.CommonCancelDone}"/></field>
     </form>

Modified: ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml?rev=669994&r1=669993&r2=669994&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml (original)
+++ ofbiz/trunk/framework/common/config/SecurityextUiLabels.xml Fri Jun 20 10:09:19 2008
@@ -611,4 +611,7 @@
         <value xml:lang="th">มันจะไม่สามารถใช้ได้อีกครั้ง ${reEnableTime}.</value>
         <value xml:lang="zh">将重新启用 ${reEnableTime}。</value>
     </property>
+    <property key="loginservices.ldap_authentication_failed">
+        <value xml:lang="en">LDAP authentication failed.</value>
+    </property>
 </resource>

Modified: ofbiz/trunk/framework/common/servicedef/services.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/servicedef/services.xml?rev=669994&r1=669993&r2=669994&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/servicedef/services.xml (original)
+++ ofbiz/trunk/framework/common/servicedef/services.xml Fri Jun 20 10:09:19 2008
@@ -398,6 +398,7 @@
         <attribute name="enabled" type="String" mode="IN" optional="false"/>
         <attribute name="disabledDateTime" type="java.sql.Timestamp" mode="IN" optional="true"/>
         <attribute name="successiveFailedLogins" type="Long" mode="IN" optional="true"/>
+        <attribute name="userLdapDn" type="String" mode="IN" optional="true"/>
     </service>
 
     <!-- common permission services -->

Added: ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LdapAuthenticationServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LdapAuthenticationServices.java?rev=669994&view=auto
==============================================================================
--- ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LdapAuthenticationServices.java (added)
+++ ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LdapAuthenticationServices.java Fri Jun 20 10:09:19 2008
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+
+package org.ofbiz.common.login;
+
+import java.util.Map;
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.transaction.Transaction;
+
+import org.ofbiz.base.crypto.HashCrypt;
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilProperties;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.entity.GenericDelegator;
+import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.transaction.GenericTransactionException;
+import org.ofbiz.entity.transaction.TransactionUtil;
+import org.ofbiz.service.DispatchContext;
+
+/** LDAP Authentication Services.
+ */
+public class LdapAuthenticationServices {
+
+    public static final String module = LdapAuthenticationServices.class.getName();
+
+    public static boolean userLogin(DispatchContext ctx, Map<String, Object> context) {
+        Debug.logVerbose("Starting LDAP authentication", module);
+        Properties env = UtilProperties.getProperties("jndiLdap");
+        String username = (String) context.get("login.username");
+        if (username == null) {
+            username = (String) context.get("username");
+        }
+        String password = (String) context.get("login.password");
+        if (password == null) {
+            password = (String) context.get("password");
+        }
+        String dn = null;
+        GenericDelegator delegator = ctx.getDelegator();
+        boolean isServiceAuth = context.get("isServiceAuth") != null && ((Boolean) context.get("isServiceAuth")).booleanValue();
+        GenericValue userLogin = null;
+        try {
+            userLogin = delegator.findOne("UserLogin", isServiceAuth, "userLoginId", username);
+        } catch (GenericEntityException e) {
+            Debug.logWarning(e, "", module);
+        }
+        if (userLogin != null) {
+            dn = userLogin.getString("userLdapDn");
+        }
+        if (UtilValidate.isEmpty(dn)) {
+            String dnTemplate = (String) env.get("ldap.dn.template");
+            if (dnTemplate != null) {
+                dn = dnTemplate.replace("%u", username);
+            }
+            Debug.logVerbose("Using DN template: " + dn, module);
+        } else {
+            Debug.logVerbose("Using UserLogin.userLdapDn: " + dn, module);
+        }
+        env.put(Context.SECURITY_PRINCIPAL, dn);
+        env.put(Context.SECURITY_CREDENTIALS, password);
+        try {
+            // Create initial context
+            DirContext ldapCtx = new InitialDirContext(env);
+            ldapCtx.close();
+        } catch (NamingException e) {
+            Debug.logVerbose("LDAP authentication failed: " + e.getMessage(), module);
+            return false;
+        }
+        Debug.logVerbose("LDAP authentication succeeded", module);
+        if (!"true".equals(env.get("ldap.synchronize.passwords"))) {
+            return true;
+        }
+        // Synchronize user's OFBiz password with user's LDAP password
+        if (userLogin != null) {
+            boolean useEncryption = "true".equals(UtilProperties.getPropertyValue("security.properties", "password.encrypt"));
+            String encodedPassword = useEncryption ? HashCrypt.getDigestHash(password, LoginServices.getHashType()) : password;
+            String encodedPasswordOldFunnyHexEncode = useEncryption ? HashCrypt.getDigestHashOldFunnyHexEncode(password, LoginServices.getHashType()) : password;
+            String encodedPasswordUsingDbHashType = encodedPassword;
+            String currentPassword = userLogin.getString("currentPassword");
+            if (useEncryption && currentPassword != null && currentPassword.startsWith("{")) {
+                String dbHashType = HashCrypt.getHashTypeFromPrefix(currentPassword);
+                if (dbHashType != null) {
+                    encodedPasswordUsingDbHashType = HashCrypt.getDigestHash(password, dbHashType);
+                }
+            }
+            boolean samePassword = currentPassword != null &&
+                    (HashCrypt.removeHashTypePrefix(encodedPassword).equals(HashCrypt.removeHashTypePrefix(currentPassword)) ||
+                            HashCrypt.removeHashTypePrefix(encodedPasswordOldFunnyHexEncode).equals(HashCrypt.removeHashTypePrefix(currentPassword)) ||
+                            HashCrypt.removeHashTypePrefix(encodedPasswordUsingDbHashType).equals(HashCrypt.removeHashTypePrefix(currentPassword)) ||
+                        ("true".equals(UtilProperties.getPropertyValue("security.properties", "password.accept.encrypted.and.plain")) && password.equals(currentPassword)));
+            if (!samePassword) {
+                Debug.logVerbose("Starting password synchronization", module);
+                userLogin.set("currentPassword", useEncryption ? HashCrypt.getDigestHash(password, LoginServices.getHashType()) : password, false);
+                Transaction parentTx = null;
+                boolean beganTransaction = false;
+                try {
+                    try {
+                        parentTx = TransactionUtil.suspend();
+                    } catch (GenericTransactionException e) {
+                        Debug.logError(e, "Could not suspend transaction: " + e.getMessage(), module);
+                    }                                
+                    try {
+                        beganTransaction = TransactionUtil.begin();
+                        userLogin.store();
+                    } catch (GenericEntityException e) {
+                        Debug.logError(e, "Error saving UserLogin", module);
+                        try {
+                            TransactionUtil.rollback(beganTransaction, "Error saving UserLogin", e);
+                        } catch (GenericTransactionException e2) {
+                            Debug.logError(e2, "Could not rollback nested transaction: " + e2.getMessage(), module);
+                        }
+                    } finally {
+                        try {
+                            TransactionUtil.commit(beganTransaction);
+                            Debug.logVerbose("Password synchronized", module);
+                        } catch (GenericTransactionException e) {
+                            Debug.logError(e, "Could not commit nested transaction: " + e.getMessage(), module);
+                        }
+                    }
+                } finally {
+                    if (parentTx != null) {
+                        try {
+                            TransactionUtil.resume(parentTx);
+                            Debug.logVerbose("Resumed the parent transaction.", module);
+                        } catch (GenericTransactionException e) {
+                            Debug.logError(e, "Could not resume parent nested transaction: " + e.getMessage(), module);
+                        }
+                    }
+                }
+            }
+        }
+        return true;
+    }
+}

Propchange: ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LdapAuthenticationServices.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java?rev=669994&r1=669993&r2=669994&view=diff
==============================================================================
--- ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java (original)
+++ ofbiz/trunk/framework/common/src/org/ofbiz/common/login/LoginServices.java Fri Jun 20 10:09:19 2008
@@ -64,10 +64,22 @@
      * @return Map of results including (userLogin) GenericValue object
      */
     public static Map userLogin(DispatchContext ctx, Map context) {
-        Map result = FastMap.newInstance();
-        GenericDelegator delegator = ctx.getDelegator();
         Locale locale = (Locale) context.get("locale");
 
+        // Authenticate to LDAP if configured to do so
+        if ("true".equals(UtilProperties.getPropertyValue("security", "security.ldap.enable"))) {
+            if (!LdapAuthenticationServices.userLogin(ctx, context)) {
+                String errMsg = UtilProperties.getMessage(resource, "loginservices.ldap_authentication_failed", locale);
+                if ("true".equals(UtilProperties.getPropertyValue("security", "security.ldap.fail.login"))) {
+                    return ServiceUtil.returnError(errMsg);
+                } else {
+                    Debug.logInfo(errMsg, module);
+                }
+            }
+        }
+        
+        Map result = FastMap.newInstance();
+        GenericDelegator delegator = ctx.getDelegator();
         boolean useEncryption = "true".equals(UtilProperties.getPropertyValue("security.properties", "password.encrypt"));
 
         // if isServiceAuth is not specified, default to not a service auth
@@ -744,6 +756,9 @@
         if (context.containsKey("successiveFailedLogins")) {
             userLoginToUpdate.set("successiveFailedLogins", context.get("successiveFailedLogins"), true);
         }
+        if (context.containsKey("userLdapDn")) {
+            userLoginToUpdate.set("userLdapDn", context.get("userLdapDn"), true);
+        }
 
         // if was disabled and we are enabling it, clear disabledDateTime
         if (!wasEnabled && "Y".equals(context.get("enabled"))) {

Added: ofbiz/trunk/framework/security/config/jndiLdap.properties
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/config/jndiLdap.properties?rev=669994&view=auto
==============================================================================
--- ofbiz/trunk/framework/security/config/jndiLdap.properties (added)
+++ ofbiz/trunk/framework/security/config/jndiLdap.properties Fri Jun 20 10:09:19 2008
@@ -0,0 +1,38 @@
+###############################################################################
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+###############################################################################
+####
+# OFBiz LDAP Authentication Settings
+####
+
+# JNDI LDAP settings. Change the following line to
+# point to your LDAP server.
+java.naming.provider.url=ldap://localhost:389
+java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
+java.naming.security.authentication=simple
+com.sun.jndi.ldap.connect.timeout=5000
+
+# Distinguished Name template. This is used as a default if
+# UserLogin.userLdapDn is empty.
+# The %u placeholder will be replaced by the user's login name,
+# then the resulting string will be used to authenticate the user.
+ldap.dn.template=cn=%u,ou=system
+
+# The following property controls whether the user's OFBiz password
+# is synchronized with the user's LDAP password.
+ldap.synchronize.passwords=true

Propchange: ofbiz/trunk/framework/security/config/jndiLdap.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: ofbiz/trunk/framework/security/config/security.properties
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/config/security.properties?rev=669994&r1=669993&r2=669994&view=diff
==============================================================================
--- ofbiz/trunk/framework/security/config/security.properties (original)
+++ ofbiz/trunk/framework/security/config/security.properties Fri Jun 20 10:09:19 2008
@@ -60,6 +60,12 @@
 username.lowercase=false
 password.lowercase=false
 
+# -- Use LDAP for user authentication? --
+security.ldap.enable=false
+
+# -- Fail login if LDAP authentication fails? --
+security.ldap.fail.login=false
+
 # -- should we allow x509 certificate login
 security.login.cert.allow=true
 
@@ -70,4 +76,4 @@
 security.login.cert.pattern=^(\\w*\\s?\\w*)\\W*.*$
 
 # -- Hours after which EmailAdressVerification should expire
-email_verification.expire.hours=48
\ No newline at end of file
+email_verification.expire.hours=48

Modified: ofbiz/trunk/framework/security/entitydef/entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/security/entitydef/entitymodel.xml?rev=669994&r1=669993&r2=669994&view=diff
==============================================================================
--- ofbiz/trunk/framework/security/entitydef/entitymodel.xml (original)
+++ ofbiz/trunk/framework/security/entitydef/entitymodel.xml Fri Jun 20 10:09:19 2008
@@ -75,6 +75,9 @@
       <field name="lastTimeZone" type="id-long"></field>
       <field name="disabledDateTime" type="date-time"></field>
       <field name="successiveFailedLogins" type="numeric"></field>
+      <field name="userLdapDn" type="id-vlong-ne">
+          <description>The user's LDAP Distinguished Name - used for LDAP authentication</description>
+      </field>
       <prim-key field="userLoginId"/>
     </entity>
     <entity entity-name="UserLoginPasswordHistory"