s4:torture: Migrate smbtorture to new cmdline option parser
[samba.git] / source4 / torture / ldap / nested_search.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    BRIEF FILE DESCRIPTION
5
6    Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2010
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 #include "includes.h"
23 #include "ldb.h"
24 #include "ldb_wrap.h"
25 #include "lib/cmdline/cmdline.h"
26 #include "libcli/ldap/ldap_client.h"
27 #include "torture/torture.h"
28 #include "torture/ldap/proto.h"
29
30 #define torture_assert_res(torture_ctx,expr,cmt,_res) \
31         if (!(expr)) { \
32                 torture_result(torture_ctx, TORTURE_FAIL, __location__": Expression `%s' failed: %s", __STRING(expr), cmt); \
33                 return _res; \
34         }
35
36
37 struct nested_search_context {
38         struct torture_context *tctx;
39         struct ldb_dn *root_dn;
40         struct ldb_context *ldb;
41         struct ldb_result *ldb_res;
42 };
43
44 /*
45  * ldb_search handler - used to executed a nested
46  * ldap search request during LDB_REPLY_ENTRY handling
47  */
48 static int nested_search_callback(struct ldb_request *req,
49                                   struct ldb_reply *ares)
50 {
51         unsigned int i;
52         int res;
53         struct nested_search_context *sctx;
54         struct ldb_result *ldb_res;
55         struct ldb_message *ldb_msg;
56         static const char *attrs[] = {
57                 "rootDomainNamingContext",
58                 "configurationNamingContext",
59                 "schemaNamingContext",
60                 "defaultNamingContext",
61                 NULL
62         };
63         enum ldb_reply_type type;
64
65         sctx = talloc_get_type(req->context, struct nested_search_context);
66
67         type = ares->type;
68         /* sanity check */
69         switch (type) {
70         case LDB_REPLY_ENTRY:
71                 torture_comment(sctx->tctx, "nested_search_callback: LDB_REPLY_ENTRY\n");
72                 ldb_msg = ares->message;
73                 torture_assert_res(sctx->tctx, ldb_msg, "ares->message is NULL!", LDB_ERR_OPERATIONS_ERROR);
74                 torture_assert_res(sctx->tctx, ldb_msg->num_elements, "No elements returned!", LDB_ERR_OPERATIONS_ERROR);
75                 torture_assert_res(sctx->tctx, ldb_msg->elements, "elements member is NULL!", LDB_ERR_OPERATIONS_ERROR);
76                 break;
77         case LDB_REPLY_DONE:
78                 torture_comment(sctx->tctx, "nested_search_callback: LDB_REPLY_DONE\n");
79                 break;
80         case LDB_REPLY_REFERRAL:
81                 torture_comment(sctx->tctx, "nested_search_callback: LDB_REPLY_REFERRAL\n");
82                 break;
83         }
84
85         /* switch context and let default handler do its job */
86         req->context = sctx->ldb_res;
87         res = ldb_search_default_callback(req, ares);
88         req->context = sctx;
89         if (res != LDB_SUCCESS) {
90                 return res;
91         }
92
93         /* not a search reply, then get out */
94         if (type != LDB_REPLY_ENTRY) {
95                 return res;
96         }
97
98
99         res = ldb_search(sctx->ldb, sctx, &ldb_res, sctx->root_dn, LDB_SCOPE_BASE, attrs, "(objectClass=*)");
100         if (res != LDB_SUCCESS) {
101                 torture_warning(sctx->tctx,
102                                 "Search on RootDSE failed in search_entry handler: %s",
103                                 ldb_errstring(sctx->ldb));
104                 return LDB_SUCCESS;
105         }
106
107         torture_assert_res(sctx->tctx, ldb_res->count == 1, "One message expected here", LDB_ERR_OPERATIONS_ERROR);
108
109         ldb_msg = ldb_res->msgs[0];
110         torture_assert_res(sctx->tctx, ldb_msg->num_elements == (ARRAY_SIZE(attrs)-1),
111                            "Search returned different number of elts than requested", LDB_ERR_OPERATIONS_ERROR);
112         for (i = 0; i < ldb_msg->num_elements; i++) {
113                 const char *msg;
114                 struct ldb_message_element *elt1;
115                 struct ldb_message_element *elt2;
116
117                 elt2 = &ldb_msg->elements[i];
118                 msg = talloc_asprintf(sctx, "Processing element: %s", elt2->name);
119                 elt1 = ldb_msg_find_element(sctx->ldb_res->msgs[0], elt2->name);
120                 torture_assert_res(sctx->tctx, elt1, msg, LDB_ERR_OPERATIONS_ERROR);
121
122                 /* compare elements */
123                 torture_assert_res(sctx->tctx, elt2->flags == elt1->flags, "", LDB_ERR_OPERATIONS_ERROR);
124                 torture_assert_res(sctx->tctx, elt2->num_values == elt1->num_values, "", LDB_ERR_OPERATIONS_ERROR);
125         }
126         /* TODO: check returned result */
127
128         return LDB_SUCCESS;
129 }
130
131 /**
132  * Test nested search execution against RootDSE
133  * on remote LDAP server.
134  */
135 bool test_ldap_nested_search(struct torture_context *tctx)
136 {
137         int ret;
138         char *url;
139         const char *host = torture_setting_string(tctx, "host", NULL);
140         struct ldb_request *req;
141         struct nested_search_context *sctx;
142         static const char *attrs[] = {
143 /*
144                 "rootDomainNamingContext",
145                 "configurationNamingContext",
146                 "schemaNamingContext",
147                 "defaultNamingContext",
148 */
149                 "*",
150                 NULL
151         };
152
153         sctx = talloc_zero(tctx, struct nested_search_context);
154         torture_assert(tctx, sctx, "Not enough memory");
155         sctx->tctx = tctx;
156
157         url = talloc_asprintf(sctx, "ldap://%s/", host);
158         if (!url) {
159                 torture_assert(tctx, url, "Not enough memory");
160         }
161
162         torture_comment(tctx, "Connecting to: %s\n", url);
163         sctx->ldb = ldb_wrap_connect(sctx, tctx->ev, tctx->lp_ctx, url,
164                                      NULL,
165                                      samba_cmdline_get_creds(),
166                                      0);
167         torture_assert(tctx, sctx->ldb, "Failed to create ldb connection");
168
169         /* prepare context for searching */
170         sctx->root_dn = ldb_dn_new(sctx, sctx->ldb, NULL);
171         sctx->ldb_res = talloc_zero(sctx, struct ldb_result);
172
173         /* build search request */
174         ret = ldb_build_search_req(&req,
175                                    sctx->ldb,
176                                    sctx,
177                                    sctx->root_dn, LDB_SCOPE_BASE,
178                                    "(objectClass=*)", attrs, NULL,
179                                    sctx, nested_search_callback,
180                                    NULL);
181         if (ret != LDB_SUCCESS) {
182                 torture_result(tctx, TORTURE_FAIL,
183                                __location__ ": Allocating request failed: %s", ldb_errstring(sctx->ldb));
184                 return false;
185         }
186
187         ret = ldb_request(sctx->ldb, req);
188         if (ret != LDB_SUCCESS) {
189                 torture_result(tctx, TORTURE_FAIL,
190                                __location__ ": Search failed: %s", ldb_errstring(sctx->ldb));
191                 return false;
192         }
193
194         ret = ldb_wait(req->handle, LDB_WAIT_ALL);
195         if (ret != LDB_SUCCESS) {
196                 torture_result(tctx, TORTURE_FAIL,
197                                __location__ ": Search error: %s", ldb_errstring(sctx->ldb));
198                 return false;
199         }
200
201         /* TODO: check returned result */
202
203         talloc_free(sctx);
204         return true;
205 }
206