diff options
Diffstat (limited to 'source4/dsdb')
-rw-r--r-- | source4/dsdb/common/util.c | 35 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/samldb.c | 135 |
2 files changed, 128 insertions, 42 deletions
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index bee1eac480..ace5e0edaf 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -469,8 +469,8 @@ NTTIME samdb_result_allow_password_change(struct ldb_context *sam_ldb, } /* - construct the force_password_change field from the PwdLastSet attribute and the - domain password settings + construct the force_password_change field from the PwdLastSet + attribute, the userAccountControl and the domain password settings */ NTTIME samdb_result_force_password_change(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, @@ -478,10 +478,12 @@ NTTIME samdb_result_force_password_change(struct ldb_context *sam_ldb, struct ldb_message *msg) { uint64_t attr_time = samdb_result_uint64(msg, "pwdLastSet", 0); - uint32_t user_flags = samdb_result_uint64(msg, "userAccountControl", 0); + uint32_t userAccountControl = samdb_result_uint64(msg, "userAccountControl", 0); int64_t maxPwdAge; - if (user_flags & UF_DONT_EXPIRE_PASSWD) { + /* Machine accounts don't expire, and there is a flag for 'no expiry' */ + if (!(userAccountControl & UF_NORMAL_ACCOUNT) + || (userAccountControl & UF_DONT_EXPIRE_PASSWD)) { return 0x7FFFFFFFFFFFFFFFULL; } @@ -596,11 +598,30 @@ struct samr_LogonHours samdb_result_logon_hours(TALLOC_CTX *mem_ctx, struct ldb_ /* pull a set of account_flags from a result set. + + This requires that the attributes: + pwdLastSet + userAccountControl + be included in 'msg' */ -uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr) +uint32_t samdb_result_acct_flags(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, + struct ldb_message *msg, struct ldb_dn *domain_dn) { - uint_t userAccountControl = ldb_msg_find_attr_as_uint(msg, attr, 0); - return samdb_uf2acb(userAccountControl); + uint32_t userAccountControl = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0); + uint32_t acct_flags = samdb_uf2acb(userAccountControl); + NTTIME must_change_time; + NTTIME now; + + must_change_time = samdb_result_force_password_change(sam_ctx, mem_ctx, + domain_dn, msg); + + /* Test account expire time */ + unix_to_nt_time(&now, time(NULL)); + /* check for expired password */ + if (must_change_time < now) { + acct_flags |= ACB_PW_EXPIRED; + } + return acct_flags; } diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index 178149a886..905cd4a995 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -396,6 +396,7 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_ struct ldb_message **ret_msg) { int ret; + unsigned int group_type; char *name; struct ldb_message *msg2; struct ldb_dn *dom_dn; @@ -452,6 +453,26 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_ } } + if (ldb_msg_find_element(msg2, "sAMAccountType") != NULL) { + ldb_asprintf_errstring(module->ldb, "sAMAccountType must not be specified"); + talloc_free(mem_ctx); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + group_type = samdb_result_uint(msg2, "groupType", 0); + if (group_type == 0) { + ldb_asprintf_errstring(module->ldb, "groupType invalid"); + talloc_free(mem_ctx); + return LDB_ERR_UNWILLING_TO_PERFORM; + } else { + unsigned int account_type = samdb_gtype2atype(group_type); + ret = samdb_msg_add_uint(module->ldb, msg2, msg2, + "sAMAccountType", + account_type); + if (ret != LDB_SUCCESS) { + return ret; + } + } + /* Manage SID allocation, conflicts etc */ ret = samldb_handle_sid(module, mem_ctx, msg2, dom_dn); @@ -473,6 +494,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const const char *rdn_name; TALLOC_CTX *mem_ctx = talloc_new(msg); const char *errstr; + unsigned int user_account_control; if (!mem_ctx) { return LDB_ERR_OPERATIONS_ERROR; } @@ -485,36 +507,15 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const return LDB_ERR_OPERATIONS_ERROR; } - if (samdb_find_attribute(module->ldb, msg, "objectclass", "computer") != NULL) { - - ret = samdb_copy_template(module->ldb, msg2, - "computer", - &errstr); - if (ret) { - ldb_asprintf_errstring(module->ldb, - "samldb_fill_user_or_computer_object: " - "Error copying computer template: %s", - errstr); - talloc_free(mem_ctx); - return ret; - } - } else { - ret = samdb_copy_template(module->ldb, msg2, - "user", - &errstr); - if (ret) { - ldb_asprintf_errstring(module->ldb, - "samldb_fill_user_or_computer_object: Error copying user template: %s\n", - errstr); - talloc_free(mem_ctx); - return ret; - } - /* readd user objectclass */ - ret = samdb_find_or_add_value(module->ldb, msg2, "objectclass", "user"); - if (ret) { - talloc_free(mem_ctx); - return ret; - } + ret = samdb_copy_template(module->ldb, msg2, + "user", + &errstr); + if (ret) { + ldb_asprintf_errstring(module->ldb, + "samldb_fill_user_or_computer_object: Error copying user template: %s\n", + errstr); + talloc_free(mem_ctx); + return ret; } rdn_name = ldb_dn_get_rdn_name(msg2->dn); @@ -545,14 +546,30 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const } } - /* - TODO: useraccountcontrol: setting value 0 gives 0x200 for users - */ + if (ldb_msg_find_element(msg2, "sAMAccountType") != NULL) { + ldb_asprintf_errstring(module->ldb, "sAMAccountType must not be specified"); + talloc_free(mem_ctx); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + user_account_control = samdb_result_uint(msg2, "userAccountControl", 0); + if (user_account_control == 0) { + ldb_asprintf_errstring(module->ldb, "userAccountControl invalid"); + talloc_free(mem_ctx); + return LDB_ERR_UNWILLING_TO_PERFORM; + } else { + unsigned int account_type = samdb_uf2atype(user_account_control); + ret = samdb_msg_add_uint(module->ldb, msg2, msg2, + "sAMAccountType", + account_type); + if (ret != LDB_SUCCESS) { + return ret; + } + } /* Manage SID allocation, conflicts etc */ ret = samldb_handle_sid(module, mem_ctx, msg2, dom_dn); - /* TODO: objectCategory, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */ + /* TODO: userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */ if (ret == 0) { *ret_msg = msg2; @@ -689,7 +706,7 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req) } /* is user or computer? */ - if ((samdb_find_attribute(module->ldb, msg, "objectclass", "user") != NULL) || + if ((samdb_find_attribute(module->ldb, msg, "objectclass", "user") != NULL) || (samdb_find_attribute(module->ldb, msg, "objectclass", "computer") != NULL)) { /* add all relevant missing objects */ ret = samldb_fill_user_or_computer_object(module, msg, &msg2); @@ -745,6 +762,53 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req) return ret; } +/* modify */ +static int samldb_modify(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_message *msg; + struct ldb_message_element *el, *el2; + int ret; + unsigned int group_type, user_account_control, account_type; + if (ldb_msg_find_element(req->op.mod.message, "sAMAccountType") != NULL) { + ldb_asprintf_errstring(module->ldb, "sAMAccountType must not be specified"); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + + el = ldb_msg_find_element(req->op.mod.message, "groupType"); + if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) { + req->op.mod.message = msg = ldb_msg_copy_shallow(req, req->op.mod.message); + + group_type = strtoul((const char *)el->values[0].data, NULL, 0); + account_type = samdb_gtype2atype(group_type); + ret = samdb_msg_add_uint(module->ldb, msg, msg, + "sAMAccountType", + account_type); + if (ret != LDB_SUCCESS) { + return ret; + } + el2 = ldb_msg_find_element(msg, "sAMAccountType"); + el2->flags = LDB_FLAG_MOD_REPLACE; + } + + el = ldb_msg_find_element(req->op.mod.message, "userAccountControl"); + if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) { + req->op.mod.message = msg = ldb_msg_copy_shallow(req, req->op.mod.message); + + user_account_control = strtoul((const char *)el->values[0].data, NULL, 0); + account_type = samdb_uf2atype(user_account_control); + ret = samdb_msg_add_uint(module->ldb, msg, msg, + "sAMAccountType", + account_type); + if (ret != LDB_SUCCESS) { + return ret; + } + el2 = ldb_msg_find_element(msg, "sAMAccountType"); + el2->flags = LDB_FLAG_MOD_REPLACE; + } + return ldb_next_request(module, req); +} + + static int samldb_init(struct ldb_module *module) { return ldb_next_init(module); @@ -754,4 +818,5 @@ _PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = { .name = "samldb", .init_context = samldb_init, .add = samldb_add, + .modify = samldb_modify }; |