Recursive lookup management
This commit is contained in:
@@ -1,14 +1,19 @@
|
|||||||
server:
|
server:
|
||||||
|
|
||||||
# Indicate on which port the Identity Server will listen. This is an unencrypted port.
|
# Indicate on which port the Identity Server will listen.
|
||||||
|
#
|
||||||
|
# This is be default an unencrypted port.
|
||||||
# HTTPS can be configured using Tomcat configuration properties.
|
# HTTPS can be configured using Tomcat configuration properties.
|
||||||
port: 8090
|
port: 8090
|
||||||
|
|
||||||
# Realm under which this Identity Server is authoritative, e.g. domain name in e-mails.
|
# Realm under which this Identity Server is authoritative.
|
||||||
# This is used in some recursive lookups to avoid endless loops and avoid bothering other Identity Servers.
|
#
|
||||||
|
# This is used to avoid unnecessary connections and endless recursive lookup.
|
||||||
|
# e.g. domain name in e-mails.
|
||||||
name: 'example.org'
|
name: 'example.org'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
key:
|
key:
|
||||||
|
|
||||||
# Where the Identity Server signing key will be stored.
|
# Where the Identity Server signing key will be stored.
|
||||||
@@ -19,6 +24,34 @@ key:
|
|||||||
path: '/var/tmp/mxis-signing.key'
|
path: '/var/tmp/mxis-signing.key'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# This element contains all the configuration item for lookup strategies
|
||||||
|
lookup:
|
||||||
|
|
||||||
|
# Configuration items for recursion-type of lookup
|
||||||
|
#
|
||||||
|
# Lookup access are divided into two types:
|
||||||
|
# - Local
|
||||||
|
# - Remote
|
||||||
|
#
|
||||||
|
# This is similar to DNS lookup and recursion and is therefore prone to the same vulnerabilities.
|
||||||
|
# By default, only non-public hosts are allowed to perform recursive lookup.
|
||||||
|
# This will also prevent basic endless loops where:
|
||||||
|
# host A ask host B, which in turn is configured to ask host B, etc.
|
||||||
|
recursive:
|
||||||
|
|
||||||
|
# Enable recursive lookup globally
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Whitelist of CIDR that will trigger a recursive lookup
|
||||||
|
allowedCidr:
|
||||||
|
- '127.0.0.0/8'
|
||||||
|
- '10.0.0.0/8'
|
||||||
|
- '172.16.0.0/16'
|
||||||
|
- '192.168.0.0/16'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ldap:
|
ldap:
|
||||||
host: 'localhost'
|
host: 'localhost'
|
||||||
port: 389
|
port: 389
|
||||||
@@ -44,3 +77,15 @@ ldap:
|
|||||||
# - For type 'mxid', regardless of the directory type, we recommend using 'pager' as it is a standard attribute but
|
# - For type 'mxid', regardless of the directory type, we recommend using 'pager' as it is a standard attribute but
|
||||||
# shouldn't be used in infrastructures.
|
# shouldn't be used in infrastructures.
|
||||||
attribute: 'sAMAccountName'
|
attribute: 'sAMAccountName'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
forward:
|
||||||
|
|
||||||
|
# List of forwarders to use to try to match a 3PID.
|
||||||
|
#
|
||||||
|
# Each server will be tried in the given order, going to the next if no binding was found or an error occurred.
|
||||||
|
# There are the current root Identity Servers of the Matrix network.
|
||||||
|
servers:
|
||||||
|
- "https://matrix.org"
|
||||||
|
- "https://vector.im"
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ dependencies {
|
|||||||
// DNS lookups
|
// DNS lookups
|
||||||
compile 'dnsjava:dnsjava:2.1.8'
|
compile 'dnsjava:dnsjava:2.1.8'
|
||||||
|
|
||||||
|
// Network utilities for recursive host check
|
||||||
|
compile 'commons-net:commons-net:3.5'
|
||||||
|
|
||||||
testCompile 'junit:junit:4.12'
|
testCompile 'junit:junit:4.12'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
40
src/main/groovy/io/kamax/mxisd/config/ForwardConfig.groovy
Normal file
40
src/main/groovy/io/kamax/mxisd/config/ForwardConfig.groovy
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.kamax.mxisd.config
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "forward")
|
||||||
|
class ForwardConfig {
|
||||||
|
|
||||||
|
private List<String> servers
|
||||||
|
|
||||||
|
List<String> getServers() {
|
||||||
|
return servers
|
||||||
|
}
|
||||||
|
|
||||||
|
void setServers(List<String> servers) {
|
||||||
|
this.servers = servers
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.kamax.mxisd.config
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "lookup.recursive")
|
||||||
|
class RecursiveLookupConfig {
|
||||||
|
|
||||||
|
private boolean enabled
|
||||||
|
private List<String> allowedCidr
|
||||||
|
|
||||||
|
boolean isEnabled() {
|
||||||
|
return enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> getAllowedCidr() {
|
||||||
|
return allowedCidr
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAllowedCidr(List<String> allowedCidr) {
|
||||||
|
this.allowedCidr = allowedCidr
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -22,18 +22,26 @@ package io.kamax.mxisd.controller.v1
|
|||||||
|
|
||||||
import groovy.json.JsonOutput
|
import groovy.json.JsonOutput
|
||||||
import io.kamax.mxisd.api.ThreePidType
|
import io.kamax.mxisd.api.ThreePidType
|
||||||
import io.kamax.mxisd.lookup.LookupStrategy
|
import io.kamax.mxisd.lookup.LookupRequest
|
||||||
|
import io.kamax.mxisd.lookup.strategy.LookupStrategy
|
||||||
import io.kamax.mxisd.signature.SignatureManager
|
import io.kamax.mxisd.signature.SignatureManager
|
||||||
|
import org.apache.commons.lang.StringUtils
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
import org.springframework.web.bind.annotation.RequestParam
|
import org.springframework.web.bind.annotation.RequestParam
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest
|
||||||
|
|
||||||
import static org.springframework.web.bind.annotation.RequestMethod.GET
|
import static org.springframework.web.bind.annotation.RequestMethod.GET
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
class MappingController {
|
class MappingController {
|
||||||
|
|
||||||
|
private Logger log = LoggerFactory.getLogger(MappingController.class)
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private LookupStrategy strategy
|
private LookupStrategy strategy
|
||||||
|
|
||||||
@@ -41,15 +49,26 @@ class MappingController {
|
|||||||
private SignatureManager signMgr
|
private SignatureManager signMgr
|
||||||
|
|
||||||
@RequestMapping(value = "/_matrix/identity/api/v1/lookup", method = GET)
|
@RequestMapping(value = "/_matrix/identity/api/v1/lookup", method = GET)
|
||||||
String lookup(@RequestParam String medium, @RequestParam String address) {
|
String lookup(HttpServletRequest request, @RequestParam String medium, @RequestParam String address) {
|
||||||
|
String remote = StringUtils.defaultIfBlank(request.getHeader("X-FORWARDED-FOR"), request.getRemoteAddr())
|
||||||
|
log.info("Got request from {}", remote)
|
||||||
|
|
||||||
ThreePidType type = ThreePidType.valueOf(medium)
|
ThreePidType type = ThreePidType.valueOf(medium)
|
||||||
Optional<?> lookupOpt = strategy.find(type, address)
|
|
||||||
|
LookupRequest lookupRequest = new LookupRequest()
|
||||||
|
lookupRequest.setRequester(remote)
|
||||||
|
lookupRequest.setType(type)
|
||||||
|
lookupRequest.setThreePid(address)
|
||||||
|
|
||||||
|
Optional<?> lookupOpt = strategy.find(lookupRequest)
|
||||||
if (!lookupOpt.isPresent()) {
|
if (!lookupOpt.isPresent()) {
|
||||||
|
log.info("No mapping was found, return empty JSON object")
|
||||||
return JsonOutput.toJson([])
|
return JsonOutput.toJson([])
|
||||||
}
|
}
|
||||||
|
|
||||||
def lookup = lookupOpt.get()
|
def lookup = lookupOpt.get()
|
||||||
if (lookup['signatures'] == null) {
|
if (lookup['signatures'] == null) {
|
||||||
|
log.info("lookup is not signed yet, we sign it")
|
||||||
lookup['signatures'] = signMgr.signMessage(JsonOutput.toJson(lookup))
|
lookup['signatures'] = signMgr.signMessage(JsonOutput.toJson(lookup))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
55
src/main/groovy/io/kamax/mxisd/lookup/LookupRequest.groovy
Normal file
55
src/main/groovy/io/kamax/mxisd/lookup/LookupRequest.groovy
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.kamax.mxisd.lookup
|
||||||
|
|
||||||
|
import io.kamax.mxisd.api.ThreePidType
|
||||||
|
|
||||||
|
class LookupRequest {
|
||||||
|
|
||||||
|
private String requester
|
||||||
|
private ThreePidType type
|
||||||
|
private String threePid
|
||||||
|
|
||||||
|
String getRequester() {
|
||||||
|
return requester
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRequester(String requester) {
|
||||||
|
this.requester = requester
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreePidType getType() {
|
||||||
|
return type
|
||||||
|
}
|
||||||
|
|
||||||
|
void setType(ThreePidType type) {
|
||||||
|
this.type = type
|
||||||
|
}
|
||||||
|
|
||||||
|
String getThreePid() {
|
||||||
|
return threePid
|
||||||
|
}
|
||||||
|
|
||||||
|
void setThreePid(String threePid) {
|
||||||
|
this.threePid = threePid
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -18,10 +18,11 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.lookup
|
package io.kamax.mxisd.lookup.provider
|
||||||
|
|
||||||
import io.kamax.mxisd.api.ThreePidType
|
import io.kamax.mxisd.api.ThreePidType
|
||||||
import io.kamax.mxisd.config.ServerConfig
|
import io.kamax.mxisd.config.ServerConfig
|
||||||
|
import io.kamax.mxisd.lookup.LookupRequest
|
||||||
import org.apache.commons.lang.StringUtils
|
import org.apache.commons.lang.StringUtils
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
@@ -45,15 +46,15 @@ class DnsLookupProvider extends RemoteIdentityServerProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Optional<?> find(ThreePidType type, String threePid) {
|
Optional<?> find(LookupRequest request) {
|
||||||
log.info("Performing DNS lookup for {}", threePid)
|
log.info("Performing DNS lookup for {}", request.getThreePid())
|
||||||
if (ThreePidType.email != type) {
|
if (ThreePidType.email != request.getType()) {
|
||||||
log.info("Skipping unsupported type {} for {}", type, threePid)
|
log.info("Skipping unsupported type {} for {}", request.getType(), request.getThreePid())
|
||||||
return Optional.empty()
|
return Optional.empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
String domain = threePid.substring(threePid.lastIndexOf("@") + 1)
|
String domain = request.getThreePid().substring(request.getThreePid().lastIndexOf("@") + 1)
|
||||||
log.info("Domain name for {}: {}", threePid, domain)
|
log.info("Domain name for {}: {}", request.getThreePid(), domain)
|
||||||
if (StringUtils.equals(srvCfg.getName(), domain)) {
|
if (StringUtils.equals(srvCfg.getName(), domain)) {
|
||||||
log.warn("We are authoritative for ${domain}, no remote lookup - is your server.name configured properly?")
|
log.warn("We are authoritative for ${domain}, no remote lookup - is your server.name configured properly?")
|
||||||
return Optional.empty()
|
return Optional.empty()
|
||||||
@@ -77,7 +78,7 @@ class DnsLookupProvider extends RemoteIdentityServerProvider {
|
|||||||
for (SRVRecord record : records) {
|
for (SRVRecord record : records) {
|
||||||
log.info("Found SRV record: {}", record.toString())
|
log.info("Found SRV record: {}", record.toString())
|
||||||
String baseUrl = "https://${record.getTarget().toString(true)}:${record.getPort()}"
|
String baseUrl = "https://${record.getTarget().toString(true)}:${record.getPort()}"
|
||||||
Optional<?> answer = find(baseUrl, type, threePid)
|
Optional<?> answer = find(baseUrl, request.getType(), request.getThreePid())
|
||||||
if (answer.isPresent()) {
|
if (answer.isPresent()) {
|
||||||
return answer
|
return answer
|
||||||
} else {
|
} else {
|
||||||
@@ -90,7 +91,7 @@ class DnsLookupProvider extends RemoteIdentityServerProvider {
|
|||||||
|
|
||||||
log.info("Performing basic lookup using domain name {}", domain)
|
log.info("Performing basic lookup using domain name {}", domain)
|
||||||
String baseUrl = "https://" + domain
|
String baseUrl = "https://" + domain
|
||||||
return find(baseUrl, type, threePid)
|
return find(baseUrl, request.getType(), request.getThreePid())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -18,15 +18,18 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.lookup
|
package io.kamax.mxisd.lookup.provider
|
||||||
|
|
||||||
import io.kamax.mxisd.api.ThreePidType
|
import io.kamax.mxisd.config.ForwardConfig
|
||||||
|
import io.kamax.mxisd.lookup.LookupRequest
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
class RootProvider extends RemoteIdentityServerProvider {
|
class ForwarderProvider extends RemoteIdentityServerProvider {
|
||||||
|
|
||||||
private List<String> roots = Arrays.asList("https://matrix.org", "https://vector.im")
|
@Autowired
|
||||||
|
private ForwardConfig cfg
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
int getPriority() {
|
int getPriority() {
|
||||||
@@ -34,9 +37,9 @@ class RootProvider extends RemoteIdentityServerProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Optional<?> find(ThreePidType type, String threePid) {
|
Optional<?> find(LookupRequest request) {
|
||||||
for (String root : roots) {
|
for (String root : cfg.getServers()) {
|
||||||
Optional<?> answer = find(root, type, threePid)
|
Optional<?> answer = find(root, request.getType(), request.getThreePid())
|
||||||
if (answer.isPresent()) {
|
if (answer.isPresent()) {
|
||||||
return answer
|
return answer
|
||||||
}
|
}
|
||||||
@@ -18,11 +18,11 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.lookup
|
package io.kamax.mxisd.lookup.provider
|
||||||
|
|
||||||
import io.kamax.mxisd.api.ThreePidType
|
|
||||||
import io.kamax.mxisd.config.LdapConfig
|
import io.kamax.mxisd.config.LdapConfig
|
||||||
import io.kamax.mxisd.config.ServerConfig
|
import io.kamax.mxisd.config.ServerConfig
|
||||||
|
import io.kamax.mxisd.lookup.LookupRequest
|
||||||
import org.apache.commons.lang.StringUtils
|
import org.apache.commons.lang.StringUtils
|
||||||
import org.apache.directory.api.ldap.model.cursor.EntryCursor
|
import org.apache.directory.api.ldap.model.cursor.EntryCursor
|
||||||
import org.apache.directory.api.ldap.model.entry.Attribute
|
import org.apache.directory.api.ldap.model.entry.Attribute
|
||||||
@@ -49,11 +49,6 @@ class LdapProvider implements ThreePidProvider, InitializingBean {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private LdapConfig ldapCfg
|
private LdapConfig ldapCfg
|
||||||
|
|
||||||
@Override
|
|
||||||
int getPriority() {
|
|
||||||
return 20
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void afterPropertiesSet() throws Exception {
|
void afterPropertiesSet() throws Exception {
|
||||||
if (!Arrays.asList(UID, MATRIX_ID).contains(ldapCfg.getType())) {
|
if (!Arrays.asList(UID, MATRIX_ID).contains(ldapCfg.getType())) {
|
||||||
@@ -62,14 +57,24 @@ class LdapProvider implements ThreePidProvider, InitializingBean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Optional<?> find(ThreePidType type, String threePid) {
|
boolean isLocal() {
|
||||||
log.info("Performing LDAP lookup ${threePid} of type ${type}")
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int getPriority() {
|
||||||
|
return 20
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Optional<?> find(LookupRequest request) {
|
||||||
|
log.info("Performing LDAP lookup ${request.getThreePid()} of type ${request.getType()}")
|
||||||
|
|
||||||
LdapConnection conn = new LdapNetworkConnection(ldapCfg.getHost(), ldapCfg.getPort())
|
LdapConnection conn = new LdapNetworkConnection(ldapCfg.getHost(), ldapCfg.getPort())
|
||||||
try {
|
try {
|
||||||
conn.bind(ldapCfg.getBindDn(), ldapCfg.getBindPassword())
|
conn.bind(ldapCfg.getBindDn(), ldapCfg.getBindPassword())
|
||||||
|
|
||||||
String searchQuery = ldapCfg.getQuery().replaceAll("%3pid", threePid)
|
String searchQuery = ldapCfg.getQuery().replaceAll("%3pid", request.getThreePid())
|
||||||
EntryCursor cursor = conn.search(ldapCfg.getBaseDn(), searchQuery, SearchScope.SUBTREE, ldapCfg.getAttribute())
|
EntryCursor cursor = conn.search(ldapCfg.getBaseDn(), searchQuery, SearchScope.SUBTREE, ldapCfg.getAttribute())
|
||||||
try {
|
try {
|
||||||
if (cursor.next()) {
|
if (cursor.next()) {
|
||||||
@@ -96,8 +101,8 @@ class LdapProvider implements ThreePidProvider, InitializingBean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Optional.of([
|
return Optional.of([
|
||||||
address : threePid,
|
address : request.getThreePid(),
|
||||||
medium : type,
|
medium : request.getType(),
|
||||||
mxid : matrixId.toString(),
|
mxid : matrixId.toString(),
|
||||||
not_before: 0,
|
not_before: 0,
|
||||||
not_after : 9223372036854775807,
|
not_after : 9223372036854775807,
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.lookup
|
package io.kamax.mxisd.lookup.provider
|
||||||
|
|
||||||
import groovy.json.JsonException
|
import groovy.json.JsonException
|
||||||
import groovy.json.JsonSlurper
|
import groovy.json.JsonSlurper
|
||||||
@@ -29,8 +29,14 @@ import org.slf4j.LoggerFactory
|
|||||||
abstract class RemoteIdentityServerProvider implements ThreePidProvider {
|
abstract class RemoteIdentityServerProvider implements ThreePidProvider {
|
||||||
|
|
||||||
private Logger log = LoggerFactory.getLogger(RemoteIdentityServerProvider.class)
|
private Logger log = LoggerFactory.getLogger(RemoteIdentityServerProvider.class)
|
||||||
|
|
||||||
private JsonSlurper json = new JsonSlurper()
|
private JsonSlurper json = new JsonSlurper()
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean isLocal() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
Optional<?> find(String remote, ThreePidType type, String threePid) {
|
Optional<?> find(String remote, ThreePidType type, String threePid) {
|
||||||
log.info("Looking up {} 3PID {} using {}", type, threePid, remote)
|
log.info("Looking up {} 3PID {} using {}", type, threePid, remote)
|
||||||
|
|
||||||
@@ -40,7 +46,8 @@ abstract class RemoteIdentityServerProvider implements ThreePidProvider {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
def output = json.parseText(rootSrvConn.getInputStream().getText())
|
def output = json.parseText(rootSrvConn.getInputStream().getText())
|
||||||
if (output['address'] != null) {
|
if (output['address']) {
|
||||||
|
log.info("Found 3PID mapping: {}", output)
|
||||||
return Optional.of(output)
|
return Optional.of(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,17 +18,19 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.lookup
|
package io.kamax.mxisd.lookup.provider
|
||||||
|
|
||||||
import io.kamax.mxisd.api.ThreePidType
|
import io.kamax.mxisd.lookup.LookupRequest
|
||||||
|
|
||||||
interface ThreePidProvider {
|
interface ThreePidProvider {
|
||||||
|
|
||||||
|
boolean isLocal()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Higher has more priority
|
* Higher has more priority
|
||||||
*/
|
*/
|
||||||
int getPriority() // Should not be here but let's KISS for now
|
int getPriority() // Should not be here but let's KISS for now
|
||||||
|
|
||||||
Optional<?> find(ThreePidType type, String threePid)
|
Optional<?> find(LookupRequest request)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -18,12 +18,12 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.lookup
|
package io.kamax.mxisd.lookup.strategy
|
||||||
|
|
||||||
import io.kamax.mxisd.api.ThreePidType
|
import io.kamax.mxisd.lookup.LookupRequest
|
||||||
|
|
||||||
interface LookupStrategy {
|
interface LookupStrategy {
|
||||||
|
|
||||||
Optional<?> find(ThreePidType type, String threePid)
|
Optional<?> find(LookupRequest request)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -18,9 +18,13 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package io.kamax.mxisd.lookup
|
package io.kamax.mxisd.lookup.strategy
|
||||||
|
|
||||||
import io.kamax.mxisd.api.ThreePidType
|
import io.kamax.mxisd.api.ThreePidType
|
||||||
|
import io.kamax.mxisd.config.RecursiveLookupConfig
|
||||||
|
import io.kamax.mxisd.lookup.LookupRequest
|
||||||
|
import io.kamax.mxisd.lookup.provider.ThreePidProvider
|
||||||
|
import org.apache.commons.net.util.SubnetUtils
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.beans.factory.InitializingBean
|
import org.springframework.beans.factory.InitializingBean
|
||||||
@@ -28,13 +32,18 @@ import org.springframework.beans.factory.annotation.Autowired
|
|||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
class PriorityLookupStrategy implements LookupStrategy, InitializingBean {
|
class RecursivePriorityLookupStrategy implements LookupStrategy, InitializingBean {
|
||||||
|
|
||||||
private Logger log = LoggerFactory.getLogger(PriorityLookupStrategy.class)
|
private Logger log = LoggerFactory.getLogger(RecursivePriorityLookupStrategy.class)
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RecursiveLookupConfig recursiveCfg
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private List<ThreePidProvider> providers
|
private List<ThreePidProvider> providers
|
||||||
|
|
||||||
|
private List<SubnetUtils.SubnetInfo> allowedCidr = new ArrayList<>()
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void afterPropertiesSet() throws Exception {
|
void afterPropertiesSet() throws Exception {
|
||||||
log.info("Found ${providers.size()} providers")
|
log.info("Found ${providers.size()} providers")
|
||||||
@@ -47,18 +56,37 @@ class PriorityLookupStrategy implements LookupStrategy, InitializingBean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
log.info("Recursive lookup enabled: {}", recursiveCfg.isEnabled())
|
||||||
|
for (String cidr : recursiveCfg.getAllowedCidr()) {
|
||||||
|
log.info("{} is allowed for recursion", cidr)
|
||||||
|
allowedCidr.add(new SubnetUtils(cidr).getInfo())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Optional<?> find(ThreePidType type, String threePid) {
|
Optional<?> find(LookupRequest request) {
|
||||||
if (ThreePidType.email != type) {
|
if (ThreePidType.email != request.getType()) {
|
||||||
throw new IllegalArgumentException("${type} is currently not supported")
|
throw new IllegalArgumentException("${request.getType()} is currently not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean canRecurse = false
|
||||||
|
if (recursiveCfg.isEnabled()) {
|
||||||
|
for (SubnetUtils.SubnetInfo cidr : allowedCidr) {
|
||||||
|
if (cidr.isInRange(request.getRequester())) {
|
||||||
|
canRecurse = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("Host {} allowed for recursion: {}", request.getRequester(), canRecurse)
|
||||||
|
|
||||||
for (ThreePidProvider provider : providers) {
|
for (ThreePidProvider provider : providers) {
|
||||||
Optional<?> lookupDataOpt = provider.find(type, threePid)
|
if (provider.isLocal() || canRecurse) {
|
||||||
if (lookupDataOpt.isPresent()) {
|
Optional<?> lookupDataOpt = provider.find(request)
|
||||||
return lookupDataOpt
|
if (lookupDataOpt.isPresent()) {
|
||||||
|
return lookupDataOpt
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user