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