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

Generated by: LCOV version 1.14