28a4f59b3a31959e0b292c318115c874c2a1b5ee
[jelmer/samba4-debian.git] / source / torture / rpc / lsa_lookup.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for lsa rpc lookup operations
4
5    Copyright (C) Volker Lendecke 2006
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "torture/torture.h"
24 #include "lib/events/events.h"
25 #include "libnet/libnet_join.h"
26 #include "torture/rpc/rpc.h"
27 #include "librpc/gen_ndr/ndr_lsa_c.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 #include "libcli/security/security.h"
30
31 static BOOL open_policy(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p,
32                         struct policy_handle **handle)
33 {
34         struct lsa_ObjectAttribute attr;
35         struct lsa_QosInfo qos;
36         struct lsa_OpenPolicy2 r;
37         NTSTATUS status;
38
39         *handle = talloc(mem_ctx, struct policy_handle);
40         if (!*handle) {
41                 return False;
42         }
43
44         qos.len = 0;
45         qos.impersonation_level = 2;
46         qos.context_mode = 1;
47         qos.effective_only = 0;
48
49         attr.len = 0;
50         attr.root_dir = NULL;
51         attr.object_name = NULL;
52         attr.attributes = 0;
53         attr.sec_desc = NULL;
54         attr.sec_qos = &qos;
55
56         r.in.system_name = "\\";
57         r.in.attr = &attr;
58         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
59         r.out.handle = *handle;
60
61         status = dcerpc_lsa_OpenPolicy2(p, mem_ctx, &r);
62
63         return NT_STATUS_IS_OK(status);
64 }
65
66 static BOOL get_domainsid(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p,
67                           struct policy_handle *handle,
68                           struct dom_sid **sid)
69 {
70         struct lsa_QueryInfoPolicy r;
71         NTSTATUS status;
72
73         r.in.level = LSA_POLICY_INFO_DOMAIN;
74         r.in.handle = handle;
75
76         status = dcerpc_lsa_QueryInfoPolicy(p, mem_ctx, &r);
77         if (!NT_STATUS_IS_OK(status)) return False;
78
79         *sid = r.out.info->domain.sid;
80         return True;
81 }
82
83 static NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, uint16_t level,
84                             struct dcerpc_pipe *p,
85                             struct policy_handle *handle,
86                             struct dom_sid **sids, uint32_t num_sids,
87                             struct lsa_TransNameArray *names)
88 {
89         struct lsa_LookupSids r;
90         struct lsa_SidArray sidarray;
91         uint32_t count = 0;
92         uint32_t i;
93
94         names->count = 0;
95         names->names = NULL;
96
97         sidarray.num_sids = num_sids;
98         sidarray.sids = talloc_array(mem_ctx, struct lsa_SidPtr, num_sids);
99
100         for (i=0; i<num_sids; i++) {
101                 sidarray.sids[i].sid = sids[i];
102         }
103
104         r.in.handle = handle;
105         r.in.sids = &sidarray;
106         r.in.names = names;
107         r.in.level = level;
108         r.in.count = &count;
109         r.out.names = names;
110         r.out.count = &count;
111
112         return dcerpc_lsa_LookupSids(p, mem_ctx, &r);
113 }
114
115 static const char *sid_type_lookup(enum lsa_SidType r)
116 {
117         switch (r) {
118                 case SID_NAME_USE_NONE: return "SID_NAME_USE_NONE"; break;
119                 case SID_NAME_USER: return "SID_NAME_USER"; break;
120                 case SID_NAME_DOM_GRP: return "SID_NAME_DOM_GRP"; break;
121                 case SID_NAME_DOMAIN: return "SID_NAME_DOMAIN"; break;
122                 case SID_NAME_ALIAS: return "SID_NAME_ALIAS"; break;
123                 case SID_NAME_WKN_GRP: return "SID_NAME_WKN_GRP"; break;
124                 case SID_NAME_DELETED: return "SID_NAME_DELETED"; break;
125                 case SID_NAME_INVALID: return "SID_NAME_INVALID"; break;
126                 case SID_NAME_UNKNOWN: return "SID_NAME_UNKNOWN"; break;
127         }
128         return "Invalid sid type\n";
129 }
130
131 static BOOL test_lookupsids(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p,
132                             struct policy_handle *handle,
133                             struct dom_sid **sids, uint32_t num_sids,
134                             int level, NTSTATUS expected_result, 
135                             enum lsa_SidType *types)
136 {
137         struct lsa_TransNameArray names;
138         NTSTATUS status;
139         uint32_t i;
140         BOOL ret = True;
141
142         status = lookup_sids(mem_ctx, level, p, handle, sids, num_sids,
143                              &names);
144         if (!NT_STATUS_EQUAL(status, expected_result)) {
145                 printf("For level %d expected %s, got %s\n",
146                        level, nt_errstr(expected_result),
147                        nt_errstr(status));
148                 return False;
149         }
150
151         if (!NT_STATUS_EQUAL(status, NT_STATUS_OK) &&
152             !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
153                 return True;
154         }
155
156         for (i=0; i<num_sids; i++) {
157                 if (names.names[i].sid_type != types[i]) {
158                         printf("In level %d, for sid %s expected %s, "
159                                "got %s\n", level,
160                                dom_sid_string(mem_ctx, sids[i]),
161                                sid_type_lookup(types[i]),
162                                sid_type_lookup(names.names[i].sid_type));
163                         ret = False;
164                 }
165         }
166         return ret;
167 }
168
169 static BOOL get_downleveltrust(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *p,
170                                struct policy_handle *handle,
171                                struct dom_sid **sid)
172 {
173         struct lsa_EnumTrustDom r;
174         uint32_t resume_handle = 0;
175         struct lsa_DomainList domains;
176         NTSTATUS status;
177         int i;
178
179         r.in.handle = handle;
180         r.in.resume_handle = &resume_handle;
181         r.in.max_size = 1000;
182         r.out.domains = &domains;
183         r.out.resume_handle = &resume_handle;
184
185         status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r);
186
187         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES)) {
188                 printf("no trusts\n");
189                 return False;
190         }
191
192         if (domains.count == 0) {
193                 printf("no trusts\n");
194                 return False;
195         }
196
197         for (i=0; i<domains.count; i++) {
198                 struct lsa_QueryTrustedDomainInfoBySid q;
199
200                 if (domains.domains[i].sid == NULL)
201                         continue;
202
203                 q.in.handle = handle;
204                 q.in.dom_sid = domains.domains[i].sid;
205                 q.in.level = 6;
206                 status = dcerpc_lsa_QueryTrustedDomainInfoBySid(p, mem_ctx, &q);
207                 if (!NT_STATUS_IS_OK(status)) continue;
208
209                 if ((q.out.info->info_ex.trust_direction & 2) &&
210                     (q.out.info->info_ex.trust_type == 1)) {
211                         *sid = domains.domains[i].sid;
212                         return True;
213                 }
214         }
215
216         printf("I need a AD DC with an outgoing trust to NT4\n");
217         return False;
218 }
219
220 #define NUM_SIDS 8
221
222 BOOL torture_rpc_lsa_lookup(struct torture_context *torture)
223 {
224         NTSTATUS status;
225         struct dcerpc_pipe *p;
226         TALLOC_CTX *mem_ctx;
227         BOOL ret = True;
228         struct policy_handle *handle;
229         struct dom_sid *dom_sid;
230         struct dom_sid *trusted_sid;
231         struct dom_sid *sids[NUM_SIDS];
232
233         mem_ctx = talloc_init("torture_rpc_lsa");
234
235         status = torture_rpc_connection(mem_ctx, &p, &dcerpc_table_lsarpc);
236         if (!NT_STATUS_IS_OK(status)) {
237                 ret = False;
238                 goto done;
239         }
240
241         ret &= open_policy(mem_ctx, p, &handle);
242         if (!ret) goto done;
243
244         ret &= get_domainsid(mem_ctx, p, handle, &dom_sid);
245         if (!ret) goto done;
246
247         ret &= get_downleveltrust(mem_ctx, p, handle, &trusted_sid);
248         if (!ret) goto done;
249
250         printf("domain sid: %s\n", dom_sid_string(mem_ctx, dom_sid));
251
252         sids[0] = dom_sid_parse_talloc(mem_ctx, "S-1-1-0");
253         sids[1] = dom_sid_parse_talloc(mem_ctx, "S-1-5-4");
254         sids[2] = dom_sid_parse_talloc(mem_ctx, "S-1-5-32");
255         sids[3] = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-545");
256         sids[4] = dom_sid_dup(mem_ctx, dom_sid);
257         sids[5] = dom_sid_add_rid(mem_ctx, dom_sid, 512);
258         sids[6] = dom_sid_dup(mem_ctx, trusted_sid);
259         sids[7] = dom_sid_add_rid(mem_ctx, trusted_sid, 512);
260
261         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 0,
262                                NT_STATUS_INVALID_PARAMETER, NULL);
263
264         {
265                 enum lsa_SidType types[NUM_SIDS] =
266                         { SID_NAME_WKN_GRP, SID_NAME_WKN_GRP, SID_NAME_DOMAIN,
267                           SID_NAME_ALIAS, SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
268                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP };
269
270                 ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 1,
271                                        NT_STATUS_OK, types);
272         }
273
274         {
275                 enum lsa_SidType types[NUM_SIDS] =
276                         { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
277                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
278                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
279                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP };
280                 ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 2,
281                                        STATUS_SOME_UNMAPPED, types);
282         }
283
284         {
285                 enum lsa_SidType types[NUM_SIDS] =
286                         { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
287                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
288                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
289                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN };
290                 ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 3,
291                                        STATUS_SOME_UNMAPPED, types);
292         }
293
294         {
295                 enum lsa_SidType types[NUM_SIDS] =
296                         { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
297                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
298                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
299                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN };
300                 ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 4,
301                                        STATUS_SOME_UNMAPPED, types);
302         }
303
304         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 5,
305                                NT_STATUS_NONE_MAPPED, NULL);
306
307         {
308                 enum lsa_SidType types[NUM_SIDS] =
309                         { SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
310                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN,
311                           SID_NAME_DOMAIN, SID_NAME_DOM_GRP,
312                           SID_NAME_UNKNOWN, SID_NAME_UNKNOWN };
313                 ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 6,
314                                        STATUS_SOME_UNMAPPED, types);
315         }
316
317         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 7,
318                                NT_STATUS_INVALID_PARAMETER, NULL);
319         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 8,
320                                NT_STATUS_INVALID_PARAMETER, NULL);
321         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 9,
322                                NT_STATUS_INVALID_PARAMETER, NULL);
323         ret &= test_lookupsids(mem_ctx, p, handle, sids, NUM_SIDS, 10,
324                                NT_STATUS_INVALID_PARAMETER, NULL);
325
326  done:
327         talloc_free(mem_ctx);
328
329         return ret;
330 }