s3-rpc: when using rpc_pipe_open_internal, make sure to go through NDR.
authorGünther Deschner <gd@samba.org>
Fri, 2 Jul 2010 08:17:44 +0000 (10:17 +0200)
committerGünther Deschner <gd@samba.org>
Thu, 8 Jul 2010 14:35:26 +0000 (16:35 +0200)
Otherwise a lot of information that is usually generated in the ndr_push remains
in an uninitialized state.

Guenther

pidl/lib/Parse/Pidl/Samba3/ServerNDR.pm
source3/include/proto.h
source3/rpc_server/rpc_ncacn_np_internal.c
source3/rpc_server/srv_netlog_nt.c
source3/rpc_server/srv_pipe_hnd.c
source3/rpc_server/srv_spoolss_util.c
source3/smbd/lanman.c
source3/winbindd/winbindd.c
source3/winbindd/winbindd_samr.c

index 311eb5b6198c008c9b68243ee0e45ece476e601f..a25d12bfea4ea627a2e5b96028c7cfa436773c44 100644 (file)
@@ -225,58 +225,6 @@ sub ParseFunction($$)
        pidl "";
 }
 
-sub ParseDispatchFunction($)
-{
-       my ($if) = @_;
-
-       pidl_hdr "NTSTATUS rpc_$if->{NAME}_dispatch(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const struct ndr_interface_table *table, uint32_t opnum, void *r);";
-       pidl "NTSTATUS rpc_$if->{NAME}_dispatch(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const struct ndr_interface_table *table, uint32_t opnum, void *_r)";
-       pidl "{";
-       indent;
-       pidl "if (cli->pipes_struct == NULL) {";
-       pidl "\treturn NT_STATUS_INVALID_PARAMETER;";
-       pidl "}";
-       pidl "";
-       pidl "/* set opnum in fake rpc header */";
-       pidl "cli->pipes_struct->hdr_req.opnum = opnum;";
-       pidl "";
-       pidl "switch (opnum)";
-       pidl "{";
-       indent;
-       foreach my $fn (@{$if->{FUNCTIONS}}) {
-               next if ($fn->{PROPERTIES}{noopnum});
-               my $op = "NDR_".uc($fn->{NAME});
-               pidl "case $op: {";
-               indent;
-               pidl "struct $fn->{NAME} *r = (struct $fn->{NAME} *)_r;";
-
-               pidl "if (DEBUGLEVEL >= 10) {";
-               pidl "\tNDR_PRINT_IN_DEBUG($fn->{NAME}, r);";
-               pidl "}";
-
-               CallWithStruct("cli->pipes_struct", "mem_ctx", $fn, 
-                       sub { pidl "\treturn NT_STATUS_NO_MEMORY;"; });
-
-               pidl "if (DEBUGLEVEL >= 10) {";
-               pidl "\tNDR_PRINT_OUT_DEBUG($fn->{NAME}, r);";
-               pidl "}";
-
-               pidl "return NT_STATUS_OK;";
-               deindent;
-               pidl "}";
-               pidl "";
-       }
-
-       pidl "default:";
-       pidl "\treturn NT_STATUS_NOT_IMPLEMENTED;";
-       deindent;
-       pidl "}";
-       deindent;
-       pidl "}";
-
-       pidl "";
-}
-
 sub ParseInterface($)
 {
        my $if = shift;
@@ -317,8 +265,6 @@ sub ParseInterface($)
        pidl "}";
        pidl "";
 
-       ParseDispatchFunction($if);
-
        if (not has_property($if, "no_srv_register")) {
            pidl_hdr "NTSTATUS rpc_$if->{NAME}_init(void);";
            pidl "NTSTATUS rpc_$if->{NAME}_init(void)";
index d08dc59ecba8655ab5c9990d47539bfddbc3ee71..8ce2bf169cf5ac4b2e9e8aa31e6c8cb23a332969 100644 (file)
@@ -4875,7 +4875,6 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
                                              const char *client_address,
                                              struct auth_serversupplied_info *server_info);
 NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *abstract_syntax,
-                               NTSTATUS (*dispatch) (struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const struct ndr_interface_table *table, uint32_t opnum, void *r),
                                struct auth_serversupplied_info *serversupplied_info,
                                struct rpc_pipe_client **presult);
 NTSTATUS rpc_connect_spoolss_pipe(connection_struct *conn,
index f9317b9756d37171399592a37dac07653a2f7aba..d702e4b4d7b03a8c612fc5d8ed05de7a18feb55d 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 #include "includes.h"
+#include "rpc_server/srv_pipe_internal.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
@@ -186,6 +187,155 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
        return p;
 }
 
+/****************************************************************************
+****************************************************************************/
+
+static NTSTATUS internal_ndr_push(TALLOC_CTX *mem_ctx,
+                                 struct rpc_pipe_client *cli,
+                                 const struct ndr_interface_table *table,
+                                 uint32_t opnum,
+                                 void *r)
+{
+       const struct ndr_interface_call *call;
+       struct ndr_push *push;
+       enum ndr_err_code ndr_err;
+       DATA_BLOB blob;
+       bool ret;
+
+       if (!ndr_syntax_id_equal(&table->syntax_id, &cli->abstract_syntax) ||
+           (opnum >= table->num_calls)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       call = &table->calls[opnum];
+
+       if (DEBUGLEVEL >= 10) {
+               ndr_print_function_debug(call->ndr_print,
+                                        call->name, NDR_IN, r);
+       }
+
+       push = ndr_push_init_ctx(mem_ctx);
+       if (push == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ndr_err = call->ndr_push(push, NDR_IN, r);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               TALLOC_FREE(push);
+               return ndr_map_error2ntstatus(ndr_err);
+       }
+
+       blob = ndr_push_blob(push);
+       ret = prs_init_data_blob(&cli->pipes_struct->in_data.data, &blob, mem_ctx);
+       TALLOC_FREE(push);
+       if (!ret) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       return NT_STATUS_OK;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static NTSTATUS internal_ndr_pull(TALLOC_CTX *mem_ctx,
+                                 struct rpc_pipe_client *cli,
+                                 const struct ndr_interface_table *table,
+                                 uint32_t opnum,
+                                 void *r)
+{
+       const struct ndr_interface_call *call;
+       struct ndr_pull *pull;
+       enum ndr_err_code ndr_err;
+       DATA_BLOB blob;
+       bool ret;
+
+       if (!ndr_syntax_id_equal(&table->syntax_id, &cli->abstract_syntax) ||
+           (opnum >= table->num_calls)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       call = &table->calls[opnum];
+
+       ret = prs_data_blob(&cli->pipes_struct->out_data.rdata, &blob, mem_ctx);
+       if (!ret) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       pull = ndr_pull_init_blob(&blob, mem_ctx);
+       if (pull == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* have the ndr parser alloc memory for us */
+       pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+       ndr_err = call->ndr_pull(pull, NDR_OUT, r);
+       TALLOC_FREE(pull);
+
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return ndr_map_error2ntstatus(ndr_err);
+       }
+
+       if (DEBUGLEVEL >= 10) {
+               ndr_print_function_debug(call->ndr_print,
+                                        call->name, NDR_OUT, r);
+       }
+
+       return NT_STATUS_OK;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static NTSTATUS rpc_pipe_internal_dispatch(struct rpc_pipe_client *cli,
+                                          TALLOC_CTX *mem_ctx,
+                                          const struct ndr_interface_table *table,
+                                          uint32_t opnum, void *r)
+{
+       NTSTATUS status;
+       int num_cmds = rpc_srv_get_pipe_num_cmds(&table->syntax_id);
+       const struct api_struct *cmds = rpc_srv_get_pipe_cmds(&table->syntax_id);
+       int i;
+
+       if (cli->pipes_struct == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       /* set opnum in fake rpc header */
+       cli->pipes_struct->hdr_req.opnum = opnum;
+
+       for (i = 0; i < num_cmds; i++) {
+               if (cmds[i].opnum == opnum && cmds[i].fn != NULL) {
+                       break;
+               }
+       }
+
+       if (i == num_cmds) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       prs_init_empty(&cli->pipes_struct->out_data.rdata, cli->pipes_struct->mem_ctx, MARSHALL);
+
+       status = internal_ndr_push(mem_ctx, cli, table, opnum, r);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (!cmds[i].fn(cli->pipes_struct)) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       status = internal_ndr_pull(mem_ctx, cli, table, opnum, r);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       prs_mem_free(&cli->pipes_struct->in_data.data);
+       prs_mem_free(&cli->pipes_struct->out_data.rdata);
+
+       return NT_STATUS_OK;
+}
+
 /**
  * @brief Create a new RPC client context which uses a local dispatch function.
  *
@@ -217,10 +367,6 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
  */
 NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx,
                                const struct ndr_syntax_id *abstract_syntax,
-                               NTSTATUS (*dispatch) (struct rpc_pipe_client *cli,
-                                                     TALLOC_CTX *mem_ctx,
-                                                     const struct ndr_interface_table *table,
-                                                     uint32_t opnum, void *r),
                                struct auth_serversupplied_info *serversupplied_info,
                                struct rpc_pipe_client **presult)
 {
@@ -233,7 +379,7 @@ NTSTATUS rpc_pipe_open_internal(TALLOC_CTX *mem_ctx,
 
        result->abstract_syntax = *abstract_syntax;
        result->transfer_syntax = ndr_transfer_syntax;
-       result->dispatch = dispatch;
+       result->dispatch = rpc_pipe_internal_dispatch;
 
        result->pipes_struct = make_internal_rpc_pipe_p(
                result, abstract_syntax, "", serversupplied_info);
index cccd0d570aec41880d1553580c501afcb08835e0..c7ff3ddeeb55ab96e97d8b24d6a4d932ca1aba8c 100644 (file)
@@ -406,7 +406,7 @@ NTSTATUS _netr_NetrEnumerateTrustedDomains(pipes_struct *p,
        DEBUG(6,("_netr_NetrEnumerateTrustedDomains: %d\n", __LINE__));
 
        status = rpc_pipe_open_internal(p->mem_ctx, &ndr_table_lsarpc.syntax_id,
-                                       rpc_lsarpc_dispatch, p->server_info,
+                                       p->server_info,
                                        &cli);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -629,7 +629,7 @@ static NTSTATUS get_md4pw(struct samr_Password *md4pw, const char *mach_acct,
        ZERO_STRUCT(user_handle);
 
        status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
-                                       rpc_samr_dispatch, server_info,
+                                       server_info,
                                        &cli);
        if (!NT_STATUS_IS_OK(status)) {
                goto out;
@@ -1032,7 +1032,7 @@ static NTSTATUS netr_set_machine_account_password(TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(user_handle);
 
        status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
-                                       rpc_samr_dispatch, server_info,
+                                       server_info,
                                        &cli);
        if (!NT_STATUS_IS_OK(status)) {
                goto out;
index e9339929dffff2f1c0aee30639c18c397e50f25e..9ed54a4e1047c484dccf33c0fdb84da6b4f53989 100644 (file)
@@ -1411,7 +1411,6 @@ NTSTATUS rpc_connect_spoolss_pipe(connection_struct *conn,
        if (!conn->spoolss_pipe) {
                status = rpc_pipe_open_internal(conn,
                                                &ndr_table_spoolss.syntax_id,
-                                               rpc_spoolss_dispatch,
                                                conn->server_info,
                                                &conn->spoolss_pipe);
                if (!NT_STATUS_IS_OK(status)) {
index 4c70ce4edb86c16f6b9f90cb002eb319109364d4..49f6a71433dd14dfbc8c5bd74261e98c18bdeeee 100644 (file)
@@ -250,7 +250,6 @@ static WERROR winreg_printer_openkey(TALLOC_CTX *mem_ctx,
        /* create winreg connection */
        status = rpc_pipe_open_internal(mem_ctx,
                                        &ndr_table_winreg.syntax_id,
-                                       rpc_winreg_dispatch,
                                        server_info,
                                        &pipe_handle);
        if (!NT_STATUS_IS_OK(status)) {
index ba51c617df4877ed80edd1e8a7a2cf81630e8206..ce7ad0e56d27fddff26a6c5859c51964c2f3e083 100644 (file)
@@ -2235,7 +2235,7 @@ static bool api_RNetShareAdd(struct smbd_server_connection *sconn,
        }
 
        status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
-                                       rpc_srvsvc_dispatch, conn->server_info,
+                                       conn->server_info,
                                        &cli);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
@@ -2341,7 +2341,7 @@ static bool api_RNetGroupEnum(struct smbd_server_connection *sconn,
        }
 
        status = rpc_pipe_open_internal(
-               talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
+               talloc_tos(), &ndr_table_samr.syntax_id,
                conn->server_info, &samr_pipe);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
@@ -2523,7 +2523,7 @@ static bool api_NetUserGetGroups(struct smbd_server_connection *sconn,
        endp = *rdata + *rdata_len;
 
        status = rpc_pipe_open_internal(
-               talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
+               talloc_tos(), &ndr_table_samr.syntax_id,
                conn->server_info, &samr_pipe);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
@@ -2679,7 +2679,7 @@ static bool api_RNetUserEnum(struct smbd_server_connection *sconn,
        endp = *rdata + *rdata_len;
 
        status = rpc_pipe_open_internal(
-               talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
+               talloc_tos(), &ndr_table_samr.syntax_id,
                conn->server_info, &samr_pipe);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
@@ -2922,7 +2922,7 @@ static bool api_SetUserPassword(struct smbd_server_connection *sconn,
        ZERO_STRUCT(user_handle);
 
        status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
-                                       rpc_samr_dispatch, conn->server_info,
+                                       conn->server_info,
                                        &cli);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
@@ -3138,7 +3138,7 @@ static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn,
        memcpy(hash.hash, data+516, 16);
 
        status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
-                                       rpc_samr_dispatch, conn->server_info,
+                                       conn->server_info,
                                        &cli);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
@@ -3691,7 +3691,7 @@ static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn,
        p2 = p + struct_len;
 
        status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
-                                       rpc_srvsvc_dispatch, conn->server_info,
+                                       conn->server_info,
                                        &cli);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
@@ -4113,7 +4113,7 @@ static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn,
        ZERO_STRUCT(user_handle);
 
        status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
-                                       rpc_samr_dispatch, conn->server_info,
+                                       conn->server_info,
                                        &cli);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
index 25d4e1d3d4ad450c08400c12ef25fa92919bee44..7e1eb3e71400cea8eaff9850a29f31ed983141d3 100644 (file)
@@ -26,6 +26,8 @@
 #include "winbindd.h"
 #include "../../nsswitch/libwbclient/wbc_async.h"
 #include "librpc/gen_ndr/messaging.h"
+#include "../librpc/gen_ndr/srv_lsa.h"
+#include "../librpc/gen_ndr/srv_samr.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
@@ -1289,6 +1291,9 @@ int main(int argc, char **argv, char **envp)
 
        winbindd_register_handlers();
 
+       rpc_lsarpc_init();
+       rpc_samr_init();
+
        if (!init_system_info()) {
                DEBUG(0,("ERROR: failed to setup system user info.\n"));
                exit(1);
index a2865a0bca8d9f08dbde73c44f0ca25802998033..e9e3e6f30d5214119d1dfb9e4cde59c0bea29d25 100644 (file)
@@ -60,7 +60,6 @@ static NTSTATUS open_internal_samr_pipe(TALLOC_CTX *mem_ctx,
        /* create a samr connection */
        status = rpc_pipe_open_internal(mem_ctx,
                                        &ndr_table_samr.syntax_id,
-                                       rpc_samr_dispatch,
                                        server_info,
                                        &cli);
        if (!NT_STATUS_IS_OK(status)) {
@@ -132,7 +131,6 @@ static NTSTATUS open_internal_lsa_pipe(TALLOC_CTX *mem_ctx,
        /* create a samr connection */
        status = rpc_pipe_open_internal(mem_ctx,
                                        &ndr_table_lsarpc.syntax_id,
-                                       rpc_lsarpc_dispatch,
                                        server_info,
                                        &cli);
        if (!NT_STATUS_IS_OK(status)) {