cope with NULL attr
[kai/samba.git] / source4 / rpc_server / lsa / lsa_init.c
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
25 NTSTATUS 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_dn *partitions_basedn;
30         struct ldb_result *dom_res;
31         const char *dom_attrs[] = {
32                 "objectSid", 
33                 "objectGUID", 
34                 "nTMixedDomain",
35                 "fSMORoleOwner",
36                 NULL
37         };
38         struct ldb_result *ref_res;
39         struct ldb_result *forest_ref_res;
40         const char *ref_attrs[] = {
41                 "nETBIOSName",
42                 "dnsRoot",
43                 NULL
44         };
45         int ret;
46
47         state = talloc(mem_ctx, struct lsa_policy_state);
48         if (!state) {
49                 return NT_STATUS_NO_MEMORY;
50         }
51
52         /* make sure the sam database is accessible */
53         state->sam_ldb = samdb_connect(state, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, dce_call->conn->auth_state.session_info); 
54         if (state->sam_ldb == NULL) {
55                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
56         }
57
58         partitions_basedn = samdb_partitions_dn(state->sam_ldb, mem_ctx);
59
60         /* work out the domain_dn - useful for so many calls its worth
61            fetching here */
62         state->domain_dn = samdb_base_dn(state->sam_ldb);
63         if (!state->domain_dn) {
64                 return NT_STATUS_NO_MEMORY;             
65         }
66
67         /* work out the forest root_dn - useful for so many calls its worth
68            fetching here */
69         state->forest_dn = samdb_root_dn(state->sam_ldb);
70         if (!state->forest_dn) {
71                 return NT_STATUS_NO_MEMORY;             
72         }
73
74         ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
75                          state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
76         if (ret != LDB_SUCCESS) {
77                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
78         }
79         if (dom_res->count != 1) {
80                 return NT_STATUS_NO_SUCH_DOMAIN;                
81         }
82
83         state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
84         if (!state->domain_sid) {
85                 return NT_STATUS_NO_SUCH_DOMAIN;                
86         }
87
88         state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
89         if (!state->domain_sid) {
90                 return NT_STATUS_NO_SUCH_DOMAIN;                
91         }
92
93         state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
94         
95         talloc_free(dom_res);
96
97         ret = ldb_search(state->sam_ldb, state, &ref_res,
98                                  partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
99                                  "(&(objectclass=crossRef)(ncName=%s))",
100                                  ldb_dn_get_linearized(state->domain_dn));
101         
102         if (ret != LDB_SUCCESS) {
103                 talloc_free(ref_res);
104                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
105         }
106         if (ref_res->count != 1) {
107                 talloc_free(ref_res);
108                 return NT_STATUS_NO_SUCH_DOMAIN;                
109         }
110
111         state->domain_name = ldb_msg_find_attr_as_string(ref_res->msgs[0], "nETBIOSName", NULL);
112         if (!state->domain_name) {
113                 talloc_free(ref_res);
114                 return NT_STATUS_NO_SUCH_DOMAIN;                
115         }
116         talloc_steal(state, state->domain_name);
117
118         state->domain_dns = ldb_msg_find_attr_as_string(ref_res->msgs[0], "dnsRoot", NULL);
119         if (!state->domain_dns) {
120                 talloc_free(ref_res);
121                 return NT_STATUS_NO_SUCH_DOMAIN;                
122         }
123         talloc_steal(state, state->domain_dns);
124
125         talloc_free(ref_res);
126
127         ret = ldb_search(state->sam_ldb, state, &forest_ref_res,
128                                  partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
129                                  "(&(objectclass=crossRef)(ncName=%s))",
130                                  ldb_dn_get_linearized(state->forest_dn));
131         
132         if (ret != LDB_SUCCESS) {
133                 talloc_free(forest_ref_res);
134                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
135         }
136         if (forest_ref_res->count != 1) {
137                 talloc_free(forest_ref_res);
138                 return NT_STATUS_NO_SUCH_DOMAIN;                
139         }
140
141         state->forest_dns = ldb_msg_find_attr_as_string(forest_ref_res->msgs[0], "dnsRoot", NULL);
142         if (!state->forest_dns) {
143                 talloc_free(forest_ref_res);
144                 return NT_STATUS_NO_SUCH_DOMAIN;                
145         }
146         talloc_steal(state, state->forest_dns);
147
148         talloc_free(forest_ref_res);
149
150         /* work out the builtin_dn - useful for so many calls its worth
151            fetching here */
152         state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
153         if (!state->builtin_dn) {
154                 return NT_STATUS_NO_SUCH_DOMAIN;                
155         }
156
157         /* work out the system_dn - useful for so many calls its worth
158            fetching here */
159         state->system_dn = samdb_search_dn(state->sam_ldb, state,
160                                            state->domain_dn, "(&(objectClass=container)(cn=System))");
161         if (!state->system_dn) {
162                 return NT_STATUS_NO_SUCH_DOMAIN;                
163         }
164
165         state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
166         if (!state->builtin_sid) {
167                 return NT_STATUS_NO_SUCH_DOMAIN;                
168         }
169
170         state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
171         if (!state->nt_authority_sid) {
172                 return NT_STATUS_NO_SUCH_DOMAIN;                
173         }
174
175         state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
176         if (!state->creator_owner_domain_sid) {
177                 return NT_STATUS_NO_SUCH_DOMAIN;                
178         }
179
180         state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
181         if (!state->world_domain_sid) {
182                 return NT_STATUS_NO_SUCH_DOMAIN;                
183         }
184
185         *_state = state;
186
187         return NT_STATUS_OK;
188 }
189
190 /* 
191   lsa_OpenPolicy2
192 */
193 NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
194                                 struct lsa_OpenPolicy2 *r)
195 {
196         NTSTATUS status;
197         struct lsa_policy_state *state;
198         struct dcesrv_handle *handle;
199
200         ZERO_STRUCTP(r->out.handle);
201
202         if (r->in.attr != NULL &&
203             r->in.attr->root_dir != NULL) {
204                 /* MS-LSAD 3.1.4.4.1 */
205                 return NT_STATUS_INVALID_PARAMETER;
206         }
207
208         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
209         if (!NT_STATUS_IS_OK(status)) {
210                 return status;
211         }
212
213         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY);
214         if (!handle) {
215                 return NT_STATUS_NO_MEMORY;
216         }
217
218         handle->data = talloc_steal(handle, state);
219
220         /* need to check the access mask against - need ACLs - fails
221            WSPP test */
222         state->access_mask = r->in.access_mask;
223         state->handle = handle;
224         *r->out.handle = handle->wire_handle;
225
226         /* note that we have completely ignored the attr element of
227            the OpenPolicy. As far as I can tell, this is what w2k3
228            does */
229
230         return NT_STATUS_OK;
231 }
232
233 /* 
234   lsa_OpenPolicy
235   a wrapper around lsa_OpenPolicy2
236 */
237 NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
238                                 struct lsa_OpenPolicy *r)
239 {
240         struct lsa_OpenPolicy2 r2;
241
242         r2.in.system_name = NULL;
243         r2.in.attr = r->in.attr;
244         r2.in.access_mask = r->in.access_mask;
245         r2.out.handle = r->out.handle;
246
247         return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
248 }
249
250