]> git.samba.org - abartlet/samba.git/.git/blobdiff - librpc/rpc/binding.c
librpc When sending endpoint mapper requests, include the minor if_version
[abartlet/samba.git/.git] / librpc / rpc / binding.c
index b755431034ab7ccae503f0abcd841638de28a93d..3f15eef926e80a68511c747aedb281302a40b230 100644 (file)
@@ -7,17 +7,17 @@
    Copyright (C) Jelmer Vernooij 2004
    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
    Copyright (C) Rafal Szczesniak 2006
-   
+
    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/>.
 */
@@ -45,7 +45,7 @@ static const struct {
        { "ncadg_ip_udp", NCACN_IP_UDP, 3, 
                { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_UDP, EPM_PROTOCOL_IP } },
        { "ncalrpc", NCALRPC, 2, 
-               { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE } },
+               { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_NAMED_PIPE } },
        { "ncacn_unix_stream", NCACN_UNIX_STREAM, 2, 
                { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_UNIX_DS } },
        { "ncadg_unix_dgram", NCADG_UNIX_DGRAM, 2, 
@@ -84,7 +84,8 @@ static const struct {
        {"padcheck", DCERPC_DEBUG_PAD_CHECK},
        {"bigendian", DCERPC_PUSH_BIGENDIAN},
        {"smb2", DCERPC_SMB2},
-       {"hdrsign", DCERPC_HEADER_SIGNING}
+       {"hdrsign", DCERPC_HEADER_SIGNING},
+       {"ndr64", DCERPC_NDR64}
 };
 
 const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
@@ -112,7 +113,7 @@ const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
                                return talloc_asprintf(mem_ctx, " uuid %s/0x%02x", uuidstr, syntax.if_version);
                        } else { /* IPX */
                                return talloc_asprintf(mem_ctx, "IPX:%s", 
-                                               data_blob_hex_string(mem_ctx, &epm_floor->rhs.uuid.unknown));
+                                               data_blob_hex_string_upper(mem_ctx, &epm_floor->rhs.uuid.unknown));
                        }
 
                case EPM_PROTOCOL_NCACN:
@@ -130,8 +131,8 @@ const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
                case EPM_PROTOCOL_IP:
                        return talloc_asprintf(mem_ctx, "IP:%s", epm_floor->rhs.ip.ipaddr);
 
-               case EPM_PROTOCOL_PIPE:
-                       return talloc_asprintf(mem_ctx, "PIPE:%s", epm_floor->rhs.pipe.path);
+               case EPM_PROTOCOL_NAMED_PIPE:
+                       return talloc_asprintf(mem_ctx, "NAMED-PIPE:%s", epm_floor->rhs.named_pipe.path);
 
                case EPM_PROTOCOL_SMB:
                        return talloc_asprintf(mem_ctx, "SMB:%s", epm_floor->rhs.smb.unc);
@@ -176,11 +177,7 @@ _PUBLIC_ char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_bi
        const char *t_name = NULL;
 
        if (b->transport != NCA_UNKNOWN) {
-               for (i=0;i<ARRAY_SIZE(transports);i++) {
-                       if (transports[i].transport == b->transport) {
-                               t_name = transports[i].name;
-                       }
-               }
+               t_name = derpc_transport_string_by_transport(b->transport);
                if (!t_name) {
                        return NULL;
                }
@@ -251,8 +248,8 @@ _PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struc
 
        if (p && PTR_DIFF(p, s) == 36) { /* 36 is the length of a UUID */
                NTSTATUS status;
-
-               status = GUID_from_string(s, &b->object.uuid);
+               DATA_BLOB blob = data_blob(s, 36);
+               status = GUID_from_data_blob(&blob, &b->object.uuid);
 
                if (NT_STATUS_IS_ERR(status)) {
                        DEBUG(0, ("Failed parsing UUID\n"));
@@ -289,7 +286,7 @@ _PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struc
                }
 
                talloc_free(type);
-       
+
                s = p+1;
        }
 
@@ -365,18 +362,24 @@ _PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struc
 
        if (b->options[0] == NULL)
                b->options = NULL;
-       
+
        *b_out = b;
        return NT_STATUS_OK;
 }
 
-_PUBLIC_ NTSTATUS dcerpc_floor_get_lhs_data(struct epm_floor *epm_floor, struct ndr_syntax_id *syntax)
+_PUBLIC_ NTSTATUS dcerpc_floor_get_lhs_data(const struct epm_floor *epm_floor,
+                                           struct ndr_syntax_id *syntax)
 {
        TALLOC_CTX *mem_ctx = talloc_init("floor_get_lhs_data");
-       struct ndr_pull *ndr = ndr_pull_init_blob(&epm_floor->lhs.lhs_data, mem_ctx, NULL);
+       struct ndr_pull *ndr;
        enum ndr_err_code ndr_err;
        uint16_t if_version=0;
 
+       ndr = ndr_pull_init_blob(&epm_floor->lhs.lhs_data, mem_ctx, NULL);
+       if (ndr == NULL) {
+               talloc_free(mem_ctx);
+               return NT_STATUS_NO_MEMORY;
+       }
        ndr->flags |= LIBNDR_FLAG_NOALIGN;
 
        ndr_err = ndr_pull_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid);
@@ -400,6 +403,7 @@ _PUBLIC_ NTSTATUS dcerpc_floor_get_lhs_data(struct epm_floor *epm_floor, struct
 
 static DATA_BLOB dcerpc_floor_pack_lhs_data(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax)
 {
+       DATA_BLOB blob;
        struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx, NULL);
 
        ndr->flags |= LIBNDR_FLAG_NOALIGN;
@@ -407,7 +411,25 @@ static DATA_BLOB dcerpc_floor_pack_lhs_data(TALLOC_CTX *mem_ctx, const struct nd
        ndr_push_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid);
        ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version);
 
-       return ndr_push_blob(ndr);
+       blob = ndr_push_blob(ndr);
+       talloc_steal(mem_ctx, blob.data);
+       talloc_free(ndr);
+       return blob;
+}
+
+static DATA_BLOB dcerpc_floor_pack_rhs_if_version_data(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax)
+{
+       DATA_BLOB blob;
+       struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx, NULL);
+
+       ndr->flags |= LIBNDR_FLAG_NOALIGN;
+
+       ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version >> 16);
+
+       blob = ndr_push_blob(ndr);
+       talloc_steal(mem_ctx, blob.data);
+       talloc_free(ndr);
+       return blob;
 }
 
 const char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor)
@@ -416,7 +438,7 @@ const char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm
        case EPM_PROTOCOL_TCP:
                if (epm_floor->rhs.tcp.port == 0) return NULL;
                return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.tcp.port);
-               
+
        case EPM_PROTOCOL_UDP:
                if (epm_floor->rhs.udp.port == 0) return NULL;
                return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.udp.port);
@@ -438,9 +460,9 @@ const char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm
                if (strlen(epm_floor->rhs.smb.unc) == 0) return NULL;
                return talloc_strdup(mem_ctx, epm_floor->rhs.smb.unc);
 
-       case EPM_PROTOCOL_PIPE:
-               if (strlen(epm_floor->rhs.pipe.path) == 0) return NULL;
-               return talloc_strdup(mem_ctx, epm_floor->rhs.pipe.path);
+       case EPM_PROTOCOL_NAMED_PIPE:
+               if (strlen(epm_floor->rhs.named_pipe.path) == 0) return NULL;
+               return talloc_strdup(mem_ctx, epm_floor->rhs.named_pipe.path);
 
        case EPM_PROTOCOL_NETBIOS:
                if (strlen(epm_floor->rhs.netbios.name) == 0) return NULL;
@@ -448,20 +470,20 @@ const char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm
 
        case EPM_PROTOCOL_NCALRPC:
                return NULL;
-               
+
        case EPM_PROTOCOL_VINES_SPP:
                return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.vines_spp.port);
-               
+
        case EPM_PROTOCOL_VINES_IPC:
                return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.vines_ipc.port);
-               
+
        case EPM_PROTOCOL_STREETTALK:
                return talloc_strdup(mem_ctx, epm_floor->rhs.streettalk.streettalk);
-               
+
        case EPM_PROTOCOL_UNIX_DS:
                if (strlen(epm_floor->rhs.unix_ds.path) == 0) return NULL;
                return talloc_strdup(mem_ctx, epm_floor->rhs.unix_ds.path);
-               
+
        case EPM_PROTOCOL_NULL:
                return NULL;
 
@@ -481,7 +503,7 @@ static NTSTATUS dcerpc_floor_set_rhs_data(TALLOC_CTX *mem_ctx,
        case EPM_PROTOCOL_TCP:
                epm_floor->rhs.tcp.port = atoi(data);
                return NT_STATUS_OK;
-               
+
        case EPM_PROTOCOL_UDP:
                epm_floor->rhs.udp.port = atoi(data);
                return NT_STATUS_OK;
@@ -508,9 +530,9 @@ static NTSTATUS dcerpc_floor_set_rhs_data(TALLOC_CTX *mem_ctx,
                NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.smb.unc);
                return NT_STATUS_OK;
 
-       case EPM_PROTOCOL_PIPE:
-               epm_floor->rhs.pipe.path = talloc_strdup(mem_ctx, data);
-               NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.pipe.path);
+       case EPM_PROTOCOL_NAMED_PIPE:
+               epm_floor->rhs.named_pipe.path = talloc_strdup(mem_ctx, data);
+               NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.named_pipe.path);
                return NT_STATUS_OK;
 
        case EPM_PROTOCOL_NETBIOS:
@@ -520,25 +542,25 @@ static NTSTATUS dcerpc_floor_set_rhs_data(TALLOC_CTX *mem_ctx,
 
        case EPM_PROTOCOL_NCALRPC:
                return NT_STATUS_OK;
-               
+
        case EPM_PROTOCOL_VINES_SPP:
                epm_floor->rhs.vines_spp.port = atoi(data);
                return NT_STATUS_OK;
-               
+
        case EPM_PROTOCOL_VINES_IPC:
                epm_floor->rhs.vines_ipc.port = atoi(data);
                return NT_STATUS_OK;
-               
+
        case EPM_PROTOCOL_STREETTALK:
                epm_floor->rhs.streettalk.streettalk = talloc_strdup(mem_ctx, data);
                NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.streettalk.streettalk);
                return NT_STATUS_OK;
-               
+
        case EPM_PROTOCOL_UNIX_DS:
                epm_floor->rhs.unix_ds.path = talloc_strdup(mem_ctx, data);
                NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.unix_ds.path);
                return NT_STATUS_OK;
-               
+
        case EPM_PROTOCOL_NULL:
                return NT_STATUS_OK;
 
@@ -561,12 +583,12 @@ enum dcerpc_transport_t dcerpc_transport_by_endpoint_protocol(int prot)
                        return transports[i].transport;
                }
        }
-       
+
        /* Unknown transport */
        return (unsigned int)-1;
 }
 
-_PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_tower(struct epm_tower *tower)
+_PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_tower(const struct epm_tower *tower)
 {
        int i;
 
@@ -587,11 +609,23 @@ _PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_tower(struct epm_tower *tow
                        return transports[i].transport;
                }
        }
-       
+
        /* Unknown transport */
        return (unsigned int)-1;
 }
 
+_PUBLIC_ const char *derpc_transport_string_by_transport(enum dcerpc_transport_t t)
+{
+       int i;
+
+       for (i=0; i<ARRAY_SIZE(transports); i++) {
+               if (t == transports[i].transport) {
+                       return transports[i].name;
+               }
+       }
+       return NULL;
+}
+
 _PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, 
                                   struct epm_tower *tower, 
                                   struct dcerpc_binding **b_out)
@@ -621,14 +655,14 @@ _PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx,
 
        /* Set object uuid */
        status = dcerpc_floor_get_lhs_data(&tower->floors[0], &binding->object);
-       
+
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("Error pulling object uuid and version: %s", nt_errstr(status)));     
                return status;
        }
 
        /* Ignore floor 1, it contains the NDR version info */
-       
+
        binding->options = NULL;
 
        /* Set endpoint */
@@ -648,12 +682,14 @@ _PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
-_PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_binding *binding, struct epm_tower *tower)
+_PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx,
+                                            const struct dcerpc_binding *binding,
+                                            struct epm_tower *tower)
 {
        const enum epm_protocol *protseq = NULL;
        int num_protocols = -1, i;
        NTSTATUS status;
-       
+
        /* Find transport */
        for (i=0;i<ARRAY_SIZE(transports);i++) {
                if (transports[i].transport == binding->transport) {
@@ -674,38 +710,38 @@ _PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_
        /* Floor 0 */
        tower->floors[0].lhs.protocol = EPM_PROTOCOL_UUID;
 
-       tower->floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx, &binding->object);
+       tower->floors[0].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors, &binding->object);
+
+       tower->floors[0].rhs.uuid.unknown = dcerpc_floor_pack_rhs_if_version_data(tower->floors, &binding->object);
 
-       tower->floors[0].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2);
-       
        /* Floor 1 */
        tower->floors[1].lhs.protocol = EPM_PROTOCOL_UUID;
 
-       tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(mem_ctx
+       tower->floors[1].lhs.lhs_data = dcerpc_floor_pack_lhs_data(tower->floors
                                                                &ndr_transfer_syntax);
-       
-       tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 2);
-       
+
+       tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(tower->floors, 2);
+
        /* Floor 2 to num_protocols */
        for (i = 0; i < num_protocols; i++) {
                tower->floors[2 + i].lhs.protocol = protseq[i];
-               tower->floors[2 + i].lhs.lhs_data = data_blob_talloc(mem_ctx, NULL, 0);
+               tower->floors[2 + i].lhs.lhs_data = data_blob_talloc(tower->floors, NULL, 0);
                ZERO_STRUCT(tower->floors[2 + i].rhs);
-               dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[2 + i], "");
+               dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[2 + i], "");
        }
 
        /* The 4th floor contains the endpoint */
        if (num_protocols >= 2 && binding->endpoint) {
-               status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[3], binding->endpoint);
+               status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[3], binding->endpoint);
                if (NT_STATUS_IS_ERR(status)) {
                        return status;
                }
        }
-       
+
        /* The 5th contains the network address */
        if (num_protocols >= 3 && binding->host) {
                if (is_ipaddress(binding->host)) {
-                       status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4], 
+                       status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[4], 
                                                           binding->host);
                } else {
                        /* note that we don't attempt to resolve the
@@ -713,7 +749,7 @@ _PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, struct dcerpc_
                           are in the client code, and want to put in
                           a wildcard all-zeros IP for the server to
                           fill in */
-                       status = dcerpc_floor_set_rhs_data(mem_ctx, &tower->floors[4], 
+                       status = dcerpc_floor_set_rhs_data(tower->floors, &tower->floors[4], 
                                                           "0.0.0.0");
                }
                if (NT_STATUS_IS_ERR(status)) {