/* This is the implementation of the lsa server code. */
#include "includes.h"
+#include "../librpc/gen_ndr/srv_lsa.h"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_SRV
struct lsa_info {
DOM_SID sid;
+ const char *name;
uint32 access;
enum lsa_handle_type type;
+ struct security_descriptor *sd;
};
const struct generic_mapping lsa_account_mapping = {
LSA_POLICY_ALL_ACCESS
};
+const struct generic_mapping lsa_secret_mapping = {
+ LSA_SECRET_READ,
+ LSA_SECRET_WRITE,
+ LSA_SECRET_EXECUTE,
+ LSA_SECRET_ALL_ACCESS
+};
+
+const struct generic_mapping lsa_trusted_domain_mapping = {
+ LSA_TRUSTED_DOMAIN_READ,
+ LSA_TRUSTED_DOMAIN_WRITE,
+ LSA_TRUSTED_DOMAIN_EXECUTE,
+ LSA_TRUSTED_DOMAIN_ALL_ACCESS
+};
+
/***************************************************************************
init_lsa_ref_domain_list - adds a domain if it's not already in, returns the index.
***************************************************************************/
/* Split name into domain and user component */
- full_name = name[i].string;
- if (full_name == NULL) {
- return NT_STATUS_NO_MEMORY;
+ /* follow w2k8 behavior and return the builtin domain when no
+ * input has been passed in */
+
+ if (name[i].string) {
+ full_name = name[i].string;
+ } else {
+ full_name = "BUILTIN";
}
DEBUG(5, ("lookup_lsa_rids: looking up name %s\n", full_name));
dom_idx = -1;
if (type != SID_NAME_UNKNOWN) {
- sid_split_rid(&sid, &rid);
+ if (type == SID_NAME_DOMAIN) {
+ rid = (uint32_t)-1;
+ } else {
+ sid_split_rid(&sid, &rid);
+ }
dom_idx = init_lsa_ref_domain_list(mem_ctx, ref, domain, &sid);
mapped_count++;
}
}
status = access_check_object(psd, p->server_info->ptok,
- NULL, 0, des_access,
- &acc_granted, "_lsa_OpenPolicy2" );
-
+ NULL, 0, des_access,
+ &acc_granted, "_lsa_OpenPolicy2" );
if (!NT_STATUS_IS_OK(status)) {
return status;
}
struct lsa_EnumTrustDom *r)
{
struct lsa_info *info;
- uint32 next_idx;
+ uint32_t count;
struct trustdom_info **domains;
- struct lsa_DomainInfo *lsa_domains = NULL;
+ struct lsa_DomainInfo *entries;
int i;
-
- /*
- * preferred length is set to 5 as a "our" preferred length
- * nt sets this parameter to 2
- * update (20.08.2002): it's not preferred length, but preferred size!
- * it needs further investigation how to optimally choose this value
- */
- uint32 max_num_domains =
- r->in.max_size < 5 ? r->in.max_size : 10;
- uint32 num_domains;
NTSTATUS nt_status;
- uint32 num_thistime;
if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&info))
return NT_STATUS_INVALID_HANDLE;
return NT_STATUS_ACCESS_DENIED;
become_root();
- nt_status = pdb_enum_trusteddoms(p->mem_ctx, &num_domains, &domains);
+ nt_status = pdb_enum_trusteddoms(p->mem_ctx, &count, &domains);
unbecome_root();
if (!NT_STATUS_IS_OK(nt_status)) {
return nt_status;
}
- if (*r->in.resume_handle < num_domains) {
- num_thistime = MIN(num_domains, max_num_domains);
-
- nt_status = STATUS_MORE_ENTRIES;
+ entries = TALLOC_ZERO_ARRAY(p->mem_ctx, struct lsa_DomainInfo, count);
+ if (!entries) {
+ return NT_STATUS_NO_MEMORY;
+ }
- if (*r->in.resume_handle + num_thistime > num_domains) {
- num_thistime = num_domains - *r->in.resume_handle;
- nt_status = NT_STATUS_OK;
- }
+ for (i=0; i<count; i++) {
+ init_lsa_StringLarge(&entries[i].name, domains[i]->name);
+ entries[i].sid = &domains[i]->sid;
+ }
- next_idx = *r->in.resume_handle + num_thistime;
- } else {
- num_thistime = 0;
- next_idx = 0xffffffff;
- nt_status = NT_STATUS_NO_MORE_ENTRIES;
+ if (*r->in.resume_handle >= count) {
+ *r->out.resume_handle = -1;
+ TALLOC_FREE(entries);
+ return NT_STATUS_NO_MORE_ENTRIES;
}
- /* set up the lsa_enum_trust_dom response */
+ /* 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_domains = TALLOC_ZERO_ARRAY(p->mem_ctx, struct lsa_DomainInfo,
- num_thistime);
- if (!lsa_domains) {
- return NT_STATUS_NO_MEMORY;
- }
+ r->out.domains->domains = entries + *r->in.resume_handle;
- for (i=0; i<num_thistime; i++) {
- init_lsa_StringLarge(&lsa_domains[i].name, domains[i]->name);
- lsa_domains[i].sid = &domains[i]->sid;
+ 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;
}
- *r->out.resume_handle = next_idx;
- r->out.domains->count = num_thistime;
- r->out.domains->domains = lsa_domains;
+ /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
+ * always be larger than the previous input resume handle, in
+ * particular when hitting the last query it is vital to set the
+ * resume handle correctly to avoid infinite client loops, as
+ * seen e.g. with Windows XP SP3 when resume handle is 0 and
+ * status is NT_STATUS_OK - gd */
- return nt_status;
+ *r->out.resume_handle = (uint32_t)-1;
+
+ return NT_STATUS_OK;
}
#define LSA_AUDIT_NUM_CATEGORIES_NT4 7
}
switch (r->in.level) {
+ /* according to MS-LSAD 3.1.4.4.3 */
+ case LSA_POLICY_INFO_MOD:
+ case LSA_POLICY_INFO_AUDIT_FULL_SET:
+ case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
+ return NT_STATUS_INVALID_PARAMETER;
+ case LSA_POLICY_INFO_AUDIT_LOG:
+ info->audit_log.percent_full = 0;
+ info->audit_log.maximum_log_size = 0;
+ info->audit_log.retention_time = 0;
+ info->audit_log.shutdown_in_progress = 0;
+ info->audit_log.time_to_shutdown = 0;
+ info->audit_log.next_audit_record = 0;
+ status = NT_STATUS_OK;
+ break;
+ case LSA_POLICY_INFO_PD:
+ info->pd.name.string = NULL;
+ status = NT_STATUS_OK;
+ break;
+ case LSA_POLICY_INFO_REPLICA:
+ info->replica.source.string = NULL;
+ info->replica.account.string = NULL;
+ status = NT_STATUS_OK;
+ break;
+ case LSA_POLICY_INFO_QUOTA:
+ info->quota.paged_pool = 0;
+ info->quota.non_paged_pool = 0;
+ info->quota.min_wss = 0;
+ info->quota.max_wss = 0;
+ info->quota.pagefile = 0;
+ info->quota.unknown = 0;
+ status = NT_STATUS_OK;
+ break;
case LSA_POLICY_INFO_AUDIT_EVENTS:
{
/***************************************************************************
***************************************************************************/
-static int lsa_lookup_level_to_flags(uint16 level)
+static int lsa_lookup_level_to_flags(enum lsa_LookupNamesLevel level)
{
int flags;
switch (level) {
- case 1:
+ case LSA_LOOKUP_NAMES_ALL: /* 1 */
flags = LOOKUP_NAME_ALL;
break;
- case 2:
+ case LSA_LOOKUP_NAMES_DOMAINS_ONLY: /* 2 */
flags = LOOKUP_NAME_DOMAIN|LOOKUP_NAME_REMOTE|LOOKUP_NAME_ISOLATED;
break;
- case 3:
+ case LSA_LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY: /* 3 */
flags = LOOKUP_NAME_DOMAIN|LOOKUP_NAME_ISOLATED;
break;
- case 4:
- case 5:
- case 6:
+ case LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY: /* 4 */
+ case LSA_LOOKUP_NAMES_FOREST_TRUSTS_ONLY: /* 5 */
+ case LSA_LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2: /* 6 */
+ case LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC: /* 7 */
default:
flags = LOOKUP_NAME_NONE;
break;
struct lsa_info *handle;
struct lsa_info *info;
uint32_t acc_granted;
+ uint32_t owner_access = (LSA_ACCOUNT_ALL_ACCESS &
+ ~(LSA_ACCOUNT_ADJUST_PRIVILEGES|
+ LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|
+ STD_RIGHT_DELETE_ACCESS));
struct security_descriptor *psd;
size_t sd_size;
return NT_STATUS_ACCESS_DENIED;
}
+ /* Work out max allowed. */
+ map_max_allowed_access(p->server_info->ptok,
+ &p->server_info->utok,
+ &r->in.access_mask);
+
/* map the generic bits to the lsa policy ones */
se_map_generic(&r->in.access_mask, &lsa_account_mapping);
status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
&lsa_account_mapping,
- r->in.sid, LSA_POLICY_ALL_ACCESS);
+ r->in.sid, owner_access);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = access_check_object(psd, p->server_info->ptok,
- NULL, 0, r->in.access_mask,
- &acc_granted, "_lsa_CreateAccount");
+ status = access_check_object(psd, p->server_info->ptok,
+ NULL, 0, r->in.access_mask,
+ &acc_granted, "_lsa_CreateAccount");
if (!NT_STATUS_IS_OK(status)) {
return status;
}
size_t sd_size;
uint32_t des_access = r->in.access_mask;
uint32_t acc_granted;
+ uint32_t owner_access = (LSA_ACCOUNT_ALL_ACCESS &
+ ~(LSA_ACCOUNT_ADJUST_PRIVILEGES|
+ LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|
+ STD_RIGHT_DELETE_ACCESS));
NTSTATUS status;
/* find the connection policy handle. */
/* get the generic lsa account SD until we store it */
status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
&lsa_account_mapping,
- r->in.sid, LSA_ACCOUNT_ALL_ACCESS);
+ r->in.sid, owner_access);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
status = access_check_object(psd, p->server_info->ptok,
- NULL, 0, des_access,
- &acc_granted, "_lsa_OpenAccount" );
-
+ NULL, 0, des_access,
+ &acc_granted, "_lsa_OpenAccount" );
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (!find_policy_by_hnd(p, r->in.handle, (void **)(void *)&handle))
return NT_STATUS_INVALID_HANDLE;
- if (handle->type == LSA_HANDLE_POLICY_TYPE) {
+ switch (handle->type) {
+ case LSA_HANDLE_POLICY_TYPE:
status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
&lsa_policy_mapping, NULL, 0);
- } else if (handle->type == LSA_HANDLE_ACCOUNT_TYPE) {
+ break;
+ case LSA_HANDLE_ACCOUNT_TYPE:
status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
&lsa_account_mapping,
&handle->sid, LSA_ACCOUNT_ALL_ACCESS);
- } else {
+ break;
+ default:
status = NT_STATUS_INVALID_HANDLE;
+ break;
}
if (!NT_STATUS_IS_OK(status)) {
return NT_STATUS_INVALID_HANDLE;
}
- /* get the generic lsa account SD for this SID until we store it */
+ /* get the generic lsa account SD until we store it */
status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
&lsa_account_mapping,
- r->in.sid, LSA_ACCOUNT_ALL_ACCESS);
+ NULL, 0);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
* on the account sid. We don't check here so just use the latter. JRA.
*/
- status = access_check_object(psd, p->server_info->ptok,
- NULL, 0, LSA_ACCOUNT_ADJUST_PRIVILEGES|LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|LSA_ACCOUNT_VIEW,
- &acc_granted, "_lsa_AddAccountRights" );
-
+ status = access_check_object(psd, p->server_info->ptok,
+ NULL, 0,
+ LSA_ACCOUNT_ADJUST_PRIVILEGES|LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|LSA_ACCOUNT_VIEW,
+ &acc_granted, "_lsa_AddAccountRights" );
if (!NT_STATUS_IS_OK(status)) {
return status;
}
return NT_STATUS_INVALID_HANDLE;
}
- /* get the generic lsa account SD for this SID until we store it */
+ /* get the generic lsa account SD until we store it */
status = make_lsa_object_sd(p->mem_ctx, &psd, &sd_size,
&lsa_account_mapping,
- r->in.sid, LSA_ACCOUNT_ALL_ACCESS);
+ NULL, 0);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
* and DELETE on the account sid.
*/
- status = access_check_object(psd, p->server_info->ptok,
- NULL, 0, LSA_ACCOUNT_ADJUST_PRIVILEGES|LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|
- LSA_ACCOUNT_VIEW|STD_RIGHT_DELETE_ACCESS,
- &acc_granted, "_lsa_AddAccountRights" );
-
+ status = access_check_object(psd, p->server_info->ptok,
+ NULL, 0,
+ LSA_ACCOUNT_ADJUST_PRIVILEGES|LSA_ACCOUNT_ADJUST_SYSTEM_ACCESS|
+ LSA_ACCOUNT_VIEW|STD_RIGHT_DELETE_ACCESS,
+ &acc_granted, "_lsa_RemoveAccountRights");
if (!NT_STATUS_IS_OK(status)) {
return status;
}