389ds / 389-ds-base

The enterprise-class Open Source LDAP server for Linux
https://www.port389.org/
Other
211 stars 93 forks source link

SyncRepl plugin provides a wrong cookie #4243

Closed 389-ds-bot closed 3 years ago

389-ds-bot commented 4 years ago

Cloned from Pagure issue: https://pagure.io/389-ds-base/issue/51190


Issue Description

Within a freeipa environment, the syncrepl plugin sometimes provides a wrong cookie 4294967295 and triggers syncrepl_entry callback for a change that should not.

Package Version and Platform

Fedora 32 with: 389-ds-base-1.4.3.10-1.fc32.x86_64 freeipa-server-4.8.7-1.fc32.x86_64

Steps to reproduce

EOF

systemctl restart dirsrv@IPA-TEST.service


Launch the attached python script to create a refreshAndPersist query:

python test_syncrepl.py

In another window, add a new ipa user:

echo $PASSWORD | kinit admin ipa user-add testuser --first test --last user


#### Actual results
The script displays the callbacks triggered by syncrepl:

syncrepl_entry dn uid=testuser,cn=users,cn=accounts,dc=ipa,dc=test Set cookie: master.ipa.test:389#cn=Directory Manager:cn=accounts,dc=ipa,dc=test:(|(objectClass=groupofnames)(objectClass=person))57 syncrepl_entry dn uid=testuser,cn=users,cn=accounts,dc=ipa,dc=test Set cookie: master.ipa.test:389#cn=Directory Manager:cn=accounts,dc=ipa,dc=test:(|(objectClass=groupofnames)(objectClass=person))57 syncrepl_entry dn uid=testuser,cn=users,cn=accounts,dc=ipa,dc=test Set cookie: master.ipa.test:389#cn=Directory Manager:cn=accounts,dc=ipa,dc=test:(|(objectClass=groupofnames)(objectClass=person))57 syncrepl_entry dn uid=testuser,cn=users,cn=accounts,dc=ipa,dc=test Set cookie: master.ipa.test:389#cn=Directory Manager:cn=accounts,dc=ipa,dc=test:(|(objectClass=groupofnames)(objectClass=person))59 syncrepl_entry dn cn=ipausers,cn=groups,cn=accounts,dc=ipa,dc=test Set cookie: master.ipa.test:389#cn=Directory Manager:cn=accounts,dc=ipa,dc=test:(|(objectClass=groupofnames)(objectClass=person))4294967295


#### Expected results

The last cookie with changenumber 4294967295 is invalid. It looks like it corresponds to the creation of IPA private group for the user, that has objectclasses `top`, `mepManagedEntry`, `ipaobject` and `posixgroup`.
I would not expect the private group creation to trigger the syncrepl callback `syncrepl_entry`, as it does not contain the objectclass groupofnames that is specified in the filterstr.

Script:

cat test_syncrepl.py

import ldap import ldapurl from ldap.syncrepl import SyncreplConsumer from ldap.ldapobject import ReconnectLDAPObject import os import pwd import sys

from ipalib import api from ipaplatform.paths import paths from ipapython.dn import DN

class TestSyncer(ReconnectLDAPObject, SyncreplConsumer): def init(self, *args, *kwargs): self.cookie = None ldap.ldapobject.ReconnectLDAPObject.init(self, args, **kwargs)

def syncrepl_set_cookie(self, cookie):
    self.cookie = cookie
    print("Set cookie: ", cookie)

def syncrepl_get_cookie(self):
    print("Get cookie: ", self.cookie)
    return self.cookie

def syncrepl_present(self, uuids, refreshDeletes=False):
    print("syncrepl_present uuids ", uuids, refreshDeletes)

def syncrepl_delete(self, uuids):
    print("syncrepl_delete uuids ", uuids)

def syncrepl_entry(self, dn, attrs, uuid):
    print("syncrepl_entry dn ", dn)

def syncrepl_refreshdone(self):
    print("syncrepl_refreshdone")

if len(sys.argv) >= 2: cookie = sys.argv[1] else: cookie = None

api.bootstrap( in_server=True, context='test_syncrepl', confdir=paths.ETC_IPA, log=None ) api.finalize()

basedn = DN(api.env.container_accounts, api.env.basedn) ldap_url = ldapurl.LDAPUrl(api.env.ldap_uri) ldap_url.dn = str(basedn) ldap_url.scope = ldapurl.LDAP_SCOPE_SUBTREE ldap_url.filterstr = '(|(objectClass=groupofnames)(objectClass=person))' ldap_url.attrs = [ 'objectclass', 'cn', 'displayname', 'gidnumber', 'givenname', 'homedirectory', 'ipaexternalmember', 'ipantsecurityidentifier', 'ipauniqueid', 'krbcanonicalname', 'krbprincipalname', 'mail', 'member', 'memberof', 'sn', 'uid', 'uidnumber', ]

ldap_connection = TestSyncer(ldap_url.initializeUrl()) user_name = pwd.getpwuid(os.geteuid()).pw_name auth_tokens = ldap.sasl.external(user_name) ldap_connection.sasl_interactive_bind_s('', auth_tokens)

ldap_search = ldap_connection.syncrepl_search( ldap_url.dn, ldap_url.scope, mode='refreshAndPersist', attrlist=ldap_url.attrs, filterstr=ldap_url.filterstr, cookie=cookie )

try: while ldap_connection.syncrepl_poll(all=1, msgid=ldap_search): pass except (ldap.SERVER_DOWN, ldap.CONNECT_ERROR) as e: print('syncrepl_poll: LDAP error (%s)', e) sys.exit(1)

tbordaz commented 3 years ago

74a96c6ad..87b39043c master 1063bb7d2..66f195b98 389-ds-base-1.4.4 b1351c30e..f3374e112 389-ds-base-1.4.3