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 \
32 "(D;;0x00000800;;;AN)" \
35 "(A;;0x00000801;;;AN)" \
36 "(A;;0x00001000;;;LS)" \
37 "(A;;0x00001000;;;NS)" \
38 "(A;;0x00001000;;;IS)" \
39 "(A;;0x00000801;;;S-1-15-2-1)"
41 static const struct generic_mapping dcesrv_lsa_policy_mapping = {
48 NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call,
50 uint32_t access_desired,
51 struct lsa_policy_state **_state)
53 struct auth_session_info *session_info = dce_call->conn->auth_state.session_info;
54 enum security_user_level security_level;
55 struct lsa_policy_state *state;
56 struct ldb_result *dom_res;
57 const char *dom_attrs[] = {
67 state = talloc_zero(mem_ctx, struct lsa_policy_state);
69 return NT_STATUS_NO_MEMORY;
72 /* make sure the sam database is accessible */
73 state->sam_ldb = samdb_connect(state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info, 0);
74 if (state->sam_ldb == NULL) {
75 return NT_STATUS_INVALID_SYSTEM_SERVICE;
78 /* and the privilege database */
79 state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
80 if (state->pdb == NULL) {
81 return NT_STATUS_INVALID_SYSTEM_SERVICE;
84 /* work out the domain_dn - useful for so many calls its worth
86 state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
87 if (!state->domain_dn) {
88 return NT_STATUS_NO_MEMORY;
91 /* work out the forest root_dn - useful for so many calls its worth
93 state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
94 if (!state->forest_dn) {
95 return NT_STATUS_NO_MEMORY;
98 ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
99 state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
100 if (ret != LDB_SUCCESS) {
101 return NT_STATUS_INVALID_SYSTEM_SERVICE;
103 if (dom_res->count != 1) {
104 return NT_STATUS_NO_SUCH_DOMAIN;
107 state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
108 if (!state->domain_sid) {
109 return NT_STATUS_NO_SUCH_DOMAIN;
112 state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
114 state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
116 talloc_free(dom_res);
118 state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
120 state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
121 if (!state->domain_dns) {
122 return NT_STATUS_NO_SUCH_DOMAIN;
124 p = strchr(state->domain_dns, '/');
129 state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
130 if (!state->forest_dns) {
131 return NT_STATUS_NO_SUCH_DOMAIN;
133 p = strchr(state->forest_dns, '/');
138 /* work out the builtin_dn - useful for so many calls its worth
140 state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
141 if (!state->builtin_dn) {
142 return NT_STATUS_NO_SUCH_DOMAIN;
145 /* work out the system_dn - useful for so many calls its worth
147 state->system_dn = samdb_search_dn(state->sam_ldb, state,
148 state->domain_dn, "(&(objectClass=container)(cn=System))");
149 if (!state->system_dn) {
150 return NT_STATUS_NO_SUCH_DOMAIN;
153 state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
154 if (!state->builtin_sid) {
155 return NT_STATUS_NO_SUCH_DOMAIN;
158 state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
159 if (!state->nt_authority_sid) {
160 return NT_STATUS_NO_SUCH_DOMAIN;
163 state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
164 if (!state->creator_owner_domain_sid) {
165 return NT_STATUS_NO_SUCH_DOMAIN;
168 state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
169 if (!state->world_domain_sid) {
170 return NT_STATUS_NO_SUCH_DOMAIN;
173 state->sd = sddl_decode(state, DCESRV_LSA_POLICY_SD_SDDL,
175 if (state->sd == NULL) {
176 return NT_STATUS_NO_MEMORY;
178 state->sd->dacl->revision = SECURITY_ACL_REVISION_NT4;
180 se_map_generic(&access_desired, &dcesrv_lsa_policy_mapping);
181 security_acl_map_generic(state->sd->dacl, &dcesrv_lsa_policy_mapping);
183 security_level = security_session_user_level(session_info, NULL);
184 if (security_level >= SECURITY_SYSTEM) {
186 * The security descriptor doesn't allow system,
187 * but we want to allow system via ncalrpc as root.
189 state->access_mask = access_desired;
190 if (state->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
191 state->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
192 state->access_mask |= LSA_POLICY_ALL_ACCESS;
197 status = se_access_check(state->sd,
198 session_info->security_token,
200 &state->access_mask);
201 if (!NT_STATUS_IS_OK(status)) {
202 DEBUG(2,("%s: access desired[0x%08X] rejected[0x%08X] - %s\n",
204 (unsigned)access_desired,
205 (unsigned)state->access_mask,
211 DEBUG(10,("%s: access desired[0x%08X] granted[0x%08X] - success.\n",
213 (unsigned)access_desired,
214 (unsigned)state->access_mask));
224 NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
225 struct lsa_OpenPolicy2 *r)
227 enum dcerpc_transport_t transport =
228 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
230 struct lsa_policy_state *state;
231 struct dcesrv_handle *handle;
233 if (transport != NCACN_NP && transport != NCALRPC) {
234 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
237 ZERO_STRUCTP(r->out.handle);
239 if (r->in.attr != NULL &&
240 r->in.attr->root_dir != NULL) {
241 /* MS-LSAD 3.1.4.4.1 */
242 return NT_STATUS_INVALID_PARAMETER;
245 status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
248 if (!NT_STATUS_IS_OK(status)) {
252 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY);
254 return NT_STATUS_NO_MEMORY;
257 handle->data = talloc_steal(handle, state);
259 state->handle = handle;
260 *r->out.handle = handle->wire_handle;
262 /* note that we have completely ignored the attr element of
263 the OpenPolicy. As far as I can tell, this is what w2k3
271 a wrapper around lsa_OpenPolicy2
273 NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
274 struct lsa_OpenPolicy *r)
276 enum dcerpc_transport_t transport =
277 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
278 struct lsa_OpenPolicy2 r2;
280 if (transport != NCACN_NP && transport != NCALRPC) {
281 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
284 r2.in.system_name = NULL;
285 r2.in.attr = r->in.attr;
286 r2.in.access_mask = r->in.access_mask;
287 r2.out.handle = r->out.handle;
289 return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);