From 6dc1de9781ab211a43d24cbaed7969d98abc1cc1 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Feb 15 2018 15:11:36 +0000 Subject: test_memory_cache: Regression test for #3571 Resolves: https://pagure.io/SSSD/sssd/issue/3592 Reviewed-by: Sumit Bose --- diff --git a/src/tests/intg/test_memory_cache.py b/src/tests/intg/test_memory_cache.py index cac9feb..0d13273 100644 --- a/src/tests/intg/test_memory_cache.py +++ b/src/tests/intg/test_memory_cache.py @@ -22,10 +22,15 @@ import ent import grp import pwd import config +import random import signal +import string +import struct import subprocess import time import pytest +import pysss_murmur + import ds_openldap import ldap_ent import sssd_id @@ -770,6 +775,82 @@ def test_invalidate_everything_after_stop(ldap_conn, sanity_rfc2307): assert_missing_mc_records_for_user1() +def get_random_string(length): + return ''.join([random.choice(string.ascii_letters + string.digits) + for n in range(length)]) + + +class MemoryCache(object): + SIZEOF_UINT32_T = 4 + + def __init__(self, path): + with open(path, "rb") as fin: + fin.seek(4 * self.SIZEOF_UINT32_T) + self.seed = struct.unpack('i', fin.read(4))[0] + self.data_size = struct.unpack('i', fin.read(4))[0] + self.ft_size = struct.unpack('i', fin.read(4))[0] + hash_len = struct.unpack('i', fin.read(4))[0] + self.hash_size = hash_len / self.SIZEOF_UINT32_T + + def sss_nss_mc_hash(self, key): + input_key = key + '\0' + input_len = len(key) + 1 + + murmur_hash = pysss_murmur.murmurhash3(input_key, input_len, self.seed) + return murmur_hash % self.hash_size + + +def test_colliding_hashes(ldap_conn, sanity_rfc2307): + """ + Regression test for ticket: + https://pagure.io/SSSD/sssd/issue/3571 + """ + + first_user = 'user1' + + # initialize data in memcache + ent.assert_passwd_by_name( + first_user, + dict(name='user1', passwd='*', uid=1001, gid=2001, + gecos='1001', shell='/bin/bash')) + + mem_cache = MemoryCache(config.MCACHE_PATH + '/passwd') + + colliding_hash = mem_cache.sss_nss_mc_hash(first_user) + + while True: + # string for colliding hash need to be longer then data for user1 + # stored in memory cache (almost equivalent to: + # `getent passwd user1 | wc -c` ==> 45 + second_user = get_random_string(80) + val = mem_cache.sss_nss_mc_hash(second_user) + if val == colliding_hash: + break + + # add new user to LDAP + ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn) + ent_list.add_user(second_user, 5001, 5001) + ldap_conn.add_s(ent_list[0][0], ent_list[0][1]) + + ent.assert_passwd_by_name( + second_user, + dict(name=second_user, passwd='*', uid=5001, gid=5001, + gecos='5001', shell='/bin/bash')) + + stop_sssd() + + # check that both users are stored in cache + ent.assert_passwd_by_name( + first_user, + dict(name='user1', passwd='*', uid=1001, gid=2001, + gecos='1001', shell='/bin/bash')) + + ent.assert_passwd_by_name( + second_user, + dict(name=second_user, passwd='*', uid=5001, gid=5001, + gecos='5001', shell='/bin/bash')) + + def test_removed_mc(ldap_conn, sanity_rfc2307): """ Regression test for ticket: