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