s3-rpc: Seperate rpc_srv_register for plain connection.
authorAndreas Schneider <asn@samba.org>
Thu, 3 Jun 2010 20:01:46 +0000 (22:01 +0200)
committerSimo Sorce <idra@samba.org>
Fri, 4 Jun 2010 16:12:43 +0000 (12:12 -0400)
This will make it possible to create plain rpc named pipe connnections.

Reviewed-by: Simo Sorce <idra@samba.org>
source3/Makefile.in
source3/rpc_server/srv_pipe.c
source3/rpc_server/srv_pipe_internal.h [new file with mode: 0644]
source3/rpc_server/srv_pipe_register.c [new file with mode: 0644]
source3/wscript_build

index 91e1518e13f0d7caa53560e60c10fde66c64bc43..19bee48ab918de4d6ff940c8d39bfad90cac3b5f 100644 (file)
@@ -653,8 +653,7 @@ RPC_EVENTLOG_OBJ = rpc_server/srv_eventlog_nt.o \
 
 NPA_TSTREAM_OBJ = ../libcli/named_pipe_auth/npa_tstream.o
 
-RPC_PIPE_OBJ = rpc_server/srv_pipe_hnd.o \
-               rpc_server/srv_pipe.o rpc_server/srv_lsa_hnd.o
+RPC_PIPE_OBJ = rpc_server/srv_pipe.o rpc_server/srv_pipe_hnd.o rpc_server/srv_pipe_register.c
 
 RPC_ECHO_OBJ = rpc_server/srv_echo_nt.o librpc/gen_ndr/srv_echo.o
 
index 50914acfbde1f2122814e229645629ba8543c50c..fccc41c33a97c5f2dae97202c6e30538bc3e91d9 100644 (file)
@@ -28,6 +28,7 @@
  */
 
 #include "includes.h"
+#include "srv_pipe_internal.h"
 #include "../librpc/gen_ndr/ndr_schannel.h"
 #include "../libcli/auth/schannel.h"
 #include "../libcli/auth/spnego.h"
@@ -741,23 +742,6 @@ static bool pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
        return True;
 }
 
-/*******************************************************************
- The switch table for the pipe names and the functions to handle them.
-*******************************************************************/
-
-struct rpc_table {
-       struct {
-               const char *clnt;
-               const char *srv;
-       } pipe;
-       struct ndr_syntax_id rpc_interface;
-       const struct api_struct *cmds;
-       int n_cmds;
-};
-
-static struct rpc_table *rpc_lookup;
-static int rpc_lookup_size;
-
 /*******************************************************************
  This is the "stage3" NTLMSSP response after a bind request and reply.
 *******************************************************************/
@@ -1044,25 +1028,18 @@ static bool check_bind_req(struct pipes_struct *p,
                           struct ndr_syntax_id* transfer,
                           uint32 context_id)
 {
-       int i=0;
        struct pipe_rpc_fns *context_fns;
 
        DEBUG(3,("check_bind_req for %s\n",
                 get_pipe_name_from_syntax(talloc_tos(), &p->syntax)));
 
        /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */
-
-       for (i=0; i<rpc_lookup_size; i++) {
-               DEBUGADD(10, ("checking %s\n", rpc_lookup[i].pipe.clnt));
-               if (ndr_syntax_id_equal(
-                           abstract, &rpc_lookup[i].rpc_interface)
-                   && ndr_syntax_id_equal(
-                           transfer, &ndr_transfer_syntax)) {
-                       break;
-               }
-       }
-
-       if (i == rpc_lookup_size) {
+       if (rpc_srv_pipe_exists_by_id(abstract) &&
+          ndr_syntax_id_equal(transfer, &ndr_transfer_syntax)) {
+               DEBUG(3, ("check_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
+                       rpc_srv_get_pipe_cli_name(abstract),
+                       rpc_srv_get_pipe_srv_name(abstract)));
+       } else {
                return false;
        }
 
@@ -1072,8 +1049,8 @@ static bool check_bind_req(struct pipes_struct *p,
                return False;
        }
 
-       context_fns->cmds = rpc_lookup[i].cmds;
-       context_fns->n_cmds = rpc_lookup[i].n_cmds;
+       context_fns->n_cmds = rpc_srv_get_pipe_num_cmds(abstract);
+       context_fns->cmds = rpc_srv_get_pipe_cmds(abstract);
        context_fns->context_id = context_id;
 
        /* add to the list of open contexts */
@@ -1083,59 +1060,6 @@ static bool check_bind_req(struct pipes_struct *p,
        return True;
 }
 
-/*******************************************************************
- Register commands to an RPC pipe
-*******************************************************************/
-
-NTSTATUS rpc_srv_register(int version, const char *clnt, const char *srv,
-                         const struct ndr_interface_table *iface,
-                         const struct api_struct *cmds, int size)
-{
-        struct rpc_table *rpc_entry;
-
-       if (!clnt || !srv || !cmds) {
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       if (version != SMB_RPC_INTERFACE_VERSION) {
-               DEBUG(0,("Can't register rpc commands!\n"
-                        "You tried to register a rpc module with SMB_RPC_INTERFACE_VERSION %d"
-                        ", while this version of samba uses version %d!\n", 
-                        version,SMB_RPC_INTERFACE_VERSION));
-               return NT_STATUS_OBJECT_TYPE_MISMATCH;
-       }
-
-       /* TODO: 
-        *
-        * we still need to make sure that don't register the same commands twice!!!
-        * 
-        * --metze
-        */
-
-        /* We use a temporary variable because this call can fail and 
-           rpc_lookup will still be valid afterwards.  It could then succeed if
-           called again later */
-       rpc_lookup_size++;
-        rpc_entry = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(rpc_lookup, struct rpc_table, rpc_lookup_size);
-        if (NULL == rpc_entry) {
-                rpc_lookup_size--;
-                DEBUG(0, ("rpc_pipe_register_commands: memory allocation failed\n"));
-                return NT_STATUS_NO_MEMORY;
-        } else {
-                rpc_lookup = rpc_entry;
-        }
-
-        rpc_entry = rpc_lookup + (rpc_lookup_size - 1);
-        ZERO_STRUCTP(rpc_entry);
-        rpc_entry->pipe.clnt = SMB_STRDUP(clnt);
-        rpc_entry->pipe.srv = SMB_STRDUP(srv);
-       rpc_entry->rpc_interface = iface->syntax_id;
-        rpc_entry->cmds = cmds;
-        rpc_entry->n_cmds = size;
-
-        return NT_STATUS_OK;
-}
-
 /**
  * Is a named pipe known?
  * @param[in] cli_filename     The pipe name requested by the client
@@ -1144,7 +1068,6 @@ NTSTATUS rpc_srv_register(int version, const char *clnt, const char *srv,
 bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax)
 {
        const char *pipename = cli_filename;
-       int i;
        NTSTATUS status;
 
        if (strnequal(pipename, "\\PIPE\\", 6)) {
@@ -1160,11 +1083,8 @@ bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax)
                return false;
        }
 
-       for (i=0; i<rpc_lookup_size; i++) {
-               if (strequal(pipename, rpc_lookup[i].pipe.clnt)) {
-                       *syntax = rpc_lookup[i].rpc_interface;
-                       return true;
-               }
+       if (rpc_srv_get_pipe_interface_by_cli_name(pipename, syntax)) {
+               return true;
        }
 
        status = smb_probe_module("rpc", pipename);
@@ -1177,12 +1097,8 @@ bool is_known_pipename(const char *cli_filename, struct ndr_syntax_id *syntax)
        /*
         * Scan the list again for the interface id
         */
-
-       for (i=0; i<rpc_lookup_size; i++) {
-               if (strequal(pipename, rpc_lookup[i].pipe.clnt)) {
-                       *syntax = rpc_lookup[i].rpc_interface;
-                       return true;
-               }
+       if (rpc_srv_get_pipe_interface_by_cli_name(pipename, syntax)) {
+               return true;
        }
 
        DEBUG(10, ("is_known_pipename: pipe %s did not register itself!\n",
@@ -1664,10 +1580,11 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
        fstring ack_pipe_name;
        prs_struct out_hdr_ba;
        prs_struct out_auth;
-       int i = 0;
        int auth_len = 0;
        unsigned int auth_type = DCERPC_AUTH_TYPE_NONE;
        uint32_t ss_padding_len = 0;
+       NTSTATUS status;
+       struct ndr_syntax_id id;
 
        /* No rebinds on a bound pipe - use alter context. */
        if (p->pipe_bound) {
@@ -1724,19 +1641,12 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
         * Try and find the correct pipe name to ensure
         * that this is a pipe name we support.
         */
-
-       for (i = 0; i < rpc_lookup_size; i++) {
-               if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface,
-                                       &hdr_rb.rpc_context[0].abstract)) {
-                       DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
-                               rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv));
-                       break;
-               }
-       }
-
-       if (i == rpc_lookup_size) {
-               NTSTATUS status;
-
+       id = hdr_rb.rpc_context[0].abstract;
+       if (rpc_srv_pipe_exists_by_id(&id)) {
+               DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
+                       rpc_srv_get_pipe_cli_name(&id),
+                       rpc_srv_get_pipe_srv_name(&id)));
+       } else {
                status = smb_probe_module(
                        "rpc", get_pipe_name_from_syntax(
                                talloc_tos(),
@@ -1752,19 +1662,16 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
                        prs_mem_free(&out_auth);
 
                        return setup_bind_nak(p);
-                }
-
-                for (i = 0; i < rpc_lookup_size; i++) {
-                       if (strequal(rpc_lookup[i].pipe.clnt,
-                                   get_pipe_name_from_syntax(talloc_tos(),
-                                                             &p->syntax))) {
-                               DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
-                                         rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv));
-                               break;
-                       }
-                }
-
-               if (i == rpc_lookup_size) {
+               }
+
+               if (rpc_srv_get_pipe_interface_by_cli_name(
+                               get_pipe_name_from_syntax(talloc_tos(),
+                                                         &p->syntax),
+                               &id)) {
+                       DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
+                               rpc_srv_get_pipe_cli_name(&id),
+                               rpc_srv_get_pipe_srv_name(&id)));
+               } else {
                        DEBUG(0, ("module %s doesn't provide functions for "
                                  "pipe %s!\n",
                                  get_pipe_name_from_syntax(talloc_tos(),
@@ -1777,7 +1684,7 @@ bool api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
 
        /* name has to be \PIPE\xxxxx */
        fstrcpy(ack_pipe_name, "\\PIPE\\");
-       fstrcat(ack_pipe_name, rpc_lookup[i].pipe.srv);
+       fstrcat(ack_pipe_name, rpc_srv_get_pipe_srv_name(&id));
 
        DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
 
diff --git a/source3/rpc_server/srv_pipe_internal.h b/source3/rpc_server/srv_pipe_internal.h
new file mode 100644 (file)
index 0000000..f84c6aa
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  RPC Pipe client / server routines
+ *  Almost completely rewritten by (C) Jeremy Allison 2005 - 2010
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _RPC_PIPE_INTERNAL_H_
+#define _RPC_PIPE_INTERNAL_H_
+
+#include "includes.h"
+
+bool rpc_srv_pipe_exists_by_id(const struct ndr_syntax_id *id);
+
+bool rpc_srv_pipe_exists_by_cli_name(const char *cli_name);
+
+bool rpc_srv_pipe_exists_by_srv_name(const char *srv_name);
+
+const char *rpc_srv_get_pipe_cli_name(const struct ndr_syntax_id *id);
+
+const char *rpc_srv_get_pipe_srv_name(const struct ndr_syntax_id *id);
+
+uint32_t rpc_srv_get_pipe_num_cmds(const struct ndr_syntax_id *id);
+
+const struct api_struct *rpc_srv_get_pipe_cmds(const struct ndr_syntax_id *id);
+
+bool rpc_srv_get_pipe_interface_by_cli_name(const char *cli_name,
+                                           struct ndr_syntax_id *id);
+
+#endif /* _RPC_PIPE_INTERNAL_H_ */
diff --git a/source3/rpc_server/srv_pipe_register.c b/source3/rpc_server/srv_pipe_register.c
new file mode 100644 (file)
index 0000000..757e4fb
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  RPC Pipe client / server routines
+ *  Almost completely rewritten by (C) Jeremy Allison 2005 - 2010
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "includes.h"
+#include "srv_pipe_internal.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+struct rpc_table {
+       struct {
+               const char *clnt;
+               const char *srv;
+       } pipe;
+       struct ndr_syntax_id rpc_interface;
+       const struct api_struct *cmds;
+       uint32_t n_cmds;
+};
+
+static struct rpc_table *rpc_lookup;
+static uint32_t rpc_lookup_size;
+
+bool rpc_srv_pipe_exists_by_id(const struct ndr_syntax_id *id)
+{
+       uint32_t i;
+
+       for (i = 0; i < rpc_lookup_size; i++) {
+               if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+bool rpc_srv_pipe_exists_by_cli_name(const char *cli_name)
+{
+       uint32_t i;
+
+       for (i = 0; i < rpc_lookup_size; i++) {
+               if (strequal(rpc_lookup[i].pipe.clnt, cli_name)) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+bool rpc_srv_pipe_exists_by_srv_name(const char *srv_name)
+{
+       uint32_t i;
+
+       for (i = 0; i < rpc_lookup_size; i++) {
+               if (strequal(rpc_lookup[i].pipe.srv, srv_name)) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+const char *rpc_srv_get_pipe_cli_name(const struct ndr_syntax_id *id)
+{
+       uint32_t i;
+
+       for (i = 0; i < rpc_lookup_size; i++) {
+               if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) {
+                       return rpc_lookup[i].pipe.clnt;
+               }
+       }
+
+       return NULL;
+}
+
+const char *rpc_srv_get_pipe_srv_name(const struct ndr_syntax_id *id)
+{
+       uint32_t i;
+
+       for (i = 0; i < rpc_lookup_size; i++) {
+               if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) {
+                       return rpc_lookup[i].pipe.srv;
+               }
+       }
+
+       return NULL;
+}
+
+uint32_t rpc_srv_get_pipe_num_cmds(const struct ndr_syntax_id *id)
+{
+       uint32_t i;
+
+       for (i = 0; i < rpc_lookup_size; i++) {
+               if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) {
+                       return rpc_lookup[i].n_cmds;
+               }
+       }
+
+       return 0;
+}
+
+const struct api_struct *rpc_srv_get_pipe_cmds(const struct ndr_syntax_id *id)
+{
+       uint32_t i;
+
+       for (i = 0; i < rpc_lookup_size; i++) {
+               if (ndr_syntax_id_equal(&rpc_lookup[i].rpc_interface, id)) {
+                       return rpc_lookup[i].cmds;
+               }
+       }
+
+       return NULL;
+}
+
+bool rpc_srv_get_pipe_interface_by_cli_name(const char *cli_name,
+                                           struct ndr_syntax_id *id)
+{
+       uint32_t i;
+
+       for (i = 0; i < rpc_lookup_size; i++) {
+               if (strequal(rpc_lookup[i].pipe.clnt, cli_name)) {
+                       if (id) {
+                               *id = rpc_lookup[i].rpc_interface;
+                       }
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+/*******************************************************************
+ Register commands to an RPC pipe
+*******************************************************************/
+
+NTSTATUS rpc_srv_register(int version, const char *clnt, const char *srv,
+                         const struct ndr_interface_table *iface,
+                         const struct api_struct *cmds, int size)
+{
+       struct rpc_table *rpc_entry;
+
+       if (!clnt || !srv || !cmds) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       if (version != SMB_RPC_INTERFACE_VERSION) {
+               DEBUG(0,("Can't register rpc commands!\n"
+                        "You tried to register a rpc module with SMB_RPC_INTERFACE_VERSION %d"
+                        ", while this version of samba uses version %d!\n",
+                        version,SMB_RPC_INTERFACE_VERSION));
+               return NT_STATUS_OBJECT_TYPE_MISMATCH;
+       }
+
+       /* TODO:
+        *
+        * we still need to make sure that don't register the same commands twice!!!
+        *
+        * --metze
+        */
+
+       /*
+        * We use a temporary variable because this call can fail and
+        * rpc_lookup will still be valid afterwards.  It could then succeed if
+        * called again later
+        */
+       rpc_lookup_size++;
+       rpc_entry = SMB_REALLOC_ARRAY_KEEP_OLD_ON_ERROR(rpc_lookup, struct rpc_table, rpc_lookup_size);
+       if (NULL == rpc_entry) {
+               rpc_lookup_size--;
+               DEBUG(0, ("rpc_pipe_register_commands: memory allocation failed\n"));
+               return NT_STATUS_NO_MEMORY;
+       } else {
+               rpc_lookup = rpc_entry;
+       }
+
+       rpc_entry = rpc_lookup + (rpc_lookup_size - 1);
+       ZERO_STRUCTP(rpc_entry);
+       rpc_entry->pipe.clnt = SMB_STRDUP(clnt);
+       rpc_entry->pipe.srv = SMB_STRDUP(srv);
+       rpc_entry->rpc_interface = iface->syntax_id;
+       rpc_entry->cmds = cmds;
+       rpc_entry->n_cmds = size;
+
+       return NT_STATUS_OK;
+}
index 3ce63adb691450d9b0ea3af855de971ea8c274cf..20776617227434d04514040764419bee58935abc 100644 (file)
@@ -396,8 +396,7 @@ RPC_EVENTLOG_SRC = '''rpc_server/srv_eventlog_nt.c
 
 NPA_TSTREAM_SRC = '''../libcli/named_pipe_auth/npa_tstream.c'''
 
-RPC_PIPE_SRC = '''rpc_server/srv_pipe_hnd.c
-               rpc_server/srv_pipe.c rpc_server/srv_lsa_hnd.c'''
+RPC_PIPE_SRC = '''rpc_server/srv_pipe_hnd.c rpc_server/srv_pipe.c rpc_server/srv_pipe_register.c'''
 
 RPC_ECHO_SRC = '''rpc_server/srv_echo_nt.c ../librpc/gen_ndr/srv_echo.c'''