return server_site_dn;
}
-/*
- * This works out if we are running on a supported forest/domain function
- * level. Basically this means that we don't support mixed/interim (NT 4 DC
- * support) levels.
- * If errmsg isn't NULL we write in an adequate error message for printing out
- * to the screen.
- */
-bool samdb_is_capable_dc(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
- char **errmsg)
+const char *samdb_server_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
{
- int32_t level_forest, level_domain, level_domain_mixed;
- bool ret = true;
-
- level_forest = (int32_t) samdb_search_int64(ldb, mem_ctx, -1,
- samdb_partitions_dn(ldb, mem_ctx), "msDS-Behavior-Version",
- NULL);
- level_domain = (int32_t) samdb_search_int64(ldb, mem_ctx, -1,
- samdb_base_dn(ldb), "msDS-Behavior-Version", NULL);
- level_domain_mixed = (int32_t) samdb_search_int64(ldb, mem_ctx, -1,
- samdb_base_dn(ldb), "nTMixedDomain", NULL);
-
- if (errmsg != NULL)
- *errmsg = talloc_asprintf(mem_ctx, "");
-
- if (level_forest == -1 || level_domain == -1 || level_domain_mixed == -1) {
- ret = false;
- if (errmsg != NULL)
- *errmsg = talloc_strdup_append(*errmsg,
- "\nATTENTION: Invalid values for forest and/or domain function level!"
- );
- }
+ const struct ldb_val *val = ldb_dn_get_rdn_val(samdb_server_site_dn(ldb, mem_ctx));
- if (level_forest == DS_DOMAIN_FUNCTION_2003_MIXED) {
- ret = false;
- if (errmsg != NULL)
- *errmsg = talloc_strdup_append(*errmsg,
- "\nATTENTION: You run SAMBA 4 on the 2003 with mixed domains (NT4 DC support) forest level. This isn't supported!"
- );
- }
- if ((level_domain == DS_DOMAIN_FUNCTION_2000 && level_domain_mixed != 0)
- || level_domain == DS_DOMAIN_FUNCTION_2003_MIXED) {
- ret = false;
- if (errmsg != NULL)
- *errmsg = talloc_strdup_append(*errmsg,
- "\nATTENTION: You run SAMBA 4 on a mixed/interim (NT4 DC support) domain level. This isn't supported!"
- );
- }
-
- if ((!ret) && (errmsg != NULL)) {
- *errmsg = talloc_strdup_append(*errmsg,
- "\nPlease raise the domain and/or forest level to an adequate value. Use for this the 'domainlevel' tool, the MS AD MMC tools or manipulate the needed attributes directly."
- );
- }
-
- return ret;
+ if (val != NULL)
+ return (const char *) val->data;
+ else
+ return NULL;
}
/*
while ((sdn = ldb_dn_get_parent(local_ctx, sdn))) {
ret = ldb_search(ldb, local_ctx, &res, sdn, LDB_SCOPE_BASE, attrs,
- "(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain))");
+ "(|(objectClass=domain)(objectClass=builtinDomain))");
if (ret == LDB_SUCCESS) {
if (res->count == 1) {
break;
if (res->count != 1) {
*errstring = talloc_asprintf(mem_ctx, "Invalid dn (%s), not child of a domain object",
ldb_dn_get_linearized(dn));
+ DEBUG(0,(__location__ ": %s\n", *errstring));
talloc_free(local_ctx);
return LDB_ERR_CONSTRAINT_VIOLATION;
}
/*
- set the user password using plaintext, obeying any user or domain
- password restrictions
+ * Performs checks on a user password (plaintext UNIX format - attribute
+ * "password"). The remaining parameters have to be extracted from the domain
+ * object in the AD.
+ *
+ * Result codes from "enum samr_ValidationStatus" (consider "samr.idl")
+ */
+enum samr_ValidationStatus samdb_check_password(const DATA_BLOB *password,
+ const uint32_t pwdProperties,
+ const uint32_t minPwdLength)
+{
+ /* checks if the "minPwdLength" property is satisfied */
+ if (minPwdLength > password->length)
+ return SAMR_VALIDATION_STATUS_PWD_TOO_SHORT;
- note that this function doesn't actually store the result in the
- database, it just fills in the "mod" structure with ldb modify
- elements to setup the correct change when samdb_replace() is
- called. This allows the caller to combine the change with other
- changes (as is needed by some of the set user info levels)
+ /* checks the password complexity */
+ if (((pwdProperties & DOMAIN_PASSWORD_COMPLEX) != 0)
+ && (password->data != NULL)
+ && (!check_password_quality((const char *) password->data)))
+ return SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH;
- The caller should probably have a transaction wrapping this
-*/
+ return SAMR_VALIDATION_STATUS_SUCCESS;
+}
+
+/*
+ * Sets the user password using plaintext UTF16 (attribute "new_password") or
+ * LM (attribute "lmNewHash") or NT (attribute "ntNewHash") hash. Also pass
+ * as parameter if it's a user change or not ("userChange"). The "rejectReason"
+ * gives some more informations if the changed failed.
+ *
+ * The caller should have a LDB transaction wrapping this.
+ *
+ * Results: NT_STATUS_OK, NT_STATUS_INTERNAL_DB_CORRUPTION,
+ * NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
+ * NT_STATUS_PASSWORD_RESTRICTION
+ */
NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
- struct ldb_dn *user_dn,
- struct ldb_dn *domain_dn,
+ struct ldb_dn *user_dn, struct ldb_dn *domain_dn,
struct ldb_message *mod,
const DATA_BLOB *new_password,
struct samr_Password *param_lmNewHash,
struct samr_Password *param_ntNewHash,
bool user_change,
- enum samr_RejectReason *reject_reason,
+ enum samPwdChangeReason *reject_reason,
struct samr_DomInfo1 **_dominfo)
{
- const char * const user_attrs[] = { "userAccountControl", "lmPwdHistory",
+ const char * const user_attrs[] = { "userAccountControl",
+ "lmPwdHistory",
"ntPwdHistory",
"dBCSPwd", "unicodePwd",
"objectSid",
"pwdLastSet", NULL };
- const char * const domain_attrs[] = { "pwdProperties", "pwdHistoryLength",
- "maxPwdAge", "minPwdAge",
- "minPwdLength", NULL };
+ const char * const domain_attrs[] = { "minPwdLength", "pwdProperties",
+ "pwdHistoryLength",
+ "maxPwdAge", "minPwdAge", NULL };
NTTIME pwdLastSet;
- int64_t minPwdAge;
- uint_t minPwdLength, pwdProperties, pwdHistoryLength;
- uint_t userAccountControl;
+ uint32_t minPwdLength, pwdProperties, pwdHistoryLength;
+ int64_t maxPwdAge, minPwdAge;
+ uint32_t userAccountControl;
struct samr_Password *sambaLMPwdHistory, *sambaNTPwdHistory,
*lmPwdHash, *ntPwdHash, *lmNewHash, *ntNewHash;
struct samr_Password local_lmNewHash, local_ntNewHash;
if (count != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- userAccountControl = samdb_result_uint(res[0], "userAccountControl", 0);
- sambaLMPwdHistory_len = samdb_result_hashes(mem_ctx, res[0],
- "lmPwdHistory", &sambaLMPwdHistory);
- sambaNTPwdHistory_len = samdb_result_hashes(mem_ctx, res[0],
- "ntPwdHistory", &sambaNTPwdHistory);
- lmPwdHash = samdb_result_hash(mem_ctx, res[0], "dBCSPwd");
- ntPwdHash = samdb_result_hash(mem_ctx, res[0], "unicodePwd");
- pwdLastSet = samdb_result_uint64(res[0], "pwdLastSet", 0);
+ userAccountControl = samdb_result_uint(res[0], "userAccountControl", 0);
+ sambaLMPwdHistory_len = samdb_result_hashes(mem_ctx, res[0],
+ "lmPwdHistory", &sambaLMPwdHistory);
+ sambaNTPwdHistory_len = samdb_result_hashes(mem_ctx, res[0],
+ "ntPwdHistory", &sambaNTPwdHistory);
+ lmPwdHash = samdb_result_hash(mem_ctx, res[0], "dBCSPwd");
+ ntPwdHash = samdb_result_hash(mem_ctx, res[0], "unicodePwd");
+ pwdLastSet = samdb_result_uint64(res[0], "pwdLastSet", 0);
/* Copy parameters */
lmNewHash = param_lmNewHash;
|UF_WORKSTATION_TRUST_ACCOUNT
|UF_SERVER_TRUST_ACCOUNT));
- if (domain_dn) {
+ if (domain_dn != NULL) {
/* pull the domain parameters */
- count = gendb_search_dn(ctx, mem_ctx, domain_dn, &res, domain_attrs);
+ count = gendb_search_dn(ctx, mem_ctx, domain_dn, &res,
+ domain_attrs);
if (count != 1) {
DEBUG(2, ("samdb_set_password: Domain DN %s is invalid, for user %s\n",
ldb_dn_get_linearized(domain_dn),
}
} else {
/* work out the domain sid, and pull the domain from there */
- domain_sid = samdb_result_sid_prefix(mem_ctx, res[0], "objectSid");
+ domain_sid = samdb_result_sid_prefix(mem_ctx, res[0],
+ "objectSid");
if (domain_sid == NULL) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
count = gendb_search(ctx, mem_ctx, NULL, &res, domain_attrs,
- "(objectSid=%s)",
- ldap_encode_ndr_dom_sid(mem_ctx, domain_sid));
+ "(objectSid=%s)",
+ ldap_encode_ndr_dom_sid(mem_ctx, domain_sid));
if (count != 1) {
DEBUG(2, ("samdb_set_password: Could not find domain to match SID: %s, for user %s\n",
dom_sid_string(mem_ctx, domain_sid),
}
}
- pwdProperties = samdb_result_uint(res[0], "pwdProperties", 0);
- pwdHistoryLength = samdb_result_uint(res[0], "pwdHistoryLength", 0);
- minPwdLength = samdb_result_uint(res[0], "minPwdLength", 0);
- minPwdAge = samdb_result_int64(res[0], "minPwdAge", 0);
+ minPwdLength = samdb_result_uint(res[0], "minPwdLength", 0);
+ pwdProperties = samdb_result_uint(res[0], "pwdProperties", 0);
+ pwdHistoryLength = samdb_result_uint(res[0], "pwdHistoryLength", 0);
+ maxPwdAge = samdb_result_int64(res[0], "maxPwdAge", 0);
+ minPwdAge = samdb_result_int64(res[0], "minPwdAge", 0);
- if (userAccountControl & UF_PASSWD_NOTREQD) {
+ if ((userAccountControl & UF_PASSWD_NOTREQD) != 0) {
/* see [MS-ADTS] 2.2.15 */
minPwdLength = 0;
}
- if (_dominfo) {
+ if (_dominfo != NULL) {
struct samr_DomInfo1 *dominfo;
/* on failure we need to fill in the reject reasons */
dominfo = talloc(mem_ctx, struct samr_DomInfo1);
dominfo->min_password_length = minPwdLength;
dominfo->password_properties = pwdProperties;
dominfo->password_history_length = pwdHistoryLength;
- dominfo->max_password_age = minPwdAge;
+ dominfo->max_password_age = maxPwdAge;
dominfo->min_password_age = minPwdAge;
*_dominfo = dominfo;
}
- if (restrictions && new_password) {
+ if ((restrictions != 0) && (new_password != 0)) {
char *new_pass;
- /* check the various password restrictions */
- if (restrictions && minPwdLength > utf16_len_n(new_password->data, new_password->length) / 2) {
+ /* checks if the "minPwdLength" property is satisfied */
+ if ((restrictions != 0)
+ && (minPwdLength > utf16_len_n(
+ new_password->data, new_password->length)/2)) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_TOO_SHORT;
+ *reject_reason = SAM_PWD_CHANGE_PASSWORD_TOO_SHORT;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
/* Create the NT hash */
- mdfour(local_ntNewHash.hash, new_password->data, new_password->length);
+ mdfour(local_ntNewHash.hash, new_password->data,
+ new_password->length);
ntNewHash = &local_ntNewHash;
new_password->data, new_password->length,
(void **)&new_pass, NULL, false)) {
- /* possibly check password complexity */
- if (restrictions && (pwdProperties & DOMAIN_PASSWORD_COMPLEX) &&
- !check_password_quality(new_pass)) {
+ /* checks the password complexity */
+ if ((restrictions != 0)
+ && ((pwdProperties
+ & DOMAIN_PASSWORD_COMPLEX) != 0)
+ && (!check_password_quality(new_pass))) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_COMPLEXITY;
+ *reject_reason = SAM_PWD_CHANGE_NOT_COMPLEX;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
}
- if (restrictions && user_change) {
+ if ((restrictions != 0) && user_change) {
/* are all password changes disallowed? */
- if (pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) {
+ if ((pwdProperties & DOMAIN_REFUSE_PASSWORD_CHANGE) != 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_OTHER;
+ *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
- /* can this user change password? */
- if (userAccountControl & UF_PASSWD_CANT_CHANGE) {
+ /* can this user change the password? */
+ if ((userAccountControl & UF_PASSWD_CANT_CHANGE) != 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_OTHER;
+ *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
- /* yes, this is a minus. The ages are in negative 100nsec units! */
+ /* Password minimum age: yes, this is a minus. The ages are in negative 100nsec units! */
if (pwdLastSet - minPwdAge > now_nt) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_OTHER;
+ *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
/* check the immediately past password */
if (pwdHistoryLength > 0) {
- if (lmNewHash && lmPwdHash && memcmp(lmNewHash->hash, lmPwdHash->hash, 16) == 0) {
+ if (lmNewHash && lmPwdHash && memcmp(lmNewHash->hash,
+ lmPwdHash->hash, 16) == 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_IN_HISTORY;
+ *reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
- if (ntNewHash && ntPwdHash && memcmp(ntNewHash->hash, ntPwdHash->hash, 16) == 0) {
+ if (ntNewHash && ntPwdHash && memcmp(ntNewHash->hash,
+ ntPwdHash->hash, 16) == 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_IN_HISTORY;
+ *reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
/* check the password history */
- sambaLMPwdHistory_len = MIN(sambaLMPwdHistory_len, pwdHistoryLength);
- sambaNTPwdHistory_len = MIN(sambaNTPwdHistory_len, pwdHistoryLength);
+ sambaLMPwdHistory_len = MIN(sambaLMPwdHistory_len,
+ pwdHistoryLength);
+ sambaNTPwdHistory_len = MIN(sambaNTPwdHistory_len,
+ pwdHistoryLength);
for (i=0; lmNewHash && i<sambaLMPwdHistory_len;i++) {
- if (memcmp(lmNewHash->hash, sambaLMPwdHistory[i].hash, 16) == 0) {
+ if (memcmp(lmNewHash->hash, sambaLMPwdHistory[i].hash,
+ 16) == 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_IN_HISTORY;
+ *reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
}
for (i=0; ntNewHash && i<sambaNTPwdHistory_len;i++) {
- if (memcmp(ntNewHash->hash, sambaNTPwdHistory[i].hash, 16) == 0) {
+ if (memcmp(ntNewHash->hash, sambaNTPwdHistory[i].hash,
+ 16) == 0) {
if (reject_reason) {
- *reject_reason = SAMR_REJECT_IN_HISTORY;
+ *reject_reason = SAM_PWD_CHANGE_PWD_IN_HISTORY;
}
return NT_STATUS_PASSWORD_RESTRICTION;
}
#define CHECK_RET(x) do { if (x != 0) return NT_STATUS_NO_MEMORY; } while(0)
/* the password is acceptable. Start forming the new fields */
- if (new_password) {
+ if (new_password != NULL) {
/* if we know the cleartext UTF16 password, then set it.
* Modules in ldb will set all the appropriate
* hashes */
}
}
+ if (reject_reason) {
+ *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
+ }
return NT_STATUS_OK;
}
/*
- set the user password using plaintext, obeying any user or domain
- password restrictions
-
- This wrapper function takes a SID as input, rather than a user DN,
- and actually performs the password change
-
-*/
-NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
+ * Sets the user password using plaintext UTF16 (attribute "new_password") or
+ * LM (attribute "lmNewHash") or NT (attribute "ntNewHash") hash. Also pass
+ * as parameter if it's a user change or not ("userChange"). The "rejectReason"
+ * gives some more informations if the changed failed.
+ *
+ * This wrapper function for "samdb_set_password" takes a SID as input rather
+ * than a user DN.
+ *
+ * This call encapsulates a new LDB transaction for changing the password;
+ * therefore the user hasn't to start a new one.
+ *
+ * Results: NT_STATUS_OK, NT_STATUS_INTERNAL_DB_CORRUPTION,
+ * NT_STATUS_INVALID_PARAMETER, NT_STATUS_UNSUCCESSFUL,
+ * NT_STATUS_PASSWORD_RESTRICTION
+ */
+NTSTATUS samdb_set_password_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
const struct dom_sid *user_sid,
- const DATA_BLOB *new_pass,
+ const DATA_BLOB *new_password,
struct samr_Password *lmNewHash,
struct samr_Password *ntNewHash,
bool user_change,
- enum samr_RejectReason *reject_reason,
+ enum samPwdChangeReason *reject_reason,
struct samr_DomInfo1 **_dominfo)
{
NTSTATUS nt_status;
struct ldb_message *msg;
int ret;
- ret = ldb_transaction_start(ctx);
- if (ret) {
- DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ctx)));
+ ret = ldb_transaction_start(ldb);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(ldb)));
return NT_STATUS_TRANSACTION_ABORTED;
}
- user_dn = samdb_search_dn(ctx, mem_ctx, NULL,
+ user_dn = samdb_search_dn(ldb, mem_ctx, NULL,
"(&(objectSid=%s)(objectClass=user))",
ldap_encode_ndr_dom_sid(mem_ctx, user_sid));
if (!user_dn) {
- ldb_transaction_cancel(ctx);
+ ldb_transaction_cancel(ldb);
DEBUG(3, ("samdb_set_password_sid: SID %s not found in samdb, returning NO_SUCH_USER\n",
dom_sid_string(mem_ctx, user_sid)));
return NT_STATUS_NO_SUCH_USER;
msg = ldb_msg_new(mem_ctx);
if (msg == NULL) {
- ldb_transaction_cancel(ctx);
+ ldb_transaction_cancel(ldb);
return NT_STATUS_NO_MEMORY;
}
msg->dn = ldb_dn_copy(msg, user_dn);
if (!msg->dn) {
- ldb_transaction_cancel(ctx);
+ ldb_transaction_cancel(ldb);
return NT_STATUS_NO_MEMORY;
}
- nt_status = samdb_set_password(ctx, mem_ctx,
+ nt_status = samdb_set_password(ldb, mem_ctx,
user_dn, NULL,
- msg, new_pass,
+ msg, new_password,
lmNewHash, ntNewHash,
user_change, /* This is a password set, not change */
reject_reason, _dominfo);
if (!NT_STATUS_IS_OK(nt_status)) {
- ldb_transaction_cancel(ctx);
+ ldb_transaction_cancel(ldb);
return nt_status;
}
/* modify the samdb record */
- ret = samdb_replace(ctx, mem_ctx, msg);
- if (ret != 0) {
- ldb_transaction_cancel(ctx);
+ ret = samdb_replace(ldb, mem_ctx, msg);
+ if (ret != LDB_SUCCESS) {
+ ldb_transaction_cancel(ldb);
return NT_STATUS_ACCESS_DENIED;
}
- ret = ldb_transaction_commit(ctx);
- if (ret != 0) {
+ ret = ldb_transaction_commit(ldb);
+ if (ret != LDB_SUCCESS) {
DEBUG(0,("Failed to commit transaction to change password on %s: %s\n",
ldb_dn_get_linearized(msg->dn),
- ldb_errstring(ctx)));
+ ldb_errstring(ldb)));
return NT_STATUS_TRANSACTION_ABORTED;
}
return NT_STATUS_OK;
}
-
NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
struct dom_sid *sid, struct ldb_dn **ret_dn)
{
}
options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
+ ret = ldb_request_add_control(search_req, LDB_CONTROL_EXTENDED_DN_OID, true, NULL);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
ret = ldb_request_add_control(search_req,
LDB_CONTROL_SEARCH_OPTIONS_OID,
true, options);
return LDB_SUCCESS;
}
+/*
+ search for attrs on one DN, allowing for deleted objects
+ */
+int dsdb_search_dn_with_deleted(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_result **_res,
+ struct ldb_dn *basedn,
+ const char * const *attrs)
+{
+ int ret;
+ struct ldb_request *req;
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_result *res;
+
+ tmp_ctx = talloc_new(mem_ctx);
+
+ res = talloc_zero(tmp_ctx, struct ldb_result);
+ if (!res) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = ldb_build_search_req(&req, ldb, tmp_ctx,
+ basedn,
+ LDB_SCOPE_BASE,
+ NULL,
+ attrs,
+ NULL,
+ res,
+ ldb_search_default_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ret = ldb_request(ldb, req);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+ }
+
+ talloc_free(req);
+ *_res = talloc_steal(mem_ctx, res);
+ return ret;
+}
+
/*
use a DN to find a GUID
const char *attrs[] = { "objectGUID", NULL };
TALLOC_CTX *tmp_ctx = talloc_new(ldb);
- ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, attrs, NULL);
+ ret = dsdb_search_dn_with_deleted(ldb, tmp_ctx, &res, dn, attrs);
if (ret != LDB_SUCCESS) {
talloc_free(tmp_ctx);
return ret;
}
+ if (res->count < 1) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_NO_SUCH_OBJECT;
+ }
*guid = samdb_result_guid(res->msgs[0], "objectGUID");
talloc_free(tmp_ctx);
return LDB_SUCCESS;
}
+/*
+ use a DN to find a SID
+ */
+int dsdb_find_sid_by_dn(struct ldb_context *ldb,
+ struct ldb_dn *dn, struct dom_sid *sid)
+{
+ int ret;
+ struct ldb_result *res;
+ const char *attrs[] = { "objectSID", NULL };
+ TALLOC_CTX *tmp_ctx = talloc_new(ldb);
+ struct dom_sid *s;
+
+ ZERO_STRUCTP(sid);
+
+ ret = dsdb_search_dn_with_deleted(ldb, tmp_ctx, &res, dn, attrs);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ if (res->count < 1) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_NO_SUCH_OBJECT;
+ }
+ s = samdb_result_dom_sid(tmp_ctx, res->msgs[0], "objectSID");
+ if (s == NULL) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_NO_SUCH_OBJECT;
+ }
+ *sid = *s;
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+}
+
/*
{
return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
}
+
+/*
+ see if we are a RODC
+
+ TODO: This should take a sam_ctx, and lookup the right object (with
+ a cache)
+*/
+bool samdb_rodc(struct loadparm_context *lp_ctx)
+{
+ return lp_parm_bool(lp_ctx, NULL, "repl", "RODC", false);
+}
+
+
+/*
+ return NTDS options flags. See MS-ADTS 7.1.1.2.2.1.2.1.1
+
+ flags are DS_NTDS_OPTION_*
+*/
+int samdb_ntds_options(struct ldb_context *ldb, uint32_t *options)
+{
+ TALLOC_CTX *tmp_ctx;
+ const char *attrs[] = { "options", NULL };
+ int ret;
+ struct ldb_result *res;
+
+ tmp_ctx = talloc_new(ldb);
+ if (tmp_ctx == NULL) {
+ goto failed;
+ }
+
+ ret = ldb_search(ldb, tmp_ctx, &res, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, attrs, NULL);
+ if (ret) {
+ goto failed;
+ }
+
+ if (res->count != 1) {
+ goto failed;
+ }
+
+ *options = samdb_result_uint(res->msgs[0], "options", 0);
+
+ talloc_free(tmp_ctx);
+
+ return LDB_SUCCESS;
+
+failed:
+ DEBUG(1,("Failed to find our own NTDS Settings objectGUID in the ldb!\n"));
+ talloc_free(tmp_ctx);
+ return LDB_ERR_NO_SUCH_OBJECT;
+}