#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"
const char *sAMAccountName;
const char *user_principal_name;
bool is_computer;
+ bool is_krbtgt;
uint32_t restrictions;
} u;
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);
"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",
& (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,
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;
"badPasswordTime",
"badPwdCount",
"lockoutTime",
+ "msDS-SecondaryKrbTgtNumber",
NULL };
struct ldb_request *search_req;
int ret;
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 */
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);