The Samba-Bugzilla – Attachment 12283 Details for
Bug 12020
Unable to enforce password history policy on password resets
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
a work in progress patch for this
0001-HACK-DSDB_LDAP_SERVER_POLICY_HINTS_OID.patch (text/plain), 10.67 KB, created by
Andrew Bartlett
on 2016-07-21 03:23:27 UTC
(
hide
)
Description:
a work in progress patch for this
Filename:
MIME Type:
Creator:
Andrew Bartlett
Created:
2016-07-21 03:23:27 UTC
Size:
10.67 KB
patch
obsolete
>From f5e0e480e1d080fc62f22b07cab41aa78e9b54a8 Mon Sep 17 00:00:00 2001 >From: Andrew Bartlett <abartlet@samba.org> >Date: Thu, 21 Jul 2016 14:47:21 +1200 >Subject: [PATCH] HACK: DSDB_LDAP_SERVER_POLICY_HINTS_OID > >Signed-off-by: Andrew Bartlett <abartlet@samba.org> >--- > lib/ldb/common/ldb_controls.c | 26 +++++++++++ > lib/ldb/include/ldb.h | 7 +++ > source4/dsdb/pydsdb.c | 2 + > source4/dsdb/samdb/ldb_modules/password_hash.c | 48 ++++++++++++++++++- > source4/dsdb/tests/python/passwords.py | 42 +++++++++++++++++ > source4/libcli/ldap/ldap_controls.c | 64 ++++++++++++++++++++++++++ > 6 files changed, 187 insertions(+), 2 deletions(-) > >diff --git a/lib/ldb/common/ldb_controls.c b/lib/ldb/common/ldb_controls.c >index a83768a..4db2808 100644 >--- a/lib/ldb/common/ldb_controls.c >+++ b/lib/ldb/common/ldb_controls.c >@@ -755,6 +755,32 @@ struct ldb_control *ldb_parse_control_from_string(struct ldb_context *ldb, TALLO > return ctrl; > } > >+ if (LDB_CONTROL_CMP(control_strings, DSDB_LDAP_SERVER_POLICY_HINTS_NAME) == 0) { >+ struct dsdb_pwd_policy_hints_control *control; >+ const char *p; >+ int crit, ret; >+ unsigned flags; >+ >+ p = &(control_strings[sizeof(DSDB_LDAP_SERVER_POLICY_HINTS_NAME)]); >+ ret = sscanf(p, "%d:%u", &crit, &flags); >+ if ((ret != 2) || (crit < 0) || (crit > 1) || (flags > 0xF)) { >+ ldb_set_errstring(ldb, >+ "invalid pwd_policy_hints control syntax\n" >+ " syntax: crit(b):flags(n)\n" >+ " note: b = boolean, n = number"); >+ talloc_free(ctrl); >+ return NULL; >+ } >+ >+ ctrl->oid = DSDB_LDAP_SERVER_POLICY_HINTS_OID; >+ ctrl->critical = crit; >+ control = talloc(ctrl, struct dsdb_pwd_policy_hints_control); >+ control->flags = flags; >+ ctrl->data = control; >+ >+ return ctrl; >+ } >+ > if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_BYPASS_OPERATIONAL_NAME) == 0) { > const char *p; > int crit, ret; >diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h >index 7422d46..6f06a13 100644 >--- a/lib/ldb/include/ldb.h >+++ b/lib/ldb/include/ldb.h >@@ -866,6 +866,13 @@ struct ldb_verify_name_control { > char *gc; > }; > >+#define DSDB_LDAP_SERVER_POLICY_HINTS_NAME "pwd_policy_hints" >+#define DSDB_LDAP_SERVER_POLICY_HINTS_OID "1.2.840.113556.1.4.2239" >+#define DSDB_LDAP_SERVER_POLICY_HINTS_DEPRECATED_OID "1.2.840.113556.1.4.2066" >+struct dsdb_pwd_policy_hints_control { >+ int flags; >+}; >+ > struct ldb_control { > const char *oid; > int critical; >diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c >index efaf66b..0aca15e 100644 >--- a/source4/dsdb/pydsdb.c >+++ b/source4/dsdb/pydsdb.c >@@ -1326,6 +1326,8 @@ void initdsdb(void) > ADD_DSDB_STRING(DSDB_CONTROL_REPLMD_VANISH_LINKS); > ADD_DSDB_STRING(DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID); > ADD_DSDB_STRING(DSDB_CONTROL_SKIP_DUPLICATES_CHECK_OID); >+ ADD_DSDB_STRING(DSDB_LDAP_SERVER_POLICY_HINTS_OID); >+ ADD_DSDB_STRING(DSDB_LDAP_SERVER_POLICY_HINTS_DEPRECATED_OID); > > ADD_DSDB_STRING(DS_GUID_COMPUTERS_CONTAINER); > ADD_DSDB_STRING(DS_GUID_DELETED_OBJECTS_CONTAINER); >diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c >index d52ad2d..1f2cbb8 100644 >--- a/source4/dsdb/samdb/ldb_modules/password_hash.c >+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c >@@ -102,6 +102,7 @@ struct ph_context { > bool update_lastset; > bool pwd_last_set_bypass; > bool pwd_last_set_default; >+ bool pwd_policy_hints_control; > }; > > >@@ -2220,7 +2221,7 @@ static int check_password_restrictions(struct setup_password_fields_io *io) > } > } > >- if (io->ac->pwd_reset) { >+ if (io->ac->pwd_reset && !io->ac->pwd_policy_hints_control) { > return LDB_SUCCESS; > } > >@@ -2262,6 +2263,10 @@ static int check_password_restrictions(struct setup_password_fields_io *io) > } > } > >+ if (io->ac->pwd_reset) { >+ return LDB_SUCCESS; >+ } >+ > /* are all password changes disallowed? */ > if (io->ac->status->domain_data.pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) { > ret = LDB_ERR_CONSTRAINT_VIOLATION; >@@ -3024,6 +3029,20 @@ static void ph_apply_controls(struct ph_context *ac) > /* Mark the "bypass pwdLastSet" control as uncritical (done) */ > ctrl->critical = false; > } >+ >+ ac->pwd_policy_hints_control = false; >+ ctrl = ldb_request_get_control(ac->req, >+ DSDB_LDAP_SERVER_POLICY_HINTS_OID); >+ if (ctrl == NULL) { >+ ctrl = ldb_request_get_control(ac->req, >+ DSDB_LDAP_SERVER_POLICY_HINTS_DEPRECATED_OID); >+ } >+ if (ctrl != NULL) { >+ ac->pwd_policy_hints_control = true; >+ >+ /* Mark the "apply password policy hints" control as uncritical (done) */ >+ ctrl->critical = false; >+ } > } > > static int ph_op_callback(struct ldb_request *req, struct ldb_reply *ares) >@@ -3783,10 +3802,35 @@ static int password_hash_mod_do_mod(struct ph_context *ac) > return ldb_next_request(ac->module, mod_req); > } > >+static int password_hash_init(struct ldb_module *module) >+{ >+ struct ldb_context *ldb; >+ int ret; >+ >+ ldb = ldb_module_get_ctx(module); >+ >+ ret = ldb_mod_register_control(module, DSDB_LDAP_SERVER_POLICY_HINTS_OID); >+ if (ret != LDB_SUCCESS) { >+ ldb_debug(ldb, LDB_DEBUG_ERROR, >+ "password_hash: Unable to register control with rootdse!\n"); >+ return ldb_operr(ldb); >+ } >+ >+ ret = ldb_mod_register_control(module, DSDB_LDAP_SERVER_POLICY_HINTS_DEPRECATED_OID); >+ if (ret != LDB_SUCCESS) { >+ ldb_debug(ldb, LDB_DEBUG_ERROR, >+ "password_hash: Unable to register control with rootdse!\n"); >+ return ldb_operr(ldb); >+ } >+ >+ return ldb_next_init(module); >+} >+ > static const struct ldb_module_ops ldb_password_hash_module_ops = { > .name = "password_hash", > .add = password_hash_add, >- .modify = password_hash_modify >+ .modify = password_hash_modify, >+ .init_context = password_hash_init > }; > > int ldb_password_hash_module_init(const char *version) >diff --git a/source4/dsdb/tests/python/passwords.py b/source4/dsdb/tests/python/passwords.py >index db013ea..1e2767c 100755 >--- a/source4/dsdb/tests/python/passwords.py >+++ b/source4/dsdb/tests/python/passwords.py >@@ -34,6 +34,7 @@ from samba import gensec > from samba.samdb import SamDB > import samba.tests > from samba.tests import delete_force >+from samba import dsdb > > parser = optparse.OptionParser("passwords.py [options] <host>") > sambaopts = options.SambaOptions(parser) >@@ -243,6 +244,47 @@ unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) > self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) > self.assertTrue('0000052D' in msg) > >+ def test_unicodePwd_clear_change_with_hints(self): >+ """Performs a password cleartext reset operation on 'unicodePwd', >+ but expect failure due to history""" >+ >+ self.ldb2.modify_ldif(""" >+dn: cn=testuser,cn=users,""" + self.base_dn + """ >+changetype: modify >+delete: unicodePwd >+unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')) + """ >+add: unicodePwd >+unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """ >+""") >+ >+ # Wrong old password >+ try: >+ self.ldb2.modify_ldif(""" >+dn: cn=testuser,cn=users,""" + self.base_dn + """ >+changetype: modify >+delete: unicodePwd >+unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS3\"".encode('utf-16-le')) + """ >+add: unicodePwd >+unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS4\"".encode('utf-16-le')) + """ >+""") >+ self.fail() >+ except LdbError, (num, msg): >+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) >+ self.assertTrue('00000056' in msg) >+ >+ # A change to the same password again will not work (password history) >+ try: >+ self.ldb.modify_ldif(""" >+dn: cn=testuser,cn=users,""" + self.base_dn + """ >+changetype: modify >+replace: unicodePwd >+unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """ >+""", controls=["pwd_policy_hints:1:1"]) >+ self.fail() >+ except LdbError, (num, msg): >+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION) >+ self.assertTrue('0000052D' in msg) >+ > def test_dBCSPwd_hash_set(self): > """Performs a password hash set operation on 'dBCSPwd' which should be prevented""" > # Notice: Direct hash password sets should never work >diff --git a/source4/libcli/ldap/ldap_controls.c b/source4/libcli/ldap/ldap_controls.c >index 9df95c3..e368c34 100644 >--- a/source4/libcli/ldap/ldap_controls.c >+++ b/source4/libcli/ldap/ldap_controls.c >@@ -263,6 +263,40 @@ static bool decode_search_options_request(void *mem_ctx, DATA_BLOB in, void *_ou > return true; > } > >+static bool decode_pwd_policy_hints_request(void *mem_ctx, DATA_BLOB in, void *_out) >+{ >+ void **out = (void **)_out; >+ struct asn1_data *data = asn1_init(mem_ctx); >+ struct dsdb_pwd_policy_hints_control *lsoc; >+ >+ if (!data) return false; >+ >+ if (!asn1_load(data, in)) { >+ return false; >+ } >+ >+ lsoc = talloc(mem_ctx, struct dsdb_pwd_policy_hints_control); >+ if (!lsoc) { >+ return false; >+ } >+ >+ if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) { >+ return false; >+ } >+ >+ if (!asn1_read_Integer(data, (int *) &(lsoc->flags))) { >+ return false; >+ } >+ >+ if (!asn1_end_tag(data)) { >+ return false; >+ } >+ >+ *out = lsoc; >+ >+ return true; >+} >+ > static bool decode_paged_results_request(void *mem_ctx, DATA_BLOB in, void *_out) > { > void **out = (void **)_out; >@@ -863,6 +897,34 @@ static bool encode_search_options_request(void *mem_ctx, void *in, DATA_BLOB *ou > return true; > } > >+static bool encode_pwd_policy_hints_request(void *mem_ctx, void *in, DATA_BLOB *out) >+{ >+ struct dsdb_pwd_policy_hints_control *lsoc = talloc_get_type(in, struct dsdb_pwd_policy_hints_control); >+ struct asn1_data *data = asn1_init(mem_ctx); >+ >+ if (!data) return false; >+ >+ if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) { >+ return false; >+ } >+ >+ if (!asn1_write_Integer(data, lsoc->flags)) { >+ return false; >+ } >+ >+ if (!asn1_pop_tag(data)) { >+ return false; >+ } >+ >+ if (!asn1_extract_blob(data, mem_ctx, out)) { >+ return false; >+ } >+ >+ talloc_free(data); >+ >+ return true; >+} >+ > static bool encode_paged_results_request(void *mem_ctx, void *in, DATA_BLOB *out) > { > struct ldb_paged_control *lprc = talloc_get_type(in, struct ldb_paged_control); >@@ -1246,6 +1308,8 @@ static const struct ldap_control_handler ldap_known_controls[] = { > { LDB_CONTROL_RELAX_OID, decode_flag_request, encode_flag_request }, > { DSDB_OPENLDAP_DEREFERENCE_CONTROL, decode_openldap_dereference, encode_openldap_dereference }, > { LDB_CONTROL_VERIFY_NAME_OID, decode_verify_name_request, encode_verify_name_request }, >+ { DSDB_LDAP_SERVER_POLICY_HINTS_OID, decode_pwd_policy_hints_request, encode_pwd_policy_hints_request }, >+ { DSDB_LDAP_SERVER_POLICY_HINTS_DEPRECATED_OID, decode_pwd_policy_hints_request, encode_pwd_policy_hints_request }, > > /* the following are internal only, with a network > representation */ >-- >2.8.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 12020
: 12283