*/
#include "includes.h"
-#include "librpc/gen_ndr/ndr_lsa.h"
-#include "librpc/gen_ndr/ndr_samr.h"
#include "rpc_server/dcerpc_server.h"
#include "rpc_server/common/common.h"
-#include "lib/ldb/include/ldb.h"
#include "auth/auth.h"
-#include "system/time.h"
+#include "dsdb/samdb/samdb.h"
+#include "libcli/ldap/ldap.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "libcli/security/security.h"
+#include "libcli/auth/libcli_auth.h"
+#include "param/secrets.h"
#include "db_wrap.h"
+#include "librpc/gen_ndr/ndr_dssetup.h"
/*
this type allows us to distinguish handle types
struct ldb_context *sam_ldb;
struct sidmap_context *sidmap;
uint32_t access_mask;
- const char *domain_dn;
- const char *builtin_dn;
- const char *system_dn;
+ struct ldb_dn *domain_dn;
+ struct ldb_dn *builtin_dn;
+ struct ldb_dn *system_dn;
const char *domain_name;
+ const char *domain_dns;
struct dom_sid *domain_sid;
+ struct GUID domain_guid;
struct dom_sid *builtin_sid;
+ int mixed_domain;
};
struct lsa_policy_state *policy;
uint32_t access_mask;
struct dom_sid *account_sid;
- const char *account_dn;
};
struct lsa_secret_state {
struct lsa_policy_state *policy;
uint32_t access_mask;
- const char *secret_dn;
+ struct ldb_dn *secret_dn;
struct ldb_context *sam_ldb;
BOOL global;
};
struct lsa_trusted_domain_state {
struct lsa_policy_state *policy;
uint32_t access_mask;
- const char *trusted_domain_dn;
+ struct ldb_dn *trusted_domain_dn;
};
+static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_EnumAccountRights *r);
+
+static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_policy_state *state,
+ int ldb_flag,
+ struct dom_sid *sid,
+ const struct lsa_RightSet *rights);
+
/*
lsa_Close
*/
}
return NT_STATUS_OK;
+ } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
+ struct lsa_RightSet *rights;
+ struct lsa_account_state *astate;
+ struct lsa_EnumAccountRights r2;
+ NTSTATUS status;
+
+ rights = talloc(mem_ctx, struct lsa_RightSet);
+
+ DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
+
+ astate = h->data;
+
+ r2.in.handle = &astate->policy->handle->wire_handle;
+ r2.in.sid = astate->account_sid;
+ r2.out.rights = rights;
+
+ status = lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ return NT_STATUS_OK;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
+ LDB_FLAG_MOD_DELETE, astate->account_sid,
+ r2.out.rights);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ return NT_STATUS_OK;
+ }
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
}
return NT_STATUS_INVALID_HANDLE;
struct lsa_policy_state **_state)
{
struct lsa_policy_state *state;
- const char *domain_attrs[] = {"nETBIOSName", "nCName", NULL};
- int ret_domain;
- struct ldb_message **msgs_domain;
+ struct ldb_dn *partitions_basedn;
+ struct ldb_result *dom_res;
+ const char *dom_attrs[] = {
+ "objectSid",
+ "objectGUID",
+ "nTMixedDomain",
+ NULL
+ };
+ struct ldb_result *ref_res;
+ const char *ref_attrs[] = {
+ "nETBIOSName",
+ "dnsRoot",
+ NULL
+ };
+ char *ref_filter;
+ int ret;
state = talloc(mem_ctx, struct lsa_policy_state);
if (!state) {
}
/* make sure the sam database is accessible */
- state->sam_ldb = samdb_connect(state);
+ state->sam_ldb = samdb_connect(state, dce_call->conn->auth_state.session_info);
if (state->sam_ldb == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
+ partitions_basedn = samdb_partitions_dn(state->sam_ldb, mem_ctx);
+
state->sidmap = sidmap_open(state);
if (state->sidmap == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
- ret_domain = gendb_search(state->sam_ldb, mem_ctx, NULL, &msgs_domain, domain_attrs,
- "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
- lp_workgroup());
+ /* work out the domain_dn - useful for so many calls its worth
+ fetching here */
+ state->domain_dn = samdb_base_dn(state->sam_ldb);
+ if (!state->domain_dn) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = ldb_search(state->sam_ldb, state->domain_dn, LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res);
- if (ret_domain == -1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ if (ret != LDB_SUCCESS) {
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
-
- if (ret_domain != 1) {
+ talloc_steal(state, dom_res);
+ if (dom_res->count != 1) {
return NT_STATUS_NO_SUCH_DOMAIN;
}
- /* work out the domain_dn - useful for so many calls its worth
- fetching here */
- state->domain_dn = talloc_steal(state, samdb_result_string(msgs_domain[0], "nCName", NULL));
- if (!state->domain_dn) {
+ state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
+ if (!state->domain_sid) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
+ if (!state->domain_sid) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+
+ state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
+
+ talloc_free(dom_res);
+
+ ref_filter = talloc_asprintf(state, "(&(objectclass=crossRef)(ncName=%s))",
+ ldb_dn_get_linearized(state->domain_dn));
+ if (!ref_filter) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = ldb_search(state->sam_ldb, partitions_basedn, LDB_SCOPE_SUBTREE, ref_filter, ref_attrs, &ref_res);
+ talloc_steal(state, ref_res);
+ talloc_free(ref_filter);
+
+ if (ret != LDB_SUCCESS) {
+ return NT_STATUS_INVALID_SYSTEM_SERVICE;
+ }
+ if (ref_res->count != 1) {
return NT_STATUS_NO_SUCH_DOMAIN;
}
+ state->domain_name = ldb_msg_find_attr_as_string(ref_res->msgs[0], "nETBIOSName", NULL);
+ if (!state->domain_name) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+ talloc_steal(state, state->domain_name);
+
+ state->domain_dns = ldb_msg_find_attr_as_string(ref_res->msgs[0], "dnsRoot", NULL);
+ if (!state->domain_dns) {
+ return NT_STATUS_NO_SUCH_DOMAIN;
+ }
+ talloc_steal(state, state->domain_dns);
+
+ talloc_free(ref_res);
+
/* work out the builtin_dn - useful for so many calls its worth
fetching here */
- state->builtin_dn = talloc_steal(state,
- samdb_search_string(state->sam_ldb, mem_ctx, NULL,
- "dn", "objectClass=builtinDomain"));
+ state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
if (!state->builtin_dn) {
return NT_STATUS_NO_SUCH_DOMAIN;
}
/* work out the system_dn - useful for so many calls its worth
fetching here */
- state->system_dn = talloc_steal(state,
- samdb_search_string(state->sam_ldb, mem_ctx, state->domain_dn,
- "dn", "(&(objectClass=container)(cn=System))"));
+ state->system_dn = samdb_search_dn(state->sam_ldb, state,
+ state->domain_dn, "(&(objectClass=container)(cn=System))");
if (!state->system_dn) {
return NT_STATUS_NO_SUCH_DOMAIN;
}
- state->domain_sid = talloc_steal(state,
- samdb_search_dom_sid(state->sam_ldb, state,
- state->domain_dn, "objectSid",
- "dn=%s", state->domain_dn));
- if (!state->domain_sid) {
- return NT_STATUS_NO_SUCH_DOMAIN;
- }
-
state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
if (!state->builtin_sid) {
return NT_STATUS_NO_SUCH_DOMAIN;
}
- state->domain_name = talloc_strdup(state,
- samdb_result_string(msgs_domain[0], "nETBIOSName",
- lp_workgroup()));
-
*_state = state;
return NT_STATUS_OK;
}
+/*
+ dssetup_DsRoleGetPrimaryDomainInformation
+
+ This is not an LSA call, but is the only call left on the DSSETUP
+ pipe (after the pipe was truncated), and needs lsa_get_policy_state
+*/
+static WERROR dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct dssetup_DsRoleGetPrimaryDomainInformation *r)
+{
+ union dssetup_DsRoleInfo *info;
+
+ info = talloc(mem_ctx, union dssetup_DsRoleInfo);
+ W_ERROR_HAVE_NO_MEMORY(info);
+
+ switch (r->in.level) {
+ case DS_ROLE_BASIC_INFORMATION:
+ {
+ enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
+ uint32_t flags = 0;
+ const char *domain = NULL;
+ const char *dns_domain = NULL;
+ const char *forest = NULL;
+ struct GUID domain_guid;
+ struct lsa_policy_state *state;
+
+ NTSTATUS status = lsa_get_policy_state(dce_call, mem_ctx, &state);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ntstatus_to_werror(status);
+ }
+
+ ZERO_STRUCT(domain_guid);
+
+ switch (lp_server_role()) {
+ case ROLE_STANDALONE:
+ role = DS_ROLE_STANDALONE_SERVER;
+ break;
+ case ROLE_DOMAIN_MEMBER:
+ role = DS_ROLE_MEMBER_SERVER;
+ break;
+ case ROLE_DOMAIN_BDC:
+ role = DS_ROLE_BACKUP_DC;
+ break;
+ case ROLE_DOMAIN_PDC:
+ role = DS_ROLE_PRIMARY_DC;
+ break;
+ }
+
+ switch (lp_server_role()) {
+ case ROLE_STANDALONE:
+ domain = talloc_strdup(mem_ctx, lp_workgroup());
+ W_ERROR_HAVE_NO_MEMORY(domain);
+ break;
+ case ROLE_DOMAIN_MEMBER:
+ domain = talloc_strdup(mem_ctx, lp_workgroup());
+ W_ERROR_HAVE_NO_MEMORY(domain);
+ /* TODO: what is with dns_domain and forest and guid? */
+ break;
+ case ROLE_DOMAIN_BDC:
+ case ROLE_DOMAIN_PDC:
+ flags = DS_ROLE_PRIMARY_DS_RUNNING;
+
+ if (state->mixed_domain == 1) {
+ flags |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
+ }
+
+ domain = state->domain_name;
+ dns_domain = state->domain_dns;
+ forest = state->domain_dns;
+
+ domain_guid = state->domain_guid;
+ flags |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
+ break;
+ }
+
+ info->basic.role = role;
+ info->basic.flags = flags;
+ info->basic.domain = domain;
+ info->basic.dns_domain = dns_domain;
+ info->basic.forest = forest;
+ info->basic.domain_guid = domain_guid;
+
+ r->out.info = info;
+ return WERR_OK;
+ }
+ case DS_ROLE_UPGRADE_STATUS:
+ {
+ info->upgrade.upgrading = DS_ROLE_NOT_UPGRADING;
+ info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
+
+ r->out.info = info;
+ return WERR_OK;
+ }
+ case DS_ROLE_OP_STATUS:
+ {
+ info->opstatus.status = DS_ROLE_OP_IDLE;
+
+ r->out.info = info;
+ return WERR_OK;
+ }
+ default:
+ return WERR_INVALID_PARAM;
+ }
+
+ return WERR_INVALID_PARAM;
+}
+
/*
lsa_OpenPolicy2
*/
static NTSTATUS lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
struct lsa_DomainInfo *info)
{
- const char * const attrs[] = { "objectSid", "name", NULL};
- int ret;
- struct ldb_message **res;
-
- ret = gendb_search_dn(state->sam_ldb, mem_ctx, state->domain_dn, &res, attrs);
- if (ret != 1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- info->name.string = samdb_result_string(res[0], "name", NULL);
- info->sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
+ info->name.string = state->domain_name;
+ info->sid = state->domain_sid;
return NT_STATUS_OK;
}
static NTSTATUS lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
struct lsa_DnsDomainInfo *info)
{
- const char * const attrs[] = { "name", "dnsDomain", "objectGUID", "objectSid", NULL };
- int ret;
- struct ldb_message **res;
-
- ret = gendb_search_dn(state->sam_ldb, mem_ctx, state->domain_dn, &res, attrs);
- if (ret != 1) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
-
- info->name.string = samdb_result_string(res[0], "name", NULL);
- info->dns_domain.string = samdb_result_string(res[0], "dnsDomain", NULL);
- info->dns_forest.string = samdb_result_string(res[0], "dnsDomain", NULL);
- info->domain_guid = samdb_result_guid(res[0], "objectGUID");
- info->sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
+ info->name.string = state->domain_name;
+ info->sid = state->domain_sid;
+ info->dns_domain.string = state->domain_dns;
+ info->dns_forest.string = state->domain_dns;
+ info->domain_guid = state->domain_guid;
return NT_STATUS_OK;
}
static NTSTATUS lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct lsa_CreateAccount *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ struct lsa_account_state *astate;
+
+ struct lsa_policy_state *state;
+ struct dcesrv_handle *h, *ah;
+
+ ZERO_STRUCTP(r->out.acct_handle);
+
+ DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+
+ state = h->data;
+
+ astate = talloc(dce_call->conn, struct lsa_account_state);
+ if (astate == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ astate->account_sid = dom_sid_dup(astate, r->in.sid);
+ if (astate->account_sid == NULL) {
+ talloc_free(astate);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ astate->policy = talloc_reference(astate, state);
+ astate->access_mask = r->in.access_mask;
+
+ ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
+ if (!ah) {
+ talloc_free(astate);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ah->data = talloc_steal(ah, astate);
+
+ *r->out.acct_handle = ah->wire_handle;
+
+ return NT_STATUS_OK;
}
state = h->data;
- ret = gendb_search(state->sam_ldb, mem_ctx, state->builtin_dn, &res, attrs,
- "privilege=*");
- if (ret <= 0) {
+ /* NOTE: This call must only return accounts that have at least
+ one privilege set
+ */
+ ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs,
+ "(&(objectSid=*)(privilege=*))");
+ if (ret < 0) {
return NT_STATUS_NO_SUCH_USER;
}
ret = gendb_search(trusted_domain_state->policy->sam_ldb,
mem_ctx, policy_state->system_dn, &msgs, attrs,
"(&(cn=%s)(objectclass=trustedDomain))",
- r->in.info->name.string);
+ ldb_binary_encode_string(mem_ctx, r->in.info->name.string));
if (ret > 0) {
return NT_STATUS_OBJECT_NAME_COLLISION;
}
if (ret < 0 || ret > 1) {
- DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
+ DEBUG(0,("Found %d records matching DN %s\n", ret,
+ ldb_dn_get_linearized(policy_state->system_dn)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- msg->dn = talloc_asprintf(mem_ctx, "cn=%s,%s", r->in.info->name.string,
- policy_state->system_dn);
- if (!msg->dn) {
+ msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
+ if ( ! ldb_dn_add_child_fmt(msg->dn, "sn=%s", r->in.info->name.string)) {
return NT_STATUS_NO_MEMORY;
}
trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
/* create the trusted_domain */
- ret = samdb_add(trusted_domain_state->policy->sam_ldb, mem_ctx, msg);
- if (ret != 0) {
- DEBUG(0,("Failed to create trusted_domain record %s\n", msg->dn));
+ ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,("Failed to create trusted_domain record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn), ldb_errstring(trusted_domain_state->policy->sam_ldb)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
if (ret != 1) {
- DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
+ DEBUG(0,("Found %d records matching DN %s\n", ret,
+ ldb_dn_get_linearized(policy_state->system_dn)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ret = gendb_search(trusted_domain_state->policy->sam_ldb,
mem_ctx, policy_state->system_dn, &msgs, attrs,
"(&(flatname=%s)(objectclass=trustedDomain))",
- r->in.name.string);
+ ldb_binary_encode_string(mem_ctx, r->in.name.string));
if (ret == 0) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
if (ret != 1) {
- DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
+ DEBUG(0,("Found %d records matching DN %s\n", ret,
+ ldb_dn_get_linearized(policy_state->system_dn)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
+
/*
- lsa_QueryTrustedDomainInfoBySid
+ lsa_SetTrustedDomainInfo
*/
-static NTSTATUS lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_QueryTrustedDomainInfoBySid *r)
+static NTSTATUS lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_SetTrustedDomainInfo *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
+
/*
- lsa_SetTrustDomainInfo
+ lsa_SetInfomrationTrustedDomain
*/
-static NTSTATUS lsa_SetTrustDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_SetTrustDomainInfo *r)
+static NTSTATUS lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_SetInformationTrustedDomain *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
- lsa_DeleteTrustDomain
+ lsa_DeleteTrustedDomain
*/
-static NTSTATUS lsa_DeleteTrustDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_DeleteTrustDomain *r)
+static NTSTATUS lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_DeleteTrustedDomain *r)
{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+ NTSTATUS status;
+ struct lsa_OpenTrustedDomain open;
+ struct lsa_Delete delete;
+ struct dcesrv_handle *h;
+
+ open.in.handle = r->in.handle;
+ open.in.sid = r->in.dom_sid;
+ open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
+ if (!open.out.trustdom_handle) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ status = lsa_OpenTrustedDomain(dce_call, mem_ctx, &open);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
+ talloc_steal(mem_ctx, h);
+
+ delete.in.handle = open.out.trustdom_handle;
+ status = lsa_Delete(dce_call, mem_ctx, &delete);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ return NT_STATUS_OK;
}
+static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
+ struct ldb_message *msg,
+ struct lsa_TrustDomainInfoInfoEx *info_ex)
+{
+ info_ex->domain_name.string
+ = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
+ info_ex->netbios_name.string
+ = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
+ info_ex->sid
+ = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
+ info_ex->trust_direction
+ = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
+ info_ex->trust_type
+ = ldb_msg_find_attr_as_int(msg, "trustType", 0);
+ info_ex->trust_attributes
+ = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
+ return NT_STATUS_OK;
+}
/*
lsa_QueryTrustedDomainInfo
int ret;
struct ldb_message **res;
const char *attrs[] = {
- "cn",
- "flatname",
- "posixOffset",
+ "flatname",
+ "trustPartner",
"securityIdentifier",
+ "trustDirection",
+ "trustType",
+ "trustAttributes",
NULL
};
r->out.info->posix_offset.posix_offset
= samdb_result_uint(msg, "posixOffset", 0);
break;
+#if 0 /* Win2k3 doesn't implement this */
+ case LSA_TRUSTED_DOMAIN_INFO_BASIC:
+ r->out.info->info_basic.netbios_name.string
+ = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
+ r->out.info->info_basic.sid
+ = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
+ break;
+#endif
+ case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
+ return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_ex);
+
+ case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
+ ZERO_STRUCT(r->out.info->full_info);
+ return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->full_info.info_ex);
+
+ case LSA_TRUSTED_DOMAIN_INFO_INFO_ALL:
+ ZERO_STRUCT(r->out.info->info_all);
+ return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_all.info_ex);
+
+ case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS_INFO:
+ case LSA_TRUSTED_DOMAIN_INFO_11:
+ /* oops, we don't want to return the info after all */
+ talloc_free(r->out.info);
+ r->out.info = NULL;
+ return NT_STATUS_INVALID_PARAMETER;
default:
/* oops, we don't want to return the info after all */
talloc_free(r->out.info);
/*
- lsa_SetInformationTrustedDomain
+ lsa_QueryTrustedDomainInfoBySid
+*/
+static NTSTATUS lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_QueryTrustedDomainInfoBySid *r)
+{
+ NTSTATUS status;
+ struct lsa_OpenTrustedDomain open;
+ struct lsa_QueryTrustedDomainInfo query;
+ struct dcesrv_handle *h;
+ open.in.handle = r->in.handle;
+ open.in.sid = r->in.dom_sid;
+ open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
+ if (!open.out.trustdom_handle) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ status = lsa_OpenTrustedDomain(dce_call, mem_ctx, &open);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* Ensure this handle goes away at the end of this call */
+ DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
+ talloc_steal(mem_ctx, h);
+
+ query.in.trustdom_handle = open.out.trustdom_handle;
+ query.in.level = r->in.level;
+ status = lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ r->out.info = query.out.info;
+ return NT_STATUS_OK;
+}
+
+/*
+ lsa_SetTrustedDomainInfoByName
*/
-static NTSTATUS lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_SetInformationTrustedDomain *r)
+static NTSTATUS lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_SetTrustedDomainInfoByName *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
+/*
+ lsa_QueryTrustedDomainInfoByName
+*/
+static NTSTATUS lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_QueryTrustedDomainInfoByName *r)
+{
+ NTSTATUS status;
+ struct lsa_OpenTrustedDomainByName open;
+ struct lsa_QueryTrustedDomainInfo query;
+ struct dcesrv_handle *h;
+ open.in.handle = r->in.handle;
+ open.in.name = r->in.trusted_domain;
+ open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
+ if (!open.out.trustdom_handle) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ status = lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &open);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* Ensure this handle goes away at the end of this call */
+ DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
+ talloc_steal(mem_ctx, h);
+
+ query.in.trustdom_handle = open.out.trustdom_handle;
+ query.in.level = r->in.level;
+ status = lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ r->out.info = query.out.info;
+ return NT_STATUS_OK;
+}
+
+/*
+ lsa_CloseTrustedDomainEx
+*/
+static NTSTATUS lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_CloseTrustedDomainEx *r)
+{
+ /* The result of a bad hair day from an IDL programmer? Not
+ * implmented in Win2k3. You should always just lsa_Close
+ * anyway. */
+ return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+
+/*
+ comparison function for sorting lsa_DomainInformation array
+*/
+static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
+{
+ return strcasecmp_m(e1->name.string, e2->name.string);
+}
+
+/*
+ lsa_EnumTrustDom
+*/
+static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_EnumTrustDom *r)
+{
+ struct dcesrv_handle *policy_handle;
+ struct lsa_DomainInfo *entries;
+ struct lsa_policy_state *policy_state;
+ struct ldb_message **domains;
+ const char *attrs[] = {
+ "flatname",
+ "securityIdentifier",
+ NULL
+ };
+
+
+ int count, i;
+
+ *r->out.resume_handle = 0;
+
+ r->out.domains->domains = NULL;
+ r->out.domains->count = 0;
+
+ DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
+
+ policy_state = policy_handle->data;
+
+ /* search for all users in this domain. This could possibly be cached and
+ resumed based on resume_key */
+ count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
+ "objectclass=trustedDomain");
+ if (count == -1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ if (count == 0 || r->in.max_size == 0) {
+ return NT_STATUS_OK;
+ }
+
+ /* convert to lsa_TrustInformation format */
+ entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
+ if (!entries) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ for (i=0;i<count;i++) {
+ entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
+ entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
+ }
+
+ /* sort the results by name */
+ qsort(entries, count, sizeof(*entries),
+ (comparison_fn_t)compare_DomainInfo);
+
+ if (*r->in.resume_handle >= count) {
+ *r->out.resume_handle = -1;
-/*
- lsa_QueryTrustedDomainInfoByName
-*/
-static NTSTATUS lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct lsa_QueryTrustedDomainInfoByName *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
+ return NT_STATUS_NO_MORE_ENTRIES;
+ }
-/*
- lsa_SetTrustedDomainInfoByName
-*/
-static NTSTATUS lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct lsa_SetTrustedDomainInfoByName *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
+ /* return the rest, limit by max_size. Note that we
+ use the w2k3 element size value of 60 */
+ r->out.domains->count = count - *r->in.resume_handle;
+ r->out.domains->count = MIN(r->out.domains->count,
+ 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
-/*
- lsa_EnumTrustedDomainsEx
-*/
-static NTSTATUS lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct lsa_EnumTrustedDomainsEx *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
+ r->out.domains->domains = entries + *r->in.resume_handle;
+ r->out.domains->count = r->out.domains->count;
-/*
- lsa_CloseTrustedDomainEx
-*/
-static NTSTATUS lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct lsa_CloseTrustedDomainEx *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
+ if (r->out.domains->count < count - *r->in.resume_handle) {
+ *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
+ return STATUS_MORE_ENTRIES;
+ }
+ return NT_STATUS_OK;
+}
/*
comparison function for sorting lsa_DomainInformation array
*/
-static int compare_DomainInformation(struct lsa_DomainInformation *e1, struct lsa_DomainInformation *e2)
+static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
{
- return strcasecmp(e1->name.string, e2->name.string);
+ return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
}
/*
- lsa_EnumTrustDom
+ lsa_EnumTrustedDomainsEx
*/
-static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_EnumTrustDom *r)
+static NTSTATUS lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_EnumTrustedDomainsEx *r)
{
struct dcesrv_handle *policy_handle;
- struct lsa_DomainInformation *entries;
+ struct lsa_TrustDomainInfoInfoEx *entries;
struct lsa_policy_state *policy_state;
struct ldb_message **domains;
const char *attrs[] = {
"flatname",
+ "trustPartner",
"securityIdentifier",
+ "trustDirection",
+ "trustType",
+ "trustAttributes",
NULL
};
-
+ NTSTATUS nt_status;
int count, i;
}
/* convert to lsa_DomainInformation format */
- entries = talloc_array(mem_ctx, struct lsa_DomainInformation, count);
+ entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
if (!entries) {
return NT_STATUS_NO_MEMORY;
}
for (i=0;i<count;i++) {
- entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
- entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
+ nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
}
/* sort the results by name */
- qsort(entries, count, sizeof(struct lsa_DomainInformation),
- (comparison_fn_t)compare_DomainInformation);
+ qsort(entries, count, sizeof(*entries),
+ (comparison_fn_t)compare_TrustDomainInfoInfoEx);
if (*r->in.resume_handle >= count) {
*r->out.resume_handle = -1;
use the w2k3 element size value of 60 */
r->out.domains->count = count - *r->in.resume_handle;
r->out.domains->count = MIN(r->out.domains->count,
- 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
+ 1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
r->out.domains->domains = entries + *r->in.resume_handle;
r->out.domains->count = r->out.domains->count;
}
domains->domains = talloc_realloc(domains,
- domains->domains,
- struct lsa_TrustInformation,
- domains->count+1);
+ domains->domains,
+ struct lsa_DomainInfo,
+ domains->count+1);
if (domains->domains == NULL) {
return NT_STATUS_NO_MEMORY;
}
domains->domains[i].name.string = authority_name;
domains->domains[i].sid = authority_sid;
domains->count++;
+ domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
*sid_index = i;
return NT_STATUS_OK;
ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs,
"objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
if (ret == 1) {
- *name = ldb_msg_find_string(res[0], "sAMAccountName", NULL);
+ *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
if (!*name) {
- *name = ldb_msg_find_string(res[0], "name", NULL);
+ *name = ldb_msg_find_attr_as_string(res[0], "name", NULL);
if (!*name) {
*name = talloc_strdup(mem_ctx, sid_str);
- NTSTATUS_TALLOC_CHECK(*name);
+ NT_STATUS_HAVE_NO_MEMORY(*name);
}
}
/*
- lsa_LookupSids3
+ lsa_LookupSids2
*/
-static NTSTATUS lsa_LookupSids3(struct dcesrv_call_state *dce_call,
+static NTSTATUS lsa_LookupSids2(struct dcesrv_call_state *dce_call,
TALLOC_CTX *mem_ctx,
- struct lsa_LookupSids3 *r)
+ struct lsa_LookupSids2 *r)
{
struct lsa_policy_state *state;
int i;
/*
- lsa_LookupSids2
+ lsa_LookupSids3
+
+ Identical to LookupSids2, but doesn't take a policy handle
+
*/
-static NTSTATUS lsa_LookupSids2(struct dcesrv_call_state *dce_call,
+static NTSTATUS lsa_LookupSids3(struct dcesrv_call_state *dce_call,
TALLOC_CTX *mem_ctx,
- struct lsa_LookupSids2 *r)
+ struct lsa_LookupSids3 *r)
{
- struct lsa_LookupSids3 r3;
+ struct lsa_LookupSids2 r2;
+ struct lsa_OpenPolicy2 pol;
NTSTATUS status;
+ struct dcesrv_handle *h;
+
+ /* No policy handle on the wire, so make one up here */
+ r2.in.handle = talloc(mem_ctx, struct policy_handle);
+ if (!r2.in.handle) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ pol.out.handle = r2.in.handle;
+ pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ pol.in.attr = NULL;
+ pol.in.system_name = NULL;
+ status = lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- r3.in.sids = r->in.sids;
- r3.in.names = r->in.names;
- r3.in.level = r->in.level;
- r3.in.count = r->in.count;
- r3.in.unknown1 = r->in.unknown1;
- r3.in.unknown2 = r->in.unknown2;
- r3.out.count = r->out.count;
- r3.out.names = r->out.names;
+ /* ensure this handle goes away at the end of this call */
+ DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
+ talloc_steal(mem_ctx, h);
- status = lsa_LookupSids3(dce_call, mem_ctx, &r3);
+ r2.in.sids = r->in.sids;
+ r2.in.names = r->in.names;
+ r2.in.level = r->in.level;
+ r2.in.count = r->in.count;
+ r2.in.unknown1 = r->in.unknown1;
+ r2.in.unknown2 = r->in.unknown2;
+ r2.out.count = r->out.count;
+ r2.out.names = r->out.names;
+
+ status = lsa_LookupSids2(dce_call, mem_ctx, &r2);
if (dce_call->fault_code != 0) {
return status;
}
- r->out.domains = r3.out.domains;
- r->out.names = r3.out.names;
- r->out.count = r3.out.count;
+ r->out.domains = r2.out.domains;
+ r->out.names = r2.out.names;
+ r->out.count = r2.out.count;
return status;
}
static NTSTATUS lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct lsa_LookupSids *r)
{
- struct lsa_LookupSids3 r3;
+ struct lsa_LookupSids2 r2;
NTSTATUS status;
int i;
- r3.in.sids = r->in.sids;
- r3.in.names = NULL;
- r3.in.level = r->in.level;
- r3.in.count = r->in.count;
- r3.in.unknown1 = 0;
- r3.in.unknown2 = 0;
- r3.out.count = r->out.count;
-
- status = lsa_LookupSids3(dce_call, mem_ctx, &r3);
+ r2.in.handle = r->in.handle;
+ r2.in.sids = r->in.sids;
+ r2.in.names = NULL;
+ r2.in.level = r->in.level;
+ r2.in.count = r->in.count;
+ r2.in.unknown1 = 0;
+ r2.in.unknown2 = 0;
+ r2.out.count = r->out.count;
+ r2.out.names = NULL;
+
+ status = lsa_LookupSids2(dce_call, mem_ctx, &r2);
if (dce_call->fault_code != 0) {
return status;
}
- r->out.domains = r3.out.domains;
+ r->out.domains = r2.out.domains;
+ if (!r2.out.names) {
+ r->out.names = NULL;
+ return status;
+ }
+
r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
if (r->out.names == NULL) {
return NT_STATUS_NO_MEMORY;
}
- r->out.names->count = r3.out.names->count;
+ r->out.names->count = r2.out.names->count;
r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName,
r->out.names->count);
if (r->out.names->names == NULL) {
return NT_STATUS_NO_MEMORY;
}
for (i=0;i<r->out.names->count;i++) {
- r->out.names->names[i].sid_type = r3.out.names->names[i].sid_type;
- r->out.names->names[i].name.string = r3.out.names->names[i].name.string;
- r->out.names->names[i].sid_index = r3.out.names->names[i].sid_index;
+ r->out.names->names[i].sid_type = r2.out.names->names[i].sid_type;
+ r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
+ r->out.names->names[i].sid_index = r2.out.names->names[i].sid_index;
}
return status;
return NT_STATUS_NO_MEMORY;
}
- /* check it really exists */
- astate->account_dn =
- samdb_search_string(state->sam_ldb, astate,
- NULL, "dn",
- "(&(objectSid=%s)(objectClass=group))",
- ldap_encode_ndr_dom_sid(mem_ctx,
- astate->account_sid));
- if (astate->account_dn == NULL) {
- talloc_free(astate);
- return NT_STATUS_NO_SUCH_USER;
- }
-
astate->policy = talloc_reference(astate, state);
astate->access_mask = r->in.access_mask;
struct ldb_message **res;
const char * const attrs[] = { "privilege", NULL};
struct ldb_message_element *el;
+ const char *sidstr;
DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
r->out.privs->unknown = 0;
r->out.privs->set = NULL;
- ret = gendb_search_dn(astate->policy->sam_ldb, mem_ctx,
- astate->account_dn, &res, attrs);
+ sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
+ if (sidstr == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = gendb_search(astate->policy->sam_ldb, mem_ctx, NULL, &res, attrs,
+ "objectSid=%s", sidstr);
if (ret != 1) {
return NT_STATUS_OK;
}
}
r->out.privs->set = talloc_array(r->out.privs,
- struct lsa_LUIDAttribute, el->num_values);
+ struct lsa_LUIDAttribute, el->num_values);
if (r->out.privs->set == NULL) {
return NT_STATUS_NO_MEMORY;
}
}
ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs,
- "objectSid=%s", sidstr);
- if (ret != 1) {
+ "(&(objectSid=%s)(privilege=*))", sidstr);
+ if (ret == 0) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ if (ret > 1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ if (ret == -1) {
+ DEBUG(3, ("searching for account rights for SID: %s failed: %s",
+ dom_sid_string(mem_ctx, r->in.sid),
+ ldb_errstring(state->sam_ldb)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
el = ldb_msg_find_element(res[0], "privilege");
if (el == NULL || el->num_values == 0) {
r->out.rights->count = el->num_values;
r->out.rights->names = talloc_array(r->out.rights,
- struct lsa_String, r->out.rights->count);
+ struct lsa_StringLarge, r->out.rights->count);
if (r->out.rights->names == NULL) {
return NT_STATUS_NO_MEMORY;
}
{
const char *sidstr;
struct ldb_message *msg;
- struct ldb_message_element el;
+ struct ldb_message_element *el;
int i, ret;
- const char *dn;
struct lsa_EnumAccountRights r2;
sidstr = ldap_encode_ndr_dom_sid(mem_ctx, sid);
return NT_STATUS_NO_MEMORY;
}
- dn = samdb_search_string(state->sam_ldb, mem_ctx, NULL, "dn",
- "objectSid=%s", sidstr);
- if (dn == NULL) {
- return NT_STATUS_NO_SUCH_USER;
- }
-
- msg->dn = talloc_strdup(mem_ctx, dn);
+ msg->dn = samdb_search_dn(state->sam_ldb, mem_ctx,
+ NULL, "objectSid=%s", sidstr);
if (msg->dn == NULL) {
- return NT_STATUS_NO_MEMORY;
+ NTSTATUS status;
+ if (ldb_flag == LDB_FLAG_MOD_DELETE) {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ status = samdb_create_foreign_security_principal(state->sam_ldb, mem_ctx,
+ sid, &msg->dn);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ return NT_STATUS_NO_SUCH_USER;
}
- if (ldb_msg_add_empty(state->sam_ldb, msg, "privilege", ldb_flag)) {
+ if (ldb_msg_add_empty(msg, "privilege", ldb_flag, NULL)) {
return NT_STATUS_NO_MEMORY;
}
}
}
- el.num_values = 0;
- el.values = talloc_array(mem_ctx, struct ldb_val, rights->count);
- if (el.values == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
for (i=0;i<rights->count;i++) {
if (sec_privilege_id(rights->names[i].string) == -1) {
return NT_STATUS_NO_SUCH_PRIVILEGE;
if (ldb_flag == LDB_FLAG_MOD_ADD) {
int j;
for (j=0;j<r2.out.rights->count;j++) {
- if (StrCaseCmp(r2.out.rights->names[j].string,
+ if (strcasecmp_m(r2.out.rights->names[j].string,
rights->names[i].string) == 0) {
break;
}
if (j != r2.out.rights->count) continue;
}
-
- el.values[el.num_values].length = strlen(rights->names[i].string);
- el.values[el.num_values].data = (uint8_t *)talloc_strdup(mem_ctx, rights->names[i].string);
- if (el.values[el.num_values].data == NULL) {
+ ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
+ if (ret != LDB_SUCCESS) {
return NT_STATUS_NO_MEMORY;
}
- el.num_values++;
}
- if (el.num_values == 0) {
+ el = ldb_msg_find_element(msg, "privilege");
+ if (!el) {
return NT_STATUS_OK;
}
ret = samdb_modify(state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- if (ldb_flag == LDB_FLAG_MOD_DELETE) {
+ if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ DEBUG(3, ("Could not %s attributes from %s: %s",
+ ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
+ ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)));
return NT_STATUS_UNEXPECTED_IO_ERROR;
}
astate = h->data;
rights.count = r->in.privs->count;
- rights.names = talloc_array(mem_ctx, struct lsa_String, rights.count);
+ rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
if (rights.names == NULL) {
return NT_STATUS_NO_MEMORY;
}
}
rights->count = r->in.privs->count;
- rights->names = talloc_array(mem_ctx, struct lsa_String, rights->count);
+ rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
if (rights->names == NULL) {
return NT_STATUS_NO_MEMORY;
}
struct lsa_secret_state *secret_state;
struct dcesrv_handle *handle;
struct ldb_message **msgs, *msg;
+ const char *errstr;
const char *attrs[] = {
NULL
};
return NT_STATUS_INVALID_PARAMETER;
}
- name2 = talloc_asprintf(mem_ctx, "%s Secret", name);
+ name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
/* search for the secret record */
ret = gendb_search(secret_state->sam_ldb,
mem_ctx, policy_state->system_dn, &msgs, attrs,
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- if (ret < 0 || ret > 1) {
- DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
+ if (ret == -1) {
+ DEBUG(0,("Failure searching for CN=%s: %s\n",
+ name2, ldb_errstring(secret_state->sam_ldb)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- msg->dn = talloc_asprintf(mem_ctx, "cn=%s,%s", name2, policy_state->system_dn);
- if (!name2 || !msg->dn) {
+ msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
+ if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
return NT_STATUS_NO_MEMORY;
}
secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
/* search for the secret record */
- ret = gendb_search(secret_state->sam_ldb,
- mem_ctx, "cn=LSA Secrets", &msgs, attrs,
+ ret = gendb_search(secret_state->sam_ldb, mem_ctx,
+ ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
+ &msgs, attrs,
"(&(cn=%s)(objectclass=secret))",
- name);
+ ldb_binary_encode_string(mem_ctx, name));
if (ret > 0) {
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- if (ret < 0 || ret > 1) {
- DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
+ if (ret == -1) {
+ DEBUG(0,("Failure searching for CN=%s: %s\n",
+ name, ldb_errstring(secret_state->sam_ldb)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- msg->dn = talloc_asprintf(mem_ctx, "cn=%s,cn=LSA Secrets", name);
+ msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
}
/* pull in all the template attributes. Note this is always from the global samdb */
- ret = samdb_copy_template(secret_state->policy->sam_ldb, mem_ctx, msg,
- "(&(name=TemplateSecret)(objectclass=secretTemplate))");
+ ret = samdb_copy_template(secret_state->policy->sam_ldb, msg,
+ "(&(cn=TemplateSecret)(objectclass=secretTemplate))", &errstr);
if (ret != 0) {
- DEBUG(0,("Failed to load TemplateSecret from samdb\n"));
+ DEBUG(0,("Failed to load TemplateSecret from samdb: %s\n",
+ errstr));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
/* create the secret */
ret = samdb_add(secret_state->sam_ldb, mem_ctx, msg);
if (ret != 0) {
- DEBUG(0,("Failed to create secret record %s\n", msg->dn));
+ DEBUG(0,("Failed to create secret record %s: %s\n",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(secret_state->sam_ldb)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ret = gendb_search(secret_state->sam_ldb,
mem_ctx, policy_state->system_dn, &msgs, attrs,
"(&(cn=%s Secret)(objectclass=secret))",
- name);
+ ldb_binary_encode_string(mem_ctx, name));
if (ret == 0) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
if (ret != 1) {
- DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
+ DEBUG(0,("Found %d records matching DN %s\n", ret,
+ ldb_dn_get_linearized(policy_state->system_dn)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
/* search for the secret record */
- ret = gendb_search(secret_state->sam_ldb,
- mem_ctx, "cn=LSA Secrets", &msgs, attrs,
+ ret = gendb_search(secret_state->sam_ldb, mem_ctx,
+ ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
+ &msgs, attrs,
"(&(cn=%s)(objectclass=secret))",
- name);
+ ldb_binary_encode_string(mem_ctx, name));
if (ret == 0) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
if (ret != 1) {
- DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
+ DEBUG(0,("Found %d records matching DN %s\n", ret,
+ ldb_dn_get_linearized(policy_state->system_dn)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
}
/* set value */
if (samdb_msg_add_value(secret_state->sam_ldb,
- mem_ctx, msg, "priorSecret", &val) != 0) {
+ mem_ctx, msg, "priorValue", &val) != 0) {
return NT_STATUS_NO_MEMORY;
}
}
} else {
if (samdb_msg_add_delete(secret_state->sam_ldb,
- mem_ctx, msg, "secret")) {
+ mem_ctx, msg, "currentValue")) {
return NT_STATUS_NO_MEMORY;
}
if (samdb_msg_add_delete(secret_state->sam_ldb,
/* set value */
if (samdb_msg_add_value(secret_state->sam_ldb,
- mem_ctx, msg, "secret", &val) != 0) {
+ mem_ctx, msg, "currentValue", &val) != 0) {
return NT_STATUS_NO_MEMORY;
}
NTTIME last_set_time;
struct ldb_message **res;
const char *attrs[] = {
- "secret",
+ "currentValue",
"lastSetTime",
NULL
};
}
if (ret != 1) {
- DEBUG(0,("Found %d records matching dn=%s\n", ret, secret_state->secret_dn));
+ DEBUG(0,("Found %d records matching dn=%s\n", ret,
+ ldb_dn_get_linearized(secret_state->secret_dn)));
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- new_val = ldb_msg_find_ldb_val(res[0], "secret");
- last_set_time = ldb_msg_find_uint64(res[0], "lastSetTime", 0);
+ new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
+ last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
if (new_val) {
/* set value */
if (samdb_msg_add_value(secret_state->sam_ldb,
- mem_ctx, msg, "priorSecret",
+ mem_ctx, msg, "priorValue",
new_val) != 0) {
return NT_STATUS_NO_MEMORY;
}
int ret;
struct ldb_message **res;
const char *attrs[] = {
- "secret",
- "priorSecret",
+ "currentValue",
+ "priorValue",
"lastSetTime",
"priorSetTime",
NULL
if (!r->out.old_val) {
return NT_STATUS_NO_MEMORY;
}
- /* Decrypt */
- prior_val = ldb_msg_find_ldb_val(res[0], "priorSecret");
+ prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
if (prior_val && prior_val->length) {
secret.data = prior_val->data;
secret.length = prior_val->length;
+ /* Encrypt */
crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
if (!crypt_secret.length) {
return NT_STATUS_NO_MEMORY;
if (!r->out.old_mtime) {
return NT_STATUS_NO_MEMORY;
}
- *r->out.old_mtime = ldb_msg_find_uint64(res[0], "priorSetTime", 0);
+ *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
}
if (r->in.new_val) {
return NT_STATUS_NO_MEMORY;
}
- /* Decrypt */
- new_val = ldb_msg_find_ldb_val(res[0], "secret");
+ new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
if (new_val && new_val->length) {
secret.data = new_val->data;
secret.length = new_val->length;
+ /* Encrypt */
crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
if (!crypt_secret.length) {
return NT_STATUS_NO_MEMORY;
if (!r->out.new_mtime) {
return NT_STATUS_NO_MEMORY;
}
- *r->out.new_mtime = ldb_msg_find_uint64(res[0], "lastSetTime", 0);
+ *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
}
return NT_STATUS_OK;
return NT_STATUS_NO_SUCH_PRIVILEGE;
}
- r->out.name = talloc(mem_ctx, struct lsa_String);
+ r->out.name = talloc(mem_ctx, struct lsa_StringLarge);
if (r->out.name == NULL) {
return NT_STATUS_NO_MEMORY;
}
return NT_STATUS_NO_SUCH_PRIVILEGE;
}
- r->out.disp_name = talloc(mem_ctx, struct lsa_String);
+ r->out.disp_name = talloc(mem_ctx, struct lsa_StringLarge);
if (r->out.disp_name == NULL) {
return NT_STATUS_NO_MEMORY;
}
ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs,
"privilege=%s", privname);
- if (ret <= 0) {
- return NT_STATUS_NO_SUCH_USER;
+ if (ret == -1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ if (ret == 0) {
+ return NT_STATUS_NO_MORE_ENTRIES;
}
r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
lsa_GetUserName
*/
static NTSTATUS lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_GetUserName *r)
+ struct lsa_GetUserName *r)
{
NTSTATUS status = NT_STATUS_OK;
const char *account_name;
return NT_STATUS_INVALID_PARAMETER;
}
- /* TODO: this check should go and we should rely on the calling code that this is valid */
- if (!dce_call->conn->auth_state.session_info ||
- !dce_call->conn->auth_state.session_info->server_info ||
- !dce_call->conn->auth_state.session_info->server_info->account_name ||
- !dce_call->conn->auth_state.session_info->server_info->domain_name) {
- return NT_STATUS_INTERNAL_ERROR;
- }
-
account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
_account_name = talloc(mem_ctx, struct lsa_String);
- NTSTATUS_TALLOC_CHECK(_account_name);
+ NT_STATUS_HAVE_NO_MEMORY(_account_name);
_account_name->string = account_name;
if (r->in.authority_name) {
_authority_name = talloc(mem_ctx, struct lsa_StringPointer);
- NTSTATUS_TALLOC_CHECK(_authority_name);
+ NT_STATUS_HAVE_NO_MEMORY(_authority_name);
_authority_name->string = talloc(mem_ctx, struct lsa_String);
- NTSTATUS_TALLOC_CHECK(_authority_name->string);
+ NT_STATUS_HAVE_NO_MEMORY(_authority_name->string);
_authority_name->string->string = authority_name;
}
/*
lsa_SetDomInfoPolicy
*/
-static NTSTATUS lsa_SetDomInfoPolicy(struct dcesrv_call_state *dce_call,
- TALLOC_CTX *mem_ctx,
- struct lsa_SetDomInfoPolicy *r)
+static NTSTATUS lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
+ TALLOC_CTX *mem_ctx,
+ struct lsa_SetDomainInformationPolicy *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
name = p + 1;
}
- ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", name);
+ ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", ldb_binary_encode_string(mem_ctx, name));
if (ret == 1) {
*sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
if (*sid == NULL) {
TALLOC_CTX *mem_ctx,
struct lsa_LookupNames3 *r)
{
- struct lsa_policy_state *state;
- struct dcesrv_handle *h;
+ struct lsa_policy_state *policy_state;
+ struct dcesrv_handle *policy_handle;
int i;
NTSTATUS status = NT_STATUS_OK;
- r->out.domains = NULL;
+ DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
- DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
+ policy_state = policy_handle->data;
- state = h->data;
+ r->out.domains = NULL;
r->out.domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
if (r->out.domains == NULL) {
r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
r->out.sids->sids[i].unknown = 0;
- status2 = lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
+ status2 = lsa_lookup_name(policy_state, mem_ctx, name, &sid, &atype);
if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
status = STATUS_SOME_UNMAPPED;
continue;
continue;
}
- status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
+ status2 = lsa_authority_list(policy_state, mem_ctx, sid, r->out.domains, &sid_index);
if (!NT_STATUS_IS_OK(status2)) {
return status2;
}
return status;
}
+/*
+ lsa_LookupNames4
+
+ Identical to LookupNames3, but doesn't take a policy handle
+
+*/
+static NTSTATUS lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct lsa_LookupNames4 *r)
+{
+ struct lsa_LookupNames3 r2;
+ struct lsa_OpenPolicy2 pol;
+ NTSTATUS status;
+ struct dcesrv_handle *h;
+
+ /* No policy handle on the wire, so make one up here */
+ r2.in.handle = talloc(mem_ctx, struct policy_handle);
+ if (!r2.in.handle) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ pol.out.handle = r2.in.handle;
+ pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+ pol.in.attr = NULL;
+ pol.in.system_name = NULL;
+ status = lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* ensure this handle goes away at the end of this call */
+ DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
+ talloc_steal(mem_ctx, h);
+
+ r2.in.num_names = r->in.num_names;
+ r2.in.names = r->in.names;
+ r2.in.sids = r->in.sids;
+ r2.in.count = r->in.count;
+ r2.in.unknown1 = r->in.unknown1;
+ r2.in.unknown2 = r->in.unknown2;
+ r2.out.domains = r->out.domains;
+ r2.out.sids = r->out.sids;
+ r2.out.count = r->out.count;
+
+ status = lsa_LookupNames3(dce_call, mem_ctx, &r2);
+ if (dce_call->fault_code != 0) {
+ return status;
+ }
+
+ r->out.domains = r2.out.domains;
+ r->out.sids = r2.out.sids;
+ r->out.count = r2.out.count;
+ return status;
+}
+
/*
lsa_LookupNames2
*/
}
-/*
- lsa_LSARLOOKUPNAMES4
-*/
-static NTSTATUS lsa_LSARLOOKUPNAMES4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
- struct lsa_LSARLOOKUPNAMES4 *r)
-{
- DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
-}
-
/*
lsa_LSAROPENPOLICYSCE
/* include the generated boilerplate */
#include "librpc/gen_ndr/ndr_lsa_s.c"
+
+
+
+/*****************************************
+NOTE! The remaining calls below were
+removed in w2k3, so the DCESRV_FAULT()
+replies are the correct implementation. Do
+not try and fill these in with anything else
+******************************************/
+
+/*
+ dssetup_DsRoleDnsNameToFlatName
+*/
+static WERROR dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dssetup_DsRoleDnsNameToFlatName *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dssetup_DsRoleDcAsDc
+*/
+static WERROR dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dssetup_DsRoleDcAsDc *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dssetup_DsRoleDcAsReplica
+*/
+static WERROR dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dssetup_DsRoleDcAsReplica *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dssetup_DsRoleDemoteDc
+*/
+static WERROR dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dssetup_DsRoleDemoteDc *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dssetup_DsRoleGetDcOperationProgress
+*/
+static WERROR dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dssetup_DsRoleGetDcOperationProgress *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dssetup_DsRoleGetDcOperationResults
+*/
+static WERROR dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dssetup_DsRoleGetDcOperationResults *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dssetup_DsRoleCancel
+*/
+static WERROR dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dssetup_DsRoleCancel *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dssetup_DsRoleServerSaveStateForUpgrade
+*/
+static WERROR dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dssetup_DsRoleServerSaveStateForUpgrade *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dssetup_DsRoleUpgradeDownlevelServer
+*/
+static WERROR dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dssetup_DsRoleUpgradeDownlevelServer *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/*
+ dssetup_DsRoleAbortDownlevelServerUpgrade
+*/
+static WERROR dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
+ struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
+{
+ DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+}
+
+
+/* include the generated boilerplate */
+#include "librpc/gen_ndr/ndr_dssetup_s.c"
+
+NTSTATUS dcerpc_server_lsa_init(void)
+{
+ NTSTATUS ret;
+
+ ret = dcerpc_server_dssetup_init();
+ if (!NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ ret = dcerpc_server_lsarpc_init();
+ if (!NT_STATUS_IS_OK(ret)) {
+ return ret;
+ }
+ return ret;
+}