From cc368fa69e6a205516c64712aee701fe0cf6d20b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 21 Nov 2004 17:47:09 +0000 Subject: r3898: Work towards local/server DCOM support, start working on Simple example server side implementation (This used to be commit 98afb504d95ccca4d6ec48273e10b52ccfa26ad0) --- source4/build/pidl/stub.pm | 2 +- source4/lib/dcom/classes/simple.c | 39 ++++++++++++ source4/lib/dcom/common/dcom.h | 5 +- source4/lib/dcom/common/main.c | 126 +++++++++++++++++++++++++++++++++++--- source4/lib/dcom/common/rot.c | 10 ++- source4/lib/dcom/common/tables.c | 5 +- source4/lib/dcom/config.mk | 6 ++ source4/libcli/util/smbencrypt.c | 12 ++-- source4/rpc_server/config.mk | 1 + source4/rpc_server/dcom/rodb.c | 39 ++++++++++++ source4/rpc_server/dcom/rot.c | 15 ++++- source4/torture/dcom/simple.c | 6 +- source4/torture/torture.c | 9 +++ 13 files changed, 249 insertions(+), 26 deletions(-) create mode 100644 source4/lib/dcom/classes/simple.c create mode 100644 source4/rpc_server/dcom/rodb.c diff --git a/source4/build/pidl/stub.pm b/source4/build/pidl/stub.pm index 2bcece8416..a9843e106e 100644 --- a/source4/build/pidl/stub.pm +++ b/source4/build/pidl/stub.pm @@ -90,7 +90,7 @@ static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_C { uint16 opnum = dce_call->pkt.u.request.opnum; struct GUID ipid = dce_call->pkt.u.request.object.object; - struct dcom_interface_p *iface = dcom_get_iface_p(&ipid); + struct dcom_interface_p *iface = dcom_get_local_iface_p(&ipid); const struct dcom_$name\_vtable *vtable = iface->vtable; dce_call->fault_code = 0; diff --git a/source4/lib/dcom/classes/simple.c b/source4/lib/dcom/classes/simple.c new file mode 100644 index 0000000000..e8b8730267 --- /dev/null +++ b/source4/lib/dcom/classes/simple.c @@ -0,0 +1,39 @@ +/* + Unix SMB/CIFS implementation. + Simple class + Copyright (C) 2004 Jelmer Vernooij + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "lib/dcom/common/dcom.h" + +static struct dcom_IClassFactory_vtable simple_classobject; + +NTSTATUS dcom_simple_init(void) +{ + struct GUID iid; + struct dcom_class simple_class = { + "Samba.Simple", + }; + + GUID_from_string(DCERPC_IUNKNOWN_UUID, &iid); + + simple_class.class_object = dcom_new_local_ifacep(NULL, dcom_interface_by_iid(&iid), &simple_classobject, NULL); + + GUID_from_string("5e9ddec7-5767-11cf-beab-00aa006c3606", &simple_class.clsid); + return dcom_register_class(&simple_class); +} diff --git a/source4/lib/dcom/common/dcom.h b/source4/lib/dcom/common/dcom.h index 9c09cc17d9..d8e3797c73 100644 --- a/source4/lib/dcom/common/dcom.h +++ b/source4/lib/dcom/common/dcom.h @@ -26,6 +26,7 @@ struct IUnknown_AddRef; struct IUnknown_Release; struct IUnknown_QueryInterface; +struct dcom_interface_p; struct dcom_context { @@ -53,7 +54,9 @@ struct dcom_class { const char *prog_id; struct GUID clsid; - void (*get_class_object) (struct GUID *iid, void **vtable); + + /* IUnknown */ + struct dcom_interface_p *class_object; }; struct dcom_interface diff --git a/source4/lib/dcom/common/main.c b/source4/lib/dcom/common/main.c index 60f866aede..3730137268 100644 --- a/source4/lib/dcom/common/main.c +++ b/source4/lib/dcom/common/main.c @@ -143,15 +143,15 @@ WERROR dcom_ping(struct dcom_context *ctx) return WERR_OK; } -WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) +static WERROR dcom_create_object_remote(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) { + uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; + struct dcerpc_pipe *p; + struct dcom_object_exporter *m; + NTSTATUS status; struct RemoteActivation r; struct DUALSTRINGARRAY dualstring; int i; - struct dcom_object_exporter *m; - struct dcerpc_pipe *p; - NTSTATUS status; - uint16 protseq[] = DCOM_NEGOTIATED_PROTOCOLS; status = dcom_connect_host(ctx, &p, server); if (NT_STATUS_IS_ERR(status)) { @@ -207,7 +207,60 @@ WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const ch return WERR_OK; } -WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) +WERROR dcom_create_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, int num_ifaces, struct GUID *iid, struct dcom_interface_p ***ip, WERROR *results) +{ + struct dcom_interface_p *factory, *iunk; + struct QueryInterface qr; + struct Release rr; + struct CreateInstance cr; + WERROR error; + int i; + NTSTATUS status; + + if (server != NULL) { + return dcom_create_object_remote(ctx, clsid, server, num_ifaces, iid, ip, results); + } + + /* Obtain class object */ + error = dcom_get_class_object(ctx, clsid, server, iid, &factory); + if (!W_ERROR_IS_OK(error)) { + DEBUG(3, ("Unable to obtain class object for %s\n", GUID_string(NULL, clsid))); + return error; + } + + dcom_OBJREF_from_ifacep(ctx, &cr.in.pUnknown->obj, factory); + + GUID_from_string(DCERPC_ICLASSFACTORY_UUID, cr.in.iid); + + /* Run IClassFactory::CreateInstance() */ + status = dcom_IClassFactory_CreateInstance(factory, ctx, &cr); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(3, ("Error while calling IClassFactory::CreateInstance : %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); + } + + /* Release class object */ + status = dcom_IUnknown_Release(factory, ctx, &rr); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(3, ("Error freeing class factory: %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); + } + + /* Do one or more QueryInterface calls */ + for (i = 0; i < num_ifaces; i++) { + qr.in.iid = &iid[i]; + status = dcom_IUnknown_QueryInterface(iunk, ctx, &qr); + if (NT_STATUS_IS_ERR(status)) { + DEBUG(4, ("Error obtaining interface %s : %s\n", GUID_string(NULL, &iid[i]), nt_errstr(status))); + return ntstatus_to_werror(status); + } + results[i] = qr.out.result; + } + + return WERR_OK; +} + +WERROR dcom_get_class_object_remote(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) { struct dcom_object_exporter *m; struct RemoteActivation r; @@ -258,6 +311,36 @@ WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const return WERR_OK; } +WERROR dcom_get_class_object(struct dcom_context *ctx, struct GUID *clsid, const char *server, struct GUID *iid, struct dcom_interface_p **ip) +{ + const struct dcom_class *c; + struct QueryInterface qi; + NTSTATUS status; + + if (server != NULL) { + return dcom_get_class_object_remote(ctx, clsid, server, iid, ip); + } + + c = dcom_class_by_clsid(clsid); + if (!c) { + /* FIXME: Better error code.. */ + return WERR_DEST_NOT_FOUND; + } + + qi.in.iid = iid; + + status = dcom_IUnknown_QueryInterface(c->class_object, ctx, &qi ); + if (NT_STATUS_IS_ERR(status)) { + return ntstatus_to_werror(status); + } + + if (!W_ERROR_IS_OK(qi.out.result)) { return qi.out.result; } + + dcom_ifacep_from_OBJREF(ctx, ip, &qi.out.data->obj); + + return WERR_OK; +} + NTSTATUS dcom_get_pipe (struct dcom_interface_p *iface, struct dcerpc_pipe **p) { struct dcerpc_binding binding; @@ -326,6 +409,12 @@ struct dcom_object *dcom_object_by_oid(struct dcom_object_exporter *ox, HYPER_T return o; } + +NTSTATUS dcom_OBJREF_from_ifacep(struct dcom_context *ctx, struct OBJREF *o, struct dcom_interface_p *_p) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface_p **_p, struct OBJREF *o) { struct dcom_interface_p *p = talloc_p(ctx, struct dcom_interface_p); @@ -363,7 +452,7 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface p->ipid = o->u_objref.u_handler.std.ipid; p->object = dcom_object_by_oid(p->ox, o->u_objref.u_standard.std.oid); p->ox->resolver_address = o->u_objref.u_handler.saResAddr; - p->vtable = dcom_vtable_by_clsid(&o->u_objref.u_handler.clsid); +/*FIXME p->vtable = dcom_vtable_by_clsid(&o->u_objref.u_handler.clsid);*/ /* FIXME: Do the custom unmarshaling call */ *_p = p; @@ -371,7 +460,6 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface case OBJREF_CUSTOM: { - const struct dcom_interface *imarshal = dcom_vtable_by_clsid(&o->u_objref.u_custom.clsid); p->vtable = NULL; /* FIXME: Do the actual custom unmarshaling call */ @@ -437,3 +525,25 @@ NTSTATUS dcom_ifacep_from_OBJREF(struct dcom_context *ctx, struct dcom_interface return NT_STATUS_NOT_SUPPORTED; } + +HYPER_T dcom_get_current_oxid(void) +{ + return getpid(); +} + +struct dcom_interface_p *dcom_new_local_ifacep(struct dcom_context *ctx, const struct dcom_interface *iface, void *vtable, struct dcom_object *object) +{ + struct dcom_interface_p *ip = talloc_p(ctx, struct dcom_interface_p); + + ip->ctx = ctx; + ip->interface = iface; + ip->vtable = vtable; + uuid_generate_random(&ip->ipid); + ip->object = object; + ip->objref_flags = 0; + ip->orpc_flags = 0; + ip->ox = NULL; + ip->private_references = 1; + + return ip; +} diff --git a/source4/lib/dcom/common/rot.c b/source4/lib/dcom/common/rot.c index 95f83d000c..7acdbe066e 100644 --- a/source4/lib/dcom/common/rot.c +++ b/source4/lib/dcom/common/rot.c @@ -22,9 +22,13 @@ #include "includes.h" - -struct dcom_interface_p *dcom_get_iface_p(struct GUID *ipid) +struct dcom_interface_p *dcom_get_local_iface_p(struct GUID *ipid) { - /* FIXME */ + /* FIXME: Call the local ROT and do a + * rot_get_interface_pointer call */ + + /* FIXME: Perhaps have a local (thread-local) table with + * local DCOM objects so that not every DCOM call requires a lookup + * to the ROT? */ return NULL; } diff --git a/source4/lib/dcom/common/tables.c b/source4/lib/dcom/common/tables.c index f9f1c49380..f615662b47 100644 --- a/source4/lib/dcom/common/tables.c +++ b/source4/lib/dcom/common/tables.c @@ -46,14 +46,15 @@ const struct dcom_interface *dcom_interface_by_iid(const struct GUID *iid) return NULL; } -const void *dcom_vtable_by_clsid(const struct GUID *clsid) +const struct dcom_class *dcom_class_by_clsid(const struct GUID *clsid) { struct class_list *c = classes; while(c) { - if (uuid_equal(clsid, &c->class.clsid)) + if (uuid_equal(clsid, &c->class.clsid)) { return &c->class; + } c = c->next; } diff --git a/source4/lib/dcom/config.mk b/source4/lib/dcom/config.mk index 9fda924881..d599231525 100644 --- a/source4/lib/dcom/config.mk +++ b/source4/lib/dcom/config.mk @@ -7,6 +7,12 @@ INIT_OBJ_FILES = \ lib/dcom/common/rot.o REQUIRED_SUBSYSTEMS = DCOM_PROXY_DCOM RPC_NDR_REMACT \ RPC_NDR_OXIDRESOLVER + +[MODULE::DCOM_SIMPLE] +SUBSYSTEM = LIBDCOM +INIT_FUNCTION = dcom_simple_init +INIT_OBJ_FILES = \ + lib/dcom/classes/simple.o # # End SUBSYSTEM LIBDCOM ################################################ diff --git a/source4/libcli/util/smbencrypt.c b/source4/libcli/util/smbencrypt.c index dac8674f03..1218de1fe7 100644 --- a/source4/libcli/util/smbencrypt.c +++ b/source4/libcli/util/smbencrypt.c @@ -46,9 +46,9 @@ BOOL SMBencrypt(const char *passwd, const uint8_t *c8, uint8_t p24[24]) #ifdef DEBUG_PASSWORD DEBUG(100,("SMBencrypt: lm#, challenge, response\n")); - dump_data(100, (char *)p21, 16); - dump_data(100, (const char *)c8, 8); - dump_data(100, (char *)p24, 24); + dump_data(100, p21, 16); + dump_data(100, c8, 8); + dump_data(100, p24, 24); #endif return ret; @@ -196,9 +196,9 @@ void SMBNTencrypt(const char *passwd, uint8_t *c8, uint8_t *p24) #ifdef DEBUG_PASSWORD DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n")); - dump_data(100, (char *)p21, 16); - dump_data(100, (char *)c8, 8); - dump_data(100, (char *)p24, 24); + dump_data(100, p21, 16); + dump_data(100, c8, 8); + dump_data(100, p24, 24); #endif } diff --git a/source4/rpc_server/config.mk b/source4/rpc_server/config.mk index 58f842add0..466d86a0c4 100644 --- a/source4/rpc_server/config.mk +++ b/source4/rpc_server/config.mk @@ -19,6 +19,7 @@ SUBSYSTEM = DCERPC INIT_OBJ_FILES = \ rpc_server/dcom/oxidresolver.o \ rpc_server/dcom/rot.o \ + rpc_server/dcom/rodb.o \ rpc_server/dcom/remact.o \ librpc/gen_ndr/ndr_dcom_d.o REQUIRED_SUBSYSTEMS = \ diff --git a/source4/rpc_server/dcom/rodb.c b/source4/rpc_server/dcom/rodb.c new file mode 100644 index 0000000000..56d51c7934 --- /dev/null +++ b/source4/rpc_server/dcom/rodb.c @@ -0,0 +1,39 @@ +/* + Unix SMB/CIFS implementation. + + Running objects database + + Copyright (C) Jelmer Vernooij 2004 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "rpc_server/dcerpc_server.h" +#include "librpc/gen_ndr/ndr_rot.h" +#include "rpc_server/common/common.h" + +struct tdb_wrap *openrodb(TALLOC_CTX *mem_ctx) +{ + struct tdb_wrap *wrap; + char *rodb_name = NULL; + + asprintf(&rodb_name, "%s/rot.tdb", lp_lockdir()); + wrap = tdb_wrap_open(mem_ctx, rodb_name, 0, 0, O_RDWR|O_CREAT, 0600); + SAFE_FREE(rodb_name); + + return wrap; +} + diff --git a/source4/rpc_server/dcom/rot.c b/source4/rpc_server/dcom/rot.c index 1a58833204..04fb7c73a5 100644 --- a/source4/rpc_server/dcom/rot.c +++ b/source4/rpc_server/dcom/rot.c @@ -25,14 +25,15 @@ #include "librpc/gen_ndr/ndr_rot.h" #include "rpc_server/common/common.h" - /* rot_add */ static WERROR rot_add(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct rot_add *r) { + struct tdb_wrap *db = openrodb(mem_ctx); DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + talloc_destroy(db); } @@ -42,7 +43,9 @@ static WERROR rot_add(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, static WERROR rot_remove(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct rot_remove *r) { + struct tdb_wrap *db = openrodb(mem_ctx); DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + talloc_destroy(db); } @@ -52,7 +55,9 @@ static WERROR rot_remove(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx static WERROR rot_is_listed(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct rot_is_listed *r) { + struct tdb_wrap *db = openrodb(mem_ctx); DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + talloc_destroy(db); } @@ -62,7 +67,9 @@ static WERROR rot_is_listed(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ static WERROR rot_get_interface_pointer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct rot_get_interface_pointer *r) { + struct tdb_wrap *db = openrodb(mem_ctx); DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + talloc_destroy(db); } @@ -72,7 +79,9 @@ static WERROR rot_get_interface_pointer(struct dcesrv_call_state *dce_call, TALL static WERROR rot_set_modification_time(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct rot_set_modification_time *r) { + struct tdb_wrap *db = openrodb(mem_ctx); DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + talloc_destroy(db); } @@ -82,7 +91,9 @@ static WERROR rot_set_modification_time(struct dcesrv_call_state *dce_call, TALL static WERROR rot_get_modification_time(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct rot_get_modification_time *r) { + struct tdb_wrap *db = openrodb(mem_ctx); DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + talloc_destroy(db); } @@ -92,7 +103,9 @@ static WERROR rot_get_modification_time(struct dcesrv_call_state *dce_call, TALL static WERROR rot_enum(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct rot_enum *r) { + struct tdb_wrap *db = openrodb(mem_ctx); DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + talloc_destroy(db); } diff --git a/source4/torture/dcom/simple.c b/source4/torture/dcom/simple.c index fe44a78cf5..68bf9be813 100644 --- a/source4/torture/dcom/simple.c +++ b/source4/torture/dcom/simple.c @@ -47,15 +47,13 @@ BOOL torture_dcom_simple(void) mem_ctx = talloc_init("torture_dcom_simple"); - dcom_init(&ctx, lp_parm_string(-1, "torture", "userdomain"), - lp_parm_string(-1, "torture", "username"), - lp_parm_string(-1, "torture", "password")); + torture_dcom_init(&ctx); GUID_from_string(DCERPC_ISTREAM_UUID, &IID[0]); GUID_from_string(DCERPC_IUNKNOWN_UUID, &IID[1]); GUID_from_string(CLSID_SIMPLE, &clsid); error = dcom_create_object(ctx, &clsid, - lp_parm_string(-1, "torture", "binding"), 2, IID, + lp_parm_string(-1, "torture", "dcomhost"), 2, IID, &interfaces, results); diff --git a/source4/torture/torture.c b/source4/torture/torture.c index 7d309f3741..b0a4f6ab8a 100644 --- a/source4/torture/torture.c +++ b/source4/torture/torture.c @@ -141,6 +141,15 @@ BOOL torture_close_connection(struct smbcli_state *c) return ret; } +/* initialise a DCOM context */ +NTSTATUS torture_dcom_init(struct dcom_context **ctx) +{ + dcom_init(ctx, lp_parm_string(-1, "torture", "userdomain"), + lp_parm_string(-1, "torture", "username"), + lp_parm_string(-1, "torture", "password")); + + return NT_STATUS_OK; +} /* open a rpc connection to the chosen binding string */ NTSTATUS torture_rpc_connection(struct dcerpc_pipe **p, -- cgit