diff --git a/ldapserver/entries.py b/ldapserver/entries.py
index 18bf7e7af27f5d2eb903a01dc38c37bf4eba5956..999897b932925df44eb6021ee7c096adc2c7c277 100644
--- a/ldapserver/entries.py
+++ b/ldapserver/entries.py
@@ -137,6 +137,7 @@ class Entry(AttributeDict):
 	def __search_match_filter(self, filter_obj):
 		# pylint: disable=too-many-branches,too-many-return-statements,too-many-statements,too-many-nested-blocks
 		if isinstance(filter_obj, ldap.FilterAnd):
+			# RFC4526: An 'and' filter consisting of an empty set of filters SHALL evaluate to True.
 			result = FilterResult.TRUE
 			for subfilter in filter_obj.filters:
 				subresult = self.__search_match_filter(subfilter)
@@ -146,6 +147,7 @@ class Entry(AttributeDict):
 					result = FilterResult.UNDEFINED
 			return result
 		elif isinstance(filter_obj, ldap.FilterOr):
+			# RFC4526: An 'or' filter consisting of an empty set of filters SHALL evaluate to False.
 			result = FilterResult.FALSE
 			for subfilter in filter_obj.filters:
 				subresult = self.__search_match_filter(subfilter)
@@ -364,6 +366,7 @@ class EntryTemplate(AttributeDict):
 	def __search_match_filter(self, filter_obj):
 		# pylint: disable=too-many-return-statements,too-many-branches,too-many-nested-blocks,too-many-statements
 		if isinstance(filter_obj, ldap.FilterAnd):
+			# RFC4526: An 'and' filter consisting of an empty set of filters SHALL evaluate to True.
 			result = TemplateFilterResult.TRUE
 			for subfilter in filter_obj.filters:
 				subresult = self.__search_match_filter(subfilter)
@@ -375,6 +378,7 @@ class EntryTemplate(AttributeDict):
 					result = TemplateFilterResult.MAYBE_TRUE
 			return result
 		elif isinstance(filter_obj, ldap.FilterOr):
+			# RFC4526: An 'or' filter consisting of an empty set of filters SHALL evaluate to False.
 			result = TemplateFilterResult.FALSE
 			for subfilter in filter_obj.filters:
 				subresult = self.__search_match_filter(subfilter)
diff --git a/ldapserver/ldap.py b/ldapserver/ldap.py
index 980c3ac8f6375bff8f44f5e76e2e24315f7559e2..1c04d8b816e3d347f933df0199d2718b906c57d7 100644
--- a/ldapserver/ldap.py
+++ b/ldapserver/ldap.py
@@ -49,7 +49,10 @@ class Filter(asn1.Choice, ABC):
 		raise NotImplementedError()
 
 class FilterAnd(asn1.Wrapper, Filter):
-	'''AND conjunction of multiple filters ``(&filters...)``'''
+	'''AND conjunction of multiple filters ``(&filters...)``
+
+	Supports RFC4526: Empty AND filters (``(&)``) are considered valid and
+	evaluate to TRUE.'''
 	BER_TAG = (2, True, 0)
 	WRAPPED_ATTRIBUTE = 'filters'
 	WRAPPED_TYPE = asn1.Set
@@ -65,7 +68,10 @@ class FilterAnd(asn1.Wrapper, Filter):
 		return '(&%s)'%(''.join([str(subfilter) for subfilter in self.filters]))
 
 class FilterOr(asn1.Wrapper, Filter):
-	'''OR conjunction of multiple filters ``(|filters...)``'''
+	'''OR conjunction of multiple filters ``(|filters...)``
+
+	Supports RFC4526: Empty OR filters (``(|)``) are considered valid and
+	evaluate to FALSE.'''
 	BER_TAG = (2, True, 1)
 	WRAPPED_ATTRIBUTE = 'filters'
 	WRAPPED_TYPE = asn1.Set
@@ -720,3 +726,6 @@ class PagedResultsValue(asn1.Sequence):
 
 	size: int
 	cookie: bytes
+
+# LDAP Absolute True and False Filters (RFC4526)
+ABSOLUTE_TRUE_FALSE_OID = '1.3.6.1.4.1.4203.1.5.3'
diff --git a/ldapserver/server.py b/ldapserver/server.py
index f9923cc438f95250decbc80c05dd55d93a57169b..cdf2729102ee905fd2b8d35392a3fc53a9753de2 100644
--- a/ldapserver/server.py
+++ b/ldapserver/server.py
@@ -198,6 +198,7 @@ class LDAPRequestHandler(BaseLDAPRequestHandler):
 			self.rootdse['supportedSASLMechanisms'].append('PLAIN')
 		if self.supports_sasl_external:
 			self.rootdse['supportedSASLMechanisms'].append('EXTERNAL')
+		self.rootdse['supportedFeatures'].append(ldap.ABSOLUTE_TRUE_FALSE_OID)
 		self.rootdse['supportedLDAPVersion'] = ['3']
 		self.bind_object = None
 		self.__bind_sasl_state = None # Set to (mechanism, iterator) by handle_bind
diff --git a/tests/test_entries.py b/tests/test_entries.py
index 5f8743625698c2d1f482854a91c99dd8c4447f46..20c9e2d72cacd735890e8107d4bc89c18fe0bb69 100644
--- a/tests/test_entries.py
+++ b/tests/test_entries.py
@@ -170,6 +170,8 @@ class TestObjectEntry(unittest.TestCase):
 		self.assertFalse(obj.match_search(dn, scope, ldap.FilterAnd([false, undefined])))
 		# True and Undefined = Undefined (behaves like False)
 		self.assertFalse(obj.match_search(dn, scope, ldap.FilterAnd([true, undefined])))
+		# Empty And = True (RFC4526)
+		self.assertTrue(obj.match_search(dn, scope, ldap.FilterAnd([])))
 
 		# Not True = False
 		self.assertFalse(obj.match_search(dn, scope, ldap.FilterNot(ldap.FilterAnd([true]))))
@@ -183,6 +185,8 @@ class TestObjectEntry(unittest.TestCase):
 		self.assertTrue(obj.match_search(dn, scope, ldap.FilterNot(ldap.FilterAnd([false, undefined]))))
 		# Not (True and Undefined) = Undefined (behaves like False)
 		self.assertFalse(obj.match_search(dn, scope, ldap.FilterNot(ldap.FilterAnd([true, undefined]))))
+		# Not (Empty And) = False (RFC4526)
+		self.assertFalse(obj.match_search(dn, scope, ldap.FilterNot(ldap.FilterAnd([]))))
 
 	def test_match_search_filter_or(self):
 		obj = ObjectEntry(schema, 'cn=foo,dc=example,dc=com', cn=['foo', 'bar'], uid=[], objectclass=['top'])
@@ -203,6 +207,8 @@ class TestObjectEntry(unittest.TestCase):
 		self.assertTrue(obj.match_search(dn, scope, ldap.FilterOr([true, undefined])))
 		# False or Undefined = Undefined (behaves like False)
 		self.assertFalse(obj.match_search(dn, scope, ldap.FilterOr([false, undefined])))
+		# Empty Or = False (RFC4526)
+		self.assertFalse(obj.match_search(dn, scope, ldap.FilterOr([])))
 
 		# Not True = False
 		self.assertFalse(obj.match_search(dn, scope, ldap.FilterNot(ldap.FilterOr([true]))))
@@ -216,6 +222,8 @@ class TestObjectEntry(unittest.TestCase):
 		self.assertFalse(obj.match_search(dn, scope, ldap.FilterNot(ldap.FilterOr([true, undefined]))))
 		# Not (False or Undefined) = Undefined (behaves like False)
 		self.assertFalse(obj.match_search(dn, scope, ldap.FilterNot(ldap.FilterOr([false, undefined]))))
+		# Not (Empty Or) = True (RFC4526)
+		self.assertTrue(obj.match_search(dn, scope, ldap.FilterNot(ldap.FilterOr([]))))
 
 	def test_match_search_filter_equal(self):
 		obj = ObjectEntry(schema, 'cn=foo,dc=example,dc=com', cn=['foo', 'bar'], uid=[], objectclass=['top'])
@@ -478,6 +486,8 @@ class TestEntryTemplate(unittest.TestCase):
 		self.assertTrue(template.match_search(dn, scope, ldap.FilterAnd([true, maybe])))
 		# Undefined and Maybe = Undefined (behaves like False)
 		self.assertFalse(template.match_search(dn, scope, ldap.FilterAnd([undefined, maybe])))
+		# Empty And = True (RFC4526)
+		self.assertTrue(template.match_search(dn, scope, ldap.FilterAnd([])))
 
 		# Not True = False
 		self.assertFalse(template.match_search(dn, scope, ldap.FilterNot(ldap.FilterAnd([true]))))
@@ -497,6 +507,8 @@ class TestEntryTemplate(unittest.TestCase):
 		self.assertTrue(template.match_search(dn, scope, ldap.FilterNot(ldap.FilterAnd([true, maybe]))))
 		# Not (Undefined and Maybe) = Undefined (behaves like False)
 		self.assertFalse(template.match_search(dn, scope, ldap.FilterNot(ldap.FilterAnd([undefined, maybe]))))
+		# Not (Empty And) = False (RFC4526)
+		self.assertFalse(template.match_search(dn, scope, ldap.FilterNot(ldap.FilterAnd([]))))
 
 	def test_match_search_filter_or(self):
 		template = EntryTemplate(schema, 'dc=example,dc=com', 'cn', objectclass=['top'], cn=WILDCARD)
@@ -525,6 +537,8 @@ class TestEntryTemplate(unittest.TestCase):
 		self.assertTrue(template.match_search(dn, scope, ldap.FilterOr([false, maybe])))
 		# Undefined or Maybe = Maybe (behaves like True)
 		self.assertTrue(template.match_search(dn, scope, ldap.FilterOr([undefined, maybe])))
+		# Empty Or = False (RFC4526)
+		self.assertFalse(template.match_search(dn, scope, ldap.FilterOr([])))
 
 		# Not True = False
 		self.assertFalse(template.match_search(dn, scope, ldap.FilterNot(ldap.FilterOr([true]))))
@@ -544,6 +558,8 @@ class TestEntryTemplate(unittest.TestCase):
 		self.assertTrue(template.match_search(dn, scope, ldap.FilterNot(ldap.FilterOr([false, maybe]))))
 		# Not (Undefined or Maybe) = Maybe (behaves like True)
 		self.assertTrue(template.match_search(dn, scope, ldap.FilterNot(ldap.FilterOr([undefined, maybe]))))
+		# Not (Empty Or) = True (RFC4526)
+		self.assertTrue(template.match_search(dn, scope, ldap.FilterNot(ldap.FilterOr([]))))
 
 	def test_match_search_filter_equal(self):
 		template = EntryTemplate(schema, 'dc=example,dc=com', 'cn', objectclass=['top'], cn=WILDCARD)