diff --git a/application.example.yaml b/application.example.yaml
index a52d1f4..05d3891 100644
--- a/application.example.yaml
+++ b/application.example.yaml
@@ -172,12 +172,14 @@ key.path: '/path/to/sign.key'
#ldap.connection.port: 389
-# Bind DN to use when performing lookups
+# Bind DN for the connection.
+#
+# If Bind DN and password are empty, anonymous authentication is performed
#
#ldap.connection.bindDn: 'CN=Matrix Identity Server,CN=Users,DC=example,DC=org'
-# Bind password to use
+# Bind password for the connection.
#
#ldap.connection.bindPassword: 'password'
@@ -256,6 +258,9 @@ key.path: '/path/to/sign.key'
#sql.enabled: true
#sql.type: 'sqlite'
#sql.connection: '/var/lib/matrix-synapse/homeserver.db'
+
+
+# See ldap.attribute.uid.type for more info on possible values
#sql.identity.type: 'mxid'
#sql.identity.query: 'SELECT user_id AS uid FROM user_threepids WHERE medium = ? AND address = ?'
#sql.identity.medium.email: "SELECT user_id AS uid FROM user_threepids WHERE medium = ? AND address = ?"
@@ -383,6 +388,7 @@ storage.provider.sqlite.database: '/path/to/mxisd.db'
#dns.overwrite.homeserver.type: 'raw'
-# The value to use, depending on the type
+# The value to use, depending on the type.
+# Protocol will always be HTTPS
#
#dns.overwrite.homeserver.value: 'localhost:8448'
diff --git a/src/main/groovy/io/kamax/mxisd/auth/provider/LdapAuthProvider.java b/src/main/groovy/io/kamax/mxisd/auth/provider/LdapAuthProvider.java
index 6edeaa6..63f19d0 100644
--- a/src/main/groovy/io/kamax/mxisd/auth/provider/LdapAuthProvider.java
+++ b/src/main/groovy/io/kamax/mxisd/auth/provider/LdapAuthProvider.java
@@ -22,7 +22,7 @@ package io.kamax.mxisd.auth.provider;
import io.kamax.matrix.MatrixID;
import io.kamax.mxisd.auth.UserAuthResult;
-import io.kamax.mxisd.config.ldap.LdapConfig;
+import io.kamax.mxisd.backend.LdapBackend;
import io.kamax.mxisd.lookup.provider.LdapProvider;
import org.apache.commons.lang.StringUtils;
import org.apache.directory.api.ldap.model.cursor.CursorException;
@@ -33,37 +33,24 @@ import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.exception.LdapException;
import org.apache.directory.api.ldap.model.message.SearchScope;
import org.apache.directory.ldap.client.api.LdapConnection;
-import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
-public class LdapAuthProvider implements AuthenticatorProvider {
+public class LdapAuthProvider extends LdapBackend implements AuthenticatorProvider {
private Logger log = LoggerFactory.getLogger(LdapAuthProvider.class);
- @Autowired
- private LdapConfig ldapCfg;
-
- private LdapConnection getConn() {
- return new LdapNetworkConnection(ldapCfg.getConn().getHost(), ldapCfg.getConn().getPort(), ldapCfg.getConn().isTls());
- }
-
- private void bind(LdapConnection conn) throws LdapException {
- conn.bind(ldapCfg.getConn().getBindDn(), ldapCfg.getConn().getBindPassword());
- }
-
private String getUidAttribute() {
- return ldapCfg.getAttribute().getUid().getValue();
+ return getCfg().getAttribute().getUid().getValue();
}
@Override
public boolean isEnabled() {
- return ldapCfg.isEnabled();
+ return getCfg().isEnabled();
}
@Override
@@ -74,11 +61,11 @@ public class LdapAuthProvider implements AuthenticatorProvider {
try {
bind(conn);
- String uidType = ldapCfg.getAttribute().getUid().getType();
+ String uidType = getCfg().getAttribute().getUid().getType();
MatrixID mxIdExt = new MatrixID(id);
String userFilterValue = StringUtils.equals(LdapProvider.UID, uidType) ? mxIdExt.getLocalPart() : mxIdExt.getId();
- String userFilter = "(" + ldapCfg.getAttribute().getUid().getValue() + "=" + userFilterValue + ")";
- EntryCursor cursor = conn.search(ldapCfg.getConn().getBaseDn(), userFilter, SearchScope.SUBTREE, getUidAttribute(), ldapCfg.getAttribute().getName());
+ String userFilter = "(" + getCfg().getAttribute().getUid().getValue() + "=" + userFilterValue + ")";
+ EntryCursor cursor = conn.search(getCfg().getConn().getBaseDn(), userFilter, SearchScope.SUBTREE, getUidAttribute(), getCfg().getAttribute().getName());
try {
while (cursor.next()) {
Entry entry = cursor.get();
@@ -105,7 +92,7 @@ public class LdapAuthProvider implements AuthenticatorProvider {
return new UserAuthResult().failure();
}
- Attribute nameAttribute = entry.get(ldapCfg.getAttribute().getName());
+ Attribute nameAttribute = entry.get(getCfg().getAttribute().getName());
String name = nameAttribute != null ? nameAttribute.get().toString() : null;
log.info("Authentication successful for {}", entry.getDn().getName());
diff --git a/src/main/groovy/io/kamax/mxisd/backend/LdapBackend.java b/src/main/groovy/io/kamax/mxisd/backend/LdapBackend.java
new file mode 100644
index 0000000..9a735ff
--- /dev/null
+++ b/src/main/groovy/io/kamax/mxisd/backend/LdapBackend.java
@@ -0,0 +1,57 @@
+/*
+ * mxisd - Matrix Identity Server Daemon
+ * Copyright (C) 2017 Maxime Dor
+ *
+ * https://max.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.mxisd.backend;
+
+import io.kamax.mxisd.config.ldap.LdapConfig;
+import org.apache.commons.lang.StringUtils;
+import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class LdapBackend {
+
+ private Logger log = LoggerFactory.getLogger(LdapBackend.class);
+
+ @Autowired
+ private LdapConfig ldapCfg;
+
+ protected LdapConnection getConn() {
+ return new LdapNetworkConnection(ldapCfg.getConn().getHost(), ldapCfg.getConn().getPort(), ldapCfg.getConn().isTls());
+ }
+
+ protected void bind(LdapConnection conn) throws LdapException {
+ if (StringUtils.isBlank(ldapCfg.getConn().getBindDn()) && StringUtils.isBlank(ldapCfg.getConn().getBindPassword())) {
+ conn.anonymousBind();
+ } else {
+ conn.bind(ldapCfg.getConn().getBindDn(), ldapCfg.getConn().getBindPassword());
+ }
+ }
+
+ protected LdapConfig getCfg() {
+ return ldapCfg;
+ }
+
+}
diff --git a/src/main/groovy/io/kamax/mxisd/lookup/provider/LdapProvider.groovy b/src/main/groovy/io/kamax/mxisd/lookup/provider/LdapProvider.groovy
index d8bb349..f39c7e6 100644
--- a/src/main/groovy/io/kamax/mxisd/lookup/provider/LdapProvider.groovy
+++ b/src/main/groovy/io/kamax/mxisd/lookup/provider/LdapProvider.groovy
@@ -20,8 +20,8 @@
package io.kamax.mxisd.lookup.provider
+import io.kamax.mxisd.backend.LdapBackend
import io.kamax.mxisd.config.MatrixConfig
-import io.kamax.mxisd.config.ldap.LdapConfig
import io.kamax.mxisd.lookup.SingleLookupReply
import io.kamax.mxisd.lookup.SingleLookupRequest
import io.kamax.mxisd.lookup.ThreePidMapping
@@ -32,14 +32,13 @@ import org.apache.directory.api.ldap.model.entry.Attribute
import org.apache.directory.api.ldap.model.entry.Entry
import org.apache.directory.api.ldap.model.message.SearchScope
import org.apache.directory.ldap.client.api.LdapConnection
-import org.apache.directory.ldap.client.api.LdapNetworkConnection
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
@Component
-class LdapProvider implements IThreePidProvider {
+class LdapProvider extends LdapBackend implements IThreePidProvider {
public static final String UID = "uid"
public static final String MATRIX_ID = "mxid"
@@ -49,24 +48,13 @@ class LdapProvider implements IThreePidProvider {
@Autowired
private MatrixConfig mxCfg
- @Autowired
- private LdapConfig ldapCfg
-
@Override
boolean isEnabled() {
- return ldapCfg.isEnabled()
- }
-
- private LdapConnection getConn() {
- return new LdapNetworkConnection(ldapCfg.getConn().getHost(), ldapCfg.getConn().getPort(), ldapCfg.getConn().isTls())
- }
-
- private void bind(LdapConnection conn) {
- conn.bind(ldapCfg.getConn().getBindDn(), ldapCfg.getConn().getBindPassword())
+ return getCfg().isEnabled()
}
private String getUidAttribute() {
- return ldapCfg.getAttribute().getUid().getValue();
+ return getCfg().getAttribute().getUid().getValue();
}
@Override
@@ -82,14 +70,14 @@ class LdapProvider implements IThreePidProvider {
Optional lookup(LdapConnection conn, String medium, String value) {
String uidAttribute = getUidAttribute()
- Optional queryOpt = ldapCfg.getIdentity().getQuery(medium)
+ Optional queryOpt = getCfg().getIdentity().getQuery(medium)
if (!queryOpt.isPresent()) {
log.warn("{} is not a configured 3PID type for LDAP lookup", medium)
return Optional.empty()
}
String searchQuery = queryOpt.get().replaceAll("%3pid", value)
- EntryCursor cursor = conn.search(ldapCfg.getConn().getBaseDn(), searchQuery, SearchScope.SUBTREE, uidAttribute)
+ EntryCursor cursor = conn.search(getCfg().getConn().getBaseDn(), searchQuery, SearchScope.SUBTREE, uidAttribute)
try {
while (cursor.next()) {
Entry entry = cursor.get()
@@ -97,19 +85,19 @@ class LdapProvider implements IThreePidProvider {
Attribute attribute = entry.get(uidAttribute)
if (attribute == null) {
- log.info("DN {}: no attribute {}, skpping", entry.getDn(), ldapCfg.getAttribute())
+ log.info("DN {}: no attribute {}, skpping", entry.getDn(), getCfg().getAttribute())
continue
}
String data = attribute.get().toString()
if (data.length() < 1) {
- log.info("DN {}: empty attribute {}, skipping", ldapCfg.getAttribute())
+ log.info("DN {}: empty attribute {}, skipping", getCfg().getAttribute())
continue
}
StringBuilder matrixId = new StringBuilder()
// TODO Should we turn this block into a map of functions?
- String uidType = ldapCfg.getAttribute().getUid().getType()
+ String uidType = getCfg().getAttribute().getUid().getType()
if (StringUtils.equals(UID, uidType)) {
matrixId.append("@").append(data).append(":").append(mxCfg.getDomain())
} else if (StringUtils.equals(MATRIX_ID, uidType)) {