You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by co...@apache.org on 2014/06/23 18:20:14 UTC

svn commit: r1604848 - /syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/LDAPPasswordPropagationActions.java

Author: coheigea
Date: Mon Jun 23 16:20:14 2014
New Revision: 1604848

URL: http://svn.apache.org/r1604848
Log:
[SYNCOPE-505] - Adding initial LDAPPropagationActions class

Added:
    syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/LDAPPasswordPropagationActions.java

Added: syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/LDAPPasswordPropagationActions.java
URL: http://svn.apache.org/viewvc/syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/LDAPPasswordPropagationActions.java?rev=1604848&view=auto
==============================================================================
--- syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/LDAPPasswordPropagationActions.java (added)
+++ syncope/trunk/core/src/main/java/org/apache/syncope/core/propagation/impl/LDAPPasswordPropagationActions.java Mon Jun 23 16:20:14 2014
@@ -0,0 +1,127 @@
+/*
+ * 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.apache.syncope.core.propagation.impl;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.syncope.common.types.AttributableType;
+import org.apache.syncope.common.types.CipherAlgorithm;
+import org.apache.syncope.common.types.ConnConfProperty;
+import org.apache.syncope.core.persistence.beans.ConnInstance;
+import org.apache.syncope.core.persistence.beans.PropagationTask;
+import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
+import org.apache.syncope.core.persistence.dao.UserDAO;
+import org.apache.syncope.core.propagation.DefaultPropagationActions;
+import org.apache.syncope.core.propagation.PropagationTaskExecutor;
+import org.identityconnectors.common.security.GuardedString;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.AttributeBuilder;
+import org.identityconnectors.framework.common.objects.AttributeUtil;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.identityconnectors.framework.common.objects.OperationalAttributes;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.codec.Base64;
+import org.springframework.security.crypto.codec.Hex;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Propagate a non-cleartext password out to a resource, if the PropagationManager has not already
+ * added a password. The CipherAlgorithm associated with the password must match the password
+ * hash algorithm property of the LDAP Connector.
+ */
+public class LDAPPasswordPropagationActions extends DefaultPropagationActions {
+    
+    private static final String CLEARTEXT = "CLEARTEXT";
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Transactional(readOnly = true)
+    @Override
+    public void before(final PropagationTask task, final ConnectorObject beforeObj) {
+        super.before(task, beforeObj);
+
+        if (AttributableType.USER == task.getSubjectType()) {
+            SyncopeUser user = userDAO.find(task.getSubjectId());
+            
+            if (user != null && user.getPassword() != null) {
+                Attribute missing = AttributeUtil.find(
+                        PropagationTaskExecutor.MANDATORY_MISSING_ATTR_NAME,
+                        task.getAttributes());
+                
+                ConnInstance connInstance = task.getResource().getConnector();
+                String cipherAlgorithm = getCipherAlgorithm(connInstance);
+                if (missing != null && missing.getValue() != null && missing.getValue().size() == 1
+                        && missing.getValue().get(0).equals(OperationalAttributes.PASSWORD_NAME)
+                        && cipherAlgorithmMatches(getCipherAlgorithm(connInstance), user.getCipherAlgorithm())) {
+
+                    String password = user.getPassword().toLowerCase();
+                    byte[] decodedPassword = Hex.decode(password);
+                    byte[] base64EncodedPassword = Base64.encode(decodedPassword);
+                    
+                    String cipherPlusPassword = 
+                        ("{" + cipherAlgorithm.toLowerCase() + "}" + new String(base64EncodedPassword));
+                    
+                    Attribute passwordAttribute = AttributeBuilder.buildPassword(
+                            new GuardedString(cipherPlusPassword.toCharArray()));
+
+                    Set<Attribute> attributes = new HashSet<Attribute>(task.getAttributes());
+                    attributes.add(passwordAttribute);
+                    attributes.remove(missing);
+
+                    task.setAttributes(attributes);
+                }
+            }
+        }
+    }
+    
+    private String getCipherAlgorithm(ConnInstance connInstance) {
+        String cipherAlgorithm = CLEARTEXT;
+        for (Iterator<ConnConfProperty> propertyIterator = connInstance.getConfiguration().iterator();
+                propertyIterator.hasNext();) {
+
+            ConnConfProperty property = propertyIterator.next();
+            if ("passwordHashAlgorithm".equals(property.getSchema().getName())
+                    && property.getValues() != null && !property.getValues().isEmpty()) {
+                return (String) property.getValues().get(0);
+            }
+        }
+        return cipherAlgorithm;
+    }
+    
+    private boolean cipherAlgorithmMatches(String connectorAlgorithm, CipherAlgorithm userAlgorithm) {
+        if (userAlgorithm == null) {
+            return false;
+        }
+    
+        if (connectorAlgorithm.equals(userAlgorithm.name())) {
+            return true;
+        }
+        
+        // Special check for "SHA" (user sync'd from LDAP)
+        if ("SHA".equals(connectorAlgorithm) && "SHA1".equals(userAlgorithm.name())) {
+            return true;
+        }
+        
+        return false;
+    }
+
+}