s3-rpc_server: enforce packet level authentication for iremotewinspool server
[samba.git] / source3 / rpc_server / rpc_ncacn_np.c
index 5c3c875a08c15c71b76fff9de6662c1ff689f314..14014ef7e8d85545b1cc660f67480bdc4590b61c 100644 (file)
@@ -37,6 +37,7 @@
 #include "rpc_contexts.h"
 #include "rpc_server/rpc_config.h"
 #include "librpc/ndr/ndr_table.h"
+#include "rpc_server/rpc_server.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
@@ -68,6 +69,113 @@ fail:
        return NULL;
 }
 
+NTSTATUS make_internal_rpc_pipe_socketpair(TALLOC_CTX *mem_ctx,
+                                          struct tevent_context *ev_ctx,
+                                          struct messaging_context *msg_ctx,
+                                          const char *pipe_name,
+                                          const struct ndr_syntax_id *syntax,
+                                          const struct tsocket_address *remote_address,
+                                          const struct auth_session_info *session_info,
+                                          struct npa_state **pnpa)
+{
+       TALLOC_CTX *tmp_ctx = talloc_stackframe();
+       struct named_pipe_client *npc;
+       struct tevent_req *subreq;
+       struct npa_state *npa;
+       NTSTATUS status;
+       int error;
+       int rc;
+
+       DEBUG(4, ("Create of internal pipe %s requested\n", pipe_name));
+
+       npa = npa_state_init(tmp_ctx);
+       if (npa == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
+       }
+
+       npa->file_type = FILE_TYPE_MESSAGE_MODE_PIPE;
+       npa->device_state = 0xff | 0x0400 | 0x0100;
+       npa->allocation_size = 4096;
+
+       npc = named_pipe_client_init(npa,
+                                    ev_ctx,
+                                    msg_ctx,
+                                    pipe_name,
+                                    NULL, /* term_fn */
+                                    npa->file_type,
+                                    npa->device_state,
+                                    npa->allocation_size,
+                                    NULL); /* private_data */
+       if (npc == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
+       }
+       npa->private_data = (void*) npc;
+
+       rc = tstream_npa_socketpair(npa->file_type,
+                                   npa,
+                                   &npa->stream,
+                                   npc,
+                                   &npc->tstream);
+       if (rc == -1) {
+               status = map_nt_error_from_unix(errno);
+               goto out;
+       }
+
+       npc->client = tsocket_address_copy(remote_address, npc);
+       if (npc->client == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
+       }
+
+       npc->client_name = tsocket_address_inet_addr_string(npc->client, npc);
+       if (npc->client_name == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
+       }
+
+       npc->session_info = copy_session_info(npc, session_info);
+       if (npc->session_info == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
+       }
+
+       rc = make_server_pipes_struct(npc,
+                                     npc->msg_ctx,
+                                     npc->pipe_name,
+                                     NCACN_NP,
+                                     npc->server,
+                                     npc->client,
+                                     npc->session_info,
+                                     &npc->p,
+                                     &error);
+       if (rc == -1) {
+               status = map_nt_error_from_unix(error);
+               goto out;
+       }
+
+       npc->write_queue = tevent_queue_create(npc, "npa_server_write_queue");
+       if (npc->write_queue == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto out;
+       }
+
+       subreq = dcerpc_read_ncacn_packet_send(npc, npc->ev, npc->tstream);
+       if (subreq == NULL) {
+               DEBUG(2, ("Failed to start receving packets\n"));
+               status = NT_STATUS_PIPE_BROKEN;
+               goto out;
+       }
+       tevent_req_set_callback(subreq, named_pipe_packet_process, npc);
+
+       *pnpa = talloc_steal(mem_ctx, npa);
+       status = NT_STATUS_OK;
+out:
+       talloc_free(tmp_ctx);
+       return status;
+}
+
 /****************************************************************************
  Make an internal namedpipes structure
 ****************************************************************************/
@@ -95,7 +203,7 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
        DEBUG(4,("Create pipe requested %s\n", pipe_name));
 
        ret = make_base_pipes_struct(mem_ctx, msg_ctx, pipe_name,
-                                    NCALRPC, RPC_LITTLE_ENDIAN, false,
+                                    NCALRPC, RPC_LITTLE_ENDIAN,
                                     remote_address, NULL, &p);
        if (ret) {
                DEBUG(0,("ERROR! no memory for pipes_struct!\n"));
@@ -116,7 +224,7 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
                return NULL;
        }
 
-       context_fns = talloc(p, struct pipe_rpc_fns);
+       context_fns = talloc_zero(p, struct pipe_rpc_fns);
        if (context_fns == NULL) {
                DEBUG(0,("talloc() failed!\n"));
                TALLOC_FREE(p);
@@ -471,8 +579,7 @@ NTSTATUS rpcint_binding_handle(TALLOC_CTX *mem_ctx,
  *
  * @param[in]  mem_ctx  The memory context to use.
  *
- * @param[in]  abstract_syntax Normally the syntax_id of the autogenerated
- *                             ndr_table_<name>.
+ * @param[in]  ndr_table the ndr_table_<name> structure.
  *
  * @param[in]  serversupplied_info The server supplied authentication function.
  *
@@ -486,7 +593,7 @@ NTSTATUS rpcint_binding_handle(TALLOC_CTX *mem_ctx,
  *                      error occured.
  */
 NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx,
-                               const struct ndr_syntax_id *abstract_syntax,
+                               const struct ndr_interface_table *ndr_table,
                                const struct auth_session_info *session_info,
                                const struct tsocket_address *remote_address,
                                struct messaging_context *msg_ctx,
@@ -500,7 +607,7 @@ NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx,
                return NT_STATUS_NO_MEMORY;
        }
 
-       result->abstract_syntax = *abstract_syntax;
+       result->abstract_syntax = ndr_table->syntax_id;
        result->transfer_syntax = ndr_transfer_syntax_ndr;
 
        if (remote_address == NULL) {
@@ -521,15 +628,13 @@ NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx,
        }
 
        result->max_xmit_frag = -1;
-       result->max_recv_frag = -1;
-
-       status = rpcint_binding_handle_ex(result,
-                                         abstract_syntax,
-                                         NULL,
-                                         remote_address,
-                                         session_info,
-                                         msg_ctx,
-                                         &result->binding_handle);
+
+       status = rpcint_binding_handle(result,
+                                      ndr_table,
+                                      remote_address,
+                                      session_info,
+                                      msg_ctx,
+                                      &result->binding_handle);
        if (!NT_STATUS_IS_OK(status)) {
                TALLOC_FREE(result);
                return status;
@@ -601,9 +706,9 @@ NTSTATUS make_external_rpc_pipe(TALLOC_CTX *mem_ctx,
                goto out;
        }
 
-       ev_ctx = s3_tevent_context_init(tmp_ctx);
+       ev_ctx = samba_tevent_context_init(tmp_ctx);
        if (ev_ctx == NULL) {
-               DEBUG(0, ("s3_tevent_context_init failed\n"));
+               DEBUG(0, ("samba_tevent_context_init failed\n"));
                status = NT_STATUS_NO_MEMORY;
                goto out;
        }
@@ -709,9 +814,9 @@ struct np_proxy_state *make_external_rpc_pipe_p(TALLOC_CTX *mem_ctx,
                goto fail;
        }
 
-       ev = s3_tevent_context_init(talloc_tos());
+       ev = samba_tevent_context_init(talloc_tos());
        if (ev == NULL) {
-               DEBUG(0, ("s3_tevent_context_init failed\n"));
+               DEBUG(0, ("samba_tevent_context_init failed\n"));
                goto fail;
        }
 
@@ -824,6 +929,7 @@ static NTSTATUS rpc_pipe_open_external(TALLOC_CTX *mem_ctx,
        proxy_state = make_external_rpc_pipe_p(mem_ctx, pipe_name,
                                                local, remote, session_info);
        if (!proxy_state) {
+               DEBUG(1, ("Unable to make proxy_state for connection to %s.\n", pipe_name));
                return NT_STATUS_UNSUCCESSFUL;
        }
 
@@ -845,7 +951,6 @@ static NTSTATUS rpc_pipe_open_external(TALLOC_CTX *mem_ctx,
        }
 
        result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
-       result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
 
        status = rpc_transport_tstream_init(result,
                                            &proxy_state->npipe,
@@ -868,6 +973,7 @@ static NTSTATUS rpc_pipe_open_external(TALLOC_CTX *mem_ctx,
        }
        result->auth->auth_type = DCERPC_AUTH_TYPE_NONE;
        result->auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
+       result->auth->auth_context_id = 0;
 
        status = rpccli_anon_bind_data(result, &auth);
        if (!NT_STATUS_IS_OK(status)) {
@@ -951,6 +1057,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx,
 
        pipe_name = dcerpc_default_transport_endpoint(mem_ctx, NCACN_NP, table);
        if (pipe_name == NULL) {
+               DEBUG(1, ("Unable to find pipe name to forward %s to.\n", table->name));
                status = NT_STATUS_INVALID_PARAMETER;
                goto done;
        }
@@ -966,7 +1073,7 @@ NTSTATUS rpc_pipe_open_interface(TALLOC_CTX *mem_ctx,
        switch (pipe_mode) {
        case RPC_SERVICE_MODE_EMBEDDED:
                status = rpc_pipe_open_internal(tmp_ctx,
-                                               &table->syntax_id, session_info,
+                                               table, session_info,
                                                remote_address, msg_ctx,
                                                &cli);
                if (!NT_STATUS_IS_OK(status)) {