s4:rpc_server: only pass dcesrv_auth to auth_state.session_key_fn()
[samba.git] / source4 / ldap_server / ldap_backend.c
1 /* 
2    Unix SMB/CIFS implementation.
3    LDAP server
4    Copyright (C) Stefan Metzmacher 2004
5    Copyright (C) Matthias Dieter Wallnöfer 2009
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "ldap_server/ldap_server.h"
23 #include "../lib/util/dlinklist.h"
24 #include "auth/credentials/credentials.h"
25 #include "auth/gensec/gensec.h"
26 #include "auth/gensec/gensec_internal.h" /* TODO: remove this */
27 #include "auth/common_auth.h"
28 #include "param/param.h"
29 #include "smbd/service_stream.h"
30 #include "dsdb/samdb/samdb.h"
31 #include <ldb_errors.h>
32 #include <ldb_module.h>
33 #include "ldb_wrap.h"
34 #include "lib/tsocket/tsocket.h"
35
36 static int map_ldb_error(TALLOC_CTX *mem_ctx, int ldb_err,
37         const char *add_err_string, const char **errstring)
38 {
39         WERROR err;
40
41         /* Certain LDB modules need to return very special WERROR codes. Proof
42          * for them here and if they exist skip the rest of the mapping. */
43         if (add_err_string != NULL) {
44                 char *endptr;
45                 strtol(add_err_string, &endptr, 16);
46                 if (endptr != add_err_string) {
47                         *errstring = add_err_string;
48                         return ldb_err;
49                 }
50         }
51
52         /* Otherwise we calculate here a generic, but appropriate WERROR. */
53
54         switch (ldb_err) {
55         case LDB_SUCCESS:
56                 err = WERR_OK;
57         break;
58         case LDB_ERR_OPERATIONS_ERROR:
59                 err = WERR_DS_OPERATIONS_ERROR;
60         break;
61         case LDB_ERR_PROTOCOL_ERROR:
62                 err = WERR_DS_PROTOCOL_ERROR;
63         break;
64         case LDB_ERR_TIME_LIMIT_EXCEEDED:
65                 err = WERR_DS_TIMELIMIT_EXCEEDED;
66         break;
67         case LDB_ERR_SIZE_LIMIT_EXCEEDED:
68                 err = WERR_DS_SIZELIMIT_EXCEEDED;
69         break;
70         case LDB_ERR_COMPARE_FALSE:
71                 err = WERR_DS_COMPARE_FALSE;
72         break;
73         case LDB_ERR_COMPARE_TRUE:
74                 err = WERR_DS_COMPARE_TRUE;
75         break;
76         case LDB_ERR_AUTH_METHOD_NOT_SUPPORTED:
77                 err = WERR_DS_AUTH_METHOD_NOT_SUPPORTED;
78         break;
79         case LDB_ERR_STRONG_AUTH_REQUIRED:
80                 err = WERR_DS_STRONG_AUTH_REQUIRED;
81         break;
82         case LDB_ERR_REFERRAL:
83                 err = WERR_DS_REFERRAL;
84         break;
85         case LDB_ERR_ADMIN_LIMIT_EXCEEDED:
86                 err = WERR_DS_ADMIN_LIMIT_EXCEEDED;
87         break;
88         case LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION:
89                 err = WERR_DS_UNAVAILABLE_CRIT_EXTENSION;
90         break;
91         case LDB_ERR_CONFIDENTIALITY_REQUIRED:
92                 err = WERR_DS_CONFIDENTIALITY_REQUIRED;
93         break;
94         case LDB_ERR_SASL_BIND_IN_PROGRESS:
95                 err = WERR_DS_BUSY;
96         break;
97         case LDB_ERR_NO_SUCH_ATTRIBUTE:
98                 err = WERR_DS_NO_ATTRIBUTE_OR_VALUE;
99         break;
100         case LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE:
101                 err = WERR_DS_ATTRIBUTE_TYPE_UNDEFINED;
102         break;
103         case LDB_ERR_INAPPROPRIATE_MATCHING:
104                 err = WERR_DS_INAPPROPRIATE_MATCHING;
105         break;
106         case LDB_ERR_CONSTRAINT_VIOLATION:
107                 err = WERR_DS_CONSTRAINT_VIOLATION;
108         break;
109         case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
110                 err = WERR_DS_ATTRIBUTE_OR_VALUE_EXISTS;
111         break;
112         case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX:
113                 err = WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
114         break;
115         case LDB_ERR_NO_SUCH_OBJECT:
116                 err = WERR_DS_NO_SUCH_OBJECT;
117         break;
118         case LDB_ERR_ALIAS_PROBLEM:
119                 err = WERR_DS_ALIAS_PROBLEM;
120         break;
121         case LDB_ERR_INVALID_DN_SYNTAX:
122                 err = WERR_DS_INVALID_DN_SYNTAX;
123         break;
124         case LDB_ERR_ALIAS_DEREFERENCING_PROBLEM:
125                 err = WERR_DS_ALIAS_DEREF_PROBLEM;
126         break;
127         case LDB_ERR_INAPPROPRIATE_AUTHENTICATION:
128                 err = WERR_DS_INAPPROPRIATE_AUTH;
129         break;
130         case LDB_ERR_INVALID_CREDENTIALS:
131                 err = WERR_ACCESS_DENIED;
132         break;
133         case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
134                 err = WERR_DS_INSUFF_ACCESS_RIGHTS;
135         break;
136         case LDB_ERR_BUSY:
137                 err = WERR_DS_BUSY;
138         break;
139         case LDB_ERR_UNAVAILABLE:
140                 err = WERR_DS_UNAVAILABLE;
141         break;
142         case LDB_ERR_UNWILLING_TO_PERFORM:
143                 err = WERR_DS_UNWILLING_TO_PERFORM;
144         break;
145         case LDB_ERR_LOOP_DETECT:
146                 err = WERR_DS_LOOP_DETECT;
147         break;
148         case LDB_ERR_NAMING_VIOLATION:
149                 err = WERR_DS_NAMING_VIOLATION;
150         break;
151         case LDB_ERR_OBJECT_CLASS_VIOLATION:
152                 err = WERR_DS_OBJ_CLASS_VIOLATION;
153         break;
154         case LDB_ERR_NOT_ALLOWED_ON_NON_LEAF:
155                 err = WERR_DS_CANT_ON_NON_LEAF;
156         break;
157         case LDB_ERR_NOT_ALLOWED_ON_RDN:
158                 err = WERR_DS_CANT_ON_RDN;
159         break;
160         case LDB_ERR_ENTRY_ALREADY_EXISTS:
161                 err = WERR_DS_OBJ_STRING_NAME_EXISTS;
162         break;
163         case LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED:
164                 err = WERR_DS_CANT_MOD_OBJ_CLASS;
165         break;
166         case LDB_ERR_AFFECTS_MULTIPLE_DSAS:
167                 err = WERR_DS_AFFECTS_MULTIPLE_DSAS;
168         break;
169         default:
170                 err = WERR_DS_GENERIC_ERROR;
171         break;
172         }
173
174         *errstring = talloc_asprintf(mem_ctx, "%08X: %s", W_ERROR_V(err),
175                 add_err_string != NULL ? add_err_string : ldb_strerror(ldb_err));
176
177         /* result is 1:1 for now */
178         return ldb_err;
179 }
180
181 /*
182   connect to the sam database
183 */
184 int ldapsrv_backend_Init(struct ldapsrv_connection *conn,
185                               char **errstring)
186 {
187         int ret = samdb_connect_url(conn,
188                                     conn->connection->event.ctx,
189                                     conn->lp_ctx,
190                                     conn->session_info,
191                                     conn->global_catalog ? LDB_FLG_RDONLY : 0,
192                                     "sam.ldb",
193                                     conn->connection->remote_address,
194                                     &conn->ldb,
195                                     errstring);
196         if (ret != LDB_SUCCESS) {
197                 return ret;
198         }
199
200         if (conn->server_credentials) {
201                 char **sasl_mechs = NULL;
202                 const struct gensec_security_ops * const *backends = gensec_security_all();
203                 const struct gensec_security_ops **ops
204                         = gensec_use_kerberos_mechs(conn, backends, conn->server_credentials);
205                 unsigned int i, j = 0;
206                 for (i = 0; ops && ops[i]; i++) {
207                         if (!lpcfg_parm_bool(conn->lp_ctx,  NULL, "gensec", ops[i]->name, ops[i]->enabled))
208                                 continue;
209
210                         if (ops[i]->sasl_name && ops[i]->server_start) {
211                                 char *sasl_name = talloc_strdup(conn, ops[i]->sasl_name);
212
213                                 if (!sasl_name) {
214                                         return LDB_ERR_OPERATIONS_ERROR;
215                                 }
216                                 sasl_mechs = talloc_realloc(conn, sasl_mechs, char *, j + 2);
217                                 if (!sasl_mechs) {
218                                         return LDB_ERR_OPERATIONS_ERROR;
219                                 }
220                                 sasl_mechs[j] = sasl_name;
221                                 talloc_steal(sasl_mechs, sasl_name);
222                                 sasl_mechs[j+1] = NULL;
223                                 j++;
224                         }
225                 }
226                 talloc_unlink(conn, ops);
227
228                 /* ldb can have a different lifetime to conn, so we
229                    need to ensure that sasl_mechs lives as long as the
230                    ldb does */
231                 talloc_steal(conn->ldb, sasl_mechs);
232
233                 ldb_set_opaque(conn->ldb, "supportedSASLMechanisms", sasl_mechs);
234         }
235
236         return LDB_SUCCESS;
237 }
238
239 struct ldapsrv_reply *ldapsrv_init_reply(struct ldapsrv_call *call, uint8_t type)
240 {
241         struct ldapsrv_reply *reply;
242
243         reply = talloc_zero(call, struct ldapsrv_reply);
244         if (!reply) {
245                 return NULL;
246         }
247         reply->msg = talloc_zero(reply, struct ldap_message);
248         if (reply->msg == NULL) {
249                 talloc_free(reply);
250                 return NULL;
251         }
252
253         reply->msg->messageid = call->request->messageid;
254         reply->msg->type = type;
255         reply->msg->controls = NULL;
256
257         return reply;
258 }
259
260 void ldapsrv_queue_reply(struct ldapsrv_call *call, struct ldapsrv_reply *reply)
261 {
262         DLIST_ADD_END(call->replies, reply);
263 }
264
265 static NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
266 {
267         struct ldapsrv_reply *reply;
268         struct ldap_ExtendedResponse *r;
269
270         DEBUG(10,("Unwilling type[%d] id[%d]\n", call->request->type, call->request->messageid));
271
272         reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
273         if (!reply) {
274                 return NT_STATUS_NO_MEMORY;
275         }
276
277         r = &reply->msg->r.ExtendedResponse;
278         r->response.resultcode = error;
279         r->response.dn = NULL;
280         r->response.errormessage = NULL;
281         r->response.referral = NULL;
282         r->oid = NULL;
283         r->value = NULL;
284
285         ldapsrv_queue_reply(call, reply);
286         return NT_STATUS_OK;
287 }
288
289 static int ldapsrv_add_with_controls(struct ldapsrv_call *call,
290                                      const struct ldb_message *message,
291                                      struct ldb_control **controls,
292                                      struct ldb_result *res)
293 {
294         struct ldb_context *ldb = call->conn->ldb;
295         struct ldb_request *req;
296         int ret;
297
298         ret = ldb_msg_sanity_check(ldb, message);
299         if (ret != LDB_SUCCESS) {
300                 return ret;
301         }
302
303         ret = ldb_build_add_req(&req, ldb, ldb,
304                                         message,
305                                         controls,
306                                         res,
307                                         ldb_modify_default_callback,
308                                         NULL);
309
310         if (ret != LDB_SUCCESS) return ret;
311
312         if (call->conn->global_catalog) {
313                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
314         }
315         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
316
317         ret = ldb_transaction_start(ldb);
318         if (ret != LDB_SUCCESS) {
319                 return ret;
320         }
321
322         if (!call->conn->is_privileged) {
323                 ldb_req_mark_untrusted(req);
324         }
325
326         LDB_REQ_SET_LOCATION(req);
327
328         ret = ldb_request(ldb, req);
329         if (ret == LDB_SUCCESS) {
330                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
331         }
332
333         if (ret == LDB_SUCCESS) {
334                 ret = ldb_transaction_commit(ldb);
335         }
336         else {
337                 ldb_transaction_cancel(ldb);
338         }
339
340         talloc_free(req);
341         return ret;
342 }
343
344 /* create and execute a modify request */
345 static int ldapsrv_mod_with_controls(struct ldapsrv_call *call,
346                                      const struct ldb_message *message,
347                                      struct ldb_control **controls,
348                                      struct ldb_result *res)
349 {
350         struct ldb_context *ldb = call->conn->ldb;
351         struct ldb_request *req;
352         int ret;
353
354         ret = ldb_msg_sanity_check(ldb, message);
355         if (ret != LDB_SUCCESS) {
356                 return ret;
357         }
358
359         ret = ldb_build_mod_req(&req, ldb, ldb,
360                                         message,
361                                         controls,
362                                         res,
363                                         ldb_modify_default_callback,
364                                         NULL);
365
366         if (ret != LDB_SUCCESS) {
367                 return ret;
368         }
369
370         if (call->conn->global_catalog) {
371                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
372         }
373         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
374
375         ret = ldb_transaction_start(ldb);
376         if (ret != LDB_SUCCESS) {
377                 return ret;
378         }
379
380         if (!call->conn->is_privileged) {
381                 ldb_req_mark_untrusted(req);
382         }
383
384         LDB_REQ_SET_LOCATION(req);
385
386         ret = ldb_request(ldb, req);
387         if (ret == LDB_SUCCESS) {
388                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
389         }
390
391         if (ret == LDB_SUCCESS) {
392                 ret = ldb_transaction_commit(ldb);
393         }
394         else {
395                 ldb_transaction_cancel(ldb);
396         }
397
398         talloc_free(req);
399         return ret;
400 }
401
402 /* create and execute a delete request */
403 static int ldapsrv_del_with_controls(struct ldapsrv_call *call,
404                                      struct ldb_dn *dn,
405                                      struct ldb_control **controls,
406                                      struct ldb_result *res)
407 {
408         struct ldb_context *ldb = call->conn->ldb;
409         struct ldb_request *req;
410         int ret;
411
412         ret = ldb_build_del_req(&req, ldb, ldb,
413                                         dn,
414                                         controls,
415                                         res,
416                                         ldb_modify_default_callback,
417                                         NULL);
418
419         if (ret != LDB_SUCCESS) return ret;
420
421         if (call->conn->global_catalog) {
422                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
423         }
424         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
425
426         ret = ldb_transaction_start(ldb);
427         if (ret != LDB_SUCCESS) {
428                 return ret;
429         }
430
431         if (!call->conn->is_privileged) {
432                 ldb_req_mark_untrusted(req);
433         }
434
435         LDB_REQ_SET_LOCATION(req);
436
437         ret = ldb_request(ldb, req);
438         if (ret == LDB_SUCCESS) {
439                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
440         }
441
442         if (ret == LDB_SUCCESS) {
443                 ret = ldb_transaction_commit(ldb);
444         }
445         else {
446                 ldb_transaction_cancel(ldb);
447         }
448
449         talloc_free(req);
450         return ret;
451 }
452
453 static int ldapsrv_rename_with_controls(struct ldapsrv_call *call,
454                                         struct ldb_dn *olddn,
455                                         struct ldb_dn *newdn,
456                                         struct ldb_control **controls,
457                                         struct ldb_result *res)
458 {
459         struct ldb_context *ldb = call->conn->ldb;
460         struct ldb_request *req;
461         int ret;
462
463         ret = ldb_build_rename_req(&req, ldb, ldb,
464                                         olddn,
465                                         newdn,
466                                         controls,
467                                         res,
468                                         ldb_modify_default_callback,
469                                         NULL);
470
471         if (ret != LDB_SUCCESS) return ret;
472
473         if (call->conn->global_catalog) {
474                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
475         }
476         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
477
478         ret = ldb_transaction_start(ldb);
479         if (ret != LDB_SUCCESS) {
480                 return ret;
481         }
482
483         if (!call->conn->is_privileged) {
484                 ldb_req_mark_untrusted(req);
485         }
486
487         LDB_REQ_SET_LOCATION(req);
488
489         ret = ldb_request(ldb, req);
490         if (ret == LDB_SUCCESS) {
491                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
492         }
493
494         if (ret == LDB_SUCCESS) {
495                 ret = ldb_transaction_commit(ldb);
496         }
497         else {
498                 ldb_transaction_cancel(ldb);
499         }
500
501         talloc_free(req);
502         return ret;
503 }
504
505 static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
506 {
507         struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
508         struct ldap_SearchResEntry *ent;
509         struct ldap_Result *done;
510         struct ldapsrv_reply *ent_r, *done_r;
511         TALLOC_CTX *local_ctx;
512         struct ldb_context *samdb = talloc_get_type(call->conn->ldb, struct ldb_context);
513         struct ldb_dn *basedn;
514         struct ldb_result *res = NULL;
515         struct ldb_request *lreq;
516         struct ldb_control *search_control;
517         struct ldb_search_options_control *search_options;
518         struct ldb_control *extended_dn_control;
519         struct ldb_extended_dn_control *extended_dn_decoded = NULL;
520         struct ldb_control *notification_control = NULL;
521         enum ldb_scope scope = LDB_SCOPE_DEFAULT;
522         const char **attrs = NULL;
523         const char *scope_str, *errstr = NULL;
524         int success_limit = 1;
525         int result = -1;
526         int ldb_ret = -1;
527         unsigned int i, j;
528         int extended_type = 1;
529
530         DEBUG(10, ("SearchRequest"));
531         DEBUGADD(10, (" basedn: %s", req->basedn));
532         DEBUGADD(10, (" filter: %s\n", ldb_filter_from_tree(call, req->tree)));
533
534         local_ctx = talloc_new(call);
535         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
536
537         basedn = ldb_dn_new(local_ctx, samdb, req->basedn);
538         NT_STATUS_HAVE_NO_MEMORY(basedn);
539
540         DEBUG(10, ("SearchRequest: basedn: [%s]\n", req->basedn));
541         DEBUG(10, ("SearchRequest: filter: [%s]\n", ldb_filter_from_tree(call, req->tree)));
542
543         switch (req->scope) {
544                 case LDAP_SEARCH_SCOPE_BASE:
545                         scope_str = "BASE";
546                         scope = LDB_SCOPE_BASE;
547                         success_limit = 0;
548                         break;
549                 case LDAP_SEARCH_SCOPE_SINGLE:
550                         scope_str = "ONE";
551                         scope = LDB_SCOPE_ONELEVEL;
552                         success_limit = 0;
553                         break;
554                 case LDAP_SEARCH_SCOPE_SUB:
555                         scope_str = "SUB";
556                         scope = LDB_SCOPE_SUBTREE;
557                         success_limit = 0;
558                         break;
559                 default:
560                         result = LDAP_PROTOCOL_ERROR;
561                         map_ldb_error(local_ctx, LDB_ERR_PROTOCOL_ERROR, NULL,
562                                 &errstr);
563                         errstr = talloc_asprintf(local_ctx,
564                                 "%s. Invalid scope", errstr);
565                         goto reply;
566         }
567         DEBUG(10,("SearchRequest: scope: [%s]\n", scope_str));
568
569         if (req->num_attributes >= 1) {
570                 attrs = talloc_array(local_ctx, const char *, req->num_attributes+1);
571                 NT_STATUS_HAVE_NO_MEMORY(attrs);
572
573                 for (i=0; i < req->num_attributes; i++) {
574                         DEBUG(10,("SearchRequest: attrs: [%s]\n",req->attributes[i]));
575                         attrs[i] = req->attributes[i];
576                 }
577                 attrs[i] = NULL;
578         }
579
580         DEBUG(5,("ldb_request %s dn=%s filter=%s\n", 
581                  scope_str, req->basedn, ldb_filter_from_tree(call, req->tree)));
582
583         res = talloc_zero(local_ctx, struct ldb_result);
584         NT_STATUS_HAVE_NO_MEMORY(res);
585
586         ldb_ret = ldb_build_search_req_ex(&lreq, samdb, local_ctx,
587                                           basedn, scope,
588                                           req->tree, attrs,
589                                           call->request->controls,
590                                           res, ldb_search_default_callback,
591                                           NULL);
592
593         if (ldb_ret != LDB_SUCCESS) {
594                 goto reply;
595         }
596
597         if (call->conn->global_catalog) {
598                 search_control = ldb_request_get_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID);
599
600                 search_options = NULL;
601                 if (search_control) {
602                         search_options = talloc_get_type(search_control->data, struct ldb_search_options_control);
603                         search_options->search_options |= LDB_SEARCH_OPTION_PHANTOM_ROOT;
604                 } else {
605                         search_options = talloc(lreq, struct ldb_search_options_control);
606                         NT_STATUS_HAVE_NO_MEMORY(search_options);
607                         search_options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
608                         ldb_request_add_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID, false, search_options);
609                 }
610         } else {
611                 ldb_request_add_control(lreq, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
612         }
613
614         extended_dn_control = ldb_request_get_control(lreq, LDB_CONTROL_EXTENDED_DN_OID);
615
616         if (extended_dn_control) {
617                 if (extended_dn_control->data) {
618                         extended_dn_decoded = talloc_get_type(extended_dn_control->data, struct ldb_extended_dn_control);
619                         extended_type = extended_dn_decoded->type;
620                 } else {
621                         extended_type = 0;
622                 }
623         }
624
625         notification_control = ldb_request_get_control(lreq, LDB_CONTROL_NOTIFICATION_OID);
626         if (notification_control != NULL) {
627                 const struct ldapsrv_call *pc = NULL;
628                 size_t count = 0;
629
630                 for (pc = call->conn->pending_calls; pc != NULL; pc = pc->next) {
631                         count += 1;
632                 }
633
634                 if (count >= call->conn->limits.max_notifications) {
635                         DEBUG(10,("SearchRequest: error MaxNotificationPerConn\n"));
636                         result = map_ldb_error(local_ctx,
637                                                LDB_ERR_ADMIN_LIMIT_EXCEEDED,
638                                                "MaxNotificationPerConn reached",
639                                                &errstr);
640                         goto reply;
641                 }
642
643                 /*
644                  * For now we need to do periodic retries on our own.
645                  * As the dsdb_notification module will return after each run.
646                  */
647                 call->notification.busy = true;
648         }
649
650         ldb_set_timeout(samdb, lreq, req->timelimit);
651
652         if (!call->conn->is_privileged) {
653                 ldb_req_mark_untrusted(lreq);
654         }
655
656         LDB_REQ_SET_LOCATION(lreq);
657
658         ldb_ret = ldb_request(samdb, lreq);
659
660         if (ldb_ret != LDB_SUCCESS) {
661                 goto reply;
662         }
663
664         ldb_ret = ldb_wait(lreq->handle, LDB_WAIT_ALL);
665
666         if (ldb_ret == LDB_SUCCESS) {
667                 for (i = 0; i < res->count; i++) {
668                         ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
669                         NT_STATUS_HAVE_NO_MEMORY(ent_r);
670
671                         /* Better to have the whole message kept here,
672                          * than to find someone further up didn't put
673                          * a value in the right spot in the talloc tree */
674                         talloc_steal(ent_r, res->msgs[i]);
675                         
676                         ent = &ent_r->msg->r.SearchResultEntry;
677                         ent->dn = ldb_dn_get_extended_linearized(ent_r, res->msgs[i]->dn, extended_type);
678                         ent->num_attributes = 0;
679                         ent->attributes = NULL;
680                         if (res->msgs[i]->num_elements == 0) {
681                                 goto queue_reply;
682                         }
683                         ent->num_attributes = res->msgs[i]->num_elements;
684                         ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes);
685                         NT_STATUS_HAVE_NO_MEMORY(ent->attributes);
686                         for (j=0; j < ent->num_attributes; j++) {
687                                 ent->attributes[j].name = res->msgs[i]->elements[j].name;
688                                 ent->attributes[j].num_values = 0;
689                                 ent->attributes[j].values = NULL;
690                                 if (req->attributesonly && (res->msgs[i]->elements[j].num_values == 0)) {
691                                         continue;
692                                 }
693                                 ent->attributes[j].num_values = res->msgs[i]->elements[j].num_values;
694                                 ent->attributes[j].values = res->msgs[i]->elements[j].values;
695                         }
696 queue_reply:
697                         ldapsrv_queue_reply(call, ent_r);
698                 }
699
700                 if (call->notification.busy) {
701                         /* Move/Add it to the end */
702                         DLIST_DEMOTE(call->conn->pending_calls, call);
703                         call->notification.generation =
704                                 call->conn->service->notification.generation;
705
706                         if (res->count != 0) {
707                                 call->notification.generation += 1;
708                                 ldapsrv_notification_retry_setup(call->conn->service,
709                                                                  true);
710                         }
711
712                         talloc_free(local_ctx);
713                         return NT_STATUS_OK;
714                 }
715
716                 /* Send back referrals if they do exist (search operations) */
717                 if (res->refs != NULL) {
718                         char **ref;
719                         struct ldap_SearchResRef *ent_ref;
720
721                         for (ref = res->refs; *ref != NULL; ++ref) {
722                                 ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultReference);
723                                 NT_STATUS_HAVE_NO_MEMORY(ent_r);
724
725                                 /* Better to have the whole referrals kept here,
726                                  * than to find someone further up didn't put
727                                  * a value in the right spot in the talloc tree
728                                  */
729                                 talloc_steal(ent_r, *ref);
730
731                                 ent_ref = &ent_r->msg->r.SearchResultReference;
732                                 ent_ref->referral = *ref;
733
734                                 ldapsrv_queue_reply(call, ent_r);
735                         }
736                 }
737         }
738
739 reply:
740         DLIST_REMOVE(call->conn->pending_calls, call);
741         call->notification.busy = false;
742
743         done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
744         NT_STATUS_HAVE_NO_MEMORY(done_r);
745
746         done = &done_r->msg->r.SearchResultDone;
747         done->dn = NULL;
748         done->referral = NULL;
749
750         if (result != -1) {
751         } else if (ldb_ret == LDB_SUCCESS) {
752                 if (res->count >= success_limit) {
753                         DEBUG(10,("SearchRequest: results: [%d]\n", res->count));
754                         result = LDAP_SUCCESS;
755                         errstr = NULL;
756                 }
757                 if (res->controls) {
758                         done_r->msg->controls = res->controls;
759                         talloc_steal(done_r, res->controls);
760                 }
761         } else {
762                 DEBUG(10,("SearchRequest: error\n"));
763                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
764                                        &errstr);
765         }
766
767         done->resultcode = result;
768         done->errormessage = (errstr?talloc_strdup(done_r, errstr):NULL);
769
770         talloc_free(local_ctx);
771
772         ldapsrv_queue_reply(call, done_r);
773         return NT_STATUS_OK;
774 }
775
776 static NTSTATUS ldapsrv_ModifyRequest(struct ldapsrv_call *call)
777 {
778         struct ldap_ModifyRequest *req = &call->request->r.ModifyRequest;
779         struct ldap_Result *modify_result;
780         struct ldapsrv_reply *modify_reply;
781         TALLOC_CTX *local_ctx;
782         struct ldb_context *samdb = call->conn->ldb;
783         struct ldb_message *msg = NULL;
784         struct ldb_dn *dn;
785         const char *errstr = NULL;
786         int result = LDAP_SUCCESS;
787         int ldb_ret;
788         unsigned int i,j;
789         struct ldb_result *res = NULL;
790
791         DEBUG(10, ("ModifyRequest"));
792         DEBUGADD(10, (" dn: %s\n", req->dn));
793
794         local_ctx = talloc_named(call, 0, "ModifyRequest local memory context");
795         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
796
797         dn = ldb_dn_new(local_ctx, samdb, req->dn);
798         NT_STATUS_HAVE_NO_MEMORY(dn);
799
800         DEBUG(10, ("ModifyRequest: dn: [%s]\n", req->dn));
801
802         msg = talloc(local_ctx, struct ldb_message);
803         NT_STATUS_HAVE_NO_MEMORY(msg);
804
805         msg->dn = dn;
806         msg->num_elements = 0;
807         msg->elements = NULL;
808
809         if (req->num_mods > 0) {
810                 msg->num_elements = req->num_mods;
811                 msg->elements = talloc_array(msg, struct ldb_message_element, req->num_mods);
812                 NT_STATUS_HAVE_NO_MEMORY(msg->elements);
813
814                 for (i=0; i < msg->num_elements; i++) {
815                         msg->elements[i].name = discard_const_p(char, req->mods[i].attrib.name);
816                         msg->elements[i].num_values = 0;
817                         msg->elements[i].values = NULL;
818
819                         switch (req->mods[i].type) {
820                         default:
821                                 result = LDAP_PROTOCOL_ERROR;
822                                 map_ldb_error(local_ctx,
823                                         LDB_ERR_PROTOCOL_ERROR, NULL, &errstr);
824                                 errstr = talloc_asprintf(local_ctx,
825                                         "%s. Invalid LDAP_MODIFY_* type", errstr);
826                                 goto reply;
827                         case LDAP_MODIFY_ADD:
828                                 msg->elements[i].flags = LDB_FLAG_MOD_ADD;
829                                 break;
830                         case LDAP_MODIFY_DELETE:
831                                 msg->elements[i].flags = LDB_FLAG_MOD_DELETE;
832                                 break;
833                         case LDAP_MODIFY_REPLACE:
834                                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
835                                 break;
836                         }
837
838                         msg->elements[i].num_values = req->mods[i].attrib.num_values;
839                         if (msg->elements[i].num_values > 0) {
840                                 msg->elements[i].values = talloc_array(msg->elements, struct ldb_val,
841                                                                        msg->elements[i].num_values);
842                                 NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
843
844                                 for (j=0; j < msg->elements[i].num_values; j++) {
845                                         msg->elements[i].values[j].length = req->mods[i].attrib.values[j].length;
846                                         msg->elements[i].values[j].data = req->mods[i].attrib.values[j].data;                   
847                                 }
848                         }
849                 }
850         }
851
852 reply:
853         modify_reply = ldapsrv_init_reply(call, LDAP_TAG_ModifyResponse);
854         NT_STATUS_HAVE_NO_MEMORY(modify_reply);
855
856         if (result == LDAP_SUCCESS) {
857                 res = talloc_zero(local_ctx, struct ldb_result);
858                 NT_STATUS_HAVE_NO_MEMORY(res);
859                 ldb_ret = ldapsrv_mod_with_controls(call, msg, call->request->controls, res);
860                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
861                                        &errstr);
862         }
863
864         modify_result = &modify_reply->msg->r.ModifyResponse;
865         modify_result->dn = NULL;
866         if ((res != NULL) && (res->refs != NULL)) {
867                 modify_result->resultcode = map_ldb_error(local_ctx,
868                                                           LDB_ERR_REFERRAL,
869                                                           NULL, &errstr);
870                 modify_result->errormessage = (errstr?talloc_strdup(modify_reply, errstr):NULL);
871                 modify_result->referral = talloc_strdup(call, *res->refs);
872         } else {
873                 modify_result->resultcode = result;
874                 modify_result->errormessage = (errstr?talloc_strdup(modify_reply, errstr):NULL);
875                 modify_result->referral = NULL;
876         }
877         talloc_free(local_ctx);
878
879         ldapsrv_queue_reply(call, modify_reply);
880         return NT_STATUS_OK;
881
882 }
883
884 static NTSTATUS ldapsrv_AddRequest(struct ldapsrv_call *call)
885 {
886         struct ldap_AddRequest *req = &call->request->r.AddRequest;
887         struct ldap_Result *add_result;
888         struct ldapsrv_reply *add_reply;
889         TALLOC_CTX *local_ctx;
890         struct ldb_context *samdb = call->conn->ldb;
891         struct ldb_message *msg = NULL;
892         struct ldb_dn *dn;
893         const char *errstr = NULL;
894         int result = LDAP_SUCCESS;
895         int ldb_ret;
896         unsigned int i,j;
897         struct ldb_result *res = NULL;
898
899         DEBUG(10, ("AddRequest"));
900         DEBUGADD(10, (" dn: %s\n", req->dn));
901
902         local_ctx = talloc_named(call, 0, "AddRequest local memory context");
903         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
904
905         dn = ldb_dn_new(local_ctx, samdb, req->dn);
906         NT_STATUS_HAVE_NO_MEMORY(dn);
907
908         DEBUG(10, ("AddRequest: dn: [%s]\n", req->dn));
909
910         msg = talloc(local_ctx, struct ldb_message);
911         NT_STATUS_HAVE_NO_MEMORY(msg);
912
913         msg->dn = dn;
914         msg->num_elements = 0;
915         msg->elements = NULL;
916
917         if (req->num_attributes > 0) {
918                 msg->num_elements = req->num_attributes;
919                 msg->elements = talloc_array(msg, struct ldb_message_element, msg->num_elements);
920                 NT_STATUS_HAVE_NO_MEMORY(msg->elements);
921
922                 for (i=0; i < msg->num_elements; i++) {
923                         msg->elements[i].name = discard_const_p(char, req->attributes[i].name);
924                         msg->elements[i].flags = 0;
925                         msg->elements[i].num_values = 0;
926                         msg->elements[i].values = NULL;
927                         
928                         if (req->attributes[i].num_values > 0) {
929                                 msg->elements[i].num_values = req->attributes[i].num_values;
930                                 msg->elements[i].values = talloc_array(msg->elements, struct ldb_val,
931                                                                        msg->elements[i].num_values);
932                                 NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
933
934                                 for (j=0; j < msg->elements[i].num_values; j++) {
935                                         msg->elements[i].values[j].length = req->attributes[i].values[j].length;
936                                         msg->elements[i].values[j].data = req->attributes[i].values[j].data;                    
937                                 }
938                         }
939                 }
940         }
941
942         add_reply = ldapsrv_init_reply(call, LDAP_TAG_AddResponse);
943         NT_STATUS_HAVE_NO_MEMORY(add_reply);
944
945         if (result == LDAP_SUCCESS) {
946                 res = talloc_zero(local_ctx, struct ldb_result);
947                 NT_STATUS_HAVE_NO_MEMORY(res);
948                 ldb_ret = ldapsrv_add_with_controls(call, msg, call->request->controls, res);
949                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
950                                        &errstr);
951         }
952
953         add_result = &add_reply->msg->r.AddResponse;
954         add_result->dn = NULL;
955         if ((res != NULL) && (res->refs != NULL)) {
956                 add_result->resultcode =  map_ldb_error(local_ctx,
957                                                         LDB_ERR_REFERRAL, NULL,
958                                                         &errstr);
959                 add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
960                 add_result->referral = talloc_strdup(call, *res->refs);
961         } else {
962                 add_result->resultcode = result;
963                 add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
964                 add_result->referral = NULL;
965         }
966         talloc_free(local_ctx);
967
968         ldapsrv_queue_reply(call, add_reply);
969         return NT_STATUS_OK;
970
971 }
972
973 static NTSTATUS ldapsrv_DelRequest(struct ldapsrv_call *call)
974 {
975         struct ldap_DelRequest *req = &call->request->r.DelRequest;
976         struct ldap_Result *del_result;
977         struct ldapsrv_reply *del_reply;
978         TALLOC_CTX *local_ctx;
979         struct ldb_context *samdb = call->conn->ldb;
980         struct ldb_dn *dn;
981         const char *errstr = NULL;
982         int result = LDAP_SUCCESS;
983         int ldb_ret;
984         struct ldb_result *res = NULL;
985
986         DEBUG(10, ("DelRequest"));
987         DEBUGADD(10, (" dn: %s\n", req->dn));
988
989         local_ctx = talloc_named(call, 0, "DelRequest local memory context");
990         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
991
992         dn = ldb_dn_new(local_ctx, samdb, req->dn);
993         NT_STATUS_HAVE_NO_MEMORY(dn);
994
995         DEBUG(10, ("DelRequest: dn: [%s]\n", req->dn));
996
997         del_reply = ldapsrv_init_reply(call, LDAP_TAG_DelResponse);
998         NT_STATUS_HAVE_NO_MEMORY(del_reply);
999
1000         if (result == LDAP_SUCCESS) {
1001                 res = talloc_zero(local_ctx, struct ldb_result);
1002                 NT_STATUS_HAVE_NO_MEMORY(res);
1003                 ldb_ret = ldapsrv_del_with_controls(call, dn, call->request->controls, res);
1004                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1005                                        &errstr);
1006         }
1007
1008         del_result = &del_reply->msg->r.DelResponse;
1009         del_result->dn = NULL;
1010         if ((res != NULL) && (res->refs != NULL)) {
1011                 del_result->resultcode = map_ldb_error(local_ctx,
1012                                                        LDB_ERR_REFERRAL, NULL,
1013                                                        &errstr);
1014                 del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
1015                 del_result->referral = talloc_strdup(call, *res->refs);
1016         } else {
1017                 del_result->resultcode = result;
1018                 del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
1019                 del_result->referral = NULL;
1020         }
1021
1022         talloc_free(local_ctx);
1023
1024         ldapsrv_queue_reply(call, del_reply);
1025         return NT_STATUS_OK;
1026 }
1027
1028 static NTSTATUS ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
1029 {
1030         struct ldap_ModifyDNRequest *req = &call->request->r.ModifyDNRequest;
1031         struct ldap_Result *modifydn;
1032         struct ldapsrv_reply *modifydn_r;
1033         TALLOC_CTX *local_ctx;
1034         struct ldb_context *samdb = call->conn->ldb;
1035         struct ldb_dn *olddn, *newdn=NULL, *newrdn;
1036         struct ldb_dn *parentdn = NULL;
1037         const char *errstr = NULL;
1038         int result = LDAP_SUCCESS;
1039         int ldb_ret;
1040         struct ldb_result *res = NULL;
1041
1042         DEBUG(10, ("ModifyDNRequest"));
1043         DEBUGADD(10, (" dn: %s", req->dn));
1044         DEBUGADD(10, (" newrdn: %s\n", req->newrdn));
1045
1046         local_ctx = talloc_named(call, 0, "ModifyDNRequest local memory context");
1047         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1048
1049         olddn = ldb_dn_new(local_ctx, samdb, req->dn);
1050         NT_STATUS_HAVE_NO_MEMORY(olddn);
1051
1052         newrdn = ldb_dn_new(local_ctx, samdb, req->newrdn);
1053         NT_STATUS_HAVE_NO_MEMORY(newrdn);
1054
1055         DEBUG(10, ("ModifyDNRequest: olddn: [%s]\n", req->dn));
1056         DEBUG(10, ("ModifyDNRequest: newrdn: [%s]\n", req->newrdn));
1057
1058         if (ldb_dn_get_comp_num(newrdn) == 0) {
1059                 result = LDAP_PROTOCOL_ERROR;
1060                 map_ldb_error(local_ctx, LDB_ERR_PROTOCOL_ERROR, NULL,
1061                               &errstr);
1062                 goto reply;
1063         }
1064
1065         if (ldb_dn_get_comp_num(newrdn) > 1) {
1066                 result = LDAP_NAMING_VIOLATION;
1067                 map_ldb_error(local_ctx, LDB_ERR_NAMING_VIOLATION, NULL,
1068                               &errstr);
1069                 goto reply;
1070         }
1071
1072         /* we can't handle the rename if we should not remove the old dn */
1073         if (!req->deleteolddn) {
1074                 result = LDAP_UNWILLING_TO_PERFORM;
1075                 map_ldb_error(local_ctx, LDB_ERR_UNWILLING_TO_PERFORM, NULL,
1076                               &errstr);
1077                 errstr = talloc_asprintf(local_ctx,
1078                         "%s. Old RDN must be deleted", errstr);
1079                 goto reply;
1080         }
1081
1082         if (req->newsuperior) {
1083                 DEBUG(10, ("ModifyDNRequest: newsuperior: [%s]\n", req->newsuperior));
1084                 parentdn = ldb_dn_new(local_ctx, samdb, req->newsuperior);
1085         }
1086
1087         if (!parentdn) {
1088                 parentdn = ldb_dn_get_parent(local_ctx, olddn);
1089         }
1090         if (!parentdn) {
1091                 result = LDAP_NO_SUCH_OBJECT;
1092                 map_ldb_error(local_ctx, LDB_ERR_NO_SUCH_OBJECT, NULL, &errstr);
1093                 goto reply;
1094         }
1095
1096         if ( ! ldb_dn_add_child(parentdn, newrdn)) {
1097                 result = LDAP_OTHER;
1098                 map_ldb_error(local_ctx, LDB_ERR_OTHER, NULL, &errstr);
1099                 goto reply;
1100         }
1101         newdn = parentdn;
1102
1103 reply:
1104         modifydn_r = ldapsrv_init_reply(call, LDAP_TAG_ModifyDNResponse);
1105         NT_STATUS_HAVE_NO_MEMORY(modifydn_r);
1106
1107         if (result == LDAP_SUCCESS) {
1108                 res = talloc_zero(local_ctx, struct ldb_result);
1109                 NT_STATUS_HAVE_NO_MEMORY(res);
1110                 ldb_ret = ldapsrv_rename_with_controls(call, olddn, newdn, call->request->controls, res);
1111                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1112                                        &errstr);
1113         }
1114
1115         modifydn = &modifydn_r->msg->r.ModifyDNResponse;
1116         modifydn->dn = NULL;
1117         if ((res != NULL) && (res->refs != NULL)) {
1118                 modifydn->resultcode = map_ldb_error(local_ctx,
1119                                                      LDB_ERR_REFERRAL, NULL,
1120                                                      &errstr);;
1121                 modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
1122                 modifydn->referral = talloc_strdup(call, *res->refs);
1123         } else {
1124                 modifydn->resultcode = result;
1125                 modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
1126                 modifydn->referral = NULL;
1127         }
1128
1129         talloc_free(local_ctx);
1130
1131         ldapsrv_queue_reply(call, modifydn_r);
1132         return NT_STATUS_OK;
1133 }
1134
1135 static NTSTATUS ldapsrv_CompareRequest(struct ldapsrv_call *call)
1136 {
1137         struct ldap_CompareRequest *req = &call->request->r.CompareRequest;
1138         struct ldap_Result *compare;
1139         struct ldapsrv_reply *compare_r;
1140         TALLOC_CTX *local_ctx;
1141         struct ldb_context *samdb = call->conn->ldb;
1142         struct ldb_result *res = NULL;
1143         struct ldb_dn *dn;
1144         const char *attrs[1];
1145         const char *errstr = NULL;
1146         const char *filter = NULL;
1147         int result = LDAP_SUCCESS;
1148         int ldb_ret;
1149
1150         DEBUG(10, ("CompareRequest"));
1151         DEBUGADD(10, (" dn: %s\n", req->dn));
1152
1153         local_ctx = talloc_named(call, 0, "CompareRequest local_memory_context");
1154         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1155
1156         dn = ldb_dn_new(local_ctx, samdb, req->dn);
1157         NT_STATUS_HAVE_NO_MEMORY(dn);
1158
1159         DEBUG(10, ("CompareRequest: dn: [%s]\n", req->dn));
1160         filter = talloc_asprintf(local_ctx, "(%s=%*s)", req->attribute, 
1161                                  (int)req->value.length, req->value.data);
1162         NT_STATUS_HAVE_NO_MEMORY(filter);
1163
1164         DEBUGADD(10, ("CompareRequest: attribute: [%s]\n", filter));
1165
1166         attrs[0] = NULL;
1167
1168         compare_r = ldapsrv_init_reply(call, LDAP_TAG_CompareResponse);
1169         NT_STATUS_HAVE_NO_MEMORY(compare_r);
1170
1171         if (result == LDAP_SUCCESS) {
1172                 ldb_ret = ldb_search(samdb, local_ctx, &res,
1173                                      dn, LDB_SCOPE_BASE, attrs, "%s", filter);
1174                 if (ldb_ret != LDB_SUCCESS) {
1175                         result = map_ldb_error(local_ctx, ldb_ret,
1176                                                ldb_errstring(samdb), &errstr);
1177                         DEBUG(10,("CompareRequest: error: %s\n", errstr));
1178                 } else if (res->count == 0) {
1179                         DEBUG(10,("CompareRequest: doesn't matched\n"));
1180                         result = LDAP_COMPARE_FALSE;
1181                         errstr = NULL;
1182                 } else if (res->count == 1) {
1183                         DEBUG(10,("CompareRequest: matched\n"));
1184                         result = LDAP_COMPARE_TRUE;
1185                         errstr = NULL;
1186                 } else if (res->count > 1) {
1187                         result = LDAP_OTHER;
1188                         map_ldb_error(local_ctx, LDB_ERR_OTHER, NULL, &errstr);
1189                         errstr = talloc_asprintf(local_ctx,
1190                                 "%s. Too many objects match!", errstr);
1191                         DEBUG(10,("CompareRequest: %d results: %s\n", res->count, errstr));
1192                 }
1193         }
1194
1195         compare = &compare_r->msg->r.CompareResponse;
1196         compare->dn = NULL;
1197         compare->resultcode = result;
1198         compare->errormessage = (errstr?talloc_strdup(compare_r,errstr):NULL);
1199         compare->referral = NULL;
1200
1201         talloc_free(local_ctx);
1202
1203         ldapsrv_queue_reply(call, compare_r);
1204         return NT_STATUS_OK;
1205 }
1206
1207 static NTSTATUS ldapsrv_AbandonRequest(struct ldapsrv_call *call)
1208 {
1209         struct ldap_AbandonRequest *req = &call->request->r.AbandonRequest;
1210         struct ldapsrv_call *c = NULL;
1211         struct ldapsrv_call *n = NULL;
1212
1213         DEBUG(10, ("AbandonRequest\n"));
1214
1215         for (c = call->conn->pending_calls; c != NULL; c = n) {
1216                 n = c->next;
1217
1218                 if (c->request->messageid != req->messageid) {
1219                         continue;
1220                 }
1221
1222                 DLIST_REMOVE(call->conn->pending_calls, c);
1223                 TALLOC_FREE(c);
1224         }
1225
1226         return NT_STATUS_OK;
1227 }
1228
1229 NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
1230 {
1231         unsigned int i;
1232         struct ldap_message *msg = call->request;
1233         NTSTATUS status;
1234
1235         /* Check for undecoded critical extensions */
1236         for (i=0; msg->controls && msg->controls[i]; i++) {
1237                 if (!msg->controls_decoded[i] && 
1238                     msg->controls[i]->critical) {
1239                         DEBUG(3, ("ldapsrv_do_call: Critical extension %s is not known to this server\n",
1240                                   msg->controls[i]->oid));
1241                         return ldapsrv_unwilling(call, LDAP_UNAVAILABLE_CRITICAL_EXTENSION);
1242                 }
1243         }
1244
1245         if (call->conn->authz_logged == false) {
1246                 bool log = true;
1247
1248                 /*
1249                  * We do not want to log anonymous access if the query
1250                  * is just for the rootDSE, or it is a startTLS or a
1251                  * Bind.
1252                  *
1253                  * A rootDSE search could also be done over
1254                  * CLDAP anonymously for example, so these don't
1255                  * really count.
1256                  * Essentially we want to know about
1257                  * access beyond that normally done prior to a
1258                  * bind.
1259                  */
1260
1261                 switch(call->request->type) {
1262                 case LDAP_TAG_BindRequest:
1263                 case LDAP_TAG_UnbindRequest:
1264                 case LDAP_TAG_AbandonRequest:
1265                         log = false;
1266                         break;
1267                 case LDAP_TAG_ExtendedResponse: {
1268                         struct ldap_ExtendedRequest *req = &call->request->r.ExtendedRequest;
1269                         if (strcmp(req->oid, LDB_EXTENDED_START_TLS_OID) == 0) {
1270                                 log = false;
1271                         }
1272                         break;
1273                 }
1274                 case LDAP_TAG_SearchRequest: {
1275                         struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
1276                         if (req->scope == LDAP_SEARCH_SCOPE_BASE) {
1277                                 if (req->basedn[0] == '\0') {
1278                                         log = false;
1279                                 }
1280                         }
1281                         break;
1282                 }
1283                 default:
1284                         break;
1285                 }
1286
1287                 if (log) {
1288                         const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
1289                         if (call->conn->sockets.active == call->conn->sockets.tls) {
1290                                 transport_protection = AUTHZ_TRANSPORT_PROTECTION_TLS;
1291                         }
1292
1293                         log_successful_authz_event(call->conn->connection->msg_ctx,
1294                                                    call->conn->connection->lp_ctx,
1295                                                    call->conn->connection->remote_address,
1296                                                    call->conn->connection->local_address,
1297                                                    "LDAP",
1298                                                    "no bind",
1299                                                    transport_protection,
1300                                                    call->conn->session_info);
1301
1302                         call->conn->authz_logged = true;
1303                 }
1304         }
1305
1306         switch(call->request->type) {
1307         case LDAP_TAG_BindRequest:
1308                 return ldapsrv_BindRequest(call);
1309         case LDAP_TAG_UnbindRequest:
1310                 return ldapsrv_UnbindRequest(call);
1311         case LDAP_TAG_SearchRequest:
1312                 return ldapsrv_SearchRequest(call);
1313         case LDAP_TAG_ModifyRequest:
1314                 status = ldapsrv_ModifyRequest(call);
1315                 break;
1316         case LDAP_TAG_AddRequest:
1317                 status = ldapsrv_AddRequest(call);
1318                 break;
1319         case LDAP_TAG_DelRequest:
1320                 status = ldapsrv_DelRequest(call);
1321                 break;
1322         case LDAP_TAG_ModifyDNRequest:
1323                 status = ldapsrv_ModifyDNRequest(call);
1324                 break;
1325         case LDAP_TAG_CompareRequest:
1326                 return ldapsrv_CompareRequest(call);
1327         case LDAP_TAG_AbandonRequest:
1328                 return ldapsrv_AbandonRequest(call);
1329         case LDAP_TAG_ExtendedRequest:
1330                 status = ldapsrv_ExtendedRequest(call);
1331                 break;
1332         default:
1333                 return ldapsrv_unwilling(call, LDAP_PROTOCOL_ERROR);
1334         }
1335
1336         if (NT_STATUS_IS_OK(status)) {
1337                 ldapsrv_notification_retry_setup(call->conn->service, true);
1338         }
1339
1340         return status;
1341 }