a165ecbf36cd79474ae9a491e05ed75727f3edcc
[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 "samba/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 #include "libcli/ldap/ldap_proto.h"
36 #include "source4/auth/auth.h"
37
38 static int map_ldb_error(TALLOC_CTX *mem_ctx, int ldb_err,
39         const char *add_err_string, const char **errstring)
40 {
41         WERROR err;
42
43         /* Certain LDB modules need to return very special WERROR codes. Proof
44          * for them here and if they exist skip the rest of the mapping. */
45         if (add_err_string != NULL) {
46                 char *endptr;
47                 strtol(add_err_string, &endptr, 16);
48                 if (endptr != add_err_string) {
49                         *errstring = add_err_string;
50                         return ldb_err;
51                 }
52         }
53
54         /* Otherwise we calculate here a generic, but appropriate WERROR. */
55
56         switch (ldb_err) {
57         case LDB_SUCCESS:
58                 err = WERR_OK;
59         break;
60         case LDB_ERR_OPERATIONS_ERROR:
61                 err = WERR_DS_OPERATIONS_ERROR;
62         break;
63         case LDB_ERR_PROTOCOL_ERROR:
64                 err = WERR_DS_PROTOCOL_ERROR;
65         break;
66         case LDB_ERR_TIME_LIMIT_EXCEEDED:
67                 err = WERR_DS_TIMELIMIT_EXCEEDED;
68         break;
69         case LDB_ERR_SIZE_LIMIT_EXCEEDED:
70                 err = WERR_DS_SIZELIMIT_EXCEEDED;
71         break;
72         case LDB_ERR_COMPARE_FALSE:
73                 err = WERR_DS_COMPARE_FALSE;
74         break;
75         case LDB_ERR_COMPARE_TRUE:
76                 err = WERR_DS_COMPARE_TRUE;
77         break;
78         case LDB_ERR_AUTH_METHOD_NOT_SUPPORTED:
79                 err = WERR_DS_AUTH_METHOD_NOT_SUPPORTED;
80         break;
81         case LDB_ERR_STRONG_AUTH_REQUIRED:
82                 err = WERR_DS_STRONG_AUTH_REQUIRED;
83         break;
84         case LDB_ERR_REFERRAL:
85                 err = WERR_DS_REFERRAL;
86         break;
87         case LDB_ERR_ADMIN_LIMIT_EXCEEDED:
88                 err = WERR_DS_ADMIN_LIMIT_EXCEEDED;
89         break;
90         case LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION:
91                 err = WERR_DS_UNAVAILABLE_CRIT_EXTENSION;
92         break;
93         case LDB_ERR_CONFIDENTIALITY_REQUIRED:
94                 err = WERR_DS_CONFIDENTIALITY_REQUIRED;
95         break;
96         case LDB_ERR_SASL_BIND_IN_PROGRESS:
97                 err = WERR_DS_BUSY;
98         break;
99         case LDB_ERR_NO_SUCH_ATTRIBUTE:
100                 err = WERR_DS_NO_ATTRIBUTE_OR_VALUE;
101         break;
102         case LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE:
103                 err = WERR_DS_ATTRIBUTE_TYPE_UNDEFINED;
104         break;
105         case LDB_ERR_INAPPROPRIATE_MATCHING:
106                 err = WERR_DS_INAPPROPRIATE_MATCHING;
107         break;
108         case LDB_ERR_CONSTRAINT_VIOLATION:
109                 err = WERR_DS_CONSTRAINT_VIOLATION;
110         break;
111         case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
112                 err = WERR_DS_ATTRIBUTE_OR_VALUE_EXISTS;
113         break;
114         case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX:
115                 err = WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
116         break;
117         case LDB_ERR_NO_SUCH_OBJECT:
118                 err = WERR_DS_NO_SUCH_OBJECT;
119         break;
120         case LDB_ERR_ALIAS_PROBLEM:
121                 err = WERR_DS_ALIAS_PROBLEM;
122         break;
123         case LDB_ERR_INVALID_DN_SYNTAX:
124                 err = WERR_DS_INVALID_DN_SYNTAX;
125         break;
126         case LDB_ERR_ALIAS_DEREFERENCING_PROBLEM:
127                 err = WERR_DS_ALIAS_DEREF_PROBLEM;
128         break;
129         case LDB_ERR_INAPPROPRIATE_AUTHENTICATION:
130                 err = WERR_DS_INAPPROPRIATE_AUTH;
131         break;
132         case LDB_ERR_INVALID_CREDENTIALS:
133                 err = WERR_ACCESS_DENIED;
134         break;
135         case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
136                 err = WERR_DS_INSUFF_ACCESS_RIGHTS;
137         break;
138         case LDB_ERR_BUSY:
139                 err = WERR_DS_BUSY;
140         break;
141         case LDB_ERR_UNAVAILABLE:
142                 err = WERR_DS_UNAVAILABLE;
143         break;
144         case LDB_ERR_UNWILLING_TO_PERFORM:
145                 err = WERR_DS_UNWILLING_TO_PERFORM;
146         break;
147         case LDB_ERR_LOOP_DETECT:
148                 err = WERR_DS_LOOP_DETECT;
149         break;
150         case LDB_ERR_NAMING_VIOLATION:
151                 err = WERR_DS_NAMING_VIOLATION;
152         break;
153         case LDB_ERR_OBJECT_CLASS_VIOLATION:
154                 err = WERR_DS_OBJ_CLASS_VIOLATION;
155         break;
156         case LDB_ERR_NOT_ALLOWED_ON_NON_LEAF:
157                 err = WERR_DS_CANT_ON_NON_LEAF;
158         break;
159         case LDB_ERR_NOT_ALLOWED_ON_RDN:
160                 err = WERR_DS_CANT_ON_RDN;
161         break;
162         case LDB_ERR_ENTRY_ALREADY_EXISTS:
163                 err = WERR_DS_OBJ_STRING_NAME_EXISTS;
164         break;
165         case LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED:
166                 err = WERR_DS_CANT_MOD_OBJ_CLASS;
167         break;
168         case LDB_ERR_AFFECTS_MULTIPLE_DSAS:
169                 err = WERR_DS_AFFECTS_MULTIPLE_DSAS;
170         break;
171         default:
172                 err = WERR_DS_GENERIC_ERROR;
173         break;
174         }
175
176         *errstring = talloc_asprintf(mem_ctx, "%08X: %s", W_ERROR_V(err),
177                 add_err_string != NULL ? add_err_string : ldb_strerror(ldb_err));
178
179         /* result is 1:1 for now */
180         return ldb_err;
181 }
182
183 /*
184   connect to the sam database
185 */
186 int ldapsrv_backend_Init(struct ldapsrv_connection *conn,
187                               char **errstring)
188 {
189         bool using_tls = conn->sockets.active == conn->sockets.tls;
190         bool using_seal = conn->gensec != NULL && gensec_have_feature(conn->gensec,
191                                                                       GENSEC_FEATURE_SEAL);
192         struct dsdb_encrypted_connection_state *opaque_connection_state = NULL;
193
194         int ret = samdb_connect_url(conn,
195                                     conn->connection->event.ctx,
196                                     conn->lp_ctx,
197                                     conn->session_info,
198                                     conn->global_catalog ? LDB_FLG_RDONLY : 0,
199                                     "sam.ldb",
200                                     conn->connection->remote_address,
201                                     &conn->ldb,
202                                     errstring);
203         if (ret != LDB_SUCCESS) {
204                 return ret;
205         }
206
207         /*
208          * We can safely call ldb_set_opaque() on this ldb as we have
209          * set remote_address above which avoids the ldb handle cache
210          */
211         opaque_connection_state = talloc_zero(conn, struct dsdb_encrypted_connection_state);
212         if (opaque_connection_state == NULL) {
213                 return LDB_ERR_OPERATIONS_ERROR;
214         }
215         opaque_connection_state->using_encrypted_connection = using_tls || using_seal;
216         ret = ldb_set_opaque(conn->ldb,
217                              DSDB_OPAQUE_ENCRYPTED_CONNECTION_STATE_NAME,
218                              opaque_connection_state);
219         if (ret != LDB_SUCCESS) {
220                 DBG_ERR("ldb_set_opaque() failed to store our "
221                         "encrypted connection state!\n");
222                 return ret;
223         }
224
225         if (conn->server_credentials) {
226                 struct gensec_security *gensec_security = NULL;
227                 const char **sasl_mechs = NULL;
228                 NTSTATUS status;
229
230                 status = samba_server_gensec_start(conn,
231                                                    conn->connection->event.ctx,
232                                                    conn->connection->msg_ctx,
233                                                    conn->lp_ctx,
234                                                    conn->server_credentials,
235                                                    "ldap",
236                                                    &gensec_security);
237                 if (!NT_STATUS_IS_OK(status)) {
238                         DBG_ERR("samba_server_gensec_start failed: %s\n",
239                                 nt_errstr(status));
240                         return LDB_ERR_OPERATIONS_ERROR;
241                 }
242
243                 /* ldb can have a different lifetime to conn, so we
244                    need to ensure that sasl_mechs lives as long as the
245                    ldb does */
246                 sasl_mechs = gensec_security_sasl_names(gensec_security,
247                                                         conn->ldb);
248                 TALLOC_FREE(gensec_security);
249                 if (sasl_mechs == NULL) {
250                         DBG_ERR("Failed to get sasl mechs!\n");
251                         return LDB_ERR_OPERATIONS_ERROR;
252                 }
253
254                 ldb_set_opaque(conn->ldb, "supportedSASLMechanisms", sasl_mechs);
255         }
256
257         return LDB_SUCCESS;
258 }
259
260 struct ldapsrv_reply *ldapsrv_init_reply(struct ldapsrv_call *call, uint8_t type)
261 {
262         struct ldapsrv_reply *reply;
263
264         reply = talloc_zero(call, struct ldapsrv_reply);
265         if (!reply) {
266                 return NULL;
267         }
268         reply->msg = talloc_zero(reply, struct ldap_message);
269         if (reply->msg == NULL) {
270                 talloc_free(reply);
271                 return NULL;
272         }
273
274         reply->msg->messageid = call->request->messageid;
275         reply->msg->type = type;
276         reply->msg->controls = NULL;
277
278         return reply;
279 }
280
281 /*
282  * Encode a reply to an LDAP client as ASN.1, free the original memory
283  */
284 static NTSTATUS ldapsrv_encode(TALLOC_CTX *mem_ctx,
285                                struct ldapsrv_reply *reply)
286 {
287         bool bret = ldap_encode(reply->msg,
288                                 samba_ldap_control_handlers(),
289                                 &reply->blob,
290                                 mem_ctx);
291         TALLOC_FREE(reply->msg);
292         if (!bret) {
293                 DEBUG(0,("Failed to encode ldap reply of type %d: "
294                          "ldap_encode() failed\n",
295                          reply->msg->type));
296                 return NT_STATUS_NO_MEMORY;
297         }
298
299         talloc_set_name_const(reply->blob.data,
300                               "Outgoing, encoded single LDAP reply");
301
302         return NT_STATUS_OK;
303 }
304
305 /*
306  * Queue a reply (encoding it also), even if it would exceed the
307  * limit.  This allows the error packet with LDAP_SIZE_LIMIT_EXCEEDED
308  * to be sent
309  */
310 static NTSTATUS ldapsrv_queue_reply_forced(struct ldapsrv_call *call,
311                                            struct ldapsrv_reply *reply)
312 {
313         NTSTATUS status = ldapsrv_encode(call, reply);
314
315         if (NT_STATUS_IS_OK(status)) {
316                 DLIST_ADD_END(call->replies, reply);
317         }
318         return status;
319 }
320
321 /*
322  * Queue a reply (encoding it also) but check we do not send more than
323  * LDAP_SERVER_MAX_REPLY_SIZE of responses as a way to limit the
324  * amount of data a client can make us allocate.
325  */
326 NTSTATUS ldapsrv_queue_reply(struct ldapsrv_call *call, struct ldapsrv_reply *reply)
327 {
328         NTSTATUS status = ldapsrv_encode(call, reply);
329
330         if (!NT_STATUS_IS_OK(status)) {
331                 return status;
332         }
333
334         if (call->reply_size > call->reply_size + reply->blob.length
335             || call->reply_size + reply->blob.length > LDAP_SERVER_MAX_REPLY_SIZE) {
336                 DBG_WARNING("Refusing to queue LDAP search response size "
337                             "of more than %zu bytes\n",
338                             LDAP_SERVER_MAX_REPLY_SIZE);
339                 TALLOC_FREE(reply->blob.data);
340                 return NT_STATUS_FILE_TOO_LARGE;
341         }
342
343         call->reply_size += reply->blob.length;
344
345         DLIST_ADD_END(call->replies, reply);
346
347         return status;
348 }
349
350 static NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
351 {
352         struct ldapsrv_reply *reply;
353         struct ldap_ExtendedResponse *r;
354
355         DEBUG(10,("Unwilling type[%d] id[%d]\n", call->request->type, call->request->messageid));
356
357         reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
358         if (!reply) {
359                 return NT_STATUS_NO_MEMORY;
360         }
361
362         r = &reply->msg->r.ExtendedResponse;
363         r->response.resultcode = error;
364         r->response.dn = NULL;
365         r->response.errormessage = NULL;
366         r->response.referral = NULL;
367         r->oid = NULL;
368         r->value = NULL;
369
370         ldapsrv_queue_reply(call, reply);
371         return NT_STATUS_OK;
372 }
373
374 static int ldapsrv_add_with_controls(struct ldapsrv_call *call,
375                                      const struct ldb_message *message,
376                                      struct ldb_control **controls,
377                                      struct ldb_result *res)
378 {
379         struct ldb_context *ldb = call->conn->ldb;
380         struct ldb_request *req;
381         int ret;
382
383         ret = ldb_msg_sanity_check(ldb, message);
384         if (ret != LDB_SUCCESS) {
385                 return ret;
386         }
387
388         ret = ldb_build_add_req(&req, ldb, ldb,
389                                         message,
390                                         controls,
391                                         res,
392                                         ldb_modify_default_callback,
393                                         NULL);
394
395         if (ret != LDB_SUCCESS) return ret;
396
397         if (call->conn->global_catalog) {
398                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
399         }
400         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
401
402         ret = ldb_transaction_start(ldb);
403         if (ret != LDB_SUCCESS) {
404                 return ret;
405         }
406
407         if (!call->conn->is_privileged) {
408                 ldb_req_mark_untrusted(req);
409         }
410
411         LDB_REQ_SET_LOCATION(req);
412
413         ret = ldb_request(ldb, req);
414         if (ret == LDB_SUCCESS) {
415                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
416         }
417
418         if (ret == LDB_SUCCESS) {
419                 ret = ldb_transaction_commit(ldb);
420         }
421         else {
422                 ldb_transaction_cancel(ldb);
423         }
424
425         talloc_free(req);
426         return ret;
427 }
428
429 /* create and execute a modify request */
430 static int ldapsrv_mod_with_controls(struct ldapsrv_call *call,
431                                      const struct ldb_message *message,
432                                      struct ldb_control **controls,
433                                      struct ldb_result *res)
434 {
435         struct ldb_context *ldb = call->conn->ldb;
436         struct ldb_request *req;
437         int ret;
438
439         ret = ldb_msg_sanity_check(ldb, message);
440         if (ret != LDB_SUCCESS) {
441                 return ret;
442         }
443
444         ret = ldb_build_mod_req(&req, ldb, ldb,
445                                         message,
446                                         controls,
447                                         res,
448                                         ldb_modify_default_callback,
449                                         NULL);
450
451         if (ret != LDB_SUCCESS) {
452                 return ret;
453         }
454
455         if (call->conn->global_catalog) {
456                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
457         }
458         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
459
460         ret = ldb_transaction_start(ldb);
461         if (ret != LDB_SUCCESS) {
462                 return ret;
463         }
464
465         if (!call->conn->is_privileged) {
466                 ldb_req_mark_untrusted(req);
467         }
468
469         LDB_REQ_SET_LOCATION(req);
470
471         ret = ldb_request(ldb, req);
472         if (ret == LDB_SUCCESS) {
473                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
474         }
475
476         if (ret == LDB_SUCCESS) {
477                 ret = ldb_transaction_commit(ldb);
478         }
479         else {
480                 ldb_transaction_cancel(ldb);
481         }
482
483         talloc_free(req);
484         return ret;
485 }
486
487 /* create and execute a delete request */
488 static int ldapsrv_del_with_controls(struct ldapsrv_call *call,
489                                      struct ldb_dn *dn,
490                                      struct ldb_control **controls,
491                                      struct ldb_result *res)
492 {
493         struct ldb_context *ldb = call->conn->ldb;
494         struct ldb_request *req;
495         int ret;
496
497         ret = ldb_build_del_req(&req, ldb, ldb,
498                                         dn,
499                                         controls,
500                                         res,
501                                         ldb_modify_default_callback,
502                                         NULL);
503
504         if (ret != LDB_SUCCESS) return ret;
505
506         if (call->conn->global_catalog) {
507                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
508         }
509         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
510
511         ret = ldb_transaction_start(ldb);
512         if (ret != LDB_SUCCESS) {
513                 return ret;
514         }
515
516         if (!call->conn->is_privileged) {
517                 ldb_req_mark_untrusted(req);
518         }
519
520         LDB_REQ_SET_LOCATION(req);
521
522         ret = ldb_request(ldb, req);
523         if (ret == LDB_SUCCESS) {
524                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
525         }
526
527         if (ret == LDB_SUCCESS) {
528                 ret = ldb_transaction_commit(ldb);
529         }
530         else {
531                 ldb_transaction_cancel(ldb);
532         }
533
534         talloc_free(req);
535         return ret;
536 }
537
538 static int ldapsrv_rename_with_controls(struct ldapsrv_call *call,
539                                         struct ldb_dn *olddn,
540                                         struct ldb_dn *newdn,
541                                         struct ldb_control **controls,
542                                         struct ldb_result *res)
543 {
544         struct ldb_context *ldb = call->conn->ldb;
545         struct ldb_request *req;
546         int ret;
547
548         ret = ldb_build_rename_req(&req, ldb, ldb,
549                                         olddn,
550                                         newdn,
551                                         controls,
552                                         res,
553                                         ldb_modify_default_callback,
554                                         NULL);
555
556         if (ret != LDB_SUCCESS) return ret;
557
558         if (call->conn->global_catalog) {
559                 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
560         }
561         ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
562
563         ret = ldb_transaction_start(ldb);
564         if (ret != LDB_SUCCESS) {
565                 return ret;
566         }
567
568         if (!call->conn->is_privileged) {
569                 ldb_req_mark_untrusted(req);
570         }
571
572         LDB_REQ_SET_LOCATION(req);
573
574         ret = ldb_request(ldb, req);
575         if (ret == LDB_SUCCESS) {
576                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
577         }
578
579         if (ret == LDB_SUCCESS) {
580                 ret = ldb_transaction_commit(ldb);
581         }
582         else {
583                 ldb_transaction_cancel(ldb);
584         }
585
586         talloc_free(req);
587         return ret;
588 }
589
590
591
592 struct ldapsrv_context {
593         struct ldapsrv_call *call;
594         int extended_type;
595         bool attributesonly;
596         struct ldb_control **controls;
597         size_t count; /* For notificaiton only */
598 };
599
600 static int ldap_server_search_callback(struct ldb_request *req, struct ldb_reply *ares)
601 {
602         struct ldapsrv_context *ctx = talloc_get_type(req->context, struct ldapsrv_context);
603         struct ldapsrv_call *call = ctx->call;
604         struct ldb_context *ldb = call->conn->ldb;
605         unsigned int j;
606         struct ldapsrv_reply *ent_r = NULL;
607         struct ldap_SearchResEntry *ent;
608         int ret;
609         NTSTATUS status;
610
611         if (!ares) {
612                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
613         }
614         if (ares->error != LDB_SUCCESS) {
615                 return ldb_request_done(req, ares->error);
616         }
617
618         switch (ares->type) {
619         case LDB_REPLY_ENTRY:
620         {
621                 struct ldb_message *msg = ares->message;
622                 ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
623                 if (ent_r == NULL) {
624                         return ldb_oom(ldb);
625                 }
626
627                 ctx->count++;
628
629                 /*
630                  * Put the LDAP search response data under ent_r->msg
631                  * so we can free that later once encoded
632                  */
633                 talloc_steal(ent_r->msg, msg);
634
635                 ent = &ent_r->msg->r.SearchResultEntry;
636                 ent->dn = ldb_dn_get_extended_linearized(ent_r, msg->dn,
637                                                          ctx->extended_type);
638                 ent->num_attributes = 0;
639                 ent->attributes = NULL;
640                 if (msg->num_elements == 0) {
641                         goto queue_reply;
642                 }
643                 ent->num_attributes = msg->num_elements;
644                 ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes);
645                 if (ent->attributes == NULL) {
646                         return ldb_oom(ldb);
647                 }
648
649                 for (j=0; j < ent->num_attributes; j++) {
650                         ent->attributes[j].name = msg->elements[j].name;
651                         ent->attributes[j].num_values = 0;
652                         ent->attributes[j].values = NULL;
653                         if (ctx->attributesonly && (msg->elements[j].num_values == 0)) {
654                                 continue;
655                         }
656                         ent->attributes[j].num_values = msg->elements[j].num_values;
657                         ent->attributes[j].values = msg->elements[j].values;
658                 }
659 queue_reply:
660                 status = ldapsrv_queue_reply(call, ent_r);
661                 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_TOO_LARGE)) {
662                         ret = ldb_request_done(req,
663                                                LDB_ERR_SIZE_LIMIT_EXCEEDED);
664                         ldb_asprintf_errstring(ldb,
665                                                "LDAP search response size "
666                                                "limited to %zu bytes\n",
667                                                LDAP_SERVER_MAX_REPLY_SIZE);
668                 } else if (!NT_STATUS_IS_OK(status)) {
669                         ret = ldb_request_done(req,
670                                                ldb_operr(ldb));
671                 } else {
672                         ret = LDB_SUCCESS;
673                 }
674                 break;
675         }
676         case LDB_REPLY_REFERRAL:
677         {
678                 struct ldap_SearchResRef *ent_ref;
679
680                 /*
681                  * TODO: This should be handled by the notification
682                  * module not here
683                  */
684                 if (call->notification.busy) {
685                         ret = LDB_SUCCESS;
686                         break;
687                 }
688
689                 ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultReference);
690                 if (ent_r == NULL) {
691                         return ldb_oom(ldb);
692                 }
693
694                 /*
695                  * Put the LDAP referral data under ent_r->msg
696                  * so we can free that later once encoded
697                  */
698                 talloc_steal(ent_r->msg, ares->referral);
699
700                 ent_ref = &ent_r->msg->r.SearchResultReference;
701                 ent_ref->referral = ares->referral;
702
703                 status = ldapsrv_queue_reply(call, ent_r);
704                 if (!NT_STATUS_IS_OK(status)) {
705                         ret = LDB_ERR_OPERATIONS_ERROR;
706                 } else {
707                         ret = LDB_SUCCESS;
708                 }
709                 break;
710         }
711         case LDB_REPLY_DONE:
712         {
713                 /*
714                  * We don't queue the reply for this one, we let that
715                  * happen outside
716                  */
717                 ctx->controls = talloc_move(ctx, &ares->controls);
718
719                 TALLOC_FREE(ares);
720                 return ldb_request_done(req, LDB_SUCCESS);
721         }
722         default:
723                 /* Doesn't happen */
724                 ret = LDB_ERR_OPERATIONS_ERROR;
725         }
726         TALLOC_FREE(ares);
727
728         return ret;
729 }
730
731
732 static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
733 {
734         struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
735         struct ldap_Result *done;
736         struct ldapsrv_reply *done_r;
737         TALLOC_CTX *local_ctx;
738         struct ldapsrv_context *callback_ctx = NULL;
739         struct ldb_context *samdb = talloc_get_type(call->conn->ldb, struct ldb_context);
740         struct ldb_dn *basedn;
741         struct ldb_request *lreq;
742         struct ldb_control *search_control;
743         struct ldb_search_options_control *search_options;
744         struct ldb_control *extended_dn_control;
745         struct ldb_extended_dn_control *extended_dn_decoded = NULL;
746         struct ldb_control *notification_control = NULL;
747         enum ldb_scope scope = LDB_SCOPE_DEFAULT;
748         const char **attrs = NULL;
749         const char *scope_str, *errstr = NULL;
750         int result = -1;
751         int ldb_ret = -1;
752         unsigned int i;
753         int extended_type = 1;
754
755         /*
756          * Warn for searches that are longer than 1/4 of the
757          * search_timeout, being 30sec by default
758          */
759         struct timeval start_time = timeval_current();
760         struct timeval warning_time
761                 = timeval_add(&start_time,
762                               call->conn->limits.search_timeout / 4,
763                               0);
764
765         local_ctx = talloc_new(call);
766         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
767
768         basedn = ldb_dn_new(local_ctx, samdb, req->basedn);
769         NT_STATUS_HAVE_NO_MEMORY(basedn);
770
771         switch (req->scope) {
772         case LDAP_SEARCH_SCOPE_BASE:
773                 scope = LDB_SCOPE_BASE;
774                 break;
775         case LDAP_SEARCH_SCOPE_SINGLE:
776                 scope = LDB_SCOPE_ONELEVEL;
777                 break;
778         case LDAP_SEARCH_SCOPE_SUB:
779                 scope = LDB_SCOPE_SUBTREE;
780                 break;
781         default:
782                 result = LDAP_PROTOCOL_ERROR;
783                 map_ldb_error(local_ctx, LDB_ERR_PROTOCOL_ERROR, NULL,
784                               &errstr);
785                 scope_str = "<Invalid scope>";
786                 errstr = talloc_asprintf(local_ctx,
787                                          "%s. Invalid scope", errstr);
788                 goto reply;
789         }
790         scope_str = dsdb_search_scope_as_string(scope);
791
792         DEBUG(10,("SearchRequest: scope: [%s]\n", scope_str));
793
794         if (req->num_attributes >= 1) {
795                 attrs = talloc_array(local_ctx, const char *, req->num_attributes+1);
796                 NT_STATUS_HAVE_NO_MEMORY(attrs);
797
798                 for (i=0; i < req->num_attributes; i++) {
799                         DEBUG(10,("SearchRequest: attrs: [%s]\n",req->attributes[i]));
800                         attrs[i] = req->attributes[i];
801                 }
802                 attrs[i] = NULL;
803         }
804
805         DEBUG(5,("ldb_request %s dn=%s filter=%s\n", 
806                  scope_str, req->basedn, ldb_filter_from_tree(call, req->tree)));
807
808         callback_ctx = talloc_zero(local_ctx, struct ldapsrv_context);
809         NT_STATUS_HAVE_NO_MEMORY(callback_ctx);
810         callback_ctx->call = call;
811         callback_ctx->extended_type = extended_type;
812         callback_ctx->attributesonly = req->attributesonly;
813
814         ldb_ret = ldb_build_search_req_ex(&lreq, samdb, local_ctx,
815                                           basedn, scope,
816                                           req->tree, attrs,
817                                           call->request->controls,
818                                           callback_ctx,
819                                           ldap_server_search_callback,
820                                           NULL);
821
822         if (ldb_ret != LDB_SUCCESS) {
823                 goto reply;
824         }
825
826         if (call->conn->global_catalog) {
827                 search_control = ldb_request_get_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID);
828
829                 search_options = NULL;
830                 if (search_control) {
831                         search_options = talloc_get_type(search_control->data, struct ldb_search_options_control);
832                         search_options->search_options |= LDB_SEARCH_OPTION_PHANTOM_ROOT;
833                 } else {
834                         search_options = talloc(lreq, struct ldb_search_options_control);
835                         NT_STATUS_HAVE_NO_MEMORY(search_options);
836                         search_options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
837                         ldb_request_add_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID, false, search_options);
838                 }
839         } else {
840                 ldb_request_add_control(lreq, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
841         }
842
843         extended_dn_control = ldb_request_get_control(lreq, LDB_CONTROL_EXTENDED_DN_OID);
844
845         if (extended_dn_control) {
846                 if (extended_dn_control->data) {
847                         extended_dn_decoded = talloc_get_type(extended_dn_control->data, struct ldb_extended_dn_control);
848                         extended_type = extended_dn_decoded->type;
849                 } else {
850                         extended_type = 0;
851                 }
852                 callback_ctx->extended_type = extended_type;
853         }
854
855         notification_control = ldb_request_get_control(lreq, LDB_CONTROL_NOTIFICATION_OID);
856         if (notification_control != NULL) {
857                 const struct ldapsrv_call *pc = NULL;
858                 size_t count = 0;
859
860                 for (pc = call->conn->pending_calls; pc != NULL; pc = pc->next) {
861                         count += 1;
862                 }
863
864                 if (count >= call->conn->limits.max_notifications) {
865                         DEBUG(10,("SearchRequest: error MaxNotificationPerConn\n"));
866                         result = map_ldb_error(local_ctx,
867                                                LDB_ERR_ADMIN_LIMIT_EXCEEDED,
868                                                "MaxNotificationPerConn reached",
869                                                &errstr);
870                         goto reply;
871                 }
872
873                 /*
874                  * For now we need to do periodic retries on our own.
875                  * As the dsdb_notification module will return after each run.
876                  */
877                 call->notification.busy = true;
878         }
879
880         {
881                 const char *scheme = NULL;
882                 switch (call->conn->referral_scheme) {
883                 case LDAP_REFERRAL_SCHEME_LDAPS:
884                         scheme = "ldaps";
885                         break;
886                 default:
887                         scheme = "ldap";
888                 }
889                 ldb_ret = ldb_set_opaque(
890                         samdb,
891                         LDAP_REFERRAL_SCHEME_OPAQUE,
892                         discard_const_p(char *, scheme));
893                 if (ldb_ret != LDB_SUCCESS) {
894                         goto reply;
895                 }
896         }
897
898         {
899                 time_t timeout = call->conn->limits.search_timeout;
900
901                 if (timeout == 0
902                     || (req->timelimit != 0
903                         && req->timelimit < timeout))
904                 {
905                         timeout = req->timelimit;
906                 }
907                 ldb_set_timeout(samdb, lreq, timeout);
908         }
909
910         if (!call->conn->is_privileged) {
911                 ldb_req_mark_untrusted(lreq);
912         }
913
914         LDB_REQ_SET_LOCATION(lreq);
915
916         ldb_ret = ldb_request(samdb, lreq);
917
918         if (ldb_ret != LDB_SUCCESS) {
919                 goto reply;
920         }
921
922         ldb_ret = ldb_wait(lreq->handle, LDB_WAIT_ALL);
923
924         if (ldb_ret == LDB_SUCCESS) {
925                 if (call->notification.busy) {
926                         /* Move/Add it to the end */
927                         DLIST_DEMOTE(call->conn->pending_calls, call);
928                         call->notification.generation =
929                                 call->conn->service->notification.generation;
930
931                         if (callback_ctx->count != 0) {
932                                 call->notification.generation += 1;
933                                 ldapsrv_notification_retry_setup(call->conn->service,
934                                                                  true);
935                         }
936
937                         talloc_free(local_ctx);
938                         return NT_STATUS_OK;
939                 }
940         }
941
942 reply:
943
944         /*
945          * This looks like duplicated code - because it is - but
946          * otherwise the work in the parameters will be done
947          * regardless, this way the functions only execute when the
948          * log level is set.
949          *
950          * The basedn is re-obtained as a string to escape it
951          */
952         if ((req->timelimit == 0 || call->conn->limits.search_timeout < req->timelimit)
953             && ldb_ret == LDB_ERR_TIME_LIMIT_EXCEEDED) {
954                 struct dom_sid_buf sid_buf;
955                 DBG_WARNING("MaxQueryDuration(%d) timeout exceeded "
956                             "in SearchRequest by %s from %s filter: [%s] "
957                             "basedn: [%s] "
958                             "scope: [%s]\n",
959                             call->conn->limits.search_timeout,
960                             dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
961                                             &sid_buf),
962                             tsocket_address_string(call->conn->connection->remote_address,
963                                                    call),
964                             ldb_filter_from_tree(call, req->tree),
965                             ldb_dn_get_extended_linearized(call, basedn, 1),
966                             scope_str);
967                 for (i=0; i < req->num_attributes; i++) {
968                         DBG_WARNING("MaxQueryDuration timeout exceeded attrs: [%s]\n",
969                                     req->attributes[i]);
970                 }
971
972         } else if (timeval_expired(&warning_time)) {
973                 struct dom_sid_buf sid_buf;
974                 DBG_NOTICE("Long LDAP Query: Duration was %.2fs, "
975                            "MaxQueryDuration(%d)/4 == %d "
976                            "in SearchRequest by %s from %s filter: [%s] "
977                            "basedn: [%s] "
978                            "scope: [%s] "
979                            "result: %s\n",
980                            timeval_elapsed(&start_time),
981                            call->conn->limits.search_timeout,
982                            call->conn->limits.search_timeout / 4,
983                            dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
984                                            &sid_buf),
985                            tsocket_address_string(call->conn->connection->remote_address,
986                                                   call),
987                            ldb_filter_from_tree(call, req->tree),
988                            ldb_dn_get_extended_linearized(call, basedn, 1),
989                            scope_str,
990                            ldb_strerror(ldb_ret));
991                 for (i=0; i < req->num_attributes; i++) {
992                         DBG_NOTICE("Long LDAP Query attrs: [%s]\n",
993                                    req->attributes[i]);
994                 }
995         } else {
996                 struct dom_sid_buf sid_buf;
997                 DBG_INFO("LDAP Query: Duration was %.2fs, "
998                          "SearchRequest by %s from %s filter: [%s] "
999                          "basedn: [%s] "
1000                          "scope: [%s] "
1001                          "result: %s\n",
1002                          timeval_elapsed(&start_time),
1003                          dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
1004                                          &sid_buf),
1005                          tsocket_address_string(call->conn->connection->remote_address,
1006                                                 call),
1007                          ldb_filter_from_tree(call, req->tree),
1008                          ldb_dn_get_extended_linearized(call, basedn, 1),
1009                          scope_str,
1010                          ldb_strerror(ldb_ret));
1011         }
1012
1013         DLIST_REMOVE(call->conn->pending_calls, call);
1014         call->notification.busy = false;
1015
1016         done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
1017         NT_STATUS_HAVE_NO_MEMORY(done_r);
1018
1019         done = &done_r->msg->r.SearchResultDone;
1020         done->dn = NULL;
1021         done->referral = NULL;
1022
1023         if (result != -1) {
1024         } else if (ldb_ret == LDB_SUCCESS) {
1025                 if (callback_ctx->controls) {
1026                         done_r->msg->controls = callback_ctx->controls;
1027                         talloc_steal(done_r->msg, callback_ctx->controls);
1028                 }
1029                 result = LDB_SUCCESS;
1030         } else {
1031                 DEBUG(10,("SearchRequest: error\n"));
1032                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1033                                        &errstr);
1034         }
1035
1036         done->resultcode = result;
1037         done->errormessage = (errstr?talloc_strdup(done_r, errstr):NULL);
1038
1039         talloc_free(local_ctx);
1040
1041         return ldapsrv_queue_reply_forced(call, done_r);
1042 }
1043
1044 static NTSTATUS ldapsrv_ModifyRequest(struct ldapsrv_call *call)
1045 {
1046         struct ldap_ModifyRequest *req = &call->request->r.ModifyRequest;
1047         struct ldap_Result *modify_result;
1048         struct ldapsrv_reply *modify_reply;
1049         TALLOC_CTX *local_ctx;
1050         struct ldb_context *samdb = call->conn->ldb;
1051         struct ldb_message *msg = NULL;
1052         struct ldb_dn *dn;
1053         const char *errstr = NULL;
1054         int result = LDAP_SUCCESS;
1055         int ldb_ret;
1056         unsigned int i,j;
1057         struct ldb_result *res = NULL;
1058
1059         DEBUG(10, ("ModifyRequest"));
1060         DEBUGADD(10, (" dn: %s\n", req->dn));
1061
1062         local_ctx = talloc_named(call, 0, "ModifyRequest local memory context");
1063         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1064
1065         dn = ldb_dn_new(local_ctx, samdb, req->dn);
1066         NT_STATUS_HAVE_NO_MEMORY(dn);
1067
1068         DEBUG(10, ("ModifyRequest: dn: [%s]\n", req->dn));
1069
1070         msg = ldb_msg_new(local_ctx);
1071         NT_STATUS_HAVE_NO_MEMORY(msg);
1072
1073         msg->dn = dn;
1074
1075         if (req->num_mods > 0) {
1076                 msg->num_elements = req->num_mods;
1077                 msg->elements = talloc_array(msg, struct ldb_message_element, req->num_mods);
1078                 NT_STATUS_HAVE_NO_MEMORY(msg->elements);
1079
1080                 for (i=0; i < msg->num_elements; i++) {
1081                         msg->elements[i].name = discard_const_p(char, req->mods[i].attrib.name);
1082                         msg->elements[i].num_values = 0;
1083                         msg->elements[i].values = NULL;
1084
1085                         switch (req->mods[i].type) {
1086                         default:
1087                                 result = LDAP_PROTOCOL_ERROR;
1088                                 map_ldb_error(local_ctx,
1089                                         LDB_ERR_PROTOCOL_ERROR, NULL, &errstr);
1090                                 errstr = talloc_asprintf(local_ctx,
1091                                         "%s. Invalid LDAP_MODIFY_* type", errstr);
1092                                 goto reply;
1093                         case LDAP_MODIFY_ADD:
1094                                 msg->elements[i].flags = LDB_FLAG_MOD_ADD;
1095                                 break;
1096                         case LDAP_MODIFY_DELETE:
1097                                 msg->elements[i].flags = LDB_FLAG_MOD_DELETE;
1098                                 break;
1099                         case LDAP_MODIFY_REPLACE:
1100                                 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1101                                 break;
1102                         }
1103
1104                         msg->elements[i].num_values = req->mods[i].attrib.num_values;
1105                         if (msg->elements[i].num_values > 0) {
1106                                 msg->elements[i].values = talloc_array(msg->elements, struct ldb_val,
1107                                                                        msg->elements[i].num_values);
1108                                 NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
1109
1110                                 for (j=0; j < msg->elements[i].num_values; j++) {
1111                                         msg->elements[i].values[j].length = req->mods[i].attrib.values[j].length;
1112                                         msg->elements[i].values[j].data = req->mods[i].attrib.values[j].data;                   
1113                                 }
1114                         }
1115                 }
1116         }
1117
1118 reply:
1119         modify_reply = ldapsrv_init_reply(call, LDAP_TAG_ModifyResponse);
1120         NT_STATUS_HAVE_NO_MEMORY(modify_reply);
1121
1122         if (result == LDAP_SUCCESS) {
1123                 res = talloc_zero(local_ctx, struct ldb_result);
1124                 NT_STATUS_HAVE_NO_MEMORY(res);
1125                 ldb_ret = ldapsrv_mod_with_controls(call, msg, call->request->controls, res);
1126                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1127                                        &errstr);
1128         }
1129
1130         modify_result = &modify_reply->msg->r.ModifyResponse;
1131         modify_result->dn = NULL;
1132         if ((res != NULL) && (res->refs != NULL)) {
1133                 modify_result->resultcode = map_ldb_error(local_ctx,
1134                                                           LDB_ERR_REFERRAL,
1135                                                           NULL, &errstr);
1136                 modify_result->errormessage = (errstr?talloc_strdup(modify_reply, errstr):NULL);
1137                 modify_result->referral = talloc_strdup(call, *res->refs);
1138         } else {
1139                 modify_result->resultcode = result;
1140                 modify_result->errormessage = (errstr?talloc_strdup(modify_reply, errstr):NULL);
1141                 modify_result->referral = NULL;
1142         }
1143         talloc_free(local_ctx);
1144
1145         return ldapsrv_queue_reply(call, modify_reply);
1146
1147 }
1148
1149 static NTSTATUS ldapsrv_AddRequest(struct ldapsrv_call *call)
1150 {
1151         struct ldap_AddRequest *req = &call->request->r.AddRequest;
1152         struct ldap_Result *add_result;
1153         struct ldapsrv_reply *add_reply;
1154         TALLOC_CTX *local_ctx;
1155         struct ldb_context *samdb = call->conn->ldb;
1156         struct ldb_message *msg = NULL;
1157         struct ldb_dn *dn;
1158         const char *errstr = NULL;
1159         int result = LDAP_SUCCESS;
1160         int ldb_ret;
1161         unsigned int i,j;
1162         struct ldb_result *res = NULL;
1163
1164         DEBUG(10, ("AddRequest"));
1165         DEBUGADD(10, (" dn: %s\n", req->dn));
1166
1167         local_ctx = talloc_named(call, 0, "AddRequest local memory context");
1168         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1169
1170         dn = ldb_dn_new(local_ctx, samdb, req->dn);
1171         NT_STATUS_HAVE_NO_MEMORY(dn);
1172
1173         DEBUG(10, ("AddRequest: dn: [%s]\n", req->dn));
1174
1175         msg = talloc(local_ctx, struct ldb_message);
1176         NT_STATUS_HAVE_NO_MEMORY(msg);
1177
1178         msg->dn = dn;
1179         msg->num_elements = 0;
1180         msg->elements = NULL;
1181
1182         if (req->num_attributes > 0) {
1183                 msg->num_elements = req->num_attributes;
1184                 msg->elements = talloc_array(msg, struct ldb_message_element, msg->num_elements);
1185                 NT_STATUS_HAVE_NO_MEMORY(msg->elements);
1186
1187                 for (i=0; i < msg->num_elements; i++) {
1188                         msg->elements[i].name = discard_const_p(char, req->attributes[i].name);
1189                         msg->elements[i].flags = 0;
1190                         msg->elements[i].num_values = 0;
1191                         msg->elements[i].values = NULL;
1192                         
1193                         if (req->attributes[i].num_values > 0) {
1194                                 msg->elements[i].num_values = req->attributes[i].num_values;
1195                                 msg->elements[i].values = talloc_array(msg->elements, struct ldb_val,
1196                                                                        msg->elements[i].num_values);
1197                                 NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
1198
1199                                 for (j=0; j < msg->elements[i].num_values; j++) {
1200                                         msg->elements[i].values[j].length = req->attributes[i].values[j].length;
1201                                         msg->elements[i].values[j].data = req->attributes[i].values[j].data;                    
1202                                 }
1203                         }
1204                 }
1205         }
1206
1207         add_reply = ldapsrv_init_reply(call, LDAP_TAG_AddResponse);
1208         NT_STATUS_HAVE_NO_MEMORY(add_reply);
1209
1210         if (result == LDAP_SUCCESS) {
1211                 res = talloc_zero(local_ctx, struct ldb_result);
1212                 NT_STATUS_HAVE_NO_MEMORY(res);
1213                 ldb_ret = ldapsrv_add_with_controls(call, msg, call->request->controls, res);
1214                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1215                                        &errstr);
1216         }
1217
1218         add_result = &add_reply->msg->r.AddResponse;
1219         add_result->dn = NULL;
1220         if ((res != NULL) && (res->refs != NULL)) {
1221                 add_result->resultcode =  map_ldb_error(local_ctx,
1222                                                         LDB_ERR_REFERRAL, NULL,
1223                                                         &errstr);
1224                 add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
1225                 add_result->referral = talloc_strdup(call, *res->refs);
1226         } else {
1227                 add_result->resultcode = result;
1228                 add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
1229                 add_result->referral = NULL;
1230         }
1231         talloc_free(local_ctx);
1232
1233         return ldapsrv_queue_reply(call, add_reply);
1234
1235 }
1236
1237 static NTSTATUS ldapsrv_DelRequest(struct ldapsrv_call *call)
1238 {
1239         struct ldap_DelRequest *req = &call->request->r.DelRequest;
1240         struct ldap_Result *del_result;
1241         struct ldapsrv_reply *del_reply;
1242         TALLOC_CTX *local_ctx;
1243         struct ldb_context *samdb = call->conn->ldb;
1244         struct ldb_dn *dn;
1245         const char *errstr = NULL;
1246         int result = LDAP_SUCCESS;
1247         int ldb_ret;
1248         struct ldb_result *res = NULL;
1249
1250         DEBUG(10, ("DelRequest"));
1251         DEBUGADD(10, (" dn: %s\n", req->dn));
1252
1253         local_ctx = talloc_named(call, 0, "DelRequest local memory context");
1254         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1255
1256         dn = ldb_dn_new(local_ctx, samdb, req->dn);
1257         NT_STATUS_HAVE_NO_MEMORY(dn);
1258
1259         DEBUG(10, ("DelRequest: dn: [%s]\n", req->dn));
1260
1261         del_reply = ldapsrv_init_reply(call, LDAP_TAG_DelResponse);
1262         NT_STATUS_HAVE_NO_MEMORY(del_reply);
1263
1264         if (result == LDAP_SUCCESS) {
1265                 res = talloc_zero(local_ctx, struct ldb_result);
1266                 NT_STATUS_HAVE_NO_MEMORY(res);
1267                 ldb_ret = ldapsrv_del_with_controls(call, dn, call->request->controls, res);
1268                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1269                                        &errstr);
1270         }
1271
1272         del_result = &del_reply->msg->r.DelResponse;
1273         del_result->dn = NULL;
1274         if ((res != NULL) && (res->refs != NULL)) {
1275                 del_result->resultcode = map_ldb_error(local_ctx,
1276                                                        LDB_ERR_REFERRAL, NULL,
1277                                                        &errstr);
1278                 del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
1279                 del_result->referral = talloc_strdup(call, *res->refs);
1280         } else {
1281                 del_result->resultcode = result;
1282                 del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
1283                 del_result->referral = NULL;
1284         }
1285
1286         talloc_free(local_ctx);
1287
1288         return ldapsrv_queue_reply(call, del_reply);
1289 }
1290
1291 static NTSTATUS ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
1292 {
1293         struct ldap_ModifyDNRequest *req = &call->request->r.ModifyDNRequest;
1294         struct ldap_Result *modifydn;
1295         struct ldapsrv_reply *modifydn_r;
1296         TALLOC_CTX *local_ctx;
1297         struct ldb_context *samdb = call->conn->ldb;
1298         struct ldb_dn *olddn, *newdn=NULL, *newrdn;
1299         struct ldb_dn *parentdn = NULL;
1300         const char *errstr = NULL;
1301         int result = LDAP_SUCCESS;
1302         int ldb_ret;
1303         struct ldb_result *res = NULL;
1304
1305         DEBUG(10, ("ModifyDNRequest"));
1306         DEBUGADD(10, (" dn: %s", req->dn));
1307         DEBUGADD(10, (" newrdn: %s\n", req->newrdn));
1308
1309         local_ctx = talloc_named(call, 0, "ModifyDNRequest local memory context");
1310         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1311
1312         olddn = ldb_dn_new(local_ctx, samdb, req->dn);
1313         NT_STATUS_HAVE_NO_MEMORY(olddn);
1314
1315         newrdn = ldb_dn_new(local_ctx, samdb, req->newrdn);
1316         NT_STATUS_HAVE_NO_MEMORY(newrdn);
1317
1318         DEBUG(10, ("ModifyDNRequest: olddn: [%s]\n", req->dn));
1319         DEBUG(10, ("ModifyDNRequest: newrdn: [%s]\n", req->newrdn));
1320
1321         if (ldb_dn_get_comp_num(newrdn) == 0) {
1322                 result = LDAP_PROTOCOL_ERROR;
1323                 map_ldb_error(local_ctx, LDB_ERR_PROTOCOL_ERROR, NULL,
1324                               &errstr);
1325                 goto reply;
1326         }
1327
1328         if (ldb_dn_get_comp_num(newrdn) > 1) {
1329                 result = LDAP_NAMING_VIOLATION;
1330                 map_ldb_error(local_ctx, LDB_ERR_NAMING_VIOLATION, NULL,
1331                               &errstr);
1332                 goto reply;
1333         }
1334
1335         /* we can't handle the rename if we should not remove the old dn */
1336         if (!req->deleteolddn) {
1337                 result = LDAP_UNWILLING_TO_PERFORM;
1338                 map_ldb_error(local_ctx, LDB_ERR_UNWILLING_TO_PERFORM, NULL,
1339                               &errstr);
1340                 errstr = talloc_asprintf(local_ctx,
1341                         "%s. Old RDN must be deleted", errstr);
1342                 goto reply;
1343         }
1344
1345         if (req->newsuperior) {
1346                 DEBUG(10, ("ModifyDNRequest: newsuperior: [%s]\n", req->newsuperior));
1347                 parentdn = ldb_dn_new(local_ctx, samdb, req->newsuperior);
1348         }
1349
1350         if (!parentdn) {
1351                 parentdn = ldb_dn_get_parent(local_ctx, olddn);
1352         }
1353         if (!parentdn) {
1354                 result = LDAP_NO_SUCH_OBJECT;
1355                 map_ldb_error(local_ctx, LDB_ERR_NO_SUCH_OBJECT, NULL, &errstr);
1356                 goto reply;
1357         }
1358
1359         if ( ! ldb_dn_add_child(parentdn, newrdn)) {
1360                 result = LDAP_OTHER;
1361                 map_ldb_error(local_ctx, LDB_ERR_OTHER, NULL, &errstr);
1362                 goto reply;
1363         }
1364         newdn = parentdn;
1365
1366 reply:
1367         modifydn_r = ldapsrv_init_reply(call, LDAP_TAG_ModifyDNResponse);
1368         NT_STATUS_HAVE_NO_MEMORY(modifydn_r);
1369
1370         if (result == LDAP_SUCCESS) {
1371                 res = talloc_zero(local_ctx, struct ldb_result);
1372                 NT_STATUS_HAVE_NO_MEMORY(res);
1373                 ldb_ret = ldapsrv_rename_with_controls(call, olddn, newdn, call->request->controls, res);
1374                 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1375                                        &errstr);
1376         }
1377
1378         modifydn = &modifydn_r->msg->r.ModifyDNResponse;
1379         modifydn->dn = NULL;
1380         if ((res != NULL) && (res->refs != NULL)) {
1381                 modifydn->resultcode = map_ldb_error(local_ctx,
1382                                                      LDB_ERR_REFERRAL, NULL,
1383                                                      &errstr);;
1384                 modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
1385                 modifydn->referral = talloc_strdup(call, *res->refs);
1386         } else {
1387                 modifydn->resultcode = result;
1388                 modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
1389                 modifydn->referral = NULL;
1390         }
1391
1392         talloc_free(local_ctx);
1393
1394         return ldapsrv_queue_reply(call, modifydn_r);
1395 }
1396
1397 static NTSTATUS ldapsrv_CompareRequest(struct ldapsrv_call *call)
1398 {
1399         struct ldap_CompareRequest *req = &call->request->r.CompareRequest;
1400         struct ldap_Result *compare;
1401         struct ldapsrv_reply *compare_r;
1402         TALLOC_CTX *local_ctx;
1403         struct ldb_context *samdb = call->conn->ldb;
1404         struct ldb_result *res = NULL;
1405         struct ldb_dn *dn;
1406         const char *attrs[1];
1407         const char *errstr = NULL;
1408         const char *filter = NULL;
1409         int result = LDAP_SUCCESS;
1410         int ldb_ret;
1411
1412         DEBUG(10, ("CompareRequest"));
1413         DEBUGADD(10, (" dn: %s\n", req->dn));
1414
1415         local_ctx = talloc_named(call, 0, "CompareRequest local_memory_context");
1416         NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1417
1418         dn = ldb_dn_new(local_ctx, samdb, req->dn);
1419         NT_STATUS_HAVE_NO_MEMORY(dn);
1420
1421         DEBUG(10, ("CompareRequest: dn: [%s]\n", req->dn));
1422         filter = talloc_asprintf(local_ctx, "(%s=%*s)", req->attribute, 
1423                                  (int)req->value.length, req->value.data);
1424         NT_STATUS_HAVE_NO_MEMORY(filter);
1425
1426         DEBUGADD(10, ("CompareRequest: attribute: [%s]\n", filter));
1427
1428         attrs[0] = NULL;
1429
1430         compare_r = ldapsrv_init_reply(call, LDAP_TAG_CompareResponse);
1431         NT_STATUS_HAVE_NO_MEMORY(compare_r);
1432
1433         if (result == LDAP_SUCCESS) {
1434                 ldb_ret = ldb_search(samdb, local_ctx, &res,
1435                                      dn, LDB_SCOPE_BASE, attrs, "%s", filter);
1436                 if (ldb_ret != LDB_SUCCESS) {
1437                         result = map_ldb_error(local_ctx, ldb_ret,
1438                                                ldb_errstring(samdb), &errstr);
1439                         DEBUG(10,("CompareRequest: error: %s\n", errstr));
1440                 } else if (res->count == 0) {
1441                         DEBUG(10,("CompareRequest: doesn't matched\n"));
1442                         result = LDAP_COMPARE_FALSE;
1443                         errstr = NULL;
1444                 } else if (res->count == 1) {
1445                         DEBUG(10,("CompareRequest: matched\n"));
1446                         result = LDAP_COMPARE_TRUE;
1447                         errstr = NULL;
1448                 } else if (res->count > 1) {
1449                         result = LDAP_OTHER;
1450                         map_ldb_error(local_ctx, LDB_ERR_OTHER, NULL, &errstr);
1451                         errstr = talloc_asprintf(local_ctx,
1452                                 "%s. Too many objects match!", errstr);
1453                         DEBUG(10,("CompareRequest: %d results: %s\n", res->count, errstr));
1454                 }
1455         }
1456
1457         compare = &compare_r->msg->r.CompareResponse;
1458         compare->dn = NULL;
1459         compare->resultcode = result;
1460         compare->errormessage = (errstr?talloc_strdup(compare_r,errstr):NULL);
1461         compare->referral = NULL;
1462
1463         talloc_free(local_ctx);
1464
1465         return ldapsrv_queue_reply(call, compare_r);
1466 }
1467
1468 static NTSTATUS ldapsrv_AbandonRequest(struct ldapsrv_call *call)
1469 {
1470         struct ldap_AbandonRequest *req = &call->request->r.AbandonRequest;
1471         struct ldapsrv_call *c = NULL;
1472         struct ldapsrv_call *n = NULL;
1473
1474         DEBUG(10, ("AbandonRequest\n"));
1475
1476         for (c = call->conn->pending_calls; c != NULL; c = n) {
1477                 n = c->next;
1478
1479                 if (c->request->messageid != req->messageid) {
1480                         continue;
1481                 }
1482
1483                 DLIST_REMOVE(call->conn->pending_calls, c);
1484                 TALLOC_FREE(c);
1485         }
1486
1487         return NT_STATUS_OK;
1488 }
1489
1490 static NTSTATUS ldapsrv_expired(struct ldapsrv_call *call)
1491 {
1492         struct ldapsrv_reply *reply = NULL;
1493         struct ldap_ExtendedResponse *r = NULL;
1494
1495         DBG_DEBUG("Sending connection expired message\n");
1496
1497         reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
1498         if (reply == NULL) {
1499                 return NT_STATUS_NO_MEMORY;
1500         }
1501
1502         /*
1503          * According to RFC4511 section 4.4.1 this has a msgid of 0
1504          */
1505         reply->msg->messageid = 0;
1506
1507         r = &reply->msg->r.ExtendedResponse;
1508         r->response.resultcode = LDB_ERR_UNAVAILABLE;
1509         r->response.errormessage = "The server has timed out this connection";
1510         r->oid = "1.3.6.1.4.1.1466.20036"; /* see rfc4511 section 4.4.1 */
1511
1512         ldapsrv_queue_reply(call, reply);
1513         return NT_STATUS_OK;
1514 }
1515
1516 NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
1517 {
1518         unsigned int i;
1519         struct ldap_message *msg = call->request;
1520         struct ldapsrv_connection *conn = call->conn;
1521         NTSTATUS status;
1522         bool expired;
1523
1524         expired = timeval_expired(&conn->limits.expire_time);
1525         if (expired) {
1526                 status = ldapsrv_expired(call);
1527                 if (!NT_STATUS_IS_OK(status)) {
1528                         return status;
1529                 }
1530                 return NT_STATUS_NETWORK_SESSION_EXPIRED;
1531         }
1532
1533         /* Check for undecoded critical extensions */
1534         for (i=0; msg->controls && msg->controls[i]; i++) {
1535                 if (!msg->controls_decoded[i] && 
1536                     msg->controls[i]->critical) {
1537                         DEBUG(3, ("ldapsrv_do_call: Critical extension %s is not known to this server\n",
1538                                   msg->controls[i]->oid));
1539                         return ldapsrv_unwilling(call, LDAP_UNAVAILABLE_CRITICAL_EXTENSION);
1540                 }
1541         }
1542
1543         if (call->conn->authz_logged == false) {
1544                 bool log = true;
1545
1546                 /*
1547                  * We do not want to log anonymous access if the query
1548                  * is just for the rootDSE, or it is a startTLS or a
1549                  * Bind.
1550                  *
1551                  * A rootDSE search could also be done over
1552                  * CLDAP anonymously for example, so these don't
1553                  * really count.
1554                  * Essentially we want to know about
1555                  * access beyond that normally done prior to a
1556                  * bind.
1557                  */
1558
1559                 switch(call->request->type) {
1560                 case LDAP_TAG_BindRequest:
1561                 case LDAP_TAG_UnbindRequest:
1562                 case LDAP_TAG_AbandonRequest:
1563                         log = false;
1564                         break;
1565                 case LDAP_TAG_ExtendedResponse: {
1566                         struct ldap_ExtendedRequest *req = &call->request->r.ExtendedRequest;
1567                         if (strcmp(req->oid, LDB_EXTENDED_START_TLS_OID) == 0) {
1568                                 log = false;
1569                         }
1570                         break;
1571                 }
1572                 case LDAP_TAG_SearchRequest: {
1573                         struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
1574                         if (req->scope == LDAP_SEARCH_SCOPE_BASE) {
1575                                 if (req->basedn[0] == '\0') {
1576                                         log = false;
1577                                 }
1578                         }
1579                         break;
1580                 }
1581                 default:
1582                         break;
1583                 }
1584
1585                 if (log) {
1586                         const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
1587                         if (call->conn->sockets.active == call->conn->sockets.tls) {
1588                                 transport_protection = AUTHZ_TRANSPORT_PROTECTION_TLS;
1589                         }
1590
1591                         log_successful_authz_event(call->conn->connection->msg_ctx,
1592                                                    call->conn->connection->lp_ctx,
1593                                                    call->conn->connection->remote_address,
1594                                                    call->conn->connection->local_address,
1595                                                    "LDAP",
1596                                                    "no bind",
1597                                                    transport_protection,
1598                                                    call->conn->session_info,
1599                                                    NULL /* client_audit_info */,
1600                                                    NULL /* server_audit_info */);
1601
1602                         call->conn->authz_logged = true;
1603                 }
1604         }
1605
1606         switch(call->request->type) {
1607         case LDAP_TAG_BindRequest:
1608                 return ldapsrv_BindRequest(call);
1609         case LDAP_TAG_UnbindRequest:
1610                 return ldapsrv_UnbindRequest(call);
1611         case LDAP_TAG_SearchRequest:
1612                 return ldapsrv_SearchRequest(call);
1613         case LDAP_TAG_ModifyRequest:
1614                 status = ldapsrv_ModifyRequest(call);
1615                 break;
1616         case LDAP_TAG_AddRequest:
1617                 status = ldapsrv_AddRequest(call);
1618                 break;
1619         case LDAP_TAG_DelRequest:
1620                 status = ldapsrv_DelRequest(call);
1621                 break;
1622         case LDAP_TAG_ModifyDNRequest:
1623                 status = ldapsrv_ModifyDNRequest(call);
1624                 break;
1625         case LDAP_TAG_CompareRequest:
1626                 return ldapsrv_CompareRequest(call);
1627         case LDAP_TAG_AbandonRequest:
1628                 return ldapsrv_AbandonRequest(call);
1629         case LDAP_TAG_ExtendedRequest:
1630                 status = ldapsrv_ExtendedRequest(call);
1631                 break;
1632         default:
1633                 return ldapsrv_unwilling(call, LDAP_PROTOCOL_ERROR);
1634         }
1635
1636         if (NT_STATUS_IS_OK(status)) {
1637                 ldapsrv_notification_retry_setup(call->conn->service, true);
1638         }
1639
1640         return status;
1641 }