2 Unix SMB/CIFS implementation.
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/>.
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) \
32 torture_result(torture_ctx, TORTURE_FAIL, __location__": Expression `%s' failed: %s", __STRING(expr), cmt); \
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
)
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",
63 enum ldb_reply_type type
;
65 sctx
= talloc_get_type(req
->context
, struct nested_search_context
);
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
);
78 torture_comment(sctx
->tctx
, "nested_search_callback: LDB_REPLY_DONE\n");
80 case LDB_REPLY_REFERRAL
:
81 torture_comment(sctx
->tctx
, "nested_search_callback: LDB_REPLY_REFERRAL\n");
85 /* switch context and let default handler do its job */
86 req
->context
= sctx
->ldb_res
;
87 res
= ldb_search_default_callback(req
, ares
);
89 if (res
!= LDB_SUCCESS
) {
93 /* not a search reply, then get out */
94 if (type
!= LDB_REPLY_ENTRY
) {
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
));
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
++) {
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 */
132 * Test nested search execution against RootDSE
133 * on remote LDAP server.
135 bool test_ldap_nested_search(struct torture_context
*tctx
)
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",
153 sctx
= talloc_zero(tctx
, struct nested_search_context
);
154 torture_assert(tctx
, sctx
, "Not enough memory");
157 url
= talloc_asprintf(sctx
, "ldap://%s/", host
);
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
,
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
,
177 sctx
->root_dn
, LDB_SCOPE_BASE
,
178 "(objectClass=*)", attrs
, NULL
,
179 sctx
, nested_search_callback
,
181 if (ret
!= LDB_SUCCESS
) {
182 torture_result(tctx
, TORTURE_FAIL
,
183 __location__
": Allocating request failed: %s", ldb_errstring(sctx
->ldb
));
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
));
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
));
201 /* TODO: check returned result */