diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2008-04-25 10:04:20 +0100 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2008-04-25 10:04:20 +0100 |
commit | cc9c4aaa8d02c4c31c9e9a4bb53e5941683fcc31 (patch) | |
tree | d0b116699dee35372ed335834989e1c885e8f94a /source4/librpc | |
parent | d1432d617e6ed04c33ca214d7f3b0099bdf53065 (diff) | |
parent | 240d959005f5fd80a38b3734b39dd5d6e425a566 (diff) | |
download | samba-cc9c4aaa8d02c4c31c9e9a4bb53e5941683fcc31.tar.gz samba-cc9c4aaa8d02c4c31c9e9a4bb53e5941683fcc31.tar.bz2 samba-cc9c4aaa8d02c4c31c9e9a4bb53e5941683fcc31.zip |
Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-gmake3
Conflicts:
source/Makefile
source/auth/config.mk
source/auth/gensec/config.mk
source/build/m4/public.m4
source/build/make/python.mk
source/build/make/rules.mk
source/build/smb_build/header.pm
source/build/smb_build/main.pl
source/build/smb_build/makefile.pm
source/dsdb/config.mk
source/dsdb/samdb/ldb_modules/config.mk
source/kdc/config.mk
source/lib/events/config.mk
source/lib/events/events.c
source/lib/ldb/config.mk
source/lib/nss_wrapper/config.mk
source/lib/policy/config.mk
source/lib/util/config.mk
source/libcli/smb2/config.mk
source/libnet/config.mk
source/librpc/config.mk
source/nbt_server/config.mk
source/ntptr/ntptr_base.c
source/ntvfs/posix/config.mk
source/ntvfs/sysdep/config.mk
source/param/config.mk
source/rpc_server/config.mk
source/rpc_server/service_rpc.c
source/scripting/ejs/config.mk
source/scripting/python/config.mk
source/smb_server/config.mk
source/smbd/server.c
source/torture/config.mk
source/torture/smb2/config.mk
source/wrepl_server/config.mk
(This used to be commit 13bbd420681519894a4036729c43273912c9b402)
Diffstat (limited to 'source4/librpc')
-rw-r--r-- | source4/librpc/config.mk | 44 | ||||
-rw-r--r-- | source4/librpc/idl/drsuapi.idl | 2 | ||||
-rw-r--r-- | source4/librpc/idl/nbt.idl | 10 | ||||
-rw-r--r-- | source4/librpc/idl/policyagent.idl | 2 | ||||
-rw-r--r-- | source4/librpc/idl/security.idl | 3 | ||||
-rw-r--r-- | source4/librpc/ndr/libndr.h | 4 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_basic.c | 4 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_sec_helper.c | 51 | ||||
-rw-r--r-- | source4/librpc/rpc/binding.c | 724 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc.c | 15 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_connect.c | 15 | ||||
-rw-r--r-- | source4/librpc/rpc/dcerpc_util.c | 710 |
12 files changed, 823 insertions, 761 deletions
diff --git a/source4/librpc/config.mk b/source4/librpc/config.mk index cb679d20bb..c5820619d9 100644 --- a/source4/librpc/config.mk +++ b/source4/librpc/config.mk @@ -459,8 +459,9 @@ PUBLIC_HEADERS += librpc/gen_ndr/ndr_svcctl_c.h [LIBRARY::dcerpc_atsvc] PUBLIC_DEPENDENCIES = dcerpc NDR_ATSVC -VERSION = 0.0.1 -SO_VERSION = 0 + +dcerpc_atsvc_VERSION = 0.0.1 +dcerpc_atsvc_SOVERSION = 0 dcerpc_atsvc_OBJ_FILES = librpc/gen_ndr/ndr_atsvc_c.o PC_FILES += librpc/dcerpc_atsvc.pc @@ -588,7 +589,7 @@ PC_FILES += librpc/dcerpc.pc dcerpc_VERSION = 0.0.1 dcerpc_SOVERSION = 0 -dcerpc_OBJ_FILES = $(addprefix librpc/rpc/, dcerpc.o dcerpc_auth.o dcerpc_schannel.o dcerpc_util.o \ +dcerpc_OBJ_FILES = $(addprefix librpc/rpc/, dcerpc.o dcerpc_auth.o dcerpc_schannel.o dcerpc_util.o binding.o \ dcerpc_error.o dcerpc_smb.o dcerpc_smb2.o dcerpc_sock.o dcerpc_connect.o dcerpc_secondary.o) @@ -718,73 +719,84 @@ PUBLIC_DEPENDENCIES = LIBCLI_SMB NDR_MISC LIBSAMBA-UTIL LIBSAMBA-HOSTCONFIG dcer swig_dcerpc_OBJ_FILES = librpc/rpc/dcerpc_wrap.o [PYTHON::python_echo] -PRIVATE_DEPENDENCIES = RPC_NDR_ECHO +PRIVATE_DEPENDENCIES = RPC_NDR_ECHO PYTALLOC python_echo_OBJ_FILES = librpc/gen_ndr/py_echo.o [PYTHON::python_winreg] -PRIVATE_DEPENDENCIES = RPC_NDR_WINREG python_misc +PRIVATE_DEPENDENCIES = RPC_NDR_WINREG python_misc PYTALLOC python_winreg_OBJ_FILES = librpc/gen_ndr/py_winreg.o [PYTHON::python_dcerpc_misc] +PRIVATE_DEPENDENCIES = PYTALLOC python_dcerpc_misc_OBJ_FILES = librpc/gen_ndr/py_misc.o [PYTHON::python_initshutdown] -PRIVATE_DEPENDENCIES = RPC_NDR_INITSHUTDOWN +PRIVATE_DEPENDENCIES = RPC_NDR_INITSHUTDOWN PYTALLOC python_initshutdown_OBJ_FILES = librpc/gen_ndr/py_initshutdown.o [PYTHON::python_epmapper] +PRIVATE_DEPENDENCIES = PYTALLOC python_epmapper_OBJ_FILES = librpc/gen_ndr/py_epmapper.o [PYTHON::python_mgmt] -PRIVATE_DEPENDENCIES = dcerpc_mgmt +PRIVATE_DEPENDENCIES = dcerpc_mgmt PYTALLOC python_mgmt_OBJ_FILES = librpc/gen_ndr/py_mgmt.o [PYTHON::python_atsvc] -PRIVATE_DEPENDENCIES = dcerpc_atsvc +PRIVATE_DEPENDENCIES = dcerpc_atsvc PYTALLOC python_atsvc_OBJ_FILES = librpc/gen_ndr/py_atsvc.o [PYTHON::python_samr] -PRIVATE_DEPENDENCIES = dcerpc_samr +PRIVATE_DEPENDENCIES = dcerpc_samr PYTALLOC + +python_samr_OBJ_FILES = librpc/gen_ndr/py_samr.o python_samr_OBJ_FILES = librpc/gen_ndr/py_samr.o [PYTHON::python_svcctl] -PRIVATE_DEPENDENCIES = RPC_NDR_SVCCTL +PRIVATE_DEPENDENCIES = RPC_NDR_SVCCTL PYTALLOC python_svcctl_OBJ_FILES = librpc/gen_ndr/py_svcctl.o [PYTHON::python_lsa] -PRIVATE_DEPENDENCIES = RPC_NDR_LSA +PRIVATE_DEPENDENCIES = RPC_NDR_LSA PYTALLOC + +python_lsa_OBJ_FILES = librpc/gen_ndr/py_lsa.o python_lsa_OBJ_FILES = librpc/gen_ndr/py_lsa.o [PYTHON::python_wkssvc] -PRIVATE_DEPENDENCIES = RPC_NDR_WKSSVC +PRIVATE_DEPENDENCIES = RPC_NDR_WKSSVC PYTALLOC python_wkssvc_OBJ_FILES = librpc/gen_ndr/py_wkssvc.o [PYTHON::python_dfs] -PRIVATE_DEPENDENCIES = RPC_NDR_DFS +PRIVATE_DEPENDENCIES = RPC_NDR_DFS PYTALLOC + +python_dfs_OBJ_FILES = librpc/gen_ndr/py_dfs.o python_dfs_OBJ_FILES = gen_ndr/py_dfs.o [PYTHON::python_unixinfo] -PRIVATE_DEPENDENCIES = RPC_NDR_UNIXINFO +PRIVATE_DEPENDENCIES = RPC_NDR_UNIXINFO PYTALLOC -python_unixinfo_OBJ_FILES = gen_ndr/py_unixinfo.o +python_unixinfo_OBJ_FILES = librpc/gen_ndr/py_unixinfo.o [PYTHON::python_drsuapi] -PRIVATE_DEPENDENCIES = RPC_NDR_DRSUAPI +PRIVATE_DEPENDENCIES = RPC_NDR_DRSUAPI PYTALLOC + +python_drsuapi_OBJ_FILES = librpc/gen_ndr/py_drsuapi.o python_drsuapi_OBJ_FILES = gen_ndr/py_drsuapi.o [PYTHON::python_dcerpc_security] +PRIVATE_DEPENDENCIES = PYTALLOC python_dcerpc_security_OBJ_FILES = librpc/gen_ndr/py_security.o diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl index 9652571668..2f48287233 100644 --- a/source4/librpc/idl/drsuapi.idl +++ b/source4/librpc/idl/drsuapi.idl @@ -849,7 +849,7 @@ interface drsuapi [case(1)] drsuapi_DsNameCtr1 *ctr1; } drsuapi_DsNameCtr; - [todo] WERROR drsuapi_DsCrackNames( + WERROR drsuapi_DsCrackNames( [in] policy_handle *bind_handle, [in, out] int32 level, [in,switch_is(level)] drsuapi_DsNameRequest req, diff --git a/source4/librpc/idl/nbt.idl b/source4/librpc/idl/nbt.idl index aa88360882..dddfa4e1ce 100644 --- a/source4/librpc/idl/nbt.idl +++ b/source4/librpc/idl/nbt.idl @@ -440,9 +440,8 @@ interface nbt nstring unicode_domain; uint32 db_count; nbt_db_change dbchange[db_count]; - [value(ndr_size_dom_sid(&sid, ndr->flags))] uint32 sid_size; - [flag(NDR_ALIGN4)] DATA_BLOB _pad2; - dom_sid sid; + [value(ndr_size_dom_sid0(&sid, ndr->flags))] uint32 sid_size; + [subcontext(0),subcontext_size(sid_size)] dom_sid0 sid; uint32 nt_version; uint16 lmnt_token; uint16 lm20_token; @@ -560,9 +559,8 @@ interface nbt nstring user_name; astring mailslot_name; uint32 acct_control; - [value(ndr_size_dom_sid(&sid, ndr->flags))] uint32 sid_size; - [flag(NDR_ALIGN4)] DATA_BLOB _pad; - dom_sid sid; + [value(ndr_size_dom_sid0(&sid, ndr->flags))] uint32 sid_size; + [subcontext(0),subcontext_size(sid_size)] dom_sid0 sid; uint32 nt_version; uint16 lmnt_token; uint16 lm20_token; diff --git a/source4/librpc/idl/policyagent.idl b/source4/librpc/idl/policyagent.idl index 295b70a2a1..ab137faf27 100644 --- a/source4/librpc/idl/policyagent.idl +++ b/source4/librpc/idl/policyagent.idl @@ -9,5 +9,5 @@ { /*****************/ /* Function 0x00 */ - WERROR policyagent_Dummy(); + [todo] WERROR policyagent_Dummy(); } diff --git a/source4/librpc/idl/security.idl b/source4/librpc/idl/security.idl index 753fad85cf..314846c53f 100644 --- a/source4/librpc/idl/security.idl +++ b/source4/librpc/idl/security.idl @@ -22,6 +22,9 @@ cpp_quote("#define dom_sid2 dom_sid") /* same struct as dom_sid but inside a 28 bytes fixed buffer in NDR */ cpp_quote("#define dom_sid28 dom_sid") +/* same struct as dom_sid but in a variable byte buffer, which is maybe empty in NDR */ +cpp_quote("#define dom_sid0 dom_sid") + [ pointer_default(unique) ] diff --git a/source4/librpc/ndr/libndr.h b/source4/librpc/ndr/libndr.h index 2439c386db..b719be2bab 100644 --- a/source4/librpc/ndr/libndr.h +++ b/source4/librpc/ndr/libndr.h @@ -336,6 +336,10 @@ enum ndr_err_code ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const enum ndr_err_code ndr_pull_dom_sid28(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid); void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct dom_sid *sid); size_t ndr_size_dom_sid28(const struct dom_sid *sid, int flags); +enum ndr_err_code ndr_push_dom_sid0(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid); +enum ndr_err_code ndr_pull_dom_sid0(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid); +void ndr_print_dom_sid0(struct ndr_print *ndr, const char *name, const struct dom_sid *sid); +size_t ndr_size_dom_sid0(const struct dom_sid *sid, int flags); void ndr_print_ipv4_addr(struct ndr_print *ndr, const char *name, const struct in_addr *_ip); void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *guid); enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, const void *p, ndr_push_flags_fn_t fn); diff --git a/source4/librpc/ndr/ndr_basic.c b/source4/librpc/ndr/ndr_basic.c index 93a177f94e..1d2b47c850 100644 --- a/source4/librpc/ndr/ndr_basic.c +++ b/source4/librpc/ndr/ndr_basic.c @@ -196,7 +196,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_hyper(struct ndr_pull *ndr, int ndr_flags, u */ _PUBLIC_ enum ndr_err_code ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v) { - intptr_t h; + uintptr_t h; NDR_PULL_ALIGN(ndr, sizeof(h)); NDR_PULL_NEED_BYTES(ndr, sizeof(h)); memcpy(&h, ndr->data+ndr->offset, sizeof(h)); @@ -393,7 +393,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_hyper(struct ndr_push *ndr, int ndr_flags, u */ _PUBLIC_ enum ndr_err_code ndr_push_pointer(struct ndr_push *ndr, int ndr_flags, void* v) { - intptr_t h = (intptr_t)v; + uintptr_t h = (intptr_t)v; NDR_PUSH_ALIGN(ndr, sizeof(h)); NDR_PUSH_NEED_BYTES(ndr, sizeof(h)); memcpy(ndr->data+ndr->offset, &h, sizeof(h)); diff --git a/source4/librpc/ndr/ndr_sec_helper.c b/source4/librpc/ndr/ndr_sec_helper.c index 5a0178bd25..1256d7dd2d 100644 --- a/source4/librpc/ndr/ndr_sec_helper.c +++ b/source4/librpc/ndr/ndr_sec_helper.c @@ -48,6 +48,11 @@ size_t ndr_size_dom_sid28(const struct dom_sid *sid, int flags) return 8 + 4*sid->num_auths; } +size_t ndr_size_dom_sid0(const struct dom_sid *sid, int flags) +{ + return ndr_size_dom_sid28(sid, flags); +} + /* return the wire size of a security_ace */ @@ -128,6 +133,11 @@ void ndr_print_dom_sid28(struct ndr_print *ndr, const char *name, const struct d ndr_print_dom_sid(ndr, name, sid); } +void ndr_print_dom_sid0(struct ndr_print *ndr, const char *name, const struct dom_sid *sid) +{ + ndr_print_dom_sid(ndr, name, sid); +} + /* parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field @@ -225,3 +235,44 @@ enum ndr_err_code ndr_push_dom_sid28(struct ndr_push *ndr, int ndr_flags, const return NDR_ERR_SUCCESS; } +/* + parse a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty +*/ +enum ndr_err_code ndr_pull_dom_sid0(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid) +{ + if (!(ndr_flags & NDR_SCALARS)) { + return NDR_ERR_SUCCESS; + } + + if (ndr->data_size == ndr->offset) { + ZERO_STRUCTP(sid); + return NDR_ERR_SUCCESS; + } + + return ndr_pull_dom_sid(ndr, ndr_flags, sid); +} + +/* + push a dom_sid0 - this is a dom_sid in a variable byte buffer, which is maybe empty +*/ +enum ndr_err_code ndr_push_dom_sid0(struct ndr_push *ndr, int ndr_flags, const struct dom_sid *sid) +{ + struct dom_sid zero_sid; + + if (!(ndr_flags & NDR_SCALARS)) { + return NDR_ERR_SUCCESS; + } + + if (!sid) { + return NDR_ERR_SUCCESS; + } + + ZERO_STRUCT(zero_sid); + + if (memcmp(&zero_sid, sid, sizeof(zero_sid)) == 0) { + return NDR_ERR_SUCCESS; + } + + return ndr_push_dom_sid(ndr, ndr_flags, sid); +} + diff --git a/source4/librpc/rpc/binding.c b/source4/librpc/rpc/binding.c new file mode 100644 index 0000000000..ae88dce1be --- /dev/null +++ b/source4/librpc/rpc/binding.c @@ -0,0 +1,724 @@ +/* + Unix SMB/CIFS implementation. + + dcerpc utility functions + + Copyright (C) Andrew Tridgell 2003 + 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/>. +*/ + +#include "includes.h" +#include "lib/events/events.h" +#include "librpc/gen_ndr/ndr_epmapper_c.h" +#include "librpc/gen_ndr/ndr_dcerpc.h" +#include "librpc/gen_ndr/ndr_misc.h" + +#define MAX_PROTSEQ 10 + +static const struct { + const char *name; + enum dcerpc_transport_t transport; + int num_protocols; + enum epm_protocol protseq[MAX_PROTSEQ]; +} transports[] = { + { "ncacn_np", NCACN_NP, 3, + { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NETBIOS }}, + { "ncacn_ip_tcp", NCACN_IP_TCP, 3, + { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP, EPM_PROTOCOL_IP } }, + { "ncacn_http", NCACN_HTTP, 3, + { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP, EPM_PROTOCOL_IP } }, + { "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 } }, + { "ncacn_unix_stream", NCACN_UNIX_STREAM, 2, + { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_UNIX_DS } }, + { "ncadg_unix_dgram", NCADG_UNIX_DGRAM, 2, + { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_UNIX_DS } }, + { "ncacn_at_dsp", NCACN_AT_DSP, 3, + { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_APPLETALK, EPM_PROTOCOL_DSP } }, + { "ncadg_at_ddp", NCADG_AT_DDP, 3, + { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_APPLETALK, EPM_PROTOCOL_DDP } }, + { "ncacn_vns_ssp", NCACN_VNS_SPP, 3, + { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_STREETTALK, EPM_PROTOCOL_VINES_SPP } }, + { "ncacn_vns_ipc", NCACN_VNS_IPC, 3, + { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_STREETTALK, EPM_PROTOCOL_VINES_IPC }, }, + { "ncadg_ipx", NCADG_IPX, 2, + { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_IPX }, + }, + { "ncacn_spx", NCACN_SPX, 3, + /* I guess some MS programmer confused the identifier for + * EPM_PROTOCOL_UUID (0x0D or 13) with the one for + * EPM_PROTOCOL_SPX (0x13) here. -- jelmer*/ + { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_UUID }, + }, +}; + +static const struct { + const char *name; + uint32_t flag; +} ncacn_options[] = { + {"sign", DCERPC_SIGN}, + {"seal", DCERPC_SEAL}, + {"connect", DCERPC_CONNECT}, + {"spnego", DCERPC_AUTH_SPNEGO}, + {"ntlm", DCERPC_AUTH_NTLM}, + {"krb5", DCERPC_AUTH_KRB5}, + {"validate", DCERPC_DEBUG_VALIDATE_BOTH}, + {"print", DCERPC_DEBUG_PRINT_BOTH}, + {"padcheck", DCERPC_DEBUG_PAD_CHECK}, + {"bigendian", DCERPC_PUSH_BIGENDIAN}, + {"smb2", DCERPC_SMB2} +}; + +const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor) +{ + struct ndr_syntax_id syntax; + NTSTATUS status; + + switch(epm_floor->lhs.protocol) { + case EPM_PROTOCOL_UUID: + status = dcerpc_floor_get_lhs_data(epm_floor, &syntax); + if (NT_STATUS_IS_OK(status)) { + /* lhs is used: UUID */ + char *uuidstr; + + if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax.uuid)) { + return "NDR"; + } + + if (GUID_equal(&syntax.uuid, &ndr64_transfer_syntax.uuid)) { + return "NDR64"; + } + + uuidstr = GUID_string(mem_ctx, &syntax.uuid); + + 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)); + } + + case EPM_PROTOCOL_NCACN: + return "RPC-C"; + + case EPM_PROTOCOL_NCADG: + return "RPC"; + + case EPM_PROTOCOL_NCALRPC: + return "NCALRPC"; + + case EPM_PROTOCOL_DNET_NSP: + return "DNET/NSP"; + + 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_SMB: + return talloc_asprintf(mem_ctx, "SMB:%s", epm_floor->rhs.smb.unc); + + case EPM_PROTOCOL_UNIX_DS: + return talloc_asprintf(mem_ctx, "Unix:%s", epm_floor->rhs.unix_ds.path); + + case EPM_PROTOCOL_NETBIOS: + return talloc_asprintf(mem_ctx, "NetBIOS:%s", epm_floor->rhs.netbios.name); + + case EPM_PROTOCOL_NETBEUI: + return "NETBeui"; + + case EPM_PROTOCOL_SPX: + return "SPX"; + + case EPM_PROTOCOL_NB_IPX: + return "NB_IPX"; + + case EPM_PROTOCOL_HTTP: + return talloc_asprintf(mem_ctx, "HTTP:%d", epm_floor->rhs.http.port); + + case EPM_PROTOCOL_TCP: + return talloc_asprintf(mem_ctx, "TCP:%d", epm_floor->rhs.tcp.port); + + case EPM_PROTOCOL_UDP: + return talloc_asprintf(mem_ctx, "UDP:%d", epm_floor->rhs.udp.port); + + default: + return talloc_asprintf(mem_ctx, "UNK(%02x):", epm_floor->lhs.protocol); + } +} + + +/* + form a binding string from a binding structure +*/ +_PUBLIC_ char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_binding *b) +{ + char *s = talloc_strdup(mem_ctx, ""); + int i; + 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; + } + } + if (!t_name) { + return NULL; + } + } + + if (!GUID_all_zero(&b->object.uuid)) { + s = talloc_asprintf(s, "%s@", + GUID_string(mem_ctx, &b->object.uuid)); + } + + if (t_name != NULL) { + s = talloc_asprintf_append_buffer(s, "%s:", t_name); + if (s == NULL) { + return NULL; + } + } + + if (b->host) { + s = talloc_asprintf_append_buffer(s, "%s", b->host); + } + + if (!b->endpoint && !b->options && !b->flags) { + return s; + } + + s = talloc_asprintf_append_buffer(s, "["); + + if (b->endpoint) { + s = talloc_asprintf_append_buffer(s, "%s", b->endpoint); + } + + /* this is a *really* inefficent way of dealing with strings, + but this is rarely called and the strings are always short, + so I don't care */ + for (i=0;b->options && b->options[i];i++) { + s = talloc_asprintf_append_buffer(s, ",%s", b->options[i]); + if (!s) return NULL; + } + + for (i=0;i<ARRAY_SIZE(ncacn_options);i++) { + if (b->flags & ncacn_options[i].flag) { + s = talloc_asprintf_append_buffer(s, ",%s", ncacn_options[i].name); + if (!s) return NULL; + } + } + + s = talloc_asprintf_append_buffer(s, "]"); + + return s; +} + +/* + parse a binding string into a dcerpc_binding structure +*/ +_PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_binding **b_out) +{ + struct dcerpc_binding *b; + char *options; + char *p; + int i, j, comma_count; + + b = talloc(mem_ctx, struct dcerpc_binding); + if (!b) { + return NT_STATUS_NO_MEMORY; + } + + p = strchr(s, '@'); + + if (p && PTR_DIFF(p, s) == 36) { /* 36 is the length of a UUID */ + NTSTATUS status; + + status = GUID_from_string(s, &b->object.uuid); + + if (NT_STATUS_IS_ERR(status)) { + DEBUG(0, ("Failed parsing UUID\n")); + return status; + } + + s = p + 1; + } else { + ZERO_STRUCT(b->object); + } + + b->object.if_version = 0; + + p = strchr(s, ':'); + + if (p == NULL) { + b->transport = NCA_UNKNOWN; + } else { + char *type = talloc_strndup(mem_ctx, s, PTR_DIFF(p, s)); + if (!type) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0;i<ARRAY_SIZE(transports);i++) { + if (strcasecmp(type, transports[i].name) == 0) { + b->transport = transports[i].transport; + break; + } + } + + if (i==ARRAY_SIZE(transports)) { + DEBUG(0,("Unknown dcerpc transport '%s'\n", type)); + return NT_STATUS_INVALID_PARAMETER; + } + + talloc_free(type); + + s = p+1; + } + + p = strchr(s, '['); + if (p) { + b->host = talloc_strndup(b, s, PTR_DIFF(p, s)); + options = talloc_strdup(mem_ctx, p+1); + if (options[strlen(options)-1] != ']') { + return NT_STATUS_INVALID_PARAMETER; + } + options[strlen(options)-1] = 0; + } else { + b->host = talloc_strdup(b, s); + options = NULL; + } + if (!b->host) { + return NT_STATUS_NO_MEMORY; + } + + b->target_hostname = b->host; + + b->options = NULL; + b->flags = 0; + b->assoc_group_id = 0; + b->endpoint = NULL; + + if (!options) { + *b_out = b; + return NT_STATUS_OK; + } + + comma_count = count_chars(options, ','); + + b->options = talloc_array(b, const char *, comma_count+2); + if (!b->options) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0; (p = strchr(options, ',')); i++) { + b->options[i] = talloc_strndup(b, options, PTR_DIFF(p, options)); + if (!b->options[i]) { + return NT_STATUS_NO_MEMORY; + } + options = p+1; + } + b->options[i] = options; + b->options[i+1] = NULL; + + /* some options are pre-parsed for convenience */ + for (i=0;b->options[i];i++) { + for (j=0;j<ARRAY_SIZE(ncacn_options);j++) { + if (strcasecmp(ncacn_options[j].name, b->options[i]) == 0) { + int k; + b->flags |= ncacn_options[j].flag; + for (k=i;b->options[k];k++) { + b->options[k] = b->options[k+1]; + } + i--; + break; + } + } + } + + if (b->options[0]) { + /* Endpoint is first option */ + b->endpoint = b->options[0]; + if (strlen(b->endpoint) == 0) b->endpoint = NULL; + + for (i=0;b->options[i];i++) { + b->options[i] = b->options[i+1]; + } + } + + 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) +{ + 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); + enum ndr_err_code ndr_err; + uint16_t if_version=0; + + ndr->flags |= LIBNDR_FLAG_NOALIGN; + + ndr_err = ndr_pull_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(mem_ctx); + return ndr_map_error2ntstatus(ndr_err); + } + + ndr_err = ndr_pull_uint16(ndr, NDR_SCALARS, &if_version); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(mem_ctx); + return ndr_map_error2ntstatus(ndr_err); + } + + syntax->if_version = if_version; + + talloc_free(mem_ctx); + + return NT_STATUS_OK; +} + +static DATA_BLOB dcerpc_floor_pack_lhs_data(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax) +{ + struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx, NULL); + + ndr->flags |= LIBNDR_FLAG_NOALIGN; + + ndr_push_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid); + ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version); + + return ndr_push_blob(ndr); +} + +const char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor) +{ + switch (epm_floor->lhs.protocol) { + 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); + + case EPM_PROTOCOL_HTTP: + if (epm_floor->rhs.http.port == 0) return NULL; + return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.http.port); + + case EPM_PROTOCOL_IP: + return talloc_strdup(mem_ctx, epm_floor->rhs.ip.ipaddr); + + case EPM_PROTOCOL_NCACN: + return NULL; + + case EPM_PROTOCOL_NCADG: + return NULL; + + case EPM_PROTOCOL_SMB: + 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_NETBIOS: + if (strlen(epm_floor->rhs.netbios.name) == 0) return NULL; + return talloc_strdup(mem_ctx, epm_floor->rhs.netbios.name); + + 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; + + default: + DEBUG(0,("Unsupported lhs protocol %d\n", epm_floor->lhs.protocol)); + break; + } + + return NULL; +} + +static NTSTATUS dcerpc_floor_set_rhs_data(TALLOC_CTX *mem_ctx, + struct epm_floor *epm_floor, + const char *data) +{ + switch (epm_floor->lhs.protocol) { + 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; + + case EPM_PROTOCOL_HTTP: + epm_floor->rhs.http.port = atoi(data); + return NT_STATUS_OK; + + case EPM_PROTOCOL_IP: + epm_floor->rhs.ip.ipaddr = talloc_strdup(mem_ctx, data); + NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.ip.ipaddr); + return NT_STATUS_OK; + + case EPM_PROTOCOL_NCACN: + epm_floor->rhs.ncacn.minor_version = 0; + return NT_STATUS_OK; + + case EPM_PROTOCOL_NCADG: + epm_floor->rhs.ncadg.minor_version = 0; + return NT_STATUS_OK; + + case EPM_PROTOCOL_SMB: + epm_floor->rhs.smb.unc = talloc_strdup(mem_ctx, data); + 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); + return NT_STATUS_OK; + + case EPM_PROTOCOL_NETBIOS: + epm_floor->rhs.netbios.name = talloc_strdup(mem_ctx, data); + NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.netbios.name); + return NT_STATUS_OK; + + 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; + + default: + DEBUG(0,("Unsupported lhs protocol %d\n", epm_floor->lhs.protocol)); + break; + } + + return NT_STATUS_NOT_SUPPORTED; +} + +enum dcerpc_transport_t dcerpc_transport_by_endpoint_protocol(int prot) +{ + int i; + + /* Find a transport that has 'prot' as 4th protocol */ + for (i=0;i<ARRAY_SIZE(transports);i++) { + if (transports[i].num_protocols >= 2 && + transports[i].protseq[1] == prot) { + return transports[i].transport; + } + } + + /* Unknown transport */ + return (unsigned int)-1; +} + +_PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_tower(struct epm_tower *tower) +{ + int i; + + /* Find a transport that matches this tower */ + for (i=0;i<ARRAY_SIZE(transports);i++) { + int j; + if (transports[i].num_protocols != tower->num_floors - 2) { + continue; + } + + for (j = 0; j < transports[i].num_protocols; j++) { + if (transports[i].protseq[j] != tower->floors[j+2].lhs.protocol) { + break; + } + } + + if (j == transports[i].num_protocols) { + return transports[i].transport; + } + } + + /* Unknown transport */ + return (unsigned int)-1; +} + +_PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, + struct epm_tower *tower, + struct dcerpc_binding **b_out) +{ + NTSTATUS status; + struct dcerpc_binding *binding; + + binding = talloc(mem_ctx, struct dcerpc_binding); + NT_STATUS_HAVE_NO_MEMORY(binding); + + ZERO_STRUCT(binding->object); + binding->options = NULL; + binding->host = NULL; + binding->target_hostname = NULL; + binding->flags = 0; + binding->assoc_group_id = 0; + + binding->transport = dcerpc_transport_by_tower(tower); + + if (binding->transport == (unsigned int)-1) { + return NT_STATUS_NOT_SUPPORTED; + } + + if (tower->num_floors < 1) { + return NT_STATUS_OK; + } + + /* 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 */ + if (tower->num_floors >= 4) { + binding->endpoint = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[3]); + } else { + binding->endpoint = NULL; + } + + /* Set network address */ + if (tower->num_floors >= 5) { + binding->host = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[4]); + NT_STATUS_HAVE_NO_MEMORY(binding->host); + binding->target_hostname = binding->host; + } + *b_out = binding; + return NT_STATUS_OK; +} + +_PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, 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) { + protseq = transports[i].protseq; + num_protocols = transports[i].num_protocols; + break; + } + } + + if (num_protocols == -1) { + DEBUG(0, ("Unable to find transport with id '%d'\n", binding->transport)); + return NT_STATUS_UNSUCCESSFUL; + } + + tower->num_floors = 2 + num_protocols; + tower->floors = talloc_array(mem_ctx, struct epm_floor, tower->num_floors); + + /* 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].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, + &ndr_transfer_syntax); + + tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 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); + ZERO_STRUCT(tower->floors[2 + i].rhs); + dcerpc_floor_set_rhs_data(mem_ctx, &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); + 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], + binding->host); + } else { + /* note that we don't attempt to resolve the + name here - when we get a hostname here we + 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], + "0.0.0.0"); + } + if (NT_STATUS_IS_ERR(status)) { + return status; + } + } + + return NT_STATUS_OK; +} diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index 5e32f6f5bf..4758189d3b 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -67,22 +67,15 @@ static struct dcerpc_connection *dcerpc_connection_init(TALLOC_CTX *mem_ctx, return NULL; } - if (ev == NULL) { - ev = event_context_init(c); - if (ev == NULL) { - talloc_free(c); - return NULL; - } - } - c->iconv_convenience = talloc_reference(c, ic); - c->event_ctx = ev; - - if (!talloc_reference(c, ev)) { + c->event_ctx = talloc_reference(c, ev); + + if (c->event_ctx == NULL) { talloc_free(c); return NULL; } + c->call_id = 1; c->security_state.auth_info = NULL; c->security_state.session_key = dcerpc_generic_session_key; diff --git a/source4/librpc/rpc/dcerpc_connect.c b/source4/librpc/rpc/dcerpc_connect.c index cc7f2ddbaa..a22cad9a4a 100644 --- a/source4/librpc/rpc/dcerpc_connect.c +++ b/source4/librpc/rpc/dcerpc_connect.c @@ -717,12 +717,6 @@ _PUBLIC_ struct composite_context* dcerpc_pipe_connect_b_send(TALLOC_CTX *parent struct pipe_connect_state *s; struct event_context *new_ev = NULL; - if (ev == NULL) { - new_ev = event_context_init(parent_ctx); - if (new_ev == NULL) return NULL; - ev = new_ev; - } - /* composite context allocation and setup */ c = composite_create(parent_ctx, ev); if (c == NULL) { @@ -844,21 +838,12 @@ _PUBLIC_ struct composite_context* dcerpc_pipe_connect_send(TALLOC_CTX *parent_c struct pipe_conn_state *s; struct dcerpc_binding *b; struct composite_context *pipe_conn_req; - struct event_context *new_ev = NULL; - - if (ev == NULL) { - new_ev = event_context_init(parent_ctx); - if (new_ev == NULL) return NULL; - ev = new_ev; - } /* composite context allocation and setup */ c = composite_create(parent_ctx, ev); if (c == NULL) { - talloc_free(new_ev); return NULL; } - talloc_steal(c, new_ev); s = talloc_zero(c, struct pipe_conn_state); if (composite_nomem(s, c)) return c; diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 3b8768ccc2..71c6d5f2cc 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -97,701 +97,6 @@ NTSTATUS ncacn_push_auth(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -#define MAX_PROTSEQ 10 - -static const struct { - const char *name; - enum dcerpc_transport_t transport; - int num_protocols; - enum epm_protocol protseq[MAX_PROTSEQ]; -} transports[] = { - { "ncacn_np", NCACN_NP, 3, - { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB, EPM_PROTOCOL_NETBIOS }}, - { "ncacn_ip_tcp", NCACN_IP_TCP, 3, - { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP, EPM_PROTOCOL_IP } }, - { "ncacn_http", NCACN_HTTP, 3, - { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_HTTP, EPM_PROTOCOL_IP } }, - { "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 } }, - { "ncacn_unix_stream", NCACN_UNIX_STREAM, 2, - { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_UNIX_DS } }, - { "ncadg_unix_dgram", NCADG_UNIX_DGRAM, 2, - { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_UNIX_DS } }, - { "ncacn_at_dsp", NCACN_AT_DSP, 3, - { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_APPLETALK, EPM_PROTOCOL_DSP } }, - { "ncadg_at_ddp", NCADG_AT_DDP, 3, - { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_APPLETALK, EPM_PROTOCOL_DDP } }, - { "ncacn_vns_ssp", NCACN_VNS_SPP, 3, - { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_STREETTALK, EPM_PROTOCOL_VINES_SPP } }, - { "ncacn_vns_ipc", NCACN_VNS_IPC, 3, - { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_STREETTALK, EPM_PROTOCOL_VINES_IPC }, }, - { "ncadg_ipx", NCADG_IPX, 2, - { EPM_PROTOCOL_NCADG, EPM_PROTOCOL_IPX }, - }, - { "ncacn_spx", NCACN_SPX, 3, - /* I guess some MS programmer confused the identifier for - * EPM_PROTOCOL_UUID (0x0D or 13) with the one for - * EPM_PROTOCOL_SPX (0x13) here. -- jelmer*/ - { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_UUID }, - }, -}; - -static const struct { - const char *name; - uint32_t flag; -} ncacn_options[] = { - {"sign", DCERPC_SIGN}, - {"seal", DCERPC_SEAL}, - {"connect", DCERPC_CONNECT}, - {"spnego", DCERPC_AUTH_SPNEGO}, - {"ntlm", DCERPC_AUTH_NTLM}, - {"krb5", DCERPC_AUTH_KRB5}, - {"validate", DCERPC_DEBUG_VALIDATE_BOTH}, - {"print", DCERPC_DEBUG_PRINT_BOTH}, - {"padcheck", DCERPC_DEBUG_PAD_CHECK}, - {"bigendian", DCERPC_PUSH_BIGENDIAN}, - {"smb2", DCERPC_SMB2} -}; - -const char *epm_floor_string(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor) -{ - struct ndr_syntax_id syntax; - NTSTATUS status; - - switch(epm_floor->lhs.protocol) { - case EPM_PROTOCOL_UUID: - status = dcerpc_floor_get_lhs_data(epm_floor, &syntax); - if (NT_STATUS_IS_OK(status)) { - /* lhs is used: UUID */ - char *uuidstr; - - if (GUID_equal(&syntax.uuid, &ndr_transfer_syntax.uuid)) { - return "NDR"; - } - - if (GUID_equal(&syntax.uuid, &ndr64_transfer_syntax.uuid)) { - return "NDR64"; - } - - uuidstr = GUID_string(mem_ctx, &syntax.uuid); - - 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)); - } - - case EPM_PROTOCOL_NCACN: - return "RPC-C"; - - case EPM_PROTOCOL_NCADG: - return "RPC"; - - case EPM_PROTOCOL_NCALRPC: - return "NCALRPC"; - - case EPM_PROTOCOL_DNET_NSP: - return "DNET/NSP"; - - 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_SMB: - return talloc_asprintf(mem_ctx, "SMB:%s", epm_floor->rhs.smb.unc); - - case EPM_PROTOCOL_UNIX_DS: - return talloc_asprintf(mem_ctx, "Unix:%s", epm_floor->rhs.unix_ds.path); - - case EPM_PROTOCOL_NETBIOS: - return talloc_asprintf(mem_ctx, "NetBIOS:%s", epm_floor->rhs.netbios.name); - - case EPM_PROTOCOL_NETBEUI: - return "NETBeui"; - - case EPM_PROTOCOL_SPX: - return "SPX"; - - case EPM_PROTOCOL_NB_IPX: - return "NB_IPX"; - - case EPM_PROTOCOL_HTTP: - return talloc_asprintf(mem_ctx, "HTTP:%d", epm_floor->rhs.http.port); - - case EPM_PROTOCOL_TCP: - return talloc_asprintf(mem_ctx, "TCP:%d", epm_floor->rhs.tcp.port); - - case EPM_PROTOCOL_UDP: - return talloc_asprintf(mem_ctx, "UDP:%d", epm_floor->rhs.udp.port); - - default: - return talloc_asprintf(mem_ctx, "UNK(%02x):", epm_floor->lhs.protocol); - } -} - - -/* - form a binding string from a binding structure -*/ -_PUBLIC_ char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_binding *b) -{ - char *s = talloc_strdup(mem_ctx, ""); - int i; - 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; - } - } - if (!t_name) { - return NULL; - } - } - - if (!GUID_all_zero(&b->object.uuid)) { - s = talloc_asprintf(s, "%s@", - GUID_string(mem_ctx, &b->object.uuid)); - } - - if (t_name != NULL) { - s = talloc_asprintf_append_buffer(s, "%s:", t_name); - if (s == NULL) { - return NULL; - } - } - - if (b->host) { - s = talloc_asprintf_append_buffer(s, "%s", b->host); - } - - if (!b->endpoint && !b->options && !b->flags) { - return s; - } - - s = talloc_asprintf_append_buffer(s, "["); - - if (b->endpoint) { - s = talloc_asprintf_append_buffer(s, "%s", b->endpoint); - } - - /* this is a *really* inefficent way of dealing with strings, - but this is rarely called and the strings are always short, - so I don't care */ - for (i=0;b->options && b->options[i];i++) { - s = talloc_asprintf_append_buffer(s, ",%s", b->options[i]); - if (!s) return NULL; - } - - for (i=0;i<ARRAY_SIZE(ncacn_options);i++) { - if (b->flags & ncacn_options[i].flag) { - s = talloc_asprintf_append_buffer(s, ",%s", ncacn_options[i].name); - if (!s) return NULL; - } - } - - s = talloc_asprintf_append_buffer(s, "]"); - - return s; -} - -/* - parse a binding string into a dcerpc_binding structure -*/ -_PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_binding **b_out) -{ - struct dcerpc_binding *b; - char *options; - char *p; - int i, j, comma_count; - - b = talloc(mem_ctx, struct dcerpc_binding); - if (!b) { - return NT_STATUS_NO_MEMORY; - } - - p = strchr(s, '@'); - - if (p && PTR_DIFF(p, s) == 36) { /* 36 is the length of a UUID */ - NTSTATUS status; - - status = GUID_from_string(s, &b->object.uuid); - - if (NT_STATUS_IS_ERR(status)) { - DEBUG(0, ("Failed parsing UUID\n")); - return status; - } - - s = p + 1; - } else { - ZERO_STRUCT(b->object); - } - - b->object.if_version = 0; - - p = strchr(s, ':'); - - if (p == NULL) { - b->transport = NCA_UNKNOWN; - } else { - char *type = talloc_strndup(mem_ctx, s, PTR_DIFF(p, s)); - if (!type) { - return NT_STATUS_NO_MEMORY; - } - - for (i=0;i<ARRAY_SIZE(transports);i++) { - if (strcasecmp(type, transports[i].name) == 0) { - b->transport = transports[i].transport; - break; - } - } - - if (i==ARRAY_SIZE(transports)) { - DEBUG(0,("Unknown dcerpc transport '%s'\n", type)); - return NT_STATUS_INVALID_PARAMETER; - } - - talloc_free(type); - - s = p+1; - } - - p = strchr(s, '['); - if (p) { - b->host = talloc_strndup(b, s, PTR_DIFF(p, s)); - options = talloc_strdup(mem_ctx, p+1); - if (options[strlen(options)-1] != ']') { - return NT_STATUS_INVALID_PARAMETER; - } - options[strlen(options)-1] = 0; - } else { - b->host = talloc_strdup(b, s); - options = NULL; - } - if (!b->host) { - return NT_STATUS_NO_MEMORY; - } - - b->target_hostname = b->host; - - b->options = NULL; - b->flags = 0; - b->assoc_group_id = 0; - b->endpoint = NULL; - - if (!options) { - *b_out = b; - return NT_STATUS_OK; - } - - comma_count = count_chars(options, ','); - - b->options = talloc_array(b, const char *, comma_count+2); - if (!b->options) { - return NT_STATUS_NO_MEMORY; - } - - for (i=0; (p = strchr(options, ',')); i++) { - b->options[i] = talloc_strndup(b, options, PTR_DIFF(p, options)); - if (!b->options[i]) { - return NT_STATUS_NO_MEMORY; - } - options = p+1; - } - b->options[i] = options; - b->options[i+1] = NULL; - - /* some options are pre-parsed for convenience */ - for (i=0;b->options[i];i++) { - for (j=0;j<ARRAY_SIZE(ncacn_options);j++) { - if (strcasecmp(ncacn_options[j].name, b->options[i]) == 0) { - int k; - b->flags |= ncacn_options[j].flag; - for (k=i;b->options[k];k++) { - b->options[k] = b->options[k+1]; - } - i--; - break; - } - } - } - - if (b->options[0]) { - /* Endpoint is first option */ - b->endpoint = b->options[0]; - if (strlen(b->endpoint) == 0) b->endpoint = NULL; - - for (i=0;b->options[i];i++) { - b->options[i] = b->options[i+1]; - } - } - - 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) -{ - 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); - enum ndr_err_code ndr_err; - uint16_t if_version=0; - - ndr->flags |= LIBNDR_FLAG_NOALIGN; - - ndr_err = ndr_pull_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - talloc_free(mem_ctx); - return ndr_map_error2ntstatus(ndr_err); - } - - ndr_err = ndr_pull_uint16(ndr, NDR_SCALARS, &if_version); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - talloc_free(mem_ctx); - return ndr_map_error2ntstatus(ndr_err); - } - - syntax->if_version = if_version; - - talloc_free(mem_ctx); - - return NT_STATUS_OK; -} - -static DATA_BLOB dcerpc_floor_pack_lhs_data(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax) -{ - struct ndr_push *ndr = ndr_push_init_ctx(mem_ctx, NULL); - - ndr->flags |= LIBNDR_FLAG_NOALIGN; - - ndr_push_GUID(ndr, NDR_SCALARS | NDR_BUFFERS, &syntax->uuid); - ndr_push_uint16(ndr, NDR_SCALARS, syntax->if_version); - - return ndr_push_blob(ndr); -} - -const char *dcerpc_floor_get_rhs_data(TALLOC_CTX *mem_ctx, struct epm_floor *epm_floor) -{ - switch (epm_floor->lhs.protocol) { - 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); - - case EPM_PROTOCOL_HTTP: - if (epm_floor->rhs.http.port == 0) return NULL; - return talloc_asprintf(mem_ctx, "%d", epm_floor->rhs.http.port); - - case EPM_PROTOCOL_IP: - return talloc_strdup(mem_ctx, epm_floor->rhs.ip.ipaddr); - - case EPM_PROTOCOL_NCACN: - return NULL; - - case EPM_PROTOCOL_NCADG: - return NULL; - - case EPM_PROTOCOL_SMB: - 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_NETBIOS: - if (strlen(epm_floor->rhs.netbios.name) == 0) return NULL; - return talloc_strdup(mem_ctx, epm_floor->rhs.netbios.name); - - 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; - - default: - DEBUG(0,("Unsupported lhs protocol %d\n", epm_floor->lhs.protocol)); - break; - } - - return NULL; -} - -static NTSTATUS dcerpc_floor_set_rhs_data(TALLOC_CTX *mem_ctx, - struct epm_floor *epm_floor, - const char *data) -{ - switch (epm_floor->lhs.protocol) { - 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; - - case EPM_PROTOCOL_HTTP: - epm_floor->rhs.http.port = atoi(data); - return NT_STATUS_OK; - - case EPM_PROTOCOL_IP: - epm_floor->rhs.ip.ipaddr = talloc_strdup(mem_ctx, data); - NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.ip.ipaddr); - return NT_STATUS_OK; - - case EPM_PROTOCOL_NCACN: - epm_floor->rhs.ncacn.minor_version = 0; - return NT_STATUS_OK; - - case EPM_PROTOCOL_NCADG: - epm_floor->rhs.ncadg.minor_version = 0; - return NT_STATUS_OK; - - case EPM_PROTOCOL_SMB: - epm_floor->rhs.smb.unc = talloc_strdup(mem_ctx, data); - 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); - return NT_STATUS_OK; - - case EPM_PROTOCOL_NETBIOS: - epm_floor->rhs.netbios.name = talloc_strdup(mem_ctx, data); - NT_STATUS_HAVE_NO_MEMORY(epm_floor->rhs.netbios.name); - return NT_STATUS_OK; - - 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; - - default: - DEBUG(0,("Unsupported lhs protocol %d\n", epm_floor->lhs.protocol)); - break; - } - - return NT_STATUS_NOT_SUPPORTED; -} - -enum dcerpc_transport_t dcerpc_transport_by_endpoint_protocol(int prot) -{ - int i; - - /* Find a transport that has 'prot' as 4th protocol */ - for (i=0;i<ARRAY_SIZE(transports);i++) { - if (transports[i].num_protocols >= 2 && - transports[i].protseq[1] == prot) { - return transports[i].transport; - } - } - - /* Unknown transport */ - return (unsigned int)-1; -} - -_PUBLIC_ enum dcerpc_transport_t dcerpc_transport_by_tower(struct epm_tower *tower) -{ - int i; - - /* Find a transport that matches this tower */ - for (i=0;i<ARRAY_SIZE(transports);i++) { - int j; - if (transports[i].num_protocols != tower->num_floors - 2) { - continue; - } - - for (j = 0; j < transports[i].num_protocols; j++) { - if (transports[i].protseq[j] != tower->floors[j+2].lhs.protocol) { - break; - } - } - - if (j == transports[i].num_protocols) { - return transports[i].transport; - } - } - - /* Unknown transport */ - return (unsigned int)-1; -} - -_PUBLIC_ NTSTATUS dcerpc_binding_from_tower(TALLOC_CTX *mem_ctx, - struct epm_tower *tower, - struct dcerpc_binding **b_out) -{ - NTSTATUS status; - struct dcerpc_binding *binding; - - binding = talloc(mem_ctx, struct dcerpc_binding); - NT_STATUS_HAVE_NO_MEMORY(binding); - - ZERO_STRUCT(binding->object); - binding->options = NULL; - binding->host = NULL; - binding->target_hostname = NULL; - binding->flags = 0; - binding->assoc_group_id = 0; - - binding->transport = dcerpc_transport_by_tower(tower); - - if (binding->transport == (unsigned int)-1) { - return NT_STATUS_NOT_SUPPORTED; - } - - if (tower->num_floors < 1) { - return NT_STATUS_OK; - } - - /* 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 */ - if (tower->num_floors >= 4) { - binding->endpoint = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[3]); - } else { - binding->endpoint = NULL; - } - - /* Set network address */ - if (tower->num_floors >= 5) { - binding->host = dcerpc_floor_get_rhs_data(mem_ctx, &tower->floors[4]); - NT_STATUS_HAVE_NO_MEMORY(binding->host); - binding->target_hostname = binding->host; - } - *b_out = binding; - return NT_STATUS_OK; -} - -_PUBLIC_ NTSTATUS dcerpc_binding_build_tower(TALLOC_CTX *mem_ctx, 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) { - protseq = transports[i].protseq; - num_protocols = transports[i].num_protocols; - break; - } - } - - if (num_protocols == -1) { - DEBUG(0, ("Unable to find transport with id '%d'\n", binding->transport)); - return NT_STATUS_UNSUCCESSFUL; - } - - tower->num_floors = 2 + num_protocols; - tower->floors = talloc_array(mem_ctx, struct epm_floor, tower->num_floors); - - /* 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].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, - &ndr_transfer_syntax); - - tower->floors[1].rhs.uuid.unknown = data_blob_talloc_zero(mem_ctx, 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); - ZERO_STRUCT(tower->floors[2 + i].rhs); - dcerpc_floor_set_rhs_data(mem_ctx, &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); - 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], - binding->host); - } else { - /* note that we don't attempt to resolve the - name here - when we get a hostname here we - 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], - "0.0.0.0"); - } - if (NT_STATUS_IS_ERR(status)) { - return status; - } - } - - return NT_STATUS_OK; -} - struct epm_map_binding_state { struct dcerpc_binding *binding; @@ -904,32 +209,20 @@ struct composite_context *dcerpc_epm_map_binding_send(TALLOC_CTX *mem_ctx, struct epm_map_binding_state *s; struct composite_context *pipe_connect_req; struct cli_credentials *anon_creds; - struct event_context *new_ev = NULL; NTSTATUS status; struct dcerpc_binding *epmapper_binding; int i; - /* Try to find event context in memory context in case passed - * event_context (argument) was NULL. If there's none, just - * create a new one. - */ if (ev == NULL) { - ev = event_context_find(mem_ctx); - if (ev == NULL) { - new_ev = event_context_init(mem_ctx); - if (new_ev == NULL) return NULL; - ev = new_ev; - } + return NULL; } /* composite context allocation and setup */ c = composite_create(mem_ctx, ev); if (c == NULL) { - talloc_free(new_ev); return NULL; } - talloc_steal(c, new_ev); s = talloc_zero(c, struct epm_map_binding_state); if (composite_nomem(s, c)) return c; @@ -940,7 +233,6 @@ struct composite_context *dcerpc_epm_map_binding_send(TALLOC_CTX *mem_ctx, /* anonymous credentials for rpc connection used to get endpoint mapping */ anon_creds = cli_credentials_init(mem_ctx); - cli_credentials_set_event_context(anon_creds, ev); cli_credentials_set_anonymous(anon_creds); /* |