LCOV - code coverage report
Current view: top level - librpc/rpc - dcesrv_core.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 1118 1376 81.2 %
Date: 2024-06-13 04:01:37 Functions: 68 72 94.4 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    server side dcerpc core code
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2003-2005
       7             :    Copyright (C) Stefan (metze) Metzmacher 2004-2005
       8             :    Copyright (C) Samuel Cabrero <scabrero@samba.org> 2019
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "librpc/rpc/dcesrv_core.h"
      26             : #include "librpc/rpc/dcesrv_core_proto.h"
      27             : #include "librpc/rpc/dcerpc_util.h"
      28             : #include "librpc/gen_ndr/auth.h"
      29             : #include "auth/gensec/gensec.h"
      30             : #include "lib/util/dlinklist.h"
      31             : #include "libcli/security/security.h"
      32             : #include "param/param.h"
      33             : #include "lib/tsocket/tsocket.h"
      34             : #include "librpc/gen_ndr/ndr_dcerpc.h"
      35             : #include "lib/util/tevent_ntstatus.h"
      36             : #include "system/network.h"
      37             : #include "nsswitch/winbind_client.h"
      38             : 
      39             : /**
      40             :  * @file
      41             :  * @brief DCERPC server
      42             :  */
      43             : 
      44             : #undef DBGC_CLASS
      45             : #define DBGC_CLASS DBGC_RPC_SRV
      46             : 
      47             : #undef strcasecmp
      48             : 
      49             : static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
      50             :                                 const struct dcerpc_bind *b,
      51             :                                 struct dcerpc_ack_ctx *ack_ctx_list);
      52             : 
      53             : /*
      54             :   see if two endpoints match
      55             : */
      56       55286 : static bool endpoints_match(const struct dcerpc_binding *ep1,
      57             :                             const struct dcerpc_binding *ep2)
      58             : {
      59             :         enum dcerpc_transport_t t1;
      60             :         enum dcerpc_transport_t t2;
      61             :         const char *e1;
      62             :         const char *e2;
      63             : 
      64       55286 :         t1 = dcerpc_binding_get_transport(ep1);
      65       55286 :         t2 = dcerpc_binding_get_transport(ep2);
      66             : 
      67       55286 :         e1 = dcerpc_binding_get_string_option(ep1, "endpoint");
      68       55286 :         e2 = dcerpc_binding_get_string_option(ep2, "endpoint");
      69             : 
      70       55286 :         if (t1 != t2) {
      71       36435 :                 return false;
      72             :         }
      73             : 
      74       18851 :         if (!e1 || !e2) {
      75        5276 :                 return e1 == e2;
      76             :         }
      77             : 
      78       13575 :         if (strcasecmp(e1, e2) != 0) {
      79       12265 :                 return false;
      80             :         }
      81             : 
      82        1310 :         return true;
      83             : }
      84             : 
      85             : /*
      86             :   find an endpoint in the dcesrv_context
      87             : */
      88        4158 : _PUBLIC_ NTSTATUS dcesrv_find_endpoint(struct dcesrv_context *dce_ctx,
      89             :                                 const struct dcerpc_binding *ep_description,
      90             :                                 struct dcesrv_endpoint **_out)
      91             : {
      92        4158 :         struct dcesrv_endpoint *ep = NULL;
      93       26091 :         for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
      94       24337 :                 if (endpoints_match(ep->ep_description, ep_description)) {
      95        2404 :                         *_out = ep;
      96        2404 :                         return NT_STATUS_OK;
      97             :                 }
      98             :         }
      99        1754 :         return NT_STATUS_NOT_FOUND;
     100             : }
     101             : 
     102             : /*
     103             :   find a registered context_id from a bind or alter_context
     104             : */
     105      196296 : static struct dcesrv_connection_context *dcesrv_find_context(struct dcesrv_connection *conn,
     106             :                                                              uint16_t context_id)
     107             : {
     108             :         struct dcesrv_connection_context *c;
     109      196428 :         for (c=conn->contexts;c;c=c->next) {
     110      179488 :                 if (c->context_id == context_id) return c;
     111             :         }
     112       16940 :         return NULL;
     113             : }
     114             : 
     115             : /*
     116             :   find the interface operations on any endpoint with this binding
     117             : */
     118        3472 : static const struct dcesrv_interface *find_interface_by_binding(struct dcesrv_context *dce_ctx,
     119             :                                                                 struct dcerpc_binding *binding,
     120             :                                                                 const struct dcesrv_interface *iface)
     121             : {
     122             :         struct dcesrv_endpoint *ep;
     123       34421 :         for (ep=dce_ctx->endpoint_list; ep; ep=ep->next) {
     124       30949 :                 if (endpoints_match(ep->ep_description, binding)) {
     125        1718 :                         const struct dcesrv_interface *ret = NULL;
     126             : 
     127        1718 :                         ret = find_interface_by_syntax_id(
     128             :                                 ep, &iface->syntax_id);
     129        1718 :                         if (ret != NULL) {
     130           0 :                                 return ret;
     131             :                         }
     132             :                 }
     133             :         }
     134        3472 :         return NULL;
     135             : }
     136             : 
     137             : /*
     138             :   find the interface operations on an endpoint by uuid
     139             : */
     140       24314 : _PUBLIC_ const struct dcesrv_interface *find_interface_by_syntax_id(
     141             :         const struct dcesrv_endpoint *endpoint,
     142             :         const struct ndr_syntax_id *interface)
     143             : {
     144             :         struct dcesrv_if_list *ifl;
     145       99789 :         for (ifl=endpoint->interface_list; ifl; ifl=ifl->next) {
     146       98050 :                 if (ndr_syntax_id_equal(&ifl->iface->syntax_id, interface)) {
     147       22575 :                         return ifl->iface;
     148             :                 }
     149             :         }
     150        1739 :         return NULL;
     151             : }
     152             : 
     153             : /*
     154             :   find the earlier parts of a fragmented call awaiting reassembly
     155             : */
     156       15806 : static struct dcesrv_call_state *dcesrv_find_fragmented_call(struct dcesrv_connection *dce_conn, uint32_t call_id)
     157             : {
     158             :         struct dcesrv_call_state *c;
     159       15855 :         for (c=dce_conn->incoming_fragmented_call_list;c;c=c->next) {
     160       15768 :                 if (c->pkt.call_id == call_id) {
     161       15719 :                         return c;
     162             :                 }
     163             :         }
     164          87 :         return NULL;
     165             : }
     166             : 
     167             : /*
     168             :   register an interface on an endpoint
     169             : 
     170             :   An endpoint is one unix domain socket (for ncalrpc), one TCP port
     171             :   (for ncacn_ip_tcp) or one (forwarded) named pipe (for ncacn_np).
     172             : 
     173             :   Each endpoint can have many interfaces such as netlogon, lsa or
     174             :   samr.  Some have essentially the full set.
     175             : 
     176             :   This is driven from the set of interfaces listed in each IDL file
     177             :   via the PIDL generated *__op_init_server() functions.
     178             : */
     179        3472 : _PUBLIC_ NTSTATUS dcesrv_interface_register(struct dcesrv_context *dce_ctx,
     180             :                                    const char *ep_name,
     181             :                                    const char *ncacn_np_secondary_endpoint,
     182             :                                    const struct dcesrv_interface *iface,
     183             :                                    const struct security_descriptor *sd)
     184             : {
     185        3472 :         struct dcerpc_binding *binding = NULL;
     186        3472 :         struct dcerpc_binding *binding2 = NULL;
     187             :         NTSTATUS ret;
     188             : 
     189        3472 :         ret = dcerpc_parse_binding(dce_ctx, ep_name, &binding);
     190        3472 :         if (NT_STATUS_IS_ERR(ret)) {
     191           0 :                 DBG_ERR("Trouble parsing binding string '%s'\n", ep_name);
     192           0 :                 goto out;
     193             :         }
     194             : 
     195        3472 :         if (ncacn_np_secondary_endpoint != NULL) {
     196         452 :                 ret = dcerpc_parse_binding(dce_ctx,
     197             :                                            ncacn_np_secondary_endpoint,
     198             :                                            &binding2);
     199         452 :                 if (NT_STATUS_IS_ERR(ret)) {
     200           0 :                         DBG_ERR("Trouble parsing 2nd binding string '%s'\n",
     201             :                                 ncacn_np_secondary_endpoint);
     202           0 :                         goto out;
     203             :                 }
     204             :         }
     205             : 
     206        3472 :         ret = dcesrv_interface_register_b(dce_ctx,
     207             :                                           binding,
     208             :                                           binding2,
     209             :                                           iface,
     210             :                                           sd);
     211        3472 : out:
     212        3472 :         TALLOC_FREE(binding);
     213        3472 :         TALLOC_FREE(binding2);
     214        3472 :         return ret;
     215             : }
     216             : 
     217        3472 : _PUBLIC_ NTSTATUS dcesrv_interface_register_b(struct dcesrv_context *dce_ctx,
     218             :                                         struct dcerpc_binding *binding,
     219             :                                         struct dcerpc_binding *binding2,
     220             :                                         const struct dcesrv_interface *iface,
     221             :                                         const struct security_descriptor *sd)
     222             : {
     223             :         struct dcesrv_endpoint *ep;
     224             :         struct dcesrv_if_list *ifl;
     225        3472 :         bool add_ep = false;
     226             :         NTSTATUS status;
     227             :         enum dcerpc_transport_t transport;
     228        3472 :         char *ep_string = NULL;
     229        3472 :         bool use_single_process = true;
     230             :         const char *ep_process_string;
     231             : 
     232             :         /*
     233             :          * If we are not using handles, there is no need for force
     234             :          * this service into using a single process.
     235             :          *
     236             :          * However, due to the way we listen for RPC packets, we can
     237             :          * only do this if we have a single service per pipe or TCP
     238             :          * port, so we still force a single combined process for
     239             :          * ncalrpc.
     240             :          */
     241        3472 :         if (iface->flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED) {
     242         156 :                 use_single_process = false;
     243             :         }
     244             : 
     245        3472 :         transport = dcerpc_binding_get_transport(binding);
     246        3472 :         if (transport == NCACN_IP_TCP) {
     247             :                 int port;
     248             : 
     249             :                 /*
     250             :                  * First check if there is already a port specified, eg
     251             :                  * for epmapper on ncacn_ip_tcp:[135]
     252             :                  */
     253         700 :                 const char *endpoint
     254         318 :                         = dcerpc_binding_get_string_option(binding,
     255             :                                                            "endpoint");
     256        1018 :                 if (endpoint == NULL) {
     257         954 :                         port = lpcfg_parm_int(dce_ctx->lp_ctx, NULL,
     258         299 :                                               "rpc server port", iface->name, 0);
     259             : 
     260             :                         /*
     261             :                          * For RPC services that are not set to use a single
     262             :                          * process, we do not default to using the 'rpc server
     263             :                          * port' because that would cause a double-bind on
     264             :                          * that port.
     265             :                          */
     266         954 :                         if (port == 0 && !use_single_process) {
     267           0 :                                 port = lpcfg_rpc_server_port(dce_ctx->lp_ctx);
     268             :                         }
     269         954 :                         if (port != 0) {
     270             :                                 char port_str[6];
     271          52 :                                 snprintf(port_str, sizeof(port_str), "%u", port);
     272          52 :                                 status = dcerpc_binding_set_string_option(binding,
     273             :                                                                           "endpoint",
     274             :                                                                           port_str);
     275          52 :                                 if (!NT_STATUS_IS_OK(status)) {
     276           0 :                                         return status;
     277             :                                 }
     278             :                         }
     279             :                 }
     280             :         }
     281             : 
     282        3472 :         if (transport == NCACN_NP && binding2 != NULL) {
     283             :                 enum dcerpc_transport_t transport2;
     284             : 
     285         254 :                 transport2 = dcerpc_binding_get_transport(binding2);
     286         254 :                 SMB_ASSERT(transport2 == transport);
     287             :         }
     288             : 
     289             :         /* see if the interface is already registered on the endpoint */
     290        3472 :         if (find_interface_by_binding(dce_ctx, binding, iface)!=NULL) {
     291           0 :                 char *binding_string = dcerpc_binding_string(dce_ctx, binding);
     292           0 :                 DBG_ERR("Interface '%s' already registered on endpoint '%s'\n",
     293             :                         iface->name, binding_string);
     294           0 :                 TALLOC_FREE(binding_string);
     295           0 :                 return NT_STATUS_OBJECT_NAME_COLLISION;
     296             :         }
     297             : 
     298             :         /* check if this endpoint exists
     299             :          */
     300        3472 :         status = dcesrv_find_endpoint(dce_ctx, binding, &ep);
     301        3472 :         if (NT_STATUS_IS_OK(status)) {
     302             :                 /*
     303             :                  * We want a new port on ncacn_ip_tcp for NETLOGON, so
     304             :                  * it can be multi-process.  Other processes can also
     305             :                  * listen on distinct ports, if they have one forced
     306             :                  * in the code above with eg 'rpc server port:drsuapi = 1027'
     307             :                  *
     308             :                  * If we have mulitiple endpoints on port 0, they each
     309             :                  * get an epemeral port (currently by walking up from
     310             :                  * 1024).
     311             :                  *
     312             :                  * Because one endpoint can only have one process
     313             :                  * model, we add a new IP_TCP endpoint for each model.
     314             :                  *
     315             :                  * This works in conjunction with the forced overwrite
     316             :                  * of ep->use_single_process below.
     317             :                  */
     318        1718 :                 if (ep->use_single_process != use_single_process
     319          61 :                     && transport == NCACN_IP_TCP) {
     320           0 :                         add_ep = true;
     321             :                 }
     322             :         }
     323             : 
     324        3472 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) || add_ep) {
     325        1754 :                 ep = talloc_zero(dce_ctx, struct dcesrv_endpoint);
     326        1754 :                 if (!ep) {
     327           0 :                         return NT_STATUS_NO_MEMORY;
     328             :                 }
     329        1754 :                 ep->ep_description = dcerpc_binding_dup(ep, binding);
     330        1754 :                 if (transport == NCACN_NP && binding2 != NULL) {
     331         399 :                         ep->ep_2nd_description =
     332         399 :                                 dcerpc_binding_dup(ep, binding2);
     333             :                 }
     334        1754 :                 add_ep = true;
     335             : 
     336             :                 /* add mgmt interface */
     337        1754 :                 ifl = talloc_zero(ep, struct dcesrv_if_list);
     338        1754 :                 if (!ifl) {
     339           0 :                         TALLOC_FREE(ep);
     340           0 :                         return NT_STATUS_NO_MEMORY;
     341             :                 }
     342             : 
     343        1754 :                 ifl->iface = talloc_memdup(ifl,
     344             :                                            dcesrv_get_mgmt_interface(),
     345             :                                            sizeof(struct dcesrv_interface));
     346        1754 :                 if (ifl->iface == NULL) {
     347           0 :                         talloc_free(ep);
     348           0 :                         return NT_STATUS_NO_MEMORY;
     349             :                 }
     350             : 
     351        1754 :                 DLIST_ADD(ep->interface_list, ifl);
     352        1718 :         } else if (!NT_STATUS_IS_OK(status)) {
     353           0 :                 DBG_NOTICE("Failed to find endpoint: %s\n", nt_errstr(status));
     354           0 :                 return status;
     355             :         }
     356             : 
     357             :         /*
     358             :          * By default don't force into a single process, but if any
     359             :          * interface on this endpoint on this service uses handles
     360             :          * (most do), then we must force into single process mode
     361             :          *
     362             :          * By overwriting this each time a new interface is added to
     363             :          * this endpoint, we end up with the most restrictive setting.
     364             :          */
     365        3472 :         if (use_single_process) {
     366        3316 :                 ep->use_single_process = true;
     367             :         }
     368             : 
     369             :         /* talloc a new interface list element */
     370        3472 :         ifl = talloc_zero(ep, struct dcesrv_if_list);
     371        3472 :         if (!ifl) {
     372           0 :                 return NT_STATUS_NO_MEMORY;
     373             :         }
     374             : 
     375             :         /* copy the given interface struct to the one on the endpoints interface list */
     376        3472 :         ifl->iface = talloc_memdup(ifl,
     377             :                                    iface,
     378             :                                    sizeof(struct dcesrv_interface));
     379        3472 :         if (ifl->iface == NULL) {
     380           0 :                 talloc_free(ep);
     381           0 :                 return NT_STATUS_NO_MEMORY;
     382             :         }
     383             : 
     384             :         /* if we have a security descriptor given,
     385             :          * we should see if we can set it up on the endpoint
     386             :          */
     387        3472 :         if (sd != NULL) {
     388             :                 /* if there's currently no security descriptor given on the endpoint
     389             :                  * we try to set it
     390             :                  */
     391           0 :                 if (ep->sd == NULL) {
     392           0 :                         ep->sd = security_descriptor_copy(ep, sd);
     393             :                 }
     394             : 
     395             :                 /* if now there's no security descriptor given on the endpoint
     396             :                  * something goes wrong, either we failed to copy the security descriptor
     397             :                  * or there was already one on the endpoint
     398             :                  */
     399           0 :                 if (ep->sd != NULL) {
     400           0 :                         char *binding_string =
     401           0 :                                 dcerpc_binding_string(dce_ctx, binding);
     402           0 :                         DBG_ERR("Interface '%s' failed to setup a security "
     403             :                                 "descriptor on endpoint '%s'\n",
     404             :                                 iface->name, binding_string);
     405           0 :                         TALLOC_FREE(binding_string);
     406           0 :                         if (add_ep) free(ep);
     407           0 :                         free(ifl);
     408           0 :                         return NT_STATUS_OBJECT_NAME_COLLISION;
     409             :                 }
     410             :         }
     411             : 
     412             :         /* finally add the interface on the endpoint */
     413        3472 :         DLIST_ADD(ep->interface_list, ifl);
     414             : 
     415             :         /* if it's a new endpoint add it to the dcesrv_context */
     416        3472 :         if (add_ep) {
     417        1754 :                 DLIST_ADD(dce_ctx->endpoint_list, ep);
     418             :         }
     419             : 
     420             :         /* Re-get the string as we may have set a port */
     421        3472 :         ep_string = dcerpc_binding_string(dce_ctx, ep->ep_description);
     422             : 
     423        3472 :         if (use_single_process) {
     424        3316 :                 ep_process_string = "single process required";
     425             :         } else {
     426         156 :                 ep_process_string = "multi process compatible";
     427             :         }
     428             : 
     429        3472 :         DBG_INFO("Interface '%s' registered on endpoint '%s' (%s)\n",
     430             :                  iface->name, ep_string, ep_process_string);
     431        3472 :         TALLOC_FREE(ep_string);
     432             : 
     433        3472 :         return NT_STATUS_OK;
     434             : }
     435             : 
     436        9475 : static NTSTATUS dcesrv_session_info_session_key(struct dcesrv_auth *auth,
     437             :                                                 DATA_BLOB *session_key)
     438             : {
     439        9475 :         if (auth->session_info == NULL) {
     440           0 :                 return NT_STATUS_NO_USER_SESSION_KEY;
     441             :         }
     442             : 
     443        9475 :         if (auth->session_info->session_key.length == 0) {
     444           0 :                 return NT_STATUS_NO_USER_SESSION_KEY;
     445             :         }
     446             : 
     447        9475 :         *session_key = auth->session_info->session_key;
     448        9475 :         return NT_STATUS_OK;
     449             : }
     450             : 
     451        4464 : static NTSTATUS dcesrv_remote_session_key(struct dcesrv_auth *auth,
     452             :                                           DATA_BLOB *session_key)
     453             : {
     454        4464 :         if (auth->auth_type != DCERPC_AUTH_TYPE_NONE) {
     455           0 :                 return NT_STATUS_NO_USER_SESSION_KEY;
     456             :         }
     457             : 
     458        4464 :         return dcesrv_session_info_session_key(auth, session_key);
     459             : }
     460             : 
     461         113 : static NTSTATUS dcesrv_local_fixed_session_key(struct dcesrv_auth *auth,
     462             :                                                DATA_BLOB *session_key)
     463             : {
     464         113 :         return dcerpc_generic_session_key(session_key);
     465             : }
     466             : 
     467             : /*
     468             :  * Fetch the authentication session key if available.
     469             :  *
     470             :  * This is the key generated by a gensec authentication.
     471             :  *
     472             :  */
     473        5011 : _PUBLIC_ NTSTATUS dcesrv_auth_session_key(struct dcesrv_call_state *call,
     474             :                                           DATA_BLOB *session_key)
     475             : {
     476        5011 :         struct dcesrv_auth *auth = call->auth_state;
     477        5011 :         SMB_ASSERT(auth->auth_finished);
     478        5011 :         return dcesrv_session_info_session_key(auth, session_key);
     479             : }
     480             : 
     481             : /*
     482             :  * Fetch the transport session key if available.
     483             :  * Typically this is the SMB session key
     484             :  * or a fixed key for local transports.
     485             :  *
     486             :  * The key is always truncated to 16 bytes.
     487             : */
     488        4577 : _PUBLIC_ NTSTATUS dcesrv_transport_session_key(struct dcesrv_call_state *call,
     489             :                                                DATA_BLOB *session_key)
     490             : {
     491        4577 :         struct dcesrv_auth *auth = call->auth_state;
     492             :         NTSTATUS status;
     493             : 
     494        4577 :         SMB_ASSERT(auth->auth_finished);
     495             : 
     496        4577 :         if (auth->session_key_fn == NULL) {
     497           0 :                 return NT_STATUS_NO_USER_SESSION_KEY;
     498             :         }
     499             : 
     500        4577 :         status = auth->session_key_fn(auth, session_key);
     501        4577 :         if (!NT_STATUS_IS_OK(status)) {
     502           0 :                 return status;
     503             :         }
     504             : 
     505        4577 :         session_key->length = MIN(session_key->length, 16);
     506             : 
     507        4577 :         return NT_STATUS_OK;
     508             : }
     509             : 
     510       23488 : static struct dcesrv_auth *dcesrv_auth_create(struct dcesrv_connection *conn)
     511             : {
     512       23488 :         const struct dcesrv_endpoint *ep = conn->endpoint;
     513       19959 :         enum dcerpc_transport_t transport =
     514       23488 :                 dcerpc_binding_get_transport(ep->ep_description);
     515       23488 :         struct dcesrv_auth *auth = NULL;
     516             : 
     517       23488 :         auth = talloc_zero(conn, struct dcesrv_auth);
     518       23488 :         if (auth == NULL) {
     519           0 :                 return NULL;
     520             :         }
     521             : 
     522       23488 :         switch (transport) {
     523        6280 :         case NCACN_NP:
     524        6280 :                 auth->session_key_fn = dcesrv_remote_session_key;
     525        6280 :                 break;
     526        2271 :         case NCALRPC:
     527             :         case NCACN_UNIX_STREAM:
     528        2271 :                 auth->session_key_fn = dcesrv_local_fixed_session_key;
     529        2271 :                 break;
     530       14937 :         default:
     531             :                 /*
     532             :                  * All other's get a NULL pointer, which
     533             :                  * results in NT_STATUS_NO_USER_SESSION_KEY
     534             :                  */
     535       14937 :                 break;
     536             :         }
     537             : 
     538       23488 :         return auth;
     539             : }
     540             : 
     541             : /*
     542             :   connect to a dcerpc endpoint
     543             : */
     544       16975 : _PUBLIC_ NTSTATUS dcesrv_endpoint_connect(struct dcesrv_context *dce_ctx,
     545             :                                 TALLOC_CTX *mem_ctx,
     546             :                                 const struct dcesrv_endpoint *ep,
     547             :                                 struct auth_session_info *session_info,
     548             :                                 struct tevent_context *event_ctx,
     549             :                                 uint32_t state_flags,
     550             :                                 struct dcesrv_connection **_p)
     551             : {
     552       16975 :         struct dcesrv_auth *auth = NULL;
     553       16975 :         struct dcesrv_connection *p = NULL;
     554             : 
     555       16975 :         if (!session_info) {
     556           0 :                 return NT_STATUS_ACCESS_DENIED;
     557             :         }
     558             : 
     559       16975 :         p = talloc_zero(mem_ctx, struct dcesrv_connection);
     560       16975 :         if (p == NULL) {
     561           0 :                 goto nomem;
     562             :         }
     563             : 
     564       16975 :         p->dce_ctx = dce_ctx;
     565       16975 :         p->endpoint = ep;
     566       16975 :         p->packet_log_dir = lpcfg_parm_string(dce_ctx->lp_ctx,
     567             :                                               NULL,
     568             :                                               "dcesrv",
     569             :                                               "stubs directory");
     570       16975 :         p->event_ctx = event_ctx;
     571       16975 :         p->state_flags = state_flags;
     572       16975 :         p->allow_bind = true;
     573       16975 :         p->max_recv_frag = 5840;
     574       16975 :         p->max_xmit_frag = 5840;
     575       16975 :         p->max_total_request_size = DCERPC_NCACN_REQUEST_DEFAULT_MAX_SIZE;
     576             : 
     577       16975 :         p->support_hdr_signing = lpcfg_parm_bool(dce_ctx->lp_ctx,
     578             :                                                  NULL,
     579             :                                                  "dcesrv",
     580             :                                                  "header signing",
     581             :                                                  true);
     582       16975 :         p->max_auth_states = lpcfg_parm_ulong(dce_ctx->lp_ctx,
     583             :                                               NULL,
     584             :                                               "dcesrv",
     585             :                                               "max auth states",
     586             :                                               2049);
     587             : 
     588       16975 :         auth = dcesrv_auth_create(p);
     589       16975 :         if (auth == NULL) {
     590           0 :                 goto nomem;
     591             :         }
     592             : 
     593       16975 :         auth->session_info = talloc_reference(auth, session_info);
     594       16975 :         if (auth->session_info == NULL) {
     595           0 :                 goto nomem;
     596             :         }
     597             : 
     598       16975 :         p->default_auth_state = auth;
     599             : 
     600             :         /*
     601             :          * For now we only support NDR32.
     602             :          */
     603       16975 :         p->preferred_transfer = &ndr_transfer_syntax_ndr;
     604             : 
     605       16975 :         *_p = p;
     606       16975 :         return NT_STATUS_OK;
     607           0 : nomem:
     608           0 :         TALLOC_FREE(p);
     609           0 :         return NT_STATUS_NO_MEMORY;
     610             : }
     611             : 
     612             : /*
     613             :   move a call from an existing linked list to the specified list. This
     614             :   prevents bugs where we forget to remove the call from a previous
     615             :   list when moving it.
     616             :  */
     617      588697 : static void dcesrv_call_set_list(struct dcesrv_call_state *call,
     618             :                                  enum dcesrv_call_list list)
     619             : {
     620      588697 :         switch (call->list) {
     621      572975 :         case DCESRV_LIST_NONE:
     622      572975 :                 break;
     623           0 :         case DCESRV_LIST_CALL_LIST:
     624           0 :                 DLIST_REMOVE(call->conn->call_list, call);
     625           0 :                 break;
     626       15722 :         case DCESRV_LIST_FRAGMENTED_CALL_LIST:
     627       15722 :                 DLIST_REMOVE(call->conn->incoming_fragmented_call_list, call);
     628       15722 :                 break;
     629           0 :         case DCESRV_LIST_PENDING_CALL_LIST:
     630           0 :                 DLIST_REMOVE(call->conn->pending_call_list, call);
     631           0 :                 break;
     632             :         }
     633      588697 :         call->list = list;
     634      588697 :         switch (list) {
     635      391741 :         case DCESRV_LIST_NONE:
     636      391741 :                 break;
     637       22612 :         case DCESRV_LIST_CALL_LIST:
     638       22612 :                 DLIST_ADD_END(call->conn->call_list, call);
     639       22612 :                 break;
     640       15768 :         case DCESRV_LIST_FRAGMENTED_CALL_LIST:
     641       15768 :                 DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
     642       15768 :                 break;
     643      158576 :         case DCESRV_LIST_PENDING_CALL_LIST:
     644      158576 :                 DLIST_ADD_END(call->conn->pending_call_list, call);
     645      158576 :                 break;
     646             :         }
     647      588697 : }
     648             : 
     649         351 : static void dcesrv_call_disconnect_after(struct dcesrv_call_state *call,
     650             :                                          const char *reason)
     651             : {
     652         351 :         struct dcesrv_auth *a = NULL;
     653             : 
     654         351 :         if (call->conn->terminate != NULL) {
     655           0 :                 return;
     656             :         }
     657             : 
     658         351 :         call->conn->allow_bind = false;
     659         351 :         call->conn->allow_alter = false;
     660             : 
     661         351 :         call->conn->default_auth_state->auth_invalid = true;
     662             : 
     663         686 :         for (a = call->conn->auth_states; a != NULL; a = a->next) {
     664         335 :                 a->auth_invalid = true;
     665             :         }
     666             : 
     667         351 :         call->terminate_reason = talloc_strdup(call, reason);
     668         351 :         if (call->terminate_reason == NULL) {
     669           0 :                 call->terminate_reason = __location__;
     670             :         }
     671             : }
     672             : 
     673             : /*
     674             :   return a dcerpc bind_nak
     675             : */
     676          94 : static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32_t reason)
     677             : {
     678             :         struct ncacn_packet pkt;
     679             :         struct dcerpc_bind_nak_version version;
     680             :         struct data_blob_list_item *rep;
     681             :         NTSTATUS status;
     682             :         static const uint8_t _pad[3] = { 0, };
     683             : 
     684             :         /*
     685             :          * We add the call to the pending_call_list
     686             :          * in order to defer the termination.
     687             :          */
     688          94 :         dcesrv_call_disconnect_after(call, "dcesrv_bind_nak");
     689             : 
     690             :         /* setup a bind_nak */
     691          94 :         dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
     692          94 :         pkt.auth_length = 0;
     693          94 :         pkt.call_id = call->pkt.call_id;
     694          94 :         pkt.ptype = DCERPC_PKT_BIND_NAK;
     695          94 :         pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
     696          94 :         pkt.u.bind_nak.reject_reason = reason;
     697          94 :         version.rpc_vers = 5;
     698          94 :         version.rpc_vers_minor = 0;
     699          94 :         pkt.u.bind_nak.num_versions = 1;
     700          94 :         pkt.u.bind_nak.versions = &version;
     701          94 :         pkt.u.bind_nak._pad = data_blob_const(_pad, sizeof(_pad));
     702             : 
     703          94 :         rep = talloc_zero(call, struct data_blob_list_item);
     704          94 :         if (!rep) {
     705           0 :                 return NT_STATUS_NO_MEMORY;
     706             :         }
     707             : 
     708          94 :         status = dcerpc_ncacn_push_auth(&rep->blob, call, &pkt, NULL);
     709          94 :         if (!NT_STATUS_IS_OK(status)) {
     710           0 :                 return status;
     711             :         }
     712             : 
     713          94 :         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
     714             : 
     715          94 :         DLIST_ADD_END(call->replies, rep);
     716          94 :         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
     717             : 
     718          94 :         if (call->conn->call_list && call->conn->call_list->replies) {
     719          94 :                 if (call->conn->transport.report_output_data) {
     720          94 :                         call->conn->transport.report_output_data(call->conn);
     721             :                 }
     722             :         }
     723             : 
     724          94 :         return NT_STATUS_OK;
     725             : }
     726             : 
     727         257 : static NTSTATUS _dcesrv_fault_disconnect_flags(struct dcesrv_call_state *call,
     728             :                                                uint32_t fault_code,
     729             :                                                uint8_t extra_flags,
     730             :                                                const char *func,
     731             :                                                const char *location)
     732             : {
     733         257 :         const char *reason = NULL;
     734             : 
     735         257 :         reason = talloc_asprintf(call, "%s:%s: fault=%u (%s) flags=0x%x",
     736             :                                  func, location,
     737             :                                  fault_code,
     738             :                                  dcerpc_errstr(call, fault_code),
     739             :                                  extra_flags);
     740         257 :         if (reason == NULL) {
     741           0 :                 reason = location;
     742             :         }
     743             : 
     744             :         /*
     745             :          * We add the call to the pending_call_list
     746             :          * in order to defer the termination.
     747             :          */
     748             : 
     749         257 :         dcesrv_call_disconnect_after(call, reason);
     750             : 
     751         257 :         return dcesrv_fault_with_flags(call, fault_code, extra_flags);
     752             : }
     753             : 
     754             : #define dcesrv_fault_disconnect(call, fault_code) \
     755             :         _dcesrv_fault_disconnect_flags(call, fault_code, \
     756             :                 DCERPC_PFC_FLAG_DID_NOT_EXECUTE, \
     757             :                 __func__, __location__)
     758             : #define dcesrv_fault_disconnect0(call, fault_code) \
     759             :         _dcesrv_fault_disconnect_flags(call, fault_code, 0, \
     760             :                 __func__, __location__)
     761             : 
     762       18067 : static int dcesrv_connection_context_destructor(struct dcesrv_connection_context *c)
     763             : {
     764       18067 :         DLIST_REMOVE(c->conn->contexts, c);
     765             : 
     766       18067 :         if (c->iface && c->iface->unbind) {
     767       18063 :                 c->iface->unbind(c, c->iface);
     768       18063 :                 c->iface = NULL;
     769             :         }
     770             : 
     771       18067 :         return 0;
     772             : }
     773             : 
     774       16915 : static void dcesrv_prepare_context_auth(struct dcesrv_call_state *dce_call)
     775             : {
     776       16915 :         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
     777       16915 :         const struct dcesrv_endpoint *endpoint = dce_call->conn->endpoint;
     778       14105 :         enum dcerpc_transport_t transport =
     779       16915 :                 dcerpc_binding_get_transport(endpoint->ep_description);
     780       16915 :         struct dcesrv_connection_context *context = dce_call->context;
     781       16915 :         const struct dcesrv_interface *iface = context->iface;
     782             : 
     783       16915 :         context->min_auth_level = DCERPC_AUTH_LEVEL_NONE;
     784             : 
     785       16915 :         if (transport == NCALRPC) {
     786        1469 :                 context->allow_connect = true;
     787        1469 :                 return;
     788             :         }
     789             : 
     790             :         /*
     791             :          * allow overwrite per interface
     792             :          * allow dcerpc auth level connect:<interface>
     793             :          */
     794       15446 :         context->allow_connect = lpcfg_allow_dcerpc_auth_level_connect(lp_ctx);
     795       15446 :         context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
     796             :                                         "allow dcerpc auth level connect",
     797        2595 :                                         iface->name,
     798       15446 :                                         context->allow_connect);
     799             : }
     800             : 
     801        1458 : NTSTATUS dcesrv_interface_bind_require_integrity(struct dcesrv_connection_context *context,
     802             :                                                  const struct dcesrv_interface *iface)
     803             : {
     804             :         /*
     805             :          * For connection oriented DCERPC DCERPC_AUTH_LEVEL_PACKET (4)
     806             :          * has the same behavior as DCERPC_AUTH_LEVEL_INTEGRITY (5).
     807             :          */
     808        1458 :         context->min_auth_level = DCERPC_AUTH_LEVEL_PACKET;
     809        1458 :         return NT_STATUS_OK;
     810             : }
     811             : 
     812        2151 : NTSTATUS dcesrv_interface_bind_require_privacy(struct dcesrv_connection_context *context,
     813             :                                                const struct dcesrv_interface *iface)
     814             : {
     815        2151 :         context->min_auth_level = DCERPC_AUTH_LEVEL_PRIVACY;
     816        2151 :         return NT_STATUS_OK;
     817             : }
     818             : 
     819        6482 : _PUBLIC_ NTSTATUS dcesrv_interface_bind_reject_connect(struct dcesrv_connection_context *context,
     820             :                                                        const struct dcesrv_interface *iface)
     821             : {
     822        6482 :         struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
     823        6482 :         const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
     824        4993 :         enum dcerpc_transport_t transport =
     825        6482 :                 dcerpc_binding_get_transport(endpoint->ep_description);
     826             : 
     827        6482 :         if (transport == NCALRPC) {
     828         689 :                 context->allow_connect = true;
     829         689 :                 return NT_STATUS_OK;
     830             :         }
     831             : 
     832             :         /*
     833             :          * allow overwrite per interface
     834             :          * allow dcerpc auth level connect:<interface>
     835             :          */
     836        5793 :         context->allow_connect = false;
     837        7176 :         context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
     838             :                                         "allow dcerpc auth level connect",
     839        1383 :                                         iface->name,
     840        5793 :                                         context->allow_connect);
     841        5793 :         return NT_STATUS_OK;
     842             : }
     843             : 
     844        6394 : _PUBLIC_ NTSTATUS dcesrv_interface_bind_allow_connect(struct dcesrv_connection_context *context,
     845             :                                                       const struct dcesrv_interface *iface)
     846             : {
     847        6394 :         struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
     848        6394 :         const struct dcesrv_endpoint *endpoint = context->conn->endpoint;
     849        5539 :         enum dcerpc_transport_t transport =
     850        6394 :                 dcerpc_binding_get_transport(endpoint->ep_description);
     851             : 
     852        6394 :         if (transport == NCALRPC) {
     853         700 :                 context->allow_connect = true;
     854         700 :                 return NT_STATUS_OK;
     855             :         }
     856             : 
     857             :         /*
     858             :          * allow overwrite per interface
     859             :          * allow dcerpc auth level connect:<interface>
     860             :          */
     861        5694 :         context->allow_connect = true;
     862        6443 :         context->allow_connect = lpcfg_parm_bool(lp_ctx, NULL,
     863             :                                         "allow dcerpc auth level connect",
     864         749 :                                         iface->name,
     865        5694 :                                         context->allow_connect);
     866        5694 :         return NT_STATUS_OK;
     867             : }
     868             : 
     869             : struct dcesrv_conn_auth_wait_context {
     870             :         struct tevent_req *req;
     871             :         bool done;
     872             :         NTSTATUS status;
     873             : };
     874             : 
     875             : struct dcesrv_conn_auth_wait_state {
     876             :         uint8_t dummy;
     877             : };
     878             : 
     879       12508 : static struct tevent_req *dcesrv_conn_auth_wait_send(TALLOC_CTX *mem_ctx,
     880             :                                                      struct tevent_context *ev,
     881             :                                                      void *private_data)
     882             : {
     883       10816 :         struct dcesrv_conn_auth_wait_context *auth_wait =
     884        1692 :                 talloc_get_type_abort(private_data,
     885             :                 struct dcesrv_conn_auth_wait_context);
     886       12508 :         struct tevent_req *req = NULL;
     887       12508 :         struct dcesrv_conn_auth_wait_state *state = NULL;
     888             : 
     889       12508 :         req = tevent_req_create(mem_ctx, &state,
     890             :                                 struct dcesrv_conn_auth_wait_state);
     891       12508 :         if (req == NULL) {
     892           0 :                 return NULL;
     893             :         }
     894       12508 :         auth_wait->req = req;
     895             : 
     896       12508 :         tevent_req_defer_callback(req, ev);
     897             : 
     898       12508 :         if (!auth_wait->done) {
     899       12508 :                 return req;
     900             :         }
     901             : 
     902           0 :         if (tevent_req_nterror(req, auth_wait->status)) {
     903           0 :                 return tevent_req_post(req, ev);
     904             :         }
     905             : 
     906           0 :         tevent_req_done(req);
     907           0 :         return tevent_req_post(req, ev);
     908             : }
     909             : 
     910       12508 : static NTSTATUS dcesrv_conn_auth_wait_recv(struct tevent_req *req)
     911             : {
     912       12508 :         return tevent_req_simple_recv_ntstatus(req);
     913             : }
     914             : 
     915       12508 : static NTSTATUS dcesrv_conn_auth_wait_setup(struct dcesrv_connection *conn)
     916             : {
     917       12508 :         struct dcesrv_conn_auth_wait_context *auth_wait = NULL;
     918             : 
     919       12508 :         if (conn->wait_send != NULL) {
     920           0 :                 return NT_STATUS_INTERNAL_ERROR;
     921             :         }
     922             : 
     923       12508 :         auth_wait = talloc_zero(conn, struct dcesrv_conn_auth_wait_context);
     924       12508 :         if (auth_wait == NULL) {
     925           0 :                 return NT_STATUS_NO_MEMORY;
     926             :         }
     927             : 
     928       12508 :         conn->wait_private = auth_wait;
     929       12508 :         conn->wait_send = dcesrv_conn_auth_wait_send;
     930       12508 :         conn->wait_recv = dcesrv_conn_auth_wait_recv;
     931       12508 :         return NT_STATUS_OK;
     932             : }
     933             : 
     934       12508 : static void dcesrv_conn_auth_wait_finished(struct dcesrv_connection *conn,
     935             :                                            NTSTATUS status)
     936             : {
     937       10816 :         struct dcesrv_conn_auth_wait_context *auth_wait =
     938       12508 :                 talloc_get_type_abort(conn->wait_private,
     939             :                 struct dcesrv_conn_auth_wait_context);
     940             : 
     941       12508 :         auth_wait->done = true;
     942       12508 :         auth_wait->status = status;
     943             : 
     944       12508 :         if (auth_wait->req == NULL) {
     945           0 :                 return;
     946             :         }
     947             : 
     948       12508 :         if (tevent_req_nterror(auth_wait->req, status)) {
     949           0 :                 return;
     950             :         }
     951             : 
     952       12508 :         tevent_req_done(auth_wait->req);
     953             : }
     954             : 
     955             : static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call);
     956             : 
     957             : static void dcesrv_bind_done(struct tevent_req *subreq);
     958             : 
     959             : /*
     960             :   handle a bind request
     961             : */
     962       16952 : static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
     963             : {
     964       16952 :         struct dcesrv_connection *conn = call->conn;
     965       16952 :         struct dcesrv_context *dce_ctx = conn->dce_ctx;
     966       16952 :         struct ncacn_packet *pkt = &call->ack_pkt;
     967             :         NTSTATUS status;
     968       16952 :         uint32_t extra_flags = 0;
     969       16952 :         uint16_t max_req = 0;
     970       16952 :         uint16_t max_rep = 0;
     971       16952 :         struct dcerpc_binding *ep_2nd_description = NULL;
     972       16952 :         const char *endpoint = NULL;
     973       16952 :         struct dcesrv_auth *auth = call->auth_state;
     974       16952 :         struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
     975       16952 :         struct dcerpc_ack_ctx *ack_ctx_list = NULL;
     976       16952 :         struct dcerpc_ack_ctx *ack_features = NULL;
     977       16952 :         struct tevent_req *subreq = NULL;
     978             :         size_t i;
     979             : 
     980       16952 :         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
     981             :                         DCERPC_PKT_BIND,
     982             :                         call->pkt.u.bind.auth_info.length,
     983             :                         0, /* required flags */
     984             :                         DCERPC_PFC_FLAG_FIRST |
     985             :                         DCERPC_PFC_FLAG_LAST |
     986             :                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
     987             :                         0x08 | /* this is not defined, but should be ignored */
     988             :                         DCERPC_PFC_FLAG_CONC_MPX |
     989             :                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
     990             :                         DCERPC_PFC_FLAG_MAYBE |
     991             :                         DCERPC_PFC_FLAG_OBJECT_UUID);
     992       16952 :         if (!NT_STATUS_IS_OK(status)) {
     993           3 :                 return dcesrv_bind_nak(call,
     994             :                         DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED);
     995             :         }
     996             : 
     997             :         /* max_recv_frag and max_xmit_frag result always in the same value! */
     998       16949 :         max_req = MIN(call->pkt.u.bind.max_xmit_frag,
     999             :                       call->pkt.u.bind.max_recv_frag);
    1000             :         /*
    1001             :          * The values are between 2048 and 5840 tested against Windows 2012R2
    1002             :          * via ncacn_ip_tcp on port 135.
    1003             :          */
    1004       16949 :         max_req = MAX(2048, max_req);
    1005       16949 :         max_rep = MIN(max_req, conn->max_recv_frag);
    1006             :         /* They are truncated to an 8 byte boundary. */
    1007       16949 :         max_rep &= 0xFFF8;
    1008             : 
    1009             :         /* max_recv_frag and max_xmit_frag result always in the same value! */
    1010       16949 :         conn->max_recv_frag = max_rep;
    1011       16949 :         conn->max_xmit_frag = max_rep;
    1012             : 
    1013       31080 :         status = dce_ctx->callbacks->assoc_group.find(
    1014       16949 :                 call, dce_ctx->callbacks->assoc_group.private_data);
    1015       16949 :         if (!NT_STATUS_IS_OK(status)) {
    1016          25 :                 DBG_NOTICE("Failed to find assoc_group 0x%08x: %s\n",
    1017             :                            call->pkt.u.bind.assoc_group_id, nt_errstr(status));
    1018          25 :                 return dcesrv_bind_nak(call, 0);
    1019             :         }
    1020             : 
    1021       16924 :         if (call->pkt.u.bind.num_contexts < 1) {
    1022           6 :                 return dcesrv_bind_nak(call, 0);
    1023             :         }
    1024             : 
    1025       16918 :         ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
    1026             :                                          call->pkt.u.bind.num_contexts);
    1027       16918 :         if (ack_ctx_list == NULL) {
    1028           0 :                 return dcesrv_bind_nak(call, 0);
    1029             :         }
    1030             : 
    1031             :         /*
    1032             :          * Set some sane defaults (required by dcesrv_negotiate_contexts()/
    1033             :          * dcesrv_check_or_create_context()) and do some protocol validation
    1034             :          * and set sane defaults.
    1035             :          */
    1036       48292 :         for (i = 0; i < call->pkt.u.bind.num_contexts; i++) {
    1037       31380 :                 const struct dcerpc_ctx_list *c = &call->pkt.u.bind.ctx_list[i];
    1038       31380 :                 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
    1039       31380 :                 bool is_feature = false;
    1040       31380 :                 uint64_t features = 0;
    1041             : 
    1042       31380 :                 if (c->num_transfer_syntaxes == 0) {
    1043           8 :                         return dcesrv_bind_nak(call, 0);
    1044             :                 }
    1045             : 
    1046       31377 :                 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
    1047       31377 :                 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
    1048             : 
    1049             :                 /*
    1050             :                  * It's only treated as bind time feature request, if the first
    1051             :                  * transfer_syntax matches, all others are ignored.
    1052             :                  */
    1053       31377 :                 is_feature = dcerpc_extract_bind_time_features(c->transfer_syntaxes[0],
    1054             :                                                                &features);
    1055       31377 :                 if (!is_feature) {
    1056       16897 :                         continue;
    1057             :                 }
    1058             : 
    1059       14480 :                 if (ack_features != NULL) {
    1060             :                         /*
    1061             :                          * Only one bind time feature context is allowed.
    1062             :                          */
    1063           3 :                         return dcesrv_bind_nak(call, 0);
    1064             :                 }
    1065       14477 :                 ack_features = a;
    1066             : 
    1067       14477 :                 a->result = DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK;
    1068       14477 :                 a->reason.negotiate = 0;
    1069       14477 :                 if (features & DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING) {
    1070       14462 :                         if (conn->max_auth_states != 0) {
    1071       13112 :                                 a->reason.negotiate |=
    1072             :                                 DCERPC_BIND_TIME_SECURITY_CONTEXT_MULTIPLEXING;
    1073             :                         }
    1074             :                 }
    1075       14477 :                 if (features & DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN) {
    1076       14468 :                         a->reason.negotiate |=
    1077             :                                 DCERPC_BIND_TIME_KEEP_CONNECTION_ON_ORPHAN;
    1078             :                 }
    1079             : 
    1080       14477 :                 conn->assoc_group->bind_time_features = a->reason.negotiate;
    1081             :         }
    1082             : 
    1083             :         /*
    1084             :          * Try to negotiate one new presentation context.
    1085             :          *
    1086             :          * Deep in here we locate the iface (by uuid) that the client
    1087             :          * requested, from the list of interfaces on the
    1088             :          * call->conn->endpoint, and call iface->bind() on that iface.
    1089             :          *
    1090             :          * call->conn was set up at the accept() of the socket, and
    1091             :          * call->conn->endpoint has a list of interfaces restricted to
    1092             :          * this port or pipe.
    1093             :          */
    1094       16912 :         status = dcesrv_negotiate_contexts(call, &call->pkt.u.bind, ack_ctx_list);
    1095       16912 :         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
    1096           0 :                 return dcesrv_bind_nak(call, 0);
    1097             :         }
    1098       16912 :         if (!NT_STATUS_IS_OK(status)) {
    1099           0 :                 return status;
    1100             :         }
    1101             : 
    1102             :         /*
    1103             :          * At this point we still don't know which interface (eg
    1104             :          * netlogon, lsa, drsuapi) the caller requested in this bind!
    1105             :          * The most recently added context is available as the first
    1106             :          * element in the linked list at call->conn->contexts, that is
    1107             :          * call->conn->contexts->iface, but they may not have
    1108             :          * requested one at all!
    1109             :          */
    1110             : 
    1111       16989 :         if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
    1112         111 :             (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
    1113         111 :                 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
    1114         111 :                 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
    1115             :         }
    1116             : 
    1117       16912 :         if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
    1118           0 :                 conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
    1119             :         }
    1120             : 
    1121             :         /*
    1122             :          * After finding the interface and setting up the NDR
    1123             :          * transport negotiation etc, handle any authentication that
    1124             :          * is being requested.
    1125             :          */
    1126       16912 :         if (!dcesrv_auth_bind(call)) {
    1127             : 
    1128          45 :                 if (auth->auth_level == DCERPC_AUTH_LEVEL_NONE) {
    1129             :                         /*
    1130             :                          * With DCERPC_AUTH_LEVEL_NONE, we get the
    1131             :                          * reject_reason in auth->auth_context_id.
    1132             :                          */
    1133          45 :                         return dcesrv_bind_nak(call, auth->auth_context_id);
    1134             :                 }
    1135             : 
    1136             :                 /*
    1137             :                  * This must a be a temporary failure e.g. talloc or invalid
    1138             :                  * configuration, e.g. no machine account.
    1139             :                  */
    1140           0 :                 return dcesrv_bind_nak(call,
    1141             :                                 DCERPC_BIND_NAK_REASON_TEMPORARY_CONGESTION);
    1142             :         }
    1143             : 
    1144             :         /* setup a bind_ack */
    1145       16867 :         dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(dce_ctx->lp_ctx));
    1146       16867 :         pkt->auth_length = 0;
    1147       16867 :         pkt->call_id = call->pkt.call_id;
    1148       16867 :         pkt->ptype = DCERPC_PKT_BIND_ACK;
    1149       16867 :         pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
    1150       16867 :         pkt->u.bind_ack.max_xmit_frag = conn->max_xmit_frag;
    1151       16867 :         pkt->u.bind_ack.max_recv_frag = conn->max_recv_frag;
    1152       16867 :         pkt->u.bind_ack.assoc_group_id = conn->assoc_group->id;
    1153             : 
    1154       16867 :         ep_2nd_description = conn->endpoint->ep_2nd_description;
    1155       16867 :         if (ep_2nd_description == NULL) {
    1156       13905 :                 ep_2nd_description = conn->endpoint->ep_description;
    1157             :         }
    1158             : 
    1159       16867 :         endpoint = dcerpc_binding_get_string_option(
    1160             :                                 ep_2nd_description,
    1161             :                                 "endpoint");
    1162       16867 :         if (endpoint == NULL) {
    1163           0 :                 endpoint = "";
    1164             :         }
    1165             : 
    1166       16867 :         pkt->u.bind_ack.secondary_address = endpoint;
    1167       16867 :         pkt->u.bind_ack.num_results = call->pkt.u.bind.num_contexts;
    1168       16867 :         pkt->u.bind_ack.ctx_list = ack_ctx_list;
    1169       16867 :         pkt->u.bind_ack.auth_info = data_blob_null;
    1170             : 
    1171       16867 :         status = dcesrv_auth_prepare_bind_ack(call, pkt);
    1172       16867 :         if (!NT_STATUS_IS_OK(status)) {
    1173           0 :                 return dcesrv_bind_nak(call, 0);
    1174             :         }
    1175             : 
    1176       16867 :         if (auth->auth_finished) {
    1177       10010 :                 return dcesrv_auth_reply(call);
    1178             :         }
    1179             : 
    1180        6857 :         cb->auth.become_root();
    1181        6857 :         subreq = gensec_update_send(call, call->event_ctx,
    1182             :                                     auth->gensec_security,
    1183             :                                     call->in_auth_info.credentials);
    1184        6857 :         cb->auth.unbecome_root();
    1185        6857 :         if (subreq == NULL) {
    1186           0 :                 return NT_STATUS_NO_MEMORY;
    1187             :         }
    1188        6857 :         tevent_req_set_callback(subreq, dcesrv_bind_done, call);
    1189             : 
    1190        6857 :         return dcesrv_conn_auth_wait_setup(conn);
    1191             : }
    1192             : 
    1193        6857 : static void dcesrv_bind_done(struct tevent_req *subreq)
    1194             : {
    1195        5926 :         struct dcesrv_call_state *call =
    1196        6857 :                 tevent_req_callback_data(subreq,
    1197             :                 struct dcesrv_call_state);
    1198        6857 :         struct dcesrv_connection *conn = call->conn;
    1199        6857 :         struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
    1200             :         NTSTATUS status;
    1201             : 
    1202        6857 :         cb->auth.become_root();
    1203        6857 :         status = gensec_update_recv(subreq, call,
    1204        6857 :                                     &call->out_auth_info->credentials);
    1205        6857 :         cb->auth.unbecome_root();
    1206        6857 :         TALLOC_FREE(subreq);
    1207             : 
    1208        6857 :         status = dcesrv_auth_complete(call, status);
    1209        6857 :         if (!NT_STATUS_IS_OK(status)) {
    1210           6 :                 status = dcesrv_bind_nak(call, 0);
    1211           6 :                 dcesrv_conn_auth_wait_finished(conn, status);
    1212           6 :                 return;
    1213             :         }
    1214             : 
    1215        6851 :         status = dcesrv_auth_reply(call);
    1216        6851 :         dcesrv_conn_auth_wait_finished(conn, status);
    1217        6851 :         return;
    1218             : }
    1219             : 
    1220       22518 : static NTSTATUS dcesrv_auth_reply(struct dcesrv_call_state *call)
    1221             : {
    1222       22518 :         struct ncacn_packet *pkt = &call->ack_pkt;
    1223       22518 :         struct data_blob_list_item *rep = NULL;
    1224             :         NTSTATUS status;
    1225             : 
    1226       22518 :         rep = talloc_zero(call, struct data_blob_list_item);
    1227       22518 :         if (!rep) {
    1228           0 :                 return NT_STATUS_NO_MEMORY;
    1229             :         }
    1230             : 
    1231       22518 :         status = dcerpc_ncacn_push_auth(&rep->blob,
    1232             :                                         call,
    1233             :                                         pkt,
    1234             :                                         call->out_auth_info);
    1235       22518 :         if (!NT_STATUS_IS_OK(status)) {
    1236           0 :                 return status;
    1237             :         }
    1238             : 
    1239       22518 :         dcerpc_set_frag_length(&rep->blob, rep->blob.length);
    1240             : 
    1241       22518 :         DLIST_ADD_END(call->replies, rep);
    1242       22518 :         dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
    1243             : 
    1244       22518 :         if (call->conn->call_list && call->conn->call_list->replies) {
    1245       22518 :                 if (call->conn->transport.report_output_data) {
    1246       22518 :                         call->conn->transport.report_output_data(call->conn);
    1247             :                 }
    1248             :         }
    1249             : 
    1250       22518 :         return NT_STATUS_OK;
    1251             : }
    1252             : 
    1253             : 
    1254             : static void dcesrv_auth3_done(struct tevent_req *subreq);
    1255             : 
    1256             : /*
    1257             :   handle a auth3 request
    1258             : */
    1259         135 : static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call)
    1260             : {
    1261         135 :         struct dcesrv_connection *conn = call->conn;
    1262         135 :         struct dcesrv_auth *auth = call->auth_state;
    1263         135 :         struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
    1264         135 :         struct tevent_req *subreq = NULL;
    1265             :         NTSTATUS status;
    1266             : 
    1267         135 :         if (!auth->auth_started) {
    1268           0 :                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
    1269             :         }
    1270             : 
    1271         135 :         if (auth->auth_finished) {
    1272           3 :                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
    1273             :         }
    1274             : 
    1275         132 :         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
    1276             :                         DCERPC_PKT_AUTH3,
    1277             :                         call->pkt.u.auth3.auth_info.length,
    1278             :                         0, /* required flags */
    1279             :                         DCERPC_PFC_FLAG_FIRST |
    1280             :                         DCERPC_PFC_FLAG_LAST |
    1281             :                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
    1282             :                         0x08 | /* this is not defined, but should be ignored */
    1283             :                         DCERPC_PFC_FLAG_CONC_MPX |
    1284             :                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
    1285             :                         DCERPC_PFC_FLAG_MAYBE |
    1286             :                         DCERPC_PFC_FLAG_OBJECT_UUID);
    1287         132 :         if (!NT_STATUS_IS_OK(status)) {
    1288           0 :                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
    1289             :         }
    1290             : 
    1291             :         /* handle the auth3 in the auth code */
    1292         132 :         if (!dcesrv_auth_prepare_auth3(call)) {
    1293             :                 /*
    1294             :                  * we don't send a reply to a auth3 request,
    1295             :                  * except by a fault.
    1296             :                  *
    1297             :                  * In anycase we mark the connection as
    1298             :                  * invalid.
    1299             :                  */
    1300           3 :                 auth->auth_invalid = true;
    1301           3 :                 if (call->fault_code != 0) {
    1302           3 :                         return dcesrv_fault_disconnect(call, call->fault_code);
    1303             :                 }
    1304           0 :                 TALLOC_FREE(call);
    1305           0 :                 return NT_STATUS_OK;
    1306             :         }
    1307             : 
    1308         129 :         cb->auth.become_root();
    1309         129 :         subreq = gensec_update_send(call, call->event_ctx,
    1310             :                                     auth->gensec_security,
    1311             :                                     call->in_auth_info.credentials);
    1312         129 :         cb->auth.unbecome_root();
    1313         129 :         if (subreq == NULL) {
    1314           0 :                 return NT_STATUS_NO_MEMORY;
    1315             :         }
    1316         129 :         tevent_req_set_callback(subreq, dcesrv_auth3_done, call);
    1317             : 
    1318         129 :         return dcesrv_conn_auth_wait_setup(conn);
    1319             : }
    1320             : 
    1321         129 : static void dcesrv_auth3_done(struct tevent_req *subreq)
    1322             : {
    1323          83 :         struct dcesrv_call_state *call =
    1324         129 :                 tevent_req_callback_data(subreq,
    1325             :                 struct dcesrv_call_state);
    1326         129 :         struct dcesrv_connection *conn = call->conn;
    1327         129 :         struct dcesrv_auth *auth = call->auth_state;
    1328         129 :         struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
    1329             :         NTSTATUS status;
    1330             : 
    1331         129 :         cb->auth.become_root();
    1332         129 :         status = gensec_update_recv(subreq, call,
    1333         129 :                                     &call->out_auth_info->credentials);
    1334         129 :         cb->auth.unbecome_root();
    1335         129 :         TALLOC_FREE(subreq);
    1336             : 
    1337         129 :         status = dcesrv_auth_complete(call, status);
    1338         129 :         if (!NT_STATUS_IS_OK(status)) {
    1339             :                 /*
    1340             :                  * we don't send a reply to a auth3 request,
    1341             :                  * except by a fault.
    1342             :                  *
    1343             :                  * In anycase we mark the connection as
    1344             :                  * invalid.
    1345             :                  */
    1346           3 :                 auth->auth_invalid = true;
    1347           3 :                 if (call->fault_code != 0) {
    1348           0 :                         status = dcesrv_fault_disconnect(call, call->fault_code);
    1349           0 :                         dcesrv_conn_auth_wait_finished(conn, status);
    1350           0 :                         return;
    1351             :                 }
    1352           3 :                 TALLOC_FREE(call);
    1353           3 :                 dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
    1354           3 :                 return;
    1355             :         }
    1356             : 
    1357             :         /*
    1358             :          * we don't send a reply to a auth3 request.
    1359             :          */
    1360         126 :         TALLOC_FREE(call);
    1361         126 :         dcesrv_conn_auth_wait_finished(conn, NT_STATUS_OK);
    1362         126 :         return;
    1363             : }
    1364             : 
    1365             : 
    1366       37070 : static NTSTATUS dcesrv_check_or_create_context(struct dcesrv_call_state *call,
    1367             :                                 const struct dcerpc_bind *b,
    1368             :                                 const struct dcerpc_ctx_list *ctx,
    1369             :                                 struct dcerpc_ack_ctx *ack,
    1370             :                                 bool validate_only,
    1371             :                                 const struct ndr_syntax_id *supported_transfer)
    1372             : {
    1373             :         struct dcesrv_connection_context *context;
    1374             :         const struct dcesrv_interface *iface;
    1375             :         NTSTATUS status;
    1376       37070 :         const struct ndr_syntax_id *selected_transfer = NULL;
    1377             :         size_t i;
    1378             :         bool ok;
    1379             : 
    1380       37070 :         if (b == NULL) {
    1381           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1382             :         }
    1383       37070 :         if (ctx == NULL) {
    1384           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1385             :         }
    1386       37070 :         if (ctx->num_transfer_syntaxes < 1) {
    1387           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1388             :         }
    1389       37070 :         if (ack == NULL) {
    1390           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1391             :         }
    1392       37070 :         if (supported_transfer == NULL) {
    1393           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1394             :         }
    1395             : 
    1396       37070 :         switch (ack->result) {
    1397       14474 :         case DCERPC_BIND_ACK_RESULT_ACCEPTANCE:
    1398             :         case DCERPC_BIND_ACK_RESULT_NEGOTIATE_ACK:
    1399             :                 /*
    1400             :                  * We is already completed.
    1401             :                  */
    1402       14474 :                 return NT_STATUS_OK;
    1403       22596 :         default:
    1404       22596 :                 break;
    1405             :         }
    1406             : 
    1407       22596 :         ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
    1408       22596 :         ack->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
    1409             : 
    1410       41626 :         iface = find_interface_by_syntax_id(
    1411       22596 :                 call->conn->endpoint, &ctx->abstract_syntax);
    1412       22596 :         if (iface == NULL) {
    1413             :                 struct ndr_syntax_id_buf buf;
    1414          21 :                 DBG_NOTICE("Request for unknown dcerpc interface %s\n",
    1415             :                            ndr_syntax_id_buf_string(
    1416             :                                    &ctx->abstract_syntax, &buf));
    1417             :                 /*
    1418             :                  * We report this only via ack->result
    1419             :                  */
    1420          21 :                 return NT_STATUS_OK;
    1421             :         }
    1422             : 
    1423       22575 :         ack->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
    1424       22575 :         ack->reason.value = DCERPC_BIND_ACK_REASON_TRANSFER_SYNTAXES_NOT_SUPPORTED;
    1425             : 
    1426       22575 :         if (validate_only) {
    1427             :                 /*
    1428             :                  * We report this only via ack->result
    1429             :                  */
    1430          15 :                 return NT_STATUS_OK;
    1431             :         }
    1432             : 
    1433       22593 :         for (i = 0; i < ctx->num_transfer_syntaxes; i++) {
    1434             :                 /*
    1435             :                  * we only do NDR encoded dcerpc for now.
    1436             :                  */
    1437       22587 :                 ok = ndr_syntax_id_equal(&ctx->transfer_syntaxes[i],
    1438             :                                          supported_transfer);
    1439       22587 :                 if (ok) {
    1440       22554 :                         selected_transfer = supported_transfer;
    1441       22554 :                         break;
    1442             :                 }
    1443             :         }
    1444             : 
    1445       22560 :         context = dcesrv_find_context(call->conn, ctx->context_id);
    1446       22560 :         if (context != NULL) {
    1447        5645 :                 ok = ndr_syntax_id_equal(&context->iface->syntax_id,
    1448             :                                          &ctx->abstract_syntax);
    1449        5645 :                 if (!ok) {
    1450           9 :                         return NT_STATUS_RPC_PROTOCOL_ERROR;
    1451             :                 }
    1452             : 
    1453        5636 :                 if (selected_transfer != NULL) {
    1454        5630 :                         ok = ndr_syntax_id_equal(&context->transfer_syntax,
    1455             :                                                  selected_transfer);
    1456        5630 :                         if (!ok) {
    1457           0 :                                 return NT_STATUS_RPC_PROTOCOL_ERROR;
    1458             :                         }
    1459             : 
    1460        5630 :                         ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
    1461        5630 :                         ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
    1462        5630 :                         ack->syntax = context->transfer_syntax;
    1463             :                 }
    1464             : 
    1465             :                 /*
    1466             :                  * We report this only via ack->result
    1467             :                  */
    1468        5636 :                 return NT_STATUS_OK;
    1469             :         }
    1470             : 
    1471       16915 :         if (selected_transfer == NULL) {
    1472             :                 /*
    1473             :                  * We report this only via ack->result
    1474             :                  */
    1475           0 :                 return NT_STATUS_OK;
    1476             :         }
    1477             : 
    1478       16915 :         ack->result = DCERPC_BIND_ACK_RESULT_USER_REJECTION;
    1479       16915 :         ack->reason.value = DCERPC_BIND_ACK_REASON_LOCAL_LIMIT_EXCEEDED;
    1480             : 
    1481             :         /* add this context to the list of available context_ids */
    1482       16915 :         context = talloc_zero(call->conn, struct dcesrv_connection_context);
    1483       16915 :         if (context == NULL) {
    1484           0 :                 return NT_STATUS_NO_MEMORY;
    1485             :         }
    1486       16915 :         context->conn = call->conn;
    1487       16915 :         context->context_id = ctx->context_id;
    1488       16915 :         context->iface = iface;
    1489       16915 :         context->transfer_syntax = *selected_transfer;
    1490       16915 :         DLIST_ADD(call->conn->contexts, context);
    1491       16915 :         call->context = context;
    1492       16915 :         talloc_set_destructor(context, dcesrv_connection_context_destructor);
    1493             : 
    1494       16915 :         dcesrv_prepare_context_auth(call);
    1495             : 
    1496             :         /*
    1497             :          * Multiplex is supported by default
    1498             :          */
    1499       16915 :         call->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
    1500             : 
    1501       16915 :         status = iface->bind(context, iface);
    1502       16915 :         call->context = NULL;
    1503       16915 :         if (!NT_STATUS_IS_OK(status)) {
    1504             :                 /* we don't want to trigger the iface->unbind() hook */
    1505           0 :                 context->iface = NULL;
    1506           0 :                 talloc_free(context);
    1507             :                 /*
    1508             :                  * We report this only via ack->result
    1509             :                  */
    1510           0 :                 return NT_STATUS_OK;
    1511             :         }
    1512             : 
    1513       16915 :         ack->result = DCERPC_BIND_ACK_RESULT_ACCEPTANCE;
    1514       16915 :         ack->reason.value = DCERPC_BIND_ACK_REASON_NOT_SPECIFIED;
    1515       16915 :         ack->syntax = context->transfer_syntax;
    1516       16915 :         return NT_STATUS_OK;
    1517             : }
    1518             : 
    1519       22596 : static NTSTATUS dcesrv_negotiate_contexts(struct dcesrv_call_state *call,
    1520             :                                 const struct dcerpc_bind *b,
    1521             :                                 struct dcerpc_ack_ctx *ack_ctx_list)
    1522             : {
    1523             :         NTSTATUS status;
    1524             :         size_t i;
    1525       22596 :         bool validate_only = false;
    1526             :         bool preferred_ndr32;
    1527             : 
    1528             :         /*
    1529             :          * Try to negotiate one new presentation context,
    1530             :          * using our preferred transfer syntax.
    1531             :          */
    1532       59657 :         for (i = 0; i < b->num_contexts; i++) {
    1533       37070 :                 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
    1534       37070 :                 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
    1535             : 
    1536       37070 :                 status = dcesrv_check_or_create_context(call, b, c, a,
    1537             :                                                 validate_only,
    1538       37070 :                                                 call->conn->preferred_transfer);
    1539       37070 :                 if (!NT_STATUS_IS_OK(status)) {
    1540           9 :                         return status;
    1541             :                 }
    1542             : 
    1543       37061 :                 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
    1544             :                         /*
    1545             :                          * We managed to negotiate one context.
    1546             :                          *
    1547             :                          * => we're done.
    1548             :                          */
    1549       22545 :                         validate_only = true;
    1550             :                 }
    1551             :         }
    1552             : 
    1553       22587 :         preferred_ndr32 = ndr_syntax_id_equal(&ndr_transfer_syntax_ndr,
    1554       22587 :                                         call->conn->preferred_transfer);
    1555       22587 :         if (preferred_ndr32) {
    1556             :                 /*
    1557             :                  * We're done.
    1558             :                  */
    1559       22587 :                 return NT_STATUS_OK;
    1560             :         }
    1561             : 
    1562             :         /*
    1563             :          * Try to negotiate one new presentation context,
    1564             :          * using NDR 32 as fallback.
    1565             :          */
    1566           0 :         for (i = 0; i < b->num_contexts; i++) {
    1567           0 :                 const struct dcerpc_ctx_list *c = &b->ctx_list[i];
    1568           0 :                 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
    1569             : 
    1570           0 :                 status = dcesrv_check_or_create_context(call, b, c, a,
    1571             :                                                 validate_only,
    1572             :                                                 &ndr_transfer_syntax_ndr);
    1573           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1574           0 :                         return status;
    1575             :                 }
    1576             : 
    1577           0 :                 if (a->result == DCERPC_BIND_ACK_RESULT_ACCEPTANCE) {
    1578             :                         /*
    1579             :                          * We managed to negotiate one context.
    1580             :                          *
    1581             :                          * => we're done.
    1582             :                          */
    1583           0 :                         validate_only = true;
    1584             :                 }
    1585             :         }
    1586             : 
    1587           0 :         return NT_STATUS_OK;
    1588             : }
    1589             : 
    1590             : static void dcesrv_alter_done(struct tevent_req *subreq);
    1591             : 
    1592             : /*
    1593             :   handle a alter context request
    1594             : */
    1595        5699 : static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call)
    1596             : {
    1597        5699 :         struct dcesrv_connection *conn = call->conn;
    1598             :         NTSTATUS status;
    1599        5699 :         bool auth_ok = false;
    1600        5699 :         struct ncacn_packet *pkt = &call->ack_pkt;
    1601        5699 :         uint32_t extra_flags = 0;
    1602        5699 :         struct dcesrv_auth *auth = call->auth_state;
    1603        5699 :         struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
    1604        5699 :         struct dcerpc_ack_ctx *ack_ctx_list = NULL;
    1605        5699 :         struct tevent_req *subreq = NULL;
    1606             :         size_t i;
    1607             : 
    1608        5699 :         if (!call->conn->allow_alter) {
    1609           0 :                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
    1610             :         }
    1611             : 
    1612        5699 :         status = dcerpc_verify_ncacn_packet_header(&call->pkt,
    1613             :                         DCERPC_PKT_ALTER,
    1614             :                         call->pkt.u.alter.auth_info.length,
    1615             :                         0, /* required flags */
    1616             :                         DCERPC_PFC_FLAG_FIRST |
    1617             :                         DCERPC_PFC_FLAG_LAST |
    1618             :                         DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN |
    1619             :                         0x08 | /* this is not defined, but should be ignored */
    1620             :                         DCERPC_PFC_FLAG_CONC_MPX |
    1621             :                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
    1622             :                         DCERPC_PFC_FLAG_MAYBE |
    1623             :                         DCERPC_PFC_FLAG_OBJECT_UUID);
    1624        5699 :         if (!NT_STATUS_IS_OK(status)) {
    1625           0 :                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
    1626             :         }
    1627             : 
    1628        5699 :         auth_ok = dcesrv_auth_alter(call);
    1629        5699 :         if (!auth_ok) {
    1630          24 :                 if (call->fault_code != 0) {
    1631           9 :                         return dcesrv_fault_disconnect(call, call->fault_code);
    1632             :                 }
    1633             :         }
    1634             : 
    1635        5690 :         if (call->pkt.u.alter.num_contexts < 1) {
    1636           3 :                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
    1637             :         }
    1638             : 
    1639        5687 :         ack_ctx_list = talloc_zero_array(call, struct dcerpc_ack_ctx,
    1640             :                                          call->pkt.u.alter.num_contexts);
    1641        5687 :         if (ack_ctx_list == NULL) {
    1642           0 :                 return NT_STATUS_NO_MEMORY;
    1643             :         }
    1644             : 
    1645             :         /*
    1646             :          * Set some sane defaults (required by dcesrv_negotiate_contexts()/
    1647             :          * dcesrv_check_or_create_context()) and do some protocol validation
    1648             :          * and set sane defaults.
    1649             :          */
    1650       11386 :         for (i = 0; i < call->pkt.u.alter.num_contexts; i++) {
    1651        5702 :                 const struct dcerpc_ctx_list *c = &call->pkt.u.alter.ctx_list[i];
    1652        5702 :                 struct dcerpc_ack_ctx *a = &ack_ctx_list[i];
    1653             : 
    1654        5702 :                 if (c->num_transfer_syntaxes == 0) {
    1655           3 :                         return dcesrv_fault_disconnect(call,
    1656             :                                         DCERPC_NCA_S_PROTO_ERROR);
    1657             :                 }
    1658             : 
    1659        5699 :                 a->result = DCERPC_BIND_ACK_RESULT_PROVIDER_REJECTION;
    1660        5699 :                 a->reason.value = DCERPC_BIND_ACK_REASON_ABSTRACT_SYNTAX_NOT_SUPPORTED;
    1661             :         }
    1662             : 
    1663             :         /*
    1664             :          * Try to negotiate one new presentation context.
    1665             :          */
    1666        5684 :         status = dcesrv_negotiate_contexts(call, &call->pkt.u.alter, ack_ctx_list);
    1667        5684 :         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
    1668           9 :                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
    1669             :         }
    1670        5675 :         if (!NT_STATUS_IS_OK(status)) {
    1671           0 :                 return status;
    1672             :         }
    1673             : 
    1674        5684 :         if ((call->pkt.pfc_flags & DCERPC_PFC_FLAG_CONC_MPX) &&
    1675          16 :             (call->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
    1676          10 :                 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_MULTIPLEXED;
    1677          10 :                 extra_flags |= DCERPC_PFC_FLAG_CONC_MPX;
    1678             :         }
    1679             : 
    1680        5675 :         if (call->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
    1681           0 :                 call->conn->state_flags |= DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL;
    1682             :         }
    1683             : 
    1684             :         /* handle any authentication that is being requested */
    1685        5675 :         if (!auth_ok) {
    1686          12 :                 if (call->in_auth_info.auth_type != auth->auth_type) {
    1687           6 :                         return dcesrv_fault_disconnect(call,
    1688             :                                         DCERPC_FAULT_SEC_PKG_ERROR);
    1689             :                 }
    1690           6 :                 return dcesrv_fault_disconnect(call, DCERPC_FAULT_ACCESS_DENIED);
    1691             :         }
    1692             : 
    1693        5663 :         dcesrv_init_hdr(pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
    1694        5663 :         pkt->auth_length = 0;
    1695        5663 :         pkt->call_id = call->pkt.call_id;
    1696        5663 :         pkt->ptype = DCERPC_PKT_ALTER_RESP;
    1697        5663 :         pkt->pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
    1698        5663 :         pkt->u.alter_resp.max_xmit_frag = call->conn->max_xmit_frag;
    1699        5663 :         pkt->u.alter_resp.max_recv_frag = call->conn->max_recv_frag;
    1700        5663 :         pkt->u.alter_resp.assoc_group_id = call->conn->assoc_group->id;
    1701        5663 :         pkt->u.alter_resp.secondary_address = "";
    1702        5663 :         pkt->u.alter_resp.num_results = call->pkt.u.alter.num_contexts;
    1703        5663 :         pkt->u.alter_resp.ctx_list = ack_ctx_list;
    1704        5663 :         pkt->u.alter_resp.auth_info = data_blob_null;
    1705             : 
    1706        5663 :         status = dcesrv_auth_prepare_alter_ack(call, pkt);
    1707        5663 :         if (!NT_STATUS_IS_OK(status)) {
    1708           0 :                 return dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
    1709             :         }
    1710             : 
    1711        5663 :         if (auth->auth_finished) {
    1712         141 :                 return dcesrv_auth_reply(call);
    1713             :         }
    1714             : 
    1715        5522 :         cb->auth.become_root();
    1716        5522 :         subreq = gensec_update_send(call, call->event_ctx,
    1717             :                                     auth->gensec_security,
    1718             :                                     call->in_auth_info.credentials);
    1719        5522 :         cb->auth.unbecome_root();
    1720        5522 :         if (subreq == NULL) {
    1721           0 :                 return NT_STATUS_NO_MEMORY;
    1722             :         }
    1723        5522 :         tevent_req_set_callback(subreq, dcesrv_alter_done, call);
    1724             : 
    1725        5522 :         return dcesrv_conn_auth_wait_setup(conn);
    1726             : }
    1727             : 
    1728        5522 : static void dcesrv_alter_done(struct tevent_req *subreq)
    1729             : {
    1730        4807 :         struct dcesrv_call_state *call =
    1731        5522 :                 tevent_req_callback_data(subreq,
    1732             :                 struct dcesrv_call_state);
    1733        5522 :         struct dcesrv_connection *conn = call->conn;
    1734        5522 :         struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
    1735             :         NTSTATUS status;
    1736             : 
    1737        5522 :         cb->auth.become_root();
    1738        5522 :         status = gensec_update_recv(subreq, call,
    1739        5522 :                                     &call->out_auth_info->credentials);
    1740        5522 :         cb->auth.unbecome_root();
    1741        5522 :         TALLOC_FREE(subreq);
    1742             : 
    1743        5522 :         status = dcesrv_auth_complete(call, status);
    1744        5522 :         if (!NT_STATUS_IS_OK(status)) {
    1745           6 :                 status = dcesrv_fault_disconnect(call, DCERPC_FAULT_SEC_PKG_ERROR);
    1746           6 :                 dcesrv_conn_auth_wait_finished(conn, status);
    1747           6 :                 return;
    1748             :         }
    1749             : 
    1750        5516 :         status = dcesrv_auth_reply(call);
    1751        5516 :         dcesrv_conn_auth_wait_finished(conn, status);
    1752        5516 :         return;
    1753             : }
    1754             : 
    1755             : /*
    1756             :   possibly save the call for inspection with ndrdump
    1757             :  */
    1758        1778 : static void dcesrv_save_call(struct dcesrv_call_state *call, const char *why)
    1759             : {
    1760             : #ifdef DEVELOPER
    1761        2859 :         dcerpc_log_packet(call->conn->packet_log_dir,
    1762        1778 :                           call->context->iface->name,
    1763        1778 :                           call->pkt.u.request.opnum,
    1764             :                           NDR_IN,
    1765        1778 :                           &call->pkt.u.request.stub_and_verifier,
    1766             :                           why);
    1767             : #endif
    1768        1778 : }
    1769             : 
    1770             : #ifdef DEVELOPER
    1771             : /*
    1772             :   Save the call for use as a seed for fuzzing.
    1773             : 
    1774             :   This is only enabled in a developer build, and only has effect if the
    1775             :   "dcesrv fuzz directory" param is set.
    1776             : */
    1777      331928 : void _dcesrv_save_ndr_fuzz_seed(DATA_BLOB call_blob,
    1778             :                                 struct dcesrv_call_state *call,
    1779             :                                 int flags)
    1780             : {
    1781      331928 :         const char *dump_dir = lpcfg_parm_string(call->conn->dce_ctx->lp_ctx,
    1782             :                                                  NULL,
    1783             :                                                  "dcesrv", "fuzz directory");
    1784             : 
    1785      865608 :         dcerpc_save_ndr_fuzz_seed(call,
    1786             :                                   call_blob,
    1787             :                                   dump_dir,
    1788      331928 :                                   call->context->iface->name,
    1789             :                                   flags,
    1790      331928 :                                   call->pkt.u.request.opnum,
    1791      331928 :                                   call->ndr_pull->flags & LIBNDR_FLAG_NDR64);
    1792      331928 : }
    1793             : #endif /*if DEVELOPER, enveloping _dcesrv_save_ndr_fuzz_seed() */
    1794             : 
    1795             : 
    1796      173422 : static NTSTATUS dcesrv_check_verification_trailer(struct dcesrv_call_state *call)
    1797             : {
    1798      173422 :         TALLOC_CTX *frame = talloc_stackframe();
    1799      314261 :         const uint32_t bitmask1 = call->conn->client_hdr_signing ?
    1800      173422 :                 DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING : 0;
    1801      314261 :         const struct dcerpc_sec_vt_pcontext pcontext = {
    1802      173422 :                 .abstract_syntax = call->context->iface->syntax_id,
    1803      173422 :                 .transfer_syntax = call->context->transfer_syntax,
    1804             :         };
    1805      140839 :         const struct dcerpc_sec_vt_header2 header2 =
    1806      173422 :                 dcerpc_sec_vt_header2_from_ncacn_packet(&call->pkt);
    1807             :         enum ndr_err_code ndr_err;
    1808      173422 :         struct dcerpc_sec_verification_trailer *vt = NULL;
    1809      173422 :         NTSTATUS status = NT_STATUS_OK;
    1810             :         bool ok;
    1811             : 
    1812      173422 :         SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_REQUEST);
    1813             : 
    1814      173422 :         ndr_err = ndr_pop_dcerpc_sec_verification_trailer(call->ndr_pull,
    1815             :                                                           frame, &vt);
    1816      173422 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1817           0 :                 status = ndr_map_error2ntstatus(ndr_err);
    1818           0 :                 goto done;
    1819             :         }
    1820             : 
    1821      173422 :         ok = dcerpc_sec_verification_trailer_check(vt, &bitmask1,
    1822             :                                                    &pcontext, &header2);
    1823      173422 :         if (!ok) {
    1824           0 :                 status = NT_STATUS_ACCESS_DENIED;
    1825           0 :                 goto done;
    1826             :         }
    1827      314261 : done:
    1828      173422 :         TALLOC_FREE(frame);
    1829      173422 :         return status;
    1830             : }
    1831             : 
    1832             : /*
    1833             :   handle a dcerpc request packet
    1834             : */
    1835      173544 : static NTSTATUS dcesrv_request(struct dcesrv_call_state *call)
    1836             : {
    1837      173544 :         const struct dcesrv_endpoint *endpoint = call->conn->endpoint;
    1838      173544 :         struct dcesrv_auth *auth = call->auth_state;
    1839      140959 :         enum dcerpc_transport_t transport =
    1840      173544 :                 dcerpc_binding_get_transport(endpoint->ep_description);
    1841             :         struct ndr_pull *pull;
    1842      173544 :         bool turn_winbind_on = false;
    1843             :         NTSTATUS status;
    1844             : 
    1845      173544 :         if (auth->auth_invalid) {
    1846           0 :                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
    1847             :         }
    1848             : 
    1849      173544 :         if (!auth->auth_finished) {
    1850           0 :                 return dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
    1851             :         }
    1852             : 
    1853             :         /* if authenticated, and the mech we use can't do async replies, don't use them... */
    1854      234299 :         if (auth->gensec_security != NULL &&
    1855       75193 :             !gensec_have_feature(auth->gensec_security, GENSEC_FEATURE_ASYNC_REPLIES)) {
    1856       17164 :                 call->state_flags &= ~DCESRV_CALL_STATE_FLAG_MAY_ASYNC;
    1857             :         }
    1858             : 
    1859      173544 :         if (call->context == NULL) {
    1860           0 :                 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
    1861             :                                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
    1862             :         }
    1863             : 
    1864      173544 :         switch (auth->auth_level) {
    1865      172354 :         case DCERPC_AUTH_LEVEL_NONE:
    1866             :         case DCERPC_AUTH_LEVEL_PACKET:
    1867             :         case DCERPC_AUTH_LEVEL_INTEGRITY:
    1868             :         case DCERPC_AUTH_LEVEL_PRIVACY:
    1869      172354 :                 break;
    1870        1190 :         default:
    1871        1190 :                 if (!call->context->allow_connect) {
    1872             :                         char *addr;
    1873             : 
    1874           4 :                         addr = tsocket_address_string(call->conn->remote_address,
    1875             :                                                       call);
    1876             : 
    1877           4 :                         DEBUG(2, ("%s: restrict auth_level_connect access "
    1878             :                                   "to [%s] with auth[type=0x%x,level=0x%x] "
    1879             :                                   "on [%s] from [%s]\n",
    1880             :                                   __func__, call->context->iface->name,
    1881             :                                   auth->auth_type,
    1882             :                                   auth->auth_level,
    1883             :                                   derpc_transport_string_by_transport(transport),
    1884             :                                   addr));
    1885           4 :                         return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
    1886             :                 }
    1887        1186 :                 break;
    1888             :         }
    1889             : 
    1890      173540 :         if (auth->auth_level < call->context->min_auth_level) {
    1891             :                 char *addr;
    1892             : 
    1893         118 :                 addr = tsocket_address_string(call->conn->remote_address, call);
    1894             : 
    1895         118 :                 DEBUG(2, ("%s: restrict access by min_auth_level[0x%x] "
    1896             :                           "to [%s] with auth[type=0x%x,level=0x%x] "
    1897             :                           "on [%s] from [%s]\n",
    1898             :                           __func__,
    1899             :                           call->context->min_auth_level,
    1900             :                           call->context->iface->name,
    1901             :                           auth->auth_type,
    1902             :                           auth->auth_level,
    1903             :                           derpc_transport_string_by_transport(transport),
    1904             :                           addr));
    1905         118 :                 return dcesrv_fault(call, DCERPC_FAULT_ACCESS_DENIED);
    1906             :         }
    1907             : 
    1908      173422 :         pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier, call);
    1909      173422 :         NT_STATUS_HAVE_NO_MEMORY(pull);
    1910             : 
    1911      173422 :         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
    1912             : 
    1913      173422 :         call->ndr_pull       = pull;
    1914             : 
    1915      173422 :         if (!(call->pkt.drep[0] & DCERPC_DREP_LE)) {
    1916       21477 :                 pull->flags |= LIBNDR_FLAG_BIGENDIAN;
    1917             :         }
    1918             : 
    1919      173422 :         status = dcesrv_check_verification_trailer(call);
    1920      173422 :         if (!NT_STATUS_IS_OK(status)) {
    1921           0 :                 uint32_t faultcode = DCERPC_FAULT_OTHER;
    1922           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
    1923           0 :                         faultcode = DCERPC_FAULT_ACCESS_DENIED;
    1924             :                 }
    1925           0 :                 DEBUG(10, ("dcesrv_check_verification_trailer failed: %s\n",
    1926             :                            nt_errstr(status)));
    1927           0 :                 return dcesrv_fault(call, faultcode);
    1928             :         }
    1929             : 
    1930             :         /* unravel the NDR for the packet */
    1931      173422 :         status = call->context->iface->ndr_pull(call, call, pull, &call->r);
    1932      173422 :         if (!NT_STATUS_IS_OK(status)) {
    1933          54 :                 uint8_t extra_flags = 0;
    1934          54 :                 if (call->fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
    1935             :                         /* we got an unknown call */
    1936          54 :                         DEBUG(3,(__location__ ": Unknown RPC call %u on %s\n",
    1937             :                                  call->pkt.u.request.opnum,
    1938             :                                  call->context->iface->name));
    1939          54 :                         dcesrv_save_call(call, "unknown");
    1940          54 :                         extra_flags |= DCERPC_PFC_FLAG_DID_NOT_EXECUTE;
    1941             :                 } else {
    1942           0 :                         dcesrv_save_call(call, "pullfail");
    1943             :                 }
    1944             : 
    1945          54 :                 return dcesrv_fault_with_flags(call, call->fault_code, extra_flags);
    1946             :         }
    1947             : 
    1948      173368 :         dcesrv_save_ndr_fuzz_seed(call->pkt.u.request.stub_and_verifier,
    1949             :                                   call,
    1950             :                                   NDR_IN);
    1951             : 
    1952      173368 :         if (pull->offset != pull->data_size) {
    1953        1724 :                 dcesrv_save_call(call, "extrabytes");
    1954        1724 :                 DEBUG(3,("Warning: %d extra bytes in incoming RPC request\n",
    1955             :                          pull->data_size - pull->offset));
    1956             :         }
    1957             : 
    1958      173368 :         if (call->state_flags & DCESRV_CALL_STATE_FLAG_WINBIND_OFF) {
    1959         291 :                 bool winbind_active = !winbind_env_set();
    1960         291 :                 if (winbind_active) {
    1961         291 :                         DBG_DEBUG("turning winbind off\n");
    1962         291 :                         (void)winbind_off();
    1963         291 :                         turn_winbind_on = true;
    1964             :                 }
    1965             :         }
    1966             : 
    1967             :         /* call the dispatch function */
    1968      173368 :         status = call->context->iface->dispatch(call, call, call->r);
    1969             : 
    1970      173366 :         if (turn_winbind_on) {
    1971         291 :                 DBG_DEBUG("turning winbind on\n");
    1972         291 :                 (void)winbind_on();
    1973             :         }
    1974             : 
    1975      173366 :         if (!NT_STATUS_IS_OK(status)) {
    1976       14790 :                 DEBUG(5,("dcerpc fault in call %s:%02x - %s\n",
    1977             :                          call->context->iface->name,
    1978             :                          call->pkt.u.request.opnum,
    1979             :                          dcerpc_errstr(pull, call->fault_code)));
    1980       14790 :                 return dcesrv_fault(call, call->fault_code);
    1981             :         }
    1982             : 
    1983             :         /* add the call to the pending list */
    1984      158576 :         dcesrv_call_set_list(call, DCESRV_LIST_PENDING_CALL_LIST);
    1985             : 
    1986      158576 :         if (call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
    1987       13702 :                 return NT_STATUS_OK;
    1988             :         }
    1989             : 
    1990      144874 :         return dcesrv_reply(call);
    1991             : }
    1992             : 
    1993             : 
    1994             : /*
    1995             :   remove the call from the right list when freed
    1996             :  */
    1997      212339 : static int dcesrv_call_dequeue(struct dcesrv_call_state *call)
    1998             : {
    1999      212339 :         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
    2000      212339 :         return 0;
    2001             : }
    2002             : 
    2003         281 : _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_local_address(struct dcesrv_connection *conn)
    2004             : {
    2005         281 :         return conn->local_address;
    2006             : }
    2007             : 
    2008         250 : _PUBLIC_ const struct tsocket_address *dcesrv_connection_get_remote_address(struct dcesrv_connection *conn)
    2009             : {
    2010         250 :         return conn->remote_address;
    2011             : }
    2012             : 
    2013             : /*
    2014             :   process some input to a dcerpc endpoint server.
    2015             : */
    2016      212344 : static NTSTATUS dcesrv_process_ncacn_packet(struct dcesrv_connection *dce_conn,
    2017             :                                             struct ncacn_packet *pkt,
    2018             :                                             DATA_BLOB blob)
    2019             : {
    2020             :         NTSTATUS status;
    2021             :         struct dcesrv_call_state *call;
    2022      212344 :         struct dcesrv_call_state *existing = NULL;
    2023      212344 :         size_t num_auth_ctx = 0;
    2024      212344 :         enum dcerpc_AuthType auth_type = 0;
    2025      212344 :         enum dcerpc_AuthLevel auth_level = 0;
    2026      212344 :         uint32_t auth_context_id = 0;
    2027      212344 :         bool auth_invalid = false;
    2028             : 
    2029      212344 :         call = talloc_zero(dce_conn, struct dcesrv_call_state);
    2030      212344 :         if (!call) {
    2031           0 :                 data_blob_free(&blob);
    2032           0 :                 talloc_free(pkt);
    2033           0 :                 return NT_STATUS_NO_MEMORY;
    2034             :         }
    2035      212344 :         call->conn           = dce_conn;
    2036      212344 :         call->event_ctx              = dce_conn->event_ctx;
    2037      212344 :         call->state_flags    = call->conn->state_flags;
    2038      212344 :         call->time           = timeval_current();
    2039      212344 :         call->list              = DCESRV_LIST_NONE;
    2040             : 
    2041      212344 :         talloc_steal(call, pkt);
    2042      212344 :         talloc_steal(call, blob.data);
    2043      212344 :         call->pkt = *pkt;
    2044             : 
    2045      212344 :         if (dce_conn->max_auth_states == 0) {
    2046       16234 :                 call->auth_state = dce_conn->default_auth_state;
    2047      196110 :         } else if (call->pkt.auth_length == 0) {
    2048      194013 :                 if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
    2049      101016 :                     dce_conn->default_auth_level_connect != NULL)
    2050             :                 {
    2051        1174 :                         call->auth_state = dce_conn->default_auth_level_connect;
    2052             :                 } else {
    2053      109236 :                         call->auth_state = dce_conn->default_auth_state;
    2054             :                 }
    2055             :         }
    2056             : 
    2057      212344 :         if (call->auth_state == NULL) {
    2058       85700 :                 struct dcesrv_auth *a = NULL;
    2059       85700 :                 bool check_type_level = true;
    2060             : 
    2061       85700 :                 auth_type = dcerpc_get_auth_type(&blob);
    2062       85700 :                 auth_level = dcerpc_get_auth_level(&blob);
    2063       85700 :                 auth_context_id = dcerpc_get_auth_context_id(&blob);
    2064             : 
    2065       85700 :                 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
    2066       74281 :                         if (!(call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
    2067        7626 :                                 check_type_level = false;
    2068             :                         }
    2069       74281 :                         dce_conn->default_auth_level_connect = NULL;
    2070       74281 :                         if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
    2071          58 :                                 dce_conn->got_explicit_auth_level_connect = true;
    2072             :                         }
    2073             :                 }
    2074             : 
    2075      158673 :                 for (a = dce_conn->auth_states; a != NULL; a = a->next) {
    2076       79450 :                         num_auth_ctx++;
    2077             : 
    2078       79450 :                         if (a->auth_context_id != auth_context_id) {
    2079         266 :                                 continue;
    2080             :                         }
    2081             : 
    2082       79184 :                         if (a->auth_type != auth_type) {
    2083          15 :                                 auth_invalid = true;
    2084             :                         }
    2085       79184 :                         if (a->auth_level != auth_level) {
    2086          27 :                                 auth_invalid = true;
    2087             :                         }
    2088             : 
    2089       79184 :                         if (check_type_level && auth_invalid) {
    2090          30 :                                 a->auth_invalid = true;
    2091             :                         }
    2092             : 
    2093       79184 :                         DLIST_PROMOTE(dce_conn->auth_states, a);
    2094       79184 :                         call->auth_state = a;
    2095       79184 :                         break;
    2096             :                 }
    2097             :         }
    2098             : 
    2099      212344 :         if (call->auth_state == NULL) {
    2100        6516 :                 struct dcesrv_auth *a = NULL;
    2101             : 
    2102        6516 :                 if (num_auth_ctx >= dce_conn->max_auth_states) {
    2103           3 :                         return dcesrv_fault_disconnect(call,
    2104             :                                         DCERPC_NCA_S_PROTO_ERROR);
    2105             :                 }
    2106             : 
    2107        6513 :                 a = dcesrv_auth_create(dce_conn);
    2108        6513 :                 if (a == NULL) {
    2109           0 :                         talloc_free(call);
    2110           0 :                         return NT_STATUS_NO_MEMORY;
    2111             :                 }
    2112        6513 :                 DLIST_ADD(dce_conn->auth_states, a);
    2113        6513 :                 if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
    2114             :                         /*
    2115             :                          * This can never be valid.
    2116             :                          */
    2117          51 :                         auth_invalid = true;
    2118          51 :                         a->auth_invalid = true;
    2119             :                 }
    2120        6513 :                 call->auth_state = a;
    2121             :         }
    2122             : 
    2123      212341 :         talloc_set_destructor(call, dcesrv_call_dequeue);
    2124             : 
    2125      212341 :         if (call->conn->allow_bind) {
    2126             :                 /*
    2127             :                  * Only one bind is possible per connection
    2128             :                  */
    2129       16952 :                 call->conn->allow_bind = false;
    2130       16952 :                 return dcesrv_bind(call);
    2131             :         }
    2132             : 
    2133             :         /* we have to check the signing here, before combining the
    2134             :            pdus */
    2135      195389 :         if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
    2136      189531 :                 dcesrv_default_auth_state_prepare_request(call);
    2137             : 
    2138      342524 :                 if (call->auth_state->auth_started &&
    2139      189480 :                     !call->auth_state->auth_finished) {
    2140           3 :                         return dcesrv_fault_disconnect(call,
    2141             :                                         DCERPC_NCA_S_PROTO_ERROR);
    2142             :                 }
    2143             : 
    2144      189528 :                 status = dcerpc_verify_ncacn_packet_header(&call->pkt,
    2145             :                                 DCERPC_PKT_REQUEST,
    2146             :                                 call->pkt.u.request.stub_and_verifier.length,
    2147             :                                 0, /* required_flags */
    2148             :                                 DCERPC_PFC_FLAG_FIRST |
    2149             :                                 DCERPC_PFC_FLAG_LAST |
    2150             :                                 DCERPC_PFC_FLAG_PENDING_CANCEL |
    2151             :                                 0x08 | /* this is not defined, but should be ignored */
    2152             :                                 DCERPC_PFC_FLAG_CONC_MPX |
    2153             :                                 DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
    2154             :                                 DCERPC_PFC_FLAG_MAYBE |
    2155             :                                 DCERPC_PFC_FLAG_OBJECT_UUID);
    2156      189528 :                 if (!NT_STATUS_IS_OK(status)) {
    2157           0 :                         return dcesrv_fault_disconnect(call,
    2158             :                                         DCERPC_NCA_S_PROTO_ERROR);
    2159             :                 }
    2160             : 
    2161      189528 :                 if (call->pkt.frag_length > DCERPC_FRAG_MAX_SIZE) {
    2162             :                         /*
    2163             :                          * We don't use dcesrv_fault_disconnect()
    2164             :                          * here, because we don't want to set
    2165             :                          * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
    2166             :                          *
    2167             :                          * Note that we don't check against the negotiated
    2168             :                          * max_recv_frag, but a hard coded value.
    2169             :                          */
    2170          24 :                         return dcesrv_fault_disconnect0(call, DCERPC_NCA_S_PROTO_ERROR);
    2171             :                 }
    2172             : 
    2173      189504 :                 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
    2174      173752 :                         if (dce_conn->pending_call_list != NULL) {
    2175             :                                 /*
    2176             :                                  * concurrent requests are only allowed
    2177             :                                  * if DCERPC_PFC_FLAG_CONC_MPX was negotiated.
    2178             :                                  */
    2179          94 :                                 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
    2180           0 :                                         return dcesrv_fault_disconnect0(call,
    2181             :                                                 DCERPC_NCA_S_PROTO_ERROR);
    2182             :                                 }
    2183             :                         }
    2184             :                         /* only one request is possible in the fragmented list */
    2185      173752 :                         if (dce_conn->incoming_fragmented_call_list != NULL) {
    2186          54 :                                 call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
    2187             : 
    2188          54 :                                 existing = dcesrv_find_fragmented_call(dce_conn,
    2189             :                                                                        call->pkt.call_id);
    2190          54 :                                 if (existing != NULL && call->auth_state != existing->auth_state) {
    2191          28 :                                         call->context = dcesrv_find_context(call->conn,
    2192          21 :                                                                 call->pkt.u.request.context_id);
    2193             : 
    2194          21 :                                         if (call->pkt.auth_length != 0 && existing->context == call->context) {
    2195           3 :                                                 call->fault_code = DCERPC_FAULT_SEC_PKG_ERROR;
    2196             :                                         }
    2197             :                                 }
    2198          54 :                                 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
    2199             :                                         /*
    2200             :                                          * Without DCERPC_PFC_FLAG_CONC_MPX
    2201             :                                          * we need to return the FAULT on the
    2202             :                                          * already existing call.
    2203             :                                          *
    2204             :                                          * This is important to get the
    2205             :                                          * call_id and context_id right.
    2206             :                                          */
    2207          33 :                                         dce_conn->incoming_fragmented_call_list->fault_code = call->fault_code;
    2208          33 :                                         TALLOC_FREE(call);
    2209          33 :                                         call = dce_conn->incoming_fragmented_call_list;
    2210             :                                 }
    2211          54 :                                 if (existing != NULL) {
    2212          26 :                                         call->context = existing->context;
    2213             :                                 }
    2214          54 :                                 return dcesrv_fault_disconnect0(call, call->fault_code);
    2215             :                         }
    2216      173698 :                         if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_PENDING_CANCEL) {
    2217           1 :                                 return dcesrv_fault_disconnect(call,
    2218             :                                                 DCERPC_FAULT_NO_CALL_ACTIVE);
    2219             :                         }
    2220      206328 :                         call->context = dcesrv_find_context(call->conn,
    2221      173697 :                                                 call->pkt.u.request.context_id);
    2222      173697 :                         if (call->context == NULL) {
    2223          10 :                                 return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
    2224             :                                         DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
    2225             :                         }
    2226             :                 } else {
    2227             :                         int cmp;
    2228             : 
    2229       15752 :                         existing = dcesrv_find_fragmented_call(dce_conn,
    2230             :                                                         call->pkt.call_id);
    2231       15752 :                         if (existing == NULL) {
    2232          59 :                                 if (!(dce_conn->state_flags & DCESRV_CALL_STATE_FLAG_MULTIPLEXED)) {
    2233             :                                         /*
    2234             :                                          * Without DCERPC_PFC_FLAG_CONC_MPX
    2235             :                                          * we need to return the FAULT on the
    2236             :                                          * already existing call.
    2237             :                                          *
    2238             :                                          * This is important to get the
    2239             :                                          * call_id and context_id right.
    2240             :                                          */
    2241          32 :                                         if (dce_conn->incoming_fragmented_call_list != NULL) {
    2242          12 :                                                 TALLOC_FREE(call);
    2243          12 :                                                 call = dce_conn->incoming_fragmented_call_list;
    2244             :                                         }
    2245          32 :                                         return dcesrv_fault_disconnect0(call,
    2246             :                                                         DCERPC_NCA_S_PROTO_ERROR);
    2247             :                                 }
    2248          27 :                                 if (dce_conn->incoming_fragmented_call_list != NULL) {
    2249           9 :                                         return dcesrv_fault_disconnect0(call, DCERPC_NCA_S_PROTO_ERROR);
    2250             :                                 }
    2251          24 :                                 call->context = dcesrv_find_context(call->conn,
    2252          18 :                                                         call->pkt.u.request.context_id);
    2253          18 :                                 if (call->context == NULL) {
    2254           3 :                                         return dcesrv_fault_with_flags(call, DCERPC_NCA_S_UNKNOWN_IF,
    2255             :                                                 DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
    2256             :                                 }
    2257          15 :                                 if (auth_invalid) {
    2258          12 :                                         return dcesrv_fault_disconnect0(call,
    2259             :                                                                         DCERPC_FAULT_ACCESS_DENIED);
    2260             :                                 }
    2261           3 :                                 return dcesrv_fault_disconnect0(call,
    2262             :                                                 DCERPC_NCA_S_PROTO_ERROR);
    2263             :                         }
    2264             : 
    2265       15693 :                         if (call->pkt.ptype != existing->pkt.ptype) {
    2266             :                                 /* trying to play silly buggers are we? */
    2267           0 :                                 return dcesrv_fault_disconnect(existing,
    2268             :                                                 DCERPC_NCA_S_PROTO_ERROR);
    2269             :                         }
    2270       15693 :                         cmp = memcmp(call->pkt.drep, existing->pkt.drep,
    2271             :                                      sizeof(pkt->drep));
    2272       15693 :                         if (cmp != 0) {
    2273           0 :                                 return dcesrv_fault_disconnect(existing,
    2274             :                                                 DCERPC_NCA_S_PROTO_ERROR);
    2275             :                         }
    2276       15693 :                         call->auth_state = existing->auth_state;
    2277       15693 :                         call->context = existing->context;
    2278             :                 }
    2279             :         }
    2280             : 
    2281      195238 :         if (call->pkt.ptype == DCERPC_PKT_REQUEST) {
    2282             :                 bool ok;
    2283      189380 :                 uint8_t payload_offset = DCERPC_REQUEST_LENGTH;
    2284             : 
    2285      189380 :                 if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
    2286           6 :                         payload_offset += 16;
    2287             :                 }
    2288             : 
    2289      189380 :                 ok = dcesrv_auth_pkt_pull(call, &blob,
    2290             :                                           0, /* required_flags */
    2291             :                                           DCERPC_PFC_FLAG_FIRST |
    2292             :                                           DCERPC_PFC_FLAG_LAST |
    2293             :                                           DCERPC_PFC_FLAG_PENDING_CANCEL |
    2294             :                                           0x08 | /* this is not defined, but should be ignored */
    2295             :                                           DCERPC_PFC_FLAG_CONC_MPX |
    2296             :                                           DCERPC_PFC_FLAG_DID_NOT_EXECUTE |
    2297             :                                           DCERPC_PFC_FLAG_MAYBE |
    2298             :                                           DCERPC_PFC_FLAG_OBJECT_UUID,
    2299             :                                           payload_offset,
    2300             :                                           &call->pkt.u.request.stub_and_verifier);
    2301      189380 :                 if (!ok) {
    2302             :                         /*
    2303             :                          * We don't use dcesrv_fault_disconnect()
    2304             :                          * here, because we don't want to set
    2305             :                          * DCERPC_PFC_FLAG_DID_NOT_EXECUTE
    2306             :                          */
    2307          66 :                         if (call->fault_code == 0) {
    2308          33 :                                 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
    2309             :                         }
    2310          66 :                         return dcesrv_fault_disconnect0(call, call->fault_code);
    2311             :                 }
    2312             :         }
    2313             : 
    2314             :         /* see if this is a continued packet */
    2315      195172 :         if (existing != NULL) {
    2316       15678 :                 struct dcerpc_request *er = &existing->pkt.u.request;
    2317       15678 :                 const struct dcerpc_request *nr = &call->pkt.u.request;
    2318             :                 size_t available;
    2319             :                 size_t alloc_size;
    2320             :                 size_t alloc_hint;
    2321             : 
    2322             :                 /*
    2323             :                  * Up to 4 MByte are allowed by all fragments
    2324             :                  */
    2325       15678 :                 available = dce_conn->max_total_request_size;
    2326       15678 :                 if (er->stub_and_verifier.length > available) {
    2327           0 :                         return dcesrv_fault_disconnect0(existing,
    2328             :                                         DCERPC_FAULT_ACCESS_DENIED);
    2329             :                 }
    2330       15678 :                 available -= er->stub_and_verifier.length;
    2331       15678 :                 if (nr->alloc_hint > available) {
    2332           0 :                         return dcesrv_fault_disconnect0(existing,
    2333             :                                         DCERPC_FAULT_ACCESS_DENIED);
    2334             :                 }
    2335       15678 :                 if (nr->stub_and_verifier.length > available) {
    2336           1 :                         return dcesrv_fault_disconnect0(existing,
    2337             :                                         DCERPC_FAULT_ACCESS_DENIED);
    2338             :                 }
    2339       15677 :                 alloc_hint = er->stub_and_verifier.length + nr->alloc_hint;
    2340             :                 /* allocate at least 1 byte */
    2341       15677 :                 alloc_hint = MAX(alloc_hint, 1);
    2342       27530 :                 alloc_size = er->stub_and_verifier.length +
    2343       15677 :                              nr->stub_and_verifier.length;
    2344       15677 :                 alloc_size = MAX(alloc_size, alloc_hint);
    2345             : 
    2346       15677 :                 er->stub_and_verifier.data =
    2347       15677 :                         talloc_realloc(existing,
    2348             :                                        er->stub_and_verifier.data,
    2349             :                                        uint8_t, alloc_size);
    2350       15677 :                 if (er->stub_and_verifier.data == NULL) {
    2351           0 :                         TALLOC_FREE(call);
    2352           0 :                         return dcesrv_fault_with_flags(existing,
    2353             :                                                        DCERPC_FAULT_OUT_OF_RESOURCES,
    2354             :                                                        DCERPC_PFC_FLAG_DID_NOT_EXECUTE);
    2355             :                 }
    2356       39383 :                 memcpy(er->stub_and_verifier.data +
    2357       15677 :                        er->stub_and_verifier.length,
    2358       15677 :                        nr->stub_and_verifier.data,
    2359        3824 :                        nr->stub_and_verifier.length);
    2360       15677 :                 er->stub_and_verifier.length += nr->stub_and_verifier.length;
    2361             : 
    2362       15677 :                 existing->pkt.pfc_flags |= (call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST);
    2363             : 
    2364       15677 :                 TALLOC_FREE(call);
    2365       15677 :                 call = existing;
    2366             :         }
    2367             : 
    2368             :         /* this may not be the last pdu in the chain - if its isn't then
    2369             :            just put it on the incoming_fragmented_call_list and wait for the rest */
    2370      348047 :         if (call->pkt.ptype == DCERPC_PKT_REQUEST &&
    2371      189313 :             !(call->pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
    2372             :                 /*
    2373             :                  * Up to 4 MByte are allowed by all fragments
    2374             :                  */
    2375       15769 :                 if (call->pkt.u.request.alloc_hint > dce_conn->max_total_request_size) {
    2376           1 :                         return dcesrv_fault_disconnect0(call,
    2377             :                                         DCERPC_FAULT_ACCESS_DENIED);
    2378             :                 }
    2379       15768 :                 dcesrv_call_set_list(call, DCESRV_LIST_FRAGMENTED_CALL_LIST);
    2380       15768 :                 return NT_STATUS_OK;
    2381             :         }
    2382             : 
    2383             :         /* This removes any fragments we may have had stashed away */
    2384      179402 :         dcesrv_call_set_list(call, DCESRV_LIST_NONE);
    2385             : 
    2386      179402 :         switch (call->pkt.ptype) {
    2387           3 :         case DCERPC_PKT_BIND:
    2388           3 :                 status = dcesrv_bind_nak(call,
    2389             :                         DCERPC_BIND_NAK_REASON_NOT_SPECIFIED);
    2390           3 :                 break;
    2391         135 :         case DCERPC_PKT_AUTH3:
    2392         135 :                 status = dcesrv_auth3(call);
    2393         135 :                 break;
    2394        5699 :         case DCERPC_PKT_ALTER:
    2395        5699 :                 status = dcesrv_alter(call);
    2396        5699 :                 break;
    2397      173544 :         case DCERPC_PKT_REQUEST:
    2398      173544 :                 status = dcesrv_request(call);
    2399      173542 :                 break;
    2400          21 :         case DCERPC_PKT_CO_CANCEL:
    2401             :         case DCERPC_PKT_ORPHANED:
    2402             :                 /*
    2403             :                  * Window just ignores CO_CANCEL and ORPHANED,
    2404             :                  * so we do...
    2405             :                  */
    2406          21 :                 status = NT_STATUS_OK;
    2407          21 :                 TALLOC_FREE(call);
    2408          21 :                 break;
    2409           0 :         case DCERPC_PKT_BIND_ACK:
    2410             :         case DCERPC_PKT_BIND_NAK:
    2411             :         case DCERPC_PKT_ALTER_RESP:
    2412             :         case DCERPC_PKT_RESPONSE:
    2413             :         case DCERPC_PKT_FAULT:
    2414             :         case DCERPC_PKT_SHUTDOWN:
    2415             :         default:
    2416           0 :                 status = dcesrv_fault_disconnect(call, DCERPC_NCA_S_PROTO_ERROR);
    2417           0 :                 break;
    2418             :         }
    2419             : 
    2420             :         /* if we are going to be sending a reply then add
    2421             :            it to the list of pending calls. We add it to the end to keep the call
    2422             :            list in the order we will answer */
    2423      179400 :         if (!NT_STATUS_IS_OK(status)) {
    2424           0 :                 talloc_free(call);
    2425             :         }
    2426             : 
    2427      179400 :         return status;
    2428             : }
    2429             : 
    2430         244 : _PUBLIC_ NTSTATUS dcesrv_init_context(TALLOC_CTX *mem_ctx,
    2431             :                                       struct loadparm_context *lp_ctx,
    2432             :                                       struct dcesrv_context_callbacks *cb,
    2433             :                                       struct dcesrv_context **_dce_ctx)
    2434             : {
    2435             :         struct dcesrv_context *dce_ctx;
    2436             : 
    2437         244 :         if (cb == NULL) {
    2438           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2439             :         }
    2440             : 
    2441         244 :         dce_ctx = talloc_zero(mem_ctx, struct dcesrv_context);
    2442         244 :         NT_STATUS_HAVE_NO_MEMORY(dce_ctx);
    2443             : 
    2444         244 :         if (uid_wrapper_enabled()) {
    2445         244 :                 setenv("UID_WRAPPER_MYUID", "1", 1);
    2446             :         }
    2447         244 :         dce_ctx->initial_euid = geteuid();
    2448         244 :         if (uid_wrapper_enabled()) {
    2449         244 :                 unsetenv("UID_WRAPPER_MYUID");
    2450             :         }
    2451             : 
    2452         244 :         dce_ctx->endpoint_list       = NULL;
    2453         244 :         dce_ctx->lp_ctx = lp_ctx;
    2454         244 :         dce_ctx->assoc_groups_idr = idr_init(dce_ctx);
    2455         244 :         if (dce_ctx->assoc_groups_idr == NULL) {
    2456           0 :                 TALLOC_FREE(dce_ctx);
    2457           0 :                 return NT_STATUS_NO_MEMORY;
    2458             :         }
    2459         244 :         dce_ctx->broken_connections = NULL;
    2460         244 :         dce_ctx->callbacks = cb;
    2461             : 
    2462         244 :         *_dce_ctx = dce_ctx;
    2463         244 :         return NT_STATUS_OK;
    2464             : }
    2465             : 
    2466             : /**
    2467             :  * @brief Set callback functions on an existing dcesrv_context
    2468             :  *
    2469             :  * This allows to reset callbacks initially set via
    2470             :  * dcesrv_init_context()
    2471             :  *
    2472             :  * @param[in] dce_ctx The context to set the callbacks on
    2473             :  * @param[in] cb The callbacks to set on dce_ctx
    2474             :  */
    2475         120 : _PUBLIC_ void dcesrv_context_set_callbacks(
    2476             :         struct dcesrv_context *dce_ctx,
    2477             :         struct dcesrv_context_callbacks *cb)
    2478             : {
    2479         120 :         dce_ctx->callbacks = cb;
    2480         120 : }
    2481             : 
    2482          56 : _PUBLIC_ NTSTATUS dcesrv_init_ep_servers(struct dcesrv_context *dce_ctx,
    2483             :                                          const char **endpoint_servers)
    2484             : {
    2485             :         NTSTATUS status;
    2486             :         int i;
    2487             : 
    2488          56 :         if (endpoint_servers == NULL) {
    2489           0 :                 DBG_ERR("No endpoint servers configured\n");
    2490           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2491             :         }
    2492             : 
    2493         806 :         for (i=0;endpoint_servers[i];i++) {
    2494         750 :                 status = dcesrv_init_ep_server(dce_ctx, endpoint_servers[i]);
    2495         750 :                 if (!NT_STATUS_IS_OK(status)) {
    2496           0 :                         DBG_ERR("failed to init endpoint server = '%s': %s\n",
    2497             :                                 endpoint_servers[i], nt_errstr(status));
    2498           0 :                         return status;
    2499             :                 }
    2500             :         }
    2501             : 
    2502          56 :         return NT_STATUS_OK;
    2503             : }
    2504             : 
    2505             : /* the list of currently registered DCERPC endpoint servers.
    2506             :  */
    2507             : static struct ep_server {
    2508             :         struct dcesrv_endpoint_server *ep_server;
    2509             : } *ep_servers = NULL;
    2510             : static int num_ep_servers = 0;
    2511             : 
    2512          68 : _PUBLIC_ NTSTATUS dcesrv_init_registered_ep_servers(
    2513             :                                         struct dcesrv_context *dce_ctx)
    2514             : {
    2515             :         NTSTATUS status;
    2516             :         int i;
    2517             : 
    2518         136 :         for (i = 0; i < num_ep_servers; i++) {
    2519          68 :                 status = dcesrv_init_ep_server(dce_ctx,
    2520          68 :                                                ep_servers[i].ep_server->name);
    2521          68 :                 if (!NT_STATUS_IS_OK(status)) {
    2522           0 :                         return status;
    2523             :                 }
    2524             :         }
    2525             : 
    2526          68 :         return NT_STATUS_OK;
    2527             : }
    2528             : 
    2529        1210 : _PUBLIC_ NTSTATUS dcesrv_init_ep_server(struct dcesrv_context *dce_ctx,
    2530             :                                         const char *ep_server_name)
    2531             : {
    2532        1210 :         struct dcesrv_endpoint_server *ep_server = NULL;
    2533             :         NTSTATUS status;
    2534             : 
    2535        1210 :         ep_server = discard_const_p(struct dcesrv_endpoint_server,
    2536             :                                     dcesrv_ep_server_byname(ep_server_name));
    2537        1210 :         if (ep_server == NULL) {
    2538           0 :                 DBG_ERR("Failed to find endpoint server '%s'\n",
    2539             :                         ep_server_name);
    2540           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2541             :         }
    2542             : 
    2543        1210 :         if (ep_server->initialized) {
    2544           0 :                 return NT_STATUS_OK;
    2545             :         }
    2546             : 
    2547        1210 :         status = ep_server->init_server(dce_ctx, ep_server);
    2548        1210 :         if (!NT_STATUS_IS_OK(status)) {
    2549           0 :                 DBG_ERR("Failed to init endpoint server '%s': %s\n",
    2550             :                         ep_server_name, nt_errstr(status));
    2551           0 :                 return status;
    2552             :         }
    2553             : 
    2554        1210 :         ep_server->initialized = true;
    2555             : 
    2556        1210 :         return NT_STATUS_OK;
    2557             : }
    2558             : 
    2559         118 : _PUBLIC_ NTSTATUS dcesrv_shutdown_registered_ep_servers(
    2560             :                                         struct dcesrv_context *dce_ctx)
    2561             : {
    2562             :         NTSTATUS status;
    2563             :         int i;
    2564             : 
    2565         503 :         for (i = 0; i < num_ep_servers; i++) {
    2566         385 :                 status = dcesrv_shutdown_ep_server(dce_ctx,
    2567         385 :                                         ep_servers[i].ep_server->name);
    2568         385 :                 if (!NT_STATUS_IS_OK(status)) {
    2569           0 :                         return status;
    2570             :                 }
    2571             :         }
    2572             : 
    2573         118 :         return NT_STATUS_OK;
    2574             : }
    2575             : 
    2576         385 : _PUBLIC_ NTSTATUS dcesrv_shutdown_ep_server(struct dcesrv_context *dce_ctx,
    2577             :                                             const char *ep_server_name)
    2578             : {
    2579         385 :         struct dcesrv_endpoint_server *ep_server = NULL;
    2580             :         NTSTATUS status;
    2581             : 
    2582         385 :         ep_server = discard_const_p(struct dcesrv_endpoint_server,
    2583             :                                     dcesrv_ep_server_byname(ep_server_name));
    2584         385 :         if (ep_server == NULL) {
    2585           0 :                 DBG_ERR("Failed to find endpoint server '%s'\n",
    2586             :                         ep_server_name);
    2587           0 :                 return NT_STATUS_INTERNAL_ERROR;
    2588             :         }
    2589             : 
    2590         385 :         if (!ep_server->initialized) {
    2591           0 :                 return NT_STATUS_OK;
    2592             :         }
    2593             : 
    2594         385 :         DBG_INFO("Shutting down DCE/RPC endpoint server '%s'\n",
    2595             :                  ep_server_name);
    2596             : 
    2597         385 :         status = ep_server->shutdown_server(dce_ctx, ep_server);
    2598         385 :         if (!NT_STATUS_IS_OK(status)) {
    2599           0 :                 DBG_ERR("Failed to shutdown endpoint server '%s': %s\n",
    2600             :                         ep_server_name, nt_errstr(status));
    2601           0 :                 return status;
    2602             :         }
    2603             : 
    2604         385 :         ep_server->initialized = false;
    2605             : 
    2606         385 :         return NT_STATUS_OK;
    2607             : }
    2608             : 
    2609             : /*
    2610             :   register a DCERPC endpoint server.
    2611             : 
    2612             :   The 'name' can be later used by other backends to find the operations
    2613             :   structure for this backend.
    2614             : 
    2615             : */
    2616        1326 : _PUBLIC_ NTSTATUS dcerpc_register_ep_server(const struct dcesrv_endpoint_server *ep_server)
    2617             : {
    2618             : 
    2619        1326 :         if (dcesrv_ep_server_byname(ep_server->name) != NULL) {
    2620             :                 /* its already registered! */
    2621           0 :                 DEBUG(0,("DCERPC endpoint server '%s' already registered\n",
    2622             :                          ep_server->name));
    2623           0 :                 return NT_STATUS_OBJECT_NAME_COLLISION;
    2624             :         }
    2625             : 
    2626        1326 :         ep_servers = realloc_p(ep_servers, struct ep_server, num_ep_servers+1);
    2627        1326 :         if (!ep_servers) {
    2628           0 :                 smb_panic("out of memory in dcerpc_register");
    2629             :         }
    2630             : 
    2631        1326 :         ep_servers[num_ep_servers].ep_server = smb_xmemdup(ep_server, sizeof(*ep_server));
    2632        1326 :         ep_servers[num_ep_servers].ep_server->name = smb_xstrdup(ep_server->name);
    2633             : 
    2634        1326 :         num_ep_servers++;
    2635             : 
    2636        1326 :         DEBUG(3,("DCERPC endpoint server '%s' registered\n",
    2637             :                  ep_server->name));
    2638             : 
    2639        1326 :         return NT_STATUS_OK;
    2640             : }
    2641             : 
    2642             : /*
    2643             :   return the operations structure for a named backend of the specified type
    2644             : */
    2645        2921 : _PUBLIC_ const struct dcesrv_endpoint_server *dcesrv_ep_server_byname(const char *name)
    2646             : {
    2647             :         int i;
    2648             : 
    2649       17622 :         for (i=0;i<num_ep_servers;i++) {
    2650       16296 :                 if (strcmp(ep_servers[i].ep_server->name, name) == 0) {
    2651        1595 :                         return ep_servers[i].ep_server;
    2652             :                 }
    2653             :         }
    2654             : 
    2655        1326 :         return NULL;
    2656             : }
    2657             : 
    2658             : /*
    2659             :   return the DCERPC module version, and the size of some critical types
    2660             :   This can be used by endpoint server modules to either detect compilation errors, or provide
    2661             :   multiple implementations for different smbd compilation options in one module
    2662             : */
    2663           0 : const struct dcesrv_critical_sizes *dcerpc_module_version(void)
    2664             : {
    2665             :         static const struct dcesrv_critical_sizes critical_sizes = {
    2666             :                 DCERPC_MODULE_VERSION,
    2667             :                 sizeof(struct dcesrv_context),
    2668             :                 sizeof(struct dcesrv_endpoint),
    2669             :                 sizeof(struct dcesrv_endpoint_server),
    2670             :                 sizeof(struct dcesrv_interface),
    2671             :                 sizeof(struct dcesrv_if_list),
    2672             :                 sizeof(struct dcesrv_connection),
    2673             :                 sizeof(struct dcesrv_call_state),
    2674             :                 sizeof(struct dcesrv_auth),
    2675             :                 sizeof(struct dcesrv_handle)
    2676             :         };
    2677             : 
    2678           0 :         return &critical_sizes;
    2679             : }
    2680             : 
    2681       16957 : _PUBLIC_ void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, const char *reason)
    2682             : {
    2683       16957 :         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
    2684       16957 :         struct dcesrv_auth *a = NULL;
    2685             : 
    2686       16957 :         dce_conn->wait_send = NULL;
    2687       16957 :         dce_conn->wait_recv = NULL;
    2688       16957 :         dce_conn->wait_private = NULL;
    2689             : 
    2690       16957 :         dce_conn->allow_bind = false;
    2691       16957 :         dce_conn->allow_alter = false;
    2692             : 
    2693       16957 :         dce_conn->default_auth_state->auth_invalid = true;
    2694             : 
    2695       23457 :         for (a = dce_conn->auth_states; a != NULL; a = a->next) {
    2696        6500 :                 a->auth_invalid = true;
    2697             :         }
    2698             : 
    2699       16957 :         if (dce_conn->pending_call_list == NULL) {
    2700       16957 :                 char *full_reason = talloc_asprintf(dce_conn, "dcesrv: %s", reason);
    2701             : 
    2702       16957 :                 DLIST_REMOVE(dce_ctx->broken_connections, dce_conn);
    2703       16957 :                 dce_conn->transport.terminate_connection(dce_conn,
    2704             :                                         full_reason ? full_reason : reason);
    2705       16646 :                 return;
    2706             :         }
    2707             : 
    2708           0 :         if (dce_conn->terminate != NULL) {
    2709           0 :                 return;
    2710             :         }
    2711             : 
    2712           0 :         DEBUG(3,("dcesrv: terminating connection due to '%s' deferred due to pending calls\n",
    2713             :                  reason));
    2714           0 :         dce_conn->terminate = talloc_strdup(dce_conn, reason);
    2715           0 :         if (dce_conn->terminate == NULL) {
    2716           0 :                 dce_conn->terminate = "dcesrv: deferred terminating connection - no memory";
    2717             :         }
    2718           0 :         DLIST_ADD_END(dce_ctx->broken_connections, dce_conn);
    2719             : }
    2720             : 
    2721      257111 : _PUBLIC_ void dcesrv_cleanup_broken_connections(struct dcesrv_context *dce_ctx)
    2722             : {
    2723             :         struct dcesrv_connection *cur, *next;
    2724             : 
    2725      257111 :         next = dce_ctx->broken_connections;
    2726      467459 :         while (next != NULL) {
    2727           0 :                 cur = next;
    2728           0 :                 next = cur->next;
    2729             : 
    2730           0 :                 if (cur->state_flags & DCESRV_CALL_STATE_FLAG_PROCESS_PENDING_CALL) {
    2731             :                         struct dcesrv_connection_context *context_cur, *context_next;
    2732             : 
    2733           0 :                         context_next = cur->contexts;
    2734           0 :                         while (context_next != NULL) {
    2735           0 :                                 context_cur = context_next;
    2736           0 :                                 context_next = context_cur->next;
    2737             : 
    2738           0 :                                 dcesrv_connection_context_destructor(context_cur);
    2739             :                         }
    2740             :                 }
    2741             : 
    2742           0 :                 dcesrv_terminate_connection(cur, cur->terminate);
    2743             :         }
    2744      257111 : }
    2745             : 
    2746             : struct dcesrv_sock_reply_state {
    2747             :         struct dcesrv_connection *dce_conn;
    2748             :         struct dcesrv_call_state *call;
    2749             :         struct iovec iov;
    2750             : };
    2751             : 
    2752             : static void dcesrv_sock_reply_done(struct tevent_req *subreq);
    2753             : static void dcesrv_call_terminate_step1(struct tevent_req *subreq);
    2754             : 
    2755      196424 : _PUBLIC_ void dcesrv_sock_report_output_data(struct dcesrv_connection *dce_conn)
    2756             : {
    2757             :         struct dcesrv_call_state *call;
    2758             : 
    2759      196424 :         call = dce_conn->call_list;
    2760      196424 :         if (!call || !call->replies) {
    2761           0 :                 return;
    2762             :         }
    2763             : 
    2764      779818 :         while (call->replies) {
    2765      423204 :                 struct data_blob_list_item *rep = call->replies;
    2766             :                 struct dcesrv_sock_reply_state *substate;
    2767             :                 struct tevent_req *subreq;
    2768             : 
    2769      423204 :                 substate = talloc_zero(call, struct dcesrv_sock_reply_state);
    2770      423204 :                 if (!substate) {
    2771           0 :                         dcesrv_terminate_connection(dce_conn, "no memory");
    2772           0 :                         return;
    2773             :                 }
    2774             : 
    2775      423204 :                 substate->dce_conn = dce_conn;
    2776      423204 :                 substate->call = NULL;
    2777             : 
    2778      423204 :                 DLIST_REMOVE(call->replies, rep);
    2779             : 
    2780      423204 :                 if (call->replies == NULL && call->terminate_reason == NULL) {
    2781      196073 :                         substate->call = call;
    2782             :                 }
    2783             : 
    2784      423204 :                 substate->iov.iov_base = (void *) rep->blob.data;
    2785      423204 :                 substate->iov.iov_len = rep->blob.length;
    2786             : 
    2787      423204 :                 subreq = tstream_writev_queue_send(substate,
    2788             :                                                    dce_conn->event_ctx,
    2789             :                                                    dce_conn->stream,
    2790             :                                                    dce_conn->send_queue,
    2791      423204 :                                                    &substate->iov, 1);
    2792      423204 :                 if (!subreq) {
    2793           0 :                         dcesrv_terminate_connection(dce_conn, "no memory");
    2794           0 :                         return;
    2795             :                 }
    2796      423204 :                 tevent_req_set_callback(subreq, dcesrv_sock_reply_done,
    2797             :                                         substate);
    2798             :         }
    2799             : 
    2800      196424 :         if (call->terminate_reason != NULL) {
    2801             :                 struct tevent_req *subreq;
    2802             : 
    2803         351 :                 subreq = tevent_queue_wait_send(call,
    2804             :                                                 dce_conn->event_ctx,
    2805             :                                                 dce_conn->send_queue);
    2806         351 :                 if (!subreq) {
    2807           0 :                         dcesrv_terminate_connection(dce_conn, __location__);
    2808           0 :                         return;
    2809             :                 }
    2810         351 :                 tevent_req_set_callback(subreq, dcesrv_call_terminate_step1,
    2811             :                                         call);
    2812             :         }
    2813             : 
    2814      196424 :         DLIST_REMOVE(call->conn->call_list, call);
    2815      196424 :         call->list = DCESRV_LIST_NONE;
    2816             : }
    2817             : 
    2818      423198 : static void dcesrv_sock_reply_done(struct tevent_req *subreq)
    2819             : {
    2820      423198 :         struct dcesrv_sock_reply_state *substate = tevent_req_callback_data(subreq,
    2821             :                                                 struct dcesrv_sock_reply_state);
    2822             :         int ret;
    2823             :         int sys_errno;
    2824             :         NTSTATUS status;
    2825      423198 :         struct dcesrv_call_state *call = substate->call;
    2826             : 
    2827      423198 :         ret = tstream_writev_queue_recv(subreq, &sys_errno);
    2828      423198 :         TALLOC_FREE(subreq);
    2829      423198 :         if (ret == -1) {
    2830           0 :                 status = map_nt_error_from_unix_common(sys_errno);
    2831           0 :                 dcesrv_terminate_connection(substate->dce_conn, nt_errstr(status));
    2832           0 :                 return;
    2833             :         }
    2834             : 
    2835      423198 :         talloc_free(substate);
    2836      423198 :         if (call) {
    2837      196073 :                 talloc_free(call);
    2838             :         }
    2839             : }
    2840             : 
    2841             : static void dcesrv_call_terminate_step2(struct tevent_req *subreq);
    2842             : 
    2843         345 : static void dcesrv_call_terminate_step1(struct tevent_req *subreq)
    2844             : {
    2845         345 :         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
    2846             :                                                 struct dcesrv_call_state);
    2847             :         bool ok;
    2848             :         struct timeval tv;
    2849             : 
    2850             :         /* make sure we stop send queue before removing subreq */
    2851         345 :         tevent_queue_stop(call->conn->send_queue);
    2852             : 
    2853         345 :         ok = tevent_queue_wait_recv(subreq);
    2854         345 :         TALLOC_FREE(subreq);
    2855         345 :         if (!ok) {
    2856           0 :                 dcesrv_terminate_connection(call->conn, __location__);
    2857           0 :                 return;
    2858             :         }
    2859             : 
    2860             :         /* disconnect after 200 usecs */
    2861         345 :         tv = timeval_current_ofs_usec(200);
    2862         345 :         subreq = tevent_wakeup_send(call, call->conn->event_ctx, tv);
    2863         345 :         if (subreq == NULL) {
    2864           0 :                 dcesrv_terminate_connection(call->conn, __location__);
    2865           0 :                 return;
    2866             :         }
    2867         345 :         tevent_req_set_callback(subreq, dcesrv_call_terminate_step2,
    2868             :                                 call);
    2869             : }
    2870             : 
    2871         301 : static void dcesrv_call_terminate_step2(struct tevent_req *subreq)
    2872             : {
    2873         301 :         struct dcesrv_call_state *call = tevent_req_callback_data(subreq,
    2874             :                                                 struct dcesrv_call_state);
    2875             :         bool ok;
    2876             : 
    2877         301 :         ok = tevent_wakeup_recv(subreq);
    2878         301 :         TALLOC_FREE(subreq);
    2879         301 :         if (!ok) {
    2880           0 :                 dcesrv_terminate_connection(call->conn, __location__);
    2881           0 :                 return;
    2882             :         }
    2883             : 
    2884         301 :         dcesrv_terminate_connection(call->conn, call->terminate_reason);
    2885             : }
    2886             : 
    2887             : static void dcesrv_conn_wait_done(struct tevent_req *subreq);
    2888             : 
    2889      228314 : static void dcesrv_read_fragment_done(struct tevent_req *subreq)
    2890             : {
    2891      228314 :         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
    2892             :                                              struct dcesrv_connection);
    2893      228314 :         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
    2894             :         struct ncacn_packet *pkt;
    2895             :         DATA_BLOB buffer;
    2896             :         NTSTATUS status;
    2897             : 
    2898      228314 :         if (dce_conn->terminate) {
    2899             :                 /*
    2900             :                  * if the current connection is broken
    2901             :                  * we need to clean it up before any other connection
    2902             :                  */
    2903           0 :                 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
    2904           0 :                 dcesrv_cleanup_broken_connections(dce_ctx);
    2905        2673 :                 return;
    2906             :         }
    2907             : 
    2908      228314 :         dcesrv_cleanup_broken_connections(dce_ctx);
    2909             : 
    2910      228314 :         status = dcerpc_read_ncacn_packet_recv(subreq, dce_conn,
    2911             :                                                &pkt, &buffer);
    2912      228314 :         TALLOC_FREE(subreq);
    2913      228314 :         if (!NT_STATUS_IS_OK(status)) {
    2914       16656 :                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
    2915       16355 :                 return;
    2916             :         }
    2917             : 
    2918      211658 :         dcesrv_loop_next_packet(dce_conn, pkt, buffer);
    2919             : }
    2920             : 
    2921             : /**
    2922             :  * @brief Start the dcesrv loop, inducing the bind as a blob
    2923             :  *
    2924             :  * Like dcesrv_connection_loop_start() but used from connections
    2925             :  * where the caller has already read the dcerpc bind packet from
    2926             :  * the socket and is available as a DATA_BLOB.
    2927             :  *
    2928             :  * @param[in] dce_conn The connection to start
    2929             :  * @param[in] pkt The parsed bind packet
    2930             :  * @param[in] buffer The full binary bind including auth data
    2931             :  */
    2932      212344 : void dcesrv_loop_next_packet(
    2933             :         struct dcesrv_connection *dce_conn,
    2934             :         struct ncacn_packet *pkt,
    2935             :         DATA_BLOB buffer)
    2936             : {
    2937      212344 :         struct tevent_req *subreq = NULL;
    2938             :         NTSTATUS status;
    2939             : 
    2940      212344 :         status = dcesrv_process_ncacn_packet(dce_conn, pkt, buffer);
    2941      212342 :         if (!NT_STATUS_IS_OK(status)) {
    2942           0 :                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
    2943        1692 :                 return;
    2944             :         }
    2945             : 
    2946             :         /*
    2947             :          * This is used to block the connection during
    2948             :          * pending authentication.
    2949             :          */
    2950      212342 :         if (dce_conn->wait_send != NULL) {
    2951       12508 :                 subreq = dce_conn->wait_send(dce_conn,
    2952             :                                              dce_conn->event_ctx,
    2953             :                                              dce_conn->wait_private);
    2954       12508 :                 if (!subreq) {
    2955           0 :                         status = NT_STATUS_NO_MEMORY;
    2956           0 :                         dcesrv_terminate_connection(dce_conn, nt_errstr(status));
    2957           0 :                         return;
    2958             :                 }
    2959       12508 :                 tevent_req_set_callback(subreq, dcesrv_conn_wait_done, dce_conn);
    2960       12508 :                 return;
    2961             :         }
    2962             : 
    2963      199834 :         subreq = dcerpc_read_ncacn_packet_send(dce_conn,
    2964             :                                                dce_conn->event_ctx,
    2965             :                                                dce_conn->stream);
    2966      199834 :         if (!subreq) {
    2967           0 :                 status = NT_STATUS_NO_MEMORY;
    2968           0 :                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
    2969           0 :                 return;
    2970             :         }
    2971      199834 :         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, dce_conn);
    2972             : }
    2973             : 
    2974       12508 : static void dcesrv_conn_wait_done(struct tevent_req *subreq)
    2975             : {
    2976       12508 :         struct dcesrv_connection *dce_conn = tevent_req_callback_data(subreq,
    2977             :                                              struct dcesrv_connection);
    2978       12508 :         struct dcesrv_context *dce_ctx = dce_conn->dce_ctx;
    2979             :         NTSTATUS status;
    2980             : 
    2981       12508 :         if (dce_conn->terminate) {
    2982             :                 /*
    2983             :                  * if the current connection is broken
    2984             :                  * we need to clean it up before any other connection
    2985             :                  */
    2986           0 :                 dcesrv_terminate_connection(dce_conn, dce_conn->terminate);
    2987           0 :                 dcesrv_cleanup_broken_connections(dce_ctx);
    2988           0 :                 return;
    2989             :         }
    2990             : 
    2991       12508 :         dcesrv_cleanup_broken_connections(dce_ctx);
    2992             : 
    2993       12508 :         status = dce_conn->wait_recv(subreq);
    2994       12508 :         dce_conn->wait_send = NULL;
    2995       12508 :         dce_conn->wait_recv = NULL;
    2996       12508 :         dce_conn->wait_private = NULL;
    2997       12508 :         TALLOC_FREE(subreq);
    2998       12508 :         if (!NT_STATUS_IS_OK(status)) {
    2999           0 :                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
    3000           0 :                 return;
    3001             :         }
    3002             : 
    3003       12508 :         status = dcesrv_connection_loop_start(dce_conn);
    3004       12508 :         if (!NT_STATUS_IS_OK(status)) {
    3005           0 :                 dcesrv_terminate_connection(dce_conn, nt_errstr(status));
    3006           0 :                 return;
    3007             :         }
    3008             : }
    3009             : 
    3010             : /**
    3011             :  * retrieve credentials from a dce_call
    3012             :  */
    3013           4 : _PUBLIC_ struct cli_credentials *dcesrv_call_credentials(struct dcesrv_call_state *dce_call)
    3014             : {
    3015           4 :         struct dcesrv_auth *auth = dce_call->auth_state;
    3016           4 :         SMB_ASSERT(auth->auth_finished);
    3017           4 :         return auth->session_info->credentials;
    3018             : }
    3019             : 
    3020             : /**
    3021             :  * returns true if this is an authenticated call
    3022             :  */
    3023           0 : _PUBLIC_ bool dcesrv_call_authenticated(struct dcesrv_call_state *dce_call)
    3024             : {
    3025           0 :         struct dcesrv_auth *auth = dce_call->auth_state;
    3026             :         enum security_user_level level;
    3027           0 :         SMB_ASSERT(auth->auth_finished);
    3028           0 :         level = security_session_user_level(auth->session_info, NULL);
    3029           0 :         return level >= SECURITY_USER;
    3030             : }
    3031             : 
    3032             : /**
    3033             :  * retrieve account_name for a dce_call
    3034             :  */
    3035           0 : _PUBLIC_ const char *dcesrv_call_account_name(struct dcesrv_call_state *dce_call)
    3036             : {
    3037           0 :         struct dcesrv_auth *auth = dce_call->auth_state;
    3038           0 :         SMB_ASSERT(auth->auth_finished);
    3039           0 :         return auth->session_info->info->account_name;
    3040             : }
    3041             : 
    3042             : /**
    3043             :  * retrieve session_info from a dce_call
    3044             :  */
    3045      224229 : _PUBLIC_ struct auth_session_info *dcesrv_call_session_info(struct dcesrv_call_state *dce_call)
    3046             : {
    3047      224229 :         struct dcesrv_auth *auth = dce_call->auth_state;
    3048      224229 :         SMB_ASSERT(auth->auth_finished);
    3049      224229 :         return auth->session_info;
    3050             : }
    3051             : 
    3052             : /**
    3053             :  * retrieve auth type/level from a dce_call
    3054             :  */
    3055       30601 : _PUBLIC_ void dcesrv_call_auth_info(struct dcesrv_call_state *dce_call,
    3056             :                                     enum dcerpc_AuthType *auth_type,
    3057             :                                     enum dcerpc_AuthLevel *auth_level)
    3058             : {
    3059       30601 :         struct dcesrv_auth *auth = dce_call->auth_state;
    3060             : 
    3061       30601 :         SMB_ASSERT(auth->auth_finished);
    3062             : 
    3063       30601 :         if (auth_type != NULL) {
    3064       19658 :                 *auth_type = auth->auth_type;
    3065             :         }
    3066       30601 :         if (auth_level != NULL) {
    3067       29076 :                 *auth_level = auth->auth_level;
    3068             :         }
    3069       30601 : }
    3070             : 
    3071       28797 : _PUBLIC_ NTSTATUS dcesrv_connection_loop_start(struct dcesrv_connection *conn)
    3072             : {
    3073             :         struct tevent_req *subreq;
    3074             : 
    3075       28797 :         subreq = dcerpc_read_ncacn_packet_send(conn,
    3076             :                                                conn->event_ctx,
    3077             :                                                conn->stream);
    3078       28797 :         if (subreq == NULL) {
    3079           0 :                 return NT_STATUS_NO_MEMORY;
    3080             :         }
    3081       28797 :         tevent_req_set_callback(subreq, dcesrv_read_fragment_done, conn);
    3082             : 
    3083       28797 :         return NT_STATUS_OK;
    3084             : }
    3085             : 
    3086           0 : _PUBLIC_ NTSTATUS dcesrv_call_dispatch_local(struct dcesrv_call_state *call)
    3087             : {
    3088             :         NTSTATUS status;
    3089           0 :         struct ndr_pull *pull = NULL;
    3090           0 :         struct ndr_push *push = NULL;
    3091           0 :         struct data_blob_list_item *rep = NULL;
    3092             : 
    3093           0 :         pull = ndr_pull_init_blob(&call->pkt.u.request.stub_and_verifier,
    3094             :                                   call);
    3095           0 :         if (pull == NULL) {
    3096           0 :                 return NT_STATUS_NO_MEMORY;
    3097             :         }
    3098             : 
    3099           0 :         pull->flags |= LIBNDR_FLAG_REF_ALLOC;
    3100             : 
    3101           0 :         call->ndr_pull = pull;
    3102             : 
    3103             :         /* unravel the NDR for the packet */
    3104           0 :         status = call->context->iface->ndr_pull(call, call, pull, &call->r);
    3105           0 :         if (!NT_STATUS_IS_OK(status)) {
    3106           0 :                 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
    3107             :                          call->context->iface->name,
    3108             :                          call->pkt.u.request.opnum,
    3109             :                          dcerpc_errstr(call, call->fault_code));
    3110           0 :                 return dcerpc_fault_to_nt_status(call->fault_code);
    3111             :         }
    3112             : 
    3113           0 :         status = call->context->iface->local(call, call, call->r);
    3114           0 :         if (!NT_STATUS_IS_OK(status)) {
    3115           0 :                 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
    3116             :                          call->context->iface->name,
    3117             :                          call->pkt.u.request.opnum,
    3118             :                          dcerpc_errstr(call, call->fault_code));
    3119           0 :                 return dcerpc_fault_to_nt_status(call->fault_code);
    3120             :         }
    3121             : 
    3122             :         /* This can never go async for now! */
    3123           0 :         SMB_ASSERT(!(call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC));
    3124             : 
    3125             :         /* call the reply function */
    3126           0 :         status = call->context->iface->reply(call, call, call->r);
    3127           0 :         if (!NT_STATUS_IS_OK(status)) {
    3128           0 :                 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
    3129             :                          call->context->iface->name,
    3130             :                          call->pkt.u.request.opnum,
    3131             :                          dcerpc_errstr(call, call->fault_code));
    3132           0 :                 return dcerpc_fault_to_nt_status(call->fault_code);
    3133             :         }
    3134             : 
    3135           0 :         push = ndr_push_init_ctx(call);
    3136           0 :         if (push == NULL) {
    3137           0 :                 return NT_STATUS_NO_MEMORY;
    3138             :         }
    3139             : 
    3140           0 :         push->ptr_count = call->ndr_pull->ptr_count;
    3141             : 
    3142           0 :         status = call->context->iface->ndr_push(call, call, push, call->r);
    3143           0 :         if (!NT_STATUS_IS_OK(status)) {
    3144           0 :                 DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n",
    3145             :                          call->context->iface->name,
    3146             :                          call->pkt.u.request.opnum,
    3147             :                          dcerpc_errstr(call, call->fault_code));
    3148           0 :                 return dcerpc_fault_to_nt_status(call->fault_code);
    3149             :         }
    3150             : 
    3151           0 :         rep = talloc_zero(call, struct data_blob_list_item);
    3152           0 :         if (rep == NULL) {
    3153           0 :                 return NT_STATUS_NO_MEMORY;
    3154             :         }
    3155             : 
    3156           0 :         rep->blob = ndr_push_blob(push);
    3157           0 :         DLIST_ADD_END(call->replies, rep);
    3158             : 
    3159           0 :         return NT_STATUS_OK;
    3160             : }

Generated by: LCOV version 1.13