ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / ldap_server / ldap_bind.c
blobf9c7dce312f7658701a1e8c45d6a69530844686a
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 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_LDAPSRV
38 static char *ldapsrv_bind_error_msg(TALLOC_CTX *mem_ctx,
39 HRESULT hresult,
40 uint32_t DSID,
41 NTSTATUS status)
43 WERROR werr;
44 char *msg = NULL;
46 status = nt_status_squash(status);
47 werr = ntstatus_to_werror(status);
50 * There are 4 lower case hex digits following 'v' at the end,
51 * but different Windows Versions return different values:
53 * Windows 2008R2 uses 'v1db1'
54 * Windows 2012R2 uses 'v2580'
56 * We just match Windows 2008R2 as that's what was referenced
57 * in https://bugzilla.samba.org/show_bug.cgi?id=9048
59 msg = talloc_asprintf(mem_ctx, "%08X: LdapErr: DSID-%08X, comment: "
60 "AcceptSecurityContext error, data %x, v1db1",
61 (unsigned)HRES_ERROR_V(hresult),
62 (unsigned)DSID,
63 (unsigned)W_ERROR_V(werr));
65 return msg;
68 struct ldapsrv_bind_wait_context {
69 struct ldapsrv_reply *reply;
70 struct tevent_req *req;
71 NTSTATUS status;
72 bool done;
75 struct ldapsrv_bind_wait_state {
76 uint8_t dummy;
79 static struct tevent_req *ldapsrv_bind_wait_send(TALLOC_CTX *mem_ctx,
80 struct tevent_context *ev,
81 void *private_data)
83 struct ldapsrv_bind_wait_context *bind_wait =
84 talloc_get_type_abort(private_data,
85 struct ldapsrv_bind_wait_context);
86 struct tevent_req *req;
87 struct ldapsrv_bind_wait_state *state;
89 req = tevent_req_create(mem_ctx, &state,
90 struct ldapsrv_bind_wait_state);
91 if (req == NULL) {
92 return NULL;
94 bind_wait->req = req;
96 tevent_req_defer_callback(req, ev);
98 if (!bind_wait->done) {
99 return req;
102 if (tevent_req_nterror(req, bind_wait->status)) {
103 return tevent_req_post(req, ev);
106 tevent_req_done(req);
107 return tevent_req_post(req, ev);
110 static NTSTATUS ldapsrv_bind_wait_recv(struct tevent_req *req)
112 return tevent_req_simple_recv_ntstatus(req);
115 static NTSTATUS ldapsrv_bind_wait_setup(struct ldapsrv_call *call,
116 struct ldapsrv_reply *reply)
118 struct ldapsrv_bind_wait_context *bind_wait = NULL;
120 if (call->wait_private != NULL) {
121 return NT_STATUS_INTERNAL_ERROR;
124 bind_wait = talloc_zero(call, struct ldapsrv_bind_wait_context);
125 if (bind_wait == NULL) {
126 return NT_STATUS_NO_MEMORY;
128 bind_wait->reply = reply;
130 call->wait_private = bind_wait;
131 call->wait_send = ldapsrv_bind_wait_send;
132 call->wait_recv = ldapsrv_bind_wait_recv;
133 return NT_STATUS_OK;
136 static void ldapsrv_bind_wait_finished(struct ldapsrv_call *call,
137 NTSTATUS status)
139 struct ldapsrv_bind_wait_context *bind_wait =
140 talloc_get_type_abort(call->wait_private,
141 struct ldapsrv_bind_wait_context);
143 bind_wait->done = true;
144 bind_wait->status = status;
146 if (bind_wait->req == NULL) {
147 return;
150 if (tevent_req_nterror(bind_wait->req, status)) {
151 return;
154 tevent_req_done(bind_wait->req);
157 static void ldapsrv_BindSimple_done(struct tevent_req *subreq);
159 static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
161 struct ldap_BindRequest *req = &call->request->r.BindRequest;
162 struct ldapsrv_reply *reply = NULL;
163 struct ldap_BindResponse *resp = NULL;
164 int result;
165 const char *errstr = NULL;
166 NTSTATUS status;
167 bool using_tls = call->conn->sockets.active == call->conn->sockets.tls;
168 struct tevent_req *subreq = NULL;
170 DEBUG(10, ("BindSimple dn: %s\n",req->dn));
172 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
173 if (!reply) {
174 return NT_STATUS_NO_MEMORY;
177 if (req->dn != NULL &&
178 strlen(req->dn) != 0 &&
179 call->conn->require_strong_auth > LDAP_SERVER_REQUIRE_STRONG_AUTH_NO &&
180 !using_tls)
182 status = NT_STATUS_NETWORK_ACCESS_DENIED;
183 result = LDAP_STRONG_AUTH_REQUIRED;
184 errstr = talloc_asprintf(reply,
185 "BindSimple: Transport encryption required.");
186 goto do_reply;
189 subreq = authenticate_ldap_simple_bind_send(call,
190 call->conn->connection->event.ctx,
191 call->conn->connection->msg_ctx,
192 call->conn->lp_ctx,
193 call->conn->connection->remote_address,
194 call->conn->connection->local_address,
195 using_tls,
196 req->dn,
197 req->creds.password);
198 if (subreq == NULL) {
199 return NT_STATUS_NO_MEMORY;
201 tevent_req_set_callback(subreq, ldapsrv_BindSimple_done, call);
203 status = ldapsrv_bind_wait_setup(call, reply);
204 if (!NT_STATUS_IS_OK(status)) {
205 TALLOC_FREE(subreq);
206 return status;
210 * The rest will be async.
212 return NT_STATUS_OK;
214 do_reply:
215 resp = &reply->msg->r.BindResponse;
216 resp->response.resultcode = result;
217 resp->response.errormessage = errstr;
218 resp->response.dn = NULL;
219 resp->response.referral = NULL;
220 resp->SASL.secblob = NULL;
222 ldapsrv_queue_reply(call, reply);
223 return NT_STATUS_OK;
226 static void ldapsrv_BindSimple_done(struct tevent_req *subreq)
228 struct ldapsrv_call *call =
229 tevent_req_callback_data(subreq,
230 struct ldapsrv_call);
231 struct ldapsrv_bind_wait_context *bind_wait =
232 talloc_get_type_abort(call->wait_private,
233 struct ldapsrv_bind_wait_context);
234 struct ldapsrv_reply *reply = bind_wait->reply;
235 struct auth_session_info *session_info = NULL;
236 NTSTATUS status;
237 struct ldap_BindResponse *resp = NULL;
238 int result;
239 const char *errstr = NULL;
241 status = authenticate_ldap_simple_bind_recv(subreq,
242 call,
243 &session_info);
244 if (NT_STATUS_IS_OK(status)) {
245 char *ldb_errstring = NULL;
246 result = LDAP_SUCCESS;
247 errstr = NULL;
249 talloc_unlink(call->conn, call->conn->session_info);
250 call->conn->session_info = talloc_steal(call->conn, session_info);
252 call->conn->authz_logged = true;
254 /* don't leak the old LDB */
255 talloc_unlink(call->conn, call->conn->ldb);
257 result = ldapsrv_backend_Init(call->conn, &ldb_errstring);
259 if (result != LDB_SUCCESS) {
260 /* Only put the detailed error in DEBUG() */
261 DBG_ERR("ldapsrv_backend_Init failed: %s: %s\n",
262 ldb_errstring, ldb_strerror(result));
263 errstr = talloc_strdup(reply,
264 "Simple Bind: Failed to advise "
265 "ldb new credentials");
266 result = LDB_ERR_OPERATIONS_ERROR;
268 } else {
269 status = nt_status_squash(status);
271 result = LDAP_INVALID_CREDENTIALS;
272 errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_INVALID_TOKEN,
273 0x0C0903A9, status);
276 resp = &reply->msg->r.BindResponse;
277 resp->response.resultcode = result;
278 resp->response.errormessage = errstr;
279 resp->response.dn = NULL;
280 resp->response.referral = NULL;
281 resp->SASL.secblob = NULL;
283 ldapsrv_queue_reply(call, reply);
284 ldapsrv_bind_wait_finished(call, NT_STATUS_OK);
287 struct ldapsrv_sasl_postprocess_context {
288 struct ldapsrv_connection *conn;
289 struct tstream_context *sasl;
292 struct ldapsrv_sasl_postprocess_state {
293 uint8_t dummy;
296 static struct tevent_req *ldapsrv_sasl_postprocess_send(TALLOC_CTX *mem_ctx,
297 struct tevent_context *ev,
298 void *private_data)
300 struct ldapsrv_sasl_postprocess_context *context =
301 talloc_get_type_abort(private_data,
302 struct ldapsrv_sasl_postprocess_context);
303 struct tevent_req *req;
304 struct ldapsrv_sasl_postprocess_state *state;
306 req = tevent_req_create(mem_ctx, &state,
307 struct ldapsrv_sasl_postprocess_state);
308 if (req == NULL) {
309 return NULL;
312 TALLOC_FREE(context->conn->sockets.sasl);
313 context->conn->sockets.sasl = talloc_move(context->conn, &context->sasl);
314 context->conn->sockets.active = context->conn->sockets.sasl;
316 tevent_req_done(req);
317 return tevent_req_post(req, ev);
320 static NTSTATUS ldapsrv_sasl_postprocess_recv(struct tevent_req *req)
322 return tevent_req_simple_recv_ntstatus(req);
325 static NTSTATUS ldapsrv_setup_gensec(struct ldapsrv_connection *conn,
326 const char *sasl_mech,
327 struct gensec_security **_gensec_security)
329 NTSTATUS status;
331 struct gensec_security *gensec_security;
333 status = samba_server_gensec_start(conn,
334 conn->connection->event.ctx,
335 conn->connection->msg_ctx,
336 conn->lp_ctx,
337 conn->server_credentials,
338 "ldap",
339 &gensec_security);
340 if (!NT_STATUS_IS_OK(status)) {
341 return status;
344 status = gensec_set_target_service_description(gensec_security,
345 "LDAP");
346 if (!NT_STATUS_IS_OK(status)) {
347 return status;
350 status = gensec_set_remote_address(gensec_security,
351 conn->connection->remote_address);
352 if (!NT_STATUS_IS_OK(status)) {
353 return status;
356 status = gensec_set_local_address(gensec_security,
357 conn->connection->local_address);
358 if (!NT_STATUS_IS_OK(status)) {
359 return status;
362 gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
363 gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAP_STYLE);
365 if (conn->sockets.active == conn->sockets.tls) {
366 uint32_t initiator_addrtype = 0;
367 const DATA_BLOB *initiator_address = NULL;
368 uint32_t acceptor_addrtype = 0;
369 const DATA_BLOB *acceptor_address = NULL;
370 const DATA_BLOB *application_data =
371 tstream_tls_channel_bindings(conn->sockets.tls);
373 status = gensec_set_channel_bindings(gensec_security,
374 initiator_addrtype,
375 initiator_address,
376 acceptor_addrtype,
377 acceptor_address,
378 application_data);
379 if (!NT_STATUS_IS_OK(status)) {
380 return status;
384 * By default channel bindings are required,
385 * so we only set GENSEC_FEATURE_CB_OPTIONAL
386 * for the legacy option:
388 * ldap server require strong auth = no
389 * or
390 * ldap server require strong auth =
391 * allow_sasl_without_tls_channel_bindings
393 * And this as an alias to cope with existing smb.conf
394 * files:
396 * ldap server require strong auth = allow_sasl_over_tls
398 switch (conn->require_strong_auth) {
399 case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO:
400 case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS:
401 case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_WITHOUT_TLS_CB:
402 gensec_want_feature(gensec_security,
403 GENSEC_FEATURE_CB_OPTIONAL);
404 break;
405 default:
406 break;
409 gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAPS_TRANSPORT);
412 status = gensec_start_mech_by_sasl_name(gensec_security, sasl_mech);
414 if (!NT_STATUS_IS_OK(status)) {
415 return status;
418 *_gensec_security = gensec_security;
419 return status;
422 static void ldapsrv_BindSASL_done(struct tevent_req *subreq);
424 static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
426 struct ldap_BindRequest *req = &call->request->r.BindRequest;
427 struct ldapsrv_reply *reply;
428 struct ldap_BindResponse *resp;
429 struct ldapsrv_connection *conn;
430 int result = 0;
431 const char *errstr=NULL;
432 NTSTATUS status = NT_STATUS_OK;
433 DATA_BLOB input = data_blob_null;
434 struct tevent_req *subreq = NULL;
436 DEBUG(10, ("BindSASL dn: %s\n",req->dn));
438 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
439 if (!reply) {
440 return NT_STATUS_NO_MEMORY;
442 resp = &reply->msg->r.BindResponse;
443 /* Windows 2000 mmc doesn't like secblob == NULL and reports a decoding error */
444 resp->SASL.secblob = talloc_zero(reply, DATA_BLOB);
445 if (resp->SASL.secblob == NULL) {
446 return NT_STATUS_NO_MEMORY;
449 conn = call->conn;
452 * TODO: a SASL bind with a different mechanism
453 * should cancel an inprogress SASL bind.
454 * (see RFC 4513)
457 if (!conn->gensec) {
458 status = ldapsrv_setup_gensec(conn, req->creds.SASL.mechanism,
459 &conn->gensec);
460 if (!NT_STATUS_IS_OK(status)) {
461 DEBUG(1, ("Failed to start GENSEC server for [%s] code: %s\n",
462 ldb_binary_encode_string(call, req->creds.SASL.mechanism),
463 nt_errstr(status)));
464 result = LDAP_OPERATIONS_ERROR;
465 errstr = talloc_asprintf(reply, "SASL: Failed to start authentication system: %s",
466 nt_errstr(status));
467 goto do_reply;
471 if (req->creds.SASL.secblob) {
472 input = *req->creds.SASL.secblob;
475 subreq = gensec_update_send(call, conn->connection->event.ctx,
476 conn->gensec, input);
477 if (subreq == NULL) {
478 return NT_STATUS_NO_MEMORY;
480 tevent_req_set_callback(subreq, ldapsrv_BindSASL_done, call);
482 status = ldapsrv_bind_wait_setup(call, reply);
483 if (!NT_STATUS_IS_OK(status)) {
484 TALLOC_FREE(subreq);
485 return status;
489 * The rest will be async.
491 return NT_STATUS_OK;
493 do_reply:
494 if (result != LDAP_SASL_BIND_IN_PROGRESS) {
496 * We should destroy the gensec context
497 * when we hit a fatal error.
499 * Note: conn->gensec is already cleared
500 * for the LDAP_SUCCESS case.
502 talloc_unlink(conn, conn->gensec);
503 conn->gensec = NULL;
506 resp->response.resultcode = result;
507 resp->response.dn = NULL;
508 resp->response.errormessage = errstr;
509 resp->response.referral = NULL;
511 ldapsrv_queue_reply(call, reply);
512 return NT_STATUS_OK;
515 static void ldapsrv_BindSASL_done(struct tevent_req *subreq)
517 struct ldapsrv_call *call =
518 tevent_req_callback_data(subreq,
519 struct ldapsrv_call);
520 struct ldapsrv_bind_wait_context *bind_wait =
521 talloc_get_type_abort(call->wait_private,
522 struct ldapsrv_bind_wait_context);
523 struct ldap_BindRequest *req = &call->request->r.BindRequest;
524 struct ldapsrv_reply *reply = bind_wait->reply;
525 struct ldap_BindResponse *resp = &reply->msg->r.BindResponse;
526 struct ldapsrv_connection *conn = call->conn;
527 struct auth_session_info *session_info = NULL;
528 struct ldapsrv_sasl_postprocess_context *context = NULL;
529 NTSTATUS status;
530 int result;
531 const char *errstr = NULL;
532 char *ldb_errstring = NULL;
533 DATA_BLOB output = data_blob_null;
534 NTTIME expire_time_nt;
536 status = gensec_update_recv(subreq, call, &output);
537 TALLOC_FREE(subreq);
539 if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
540 *resp->SASL.secblob = output;
541 result = LDAP_SASL_BIND_IN_PROGRESS;
542 errstr = NULL;
543 goto do_reply;
546 if (NT_STATUS_EQUAL(status, NT_STATUS_BAD_BINDINGS)) {
547 result = LDAP_INVALID_CREDENTIALS;
548 errstr = ldapsrv_bind_error_msg(reply,
549 HRES_SEC_E_BAD_BINDINGS,
550 0x0C090711,
551 status);
552 goto do_reply;
554 if (!NT_STATUS_IS_OK(status)) {
555 status = nt_status_squash(status);
556 result = LDAP_INVALID_CREDENTIALS;
557 errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_LOGON_DENIED,
558 0x0C0904DC, status);
559 goto do_reply;
562 if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
563 gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
565 context = talloc_zero(call, struct ldapsrv_sasl_postprocess_context);
566 if (context == NULL) {
567 ldapsrv_bind_wait_finished(call, NT_STATUS_NO_MEMORY);
568 return;
572 if (context && conn->sockets.tls) {
573 TALLOC_FREE(context);
574 status = NT_STATUS_NOT_SUPPORTED;
575 result = LDAP_UNWILLING_TO_PERFORM;
576 errstr = talloc_asprintf(reply,
577 "SASL:[%s]: Sign or Seal are not allowed if TLS is used",
578 req->creds.SASL.mechanism);
579 goto do_reply;
582 if (context && conn->sockets.sasl) {
583 TALLOC_FREE(context);
584 status = NT_STATUS_NOT_SUPPORTED;
585 result = LDAP_UNWILLING_TO_PERFORM;
586 errstr = talloc_asprintf(reply,
587 "SASL:[%s]: Sign or Seal are not allowed if SASL encryption has already been set up",
588 req->creds.SASL.mechanism);
589 goto do_reply;
592 if (context == NULL) {
593 switch (call->conn->require_strong_auth) {
594 case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO:
595 break;
596 case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS:
597 case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_WITHOUT_TLS_CB:
598 case LDAP_SERVER_REQUIRE_STRONG_AUTH_YES:
599 if (call->conn->sockets.active == call->conn->sockets.tls) {
600 break;
602 status = NT_STATUS_NETWORK_ACCESS_DENIED;
603 result = LDAP_STRONG_AUTH_REQUIRED;
604 errstr = talloc_asprintf(reply,
605 "SASL:[%s]: Sign or Seal are required.",
606 req->creds.SASL.mechanism);
607 goto do_reply;
611 if (context != NULL) {
612 context->conn = conn;
613 status = gensec_create_tstream(context,
614 context->conn->gensec,
615 context->conn->sockets.raw,
616 &context->sasl);
617 if (!NT_STATUS_IS_OK(status)) {
618 result = LDAP_OPERATIONS_ERROR;
619 errstr = talloc_asprintf(reply,
620 "SASL:[%s]: Failed to setup SASL socket: %s",
621 req->creds.SASL.mechanism, nt_errstr(status));
622 goto do_reply;
626 status = gensec_session_info(conn->gensec, call, &session_info);
627 if (!NT_STATUS_IS_OK(status)) {
628 result = LDAP_OPERATIONS_ERROR;
629 errstr = talloc_asprintf(reply,
630 "SASL:[%s]: Failed to get session info: %s",
631 req->creds.SASL.mechanism, nt_errstr(status));
632 goto do_reply;
635 talloc_unlink(conn, conn->session_info);
636 conn->session_info = talloc_steal(conn, session_info);
638 /* don't leak the old LDB */
639 talloc_unlink(conn, conn->ldb);
641 call->conn->authz_logged = true;
643 result = ldapsrv_backend_Init(call->conn, &ldb_errstring);
645 if (result != LDB_SUCCESS) {
646 /* Only put the detailed error in DEBUG() */
647 DBG_ERR("ldapsrv_backend_Init failed: %s: %s\n",
648 ldb_errstring, ldb_strerror(result));
649 errstr = talloc_strdup(reply,
650 "SASL Bind: Failed to advise "
651 "ldb new credentials");
652 result = LDB_ERR_OPERATIONS_ERROR;
653 goto do_reply;
656 expire_time_nt = gensec_expire_time(conn->gensec);
657 if (expire_time_nt != GENSEC_EXPIRE_TIME_INFINITY) {
658 struct timeval_buf buf;
660 nttime_to_timeval(&conn->limits.expire_time, expire_time_nt);
662 DBG_DEBUG("Setting connection expire_time to %s\n",
663 timeval_str_buf(&conn->limits.expire_time,
664 false,
665 true,
666 &buf));
669 if (context != NULL) {
670 const void *ptr = NULL;
672 ptr = talloc_reparent(conn, context->sasl, conn->gensec);
673 if (ptr == NULL) {
674 ldapsrv_bind_wait_finished(call, NT_STATUS_NO_MEMORY);
675 return;
678 call->postprocess_send = ldapsrv_sasl_postprocess_send;
679 call->postprocess_recv = ldapsrv_sasl_postprocess_recv;
680 call->postprocess_private = context;
681 } else {
682 talloc_unlink(conn, conn->gensec);
684 conn->gensec = NULL;
686 *resp->SASL.secblob = output;
687 result = LDAP_SUCCESS;
688 errstr = NULL;
690 do_reply:
691 if (result != LDAP_SASL_BIND_IN_PROGRESS) {
693 * We should destroy the gensec context
694 * when we hit a fatal error.
696 * Note: conn->gensec is already cleared
697 * for the LDAP_SUCCESS case.
699 talloc_unlink(conn, conn->gensec);
700 conn->gensec = NULL;
703 resp->response.resultcode = result;
704 resp->response.dn = NULL;
705 resp->response.errormessage = errstr;
706 resp->response.referral = NULL;
708 ldapsrv_queue_reply(call, reply);
709 ldapsrv_bind_wait_finished(call, NT_STATUS_OK);
712 NTSTATUS ldapsrv_BindRequest(struct ldapsrv_call *call)
714 struct ldap_BindRequest *req = &call->request->r.BindRequest;
715 struct ldapsrv_reply *reply;
716 struct ldap_BindResponse *resp;
718 if (call->conn->pending_calls != NULL) {
719 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
720 if (!reply) {
721 return NT_STATUS_NO_MEMORY;
724 resp = &reply->msg->r.BindResponse;
725 resp->response.resultcode = LDAP_BUSY;
726 resp->response.dn = NULL;
727 resp->response.errormessage = talloc_asprintf(reply, "Pending requests on this LDAP session");
728 resp->response.referral = NULL;
729 resp->SASL.secblob = NULL;
731 ldapsrv_queue_reply(call, reply);
732 return NT_STATUS_OK;
736 * TODO: a simple bind should cancel an
737 * inprogress SASL bind.
738 * (see RFC 4513)
740 switch (req->mechanism) {
741 case LDAP_AUTH_MECH_SIMPLE:
742 return ldapsrv_BindSimple(call);
743 case LDAP_AUTH_MECH_SASL:
744 return ldapsrv_BindSASL(call);
747 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
748 if (!reply) {
749 return NT_STATUS_NO_MEMORY;
752 resp = &reply->msg->r.BindResponse;
753 resp->response.resultcode = LDAP_AUTH_METHOD_NOT_SUPPORTED;
754 resp->response.dn = NULL;
755 resp->response.errormessage = talloc_asprintf(reply, "Bad AuthenticationChoice [%d]", req->mechanism);
756 resp->response.referral = NULL;
757 resp->SASL.secblob = NULL;
759 ldapsrv_queue_reply(call, reply);
760 return NT_STATUS_OK;
763 struct ldapsrv_unbind_wait_context {
764 uint8_t dummy;
767 struct ldapsrv_unbind_wait_state {
768 uint8_t dummy;
771 static struct tevent_req *ldapsrv_unbind_wait_send(TALLOC_CTX *mem_ctx,
772 struct tevent_context *ev,
773 void *private_data)
775 struct ldapsrv_unbind_wait_context *unbind_wait =
776 talloc_get_type_abort(private_data,
777 struct ldapsrv_unbind_wait_context);
778 struct tevent_req *req;
779 struct ldapsrv_unbind_wait_state *state;
781 req = tevent_req_create(mem_ctx, &state,
782 struct ldapsrv_unbind_wait_state);
783 if (req == NULL) {
784 return NULL;
787 (void)unbind_wait;
789 tevent_req_nterror(req, NT_STATUS_LOCAL_DISCONNECT);
790 return tevent_req_post(req, ev);
793 static NTSTATUS ldapsrv_unbind_wait_recv(struct tevent_req *req)
795 return tevent_req_simple_recv_ntstatus(req);
798 static NTSTATUS ldapsrv_unbind_wait_setup(struct ldapsrv_call *call)
800 struct ldapsrv_unbind_wait_context *unbind_wait = NULL;
802 if (call->wait_private != NULL) {
803 return NT_STATUS_INTERNAL_ERROR;
806 unbind_wait = talloc_zero(call, struct ldapsrv_unbind_wait_context);
807 if (unbind_wait == NULL) {
808 return NT_STATUS_NO_MEMORY;
811 call->wait_private = unbind_wait;
812 call->wait_send = ldapsrv_unbind_wait_send;
813 call->wait_recv = ldapsrv_unbind_wait_recv;
814 return NT_STATUS_OK;
817 NTSTATUS ldapsrv_UnbindRequest(struct ldapsrv_call *call)
819 struct ldapsrv_call *c = NULL;
820 struct ldapsrv_call *n = NULL;
822 DEBUG(10, ("UnbindRequest\n"));
824 for (c = call->conn->pending_calls; c != NULL; c = n) {
825 n = c->next;
827 DLIST_REMOVE(call->conn->pending_calls, c);
828 TALLOC_FREE(c);
831 return ldapsrv_unbind_wait_setup(call);