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:
parent
26515dca99
commit
0ed258bfe4
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user