python:tests: Store keys as bytes rather than as tuples
[Samba.git] / source4 / ldap_server / ldap_bind.c
blob65e252edb702a4a1ef981933031ff61d766440ea
1 /*
2 Unix SMB/CIFS implementation.
3 LDAP server
4 Copyright (C) Stefan Metzmacher 2004
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "ldap_server/ldap_server.h"
22 #include "auth/auth.h"
23 #include "samba/service.h"
24 #include <ldb.h>
25 #include <ldb_errors.h>
26 #include "../lib/util/dlinklist.h"
27 #include "dsdb/samdb/samdb.h"
28 #include "auth/gensec/gensec.h"
29 #include "auth/gensec/gensec_tstream.h"
30 #include "lib/tls/tls.h"
31 #include "param/param.h"
32 #include "../lib/util/tevent_ntstatus.h"
33 #include "lib/util/time_basic.h"
35 static char *ldapsrv_bind_error_msg(TALLOC_CTX *mem_ctx,
36 HRESULT hresult,
37 uint32_t DSID,
38 NTSTATUS status)
40 WERROR werr;
41 char *msg = NULL;
43 status = nt_status_squash(status);
44 werr = ntstatus_to_werror(status);
47 * There are 4 lower case hex digits following 'v' at the end,
48 * but different Windows Versions return different values:
50 * Windows 2008R2 uses 'v1db1'
51 * Windows 2012R2 uses 'v2580'
53 * We just match Windows 2008R2 as that's what was referenced
54 * in https://bugzilla.samba.org/show_bug.cgi?id=9048
56 msg = talloc_asprintf(mem_ctx, "%08X: LdapErr: DSID-%08X, comment: "
57 "AcceptSecurityContext error, data %x, v1db1",
58 (unsigned)HRES_ERROR_V(hresult),
59 (unsigned)DSID,
60 (unsigned)W_ERROR_V(werr));
62 return msg;
65 struct ldapsrv_bind_wait_context {
66 struct ldapsrv_reply *reply;
67 struct tevent_req *req;
68 NTSTATUS status;
69 bool done;
72 struct ldapsrv_bind_wait_state {
73 uint8_t dummy;
76 static struct tevent_req *ldapsrv_bind_wait_send(TALLOC_CTX *mem_ctx,
77 struct tevent_context *ev,
78 void *private_data)
80 struct ldapsrv_bind_wait_context *bind_wait =
81 talloc_get_type_abort(private_data,
82 struct ldapsrv_bind_wait_context);
83 struct tevent_req *req;
84 struct ldapsrv_bind_wait_state *state;
86 req = tevent_req_create(mem_ctx, &state,
87 struct ldapsrv_bind_wait_state);
88 if (req == NULL) {
89 return NULL;
91 bind_wait->req = req;
93 tevent_req_defer_callback(req, ev);
95 if (!bind_wait->done) {
96 return req;
99 if (tevent_req_nterror(req, bind_wait->status)) {
100 return tevent_req_post(req, ev);
103 tevent_req_done(req);
104 return tevent_req_post(req, ev);
107 static NTSTATUS ldapsrv_bind_wait_recv(struct tevent_req *req)
109 return tevent_req_simple_recv_ntstatus(req);
112 static NTSTATUS ldapsrv_bind_wait_setup(struct ldapsrv_call *call,
113 struct ldapsrv_reply *reply)
115 struct ldapsrv_bind_wait_context *bind_wait = NULL;
117 if (call->wait_private != NULL) {
118 return NT_STATUS_INTERNAL_ERROR;
121 bind_wait = talloc_zero(call, struct ldapsrv_bind_wait_context);
122 if (bind_wait == NULL) {
123 return NT_STATUS_NO_MEMORY;
125 bind_wait->reply = reply;
127 call->wait_private = bind_wait;
128 call->wait_send = ldapsrv_bind_wait_send;
129 call->wait_recv = ldapsrv_bind_wait_recv;
130 return NT_STATUS_OK;
133 static void ldapsrv_bind_wait_finished(struct ldapsrv_call *call,
134 NTSTATUS status)
136 struct ldapsrv_bind_wait_context *bind_wait =
137 talloc_get_type_abort(call->wait_private,
138 struct ldapsrv_bind_wait_context);
140 bind_wait->done = true;
141 bind_wait->status = status;
143 if (bind_wait->req == NULL) {
144 return;
147 if (tevent_req_nterror(bind_wait->req, status)) {
148 return;
151 tevent_req_done(bind_wait->req);
154 static void ldapsrv_BindSimple_done(struct tevent_req *subreq);
156 static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
158 struct ldap_BindRequest *req = &call->request->r.BindRequest;
159 struct ldapsrv_reply *reply = NULL;
160 struct ldap_BindResponse *resp = NULL;
161 int result;
162 const char *errstr = NULL;
163 NTSTATUS status;
164 bool using_tls = call->conn->sockets.active == call->conn->sockets.tls;
165 struct tevent_req *subreq = NULL;
167 DEBUG(10, ("BindSimple dn: %s\n",req->dn));
169 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
170 if (!reply) {
171 return NT_STATUS_NO_MEMORY;
174 if (req->dn != NULL &&
175 strlen(req->dn) != 0 &&
176 call->conn->require_strong_auth > LDAP_SERVER_REQUIRE_STRONG_AUTH_NO &&
177 !using_tls)
179 status = NT_STATUS_NETWORK_ACCESS_DENIED;
180 result = LDAP_STRONG_AUTH_REQUIRED;
181 errstr = talloc_asprintf(reply,
182 "BindSimple: Transport encryption required.");
183 goto do_reply;
186 subreq = authenticate_ldap_simple_bind_send(call,
187 call->conn->connection->event.ctx,
188 call->conn->connection->msg_ctx,
189 call->conn->lp_ctx,
190 call->conn->connection->remote_address,
191 call->conn->connection->local_address,
192 using_tls,
193 req->dn,
194 req->creds.password);
195 if (subreq == NULL) {
196 return NT_STATUS_NO_MEMORY;
198 tevent_req_set_callback(subreq, ldapsrv_BindSimple_done, call);
200 status = ldapsrv_bind_wait_setup(call, reply);
201 if (!NT_STATUS_IS_OK(status)) {
202 TALLOC_FREE(subreq);
203 return status;
207 * The rest will be async.
209 return NT_STATUS_OK;
211 do_reply:
212 resp = &reply->msg->r.BindResponse;
213 resp->response.resultcode = result;
214 resp->response.errormessage = errstr;
215 resp->response.dn = NULL;
216 resp->response.referral = NULL;
217 resp->SASL.secblob = NULL;
219 ldapsrv_queue_reply(call, reply);
220 return NT_STATUS_OK;
223 static void ldapsrv_BindSimple_done(struct tevent_req *subreq)
225 struct ldapsrv_call *call =
226 tevent_req_callback_data(subreq,
227 struct ldapsrv_call);
228 struct ldapsrv_bind_wait_context *bind_wait =
229 talloc_get_type_abort(call->wait_private,
230 struct ldapsrv_bind_wait_context);
231 struct ldapsrv_reply *reply = bind_wait->reply;
232 struct auth_session_info *session_info = NULL;
233 NTSTATUS status;
234 struct ldap_BindResponse *resp = NULL;
235 int result;
236 const char *errstr = NULL;
238 status = authenticate_ldap_simple_bind_recv(subreq,
239 call,
240 &session_info);
241 if (NT_STATUS_IS_OK(status)) {
242 char *ldb_errstring = NULL;
243 result = LDAP_SUCCESS;
244 errstr = NULL;
246 talloc_unlink(call->conn, call->conn->session_info);
247 call->conn->session_info = talloc_steal(call->conn, session_info);
249 call->conn->authz_logged = true;
251 /* don't leak the old LDB */
252 talloc_unlink(call->conn, call->conn->ldb);
254 result = ldapsrv_backend_Init(call->conn, &ldb_errstring);
256 if (result != LDB_SUCCESS) {
257 /* Only put the detailed error in DEBUG() */
258 DBG_ERR("ldapsrv_backend_Init failed: %s: %s\n",
259 ldb_errstring, ldb_strerror(result));
260 errstr = talloc_strdup(reply,
261 "Simple Bind: Failed to advise "
262 "ldb new credentials");
263 result = LDB_ERR_OPERATIONS_ERROR;
265 } else {
266 status = nt_status_squash(status);
268 result = LDAP_INVALID_CREDENTIALS;
269 errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_INVALID_TOKEN,
270 0x0C0903A9, status);
273 resp = &reply->msg->r.BindResponse;
274 resp->response.resultcode = result;
275 resp->response.errormessage = errstr;
276 resp->response.dn = NULL;
277 resp->response.referral = NULL;
278 resp->SASL.secblob = NULL;
280 ldapsrv_queue_reply(call, reply);
281 ldapsrv_bind_wait_finished(call, NT_STATUS_OK);
284 struct ldapsrv_sasl_postprocess_context {
285 struct ldapsrv_connection *conn;
286 struct tstream_context *sasl;
289 struct ldapsrv_sasl_postprocess_state {
290 uint8_t dummy;
293 static struct tevent_req *ldapsrv_sasl_postprocess_send(TALLOC_CTX *mem_ctx,
294 struct tevent_context *ev,
295 void *private_data)
297 struct ldapsrv_sasl_postprocess_context *context =
298 talloc_get_type_abort(private_data,
299 struct ldapsrv_sasl_postprocess_context);
300 struct tevent_req *req;
301 struct ldapsrv_sasl_postprocess_state *state;
303 req = tevent_req_create(mem_ctx, &state,
304 struct ldapsrv_sasl_postprocess_state);
305 if (req == NULL) {
306 return NULL;
309 TALLOC_FREE(context->conn->sockets.sasl);
310 context->conn->sockets.sasl = talloc_move(context->conn, &context->sasl);
311 context->conn->sockets.active = context->conn->sockets.sasl;
313 tevent_req_done(req);
314 return tevent_req_post(req, ev);
317 static NTSTATUS ldapsrv_sasl_postprocess_recv(struct tevent_req *req)
319 return tevent_req_simple_recv_ntstatus(req);
322 static NTSTATUS ldapsrv_setup_gensec(struct ldapsrv_connection *conn,
323 const char *sasl_mech,
324 struct gensec_security **_gensec_security)
326 NTSTATUS status;
328 struct gensec_security *gensec_security;
330 status = samba_server_gensec_start(conn,
331 conn->connection->event.ctx,
332 conn->connection->msg_ctx,
333 conn->lp_ctx,
334 conn->server_credentials,
335 "ldap",
336 &gensec_security);
337 if (!NT_STATUS_IS_OK(status)) {
338 return status;
341 status = gensec_set_target_service_description(gensec_security,
342 "LDAP");
343 if (!NT_STATUS_IS_OK(status)) {
344 return status;
347 status = gensec_set_remote_address(gensec_security,
348 conn->connection->remote_address);
349 if (!NT_STATUS_IS_OK(status)) {
350 return status;
353 status = gensec_set_local_address(gensec_security,
354 conn->connection->local_address);
355 if (!NT_STATUS_IS_OK(status)) {
356 return status;
359 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
360 gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAP_STYLE);
362 if (conn->sockets.active == conn->sockets.tls) {
363 uint32_t initiator_addrtype = 0;
364 const DATA_BLOB *initiator_address = NULL;
365 uint32_t acceptor_addrtype = 0;
366 const DATA_BLOB *acceptor_address = NULL;
367 const DATA_BLOB *application_data =
368 tstream_tls_channel_bindings(conn->sockets.tls);
370 status = gensec_set_channel_bindings(gensec_security,
371 initiator_addrtype,
372 initiator_address,
373 acceptor_addrtype,
374 acceptor_address,
375 application_data);
376 if (!NT_STATUS_IS_OK(status)) {
377 return status;
381 * By default channel bindings are required,
382 * so we only set GENSEC_FEATURE_CB_OPTIONAL
383 * for the legacy option:
385 * ldap server require strong auth = no
386 * or
387 * ldap server require strong auth =
388 * allow_sasl_without_tls_channel_bindings
390 * And this as an alias to cope with existing smb.conf
391 * files:
393 * ldap server require strong auth = allow_sasl_over_tls
395 switch (conn->require_strong_auth) {
396 case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO:
397 case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS:
398 case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_WITHOUT_TLS_CB:
399 gensec_want_feature(gensec_security,
400 GENSEC_FEATURE_CB_OPTIONAL);
401 break;
402 default:
403 break;
406 gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAPS_TRANSPORT);
409 status = gensec_start_mech_by_sasl_name(gensec_security, sasl_mech);
411 if (!NT_STATUS_IS_OK(status)) {
412 return status;
415 *_gensec_security = gensec_security;
416 return status;
419 static void ldapsrv_BindSASL_done(struct tevent_req *subreq);
421 static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
423 struct ldap_BindRequest *req = &call->request->r.BindRequest;
424 struct ldapsrv_reply *reply;
425 struct ldap_BindResponse *resp;
426 struct ldapsrv_connection *conn;
427 int result = 0;
428 const char *errstr=NULL;
429 NTSTATUS status = NT_STATUS_OK;
430 DATA_BLOB input = data_blob_null;
431 struct tevent_req *subreq = NULL;
433 DEBUG(10, ("BindSASL dn: %s\n",req->dn));
435 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
436 if (!reply) {
437 return NT_STATUS_NO_MEMORY;
439 resp = &reply->msg->r.BindResponse;
440 /* Windows 2000 mmc doesn't like secblob == NULL and reports a decoding error */
441 resp->SASL.secblob = talloc_zero(reply, DATA_BLOB);
442 if (resp->SASL.secblob == NULL) {
443 return NT_STATUS_NO_MEMORY;
446 conn = call->conn;
449 * TODO: a SASL bind with a different mechanism
450 * should cancel an inprogress SASL bind.
451 * (see RFC 4513)
454 if (!conn->gensec) {
455 status = ldapsrv_setup_gensec(conn, req->creds.SASL.mechanism,
456 &conn->gensec);
457 if (!NT_STATUS_IS_OK(status)) {
458 DEBUG(1, ("Failed to start GENSEC server for [%s] code: %s\n",
459 ldb_binary_encode_string(call, req->creds.SASL.mechanism),
460 nt_errstr(status)));
461 result = LDAP_OPERATIONS_ERROR;
462 errstr = talloc_asprintf(reply, "SASL: Failed to start authentication system: %s",
463 nt_errstr(status));
464 goto do_reply;
468 if (req->creds.SASL.secblob) {
469 input = *req->creds.SASL.secblob;
472 subreq = gensec_update_send(call, conn->connection->event.ctx,
473 conn->gensec, input);
474 if (subreq == NULL) {
475 return NT_STATUS_NO_MEMORY;
477 tevent_req_set_callback(subreq, ldapsrv_BindSASL_done, call);
479 status = ldapsrv_bind_wait_setup(call, reply);
480 if (!NT_STATUS_IS_OK(status)) {
481 TALLOC_FREE(subreq);
482 return status;
486 * The rest will be async.
488 return NT_STATUS_OK;
490 do_reply:
491 if (result != LDAP_SASL_BIND_IN_PROGRESS) {
493 * We should destroy the gensec context
494 * when we hit a fatal error.
496 * Note: conn->gensec is already cleared
497 * for the LDAP_SUCCESS case.
499 talloc_unlink(conn, conn->gensec);
500 conn->gensec = NULL;
503 resp->response.resultcode = result;
504 resp->response.dn = NULL;
505 resp->response.errormessage = errstr;
506 resp->response.referral = NULL;
508 ldapsrv_queue_reply(call, reply);
509 return NT_STATUS_OK;
512 static void ldapsrv_BindSASL_done(struct tevent_req *subreq)
514 struct ldapsrv_call *call =
515 tevent_req_callback_data(subreq,
516 struct ldapsrv_call);
517 struct ldapsrv_bind_wait_context *bind_wait =
518 talloc_get_type_abort(call->wait_private,
519 struct ldapsrv_bind_wait_context);
520 struct ldap_BindRequest *req = &call->request->r.BindRequest;
521 struct ldapsrv_reply *reply = bind_wait->reply;
522 struct ldap_BindResponse *resp = &reply->msg->r.BindResponse;
523 struct ldapsrv_connection *conn = call->conn;
524 struct auth_session_info *session_info = NULL;
525 struct ldapsrv_sasl_postprocess_context *context = NULL;
526 NTSTATUS status;
527 int result;
528 const char *errstr = NULL;
529 char *ldb_errstring = NULL;
530 DATA_BLOB output = data_blob_null;
531 NTTIME expire_time_nt;
533 status = gensec_update_recv(subreq, call, &output);
534 TALLOC_FREE(subreq);
536 if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
537 *resp->SASL.secblob = output;
538 result = LDAP_SASL_BIND_IN_PROGRESS;
539 errstr = NULL;
540 goto do_reply;
543 if (NT_STATUS_EQUAL(status, NT_STATUS_BAD_BINDINGS)) {
544 result = LDAP_INVALID_CREDENTIALS;
545 errstr = ldapsrv_bind_error_msg(reply,
546 HRES_SEC_E_BAD_BINDINGS,
547 0x0C090711,
548 status);
549 goto do_reply;
551 if (!NT_STATUS_IS_OK(status)) {
552 status = nt_status_squash(status);
553 result = LDAP_INVALID_CREDENTIALS;
554 errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_LOGON_DENIED,
555 0x0C0904DC, status);
556 goto do_reply;
559 if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
560 gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
562 context = talloc_zero(call, struct ldapsrv_sasl_postprocess_context);
563 if (context == NULL) {
564 ldapsrv_bind_wait_finished(call, NT_STATUS_NO_MEMORY);
565 return;
569 if (context && conn->sockets.tls) {
570 TALLOC_FREE(context);
571 status = NT_STATUS_NOT_SUPPORTED;
572 result = LDAP_UNWILLING_TO_PERFORM;
573 errstr = talloc_asprintf(reply,
574 "SASL:[%s]: Sign or Seal are not allowed if TLS is used",
575 req->creds.SASL.mechanism);
576 goto do_reply;
579 if (context && conn->sockets.sasl) {
580 TALLOC_FREE(context);
581 status = NT_STATUS_NOT_SUPPORTED;
582 result = LDAP_UNWILLING_TO_PERFORM;
583 errstr = talloc_asprintf(reply,
584 "SASL:[%s]: Sign or Seal are not allowed if SASL encryption has already been set up",
585 req->creds.SASL.mechanism);
586 goto do_reply;
589 if (context == NULL) {
590 switch (call->conn->require_strong_auth) {
591 case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO:
592 break;
593 case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS:
594 case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_WITHOUT_TLS_CB:
595 case LDAP_SERVER_REQUIRE_STRONG_AUTH_YES:
596 if (call->conn->sockets.active == call->conn->sockets.tls) {
597 break;
599 status = NT_STATUS_NETWORK_ACCESS_DENIED;
600 result = LDAP_STRONG_AUTH_REQUIRED;
601 errstr = talloc_asprintf(reply,
602 "SASL:[%s]: Sign or Seal are required.",
603 req->creds.SASL.mechanism);
604 goto do_reply;
608 if (context != NULL) {
609 context->conn = conn;
610 status = gensec_create_tstream(context,
611 context->conn->gensec,
612 context->conn->sockets.raw,
613 &context->sasl);
614 if (!NT_STATUS_IS_OK(status)) {
615 result = LDAP_OPERATIONS_ERROR;
616 errstr = talloc_asprintf(reply,
617 "SASL:[%s]: Failed to setup SASL socket: %s",
618 req->creds.SASL.mechanism, nt_errstr(status));
619 goto do_reply;
623 status = gensec_session_info(conn->gensec, call, &session_info);
624 if (!NT_STATUS_IS_OK(status)) {
625 result = LDAP_OPERATIONS_ERROR;
626 errstr = talloc_asprintf(reply,
627 "SASL:[%s]: Failed to get session info: %s",
628 req->creds.SASL.mechanism, nt_errstr(status));
629 goto do_reply;
632 talloc_unlink(conn, conn->session_info);
633 conn->session_info = talloc_steal(conn, session_info);
635 /* don't leak the old LDB */
636 talloc_unlink(conn, conn->ldb);
638 call->conn->authz_logged = true;
640 result = ldapsrv_backend_Init(call->conn, &ldb_errstring);
642 if (result != LDB_SUCCESS) {
643 /* Only put the detailed error in DEBUG() */
644 DBG_ERR("ldapsrv_backend_Init failed: %s: %s\n",
645 ldb_errstring, ldb_strerror(result));
646 errstr = talloc_strdup(reply,
647 "SASL Bind: Failed to advise "
648 "ldb new credentials");
649 result = LDB_ERR_OPERATIONS_ERROR;
650 goto do_reply;
653 expire_time_nt = gensec_expire_time(conn->gensec);
654 if (expire_time_nt != GENSEC_EXPIRE_TIME_INFINITY) {
655 struct timeval_buf buf;
657 nttime_to_timeval(&conn->limits.expire_time, expire_time_nt);
659 DBG_DEBUG("Setting connection expire_time to %s\n",
660 timeval_str_buf(&conn->limits.expire_time,
661 false,
662 true,
663 &buf));
666 if (context != NULL) {
667 const void *ptr = NULL;
669 ptr = talloc_reparent(conn, context->sasl, conn->gensec);
670 if (ptr == NULL) {
671 ldapsrv_bind_wait_finished(call, NT_STATUS_NO_MEMORY);
672 return;
675 call->postprocess_send = ldapsrv_sasl_postprocess_send;
676 call->postprocess_recv = ldapsrv_sasl_postprocess_recv;
677 call->postprocess_private = context;
678 } else {
679 talloc_unlink(conn, conn->gensec);
681 conn->gensec = NULL;
683 *resp->SASL.secblob = output;
684 result = LDAP_SUCCESS;
685 errstr = NULL;
687 do_reply:
688 if (result != LDAP_SASL_BIND_IN_PROGRESS) {
690 * We should destroy the gensec context
691 * when we hit a fatal error.
693 * Note: conn->gensec is already cleared
694 * for the LDAP_SUCCESS case.
696 talloc_unlink(conn, conn->gensec);
697 conn->gensec = NULL;
700 resp->response.resultcode = result;
701 resp->response.dn = NULL;
702 resp->response.errormessage = errstr;
703 resp->response.referral = NULL;
705 ldapsrv_queue_reply(call, reply);
706 ldapsrv_bind_wait_finished(call, NT_STATUS_OK);
709 NTSTATUS ldapsrv_BindRequest(struct ldapsrv_call *call)
711 struct ldap_BindRequest *req = &call->request->r.BindRequest;
712 struct ldapsrv_reply *reply;
713 struct ldap_BindResponse *resp;
715 if (call->conn->pending_calls != NULL) {
716 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
717 if (!reply) {
718 return NT_STATUS_NO_MEMORY;
721 resp = &reply->msg->r.BindResponse;
722 resp->response.resultcode = LDAP_BUSY;
723 resp->response.dn = NULL;
724 resp->response.errormessage = talloc_asprintf(reply, "Pending requests on this LDAP session");
725 resp->response.referral = NULL;
726 resp->SASL.secblob = NULL;
728 ldapsrv_queue_reply(call, reply);
729 return NT_STATUS_OK;
733 * TODO: a simple bind should cancel an
734 * inprogress SASL bind.
735 * (see RFC 4513)
737 switch (req->mechanism) {
738 case LDAP_AUTH_MECH_SIMPLE:
739 return ldapsrv_BindSimple(call);
740 case LDAP_AUTH_MECH_SASL:
741 return ldapsrv_BindSASL(call);
744 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
745 if (!reply) {
746 return NT_STATUS_NO_MEMORY;
749 resp = &reply->msg->r.BindResponse;
750 resp->response.resultcode = LDAP_AUTH_METHOD_NOT_SUPPORTED;
751 resp->response.dn = NULL;
752 resp->response.errormessage = talloc_asprintf(reply, "Bad AuthenticationChoice [%d]", req->mechanism);
753 resp->response.referral = NULL;
754 resp->SASL.secblob = NULL;
756 ldapsrv_queue_reply(call, reply);
757 return NT_STATUS_OK;
760 struct ldapsrv_unbind_wait_context {
761 uint8_t dummy;
764 struct ldapsrv_unbind_wait_state {
765 uint8_t dummy;
768 static struct tevent_req *ldapsrv_unbind_wait_send(TALLOC_CTX *mem_ctx,
769 struct tevent_context *ev,
770 void *private_data)
772 struct ldapsrv_unbind_wait_context *unbind_wait =
773 talloc_get_type_abort(private_data,
774 struct ldapsrv_unbind_wait_context);
775 struct tevent_req *req;
776 struct ldapsrv_unbind_wait_state *state;
778 req = tevent_req_create(mem_ctx, &state,
779 struct ldapsrv_unbind_wait_state);
780 if (req == NULL) {
781 return NULL;
784 (void)unbind_wait;
786 tevent_req_nterror(req, NT_STATUS_LOCAL_DISCONNECT);
787 return tevent_req_post(req, ev);
790 static NTSTATUS ldapsrv_unbind_wait_recv(struct tevent_req *req)
792 return tevent_req_simple_recv_ntstatus(req);
795 static NTSTATUS ldapsrv_unbind_wait_setup(struct ldapsrv_call *call)
797 struct ldapsrv_unbind_wait_context *unbind_wait = NULL;
799 if (call->wait_private != NULL) {
800 return NT_STATUS_INTERNAL_ERROR;
803 unbind_wait = talloc_zero(call, struct ldapsrv_unbind_wait_context);
804 if (unbind_wait == NULL) {
805 return NT_STATUS_NO_MEMORY;
808 call->wait_private = unbind_wait;
809 call->wait_send = ldapsrv_unbind_wait_send;
810 call->wait_recv = ldapsrv_unbind_wait_recv;
811 return NT_STATUS_OK;
814 NTSTATUS ldapsrv_UnbindRequest(struct ldapsrv_call *call)
816 struct ldapsrv_call *c = NULL;
817 struct ldapsrv_call *n = NULL;
819 DEBUG(10, ("UnbindRequest\n"));
821 for (c = call->conn->pending_calls; c != NULL; c = n) {
822 n = c->next;
824 DLIST_REMOVE(call->conn->pending_calls, c);
825 TALLOC_FREE(c);
828 return ldapsrv_unbind_wait_setup(call);