LCOV - code coverage report
Current view: top level - librpc/rpc - dcesrv_core.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 1235 1518 81.4 %
Date: 2023-11-21 12:31:41 Functions: 72 76 94.7 %

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

Generated by: LCOV version 1.14