From ab4ff93b05b21c81ffd52c3cc992d38887d078d2 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Thu, 2 Apr 2020 15:25:53 +1300 Subject: [PATCH] CVE-2020-10704: libcli ldap: test recursion depth in ldap_decode_filter_tree Add tests to check that ASN.1 ldap requests with deeply nested elements are rejected. Previously there was no check on the on the depth of nesting and excessive nesting could cause a stack overflow. Credit to OSS-Fuzz REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20454 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14334 Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett --- libcli/ldap/tests/data/10000-or.dat | Bin 0 -> 39875 bytes libcli/ldap/tests/data/ldap-recursive.dat | Bin 0 -> 970 bytes libcli/ldap/tests/ldap_message_test.c | 271 ++++++++++++++++++++++ libcli/ldap/wscript_build | 15 ++ selftest/knownfail.d/ldap_message | 2 + source4/selftest/tests.py | 2 + 6 files changed, 290 insertions(+) create mode 100644 libcli/ldap/tests/data/10000-or.dat create mode 100644 libcli/ldap/tests/data/ldap-recursive.dat create mode 100644 libcli/ldap/tests/ldap_message_test.c create mode 100644 selftest/knownfail.d/ldap_message diff --git a/libcli/ldap/tests/data/10000-or.dat b/libcli/ldap/tests/data/10000-or.dat new file mode 100644 index 0000000000000000000000000000000000000000..e2d6de2ce330e80d1c2f28854b3542b789de9834 GIT binary patch literal 39875 zc-kD-rSAaXyYS`roI!w%Kp?Q+*WKOS-QC^Y-QC^K-f#keKp?O|V2nT@5C{YUfj}S- z2m}Hf7i{OauGr+-)f^si@s|BwD}{a^Y&^?&Gp*Z-#fRsW0rXZ=t5AN4=zzt?}K|5pFC{ww_# z`p@;B=|9zfBK|-AKmI@dKmI@dKmI@dKmI@dKmI@dKmI@dKmI@dKmI@dKmI@dKmI@d zKmI@dKmI@dKmI@dKmI@dKmI@dKmI@dKmI@dKmI@dKmI@dKmK3-U;bbIU;bbIU;bbI zU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbI zU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbIU;bbI zU;bbIU;bbIU;ZEdAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0Wy zAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0Wy zAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO0WyAO3ItZ~kxoZ~kxoZ~kxoZ~kxo zZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxo zZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxoZ~kxo zZ~kxoZ~ia-Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7 zFa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7 zFa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7Fa9t7FaA&dPySE-PySE-PySE-PySE-PySE- zPySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE- zPySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE-PySE- zPyP@75B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS z5B?AS5B?AS5B?AS5B?AS5B?AS5B?AS5B_)lcm8+&cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+& zcm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm8+&cm6m2 zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&NH~u&N zH~u&NH~u&NH~u&NH~u&NH~u&NH~v@tSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2 zSN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN>Q2SN<3N7ycLi z7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi z7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi7ycLi z7ycLi7ycLi7ycLi7ycLi7yf7dXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mY zXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ~mYXZ|PtC;lh?C;lh? zC;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh?C;lh? zC;lh?C;lh?C;lh?C;mtNNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3t zNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3t zNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB&3tNB#%?2mS~C2mS~C2mS~C z2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C z2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C2mS~C z2mS~C2mS~C2mX8hd;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX= zd;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX= zd;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;WX=d;UBAJN`TVJN`TVJN`TVJN`TV zJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TV zJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TVJN`TV zJN`TVJN{e#TmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=A zTmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=A zTmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmD=ATmBpV8~z*q8~z*q8~z*q8~z*q8~z*q z8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q z8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q8~z*q z8~$tlYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBg zYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyNBg zYyNBgYyNBgYyNBgYyNBgYyNBgYyNBgYyK<#EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~ zEB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~ zEB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB-6~EB;IV zOa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p# zOa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa4p# zOa4p#Oa4p#Oa4p#Oa4p#Oa4p#Oa2S~3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK z3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK z3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;qlK3;uKdbN+Mw zbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+Mw zbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+MwbN+Mw zbN+MwbN+MwbN+MwbN+MwbN(~_GyXIFGyXIFGyXIFGyXIFGyXIFGyXIFGyXIFGyXIF zGyXIFGyXIFGyXIFGyXIFGyXGv2l1Ju_{_(6=5d^z@t^UZ@t^UZ@t^UZ@t^UZ@t^UZ z@t^UZ@t^UZ@t^UZ@t^UZ@t^UZ@t^UZ@t^UZ@t^UZ@t^UZ@t^UZ@t^UZ@t^Xa@}Kgb z@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb z@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb@}Kgb z@}Kgb@}Kgb@}Kgb@}Kgb@}KaZ@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX z@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX z@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@SpIX@E`LZ^B?mc^B?mc z^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc z^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc^B?mc z^B?mc^B?mc^B?mc^B?ga@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY z@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY z@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMOY@gMRZ@*naa@*naa@*naa z@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa z@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa@*naa z@*naa@*naa@*nUY@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW z@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW z@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@E`CW@bB~Q^Y8QT^Y8QT^Y8QT^Y8QT z^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT z^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT^Y8QT z^Y8QT^Y8KR@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P z@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P z@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d2P@$d5Q^6&ER^6&ER^6&ER^6&ER^6&ER z^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER z^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER^6&ER z^6&8P@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N z@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N z@bB>N@bB>N@bB>N@bB>N@bB>N@bB>N@Ne^P^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS z^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS z^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbKS^KbEQ z@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O z@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O@o({O z@o({O@o({O@o({O@o({O@o({O@o(~P@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q z@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q z@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A8Q@^A2O@Ne*M z@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M z@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M@Ne*M z@Ne*M@Ne*M@Ne*M@Ne*M@UQc)^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%- z^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%- z^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RM%-^RMx*@vrf(@vrf( z@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf( z@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf(@vrf( z@vrf(@vrf(@vrf(@vri)@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r* z@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r* z@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`r*@~`l(@UQT%@UQT%@UQT% z@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT% z@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT%@UQT% z@UQT%@UQT%@GtW(^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+ z^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+ z^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpx+^Dpr)@h|Z&@h|Z&@h|Z&@h|Z& z@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z& z@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z&@h|Z& z@h|Z&@h|c(@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol) z@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol) z@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Ol)@-Of&@GtN$@GtN$@GtN$@GtN$@GtN$ z@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$ z@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$@GtN$ z@Xzzl^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o z^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o z^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uw3o^Uv|m@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k z@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k z@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3$k@z3(l z^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m z^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m^3U?m z^3U?m^3U?m^3U?m^3U?m^3U?m^3U+k@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi z@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi z@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@Xzqi@K5tk^H1|n z^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n z^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n^H1|n z^H1|n^H1|n^H1|n^H1|n^H1?l@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj z@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj z@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWwj@lWzk@=x+l@=x+l z@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l z@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l@=x+l z@=x+l@=x+l@=x+l@=x$j@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh z@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh z@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@K5kh@Q?G4^N;h7^N;h7^N;h7 z^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7 z^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7^N;h7 z^N;h7^N;h7^N;b5@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3 z@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3 z@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIJ3@sIM4@{jV5@{jV5@{jV5@{jV5 z@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5 z@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5@{jV5 z@{jV5@{jP3@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71 z@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71 z@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@Q?71@DKA3^AGb6^AGb6^AGb6^AGb6^AGb6 z^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6 z^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6^AGb6 z^AGV4@elD2@elD2@elD2@elD2@elD2@elD2@elD2@elD2@elD2@elD2@elD2@elD2 z@elD2@elD2@elD2@elD2@elD2@elD2@elD2@elD2@elD2@elD2@elD2@elD2@elD2 z@elD2@elD2@elD2@elD2@elD2@elD2@elG3@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4 z@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4 z@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=P4@(=J2 z@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10 z@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10@DK10 z@DK10@DK10@DK10@DK10@DK10@b~lg^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j z^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j z^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`=j^Y`)h@%Qof z@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof z@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof@%Qof z@%Qof@%Qof@%Qof@%Qof@%Qrg^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h z^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h z^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7r!h^7ruf@b~cd@b~cd z@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd z@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd@b~cd z@b~cd@b~cd@b~cd@OSff^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i z^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i z^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO)i^LO!g@ptie@ptie@ptie z@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie z@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie@ptie z@ptie@ptie@ptlf@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug z@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug z@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|ug@^|oe@OSWc@OSWc@OSWc@OSWc z@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc z@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc@OSWc z@OSWc@VE1~^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2 z^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2 z^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAT2^SAN0@wf4}@wf4}@wf4}@wf4}@wf4} z@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4} z@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4}@wf4} z@wf7~^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0 z^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0 z^0)H0^0)H0^0)H0^0)H0^0)H0^0)H0^0)A}@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{ z@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{ z@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@VD@{@Hg`} z^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1 z^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1^EdN1 z^EdN1^EdN1^EdN1^EdN1^EdN1^EdG~@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}| z@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}| z@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i*}|@i+1}@;CA~ z@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~ z@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~@;CA~ z@;CA~@;CA~@;CA~@;CA~@;C4|@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-` z@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-` z@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@Hg-`@YnO#^Vjp&^Vjp& z^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp& z^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp&^Vjp& z^Vjp&^Vjp&^Vjp&^Vjj$@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R! z@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R! z@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?R!@z?U#^4Id$^4Id$^4Id$ z^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$ z^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$^4Id$ z^4Id$^4Id$^4IX!@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy z@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy z@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@YnFy@K^I!^H=j%^H=j%^H=j%^H=j% z^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j% z^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j%^H=j% z^H=j%^H=d#@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz z@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz z@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKLz@mKO!@>lX#@>lX#@>lX#@>lX#@>lX# z@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX# z@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX#@>lX# z@>lRz@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x z@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x z@K^9x@K^9x@K^9x@K^9x@K^9x@K^9x@R#$K^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N z^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N z^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy6N^Oy0L z@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J z@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J@t5(J z@t5(J@t5(J@t5(J@t5(J@t5(J@t5+K@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L z@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L z@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|W_L@|Wq^QZHt z^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt z^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt^QZHt z^QZHt^QZHt^QZHt^QZHt^QZBr@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p z@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p z@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%^p@u%{q@~85r@~85r z@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r z@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r@~85r z@~85r@~85r@~85r@~7~p@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n z@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n z@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@Tc&n@F(*p^C$Bs^C$Bs^C$Bs z^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs z^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs^C$Bs z^C$Bs^C$Bs^C$5q@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o z@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o z@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9;o@h9>p@+a~q@+a~q@+a~q@+a~q z@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q z@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q@+a~q z@+a~q@+a^o@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym z@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym z@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@F(ym@W=DV^T+eY^T+eY^T+eY^T+eY^T+eY z^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY z^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY^T+eY z^T+YW@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU z@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU z@yGGU@yGGU@yGGU@yGGU@yGGU@yGGU@yGJV^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW z^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW z^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hSW^2hMU z@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S z@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S@W=4S z@W=4S@W=4S@W=4S@W=4S@W=4S@JI7U^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX z^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX z^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GEYX^GESV@kjAT z@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT z@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT@kjAT z@kjAT@kjAT@kjAT@kjAT@kjDU@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV z@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV z@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;MV@<;GT@JH}R@JH}R z@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R z@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R@JH}R z@JH}R@JH}R@JH}R@Q3q<^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_? z^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_? z^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~_?^M~<=@rUt;@rUt;@rUt; z@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt; z@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt;@rUt; z@rUt;@rUt;@rUw<@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(= z@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(= z@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`v(=@`vz;@Q3h+@Q3h+@Q3h+@Q3h+ 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 THq@c~^E{2dm`1<%kstVfGkj_X literal 0 Hc-jL100001 diff --git a/libcli/ldap/tests/data/ldap-recursive.dat b/libcli/ldap/tests/data/ldap-recursive.dat new file mode 100644 index 0000000000000000000000000000000000000000..dd18d857660df41c30024264d4623680a9404613 GIT binary patch literal 970 zc-k{)Vm`*i$ei57yq|@EixGsFz=)BNVWC1hcYab. + * + */ + +/* + * from cmocka.c: + * These headers or their equivalents should be included prior to + * including + * this header file. + * + * #include + * #include + * #include + * + * This allows test applications to use custom definitions of C standard + * library functions and types. + * + */ +#include +#include +#include +#include + +#include "lib/util/attr.h" +#include "includes.h" +#include "lib/util/asn1.h" +#include "libcli/ldap/ldap_message.h" +#include "libcli/ldap/ldap_proto.h" + +/* + * declare the internal cmocka cm_print so we can output messages in + * sub unit format + */ +void cm_print_error(const char * const format, ...); +/* + * helper function and macro to compare an ldap error code constant with the + * coresponding nt_status code + */ +#define NT_STATUS_LDAP_V(code) (0xF2000000 | code) +static void _assert_ldap_status_equal( + int a, + NTSTATUS b, + const char * const file, + const int line) +{ + _assert_int_equal(NT_STATUS_LDAP_V(a), NT_STATUS_V(b), file, line); +} + +#define assert_ldap_status_equal(a, b) \ + _assert_ldap_status_equal((a), (b), __FILE__, __LINE__) + +/* + * helper function and macro to assert there were no errors in the last + * file operation + */ +static void _assert_not_ferror( + FILE *f, + const char * const file, + const int line) +{ + if (f == NULL || ferror(f)) { + cm_print_error("ferror (%d) %s\n", errno, strerror(errno)); + _fail(file, line); + } +} + +#define assert_not_ferror(f) \ + _assert_not_ferror((f), __FILE__, __LINE__) + +struct test_ctx { +}; + +static int setup(void **state) +{ + struct test_ctx *test_ctx; + + test_ctx = talloc_zero(NULL, struct test_ctx); + *state = test_ctx; + return 0; +} + +static int teardown(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort(*state, + struct test_ctx); + + TALLOC_FREE(test_ctx); + return 0; +} + +/* + * Test that an empty request is handled correctly + */ +static void test_empty_input(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort( + *state, + struct test_ctx); + struct asn1_data *asn1; + struct ldap_message *ldap_msg; + NTSTATUS status; + uint8_t buf[0]; + size_t len = 0; + + + asn1 = asn1_init(test_ctx, ASN1_MAX_TREE_DEPTH); + assert_non_null(asn1); + + asn1_load_nocopy(asn1, buf, len); + + ldap_msg = talloc(test_ctx, struct ldap_message); + assert_non_null(ldap_msg); + + status = ldap_decode(asn1, samba_ldap_control_handlers(), ldap_msg); + assert_ldap_status_equal(LDAP_PROTOCOL_ERROR, status); +} + +/* + * Check that a request is rejected it it's recursion depth exceeds + * the maximum value specified. This test uses a very deeply nested query, + * 10,000 or clauses. + * + */ +static void test_recursion_depth_large(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort( + *state, + struct test_ctx); + struct asn1_data *asn1; + struct ldap_message *ldap_msg; + NTSTATUS status; + FILE *f = NULL; + uint8_t *buffer = NULL; + const size_t BUFF_SIZE = 1048576; + size_t len; + + + /* + * Load a test data file containg 10,000 or clauses in encoded as + * an ASN.1 packet. + */ + buffer = talloc_zero_array(test_ctx, uint8_t, BUFF_SIZE); + f = fopen("./libcli/ldap/tests/data/10000-or.dat", "r"); + assert_not_ferror(f); + len = fread(buffer, sizeof(uint8_t), BUFF_SIZE, f); + assert_not_ferror(f); + assert_true(len > 0); + + asn1 = asn1_init(test_ctx, ASN1_MAX_TREE_DEPTH); + assert_non_null(asn1); + asn1_load_nocopy(asn1, buffer, len); + + ldap_msg = talloc(test_ctx, struct ldap_message); + assert_non_null(ldap_msg); + + status = ldap_decode(asn1, samba_ldap_control_handlers(), ldap_msg); + assert_ldap_status_equal(LDAP_PROTOCOL_ERROR, status); +} + +/* + * Check that a request is not rejected it it's recursion depth equals the + * maximum value + */ +static void test_recursion_depth_equals_max(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort( + *state, + struct test_ctx); + struct asn1_data *asn1; + struct ldap_message *ldap_msg; + NTSTATUS status; + FILE *f = NULL; + uint8_t *buffer = NULL; + const size_t BUFF_SIZE = 1048576; + size_t len; + + + buffer = talloc_zero_array(test_ctx, uint8_t, BUFF_SIZE); + f = fopen("./libcli/ldap/tests/data/ldap-recursive.dat", "r"); + assert_not_ferror(f); + len = fread(buffer, sizeof(uint8_t), BUFF_SIZE, f); + assert_not_ferror(f); + assert_true(len > 0); + + asn1 = asn1_init(test_ctx, 4); + assert_non_null(asn1); + asn1_load_nocopy(asn1, buffer, len); + + ldap_msg = talloc(test_ctx, struct ldap_message); + assert_non_null(ldap_msg); + + status = ldap_decode(asn1, samba_ldap_control_handlers(), ldap_msg); + assert_true(NT_STATUS_IS_OK(status)); +} + +/* + * Check that a request is rejected it it's recursion depth is greater than the + * maximum value + */ +static void test_recursion_depth_greater_than_max(void **state) +{ + struct test_ctx *test_ctx = talloc_get_type_abort( + *state, + struct test_ctx); + struct asn1_data *asn1; + struct ldap_message *ldap_msg; + NTSTATUS status; + FILE *f = NULL; + uint8_t *buffer = NULL; + const size_t BUFF_SIZE = 1048576; + size_t len; + + + buffer = talloc_zero_array(test_ctx, uint8_t, BUFF_SIZE); + f = fopen("./libcli/ldap/tests/data/ldap-recursive.dat", "r"); + assert_not_ferror(f); + len = fread(buffer, sizeof(uint8_t), BUFF_SIZE, f); + assert_not_ferror(f); + assert_true(len > 0); + + asn1 = asn1_init(test_ctx, 3); + assert_non_null(asn1); + asn1_load_nocopy(asn1, buffer, len); + + ldap_msg = talloc(test_ctx, struct ldap_message); + assert_non_null(ldap_msg); + + status = ldap_decode(asn1, samba_ldap_control_handlers(), ldap_msg); + assert_ldap_status_equal(LDAP_PROTOCOL_ERROR, status); +} + +int main(_UNUSED_ int argc, _UNUSED_ const char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown( + test_empty_input, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_recursion_depth_large, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_recursion_depth_equals_max, + setup, + teardown), + cmocka_unit_test_setup_teardown( + test_recursion_depth_greater_than_max, + setup, + teardown), + }; + + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/libcli/ldap/wscript_build b/libcli/ldap/wscript_build index db5b1df497a..d0aa7c11ced 100644 --- a/libcli/ldap/wscript_build +++ b/libcli/ldap/wscript_build @@ -6,3 +6,18 @@ bld.SAMBA_LIBRARY('cli-ldap-common', private_headers='ldap_message.h ldap_errors.h ldap_ndr.h', deps='samba-util asn1util NDR_SECURITY tevent', private_library=True) + +bld.SAMBA_BINARY( + 'test_ldap_message', + source='tests/ldap_message_test.c', + deps=''' + cmocka + talloc + ldb + samba-util + asn1util + NDR_SECURITY + cli-ldap + ''', + install=False +) diff --git a/selftest/knownfail.d/ldap_message b/selftest/knownfail.d/ldap_message new file mode 100644 index 00000000000..242eff45e59 --- /dev/null +++ b/selftest/knownfail.d/ldap_message @@ -0,0 +1,2 @@ +^libcli.ldap.ldap_message.test_recursion_depth_greater_than_max\(none\) +^libcli.ldap.ldap_message.test_recursion_depth_large\(none\) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index c65aeb1b923..46c1eb9a18b 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -1287,6 +1287,8 @@ plantestsuite("samba4.dsdb.samdb.ldb_modules.group_audit.errors", "none", [os.path.join(bindir(), "test_group_audit_errors")]) plantestsuite("samba4.dcerpc.dnsserver.dnsutils", "none", [os.path.join(bindir(), "test_rpc_dns_server_dnsutils")]) +plantestsuite("libcli.ldap.ldap_message", "none", + [os.path.join(bindir(), "test_ldap_message")]) # process restart and limit tests, these break the environment so need to run # in their own specific environment -- 2.47.2