* prepared the dcerpc subsystem for adding the RPC over TCP transport
authorAndrew Tridgell <tridge@samba.org>
Mon, 24 Nov 2003 11:45:33 +0000 (11:45 +0000)
committerAndrew Tridgell <tridge@samba.org>
Mon, 24 Nov 2003 11:45:33 +0000 (11:45 +0000)
 * fixed a uninitialised variable bug in pidl (found by valgrind)
(This used to be commit 8bce61b8af6351c72c0dd84dc61b49d8aeb1fbbd)

source4/build/pidl/parser.pm
source4/librpc/rpc/dcerpc.c
source4/librpc/rpc/dcerpc.h
source4/librpc/rpc/dcerpc_smb.c
source4/torture/torture.c

index e536ab083d397fe47b6dc15d99f09313a29c814b..a7dad3707c84c72205a42c9ceb5a98e389f8ee89 100644 (file)
@@ -1176,10 +1176,10 @@ sub ParseFunctionElementPull($$)
                if (util::need_wire_pointer($e)) {
                        pidl "\tNDR_CHECK(ndr_pull_uint32(ndr, &_ptr_$e->{NAME}));\n";
                        pidl "\tif (_ptr_$e->{NAME}) {\n";
-               } elsif ($inout eq "in" && util::has_property($e, "ref")) {
-                       pidl "\t{\n";
-               } else {
+               } elsif ($inout eq "out" && util::has_property($e, "ref")) {
                        pidl "\tif (r->$inout.$e->{NAME}) {\n";
+               } else {
+                       pidl "\t{\n";
                }
                ParseArrayPull($e, "r->$inout.", "NDR_SCALARS|NDR_BUFFERS");
                pidl "\t}\n";
index 276b3c9ef45024e0f30d8952c62e405d18b33beb..495e36ec1f5fd407909324b1088fdb5e19731681 100644 (file)
@@ -40,10 +40,7 @@ struct dcerpc_pipe *dcerpc_pipe_init(struct cli_tree *tree)
 
        p->reference_count = 0;
        p->mem_ctx = mem_ctx;
-       p->tree = tree;
-       p->tree->reference_count++;
        p->call_id = 1;
-       p->fnum = 0;
 
        return p;
 }
@@ -54,7 +51,7 @@ void dcerpc_pipe_close(struct dcerpc_pipe *p)
        if (!p) return;
        p->reference_count--;
        if (p->reference_count <= 0) {
-               cli_tree_close(p->tree);
+               p->transport.shutdown_pipe(p);
                talloc_destroy(p->mem_ctx);
        }
 }
@@ -167,7 +164,7 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p,
                return status;
        }
 
-       status = dcerpc_raw_packet(p, mem_ctx, &blob, &blob_out);
+       status = p->transport.full_request(p, mem_ctx, &blob, &blob_out);
        if (!NT_STATUS_IS_OK(status)) {
                talloc_destroy(mem_ctx);
                return status;
@@ -269,7 +266,7 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
                        return status;
                }
                
-               status = dcerpc_raw_packet_initial(p, mem_ctx, &blob_in);
+               status = p->transport.initial_request(p, mem_ctx, &blob_in);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }               
@@ -294,7 +291,7 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
        }
 
        /* send the pdu and get the initial response pdu */
-       status = dcerpc_raw_packet(p, mem_ctx, &blob_in, &blob_out);
+       status = p->transport.full_request(p, mem_ctx, &blob_in, &blob_out);
 
        status = dcerpc_pull(&blob_out, mem_ctx, &pkt);
        if (!NT_STATUS_IS_OK(status)) {
@@ -320,7 +317,7 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
        while (!(pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) {
                uint32 length;
 
-               status = dcerpc_raw_packet_secondary(p, mem_ctx, &blob_out);
+               status = p->transport.secondary_request(p, mem_ctx, &blob_out);
                if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
@@ -596,5 +593,8 @@ failed:
 */
 const char *dcerpc_server_name(struct dcerpc_pipe *p)
 {
-       return p->tree->session->transport->called.name;
+       if (!p->transport.peer_name) {
+               return "";
+       }
+       return p->transport.peer_name(p);
 }
index 6ba0f8429ab9e2c25e3172e36c55d093a7400366..e0e7c8bd5a68feb568428bfc791ec11b512e910a 100644 (file)
 
 struct dcerpc_pipe {
        TALLOC_CTX *mem_ctx;
-       uint16 fnum;
        int reference_count;
        uint32 call_id;
        uint32 srv_max_xmit_frag;
        uint32 srv_max_recv_frag;
-       struct cli_tree *tree;
        unsigned flags;
+
+       struct dcerpc_transport {
+               void *private;
+               NTSTATUS (*full_request)(struct dcerpc_pipe *, 
+                                        TALLOC_CTX *, DATA_BLOB *, DATA_BLOB *);
+               NTSTATUS (*secondary_request)(struct dcerpc_pipe *, TALLOC_CTX *, DATA_BLOB *);
+               NTSTATUS (*initial_request)(struct dcerpc_pipe *, TALLOC_CTX *, DATA_BLOB *);
+               NTSTATUS (*shutdown_pipe)(struct dcerpc_pipe *);
+               const char *(*peer_name)(struct dcerpc_pipe *);
+       } transport;
 };
 
 /* dcerpc pipe flags */
index a5570a4ea9b7dd95b7f99e9b5a179aa83f709844..ba9c0c62a2471c4f3c1a770c62a79d4e9ce3955b 100644 (file)
 
 #include "includes.h"
 
+/* transport private information used by SMB pipe transport */
+struct smb_private {
+       uint16 fnum;
+       struct cli_tree *tree;
+};
 
-/* 
-   open a rpc connection to a named pipe 
-*/
-NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe *p, 
-                             const char *pipe_name,
-                             const char *pipe_uuid, 
-                             uint32 pipe_version)
-{
-        NTSTATUS status;
-       char *name = NULL;
-       union smb_open io;
-       TALLOC_CTX *mem_ctx;
-
-       asprintf(&name, "\\%s", pipe_name);
-       if (!name) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       io.ntcreatex.level = RAW_OPEN_NTCREATEX;
-       io.ntcreatex.in.flags = 0;
-       io.ntcreatex.in.root_fid = 0;
-       io.ntcreatex.in.access_mask = 
-               STD_RIGHT_READ_CONTROL_ACCESS | 
-               SA_RIGHT_FILE_WRITE_ATTRIBUTES | 
-               SA_RIGHT_FILE_WRITE_EA | 
-               GENERIC_RIGHTS_FILE_READ |
-               GENERIC_RIGHTS_FILE_WRITE;
-       io.ntcreatex.in.file_attr = 0;
-       io.ntcreatex.in.alloc_size = 0;
-       io.ntcreatex.in.share_access = 
-               NTCREATEX_SHARE_ACCESS_READ |
-               NTCREATEX_SHARE_ACCESS_WRITE;
-       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
-       io.ntcreatex.in.create_options = 0;
-       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
-       io.ntcreatex.in.security_flags = 0;
-       io.ntcreatex.in.fname = name;
-
-       mem_ctx = talloc_init("torture_rpc_connection");
-       if (!mem_ctx) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       status = smb_raw_open(p->tree, mem_ctx, &io);
-       free(name);
-       talloc_destroy(mem_ctx);
-
-       if (!NT_STATUS_IS_OK(status)) {
-                return status;
-        }
-       p->fnum = io.ntcreatex.out.fnum;
-
-       /* bind to the pipe, using the pipe_name as the key */
-       status = dcerpc_bind_byuuid(p, pipe_uuid, pipe_version);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               union smb_close c;
-               c.close.level = RAW_CLOSE_CLOSE;
-               c.close.in.fnum = p->fnum;
-               c.close.in.write_time = 0;
-               smb_raw_close(p->tree, &c);
-       }
-
-        return status;
-}
-
-
-struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob)
+static struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob)
 {
+       struct smb_private *smb = p->transport.private;
        struct smb_trans2 trans;
        uint16 setup[2];
        struct cli_request *req;
@@ -104,7 +43,7 @@ struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob)
        trans.in.params = data_blob(NULL, 0);
        
        setup[0] = TRANSACT_DCERPCCMD;
-       setup[1] = p->fnum;
+       setup[1] = smb->fnum;
 
        trans.in.max_param = 0;
        trans.in.max_data = 0x8000;
@@ -115,7 +54,7 @@ struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob)
        trans.in.setup = setup;
        trans.in.trans_name = "\\PIPE\\";
 
-       req = smb_raw_trans_send(p->tree, &trans);
+       req = smb_raw_trans_send(smb->tree, &trans);
 
        talloc_destroy(mem_ctx);
 
@@ -123,11 +62,12 @@ struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob)
 }
 
 
-NTSTATUS dcerpc_raw_recv(struct dcerpc_pipe *p, 
-                        struct cli_request *req,
-                        TALLOC_CTX *mem_ctx,
-                        DATA_BLOB *blob)
+static NTSTATUS dcerpc_raw_recv(struct dcerpc_pipe *p, 
+                               struct cli_request *req,
+                               TALLOC_CTX *mem_ctx,
+                               DATA_BLOB *blob)
 {
+       struct smb_private *smb = p->transport.private;
        struct smb_trans2 trans;
        NTSTATUS status;
        uint16 frag_length;
@@ -172,13 +112,13 @@ NTSTATUS dcerpc_raw_recv(struct dcerpc_pipe *p,
                }
 
                io.generic.level = RAW_READ_READX;
-               io.readx.in.fnum = p->fnum;
+               io.readx.in.fnum = smb->fnum;
                io.readx.in.mincnt = n;
                io.readx.in.maxcnt = n;
                io.readx.in.offset = 0;
                io.readx.in.remaining = 0;
                io.readx.out.data = payload.data + payload.length;
-               status = smb_raw_read(p->tree, &io);
+               status = smb_raw_read(smb->tree, &io);
                if (!NT_STATUS_IS_OK(status) &&
                    !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
                        break;
@@ -207,10 +147,10 @@ done:
        return status;
 }
 
-NTSTATUS dcerpc_raw_packet(struct dcerpc_pipe *p, 
-                          TALLOC_CTX *mem_ctx,
-                          DATA_BLOB *request_blob,
-                          DATA_BLOB *reply_blob)
+static NTSTATUS smb_full_request(struct dcerpc_pipe *p, 
+                                TALLOC_CTX *mem_ctx,
+                                DATA_BLOB *request_blob,
+                                DATA_BLOB *reply_blob)
 {
        struct cli_request *req;
        req = dcerpc_raw_send(p, request_blob);
@@ -221,10 +161,11 @@ NTSTATUS dcerpc_raw_packet(struct dcerpc_pipe *p,
 /* 
    retrieve a secondary pdu from a pipe 
 */
-NTSTATUS dcerpc_raw_packet_secondary(struct dcerpc_pipe *p, 
-                                    TALLOC_CTX *mem_ctx,
-                                    DATA_BLOB *blob)
+NTSTATUS smb_secondary_request(struct dcerpc_pipe *p, 
+                              TALLOC_CTX *mem_ctx,
+                              DATA_BLOB *blob)
 {
+       struct smb_private *smb = p->transport.private;
        union smb_read io;
        uint32 n = 0x2000;
        uint32 frag_length;
@@ -236,14 +177,14 @@ NTSTATUS dcerpc_raw_packet_secondary(struct dcerpc_pipe *p,
        }
 
        io.generic.level = RAW_READ_READX;
-       io.readx.in.fnum = p->fnum;
+       io.readx.in.fnum = smb->fnum;
        io.readx.in.mincnt = n;
        io.readx.in.maxcnt = n;
        io.readx.in.offset = 0;
        io.readx.in.remaining = 0;
        io.readx.out.data = blob->data;
 
-       status = smb_raw_read(p->tree, &io);
+       status = smb_raw_read(smb->tree, &io);
        if (!NT_STATUS_IS_OK(status) &&
            !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
                return status;
@@ -276,7 +217,7 @@ NTSTATUS dcerpc_raw_packet_secondary(struct dcerpc_pipe *p,
                io.readx.in.mincnt = n;
                io.readx.in.maxcnt = n;
                io.readx.out.data = blob->data + blob->length;
-               status = smb_raw_read(p->tree, &io);
+               status = smb_raw_read(smb->tree, &io);
 
                if (!NT_STATUS_IS_OK(status) &&
                    !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) {
@@ -294,22 +235,23 @@ NTSTATUS dcerpc_raw_packet_secondary(struct dcerpc_pipe *p,
 /* 
    send an initial pdu in a multi-pdu sequence
 */
-NTSTATUS dcerpc_raw_packet_initial(struct dcerpc_pipe *p, 
-                                  TALLOC_CTX *mem_ctx,
-                                  DATA_BLOB *blob)
+static NTSTATUS smb_initial_request(struct dcerpc_pipe *p, 
+                                   TALLOC_CTX *mem_ctx,
+                                   DATA_BLOB *blob)
 {
+       struct smb_private *smb = p->transport.private;
        union smb_write io;
        NTSTATUS status;
 
        io.generic.level = RAW_WRITE_WRITEX;
-       io.writex.in.fnum = p->fnum;
+       io.writex.in.fnum = smb->fnum;
        io.writex.in.offset = 0;
        io.writex.in.wmode = PIPE_START_MESSAGE;
        io.writex.in.remaining = blob->length;
        io.writex.in.count = blob->length;
        io.writex.in.data = blob->data;
 
-       status = smb_raw_write(p->tree, &io);
+       status = smb_raw_write(smb->tree, &io);
        if (NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -321,3 +263,123 @@ NTSTATUS dcerpc_raw_packet_initial(struct dcerpc_pipe *p,
 
        return status;
 }
+
+
+/* 
+   shutdown SMB pipe connection
+*/
+static NTSTATUS smb_shutdown_pipe(struct dcerpc_pipe *p)
+{
+       struct smb_private *smb = p->transport.private;
+       union smb_close c;
+
+       /* maybe we're still starting up */
+       if (!smb) return NT_STATUS_OK;
+
+       c.close.level = RAW_CLOSE_CLOSE;
+       c.close.in.fnum = smb->fnum;
+       c.close.in.write_time = 0;
+       smb_raw_close(smb->tree, &c);
+       cli_tree_close(smb->tree);
+
+       return NT_STATUS_OK;
+}
+
+/*
+  return SMB server name
+*/
+static const char *smb_peer_name(struct dcerpc_pipe *p)
+{
+       struct smb_private *smb = p->transport.private;
+       return smb->tree->session->transport->called.name;
+}
+
+
+/* 
+   open a rpc connection to a named pipe 
+*/
+NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p, 
+                             struct cli_tree *tree,
+                             const char *pipe_name,
+                             const char *pipe_uuid, 
+                             uint32 pipe_version)
+{
+       struct smb_private *smb;
+        NTSTATUS status;
+       char *name = NULL;
+       union smb_open io;
+       TALLOC_CTX *mem_ctx;
+
+       asprintf(&name, "\\%s", pipe_name);
+       if (!name) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       io.ntcreatex.level = RAW_OPEN_NTCREATEX;
+       io.ntcreatex.in.flags = 0;
+       io.ntcreatex.in.root_fid = 0;
+       io.ntcreatex.in.access_mask = 
+               STD_RIGHT_READ_CONTROL_ACCESS | 
+               SA_RIGHT_FILE_WRITE_ATTRIBUTES | 
+               SA_RIGHT_FILE_WRITE_EA | 
+               GENERIC_RIGHTS_FILE_READ |
+               GENERIC_RIGHTS_FILE_WRITE;
+       io.ntcreatex.in.file_attr = 0;
+       io.ntcreatex.in.alloc_size = 0;
+       io.ntcreatex.in.share_access = 
+               NTCREATEX_SHARE_ACCESS_READ |
+               NTCREATEX_SHARE_ACCESS_WRITE;
+       io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+       io.ntcreatex.in.create_options = 0;
+       io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
+       io.ntcreatex.in.security_flags = 0;
+       io.ntcreatex.in.fname = name;
+
+       mem_ctx = talloc_init("torture_rpc_connection");
+       if (!mem_ctx) {
+               free(name);
+               return NT_STATUS_NO_MEMORY;
+       }
+       status = smb_raw_open(tree, mem_ctx, &io);
+       free(name);
+       talloc_destroy(mem_ctx);
+
+       if (!NT_STATUS_IS_OK(status)) {
+                return status;
+        }
+
+        if (!(*p = dcerpc_pipe_init(tree))) {
+                return NT_STATUS_NO_MEMORY;
+       }
+       /*
+         fill in the transport methods
+       */
+       (*p)->transport.private = NULL;
+       (*p)->transport.full_request = smb_full_request;
+       (*p)->transport.secondary_request = smb_secondary_request;
+       (*p)->transport.initial_request = smb_initial_request;
+       (*p)->transport.shutdown_pipe = smb_shutdown_pipe;
+       (*p)->transport.peer_name = smb_peer_name;
+       
+       smb = talloc((*p)->mem_ctx, sizeof(*smb));
+       if (!smb) {
+               dcerpc_pipe_close(*p);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       smb->fnum = io.ntcreatex.out.fnum;
+       smb->tree = tree;
+
+       (*p)->transport.private = smb;
+       tree->reference_count++;
+
+       /* bind to the pipe, using the uuid as the key */
+       status = dcerpc_bind_byuuid(*p, pipe_uuid, pipe_version);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               dcerpc_pipe_close(*p);
+       }
+
+        return status;
+}
index e13933a231bb4f9653bbbd35a44c32e410daaf4c..c07b516baab4f61f552aee767ff1c8188eeaa926 100644 (file)
@@ -143,14 +143,11 @@ NTSTATUS torture_rpc_connection(struct dcerpc_pipe **p,
                 return NT_STATUS_UNSUCCESSFUL;
        }
 
-        if (!(*p = dcerpc_pipe_init(cli->tree))) {
-                return NT_STATUS_NO_MEMORY;
-       }
-       status = dcerpc_pipe_open_smb(*p, pipe_name, pipe_uuid, pipe_version);
+       status = dcerpc_pipe_open_smb(p, cli->tree, pipe_name, pipe_uuid, pipe_version);
        if (!NT_STATUS_IS_OK(status)) {
                 printf("Open of pipe '%s' failed with error (%s)\n",
                       pipe_name, nt_errstr(status));
+               torture_close_connection(cli);
                 return status;
         }
 
@@ -163,17 +160,8 @@ NTSTATUS torture_rpc_connection(struct dcerpc_pipe **p,
 /* close a rpc connection to a named pipe */
 NTSTATUS torture_rpc_close(struct dcerpc_pipe *p)
 {
-       union smb_close io;
-       NTSTATUS status;
-
-       io.close.level = RAW_CLOSE_CLOSE;
-       io.close.in.fnum = p->fnum;
-       io.close.in.write_time = 0;
-       status = smb_raw_close(p->tree, &io);
-
        dcerpc_pipe_close(p);
-
-       return status;
+       return NT_STATUS_OK;
 }