s4: popt: Global replace of cmdline_credentials -> popt_get_cmdline_credentials().
[Samba.git] / source4 / torture / ldap / nested_search.c
blob31e127d04ff3b329b7277fcfba30729071e46417
1 /*
2 Unix SMB/CIFS implementation.
4 BRIEF FILE DESCRIPTION
6 Copyright (C) Kamen Mazdrashki <kamen.mazdrashki@postpath.com> 2010
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.
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.
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/>.
22 #include "includes.h"
23 #include "ldb.h"
24 #include "ldb_wrap.h"
25 #include "lib/cmdline/popt_common.h"
26 #include "libcli/ldap/ldap_client.h"
27 #include "torture/torture.h"
28 #include "torture/ldap/proto.h"
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; \
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;
45 * ldb_search handler - used to executed a nested
46 * ldap search request during LDB_REPLY_ENTRY handling
48 static int nested_search_callback(struct ldb_request *req,
49 struct ldb_reply *ares)
51 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
63 enum ldb_reply_type type;
65 sctx = talloc_get_type(req->context, struct nested_search_context);
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;
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;
93 /* not a search reply, then get out */
94 if (type != LDB_REPLY_ENTRY) {
95 return res;
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;
107 torture_assert_res(sctx->tctx, ldb_res->count == 1, "One message expected here", LDB_ERR_OPERATIONS_ERROR);
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;
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);
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);
126 /* TODO: check returned result */
128 return LDB_SUCCESS;
132 * Test nested search execution against RootDSE
133 * on remote LDAP server.
135 bool test_ldap_nested_search(struct torture_context *tctx)
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[] = {
144 "rootDomainNamingContext",
145 "configurationNamingContext",
146 "schemaNamingContext",
147 "defaultNamingContext",
149 "*",
150 NULL
153 sctx = talloc_zero(tctx, struct nested_search_context);
154 torture_assert(tctx, sctx, "Not enough memory");
155 sctx->tctx = tctx;
157 url = talloc_asprintf(sctx, "ldap://%s/", host);
158 if (!url) {
159 torture_assert(tctx, url, "Not enough memory");
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 popt_get_cmdline_credentials(),
167 torture_assert(tctx, sctx->ldb, "Failed to create ldb connection");
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);
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;
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;
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;
201 /* TODO: check returned result */
203 talloc_free(sctx);
204 return true;