summaryrefslogtreecommitdiff
path: root/source4/auth/sam.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2013-11-06 10:39:42 +1300
committerStefan Metzmacher <metze@samba.org>2014-04-02 17:12:46 +0200
commit3f07737fd4a92fc948cfc432bc46098d6dd5269a (patch)
tree9fb99bf3cad568fe51ad3d6cbeeba83718462223 /source4/auth/sam.c
parenta0de9290099a93413048a03740cfb04ca1355c78 (diff)
downloadsamba-3f07737fd4a92fc948cfc432bc46098d6dd5269a.tar.gz
s4:auth: Add password lockout support to the AD DC
Including a fix by Arvid Requate <requate@univention.de> Change-Id: I25d10da50dd6119801cd37349cce970599531c6b Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'source4/auth/sam.c')
-rw-r--r--source4/auth/sam.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/source4/auth/sam.c b/source4/auth/sam.c
index 1c3b81ad0c6..789ff19d15c 100644
--- a/source4/auth/sam.c
+++ b/source4/auth/sam.c
@@ -83,6 +83,7 @@ const char *user_attrs[] = {
"logonCount",
"primaryGroupID",
"memberOf",
+ "badPasswordTime",
NULL,
};
@@ -634,3 +635,119 @@ NTSTATUS authsam_get_user_info_dc_principal(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
+
+NTSTATUS authsam_update_bad_pwd_count(struct ldb_context *sam_ctx,
+ struct ldb_message *msg,
+ struct ldb_dn *domain_dn)
+{
+ const char *attrs[] = { "lockoutThreshold",
+ "lockOutObservationWindow",
+ "lockoutDuration",
+ "pwdProperties",
+ NULL };
+ int ret, badPwdCount;
+ int64_t lockoutThreshold, lockOutObservationWindow, badPasswordTime;
+ struct dom_sid *sid;
+ struct ldb_result *domain_res;
+ struct ldb_message *msg_mod;
+ struct timeval tv_now = timeval_current();
+ NTTIME now = timeval_to_nttime(&tv_now);
+ NTSTATUS status;
+ uint32_t pwdProperties, rid = 0;
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_new(msg);
+ if (mem_ctx == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ sid = samdb_result_dom_sid(mem_ctx, msg, "objectSid");
+
+ ret = dsdb_search_dn(sam_ctx, mem_ctx, &domain_res, domain_dn, attrs, 0);
+ if (ret != LDB_SUCCESS) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ pwdProperties = ldb_msg_find_attr_as_uint(domain_res->msgs[0],
+ "pwdProperties", -1);
+ if (sid && !(pwdProperties & DOMAIN_PASSWORD_LOCKOUT_ADMINS)) {
+ status = dom_sid_split_rid(NULL, sid, NULL, &rid);
+ if (!NT_STATUS_IS_OK(status)) {
+ /*
+ * This can't happen anyway, but always try
+ * and update the badPwdCount on failure
+ */
+ rid = 0;
+ }
+ }
+
+ /*
+ * Work out if we are doing password lockout on the domain.
+ * Also, the built in administrator account is exempt:
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/aa375371%28v=vs.85%29.aspx
+ */
+ lockoutThreshold = ldb_msg_find_attr_as_int(domain_res->msgs[0],
+ "lockoutThreshold", 0);
+ if (lockoutThreshold == 0 || (rid == DOMAIN_RID_ADMINISTRATOR)) {
+ DEBUG(5, ("Not updating badPwdCount on %s after wrong password\n",
+ ldb_dn_get_linearized(msg->dn)));
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_OK;
+ }
+
+ lockOutObservationWindow = ldb_msg_find_attr_as_int64(domain_res->msgs[0],
+ "lockOutObservationWindow", 0);
+
+ badPasswordTime = ldb_msg_find_attr_as_int64(msg, "badPasswordTime", 0);
+
+ msg_mod = ldb_msg_new(mem_ctx);
+ if (msg_mod == NULL) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ msg_mod->dn = msg->dn;
+
+ if (badPasswordTime - lockOutObservationWindow >= now) {
+ badPwdCount = ldb_msg_find_attr_as_int(msg, "badPwdCount", 0);
+ } else {
+ badPwdCount = 0;
+ }
+
+ badPwdCount++;
+
+ ret = samdb_msg_add_int(sam_ctx, msg_mod, msg_mod, "badPwdCount", badPwdCount);
+ if (ret != LDB_SUCCESS) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ ret = samdb_msg_add_int64(sam_ctx, msg_mod, msg_mod, "badPasswordTime", now);
+ if (ret != LDB_SUCCESS) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (badPwdCount >= lockoutThreshold) {
+ ret = samdb_msg_add_int64(sam_ctx, msg_mod, msg_mod, "lockoutTime", now);
+ if (ret != LDB_SUCCESS) {
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ DEBUG(5, ("Locked out user %s after %d wrong passwords\n",
+ ldb_dn_get_linearized(msg->dn), badPwdCount));
+ }
+
+ ret = dsdb_replace(sam_ctx, msg_mod, 0);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("Failed to upate badPwdCount, badPasswordTime or set lockoutTime on %s: %s\n",
+ ldb_dn_get_linearized(msg_mod->dn), ldb_errstring(sam_ctx)));
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+
+ DEBUG(5, ("Updated badPwdCount on %s after %d wrong passwords\n",
+ ldb_dn_get_linearized(msg->dn), badPwdCount));
+
+ TALLOC_FREE(mem_ctx);
+ return NT_STATUS_OK;
+}