diff options
Diffstat (limited to 'source4/dsdb/common')
-rw-r--r-- | source4/dsdb/common/sidmap.c | 612 | ||||
-rw-r--r-- | source4/dsdb/common/util.c | 241 |
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; +} |