diff options
Diffstat (limited to 'source4/dsdb/common/util.c')
-rw-r--r-- | source4/dsdb/common/util.c | 241 |
1 files changed, 126 insertions, 115 deletions
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; +} |