]> git.argeo.org Git - lgpl/argeo-commons.git/commitdiff
Introduce LDIF parser
authorMathieu Baudier <mbaudier@argeo.org>
Mon, 24 Aug 2015 14:29:04 +0000 (14:29 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Mon, 24 Aug 2015 14:29:04 +0000 (14:29 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@8332 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

org.argeo.security.core/bnd.bnd
org.argeo.security.core/build.properties
org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifParserTest.java [new file with mode: 0644]
org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/test.ldif [new file with mode: 0644]
org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifParser.java [new file with mode: 0644]

index 9124816cb6dd5b20407b0449c8f3c483b89919b5..4d6f374a1c6981f8fd9a3650ba763323f61c975e 100644 (file)
@@ -2,4 +2,6 @@ Bundle-ActivationPolicy: lazy
 Import-Package:org.bouncycastle.*;resolution:=optional,\
 org.springframework.util,\
 javax.jcr.security,\
+org.apache.commons.codec,\
+org.apache.commons.codec.digest,\
 *
index 3ad70fd322c8dff6a1a0cb3918aefb371601abaf..1047348bbc028e6fbf3fef6acb67cadcb2f881c3 100644 (file)
@@ -2,5 +2,4 @@ source.. = src/,\
            ext/test/
 additional.bundles = org.junit,\
                      org.slf4j.commons.logging,\
-                     org.apache.commons.codec,\
                      org.springframework.security.core
diff --git a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifParserTest.java b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/LdifParserTest.java
new file mode 100644 (file)
index 0000000..dd32dca
--- /dev/null
@@ -0,0 +1,31 @@
+package org.argeo.osgi.useradmin;
+
+import java.util.SortedMap;
+
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.digest.DigestUtils;
+
+import junit.framework.TestCase;
+
+public class LdifParserTest extends TestCase {
+       public void testSimpleLdif() throws Exception {
+               LdifParser ldifParser = new LdifParser();
+               SortedMap<LdapName, Attributes> res = ldifParser.read(getClass()
+                               .getResourceAsStream("test.ldif"));
+               LdapName rootDn = new LdapName(
+                               "uid=root,ou=People,dc=demo,dc=example,dc=org");
+               Attributes rootAttributes = res.get(rootDn);
+               assertNotNull(rootAttributes);
+               assertEquals("Superuser", rootAttributes.get("description").get());
+               byte[] rawPwEntry = (byte[]) rootAttributes.get("userpassword").get();
+               assertEquals("{SHA}ieSV55Qc+eQOaYDRSha/AjzNTJE=",
+                               new String(rawPwEntry));
+               byte[] hashedPassword = DigestUtils.sha1("demo".getBytes());
+               assertEquals("{SHA}" + Base64.encodeBase64String(hashedPassword),
+                               new String(rawPwEntry));
+
+       }
+}
diff --git a/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/test.ldif b/org.argeo.security.core/ext/test/org/argeo/osgi/useradmin/test.ldif
new file mode 100644 (file)
index 0000000..0d2e8ba
--- /dev/null
@@ -0,0 +1,47 @@
+dn: dc=demo,dc=example,dc=org
+objectClass: domain
+objectClass: extensibleObject
+objectClass: top
+dc: demo
+
+dn: ou=Roles,dc=demo,dc=example,dc=org
+objectClass: organizationalUnit
+objectClass: top
+ou: Roles
+
+dn: ou=People,dc=demo,dc=example,dc=org
+objectClass: organizationalUnit
+objectClass: top
+ou: People
+
+dn: uid=demo,ou=People,dc=demo,dc=example,dc=org
+objectClass: organizationalPerson
+objectClass: person
+objectClass: inetOrgPerson
+objectClass: top
+cn: demo User
+description: Demo user
+givenname: Demo
+mail: demo@localhost
+sn: User
+uid: demo
+userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9
+
+dn: uid=root,ou=People,dc=demo,dc=example,dc=org
+objectClass: person
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: top
+cn: demo User
+description: Superuser
+givenname: Root
+mail: root@localhost
+sn: Root
+uid: root
+userpassword:: e1NIQX1pZVNWNTVRYytlUU9hWURSU2hhL0Fqek5USkU9
+
+dn: cn=admin,ou=Roles,dc=demo,dc=example,dc=org
+objectClass: groupOfNames
+objectClass: top
+cn: admin
+member: uid=root,ou=People,dc=demo,dc=example,dc=org
diff --git a/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifParser.java b/org.argeo.security.core/src/org/argeo/osgi/useradmin/LdifParser.java
new file mode 100644 (file)
index 0000000..1e9390a
--- /dev/null
@@ -0,0 +1,105 @@
+package org.argeo.osgi.useradmin;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.naming.InvalidNameException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.ldap.LdapName;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/** Basic LDIF parser. */
+class LdifParser {
+       private final static Log log = LogFactory.getLog(LdifParser.class);
+
+       SortedMap<LdapName, Attributes> read(InputStream in) throws IOException {
+               SortedMap<LdapName, Attributes> res = new TreeMap<LdapName, Attributes>();
+               try {
+                       List<String> lines = IOUtils.readLines(in);
+
+                       LdapName currentDn = null;
+                       Attributes currentAttributes = null;
+                       StringBuilder currentEntry = new StringBuilder();
+
+                       readLines: for (String line : lines) {
+                               if (line.startsWith(" ")) {
+                                       currentEntry.append(line.substring(1));
+                                       continue readLines;
+                               } else {
+                                       if (currentEntry.length() != 0) {
+                                               // read previous attribute
+                                               StringBuilder attrId = new StringBuilder(8);
+                                               boolean isBase64 = false;
+                                               readAttrId: for (int i = 0; i < currentEntry.length(); i++) {
+                                                       char c = currentEntry.charAt(i);
+                                                       if (c == ':') {
+                                                               if (i + 1 < currentEntry.length()
+                                                                               && currentEntry.charAt(i + 1) == ':')
+                                                                       isBase64 = true;
+                                                               currentEntry.delete(0, i + (isBase64 ? 2 : 1));
+                                                               break readAttrId;
+                                                       } else {
+                                                               attrId.append(c);
+                                                       }
+                                               }
+
+                                               String attributeId = attrId.toString();
+                                               String cleanValueStr = currentEntry.toString().trim();
+                                               Object attributeValue = isBase64 ? Base64
+                                                               .decodeBase64(cleanValueStr) : cleanValueStr;
+
+                                               // manage DN attributes
+                                               if (attributeId.equals("dn")) {
+                                                       if (currentDn != null) {
+                                                               Attributes previous = res.put(currentDn,
+                                                                               currentAttributes);
+                                                               if (previous != null) {
+                                                                       log.warn("There was already an entry with DN "
+                                                                                       + currentDn
+                                                                                       + ", which has been discarded by a subsequent one.");
+                                                               }
+                                                       }
+
+                                                       try {
+                                                               currentDn = new LdapName(
+                                                                               attributeValue.toString());
+                                                               currentAttributes = new BasicAttributes();
+                                                       } catch (InvalidNameException e) {
+                                                               log.error(attributeValue
+                                                                               + " not a valid DN, skipping the entry.");
+                                                               currentDn = null;
+                                                               currentAttributes = null;
+                                                       }
+                                               }
+
+                                               // store attribute
+                                               if (currentAttributes != null) {
+                                                       Attribute attribute = currentAttributes
+                                                                       .get(attributeId);
+                                                       if (attribute == null) {
+                                                               attribute = new BasicAttribute(attributeId);
+                                                               currentAttributes.put(attribute);
+                                                       }
+                                                       attribute.add(attributeValue);
+                                               }
+                                               currentEntry = new StringBuilder();
+                                       }
+                                       currentEntry.append(line);
+                               }
+                       }
+               } finally {
+                       IOUtils.closeQuietly(in);
+               }
+               return res;
+       }
+}
\ No newline at end of file