summaryrefslogtreecommitdiffstats
path: root/source4/dsdb/samdb
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2013-10-29 15:38:08 +1300
committerStefan Metzmacher <metze@samba.org>2014-04-02 17:12:46 +0200
commit1d266b493894ad55c6c30e73a4cf9bc6aa28f559 (patch)
tree96f0a7535ed7a677d41df8527996f35e78c8c075 /source4/dsdb/samdb
parent9a3651ece1ddd273fdf88b5d4fceef82babbf4a7 (diff)
downloadsamba-1d266b493894ad55c6c30e73a4cf9bc6aa28f559.tar.gz
samba-1d266b493894ad55c6c30e73a4cf9bc6aa28f559.tar.xz
samba-1d266b493894ad55c6c30e73a4cf9bc6aa28f559.zip
dsdb-operational: Implement msDS-User-Account-Control-Computed
This is needed to get consistent account lockout support across the whole server. Andrew Bartlett Change-Id: I2fa1e707d33f5567b6cb4e2b27e340fa9f40cee9 Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> Signed-off-by: Andrew Bartlett <abartlet@samba.org> Signed-off-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'source4/dsdb/samdb')
-rw-r--r--source4/dsdb/samdb/ldb_modules/operational.c166
1 files changed, 165 insertions, 1 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/operational.c b/source4/dsdb/samdb/ldb_modules/operational.c
index 2e1a1e2aa80..5f15932f3f4 100644
--- a/source4/dsdb/samdb/ldb_modules/operational.c
+++ b/source4/dsdb/samdb/ldb_modules/operational.c
@@ -606,6 +606,160 @@ static int construct_msds_keyversionnumber(struct ldb_module *module,
}
+#define _UF_TRUST_ACCOUNTS ( \
+ UF_WORKSTATION_TRUST_ACCOUNT | \
+ UF_SERVER_TRUST_ACCOUNT | \
+ UF_INTERDOMAIN_TRUST_ACCOUNT \
+)
+#define _UF_NO_EXPIRY_ACCOUNTS ( \
+ UF_SMARTCARD_REQUIRED | \
+ UF_DONT_EXPIRE_PASSWD | \
+ _UF_TRUST_ACCOUNTS \
+)
+
+/*
+ calculate msDS-UserPasswordExpiryTimeComputed
+*/
+static NTTIME get_msds_user_password_expiry_time_computed(struct ldb_module *module,
+ struct ldb_message *msg,
+ struct ldb_dn *domain_dn)
+{
+ int64_t pwdLastSet, maxPwdAge;
+ uint32_t userAccountControl;
+ NTTIME ret;
+
+ userAccountControl = ldb_msg_find_attr_as_uint(msg,
+ "userAccountControl",
+ 0);
+ if (userAccountControl & _UF_NO_EXPIRY_ACCOUNTS) {
+ return 0x7FFFFFFFFFFFFFFFULL;
+ }
+
+ pwdLastSet = ldb_msg_find_attr_as_int64(msg, "pwdLastSet", 0);
+ if (pwdLastSet == 0) {
+ return 0;
+ }
+
+ if (pwdLastSet <= -1) {
+ /*
+ * This can't really happen...
+ */
+ return 0x7FFFFFFFFFFFFFFFULL;
+ }
+
+ if (pwdLastSet >= 0x7FFFFFFFFFFFFFFFULL) {
+ /*
+ * Somethings wrong with the clock...
+ */
+ return 0x7FFFFFFFFFFFFFFFULL;
+ }
+
+ /*
+ * Note that maxPwdAge is a stored as negative value.
+ *
+ * Possible values are in the range of:
+ *
+ * maxPwdAge: -864000000001
+ * to
+ * maxPwdAge: -9223372036854775808 (-0x8000000000000000ULL)
+ *
+ */
+ maxPwdAge = samdb_search_int64(ldb_module_get_ctx(module), msg, 0,
+ domain_dn, "maxPwdAge", NULL);
+ if (maxPwdAge >= -864000000000) {
+ /*
+ * This is not really possible...
+ */
+ return 0x7FFFFFFFFFFFFFFFULL;
+ }
+
+ if (maxPwdAge == -0x8000000000000000ULL) {
+ return 0x7FFFFFFFFFFFFFFFULL;
+ }
+
+ /*
+ * Note we already catched maxPwdAge == -0x8000000000000000ULL
+ * and pwdLastSet >= 0x7FFFFFFFFFFFFFFFULL above.
+ *
+ * Remember maxPwdAge is a negative number,
+ * so it results in the following.
+ *
+ * 0x7FFFFFFFFFFFFFFEULL + 0x7FFFFFFFFFFFFFFFULL
+ * =
+ * 0xFFFFFFFFFFFFFFFFULL
+ */
+ ret = pwdLastSet - maxPwdAge;
+ if (ret >= 0x7FFFFFFFFFFFFFFFULL) {
+ return 0x7FFFFFFFFFFFFFFFULL;
+ }
+
+ return ret;
+}
+
+
+/*
+ construct msDS-User-Account-Control-Computed attr
+*/
+static int construct_msds_user_account_control_computed(struct ldb_module *module,
+ struct ldb_message *msg, enum ldb_scope scope,
+ struct ldb_request *parent)
+{
+ uint32_t userAccountControl;
+ uint32_t msDS_User_Account_Control_Computed = 0;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ NTTIME now;
+ struct ldb_dn *nc_root;
+ int ret;
+
+ ret = dsdb_find_nc_root(ldb, msg, msg->dn, &nc_root);
+ if (ret != 0) {
+ ldb_asprintf_errstring(ldb,
+ "Failed to find NC root of DN: %s: %s",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(ldb_module_get_ctx(module)));
+ return ret;
+ }
+ if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) != 0) {
+ /* Only calculate this on our default NC */
+ return 0;
+ }
+ /* Test account expire time */
+ unix_to_nt_time(&now, time(NULL));
+
+ userAccountControl = ldb_msg_find_attr_as_uint(msg,
+ "userAccountControl",
+ 0);
+ if (!(userAccountControl & _UF_TRUST_ACCOUNTS)) {
+
+ int64_t lockoutTime = ldb_msg_find_attr_as_int64(msg, "lockoutTime", 0);
+ if (lockoutTime != 0) {
+ int64_t lockoutDuration = samdb_search_int64(ldb,
+ msg, 0, nc_root,
+ "lockoutDuration", NULL);
+ if (lockoutDuration >= 0) {
+ msDS_User_Account_Control_Computed |= UF_LOCKOUT;
+ } else if (lockoutTime - lockoutDuration >= now) {
+ msDS_User_Account_Control_Computed |= UF_LOCKOUT;
+ }
+ }
+ }
+
+ if (!(userAccountControl & _UF_NO_EXPIRY_ACCOUNTS)) {
+ NTTIME must_change_time
+ = get_msds_user_password_expiry_time_computed(module,
+ msg, nc_root);
+ /* check for expired password */
+ if (must_change_time < now) {
+ msDS_User_Account_Control_Computed |= UF_PASSWORD_EXPIRED;
+ }
+ }
+
+ return samdb_msg_add_int64(ldb,
+ msg->elements, msg,
+ "msDS-User-Account-Control-Computed",
+ msDS_User_Account_Control_Computed);
+}
+
struct op_controls_flags {
bool sd;
bool bypassoperational;
@@ -653,6 +807,14 @@ static const char *objectCategory_attr[] =
};
+static const char *user_account_control_computed_attrs[] =
+{
+ "lockoutTime",
+ "pwdLastSet",
+ NULL
+};
+
+
/*
a list of attribute names that are hidden, but can be searched for
using another (non-hidden) name to produce the correct result
@@ -667,7 +829,9 @@ static const struct op_attributes_replace search_sub[] = {
{ "parentGUID", NULL, NULL, construct_parent_guid },
{ "subSchemaSubEntry", NULL, NULL, construct_subschema_subentry },
{ "msDS-isRODC", "objectClass", objectCategory_attr, construct_msds_isrodc },
- { "msDS-KeyVersionNumber", "replPropertyMetaData", NULL, construct_msds_keyversionnumber }
+ { "msDS-KeyVersionNumber", "replPropertyMetaData", NULL, construct_msds_keyversionnumber },
+ { "msDS-User-Account-Control-Computed", "userAccountControl", user_account_control_computed_attrs,
+ construct_msds_user_account_control_computed }
};