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

Generated by: LCOV version 1.14