r26223: Move loadparm context up in the stack.
[kai/samba.git] / source4 / torture / ldap / cldap.c
1 /* 
2    Unix SMB/CIFS mplementation.
3
4    test CLDAP operations
5    
6    Copyright (C) Andrew Tridgell 2005
7     
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20    
21 */
22
23 #include "includes.h"
24 #include "libcli/cldap/cldap.h"
25 #include "libcli/ldap/ldap.h"
26 #include "librpc/gen_ndr/ndr_nbt.h"
27 #include "torture/torture.h"
28 #include "lib/ldb/include/ldb.h"
29 #include "param/param.h"
30
31 #define CHECK_STATUS(status, correct) do { \
32         if (!NT_STATUS_EQUAL(status, correct)) { \
33                 printf("(%s) Incorrect status %s - should be %s\n", \
34                        __location__, nt_errstr(status), nt_errstr(correct)); \
35                 ret = false; \
36                 goto done; \
37         } \
38 } while (0)
39
40 /*
41   test netlogon operations
42 */
43 static bool test_cldap_netlogon(TALLOC_CTX *mem_ctx, const char *dest)
44 {
45         struct cldap_socket *cldap = cldap_socket_init(mem_ctx, NULL);
46         NTSTATUS status;
47         struct cldap_netlogon search, empty_search;
48         union nbt_cldap_netlogon n1;
49         struct GUID guid;
50         int i;
51         bool ret = true;
52
53         ZERO_STRUCT(search);
54         search.in.dest_address = dest;
55         search.in.acct_control = -1;
56         search.in.version = 6;
57
58         empty_search = search;
59
60         printf("Trying without any attributes\n");
61         search = empty_search;
62         status = cldap_netlogon(cldap, mem_ctx, &search);
63         CHECK_STATUS(status, NT_STATUS_OK);
64
65         n1 = search.out.netlogon;
66
67         search.in.user         = "Administrator";
68         search.in.realm        = n1.logon5.dns_domain;
69         search.in.host         = "__cldap_torture__";
70
71         printf("Scanning for netlogon levels\n");
72         for (i=0;i<256;i++) {
73                 search.in.version = i;
74                 printf("Trying netlogon level %d\n", i);
75                 status = cldap_netlogon(cldap, mem_ctx, &search);
76                 CHECK_STATUS(status, NT_STATUS_OK);
77         }
78
79         printf("Scanning for netlogon level bits\n");
80         for (i=0;i<31;i++) {
81                 search.in.version = (1<<i);
82                 printf("Trying netlogon level 0x%x\n", i);
83                 status = cldap_netlogon(cldap, mem_ctx, &search);
84                 CHECK_STATUS(status, NT_STATUS_OK);
85         }
86
87         search.in.version = 6;
88         status = cldap_netlogon(cldap, mem_ctx, &search);
89         CHECK_STATUS(status, NT_STATUS_OK);
90
91         printf("Trying with User=NULL\n");
92
93         search.in.user = NULL;
94         status = cldap_netlogon(cldap, mem_ctx, &search);
95         CHECK_STATUS(status, NT_STATUS_OK);
96
97         printf("Trying with User=Administrator\n");
98
99         search.in.user = "Administrator";
100         status = cldap_netlogon(cldap, mem_ctx, &search);
101         CHECK_STATUS(status, NT_STATUS_OK);
102
103         printf("Trying with a GUID\n");
104         search.in.realm       = NULL;
105         search.in.domain_guid = GUID_string(mem_ctx, &n1.logon5.domain_uuid);
106         status = cldap_netlogon(cldap, mem_ctx, &search);
107         CHECK_STATUS(status, NT_STATUS_OK);
108
109         printf("Trying with a incorrect GUID\n");
110         guid = GUID_random();
111         search.in.user        = NULL;
112         search.in.domain_guid = GUID_string(mem_ctx, &guid);
113         status = cldap_netlogon(cldap, mem_ctx, &search);
114         CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
115
116         printf("Trying with a AAC\n");
117         search.in.acct_control = 0x180;
118         search.in.realm = n1.logon5.dns_domain;
119         status = cldap_netlogon(cldap, mem_ctx, &search);
120         CHECK_STATUS(status, NT_STATUS_OK);
121
122         printf("Trying with a bad AAC\n");
123         search.in.acct_control = 0xFF00FF00;
124         search.in.realm = n1.logon5.dns_domain;
125         status = cldap_netlogon(cldap, mem_ctx, &search);
126         CHECK_STATUS(status, NT_STATUS_OK);
127
128         printf("Trying with a user only\n");
129         search = empty_search;
130         search.in.user = "Administrator";
131         status = cldap_netlogon(cldap, mem_ctx, &search);
132         CHECK_STATUS(status, NT_STATUS_OK);
133
134         printf("Trying with just a bad username\n");
135         search.in.user = "___no_such_user___";
136         status = cldap_netlogon(cldap, mem_ctx, &search);
137         CHECK_STATUS(status, NT_STATUS_OK);
138
139         printf("Trying with just a bad domain\n");
140         search = empty_search;
141         search.in.realm = "___no_such_domain___";
142         status = cldap_netlogon(cldap, mem_ctx, &search);
143         CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
144
145         printf("Trying with a incorrect domain and correct guid\n");
146         search.in.domain_guid = GUID_string(mem_ctx, &n1.logon5.domain_uuid);
147         status = cldap_netlogon(cldap, mem_ctx, &search);
148         CHECK_STATUS(status, NT_STATUS_OK);
149
150         printf("Trying with a incorrect domain and incorrect guid\n");
151         search.in.domain_guid = GUID_string(mem_ctx, &guid);
152         status = cldap_netlogon(cldap, mem_ctx, &search);
153         CHECK_STATUS(status, NT_STATUS_NOT_FOUND);
154
155         printf("Trying with a incorrect GUID and correct domain\n");
156         search.in.domain_guid = GUID_string(mem_ctx, &guid);
157         search.in.realm = n1.logon5.dns_domain;
158         status = cldap_netlogon(cldap, mem_ctx, &search);
159         CHECK_STATUS(status, NT_STATUS_OK);
160
161 done:
162         return ret;     
163 }
164
165 /*
166   convert a ldap result message to a ldb message. This allows us to
167   use the convenient ldif dump routines in ldb to print out cldap
168   search results
169 */
170 static struct ldb_message *ldap_msg_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldap_SearchResEntry *res)
171 {
172         struct ldb_message *msg;
173
174         msg = ldb_msg_new(mem_ctx);
175         msg->dn = ldb_dn_new(msg, ldb, res->dn);
176         msg->num_elements = res->num_attributes;
177         msg->elements = talloc_steal(msg, res->attributes);
178         return msg;
179 }
180
181 /*
182   dump a set of cldap results
183 */
184 static void cldap_dump_results(struct cldap_search *search)
185 {
186         struct ldb_ldif ldif;
187         struct ldb_context *ldb;
188
189         if (!search || !(search->out.response)) {
190                 return;
191         }
192
193         /* we need a ldb context to use ldb_ldif_write_file() */
194         ldb = ldb_init(NULL);
195
196         ZERO_STRUCT(ldif);
197         ldif.msg = ldap_msg_to_ldb(ldb, ldb, search->out.response);
198
199         ldb_ldif_write_file(ldb, stdout, &ldif);
200
201         talloc_free(ldb);
202 }
203
204 /*
205   test generic cldap operations
206 */
207 static bool test_cldap_generic(TALLOC_CTX *mem_ctx, const char *dest)
208 {
209         struct cldap_socket *cldap = cldap_socket_init(mem_ctx, NULL);
210         NTSTATUS status;
211         struct cldap_search search;
212         bool ret = true;
213         const char *attrs1[] = { "currentTime", "highestCommittedUSN", NULL };
214         const char *attrs2[] = { "currentTime", "highestCommittedUSN", "netlogon", NULL };
215         const char *attrs3[] = { "netlogon", NULL };
216
217         ZERO_STRUCT(search);
218         search.in.dest_address = dest;
219         search.in.dest_port = lp_cldap_port(global_loadparm);
220         search.in.timeout = 10;
221         search.in.retries = 3;
222
223         status = cldap_search(cldap, mem_ctx, &search);
224         CHECK_STATUS(status, NT_STATUS_OK);
225
226         printf("fetching whole rootDSE\n");
227         search.in.filter = "(objectclass=*)";
228         search.in.attributes = NULL;
229
230         status = cldap_search(cldap, mem_ctx, &search);
231         CHECK_STATUS(status, NT_STATUS_OK);
232
233         if (DEBUGLVL(3)) cldap_dump_results(&search);
234
235         printf("fetching currentTime and USN\n");
236         search.in.filter = "(objectclass=*)";
237         search.in.attributes = attrs1;
238
239         status = cldap_search(cldap, mem_ctx, &search);
240         CHECK_STATUS(status, NT_STATUS_OK);
241         
242         if (DEBUGLVL(3)) cldap_dump_results(&search);
243
244         printf("Testing currentTime, USN and netlogon\n");
245         search.in.filter = "(objectclass=*)";
246         search.in.attributes = attrs2;
247
248         status = cldap_search(cldap, mem_ctx, &search);
249         CHECK_STATUS(status, NT_STATUS_OK);
250
251         if (DEBUGLVL(3)) cldap_dump_results(&search);
252
253         printf("Testing objectClass=* and netlogon\n");
254         search.in.filter = "(objectclass2=*)";
255         search.in.attributes = attrs3;
256
257         status = cldap_search(cldap, mem_ctx, &search);
258         CHECK_STATUS(status, NT_STATUS_OK);
259
260         if (DEBUGLVL(3)) cldap_dump_results(&search);
261
262         printf("Testing a false expression\n");
263         search.in.filter = "(&(objectclass=*)(highestCommittedUSN=2))";
264         search.in.attributes = attrs1;
265
266         status = cldap_search(cldap, mem_ctx, &search);
267         CHECK_STATUS(status, NT_STATUS_OK);
268
269         if (DEBUGLVL(3)) cldap_dump_results(&search);   
270
271 done:
272         return ret;     
273 }
274
275 bool torture_cldap(struct torture_context *torture)
276 {
277         TALLOC_CTX *mem_ctx;
278         bool ret = true;
279         const char *host = torture_setting_string(torture, "host", NULL);
280
281         mem_ctx = talloc_init("torture_cldap");
282
283         ret &= test_cldap_netlogon(mem_ctx, host);
284         ret &= test_cldap_generic(mem_ctx, host);
285
286         talloc_free(mem_ctx);
287
288         return ret;
289 }
290