Skip to content
Commits on Source (17)
......@@ -882,10 +882,12 @@ systemdsystemunit_DATA = wrappers/$(PACKAGE_NAME)@.service \
wrappers/$(systemdgroupname) \
wrappers/$(PACKAGE_NAME)-snmp.service
systemdsystemunitdropin_DATA = wrappers/$(PACKAGE_NAME)@.service.d/custom.conf
if with_sanitizer
systemdsystemunitdropin_DATA += wrappers/$(PACKAGE_NAME)@.service.d/xsan.conf
systemdsystemunitdropin_DATA = wrappers/$(PACKAGE_NAME)@.service.d/xsan.conf
else
systemdsystemunitdropin_DATA = wrappers/$(PACKAGE_NAME)@.service.d/custom.conf
endif
else
if INITDDIR
init_SCRIPTS = wrappers/$(PACKAGE_NAME) \
......
......@@ -10,7 +10,7 @@ vendor="389 Project"
# PACKAGE_VERSION is constructed from these
VERSION_MAJOR=1
VERSION_MINOR=4
VERSION_MAINT=1.5
VERSION_MAINT=1.6
# NOTE: VERSION_PREREL is automatically set for builds made out of a git tree
VERSION_PREREL=
VERSION_DATE=$(date -u +%Y%m%d)
......
# --- BEGIN COPYRIGHT BLOCK ---
# Copyright (C) 2019 Red Hat, Inc.
# All rights reserved.
#
# License: GPL (version 3 or any later version).
# See LICENSE for details.
# --- END COPYRIGHT BLOCK ----
"""
verify and testing Filter from a search
"""
import os
import pytest
from lib389._constants import DEFAULT_SUFFIX, PW_DM
from lib389.topologies import topology_st as topo
from lib389.idm.user import UserAccounts, UserAccount
from lib389.idm.account import Accounts
pytestmark = pytest.mark.tier1
FILTER_MWARD = "(uid=mward)"
FILTER_L = "(l=sunnyvale)"
FILTER_MAIL = "(mail=jreu*)"
FILTER_EXAM = "(mail=*exam*)"
FILTER_7393 = "(telephonenumber=*7393)"
FILTER_408 = "(telephonenumber=*408*3)"
FILTER_UID = "(uid=*)"
FILTER_PASSWD = "(userpassword=*)"
FILTER_FRED = "(fred=*)"
FILTER_AAA = "(uid:2.16.840.1.113730.3.3.2.15.1:=>AAA)"
FILTER_AAA_ES = "(uid:es:=>AAA)"
FILTER_AAA_UID = "(uid:2.16.840.1.113730.3.3.2.15.1.5:=AAA)"
FILTER_100 = "(uid:2.16.840.1.113730.3.3.2.15.1:=>user100)"
FILTER_ES_100 = "(uid:es:=>user100)"
FILTER_UID_100 = "(uid:2.16.840.1.113730.3.3.2.15.1.5:=user100)"
FILTER_UID_1 = "(uid:2.16.840.1.113730.3.3.2.15.1:=<1)"
FILTER_UID_ES = "(uid:es:=<1)"
FILTER_UID_2 = "(uid:2.16.840.1.113730.3.3.2.15.1.1:=1)"
FILTER_UID_USER1 = "(uid:2.16.840.1.113730.3.3.2.15.1:=<user1)"
FILTER_ES_USER1 = "(uid:es:=<user1)"
FILTER_UI_USER1 = "(uid:2.16.840.1.113730.3.3.2.15.1.1:=user1)"
FILTER_Z = "(uid:2.16.840.1.113730.3.3.2.15.1:=<z)"
FILTER_NZ = "(uid:es:=<z)"
FILTER_UIDZ = "(uid:2.16.840.1.113730.3.3.2.15.1.1:=z)"
FILTER_UID_LS = "(uid<=1)"
FILTER_UID_LA = "(uid<=A)"
FILTER_USER1 = "(uid=user1)"
FILTER_UIDLEZ = "(uid<=Z)"
FILTER_UIDGE1 = "(uid>=1)"
FILTER_UIDGEA = "(uid>=A)"
FILTER_UIDGEAU20 = "(uid>=user20)"
FILTER_UIDGEZ = "(uid>=Z)"
FILTER_A = "(uid:2.16.840.1.113730.3.3.2.18.1:=<=A)"
FILTER_FR_A = "(uid:fr:=<=A)"
FILTER_E_A = "(uid:2.16.840.1.113730.3.3.2.18.1.2:=A)"
FILTER_USER20 = "(uid:2.16.840.1.113730.3.3.2.18.1:=<=user20)"
FILTER_L_USER20 = "(uid:fr:=<=user20)"
FILTER_E_USER20 = "(uid:2.16.840.1.113730.3.3.2.18.1.2:=user20)"
FILTER_Z2 = "(uid:2.16.840.1.113730.3.3.2.18.1:=<=z)"
FILTER_LE_Z = "(uid:fr:=<=z)"
FILTER_E_Z = "(uid:2.16.840.1.113730.3.3.2.18.1.2:=z)"
FILTER_GE_Z = "(uid:2.16.840.1.113730.3.3.2.18.1:=>=A)"
FILTER_GE_A = "(uid:fr:=>=A)"
FILTER_UID_A = "(uid:2.16.840.1.113730.3.3.2.18.1.4:=A)"
FILTER_UID_USER20 = "(uid:2.16.840.1.113730.3.3.2.18.1:=>=user20)"
FILTER_FR_USER20 = "(uid:fr:=>=user20)"
FILTER_UID_E_USER20 = "(uid:2.16.840.1.113730.3.3.2.18.1.4:=user20)"
FILTER_EGE_Z = "(uid:2.16.840.1.113730.3.3.2.18.1:=>=z)"
FILTER_FR_Z = "(uid:fr:=>=z)"
FILTER_UID_Z = "(uid:2.16.840.1.113730.3.3.2.18.1.4:=z)"
FILTER_SN = "(sn~=tiller)"
FILTER_GN = "(givenName~=pricella)"
FILTER_DES = "(description=This is the special * attribute value)"
FILTER_DES_X = "(description=*x*)"
FILTER_PTYL = "(uid=ptyler)"
FILTER_WAL = "(uid=*wal*)"
FILTER_RN = "(roomNumber=0312)"
FILTER_MW = "(uid=mw*)"
FILTER_2295 = "(roomNumber=2295)"
FILTER_CAPERTION = "(l=Cupertino)"
FILTER_INTER = "(objectclass=inetorgperson)"
FILTER_MAIL2 = "(mail=cnewport@example.com)"
FILTER_VALE = "(l=sunnyvale)"
FILTER_UID20 = "(uid=user20)"
FILTER_UID30 = "(uid=user30)"
FILTER_4012 = "(roomNumber=200)"
FILTER_3924 = "(roomNumber=201)"
FILTER_4508 = "(roomNumber=202)"
FILTER_UID40 = "(uid=user40)"
FILTER_2254 = "(roomNumber=2254)"
FILTER_L2 = "(l=*)"
FILTER_C_SN_GN = f"(&{FILTER_SN} {FILTER_GN})"
FILTER_C_SN_PTYL = f"(&(!{FILTER_SN})(!{FILTER_PTYL}))"
FILTER_SN_PTYL = f"(&(!{FILTER_SN}) {FILTER_PTYL})"
FILTER_N_SN_PTYL = f"(&{FILTER_SN}(!{FILTER_PTYL}))"
FILTER_C_WALL_RN = f"(|{FILTER_WAL} {FILTER_RN})"
FILTER_N_WALL_RN = f"(|(!{FILTER_WAL})(!{FILTER_RN}))"
FILTER_C_N_WALL_RN = f"(|(!{FILTER_WAL}){FILTER_RN})"
FILTER_C_N_WAL_RN = f"(|{FILTER_WAL}(!{FILTER_RN}))"
FILTER_C_WAL_SN = f"(&{FILTER_WAL}(|{FILTER_SN} {FILTER_2295}))"
FILTER_C_WAL_2295 = f"(|(&{FILTER_WAL} {FILTER_2295})(&{FILTER_WAL} {FILTER_SN}))"
FILTER_C_WAL_SN_2295 = f"(|{FILTER_WAL}(&{FILTER_SN} {FILTER_2295}))"
FILTER_C_WAL_SN_WAL = f"(&(|{FILTER_WAL} {FILTER_SN})(|{FILTER_WAL} {FILTER_2295}))"
FILTER_WAL_2295 = f"(&{FILTER_WAL} {FILTER_2295})"
FILTER_2295_WAL = f"(&{FILTER_2295} {FILTER_WAL})"
FILTER_OR_2295_WAL = f"(|{FILTER_2295} {FILTER_WAL})"
FILTER_OR_WAL_SN = f"(|{FILTER_WAL}(&{FILTER_SN} {FILTER_2295}))"
FILTER_OR_WAL_2295 = f"(|{FILTER_WAL} {FILTER_2295})"
FILTER_OR_WAL_L = f"(|{FILTER_WAL} {FILTER_L2})"
FILTER_AND_C_OR = f"(&{FILTER_CAPERTION} {FILTER_OR_WAL_SN})"
FILTER_AND_C_F = f"(&(!{FILTER_CAPERTION})(!{FILTER_OR_WAL_SN}))"
FILTER_AND_C_W_SN = f"(&(!{FILTER_CAPERTION}){FILTER_OR_WAL_SN})"
FILTER_AND_N_C_W_SN = f"(&{FILTER_CAPERTION}(!{FILTER_OR_WAL_SN}))"
FILTER_OR_N_C_W_SN = f"(|{FILTER_CAPERTION} {FILTER_OR_WAL_SN})"
FILTER_OR_N_CWS = f"(|(!{FILTER_CAPERTION})(!{FILTER_OR_WAL_SN}))"
FILTER_OR_N_CWSN = f"(|(!{FILTER_CAPERTION}){FILTER_OR_WAL_SN})"
FILTER_OR_CWSN_N = f"(|{FILTER_CAPERTION}(!{FILTER_OR_WAL_SN}))"
FILTER_AND_USER1 = f"(&(!{FILTER_USER1}){FILTER_INTER})"
FILTER_OR_USER1 = f"(|(!{FILTER_USER1}){FILTER_INTER})"
FILTER_MAIL_VAL = f"(&(!{FILTER_MAIL2}){FILTER_VALE})"
FILTER_OR_MAIL_VAL = f"(|(!{FILTER_MAIL2}){FILTER_VALE})"
FILTER_USER1_UID = f"(&(!{FILTER_USER1})(!{FILTER_UID20})(!{FILTER_UID30}){FILTER_INTER})"
FILTER_USER1_UID20 = f"(|(!{FILTER_USER1})(!{FILTER_UID20})(!{FILTER_UID30}){FILTER_INTER})"
FILTER_USER4012_3924 = f"(&(!{FILTER_4012})(!{FILTER_3924})(!{FILTER_4508}){FILTER_VALE})"
FILTER_USER4012_3924_4520 = f"(|(!{FILTER_4012})(!{FILTER_3924})(!{FILTER_4508}){FILTER_VALE})"
FILTER_USER40_USER1 = f"(&(!{FILTER_UID40})(&(!{FILTER_USER1})(!{FILTER_UID20})" \
f"(!{FILTER_UID30}){FILTER_INTER}))"
FILTER_USER40_USER20 = f"(|(!{FILTER_UID40})(&(!{FILTER_USER1})(!{FILTER_UID20})" \
f"(!{FILTER_UID30}){FILTER_INTER}))"
FILTER_SN0 = f"(&(!{FILTER_2254}){FILTER_USER4012_3924})"
FILTER_SN1 = f"(|(!{FILTER_2254}){FILTER_USER4012_3924})"
FILTER_ORG = "(objectclass=inetorgperson)"
FILTER_SV = "(l=sunnyvale)"
FILTER_USER30 = "(uid=user30)"
FILTER_RN_4012 = "(roomNumber=4012)"
FILTER_RN_3924 = "(roomNumber=3924)"
FILTER_RN_4508 = "(roomNumber=4508)"
FILTER_L_ALL = "(l=*)"
FILTER_UID_WAL = f"(|(uid=*wal*) {FILTER_L_ALL})"
FILTER_U1_U20_U30 = f"(&(!{FILTER_USER1})(!{FILTER_USER20})(!{FILTER_USER30}))"
FILTER_N_U1_U20_U30 = f"(|(!{FILTER_USER1})(!{FILTER_USER20})(!{FILTER_USER30}))"
FILTER_RN_4012_3924_4508 = f"(&(!{FILTER_RN_4012})(!{FILTER_RN_3924})(!{FILTER_RN_4508}))"
FILTER_RN_N_4012_3924_4508 = f"(|(!{FILTER_RN_4012})(!{FILTER_RN_3924})(!{FILTER_RN_4508}))"
FILTER_RN_ORG_1_20 = f"(& {FILTER_ORG}(!{FILTER_USER1})(!{FILTER_USER20})(!{FILTER_USER30}))"
FILTER_RN_ORG_1_20_30 = f"(| {FILTER_ORG}(!{FILTER_USER1})(!{FILTER_USER20})(!{FILTER_USER30}))"
FILTER_SV_4012_3924 = f"(&{FILTER_SV}(!{FILTER_RN_4012})(!{FILTER_RN_3924})(!{FILTER_RN_4508}))"
FILTER_SV_4012_3924_45 = f"(|{FILTER_SV}(!{FILTER_RN_4012})(!{FILTER_RN_3924})(!{FILTER_RN_4508}))"
FILTER_ALL_SV = f"(!(|(!{FILTER_L_ALL})(!{FILTER_SV})))"
FILTER_L_ALL_SV = f"(|(!{FILTER_L_ALL})(!{FILTER_SV}))"
FILTER_CAP_EXAM = f"(&{FILTER_CAPERTION} {FILTER_EXAM} {FILTER_UID_WAL})"
FILTER_CAP_EXAM_WALL = f"(&(!{FILTER_CAPERTION})(!{FILTER_EXAM})(!{FILTER_UID_WAL}))"
FILTER_CAP_EXAM_U_WALL = f"(&(!{FILTER_CAPERTION})(!{FILTER_EXAM}){FILTER_UID_WAL})"
FILTER_EXAM_U_WALL = f"(&(!{FILTER_CAPERTION}){FILTER_EXAM}(!{FILTER_UID_WAL}))"
FILTER_CAP_E_W = f"(&(!{FILTER_CAPERTION}){FILTER_EXAM} {FILTER_UID_WAL})"
FILTER_CAP_E_N_W = f"(&{FILTER_CAPERTION}(!{FILTER_EXAM})(!{FILTER_UID_WAL}))"
FILTER_CAP_N_E_W = f"(&{FILTER_CAPERTION}(!{FILTER_EXAM}){FILTER_UID_WAL})"
FILTER_N_CP_E_W = f"(&{FILTER_CAPERTION} {FILTER_EXAM}(!{FILTER_UID_WAL}))"
FILTER_N_CP_N_E_W = f"(|{FILTER_CAPERTION} {FILTER_EXAM} {FILTER_UID_WAL})"
FILTER_N_CP_N_E_N_W = f"(|(!{FILTER_CAPERTION})(!{FILTER_EXAM})(!{FILTER_UID_WAL}))"
FILTER_OR_CP_E_W = f"(|(!{FILTER_CAPERTION})(!{FILTER_EXAM}){FILTER_UID_WAL})"
FILTER_OR_N_CP_E_W = f"(|(!{FILTER_CAPERTION}){FILTER_EXAM}(!{FILTER_UID_WAL}))"
FILTER_OR_N_CP_N_E_W = f"(|(!{FILTER_CAPERTION}){FILTER_EXAM} {FILTER_UID_WAL})"
FILTER_OR_N_CP_N_E_N_W = f"(|{FILTER_CAPERTION}(!{FILTER_EXAM})(!{FILTER_UID_WAL}))"
FILTER_NOT_CP_N_E_N_W = f"(|{FILTER_CAPERTION}(!{FILTER_EXAM}){FILTER_UID_WAL})"
FILTER_NOT_CP_NOT_E_N_W = f"(|{FILTER_CAPERTION} {FILTER_EXAM}(!{FILTER_UID_WAL}))"
VALUES = [FILTER_7393, FILTER_408]
POSITIVE = [FILTER_MWARD, FILTER_L, FILTER_MAIL, FILTER_EXAM, FILTER_UID,
FILTER_AAA, FILTER_AAA_ES, FILTER_AAA_UID, FILTER_100,
FILTER_ES_100, FILTER_UID_100, FILTER_UI_USER1, FILTER_UIDZ,
FILTER_USER1, FILTER_UIDLEZ, FILTER_UIDGE1, FILTER_UIDGEA, FILTER_UIDGEAU20,
FILTER_E_USER20, FILTER_E_Z, FILTER_GE_Z, FILTER_GE_A, FILTER_UID_A,
FILTER_UID_USER20, FILTER_FR_USER20, FILTER_UID_E_USER20, FILTER_EGE_Z,
FILTER_FR_Z, FILTER_DES, FILTER_DES_X, FILTER_PTYL, FILTER_WAL, FILTER_RN,
FILTER_MW, FILTER_2295, FILTER_CAPERTION, FILTER_INTER, FILTER_VALE, FILTER_4012,
FILTER_3924, FILTER_4508, FILTER_L2, FILTER_C_SN_PTYL, FILTER_SN_PTYL,
FILTER_C_WALL_RN, FILTER_N_WALL_RN, FILTER_C_N_WALL_RN,
FILTER_C_N_WAL_RN, FILTER_C_WAL_SN, FILTER_C_WAL_2295, FILTER_C_WAL_SN_2295,
FILTER_C_WAL_SN_WAL, FILTER_WAL_2295, FILTER_2295_WAL, FILTER_OR_2295_WAL,
FILTER_OR_WAL_SN, FILTER_OR_WAL_2295, FILTER_OR_WAL_L, FILTER_AND_C_OR,
FILTER_AND_C_F, FILTER_AND_C_W_SN, FILTER_AND_N_C_W_SN, FILTER_OR_N_C_W_SN,
FILTER_OR_N_CWS, FILTER_OR_N_CWSN, FILTER_OR_CWSN_N, FILTER_AND_USER1,
FILTER_OR_USER1, FILTER_MAIL_VAL, FILTER_C_WAL_SN_WAL, FILTER_WAL_2295,
FILTER_2295_WAL, FILTER_OR_2295_WAL, FILTER_USER4012_3924_4520, FILTER_USER40_USER1,
FILTER_USER40_USER20, FILTER_SN0, FILTER_SN1, FILTER_U1_U20_U30, FILTER_N_U1_U20_U30,
FILTER_RN_4012_3924_4508, FILTER_RN_N_4012_3924_4508, FILTER_RN_ORG_1_20,
FILTER_RN_ORG_1_20_30, FILTER_SV_4012_3924, FILTER_SV_4012_3924_45, FILTER_ALL_SV,
FILTER_L_ALL_SV, FILTER_CAP_EXAM_WALL, FILTER_CAP_EXAM_U_WALL,
FILTER_CAP_E_W, FILTER_N_CP_N_E_W, FILTER_N_CP_N_E_N_W, FILTER_OR_CP_E_W,
FILTER_OR_N_CP_E_W, FILTER_OR_N_CP_N_E_W, FILTER_OR_N_CP_N_E_N_W,
FILTER_NOT_CP_N_E_N_W, FILTER_NOT_CP_NOT_E_N_W, FILTER_CAP_N_E_W]
NEGATIVE = [FILTER_PASSWD, FILTER_FRED, FILTER_UID_1, FILTER_UID_ES, FILTER_UID_2,
FILTER_UID_USER1, FILTER_ES_USER1, FILTER_Z, FILTER_NZ, FILTER_UID_LS,
FILTER_UID_LA, FILTER_UIDGEZ, FILTER_A, FILTER_FR_A, FILTER_E_A,
FILTER_USER20, FILTER_L_USER20, FILTER_Z2,
FILTER_LE_Z, FILTER_UID_Z, FILTER_SN, FILTER_GN, FILTER_MAIL2, FILTER_UID20,
FILTER_UID30, FILTER_UID40, FILTER_C_SN_GN, FILTER_N_SN_PTYL, FILTER_EXAM_U_WALL,
FILTER_CAP_E_N_W, FILTER_N_CP_E_W, FILTER_CAP_EXAM]
def create_users_all(instance, user, room, l_l, description, telephonenumber):
"""
Will create users with different type of l
"""
instance.create(properties={
'mail': f'{user}@redhat.com',
'uid': user,
'givenName': user.title(),
'cn': f'bit {user}',
'sn': user.title(),
'l': l_l,
'manager': f'uid={user},ou=People,{DEFAULT_SUFFIX}',
'roomnumber': room,
'userpassword': PW_DM,
'homeDirectory': '/home/' + user,
'uidNumber': '1000',
'gidNumber': '2000',
'description': description,
'telephonenumber': telephonenumber
})
@pytest.fixture(scope="module")
def _create_entries(topo):
"""
Will create necessary users for this script.
"""
# Creating Users
users_people = UserAccounts(topo.standalone, DEFAULT_SUFFIX)
for user, room in [('scarte2', '2013'),
('mward', '1707'),
('tclow', '4376'),
('bwalker', '3529')]:
create_users_all(users_people, user, room, 'Santa Clara',
'This is the special * attribute value',
'+1 408 555 7393')
for number in range(200, 300):
create_users_all(users_people, f'user{number}', f'{number}',
'Sunnyvale', 'Not the one you looking for.',
'123')
for user, room in [('abergin', '3472'),
('mtyler', '2701'),
('ptyler', '0327'),
('gtyler', '0312'),
('ewalker', '2295'),
('awalker', '0061'),
('jreuter', '2942'),
('passin', '3530')
]:
create_users_all(users_people, user, room, 'Cupertino',
'Not the one you looking for.',
'123')
for user, name, lang, tele in [
(f'uid=user147,ou=Çlose Crèkä,{DEFAULT_SUFFIX}', 'Ellàdiñé Passin',
'lang-de', '+1 408 555 7393'),
(f'uid=user0, ou=Ännheimè,{DEFAULT_SUFFIX}', 'Babette Rynders',
'lang-es', '+1 415 788-4115'),
(f'uid=user1,ou=Sàn Fråncêscô,{DEFAULT_SUFFIX}', 'myrty DeCoursin',
'lang-ie', '+1 408 689-8883'),
(f'uid=user2,ou=Çéliné Ändrè,{DEFAULT_SUFFIX}', "Row O'Conner",
'lang-it', '+1 714 902-8784'),
(f'uid=user10,ou=Sàn Fråncêscô,{DEFAULT_SUFFIX}', "Candide Ruiz",
'lang-be', '+1 818 774-5666'),
(f'uid=user11,ou=Çéliné Ändrè,{DEFAULT_SUFFIX}', "Rosene Tarquinio",
'lang-ie', '+1 818 512-5483'),
(f'uid=user22,ou=Çéliné Ändrè,{DEFAULT_SUFFIX}', "Drusie Dynie",
'lang-it', '+1 303 520-7607'),
(f'uid=user32,ou=Sàn Fråncêscô,{DEFAULT_SUFFIX}', "Deat Liverman",
'lang-it', '+1 714 986-7403'),
(f'uid=user42,ou=Sàn Fråncêscô,{DEFAULT_SUFFIX}', "Emyd Artzer",
'lang-be', '+1 415 382-3440'),
(f'uid=user52,ou=Ännheimè,{DEFAULT_SUFFIX}', "Lurlene Christie",
'lang-se', '+1 818 301-7281'),
(f'uid=user62,ou=Çlose Crèkä,{DEFAULT_SUFFIX}', "Goutam Sawchuk",
'lang-es', '+1 804 159-3054'),
(f'uid=user74,ou=Sàn Fråncêscô,{DEFAULT_SUFFIX}', "Sally Rossi",
'lang-de', '+1 714 558-4165'),
(f'uid=user93,ou=Sàn Fråncêscô,{DEFAULT_SUFFIX}', "Dolores Markovic",
'lang-it', '+1 408 374-9555'),
(f'uid=user102,ou=Çlose Crèkä,{DEFAULT_SUFFIX}', "Clovis Safah",
'lang-de', '+1 415 964-2124'),
(f'uid=user115,ou=Ännheimè,{DEFAULT_SUFFIX}', "Angelie Mirande",
'lang-ie', '+1 804 832-8156'),
(f'uid=user127,ou=Sàn Fråncêscô,{DEFAULT_SUFFIX}', "Sibilla Millspaugh",
'lang-it', '+1 818 204-6815')]:
users_people.create(properties={
'mail': f'{user}'.split(',')[0].split('=')[1] + '@redhat.com',
'uid': f'{user}'.split(',')[0].split('=')[1],
'cn': name,
'sn': name.split()[1],
'givenName': f'{user}'.split(',')[0].split('=')[1].title(),
f'givenName;{lang}': f'{user}'.split(',')[0].split('=')[1].title(),
f'cn;{lang}': name,
f'sn;{lang}': name.split()[1],
'manager': user,
'roomnumber': '0056',
'telephonenumber': tele,
'userpassword': PW_DM,
'homeDirectory': '/home/' + f'{user}'.split(',')[0].split('=')[1],
'uidNumber': '1000',
'gidNumber': '2000',
'description': 'This is xman * attribute value'
})
users_people.create(properties={
'l': 'Sunnyvale',
'cn': 'Kirsten Vaughan',
'sn': 'Vaughan',
'givenname': 'Kirsten',
'uid': 'kvaughan',
'mail': 'kvaughan@example.com',
'roomnumber': '2871',
'nsSizeLimit': '-1',
'nsTimeLimit': '-1',
'nsIdleTimeout': '-1',
'manager': f'uid=kvaughan,ou=People,{DEFAULT_SUFFIX}',
'userpassword': PW_DM,
'homeDirectory': '/home/' + 'kvaughan',
'uidNumber': '1000',
'gidNumber': '2000',
})
@pytest.mark.parametrize("real_value", VALUES)
def test_telephone(topo, _create_entries, real_value):
"""Test telephone number attr with filter
:id: abe3e6de-9eec-11e8-adf0-8c16451d917b
:setup: Standalone
:steps:
1. Pass filter rules as per the condition .
:expected results:
2. Pass
"""
conn = UserAccount(topo.standalone, f'uid=jreuter,ou=People,{DEFAULT_SUFFIX}').bind(PW_DM)
for user in Accounts(conn, DEFAULT_SUFFIX).filter(real_value):
assert user.get_attr_val_utf8("telephoneNumber")
@pytest.mark.parametrize("real_value", POSITIVE)
def test_all_positive(topo, _create_entries, real_value):
"""Test filters with positive output.
:id: abe3e6dd-9ecc-11e8-adf0-8c16451d917b
:setup: Standalone
:steps:
1. Pass filter rules as per the condition .
:expected results:
1. Pass
"""
conn = UserAccount(topo.standalone, f'uid=tclow,ou=People,{DEFAULT_SUFFIX}').bind(PW_DM)
assert Accounts(conn, DEFAULT_SUFFIX).filter(real_value)
@pytest.mark.parametrize("real_value", NEGATIVE)
def test_all_negative(topo, _create_entries, real_value):
"""Test filters which will not give any output.
:id: abe3e1de-9ecc-11e8-adf0-8c16451d917b
:setup: Standalone
:steps:
1. Pass filter rules as per the negative condition .
:expected results:
1. Fail
"""
conn = UserAccount(topo.standalone, f'uid=tclow,ou=People,{DEFAULT_SUFFIX}').bind(PW_DM)
assert not Accounts(conn, DEFAULT_SUFFIX).filter(real_value)
if __name__ == '__main__':
CURRENT_FILE = os.path.realpath(__file__)
pytest.main("-s -v %s" % CURRENT_FILE)
# --- BEGIN COPYRIGHT BLOCK ---
# Copyright (C) 2019 William Brown <william@blackhats.net.au>
# All rights reserved.
#
# License: GPL (version 3 or any later version).
# See LICENSE for details.
# --- END COPYRIGHT BLOCK ---
#
import ldap
import pytest
from lib389.topologies import topology_st
from lib389.idm.user import UserAccounts
from lib389._constants import (DEFAULT_SUFFIX, PASSWORD)
def test_password_hash_on_upgrade(topology_st):
"""If a legacy password hash is present, assert that on a correct bind
the hash is "upgraded" to the latest-and-greatest hash format on the
server.
Assert also that password FAILURE does not alter the password.
:id: 42cf99e6-454d-46f5-8f1c-8bb699864a07
:setup: Single instance
:steps: 1. Set a password hash in SSHA256, and hash to pbkdf2 statically
2. Test a faulty bind
3. Assert the PW is SSHA256
4. Test a correct bind
5. Assert the PW is PBKDF2
:expectedresults:
1. Successfully set the values
2. The bind fails
3. The PW is SSHA256
4. The bind succeeds
5. The PW is PBKDF2
"""
# Make sure the server is set to pkbdf
topology_st.standalone.config.set('passwordStorageScheme', 'PBKDF2_SHA256')
topology_st.standalone.config.set('nsslapd-allow-hashed-passwords', 'on')
topology_st.standalone.config.set('nsslapd-enable-upgrade-hash', 'on')
users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX)
user = users.create_test_user()
# Static version of "password" in SSHA256.
user.set('userPassword', "{SSHA256}9eliEQgjfc4Fcj1IXZtc/ne1GRF+OIjz/NfSTX4f7HByGMQrWHLMLA==")
# Attempt to bind with incorrect password.
with pytest.raises(ldap.INVALID_CREDENTIALS):
badconn = user.bind('badpassword')
# Check the pw is SSHA256
up = user.get_attr_val_utf8('userPassword')
assert up.startswith('{SSHA256}')
# Bind with correct.
conn = user.bind(PASSWORD)
# Check the pw is now PBKDF2!
up = user.get_attr_val_utf8('userPassword')
assert up.startswith('{PBKDF2_SHA256}')
def test_password_hash_on_upgrade_clearcrypt(topology_st):
"""In some deploymentes, some passwords MAY be in clear or crypt which have
specific possible application integrations allowing the read value to be
processed by other entities. We avoid upgrading these two, to prevent
breaking these integrations.
:id: 27712492-a4bf-4ea9-977b-b4850ddfb628
:setup: Single instance
:steps: 1. Set a password hash in CLEAR, and hash to pbkdf2 statically
2. Test a correct bind
3. Assert the PW is CLEAR
4. Set the password to CRYPT
5. Test a correct bind
6. Assert the PW is CLEAR
:expectedresults:
1. Successfully set the values
2. The bind succeeds
3. The PW is CLEAR
4. The set succeeds
4. The bind succeeds
5. The PW is CRYPT
"""
# Make sure the server is set to pkbdf
topology_st.standalone.config.set('nsslapd-allow-hashed-passwords', 'on')
topology_st.standalone.config.set('nsslapd-enable-upgrade-hash', 'on')
users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX)
user = users.create_test_user(1001)
topology_st.standalone.config.set('passwordStorageScheme', 'CLEAR')
user.set('userPassword', "password")
topology_st.standalone.config.set('passwordStorageScheme', 'PBKDF2_SHA256')
conn = user.bind(PASSWORD)
up = user.get_attr_val_utf8('userPassword')
assert up.startswith('password')
user.set('userPassword', "{crypt}I0S3Ry62CSoFg")
conn = user.bind(PASSWORD)
up = user.get_attr_val_utf8('userPassword')
assert up.startswith('{crypt}')
def test_password_hash_on_upgrade_disable(topology_st):
"""If a legacy password hash is present, assert that on a correct bind
the hash is "upgraded" to the latest-and-greatest hash format on the
server. But some people may not like this, so test that we can disable
the feature too!
:id: ed315145-a3d1-4f17-b04c-73d3638e7ade
:setup: Single instance
:steps: 1. Set a password hash in SSHA256, and hash to pbkdf2 statically
2. Test a faulty bind
3. Assert the PW is SSHA256
4. Test a correct bind
5. Assert the PW is SSHA256
:expectedresults:
1. Successfully set the values
2. The bind fails
3. The PW is SSHA256
4. The bind succeeds
5. The PW is SSHA256
"""
# Make sure the server is set to pkbdf
topology_st.standalone.config.set('passwordStorageScheme', 'PBKDF2_SHA256')
topology_st.standalone.config.set('nsslapd-allow-hashed-passwords', 'on')
topology_st.standalone.config.set('nsslapd-enable-upgrade-hash', 'off')
users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX)
user = users.create_test_user(1002)
# Static version of "password" in SSHA256.
user.set('userPassword', "{SSHA256}9eliEQgjfc4Fcj1IXZtc/ne1GRF+OIjz/NfSTX4f7HByGMQrWHLMLA==")
# Attempt to bind with incorrect password.
with pytest.raises(ldap.INVALID_CREDENTIALS):
badconn = user.bind('badpassword')
# Check the pw is SSHA256
up = user.get_attr_val_utf8('userPassword')
assert up.startswith('{SSHA256}')
# Bind with correct.
conn = user.bind(PASSWORD)
# Check the pw is NOT upgraded!
up = user.get_attr_val_utf8('userPassword')
assert up.startswith('{SSHA256}')
......@@ -8,8 +8,11 @@
import pytest
import time
from lib389._constants import PASSWORD, DN_DM, DEFAULT_SUFFIX
from lib389._constants import SUFFIX, PASSWORD, DN_DM, DN_CONFIG, PLUGIN_RETRO_CHANGELOG, DEFAULT_SUFFIX, DEFAULT_CHANGELOG_DB
from lib389 import Entry
from lib389.topologies import topology_m1 as topo_master
from lib389.idm.user import UserAccounts
from lib389.utils import ldap, os, logging
from lib389.utils import ldap, os, logging, ensure_bytes
from lib389.topologies import topology_st as topo
from lib389.idm.organizationalunit import OrganizationalUnits
......@@ -36,6 +39,23 @@ TEST_PASSWORDS += ['CNpwtest1ZZZZ', 'ZZZZZCNpwtest1',
TEST_PASSWORDS2 = (
'CN12pwtest31', 'SN3pwtest231', 'UID1pwtest123', 'MAIL2pwtest12@redhat.com', '2GN1pwtest123', 'People123')
def _check_unhashed_userpw(inst, user_dn, is_present=False):
"""Check if unhashed#user#password attribute is present of not in the changelog"""
unhashed_pwd_attribute = 'unhashed#user#password'
changelog_dbdir = os.path.join(os.path.dirname(inst.dbdir), DEFAULT_CHANGELOG_DB)
for dbfile in os.listdir(changelog_dbdir):
if dbfile.endswith('.db'):
changelog_dbfile = os.path.join(changelog_dbdir, dbfile)
log.info('Changelog dbfile file exist: {}'.format(changelog_dbfile))
log.info('Running dbscan -f to check {} attr'.format(unhashed_pwd_attribute))
dbscanOut = inst.dbscan(DEFAULT_CHANGELOG_DB, changelog_dbfile)
for entry in dbscanOut.split(b'dbid: '):
if ensure_bytes('operation: modify') in entry and ensure_bytes(user_dn) in entry and ensure_bytes('userPassword') in entry:
if is_present:
assert ensure_bytes(unhashed_pwd_attribute) in entry
else:
assert ensure_bytes(unhashed_pwd_attribute) not in entry
@pytest.fixture(scope="module")
def passw_policy(topo, request):
......@@ -193,6 +213,105 @@ def test_global_vs_local(topo, passw_policy, create_user, user_pasw):
# reset password
create_user.set('userPassword', PASSWORD)
@pytest.mark.ds49789
def test_unhashed_pw_switch(topo_master):
"""Check that nsslapd-unhashed-pw-switch works corrently
:id: e5aba180-d174-424d-92b0-14fe7bb0b92a
:setup: Master Instance
:steps:
1. A Master is created, enable retrocl (not used here)
2. create a set of users
3. update userpassword of user1 and check that unhashed#user#password is not logged (default)
4. udpate userpassword of user2 and check that unhashed#user#password is not logged ('nolog')
5. udpate userpassword of user3 and check that unhashed#user#password is logged ('on')
:expectedresults:
1. Success
2. Success
3 Success (unhashed#user#password is not logged in the replication changelog)
4. Success (unhashed#user#password is not logged in the replication changelog)
5. Success (unhashed#user#password is logged in the replication changelog)
"""
MAX_USERS = 10
PEOPLE_DN = ("ou=people," + DEFAULT_SUFFIX)
inst = topo_master.ms["master1"]
inst.modify_s("cn=Retro Changelog Plugin,cn=plugins,cn=config",
[(ldap.MOD_REPLACE, 'nsslapd-changelogmaxage', b'2m'),
(ldap.MOD_REPLACE, 'nsslapd-changelog-trim-interval', b"5s"),
(ldap.MOD_REPLACE, 'nsslapd-logAccess', b'on')])
inst.config.loglevel(vals=[256 + 4], service='access')
inst.restart()
# If you need any test suite initialization,
# please, write additional fixture for that (including finalizer).
# Topology for suites are predefined in lib389/topologies.py.
# enable dynamic plugins, memberof and retro cl plugin
#
log.info('Enable plugins...')
try:
inst.modify_s(DN_CONFIG,
[(ldap.MOD_REPLACE,
'nsslapd-dynamic-plugins',
b'on')])
except ldap.LDAPError as e:
ldap.error('Failed to enable dynamic plugins! ' + e.message['desc'])
assert False
#topology_st.standalone.plugins.enable(name=PLUGIN_MEMBER_OF)
inst.plugins.enable(name=PLUGIN_RETRO_CHANGELOG)
#topology_st.standalone.modify_s("cn=changelog,cn=ldbm database,cn=plugins,cn=config", [(ldap.MOD_REPLACE, 'nsslapd-cachememsize', str(100000))])
inst.restart()
log.info('create users and group...')
for idx in range(1, MAX_USERS):
try:
USER_DN = ("uid=member%d,%s" % (idx, PEOPLE_DN))
inst.add_s(Entry((USER_DN,
{'objectclass': 'top extensibleObject'.split(),
'uid': 'member%d' % (idx)})))
except ldap.LDAPError as e:
log.fatal('Failed to add user (%s): error %s' % (USER_DN, e.message['desc']))
assert False
# Check default is that unhashed#user#password is not logged
user = "uid=member1,%s" % (PEOPLE_DN)
inst.modify_s(user, [(ldap.MOD_REPLACE,
'userpassword',
PASSWORD.encode())])
inst.stop()
_check_unhashed_userpw(inst, user, is_present=False)
# Check with nolog that unhashed#user#password is not logged
inst.modify_s(DN_CONFIG,
[(ldap.MOD_REPLACE,
'nsslapd-unhashed-pw-switch',
b'nolog')])
inst.restart()
user = "uid=member2,%s" % (PEOPLE_DN)
inst.modify_s(user, [(ldap.MOD_REPLACE,
'userpassword',
PASSWORD.encode())])
inst.stop()
_check_unhashed_userpw(inst, user, is_present=False)
# Check with value 'on' that unhashed#user#password is logged
inst.modify_s(DN_CONFIG,
[(ldap.MOD_REPLACE,
'nsslapd-unhashed-pw-switch',
b'on')])
inst.restart()
user = "uid=member3,%s" % (PEOPLE_DN)
inst.modify_s(user, [(ldap.MOD_REPLACE,
'userpassword',
PASSWORD.encode())])
inst.stop()
_check_unhashed_userpw(inst, user, is_present=True)
if DEBUGGING:
# Add debugging steps(if any)...
pass
if __name__ == '__main__':
# Run isolated
......
......@@ -6,7 +6,7 @@ import time
from lib389._constants import *
from lib389.properties import *
from lib389.topologies import topology_m1 as topo
from lib389.changelog import Changelog5
from lib389.replica import Changelog5
from lib389.idm.domain import Domain
pytestmark = pytest.mark.tier1
......@@ -132,4 +132,3 @@ if __name__ == '__main__':
# -s for DEBUG mode
CURRENT_FILE = os.path.realpath(__file__)
pytest.main("-s %s" % CURRENT_FILE)
......@@ -18,9 +18,8 @@ from lib389.idm.user import UserAccount
from lib389.idm.group import Groups, Group
from lib389.idm.domain import Domain
from lib389.idm.directorymanager import DirectoryManager
from lib389.replica import Replicas, ReplicationManager
from lib389.replica import Replicas, ReplicationManager, Changelog5
from lib389.agreement import Agreements
from lib389.changelog import Changelog5
from lib389 import pid_from_file
......
import logging
import pytest
import os
from lib389.config import Encryption
from lib389.topologies import topology_st as topo
DEBUGGING = os.getenv("DEBUGGING", default=False)
if DEBUGGING:
logging.getLogger(__name__).setLevel(logging.DEBUG)
else:
logging.getLogger(__name__).setLevel(logging.INFO)
log = logging.getLogger(__name__)
def test_ssl_version_range(topo):
"""Specify a test case purpose or name here
:id: bc400f54-3966-49c8-b640-abbf4fb2377e
1. Get current default range
2. Set sslVersionMin and verify it is applied after a restart
3. Set sslVersionMax and verify it is applied after a restart
:expectedresults:
1. Success
2. Success
3. Success
"""
topo.standalone.enable_tls()
enc = Encryption(topo.standalone)
default_min = enc.get_attr_val_utf8('sslVersionMin')
default_max = enc.get_attr_val_utf8('sslVersionMax')
log.info(f"default min: {default_min} max: {default_max}")
if DEBUGGING:
topo.standalone.config.set('nsslapd-auditlog-logging-enabled', 'on')
# Test that setting the min version is applied after a restart
enc.replace('sslVersionMin', default_max)
enc.replace('sslVersionMax', default_max)
topo.standalone.restart()
min = enc.get_attr_val_utf8('sslVersionMin')
assert min == default_max
# Test that setting the max version is applied after a restart
enc.replace('sslVersionMin', default_min)
enc.replace('sslVersionMax', default_min)
topo.standalone.restart()
max = enc.get_attr_val_utf8('sslVersionMax')
assert max == default_min
if __name__ == '__main__':
# Run isolated
# -s for DEBUG mode
CURRENT_FILE = os.path.realpath(__file__)
pytest.main(["-s", CURRENT_FILE])
......@@ -12,7 +12,7 @@ RUN zypper ar http://download.opensuse.org/update/leap/15.1/oss/ u && \
zypper --gpg-auto-import-keys ref
RUN zypper --non-interactive si --build-deps-only 389-ds && \
zypper in -y 389-ds rust cargo rust-std && \
zypper in -y 389-ds rust cargo rust-std libevent && \
zypper rm -y 389-ds
# Install build dependencies
......@@ -33,7 +33,8 @@ WORKDIR /usr/local/src/389-ds-base
# Build and install
# Derived from rpm --eval '%configure' on opensuse.
RUN ./configure --host=x86_64-suse-linux-gnu --build=x86_64-suse-linux-gnu \
RUN autoreconf -fiv && \
./configure --host=x86_64-suse-linux-gnu --build=x86_64-suse-linux-gnu \
--program-prefix= \
--disable-dependency-tracking \
--prefix=/usr \
......
#!BuildTag: 389-ds-container
FROM opensuse/leap:15.1
MAINTAINER wbrown@suse.de
EXPOSE 3389 3636
# RUN zypper ar -G obs://network:ldap network:ldap && \
RUN zypper ar http://download.opensuse.org/update/leap/15.1/oss/ u && \
zypper ar http://download.opensuse.org/distribution/leap/15.1/repo/oss/ m && \
zypper ar http://download.opensuse.org/repositories/network:ldap/openSUSE_Leap_15.1/ "network:ldap" && \
zypper mr -p 97 "network:ldap" && \
zypper --gpg-auto-import-keys ref
# Push source code to the container - we do this early because we want the zypper and
# build instructions in a single RUN stanza to minimise the container final size.
ADD ./ /usr/local/src/389-ds-base
WORKDIR /usr/local/src/389-ds-base
# Build and install
# Derived from rpm --eval '%configure' on opensuse.
RUN zypper --non-interactive si --build-deps-only 389-ds && \
zypper in -y 389-ds rust cargo rust-std && \
zypper rm -y 389-ds lib389 && \
autoreconf -fiv && \
./configure --host=x86_64-suse-linux-gnu --build=x86_64-suse-linux-gnu \
--program-prefix= \
--disable-dependency-tracking \
--prefix=/usr \
--exec-prefix=/usr \
--bindir=/usr/bin \
--sbindir=/usr/sbin \
--sysconfdir=/etc \
--datadir=/usr/share \
--includedir=/usr/include \
--libdir=/usr/lib64 \
--libexecdir=/usr/lib \
--localstatedir=/var \
--sharedstatedir=/var/lib \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
--disable-dependency-tracking \
--enable-gcc-security --enable-autobind --enable-auto-dn-suffix --with-openldap \
--enable-rust --disable-perl --with-pythonexec="python3" --without-systemd \
--libexecdir=/usr/lib/dirsrv/ --prefix=/ && \
make -j 12 && \
make install && \
make lib389 && \
make lib389-install && \
make clean && \
zypper rm -y -u rust cargo rust-std gcc gcc-c++ automake autoconf
# Link some known static locations to point to /data
RUN mkdir -p /data/config && \
mkdir -p /data/ssca && \
mkdir -p /data/run && \
mkdir -p /var/run/dirsrv && \
ln -s /data/config /etc/dirsrv/slapd-localhost && \
ln -s /data/ssca /etc/dirsrv/ssca && \
ln -s /data/run /var/run/dirsrv
# Temporal volumes for each instance
VOLUME /data
# Set the userup correctly. This was created as part of the 389ds in above.
# For k8s we'll need 389 to not drop privs? I think we don't specify a user
# here and ds should do the right thing if a non root user runs the server.
# USER dirsrv
CMD [ "/usr/sbin/dscontainer", "-r" ]
......@@ -44,7 +44,7 @@ start_instance() {
instance=`get_slapd_instance @instconfigdir@ $SERV_ID` || { echo Instance $SERV_ID not found. ; return 1 ; }
CONFIG_DIR="@instconfigdir@/slapd-$instance";
PIDFILE=$RUN_DIR/slapd-$SERV_ID.pid
PIDFILE=@localstatedir@$RUN_DIR/slapd-$SERV_ID.pid
if test -f $PIDFILE ; then
PID=`cat $PIDFILE`
......@@ -58,12 +58,12 @@ start_instance() {
if test 1 -eq @enable_asan@; then
echo "NOTICE: Starting instance ${SERV_ID} with ASAN options."
echo "This is probably not what you want. Please contact support."
: ${ASAN_LOG_PATH:=$RUN_DIR/ns-slapd-${SERV_ID}.asan}
: ${ASAN_LOG_PATH:=@localstatedir@$RUN_DIR/ns-slapd-${SERV_ID}.asan}
echo "Asan errors will go to ${ASAN_LOG_PATH}*"
export ASAN_OPTIONS="detect_leaks=1 symbolize=1 detect_deadlocks=1 log_path=${ASAN_LOG_PATH}"
export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer
fi
$SERVERBIN_DIR/ns-slapd -D $CONFIG_DIR -i $PIDFILE "$@"
@sbindir@/ns-slapd -D $CONFIG_DIR -i $PIDFILE "$@"
if [ $? -ne 0 ]; then
return 1
fi
......
......@@ -13,7 +13,7 @@ RUN_DIR="@localrundir@/@PACKAGE_NAME@";
stop_instance() {
SERV_ID=$1
PIDFILE=$RUN_DIR/slapd-$SERV_ID.pid
PIDFILE=@localstatedir@$RUN_DIR/slapd-$SERV_ID.pid
if test ! -f $PIDFILE ; then
echo No ns-slapd PID file found. Server is probably not running
return 2
......
......@@ -88,7 +88,7 @@ do_abandon(Slapi_PBlock *pb)
* flag and abort the operation at a convenient time.
*/
PR_EnterMonitor(pb_conn->c_mutex);
pthread_mutex_lock(&(pb_conn->c_mutex));
for (o = pb_conn->c_ops; o != NULL; o = o->o_next) {
if (o->o_msgid == id && o != pb_op)
break;
......@@ -151,7 +151,7 @@ do_abandon(Slapi_PBlock *pb)
o->o_results.r.r_search.nentries, (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec);
}
PR_ExitMonitor(pb_conn->c_mutex);
pthread_mutex_unlock(&(pb_conn->c_mutex));
/*
* Wake up the persistent searches, so they
* can notice if they've been abandoned.
......
......@@ -232,7 +232,7 @@ do_bind(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_PWPOLICY, &pw_response_requested);
}
PR_EnterMonitor(pb_conn->c_mutex);
pthread_mutex_lock(&(pb_conn->c_mutex));
bind_credentials_clear(pb_conn, PR_FALSE, /* do not lock conn */
PR_FALSE /* do not clear external creds. */);
......@@ -263,7 +263,7 @@ do_bind(Slapi_PBlock *pb)
* bound user can work properly
*/
pb_conn->c_needpw = 0;
PR_ExitMonitor(pb_conn->c_mutex);
pthread_mutex_unlock(&(pb_conn->c_mutex));
log_bind_access(pb, dn ? dn : "empty", method, version, saslmech, NULL);
......@@ -762,6 +762,15 @@ do_bind(Slapi_PBlock *pb)
goto free_and_return;
}
}
/*
* If required, update the pw hash to the "current setting" on bind
* if it was successful.
*/
if (config_get_enable_upgrade_hash()) {
update_pw_encoding(pb, bind_target_entry, sdn, cred.bv_val);
}
bind_credentials_set(pb_conn, authtype,
slapi_ch_strdup(slapi_sdn_get_ndn(sdn)),
NULL, NULL, NULL, bind_target_entry);
......@@ -783,6 +792,7 @@ do_bind(Slapi_PBlock *pb)
/* need_new_pw failed; need_new_pw already send_ldap_result in it. */
goto free_and_return;
}
} else { /* anonymous */
/* set bind creds here so anonymous limits are set */
bind_credentials_set(pb_conn, authtype, NULL, NULL, NULL, NULL, NULL);
......
......@@ -144,18 +144,19 @@ connection_done(Connection *conn)
connection_cleanup(conn);
/* free the private content, the buffer has been freed by above connection_cleanup */
slapi_ch_free((void **)&conn->c_private);
pthread_mutex_destroy(&(conn->c_mutex));
if (NULL != conn->c_sb) {
ber_sockbuf_free(conn->c_sb);
}
if (NULL != conn->c_mutex) {
PR_DestroyMonitor(conn->c_mutex);
}
if (NULL != conn->c_pdumutex) {
PR_DestroyLock(conn->c_pdumutex);
}
/* PAGED_RESULTS */
pagedresults_cleanup_all(conn, 0);
/* Finally, flag that we are clean - basically write a 0 ...*/
conn->c_state = CONN_STATE_FREE;
/*
* WARNING: There is a memory leak here! During a shutdown, connections
* can still have events in ns add io timeout job because of post connection
......@@ -748,15 +749,18 @@ connection_acquire_nolock(Connection *conn)
int
connection_is_free(Connection *conn, int use_lock)
{
int rc;
int rc = 0;
if (use_lock) {
PR_EnterMonitor(conn->c_mutex);
/* If the lock is held, someone owns this! */
if (pthread_mutex_trylock(&(conn->c_mutex)) != 0) {
return 0;
}
}
rc = conn->c_sd == SLAPD_INVALID_SOCKET && conn->c_refcnt == 0 &&
!(conn->c_flags & CONN_FLAG_CLOSING);
if (use_lock) {
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
}
return rc;
......@@ -1130,7 +1134,7 @@ connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, int *
size_t buffer_data_avail;
int conn_closed = 0;
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
/*
* if the socket is still valid, get the ber element
* waiting for us on this connection. timeout is handled
......@@ -1323,16 +1327,16 @@ connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, int *
}
op->o_tag = *tag;
done:
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
return ret;
}
void
connection_make_readable(Connection *conn)
{
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
conn->c_gettingber = 0;
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
signal_listner();
}
......@@ -1356,7 +1360,7 @@ connection_check_activity_level(Connection *conn)
{
int current_count = 0;
int delta_count = 0;
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
/* get the current op count */
current_count = conn->c_opscompleted;
/* compare to the previous op count */
......@@ -1367,7 +1371,7 @@ connection_check_activity_level(Connection *conn)
conn->c_private->previous_op_count = current_count;
/* update the last checked time */
conn->c_private->previous_count_check_time = slapi_current_utc_time();
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
slapi_log_err(SLAPI_LOG_CONNS, "connection_check_activity_level", "conn %" PRIu64 " activity level = %d\n", conn->c_connid, delta_count);
}
......@@ -1415,7 +1419,7 @@ connection_enter_leave_turbo(Connection *conn, int current_turbo_flag, int *new_
int connection_count = 0;
int our_rank = 0;
int threshold_rank = 0;
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
/* We can already be in turbo mode, or not */
current_mode = current_turbo_flag;
if (pagedresults_in_use_nolock(conn)) {
......@@ -1460,7 +1464,7 @@ connection_enter_leave_turbo(Connection *conn, int current_turbo_flag, int *new_
new_mode = 1;
}
}
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
if (current_mode != new_mode) {
if (current_mode) {
slapi_log_err(SLAPI_LOG_CONNS, "connection_enter_leave_turbo", "conn %" PRIu64 " leaving turbo mode\n", conn->c_connid);
......@@ -1541,7 +1545,7 @@ connection_threadmain()
return;
}
PR_EnterMonitor(pb_conn->c_mutex);
pthread_mutex_lock(&(pb_conn->c_mutex));
if (pb_conn->c_anonlimits_set == 0) {
/*
* We have a new connection, set the anonymous reslimit idletimeout
......@@ -1567,7 +1571,7 @@ connection_threadmain()
*/
pb_conn->c_anonlimits_set = 1;
}
PR_ExitMonitor(pb_conn->c_mutex);
pthread_mutex_unlock(&(pb_conn->c_mutex));
if (connection_call_io_layer_callbacks(pb_conn)) {
slapi_log_err(SLAPI_LOG_ERR, "connection_threadmain",
......@@ -1584,14 +1588,14 @@ connection_threadmain()
*/
PR_Sleep(PR_INTERVAL_NO_WAIT);
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
/* Make our own pb in turbo mode */
connection_make_new_pb(pb, conn);
if (connection_call_io_layer_callbacks(conn)) {
slapi_log_err(SLAPI_LOG_ERR, "connection_threadmain",
"Could not add/remove IO layers from connection\n");
}
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
if (!config_check_referral_mode()) {
slapi_counter_increment(ops_initiated);
slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsInOps);
......@@ -1706,9 +1710,9 @@ connection_threadmain()
if ((tag != LDAP_REQ_UNBIND) && !thread_turbo_flag && !replication_connection) {
if (!more_data) {
conn->c_flags &= ~CONN_FLAG_MAX_THREADS;
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
connection_make_readable_nolock(conn);
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
/* once the connection is readable, another thread may access conn,
* so need locking from here on */
signal_listner();
......@@ -1720,7 +1724,7 @@ connection_threadmain()
*/
} else if (!enable_nunc_stans) { /* more data in conn - just put back on work_q - bypass poll */
bypasspollcnt++;
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
/* don't do this if it would put us over the max threads per conn */
if (conn->c_threadnumber < maxthreads) {
/* for turbo, c_idlesince is set above - for !turbo and
......@@ -1736,7 +1740,7 @@ connection_threadmain()
/* keep count of how many times maxthreads has blocked an operation */
conn->c_maxthreadsblocked++;
}
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
}
}
......@@ -1772,14 +1776,14 @@ connection_threadmain()
done:
if (doshutdown) {
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
connection_remove_operation_ext(pb, conn, op);
connection_make_readable_nolock(conn);
conn->c_threadnumber--;
slapi_counter_decrement(conns_in_maxthreads);
slapi_counter_decrement(g_get_global_snmp_vars()->ops_tbl.dsConnectionsInMaxThreads);
connection_release_nolock(conn);
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
signal_listner();
slapi_pblock_destroy(pb);
return;
......@@ -1804,9 +1808,9 @@ connection_threadmain()
* continues to hold the connection
*/
if (!thread_turbo_flag && !more_data) {
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
connection_release_nolock(conn); /* psearch acquires ref to conn - release this one now */
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
}
/* ps_add makes a shallow copy of the pb - so we
* can't free it or init it here - just set operation to NULL.
......@@ -1817,7 +1821,7 @@ connection_threadmain()
} else {
/* delete from connection operation queue & decr refcnt */
int conn_closed = 0;
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
connection_remove_operation_ext(pb, conn, op);
/* If we're in turbo mode, we keep our reference to the connection alive */
......@@ -1869,7 +1873,7 @@ connection_threadmain()
signal_listner();
}
}
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
}
} /* while (1) */
}
......@@ -2125,7 +2129,7 @@ op_copy_identity(Connection *conn, Operation *op)
size_t dnlen;
size_t typelen;
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
dnlen = conn->c_dn ? strlen(conn->c_dn) : 0;
typelen = conn->c_authtype ? strlen(conn->c_authtype) : 0;
......@@ -2157,14 +2161,14 @@ op_copy_identity(Connection *conn, Operation *op)
op->o_ssf = conn->c_local_ssf;
}
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
}
/* Sets the SSL SSF in the connection struct. */
static void
connection_set_ssl_ssf(Connection *conn)
{
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
if (conn->c_flags & CONN_FLAG_SSL) {
SSL_SecurityStatus(conn->c_prfd, NULL, NULL, NULL, &(conn->c_ssl_ssf), NULL, NULL);
......@@ -2172,7 +2176,7 @@ connection_set_ssl_ssf(Connection *conn)
conn->c_ssl_ssf = 0;
}
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
}
static int
......@@ -2223,9 +2227,9 @@ log_ber_too_big_error(const Connection *conn, ber_len_t ber_len, ber_len_t maxbe
void
disconnect_server(Connection *conn, PRUint64 opconnid, int opid, PRErrorCode reason, PRInt32 error)
{
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
disconnect_server_nomutex(conn, opconnid, opid, reason, error);
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
}
static ps_wakeup_all_fn_ptr ps_wakeup_all_fn = NULL;
......
......@@ -51,6 +51,11 @@ connection_table_new(int table_size)
ct->c[i].c_prev = NULL;
ct->c[i].c_ci = i;
ct->c[i].c_fdi = SLAPD_INVALID_SOCKET_INDEX;
/*
* Technically this is a no-op due to calloc, but we should always be
* careful with things like this ....
*/
ct->c[i].c_state = CONN_STATE_FREE;
}
return ct;
}
......@@ -75,10 +80,10 @@ connection_table_abandon_all_operations(Connection_Table *ct)
{
int i;
for (i = 0; i < ct->size; i++) {
if (ct->c[i].c_mutex) {
PR_EnterMonitor(ct->c[i].c_mutex);
if (ct->c[i].c_state != CONN_STATE_FREE) {
pthread_mutex_lock(&(ct->c[i].c_mutex));
connection_abandon_operations(&ct->c[i]);
PR_ExitMonitor(ct->c[i].c_mutex);
pthread_mutex_unlock(&(ct->c[i].c_mutex));
}
}
}
......@@ -87,11 +92,11 @@ void
connection_table_disconnect_all(Connection_Table *ct)
{
for (size_t i = 0; i < ct->size; i++) {
if (ct->c[i].c_mutex) {
if (ct->c[i].c_state != CONN_STATE_FREE) {
Connection *c = &(ct->c[i]);
PR_EnterMonitor(c->c_mutex);
pthread_mutex_lock(&(c->c_mutex));
disconnect_server_nomutex(c, c->c_connid, -1, SLAPD_DISCONNECT_ABORT, ECANCELED);
PR_ExitMonitor(c->c_mutex);
pthread_mutex_unlock(&(c->c_mutex));
}
}
}
......@@ -110,35 +115,57 @@ Connection *
connection_table_get_connection(Connection_Table *ct, int sd)
{
Connection *c = NULL;
int index, count;
size_t index = 0;
size_t count = 0;
PR_Lock(ct->table_mutex);
/*
* We attempt to loop over the ct twice, because connection_is_free uses trylock
* and some resources *might* free in the time needed to loop around.
*/
size_t ct_max_loops = ct->size * 2;
/*
* This uses sd as entropy to randomly start inside the ct rather than
* always head-loading the list. Not my idea, but it's probably okay ...
*/
index = sd % ct->size;
for (count = 0; count < ct->size; count++, index = (index + 1) % ct->size) {
for (count = 0; count < ct_max_loops; count++, index = (index + 1) % ct->size) {
/* Do not use slot 0, slot 0 is head of the list of active connections */
if (index == 0) {
continue;
} else if (ct->c[index].c_mutex == NULL) {
} else if (ct->c[index].c_state == CONN_STATE_FREE) {
break;
}
if (connection_is_free(&(ct->c[index]), 1 /*use lock */)) {
} else if (connection_is_free(&(ct->c[index]), 1 /*use lock */)) {
/* Connection must be allocated, check if it's okay */
break;
}
}
if (count < ct->size) {
/* If count exceeds max loops, we didn't find something into index. */
if (count < ct_max_loops) {
/* Found an available Connection */
c = &(ct->c[index]);
PR_ASSERT(c->c_next == NULL);
PR_ASSERT(c->c_prev == NULL);
PR_ASSERT(c->c_extension == NULL);
if (c->c_mutex == NULL) {
PR_Lock(ct->table_mutex);
c->c_mutex = PR_NewMonitor();
if (c->c_state == CONN_STATE_FREE) {
c->c_state = CONN_STATE_INIT;
pthread_mutexattr_t monitor_attr = {0};
pthread_mutexattr_init(&monitor_attr);
pthread_mutexattr_settype(&monitor_attr, PTHREAD_MUTEX_RECURSIVE);
if (pthread_mutex_init(&(c->c_mutex), &monitor_attr) != 0) {
slapi_log_err(SLAPI_LOG_ERR, "connection_table_get_connection", "pthread_mutex_init failed\n");
exit(1);
}
c->c_pdumutex = PR_NewLock();
PR_Unlock(ct->table_mutex);
if (c->c_mutex == NULL || c->c_pdumutex == NULL) {
c->c_mutex = NULL;
if (c->c_pdumutex == NULL) {
c->c_pdumutex = NULL;
slapi_log_err(SLAPI_LOG_ERR, "connection_table_get_connection", "PR_NewLock failed\n");
exit(1);
......@@ -156,6 +183,9 @@ connection_table_get_connection(Connection_Table *ct, int sd)
/* couldn't find a Connection */
slapi_log_err(SLAPI_LOG_CONNS, "connection_table_get_connection", "Max open connections reached\n");
}
PR_Unlock(ct->table_mutex);
return c;
}
......@@ -364,14 +394,14 @@ connection_table_as_entry(Connection_Table *ct, Slapi_Entry *e)
nreadwaiters = 0;
for (i = 0; i < (ct != NULL ? ct->size : 0); i++) {
PR_Lock(ct->table_mutex);
if ((ct->c[i].c_mutex == NULL) || (ct->c[i].c_mutex == (PRMonitor *)-1)) {
if (ct->c[i].c_state == CONN_STATE_FREE) {
PR_Unlock(ct->table_mutex);
continue;
}
/* Can't take c_mutex if holding table_mutex; temporarily unlock */
PR_Unlock(ct->table_mutex);
PR_EnterMonitor(ct->c[i].c_mutex);
pthread_mutex_lock(&(ct->c[i].c_mutex));
if (ct->c[i].c_sd != SLAPD_INVALID_SOCKET) {
char buf2[SLAPI_TIMESTAMP_BUFSIZE+1];
size_t lendn = ct->c[i].c_dn ? strlen(ct->c[i].c_dn) : 6; /* "NULLDN" */
......@@ -445,7 +475,7 @@ connection_table_as_entry(Connection_Table *ct, Slapi_Entry *e)
attrlist_merge(&e->e_attrs, "connection", vals);
slapi_ch_free_string(&newbuf);
}
PR_ExitMonitor(ct->c[i].c_mutex);
pthread_mutex_unlock(&(ct->c[i].c_mutex));
}
snprintf(buf, sizeof(buf), "%d", nconns);
......@@ -486,10 +516,10 @@ connection_table_dump_activity_to_errors_log(Connection_Table *ct)
for (i = 0; i < ct->size; i++) {
Connection *c = &(ct->c[i]);
if (c->c_mutex) {
if (c->c_state) {
/* Find the connection we are referring to */
int j = c->c_fdi;
PR_EnterMonitor(c->c_mutex);
pthread_mutex_lock(&(c->c_mutex));
if ((c->c_sd != SLAPD_INVALID_SOCKET) &&
(j >= 0) && (c->c_prfd == ct->fd[j].fd)) {
int r = ct->fd[j].out_flags & SLAPD_POLL_FLAGS;
......@@ -498,7 +528,7 @@ connection_table_dump_activity_to_errors_log(Connection_Table *ct)
"activity on %d%s\n", i, r ? "r" : "");
}
}
PR_ExitMonitor(c->c_mutex);
pthread_mutex_unlock(&(c->c_mutex));
}
}
}
......
......@@ -167,69 +167,6 @@ static ns_job_func_t ns_handlers[] = {
ns_handle_pr_read_ready,
ns_handle_closure
};
/*
* NSPR has different implementations for PRMonitor, depending
* on the availble threading model
* The PR_TestAndEnterMonitor is not available for pthreads
* so this is a implementation based on the code in
* prmon.c adapted to resemble the implementation in ptsynch.c
*
* The function needs access to the elements of the PRMonitor struct.
* Therfor the pthread variant of PRMonitor is copied here.
*/
typedef struct MY_PRMonitor
{
const char *name;
pthread_mutex_t lock;
pthread_t owner;
pthread_cond_t entryCV;
pthread_cond_t waitCV;
PRInt32 refCount;
PRUint32 entryCount;
PRIntn notifyTimes;
} MY_PRMonitor;
static PRBool
MY_TestAndEnterMonitor(MY_PRMonitor *mon)
{
pthread_t self = pthread_self();
PRStatus rv;
PRBool rc = PR_FALSE;
PR_ASSERT(mon != NULL);
rv = pthread_mutex_lock(&mon->lock);
if (rv != 0) {
slapi_log_err(SLAPI_LOG_ERR, "TestAndEnterMonitor",
"Failed to acquire monitor mutex, error (%d)\n", rv);
return rc;
}
if (mon->entryCount != 0) {
if (pthread_equal(mon->owner, self))
goto done;
rv = pthread_mutex_unlock(&mon->lock);
if (rv != 0) {
slapi_log_err(SLAPI_LOG_ERR, "TestAndEnterMonitor",
"Failed to release monitor mutex, error (%d)\n", rv);
}
return PR_FALSE;
}
/* and now I have the monitor */
PR_ASSERT(mon->notifyTimes == 0);
PR_ASSERT((mon->owner) == 0);
mon->owner = self;
done:
mon->entryCount += 1;
rv = pthread_mutex_unlock(&mon->lock);
if (rv == PR_SUCCESS) {
rc = PR_TRUE;
} else {
slapi_log_err(SLAPI_LOG_ERR, "TestAndEnterMonitor",
"Failed to release monitor mutex, error (%d)\n", rv);
rc = PR_FALSE;
}
return rc;
}
/* Globals which are used to store the sockets between
* calls to daemon_pre_setuid_init() and the daemon thread
* creation. */
......@@ -1491,13 +1428,13 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
c = connection_table_get_first_active_connection(ct);
while (c) {
next = connection_table_get_next_active_connection(ct, c);
if (c->c_mutex == NULL) {
if (c->c_state == CONN_STATE_FREE) {
connection_table_move_connection_out_of_active_list(ct, c);
} else {
/* we try to acquire the connection mutex, if it is already
* acquired by another thread, don't wait
*/
if (PR_FALSE == MY_TestAndEnterMonitor((MY_PRMonitor *)c->c_mutex)) {
if (pthread_mutex_trylock(&(c->c_mutex)) == EBUSY) {
c = next;
continue;
}
......@@ -1538,7 +1475,7 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
c->c_fdi = SLAPD_INVALID_SOCKET_INDEX;
}
}
PR_ExitMonitor(c->c_mutex);
pthread_mutex_unlock(&(c->c_mutex));
}
c = next;
}
......@@ -1579,12 +1516,13 @@ handle_pr_read_ready(Connection_Table *ct, PRIntn num_poll __attribute__((unused
*/
for (c = connection_table_get_first_active_connection(ct); c != NULL;
c = connection_table_get_next_active_connection(ct, c)) {
if (c->c_mutex != NULL) {
if (c->c_state != CONN_STATE_FREE) {
/* this check can be done without acquiring the mutex */
if (c->c_gettingber)
if (c->c_gettingber) {
continue;
}
PR_EnterMonitor(c->c_mutex);
pthread_mutex_lock(&(c->c_mutex));
if (connection_is_active_nolock(c) && c->c_gettingber == 0) {
PRInt16 out_flags;
short readready;
......@@ -1634,7 +1572,7 @@ handle_pr_read_ready(Connection_Table *ct, PRIntn num_poll __attribute__((unused
SLAPD_DISCONNECT_IDLE_TIMEOUT, EAGAIN);
}
}
PR_ExitMonitor(c->c_mutex);
pthread_mutex_unlock(&(c->c_mutex));
}
}
}
......@@ -1668,7 +1606,7 @@ ns_handle_closure(struct ns_job_t *job)
Connection *c = (Connection *)ns_job_get_data(job);
int do_yield = 0;
PR_EnterMonitor(c->c_mutex);
pthread_mutex_lock(&(c->c_mutex));
/* Assert we really have the right job state. */
PR_ASSERT(job == c->c_job);
......@@ -1678,7 +1616,7 @@ ns_handle_closure(struct ns_job_t *job)
/* Because handle closure will add a new job, we need to detach our current one. */
c->c_job = NULL;
do_yield = ns_handle_closure_nomutex(c);
PR_ExitMonitor(c->c_mutex);
pthread_mutex_unlock(&(c->c_mutex));
/* Remove this task now. */
ns_job_done(job);
if (do_yield) {
......@@ -1855,7 +1793,7 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
{
Connection *c = (Connection *)ns_job_get_data(job);
PR_EnterMonitor(c->c_mutex);
pthread_mutex_lock(&(c->c_mutex));
/* Assert we really have the right job state. */
PR_ASSERT(job == c->c_job);
......@@ -1921,7 +1859,7 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
c->c_connid, c->c_sd);
}
/* Since we call done on the job, we need to remove it here. */
PR_ExitMonitor(c->c_mutex);
pthread_mutex_unlock(&(c->c_mutex));
ns_job_done(job);
return;
}
......@@ -2390,7 +2328,7 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
PR_Close(pr_acceptfd);
return -1;
}
PR_EnterMonitor(conn->c_mutex);
pthread_mutex_lock(&(conn->c_mutex));
/*
* Set the default idletimeout and the handle. We'll update c_idletimeout
......@@ -2478,7 +2416,7 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
connection_table_move_connection_on_to_active_list(the_connection_table, conn);
}
PR_ExitMonitor(conn->c_mutex);
pthread_mutex_unlock(&(conn->c_mutex));
g_increment_current_conn_count();
......@@ -2529,9 +2467,9 @@ ns_handle_new_connection(struct ns_job_t *job)
* that poll() was avoided, even at the expense of putting this new fd back
* in nunc-stans to poll for read ready.
*/
PR_EnterMonitor(c->c_mutex);
pthread_mutex_lock(&(c->c_mutex));
ns_connection_post_io_or_closing(c);
PR_ExitMonitor(c->c_mutex);
pthread_mutex_unlock(&(c->c_mutex));
return;
}
......
......@@ -136,10 +136,10 @@ extop_handle_import_start(Slapi_PBlock *pb, char *extoid __attribute__((unused))
*/
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
if (pb_conn) {
PR_EnterMonitor(pb_conn->c_mutex);
pthread_mutex_lock(&(pb_conn->c_mutex));
pb_conn->c_flags |= CONN_FLAG_IMPORT;
pb_conn->c_bi_backend = be;
PR_ExitMonitor(pb_conn->c_mutex);
pthread_mutex_unlock(&(pb_conn->c_mutex));
}
slapi_pblock_set(pb, SLAPI_EXT_OP_RET_OID, EXTOP_BULK_IMPORT_START_OID);
......@@ -164,11 +164,11 @@ extop_handle_import_done(Slapi_PBlock *pb, char *extoid __attribute__((unused)),
Connection *pb_conn;
slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
PR_EnterMonitor(pb_conn->c_mutex);
pthread_mutex_lock(&(pb_conn->c_mutex));
pb_conn->c_flags &= ~CONN_FLAG_IMPORT;
be = pb_conn->c_bi_backend;
pb_conn->c_bi_backend = NULL;
PR_ExitMonitor(pb_conn->c_mutex);
pthread_mutex_unlock(&(pb_conn->c_mutex));
if ((be == NULL) || (be->be_wire_import == NULL)) {
/* can this even happen? */
......
......@@ -249,6 +249,7 @@ slapi_int_t init_malloc_mmap_threshold;
#endif
slapi_onoff_t init_extract_pem;
slapi_onoff_t init_ignore_vattrs;
slapi_onoff_t init_enable_upgrade_hash;
static int
isInt(ConfigVarType type)
......@@ -1232,8 +1233,11 @@ static struct config_get_and_set
NULL, 0,
(void **)&global_slapdFrontendConfig.tls_check_crl,
CONFIG_SPECIAL_TLS_CHECK_CRL, (ConfigGetFunc)config_get_tls_check_crl,
"none" /* Allow reset to this value */}
"none" /* Allow reset to this value */},
{CONFIG_ENABLE_UPGRADE_HASH, config_set_enable_upgrade_hash,
NULL, 0,
(void **)&global_slapdFrontendConfig.enable_upgrade_hash,
CONFIG_ON_OFF, (ConfigGetFunc)config_get_enable_upgrade_hash, &init_enable_upgrade_hash}
/* End config */
};
......@@ -1751,6 +1755,18 @@ FrontendConfig_init(void)
#endif
init_extract_pem = cfg->extract_pem = LDAP_ON;
/*
* Default upgrade hash to on - this is an important security step, meaning that old
* or legacy hashes are upgraded on bind. It means we are proactive in securing accounts
* that may have infrequent on no password changes (which is current best practice in
* computer security).
*
* A risk is that some accounts may use clear/crypt for other application integrations
* where the hash is "read" from the account. To avoid this, these two hashes are NEVER
* upgraded - in other words, "ON" means only MD5, SHA*, are upgraded to the "current"
* scheme set in cn=config
*/
init_enable_upgrade_hash = cfg->enable_upgrade_hash = LDAP_ON;
/* Done, unlock! */
CFG_UNLOCK_WRITE(cfg);
......@@ -7589,6 +7605,30 @@ config_set_enable_nunc_stans(const char *attrname, char *value, char *errorbuf,
return retVal;
}
int32_t
config_get_enable_upgrade_hash()
{
int32_t retVal;
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
CFG_LOCK_READ(slapdFrontendConfig);
retVal = slapdFrontendConfig->enable_upgrade_hash;
CFG_UNLOCK_READ(slapdFrontendConfig);
return retVal;
}
int32_t
config_set_enable_upgrade_hash(const char *attrname, char *value, char *errorbuf, int32_t apply)
{
int32_t retVal = LDAP_SUCCESS;
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
retVal = config_set_onoff(attrname, value,
&(slapdFrontendConfig->enable_upgrade_hash),
errorbuf, apply);
return retVal;
}
static char *
config_initvalue_to_onoff(struct config_get_and_set *cgas, char *initvalbuf, size_t initvalbufsize)
{
......
......@@ -911,14 +911,13 @@ main(int argc, char **argv)
slapi_ch_free_string(&securelistenhost);
#if defined(ENABLE_LDAPI)
if (config_get_ldapi_switch() &&
config_get_ldapi_filename() != 0) {
if (config_get_ldapi_switch() && slapdFrontendConfig->ldapi_filename != 0) {
mcfg.i_port = ports_info.i_port = 1; /* flag ldapi as on */
ports_info.i_listenaddr = (PRNetAddr **)slapi_ch_calloc(2, sizeof(PRNetAddr *));
*ports_info.i_listenaddr = (PRNetAddr *)slapi_ch_calloc(1, sizeof(PRNetAddr));
(*ports_info.i_listenaddr)->local.family = PR_AF_LOCAL;
PL_strncpyz((*ports_info.i_listenaddr)->local.path,
config_get_ldapi_filename(),
slapdFrontendConfig->ldapi_filename,
sizeof((*ports_info.i_listenaddr)->local.path));
unlink((*ports_info.i_listenaddr)->local.path);
}
......