Line data Source code
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 2 : static int nested_search_callback(struct ldb_request *req,
49 : struct ldb_reply *ares)
50 : {
51 0 : unsigned int i;
52 0 : int res;
53 0 : struct nested_search_context *sctx;
54 0 : struct ldb_result *ldb_res;
55 0 : struct ldb_message *ldb_msg;
56 0 : static const char *attrs[] = {
57 : "rootDomainNamingContext",
58 : "configurationNamingContext",
59 : "schemaNamingContext",
60 : "defaultNamingContext",
61 : NULL
62 : };
63 0 : enum ldb_reply_type type;
64 :
65 2 : sctx = talloc_get_type(req->context, struct nested_search_context);
66 :
67 2 : type = ares->type;
68 : /* sanity check */
69 2 : switch (type) {
70 1 : case LDB_REPLY_ENTRY:
71 1 : torture_comment(sctx->tctx, "nested_search_callback: LDB_REPLY_ENTRY\n");
72 1 : ldb_msg = ares->message;
73 1 : torture_assert_res(sctx->tctx, ldb_msg, "ares->message is NULL!", LDB_ERR_OPERATIONS_ERROR);
74 1 : torture_assert_res(sctx->tctx, ldb_msg->num_elements, "No elements returned!", LDB_ERR_OPERATIONS_ERROR);
75 1 : torture_assert_res(sctx->tctx, ldb_msg->elements, "elements member is NULL!", LDB_ERR_OPERATIONS_ERROR);
76 1 : break;
77 1 : case LDB_REPLY_DONE:
78 1 : torture_comment(sctx->tctx, "nested_search_callback: LDB_REPLY_DONE\n");
79 1 : break;
80 0 : case LDB_REPLY_REFERRAL:
81 0 : torture_comment(sctx->tctx, "nested_search_callback: LDB_REPLY_REFERRAL\n");
82 0 : break;
83 : }
84 :
85 : /* switch context and let default handler do its job */
86 2 : req->context = sctx->ldb_res;
87 2 : res = ldb_search_default_callback(req, ares);
88 2 : req->context = sctx;
89 2 : if (res != LDB_SUCCESS) {
90 0 : return res;
91 : }
92 :
93 : /* not a search reply, then get out */
94 2 : if (type != LDB_REPLY_ENTRY) {
95 1 : return res;
96 : }
97 :
98 :
99 1 : res = ldb_search(sctx->ldb, sctx, &ldb_res, sctx->root_dn, LDB_SCOPE_BASE, attrs, "(objectClass=*)");
100 1 : if (res != LDB_SUCCESS) {
101 0 : torture_warning(sctx->tctx,
102 : "Search on RootDSE failed in search_entry handler: %s",
103 : ldb_errstring(sctx->ldb));
104 0 : return LDB_SUCCESS;
105 : }
106 :
107 1 : torture_assert_res(sctx->tctx, ldb_res->count == 1, "One message expected here", LDB_ERR_OPERATIONS_ERROR);
108 :
109 1 : ldb_msg = ldb_res->msgs[0];
110 1 : 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 5 : for (i = 0; i < ldb_msg->num_elements; i++) {
113 0 : const char *msg;
114 0 : struct ldb_message_element *elt1;
115 0 : struct ldb_message_element *elt2;
116 :
117 4 : elt2 = &ldb_msg->elements[i];
118 4 : msg = talloc_asprintf(sctx, "Processing element: %s", elt2->name);
119 4 : elt1 = ldb_msg_find_element(sctx->ldb_res->msgs[0], elt2->name);
120 4 : torture_assert_res(sctx->tctx, elt1, msg, LDB_ERR_OPERATIONS_ERROR);
121 :
122 : /* compare elements */
123 4 : torture_assert_res(sctx->tctx, elt2->flags == elt1->flags, "", LDB_ERR_OPERATIONS_ERROR);
124 4 : torture_assert_res(sctx->tctx, elt2->num_values == elt1->num_values, "", LDB_ERR_OPERATIONS_ERROR);
125 : }
126 : /* TODO: check returned result */
127 :
128 1 : return LDB_SUCCESS;
129 : }
130 :
131 : /**
132 : * Test nested search execution against RootDSE
133 : * on remote LDAP server.
134 : */
135 1 : bool test_ldap_nested_search(struct torture_context *tctx)
136 : {
137 0 : int ret;
138 0 : char *url;
139 1 : const char *host = torture_setting_string(tctx, "host", NULL);
140 0 : struct ldb_request *req;
141 0 : struct nested_search_context *sctx;
142 0 : static const char *attrs[] = {
143 : /*
144 : "rootDomainNamingContext",
145 : "configurationNamingContext",
146 : "schemaNamingContext",
147 : "defaultNamingContext",
148 : */
149 : "*",
150 : NULL
151 : };
152 :
153 1 : sctx = talloc_zero(tctx, struct nested_search_context);
154 1 : torture_assert(tctx, sctx, "Not enough memory");
155 1 : sctx->tctx = tctx;
156 :
157 1 : url = talloc_asprintf(sctx, "ldap://%s/", host);
158 1 : if (!url) {
159 0 : torture_assert(tctx, url, "Not enough memory");
160 : }
161 :
162 1 : torture_comment(tctx, "Connecting to: %s\n", url);
163 1 : sctx->ldb = ldb_wrap_connect(sctx, tctx->ev, tctx->lp_ctx, url,
164 : NULL,
165 : samba_cmdline_get_creds(),
166 : 0);
167 1 : torture_assert(tctx, sctx->ldb, "Failed to create ldb connection");
168 :
169 : /* prepare context for searching */
170 1 : sctx->root_dn = ldb_dn_new(sctx, sctx->ldb, NULL);
171 1 : sctx->ldb_res = talloc_zero(sctx, struct ldb_result);
172 :
173 : /* build search request */
174 1 : 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 1 : if (ret != LDB_SUCCESS) {
182 0 : torture_result(tctx, TORTURE_FAIL,
183 : __location__ ": Allocating request failed: %s", ldb_errstring(sctx->ldb));
184 0 : return false;
185 : }
186 :
187 1 : ret = ldb_request(sctx->ldb, req);
188 1 : if (ret != LDB_SUCCESS) {
189 0 : torture_result(tctx, TORTURE_FAIL,
190 : __location__ ": Search failed: %s", ldb_errstring(sctx->ldb));
191 0 : return false;
192 : }
193 :
194 1 : ret = ldb_wait(req->handle, LDB_WAIT_ALL);
195 1 : if (ret != LDB_SUCCESS) {
196 0 : torture_result(tctx, TORTURE_FAIL,
197 : __location__ ": Search error: %s", ldb_errstring(sctx->ldb));
198 0 : return false;
199 : }
200 :
201 : /* TODO: check returned result */
202 :
203 1 : talloc_free(sctx);
204 1 : return true;
205 : }
206 :
|