LCOV - code coverage report
Current view: top level - source4/ldap_server - ldap_bind.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 303 399 75.9 %
Date: 2024-04-13 12:30:31 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    LDAP server
       4             :    Copyright (C) Stefan Metzmacher 2004
       5             :    
       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.
      10             :    
      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.
      15             :    
      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/>.
      18             : */
      19             : 
      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 "param/param.h"
      31             : #include "../lib/util/tevent_ntstatus.h"
      32             : #include "lib/util/time_basic.h"
      33             : 
      34         335 : static char *ldapsrv_bind_error_msg(TALLOC_CTX *mem_ctx,
      35             :                                     HRESULT hresult,
      36             :                                     uint32_t DSID,
      37             :                                     NTSTATUS status)
      38             : {
      39           0 :         WERROR werr;
      40         335 :         char *msg = NULL;
      41             : 
      42         335 :         status = nt_status_squash(status);
      43         335 :         werr = ntstatus_to_werror(status);
      44             : 
      45             :         /*
      46             :          * There are 4 lower case hex digits following 'v' at the end,
      47             :          * but different Windows Versions return different values:
      48             :          *
      49             :          * Windows 2008R2 uses 'v1db1'
      50             :          * Windows 2012R2 uses 'v2580'
      51             :          *
      52             :          * We just match Windows 2008R2 as that's what was referenced
      53             :          * in https://bugzilla.samba.org/show_bug.cgi?id=9048
      54             :          */
      55         335 :         msg = talloc_asprintf(mem_ctx, "%08X: LdapErr: DSID-%08X, comment: "
      56             :                               "AcceptSecurityContext error, data %x, v1db1",
      57         335 :                               (unsigned)HRES_ERROR_V(hresult),
      58             :                               (unsigned)DSID,
      59         335 :                               (unsigned)W_ERROR_V(werr));
      60             : 
      61         335 :         return msg;
      62             : }
      63             : 
      64             : struct ldapsrv_bind_wait_context {
      65             :         struct ldapsrv_reply *reply;
      66             :         struct tevent_req *req;
      67             :         NTSTATUS status;
      68             :         bool done;
      69             : };
      70             : 
      71             : struct ldapsrv_bind_wait_state {
      72             :         uint8_t dummy;
      73             : };
      74             : 
      75       35995 : static struct tevent_req *ldapsrv_bind_wait_send(TALLOC_CTX *mem_ctx,
      76             :                                                  struct tevent_context *ev,
      77             :                                                  void *private_data)
      78             : {
      79         122 :         struct ldapsrv_bind_wait_context *bind_wait =
      80       35995 :                 talloc_get_type_abort(private_data,
      81             :                 struct ldapsrv_bind_wait_context);
      82         122 :         struct tevent_req *req;
      83         122 :         struct ldapsrv_bind_wait_state *state;
      84             : 
      85       35995 :         req = tevent_req_create(mem_ctx, &state,
      86             :                                 struct ldapsrv_bind_wait_state);
      87       35995 :         if (req == NULL) {
      88           0 :                 return NULL;
      89             :         }
      90       35995 :         bind_wait->req = req;
      91             : 
      92       35995 :         tevent_req_defer_callback(req, ev);
      93             : 
      94       35995 :         if (!bind_wait->done) {
      95       35873 :                 return req;
      96             :         }
      97             : 
      98           0 :         if (tevent_req_nterror(req, bind_wait->status)) {
      99           0 :                 return tevent_req_post(req, ev);
     100             :         }
     101             : 
     102           0 :         tevent_req_done(req);
     103           0 :         return tevent_req_post(req, ev);
     104             : }
     105             : 
     106       35995 : static NTSTATUS ldapsrv_bind_wait_recv(struct tevent_req *req)
     107             : {
     108       35995 :         return tevent_req_simple_recv_ntstatus(req);
     109             : }
     110             : 
     111       35995 : static NTSTATUS ldapsrv_bind_wait_setup(struct ldapsrv_call *call,
     112             :                                         struct ldapsrv_reply *reply)
     113             : {
     114       35995 :         struct ldapsrv_bind_wait_context *bind_wait = NULL;
     115             : 
     116       35995 :         if (call->wait_private != NULL) {
     117           0 :                 return NT_STATUS_INTERNAL_ERROR;
     118             :         }
     119             : 
     120       35995 :         bind_wait = talloc_zero(call, struct ldapsrv_bind_wait_context);
     121       35995 :         if (bind_wait == NULL) {
     122           0 :                 return NT_STATUS_NO_MEMORY;
     123             :         }
     124       35995 :         bind_wait->reply = reply;
     125             : 
     126       35995 :         call->wait_private = bind_wait;
     127       35995 :         call->wait_send = ldapsrv_bind_wait_send;
     128       35995 :         call->wait_recv = ldapsrv_bind_wait_recv;
     129       35995 :         return NT_STATUS_OK;
     130             : }
     131             : 
     132       35995 : static void ldapsrv_bind_wait_finished(struct ldapsrv_call *call,
     133             :                                        NTSTATUS status)
     134             : {
     135         122 :         struct ldapsrv_bind_wait_context *bind_wait =
     136       35995 :                 talloc_get_type_abort(call->wait_private,
     137             :                 struct ldapsrv_bind_wait_context);
     138             : 
     139       35995 :         bind_wait->done = true;
     140       35995 :         bind_wait->status = status;
     141             : 
     142       35995 :         if (bind_wait->req == NULL) {
     143           0 :                 return;
     144             :         }
     145             : 
     146       35995 :         if (tevent_req_nterror(bind_wait->req, status)) {
     147           0 :                 return;
     148             :         }
     149             : 
     150       35995 :         tevent_req_done(bind_wait->req);
     151             : }
     152             : 
     153             : static void ldapsrv_BindSimple_done(struct tevent_req *subreq);
     154             : 
     155         471 : static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
     156             : {
     157         471 :         struct ldap_BindRequest *req = &call->request->r.BindRequest;
     158         471 :         struct ldapsrv_reply *reply = NULL;
     159         471 :         struct ldap_BindResponse *resp = NULL;
     160           0 :         int result;
     161         471 :         const char *errstr = NULL;
     162           0 :         NTSTATUS status;
     163         471 :         bool using_tls = call->conn->sockets.active == call->conn->sockets.tls;
     164         471 :         struct tevent_req *subreq = NULL;
     165             : 
     166         471 :         DEBUG(10, ("BindSimple dn: %s\n",req->dn));
     167             : 
     168         471 :         reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
     169         471 :         if (!reply) {
     170           0 :                 return NT_STATUS_NO_MEMORY;
     171             :         }
     172             : 
     173         471 :         if (req->dn != NULL &&
     174         471 :             strlen(req->dn) != 0 &&
     175         453 :             call->conn->require_strong_auth > LDAP_SERVER_REQUIRE_STRONG_AUTH_NO &&
     176         385 :             !using_tls)
     177             :         {
     178           5 :                 status = NT_STATUS_NETWORK_ACCESS_DENIED;
     179           5 :                 result = LDAP_STRONG_AUTH_REQUIRED;
     180           5 :                 errstr = talloc_asprintf(reply,
     181             :                                          "BindSimple: Transport encryption required.");
     182           5 :                 goto do_reply;
     183             :         }
     184             : 
     185         466 :         subreq = authenticate_ldap_simple_bind_send(call,
     186         466 :                                         call->conn->connection->event.ctx,
     187         466 :                                         call->conn->connection->msg_ctx,
     188         466 :                                         call->conn->lp_ctx,
     189         466 :                                         call->conn->connection->remote_address,
     190         466 :                                         call->conn->connection->local_address,
     191             :                                         using_tls,
     192             :                                         req->dn,
     193             :                                         req->creds.password);
     194         466 :         if (subreq == NULL) {
     195           0 :                 return NT_STATUS_NO_MEMORY;
     196             :         }
     197         466 :         tevent_req_set_callback(subreq, ldapsrv_BindSimple_done, call);
     198             : 
     199         466 :         status = ldapsrv_bind_wait_setup(call, reply);
     200         466 :         if (!NT_STATUS_IS_OK(status)) {
     201           0 :                 TALLOC_FREE(subreq);
     202           0 :                 return status;
     203             :         }
     204             : 
     205             :         /*
     206             :          * The rest will be async.
     207             :          */
     208         466 :         return NT_STATUS_OK;
     209             : 
     210           5 : do_reply:
     211           5 :         resp = &reply->msg->r.BindResponse;
     212           5 :         resp->response.resultcode = result;
     213           5 :         resp->response.errormessage = errstr;
     214           5 :         resp->response.dn = NULL;
     215           5 :         resp->response.referral = NULL;
     216           5 :         resp->SASL.secblob = NULL;
     217             : 
     218           5 :         ldapsrv_queue_reply(call, reply);
     219           5 :         return NT_STATUS_OK;
     220             : }
     221             : 
     222         466 : static void ldapsrv_BindSimple_done(struct tevent_req *subreq)
     223             : {
     224           0 :         struct ldapsrv_call *call =
     225         466 :                 tevent_req_callback_data(subreq,
     226             :                 struct ldapsrv_call);
     227           0 :         struct ldapsrv_bind_wait_context *bind_wait =
     228         466 :                 talloc_get_type_abort(call->wait_private,
     229             :                 struct ldapsrv_bind_wait_context);
     230         466 :         struct ldapsrv_reply *reply = bind_wait->reply;
     231         466 :         struct auth_session_info *session_info = NULL;
     232           0 :         NTSTATUS status;
     233         466 :         struct ldap_BindResponse *resp = NULL;
     234           0 :         int result;
     235         466 :         const char *errstr = NULL;
     236             : 
     237         466 :         status = authenticate_ldap_simple_bind_recv(subreq,
     238             :                                                     call,
     239             :                                                     &session_info);
     240         466 :         if (NT_STATUS_IS_OK(status)) {
     241         344 :                 char *ldb_errstring = NULL;
     242         344 :                 result = LDAP_SUCCESS;
     243         344 :                 errstr = NULL;
     244             : 
     245         344 :                 talloc_unlink(call->conn, call->conn->session_info);
     246         344 :                 call->conn->session_info = talloc_steal(call->conn, session_info);
     247             : 
     248         344 :                 call->conn->authz_logged = true;
     249             : 
     250             :                 /* don't leak the old LDB */
     251         344 :                 talloc_unlink(call->conn, call->conn->ldb);
     252             : 
     253         344 :                 result = ldapsrv_backend_Init(call->conn, &ldb_errstring);
     254             : 
     255         344 :                 if (result != LDB_SUCCESS) {
     256             :                         /* Only put the detailed error in DEBUG() */
     257           0 :                         DBG_ERR("ldapsrv_backend_Init failed: %s: %s\n",
     258             :                                 ldb_errstring, ldb_strerror(result));
     259           0 :                         errstr = talloc_strdup(reply,
     260             :                                                "Simple Bind: Failed to advise "
     261             :                                                "ldb new credentials");
     262           0 :                         result = LDB_ERR_OPERATIONS_ERROR;
     263             :                 }
     264             :         } else {
     265         122 :                 status = nt_status_squash(status);
     266             : 
     267         122 :                 result = LDAP_INVALID_CREDENTIALS;
     268         122 :                 errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_INVALID_TOKEN,
     269             :                                                 0x0C0903A9, status);
     270             :         }
     271             : 
     272         466 :         resp = &reply->msg->r.BindResponse;
     273         466 :         resp->response.resultcode = result;
     274         466 :         resp->response.errormessage = errstr;
     275         466 :         resp->response.dn = NULL;
     276         466 :         resp->response.referral = NULL;
     277         466 :         resp->SASL.secblob = NULL;
     278             : 
     279         466 :         ldapsrv_queue_reply(call, reply);
     280         466 :         ldapsrv_bind_wait_finished(call, NT_STATUS_OK);
     281         466 : }
     282             : 
     283             : struct ldapsrv_sasl_postprocess_context {
     284             :         struct ldapsrv_connection *conn;
     285             :         struct tstream_context *sasl;
     286             : };
     287             : 
     288             : struct ldapsrv_sasl_postprocess_state {
     289             :         uint8_t dummy;
     290             : };
     291             : 
     292       25707 : static struct tevent_req *ldapsrv_sasl_postprocess_send(TALLOC_CTX *mem_ctx,
     293             :                                                 struct tevent_context *ev,
     294             :                                                 void *private_data)
     295             : {
     296         122 :         struct ldapsrv_sasl_postprocess_context *context =
     297       25707 :                 talloc_get_type_abort(private_data,
     298             :                 struct ldapsrv_sasl_postprocess_context);
     299         122 :         struct tevent_req *req;
     300         122 :         struct ldapsrv_sasl_postprocess_state *state;
     301             : 
     302       25707 :         req = tevent_req_create(mem_ctx, &state,
     303             :                                 struct ldapsrv_sasl_postprocess_state);
     304       25707 :         if (req == NULL) {
     305           0 :                 return NULL;
     306             :         }
     307             : 
     308       25707 :         TALLOC_FREE(context->conn->sockets.sasl);
     309       25707 :         context->conn->sockets.sasl = talloc_move(context->conn, &context->sasl);
     310       25707 :         context->conn->sockets.active = context->conn->sockets.sasl;
     311             : 
     312       25707 :         tevent_req_done(req);
     313       25707 :         return tevent_req_post(req, ev);
     314             : }
     315             : 
     316       25707 : static NTSTATUS ldapsrv_sasl_postprocess_recv(struct tevent_req *req)
     317             : {
     318       25707 :         return tevent_req_simple_recv_ntstatus(req);
     319             : }
     320             : 
     321       26201 : static NTSTATUS ldapsrv_setup_gensec(struct ldapsrv_connection *conn,
     322             :                                      const char *sasl_mech,
     323             :                                      struct gensec_security **_gensec_security)
     324             : {
     325         122 :         NTSTATUS status;
     326             : 
     327         122 :         struct gensec_security *gensec_security;
     328             : 
     329       26323 :         status = samba_server_gensec_start(conn,
     330       26079 :                                            conn->connection->event.ctx,
     331       26201 :                                            conn->connection->msg_ctx,
     332             :                                            conn->lp_ctx,
     333             :                                            conn->server_credentials,
     334             :                                            "ldap",
     335             :                                            &gensec_security);
     336       26201 :         if (!NT_STATUS_IS_OK(status)) {
     337           0 :                 return status;
     338             :         }
     339             : 
     340       26201 :         status = gensec_set_target_service_description(gensec_security,
     341             :                                                        "LDAP");
     342       26201 :         if (!NT_STATUS_IS_OK(status)) {
     343           0 :                 return status;
     344             :         }
     345             : 
     346       26323 :         status = gensec_set_remote_address(gensec_security,
     347       26201 :                                            conn->connection->remote_address);
     348       26201 :         if (!NT_STATUS_IS_OK(status)) {
     349           0 :                 return status;
     350             :         }
     351             : 
     352       26323 :         status = gensec_set_local_address(gensec_security,
     353       26201 :                                           conn->connection->local_address);
     354       26201 :         if (!NT_STATUS_IS_OK(status)) {
     355           0 :                 return status;
     356             :         }
     357             : 
     358       26201 :         gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
     359       26201 :         gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAP_STYLE);
     360             : 
     361       26201 :         if (conn->sockets.active == conn->sockets.tls) {
     362          50 :                 gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAPS_TRANSPORT);
     363             :         }
     364             : 
     365       26201 :         status = gensec_start_mech_by_sasl_name(gensec_security, sasl_mech);
     366             : 
     367       26201 :         if (!NT_STATUS_IS_OK(status)) {
     368           0 :                 return status;
     369             :         }
     370             : 
     371       26201 :         *_gensec_security = gensec_security;
     372       26201 :         return status;
     373             : }
     374             : 
     375             : static void ldapsrv_BindSASL_done(struct tevent_req *subreq);
     376             : 
     377       35529 : static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
     378             : {
     379       35529 :         struct ldap_BindRequest *req = &call->request->r.BindRequest;
     380         122 :         struct ldapsrv_reply *reply;
     381         122 :         struct ldap_BindResponse *resp;
     382         122 :         struct ldapsrv_connection *conn;
     383       35529 :         int result = 0;
     384       35529 :         const char *errstr=NULL;
     385       35529 :         NTSTATUS status = NT_STATUS_OK;
     386       35529 :         DATA_BLOB input = data_blob_null;
     387       35529 :         struct tevent_req *subreq = NULL;
     388             : 
     389       35529 :         DEBUG(10, ("BindSASL dn: %s\n",req->dn));
     390             : 
     391       35529 :         reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
     392       35529 :         if (!reply) {
     393           0 :                 return NT_STATUS_NO_MEMORY;
     394             :         }
     395       35529 :         resp = &reply->msg->r.BindResponse;
     396             :         /* Windows 2000 mmc doesn't like secblob == NULL and reports a decoding error */
     397       35529 :         resp->SASL.secblob = talloc_zero(reply, DATA_BLOB);
     398       35529 :         if (resp->SASL.secblob == NULL) {
     399           0 :                 return NT_STATUS_NO_MEMORY;
     400             :         }
     401             : 
     402       35529 :         conn = call->conn;
     403             : 
     404             :         /* 
     405             :          * TODO: a SASL bind with a different mechanism
     406             :          *       should cancel an inprogress SASL bind.
     407             :          *       (see RFC 4513)
     408             :          */
     409             : 
     410       35529 :         if (!conn->gensec) {
     411       26201 :                 status = ldapsrv_setup_gensec(conn, req->creds.SASL.mechanism,
     412             :                                               &conn->gensec);
     413       26201 :                 if (!NT_STATUS_IS_OK(status)) {
     414           0 :                         DEBUG(1, ("Failed to start GENSEC server for [%s] code: %s\n",
     415             :                                   ldb_binary_encode_string(call, req->creds.SASL.mechanism),
     416             :                                   nt_errstr(status)));
     417           0 :                         result = LDAP_OPERATIONS_ERROR;
     418           0 :                         errstr = talloc_asprintf(reply, "SASL: Failed to start authentication system: %s", 
     419             :                                                  nt_errstr(status));
     420           0 :                         goto do_reply;
     421             :                 }
     422             :         }
     423             : 
     424       35529 :         if (req->creds.SASL.secblob) {
     425       35207 :                 input = *req->creds.SASL.secblob;
     426             :         }
     427             : 
     428       35529 :         subreq = gensec_update_send(call, conn->connection->event.ctx,
     429             :                                     conn->gensec, input);
     430       35529 :         if (subreq == NULL) {
     431           0 :                 return NT_STATUS_NO_MEMORY;
     432             :         }
     433       35529 :         tevent_req_set_callback(subreq, ldapsrv_BindSASL_done, call);
     434             : 
     435       35529 :         status = ldapsrv_bind_wait_setup(call, reply);
     436       35529 :         if (!NT_STATUS_IS_OK(status)) {
     437           0 :                 TALLOC_FREE(subreq);
     438           0 :                 return status;
     439             :         }
     440             : 
     441             :         /*
     442             :          * The rest will be async.
     443             :          */
     444       35529 :         return NT_STATUS_OK;
     445             : 
     446           0 : do_reply:
     447           0 :         if (result != LDAP_SASL_BIND_IN_PROGRESS) {
     448             :                 /*
     449             :                  * We should destroy the gensec context
     450             :                  * when we hit a fatal error.
     451             :                  *
     452             :                  * Note: conn->gensec is already cleared
     453             :                  * for the LDAP_SUCCESS case.
     454             :                  */
     455           0 :                 talloc_unlink(conn, conn->gensec);
     456           0 :                 conn->gensec = NULL;
     457             :         }
     458             : 
     459           0 :         resp->response.resultcode = result;
     460           0 :         resp->response.dn = NULL;
     461           0 :         resp->response.errormessage = errstr;
     462           0 :         resp->response.referral = NULL;
     463             : 
     464           0 :         ldapsrv_queue_reply(call, reply);
     465           0 :         return NT_STATUS_OK;
     466             : }
     467             : 
     468       35529 : static void ldapsrv_BindSASL_done(struct tevent_req *subreq)
     469             : {
     470         122 :         struct ldapsrv_call *call =
     471       35529 :                 tevent_req_callback_data(subreq,
     472             :                 struct ldapsrv_call);
     473         122 :         struct ldapsrv_bind_wait_context *bind_wait =
     474       35529 :                 talloc_get_type_abort(call->wait_private,
     475             :                 struct ldapsrv_bind_wait_context);
     476       35529 :         struct ldap_BindRequest *req = &call->request->r.BindRequest;
     477       35529 :         struct ldapsrv_reply *reply = bind_wait->reply;
     478       35529 :         struct ldap_BindResponse *resp = &reply->msg->r.BindResponse;
     479       35529 :         struct ldapsrv_connection *conn = call->conn;
     480       35529 :         struct auth_session_info *session_info = NULL;
     481       35529 :         struct ldapsrv_sasl_postprocess_context *context = NULL;
     482         122 :         NTSTATUS status;
     483         122 :         int result;
     484       35529 :         const char *errstr = NULL;
     485       35529 :         char *ldb_errstring = NULL;
     486       35529 :         DATA_BLOB output = data_blob_null;
     487         122 :         NTTIME expire_time_nt;
     488             : 
     489       35529 :         status = gensec_update_recv(subreq, call, &output);
     490       35529 :         TALLOC_FREE(subreq);
     491             : 
     492       35529 :         if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
     493        9429 :                 *resp->SASL.secblob = output;
     494        9429 :                 result = LDAP_SASL_BIND_IN_PROGRESS;
     495        9429 :                 errstr = NULL;
     496        9429 :                 goto do_reply;
     497             :         }
     498             : 
     499       26100 :         if (!NT_STATUS_IS_OK(status)) {
     500         213 :                 status = nt_status_squash(status);
     501         213 :                 result = LDAP_INVALID_CREDENTIALS;
     502         213 :                 errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_LOGON_DENIED,
     503             :                                                 0x0C0904DC, status);
     504         213 :                 goto do_reply;
     505             :         }
     506             : 
     507       26064 :         if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
     508         177 :             gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
     509             : 
     510       25710 :                 context = talloc_zero(call, struct ldapsrv_sasl_postprocess_context);
     511       25710 :                 if (context == NULL) {
     512           0 :                         ldapsrv_bind_wait_finished(call, NT_STATUS_NO_MEMORY);
     513           0 :                         return;
     514             :                 }
     515             :         }
     516             : 
     517       25887 :         if (context && conn->sockets.tls) {
     518           2 :                 TALLOC_FREE(context);
     519           2 :                 status = NT_STATUS_NOT_SUPPORTED;
     520           2 :                 result = LDAP_UNWILLING_TO_PERFORM;
     521           2 :                 errstr = talloc_asprintf(reply,
     522             :                                          "SASL:[%s]: Sign or Seal are not allowed if TLS is used",
     523             :                                          req->creds.SASL.mechanism);
     524           2 :                 goto do_reply;
     525             :         }
     526             : 
     527       25885 :         if (context && conn->sockets.sasl) {
     528           0 :                 TALLOC_FREE(context);
     529           0 :                 status = NT_STATUS_NOT_SUPPORTED;
     530           0 :                 result = LDAP_UNWILLING_TO_PERFORM;
     531           0 :                 errstr = talloc_asprintf(reply,
     532             :                                          "SASL:[%s]: Sign or Seal are not allowed if SASL encryption has already been set up",
     533             :                                          req->creds.SASL.mechanism);
     534           0 :                 goto do_reply;
     535             :         }
     536             : 
     537       25885 :         if (context == NULL) {
     538         177 :                 switch (call->conn->require_strong_auth) {
     539           8 :                 case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO:
     540          52 :                         break;
     541          47 :                 case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS:
     542          47 :                         if (call->conn->sockets.active == call->conn->sockets.tls) {
     543          44 :                                 break;
     544             :                         }
     545           3 :                         status = NT_STATUS_NETWORK_ACCESS_DENIED;
     546           3 :                         result = LDAP_STRONG_AUTH_REQUIRED;
     547           3 :                         errstr = talloc_asprintf(reply,
     548             :                                         "SASL:[%s]: not allowed if TLS is used.",
     549             :                                          req->creds.SASL.mechanism);
     550         125 :                         goto do_reply;
     551             : 
     552         122 :                 case LDAP_SERVER_REQUIRE_STRONG_AUTH_YES:
     553         122 :                         status = NT_STATUS_NETWORK_ACCESS_DENIED;
     554         122 :                         result = LDAP_STRONG_AUTH_REQUIRED;
     555         122 :                         errstr = talloc_asprintf(reply,
     556             :                                          "SASL:[%s]: Sign or Seal are required.",
     557             :                                          req->creds.SASL.mechanism);
     558         122 :                         goto do_reply;
     559             :                 }
     560             :         }
     561             : 
     562       25760 :         if (context != NULL) {
     563       25708 :                 context->conn = conn;
     564       25708 :                 status = gensec_create_tstream(context,
     565             :                                                context->conn->gensec,
     566             :                                                context->conn->sockets.raw,
     567             :                                                &context->sasl);
     568       25708 :                 if (!NT_STATUS_IS_OK(status)) {
     569           0 :                         result = LDAP_OPERATIONS_ERROR;
     570           0 :                         errstr = talloc_asprintf(reply,
     571             :                                          "SASL:[%s]: Failed to setup SASL socket: %s",
     572             :                                          req->creds.SASL.mechanism, nt_errstr(status));
     573           0 :                         goto do_reply;
     574             :                 }
     575             :         }
     576             : 
     577       25760 :         status = gensec_session_info(conn->gensec, call, &session_info);
     578       25760 :         if (!NT_STATUS_IS_OK(status)) {
     579           1 :                 result = LDAP_OPERATIONS_ERROR;
     580           1 :                 errstr = talloc_asprintf(reply,
     581             :                                          "SASL:[%s]: Failed to get session info: %s",
     582             :                                          req->creds.SASL.mechanism, nt_errstr(status));
     583           1 :                 goto do_reply;
     584             :         }
     585             : 
     586       25759 :         talloc_unlink(conn, conn->session_info);
     587       25759 :         conn->session_info = talloc_steal(conn, session_info);
     588             : 
     589             :         /* don't leak the old LDB */
     590       25759 :         talloc_unlink(conn, conn->ldb);
     591             : 
     592       25759 :         call->conn->authz_logged = true;
     593             : 
     594       25759 :         result = ldapsrv_backend_Init(call->conn, &ldb_errstring);
     595             : 
     596       25759 :         if (result != LDB_SUCCESS) {
     597             :                 /* Only put the detailed error in DEBUG() */
     598           0 :                 DBG_ERR("ldapsrv_backend_Init failed: %s: %s\n",
     599             :                         ldb_errstring, ldb_strerror(result));
     600           0 :                 errstr = talloc_strdup(reply,
     601             :                                        "SASL Bind: Failed to advise "
     602             :                                        "ldb new credentials");
     603           0 :                 result = LDB_ERR_OPERATIONS_ERROR;
     604           0 :                 goto do_reply;
     605             :         }
     606             : 
     607       25759 :         expire_time_nt = gensec_expire_time(conn->gensec);
     608       25759 :         if (expire_time_nt != GENSEC_EXPIRE_TIME_INFINITY) {
     609         122 :                 struct timeval_buf buf;
     610             : 
     611       17001 :                 nttime_to_timeval(&conn->limits.expire_time, expire_time_nt);
     612             : 
     613       17001 :                 DBG_DEBUG("Setting connection expire_time to %s\n",
     614             :                           timeval_str_buf(&conn->limits.expire_time,
     615             :                                           false,
     616             :                                           true,
     617             :                                           &buf));
     618             :         }
     619             : 
     620       25759 :         if (context != NULL) {
     621       25707 :                 const void *ptr = NULL;
     622             : 
     623       25707 :                 ptr = talloc_reparent(conn, context->sasl, conn->gensec);
     624       25707 :                 if (ptr == NULL) {
     625           0 :                         ldapsrv_bind_wait_finished(call, NT_STATUS_NO_MEMORY);
     626           0 :                         return;
     627             :                 }
     628             : 
     629       25707 :                 call->postprocess_send = ldapsrv_sasl_postprocess_send;
     630       25707 :                 call->postprocess_recv = ldapsrv_sasl_postprocess_recv;
     631       25707 :                 call->postprocess_private = context;
     632             :         } else {
     633          52 :                 talloc_unlink(conn, conn->gensec);
     634             :         }
     635       25759 :         conn->gensec = NULL;
     636             : 
     637       25759 :         *resp->SASL.secblob = output;
     638       25759 :         result = LDAP_SUCCESS;
     639       25759 :         errstr = NULL;
     640             : 
     641       35407 : do_reply:
     642       35529 :         if (result != LDAP_SASL_BIND_IN_PROGRESS) {
     643             :                 /*
     644             :                  * We should destroy the gensec context
     645             :                  * when we hit a fatal error.
     646             :                  *
     647             :                  * Note: conn->gensec is already cleared
     648             :                  * for the LDAP_SUCCESS case.
     649             :                  */
     650       26100 :                 talloc_unlink(conn, conn->gensec);
     651       26100 :                 conn->gensec = NULL;
     652             :         }
     653             : 
     654       35529 :         resp->response.resultcode = result;
     655       35529 :         resp->response.dn = NULL;
     656       35529 :         resp->response.errormessage = errstr;
     657       35529 :         resp->response.referral = NULL;
     658             : 
     659       35529 :         ldapsrv_queue_reply(call, reply);
     660       35529 :         ldapsrv_bind_wait_finished(call, NT_STATUS_OK);
     661             : }
     662             : 
     663       36000 : NTSTATUS ldapsrv_BindRequest(struct ldapsrv_call *call)
     664             : {
     665       36000 :         struct ldap_BindRequest *req = &call->request->r.BindRequest;
     666         122 :         struct ldapsrv_reply *reply;
     667         122 :         struct ldap_BindResponse *resp;
     668             : 
     669       36000 :         if (call->conn->pending_calls != NULL) {
     670           0 :                 reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
     671           0 :                 if (!reply) {
     672           0 :                         return NT_STATUS_NO_MEMORY;
     673             :                 }
     674             : 
     675           0 :                 resp = &reply->msg->r.BindResponse;
     676           0 :                 resp->response.resultcode = LDAP_BUSY;
     677           0 :                 resp->response.dn = NULL;
     678           0 :                 resp->response.errormessage = talloc_asprintf(reply, "Pending requests on this LDAP session");
     679           0 :                 resp->response.referral = NULL;
     680           0 :                 resp->SASL.secblob = NULL;
     681             : 
     682           0 :                 ldapsrv_queue_reply(call, reply);
     683           0 :                 return NT_STATUS_OK;
     684             :         }
     685             : 
     686             :         /* 
     687             :          * TODO: a simple bind should cancel an
     688             :          *       inprogress SASL bind.
     689             :          *       (see RFC 4513)
     690             :          */
     691       36000 :         switch (req->mechanism) {
     692         471 :                 case LDAP_AUTH_MECH_SIMPLE:
     693         471 :                         return ldapsrv_BindSimple(call);
     694       35529 :                 case LDAP_AUTH_MECH_SASL:
     695       35529 :                         return ldapsrv_BindSASL(call);
     696             :         }
     697             : 
     698           0 :         reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
     699           0 :         if (!reply) {
     700           0 :                 return NT_STATUS_NO_MEMORY;
     701             :         }
     702             : 
     703           0 :         resp = &reply->msg->r.BindResponse;
     704           0 :         resp->response.resultcode = LDAP_AUTH_METHOD_NOT_SUPPORTED;
     705           0 :         resp->response.dn = NULL;
     706           0 :         resp->response.errormessage = talloc_asprintf(reply, "Bad AuthenticationChoice [%d]", req->mechanism);
     707           0 :         resp->response.referral = NULL;
     708           0 :         resp->SASL.secblob = NULL;
     709             : 
     710           0 :         ldapsrv_queue_reply(call, reply);
     711           0 :         return NT_STATUS_OK;
     712             : }
     713             : 
     714             : struct ldapsrv_unbind_wait_context {
     715             :         uint8_t dummy;
     716             : };
     717             : 
     718             : struct ldapsrv_unbind_wait_state {
     719             :         uint8_t dummy;
     720             : };
     721             : 
     722          31 : static struct tevent_req *ldapsrv_unbind_wait_send(TALLOC_CTX *mem_ctx,
     723             :                                                  struct tevent_context *ev,
     724             :                                                  void *private_data)
     725             : {
     726           0 :         struct ldapsrv_unbind_wait_context *unbind_wait =
     727          31 :                 talloc_get_type_abort(private_data,
     728             :                 struct ldapsrv_unbind_wait_context);
     729           0 :         struct tevent_req *req;
     730           0 :         struct ldapsrv_unbind_wait_state *state;
     731             : 
     732          31 :         req = tevent_req_create(mem_ctx, &state,
     733             :                                 struct ldapsrv_unbind_wait_state);
     734          31 :         if (req == NULL) {
     735           0 :                 return NULL;
     736             :         }
     737             : 
     738           0 :         (void)unbind_wait;
     739             : 
     740          31 :         tevent_req_nterror(req, NT_STATUS_LOCAL_DISCONNECT);
     741          31 :         return tevent_req_post(req, ev);
     742             : }
     743             : 
     744          31 : static NTSTATUS ldapsrv_unbind_wait_recv(struct tevent_req *req)
     745             : {
     746          31 :         return tevent_req_simple_recv_ntstatus(req);
     747             : }
     748             : 
     749          31 : static NTSTATUS ldapsrv_unbind_wait_setup(struct ldapsrv_call *call)
     750             : {
     751          31 :         struct ldapsrv_unbind_wait_context *unbind_wait = NULL;
     752             : 
     753          31 :         if (call->wait_private != NULL) {
     754           0 :                 return NT_STATUS_INTERNAL_ERROR;
     755             :         }
     756             : 
     757          31 :         unbind_wait = talloc_zero(call, struct ldapsrv_unbind_wait_context);
     758          31 :         if (unbind_wait == NULL) {
     759           0 :                 return NT_STATUS_NO_MEMORY;
     760             :         }
     761             : 
     762          31 :         call->wait_private = unbind_wait;
     763          31 :         call->wait_send = ldapsrv_unbind_wait_send;
     764          31 :         call->wait_recv = ldapsrv_unbind_wait_recv;
     765          31 :         return NT_STATUS_OK;
     766             : }
     767             : 
     768          31 : NTSTATUS ldapsrv_UnbindRequest(struct ldapsrv_call *call)
     769             : {
     770          31 :         struct ldapsrv_call *c = NULL;
     771          31 :         struct ldapsrv_call *n = NULL;
     772             : 
     773          31 :         DEBUG(10, ("UnbindRequest\n"));
     774             : 
     775          31 :         for (c = call->conn->pending_calls; c != NULL; c = n) {
     776           0 :                 n = c->next;
     777             : 
     778           0 :                 DLIST_REMOVE(call->conn->pending_calls, c);
     779           0 :                 TALLOC_FREE(c);
     780             :         }
     781             : 
     782          31 :         return ldapsrv_unbind_wait_setup(call);
     783             : }

Generated by: LCOV version 1.14