LCOV - code coverage report
Current view: top level - source4/ldap_server - ldap_bind.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 288 376 76.6 %
Date: 2021-09-23 10:06:22 Functions: 18 18 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         171 : static char *ldapsrv_bind_error_msg(TALLOC_CTX *mem_ctx,
      35             :                                     HRESULT hresult,
      36             :                                     uint32_t DSID,
      37             :                                     NTSTATUS status)
      38             : {
      39             :         WERROR werr;
      40         171 :         char *msg = NULL;
      41             : 
      42         171 :         status = nt_status_squash(status);
      43         171 :         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         171 :         msg = talloc_asprintf(mem_ctx, "%08X: LdapErr: DSID-%08X, comment: "
      56             :                               "AcceptSecurityContext error, data %x, v1db1",
      57         171 :                               (unsigned)HRES_ERROR_V(hresult),
      58             :                               (unsigned)DSID,
      59         171 :                               (unsigned)W_ERROR_V(werr));
      60             : 
      61         171 :         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       23718 : static struct tevent_req *ldapsrv_bind_wait_send(TALLOC_CTX *mem_ctx,
      76             :                                                  struct tevent_context *ev,
      77             :                                                  void *private_data)
      78             : {
      79       16661 :         struct ldapsrv_bind_wait_context *bind_wait =
      80        7057 :                 talloc_get_type_abort(private_data,
      81             :                 struct ldapsrv_bind_wait_context);
      82             :         struct tevent_req *req;
      83             :         struct ldapsrv_bind_wait_state *state;
      84             : 
      85       23718 :         req = tevent_req_create(mem_ctx, &state,
      86             :                                 struct ldapsrv_bind_wait_state);
      87       23718 :         if (req == NULL) {
      88           0 :                 return NULL;
      89             :         }
      90       23718 :         bind_wait->req = req;
      91             : 
      92       23718 :         tevent_req_defer_callback(req, ev);
      93             : 
      94       23718 :         if (!bind_wait->done) {
      95       23596 :                 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       23718 : static NTSTATUS ldapsrv_bind_wait_recv(struct tevent_req *req)
     107             : {
     108       23718 :         return tevent_req_simple_recv_ntstatus(req);
     109             : }
     110             : 
     111       23718 : static NTSTATUS ldapsrv_bind_wait_setup(struct ldapsrv_call *call,
     112             :                                         struct ldapsrv_reply *reply)
     113             : {
     114       23718 :         struct ldapsrv_bind_wait_context *bind_wait = NULL;
     115             : 
     116       23718 :         if (call->wait_private != NULL) {
     117           0 :                 return NT_STATUS_INTERNAL_ERROR;
     118             :         }
     119             : 
     120       23718 :         bind_wait = talloc_zero(call, struct ldapsrv_bind_wait_context);
     121       23718 :         if (bind_wait == NULL) {
     122           0 :                 return NT_STATUS_NO_MEMORY;
     123             :         }
     124       23718 :         bind_wait->reply = reply;
     125             : 
     126       23718 :         call->wait_private = bind_wait;
     127       23718 :         call->wait_send = ldapsrv_bind_wait_send;
     128       23718 :         call->wait_recv = ldapsrv_bind_wait_recv;
     129       23718 :         return NT_STATUS_OK;
     130             : }
     131             : 
     132       23718 : static void ldapsrv_bind_wait_finished(struct ldapsrv_call *call,
     133             :                                        NTSTATUS status)
     134             : {
     135       16661 :         struct ldapsrv_bind_wait_context *bind_wait =
     136       23718 :                 talloc_get_type_abort(call->wait_private,
     137             :                 struct ldapsrv_bind_wait_context);
     138             : 
     139       23718 :         bind_wait->done = true;
     140       23718 :         bind_wait->status = status;
     141             : 
     142       23718 :         if (bind_wait->req == NULL) {
     143           0 :                 return;
     144             :         }
     145             : 
     146       23718 :         if (tevent_req_nterror(bind_wait->req, status)) {
     147           0 :                 return;
     148             :         }
     149             : 
     150       23718 :         tevent_req_done(bind_wait->req);
     151             : }
     152             : 
     153             : static void ldapsrv_BindSimple_done(struct tevent_req *subreq);
     154             : 
     155         125 : static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
     156             : {
     157         125 :         struct ldap_BindRequest *req = &call->request->r.BindRequest;
     158         125 :         struct ldapsrv_reply *reply = NULL;
     159         125 :         struct ldap_BindResponse *resp = NULL;
     160             :         int result;
     161         125 :         const char *errstr = NULL;
     162             :         NTSTATUS status;
     163         125 :         bool using_tls = call->conn->sockets.active == call->conn->sockets.tls;
     164         125 :         struct tevent_req *subreq = NULL;
     165             : 
     166         125 :         DEBUG(10, ("BindSimple dn: %s\n",req->dn));
     167             : 
     168         125 :         reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
     169         125 :         if (!reply) {
     170           0 :                 return NT_STATUS_NO_MEMORY;
     171             :         }
     172             : 
     173         214 :         if (req->dn != NULL &&
     174         209 :             strlen(req->dn) != 0 &&
     175         175 :             call->conn->require_strong_auth > LDAP_SERVER_REQUIRE_STRONG_AUTH_NO &&
     176          63 :             !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         545 :         subreq = authenticate_ldap_simple_bind_send(call,
     186         120 :                                         call->conn->connection->event.ctx,
     187         120 :                                         call->conn->connection->msg_ctx,
     188         120 :                                         call->conn->lp_ctx,
     189         120 :                                         call->conn->connection->remote_address,
     190         120 :                                         call->conn->connection->local_address,
     191             :                                         using_tls,
     192             :                                         req->dn,
     193             :                                         req->creds.password);
     194         120 :         if (subreq == NULL) {
     195           0 :                 return NT_STATUS_NO_MEMORY;
     196             :         }
     197         120 :         tevent_req_set_callback(subreq, ldapsrv_BindSimple_done, call);
     198             : 
     199         120 :         status = ldapsrv_bind_wait_setup(call, reply);
     200         120 :         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         120 :         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         120 : static void ldapsrv_BindSimple_done(struct tevent_req *subreq)
     223             : {
     224          85 :         struct ldapsrv_call *call =
     225         120 :                 tevent_req_callback_data(subreq,
     226             :                 struct ldapsrv_call);
     227          85 :         struct ldapsrv_bind_wait_context *bind_wait =
     228         120 :                 talloc_get_type_abort(call->wait_private,
     229             :                 struct ldapsrv_bind_wait_context);
     230         120 :         struct ldapsrv_reply *reply = bind_wait->reply;
     231         120 :         struct auth_session_info *session_info = NULL;
     232             :         NTSTATUS status;
     233         120 :         struct ldap_BindResponse *resp = NULL;
     234             :         int result;
     235         120 :         const char *errstr = NULL;
     236             : 
     237         120 :         status = authenticate_ldap_simple_bind_recv(subreq,
     238             :                                                     call,
     239             :                                                     &session_info);
     240         120 :         if (NT_STATUS_IS_OK(status)) {
     241         106 :                 char *ldb_errstring = NULL;
     242         106 :                 result = LDAP_SUCCESS;
     243         106 :                 errstr = NULL;
     244             : 
     245         106 :                 talloc_unlink(call->conn, call->conn->session_info);
     246         106 :                 call->conn->session_info = talloc_steal(call->conn, session_info);
     247             : 
     248         106 :                 call->conn->authz_logged = true;
     249             : 
     250             :                 /* don't leak the old LDB */
     251         106 :                 talloc_unlink(call->conn, call->conn->ldb);
     252             : 
     253         106 :                 result = ldapsrv_backend_Init(call->conn, &ldb_errstring);
     254             : 
     255         106 :                 if (result != LDB_SUCCESS) {
     256             :                         /* Only put the detailed error in DEBUG() */
     257           0 :                         DBG_ERR("ldapsrv_backend_Init failed: %s: %s",
     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          14 :                 status = nt_status_squash(status);
     266             : 
     267          14 :                 result = LDAP_INVALID_CREDENTIALS;
     268          14 :                 errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_INVALID_TOKEN,
     269             :                                                 0x0C0903A9, status);
     270             :         }
     271             : 
     272         120 :         resp = &reply->msg->r.BindResponse;
     273         120 :         resp->response.resultcode = result;
     274         120 :         resp->response.errormessage = errstr;
     275         120 :         resp->response.dn = NULL;
     276         120 :         resp->response.referral = NULL;
     277         120 :         resp->SASL.secblob = NULL;
     278             : 
     279         120 :         ldapsrv_queue_reply(call, reply);
     280         120 :         ldapsrv_bind_wait_finished(call, NT_STATUS_OK);
     281         120 : }
     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       17649 : static struct tevent_req *ldapsrv_sasl_postprocess_send(TALLOC_CTX *mem_ctx,
     293             :                                                 struct tevent_context *ev,
     294             :                                                 void *private_data)
     295             : {
     296       12705 :         struct ldapsrv_sasl_postprocess_context *context =
     297        4944 :                 talloc_get_type_abort(private_data,
     298             :                 struct ldapsrv_sasl_postprocess_context);
     299             :         struct tevent_req *req;
     300             :         struct ldapsrv_sasl_postprocess_state *state;
     301             : 
     302       17649 :         req = tevent_req_create(mem_ctx, &state,
     303             :                                 struct ldapsrv_sasl_postprocess_state);
     304       17649 :         if (req == NULL) {
     305           0 :                 return NULL;
     306             :         }
     307             : 
     308       17649 :         TALLOC_FREE(context->conn->sockets.sasl);
     309       17649 :         context->conn->sockets.sasl = talloc_move(context->conn, &context->sasl);
     310       17649 :         context->conn->sockets.active = context->conn->sockets.sasl;
     311             : 
     312       17649 :         tevent_req_done(req);
     313       17649 :         return tevent_req_post(req, ev);
     314             : }
     315             : 
     316       17649 : static NTSTATUS ldapsrv_sasl_postprocess_recv(struct tevent_req *req)
     317             : {
     318       17649 :         return tevent_req_simple_recv_ntstatus(req);
     319             : }
     320             : 
     321       18015 : static NTSTATUS ldapsrv_setup_gensec(struct ldapsrv_connection *conn,
     322             :                                      const char *sasl_mech,
     323             :                                      struct gensec_security **_gensec_security)
     324             : {
     325             :         NTSTATUS status;
     326             : 
     327             :         struct gensec_security *gensec_security;
     328             : 
     329       44011 :         status = samba_server_gensec_start(conn,
     330       17893 :                                            conn->connection->event.ctx,
     331       18015 :                                            conn->connection->msg_ctx,
     332             :                                            conn->lp_ctx,
     333             :                                            conn->server_credentials,
     334             :                                            "ldap",
     335             :                                            &gensec_security);
     336       18015 :         if (!NT_STATUS_IS_OK(status)) {
     337           0 :                 return status;
     338             :         }
     339             : 
     340       18015 :         status = gensec_set_target_service_description(gensec_security,
     341             :                                                        "LDAP");
     342       18015 :         if (!NT_STATUS_IS_OK(status)) {
     343           0 :                 return status;
     344             :         }
     345             : 
     346       18015 :         status = gensec_set_remote_address(gensec_security,
     347       18015 :                                            conn->connection->remote_address);
     348       18015 :         if (!NT_STATUS_IS_OK(status)) {
     349           0 :                 return status;
     350             :         }
     351             : 
     352       18015 :         status = gensec_set_local_address(gensec_security,
     353       18015 :                                           conn->connection->local_address);
     354       18015 :         if (!NT_STATUS_IS_OK(status)) {
     355           0 :                 return status;
     356             :         }
     357             : 
     358       18015 :         gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
     359       18015 :         gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAP_STYLE);
     360             : 
     361       18015 :         if (conn->sockets.active == conn->sockets.tls) {
     362          78 :                 gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAPS_TRANSPORT);
     363             :         }
     364             : 
     365       18015 :         status = gensec_start_mech_by_sasl_name(gensec_security, sasl_mech);
     366             : 
     367       18015 :         if (!NT_STATUS_IS_OK(status)) {
     368           0 :                 return status;
     369             :         }
     370             : 
     371       18015 :         *_gensec_security = gensec_security;
     372       18015 :         return status;
     373             : }
     374             : 
     375             : static void ldapsrv_BindSASL_done(struct tevent_req *subreq);
     376             : 
     377       23598 : static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
     378             : {
     379       23598 :         struct ldap_BindRequest *req = &call->request->r.BindRequest;
     380             :         struct ldapsrv_reply *reply;
     381             :         struct ldap_BindResponse *resp;
     382             :         struct ldapsrv_connection *conn;
     383       23598 :         int result = 0;
     384       23598 :         const char *errstr=NULL;
     385       23598 :         NTSTATUS status = NT_STATUS_OK;
     386       23598 :         DATA_BLOB input = data_blob_null;
     387       23598 :         struct tevent_req *subreq = NULL;
     388             : 
     389       23598 :         DEBUG(10, ("BindSASL dn: %s\n",req->dn));
     390             : 
     391       23598 :         reply = ldapsrv_init_reply(call, LDAP_TAG_BindResponse);
     392       23598 :         if (!reply) {
     393           0 :                 return NT_STATUS_NO_MEMORY;
     394             :         }
     395       23598 :         resp = &reply->msg->r.BindResponse;
     396             :         /* Windows 2000 mmc doesn't like secblob == NULL and reports a decoding error */
     397       23598 :         resp->SASL.secblob = talloc_zero(reply, DATA_BLOB);
     398       23598 :         if (resp->SASL.secblob == NULL) {
     399           0 :                 return NT_STATUS_NO_MEMORY;
     400             :         }
     401             : 
     402       23598 :         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       23598 :         if (!conn->gensec) {
     411       18015 :                 status = ldapsrv_setup_gensec(conn, req->creds.SASL.mechanism,
     412             :                                               &conn->gensec);
     413       18015 :                 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       23598 :         if (req->creds.SASL.secblob) {
     425       23246 :                 input = *req->creds.SASL.secblob;
     426             :         }
     427             : 
     428       23598 :         subreq = gensec_update_send(call, conn->connection->event.ctx,
     429             :                                     conn->gensec, input);
     430       23598 :         if (subreq == NULL) {
     431           0 :                 return NT_STATUS_NO_MEMORY;
     432             :         }
     433       23598 :         tevent_req_set_callback(subreq, ldapsrv_BindSASL_done, call);
     434             : 
     435       23598 :         status = ldapsrv_bind_wait_setup(call, reply);
     436       23598 :         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       23598 :         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       23598 : static void ldapsrv_BindSASL_done(struct tevent_req *subreq)
     469             : {
     470       16576 :         struct ldapsrv_call *call =
     471       23598 :                 tevent_req_callback_data(subreq,
     472             :                 struct ldapsrv_call);
     473       16576 :         struct ldapsrv_bind_wait_context *bind_wait =
     474       23598 :                 talloc_get_type_abort(call->wait_private,
     475             :                 struct ldapsrv_bind_wait_context);
     476       23598 :         struct ldap_BindRequest *req = &call->request->r.BindRequest;
     477       23598 :         struct ldapsrv_reply *reply = bind_wait->reply;
     478       23598 :         struct ldap_BindResponse *resp = &reply->msg->r.BindResponse;
     479       23598 :         struct ldapsrv_connection *conn = call->conn;
     480       23598 :         struct auth_session_info *session_info = NULL;
     481       23598 :         struct ldapsrv_sasl_postprocess_context *context = NULL;
     482             :         NTSTATUS status;
     483             :         int result;
     484       23598 :         const char *errstr = NULL;
     485       23598 :         char *ldb_errstring = NULL;
     486       23598 :         DATA_BLOB output = data_blob_null;
     487             :         NTTIME expire_time_nt;
     488             : 
     489       23598 :         status = gensec_update_recv(subreq, call, &output);
     490       23598 :         TALLOC_FREE(subreq);
     491             : 
     492       23598 :         if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
     493        5585 :                 *resp->SASL.secblob = output;
     494        5585 :                 result = LDAP_SASL_BIND_IN_PROGRESS;
     495        5585 :                 errstr = NULL;
     496        5585 :                 goto do_reply;
     497             :         }
     498             : 
     499       18013 :         if (!NT_STATUS_IS_OK(status)) {
     500         157 :                 status = nt_status_squash(status);
     501         157 :                 result = LDAP_INVALID_CREDENTIALS;
     502         157 :                 errstr = ldapsrv_bind_error_msg(reply, HRES_SEC_E_LOGON_DENIED,
     503             :                                                 0x0C0904DC, status);
     504         157 :                 goto do_reply;
     505             :         }
     506             : 
     507       18061 :         if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
     508         205 :             gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
     509             : 
     510       17651 :                 context = talloc_zero(call, struct ldapsrv_sasl_postprocess_context);
     511       17651 :                 if (context == NULL) {
     512           0 :                         ldapsrv_bind_wait_finished(call, NT_STATUS_NO_MEMORY);
     513           0 :                         return;
     514             :                 }
     515             :         }
     516             : 
     517       17856 :         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       17854 :         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       17854 :         if (context == NULL) {
     538         205 :                 switch (call->conn->require_strong_auth) {
     539           8 :                 case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO:
     540           8 :                         break;
     541          75 :                 case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS:
     542          75 :                         if (call->conn->sockets.active == call->conn->sockets.tls) {
     543          72 :                                 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           7 :                         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       17729 :         if (context != NULL) {
     563       17649 :                 context->conn = conn;
     564       17649 :                 status = gensec_create_tstream(context,
     565             :                                                context->conn->gensec,
     566             :                                                context->conn->sockets.raw,
     567             :                                                &context->sasl);
     568       17649 :                 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       17729 :         status = gensec_session_info(conn->gensec, call, &session_info);
     578       17729 :         if (!NT_STATUS_IS_OK(status)) {
     579           0 :                 result = LDAP_OPERATIONS_ERROR;
     580           0 :                 errstr = talloc_asprintf(reply,
     581             :                                          "SASL:[%s]: Failed to get session info: %s",
     582             :                                          req->creds.SASL.mechanism, nt_errstr(status));
     583           0 :                 goto do_reply;
     584             :         }
     585             : 
     586       17729 :         talloc_unlink(conn, conn->session_info);
     587       17729 :         conn->session_info = talloc_steal(conn, session_info);
     588             : 
     589             :         /* don't leak the old LDB */
     590       17729 :         talloc_unlink(conn, conn->ldb);
     591             : 
     592       17729 :         call->conn->authz_logged = true;
     593             : 
     594       17729 :         result = ldapsrv_backend_Init(call->conn, &ldb_errstring);
     595             : 
     596       17729 :         if (result != LDB_SUCCESS) {
     597             :                 /* Only put the detailed error in DEBUG() */
     598           0 :                 DBG_ERR("ldapsrv_backend_Init failed: %s: %s",
     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       17729 :         expire_time_nt = gensec_expire_time(conn->gensec);
     608       17729 :         if (expire_time_nt != GENSEC_EXPIRE_TIME_INFINITY) {
     609             :                 struct timeval_buf buf;
     610             : 
     611       12693 :                 nttime_to_timeval(&conn->limits.expire_time, expire_time_nt);
     612             : 
     613       12693 :                 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       17729 :         if (context != NULL) {
     621       17649 :                 const void *ptr = NULL;
     622             : 
     623       17649 :                 ptr = talloc_reparent(conn, context->sasl, conn->gensec);
     624       17649 :                 if (ptr == NULL) {
     625           0 :                         ldapsrv_bind_wait_finished(call, NT_STATUS_NO_MEMORY);
     626           0 :                         return;
     627             :                 }
     628             : 
     629       17649 :                 call->postprocess_send = ldapsrv_sasl_postprocess_send;
     630       17649 :                 call->postprocess_recv = ldapsrv_sasl_postprocess_recv;
     631       17649 :                 call->postprocess_private = context;
     632             :         } else {
     633          80 :                 talloc_unlink(conn, conn->gensec);
     634             :         }
     635       17729 :         conn->gensec = NULL;
     636             : 
     637       17729 :         *resp->SASL.secblob = output;
     638       17729 :         result = LDAP_SUCCESS;
     639       17729 :         errstr = NULL;
     640             : 
     641       23476 : do_reply:
     642       23476 :         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       18013 :                 talloc_unlink(conn, conn->gensec);
     651       18013 :                 conn->gensec = NULL;
     652             :         }
     653             : 
     654       23598 :         resp->response.resultcode = result;
     655       23598 :         resp->response.dn = NULL;
     656       23598 :         resp->response.errormessage = errstr;
     657       23598 :         resp->response.referral = NULL;
     658             : 
     659       23598 :         ldapsrv_queue_reply(call, reply);
     660       23598 :         ldapsrv_bind_wait_finished(call, NT_STATUS_OK);
     661             : }
     662             : 
     663       23723 : NTSTATUS ldapsrv_BindRequest(struct ldapsrv_call *call)
     664             : {
     665       23723 :         struct ldap_BindRequest *req = &call->request->r.BindRequest;
     666             :         struct ldapsrv_reply *reply;
     667             :         struct ldap_BindResponse *resp;
     668             : 
     669       23723 :         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       23723 :         switch (req->mechanism) {
     692         125 :                 case LDAP_AUTH_MECH_SIMPLE:
     693         125 :                         return ldapsrv_BindSimple(call);
     694       23598 :                 case LDAP_AUTH_MECH_SASL:
     695       23598 :                         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         280 : static struct tevent_req *ldapsrv_unbind_wait_send(TALLOC_CTX *mem_ctx,
     723             :                                                  struct tevent_context *ev,
     724             :                                                  void *private_data)
     725             : {
     726         147 :         struct ldapsrv_unbind_wait_context *unbind_wait =
     727         133 :                 talloc_get_type_abort(private_data,
     728             :                 struct ldapsrv_unbind_wait_context);
     729             :         struct tevent_req *req;
     730             :         struct ldapsrv_unbind_wait_state *state;
     731             : 
     732         280 :         req = tevent_req_create(mem_ctx, &state,
     733             :                                 struct ldapsrv_unbind_wait_state);
     734         280 :         if (req == NULL) {
     735           0 :                 return NULL;
     736             :         }
     737             : 
     738             :         (void)unbind_wait;
     739             : 
     740         280 :         tevent_req_nterror(req, NT_STATUS_LOCAL_DISCONNECT);
     741         280 :         return tevent_req_post(req, ev);
     742             : }
     743             : 
     744         280 : static NTSTATUS ldapsrv_unbind_wait_recv(struct tevent_req *req)
     745             : {
     746         280 :         return tevent_req_simple_recv_ntstatus(req);
     747             : }
     748             : 
     749         280 : static NTSTATUS ldapsrv_unbind_wait_setup(struct ldapsrv_call *call)
     750             : {
     751         280 :         struct ldapsrv_unbind_wait_context *unbind_wait = NULL;
     752             : 
     753         280 :         if (call->wait_private != NULL) {
     754           0 :                 return NT_STATUS_INTERNAL_ERROR;
     755             :         }
     756             : 
     757         280 :         unbind_wait = talloc_zero(call, struct ldapsrv_unbind_wait_context);
     758         280 :         if (unbind_wait == NULL) {
     759           0 :                 return NT_STATUS_NO_MEMORY;
     760             :         }
     761             : 
     762         280 :         call->wait_private = unbind_wait;
     763         280 :         call->wait_send = ldapsrv_unbind_wait_send;
     764         280 :         call->wait_recv = ldapsrv_unbind_wait_recv;
     765         280 :         return NT_STATUS_OK;
     766             : }
     767             : 
     768         280 : NTSTATUS ldapsrv_UnbindRequest(struct ldapsrv_call *call)
     769             : {
     770         280 :         struct ldapsrv_call *c = NULL;
     771         280 :         struct ldapsrv_call *n = NULL;
     772             : 
     773         280 :         DEBUG(10, ("UnbindRequest\n"));
     774             : 
     775         280 :         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         280 :         return ldapsrv_unbind_wait_setup(call);
     783             : }

Generated by: LCOV version 1.13