* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- * Copyright (C) Paul Ashton 1997.
- * Copyright (C) Jeremy Allison 2001.
+ * Copyright (C) Paul Ashton 1997,
+ * Copyright (C) Jeremy Allison 2001,
+ * Copyright (C) Rafal Szczesniak 2002,
+ * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002.
*
* 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
#include "includes.h"
-extern DOM_SID global_sam_sid;
-extern fstring global_myworkgroup;
-extern pstring global_myname;
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
extern PRIVS privs[];
struct lsa_info {
- DOM_SID sid;
- uint32 access;
+ DOM_SID sid;
+ uint32 access;
};
struct generic_mapping lsa_generic_mapping = {
Init dom_query
***************************************************************************/
-static void init_dom_query(DOM_QUERY *d_q, char *dom_name, DOM_SID *dom_sid)
+static void init_dom_query(DOM_QUERY *d_q, const char *dom_name, DOM_SID *dom_sid)
{
int domlen = (dom_name != NULL) ? strlen(dom_name) : 0;
DEBUG(5, ("init_lsa_rid2s: %s\n", status ? "found" :
"not found"));
- if (status) {
+ if (status && name_type != SID_NAME_UNKNOWN) {
sid_split_rid(&sid, &rid);
dom_idx = init_dom_ref(ref, dom_name, &sid);
(*mapped_count)++;
}
}
+ become_root(); /* Need root to get to passdb to for local sids */
+
for (i = 0; i < num_entries; i++) {
BOOL status = False;
DOM_SID find_sid = sid[i].sid;
if (!status) {
sid_name_use = SID_NAME_UNKNOWN;
+ } else {
+ (*mapped_count)++;
}
/* Store domain sid in ref array */
DEBUG(10,("init_lsa_trans_names: added user '%s\\%s' to "
"referenced list.\n", dom_name, name ));
- (*mapped_count)++;
-
init_lsa_trans_name(&trn->name[total], &trn->uni_name[total],
sid_name_use, name, dom_idx);
total++;
}
+ unbecome_root();
+
trn->num_entries = total;
trn->ptr_trans_names = 1;
trn->num_entries2 = total;
init_sec_access(&mask, POLICY_EXECUTE);
init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
- sid_copy(&adm_sid, &global_sam_sid);
+ sid_copy(&adm_sid, get_global_sam_sid());
sid_append_rid(&adm_sid, DOMAIN_GROUP_RID_ADMINS);
init_sec_access(&mask, POLICY_ALL_ACCESS);
init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
return NT_STATUS_OK;
}
+/***************************************************************************
+ Init_dns_dom_info.
+***************************************************************************/
+
+static void init_dns_dom_info(LSA_DNS_DOM_INFO *r_l, const char *nb_name,
+ const char *dns_name, const char *forest_name,
+ GUID *dom_guid, DOM_SID *dom_sid)
+{
+ if (nb_name && *nb_name) {
+ init_uni_hdr(&r_l->hdr_nb_dom_name, strlen(nb_name));
+ init_unistr2(&r_l->uni_nb_dom_name, nb_name,
+ strlen(nb_name));
+ r_l->hdr_nb_dom_name.uni_max_len += 2;
+ r_l->uni_nb_dom_name.uni_max_len += 1;
+ }
+
+ if (dns_name && *dns_name) {
+ init_uni_hdr(&r_l->hdr_dns_dom_name, strlen(dns_name));
+ init_unistr2(&r_l->uni_dns_dom_name, dns_name,
+ strlen(dns_name));
+ r_l->hdr_dns_dom_name.uni_max_len += 2;
+ r_l->uni_dns_dom_name.uni_max_len += 1;
+ }
+
+ if (forest_name && *forest_name) {
+ init_uni_hdr(&r_l->hdr_forest_name, strlen(forest_name));
+ init_unistr2(&r_l->uni_forest_name, forest_name,
+ strlen(forest_name));
+ r_l->hdr_forest_name.uni_max_len += 2;
+ r_l->uni_forest_name.uni_max_len += 1;
+ }
+
+ /* how do we init the guid ? probably should write an init fn */
+ if (dom_guid) {
+ memcpy(&r_l->dom_guid, dom_guid, sizeof(GUID));
+ }
+
+ if (dom_sid) {
+ r_l->ptr_dom_sid = 1;
+ init_dom_sid2(&r_l->dom_sid, dom_sid);
+ }
+}
+
/***************************************************************************
_lsa_open_policy2.
***************************************************************************/
/* get the generic lsa policy SD until we store it */
lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
- if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status))
- return status;
+ if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status)) {
+ if (geteuid() != 0) {
+ return status;
+ }
+ DEBUG(4,("ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+ acc_granted, des_access));
+ DEBUGADD(4,("but overwritten by euid == 0\n"));
+ acc_granted = des_access;
+ }
+
/* associate the domain SID with the (unique) handle. */
if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL)
return NT_STATUS_NO_MEMORY;
ZERO_STRUCTP(info);
- info->sid = global_sam_sid;
+ sid_copy(&info->sid,get_global_sam_sid());
info->access = acc_granted;
/* set up the LSA QUERY INFO response */
/* get the generic lsa policy SD until we store it */
lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size);
- if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status))
- return status;
+ if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status)) {
+ if (geteuid() != 0) {
+ return status;
+ }
+ DEBUG(4,("ACCESS should be DENIED (granted: %#010x; required: %#010x)\n",
+ acc_granted, des_access));
+ DEBUGADD(4,("but overwritten by euid == 0\n"));
+ acc_granted = des_access;
+ }
/* associate the domain SID with the (unique) handle. */
if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL)
return NT_STATUS_NO_MEMORY;
ZERO_STRUCTP(info);
- info->sid = global_sam_sid;
+ sid_copy(&info->sid,get_global_sam_sid());
info->access = acc_granted;
/* set up the LSA QUERY INFO response */
/***************************************************************************
_lsa_enum_trust_dom - this needs fixing to do more than return NULL ! JRA.
+ ufff, done :) mimir
***************************************************************************/
NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_ENUM_TRUST_DOM *r_u)
{
struct lsa_info *info;
- uint32 enum_context = 0;
- char *dom_name = NULL;
- DOM_SID *dom_sid = NULL;
+ uint32 enum_context = q_u->enum_context;
+
+ /*
+ * 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 = q_u->preferred_len < 5 ? q_u->preferred_len : 10;
+ TRUSTDOM **trust_doms;
+ uint32 num_domains;
+ NTSTATUS nt_status;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
if (!(info->access & POLICY_VIEW_LOCAL_INFORMATION))
return NT_STATUS_ACCESS_DENIED;
- /* set up the LSA QUERY INFO response */
- init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, dom_name, dom_sid,
- dom_name != NULL ? NT_STATUS_OK : NT_STATUS_NO_MORE_ENTRIES);
+ nt_status = secrets_get_trusted_domains(p->mem_ctx, (int *)&enum_context, max_num_domains, (int *)&num_domains, &trust_doms);
+
+ if (!NT_STATUS_IS_OK(nt_status) &&
+ !NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES) &&
+ !NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
+ return nt_status;
+ } else {
+ r_u->status = nt_status;
+ }
+
+ /* set up the lsa_enum_trust_dom response */
+ init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, max_num_domains, num_domains, trust_doms);
return r_u->status;
}
struct lsa_info *handle;
LSA_INFO_UNION *info = &r_u->dom;
DOM_SID domain_sid;
- char *name = NULL;
+ const char *name;
DOM_SID *sid = NULL;
r_u->status = NT_STATUS_OK;
switch (lp_server_role()) {
case ROLE_DOMAIN_PDC:
case ROLE_DOMAIN_BDC:
- name = global_myworkgroup;
- sid = &global_sam_sid;
+ name = get_global_sam_name();
+ sid = get_global_sam_sid();
break;
case ROLE_DOMAIN_MEMBER:
- name = global_myworkgroup;
+ name = lp_workgroup();
/* We need to return the Domain SID here. */
- if (secrets_fetch_domain_sid(global_myworkgroup,
- &domain_sid))
+ if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid))
sid = &domain_sid;
else
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
break;
case ROLE_STANDALONE:
- name = global_myworkgroup;
+ name = lp_workgroup();
sid = NULL;
break;
default:
return NT_STATUS_ACCESS_DENIED;
/* Request PolicyAccountDomainInformation. */
- switch (lp_server_role()) {
- case ROLE_DOMAIN_PDC:
- case ROLE_DOMAIN_BDC:
- name = global_myworkgroup;
- sid = &global_sam_sid;
- break;
- case ROLE_DOMAIN_MEMBER:
- name = global_myname;
- sid = &global_sam_sid;
- break;
- case ROLE_STANDALONE:
- name = global_myname;
- sid = &global_sam_sid;
- break;
- default:
- return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
- }
+ name = get_global_sam_name();
+ sid = get_global_sam_sid();
init_dom_query(&r_u->dom.id5, name, sid);
break;
case 0x06:
LSA_TRANS_NAME_ENUM *names = NULL;
uint32 mapped_count = 0;
+ if (num_entries > MAX_LOOKUP_SIDS) {
+ num_entries = MAX_LOOKUP_SIDS;
+ DEBUG(5,("_lsa_lookup_sids: truncating SID lookup list to %d\n", num_entries));
+ }
+
ref = (DOM_R_REF *)talloc_zero(p->mem_ctx, sizeof(DOM_R_REF));
names = (LSA_TRANS_NAME_ENUM *)talloc_zero(p->mem_ctx, sizeof(LSA_TRANS_NAME_ENUM));
- if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
- return NT_STATUS_INVALID_HANDLE;
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) {
+ r_u->status = NT_STATUS_INVALID_HANDLE;
+ goto done;
+ }
/* check if the user have enough rights */
- if (!(handle->access & POLICY_LOOKUP_NAMES))
- return NT_STATUS_ACCESS_DENIED;
-
+ if (!(handle->access & POLICY_LOOKUP_NAMES)) {
+ r_u->status = NT_STATUS_ACCESS_DENIED;
+ goto done;
+ }
if (!ref || !names)
return NT_STATUS_NO_MEMORY;
+done:
+
/* set up the LSA Lookup SIDs response */
init_lsa_trans_names(p->mem_ctx, ref, names, num_entries, sid, &mapped_count);
init_reply_lookup_sids(r_u, ref, names, mapped_count);
ref = (DOM_R_REF *)talloc_zero(p->mem_ctx, sizeof(DOM_R_REF));
rids = (DOM_RID2 *)talloc_zero(p->mem_ctx, sizeof(DOM_RID2)*num_entries);
- if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
- return NT_STATUS_INVALID_HANDLE;
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) {
+ r_u->status = NT_STATUS_INVALID_HANDLE;
+ goto done;
+ }
/* check if the user have enough rights */
- if (!(handle->access & POLICY_LOOKUP_NAMES))
- return NT_STATUS_ACCESS_DENIED;
+ if (!(handle->access & POLICY_LOOKUP_NAMES)) {
+ r_u->status = NT_STATUS_ACCESS_DENIED;
+ goto done;
+ }
if (!ref || !rids)
return NT_STATUS_NO_MEMORY;
+done:
+
/* set up the LSA Lookup RIDs response */
init_lsa_rid2s(ref, rids, num_entries, names, &mapped_count, p->endian);
init_reply_lookup_names(r_u, ref, num_entries, rids, mapped_count);
return NT_STATUS_ACCESS_DENIED;
/* get the list of mapped groups (domain, local, builtin) */
- if(!enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV))
+ if(!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED))
return NT_STATUS_OK;
if (q_u->enum_context >= num_entries)
{
struct lsa_info *info=NULL;
GROUP_MAP map;
- int i=0;
-
LUID_ATTR *set=NULL;
r_u->status = NT_STATUS_OK;
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!get_group_map_from_sid(info->sid, &map, MAPPING_WITH_PRIV))
+ if (!pdb_getgrsid(&map, info->sid))
return NT_STATUS_NO_SUCH_GROUP;
+#if 0 /* privileges currently not implemented! */
DEBUG(10,("_lsa_enum_privsaccount: %d privileges\n", map.priv_set.count));
if (map.priv_set.count!=0) {
init_lsa_r_enum_privsaccount(r_u, set, map.priv_set.count, 0);
free_privilege(&map.priv_set);
+#endif
+
+ init_lsa_r_enum_privsaccount(r_u, set, 0, 0);
return r_u->status;
}
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!get_group_map_from_sid(info->sid, &map, MAPPING_WITHOUT_PRIV))
+ if (!pdb_getgrsid(&map, info->sid))
return NT_STATUS_NO_SUCH_GROUP;
/*
they can be ORed together
*/
- r_u->access=map.systemaccount;
+ r_u->access = PR_LOG_ON_LOCALLY | PR_ACCESS_FROM_NETWORK;
return r_u->status;
}
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!get_group_map_from_sid(info->sid, &map, MAPPING_WITH_PRIV))
+ if (!pdb_getgrsid(&map, info->sid))
return NT_STATUS_NO_SUCH_GROUP;
- map.systemaccount=q_u->access;
-
- if(!add_mapping_entry(&map, TDB_REPLACE))
+ if(!pdb_update_group_mapping_entry(&map))
return NT_STATUS_NO_SUCH_GROUP;
- free_privilege(&map.priv_set);
-
return r_u->status;
}
NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u)
{
+#if 0
struct lsa_info *info=NULL;
GROUP_MAP map;
int i=0;
-
LUID_ATTR *luid_attr=NULL;
PRIVILEGE_SET *set=NULL;
+#endif
r_u->status = NT_STATUS_OK;
+#if 0 /* privileges are not implemented */
/* find the connection policy handle. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!get_group_map_from_sid(info->sid, &map, MAPPING_WITH_PRIV))
+ if (!pdb_getgrsid(&map, info->sid))
return NT_STATUS_NO_SUCH_GROUP;
set=&q_u->set;
add_privilege(&map.priv_set, *luid_attr);
}
- if(!add_mapping_entry(&map, TDB_REPLACE))
+ if(!pdb_update_group_mapping_entry(&map))
return NT_STATUS_NO_SUCH_GROUP;
free_privilege(&map.priv_set);
+#endif
return r_u->status;
}
NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEPRIVS *r_u)
{
+#if 0
struct lsa_info *info=NULL;
GROUP_MAP map;
int i=0;
-
LUID_ATTR *luid_attr=NULL;
PRIVILEGE_SET *set=NULL;
+#endif
r_u->status = NT_STATUS_OK;
+#if 0 /* privileges are not implemented */
/* find the connection policy handle. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!get_group_map_from_sid(info->sid, &map, MAPPING_WITH_PRIV))
+ if (!pdb_getgrsid(&map, info->sid))
return NT_STATUS_NO_SUCH_GROUP;
if (q_u->allrights!=0) {
remove_privilege(&map.priv_set, *luid_attr);
}
- if(!add_mapping_entry(&map, TDB_REPLACE))
+ if(!pdb_update_group_mapping_entry(&map))
return NT_STATUS_NO_SUCH_GROUP;
free_privilege(&map.priv_set);
-
+#endif
return r_u->status;
}
}
+NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_INFO2 *r_u)
+{
+ struct lsa_info *handle;
+ const char *nb_name;
+ char *dns_name = NULL;
+ char *forest_name = NULL;
+ DOM_SID *sid = NULL;
+ GUID guid;
+ fstring dnsdomname;
+
+ ZERO_STRUCT(guid);
+ r_u->status = NT_STATUS_OK;
+
+ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle))
+ return NT_STATUS_INVALID_HANDLE;
+
+ switch (q_u->info_class) {
+ case 0x0c:
+ /* check if the user have enough rights */
+ if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION))
+ return NT_STATUS_ACCESS_DENIED;
+
+ /* Request PolicyPrimaryDomainInformation. */
+ switch (lp_server_role()) {
+ case ROLE_DOMAIN_PDC:
+ case ROLE_DOMAIN_BDC:
+ nb_name = get_global_sam_name();
+ /* ugly temp hack for these next two */
+
+ /* This should be a 'netbios domain -> DNS domain' mapping */
+ dnsdomname[0] = '\0';
+ get_mydomname(dnsdomname);
+ strlower_m(dnsdomname);
+
+ dns_name = dnsdomname;
+ forest_name = dnsdomname;
+
+ sid = get_global_sam_sid();
+ secrets_fetch_domain_guid(lp_workgroup(), &guid);
+ break;
+ default:
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ }
+ init_dns_dom_info(&r_u->info.dns_dom_info, nb_name, dns_name,
+ forest_name,&guid,sid);
+ break;
+ default:
+ DEBUG(0,("_lsa_query_info2: unknown info level in Lsa Query: %d\n", q_u->info_class));
+ r_u->status = NT_STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ if (NT_STATUS_IS_OK(r_u->status)) {
+ r_u->ptr = 0x1;
+ r_u->info_class = q_u->info_class;
+ }
+
+ return r_u->status;
+}