2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2004
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "ldap_server/ldap_server.h"
23 #include "dlinklist.h"
24 #include "libcli/ldap/ldap.h"
25 #include "lib/ldb/include/ldb.h"
26 #include "lib/ldb/include/ldb_errors.h"
27 #include "dsdb/samdb/samdb.h"
29 #define VALID_DN_SYNTAX(dn,i) do {\
31 return NT_STATUS_NO_MEMORY;\
32 } else if ((dn)->comp_num < (i)) {\
33 result = LDAP_INVALID_DN_SYNTAX;\
34 errstr = "Invalid DN (" #i " components needed for '" #dn "')";\
39 static int map_ldb_error(struct ldb_context
*ldb
, int err
, const char **errstring
)
41 *errstring
= ldb_errstring(ldb
);
50 static int get_ldb_controls(void *mem_ctx
, struct ldap_Control
**controls
, struct ldb_control
***lcontrols
)
52 struct ldb_control
**lctrl
;
55 if (controls
== NULL
|| controls
[0] == NULL
) {
64 for (i
= 0; controls
[i
] != NULL
; i
++) {
65 lctrl
= talloc_realloc(mem_ctx
, lctrl
, struct ldb_control
*, l
+ 2);
69 lctrl
[l
] = talloc(lctrl
, struct ldb_control
);
70 if (lctrl
[l
] == NULL
) {
73 lctrl
[l
]->oid
= controls
[i
]->oid
;
74 lctrl
[l
]->critical
= controls
[i
]->critical
;
75 lctrl
[l
]->data
= controls
[i
]->value
;
86 connect to the sam database
88 NTSTATUS
ldapsrv_backend_Init(struct ldapsrv_connection
*conn
)
90 conn
->ldb
= samdb_connect(conn
, conn
->session_info
);
91 if (conn
->ldb
== NULL
) {
92 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
94 ldb_set_opaque(conn
->ldb
, "server_credentials", conn
->server_credentials
);
99 struct ldapsrv_reply
*ldapsrv_init_reply(struct ldapsrv_call
*call
, uint8_t type
)
101 struct ldapsrv_reply
*reply
;
103 reply
= talloc(call
, struct ldapsrv_reply
);
107 reply
->msg
= talloc(reply
, struct ldap_message
);
108 if (reply
->msg
== NULL
) {
113 reply
->msg
->messageid
= call
->request
->messageid
;
114 reply
->msg
->type
= type
;
115 reply
->msg
->controls
= NULL
;
120 void ldapsrv_queue_reply(struct ldapsrv_call
*call
, struct ldapsrv_reply
*reply
)
122 DLIST_ADD_END(call
->replies
, reply
, struct ldapsrv_reply
*);
125 NTSTATUS
ldapsrv_unwilling(struct ldapsrv_call
*call
, int error
)
127 struct ldapsrv_reply
*reply
;
128 struct ldap_ExtendedResponse
*r
;
130 DEBUG(10,("Unwilling type[%d] id[%d]\n", call
->request
->type
, call
->request
->messageid
));
132 reply
= ldapsrv_init_reply(call
, LDAP_TAG_ExtendedResponse
);
134 return NT_STATUS_NO_MEMORY
;
137 r
= &reply
->msg
->r
.ExtendedResponse
;
138 r
->response
.resultcode
= error
;
139 r
->response
.dn
= NULL
;
140 r
->response
.errormessage
= NULL
;
141 r
->response
.referral
= NULL
;
143 r
->value
.data
= NULL
;
146 ldapsrv_queue_reply(call
, reply
);
150 static NTSTATUS
ldapsrv_SearchRequest(struct ldapsrv_call
*call
)
152 struct ldap_SearchRequest
*req
= &call
->request
->r
.SearchRequest
;
153 struct ldap_SearchResEntry
*ent
;
154 struct ldap_Result
*done
;
155 struct ldapsrv_reply
*ent_r
, *done_r
;
157 struct ldb_context
*samdb
= call
->conn
->ldb
;
158 struct ldb_dn
*basedn
;
159 struct ldb_result
*res
= NULL
;
160 struct ldb_request lreq
;
161 enum ldb_scope scope
= LDB_SCOPE_DEFAULT
;
162 const char **attrs
= NULL
;
163 const char *errstr
= NULL
;
164 int success_limit
= 1;
165 int result
= LDAP_SUCCESS
;
169 DEBUG(10, ("SearchRequest"));
170 DEBUGADD(10, (" basedn: %s", req
->basedn
));
171 DEBUGADD(10, (" filter: %s\n", ldb_filter_from_tree(call
, req
->tree
)));
173 local_ctx
= talloc_named(call
, 0, "sldb_Search local memory context");
174 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
176 basedn
= ldb_dn_explode(local_ctx
, req
->basedn
);
177 VALID_DN_SYNTAX(basedn
, 0);
179 DEBUG(10, ("SearchRequest: basedn: [%s]\n", req
->basedn
));
180 DEBUG(10, ("SearchRequest: filter: [%s]\n", ldb_filter_from_tree(call
, req
->tree
)));
182 switch (req
->scope
) {
183 case LDAP_SEARCH_SCOPE_BASE
:
184 DEBUG(10,("SearchRequest: scope: [BASE]\n"));
185 scope
= LDB_SCOPE_BASE
;
188 case LDAP_SEARCH_SCOPE_SINGLE
:
189 DEBUG(10,("SearchRequest: scope: [ONE]\n"));
190 scope
= LDB_SCOPE_ONELEVEL
;
193 case LDAP_SEARCH_SCOPE_SUB
:
194 DEBUG(10,("SearchRequest: scope: [SUB]\n"));
195 scope
= LDB_SCOPE_SUBTREE
;
200 if (req
->num_attributes
>= 1) {
201 attrs
= talloc_array(samdb
, const char *, req
->num_attributes
+1);
202 NT_STATUS_HAVE_NO_MEMORY(attrs
);
204 for (i
=0; i
< req
->num_attributes
; i
++) {
205 DEBUG(10,("SearchRequest: attrs: [%s]\n",req
->attributes
[i
]));
206 attrs
[i
] = req
->attributes
[i
];
211 DEBUG(5,("ldb_request dn=%s filter=%s\n",
212 req
->basedn
, ldb_filter_from_tree(call
, req
->tree
)));
215 lreq
.operation
= LDB_REQ_SEARCH
;
216 lreq
.op
.search
.base
= basedn
;
217 lreq
.op
.search
.scope
= scope
;
218 lreq
.op
.search
.tree
= req
->tree
;
219 lreq
.op
.search
.attrs
= attrs
;
221 ldb_ret
= get_ldb_controls(local_ctx
, call
->request
->controls
, &lreq
.controls
);
223 if (ldb_ret
!= LDB_SUCCESS
) {
224 /* get_ldb_controls fails only on a critical internal error or when
225 * a control is defined as critical but it is not supported
230 ldb_ret
= ldb_request(samdb
, &lreq
);
232 res
= talloc_steal(samdb
, lreq
.op
.search
.res
);
234 if (ldb_ret
== LDB_SUCCESS
) {
235 for (i
= 0; i
< res
->count
; i
++) {
236 ent_r
= ldapsrv_init_reply(call
, LDAP_TAG_SearchResultEntry
);
237 NT_STATUS_HAVE_NO_MEMORY(ent_r
);
239 ent
= &ent_r
->msg
->r
.SearchResultEntry
;
240 ent
->dn
= ldb_dn_linearize(ent_r
, res
->msgs
[i
]->dn
);
241 ent
->num_attributes
= 0;
242 ent
->attributes
= NULL
;
243 if (res
->msgs
[i
]->num_elements
== 0) {
246 ent
->num_attributes
= res
->msgs
[i
]->num_elements
;
247 ent
->attributes
= talloc_array(ent_r
, struct ldb_message_element
, ent
->num_attributes
);
248 NT_STATUS_HAVE_NO_MEMORY(ent
->attributes
);
249 for (j
=0; j
< ent
->num_attributes
; j
++) {
250 ent
->attributes
[j
].name
= talloc_steal(ent
->attributes
, res
->msgs
[i
]->elements
[j
].name
);
251 ent
->attributes
[j
].num_values
= 0;
252 ent
->attributes
[j
].values
= NULL
;
253 if (req
->attributesonly
&& (res
->msgs
[i
]->elements
[j
].num_values
== 0)) {
256 ent
->attributes
[j
].num_values
= res
->msgs
[i
]->elements
[j
].num_values
;
257 ent
->attributes
[j
].values
= talloc_array(ent
->attributes
,
258 DATA_BLOB
, ent
->attributes
[j
].num_values
);
259 NT_STATUS_HAVE_NO_MEMORY(ent
->attributes
[j
].values
);
260 for (y
=0; y
< ent
->attributes
[j
].num_values
; y
++) {
261 ent
->attributes
[j
].values
[y
].length
= res
->msgs
[i
]->elements
[j
].values
[y
].length
;
262 ent
->attributes
[j
].values
[y
].data
= talloc_steal(ent
->attributes
[j
].values
,
263 res
->msgs
[i
]->elements
[j
].values
[y
].data
);
267 ldapsrv_queue_reply(call
, ent_r
);
272 done_r
= ldapsrv_init_reply(call
, LDAP_TAG_SearchResultDone
);
273 NT_STATUS_HAVE_NO_MEMORY(done_r
);
275 done
= &done_r
->msg
->r
.SearchResultDone
;
277 done
->referral
= NULL
;
279 if (ldb_ret
== LDB_SUCCESS
) {
280 if (res
->count
>= success_limit
) {
281 DEBUG(10,("SearchRequest: results: [%d]\n", res
->count
));
282 result
= LDAP_SUCCESS
;
284 } else if (res
->count
== 0) {
285 DEBUG(10,("SearchRequest: no results\n"));
286 result
= LDAP_NO_SUCH_OBJECT
;
287 errstr
= ldb_errstring(samdb
);
290 done_r
->msg
->controls
= (struct ldap_Control
**)(res
->controls
);
293 DEBUG(10,("SearchRequest: error\n"));
294 result
= map_ldb_error(samdb
, ldb_ret
, &errstr
);
297 done
->resultcode
= result
;
298 done
->errormessage
= (errstr
?talloc_strdup(done_r
, errstr
):NULL
);
300 talloc_free(local_ctx
);
302 ldapsrv_queue_reply(call
, done_r
);
306 static NTSTATUS
ldapsrv_ModifyRequest(struct ldapsrv_call
*call
)
308 struct ldap_ModifyRequest
*req
= &call
->request
->r
.ModifyRequest
;
309 struct ldap_Result
*modify_result
;
310 struct ldapsrv_reply
*modify_reply
;
312 struct ldb_context
*samdb
= call
->conn
->ldb
;
313 struct ldb_message
*msg
= NULL
;
315 const char *errstr
= NULL
;
316 int result
= LDAP_SUCCESS
;
320 DEBUG(10, ("ModifyRequest"));
321 DEBUGADD(10, (" dn: %s", req
->dn
));
323 local_ctx
= talloc_named(call
, 0, "ModifyRequest local memory context");
324 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
326 dn
= ldb_dn_explode(local_ctx
, req
->dn
);
327 VALID_DN_SYNTAX(dn
, 1);
329 DEBUG(10, ("ModifyRequest: dn: [%s]\n", req
->dn
));
331 msg
= talloc(local_ctx
, struct ldb_message
);
332 NT_STATUS_HAVE_NO_MEMORY(msg
);
335 msg
->private_data
= NULL
;
336 msg
->num_elements
= 0;
337 msg
->elements
= NULL
;
339 if (req
->num_mods
> 0) {
340 msg
->num_elements
= req
->num_mods
;
341 msg
->elements
= talloc_array(msg
, struct ldb_message_element
, req
->num_mods
);
342 NT_STATUS_HAVE_NO_MEMORY(msg
->elements
);
344 for (i
=0; i
< msg
->num_elements
; i
++) {
345 msg
->elements
[i
].name
= discard_const_p(char, req
->mods
[i
].attrib
.name
);
346 msg
->elements
[i
].num_values
= 0;
347 msg
->elements
[i
].values
= NULL
;
349 switch (req
->mods
[i
].type
) {
351 result
= LDAP_PROTOCOL_ERROR
;
352 errstr
= "Invalid LDAP_MODIFY_* type";
354 case LDAP_MODIFY_ADD
:
355 msg
->elements
[i
].flags
= LDB_FLAG_MOD_ADD
;
357 case LDAP_MODIFY_DELETE
:
358 msg
->elements
[i
].flags
= LDB_FLAG_MOD_DELETE
;
360 case LDAP_MODIFY_REPLACE
:
361 msg
->elements
[i
].flags
= LDB_FLAG_MOD_REPLACE
;
365 msg
->elements
[i
].num_values
= req
->mods
[i
].attrib
.num_values
;
366 if (msg
->elements
[i
].num_values
> 0) {
367 msg
->elements
[i
].values
= talloc_array(msg
, struct ldb_val
, msg
->elements
[i
].num_values
);
368 NT_STATUS_HAVE_NO_MEMORY(msg
->elements
[i
].values
);
370 for (j
=0; j
< msg
->elements
[i
].num_values
; j
++) {
371 if (!(req
->mods
[i
].attrib
.values
[j
].length
> 0)) {
373 errstr
= "Empty attribute values are not allowed";
376 msg
->elements
[i
].values
[j
].length
= req
->mods
[i
].attrib
.values
[j
].length
;
377 msg
->elements
[i
].values
[j
].data
= req
->mods
[i
].attrib
.values
[j
].data
;
383 errstr
= "No mods are not allowed";
388 modify_reply
= ldapsrv_init_reply(call
, LDAP_TAG_ModifyResponse
);
389 NT_STATUS_HAVE_NO_MEMORY(modify_reply
);
391 if (result
== LDAP_SUCCESS
) {
392 ldb_ret
= ldb_modify(samdb
, msg
);
393 result
= map_ldb_error(samdb
, ldb_ret
, &errstr
);
396 modify_result
= &modify_reply
->msg
->r
.AddResponse
;
397 modify_result
->dn
= NULL
;
398 modify_result
->resultcode
= result
;
399 modify_result
->errormessage
= (errstr
?talloc_strdup(modify_reply
, errstr
):NULL
);
400 modify_result
->referral
= NULL
;
402 talloc_free(local_ctx
);
404 ldapsrv_queue_reply(call
, modify_reply
);
409 static NTSTATUS
ldapsrv_AddRequest(struct ldapsrv_call
*call
)
411 struct ldap_AddRequest
*req
= &call
->request
->r
.AddRequest
;
412 struct ldap_Result
*add_result
;
413 struct ldapsrv_reply
*add_reply
;
415 struct ldb_context
*samdb
= call
->conn
->ldb
;
416 struct ldb_message
*msg
= NULL
;
418 const char *errstr
= NULL
;
419 int result
= LDAP_SUCCESS
;
423 DEBUG(10, ("AddRequest"));
424 DEBUGADD(10, (" dn: %s", req
->dn
));
426 local_ctx
= talloc_named(call
, 0, "AddRequest local memory context");
427 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
429 dn
= ldb_dn_explode(local_ctx
, req
->dn
);
430 VALID_DN_SYNTAX(dn
,1);
432 DEBUG(10, ("AddRequest: dn: [%s]\n", req
->dn
));
434 msg
= talloc(local_ctx
, struct ldb_message
);
435 NT_STATUS_HAVE_NO_MEMORY(msg
);
438 msg
->private_data
= NULL
;
439 msg
->num_elements
= 0;
440 msg
->elements
= NULL
;
442 if (req
->num_attributes
> 0) {
443 msg
->num_elements
= req
->num_attributes
;
444 msg
->elements
= talloc_array(msg
, struct ldb_message_element
, msg
->num_elements
);
445 NT_STATUS_HAVE_NO_MEMORY(msg
->elements
);
447 for (i
=0; i
< msg
->num_elements
; i
++) {
448 msg
->elements
[i
].name
= discard_const_p(char, req
->attributes
[i
].name
);
449 msg
->elements
[i
].flags
= 0;
450 msg
->elements
[i
].num_values
= 0;
451 msg
->elements
[i
].values
= NULL
;
453 if (req
->attributes
[i
].num_values
> 0) {
454 msg
->elements
[i
].num_values
= req
->attributes
[i
].num_values
;
455 msg
->elements
[i
].values
= talloc_array(msg
, struct ldb_val
, msg
->elements
[i
].num_values
);
456 NT_STATUS_HAVE_NO_MEMORY(msg
->elements
[i
].values
);
458 for (j
=0; j
< msg
->elements
[i
].num_values
; j
++) {
459 if (!(req
->attributes
[i
].values
[j
].length
> 0)) {
461 errstr
= "Empty attribute values are not allowed";
464 msg
->elements
[i
].values
[j
].length
= req
->attributes
[i
].values
[j
].length
;
465 msg
->elements
[i
].values
[j
].data
= req
->attributes
[i
].values
[j
].data
;
469 errstr
= "No attribute values are not allowed";
475 errstr
= "No attributes are not allowed";
480 add_reply
= ldapsrv_init_reply(call
, LDAP_TAG_AddResponse
);
481 NT_STATUS_HAVE_NO_MEMORY(add_reply
);
483 if (result
== LDAP_SUCCESS
) {
484 ldb_ret
= ldb_add(samdb
, msg
);
485 result
= map_ldb_error(samdb
, ldb_ret
, &errstr
);
488 add_result
= &add_reply
->msg
->r
.AddResponse
;
489 add_result
->dn
= NULL
;
490 add_result
->resultcode
= result
;
491 add_result
->errormessage
= (errstr
?talloc_strdup(add_reply
,errstr
):NULL
);
492 add_result
->referral
= NULL
;
494 talloc_free(local_ctx
);
496 ldapsrv_queue_reply(call
, add_reply
);
501 static NTSTATUS
ldapsrv_DelRequest(struct ldapsrv_call
*call
)
503 struct ldap_DelRequest
*req
= &call
->request
->r
.DelRequest
;
504 struct ldap_Result
*del_result
;
505 struct ldapsrv_reply
*del_reply
;
507 struct ldb_context
*samdb
= call
->conn
->ldb
;
509 const char *errstr
= NULL
;
510 int result
= LDAP_SUCCESS
;
513 DEBUG(10, ("DelRequest"));
514 DEBUGADD(10, (" dn: %s", req
->dn
));
516 local_ctx
= talloc_named(call
, 0, "DelRequest local memory context");
517 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
519 dn
= ldb_dn_explode(local_ctx
, req
->dn
);
520 VALID_DN_SYNTAX(dn
,1);
522 DEBUG(10, ("DelRequest: dn: [%s]\n", req
->dn
));
525 del_reply
= ldapsrv_init_reply(call
, LDAP_TAG_DelResponse
);
526 NT_STATUS_HAVE_NO_MEMORY(del_reply
);
528 if (result
== LDAP_SUCCESS
) {
529 ldb_ret
= ldb_delete(samdb
, dn
);
530 result
= map_ldb_error(samdb
, ldb_ret
, &errstr
);
533 del_result
= &del_reply
->msg
->r
.DelResponse
;
534 del_result
->dn
= NULL
;
535 del_result
->resultcode
= result
;
536 del_result
->errormessage
= (errstr
?talloc_strdup(del_reply
,errstr
):NULL
);
537 del_result
->referral
= NULL
;
539 talloc_free(local_ctx
);
541 ldapsrv_queue_reply(call
, del_reply
);
545 static NTSTATUS
ldapsrv_ModifyDNRequest(struct ldapsrv_call
*call
)
547 struct ldap_ModifyDNRequest
*req
= &call
->request
->r
.ModifyDNRequest
;
548 struct ldap_Result
*modifydn
;
549 struct ldapsrv_reply
*modifydn_r
;
551 struct ldb_context
*samdb
= call
->conn
->ldb
;
552 struct ldb_dn
*olddn
, *newdn
, *newrdn
;
553 struct ldb_dn
*parentdn
= NULL
;
554 const char *errstr
= NULL
;
555 int result
= LDAP_SUCCESS
;
558 DEBUG(10, ("ModifyDNRequrest"));
559 DEBUGADD(10, (" dn: %s", req
->dn
));
560 DEBUGADD(10, (" newrdn: %s", req
->newrdn
));
562 local_ctx
= talloc_named(call
, 0, "ModifyDNRequest local memory context");
563 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
565 olddn
= ldb_dn_explode(local_ctx
, req
->dn
);
566 VALID_DN_SYNTAX(olddn
, 2);
568 newrdn
= ldb_dn_explode(local_ctx
, req
->newrdn
);
569 VALID_DN_SYNTAX(newrdn
, 1);
571 DEBUG(10, ("ModifyDNRequest: olddn: [%s]\n", req
->dn
));
572 DEBUG(10, ("ModifyDNRequest: newrdn: [%s]\n", req
->newrdn
));
574 /* we can't handle the rename if we should not remove the old dn */
575 if (!req
->deleteolddn
) {
576 result
= LDAP_UNWILLING_TO_PERFORM
;
577 errstr
= "Old RDN must be deleted";
581 if (newrdn
->comp_num
> 1) {
582 result
= LDAP_NAMING_VIOLATION
;
583 errstr
= "Error new RDN invalid";
587 if (req
->newsuperior
) {
588 parentdn
= ldb_dn_explode(local_ctx
, req
->newsuperior
);
589 VALID_DN_SYNTAX(parentdn
, 0);
590 DEBUG(10, ("ModifyDNRequest: newsuperior: [%s]\n", req
->newsuperior
));
592 if (parentdn
->comp_num
< 1) {
593 result
= LDAP_AFFECTS_MULTIPLE_DSAS
;
594 errstr
= "Error new Superior DN invalid";
600 parentdn
= ldb_dn_get_parent(local_ctx
, olddn
);
601 NT_STATUS_HAVE_NO_MEMORY(parentdn
);
604 newdn
= ldb_dn_make_child(local_ctx
, ldb_dn_get_rdn(local_ctx
, newrdn
), parentdn
);
605 NT_STATUS_HAVE_NO_MEMORY(newdn
);
608 modifydn_r
= ldapsrv_init_reply(call
, LDAP_TAG_ModifyDNResponse
);
609 NT_STATUS_HAVE_NO_MEMORY(modifydn_r
);
611 if (result
== LDAP_SUCCESS
) {
612 ldb_ret
= ldb_rename(samdb
, olddn
, newdn
);
613 result
= map_ldb_error(samdb
, ldb_ret
, &errstr
);
616 modifydn
= &modifydn_r
->msg
->r
.ModifyDNResponse
;
618 modifydn
->resultcode
= result
;
619 modifydn
->errormessage
= (errstr
?talloc_strdup(modifydn_r
,errstr
):NULL
);
620 modifydn
->referral
= NULL
;
622 talloc_free(local_ctx
);
624 ldapsrv_queue_reply(call
, modifydn_r
);
628 static NTSTATUS
ldapsrv_CompareRequest(struct ldapsrv_call
*call
)
630 struct ldap_CompareRequest
*req
= &call
->request
->r
.CompareRequest
;
631 struct ldap_Result
*compare
;
632 struct ldapsrv_reply
*compare_r
;
634 struct ldb_context
*samdb
= call
->conn
->ldb
;
635 struct ldb_result
*res
= NULL
;
637 const char *attrs
[1];
638 const char *errstr
= NULL
;
639 const char *filter
= NULL
;
640 int result
= LDAP_SUCCESS
;
643 DEBUG(10, ("CompareRequest"));
644 DEBUGADD(10, (" dn: %s", req
->dn
));
646 local_ctx
= talloc_named(call
, 0, "CompareRequest local_memory_context");
647 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
649 dn
= ldb_dn_explode(local_ctx
, req
->dn
);
650 VALID_DN_SYNTAX(dn
, 1);
652 DEBUG(10, ("CompareRequest: dn: [%s]\n", req
->dn
));
653 filter
= talloc_asprintf(local_ctx
, "(%s=%*s)", req
->attribute
,
654 (int)req
->value
.length
, req
->value
.data
);
655 NT_STATUS_HAVE_NO_MEMORY(filter
);
657 DEBUGADD(10, ("CompareRequest: attribute: [%s]\n", filter
));
662 compare_r
= ldapsrv_init_reply(call
, LDAP_TAG_CompareResponse
);
663 NT_STATUS_HAVE_NO_MEMORY(compare_r
);
665 if (result
== LDAP_SUCCESS
) {
666 ldb_ret
= ldb_search(samdb
, dn
, LDB_SCOPE_BASE
, filter
, attrs
, &res
);
667 talloc_steal(samdb
, res
);
668 if (ldb_ret
!= LDB_SUCCESS
) {
669 result
= map_ldb_error(samdb
, ldb_ret
, &errstr
);
670 DEBUG(10,("CompareRequest: error: %s\n", errstr
));
671 } else if (res
->count
== 0) {
672 DEBUG(10,("CompareRequest: doesn't matched\n"));
673 result
= LDAP_COMPARE_FALSE
;
675 } else if (res
->count
== 1) {
676 DEBUG(10,("CompareRequest: matched\n"));
677 result
= LDAP_COMPARE_TRUE
;
679 } else if (res
->count
> 1) {
681 errstr
= "too many objects match";
682 DEBUG(10,("CompareRequest: %d results: %s\n", res
->count
, errstr
));
686 compare
= &compare_r
->msg
->r
.CompareResponse
;
688 compare
->resultcode
= result
;
689 compare
->errormessage
= (errstr
?talloc_strdup(compare_r
,errstr
):NULL
);
690 compare
->referral
= NULL
;
692 talloc_free(local_ctx
);
694 ldapsrv_queue_reply(call
, compare_r
);
698 static NTSTATUS
ldapsrv_AbandonRequest(struct ldapsrv_call
*call
)
700 /* struct ldap_AbandonRequest *req = &call->request.r.AbandonRequest;*/
701 DEBUG(10, ("AbandonRequest\n"));
705 static NTSTATUS
ldapsrv_ExtendedRequest(struct ldapsrv_call
*call
)
707 /* struct ldap_ExtendedRequest *req = &call->request.r.ExtendedRequest;*/
708 struct ldapsrv_reply
*reply
;
710 DEBUG(10, ("Extended\n"));
712 reply
= ldapsrv_init_reply(call
, LDAP_TAG_ExtendedResponse
);
714 return NT_STATUS_NO_MEMORY
;
717 ZERO_STRUCT(reply
->msg
->r
);
719 ldapsrv_queue_reply(call
, reply
);
723 NTSTATUS
ldapsrv_do_call(struct ldapsrv_call
*call
)
725 switch(call
->request
->type
) {
726 case LDAP_TAG_BindRequest
:
727 return ldapsrv_BindRequest(call
);
728 case LDAP_TAG_UnbindRequest
:
729 return ldapsrv_UnbindRequest(call
);
730 case LDAP_TAG_SearchRequest
:
731 return ldapsrv_SearchRequest(call
);
732 case LDAP_TAG_ModifyRequest
:
733 return ldapsrv_ModifyRequest(call
);
734 case LDAP_TAG_AddRequest
:
735 return ldapsrv_AddRequest(call
);
736 case LDAP_TAG_DelRequest
:
737 return ldapsrv_DelRequest(call
);
738 case LDAP_TAG_ModifyDNRequest
:
739 return ldapsrv_ModifyDNRequest(call
);
740 case LDAP_TAG_CompareRequest
:
741 return ldapsrv_CompareRequest(call
);
742 case LDAP_TAG_AbandonRequest
:
743 return ldapsrv_AbandonRequest(call
);
744 case LDAP_TAG_ExtendedRequest
:
745 return ldapsrv_ExtendedRequest(call
);
747 return ldapsrv_unwilling(call
, 2);