diff --git a/config.json b/config.json index e04452f71ea89698547493df0b6c8d72a87b9f06..2c41b877e16f50ab39db68acc6e62e142b8f0a27 100644 --- a/config.json +++ b/config.json @@ -4,5 +4,6 @@ "api_baseurl": "http://localhost:5000/api/v1", "api_key": "secretapikey", "listen_addr": "127.0.0.1:3389", - "cache_ttl": 60 + "cache_ttl": 60, + "enable_mail": false } diff --git a/server.py b/server.py index 342998d64c69f7c7ef9f1013dc1f2e63ce3a464a..670351b4f9eb9f50df7048e3a788991388de6636 100644 --- a/server.py +++ b/server.py @@ -145,6 +145,51 @@ class GroupDirectory(SimpleFilterMixin, BaseDirectory): value = str(DN.from_str(value.decode())).encode() return super().filter_equal(attribute, value) +class MailDirectory(SimpleFilterMixin, BaseDirectory): + def __init__(self, api, dn_base): + self.api = api + self.rdn_attr = 'uid' + self.dn_base = DN('ou=postfix') + DN(dn_base) + self.structuralobjectclass = b'postfixVirtual' + self.objectclasses = [b'top', b'postfixVirtual'] + + def generate_result(self, mail): + attributes = CaseInsensitiveDict( + structuralObjectClass=[self.structuralobjectclass], + objectClass=self.objectclasses, + uid=[encode_attribute(mail['name'])], + mailacceptinggeneralid=[encode_attribute(address) for address in mail['receive_addresses']], + maildrop=[encode_attribute(address) for address in mail['destination_addresses']], + ) + dn = str(DN(uid=mail['name']) + self.dn_base) + return dn, attributes + + def get_best_api_param(self, expr): + if isinstance(expr, FilterEqual) and expr.attribute.lower() == 'uid': + return 'name', expr.value + elif isinstance(expr, FilterEqual) and expr.attribute.lower() == 'mailacceptinggeneralid': + return 'receive_address', expr.value + elif isinstance(expr, FilterEqual) and expr.attribute.lower() == 'maildrop': + return 'destination_address', expr.value + if isinstance(expr, FilterAnd): + params = dict([self.get_best_api_param(subexpr) for subexpr in expr.filters]) + for key in ['name', 'receive_address', 'destination_address']: + if key in params: + return key, params[key] + return None, None + + def search_fetch(self, expr): + if expr is False: + return + kwargs = {} + key, value = self.get_best_api_param(expr) + if key is not None: + kwargs[key] = value + for mail in self.api.get('getmails', **kwargs): + dn, obj = self.generate_result(mail) + if eval_ldap_filter(obj, expr): + yield dn, obj + class RequestHandler(SimpleLDAPRequestHandler): subschema = RFC2307BIS_SUBSCHEMA @@ -154,6 +199,7 @@ class RequestHandler(SimpleLDAPRequestHandler): static_directory = None user_directory = None group_directory = None + mail_directory = None bind_dn = None bind_password = None @@ -198,12 +244,15 @@ class RequestHandler(SimpleLDAPRequestHandler): yield from self.static_directory.search(baseobj, scope, filter) yield from self.user_directory.search(baseobj, scope, filter) yield from self.group_directory.search(baseobj, scope, filter) + if self.mail_directory is not None: + yield from self.mail_directory.search(baseobj, scope, filter) def main(config): dn_base = DN.from_str(config['dn_base']) api = UffdAPI(config['api_baseurl'], config['api_key'], config.get('cache_ttl', 60)) user_directory = UserDirectory(api, dn_base) group_directory = GroupDirectory(api, dn_base) + mail_directory = MailDirectory(api, dn_base) static_directory = StaticDirectory() base_attrs = { @@ -223,6 +272,12 @@ def main(config): 'objectClass': ['top', 'organizationalUnit'], 'structuralObjectClass': ['organizationalUnit'], }) + if config.get('enable_mail'): + static_directory.add(DN('ou=postfix') + dn_base, { + 'ou': ['postfix'], + 'objectClass': ['top', 'organizationalUnit'], + 'structuralObjectClass': ['organizationalUnit'], + }) static_directory.add(DN('ou=system') + dn_base, { 'ou': ['system'], 'objectClass': ['top', 'organizationalUnit'], @@ -244,6 +299,8 @@ def main(config): CustomRequestHandler.static_directory = static_directory CustomRequestHandler.user_directory = user_directory CustomRequestHandler.group_directory = group_directory + if config.get('enable_mail'): + CustomRequestHandler.mail_directory = mail_directory if config['listen_addr'].startswith('unix:'): socketserver.ThreadingUnixStreamServer(config['listen_addr'][5:], CustomRequestHandler).serve_forever()