diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/dsdb/common/util.c | 33 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/dirsync.c | 15 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/ranged_results.c | 25 | ||||
-rwxr-xr-x | source4/dsdb/tests/python/dirsync.py | 26 |
4 files changed, 85 insertions, 14 deletions
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index 18f700370a3..c7893bff43b 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -2088,21 +2088,36 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx, const uint32_t pwdProperties, const uint32_t minPwdLength) { - const char *utf8_pw = (const char *)utf8_blob->data; - size_t utf8_len = strlen_m(utf8_pw); char *password_script = NULL; + const char *utf8_pw = (const char *)utf8_blob->data; + + /* + * This looks strange because it is. + * + * The check for the number of characters in the password + * should clearly not be against the byte length, or else a + * single UTF8 character would count for more than one. + * + * We have chosen to use the number of 16-bit units that the + * password encodes to as the measure of length. This is not + * the same as the number of codepoints, if a password + * contains a character beyond the Basic Multilingual Plane + * (above 65535) it will count for more than one "character". + */ + + size_t password_characters_roughly = strlen_m(utf8_pw); /* checks if the "minPwdLength" property is satisfied */ - if (minPwdLength > utf8_len) { + if (minPwdLength > password_characters_roughly) { return SAMR_VALIDATION_STATUS_PWD_TOO_SHORT; } - /* checks the password complexity */ + /* We might not be asked to check the password complexity */ if (!(pwdProperties & DOMAIN_PASSWORD_COMPLEX)) { return SAMR_VALIDATION_STATUS_SUCCESS; } - if (utf8_len == 0) { + if (password_characters_roughly == 0) { return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH; } @@ -2110,6 +2125,7 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx, if (password_script != NULL && *password_script != '\0') { int check_ret = 0; int error = 0; + ssize_t nwritten = 0; struct tevent_context *event_ctx = NULL; struct tevent_req *req = NULL; struct samba_runcmd_state *run_cmd = NULL; @@ -2134,7 +2150,12 @@ enum samr_ValidationStatus samdb_check_password(TALLOC_CTX *mem_ctx, tevent_timeval_current_ofs(10, 0), 100, 100, cmd, NULL); run_cmd = tevent_req_data(req, struct samba_runcmd_state); - if (write(run_cmd->fd_stdin, utf8_pw, utf8_len) != utf8_len) { + nwritten = write(run_cmd->fd_stdin, + utf8_blob->data, + utf8_blob->length); + if (nwritten != utf8_blob->length) { + close(run_cmd->fd_stdin); + run_cmd->fd_stdin = -1; TALLOC_FREE(password_script); TALLOC_FREE(event_ctx); return SAMR_VALIDATION_STATUS_PASSWORD_FILTER_ERROR; diff --git a/source4/dsdb/samdb/ldb_modules/dirsync.c b/source4/dsdb/samdb/ldb_modules/dirsync.c index b5510eccd24..4ac5faad403 100644 --- a/source4/dsdb/samdb/ldb_modules/dirsync.c +++ b/source4/dsdb/samdb/ldb_modules/dirsync.c @@ -343,6 +343,10 @@ skip: attr = dsdb_attribute_by_lDAPDisplayName(dsc->schema, el->name); + if (attr == NULL) { + continue; + } + keep = false; if (attr->linkID & 1) { @@ -994,7 +998,7 @@ static int dirsync_ldb_search(struct ldb_module *module, struct ldb_request *req } /* - * check if there's an extended dn control + * check if there's a dirsync control */ control = ldb_request_get_control(req, LDB_CONTROL_DIRSYNC_OID); if (control == NULL) { @@ -1323,11 +1327,12 @@ static int dirsync_ldb_search(struct ldb_module *module, struct ldb_request *req } /* - * Remove our control from the list of controls + * Mark dirsync control as uncritical (done) + * + * We need this so ranged_results knows how to behave with + * dirsync */ - if (!ldb_save_controls(control, req, NULL)) { - return ldb_operr(ldb); - } + control->critical = false; dsc->schema = dsdb_get_schema(ldb, dsc); /* * At the begining we make the hypothesis that we will return a complete diff --git a/source4/dsdb/samdb/ldb_modules/ranged_results.c b/source4/dsdb/samdb/ldb_modules/ranged_results.c index 13bf3a2d0a9..98438799997 100644 --- a/source4/dsdb/samdb/ldb_modules/ranged_results.c +++ b/source4/dsdb/samdb/ldb_modules/ranged_results.c @@ -35,14 +35,14 @@ struct rr_context { struct ldb_module *module; struct ldb_request *req; + bool dirsync_in_use; }; static struct rr_context *rr_init_context(struct ldb_module *module, struct ldb_request *req) { - struct rr_context *ac; - - ac = talloc_zero(req, struct rr_context); + struct ldb_control *dirsync_control = NULL; + struct rr_context *ac = talloc_zero(req, struct rr_context); if (ac == NULL) { ldb_set_errstring(ldb_module_get_ctx(module), "Out of Memory"); return NULL; @@ -51,6 +51,16 @@ static struct rr_context *rr_init_context(struct ldb_module *module, ac->module = module; ac->req = req; + /* + * check if there's a dirsync control (as there is an + * interaction between these modules) + */ + dirsync_control = ldb_request_get_control(req, + LDB_CONTROL_DIRSYNC_OID); + if (dirsync_control != NULL) { + ac->dirsync_in_use = true; + } + return ac; } @@ -82,6 +92,15 @@ static int rr_search_callback(struct ldb_request *req, struct ldb_reply *ares) ares->response, ares->error); } + if (ac->dirsync_in_use) { + /* + * We return full attribute values when mixed with + * dirsync + */ + return ldb_module_send_entry(ac->req, + ares->message, + ares->controls); + } /* LDB_REPLY_ENTRY */ temp_ctx = talloc_new(ac->req); diff --git a/source4/dsdb/tests/python/dirsync.py b/source4/dsdb/tests/python/dirsync.py index 136f4d3bba6..b6f7022a50b 100755 --- a/source4/dsdb/tests/python/dirsync.py +++ b/source4/dsdb/tests/python/dirsync.py @@ -28,6 +28,7 @@ from samba.tests.subunitrun import TestProgram, SubunitOptions import samba.getopt as options import base64 +import ldb from ldb import LdbError, SCOPE_BASE from ldb import Message, MessageElement, Dn from ldb import FLAG_MOD_ADD, FLAG_MOD_DELETE @@ -590,6 +591,31 @@ class SimpleDirsyncTests(DirsyncBaseTests): class ExtendedDirsyncTests(SimpleDirsyncTests): + def test_dirsync_linkedattributes_range(self): + self.ldb_simple = self.get_ldb_connection(self.simple_user, self.user_pass) + res = self.ldb_admin.search(self.base_dn, + attrs=["member;range=1-1"], + expression="(name=Administrators)", + controls=["dirsync:1:0:0"]) + + self.assertTrue(len(res) > 0) + self.assertTrue(res[0].get("member;range=1-1") is None) + self.assertTrue(res[0].get("member") is not None) + self.assertTrue(len(res[0].get("member")) > 0) + + def test_dirsync_linkedattributes_range_user(self): + self.ldb_simple = self.get_ldb_connection(self.simple_user, self.user_pass) + try: + res = self.ldb_simple.search(self.base_dn, + attrs=["member;range=1-1"], + expression="(name=Administrators)", + controls=["dirsync:1:0:0"]) + except LdbError as e: + (num, _) = e.args + self.assertEquals(num, ldb.ERR_INSUFFICIENT_ACCESS_RIGHTS) + else: + self.fail() + def test_dirsync_linkedattributes(self): flag_incr_linked = 2147483648 self.ldb_simple = self.get_ldb_connection(self.simple_user, self.user_pass) |