summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/rpc_server/samr/dcesrv_samr.c9
-rw-r--r--source4/rpc_server/samr/samdb.c117
2 files changed, 82 insertions, 44 deletions
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 1d64fad5ba..44bf55b013 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -488,7 +488,7 @@ static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLO
ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, &msg,
"(&(name=TemplateGroup)(objectclass=groupTemplate))");
if (ret != 0) {
- DEBUG(1,("Failed to load TemplateUser from samdb\n"));
+ DEBUG(1,("Failed to load TemplateGroup from samdb\n"));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
@@ -1771,9 +1771,12 @@ static NTSTATUS samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX
return status;
}
- /* mark all the message elements as LDB_FLAG_MOD_REPLACE */
+ /* mark all the message elements as LDB_FLAG_MOD_REPLACE,
+ unless they are already marked with some other flag */
for (i=0;i<mod.num_elements;i++) {
- mod.elements[i].flags = LDB_FLAG_MOD_REPLACE;
+ if (mod.elements[i].flags == 0) {
+ mod.elements[i].flags = LDB_FLAG_MOD_REPLACE;
+ }
}
/* modify the samdb record */
diff --git a/source4/rpc_server/samr/samdb.c b/source4/rpc_server/samr/samdb.c
index 5f59ce1883..2fa17af8ea 100644
--- a/source4/rpc_server/samr/samdb.c
+++ b/source4/rpc_server/samr/samdb.c
@@ -499,7 +499,8 @@ int samdb_copy_template(void *ctx, TALLOC_CTX *mem_ctx,
}
for (j=0;j<el->num_values;j++) {
if (strcasecmp(el->name, "objectClass") == 0 &&
- (strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
+ (strcasecmp((char *)el->values[j].data, "Template") == 0 ||
+ strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
strcasecmp((char *)el->values[j].data, "groupTemplate") == 0)) {
continue;
}
@@ -627,6 +628,21 @@ int samdb_msg_add_string(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg
}
/*
+ add a delete element operation to a message
+*/
+int samdb_msg_add_delete(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char *attr_name)
+{
+ struct samdb_context *sam_ctx = ctx;
+ char *a = talloc_strdup(mem_ctx, attr_name);
+ if (a == NULL) {
+ return -1;
+ }
+ ldb_set_alloc(sam_ctx->ldb, samdb_alloc, mem_ctx);
+ return ldb_msg_add_empty(sam_ctx->ldb, msg, a, LDB_FLAG_MOD_DELETE);
+}
+
+/*
add a uint_t element to a message
*/
int samdb_msg_add_uint(void *ctx, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
@@ -815,6 +831,7 @@ NTSTATUS samdb_set_password(void *ctx, TALLOC_CTX *mem_ctx,
NTTIME now_nt;
double now_double;
int i;
+ BOOL lm_hash_ok;
/* we need to know the time to compute password age */
unix_to_nt_time(&now_nt, now);
@@ -873,14 +890,17 @@ NTSTATUS samdb_set_password(void *ctx, TALLOC_CTX *mem_ctx,
}
/* compute the new nt and lm hashes */
- E_deshash(new_pass, lmNewHash.hash);
+ lm_hash_ok = E_deshash(new_pass, lmNewHash.hash);
E_md4hash(new_pass, ntNewHash.hash);
/* check the immediately past password */
- if (pwdHistoryLength > 0 &&
- (memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0 ||
- memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0)) {
- return NT_STATUS_PASSWORD_RESTRICTION;
+ if (pwdHistoryLength > 0) {
+ if (lm_hash_ok && memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0) {
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+ if (memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) {
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
}
/* check the password history */
@@ -888,14 +908,18 @@ NTSTATUS samdb_set_password(void *ctx, TALLOC_CTX *mem_ctx,
ntPwdHistory_len = MIN(ntPwdHistory_len, pwdHistoryLength);
if (pwdHistoryLength > 0) {
- if (strcmp(unicodePwd, new_pass) == 0 ||
- memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0 ||
- memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) {
+ if (unicodePwd && strcmp(unicodePwd, new_pass) == 0) {
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+ if (lm_hash_ok && memcmp(lmNewHash.hash, lmPwdHash.hash, 16) == 0) {
+ return NT_STATUS_PASSWORD_RESTRICTION;
+ }
+ if (memcmp(ntNewHash.hash, ntPwdHash.hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
- for (i=0;i<lmPwdHistory_len;i++) {
+ for (i=0;lm_hash_ok && i<lmPwdHistory_len;i++) {
if (memcmp(lmNewHash.hash, lmPwdHistory[i].hash, 16) == 0) {
return NT_STATUS_PASSWORD_RESTRICTION;
}
@@ -909,46 +933,57 @@ NTSTATUS samdb_set_password(void *ctx, TALLOC_CTX *mem_ctx,
#define CHECK_RET(x) do { if (x != 0) return NT_STATUS_NO_MEMORY; } while(0)
/* the password is acceptable. Start forming the new fields */
- CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "lmPwdHash", lmNewHash));
+ if (lm_hash_ok) {
+ CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "lmPwdHash", lmNewHash));
+ } else {
+ CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "lmPwdHash"));
+ }
CHECK_RET(samdb_msg_add_hash(ctx, mem_ctx, mod, "ntPwdHash", ntNewHash));
if ((pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT) &&
(userAccountControl & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) {
CHECK_RET(samdb_msg_add_string(ctx, mem_ctx, mod,
"unicodePwd", new_pass));
- }
-
- if (pwdHistoryLength > 0) {
- new_lmPwdHistory = talloc_array_p(mem_ctx, struct samr_Hash,
- pwdHistoryLength);
- if (!new_lmPwdHistory) {
- return NT_STATUS_NO_MEMORY;
- }
- new_ntPwdHistory = talloc_array_p(mem_ctx, struct samr_Hash,
- pwdHistoryLength);
- if (!new_ntPwdHistory) {
- return NT_STATUS_NO_MEMORY;
- }
- for (i=0;i<MIN(pwdHistoryLength-1, lmPwdHistory_len);i++) {
- new_lmPwdHistory[i+1] = lmPwdHistory[i];
- }
- for (i=0;i<MIN(pwdHistoryLength-1, ntPwdHistory_len);i++) {
- new_ntPwdHistory[i+1] = ntPwdHistory[i];
- }
- new_lmPwdHistory[0] = lmNewHash;
- new_ntPwdHistory[0] = ntNewHash;
-
- CHECK_RET(samdb_msg_add_hashes(ctx, mem_ctx, mod,
- "lmPwdHistory",
- new_lmPwdHistory,
- MIN(pwdHistoryLength, lmPwdHistory_len+1)));
- CHECK_RET(samdb_msg_add_hashes(ctx, mem_ctx, mod,
- "ntPwdHistory",
- new_ntPwdHistory,
- MIN(pwdHistoryLength, ntPwdHistory_len+1)));
+ } else {
+ CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "unicodePwd"));
}
CHECK_RET(samdb_msg_add_double(ctx, mem_ctx, mod, "pwdLastSet", now_double));
+ if (pwdHistoryLength == 0) {
+ CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "lmPwdHistory"));
+ CHECK_RET(samdb_msg_add_delete(ctx, mem_ctx, mod, "ntPwdHistory"));
+ return NT_STATUS_OK;
+ }
+
+ /* store the password history */
+ new_lmPwdHistory = talloc_array_p(mem_ctx, struct samr_Hash,
+ pwdHistoryLength);
+ if (!new_lmPwdHistory) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ new_ntPwdHistory = talloc_array_p(mem_ctx, struct samr_Hash,
+ pwdHistoryLength);
+ if (!new_ntPwdHistory) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ for (i=0;i<MIN(pwdHistoryLength-1, lmPwdHistory_len);i++) {
+ new_lmPwdHistory[i+1] = lmPwdHistory[i];
+ }
+ for (i=0;i<MIN(pwdHistoryLength-1, ntPwdHistory_len);i++) {
+ new_ntPwdHistory[i+1] = ntPwdHistory[i];
+ }
+ new_lmPwdHistory[0] = lmNewHash;
+ new_ntPwdHistory[0] = ntNewHash;
+
+ CHECK_RET(samdb_msg_add_hashes(ctx, mem_ctx, mod,
+ "lmPwdHistory",
+ new_lmPwdHistory,
+ MIN(pwdHistoryLength, lmPwdHistory_len+1)));
+ CHECK_RET(samdb_msg_add_hashes(ctx, mem_ctx, mod,
+ "ntPwdHistory",
+ new_ntPwdHistory,
+ MIN(pwdHistoryLength, ntPwdHistory_len+1)));
+
return NT_STATUS_OK;
}