summaryrefslogtreecommitdiff
path: root/source4/dsdb/common
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb/common')
-rw-r--r--source4/dsdb/common/sidmap.c612
-rw-r--r--source4/dsdb/common/util.c241
2 files changed, 126 insertions, 727 deletions
diff --git a/source4/dsdb/common/sidmap.c b/source4/dsdb/common/sidmap.c
deleted file mode 100644
index 3111a78e51..0000000000
--- a/source4/dsdb/common/sidmap.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- mapping routines for SID <-> unix uid/gid
-
- Copyright (C) Andrew Tridgell 2004
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "system/passwd.h"
-#include "../libds/common/flags.h"
-#include "dsdb/samdb/samdb.h"
-#include "auth/auth.h"
-#include "libcli/ldap/ldap_ndr.h"
-#include "lib/ldb/include/ldb.h"
-#include "../lib/util/util_ldb.h"
-#include "libcli/security/security.h"
-#include "param/param.h"
-
-/*
- these are used for the fallback local uid/gid to sid mapping
- code.
-*/
-#define SIDMAP_LOCAL_USER_BASE 0x80000000
-#define SIDMAP_LOCAL_GROUP_BASE 0xC0000000
-#define SIDMAP_MAX_LOCAL_UID 0x3fffffff
-#define SIDMAP_MAX_LOCAL_GID 0x3fffffff
-
-/*
- private context for sid mapping routines
-*/
-struct sidmap_context {
- struct ldb_context *samctx;
-};
-
-/*
- open a sidmap context - use talloc_free to close
-*/
-struct sidmap_context *sidmap_open(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx,
- struct loadparm_context *lp_ctx)
-{
- struct sidmap_context *sidmap;
- sidmap = talloc(mem_ctx, struct sidmap_context);
- if (sidmap == NULL) {
- return NULL;
- }
- sidmap->samctx = samdb_connect(sidmap, ev_ctx, lp_ctx, system_session(sidmap, lp_ctx));
- if (sidmap->samctx == NULL) {
- talloc_free(sidmap);
- return NULL;
- }
-
- return sidmap;
-}
-
-
-/*
- check the sAMAccountType field of a search result to see if
- the account is a user account
-*/
-static bool is_user_account(struct ldb_message *res)
-{
- uint_t atype = samdb_result_uint(res, "sAMAccountType", 0);
- if (atype && (!(atype & ATYPE_ACCOUNT))) {
- return false;
- }
- return true;
-}
-
-/*
- check the sAMAccountType field of a search result to see if
- the account is a group account
-*/
-static bool is_group_account(struct ldb_message *res)
-{
- uint_t atype = samdb_result_uint(res, "sAMAccountType", 0);
- if (atype && atype == ATYPE_NORMAL_ACCOUNT) {
- return false;
- }
- return true;
-}
-
-
-
-/*
- return the dom_sid of our primary domain
-*/
-static NTSTATUS sidmap_primary_domain_sid(struct sidmap_context *sidmap,
- TALLOC_CTX *mem_ctx, struct dom_sid **sid)
-{
- const char *attrs[] = { "objectSid", NULL };
- int ret;
- struct ldb_message **res = NULL;
-
- ret = gendb_search_dn(sidmap->samctx, mem_ctx, NULL, &res, attrs);
- if (ret != 1) {
- talloc_free(res);
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- *sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
- talloc_free(res);
- if (*sid == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- return NT_STATUS_OK;
-}
-
-
-/*
- map a sid to a unix uid
-*/
-NTSTATUS sidmap_sid_to_unixuid(struct sidmap_context *sidmap,
- const struct dom_sid *sid, uid_t *uid)
-{
- const char *attrs[] = { "sAMAccountName", "uidNumber",
- "sAMAccountType", "unixName", NULL };
- int ret;
- const char *s;
- TALLOC_CTX *tmp_ctx;
- struct ldb_message **res;
- struct dom_sid *domain_sid;
- NTSTATUS status;
-
- tmp_ctx = talloc_new(sidmap);
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "objectSid=%s",
- ldap_encode_ndr_dom_sid(tmp_ctx, sid));
-
- if (ret != 1) {
- goto allocated_sid;
- }
-
- /* make sure its a user, not a group */
- if (!is_user_account(res[0])) {
- DEBUG(0,("sid_to_unixuid: sid %s is not an account!\n",
- dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_INVALID_SID;
- }
-
- /* first try to get the uid directly */
- s = samdb_result_string(res[0], "uidNumber", NULL);
- if (s != NULL) {
- *uid = strtoul(s, NULL, 0);
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
- /* next try via the UnixName attribute */
- s = samdb_result_string(res[0], "unixName", NULL);
- if (s != NULL) {
- struct passwd *pwd = getpwnam(s);
- if (!pwd) {
- DEBUG(0,("unixName %s for sid %s does not exist as a local user\n", s,
- dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_USER;
- }
- *uid = pwd->pw_uid;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
- /* finally try via the sAMAccountName attribute */
- s = samdb_result_string(res[0], "sAMAccountName", NULL);
- if (s != NULL) {
- struct passwd *pwd = getpwnam(s);
- if (!pwd) {
- DEBUG(0,("sAMAccountName '%s' for sid %s does not exist as a local user\n",
- s, dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_USER;
- }
- *uid = pwd->pw_uid;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
-
-allocated_sid:
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- if (dom_sid_in_domain(domain_sid, sid)) {
- uint32_t rid = sid->sub_auths[sid->num_auths-1];
- if (rid >= SIDMAP_LOCAL_USER_BASE &&
- rid < SIDMAP_LOCAL_GROUP_BASE) {
- *uid = rid - SIDMAP_LOCAL_USER_BASE;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
- }
-
-
- DEBUG(0,("sid_to_unixuid: no uidNumber, unixName or sAMAccountName for sid %s\n",
- dom_sid_string(tmp_ctx, sid)));
-
- talloc_free(tmp_ctx);
- return NT_STATUS_NONE_MAPPED;
-}
-
-
-/*
- see if a sid is a group - very inefficient!
-*/
-bool sidmap_sid_is_group(struct sidmap_context *sidmap, struct dom_sid *sid)
-{
- const char *attrs[] = { "sAMAccountType", NULL };
- int ret;
- TALLOC_CTX *tmp_ctx;
- struct ldb_message **res;
- NTSTATUS status;
- struct dom_sid *domain_sid;
- bool is_group;
-
- tmp_ctx = talloc_new(sidmap);
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "objectSid=%s", ldap_encode_ndr_dom_sid(tmp_ctx, sid));
- if (ret == 1) {
- is_group = is_group_account(res[0]);
- talloc_free(tmp_ctx);
- return is_group;
- }
-
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return false;
- }
-
- if (dom_sid_in_domain(domain_sid, sid)) {
- uint32_t rid = sid->sub_auths[sid->num_auths-1];
- if (rid >= SIDMAP_LOCAL_GROUP_BASE) {
- talloc_free(tmp_ctx);
- return true;
- }
- }
-
- talloc_free(tmp_ctx);
- return false;
-}
-
-/*
- map a sid to a unix gid
-*/
-NTSTATUS sidmap_sid_to_unixgid(struct sidmap_context *sidmap,
- const struct dom_sid *sid, gid_t *gid)
-{
- const char *attrs[] = { "sAMAccountName", "gidNumber",
- "unixName", "sAMAccountType", NULL };
- int ret;
- const char *s;
- TALLOC_CTX *tmp_ctx;
- struct ldb_message **res;
- NTSTATUS status;
- struct dom_sid *domain_sid;
-
- tmp_ctx = talloc_new(sidmap);
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "objectSid=%s", ldap_encode_ndr_dom_sid(tmp_ctx, sid));
- if (ret != 1) {
- goto allocated_sid;
- }
-
- /* make sure its not a user */
- if (!is_group_account(res[0])) {
- DEBUG(0,("sid_to_unixgid: sid %s is a ATYPE_NORMAL_ACCOUNT\n",
- dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_INVALID_SID;
- }
-
- /* first try to get the gid directly */
- s = samdb_result_string(res[0], "gidNumber", NULL);
- if (s != NULL) {
- *gid = strtoul(s, NULL, 0);
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
- /* next try via the UnixName attribute */
- s = samdb_result_string(res[0], "unixName", NULL);
- if (s != NULL) {
- struct group *grp = getgrnam(s);
- if (!grp) {
- DEBUG(0,("unixName '%s' for sid %s does not exist as a local group\n",
- s, dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_GROUP;
- }
- *gid = grp->gr_gid;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
- /* finally try via the sAMAccountName attribute */
- s = samdb_result_string(res[0], "sAMAccountName", NULL);
- if (s != NULL) {
- struct group *grp = getgrnam(s);
- if (!grp) {
- DEBUG(0,("sAMAccountName '%s' for sid %s does not exist as a local group\n", s, dom_sid_string(tmp_ctx, sid)));
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_GROUP;
- }
- *gid = grp->gr_gid;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
-
-allocated_sid:
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- if (dom_sid_in_domain(domain_sid, sid)) {
- uint32_t rid = sid->sub_auths[sid->num_auths-1];
- if (rid >= SIDMAP_LOCAL_GROUP_BASE) {
- *gid = rid - SIDMAP_LOCAL_GROUP_BASE;
- talloc_free(tmp_ctx);
- return NT_STATUS_OK;
- }
- }
-
- DEBUG(0,("sid_to_unixgid: no gidNumber, unixName or sAMAccountName for sid %s\n",
- dom_sid_string(tmp_ctx, sid)));
-
- talloc_free(tmp_ctx);
- return NT_STATUS_NONE_MAPPED;
-}
-
-
-/*
- map a unix uid to a dom_sid
- the returned sid is allocated in the supplied mem_ctx
-*/
-NTSTATUS sidmap_uid_to_sid(struct sidmap_context *sidmap,
- TALLOC_CTX *mem_ctx,
- const uid_t uid, struct dom_sid **sid)
-{
- const char *attrs[] = { "sAMAccountName", "objectSid", "sAMAccountType", NULL };
- int ret, i;
- TALLOC_CTX *tmp_ctx;
- struct ldb_message **res;
- struct passwd *pwd;
- struct dom_sid *domain_sid;
- NTSTATUS status;
-
- /*
- we search for the mapping in the following order:
-
- - check if the uid is in the dynamic uid range assigned for winbindd
- use. If it is, then look in winbindd sid mapping
- database (not implemented yet)
- - look for a user account in samdb that has uidNumber set to the
- given uid
- - look for a user account in samdb that has unixName or
- sAMAccountName set to the name given by getpwuid()
- - assign a SID by adding the uid to SIDMAP_LOCAL_USER_BASE in the local
- domain
- */
-
-
- tmp_ctx = talloc_new(mem_ctx);
-
-
- /*
- step 2: look for a user account in samdb that has uidNumber set to the
- given uid
- */
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "uidNumber=%u", (unsigned int)uid);
- for (i=0;i<ret;i++) {
- if (!is_user_account(res[i])) continue;
-
- *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
- talloc_free(tmp_ctx);
- NT_STATUS_HAVE_NO_MEMORY(*sid);
- return NT_STATUS_OK;
- }
-
- /*
- step 3: look for a user account in samdb that has unixName
- or sAMAccountName set to the name given by getpwuid()
- */
- pwd = getpwuid(uid);
- if (pwd == NULL) {
- goto allocate_sid;
- }
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "(|(unixName=%s)(sAMAccountName=%s))",
- pwd->pw_name, pwd->pw_name);
- for (i=0;i<ret;i++) {
- if (!is_user_account(res[i])) continue;
-
- *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
- talloc_free(tmp_ctx);
- NT_STATUS_HAVE_NO_MEMORY(*sid);
- return NT_STATUS_OK;
- }
-
-
- /*
- step 4: assign a SID by adding the uid to
- SIDMAP_LOCAL_USER_BASE in the local domain
- */
-allocate_sid:
- if (uid > SIDMAP_MAX_LOCAL_UID) {
- return NT_STATUS_NONE_MAPPED;
- }
-
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return status;
- }
-
- *sid = dom_sid_add_rid(mem_ctx, domain_sid, SIDMAP_LOCAL_USER_BASE + uid);
- talloc_free(tmp_ctx);
-
- if (*sid == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- return NT_STATUS_OK;
-}
-
-
-/*
- map a unix gid to a dom_sid
- the returned sid is allocated in the supplied mem_ctx
-*/
-NTSTATUS sidmap_gid_to_sid(struct sidmap_context *sidmap,
- TALLOC_CTX *mem_ctx,
- const gid_t gid, struct dom_sid **sid)
-{
- const char *attrs[] = { "sAMAccountName", "objectSid", "sAMAccountType", NULL };
- int ret, i;
- TALLOC_CTX *tmp_ctx;
- struct ldb_message **res;
- struct group *grp;
- struct dom_sid *domain_sid;
- NTSTATUS status;
-
- /*
- we search for the mapping in the following order:
-
- - check if the gid is in the dynamic gid range assigned for winbindd
- use. If it is, then look in winbindd sid mapping
- database (not implemented yet)
- - look for a group account in samdb that has gidNumber set to the
- given gid
- - look for a group account in samdb that has unixName or
- sAMAccountName set to the name given by getgrgid()
- - assign a SID by adding the gid to SIDMAP_LOCAL_GROUP_BASE in the local
- domain
- */
-
-
- tmp_ctx = talloc_new(sidmap);
-
-
- /*
- step 2: look for a group account in samdb that has gidNumber set to the
- given gid
- */
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "gidNumber=%u", (unsigned int)gid);
- for (i=0;i<ret;i++) {
- if (!is_group_account(res[i])) continue;
-
- *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
- talloc_free(tmp_ctx);
- NT_STATUS_HAVE_NO_MEMORY(*sid);
- return NT_STATUS_OK;
- }
-
- /*
- step 3: look for a group account in samdb that has unixName
- or sAMAccountName set to the name given by getgrgid()
- */
- grp = getgrgid(gid);
- if (grp == NULL) {
- goto allocate_sid;
- }
-
- ret = gendb_search(sidmap->samctx, tmp_ctx, NULL, &res, attrs,
- "(|(unixName=%s)(sAMAccountName=%s))",
- grp->gr_name, grp->gr_name);
- for (i=0;i<ret;i++) {
- if (!is_group_account(res[i])) continue;
-
- *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
- talloc_free(tmp_ctx);
- NT_STATUS_HAVE_NO_MEMORY(*sid);
- return NT_STATUS_OK;
- }
-
-
- /*
- step 4: assign a SID by adding the gid to
- SIDMAP_LOCAL_GROUP_BASE in the local domain
- */
-allocate_sid:
- if (gid > SIDMAP_MAX_LOCAL_GID) {
- return NT_STATUS_NONE_MAPPED;
- }
-
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_free(tmp_ctx);
- return status;
- }
-
- *sid = dom_sid_add_rid(mem_ctx, domain_sid, SIDMAP_LOCAL_GROUP_BASE + gid);
- talloc_free(tmp_ctx);
-
- if (*sid == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- return NT_STATUS_OK;
-}
-
-/*
- check if a sid is in the range of auto-allocated SIDs from our primary domain,
- and if it is, then return the name and atype
-*/
-NTSTATUS sidmap_allocated_sid_lookup(struct sidmap_context *sidmap,
- TALLOC_CTX *mem_ctx,
- const struct dom_sid *sid,
- const char **name,
- enum lsa_SidType *rtype)
-{
- NTSTATUS status;
- struct dom_sid *domain_sid;
- TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
- uint32_t rid, atype;
-
- status = sidmap_primary_domain_sid(sidmap, tmp_ctx, &domain_sid);
- if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
- if (!dom_sid_in_domain(domain_sid, sid)) {
- talloc_free(tmp_ctx);
- return NT_STATUS_NONE_MAPPED;
- }
-
- talloc_free(tmp_ctx);
-
- rid = sid->sub_auths[sid->num_auths-1];
- if (rid < SIDMAP_LOCAL_USER_BASE) {
- return NT_STATUS_NONE_MAPPED;
- }
-
- if (rid < SIDMAP_LOCAL_GROUP_BASE) {
- struct passwd *pwd;
- uid_t uid = rid - SIDMAP_LOCAL_USER_BASE;
- atype = ATYPE_NORMAL_ACCOUNT;
- *rtype = ds_atype_map(atype);
-
- pwd = getpwuid(uid);
- if (pwd == NULL) {
- *name = talloc_asprintf(mem_ctx, "uid%u", uid);
- } else {
- *name = talloc_strdup(mem_ctx, pwd->pw_name);
- }
- } else {
- struct group *grp;
- gid_t gid = rid - SIDMAP_LOCAL_GROUP_BASE;
- atype = ATYPE_LOCAL_GROUP;
- *rtype = ds_atype_map(atype);
- grp = getgrgid(gid);
- if (grp == NULL) {
- *name = talloc_asprintf(mem_ctx, "gid%u", gid);
- } else {
- *name = talloc_strdup(mem_ctx, grp->gr_name);
- }
- }
-
- if (*name == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- return NT_STATUS_OK;
-}
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 45f19e93bb..c9562b0de7 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -1433,63 +1433,6 @@ struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx
}
/*
- * 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)
-{
- 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_strdup(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!"
- );
- }
-
- 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;
-}
-
-/*
work out if we are the PDC for the domain of the current open ldb
*/
bool samdb_is_pdc(struct ldb_context *ldb)
@@ -1588,7 +1531,7 @@ int samdb_search_for_parent_domain(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
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;
@@ -1640,21 +1583,22 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
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;
@@ -1675,14 +1619,14 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
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;
@@ -1695,9 +1639,10 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
|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),
@@ -1706,14 +1651,15 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
}
} 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),
@@ -1722,17 +1668,18 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
}
}
- 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);
@@ -1742,24 +1689,27 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
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;
@@ -1770,11 +1720,13 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
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;
}
@@ -1786,63 +1738,69 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
}
}
- 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;
}
@@ -1852,7 +1810,7 @@ NTSTATUS samdb_set_password(struct ldb_context *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 */
- 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 */
@@ -1875,6 +1833,9 @@ NTSTATUS samdb_set_password(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
}
}
+ if (reject_reason) {
+ *reject_reason = SAM_PWD_CHANGE_NO_ERROR;
+ }
return NT_STATUS_OK;
}
@@ -1893,7 +1854,7 @@ NTSTATUS samdb_set_password_sid(struct ldb_context *ctx, TALLOC_CTX *mem_ctx,
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;
@@ -2567,3 +2528,53 @@ int drsuapi_DsReplicaCursor2_compare(const struct drsuapi_DsReplicaCursor2 *c1,
{
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;
+}