s4-rpc_server/lsa: Use samdb_system_container_dn() in dcesrv_lsa_get_policy_state()
[Samba.git] / source4 / rpc_server / lsa / lsa_init.c
blob1065cc33f4da4f2e1c31f709e9f9c5290879619d
1 /*
2 Unix SMB/CIFS implementation.
4 endpoint server for the lsarpc pipe
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "rpc_server/lsa/lsa.h"
26 * This matches a Windows 2012R2 dc in
27 * a domain with function level 2012R2.
29 #define DCESRV_LSA_POLICY_SD_SDDL \
30 "O:BAG:SY" \
31 "D:" \
32 "(D;;0x00000800;;;AN)" \
33 "(A;;0x000f1fff;;;BA)" \
34 "(A;;0x00020801;;;WD)" \
35 "(A;;0x00000801;;;AN)" \
36 "(A;;0x00001000;;;LS)" \
37 "(A;;0x00001000;;;NS)" \
38 "(A;;0x00001000;;;S-1-5-17)" \
39 "(A;;0x00000801;;;AC)" \
40 "(A;;0x00000801;;;S-1-15-2-2)"
42 static const struct generic_mapping dcesrv_lsa_policy_mapping = {
43 LSA_POLICY_READ,
44 LSA_POLICY_WRITE,
45 LSA_POLICY_EXECUTE,
46 LSA_POLICY_ALL_ACCESS
49 NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call,
50 TALLOC_CTX *mem_ctx,
51 uint32_t access_desired,
52 struct lsa_policy_state **_state)
54 struct auth_session_info *session_info =
55 dcesrv_call_session_info(dce_call);
56 enum security_user_level security_level;
57 struct lsa_policy_state *state;
58 struct ldb_result *dom_res;
59 const char *dom_attrs[] = {
60 "objectSid",
61 "objectGUID",
62 "nTMixedDomain",
63 "fSMORoleOwner",
64 NULL
66 char *p;
67 int ret;
69 state = talloc_zero(mem_ctx, struct lsa_policy_state);
70 if (!state) {
71 return NT_STATUS_NO_MEMORY;
74 /* make sure the sam database is accessible */
75 state->sam_ldb = dcesrv_samdb_connect_as_user(state, dce_call);
76 if (state->sam_ldb == NULL) {
77 return NT_STATUS_INVALID_SYSTEM_SERVICE;
80 /* and the privilege database */
81 state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
82 if (state->pdb == NULL) {
83 return NT_STATUS_INVALID_SYSTEM_SERVICE;
86 /* work out the domain_dn - useful for so many calls its worth
87 fetching here */
88 state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
89 if (!state->domain_dn) {
90 return NT_STATUS_NO_MEMORY;
93 /* work out the forest root_dn - useful for so many calls its worth
94 fetching here */
95 state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
96 if (!state->forest_dn) {
97 return NT_STATUS_NO_MEMORY;
100 ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
101 state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
102 if (ret != LDB_SUCCESS) {
103 return NT_STATUS_INVALID_SYSTEM_SERVICE;
105 if (dom_res->count != 1) {
106 return NT_STATUS_NO_SUCH_DOMAIN;
109 state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
110 if (!state->domain_sid) {
111 return NT_STATUS_NO_SUCH_DOMAIN;
114 state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
116 state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
118 talloc_free(dom_res);
120 state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
122 state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
123 if (!state->domain_dns) {
124 return NT_STATUS_NO_SUCH_DOMAIN;
126 p = strchr(state->domain_dns, '/');
127 if (p) {
128 *p = '\0';
131 state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
132 if (!state->forest_dns) {
133 return NT_STATUS_NO_SUCH_DOMAIN;
135 p = strchr(state->forest_dns, '/');
136 if (p) {
137 *p = '\0';
140 /* work out the builtin_dn - useful for so many calls its worth
141 fetching here */
142 state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
143 if (!state->builtin_dn) {
144 return NT_STATUS_NO_SUCH_DOMAIN;
147 /* work out the system_dn - useful for so many calls its worth
148 fetching here */
149 state->system_dn = samdb_system_container_dn(state->sam_ldb, state);
150 if (state->system_dn == NULL) {
151 return NT_STATUS_NO_MEMORY;
154 state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
155 if (!state->builtin_sid) {
156 return NT_STATUS_NO_SUCH_DOMAIN;
159 state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
160 if (!state->nt_authority_sid) {
161 return NT_STATUS_NO_SUCH_DOMAIN;
164 state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
165 if (!state->creator_owner_domain_sid) {
166 return NT_STATUS_NO_SUCH_DOMAIN;
169 state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
170 if (!state->world_domain_sid) {
171 return NT_STATUS_NO_SUCH_DOMAIN;
174 state->sd = sddl_decode(state, DCESRV_LSA_POLICY_SD_SDDL,
175 state->domain_sid);
176 if (state->sd == NULL) {
177 return NT_STATUS_NO_MEMORY;
179 state->sd->dacl->revision = SECURITY_ACL_REVISION_NT4;
181 se_map_generic(&access_desired, &dcesrv_lsa_policy_mapping);
182 security_acl_map_generic(state->sd->dacl, &dcesrv_lsa_policy_mapping);
184 security_level = security_session_user_level(session_info, NULL);
185 if (security_level >= SECURITY_SYSTEM) {
187 * The security descriptor doesn't allow system,
188 * but we want to allow system via ncalrpc as root.
190 state->access_mask = access_desired;
191 if (state->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
192 state->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
193 state->access_mask |= LSA_POLICY_ALL_ACCESS;
195 } else {
196 NTSTATUS status;
198 status = se_access_check(state->sd,
199 session_info->security_token,
200 access_desired,
201 &state->access_mask);
202 if (!NT_STATUS_IS_OK(status)) {
203 DEBUG(2,("%s: access desired[0x%08X] rejected[0x%08X] - %s\n",
204 __func__,
205 (unsigned)access_desired,
206 (unsigned)state->access_mask,
207 nt_errstr(status)));
208 return status;
212 DEBUG(10,("%s: access desired[0x%08X] granted[0x%08X] - success.\n",
213 __func__,
214 (unsigned)access_desired,
215 (unsigned)state->access_mask));
217 *_state = state;
219 return NT_STATUS_OK;
223 lsa_OpenPolicy2
225 NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
226 struct lsa_OpenPolicy2 *r)
228 enum dcerpc_transport_t transport =
229 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
230 NTSTATUS status;
231 struct lsa_policy_state *state;
232 struct dcesrv_handle *handle;
234 if (transport != NCACN_NP && transport != NCALRPC) {
235 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
238 ZERO_STRUCTP(r->out.handle);
240 if (r->in.attr != NULL &&
241 r->in.attr->root_dir != NULL) {
242 /* MS-LSAD 3.1.4.4.1 */
243 return NT_STATUS_INVALID_PARAMETER;
246 status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
247 r->in.access_mask,
248 &state);
249 if (!NT_STATUS_IS_OK(status)) {
250 return status;
253 handle = dcesrv_handle_create(dce_call, LSA_HANDLE_POLICY);
254 if (!handle) {
255 return NT_STATUS_NO_MEMORY;
258 handle->data = talloc_steal(handle, state);
260 state->handle = handle;
261 *r->out.handle = handle->wire_handle;
263 /* note that we have completely ignored the attr element of
264 the OpenPolicy. As far as I can tell, this is what w2k3
265 does */
267 return NT_STATUS_OK;
271 lsa_OpenPolicy
272 a wrapper around lsa_OpenPolicy2
274 NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
275 struct lsa_OpenPolicy *r)
277 enum dcerpc_transport_t transport =
278 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
279 struct lsa_OpenPolicy2 r2;
281 if (transport != NCACN_NP && transport != NCALRPC) {
282 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
285 r2.in.system_name = NULL;
286 r2.in.attr = r->in.attr;
287 r2.in.access_mask = r->in.access_mask;
288 r2.out.handle = r->out.handle;
290 return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);