1/* 2 Unix SMB/CIFS implementation. 3 4 endpoint server for the lsarpc pipe 5 6 Copyright (C) Andrew Tridgell 2004 7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007 8 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. 13 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. 18 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/>. 21*/ 22 23#include "rpc_server/lsa/lsa.h" 24 25NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 26 struct lsa_policy_state **_state) 27{ 28 struct lsa_policy_state *state; 29 struct ldb_result *dom_res; 30 const char *dom_attrs[] = { 31 "objectSid", 32 "objectGUID", 33 "nTMixedDomain", 34 "fSMORoleOwner", 35 NULL 36 }; 37 char *p; 38 int ret; 39 40 state = talloc(mem_ctx, struct lsa_policy_state); 41 if (!state) { 42 return NT_STATUS_NO_MEMORY; 43 } 44 45 /* make sure the sam database is accessible */ 46 state->sam_ldb = samdb_connect(state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info); 47 if (state->sam_ldb == NULL) { 48 return NT_STATUS_INVALID_SYSTEM_SERVICE; 49 } 50 51 /* work out the domain_dn - useful for so many calls its worth 52 fetching here */ 53 state->domain_dn = ldb_get_default_basedn(state->sam_ldb); 54 if (!state->domain_dn) { 55 return NT_STATUS_NO_MEMORY; 56 } 57 58 /* work out the forest root_dn - useful for so many calls its worth 59 fetching here */ 60 state->forest_dn = samdb_root_dn(state->sam_ldb); 61 if (!state->forest_dn) { 62 return NT_STATUS_NO_MEMORY; 63 } 64 65 ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res, 66 state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL); 67 if (ret != LDB_SUCCESS) { 68 return NT_STATUS_INVALID_SYSTEM_SERVICE; 69 } 70 if (dom_res->count != 1) { 71 return NT_STATUS_NO_SUCH_DOMAIN; 72 } 73 74 state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid"); 75 if (!state->domain_sid) { 76 return NT_STATUS_NO_SUCH_DOMAIN; 77 } 78 79 state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID"); 80 81 state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0); 82 83 talloc_free(dom_res); 84 85 state->domain_name = lp_sam_name(dce_call->conn->dce_ctx->lp_ctx); 86 87 state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn); 88 if (!state->domain_dns) { 89 return NT_STATUS_NO_SUCH_DOMAIN; 90 } 91 p = strchr(state->domain_dns, '/'); 92 if (p) { 93 *p = '\0'; 94 } 95 96 state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn); 97 if (!state->forest_dns) { 98 return NT_STATUS_NO_SUCH_DOMAIN; 99 } 100 p = strchr(state->forest_dns, '/'); 101 if (p) { 102 *p = '\0'; 103 } 104 105 /* work out the builtin_dn - useful for so many calls its worth 106 fetching here */ 107 state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)"); 108 if (!state->builtin_dn) { 109 return NT_STATUS_NO_SUCH_DOMAIN; 110 } 111 112 /* work out the system_dn - useful for so many calls its worth 113 fetching here */ 114 state->system_dn = samdb_search_dn(state->sam_ldb, state, 115 state->domain_dn, "(&(objectClass=container)(cn=System))"); 116 if (!state->system_dn) { 117 return NT_STATUS_NO_SUCH_DOMAIN; 118 } 119 120 state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN); 121 if (!state->builtin_sid) { 122 return NT_STATUS_NO_SUCH_DOMAIN; 123 } 124 125 state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY); 126 if (!state->nt_authority_sid) { 127 return NT_STATUS_NO_SUCH_DOMAIN; 128 } 129 130 state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN); 131 if (!state->creator_owner_domain_sid) { 132 return NT_STATUS_NO_SUCH_DOMAIN; 133 } 134 135 state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN); 136 if (!state->world_domain_sid) { 137 return NT_STATUS_NO_SUCH_DOMAIN; 138 } 139 140 *_state = state; 141 142 return NT_STATUS_OK; 143} 144 145/* 146 lsa_OpenPolicy2 147*/ 148NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 149 struct lsa_OpenPolicy2 *r) 150{ 151 NTSTATUS status; 152 struct lsa_policy_state *state; 153 struct dcesrv_handle *handle; 154 155 ZERO_STRUCTP(r->out.handle); 156 157 if (r->in.attr != NULL && 158 r->in.attr->root_dir != NULL) { 159 /* MS-LSAD 3.1.4.4.1 */ 160 return NT_STATUS_INVALID_PARAMETER; 161 } 162 163 status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state); 164 if (!NT_STATUS_IS_OK(status)) { 165 return status; 166 } 167 168 handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY); 169 if (!handle) { 170 return NT_STATUS_NO_MEMORY; 171 } 172 173 handle->data = talloc_steal(handle, state); 174 175 /* need to check the access mask against - need ACLs - fails 176 WSPP test */ 177 state->access_mask = r->in.access_mask; 178 state->handle = handle; 179 *r->out.handle = handle->wire_handle; 180 181 /* note that we have completely ignored the attr element of 182 the OpenPolicy. As far as I can tell, this is what w2k3 183 does */ 184 185 return NT_STATUS_OK; 186} 187 188/* 189 lsa_OpenPolicy 190 a wrapper around lsa_OpenPolicy2 191*/ 192NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, 193 struct lsa_OpenPolicy *r) 194{ 195 struct lsa_OpenPolicy2 r2; 196 197 r2.in.system_name = NULL; 198 r2.in.attr = r->in.attr; 199 r2.in.access_mask = r->in.access_mask; 200 r2.out.handle = r->out.handle; 201 202 return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2); 203} 204 205 206