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