1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-03 13:47:25 +03:00

s4:dsdb: autogenerate a random utf16 buffer for krbtgt password resets.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12262

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
This commit is contained in:
Stefan Metzmacher 2017-02-13 19:01:21 +01:00 committed by Ralph Boehme
parent 26515dca99
commit 0ed258bfe4
2 changed files with 94 additions and 15 deletions

View File

@ -35,6 +35,7 @@
#include "includes.h"
#include "ldb_module.h"
#include "libcli/auth/libcli_auth.h"
#include "libcli/security/dom_sid.h"
#include "system/kerberos.h"
#include "auth/kerberos/kerberos.h"
#include "dsdb/samdb/samdb.h"
@ -125,6 +126,7 @@ struct setup_password_fields_io {
const char *sAMAccountName;
const char *user_principal_name;
bool is_computer;
bool is_krbtgt;
uint32_t restrictions;
} u;
@ -2793,6 +2795,8 @@ static int setup_io(struct ph_context *ac,
ldb_get_opaque(ldb, "loadparm"), struct loadparm_context);
int ret;
const struct ldb_message *info_msg = NULL;
struct dom_sid *account_sid = NULL;
int rodc_krbtgt = 0;
ZERO_STRUCTP(io);
@ -2837,6 +2841,26 @@ static int setup_io(struct ph_context *ac,
"userPrincipalName", NULL);
io->u.is_computer = ldb_msg_check_string_attribute(info_msg, "objectClass", "computer");
/* Ensure it has an objectSID too */
account_sid = samdb_result_dom_sid(ac, info_msg, "objectSid");
if (account_sid != NULL) {
NTSTATUS status;
uint32_t rid = 0;
status = dom_sid_split_rid(account_sid, account_sid, NULL, &rid);
if (NT_STATUS_IS_OK(status)) {
if (rid == DOMAIN_RID_KRBTGT) {
io->u.is_krbtgt = true;
}
}
}
rodc_krbtgt = ldb_msg_find_attr_as_int(info_msg,
"msDS-SecondaryKrbTgtNumber", 0);
if (rodc_krbtgt != 0) {
io->u.is_krbtgt = true;
}
if (io->u.sAMAccountName == NULL) {
ldb_asprintf_errstring(ldb,
"setup_io: sAMAccountName attribute is missing on %s for attempted password set/change",
@ -2867,6 +2891,12 @@ static int setup_io(struct ph_context *ac,
& (UF_INTERDOMAIN_TRUST_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT
| UF_SERVER_TRUST_ACCOUNT));
if (io->u.is_krbtgt) {
io->u.restrictions = 0;
io->ac->status->domain_data.pwdHistoryLength =
MAX(io->ac->status->domain_data.pwdHistoryLength, 3);
}
if (ac->userPassword) {
ret = msg_find_old_and_new_pwd_val(client_msg, "userPassword",
ac->req->operation,
@ -3172,6 +3202,59 @@ static int setup_io(struct ph_context *ac,
return ldb_operr(ldb);
}
if (io->u.is_krbtgt) {
size_t min = 196;
size_t max = 255;
size_t diff = max - min;
size_t len = max;
struct ldb_val *krbtgt_utf16 = NULL;
if (!ac->pwd_reset) {
return dsdb_module_werror(ac->module,
LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS,
WERR_DS_ATT_ALREADY_EXISTS,
"Password change on krbtgt not permitted!");
}
if (io->n.cleartext_utf16 == NULL) {
return dsdb_module_werror(ac->module,
LDB_ERR_UNWILLING_TO_PERFORM,
WERR_DS_INVALID_ATTRIBUTE_SYNTAX,
"Password reset on krbtgt requires UTF16!");
}
/*
* Instead of taking the callers value,
* we just generate a new random value here.
*
* Include null termination in the array.
*/
if (diff > 0) {
size_t tmp;
generate_random_buffer((uint8_t *)&tmp, sizeof(tmp));
tmp %= diff;
len = min + tmp;
}
krbtgt_utf16 = talloc_zero(io->ac, struct ldb_val);
if (krbtgt_utf16 == NULL) {
return ldb_oom(ldb);
}
*krbtgt_utf16 = data_blob_talloc_zero(krbtgt_utf16,
(len+1)*2);
if (krbtgt_utf16->data == NULL) {
return ldb_oom(ldb);
}
krbtgt_utf16->length = len * 2;
generate_secret_buffer(krbtgt_utf16->data,
krbtgt_utf16->length);
io->n.cleartext_utf16 = krbtgt_utf16;
}
if (existing_msg != NULL) {
NTSTATUS status;
@ -4055,6 +4138,7 @@ static int password_hash_mod_search_self(struct ph_context *ac)
"badPasswordTime",
"badPwdCount",
"lockoutTime",
"msDS-SecondaryKrbTgtNumber",
NULL };
struct ldb_request *search_req;
int ret;

View File

@ -664,7 +664,6 @@ static int samldb_rodc_add(struct samldb_ctx *ac)
struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
uint32_t krbtgt_number, i_start, i;
int ret;
char *newpass;
struct ldb_val newpass_utf16;
/* find a unused msDC-SecondaryKrbTgtNumber */
@ -710,21 +709,17 @@ found:
return ldb_operr(ldb);
}
newpass = generate_random_password(ac->msg, 128, 255);
if (newpass == NULL) {
return ldb_operr(ldb);
}
if (!convert_string_talloc(ac,
CH_UNIX, CH_UTF16,
newpass, strlen(newpass),
(void *)&newpass_utf16.data,
&newpass_utf16.length)) {
ldb_asprintf_errstring(ldb,
"samldb_rodc_add: "
"failed to generate UTF16 password from random password");
return LDB_ERR_OPERATIONS_ERROR;
newpass_utf16 = data_blob_talloc_zero(ac->module, 256);
if (newpass_utf16.data == NULL) {
return ldb_oom(ldb);
}
/*
* Note that the password_hash module will ignore
* this value and use it's own generate_secret_buffer()
* that's why we can just use generate_random_buffer()
* here.
*/
generate_random_buffer(newpass_utf16.data, newpass_utf16.length);
ret = ldb_msg_add_steal_value(ac->msg, "clearTextPassword", &newpass_utf16);
if (ret != LDB_SUCCESS) {
return ldb_operr(ldb);