From cdbc00bb52f39472fe5f1380b15180205644c8e9 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 2 Mar 2009 05:07:30 +0100 Subject: Fix test_surrounding in samba4.rpcecho.python. --- source4/scripting/python/samba/tests/dcerpc/rpcecho.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py index 12638e2397b..62268005c25 100644 --- a/source4/scripting/python/samba/tests/dcerpc/rpcecho.py +++ b/source4/scripting/python/samba/tests/dcerpc/rpcecho.py @@ -49,7 +49,7 @@ class RpcEchoTests(RpcInterfaceTestCase): surrounding_struct.x = 4 surrounding_struct.surrounding = [1,2,3,4] y = self.conn.TestSurrounding(surrounding_struct) - self.assertEquals(8 * [0], y.surrounding) + self.assertEquals(4 * [0], y.surrounding) def test_manual_request(self): self.assertEquals("\x01\x00\x00\x00", self.conn.request(0, chr(0) * 4)) -- cgit From 88bd0f2ac6bb7ec41d72a1ea3d7ee90333f4e978 Mon Sep 17 00:00:00 2001 From: Björn Jacke Date: Sun, 1 Mar 2009 21:38:31 +0100 Subject: some shells are picky about ^ without quotes --- source4/selftest/tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/selftest/tests.sh b/source4/selftest/tests.sh index 99e530ec385..39e6cff2744 100755 --- a/source4/selftest/tests.sh +++ b/source4/selftest/tests.sh @@ -126,7 +126,7 @@ all_tests="$ncalrpc_tests $ncacn_np_tests $ncacn_ip_tcp_tests $slow_ncalrpc_test # Make sure all tests get run for t in `$smb4torture --list | grep "^RPC-"` do - echo $all_tests | grep $t > /dev/null + echo $all_tests | grep "$t" > /dev/null if [ $? -ne 0 ] then auto_rpc_tests="$auto_rpc_tests $t" @@ -174,7 +174,7 @@ done # Tests for the NET API -net=`$smb4torture --list | grep ^NET-` +net=`$smb4torture --list | grep "^NET-"` for t in $net; do plansmbtorturetest "$t" dc "\$SERVER[$VALIDATE]" -U"\$USERNAME"%"\$PASSWORD" -W "\$DOMAIN" "$*" -- cgit From 212756646efa85880a6b50aa7cb404e402c2ae4a Mon Sep 17 00:00:00 2001 From: Björn Jacke Date: Sun, 1 Mar 2009 21:08:33 +0100 Subject: make man page (un)install more portable --- source4/script/installman.sh | 2 +- source4/script/uninstallman.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/script/installman.sh b/source4/script/installman.sh index ae99bceacf0..a3b6ec0d937 100755 --- a/source4/script/installman.sh +++ b/source4/script/installman.sh @@ -6,7 +6,7 @@ MANPAGES=$* for I in $MANPAGES do - SECTION=`echo $I | grep -o '.$'` + SECTION=`echo -n $I | sed "s/.*\(.\)$/\1/" DIR="$MANDIR/man$SECTION" if [ ! -d "$DIR" ] then diff --git a/source4/script/uninstallman.sh b/source4/script/uninstallman.sh index 72b523ed9e8..9b087c68bb2 100755 --- a/source4/script/uninstallman.sh +++ b/source4/script/uninstallman.sh @@ -8,7 +8,7 @@ MANPAGES=$* for I in $MANPAGES do - SECTION=`echo $I | grep -o '.$'` + SECTION=`echo -n $I | sed "s/.*\(.\)$/\1/" FNAME=$MANDIR/man$SECTION/$I if test -f $FNAME; then echo Deleting $FNAME -- cgit From 44c94b6c66b00807d58233550cf8915566cb97d0 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 4 Mar 2009 13:58:07 +1100 Subject: Allow 'net vampire' to work without an existing smb.conf Now the provision can generate one based on the detected settings from the target domain. Andrew Bartlett --- source4/param/provision.c | 8 ++++++-- source4/param/util.c | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'source4') diff --git a/source4/param/provision.c b/source4/param/provision.c index 7a06f77d968..c8bff59deb6 100644 --- a/source4/param/provision.c +++ b/source4/param/provision.c @@ -34,6 +34,7 @@ NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct provision_settings *settings, struct provision_result *result) { + char *configfile; PyObject *provision_mod, *provision_dict, *provision_fn, *py_result, *parameters; DEBUG(0,("Provision for Become-DC test using python\n")); @@ -76,8 +77,11 @@ NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, settings->targetdir)); parameters = PyDict_New(); - PyDict_SetItemString(parameters, "smbconf", - PyString_FromString(lp_configfile(lp_ctx))); + configfile = lp_configfile(lp_ctx); + if (configfile != NULL) { + PyDict_SetItemString(parameters, "smbconf", + PyString_FromString(configfile)); + } PyDict_SetItemString(parameters, "rootdn", PyString_FromString(settings->root_dn_str)); diff --git a/source4/param/util.c b/source4/param/util.c index 92728d505a8..3881107cbcf 100644 --- a/source4/param/util.c +++ b/source4/param/util.c @@ -107,7 +107,7 @@ char *config_path(TALLOC_CTX* mem_ctx, struct loadparm_context *lp_ctx, char *fname, *config_dir, *p; config_dir = talloc_strdup(mem_ctx, lp_configfile(lp_ctx)); if (config_dir == NULL) { - return NULL; + config_dir = talloc_strdup(mem_ctx, lp_default_path()); } p = strrchr(config_dir, '/'); if (p == NULL) { -- cgit From 952bdffaadebe8fc147c69da160ddd83e1d03245 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 4 Mar 2009 14:02:35 +1100 Subject: Don't print the admin password if we don't set one. For example, if we don't create the admin user (perhaps expecting users to be in LDAP already, or we are due an incoming replication) we should not confuse the administrator by printing a unused password. Andrew Bartlett --- source4/scripting/python/samba/provision.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 0aa84ec6db7..d96857661ea 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -1136,7 +1136,8 @@ def provision(setup_dir, message, session_info, message("NetBIOS Domain: %s" % names.domain) message("DNS Domain: %s" % names.dnsdomain) message("DOMAIN SID: %s" % str(domainsid)) - message("Admin password: %s" % adminpass) + if samdb_fill == FILL_FULL: + message("Admin password: %s" % adminpass) result = ProvisionResult() result.domaindn = domaindn -- cgit From 52542e1affbaad3a29d913ced06f6c5ae0d7b4ad Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 4 Mar 2009 14:06:11 +1100 Subject: Pull in all the schema information during DRS schema fetch This includes things such as allowed attributes, which were not populated into the schema structure before. Andrew Bartlett --- source4/dsdb/schema/schema_init.c | 47 +++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 9 deletions(-) (limited to 'source4') diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index fbd8946bb59..a67aecd1e86 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -1202,6 +1202,34 @@ static struct drsuapi_DsReplicaAttribute *dsdb_find_object_attr_name(struct dsdb } \ } while (0) +#define GET_STRING_LIST_DS(s, r, attr, mem_ctx, p, elem, strict) do { \ + int get_string_list_counter; \ + struct drsuapi_DsReplicaAttribute *_a; \ + _a = dsdb_find_object_attr_name(s, r, attr, NULL); \ + if (strict && !_a) { \ + d_printf("%s: %s == NULL\n", __location__, attr); \ + return WERR_INVALID_PARAM; \ + } \ + (p)->elem = _a ? talloc_array(mem_ctx, const char *, _a->value_ctr.num_values + 1) : NULL; \ + for (get_string_list_counter=0; \ + _a && get_string_list_counter < _a->value_ctr.num_values; \ + get_string_list_counter++) { \ + size_t _ret; \ + if (!convert_string_talloc_convenience(mem_ctx, s->iconv_convenience, CH_UTF16, CH_UNIX, \ + _a->value_ctr.values[get_string_list_counter].blob->data, \ + _a->value_ctr.values[get_string_list_counter].blob->length, \ + (void **)discard_const(&(p)->elem[get_string_list_counter]), &_ret, false)) { \ + DEBUG(0,("%s: invalid data!\n", attr)); \ + dump_data(0, \ + _a->value_ctr.values[get_string_list_counter].blob->data, \ + _a->value_ctr.values[get_string_list_counter].blob->length); \ + return WERR_FOOBAR; \ + } \ + (p)->elem[get_string_list_counter+1] = NULL; \ + } \ + talloc_steal(mem_ctx, (p)->elem); \ +} while (0) + #define GET_DN_DS(s, r, attr, mem_ctx, p, elem, strict) do { \ struct drsuapi_DsReplicaAttribute *_a; \ _a = dsdb_find_object_attr_name(s, r, attr, NULL); \ @@ -1412,17 +1440,18 @@ WERROR dsdb_class_from_drsuapi(struct dsdb_schema *schema, GET_STRING_DS(schema, r, "subClassOf", mem_ctx, obj, subClassOf, true); - obj->systemAuxiliaryClass = NULL; - obj->systemPossSuperiors = NULL; - obj->systemMustContain = NULL; - obj->systemMayContain = NULL; - obj->auxiliaryClass = NULL; - obj->possSuperiors = NULL; - obj->mustContain = NULL; - obj->mayContain = NULL; + GET_STRING_LIST_DS(schema, r, "systemAuxiliaryClass", mem_ctx, obj, systemAuxiliaryClass, false); + GET_STRING_LIST_DS(schema, r, "auxiliaryClass", mem_ctx, obj, auxiliaryClass, false); + + GET_STRING_LIST_DS(schema, r, "systemMustContain", mem_ctx, obj, systemMustContain, false); + GET_STRING_LIST_DS(schema, r, "systemMayContain", mem_ctx, obj, systemMayContain, false); + GET_STRING_LIST_DS(schema, r, "mustContain", mem_ctx, obj, mustContain, false); + GET_STRING_LIST_DS(schema, r, "mayContain", mem_ctx, obj, mayContain, false); - obj->possibleInferiors = NULL; + GET_STRING_LIST_DS(schema, r, "systemPossSuperiors", mem_ctx, obj, systemPossSuperiors, false); + GET_STRING_LIST_DS(schema, r, "possSuperiors", mem_ctx, obj, possSuperiors, false); + GET_STRING_LIST_DS(schema, r, "possibleInferiors", mem_ctx, obj, possibleInferiors, false); GET_STRING_DS(schema, r, "defaultSecurityDescriptor", mem_ctx, obj, defaultSecurityDescriptor, false); -- cgit From 92bb91a6115ac035e3c37e471931c2a388dc843e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 5 Mar 2009 10:46:46 +1100 Subject: Update talloc version so we don't fail on system talloc 1.2.0 The problem is that talloc in the Samba tree now includes talloc_get_type_abort(), which is not present on Fedora 10 or ubuntu's talloc 1.2.0. Andrew Bartlett --- source4/configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/configure.ac b/source4/configure.ac index 54ca9108b14..d33df084068 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -42,7 +42,7 @@ AC_CONFIG_FILES(param/samba-hostconfig.pc) AC_CONFIG_FILES(librpc/dcerpc_samr.pc) AC_CONFIG_FILES(librpc/dcerpc_atsvc.pc) -SMB_INCLUDED_LIB_PKGCONFIG(LIBTALLOC, talloc >= 1.2.0, [], +SMB_INCLUDED_LIB_PKGCONFIG(LIBTALLOC, talloc >= 1.2.1, [], [ m4_include(../lib/talloc/libtalloc.m4) SMB_INCLUDE_MK(../lib/talloc/config.mk) -- cgit From 5a10d804919af205b027ee519b9fa05519913ebe Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 5 Mar 2009 11:07:35 +1100 Subject: Remove parse_control from header, long after the function was removed Simo reminded me that when (long ago) I moved parse_controls away from this place, I forgot to update the manually maintained header file. Andrew Bartlett --- source4/lib/ldb/tools/cmdline.h | 1 - 1 file changed, 1 deletion(-) (limited to 'source4') diff --git a/source4/lib/ldb/tools/cmdline.h b/source4/lib/ldb/tools/cmdline.h index 3473d62a169..45619ce496a 100644 --- a/source4/lib/ldb/tools/cmdline.h +++ b/source4/lib/ldb/tools/cmdline.h @@ -50,5 +50,4 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const void (*usage)(void)); -struct ldb_control **parse_controls(void *mem_ctx, char **control_strings); int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request); -- cgit From df145c33822f1fc77e2602709a75c2eac71abab3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 6 Mar 2009 07:15:13 +0100 Subject: s4:errormap: map ECANCELED to NT_STATUS_CANCELLED metze --- source4/libcli/util/errormap.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4') diff --git a/source4/libcli/util/errormap.c b/source4/libcli/util/errormap.c index 0185e66c390..930e45b214e 100644 --- a/source4/libcli/util/errormap.c +++ b/source4/libcli/util/errormap.c @@ -1356,6 +1356,10 @@ const struct unix_error_map unix_nt_errmap[] = { #ifdef ENOSYS { ENOSYS, NT_STATUS_INVALID_SYSTEM_SERVICE }, #endif +#ifdef ECANCELED + { ECANCELED, NT_STATUS_CANCELLED }, +#endif + { 0, NT_STATUS_UNSUCCESSFUL } }; -- cgit From 47adaea11e553f30a43ad1dd9ac700a510c9e909 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 2 Mar 2009 17:32:24 +0100 Subject: s4-smbtorture: fix RPC-SPOOLSS test after enum out info pointer changes. Guenther --- source4/torture/rpc/spoolss.c | 48 +++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 18 deletions(-) (limited to 'source4') diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c index 9d8bc4b186e..7e8461ef831 100644 --- a/source4/torture/rpc/spoolss.c +++ b/source4/torture/rpc/spoolss.c @@ -108,6 +108,7 @@ static bool test_EnumPorts(struct torture_context *tctx, DATA_BLOB blob; uint32_t needed; uint32_t count; + union spoolss_PortInfo *info; r.in.servername = ""; r.in.level = level; @@ -115,6 +116,7 @@ static bool test_EnumPorts(struct torture_context *tctx, r.in.offered = 0; r.out.needed = &needed; r.out.count = &count; + r.out.info = &info; torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level); @@ -138,7 +140,7 @@ static bool test_EnumPorts(struct torture_context *tctx, torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed"); ctx->port_count[level] = count; - ctx->ports[level] = r.out.info; + ctx->ports[level] = info; } for (i=1;idriver_count[level] = count; - ctx->drivers[level] = r.out.info; + ctx->drivers[level] = info; } for (i=1;imonitor_count[level] = count; - ctx->monitors[level] = r.out.info; + ctx->monitors[level] = info; } for (i=1;iprint_processor_count[level] = count; - ctx->print_processors[level] = r.out.info; + ctx->print_processors[level] = info; } for (i=1;iprinter_count[level] = count; - ctx->printers[level] = r.out.info; + ctx->printers[level] = info; } for (i=1;i Date: Mon, 2 Mar 2009 17:58:13 +0100 Subject: s4-smbtorture: fix RPC-SPOOLSS-WIN. Guenther --- source4/torture/rpc/spoolss_win.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/torture/rpc/spoolss_win.c b/source4/torture/rpc/spoolss_win.c index 08fadafe2c8..add06522c61 100644 --- a/source4/torture/rpc/spoolss_win.c +++ b/source4/torture/rpc/spoolss_win.c @@ -188,6 +188,7 @@ static bool test_EnumPrinters(struct torture_context *tctx, DATA_BLOB blob = data_blob_talloc_zero(ctx, initial_blob_size); uint32_t needed; uint32_t count; + union spoolss_PrinterInfo *info; ep.in.flags = PRINTER_ENUM_NAME; ep.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); @@ -196,6 +197,7 @@ static bool test_EnumPrinters(struct torture_context *tctx, ep.in.offered = initial_blob_size; ep.out.needed = &needed; ep.out.count = &count; + ep.out.info = &info; status = dcerpc_spoolss_EnumPrinters(p, ctx, &ep); torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed."); @@ -211,7 +213,7 @@ static bool test_EnumPrinters(struct torture_context *tctx, torture_assert_werr_ok(tctx, ep.out.result, "EnumPrinters failed."); ctx->printer_count = count; - ctx->printer_info = ep.out.info; + ctx->printer_info = info; torture_comment(tctx, "Found %d printer(s).\n", ctx->printer_count); @@ -264,6 +266,7 @@ static bool test_EnumJobs(struct torture_context *tctx, DATA_BLOB blob = data_blob_talloc_zero(tctx, 1024); uint32_t needed; uint32_t count; + union spoolss_JobInfo *info; torture_comment(tctx, "Test EnumJobs\n"); @@ -273,6 +276,7 @@ static bool test_EnumJobs(struct torture_context *tctx, ej.in.offered = 1024; ej.out.needed = &needed; ej.out.count = &count; + ej.out.info = &info; status = dcerpc_spoolss_EnumJobs(p, tctx, &ej); torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed"); @@ -323,6 +327,7 @@ static bool test_EnumForms(struct torture_context *tctx, DATA_BLOB blob = data_blob_talloc_zero(tctx, initial_blob_size); uint32_t needed; uint32_t count; + union spoolss_FormInfo *info; torture_comment(tctx, "Testing EnumForms\n"); @@ -332,6 +337,7 @@ static bool test_EnumForms(struct torture_context *tctx, ef.in.offered = initial_blob_size; ef.out.needed = &needed; ef.out.count = &count; + ef.out.info = &info; status = dcerpc_spoolss_EnumForms(p, tctx, &ef); torture_assert_ntstatus_ok(tctx, status, "EnumForms failed"); -- cgit From 2fcc921237bbaac2de331ee53828ab72394a6186 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 6 Mar 2009 12:20:14 +0100 Subject: s4-smbtorture: fix s3 flavor rpc spoolss test. Guenther --- source4/torture/rpc/samba3rpc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4') diff --git a/source4/torture/rpc/samba3rpc.c b/source4/torture/rpc/samba3rpc.c index 7cacba74181..fe128fea52b 100644 --- a/source4/torture/rpc/samba3rpc.c +++ b/source4/torture/rpc/samba3rpc.c @@ -2619,6 +2619,7 @@ static bool enumprinters(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *pipe, DATA_BLOB blob; uint32_t needed; uint32_t count; + union spoolss_PrinterInfo *info; r.in.flags = PRINTER_ENUM_LOCAL; r.in.server = talloc_asprintf(mem_ctx, "\\\\%s", servername); @@ -2627,6 +2628,7 @@ static bool enumprinters(TALLOC_CTX *mem_ctx, struct dcerpc_pipe *pipe, r.in.offered = 0; r.out.needed = &needed; r.out.count = &count; + r.out.info = &info; status = dcerpc_spoolss_EnumPrinters(pipe, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { -- cgit From 8bc7bb77bebcac9b10f2718f879d92813fe275da Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 6 Mar 2009 12:24:23 +0100 Subject: s4-smbtorture: exit early in test_EnumPorts when no port info has been returned. Guenther --- source4/torture/rpc/spoolss.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4') diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c index 7e8461ef831..64b698a4020 100644 --- a/source4/torture/rpc/spoolss.c +++ b/source4/torture/rpc/spoolss.c @@ -139,6 +139,8 @@ static bool test_EnumPorts(struct torture_context *tctx, torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed"); + torture_assert(tctx, info, "EnumPorts returned no info"); + ctx->port_count[level] = count; ctx->ports[level] = info; } -- cgit From 007f3f231914eaa3fe9ce83c95e0db49d67151d2 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 2 Mar 2009 18:02:04 +0100 Subject: s4-spoolss: fix spoolss server enum calls after pointer changes. Guenther --- source4/ntptr/simple_ldb/ntptr_simple_ldb.c | 8 ++++---- source4/rpc_server/spoolss/dcesrv_spoolss.c | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'source4') diff --git a/source4/ntptr/simple_ldb/ntptr_simple_ldb.c b/source4/ntptr/simple_ldb/ntptr_simple_ldb.c index 459babce0ee..aea5d08c3f3 100644 --- a/source4/ntptr/simple_ldb/ntptr_simple_ldb.c +++ b/source4/ntptr/simple_ldb/ntptr_simple_ldb.c @@ -259,7 +259,7 @@ static WERROR sptr_EnumPrintServerForms(struct ntptr_GenericHandle *server, TALL return WERR_UNKNOWN_LEVEL; } - r->out.info = info; + *r->out.info = info; *r->out.count = count; return WERR_OK; } @@ -587,7 +587,7 @@ static WERROR sptr_EnumPrinters(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx return WERR_UNKNOWN_LEVEL; } - r->out.info = info; + *r->out.info = info; *r->out.count = count; return WERR_OK; } @@ -645,7 +645,7 @@ static WERROR sptr_EnumPorts(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx, return WERR_UNKNOWN_LEVEL; } - r->out.info = info; + *r->out.info = info; *r->out.count = count; return WERR_OK; } @@ -692,7 +692,7 @@ static WERROR sptr_EnumMonitors(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx return WERR_UNKNOWN_LEVEL; } - r->out.info = info; + *r->out.info = info; *r->out.count = count; return WERR_OK; } diff --git a/source4/rpc_server/spoolss/dcesrv_spoolss.c b/source4/rpc_server/spoolss/dcesrv_spoolss.c index f1ef2f0acb9..aec7422571b 100644 --- a/source4/rpc_server/spoolss/dcesrv_spoolss.c +++ b/source4/rpc_server/spoolss/dcesrv_spoolss.c @@ -243,8 +243,8 @@ static WERROR dcesrv_spoolss_EnumPrinters(struct dcesrv_call_state *dce_call, TA status = ntptr_EnumPrinters(ntptr, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); - *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinters, ic, r->out.info, r->in.level, *r->out.count); - r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); + *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinters, ic, *r->out.info, r->in.level, *r->out.count); + *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL); *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } @@ -379,8 +379,8 @@ static WERROR dcesrv_spoolss_EnumPrinterDrivers(struct dcesrv_call_state *dce_ca status = ntptr_EnumPrinterDrivers(ntptr, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); - *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinterDrivers, ic, r->out.info, r->in.level, *r->out.count); - r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); + *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPrinterDrivers, ic, *r->out.info, r->in.level, *r->out.count); + *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL); *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } @@ -802,8 +802,8 @@ static WERROR dcesrv_spoolss_EnumForms(struct dcesrv_call_state *dce_call, TALLO return WERR_FOOBAR; } - *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumForms, ic, r->out.info, r->in.level, *r->out.count); - r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); + *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumForms, ic, *r->out.info, r->in.level, *r->out.count); + *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL); *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } @@ -825,8 +825,8 @@ static WERROR dcesrv_spoolss_EnumPorts(struct dcesrv_call_state *dce_call, TALLO status = ntptr_EnumPorts(ntptr, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); - *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPorts, ic, r->out.info, r->in.level, *r->out.count); - r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); + *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumPorts, ic, *r->out.info, r->in.level, *r->out.count); + *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL); *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } @@ -848,8 +848,8 @@ static WERROR dcesrv_spoolss_EnumMonitors(struct dcesrv_call_state *dce_call, TA status = ntptr_EnumMonitors(ntptr, mem_ctx, r); W_ERROR_NOT_OK_RETURN(status); - *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumMonitors, ic, r->out.info, r->in.level, *r->out.count); - r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL); + *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(spoolss_EnumMonitors, ic, *r->out.info, r->in.level, *r->out.count); + *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL); *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER); } -- cgit From a93fbf8b2648f34a4a08de48c2b68eeb2ee7088d Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 6 Mar 2009 21:50:15 +0100 Subject: s4-smbtorture: add test_EnumPrintProcDataTypes to RPC-SPOOLSS test. Guenther --- source4/selftest/knownfail | 1 + source4/torture/rpc/spoolss.c | 52 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) (limited to 'source4') diff --git a/source4/selftest/knownfail b/source4/selftest/knownfail index f5aaaa00619..361f1d504e0 100644 --- a/source4/selftest/knownfail +++ b/source4/selftest/knownfail @@ -36,6 +36,7 @@ rpc.netlogon.*.GetPassword rpc.netlogon.*.GetTrustPasswords rpc.netlogon.*.DatabaseRedo rpc.netlogon.*.ServerGetTrustInfo +rpc.spoolss.*.EnumPrintProcDataTypes # not implemented yet base.charset.*.Testing partial surrogate .*net.api.delshare.* # DelShare isn't implemented yet rap.*netservergetinfo diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c index 64b698a4020..ad8158d9562 100644 --- a/source4/torture/rpc/spoolss.c +++ b/source4/torture/rpc/spoolss.c @@ -568,6 +568,57 @@ static bool test_EnumPrintProcessors(struct torture_context *tctx, return true; } +static bool test_EnumPrintProcDataTypes(struct torture_context *tctx, + struct dcerpc_pipe *p, + struct test_spoolss_context *ctx) +{ + NTSTATUS status; + struct spoolss_EnumPrintProcDataTypes r; + uint16_t levels[] = { 1 }; + int i, j; + + for (i=0;i Date: Wed, 4 Mar 2009 16:52:12 +0100 Subject: don't rely on shebang's perl path, call our $PERL instead Signed-off-by: Stefan Metzmacher --- source4/selftest/tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/selftest/tests.sh b/source4/selftest/tests.sh index 39e6cff2744..821db064146 100755 --- a/source4/selftest/tests.sh +++ b/source4/selftest/tests.sh @@ -291,7 +291,7 @@ if test x"${PIDL_TESTS_SKIP}" = x"yes"; then echo "Skipping pidl tests - PIDL_TESTS_SKIP=yes" elif $PERL -e 'eval require Test::More;' > /dev/null 2>&1; then for f in $samba4srcdir/../pidl/tests/*.pl; do - plantest "pidl.`basename $f .pl`" none $PERL $f "|" $samba4srcdir/../lib/subunit/harness2subunit.pl + plantest "pidl.`basename $f .pl`" none $PERL $f "|" $PERL $samba4srcdir/../lib/subunit/harness2subunit.pl done else echo "Skipping pidl tests - Test::More not installed" -- cgit From ca9d67bf187409e92d1800b86aa7f45e9d2f7260 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 7 Mar 2009 09:30:11 +0100 Subject: s4-spoolss: just return OK for dcesrv_spoolss_EnumPrintProcDataTypes for now. Guenther --- source4/rpc_server/spoolss/dcesrv_spoolss.c | 2 +- source4/selftest/knownfail | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/rpc_server/spoolss/dcesrv_spoolss.c b/source4/rpc_server/spoolss/dcesrv_spoolss.c index aec7422571b..61c8009716b 100644 --- a/source4/rpc_server/spoolss/dcesrv_spoolss.c +++ b/source4/rpc_server/spoolss/dcesrv_spoolss.c @@ -1001,7 +1001,7 @@ static WERROR dcesrv_spoolss_DeletePrintProvidor(struct dcesrv_call_state *dce_c static WERROR dcesrv_spoolss_EnumPrintProcDataTypes(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_EnumPrintProcDataTypes *r) { - DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR); + return WERR_OK; } diff --git a/source4/selftest/knownfail b/source4/selftest/knownfail index 361f1d504e0..f5aaaa00619 100644 --- a/source4/selftest/knownfail +++ b/source4/selftest/knownfail @@ -36,7 +36,6 @@ rpc.netlogon.*.GetPassword rpc.netlogon.*.GetTrustPasswords rpc.netlogon.*.DatabaseRedo rpc.netlogon.*.ServerGetTrustInfo -rpc.spoolss.*.EnumPrintProcDataTypes # not implemented yet base.charset.*.Testing partial surrogate .*net.api.delshare.* # DelShare isn't implemented yet rap.*netservergetinfo -- cgit From f088353d37b433af7b979a17871233cccddf7aca Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 9 Mar 2009 18:04:38 -0400 Subject: Fix potential segfaults using freed memory. In some code paths ltdb_context was still referenced even after we were returned an error by one of the callbacks. Because the interface assumes that once an error is returned the ldb_request may be freed, and because the ltdb_context was allocated as a child of the request, this might cause access to freed memory. Allocate the ltdb_context on ldb, and keep track of what's going on with the request by adding a spy children on it. This way even if the request is freed before the ltdb_callback is called, we will safely free the ctx and just quietly return. --- source4/lib/ldb/ldb_tdb/ldb_index.c | 2 +- source4/lib/ldb/ldb_tdb/ldb_search.c | 6 ++--- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 49 ++++++++++++++++++++++++++++++++---- source4/lib/ldb/ldb_tdb/ldb_tdb.h | 7 +++++- 4 files changed, 54 insertions(+), 10 deletions(-) (limited to 'source4') diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index ad27c9a9a9a..c99c2936d85 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -1055,7 +1055,7 @@ static int ltdb_index_filter(const struct dn_list *dn_list, ret = ldb_module_send_entry(ac->req, msg, NULL); if (ret != LDB_SUCCESS) { - ac->callback_failed = true; + ac->request_terminated = true; return ret; } } diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index 0f595267fcb..d395c28f287 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -424,10 +424,10 @@ static int search_func(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, voi ret = ldb_module_send_entry(ac->req, msg, NULL); if (ret != LDB_SUCCESS) { - ac->callback_failed = true; + ac->request_terminated = true; /* the callback failed, abort the operation */ return -1; - } + } return 0; } @@ -544,7 +544,7 @@ int ltdb_search(struct ltdb_context *ctx) /* Check if we got just a normal error. * In that case proceed to a full search unless we got a * callback error */ - if ( ! ctx->callback_failed && ret != LDB_SUCCESS) { + if ( ! ctx->request_terminated && ret != LDB_SUCCESS) { /* Not indexed, so we need to do a full scan */ ret = ltdb_search_full(ctx); if (ret != LDB_SUCCESS) { diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 24ec06ea320..d38cb828bbe 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -1019,7 +1019,15 @@ static void ltdb_timeout(struct tevent_context *ev, struct ltdb_context *ctx; ctx = talloc_get_type(private_data, struct ltdb_context); - ltdb_request_done(ctx, LDB_ERR_TIME_LIMIT_EXCEEDED); + if (!ctx->request_terminated) { + /* neutralize the spy */ + ctx->spy->ctx = NULL; + + /* request is done now */ + ltdb_request_done(ctx, LDB_ERR_TIME_LIMIT_EXCEEDED); + } + + talloc_free(ctx); } static void ltdb_request_extended_done(struct ltdb_context *ctx, @@ -1078,6 +1086,11 @@ static void ltdb_callback(struct tevent_context *ev, ctx = talloc_get_type(private_data, struct ltdb_context); + if (!ctx->request_terminated) { + /* neutralize the spy */ + ctx->spy->ctx = NULL; + } else goto done; + switch (ctx->req->operation) { case LDB_SEARCH: ret = ltdb_search(ctx); @@ -1102,11 +1115,24 @@ static void ltdb_callback(struct tevent_context *ev, ret = LDB_ERR_UNWILLING_TO_PERFORM; } - if (!ctx->callback_failed) { - /* Once we are done, we do not need timeout events */ - talloc_free(ctx->timeout_event); + if (!ctx->request_terminated) { + /* request is done now */ ltdb_request_done(ctx, ret); } + +done: + talloc_free(ctx); +} + +static int ltdb_request_destructor(void *ptr) +{ + struct ltdb_req_spy *spy = talloc_get_type(ptr, struct ltdb_req_spy); + + if (spy->ctx != NULL) { + spy->ctx->request_terminated = true; + } + + return 0; } static int ltdb_handle_request(struct ldb_module *module, @@ -1131,7 +1157,7 @@ static int ltdb_handle_request(struct ldb_module *module, ev = ldb_get_event_context(ldb); - ac = talloc_zero(req, struct ltdb_context); + ac = talloc_zero(ldb, struct ltdb_context); if (ac == NULL) { ldb_set_errstring(ldb, "Out of Memory"); return LDB_ERR_OPERATIONS_ERROR; @@ -1144,15 +1170,28 @@ static int ltdb_handle_request(struct ldb_module *module, tv.tv_usec = 0; te = tevent_add_timer(ev, ac, tv, ltdb_callback, ac); if (NULL == te) { + talloc_free(ac); return LDB_ERR_OPERATIONS_ERROR; } tv.tv_sec = req->starttime + req->timeout; ac->timeout_event = tevent_add_timer(ev, ac, tv, ltdb_timeout, ac); if (NULL == ac->timeout_event) { + talloc_free(ac); return LDB_ERR_OPERATIONS_ERROR; } + /* set a spy so that we do not try to use the request context + * if it is freed before ltdb_callback fires */ + ac->spy = talloc(req, struct ltdb_req_spy); + if (NULL == ac->spy) { + talloc_free(ac); + return LDB_ERR_OPERATIONS_ERROR; + } + ac->spy->ctx = ac; + + talloc_set_destructor((TALLOC_CTX *)ac->spy, ltdb_request_destructor); + return LDB_SUCCESS; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 0a06cdb1b08..5a1c8fee2d7 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -36,11 +36,16 @@ struct ltdb_private { the async local context holds also internal search state during a full db search */ +struct ltdb_req_spy { + struct ltdb_context *ctx; +}; + struct ltdb_context { struct ldb_module *module; struct ldb_request *req; - bool callback_failed; + bool request_terminated; + struct ltdb_req_spy *spy; /* search stuff */ const struct ldb_parse_tree *tree; -- cgit From a67bc41d6bc25974e6aa6d864d5265d07c890413 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Mar 2009 15:12:48 +1100 Subject: added a test that triggers a bug in the Samba3 notify code The Samba3 internal notify code doesn't work correctly when there is more than one tree connect to the same smbd process. This change to the RAW-NOTIFY test triggers the bug. --- source4/torture/raw/notify.c | 169 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) (limited to 'source4') diff --git a/source4/torture/raw/notify.c b/source4/torture/raw/notify.c index 3ffc58dbe67..c92170cf619 100644 --- a/source4/torture/raw/notify.c +++ b/source4/torture/raw/notify.c @@ -1429,6 +1429,174 @@ done: return ret; } + +/* + create a secondary tree connect - used to test for a bug in Samba3 messaging + with change notify +*/ +static struct smbcli_tree *secondary_tcon(struct smbcli_state *cli, + struct torture_context *tctx) +{ + NTSTATUS status; + const char *share, *host; + struct smbcli_tree *tree; + union smb_tcon tcon; + + share = torture_setting_string(tctx, "share", NULL); + host = torture_setting_string(tctx, "host", NULL); + + printf("create a second tree context on the same session\n"); + tree = smbcli_tree_init(cli->session, tctx, false); + + tcon.generic.level = RAW_TCON_TCONX; + tcon.tconx.in.flags = 0; + tcon.tconx.in.password = data_blob(NULL, 0); + tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share); + tcon.tconx.in.device = "A:"; + status = smb_raw_tcon(tree, tctx, &tcon); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tree); + printf("Failed to create secondary tree\n"); + return NULL; + } + + tree->tid = tcon.tconx.out.tid; + printf("tid1=%d tid2=%d\n", cli->tree->tid, tree->tid); + + return tree; +} + + +/* + very simple change notify test +*/ +static bool test_notify_tcon(struct smbcli_state *cli, struct torture_context *torture) +{ + bool ret = true; + NTSTATUS status; + union smb_notify notify; + union smb_open io; + int fnum, fnum2; + struct smbcli_request *req; + extern int torture_numops; + struct smbcli_tree *tree = NULL; + + printf("TESTING SIMPLE CHANGE NOTIFY\n"); + + /* + get a handle on the directory + */ + io.generic.level = RAW_OPEN_NTCREATEX; + io.ntcreatex.in.root_fid = 0; + io.ntcreatex.in.flags = 0; + io.ntcreatex.in.access_mask = SEC_FILE_ALL; + io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY; + io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; + io.ntcreatex.in.alloc_size = 0; + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; + io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; + io.ntcreatex.in.security_flags = 0; + io.ntcreatex.in.fname = BASEDIR; + + status = smb_raw_open(cli->tree, torture, &io); + CHECK_STATUS(status, NT_STATUS_OK); + fnum = io.ntcreatex.out.file.fnum; + + status = smb_raw_open(cli->tree, torture, &io); + CHECK_STATUS(status, NT_STATUS_OK); + fnum2 = io.ntcreatex.out.file.fnum; + + /* ask for a change notify, + on file or directory name changes */ + notify.nttrans.level = RAW_NOTIFY_NTTRANS; + notify.nttrans.in.buffer_size = 1000; + notify.nttrans.in.completion_filter = FILE_NOTIFY_CHANGE_NAME; + notify.nttrans.in.file.fnum = fnum; + notify.nttrans.in.recursive = true; + + printf("testing notify mkdir\n"); + req = smb_raw_changenotify_send(cli->tree, ¬ify); + smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name"); + + status = smb_raw_changenotify_recv(req, torture, ¬ify); + CHECK_STATUS(status, NT_STATUS_OK); + + CHECK_VAL(notify.nttrans.out.num_changes, 1); + CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED); + CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE); + + printf("testing notify rmdir\n"); + req = smb_raw_changenotify_send(cli->tree, ¬ify); + smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name"); + + status = smb_raw_changenotify_recv(req, torture, ¬ify); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(notify.nttrans.out.num_changes, 1); + CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED); + CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE); + + printf("SIMPLE CHANGE NOTIFY OK\n"); + + printf("TESTING WITH SECONDARY TCON\n"); + tree = secondary_tcon(cli, torture); + + printf("testing notify mkdir\n"); + req = smb_raw_changenotify_send(cli->tree, ¬ify); + smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name"); + + status = smb_raw_changenotify_recv(req, torture, ¬ify); + CHECK_STATUS(status, NT_STATUS_OK); + + CHECK_VAL(notify.nttrans.out.num_changes, 1); + CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED); + CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE); + + printf("testing notify rmdir\n"); + req = smb_raw_changenotify_send(cli->tree, ¬ify); + smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name"); + + status = smb_raw_changenotify_recv(req, torture, ¬ify); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(notify.nttrans.out.num_changes, 1); + CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED); + CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE); + + printf("CHANGE NOTIFY WITH TCON OK\n"); + + printf("Disconnecting secondary tree\n"); + status = smb_tree_disconnect(tree); + CHECK_STATUS(status, NT_STATUS_OK); + talloc_free(tree); + + printf("testing notify mkdir\n"); + req = smb_raw_changenotify_send(cli->tree, ¬ify); + smbcli_mkdir(cli->tree, BASEDIR "\\subdir-name"); + + status = smb_raw_changenotify_recv(req, torture, ¬ify); + CHECK_STATUS(status, NT_STATUS_OK); + + CHECK_VAL(notify.nttrans.out.num_changes, 1); + CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_ADDED); + CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE); + + printf("testing notify rmdir\n"); + req = smb_raw_changenotify_send(cli->tree, ¬ify); + smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name"); + + status = smb_raw_changenotify_recv(req, torture, ¬ify); + CHECK_STATUS(status, NT_STATUS_OK); + CHECK_VAL(notify.nttrans.out.num_changes, 1); + CHECK_VAL(notify.nttrans.out.changes[0].action, NOTIFY_ACTION_REMOVED); + CHECK_WSTR(notify.nttrans.out.changes[0].name, "subdir-name", STR_UNICODE); + + printf("CHANGE NOTIFY WITH TDIS OK\n"); +done: + smb_raw_exit(cli->session); + return ret; +} + + /* basic testing of change notify */ @@ -1442,6 +1610,7 @@ bool torture_raw_notify(struct torture_context *torture, return false; } + ret &= test_notify_tcon(cli, torture); ret &= test_notify_dir(cli, cli2, torture); ret &= test_notify_mask(cli, torture); ret &= test_notify_recursive(cli, torture); -- cgit From 97cccb22194380ce84bf6188df90e2438f1176db Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 10 Mar 2009 10:05:52 -0400 Subject: Fix extended operation return path. Extended operations return was not going thorugh the same patch as others leaving the ctx around. Plus we were neutralizing the spy too early so that it didn't set the request_terminated flag as it should have. This should hopefully fix the failures in the build farm. --- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'source4') diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index d38cb828bbe..9df62be9363 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -1020,13 +1020,14 @@ static void ltdb_timeout(struct tevent_context *ev, ctx = talloc_get_type(private_data, struct ltdb_context); if (!ctx->request_terminated) { - /* neutralize the spy */ - ctx->spy->ctx = NULL; - /* request is done now */ ltdb_request_done(ctx, LDB_ERR_TIME_LIMIT_EXCEEDED); } + if (!ctx->request_terminated) { + /* neutralize the spy */ + ctx->spy->ctx = NULL; + } talloc_free(ctx); } @@ -1086,10 +1087,9 @@ static void ltdb_callback(struct tevent_context *ev, ctx = talloc_get_type(private_data, struct ltdb_context); - if (!ctx->request_terminated) { - /* neutralize the spy */ - ctx->spy->ctx = NULL; - } else goto done; + if (ctx->request_terminated) { + goto done; + } switch (ctx->req->operation) { case LDB_SEARCH: @@ -1109,7 +1109,7 @@ static void ltdb_callback(struct tevent_context *ev, break; case LDB_EXTENDED: ltdb_handle_extended(ctx); - return; + goto done; default: /* no other op supported */ ret = LDB_ERR_UNWILLING_TO_PERFORM; @@ -1121,6 +1121,10 @@ static void ltdb_callback(struct tevent_context *ev, } done: + if (!ctx->request_terminated) { + /* neutralize the spy */ + ctx->spy->ctx = NULL; + } talloc_free(ctx); } -- cgit From 41c5d70c8d7b2af4fab50215f9bfea8e910cf99f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 23 Feb 2009 16:10:42 +0100 Subject: LDAP-BENCH-CLDAP: also test CLDAP rootdse searches. metze --- source4/torture/ldap/cldapbench.c | 85 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 6 deletions(-) (limited to 'source4') diff --git a/source4/torture/ldap/cldapbench.c b/source4/torture/ldap/cldapbench.c index 1fcfe5a0508..ae2cb808360 100644 --- a/source4/torture/ldap/cldapbench.c +++ b/source4/torture/ldap/cldapbench.c @@ -30,7 +30,7 @@ struct bench_state { int pass_count, fail_count; }; -static void request_handler(struct cldap_request *req) +static void request_netlogon_handler(struct cldap_request *req) { struct cldap_netlogon io; struct bench_state *state = talloc_get_type(req->async.private_data, struct bench_state); @@ -47,9 +47,9 @@ static void request_handler(struct cldap_request *req) } /* - benchmark cldap calls + benchmark cldap netlogon calls */ -static bool bench_cldap(struct torture_context *tctx, const char *address) +static bool bench_cldap_netlogon(struct torture_context *tctx, const char *address) { struct cldap_socket *cldap; int num_sent=0; @@ -69,14 +69,14 @@ static bool bench_cldap(struct torture_context *tctx, const char *address) search.in.acct_control = -1; search.in.version = 6; - printf("Running for %d seconds\n", timelimit); + printf("Running CLDAP/netlogon for %d seconds\n", timelimit); while (timeval_elapsed(&tv) < timelimit) { while (num_sent - (state->pass_count+state->fail_count) < 10) { struct cldap_request *req; req = cldap_netlogon_send(cldap, &search); req->async.private_data = state; - req->async.fn = request_handler; + req->async.fn = request_netlogon_handler; num_sent++; if (num_sent % 50 == 0) { if (torture_setting_bool(tctx, "progress", true)) { @@ -103,6 +103,78 @@ static bool bench_cldap(struct torture_context *tctx, const char *address) return ret; } +static void request_rootdse_handler(struct cldap_request *req) +{ + struct cldap_search io; + struct bench_state *state = talloc_get_type(req->async.private_data, struct bench_state); + NTSTATUS status; + TALLOC_CTX *tmp_ctx = talloc_new(NULL); + status = cldap_search_recv(req, tmp_ctx, &io); + if (NT_STATUS_IS_OK(status)) { + state->pass_count++; + } else { + state->fail_count++; + } + talloc_free(tmp_ctx); +} + +/* + benchmark cldap netlogon calls +*/ +static bool bench_cldap_rootdse(struct torture_context *tctx, const char *address) +{ + struct cldap_socket *cldap; + int num_sent=0; + struct timeval tv = timeval_current(); + bool ret = true; + int timelimit = torture_setting_int(tctx, "timelimit", 10); + struct cldap_search search; + struct bench_state *state; + + cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); + + state = talloc_zero(tctx, struct bench_state); + + ZERO_STRUCT(search); + search.in.dest_address = address; + search.in.dest_port = lp_cldap_port(tctx->lp_ctx); + search.in.filter = "(objectClass=*)"; + search.in.timeout = 2; + search.in.retries = 1; + + printf("Running CLDAP/rootdse for %d seconds\n", timelimit); + while (timeval_elapsed(&tv) < timelimit) { + while (num_sent - (state->pass_count+state->fail_count) < 10) { + struct cldap_request *req; + req = cldap_search_send(cldap, &search); + + req->async.private_data = state; + req->async.fn = request_rootdse_handler; + num_sent++; + if (num_sent % 50 == 0) { + if (torture_setting_bool(tctx, "progress", true)) { + printf("%.1f queries per second (%d failures) \r", + state->pass_count / timeval_elapsed(&tv), + state->fail_count); + fflush(stdout); + } + } + } + + tevent_loop_once(tctx->ev); + } + + while (num_sent != (state->pass_count + state->fail_count)) { + tevent_loop_once(tctx->ev); + } + + printf("%.1f queries per second (%d failures) \n", + state->pass_count / timeval_elapsed(&tv), + state->fail_count); + + talloc_free(cldap); + return ret; +} /* benchmark how fast a CLDAP server can respond to a series of parallel @@ -125,7 +197,8 @@ bool torture_bench_cldap(struct torture_context *torture) return false; } - ret &= bench_cldap(torture, address); + ret &= bench_cldap_netlogon(torture, address); + ret &= bench_cldap_rootdse(torture, address); return ret; } -- cgit From 917905aea0cfeff53009839f70cdc9eefdcfa2c9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 Mar 2009 13:13:14 +1100 Subject: removed leading spaces from embedded ldif This fixes the problem with the setpassword command failing like this: Error: First line of ldif must be a dn not ' dn' --- source4/scripting/python/samba/samdb.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'source4') diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py index 614970d3ec5..740806f2667 100644 --- a/source4/scripting/python/samba/samdb.py +++ b/source4/scripting/python/samba/samdb.py @@ -175,10 +175,10 @@ userAccountControl: %u user_dn = res[0].dn setpw = """ - dn: %s - changetype: modify - replace: userPassword - userPassword: %s +dn: %s +changetype: modify +replace: userPassword +userPassword: %s """ % (user_dn, password) self.modify_ldif(setpw) @@ -229,12 +229,12 @@ userAccountControl: %u accountExpires = glue.unix2nttime(expiry_seconds + int(time.time())) mod = """ - dn: %s - changetype: modify - replace: userAccountControl - userAccountControl: %u - replace: accountExpires - accountExpires: %u +dn: %s +changetype: modify +replace: userAccountControl +userAccountControl: %u +replace: accountExpires +accountExpires: %u """ % (res[0].dn, userAccountControl, accountExpires) # now change the database self.modify_ldif(mod) -- cgit From 0770028cbea5f13c0dda2b9a89803359bed66306 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 Mar 2009 15:13:23 +1100 Subject: fixed more embedded spaces in LDIF This one added 3 spaces to the end of any new passwords --- source4/scripting/python/samba/samdb.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4') diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py index 740806f2667..1c5a8dfcde7 100644 --- a/source4/scripting/python/samba/samdb.py +++ b/source4/scripting/python/samba/samdb.py @@ -59,7 +59,7 @@ dn: CN=%s,CN=ForeignSecurityPrincipals,%s objectClass: top objectClass: foreignSecurityPrincipal description: %s - """ % (sid, domaindn, desc) +""" % (sid, domaindn, desc) # deliberately ignore errors from this, as the records may # already exist for msg in self.parse_ldif(add): @@ -179,7 +179,7 @@ dn: %s changetype: modify replace: userPassword userPassword: %s - """ % (user_dn, password) +""" % (user_dn, password) self.modify_ldif(setpw) @@ -235,7 +235,7 @@ replace: userAccountControl userAccountControl: %u replace: accountExpires accountExpires: %u - """ % (res[0].dn, userAccountControl, accountExpires) +""" % (res[0].dn, userAccountControl, accountExpires) # now change the database self.modify_ldif(mod) except: -- cgit From 483525f73c5597c0c35de4288d97f53b9d3d262e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 12 Mar 2009 15:20:25 +1100 Subject: use a base64 encoded password when changing passwords This avoids problems with embedded control characters in password changes --- source4/scripting/python/samba/samdb.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py index 1c5a8dfcde7..b92a91e2ef5 100644 --- a/source4/scripting/python/samba/samdb.py +++ b/source4/scripting/python/samba/samdb.py @@ -28,6 +28,7 @@ import ldb from samba.idmap import IDmapDB import pwd import time +import base64 __docformat__ = "restructuredText" @@ -178,8 +179,8 @@ userAccountControl: %u dn: %s changetype: modify replace: userPassword -userPassword: %s -""" % (user_dn, password) +userPassword:: %s +""" % (user_dn, base64.b64encode(password)) self.modify_ldif(setpw) -- cgit From 1e4f78cc41d7d44703bea238fee86da618d1587b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 12 Mar 2009 10:04:02 +0100 Subject: s4:ldb: setup tevent debug functions on a selfcreated event context metze --- source4/lib/ldb/common/ldb.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'source4') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index f1b28b6819b..e17e10dcaaf 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -47,6 +47,40 @@ static int ldb_context_destructor(void *ptr) return 0; } +/* + this is used to catch debug messages from events +*/ +static void ldb_tevent_debug(void *context, enum tevent_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); + +static void ldb_tevent_debug(void *context, enum tevent_debug_level level, + const char *fmt, va_list ap) +{ + struct ldb_context = talloc_get_type_abort(context, struct ldb_context); + enum ldb_debug_level ldb_level = LDB_DEBUG_FATAL; + char *s = NULL; + + switch (level) { + case TEVENT_DEBUG_FATAL: + ldb_level = LDB_DEBUG_FATAL; + break; + case TEVENT_DEBUG_ERROR: + ldb_level = LDB_DEBUG_ERROR; + break; + case TEVENT_DEBUG_WARNING: + ldb_level = LDB_DEBUG_WARNING; + break; + case TEVENT_DEBUG_TRACE: + ldb_level = LDB_DEBUG_TRACE; + break; + }; + + vasprintf(&s, fmt, ap); + if (!s) return; + ldb_debug(ldb, ldb_level, "tevent: %s", s); + free(s); +} + /* initialise a ldb context The mem_ctx is required @@ -62,6 +96,7 @@ struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx) * until we have them all converted */ if (ev_ctx == NULL) { ev_ctx = tevent_context_init(talloc_autofree_context()); + tevent_set_debug(ev_ctx, ldb_tevent_debug, ldb); } ret = ldb_setup_wellknown_attributes(ldb); -- cgit From 6802394212f7fefc21d1e2ad257fbeee26238b2d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 12 Mar 2009 10:05:05 +0100 Subject: s4:ldb: allow nested events until the code is fixed to avoid them metze --- source4/lib/ldb/common/ldb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index e17e10dcaaf..86ce2069a51 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -32,6 +32,7 @@ * Author: Andrew Tridgell */ +#define TEVENT_DEPRECATED 1 #include "ldb_private.h" static int ldb_context_destructor(void *ptr) @@ -56,7 +57,7 @@ static void ldb_tevent_debug(void *context, enum tevent_debug_level level, static void ldb_tevent_debug(void *context, enum tevent_debug_level level, const char *fmt, va_list ap) { - struct ldb_context = talloc_get_type_abort(context, struct ldb_context); + struct ldb_context *ldb = talloc_get_type(context, struct ldb_context); enum ldb_debug_level ldb_level = LDB_DEBUG_FATAL; char *s = NULL; @@ -97,6 +98,7 @@ struct ldb_context *ldb_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx) if (ev_ctx == NULL) { ev_ctx = tevent_context_init(talloc_autofree_context()); tevent_set_debug(ev_ctx, ldb_tevent_debug, ldb); + tevent_loop_allow_nesting(ev_ctx); } ret = ldb_setup_wellknown_attributes(ldb); -- cgit From a3d5d8378c8edb6baa9ab42b02cee4711a58840b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 12 Mar 2009 10:05:47 +0100 Subject: s4:events: allow nested events until we fixed all code to avoid them metze --- source4/lib/events/tevent_s4.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4') diff --git a/source4/lib/events/tevent_s4.c b/source4/lib/events/tevent_s4.c index 89ca7bbe5ca..06bfbf61edd 100644 --- a/source4/lib/events/tevent_s4.c +++ b/source4/lib/events/tevent_s4.c @@ -17,6 +17,7 @@ */ #include "includes.h" +#define TEVENT_DEPRECATED 1 #include "lib/events/events.h" /* @@ -65,6 +66,7 @@ struct tevent_context *s4_event_context_init(TALLOC_CTX *mem_ctx) ev = tevent_context_init_byname(mem_ctx, NULL); if (ev) { tevent_set_debug(ev, ev_wrap_debug, NULL); + tevent_loop_allow_nesting(ev); } return ev; } -- cgit From 2f579200fb439693540ada6e098959aa2d5f414e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 12 Mar 2009 14:28:22 +0100 Subject: s4:build: try to fix the build with the ibm checker in the build-farm The problem is that the shell eats the quotes in -DFOO="foo, bar, NULL" metze --- source4/build/smb_build/main.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/build/smb_build/main.pl b/source4/build/smb_build/main.pl index 3c84a91a59e..0d19e418270 100644 --- a/source4/build/smb_build/main.pl +++ b/source4/build/smb_build/main.pl @@ -73,7 +73,7 @@ foreach my $key (values %$OUTPUT) { $shared_libs_used = 1; } if ($key->{TYPE} eq "MODULE" and @{$key->{OUTPUT_TYPE}}[0] eq "MERGED_OBJ" and defined($key->{INIT_FUNCTION})) { - $mkenv->output("$key->{SUBSYSTEM}_INIT_FUNCTIONS += $key->{INIT_FUNCTION},\n"); + $mkenv->output("$key->{SUBSYSTEM}_INIT_FUNCTIONS +=$key->{INIT_FUNCTION},\n"); } $mkenv->CFlags($key); } -- cgit From 1355dc2fd3a10c54fc3534409b78972d59d59b30 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 13 Mar 2009 15:50:23 +0100 Subject: s4:build: require tevent 0.9.4 metze --- source4/configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/configure.ac b/source4/configure.ac index d33df084068..87ed4d82513 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -59,7 +59,7 @@ SMB_INCLUDED_LIB_PKGCONFIG(LIBTDB, tdb >= 1.1.3, SMB_INCLUDE_MK(../lib/tdb/python.mk) -SMB_INCLUDED_LIB_PKGCONFIG(LIBTEVENT, tevent = 0.9.3, +SMB_INCLUDED_LIB_PKGCONFIG(LIBTEVENT, tevent = 0.9.4, [],[m4_include(../lib/tevent/samba.m4)] ) -- cgit From 4638633308e0508fa753173fa3e430c38e51732e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 14 Mar 2009 21:57:44 +0100 Subject: Move tdr to top-level. --- source4/Makefile | 2 +- source4/lib/tdr/TODO | 1 - source4/lib/tdr/config.mk | 9 - source4/lib/tdr/tdr.c | 397 ---------------------------------------- source4/lib/tdr/tdr.h | 67 ------- source4/lib/tdr/testsuite.c | 186 ------------------- source4/main.mk | 2 +- source4/torture/local/config.mk | 2 +- 8 files changed, 3 insertions(+), 663 deletions(-) delete mode 100644 source4/lib/tdr/TODO delete mode 100644 source4/lib/tdr/config.mk delete mode 100644 source4/lib/tdr/tdr.c delete mode 100644 source4/lib/tdr/tdr.h delete mode 100644 source4/lib/tdr/testsuite.c (limited to 'source4') diff --git a/source4/Makefile b/source4/Makefile index 15b1b8ba403..c42f0ba9fff 100644 --- a/source4/Makefile +++ b/source4/Makefile @@ -77,7 +77,7 @@ nsswrappersrcdir := ../lib/nss_wrapper appwebsrcdir := lib/appweb libstreamsrcdir := lib/stream libutilsrcdir := ../lib/util -libtdrsrcdir := lib/tdr +libtdrsrcdir := ../lib/tdr libcryptosrcdir := ../lib/crypto libtorturesrcdir := ../lib/torture smb_serversrcdir := smb_server diff --git a/source4/lib/tdr/TODO b/source4/lib/tdr/TODO deleted file mode 100644 index 5093afd4387..00000000000 --- a/source4/lib/tdr/TODO +++ /dev/null @@ -1 +0,0 @@ -- Support read/write (to fd) as well as push/pull (to DATA_BLOB) diff --git a/source4/lib/tdr/config.mk b/source4/lib/tdr/config.mk deleted file mode 100644 index 07506ec6472..00000000000 --- a/source4/lib/tdr/config.mk +++ /dev/null @@ -1,9 +0,0 @@ -[SUBSYSTEM::TDR] -CFLAGS = -Ilib/tdr -PUBLIC_DEPENDENCIES = LIBTALLOC LIBSAMBA-UTIL - -TDR_OBJ_FILES = $(libtdrsrcdir)/tdr.o - -$(eval $(call proto_header_template,$(libtdrsrcdir)/tdr_proto.h,$(TDR_OBJ_FILES:.o=.c))) - -PUBLIC_HEADERS += $(libtdrsrcdir)/tdr.h diff --git a/source4/lib/tdr/tdr.c b/source4/lib/tdr/tdr.c deleted file mode 100644 index 8b62ea0c2b9..00000000000 --- a/source4/lib/tdr/tdr.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - TDR (Trivial Data Representation) helper functions - Based loosely on ndr.c by Andrew Tridgell. - - Copyright (C) Jelmer Vernooij 2005 - - 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 . -*/ - -#include "includes.h" -#include "system/filesys.h" -#include "system/network.h" -#include "tdr/tdr.h" - -#define TDR_BASE_MARSHALL_SIZE 1024 - -#define TDR_PUSH_NEED_BYTES(tdr, n) TDR_CHECK(tdr_push_expand(tdr, tdr->data.length+(n))) - -#define TDR_PULL_NEED_BYTES(tdr, n) do { \ - if ((n) > tdr->data.length || tdr->offset + (n) > tdr->data.length) { \ - return NT_STATUS_BUFFER_TOO_SMALL; \ - } \ -} while(0) - -#define TDR_BE(tdr) ((tdr)->flags & TDR_BIG_ENDIAN) - -#define TDR_CVAL(tdr, ofs) CVAL(tdr->data.data,ofs) -#define TDR_SVAL(tdr, ofs) (TDR_BE(tdr)?RSVAL(tdr->data.data,ofs):SVAL(tdr->data.data,ofs)) -#define TDR_IVAL(tdr, ofs) (TDR_BE(tdr)?RIVAL(tdr->data.data,ofs):IVAL(tdr->data.data,ofs)) -#define TDR_SCVAL(tdr, ofs, v) SCVAL(tdr->data.data,ofs,v) -#define TDR_SSVAL(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSSVAL(tdr->data.data,ofs,v); } else SSVAL(tdr->data.data,ofs,v); } while (0) -#define TDR_SIVAL(tdr, ofs, v) do { if (TDR_BE(tdr)) { RSIVAL(tdr->data.data,ofs,v); } else SIVAL(tdr->data.data,ofs,v); } while (0) - -/** - expand the available space in the buffer to 'size' -*/ -NTSTATUS tdr_push_expand(struct tdr_push *tdr, uint32_t size) -{ - if (talloc_get_size(tdr->data.data) >= size) { - return NT_STATUS_OK; - } - - tdr->data.data = talloc_realloc(tdr, tdr->data.data, uint8_t, tdr->data.length + TDR_BASE_MARSHALL_SIZE); - - if (tdr->data.data == NULL) - return NT_STATUS_NO_MEMORY; - - return NT_STATUS_OK; -} - - -NTSTATUS tdr_pull_uint8(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint8_t *v) -{ - TDR_PULL_NEED_BYTES(tdr, 1); - *v = TDR_CVAL(tdr, tdr->offset); - tdr->offset += 1; - return NT_STATUS_OK; -} - -NTSTATUS tdr_push_uint8(struct tdr_push *tdr, const uint8_t *v) -{ - TDR_PUSH_NEED_BYTES(tdr, 1); - TDR_SCVAL(tdr, tdr->data.length, *v); - tdr->data.length += 1; - return NT_STATUS_OK; -} - -NTSTATUS tdr_print_uint8(struct tdr_print *tdr, const char *name, uint8_t *v) -{ - tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v); - return NT_STATUS_OK; -} - -NTSTATUS tdr_pull_uint16(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint16_t *v) -{ - TDR_PULL_NEED_BYTES(tdr, 2); - *v = TDR_SVAL(tdr, tdr->offset); - tdr->offset += 2; - return NT_STATUS_OK; -} - -NTSTATUS tdr_push_uint16(struct tdr_push *tdr, const uint16_t *v) -{ - TDR_PUSH_NEED_BYTES(tdr, 2); - TDR_SSVAL(tdr, tdr->data.length, *v); - tdr->data.length += 2; - return NT_STATUS_OK; -} - -NTSTATUS tdr_print_uint16(struct tdr_print *tdr, const char *name, uint16_t *v) -{ - tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v); - return NT_STATUS_OK; -} - -NTSTATUS tdr_pull_uint32(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint32_t *v) -{ - TDR_PULL_NEED_BYTES(tdr, 4); - *v = TDR_IVAL(tdr, tdr->offset); - tdr->offset += 4; - return NT_STATUS_OK; -} - -NTSTATUS tdr_push_uint32(struct tdr_push *tdr, const uint32_t *v) -{ - TDR_PUSH_NEED_BYTES(tdr, 4); - TDR_SIVAL(tdr, tdr->data.length, *v); - tdr->data.length += 4; - return NT_STATUS_OK; -} - -NTSTATUS tdr_print_uint32(struct tdr_print *tdr, const char *name, uint32_t *v) -{ - tdr->print(tdr, "%-25s: 0x%02x (%u)", name, *v, *v); - return NT_STATUS_OK; -} - -NTSTATUS tdr_pull_charset(struct tdr_pull *tdr, TALLOC_CTX *ctx, const char **v, uint32_t length, uint32_t el_size, charset_t chset) -{ - size_t ret; - - if (length == -1) { - switch (chset) { - case CH_DOS: - length = ascii_len_n((const char*)tdr->data.data+tdr->offset, tdr->data.length-tdr->offset); - break; - case CH_UTF16: - length = utf16_len_n(tdr->data.data+tdr->offset, tdr->data.length-tdr->offset); - break; - - default: - return NT_STATUS_INVALID_PARAMETER; - } - } - - if (length == 0) { - *v = talloc_strdup(ctx, ""); - return NT_STATUS_OK; - } - - TDR_PULL_NEED_BYTES(tdr, el_size*length); - - if (!convert_string_talloc_convenience(ctx, tdr->iconv_convenience, chset, CH_UNIX, tdr->data.data+tdr->offset, el_size*length, discard_const_p(void *, v), &ret, false)) { - return NT_STATUS_INVALID_PARAMETER; - } - - tdr->offset += length * el_size; - - return NT_STATUS_OK; -} - -NTSTATUS tdr_push_charset(struct tdr_push *tdr, const char **v, uint32_t length, uint32_t el_size, charset_t chset) -{ - size_t ret, required; - - if (length == -1) { - length = strlen(*v) + 1; /* Extra element for null character */ - } - - required = el_size * length; - TDR_PUSH_NEED_BYTES(tdr, required); - - if (!convert_string_convenience(tdr->iconv_convenience, CH_UNIX, chset, *v, strlen(*v), tdr->data.data+tdr->data.length, required, &ret, false)) { - return NT_STATUS_INVALID_PARAMETER; - } - - /* Make sure the remaining part of the string is filled with zeroes */ - if (ret < required) { - memset(tdr->data.data+tdr->data.length+ret, 0, required-ret); - } - - tdr->data.length += required; - - return NT_STATUS_OK; -} - -NTSTATUS tdr_print_charset(struct tdr_print *tdr, const char *name, const char **v, uint32_t length, uint32_t el_size, charset_t chset) -{ - tdr->print(tdr, "%-25s: %s", name, *v); - return NT_STATUS_OK; -} - -/** - parse a hyper -*/ -NTSTATUS tdr_pull_hyper(struct tdr_pull *tdr, TALLOC_CTX *ctx, uint64_t *v) -{ - TDR_PULL_NEED_BYTES(tdr, 8); - *v = TDR_IVAL(tdr, tdr->offset); - *v |= (uint64_t)(TDR_IVAL(tdr, tdr->offset+4)) << 32; - tdr->offset += 8; - return NT_STATUS_OK; -} - -/** - push a hyper -*/ -NTSTATUS tdr_push_hyper(struct tdr_push *tdr, uint64_t *v) -{ - TDR_PUSH_NEED_BYTES(tdr, 8); - TDR_SIVAL(tdr, tdr->data.length, ((*v) & 0xFFFFFFFF)); - TDR_SIVAL(tdr, tdr->data.length+4, ((*v)>>32)); - tdr->data.length += 8; - return NT_STATUS_OK; -} - -/** - push a NTTIME -*/ -NTSTATUS tdr_push_NTTIME(struct tdr_push *tdr, NTTIME *t) -{ - TDR_CHECK(tdr_push_hyper(tdr, t)); - return NT_STATUS_OK; -} - -/** - pull a NTTIME -*/ -NTSTATUS tdr_pull_NTTIME(struct tdr_pull *tdr, TALLOC_CTX *ctx, NTTIME *t) -{ - TDR_CHECK(tdr_pull_hyper(tdr, ctx, t)); - return NT_STATUS_OK; -} - -/** - push a time_t -*/ -NTSTATUS tdr_push_time_t(struct tdr_push *tdr, time_t *t) -{ - return tdr_push_uint32(tdr, (uint32_t *)t); -} - -/** - pull a time_t -*/ -NTSTATUS tdr_pull_time_t(struct tdr_pull *tdr, TALLOC_CTX *ctx, time_t *t) -{ - uint32_t tt; - TDR_CHECK(tdr_pull_uint32(tdr, ctx, &tt)); - *t = tt; - return NT_STATUS_OK; -} - -NTSTATUS tdr_print_time_t(struct tdr_print *tdr, const char *name, time_t *t) -{ - if (*t == (time_t)-1 || *t == 0) { - tdr->print(tdr, "%-25s: (time_t)%d", name, (int)*t); - } else { - tdr->print(tdr, "%-25s: %s", name, timestring(tdr, *t)); - } - - return NT_STATUS_OK; -} - -NTSTATUS tdr_print_NTTIME(struct tdr_print *tdr, const char *name, NTTIME *t) -{ - tdr->print(tdr, "%-25s: %s", name, nt_time_string(tdr, *t)); - - return NT_STATUS_OK; -} - -NTSTATUS tdr_print_DATA_BLOB(struct tdr_print *tdr, const char *name, DATA_BLOB *r) -{ - tdr->print(tdr, "%-25s: DATA_BLOB length=%u", name, r->length); - if (r->length) { - dump_data(10, r->data, r->length); - } - - return NT_STATUS_OK; -} - -#define TDR_ALIGN(l,n) (((l) & ((n)-1)) == 0?0:((n)-((l)&((n)-1)))) - -/* - push a DATA_BLOB onto the wire. -*/ -NTSTATUS tdr_push_DATA_BLOB(struct tdr_push *tdr, DATA_BLOB *blob) -{ - if (tdr->flags & TDR_ALIGN2) { - blob->length = TDR_ALIGN(tdr->data.length, 2); - } else if (tdr->flags & TDR_ALIGN4) { - blob->length = TDR_ALIGN(tdr->data.length, 4); - } else if (tdr->flags & TDR_ALIGN8) { - blob->length = TDR_ALIGN(tdr->data.length, 8); - } - - TDR_PUSH_NEED_BYTES(tdr, blob->length); - - memcpy(tdr->data.data+tdr->data.length, blob->data, blob->length); - return NT_STATUS_OK; -} - -/* - pull a DATA_BLOB from the wire. -*/ -NTSTATUS tdr_pull_DATA_BLOB(struct tdr_pull *tdr, TALLOC_CTX *ctx, DATA_BLOB *blob) -{ - uint32_t length; - - if (tdr->flags & TDR_ALIGN2) { - length = TDR_ALIGN(tdr->offset, 2); - } else if (tdr->flags & TDR_ALIGN4) { - length = TDR_ALIGN(tdr->offset, 4); - } else if (tdr->flags & TDR_ALIGN8) { - length = TDR_ALIGN(tdr->offset, 8); - } else if (tdr->flags & TDR_REMAINING) { - length = tdr->data.length - tdr->offset; - } else { - return NT_STATUS_INVALID_PARAMETER; - } - - if (tdr->data.length - tdr->offset < length) { - length = tdr->data.length - tdr->offset; - } - - TDR_PULL_NEED_BYTES(tdr, length); - - *blob = data_blob_talloc(tdr, tdr->data.data+tdr->offset, length); - tdr->offset += length; - return NT_STATUS_OK; -} - -struct tdr_push *tdr_push_init(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *ic) -{ - struct tdr_push *push = talloc_zero(mem_ctx, struct tdr_push); - - if (push == NULL) - return NULL; - - push->iconv_convenience = talloc_reference(push, ic); - - return push; -} - -struct tdr_pull *tdr_pull_init(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *ic) -{ - struct tdr_pull *pull = talloc_zero(mem_ctx, struct tdr_pull); - - if (pull == NULL) - return NULL; - - pull->iconv_convenience = talloc_reference(pull, ic); - - return pull; -} - -NTSTATUS tdr_push_to_fd(int fd, struct smb_iconv_convenience *iconv_convenience, tdr_push_fn_t push_fn, const void *p) -{ - struct tdr_push *push = tdr_push_init(NULL, iconv_convenience); - - if (push == NULL) - return NT_STATUS_NO_MEMORY; - - if (NT_STATUS_IS_ERR(push_fn(push, p))) { - DEBUG(1, ("Error pushing data\n")); - talloc_free(push); - return NT_STATUS_UNSUCCESSFUL; - } - - if (write(fd, push->data.data, push->data.length) < push->data.length) { - DEBUG(1, ("Error writing all data\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - talloc_free(push); - - return NT_STATUS_OK; -} - -void tdr_print_debug_helper(struct tdr_print *tdr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3) -{ - va_list ap; - char *s = NULL; - int i; - - va_start(ap, format); - vasprintf(&s, format, ap); - va_end(ap); - - for (i=0;ilevel;i++) { DEBUG(0,(" ")); } - - DEBUG(0,("%s\n", s)); - free(s); -} diff --git a/source4/lib/tdr/tdr.h b/source4/lib/tdr/tdr.h deleted file mode 100644 index c983cd35c14..00000000000 --- a/source4/lib/tdr/tdr.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - Unix SMB/CIFS implementation. - TDR definitions - Copyright (C) Jelmer Vernooij 2005 - - 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 . -*/ - -#ifndef __TDR_H__ -#define __TDR_H__ - -#include -#include "../lib/util/charset/charset.h" - -#define TDR_BIG_ENDIAN 0x01 -#define TDR_ALIGN2 0x02 -#define TDR_ALIGN4 0x04 -#define TDR_ALIGN8 0x08 -#define TDR_REMAINING 0x10 - -struct tdr_pull { - DATA_BLOB data; - uint32_t offset; - int flags; - struct smb_iconv_convenience *iconv_convenience; -}; - -struct tdr_push { - DATA_BLOB data; - int flags; - struct smb_iconv_convenience *iconv_convenience; -}; - -struct tdr_print { - int level; - void (*print)(struct tdr_print *, const char *, ...); - int flags; -}; - -#define TDR_CHECK(call) do { NTSTATUS _status; \ - _status = call; \ - if (!NT_STATUS_IS_OK(_status)) \ - return _status; \ - } while (0) - -#define TDR_ALLOC(ctx, s, n) do { \ - (s) = talloc_array_size(ctx, sizeof(*(s)), n); \ - if ((n) && !(s)) return NT_STATUS_NO_MEMORY; \ - } while (0) - -typedef NTSTATUS (*tdr_push_fn_t) (struct tdr_push *, const void *); -typedef NTSTATUS (*tdr_pull_fn_t) (struct tdr_pull *, TALLOC_CTX *, void *); - -#include "lib/tdr/tdr_proto.h" - -#endif /* __TDR_H__ */ diff --git a/source4/lib/tdr/testsuite.c b/source4/lib/tdr/testsuite.c deleted file mode 100644 index 44c5810f907..00000000000 --- a/source4/lib/tdr/testsuite.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - Unix SMB/CIFS implementation. - test suite for basic tdr functions - - Copyright (C) Jelmer Vernooij 2007 - - 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 . -*/ - -#include "includes.h" -#include "torture/torture.h" -#include "lib/tdr/tdr.h" -#include "param/param.h" - -static bool test_push_uint8(struct torture_context *tctx) -{ - uint8_t v = 4; - struct tdr_push *tdr = tdr_push_init(tctx, lp_iconv_convenience(tctx->lp_ctx)); - - torture_assert_ntstatus_ok(tctx, tdr_push_uint8(tdr, &v), "push failed"); - torture_assert_int_equal(tctx, tdr->data.length, 1, "length incorrect"); - torture_assert_int_equal(tctx, tdr->data.data[0], 4, "data incorrect"); - return true; -} - -static bool test_pull_uint8(struct torture_context *tctx) -{ - uint8_t d = 2; - uint8_t l; - struct tdr_pull *tdr = tdr_pull_init(tctx, lp_iconv_convenience(tctx->lp_ctx)); - tdr->data.data = &d; - tdr->data.length = 1; - tdr->offset = 0; - tdr->flags = 0; - torture_assert_ntstatus_ok(tctx, tdr_pull_uint8(tdr, tctx, &l), - "pull failed"); - torture_assert_int_equal(tctx, 1, tdr->offset, - "offset invalid"); - return true; -} - -static bool test_push_uint16(struct torture_context *tctx) -{ - uint16_t v = 0xF32; - struct tdr_push *tdr = tdr_push_init(tctx, lp_iconv_convenience(tctx->lp_ctx)); - - torture_assert_ntstatus_ok(tctx, tdr_push_uint16(tdr, &v), "push failed"); - torture_assert_int_equal(tctx, tdr->data.length, 2, "length incorrect"); - torture_assert_int_equal(tctx, tdr->data.data[0], 0x32, "data incorrect"); - torture_assert_int_equal(tctx, tdr->data.data[1], 0x0F, "data incorrect"); - return true; -} - -static bool test_pull_uint16(struct torture_context *tctx) -{ - uint8_t d[2] = { 782 & 0xFF, (782 & 0xFF00) / 0x100 }; - uint16_t l; - struct tdr_pull *tdr = tdr_pull_init(tctx, lp_iconv_convenience(tctx->lp_ctx)); - tdr->data.data = d; - tdr->data.length = 2; - tdr->offset = 0; - tdr->flags = 0; - torture_assert_ntstatus_ok(tctx, tdr_pull_uint16(tdr, tctx, &l), - "pull failed"); - torture_assert_int_equal(tctx, 2, tdr->offset, "offset invalid"); - torture_assert_int_equal(tctx, 782, l, "right int read"); - return true; -} - -static bool test_push_uint32(struct torture_context *tctx) -{ - uint32_t v = 0x100F32; - struct tdr_push *tdr = tdr_push_init(tctx, lp_iconv_convenience(tctx->lp_ctx)); - - torture_assert_ntstatus_ok(tctx, tdr_push_uint32(tdr, &v), "push failed"); - torture_assert_int_equal(tctx, tdr->data.length, 4, "length incorrect"); - torture_assert_int_equal(tctx, tdr->data.data[0], 0x32, "data incorrect"); - torture_assert_int_equal(tctx, tdr->data.data[1], 0x0F, "data incorrect"); - torture_assert_int_equal(tctx, tdr->data.data[2], 0x10, "data incorrect"); - torture_assert_int_equal(tctx, tdr->data.data[3], 0x00, "data incorrect"); - return true; -} - -static bool test_pull_uint32(struct torture_context *tctx) -{ - uint8_t d[4] = { 782 & 0xFF, (782 & 0xFF00) / 0x100, 0, 0 }; - uint32_t l; - struct tdr_pull *tdr = tdr_pull_init(tctx, lp_iconv_convenience(tctx->lp_ctx)); - tdr->data.data = d; - tdr->data.length = 4; - tdr->offset = 0; - tdr->flags = 0; - torture_assert_ntstatus_ok(tctx, tdr_pull_uint32(tdr, tctx, &l), - "pull failed"); - torture_assert_int_equal(tctx, 4, tdr->offset, "offset invalid"); - torture_assert_int_equal(tctx, 782, l, "right int read"); - return true; -} - -static bool test_pull_charset(struct torture_context *tctx) -{ - struct tdr_pull *tdr = tdr_pull_init(tctx, lp_iconv_convenience(tctx->lp_ctx)); - const char *l = NULL; - tdr->data.data = (uint8_t *)talloc_strdup(tctx, "bla"); - tdr->data.length = 4; - tdr->offset = 0; - tdr->flags = 0; - torture_assert_ntstatus_ok(tctx, tdr_pull_charset(tdr, tctx, &l, -1, 1, CH_DOS), - "pull failed"); - torture_assert_int_equal(tctx, 4, tdr->offset, "offset invalid"); - torture_assert_str_equal(tctx, "bla", l, "right int read"); - - tdr->offset = 0; - torture_assert_ntstatus_ok(tctx, tdr_pull_charset(tdr, tctx, &l, 2, 1, CH_UNIX), - "pull failed"); - torture_assert_int_equal(tctx, 2, tdr->offset, "offset invalid"); - torture_assert_str_equal(tctx, "bl", l, "right int read"); - - return true; -} - -static bool test_pull_charset_empty(struct torture_context *tctx) -{ - struct tdr_pull *tdr = tdr_pull_init(tctx, lp_iconv_convenience(tctx->lp_ctx)); - const char *l = NULL; - tdr->data.data = (uint8_t *)talloc_strdup(tctx, "bla"); - tdr->data.length = 4; - tdr->offset = 0; - tdr->flags = 0; - torture_assert_ntstatus_ok(tctx, tdr_pull_charset(tdr, tctx, &l, 0, 1, CH_DOS), - "pull failed"); - torture_assert_int_equal(tctx, 0, tdr->offset, "offset invalid"); - torture_assert_str_equal(tctx, "", l, "right string read"); - - return true; -} - - - -static bool test_push_charset(struct torture_context *tctx) -{ - const char *l = "bloe"; - struct tdr_push *tdr = tdr_push_init(tctx, lp_iconv_convenience(tctx->lp_ctx)); - torture_assert_ntstatus_ok(tctx, tdr_push_charset(tdr, &l, 4, 1, CH_UTF8), - "push failed"); - torture_assert_int_equal(tctx, 4, tdr->data.length, "offset invalid"); - torture_assert(tctx, strcmp("bloe", (const char *)tdr->data.data) == 0, "right string push"); - - torture_assert_ntstatus_ok(tctx, tdr_push_charset(tdr, &l, -1, 1, CH_UTF8), - "push failed"); - torture_assert_int_equal(tctx, 9, tdr->data.length, "offset invalid"); - torture_assert_str_equal(tctx, "bloe", (const char *)tdr->data.data+4, "right string read"); - - return true; -} - -struct torture_suite *torture_local_tdr(TALLOC_CTX *mem_ctx) -{ - struct torture_suite *suite = torture_suite_create(mem_ctx, "TDR"); - - torture_suite_add_simple_test(suite, "pull_uint8", test_pull_uint8); - torture_suite_add_simple_test(suite, "push_uint8", test_push_uint8); - - torture_suite_add_simple_test(suite, "pull_uint16", test_pull_uint16); - torture_suite_add_simple_test(suite, "push_uint16", test_push_uint16); - - torture_suite_add_simple_test(suite, "pull_uint32", test_pull_uint32); - torture_suite_add_simple_test(suite, "push_uint32", test_push_uint32); - - torture_suite_add_simple_test(suite, "pull_charset", test_pull_charset); - torture_suite_add_simple_test(suite, "pull_charset", test_pull_charset_empty); - torture_suite_add_simple_test(suite, "push_charset", test_push_charset); - - return suite; -} diff --git a/source4/main.mk b/source4/main.mk index ee2018fb694..8ea9727ed3b 100644 --- a/source4/main.mk +++ b/source4/main.mk @@ -20,7 +20,7 @@ mkinclude ../lib/socket_wrapper/config.mk mkinclude ../lib/nss_wrapper/config.mk mkinclude lib/stream/config.mk mkinclude ../lib/util/config.mk -mkinclude lib/tdr/config.mk +mkinclude ../lib/tdr/config.mk mkinclude ../lib/crypto/config.mk mkinclude ../lib/torture/config.mk mkinclude lib/basic.mk diff --git a/source4/torture/local/config.mk b/source4/torture/local/config.mk index 36f4f08072a..e13056190a2 100644 --- a/source4/torture/local/config.mk +++ b/source4/torture/local/config.mk @@ -44,7 +44,7 @@ TORTURE_LOCAL_OBJ_FILES = \ $(torturesrcdir)/../../lib/compression/testsuite.o \ $(torturesrcdir)/../../lib/util/charset/tests/charset.o \ $(torturesrcdir)/../libcli/security/tests/sddl.o \ - $(torturesrcdir)/../lib/tdr/testsuite.o \ + ../lib/tdr/testsuite.o \ $(torturesrcdir)/../../lib/tevent/testsuite.o \ $(torturesrcdir)/../param/tests/share.o \ $(torturesrcdir)/../param/tests/loadparm.o \ -- cgit From 4ceaec6725509dac4a5c71421dabea1da96b70ab Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 14 Mar 2009 22:07:15 +0100 Subject: Depend on a newer talloc in Samba 4. --- source4/configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/configure.ac b/source4/configure.ac index d33df084068..792e90131a9 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -42,7 +42,7 @@ AC_CONFIG_FILES(param/samba-hostconfig.pc) AC_CONFIG_FILES(librpc/dcerpc_samr.pc) AC_CONFIG_FILES(librpc/dcerpc_atsvc.pc) -SMB_INCLUDED_LIB_PKGCONFIG(LIBTALLOC, talloc >= 1.2.1, [], +SMB_INCLUDED_LIB_PKGCONFIG(LIBTALLOC, talloc >= 1.3.0, [], [ m4_include(../lib/talloc/libtalloc.m4) SMB_INCLUDE_MK(../lib/talloc/config.mk) -- cgit From ec0c6e1617ea1d8a41ee4677ae270ede38024f2a Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 14 Mar 2009 01:36:01 +0100 Subject: s4-smbtorture: fix build warning in test_EnumPrintProcDataTypes. Guenther --- source4/torture/rpc/spoolss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c index ad8158d9562..f8029b246b9 100644 --- a/source4/torture/rpc/spoolss.c +++ b/source4/torture/rpc/spoolss.c @@ -575,7 +575,7 @@ static bool test_EnumPrintProcDataTypes(struct torture_context *tctx, NTSTATUS status; struct spoolss_EnumPrintProcDataTypes r; uint16_t levels[] = { 1 }; - int i, j; + int i; for (i=0;i Date: Sun, 15 Mar 2009 00:54:55 +0100 Subject: Remove -L/usr/lib from a couple more make variables. --- source4/auth/config.m4 | 1 + source4/build/m4/public.m4 | 4 +++- source4/torture/local/config.mk | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/auth/config.m4 b/source4/auth/config.m4 index a271a9f6fe4..fb9ee58c60f 100644 --- a/source4/auth/config.m4 +++ b/source4/auth/config.m4 @@ -27,6 +27,7 @@ if test x"$ac_cv_header_sasl_sasl_h" = x"yes" -a x"$ac_cv_lib_ext_sasl2_sasl_cli SASL_CFLAGS="$CFLAGS" SASL_CPPFLAGS="$CPPFLAGS" SASL_LDFLAGS="$LDFLAGS" + LIB_REMOVE_USR_LIB(SASL_LDFLAGS) else SMB_ENABLE(cyrus_sasl,NO) fi diff --git a/source4/build/m4/public.m4 b/source4/build/m4/public.m4 index ffdf92f7844..6860e56e7fc 100644 --- a/source4/build/m4/public.m4 +++ b/source4/build/m4/public.m4 @@ -99,11 +99,13 @@ AC_DEFUN([SMB_EXT_LIB_FROM_PKGCONFIG], AC_MSG_WARN([cannot run when cross-compiling])) CFLAGS="$OLD_CFLAGS" + ac_cv_$1_libs_only_other="`$PKG_CONFIG --libs-only-other '$2'` `$PKG_CONFIG --libs-only-L '$2'`" + LIB_REMOVE_USR_LIB(ac_cv_$1_libs_only_other) SMB_EXT_LIB($1, [`$PKG_CONFIG --libs-only-l '$2'`], [`$PKG_CONFIG --cflags-only-other '$2'`], [`$PKG_CONFIG --cflags-only-I '$2'`], - [`$PKG_CONFIG --libs-only-other '$2'` `$PKG_CONFIG --libs-only-L '$2'`]) + [$ac_cv_$1_libs_only_other]) ac_cv_$1_found=yes else diff --git a/source4/torture/local/config.mk b/source4/torture/local/config.mk index e13056190a2..967e545225a 100644 --- a/source4/torture/local/config.mk +++ b/source4/torture/local/config.mk @@ -44,7 +44,7 @@ TORTURE_LOCAL_OBJ_FILES = \ $(torturesrcdir)/../../lib/compression/testsuite.o \ $(torturesrcdir)/../../lib/util/charset/tests/charset.o \ $(torturesrcdir)/../libcli/security/tests/sddl.o \ - ../lib/tdr/testsuite.o \ + $(libtdrsrcdir)/testsuite.o \ $(torturesrcdir)/../../lib/tevent/testsuite.o \ $(torturesrcdir)/../param/tests/share.o \ $(torturesrcdir)/../param/tests/loadparm.o \ -- cgit From 75783473d180661257e3f0e3d300179caf34bd8e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 15 Mar 2009 03:05:46 +0100 Subject: Remove unused CONST_DISCARD macro. --- source4/configure.ac | 2 +- source4/include/includes.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'source4') diff --git a/source4/configure.ac b/source4/configure.ac index d33df084068..792e90131a9 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -42,7 +42,7 @@ AC_CONFIG_FILES(param/samba-hostconfig.pc) AC_CONFIG_FILES(librpc/dcerpc_samr.pc) AC_CONFIG_FILES(librpc/dcerpc_atsvc.pc) -SMB_INCLUDED_LIB_PKGCONFIG(LIBTALLOC, talloc >= 1.2.1, [], +SMB_INCLUDED_LIB_PKGCONFIG(LIBTALLOC, talloc >= 1.3.0, [], [ m4_include(../lib/talloc/libtalloc.m4) SMB_INCLUDE_MK(../lib/talloc/config.mk) diff --git a/source4/include/includes.h b/source4/include/includes.h index ddda21f9d8e..d9b7759e7e9 100644 --- a/source4/include/includes.h +++ b/source4/include/includes.h @@ -64,10 +64,6 @@ /* String routines */ #include "../lib/util/safe_string.h" -#ifndef CONST_DISCARD -#define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr))) -#endif - #if 0 /* darn, we can't do this now that we don't link the ldb tools to all the smb libs */ #define TALLOC_ABORT(reason) smb_panic(reason) -- cgit From 0ea702efaeaadcdcb05e99e838dae1b2dbdd95b9 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 15 Mar 2009 16:35:13 +0100 Subject: configure: Add common file with minimum versions of external libraries. --- source4/configure.ac | 10 ++++++---- source4/min_versions.m4 | 6 ++++++ 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 source4/min_versions.m4 (limited to 'source4') diff --git a/source4/configure.ac b/source4/configure.ac index a1eb4f4b468..065a3300cab 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -42,14 +42,16 @@ AC_CONFIG_FILES(param/samba-hostconfig.pc) AC_CONFIG_FILES(librpc/dcerpc_samr.pc) AC_CONFIG_FILES(librpc/dcerpc_atsvc.pc) -SMB_INCLUDED_LIB_PKGCONFIG(LIBTALLOC, talloc >= 1.3.0, [], +m4_include(min_versions.m4) + +SMB_INCLUDED_LIB_PKGCONFIG(LIBTALLOC, talloc >= $TALLOC_MIN_VERSION, [], [ m4_include(../lib/talloc/libtalloc.m4) SMB_INCLUDE_MK(../lib/talloc/config.mk) ] ) -SMB_INCLUDED_LIB_PKGCONFIG(LIBTDB, tdb >= 1.1.3, +SMB_INCLUDED_LIB_PKGCONFIG(LIBTDB, tdb >= $TDB_MIN_VERSION, [], [ m4_include(../lib/tdb/libtdb.m4) @@ -59,13 +61,13 @@ SMB_INCLUDED_LIB_PKGCONFIG(LIBTDB, tdb >= 1.1.3, SMB_INCLUDE_MK(../lib/tdb/python.mk) -SMB_INCLUDED_LIB_PKGCONFIG(LIBTEVENT, tevent = 0.9.4, +SMB_INCLUDED_LIB_PKGCONFIG(LIBTEVENT, tevent = TEVENT_REQUIRED_VERSION, [],[m4_include(../lib/tevent/samba.m4)] ) SMB_INCLUDE_MK(../lib/tevent/python.mk) -SMB_INCLUDED_LIB_PKGCONFIG(LIBLDB, ldb = 0.9.3, +SMB_INCLUDED_LIB_PKGCONFIG(LIBLDB, ldb = $LDB_REQUIRED_VERSION, [ SMB_INCLUDE_MK(lib/ldb/ldb_ildap/config.mk) SMB_INCLUDE_MK(lib/ldb/tools/config.mk) diff --git a/source4/min_versions.m4 b/source4/min_versions.m4 new file mode 100644 index 00000000000..46f45a1bf33 --- /dev/null +++ b/source4/min_versions.m4 @@ -0,0 +1,6 @@ +# Minimum and exact required versions for various libraries +# if we use the ones installed in the system. +TDB_MIN_VERSION=1.1.3 +TALLOC_MIN_VERSION=1.3.0 +LDB_REQUIRED_VERSION=0.9.3 +TEVENT_REQUIRED_VERSION=0.9.4 -- cgit From 693221cfdff655dd78199c9d25a47db8783160a9 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 15 Mar 2009 16:49:12 +0100 Subject: Fix installation of tdr.h. --- source4/headermap.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/headermap.txt b/source4/headermap.txt index 82870446223..9de5b1cc0cc 100644 --- a/source4/headermap.txt +++ b/source4/headermap.txt @@ -9,7 +9,7 @@ ../lib/util/memory.h: util/memory.h ../lib/util/talloc_stack.h: util/talloc_stack.h ../lib/util/xfile.h: util/xfile.h -lib/tdr/tdr.h: tdr.h +../lib/tdr/tdr.h: tdr.h librpc/rpc/dcerpc.h: dcerpc.h lib/ldb/include/ldb.h: ldb.h lib/ldb/include/ldb_errors.h: ldb_errors.h -- cgit From 1a06b31b592a9c1d0188f4470b38e881b0bf3633 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 11 Mar 2009 20:01:13 +1100 Subject: s4:password_hash Only store the LM hash if 'lanman auth = yes' The clients that do only lanman auth are on their way out, the passwords are case insensitive, it does not support unicode and we should not store such a poor hash of the password if we can avoid it. Andrew Bartlett --- source4/dsdb/samdb/ldb_modules/password_hash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 56d4c4fe368..5a9926b6d18 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1379,7 +1379,8 @@ static int setup_password_fields(struct setup_password_fields_io *io) if (io->n.cleartext_utf8) { struct samr_Password *lm_hash; char *cleartext_unix; - if (convert_string_talloc_convenience(io->ac, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), + if (lp_lanman_auth(ldb_get_opaque(ldb, "loadparm")) && + convert_string_talloc_convenience(io->ac, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), CH_UTF8, CH_UNIX, io->n.cleartext_utf8->data, io->n.cleartext_utf8->length, (void **)&cleartext_unix, &converted_pw_len, false)) { lm_hash = talloc(io->ac, struct samr_Password); -- cgit From a1ebb850209289734b12ea966b01d295d8fc436d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 17 Mar 2009 14:18:53 +1100 Subject: added support for parentGUID This is made up of 4 parts: 1) change our schema to include the parentGUID attribute type 2) in the add hook in the objectclass module, get the objectGUID of the parent and add it to the message as parentGUID 3) in the rename hook in the objectclass module, get the objectGUID of the new parent, and insert an async modify request after the renmam is done 4) added a simple test suite --- source4/dsdb/samdb/ldb_modules/objectclass.c | 89 ++++++++++++++++++++++++++-- source4/lib/ldb/tests/python/ldap.py | 30 ++++++++++ source4/setup/schema.ldif | 15 +++++ 3 files changed, 129 insertions(+), 5 deletions(-) (limited to 'source4') diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c index 898d9139659..7883bccfe70 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass.c @@ -414,6 +414,7 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req) struct oc_context *ac; struct ldb_dn *parent_dn; int ret; + static const char * const parent_attrs[] = { "objectGUID", NULL }; ldb = ldb_module_get_ctx(module); @@ -449,7 +450,7 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req) ret = ldb_build_search_req(&search_req, ldb, ac, parent_dn, LDB_SCOPE_BASE, - "(objectClass=*)", NULL, + "(objectClass=*)", parent_attrs, NULL, ac, get_search_callback, req); @@ -500,7 +501,8 @@ static int objectclass_do_add(struct oc_context *ac) return LDB_ERR_UNWILLING_TO_PERFORM; } } else { - + const struct ldb_val *parent_guid; + /* Fix up the DN to be in the standard form, taking particular care to match the parent DN */ ret = fix_dn(msg, ac->req->op.add.message->dn, @@ -514,10 +516,24 @@ static int objectclass_do_add(struct oc_context *ac) return ret; } + parent_guid = ldb_msg_find_ldb_val(ac->search_res->message, "objectGUID"); + if (parent_guid == NULL) { + ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not have an objectGUID!", + ldb_dn_get_linearized(msg->dn)); + talloc_free(mem_ctx); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + /* TODO: Check this is a valid child to this parent, * by reading the allowedChildClasses and * allowedChildClasssesEffective attributes */ - + ret = ldb_msg_add_steal_value(msg, "parentGUID", discard_const(parent_guid)); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, failed to add parentGUID", + ldb_dn_get_linearized(msg->dn)); + talloc_free(mem_ctx); + return LDB_ERR_UNWILLING_TO_PERFORM; + } } if (schema) { @@ -974,7 +990,7 @@ static int objectclass_do_rename(struct oc_context *ac); static int objectclass_rename(struct ldb_module *module, struct ldb_request *req) { - static const char * const attrs[] = { NULL }; + static const char * const attrs[] = { "objectGUID", NULL }; struct ldb_context *ldb; struct ldb_request *search_req; struct oc_context *ac; @@ -1007,6 +1023,9 @@ static int objectclass_rename(struct ldb_module *module, struct ldb_request *req ldb_oom(ldb); return LDB_ERR_OPERATIONS_ERROR; } + + /* note that the results of this search are kept and used to + update the parentGUID in objectclass_rename_callback() */ ret = ldb_build_search_req(&search_req, ldb, ac, parent_dn, LDB_SCOPE_BASE, "(objectClass=*)", @@ -1022,6 +1041,66 @@ static int objectclass_rename(struct ldb_module *module, struct ldb_request *req return ldb_next_request(ac->module, search_req); } +/* + called after the rename happens. + We now need to fix the parentGUID of the object to be the objectGUID of + the new parent +*/ +static int objectclass_rename_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct ldb_context *ldb; + struct oc_context *ac; + const struct ldb_val *parent_guid; + struct ldb_request *mod_req = NULL; + int ret; + struct ldb_message *msg; + struct ldb_message_element *el = NULL; + + ac = talloc_get_type(req->context, struct oc_context); + ldb = ldb_module_get_ctx(ac->module); + + /* make sure the rename succeeded */ + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + + /* the ac->search_res should contain the new parents objectGUID */ + parent_guid = ldb_msg_find_ldb_val(ac->search_res->message, "objectGUID"); + if (parent_guid == NULL) { + ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, new parent does not have an objectGUID!", + ldb_dn_get_linearized(ac->req->op.rename.newdn)); + return LDB_ERR_UNWILLING_TO_PERFORM; + + } + + /* construct the modify message */ + msg = ldb_msg_new(ac); + if (msg == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + msg->dn = ac->req->op.rename.newdn; + + ret = ldb_msg_add_value(msg, "parentGUID", parent_guid, &el); + if (ret != LDB_SUCCESS) { + return ret; + } + + el->flags = LDB_FLAG_MOD_REPLACE; + + ret = ldb_build_mod_req(&mod_req, ldb, ac, msg, + NULL, ac, oc_op_callback, req); + + return ldb_next_request(ac->module, mod_req); +} + static int objectclass_do_rename(struct oc_context *ac) { struct ldb_context *ldb; @@ -1055,7 +1134,7 @@ static int objectclass_do_rename(struct oc_context *ac) ret = ldb_build_rename_req(&rename_req, ldb, ac, ac->req->op.rename.olddn, fixed_dn, ac->req->controls, - ac, oc_op_callback, + ac, objectclass_rename_callback, ac->req); if (ret != LDB_SUCCESS) { return ret; diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py index a30273fc668..7d2c7d05472 100755 --- a/source4/lib/ldb/tests/python/ldap.py +++ b/source4/lib/ldb/tests/python/ldap.py @@ -90,6 +90,36 @@ class BasicTests(unittest.TestCase): except LdbError, (num, _): self.assertEquals(num, ERR_NO_SUCH_OBJECT) + def test_parentGUID(self): + """Test parentGUID behaviour""" + print "Testing parentGUID behaviour\n" + + self.ldb.add({ + "dn": "cn=parentguidtest,cn=users," + self.base_dn, + "objectclass":"user", + "samaccountname":"parentguidtest"}); + res1 = ldb.search(base="cn=parentguidtest,cn=users," + self.base_dn, scope=SCOPE_BASE, + attrs=["parentGUID"]); + res2 = ldb.search(base="cn=users," + self.base_dn,scope=SCOPE_BASE, + attrs=["objectGUID"]); + self.assertEquals(res1[0]["parentGUID"], res2[0]["objectGUID"]); + + """Test parentGUID behaviour""" + print "Testing parentGUID behaviour on rename\n" + + self.ldb.add({ + "dn": "cn=testotherusers," + self.base_dn, + "objectclass":"container"}); + res1 = ldb.search(base="cn=testotherusers," + self.base_dn,scope=SCOPE_BASE, + attrs=["objectGUID"]); + ldb.rename("cn=parentguidtest,cn=users," + self.base_dn, + "cn=parentguidtest,cn=testotherusers," + self.base_dn); + res2 = ldb.search(base="cn=parentguidtest,cn=testotherusers," + self.base_dn, + scope=SCOPE_BASE, + attrs=["parentGUID"]); + self.assertEquals(res1[0]["objectGUID"], res2[0]["parentGUID"]); + + def test_all(self): """Basic tests""" diff --git a/source4/setup/schema.ldif b/source4/setup/schema.ldif index 56eb7ce0c07..a4dfaea7eb5 100644 --- a/source4/setup/schema.ldif +++ b/source4/setup/schema.ldif @@ -4096,6 +4096,21 @@ systemOnly: TRUE systemFlags: 19 isMemberOfPartialAttributeSet: TRUE +dn: CN=Parent-GUID,${SCHEMADN} +objectClass: top +objectClass: attributeSchema +cn: Parent-GUID +ldapDisplayName: parentGUID +attributeId: 1.2.840.113556.1.4.1224 +attributeSyntax: 2.5.5.10 +omSyntax: 4 +isSingleValued: TRUE +schemaIdGuid: 2df90d74-009f-11d2-aa4c-00c04fd7d83a +systemOnly: TRUE +searchFlags: 0 +systemFlags: 134217748 +schemaFlagsEx: 1 + dn: CN=ms-DS-Tasks-For-Az-Task-BL,${SCHEMADN} objectClass: top objectClass: attributeSchema -- cgit From 937a058cf25672bc22bf07183b0fb485138f6593 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Mar 2009 08:58:04 +0100 Subject: s4:build: use SAMBA_PKG_CONFIG_MIN_VERSION instead of PKG_CONFIG_MIN_VERSION And also intialize the variable. This fixes ./autogen.sh in the merged build for me. metze --- source4/build/m4/public.m4 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/build/m4/public.m4 b/source4/build/m4/public.m4 index 6860e56e7fc..bd98a400be4 100644 --- a/source4/build/m4/public.m4 +++ b/source4/build/m4/public.m4 @@ -82,7 +82,8 @@ AC_DEFUN([SMB_EXT_LIB_FROM_PKGCONFIG], echo "*** Or see http://pkg-config.freedesktop.org/ to get pkg-config." ac_cv_$1_found=no else - if $PKG_CONFIG --atleast-pkgconfig-version 0.9.0; then + SAMBA_PKG_CONFIG_MIN_VERSION="0.9.0" + if $PKG_CONFIG --atleast-pkgconfig-version $SAMBA_PKG_CONFIG_MIN_VERSION; then AC_MSG_CHECKING(for $2) if $PKG_CONFIG --exists '$2' ; then @@ -114,7 +115,7 @@ AC_DEFUN([SMB_EXT_LIB_FROM_PKGCONFIG], ac_cv_$1_found=no fi else - echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." + echo "*** Your version of pkg-config is too old. You need version $SAMBA_PKG_CONFIG_MIN_VERSION or newer." echo "*** See http://pkg-config.freedesktop.org/" ac_cv_$1_found=no fi -- cgit From c6e3e5eabc6de32117ce7d5403948e9ab739e4eb Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 14 Mar 2009 01:36:31 +0100 Subject: s4-smbtorture: fix test_GetPrinterData tests after out pointer changes. Guenther --- source4/torture/rpc/spoolss.c | 2 ++ source4/torture/rpc/spoolss_win.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c index f8029b246b9..9e02c903969 100644 --- a/source4/torture/rpc/spoolss.c +++ b/source4/torture/rpc/spoolss.c @@ -1338,12 +1338,14 @@ static bool test_GetPrinterData(struct torture_context *tctx, struct spoolss_GetPrinterData r; uint32_t needed; enum spoolss_PrinterDataType type; + union spoolss_PrinterData data; r.in.handle = handle; r.in.value_name = value_name; r.in.offered = 0; r.out.needed = &needed; r.out.type = &type; + r.out.data = &data; torture_comment(tctx, "Testing GetPrinterData\n"); diff --git a/source4/torture/rpc/spoolss_win.c b/source4/torture/rpc/spoolss_win.c index add06522c61..1f22c398424 100644 --- a/source4/torture/rpc/spoolss_win.c +++ b/source4/torture/rpc/spoolss_win.c @@ -157,6 +157,7 @@ static bool test_GetPrinterData(struct torture_context *tctx, struct spoolss_GetPrinterData gpd; uint32_t needed; enum spoolss_PrinterDataType type; + union spoolss_PrinterData data; torture_comment(tctx, "Testing GetPrinterData(%s).\n", value_name); gpd.in.handle = handle; @@ -164,6 +165,7 @@ static bool test_GetPrinterData(struct torture_context *tctx, gpd.in.offered = 4; gpd.out.needed = &needed; gpd.out.type = &type; + gpd.out.data = &data; status = dcerpc_spoolss_GetPrinterData(p, tctx, &gpd); torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed."); @@ -171,7 +173,7 @@ static bool test_GetPrinterData(struct torture_context *tctx, "GetPrinterData did not return expected error value."); if (W_ERROR_IS_OK(expected_werr)) { - torture_assert_int_equal(tctx, gpd.out.data.value, + torture_assert_int_equal(tctx, data.value, expected_value, "GetPrinterData did not return expected value."); } -- cgit From be9a34e75d03ca09b4d57c57f59f83d4214c7754 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Sat, 14 Mar 2009 01:38:08 +0100 Subject: s4-spoolss: fix spoolss_GetPrinterData w.r.t. out pointer changes. Guenther --- source4/ntptr/simple_ldb/ntptr_simple_ldb.c | 28 ++++++++++++++-------------- source4/rpc_server/spoolss/dcesrv_spoolss.c | 8 +++++++- 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'source4') diff --git a/source4/ntptr/simple_ldb/ntptr_simple_ldb.c b/source4/ntptr/simple_ldb/ntptr_simple_ldb.c index aea5d08c3f3..f4ba6b71575 100644 --- a/source4/ntptr/simple_ldb/ntptr_simple_ldb.c +++ b/source4/ntptr/simple_ldb/ntptr_simple_ldb.c @@ -128,43 +128,43 @@ static WERROR sptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC struct dcerpc_server_info *server_info = lp_dcerpc_server_info(mem_ctx, server->ntptr->lp_ctx); if (strcmp("W3SvcInstalled", r->in.value_name) == 0) { *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - r->out.data.value = 0; + r->out.data->value = 0; return WERR_OK; } else if (strcmp("BeepEnabled", r->in.value_name) == 0) { *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - r->out.data.value = 0; + r->out.data->value = 0; return WERR_OK; } else if (strcmp("EventLog", r->in.value_name) == 0) { *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - r->out.data.value = 0; + r->out.data->value = 0; return WERR_OK; } else if (strcmp("NetPopup", r->in.value_name) == 0) { *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - r->out.data.value = 0; + r->out.data->value = 0; return WERR_OK; } else if (strcmp("NetPopupToComputer", r->in.value_name) == 0) { *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - r->out.data.value = 0; + r->out.data->value = 0; return WERR_OK; } else if (strcmp("MajorVersion", r->in.value_name) == 0) { *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - r->out.data.value = 3; + r->out.data->value = 3; return WERR_OK; } else if (strcmp("MinorVersion", r->in.value_name) == 0) { *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - r->out.data.value = 0; + r->out.data->value = 0; return WERR_OK; } else if (strcmp("DefaultSpoolDirectory", r->in.value_name) == 0) { *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_STRING; - r->out.data.string = "C:\\PRINTERS"; + r->out.data->string = "C:\\PRINTERS"; return WERR_OK; } else if (strcmp("Architecture", r->in.value_name) == 0) { *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_STRING; - r->out.data.string = SPOOLSS_ARCHITECTURE_NT_X86; + r->out.data->string = SPOOLSS_ARCHITECTURE_NT_X86; return WERR_OK; } else if (strcmp("DsPresent", r->in.value_name) == 0) { *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; - r->out.data.value = 1; + r->out.data->value = 1; return WERR_OK; } else if (strcmp("OSVersion", r->in.value_name) == 0) { DATA_BLOB blob; @@ -182,7 +182,7 @@ static WERROR sptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC } *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_BINARY; - r->out.data.binary = blob; + r->out.data->binary = blob; return WERR_OK; } else if (strcmp("OSVersionEx", r->in.value_name) == 0) { DATA_BLOB blob; @@ -202,16 +202,16 @@ static WERROR sptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC } *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_BINARY; - r->out.data.binary = blob; + r->out.data->binary = blob; return WERR_OK; } else if (strcmp("DNSMachineName", r->in.value_name) == 0) { if (!lp_realm(server->ntptr->lp_ctx)) return WERR_INVALID_PARAM; *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_STRING; - r->out.data.string = talloc_asprintf(mem_ctx, "%s.%s", + r->out.data->string = talloc_asprintf(mem_ctx, "%s.%s", lp_netbios_name(server->ntptr->lp_ctx), lp_realm(server->ntptr->lp_ctx)); - W_ERROR_HAVE_NO_MEMORY(r->out.data.string); + W_ERROR_HAVE_NO_MEMORY(r->out.data->string); return WERR_OK; } diff --git a/source4/rpc_server/spoolss/dcesrv_spoolss.c b/source4/rpc_server/spoolss/dcesrv_spoolss.c index 61c8009716b..820fb7d39ef 100644 --- a/source4/rpc_server/spoolss/dcesrv_spoolss.c +++ b/source4/rpc_server/spoolss/dcesrv_spoolss.c @@ -583,6 +583,12 @@ static WERROR dcesrv_spoolss_GetPrinterData(struct dcesrv_call_state *dce_call, r->out.type = talloc_zero(mem_ctx, enum spoolss_PrinterDataType); W_ERROR_HAVE_NO_MEMORY(r->out.type); + r->out.needed = talloc_zero(mem_ctx, uint32_t); + W_ERROR_HAVE_NO_MEMORY(r->out.needed); + + r->out.data = talloc_zero(mem_ctx, union spoolss_PrinterData); + W_ERROR_HAVE_NO_MEMORY(r->out.data); + switch (handle->type) { case NTPTR_HANDLE_SERVER: status = ntptr_GetPrintServerData(handle, mem_ctx, r); @@ -594,7 +600,7 @@ static WERROR dcesrv_spoolss_GetPrinterData(struct dcesrv_call_state *dce_call, W_ERROR_NOT_OK_RETURN(status); - *r->out.needed = ndr_size_spoolss_PrinterData(&r->out.data, *r->out.type, ic, 0); + *r->out.needed = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, ic, 0); *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, SPOOLSS_PRINTER_DATA_TYPE_NULL); r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA); -- cgit From 4727e3fa9784b183d223cd0779b6748f9916a538 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 16 Mar 2009 15:44:16 +0100 Subject: s4-spoolss: use winreg_Type for GetPrinterData implementation. Guenther --- source4/ntptr/simple_ldb/ntptr_simple_ldb.c | 26 +++++++++++++------------- source4/rpc_server/spoolss/dcesrv_spoolss.c | 4 ++-- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'source4') diff --git a/source4/ntptr/simple_ldb/ntptr_simple_ldb.c b/source4/ntptr/simple_ldb/ntptr_simple_ldb.c index f4ba6b71575..4ebbaaeffc6 100644 --- a/source4/ntptr/simple_ldb/ntptr_simple_ldb.c +++ b/source4/ntptr/simple_ldb/ntptr_simple_ldb.c @@ -127,43 +127,43 @@ static WERROR sptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC { struct dcerpc_server_info *server_info = lp_dcerpc_server_info(mem_ctx, server->ntptr->lp_ctx); if (strcmp("W3SvcInstalled", r->in.value_name) == 0) { - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + *r->out.type = REG_DWORD; r->out.data->value = 0; return WERR_OK; } else if (strcmp("BeepEnabled", r->in.value_name) == 0) { - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + *r->out.type = REG_DWORD; r->out.data->value = 0; return WERR_OK; } else if (strcmp("EventLog", r->in.value_name) == 0) { - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + *r->out.type = REG_DWORD; r->out.data->value = 0; return WERR_OK; } else if (strcmp("NetPopup", r->in.value_name) == 0) { - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + *r->out.type = REG_DWORD; r->out.data->value = 0; return WERR_OK; } else if (strcmp("NetPopupToComputer", r->in.value_name) == 0) { - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + *r->out.type = REG_DWORD; r->out.data->value = 0; return WERR_OK; } else if (strcmp("MajorVersion", r->in.value_name) == 0) { - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + *r->out.type = REG_DWORD; r->out.data->value = 3; return WERR_OK; } else if (strcmp("MinorVersion", r->in.value_name) == 0) { - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + *r->out.type = REG_DWORD; r->out.data->value = 0; return WERR_OK; } else if (strcmp("DefaultSpoolDirectory", r->in.value_name) == 0) { - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_STRING; + *r->out.type = REG_SZ; r->out.data->string = "C:\\PRINTERS"; return WERR_OK; } else if (strcmp("Architecture", r->in.value_name) == 0) { - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_STRING; + *r->out.type = REG_SZ; r->out.data->string = SPOOLSS_ARCHITECTURE_NT_X86; return WERR_OK; } else if (strcmp("DsPresent", r->in.value_name) == 0) { - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_UINT32; + *r->out.type = REG_DWORD; r->out.data->value = 1; return WERR_OK; } else if (strcmp("OSVersion", r->in.value_name) == 0) { @@ -181,7 +181,7 @@ static WERROR sptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC return WERR_GENERAL_FAILURE; } - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_BINARY; + *r->out.type = REG_BINARY; r->out.data->binary = blob; return WERR_OK; } else if (strcmp("OSVersionEx", r->in.value_name) == 0) { @@ -201,13 +201,13 @@ static WERROR sptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC return WERR_GENERAL_FAILURE; } - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_BINARY; + *r->out.type = REG_BINARY; r->out.data->binary = blob; return WERR_OK; } else if (strcmp("DNSMachineName", r->in.value_name) == 0) { if (!lp_realm(server->ntptr->lp_ctx)) return WERR_INVALID_PARAM; - *r->out.type = SPOOLSS_PRINTER_DATA_TYPE_STRING; + *r->out.type = REG_SZ; r->out.data->string = talloc_asprintf(mem_ctx, "%s.%s", lp_netbios_name(server->ntptr->lp_ctx), lp_realm(server->ntptr->lp_ctx)); diff --git a/source4/rpc_server/spoolss/dcesrv_spoolss.c b/source4/rpc_server/spoolss/dcesrv_spoolss.c index 820fb7d39ef..7d14c0e5028 100644 --- a/source4/rpc_server/spoolss/dcesrv_spoolss.c +++ b/source4/rpc_server/spoolss/dcesrv_spoolss.c @@ -580,7 +580,7 @@ static WERROR dcesrv_spoolss_GetPrinterData(struct dcesrv_call_state *dce_call, if (!handle) return WERR_BADFID; - r->out.type = talloc_zero(mem_ctx, enum spoolss_PrinterDataType); + r->out.type = talloc_zero(mem_ctx, enum winreg_Type); W_ERROR_HAVE_NO_MEMORY(r->out.type); r->out.needed = talloc_zero(mem_ctx, uint32_t); @@ -601,7 +601,7 @@ static WERROR dcesrv_spoolss_GetPrinterData(struct dcesrv_call_state *dce_call, W_ERROR_NOT_OK_RETURN(status); *r->out.needed = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, ic, 0); - *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, SPOOLSS_PRINTER_DATA_TYPE_NULL); + *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE); r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA); } -- cgit From 0e2139c6936b28015a8a2a539810c2bd7821d36f Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 16 Mar 2009 16:01:10 +0100 Subject: s4-smbtorture: fix RPC-SPOOLSS test after PrinterData changes. Guenther --- source4/torture/rpc/spoolss.c | 15 ++++++++------- source4/torture/rpc/spoolss_win.c | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'source4') diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c index 9e02c903969..c16def09d20 100644 --- a/source4/torture/rpc/spoolss.c +++ b/source4/torture/rpc/spoolss.c @@ -1337,7 +1337,7 @@ static bool test_GetPrinterData(struct torture_context *tctx, NTSTATUS status; struct spoolss_GetPrinterData r; uint32_t needed; - enum spoolss_PrinterDataType type; + enum winreg_Type type; union spoolss_PrinterData data; r.in.handle = handle; @@ -1372,7 +1372,7 @@ static bool test_GetPrinterDataEx(struct torture_context *tctx, { NTSTATUS status; struct spoolss_GetPrinterDataEx r; - uint32_t type; + enum winreg_Type type; uint32_t needed; r.in.handle = handle; @@ -1419,16 +1419,15 @@ static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pip do { uint32_t value_size = 0; uint32_t data_size = 0; - uint32_t printerdata_type = 0; - DATA_BLOB data = data_blob(NULL,0); + enum winreg_Type type = 0; r.in.value_offered = value_size; r.out.value_needed = &value_size; r.in.data_offered = data_size; r.out.data_needed = &data_size; - r.out.printerdata_type = &printerdata_type; - r.out.buffer = &data; + r.out.type = &type; + r.out.data = talloc_zero_array(tctx, uint8_t, 0); torture_comment(tctx, "Testing EnumPrinterData\n"); @@ -1437,7 +1436,9 @@ static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pip torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed"); r.in.value_offered = value_size; + r.out.value_name = talloc_zero_array(tctx, const char, value_size); r.in.data_offered = data_size; + r.out.data = talloc_zero_array(tctx, uint8_t, data_size); status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r); @@ -1517,7 +1518,7 @@ static bool test_SetPrinterData(struct torture_context *tctx, r.in.handle = handle; r.in.value_name = value_name; - r.in.type = SPOOLSS_PRINTER_DATA_TYPE_STRING; + r.in.type = REG_SZ; r.in.data.string = "dog"; torture_comment(tctx, "Testing SetPrinterData\n"); diff --git a/source4/torture/rpc/spoolss_win.c b/source4/torture/rpc/spoolss_win.c index 1f22c398424..b7ee2386dae 100644 --- a/source4/torture/rpc/spoolss_win.c +++ b/source4/torture/rpc/spoolss_win.c @@ -156,7 +156,7 @@ static bool test_GetPrinterData(struct torture_context *tctx, NTSTATUS status; struct spoolss_GetPrinterData gpd; uint32_t needed; - enum spoolss_PrinterDataType type; + enum winreg_Type type; union spoolss_PrinterData data; torture_comment(tctx, "Testing GetPrinterData(%s).\n", value_name); -- cgit From 87d97ad0422c771ea575e9a5e68d0d2e5bfe25be Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 17 Mar 2009 03:08:34 +0100 Subject: s4-smbtorture: fix test_EnumPrinterKey. Guenther --- source4/torture/rpc/spoolss_win.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4') diff --git a/source4/torture/rpc/spoolss_win.c b/source4/torture/rpc/spoolss_win.c index b7ee2386dae..71c1ce9e995 100644 --- a/source4/torture/rpc/spoolss_win.c +++ b/source4/torture/rpc/spoolss_win.c @@ -366,22 +366,22 @@ static bool test_EnumPrinterKey(struct torture_context *tctx, NTSTATUS status; struct spoolss_EnumPrinterKey epk; uint32_t needed = 0; + const char **key_buffer = NULL; torture_comment(tctx, "Testing EnumPrinterKey(%s)\n", key); epk.in.handle = handle; epk.in.key_name = talloc_strdup(tctx, key); - epk.in.key_buffer_size = 0; + epk.in.offered = 0; epk.out.needed = &needed; - epk.out.key_buffer = talloc_array(tctx, uint16_t, 0); + epk.out.key_buffer = &key_buffer; status = dcerpc_spoolss_EnumPrinterKey(p, tctx, &epk); torture_assert_ntstatus_ok(tctx, status, "EnumPrinterKey failed"); if (W_ERROR_EQUAL(epk.out.result, WERR_MORE_DATA)) { - epk.in.key_buffer_size = needed; - epk.out.key_buffer = talloc_array(tctx, uint16_t, needed/2); + epk.in.offered = needed; status = dcerpc_spoolss_EnumPrinterKey(p, tctx, &epk); torture_assert_ntstatus_ok(tctx, status, "EnumPrinterKey failed"); -- cgit From a23719babb7fd117ed2d4d2355748d00e415d561 Mon Sep 17 00:00:00 2001 From: Björn Jacke Date: Sun, 15 Mar 2009 17:26:21 +0100 Subject: fix build on sles8 and other old popt installations Signed-off-by: Michael Adam --- source4/lib/cmdline/popt_common.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4') diff --git a/source4/lib/cmdline/popt_common.h b/source4/lib/cmdline/popt_common.h index 733d12a4433..2f4ab2c1786 100644 --- a/source4/lib/cmdline/popt_common.h +++ b/source4/lib/cmdline/popt_common.h @@ -28,6 +28,10 @@ extern struct poptOption popt_common_connection[]; extern struct poptOption popt_common_version[]; extern struct poptOption popt_common_credentials[]; +#ifndef POPT_TABLEEND +#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL } +#endif + #define POPT_COMMON_SAMBA { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_samba, 0, "Common samba options:", NULL }, #define POPT_COMMON_CONNECTION { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_connection, 0, "Connection options:", NULL }, #define POPT_COMMON_VERSION { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version, 0, "Common samba options:", NULL }, -- cgit From 066cbb5835feae90e2ce4172e3c58bf50a2b004b Mon Sep 17 00:00:00 2001 From: Björn Jacke Date: Wed, 11 Mar 2009 15:32:49 +0100 Subject: clean up lib64 linking paths the same way as lib Signed-off-by: Michael Adam --- source4/aclocal.m4 | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/aclocal.m4 b/source4/aclocal.m4 index 240a994f9df..8ad8f47cd69 100644 --- a/source4/aclocal.m4 +++ b/source4/aclocal.m4 @@ -31,11 +31,17 @@ AC_DEFUN(LIB_REMOVE_USR_LIB,[ case [$]l[$]i in -L/usr/lib) ;; -L/usr/lib/) ;; - -Wl,-rpath,/usr/lib) ;; - -Wl,-rpath,/usr/lib/) ;; + -L/usr/lib64) ;; + -L/usr/lib64/) ;; + -Wl,-rpath,/usr/lib) l="";; + -Wl,-rpath,/usr/lib/) l="";; + -Wl,-rpath,/usr/lib64) l="";; + -Wl,-rpath,/usr/lib64/) l="";; -Wl,-rpath) l=[$]i;; -Wl,-rpath-Wl,/usr/lib) l="";; -Wl,-rpath-Wl,/usr/lib/) l="";; + -Wl,-rpath-Wl,/usr/lib64) l="";; + -Wl,-rpath-Wl,/usr/lib64/) l="";; *) s=" " if test x"[$]ac_new_flags" = x""; then -- cgit From fac7208273a24fa35d3274df28aea3bb87374861 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 17 Mar 2009 18:03:36 +0100 Subject: s4-smbtorture: fix spoolss notify test for notify type changes. Guenther --- source4/torture/rpc/spoolss_notify.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/torture/rpc/spoolss_notify.c b/source4/torture/rpc/spoolss_notify.c index 048f255ffc8..cb875c9eee7 100644 --- a/source4/torture/rpc/spoolss_notify.c +++ b/source4/torture/rpc/spoolss_notify.c @@ -252,12 +252,12 @@ static bool test_RFFPCNEx(struct torture_context *tctx, t1.flags = 0; t1.count = 2; t1.types = talloc_zero_array(tctx, struct spoolss_NotifyOptionType, 2); - t1.types[0].type = SPOOLSS_NOTIFY_PRINTER; + t1.types[0].type = PRINTER_NOTIFY_TYPE; t1.types[0].count = 1; t1.types[0].fields = talloc_array(t1.types, enum spoolss_Field, 1); t1.types[0].fields[0] = SPOOLSS_FIELD_SERVER_NAME; - t1.types[1].type = SPOOLSS_NOTIFY_JOB; + t1.types[1].type = JOB_NOTIFY_TYPE; t1.types[1].count = 1; t1.types[1].fields = talloc_array(t1.types, enum spoolss_Field, 1); t1.types[1].fields[0] = SPOOLSS_FIELD_PRINTER_NAME; -- cgit From e95d0b548e344dbc8cb3dd0a0f29854711bd0cac Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 17 Mar 2009 20:18:31 +0100 Subject: s4:build: require tevent 0.9.5 metze --- source4/min_versions.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/min_versions.m4 b/source4/min_versions.m4 index 46f45a1bf33..eaefbd5148f 100644 --- a/source4/min_versions.m4 +++ b/source4/min_versions.m4 @@ -3,4 +3,4 @@ TDB_MIN_VERSION=1.1.3 TALLOC_MIN_VERSION=1.3.0 LDB_REQUIRED_VERSION=0.9.3 -TEVENT_REQUIRED_VERSION=0.9.4 +TEVENT_REQUIRED_VERSION=0.9.5 -- cgit From 6c08e329fa9396474b200fe7593d4a5c2082930a Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Thu, 12 Mar 2009 08:32:58 -0700 Subject: s4 libcli: Add SMB2.1 dialect to libcli Negotiate 2.1 if possible, leave negotiate results in transport->negotiate.dialect_revision. --- source4/libcli/smb2/connect.c | 3 ++- source4/libcli/smb2/smb2.h | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 11bec42737d..3fd9a38e019 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -108,6 +108,7 @@ static void continue_negprot(struct smb2_request *req) transport->negotiate.system_time = state->negprot.out.system_time; transport->negotiate.server_start_time = state->negprot.out.server_start_time; transport->negotiate.security_mode = state->negprot.out.security_mode; + transport->negotiate.dialect_revision = state->negprot.out.dialect_revision; switch (transport->options.signing) { case SMB_SIGNING_OFF: @@ -187,7 +188,7 @@ static void continue_socket(struct composite_context *creq) state->negprot.in.capabilities = 0; unix_to_nt_time(&state->negprot.in.start_time, time(NULL)); dialects[0] = SMB2_DIALECT_REVISION; - dialects[1] = 0; + dialects[1] = SMB21_DIALECT_REVISION; state->negprot.in.dialects = dialects; req = smb2_negprot_send(transport, &state->negprot); diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index d1d5b842c33..3cc3ec2f25b 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -35,6 +35,7 @@ struct smb2_negotiate { NTTIME system_time; NTTIME server_start_time; uint16_t security_mode; + uint16_t dialect_revision; }; /* this is the context for the smb2 transport layer */ @@ -226,8 +227,9 @@ struct smb2_request { #define SMB2_MAGIC 0x424D53FE /* 0xFE 'S' 'M' 'B' */ -/* the dialect we support */ +/* the dialects we support */ #define SMB2_DIALECT_REVISION 0x202 +#define SMB21_DIALECT_REVISION 0x210 /* SMB2 negotiate security_mode */ #define SMB2_NEGOTIATE_SIGNING_ENABLED 0x01 -- cgit From 7bf2a213cd589e1f0f80faab343aea30263046c2 Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Fri, 13 Mar 2009 09:04:33 -0700 Subject: s4 torture: Add a string version for NT_STATUS_WIN7_INVALID_RANGE Also submitted a request to cifs-protocol for a real name for this thing. Use win7 target logic in smb2 lock test, SMB2-LOCK now passes against Win7. --- source4/libcli/util/nterr.c | 1 + source4/torture/smb2/lock.c | 39 +++++++++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 10 deletions(-) (limited to 'source4') diff --git a/source4/libcli/util/nterr.c b/source4/libcli/util/nterr.c index 4e7cdf5c3aa..7f544b59225 100644 --- a/source4/libcli/util/nterr.c +++ b/source4/libcli/util/nterr.c @@ -549,6 +549,7 @@ static const nt_err_code_struct nt_errs[] = { "NT_STATUS_OBJECTID_NOT_FOUND", NT_STATUS_OBJECTID_NOT_FOUND }, { "NT_STATUS_DOWNGRADE_DETECTED", NT_STATUS_DOWNGRADE_DETECTED }, { "NT_STATUS_DS_BUSY", NT_STATUS_DS_BUSY }, + { "XXX_INVALID_RANGE", NT_STATUS_WIN7_INVALID_RANGE }, { "STATUS_MORE_ENTRIES", STATUS_MORE_ENTRIES }, { "STATUS_SOME_UNMAPPED", STATUS_SOME_UNMAPPED }, { "STATUS_NOTIFY_CLEANUP", STATUS_NOTIFY_CLEANUP }, diff --git a/source4/torture/smb2/lock.c b/source4/torture/smb2/lock.c index d820983022b..5f0293c6810 100644 --- a/source4/torture/smb2/lock.c +++ b/source4/torture/smb2/lock.c @@ -28,6 +28,9 @@ #include "librpc/gen_ndr/ndr_security.h" +#define TARGET_IS_WINDOWS(_tctx) (torture_setting_bool(_tctx, "win7", false) || torture_setting_bool(torture, "windows", false)) +#define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false)) + #define CHECK_STATUS(status, correct) do { \ if (!NT_STATUS_EQUAL(status, correct)) { \ printf("(%s) Incorrect status %s - should be %s\n", \ @@ -97,16 +100,26 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree el[0].reserved = 0x00000000; el[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE|SMB2_LOCK_FLAG_FAIL_IMMEDIATELY; status = smb2_lock(tree, &lck); - CHECK_STATUS(status, NT_STATUS_OK); + if (TARGET_IS_WIN7(torture)) { + CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE); + } else { + CHECK_STATUS(status, NT_STATUS_OK); + } CHECK_VALUE(lck.out.reserved, 0); lck.in.reserved = 0x123ab2; status = smb2_lock(tree, &lck); - CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + if (TARGET_IS_WIN7(torture)) { + CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE); + } else { + CHECK_STATUS(status, NT_STATUS_OK); + } lck.in.reserved = 0x123ab3; status = smb2_lock(tree, &lck); - if (torture_setting_bool(torture, "windows", false)) { + if (TARGET_IS_WIN7(torture)) { + CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE); + } else if (TARGET_IS_WINDOWS(torture)) { CHECK_STATUS(status, NT_STATUS_OK); } else { CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); @@ -115,11 +128,17 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree lck.in.reserved = 0x123ab4; status = smb2_lock(tree, &lck); - CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + if (TARGET_IS_WIN7(torture)) { + CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE); + } else { + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); + } lck.in.reserved = 0x123ab5; status = smb2_lock(tree, &lck); - if (torture_setting_bool(torture, "windows", false)) { + if (TARGET_IS_WIN7(torture)) { + CHECK_STATUS(status, NT_STATUS_WIN7_INVALID_RANGE); + } else if (TARGET_IS_WINDOWS(torture)) { CHECK_STATUS(status, NT_STATUS_OK); } else { CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); @@ -141,7 +160,7 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); status = smb2_lock(tree, &lck); - if (torture_setting_bool(torture, "windows", false)) { + if (TARGET_IS_WINDOWS(torture)) { CHECK_STATUS(status, NT_STATUS_OK); } else { CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); @@ -152,7 +171,7 @@ static bool test_valid_request(struct torture_context *torture, struct smb2_tree CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); status = smb2_lock(tree, &lck); - if (torture_setting_bool(torture, "windows", false)) { + if (TARGET_IS_WINDOWS(torture)) { CHECK_STATUS(status, NT_STATUS_OK); } else { CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); @@ -481,7 +500,6 @@ static bool test_lock_rw_exclusiv(struct torture_context *torture, struct smb2_t return test_lock_read_write(torture, tree, &s); } - static bool test_lock_auto_unlock(struct torture_context *torture, struct smb2_tree *tree) { bool ret = true; @@ -513,13 +531,14 @@ static bool test_lock_auto_unlock(struct torture_context *torture, struct smb2_t CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); status = smb2_lock(tree, &lck); - if (torture_setting_bool(torture, "windows", false)) { + if (TARGET_IS_WINDOWS(torture)) { CHECK_STATUS(status, NT_STATUS_OK); } else { CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); } - + status = smb2_lock(tree, &lck); + CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED); done: return ret; -- cgit From 211e2555690afc0436c2bafb7ef8d426564cc680 Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Mon, 16 Mar 2009 09:24:06 -0700 Subject: s4 torture: Win7 has a slightly different allowed access mask Still investigating. --- source4/torture/smb2/create.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/torture/smb2/create.c b/source4/torture/smb2/create.c index 6d898a128cf..febfbe03ec4 100644 --- a/source4/torture/smb2/create.c +++ b/source4/torture/smb2/create.c @@ -43,6 +43,8 @@ return false; \ }} while (0) +#define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false)) + /* test some interesting combinations found by gentest */ @@ -160,7 +162,11 @@ static bool test_create_gentest(struct torture_context *torture, struct smb2_tre } } - CHECK_EQUAL(access_mask, 0x0df0fe00); + if (TARGET_IS_WIN7(torture)) { + CHECK_EQUAL(access_mask, 0x0de0fe00); + } else { + CHECK_EQUAL(access_mask, 0x0df0fe00); + } io.in.create_disposition = NTCREATEX_DISP_OPEN_IF; io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED; -- cgit From 6e52c232c7c761a7b7d0ea4ec94214f580a481a7 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 18 Mar 2009 01:39:49 +0100 Subject: s4-smbtorture: fix spoolss_EnumPrinterDataEx tests. sorry, I could swear this did compile... Guenther --- source4/torture/rpc/spoolss.c | 3 ++- source4/torture/rpc/spoolss_win.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'source4') diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c index c16def09d20..2bdcc3fdaf7 100644 --- a/source4/torture/rpc/spoolss.c +++ b/source4/torture/rpc/spoolss.c @@ -1463,6 +1463,7 @@ static bool test_EnumPrinterDataEx(struct torture_context *tctx, { NTSTATUS status; struct spoolss_EnumPrinterDataEx r; + struct spoolss_PrinterEnumValues *info; uint32_t needed; uint32_t count; @@ -1471,6 +1472,7 @@ static bool test_EnumPrinterDataEx(struct torture_context *tctx, r.in.offered = 0; r.out.needed = &needed; r.out.count = &count; + r.out.info = &info; torture_comment(tctx, "Testing EnumPrinterDataEx\n"); @@ -1478,7 +1480,6 @@ static bool test_EnumPrinterDataEx(struct torture_context *tctx, torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed"); r.in.offered = needed; - r.out.buffer = talloc_array(tctx, uint8_t, needed); status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r); diff --git a/source4/torture/rpc/spoolss_win.c b/source4/torture/rpc/spoolss_win.c index 71c1ce9e995..5624e68d03f 100644 --- a/source4/torture/rpc/spoolss_win.c +++ b/source4/torture/rpc/spoolss_win.c @@ -405,6 +405,7 @@ static bool test_EnumPrinterDataEx(struct torture_context *tctx, { NTSTATUS status; struct spoolss_EnumPrinterDataEx epde; + struct spoolss_PrinterEnumValues *info; uint32_t needed; uint32_t count; @@ -415,13 +416,12 @@ static bool test_EnumPrinterDataEx(struct torture_context *tctx, epde.in.offered = 0; epde.out.needed = &needed; epde.out.count = &count; - epde.out.buffer = talloc_array(tctx, uint8_t, 0); + epde.out.info = &info; status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &epde); torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed."); if (W_ERROR_EQUAL(epde.out.result, WERR_MORE_DATA)) { epde.in.offered = needed; - epde.out.buffer = talloc_array(tctx, uint8_t, needed); status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &epde); torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed."); -- cgit From 342b436691a99fc6c4fb6606e7148e5c7ddd56c1 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 18 Mar 2009 03:00:37 +0100 Subject: s4-smbtorture: fix spoolss_EnumPrinterKey callers in RPC-SPOOLSS-WIN test. Kai, please check. Guenther --- source4/torture/rpc/spoolss_win.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) (limited to 'source4') diff --git a/source4/torture/rpc/spoolss_win.c b/source4/torture/rpc/spoolss_win.c index 5624e68d03f..c50cbfbaee3 100644 --- a/source4/torture/rpc/spoolss_win.c +++ b/source4/torture/rpc/spoolss_win.c @@ -33,7 +33,7 @@ struct test_spoolss_win_context { union spoolss_PrinterInfo *current_info; /* EnumPrinterKeys */ - char *printer_keys; + const char **printer_keys; }; /* This is a convenience function for all OpenPrinterEx calls */ @@ -389,9 +389,7 @@ static bool test_EnumPrinterKey(struct torture_context *tctx, torture_assert_werr_ok(tctx, epk.out.result, "EnumPrinterKey failed"); - convert_string_talloc_convenience(ctx, lp_iconv_convenience(tctx->lp_ctx), CH_UTF16, - CH_UNIX, epk.out.key_buffer, *epk.out.needed, - (void**)&ctx->printer_keys, NULL, false); + ctx->printer_keys = key_buffer; return true; } @@ -458,7 +456,7 @@ static bool test_WinXP(struct torture_context *tctx, struct dcerpc_pipe *p) * code, the unused_handle structures are used for that. */ struct policy_handle unused_handle1, unused_handle2; char *server_name; - char *key_pointer; + uint32_t i; ntvfs_init(tctx->lp_ctx); @@ -533,24 +531,15 @@ static bool test_WinXP(struct torture_context *tctx, struct dcerpc_pipe *p) ret &= test_EnumForms(tctx, p, &handle03, 0); ret &= test_EnumPrinterKey(tctx, p, &handle03, "", ctx); - key_pointer = ctx->printer_keys; - while(*key_pointer != '\0') { - char *end_pointer; - char *key_name; - - for(end_pointer = key_pointer; *end_pointer != '\0'; - ++end_pointer) { - /* Do nothing, just move the pointer */ - } - key_name = talloc_strndup(tctx, key_pointer, - end_pointer - key_pointer); - - ret &= test_EnumPrinterKey(tctx, p, &handle03, key_name, - tmp_ctx); - ret &= test_EnumPrinterDataEx(tctx, p, &handle03, key_name, 0, - WERR_OK); - - key_pointer = ++end_pointer; + + for (i=0; ctx->printer_keys[i] != NULL; i++) { + + ret &= test_EnumPrinterKey(tctx, p, &handle03, + ctx->printer_keys[i], + tmp_ctx); + ret &= test_EnumPrinterDataEx(tctx, p, &handle03, + ctx->printer_keys[i], 0, + WERR_OK); } ret &= test_EnumPrinterDataEx(tctx, p, &handle03, "", 0, -- cgit From 9744a7058c1f4805c9ca12080fd8ccffe3a038b8 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 18 Mar 2009 16:10:11 +0100 Subject: s4-smbtorture: fix spoolss notify test after spoolss_Field changes. Guenther --- source4/torture/rpc/spoolss_notify.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4') diff --git a/source4/torture/rpc/spoolss_notify.c b/source4/torture/rpc/spoolss_notify.c index cb875c9eee7..b7f2d3c4101 100644 --- a/source4/torture/rpc/spoolss_notify.c +++ b/source4/torture/rpc/spoolss_notify.c @@ -254,13 +254,13 @@ static bool test_RFFPCNEx(struct torture_context *tctx, t1.types = talloc_zero_array(tctx, struct spoolss_NotifyOptionType, 2); t1.types[0].type = PRINTER_NOTIFY_TYPE; t1.types[0].count = 1; - t1.types[0].fields = talloc_array(t1.types, enum spoolss_Field, 1); - t1.types[0].fields[0] = SPOOLSS_FIELD_SERVER_NAME; + t1.types[0].fields = talloc_array(t1.types, union spoolss_Field, 1); + t1.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME; t1.types[1].type = JOB_NOTIFY_TYPE; t1.types[1].count = 1; - t1.types[1].fields = talloc_array(t1.types, enum spoolss_Field, 1); - t1.types[1].fields[0] = SPOOLSS_FIELD_PRINTER_NAME; + t1.types[1].fields = talloc_array(t1.types, union spoolss_Field, 1); + t1.types[1].fields[0].field = PRINTER_NOTIFY_FIELD_PRINTER_NAME; r.in.notify_options = &t1; r.in.handle = &handle; -- cgit From 8595f260ebec2bf06d24d68a8c2f96810647156b Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Wed, 18 Mar 2009 10:36:59 -0700 Subject: s4 libcli: Add back Longhorn beta dialect as a constant Also tweak how the dialect array and count is initialized. --- source4/libcli/smb2/connect.c | 7 +++---- source4/libcli/smb2/smb2.h | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'source4') diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 3fd9a38e019..b522a56239b 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -162,7 +162,8 @@ static void continue_socket(struct composite_context *creq) struct smbcli_socket *sock; struct smb2_transport *transport; struct smb2_request *req; - uint16_t dialects[2]; + uint16_t dialects[3] = { SMB2_DIALECT_REVISION, SMB21_DIALECT_REVISION, + SMB2_LONGHORN_BETA_DIALECT_REVISION }; c->status = smbcli_sock_connect_recv(creq, state, &sock); if (!composite_is_ok(c)) return; @@ -171,7 +172,7 @@ static void continue_socket(struct composite_context *creq) if (composite_nomem(transport, c)) return; ZERO_STRUCT(state->negprot); - state->negprot.in.dialect_count = 2; + state->negprot.in.dialect_count = sizeof(dialects) / sizeof(dialects[0]); switch (transport->options.signing) { case SMB_SIGNING_OFF: state->negprot.in.security_mode = 0; @@ -187,8 +188,6 @@ static void continue_socket(struct composite_context *creq) } state->negprot.in.capabilities = 0; unix_to_nt_time(&state->negprot.in.start_time, time(NULL)); - dialects[0] = SMB2_DIALECT_REVISION; - dialects[1] = SMB21_DIALECT_REVISION; state->negprot.in.dialects = dialects; req = smb2_negprot_send(transport, &state->negprot); diff --git a/source4/libcli/smb2/smb2.h b/source4/libcli/smb2/smb2.h index 3cc3ec2f25b..7c07c847403 100644 --- a/source4/libcli/smb2/smb2.h +++ b/source4/libcli/smb2/smb2.h @@ -230,6 +230,7 @@ struct smb2_request { /* the dialects we support */ #define SMB2_DIALECT_REVISION 0x202 #define SMB21_DIALECT_REVISION 0x210 +#define SMB2_LONGHORN_BETA_DIALECT_REVISION 0x0 /* early beta dialect */ /* SMB2 negotiate security_mode */ #define SMB2_NEGOTIATE_SIGNING_ENABLED 0x01 -- cgit From d380c49791d1010d759369cab12d93b6fbd48dc7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 19 Mar 2009 11:23:49 +1100 Subject: use the tevent nesting code to avoid the uid problem in the VFS backend The vfs_unixuid module changes the uid of the process when executing operations on behalf of the user. Within the VFS backend we may rely on semi-async calls, such as winbind calls, which will call the event loop again. To cope with this we need to ensure that while inside those calls we revert the uid to root, then revert back to the connected user when we have finished with the semi-async calls. --- source4/ntvfs/unixuid/vfs_unixuid.c | 66 +++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'source4') diff --git a/source4/ntvfs/unixuid/vfs_unixuid.c b/source4/ntvfs/unixuid/vfs_unixuid.c index db22a85492e..062fa41889f 100644 --- a/source4/ntvfs/unixuid/vfs_unixuid.c +++ b/source4/ntvfs/unixuid/vfs_unixuid.c @@ -26,6 +26,8 @@ #include "auth/auth.h" #include "ntvfs/ntvfs.h" #include "libcli/wbclient/wbclient.h" +#define TEVENT_DEPRECATED +#include struct unixuid_private { struct wbc_context *wbc_ctx; @@ -91,6 +93,64 @@ static NTSTATUS set_unix_security(struct unix_sec_ctx *sec) return NT_STATUS_OK; } +static int unixuid_nesting_level; + +/* + called at the start and end of a tevent nesting loop. Needs to save/restore + unix security context + */ +static int unixuid_event_nesting_hook(struct tevent_context *ev, + void *private_data, + uint32_t level, + bool begin, + void *stack_ptr, + const char *location) +{ + struct unix_sec_ctx *sec_ctx; + + if (unixuid_nesting_level == 0) { + /* we don't need to do anything unless we are nested + inside of a call in this module */ + return 0; + } + + if (begin) { + sec_ctx = save_unix_security(ev); + if (sec_ctx == NULL) { + DEBUG(0,("%s: Failed to save security context\n", location)); + return -1; + } + *(struct unix_sec_ctx **)stack_ptr = sec_ctx; + if (seteuid(0) != 0 || setegid(0) != 0) { + DEBUG(0,("%s: Failed to change to root\n", location)); + return -1; + } + } else { + /* called when we come out of a nesting level */ + NTSTATUS status; + + sec_ctx = *(struct unix_sec_ctx **)stack_ptr; + if (sec_ctx == NULL) { + /* this happens the first time this function + is called, as we install the hook while + inside an event in unixuid_connect() */ + return 0; + } + + sec_ctx = talloc_get_type_abort(sec_ctx, struct unix_sec_ctx); + status = set_unix_security(sec_ctx); + talloc_free(sec_ctx); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("%s: Failed to revert security context (%s)\n", + location, nt_errstr(status))); + return -1; + } + } + + return 0; +} + + /* form a unix_sec_ctx from the current security_token */ @@ -219,7 +279,9 @@ static NTSTATUS unixuid_setup_security(struct ntvfs_module_context *ntvfs, struct unix_sec_ctx *sec; \ status = unixuid_setup_security(ntvfs, req, &sec); \ NT_STATUS_NOT_OK_RETURN(status); \ + unixuid_nesting_level++; \ status = ntvfs_next_##op args; \ + unixuid_nesting_level--; \ status2 = set_unix_security(sec); \ talloc_free(sec); \ if (!NT_STATUS_IS_OK(status2)) smb_panic("Unable to reset security context"); \ @@ -252,6 +314,10 @@ static NTSTATUS unixuid_connect(struct ntvfs_module_context *ntvfs, priv->last_sec_ctx = NULL; priv->last_token = NULL; + tevent_loop_set_nesting_hook(ntvfs->ctx->event_ctx, + unixuid_event_nesting_hook, + &unixuid_nesting_level); + /* we don't use PASS_THRU_REQ here, as the connect operation runs with root privileges. This allows the backends to setup any database links they might need during the connect. */ -- cgit From 2e0e416676f5d67e716f272d3923386c3f0c9524 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Feb 2009 09:10:54 +0100 Subject: lib/tsocket: add generic socket abstraction layer This will replace source4/lib/socket/. metze --- source4/headermap.txt | 2 ++ source4/main.mk | 1 + 2 files changed, 3 insertions(+) (limited to 'source4') diff --git a/source4/headermap.txt b/source4/headermap.txt index 9de5b1cc0cc..d0d0a575d83 100644 --- a/source4/headermap.txt +++ b/source4/headermap.txt @@ -10,6 +10,8 @@ ../lib/util/talloc_stack.h: util/talloc_stack.h ../lib/util/xfile.h: util/xfile.h ../lib/tdr/tdr.h: tdr.h +../lib/tsocket/tsocket.h: tsocket.h +../lib/tsocket/tsocket_internal.h: tsocket_internal.h librpc/rpc/dcerpc.h: dcerpc.h lib/ldb/include/ldb.h: ldb.h lib/ldb/include/ldb_errors.h: ldb_errors.h diff --git a/source4/main.mk b/source4/main.mk index 8ea9727ed3b..a143604f33c 100644 --- a/source4/main.mk +++ b/source4/main.mk @@ -21,6 +21,7 @@ mkinclude ../lib/nss_wrapper/config.mk mkinclude lib/stream/config.mk mkinclude ../lib/util/config.mk mkinclude ../lib/tdr/config.mk +mkinclude ../lib/tsocket/config.mk mkinclude ../lib/crypto/config.mk mkinclude ../lib/torture/config.mk mkinclude lib/basic.mk -- cgit From c600e8ef42c3cb71c03330782f96bfdf71870e0f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 13 Feb 2009 13:13:54 +0100 Subject: s4:cldap: rewrite the cldap library based on tsocket metze --- source4/cldap_server/cldap_server.c | 96 +-- source4/cldap_server/netlogon.c | 23 +- source4/cldap_server/rootdse.c | 13 +- source4/libcli/cldap/cldap.c | 1147 +++++++++++++++++++++++------------ source4/libcli/cldap/cldap.h | 139 ++--- source4/libcli/config.mk | 2 +- source4/libnet/libnet_become_dc.c | 24 +- source4/libnet/libnet_site.c | 10 +- source4/libnet/libnet_unbecome_dc.c | 24 +- source4/torture/ldap/cldap.c | 75 ++- source4/torture/ldap/cldapbench.c | 46 +- source4/torture/rpc/dssync.c | 9 +- 12 files changed, 1002 insertions(+), 606 deletions(-) (limited to 'source4') diff --git a/source4/cldap_server/cldap_server.c b/source4/cldap_server/cldap_server.c index 240f2b1dc23..1a08cd21f90 100644 --- a/source4/cldap_server/cldap_server.c +++ b/source4/cldap_server/cldap_server.c @@ -20,8 +20,8 @@ */ #include "includes.h" +#include #include "libcli/ldap/ldap.h" -#include "lib/socket/socket.h" #include "lib/messaging/irpc.h" #include "smbd/service_task.h" #include "smbd/service.h" @@ -34,50 +34,67 @@ #include "ldb_wrap.h" #include "auth/auth.h" #include "param/param.h" +#include "../lib/tsocket/tsocket.h" /* handle incoming cldap requests */ -static void cldapd_request_handler(struct cldap_socket *cldap, - struct ldap_message *ldap_msg, - struct socket_address *src) +static void cldapd_request_handler(struct cldap_socket *cldap, + void *private_data, + struct cldap_incoming *in) { + struct cldapd_server *cldapd = talloc_get_type(private_data, + struct cldapd_server); struct ldap_SearchRequest *search; - if (ldap_msg->type != LDAP_TAG_SearchRequest) { - DEBUG(0,("Invalid CLDAP request type %d from %s:%d\n", - ldap_msg->type, src->addr, src->port)); - cldap_error_reply(cldap, ldap_msg->messageid, src, + + if (in->ldap_msg->type != LDAP_TAG_SearchRequest) { + DEBUG(0,("Invalid CLDAP request type %d from %s\n", + in->ldap_msg->type, + tsocket_address_string(in->src, in))); + cldap_error_reply(cldap, in->ldap_msg->messageid, in->src, LDAP_OPERATIONS_ERROR, "Invalid CLDAP request"); + talloc_free(in); return; } - search = &ldap_msg->r.SearchRequest; + search = &in->ldap_msg->r.SearchRequest; if (strcmp("", search->basedn) != 0) { - DEBUG(0,("Invalid CLDAP basedn '%s' from %s:%d\n", - search->basedn, src->addr, src->port)); - cldap_error_reply(cldap, ldap_msg->messageid, src, + DEBUG(0,("Invalid CLDAP basedn '%s' from %s\n", + search->basedn, + tsocket_address_string(in->src, in))); + cldap_error_reply(cldap, in->ldap_msg->messageid, in->src, LDAP_OPERATIONS_ERROR, "Invalid CLDAP basedn"); + talloc_free(in); return; } if (search->scope != LDAP_SEARCH_SCOPE_BASE) { - DEBUG(0,("Invalid CLDAP scope %d from %s:%d\n", - search->scope, src->addr, src->port)); - cldap_error_reply(cldap, ldap_msg->messageid, src, + DEBUG(0,("Invalid CLDAP scope %d from %s\n", + search->scope, + tsocket_address_string(in->src, in))); + cldap_error_reply(cldap, in->ldap_msg->messageid, in->src, LDAP_OPERATIONS_ERROR, "Invalid CLDAP scope"); + talloc_free(in); return; } if (search->num_attributes == 1 && strcasecmp(search->attributes[0], "netlogon") == 0) { - cldapd_netlogon_request(cldap, ldap_msg->messageid, - search->tree, src); + cldapd_netlogon_request(cldap, + cldapd, + in, + in->ldap_msg->messageid, + search->tree, + in->src); + talloc_free(in); return; } - cldapd_rootdse_request(cldap, ldap_msg->messageid, - search, src); + cldapd_rootdse_request(cldap, cldapd, in, + in->ldap_msg->messageid, + search, in->src); + talloc_free(in); } @@ -88,28 +105,36 @@ static NTSTATUS cldapd_add_socket(struct cldapd_server *cldapd, struct loadparm_ const char *address) { struct cldap_socket *cldapsock; - struct socket_address *socket_address; + struct tsocket_address *socket_address; NTSTATUS status; - - /* listen for unicasts on the CLDAP port (389) */ - cldapsock = cldap_socket_init(cldapd, cldapd->task->event_ctx, lp_iconv_convenience(cldapd->task->lp_ctx)); - NT_STATUS_HAVE_NO_MEMORY(cldapsock); - - socket_address = socket_address_from_strings(cldapsock, cldapsock->sock->backend_name, - address, lp_cldap_port(lp_ctx)); - if (!socket_address) { - talloc_free(cldapsock); - return NT_STATUS_NO_MEMORY; + int ret; + + ret = tsocket_address_inet_from_strings(cldapd, + "ip", + address, + lp_cldap_port(lp_ctx), + &socket_address); + if (ret != 0) { + status = map_nt_error_from_unix(errno); + DEBUG(0,("invalid address %s:%d - %s:%s\n", + address, lp_cldap_port(lp_ctx), + gai_strerror(ret), nt_errstr(status))); + return status; } - status = socket_listen(cldapsock->sock, socket_address, 0, 0); + /* listen for unicasts on the CLDAP port (389) */ + status = cldap_socket_init(cldapd, + cldapd->task->event_ctx, + socket_address, + NULL, + &cldapsock); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Failed to bind to %s:%d - %s\n", - address, lp_cldap_port(lp_ctx), nt_errstr(status))); - talloc_free(cldapsock); + DEBUG(0,("Failed to bind to %s - %s\n", + tsocket_address_string(socket_address, socket_address), + nt_errstr(status))); + talloc_free(socket_address); return status; } - talloc_free(socket_address); cldap_set_incoming_handler(cldapsock, cldapd_request_handler, cldapd); @@ -117,7 +142,6 @@ static NTSTATUS cldapd_add_socket(struct cldapd_server *cldapd, struct loadparm_ return NT_STATUS_OK; } - /* setup our listening sockets on the configured network interfaces */ diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c index 0df35be6fdd..33c0adc3b18 100644 --- a/source4/cldap_server/netlogon.c +++ b/source4/cldap_server/netlogon.c @@ -24,7 +24,6 @@ #include "lib/ldb/include/ldb.h" #include "lib/ldb/include/ldb_errors.h" #include "lib/events/events.h" -#include "lib/socket/socket.h" #include "smbd/service_task.h" #include "cldap_server/cldap_server.h" #include "librpc/gen_ndr/ndr_misc.h" @@ -36,6 +35,8 @@ #include "system/network.h" #include "lib/socket/netif.h" #include "param/param.h" +#include "../lib/tsocket/tsocket.h" + /* fill in the cldap netlogon union for a given version */ @@ -402,12 +403,13 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx, /* handle incoming cldap requests */ -void cldapd_netlogon_request(struct cldap_socket *cldap, +void cldapd_netlogon_request(struct cldap_socket *cldap, + struct cldapd_server *cldapd, + TALLOC_CTX *tmp_ctx, uint32_t message_id, struct ldb_parse_tree *tree, - struct socket_address *src) + struct tsocket_address *src) { - struct cldapd_server *cldapd = talloc_get_type(cldap->incoming.private_data, struct cldapd_server); int i; const char *domain = NULL; const char *host = NULL; @@ -419,8 +421,6 @@ void cldapd_netlogon_request(struct cldap_socket *cldap, struct netlogon_samlogon_response netlogon; NTSTATUS status = NT_STATUS_INVALID_PARAMETER; - TALLOC_CTX *tmp_ctx = talloc_new(cldap); - if (tree->operation != LDB_OP_AND) goto failed; /* extract the query elements */ @@ -478,24 +478,25 @@ void cldapd_netlogon_request(struct cldap_socket *cldap, domain, host, user, version, domain_guid)); status = fill_netlogon_samlogon_response(cldapd->samctx, tmp_ctx, domain, NULL, NULL, domain_guid, - user, acct_control, src->addr, + user, acct_control, + tsocket_address_inet_addr_string(src, tmp_ctx), version, cldapd->task->lp_ctx, &netlogon); if (!NT_STATUS_IS_OK(status)) { goto failed; } - status = cldap_netlogon_reply(cldap, message_id, src, version, + status = cldap_netlogon_reply(cldap, + lp_iconv_convenience(cldapd->task->lp_ctx), + message_id, src, version, &netlogon); if (!NT_STATUS_IS_OK(status)) { goto failed; } - talloc_free(tmp_ctx); return; failed: DEBUG(2,("cldap netlogon query failed domain=%s host=%s version=%d - %s\n", domain, host, version, nt_errstr(status))); - talloc_free(tmp_ctx); - cldap_empty_reply(cldap, message_id, src); + cldap_empty_reply(cldap, message_id, src); } diff --git a/source4/cldap_server/rootdse.c b/source4/cldap_server/rootdse.c index daa5060d07c..7e867deff29 100644 --- a/source4/cldap_server/rootdse.c +++ b/source4/cldap_server/rootdse.c @@ -20,19 +20,15 @@ */ #include "includes.h" +#include #include "libcli/ldap/ldap.h" #include "lib/ldb/include/ldb.h" #include "lib/ldb/include/ldb_errors.h" -#include "lib/events/events.h" -#include "lib/socket/socket.h" #include "smbd/service_task.h" #include "cldap_server/cldap_server.h" #include "librpc/gen_ndr/ndr_misc.h" #include "dsdb/samdb/samdb.h" -#include "auth/auth.h" #include "ldb_wrap.h" -#include "system/network.h" -#include "lib/socket/netif.h" static void cldapd_rootdse_fill(struct cldapd_server *cldapd, TALLOC_CTX *mem_ctx, @@ -151,15 +147,15 @@ done: handle incoming cldap requests */ void cldapd_rootdse_request(struct cldap_socket *cldap, + struct cldapd_server *cldapd, + TALLOC_CTX *tmp_ctx, uint32_t message_id, struct ldap_SearchRequest *search, - struct socket_address *src) + struct tsocket_address *src) { - struct cldapd_server *cldapd = talloc_get_type(cldap->incoming.private_data, struct cldapd_server); NTSTATUS status; struct cldap_reply reply; struct ldap_Result result; - TALLOC_CTX *tmp_ctx = talloc_new(cldap); ZERO_STRUCT(result); @@ -176,6 +172,5 @@ void cldapd_rootdse_request(struct cldap_socket *cldap, ldb_filter_from_tree(tmp_ctx, search->tree), nt_errstr(status))); } - talloc_free(tmp_ctx); return; } diff --git a/source4/libcli/cldap/cldap.c b/source4/libcli/cldap/cldap.c index b18ba12b1fc..0f2175b42dd 100644 --- a/source4/libcli/cldap/cldap.c +++ b/source4/libcli/cldap/cldap.c @@ -4,6 +4,7 @@ cldap client library Copyright (C) Andrew Tridgell 2005 + Copyright (C) Stefan Metzmacher 2009 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 @@ -32,442 +33,708 @@ */ #include "includes.h" -#include "lib/events/events.h" +#include #include "../lib/util/dlinklist.h" #include "libcli/ldap/ldap.h" #include "libcli/ldap/ldap_ndr.h" #include "libcli/cldap/cldap.h" -#include "lib/socket/socket.h" +#include "../lib/tsocket/tsocket.h" #include "libcli/security/security.h" #include "librpc/gen_ndr/ndr_nbt.h" +#include "../lib/util/asn1.h" +#include "../lib/util/tevent_ntstatus.h" /* - destroy a pending request + context structure for operations on cldap packets */ -static int cldap_request_destructor(struct cldap_request *req) +struct cldap_socket { + /* the low level socket */ + struct tsocket_context *sock; + + /* + * Are we in connected mode, which means + * we get ICMP errors back instead of timing + * out requests. And we can only send requests + * to the connected peer. + */ + bool connected; + + /* + * we allow sync requests only, if the caller + * did not pass an event context to cldap_socket_init() + */ + struct { + bool allow_poll; + struct tevent_context *ctx; + } event; + + /* the queue for outgoing dgrams */ + struct tevent_queue *send_queue; + + /* do we have an async tsocket_recvfrom request pending */ + struct tevent_req *recv_subreq; + + struct { + /* a queue of pending search requests */ + struct cldap_search_state *list; + + /* mapping from message_id to pending request */ + struct idr_context *idr; + } searches; + + /* what to do with incoming request packets */ + struct { + void (*handler)(struct cldap_socket *, + void *private_data, + struct cldap_incoming *); + void *private_data; + } incoming; +}; + +struct cldap_search_state { + struct cldap_search_state *prev, *next; + + struct { + struct cldap_socket *cldap; + } caller; + + int message_id; + + struct { + uint32_t idx; + uint32_t delay; + uint32_t count; + struct tsocket_address *dest; + DATA_BLOB blob; + } request; + + struct { + struct cldap_incoming *in; + struct asn1_data *asn1; + } response; + + struct tevent_req *req; +}; + +static int cldap_socket_destructor(struct cldap_socket *c) { - if (req->state == CLDAP_REQUEST_SEND) { - DLIST_REMOVE(req->cldap->send_queue, req); - } - if (!req->is_reply && req->message_id != 0) { - idr_remove(req->cldap->idr, req->message_id); - req->message_id = 0; + tsocket_disconnect(c->sock); + + while (c->searches.list) { + struct cldap_search_state *s = c->searches.list; + DLIST_REMOVE(c->searches.list, s); + ZERO_STRUCT(s->caller); } + + talloc_free(c->recv_subreq); + talloc_free(c->send_queue); + talloc_free(c->sock); return 0; } -/* - handle recv events on a cldap socket -*/ -static void cldap_socket_recv(struct cldap_socket *cldap) -{ - TALLOC_CTX *tmp_ctx = talloc_new(cldap); - NTSTATUS status; - struct socket_address *src; - DATA_BLOB blob; - size_t nread, dsize; - struct asn1_data *asn1 = asn1_init(tmp_ctx); - struct ldap_message *ldap_msg; - struct cldap_request *req; - - if (!asn1) return; +static void cldap_recvfrom_done(struct tevent_req *subreq); - status = socket_pending(cldap->sock, &dsize); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(tmp_ctx); - return; +static bool cldap_recvfrom_setup(struct cldap_socket *c) +{ + if (c->recv_subreq) { + return true; } - blob = data_blob_talloc(tmp_ctx, NULL, dsize); - if (blob.data == NULL) { - talloc_free(tmp_ctx); - return; + if (!c->searches.list && !c->incoming.handler) { + return true; } - status = socket_recvfrom(cldap->sock, blob.data, blob.length, &nread, - tmp_ctx, &src); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(tmp_ctx); - return; + c->recv_subreq = tsocket_recvfrom_send(c->sock, c); + if (!c->recv_subreq) { + return false; } - blob.length = nread; + tevent_req_set_callback(c->recv_subreq, cldap_recvfrom_done, c); - DEBUG(2,("Received cldap packet of length %d from %s:%d\n", - (int)blob.length, src->addr, src->port)); + return true; +} - if (!asn1_load(asn1, blob)) { - DEBUG(2,("Failed to setup for asn.1 decode\n")); - talloc_free(tmp_ctx); +static void cldap_recvfrom_stop(struct cldap_socket *c) +{ + if (!c->recv_subreq) { return; } - ldap_msg = talloc(tmp_ctx, struct ldap_message); - if (ldap_msg == NULL) { - talloc_free(tmp_ctx); + if (c->searches.list || c->incoming.handler) { return; } - /* this initial decode is used to find the message id */ - status = ldap_decode(asn1, NULL, ldap_msg); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(2,("Failed to decode ldap message: %s\n", nt_errstr(status))); - talloc_free(tmp_ctx); - return; - } - - /* find the pending request */ - req = idr_find(cldap->idr, ldap_msg->messageid); - if (req == NULL) { - if (cldap->incoming.handler) { - cldap->incoming.handler(cldap, ldap_msg, src); - } else { - DEBUG(2,("Mismatched cldap reply %u from %s:%d\n", - ldap_msg->messageid, src->addr, src->port)); - } - talloc_free(tmp_ctx); - return; - } + talloc_free(c->recv_subreq); + c->recv_subreq = NULL; +} - req->asn1 = talloc_steal(req, asn1); - req->asn1->ofs = 0; +static void cldap_socket_recv_dgram(struct cldap_socket *c, + struct cldap_incoming *in); - req->state = CLDAP_REQUEST_DONE; - talloc_free(req->te); +static void cldap_recvfrom_done(struct tevent_req *subreq) +{ + struct cldap_socket *c = tevent_req_callback_data(subreq, + struct cldap_socket); + struct cldap_incoming *in = NULL; + ssize_t ret; - talloc_free(tmp_ctx); + c->recv_subreq = NULL; - if (req->async.fn) { - req->async.fn(req); + in = talloc_zero(c, struct cldap_incoming); + if (!in) { + goto nomem; } -} - -/* - handle request timeouts -*/ -static void cldap_request_timeout(struct tevent_context *event_ctx, - struct tevent_timer *te, struct timeval t, - void *private_data) -{ - struct cldap_request *req = talloc_get_type(private_data, struct cldap_request); - - /* possibly try again */ - if (req->num_retries != 0) { - size_t len = req->encoded.length; - req->num_retries--; + ret = tsocket_recvfrom_recv(subreq, + &in->recv_errno, + in, + &in->buf, + &in->src); + talloc_free(subreq); + subreq = NULL; + if (ret >= 0) { + in->len = ret; + } + if (ret == -1 && in->recv_errno == 0) { + in->recv_errno = EIO; + } - socket_sendto(req->cldap->sock, &req->encoded, &len, - req->dest); + /* this function should free or steal 'in' */ + cldap_socket_recv_dgram(c, in); + in = NULL; - req->te = event_add_timed(req->cldap->event_ctx, req, - timeval_current_ofs(req->timeout, 0), - cldap_request_timeout, req); - return; + if (!cldap_recvfrom_setup(c)) { + goto nomem; } - req->state = CLDAP_REQUEST_ERROR; - req->status = NT_STATUS_IO_TIMEOUT; - if (req->async.fn) { - req->async.fn(req); - } + return; + +nomem: + talloc_free(subreq); + talloc_free(in); + /*TODO: call a dead socket handler */ + return; } /* - handle send events on a cldap socket + handle recv events on a cldap socket */ -static void cldap_socket_send(struct cldap_socket *cldap) +static void cldap_socket_recv_dgram(struct cldap_socket *c, + struct cldap_incoming *in) { - struct cldap_request *req; + DATA_BLOB blob; + struct asn1_data *asn1; + void *p; + struct cldap_search_state *search; NTSTATUS status; - while ((req = cldap->send_queue)) { - size_t len; - - len = req->encoded.length; - status = socket_sendto(cldap->sock, &req->encoded, &len, - req->dest); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(0,("Failed to send cldap request of length %u to %s:%d\n", - (unsigned)req->encoded.length, req->dest->addr, req->dest->port)); - DLIST_REMOVE(cldap->send_queue, req); - req->state = CLDAP_REQUEST_ERROR; - req->status = status; - if (req->async.fn) { - req->async.fn(req); - } - continue; - } + if (in->recv_errno != 0) { + goto error; + } - if (!NT_STATUS_IS_OK(status)) return; + blob = data_blob_const(in->buf, in->len); - DLIST_REMOVE(cldap->send_queue, req); + asn1 = asn1_init(in); + if (!asn1) { + goto nomem; + } - if (req->is_reply) { - talloc_free(req); - } else { - req->state = CLDAP_REQUEST_WAIT; + if (!asn1_load(asn1, blob)) { + goto nomem; + } - req->te = event_add_timed(cldap->event_ctx, req, - timeval_current_ofs(req->timeout, 0), - cldap_request_timeout, req); + in->ldap_msg = talloc(in, struct ldap_message); + if (in->ldap_msg == NULL) { + goto nomem; + } - EVENT_FD_READABLE(cldap->fde); - } + /* this initial decode is used to find the message id */ + status = ldap_decode(asn1, NULL, in->ldap_msg); + if (!NT_STATUS_IS_OK(status)) { + goto nterror; } - EVENT_FD_NOT_WRITEABLE(cldap->fde); - return; -} + /* find the pending request */ + p = idr_find(c->searches.idr, in->ldap_msg->messageid); + if (p == NULL) { + if (!c->incoming.handler) { + goto done; + } + /* this function should free or steal 'in' */ + c->incoming.handler(c, c->incoming.private_data, in); + return; + } -/* - handle fd events on a cldap_socket -*/ -static void cldap_socket_handler(struct tevent_context *ev, struct tevent_fd *fde, - uint16_t flags, void *private_data) -{ - struct cldap_socket *cldap = talloc_get_type(private_data, struct cldap_socket); - if (flags & EVENT_FD_WRITE) { - cldap_socket_send(cldap); - } - if (flags & EVENT_FD_READ) { - cldap_socket_recv(cldap); + search = talloc_get_type(p, struct cldap_search_state); + search->response.in = talloc_move(search, &in); + search->response.asn1 = asn1; + search->response.asn1->ofs = 0; + + tevent_req_done(search->req); + goto done; + +nomem: + in->recv_errno = ENOMEM; +error: + status = map_nt_error_from_unix(in->recv_errno); +nterror: + /* in connected mode the first pending search gets the error */ + if (!c->connected) { + /* otherwise we just ignore the error */ + goto done; } + if (!c->searches.list) { + goto done; + } + tevent_req_nterror(c->searches.list->req, status); +done: + talloc_free(in); } /* - initialise a cldap_socket. The event_ctx is optional, if provided - then operations will use that event context + initialise a cldap_sock */ -struct cldap_socket *cldap_socket_init(TALLOC_CTX *mem_ctx, - struct tevent_context *event_ctx, - struct smb_iconv_convenience *iconv_convenience) +NTSTATUS cldap_socket_init(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const struct tsocket_address *local_addr, + const struct tsocket_address *remote_addr, + struct cldap_socket **_cldap) { - struct cldap_socket *cldap; + struct cldap_socket *c = NULL; + struct tsocket_address *any = NULL; NTSTATUS status; + int ret; - cldap = talloc(mem_ctx, struct cldap_socket); - if (cldap == NULL) goto failed; + c = talloc_zero(mem_ctx, struct cldap_socket); + if (!c) { + goto nomem; + } - cldap->event_ctx = talloc_reference(cldap, event_ctx); - if (cldap->event_ctx == NULL) goto failed; + if (!ev) { + ev = tevent_context_init(c); + if (!ev) { + goto nomem; + } + c->event.allow_poll = true; + } + c->event.ctx = ev; + + if (!local_addr) { + ret = tsocket_address_inet_from_strings(c, "ipv4", + NULL, 0, + &any); + if (ret != 0) { + status = map_nt_error_from_unix(errno); + goto nterror; + } + local_addr = any; + } - cldap->idr = idr_init(cldap); - if (cldap->idr == NULL) goto failed; + c->searches.idr = idr_init(c); + if (!c->searches.idr) { + goto nomem; + } - status = socket_create("ip", SOCKET_TYPE_DGRAM, &cldap->sock, 0); - if (!NT_STATUS_IS_OK(status)) goto failed; + ret = tsocket_address_create_socket(local_addr, + TSOCKET_TYPE_DGRAM, + c, &c->sock); + if (ret != 0) { + status = map_nt_error_from_unix(errno); + goto nterror; + } + talloc_free(any); - talloc_steal(cldap, cldap->sock); + tsocket_set_event_context(c->sock, c->event.ctx); - cldap->fde = event_add_fd(cldap->event_ctx, cldap, - socket_get_fd(cldap->sock), 0, - cldap_socket_handler, cldap); + if (remote_addr) { + ret = tsocket_connect(c->sock, remote_addr); + if (ret != 0) { + status = map_nt_error_from_unix(errno); + goto nterror; + } + c->connected = true; + } - cldap->send_queue = NULL; - cldap->incoming.handler = NULL; - cldap->iconv_convenience = iconv_convenience; - - return cldap; + c->send_queue = tevent_queue_create(c, "cldap_send_queue"); + if (!c->send_queue) { + goto nomem; + } -failed: - talloc_free(cldap); - return NULL; -} + talloc_set_destructor(c, cldap_socket_destructor); + + *_cldap = c; + return NT_STATUS_OK; +nomem: + status = NT_STATUS_NO_MEMORY; +nterror: + talloc_free(c); + return status; +} /* setup a handler for incoming requests */ -NTSTATUS cldap_set_incoming_handler(struct cldap_socket *cldap, - void (*handler)(struct cldap_socket *, struct ldap_message *, - struct socket_address *), - void *private_data) +NTSTATUS cldap_set_incoming_handler(struct cldap_socket *c, + void (*handler)(struct cldap_socket *, + void *private_data, + struct cldap_incoming *), + void *private_data) { - cldap->incoming.handler = handler; - cldap->incoming.private_data = private_data; - EVENT_FD_READABLE(cldap->fde); + if (c->connected) { + return NT_STATUS_PIPE_CONNECTED; + } + + /* if sync requests are allowed, we don't allow an incoming handler */ + if (c->event.allow_poll) { + return NT_STATUS_INVALID_PIPE_STATE; + } + + c->incoming.handler = handler; + c->incoming.private_data = private_data; + + if (!cldap_recvfrom_setup(c)) { + ZERO_STRUCT(c->incoming); + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; } +struct cldap_reply_state { + struct tsocket_address *dest; + DATA_BLOB blob; +}; + +static void cldap_reply_state_destroy(struct tevent_req *req); + /* - queue a cldap request for send + queue a cldap reply for send */ -struct cldap_request *cldap_search_send(struct cldap_socket *cldap, - struct cldap_search *io) +NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io) { + struct cldap_reply_state *state = NULL; struct ldap_message *msg; - struct cldap_request *req; - struct ldap_SearchRequest *search; + DATA_BLOB blob1, blob2; + NTSTATUS status; + struct tevent_req *req; - req = talloc_zero(cldap, struct cldap_request); - if (req == NULL) goto failed; + if (cldap->connected) { + return NT_STATUS_PIPE_CONNECTED; + } - req->cldap = cldap; - req->state = CLDAP_REQUEST_SEND; - req->timeout = io->in.timeout; - req->num_retries = io->in.retries; - req->is_reply = false; - req->asn1 = asn1_init(req); - if (!req->asn1) { - goto failed; + if (!io->dest) { + return NT_STATUS_INVALID_ADDRESS; } - req->dest = socket_address_from_strings(req, cldap->sock->backend_name, - io->in.dest_address, - io->in.dest_port); - if (!req->dest) goto failed; + state = talloc(cldap, struct cldap_reply_state); + NT_STATUS_HAVE_NO_MEMORY(state); - req->message_id = idr_get_new_random(cldap->idr, req, UINT16_MAX); - if (req->message_id == -1) goto failed; + state->dest = tsocket_address_copy(io->dest, state); + if (!state->dest) { + goto nomem; + } - talloc_set_destructor(req, cldap_request_destructor); + msg = talloc(state, struct ldap_message); + if (!msg) { + goto nomem; + } - msg = talloc(req, struct ldap_message); - if (msg == NULL) goto failed; - msg->messageid = req->message_id; - msg->type = LDAP_TAG_SearchRequest; + msg->messageid = io->messageid; msg->controls = NULL; - search = &msg->r.SearchRequest; - search->basedn = ""; - search->scope = LDAP_SEARCH_SCOPE_BASE; - search->deref = LDAP_DEREFERENCE_NEVER; - search->timelimit = 0; - search->sizelimit = 0; - search->attributesonly = false; - search->num_attributes = str_list_length(io->in.attributes); - search->attributes = io->in.attributes; - search->tree = ldb_parse_tree(req, io->in.filter); - if (search->tree == NULL) { - goto failed; + if (io->response) { + msg->type = LDAP_TAG_SearchResultEntry; + msg->r.SearchResultEntry = *io->response; + + if (!ldap_encode(msg, NULL, &blob1, state)) { + status = NT_STATUS_INVALID_PARAMETER; + goto failed; + } + } else { + blob1 = data_blob(NULL, 0); } - if (!ldap_encode(msg, NULL, &req->encoded, req)) { - DEBUG(0,("Failed to encode cldap message to %s:%d\n", - req->dest->addr, req->dest->port)); + msg->type = LDAP_TAG_SearchResultDone; + msg->r.SearchResultDone = *io->result; + + if (!ldap_encode(msg, NULL, &blob2, state)) { + status = NT_STATUS_INVALID_PARAMETER; goto failed; } + talloc_free(msg); - DLIST_ADD_END(cldap->send_queue, req, struct cldap_request *); + state->blob = data_blob_talloc(state, NULL, blob1.length + blob2.length); + if (!state->blob.data) { + goto nomem; + } - EVENT_FD_WRITEABLE(cldap->fde); + memcpy(state->blob.data, blob1.data, blob1.length); + memcpy(state->blob.data+blob1.length, blob2.data, blob2.length); + data_blob_free(&blob1); + data_blob_free(&blob2); + + req = tsocket_sendto_queue_send(state, + cldap->sock, + cldap->send_queue, + state->blob.data, + state->blob.length, + state->dest); + if (!req) { + goto nomem; + } + /* the callback will just free the state, as we don't need a result */ + tevent_req_set_callback(req, cldap_reply_state_destroy, state); - return req; + return NT_STATUS_OK; +nomem: + status = NT_STATUS_NO_MEMORY; failed: + talloc_free(state); + return status; +} + +static void cldap_reply_state_destroy(struct tevent_req *req) +{ + struct cldap_reply_state *state = tevent_req_callback_data(req, + struct cldap_reply_state); + + /* we don't want to know the result here, we just free the state */ talloc_free(req); - return NULL; + talloc_free(state); +} + +static int cldap_search_state_destructor(struct cldap_search_state *s) +{ + if (s->caller.cldap) { + DLIST_REMOVE(s->caller.cldap->searches.list, s); + cldap_recvfrom_stop(s->caller.cldap); + ZERO_STRUCT(s->caller); + } + + return 0; } +static void cldap_search_state_queue_done(struct tevent_req *subreq); +static void cldap_search_state_wakeup_done(struct tevent_req *subreq); /* queue a cldap reply for send */ -NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io) +struct tevent_req *cldap_search_send(TALLOC_CTX *mem_ctx, + struct cldap_socket *cldap, + const struct cldap_search *io) { + struct tevent_req *req, *subreq; + struct cldap_search_state *state = NULL; struct ldap_message *msg; - struct cldap_request *req; - DATA_BLOB blob1, blob2; - NTSTATUS status = NT_STATUS_NO_MEMORY; + struct ldap_SearchRequest *search; + struct timeval now; + struct timeval end; + uint32_t i; + int ret; + + req = tevent_req_create(mem_ctx, &state, + struct cldap_search_state); + if (!req) { + return NULL; + } + state->req = req; + state->caller.cldap = cldap; + + if (io->in.dest_address) { + if (cldap->connected) { + tevent_req_nterror(req, NT_STATUS_PIPE_CONNECTED); + goto post; + } + ret = tsocket_address_inet_from_strings(state, + "ipv4", + io->in.dest_address, + io->in.dest_port, + &state->request.dest); + if (ret != 0) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + goto post; + } + } else { + if (!cldap->connected) { + tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS); + goto post; + } + state->request.dest = NULL; + } - req = talloc_zero(cldap, struct cldap_request); - if (req == NULL) goto failed; + state->message_id = idr_get_new_random(cldap->searches.idr, + state, UINT16_MAX); + if (state->message_id == -1) { + tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES); + goto post; + } - req->cldap = cldap; - req->state = CLDAP_REQUEST_SEND; - req->is_reply = true; - req->asn1 = asn1_init(req); - if (!req->asn1) { - goto failed; + msg = talloc(state, struct ldap_message); + if (tevent_req_nomem(msg, req)) { + goto post; } - req->dest = io->dest; - if (talloc_reference(req, io->dest) == NULL) goto failed; + msg->messageid = state->message_id; + msg->type = LDAP_TAG_SearchRequest; + msg->controls = NULL; + search = &msg->r.SearchRequest; - talloc_set_destructor(req, cldap_request_destructor); + search->basedn = ""; + search->scope = LDAP_SEARCH_SCOPE_BASE; + search->deref = LDAP_DEREFERENCE_NEVER; + search->timelimit = 0; + search->sizelimit = 0; + search->attributesonly = false; + search->num_attributes = str_list_length(io->in.attributes); + search->attributes = io->in.attributes; + search->tree = ldb_parse_tree(msg, io->in.filter); + if (tevent_req_nomem(search->tree, req)) { + goto post; + } - msg = talloc(req, struct ldap_message); - if (msg == NULL) goto failed; - msg->messageid = io->messageid; - msg->controls = NULL; - - if (io->response) { - msg->type = LDAP_TAG_SearchResultEntry; - msg->r.SearchResultEntry = *io->response; + if (!ldap_encode(msg, NULL, &state->request.blob, state)) { + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + goto post; + } + talloc_free(msg); + + state->request.idx = 0; + state->request.delay = 10*1000*1000; + state->request.count = 3; + if (io->in.timeout > 0) { + state->request.delay = io->in.timeout * 1000 * 1000; + state->request.count = io->in.retries + 1; + } - if (!ldap_encode(msg, NULL, &blob1, req)) { - DEBUG(0,("Failed to encode cldap message to %s:%d\n", - req->dest->addr, req->dest->port)); - status = NT_STATUS_INVALID_PARAMETER; - goto failed; - } - } else { - blob1 = data_blob(NULL, 0); + now = tevent_timeval_current(); + end = now; + for (i = 0; i < state->request.count; i++) { + end = tevent_timeval_add(&end, 0, state->request.delay); } - msg->type = LDAP_TAG_SearchResultDone; - msg->r.SearchResultDone = *io->result; + if (!tevent_req_set_endtime(req, state->caller.cldap->event.ctx, end)) { + tevent_req_nomem(NULL, req); + goto post; + } - if (!ldap_encode(msg, NULL, &blob2, req)) { - DEBUG(0,("Failed to encode cldap message to %s:%d\n", - req->dest->addr, req->dest->port)); - status = NT_STATUS_INVALID_PARAMETER; - goto failed; + subreq = tsocket_sendto_queue_send(state, + state->caller.cldap->sock, + state->caller.cldap->send_queue, + state->request.blob.data, + state->request.blob.length, + state->request.dest); + if (tevent_req_nomem(subreq, req)) { + goto post; } + tevent_req_set_callback(subreq, cldap_search_state_queue_done, req); - req->encoded = data_blob_talloc(req, NULL, blob1.length + blob2.length); - if (req->encoded.data == NULL) goto failed; + DLIST_ADD_END(cldap->searches.list, state, struct cldap_search_state *); + talloc_set_destructor(state, cldap_search_state_destructor); - memcpy(req->encoded.data, blob1.data, blob1.length); - memcpy(req->encoded.data+blob1.length, blob2.data, blob2.length); + return req; - DLIST_ADD_END(cldap->send_queue, req, struct cldap_request *); + post: + return tevent_req_post(req, cldap->event.ctx); +} - EVENT_FD_WRITEABLE(cldap->fde); +static void cldap_search_state_queue_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct cldap_search_state *state = tevent_req_data(req, + struct cldap_search_state); + ssize_t ret; + int sys_errno = 0; + struct timeval next; + + ret = tsocket_sendto_queue_recv(subreq, &sys_errno); + talloc_free(subreq); + if (ret == -1) { + NTSTATUS status; + status = map_nt_error_from_unix(sys_errno); + DLIST_REMOVE(state->caller.cldap->searches.list, state); + ZERO_STRUCT(state->caller.cldap); + tevent_req_nterror(req, status); + return; + } - return NT_STATUS_OK; + state->request.idx++; -failed: - talloc_free(req); - return status; + /* wait for incoming traffic */ + if (!cldap_recvfrom_setup(state->caller.cldap)) { + tevent_req_nomem(NULL, req); + return; + } + + if (state->request.idx > state->request.count) { + /* we just wait for the response or a timeout */ + return; + } + + next = tevent_timeval_current_ofs(0, state->request.delay); + subreq = tevent_wakeup_send(state, + state->caller.cldap->event.ctx, + next); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, cldap_search_state_wakeup_done, req); +} + +static void cldap_search_state_wakeup_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct cldap_search_state *state = tevent_req_data(req, + struct cldap_search_state); + bool ok; + + ok = tevent_wakeup_recv(subreq); + talloc_free(subreq); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + + subreq = tsocket_sendto_queue_send(state, + state->caller.cldap->sock, + state->caller.cldap->send_queue, + state->request.blob.data, + state->request.blob.length, + state->request.dest); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, cldap_search_state_queue_done, req); } /* receive a cldap reply */ -NTSTATUS cldap_search_recv(struct cldap_request *req, - TALLOC_CTX *mem_ctx, +NTSTATUS cldap_search_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, struct cldap_search *io) { + struct cldap_search_state *state = tevent_req_data(req, + struct cldap_search_state); struct ldap_message *ldap_msg; NTSTATUS status; - if (req == NULL) { - return NT_STATUS_NO_MEMORY; - } - - while (req->state < CLDAP_REQUEST_DONE) { - if (event_loop_once(req->cldap->event_ctx) != 0) { - talloc_free(req); - return NT_STATUS_UNEXPECTED_NETWORK_ERROR; - } - } - - if (req->state == CLDAP_REQUEST_ERROR) { - status = req->status; - talloc_free(req); - return status; + if (tevent_req_is_nterror(req, &status)) { + goto failed; } ldap_msg = talloc(mem_ctx, struct ldap_message); - NT_STATUS_HAVE_NO_MEMORY(ldap_msg); + if (!ldap_msg) { + goto nomem; + } - status = ldap_decode(req->asn1, NULL, ldap_msg); + status = ldap_decode(state->response.asn1, NULL, ldap_msg); if (!NT_STATUS_IS_OK(status)) { - DEBUG(2,("Failed to decode cldap search reply: %s\n", nt_errstr(status))); - talloc_free(req); - return status; + goto failed; } ZERO_STRUCT(io->out); @@ -475,167 +742,283 @@ NTSTATUS cldap_search_recv(struct cldap_request *req, /* the first possible form has a search result in first place */ if (ldap_msg->type == LDAP_TAG_SearchResultEntry) { io->out.response = talloc(mem_ctx, struct ldap_SearchResEntry); - NT_STATUS_HAVE_NO_MEMORY(io->out.response); + if (!io->out.response) { + goto nomem; + } *io->out.response = ldap_msg->r.SearchResultEntry; /* decode the 2nd part */ - status = ldap_decode(req->asn1, NULL, ldap_msg); + status = ldap_decode(state->response.asn1, NULL, ldap_msg); if (!NT_STATUS_IS_OK(status)) { - DEBUG(2,("Failed to decode cldap search result entry: %s\n", nt_errstr(status))); - talloc_free(req); - return status; + goto failed; } } if (ldap_msg->type != LDAP_TAG_SearchResultDone) { - talloc_free(req); - return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + status = NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); + goto failed; } io->out.result = talloc(mem_ctx, struct ldap_Result); - NT_STATUS_HAVE_NO_MEMORY(io->out.result); + if (!io->out.result) { + goto nomem; + } *io->out.result = ldap_msg->r.SearchResultDone; - talloc_free(req); - if (io->out.result->resultcode != LDAP_SUCCESS) { - return NT_STATUS_LDAP(io->out.result->resultcode); + status = NT_STATUS_LDAP(io->out.result->resultcode); + goto failed; } + + tevent_req_received(req); return NT_STATUS_OK; + +nomem: + status = NT_STATUS_NO_MEMORY; +failed: + tevent_req_received(req); + return status; } /* synchronous cldap search */ -NTSTATUS cldap_search(struct cldap_socket *cldap, - TALLOC_CTX *mem_ctx, +NTSTATUS cldap_search(struct cldap_socket *cldap, + TALLOC_CTX *mem_ctx, struct cldap_search *io) { - struct cldap_request *req = cldap_search_send(cldap, io); - return cldap_search_recv(req, mem_ctx, io); -} + struct tevent_req *req; + NTSTATUS status; + + if (!cldap->event.allow_poll) { + return NT_STATUS_INVALID_PIPE_STATE; + } + + if (cldap->searches.list) { + return NT_STATUS_PIPE_BUSY; + } + req = cldap_search_send(mem_ctx, cldap, io); + NT_STATUS_HAVE_NO_MEMORY(req); + if (!tevent_req_poll(req, cldap->event.ctx)) { + talloc_free(req); + return NT_STATUS_INTERNAL_ERROR; + } + status = cldap_search_recv(req, mem_ctx, io); + talloc_free(req); + + return status; +} + +struct cldap_netlogon_state { + struct cldap_search search; +}; + +static void cldap_netlogon_state_done(struct tevent_req *subreq); /* queue a cldap netlogon for send */ -struct cldap_request *cldap_netlogon_send(struct cldap_socket *cldap, - struct cldap_netlogon *io) +struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx, + struct cldap_socket *cldap, + const struct cldap_netlogon *io) { - struct cldap_search search; + struct tevent_req *req, *subreq; + struct cldap_netlogon_state *state; char *filter; - struct cldap_request *req; - const char *attr[] = { "NetLogon", NULL }; - TALLOC_CTX *tmp_ctx = talloc_new(cldap); + static const char * const attr[] = { "NetLogon", NULL }; + + req = tevent_req_create(mem_ctx, &state, + struct cldap_netlogon_state); + if (!req) { + return NULL; + } - filter = talloc_asprintf(tmp_ctx, "(&(NtVer=%s)", - ldap_encode_ndr_uint32(tmp_ctx, io->in.version)); - if (filter == NULL) goto failed; + filter = talloc_asprintf(state, "(&(NtVer=%s)", + ldap_encode_ndr_uint32(state, io->in.version)); + if (tevent_req_nomem(filter, req)) { + goto post; + } if (io->in.user) { filter = talloc_asprintf_append_buffer(filter, "(User=%s)", io->in.user); - if (filter == NULL) goto failed; + if (tevent_req_nomem(filter, req)) { + goto post; + } } if (io->in.host) { filter = talloc_asprintf_append_buffer(filter, "(Host=%s)", io->in.host); - if (filter == NULL) goto failed; + if (tevent_req_nomem(filter, req)) { + goto post; + } } if (io->in.realm) { filter = talloc_asprintf_append_buffer(filter, "(DnsDomain=%s)", io->in.realm); - if (filter == NULL) goto failed; + if (tevent_req_nomem(filter, req)) { + goto post; + } } if (io->in.acct_control != -1) { filter = talloc_asprintf_append_buffer(filter, "(AAC=%s)", - ldap_encode_ndr_uint32(tmp_ctx, io->in.acct_control)); - if (filter == NULL) goto failed; + ldap_encode_ndr_uint32(state, io->in.acct_control)); + if (tevent_req_nomem(filter, req)) { + goto post; + } } if (io->in.domain_sid) { - struct dom_sid *sid = dom_sid_parse_talloc(tmp_ctx, io->in.domain_sid); - if (sid == NULL) goto failed; + struct dom_sid *sid = dom_sid_parse_talloc(state, io->in.domain_sid); + if (tevent_req_nomem(sid, req)) { + goto post; + } filter = talloc_asprintf_append_buffer(filter, "(domainSid=%s)", - ldap_encode_ndr_dom_sid(tmp_ctx, sid)); - if (filter == NULL) goto failed; + ldap_encode_ndr_dom_sid(state, sid)); + if (tevent_req_nomem(filter, req)) { + goto post; + } } if (io->in.domain_guid) { struct GUID guid; NTSTATUS status; status = GUID_from_string(io->in.domain_guid, &guid); - if (!NT_STATUS_IS_OK(status)) goto failed; + if (tevent_req_nterror(req, status)) { + goto post; + } filter = talloc_asprintf_append_buffer(filter, "(DomainGuid=%s)", - ldap_encode_ndr_GUID(tmp_ctx, &guid)); - if (filter == NULL) goto failed; + ldap_encode_ndr_GUID(state, &guid)); + if (tevent_req_nomem(filter, req)) { + goto post; + } } filter = talloc_asprintf_append_buffer(filter, ")"); - if (filter == NULL) goto failed; - - search.in.dest_address = io->in.dest_address; - search.in.dest_port = io->in.dest_port; - search.in.filter = filter; - search.in.attributes = attr; - search.in.timeout = 2; - search.in.retries = 2; + if (tevent_req_nomem(filter, req)) { + goto post; + } - req = cldap_search_send(cldap, &search); + if (io->in.dest_address) { + state->search.in.dest_address = talloc_strdup(state, + io->in.dest_address); + if (tevent_req_nomem(state->search.in.dest_address, req)) { + goto post; + } + state->search.in.dest_port = io->in.dest_port; + } else { + state->search.in.dest_address = NULL; + state->search.in.dest_port = 0; + } + state->search.in.filter = filter; + state->search.in.attributes = attr; + state->search.in.timeout = 2; + state->search.in.retries = 2; + + subreq = cldap_search_send(state, cldap, &state->search); + if (tevent_req_nomem(subreq, req)) { + goto post; + } + tevent_req_set_callback(subreq, cldap_netlogon_state_done, req); - talloc_free(tmp_ctx); return req; -failed: - talloc_free(tmp_ctx); - return NULL; +post: + return tevent_req_post(req, cldap->event.ctx); } +static void cldap_netlogon_state_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct cldap_netlogon_state *state = tevent_req_data(req, + struct cldap_netlogon_state); + NTSTATUS status; + + status = cldap_search_recv(subreq, state, &state->search); + talloc_free(subreq); + + if (tevent_req_nterror(req, status)) { + return; + } + + tevent_req_done(req); +} /* receive a cldap netlogon reply */ -NTSTATUS cldap_netlogon_recv(struct cldap_request *req, - TALLOC_CTX *mem_ctx, +NTSTATUS cldap_netlogon_recv(struct tevent_req *req, + struct smb_iconv_convenience *iconv_convenience, + TALLOC_CTX *mem_ctx, struct cldap_netlogon *io) { + struct cldap_netlogon_state *state = tevent_req_data(req, + struct cldap_netlogon_state); NTSTATUS status; - struct cldap_search search; - struct cldap_socket *cldap; DATA_BLOB *data; - cldap = req->cldap; - - status = cldap_search_recv(req, mem_ctx, &search); - if (!NT_STATUS_IS_OK(status)) { - return status; + if (tevent_req_is_nterror(req, &status)) { + goto failed; } - if (search.out.response == NULL) { - return NT_STATUS_NOT_FOUND; + + if (state->search.out.response == NULL) { + status = NT_STATUS_NOT_FOUND; + goto failed; } - if (search.out.response->num_attributes != 1 || - strcasecmp(search.out.response->attributes[0].name, "netlogon") != 0 || - search.out.response->attributes[0].num_values != 1 || - search.out.response->attributes[0].values->length < 2) { - return NT_STATUS_UNEXPECTED_NETWORK_ERROR; + if (state->search.out.response->num_attributes != 1 || + strcasecmp(state->search.out.response->attributes[0].name, "netlogon") != 0 || + state->search.out.response->attributes[0].num_values != 1 || + state->search.out.response->attributes[0].values->length < 2) { + status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; + goto failed; } - data = search.out.response->attributes[0].values; + data = state->search.out.response->attributes[0].values; - status = pull_netlogon_samlogon_response(data, mem_ctx, req->cldap->iconv_convenience, + status = pull_netlogon_samlogon_response(data, mem_ctx, + iconv_convenience, &io->out.netlogon); if (!NT_STATUS_IS_OK(status)) { - return status; + goto failed; } - + if (io->in.map_response) { map_netlogon_samlogon_response(&io->out.netlogon); } - return NT_STATUS_OK; + + status = NT_STATUS_OK; +failed: + tevent_req_received(req); + return status; } /* sync cldap netlogon search */ -NTSTATUS cldap_netlogon(struct cldap_socket *cldap, - TALLOC_CTX *mem_ctx, struct cldap_netlogon *io) +NTSTATUS cldap_netlogon(struct cldap_socket *cldap, + struct smb_iconv_convenience *iconv_convenience, + TALLOC_CTX *mem_ctx, + struct cldap_netlogon *io) { - struct cldap_request *req = cldap_netlogon_send(cldap, io); - return cldap_netlogon_recv(req, mem_ctx, io); + struct tevent_req *req; + NTSTATUS status; + + if (!cldap->event.allow_poll) { + return NT_STATUS_INVALID_PIPE_STATE; + } + + if (cldap->searches.list) { + return NT_STATUS_PIPE_BUSY; + } + + req = cldap_netlogon_send(mem_ctx, cldap, io); + NT_STATUS_HAVE_NO_MEMORY(req); + + if (!tevent_req_poll(req, cldap->event.ctx)) { + talloc_free(req); + return NT_STATUS_INTERNAL_ERROR; + } + + status = cldap_netlogon_recv(req, iconv_convenience, mem_ctx, io); + talloc_free(req); + + return status; } @@ -643,16 +1026,16 @@ NTSTATUS cldap_netlogon(struct cldap_socket *cldap, send an empty reply (used on any error, so the client doesn't keep waiting or send the bad request again) */ -NTSTATUS cldap_empty_reply(struct cldap_socket *cldap, +NTSTATUS cldap_empty_reply(struct cldap_socket *cldap, uint32_t message_id, - struct socket_address *src) + struct tsocket_address *dest) { NTSTATUS status; struct cldap_reply reply; struct ldap_Result result; reply.messageid = message_id; - reply.dest = src; + reply.dest = dest; reply.response = NULL; reply.result = &result; @@ -667,9 +1050,9 @@ NTSTATUS cldap_empty_reply(struct cldap_socket *cldap, send an error reply (used on any error, so the client doesn't keep waiting or send the bad request again) */ -NTSTATUS cldap_error_reply(struct cldap_socket *cldap, +NTSTATUS cldap_error_reply(struct cldap_socket *cldap, uint32_t message_id, - struct socket_address *src, + struct tsocket_address *dest, int resultcode, const char *errormessage) { @@ -678,7 +1061,7 @@ NTSTATUS cldap_error_reply(struct cldap_socket *cldap, struct ldap_Result result; reply.messageid = message_id; - reply.dest = src; + reply.dest = dest; reply.response = NULL; reply.result = &result; @@ -695,9 +1078,10 @@ NTSTATUS cldap_error_reply(struct cldap_socket *cldap, /* send a netlogon reply */ -NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, +NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, + struct smb_iconv_convenience *iconv_convenience, uint32_t message_id, - struct socket_address *src, + struct tsocket_address *dest, uint32_t version, struct netlogon_samlogon_response *netlogon) { @@ -708,13 +1092,15 @@ NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, TALLOC_CTX *tmp_ctx = talloc_new(cldap); DATA_BLOB blob; - status = push_netlogon_samlogon_response(&blob, tmp_ctx, cldap->iconv_convenience, + status = push_netlogon_samlogon_response(&blob, tmp_ctx, + iconv_convenience, netlogon); if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); return status; } reply.messageid = message_id; - reply.dest = src; + reply.dest = dest; reply.response = &response; reply.result = &result; @@ -735,4 +1121,3 @@ NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, return status; } - diff --git a/source4/libcli/cldap/cldap.h b/source4/libcli/cldap/cldap.h index 8951daa775a..111fa2cfc45 100644 --- a/source4/libcli/cldap/cldap.h +++ b/source4/libcli/cldap/cldap.h @@ -19,89 +19,29 @@ along with this program. If not, see . */ -#include "../lib/util/asn1.h" #include "../libcli/netlogon.h" struct ldap_message; - -enum cldap_request_state {CLDAP_REQUEST_SEND, - CLDAP_REQUEST_WAIT, - CLDAP_REQUEST_DONE, - CLDAP_REQUEST_ERROR}; - -/* - a cldap request packet -*/ -struct cldap_request { - struct cldap_request *next, *prev; - - struct cldap_socket *cldap; - - enum cldap_request_state state; - NTSTATUS status; - - /* where to send the request */ - struct socket_address *dest; - - /* timeout between retries (seconds) */ - int timeout; - int num_retries; - - bool is_reply; - - /* the ldap message_id */ - int message_id; - - struct tevent_timer *te; - - /* the encoded request */ - DATA_BLOB encoded; - - /* the reply data */ - struct asn1_data *asn1; - - /* information on what to do on completion */ - struct { - void (*fn)(struct cldap_request *); - void *private_data; - } async; +struct tsocket_address; +struct cldap_socket; + +struct cldap_incoming { + int recv_errno; + uint8_t *buf; + size_t len; + struct tsocket_address *src; + struct ldap_message *ldap_msg; }; /* - context structure for operations on cldap packets -*/ -struct cldap_socket { - struct socket_context *sock; - struct tevent_context *event_ctx; - struct smb_iconv_convenience *iconv_convenience; - - /* the fd event */ - struct tevent_fd *fde; - - /* a queue of outgoing requests */ - struct cldap_request *send_queue; - - /* mapping from message_id to pending request */ - struct idr_context *idr; - - /* what to do with incoming request packets */ - struct { - void (*handler)(struct cldap_socket *, struct ldap_message *, - struct socket_address *); - void *private_data; - } incoming; -}; - - -/* - a general cldap search request + a general cldap search request */ struct cldap_search { struct { const char *dest_address; uint16_t dest_port; const char *filter; - const char **attributes; + const char * const *attributes; int timeout; int retries; } in; @@ -111,39 +51,43 @@ struct cldap_search { } out; }; -struct cldap_socket *cldap_socket_init(TALLOC_CTX *mem_ctx, - struct tevent_context *event_ctx, - struct smb_iconv_convenience *iconv_convenience); +NTSTATUS cldap_socket_init(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + const struct tsocket_address *local_addr, + const struct tsocket_address *remote_addr, + struct cldap_socket **_cldap); + NTSTATUS cldap_set_incoming_handler(struct cldap_socket *cldap, - void (*handler)(struct cldap_socket *, struct ldap_message *, - struct socket_address *), + void (*handler)(struct cldap_socket *, + void *private_data, + struct cldap_incoming *), void *private_data); -struct cldap_request *cldap_search_send(struct cldap_socket *cldap, - struct cldap_search *io); -NTSTATUS cldap_search_recv(struct cldap_request *req, TALLOC_CTX *mem_ctx, +struct tevent_req *cldap_search_send(TALLOC_CTX *mem_ctx, + struct cldap_socket *cldap, + const struct cldap_search *io); +NTSTATUS cldap_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, struct cldap_search *io); -NTSTATUS cldap_search(struct cldap_socket *cldap, TALLOC_CTX *mem_ctx, +NTSTATUS cldap_search(struct cldap_socket *cldap, TALLOC_CTX *mem_ctx, struct cldap_search *io); - /* a general cldap reply */ struct cldap_reply { uint32_t messageid; - struct socket_address *dest; + struct tsocket_address *dest; struct ldap_SearchResEntry *response; struct ldap_Result *result; }; NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io); -NTSTATUS cldap_empty_reply(struct cldap_socket *cldap, +NTSTATUS cldap_empty_reply(struct cldap_socket *cldap, uint32_t message_id, - struct socket_address *src); -NTSTATUS cldap_error_reply(struct cldap_socket *cldap, + struct tsocket_address *dst); +NTSTATUS cldap_error_reply(struct cldap_socket *cldap, uint32_t message_id, - struct socket_address *src, + struct tsocket_address *dst, int resultcode, const char *errormessage); @@ -168,15 +112,22 @@ struct cldap_netlogon { } out; }; -struct cldap_request *cldap_netlogon_send(struct cldap_socket *cldap, - struct cldap_netlogon *io); -NTSTATUS cldap_netlogon_recv(struct cldap_request *req, - TALLOC_CTX *mem_ctx, +struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx, + struct cldap_socket *cldap, + const struct cldap_netlogon *io); +NTSTATUS cldap_netlogon_recv(struct tevent_req *req, + struct smb_iconv_convenience *iconv_convenience, + TALLOC_CTX *mem_ctx, struct cldap_netlogon *io); -NTSTATUS cldap_netlogon(struct cldap_socket *cldap, - TALLOC_CTX *mem_ctx, struct cldap_netlogon *io); -NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, +NTSTATUS cldap_netlogon(struct cldap_socket *cldap, + struct smb_iconv_convenience *iconv_convenience, + TALLOC_CTX *mem_ctx, + struct cldap_netlogon *io); + +NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, + struct smb_iconv_convenience *iconv_convenience, uint32_t message_id, - struct socket_address *src, + struct tsocket_address *dst, uint32_t version, struct netlogon_samlogon_response *netlogon); + diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index dc3431ab9fc..1b87530af80 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -98,7 +98,7 @@ LIBCLI_DGRAM_OBJ_FILES = $(addprefix $(libclisrcdir)/dgram/, \ [SUBSYSTEM::LIBCLI_CLDAP] PUBLIC_DEPENDENCIES = LIBCLI_LDAP -PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL LIBLDB LIBCLI_NETLOGON +PRIVATE_DEPENDENCIES = LIBTSOCKET LIBSAMBA-UTIL UTIL_TEVENT LIBLDB LIBCLI_NETLOGON LIBCLI_CLDAP_OBJ_FILES = $(libclisrcdir)/cldap/cldap.o # PUBLIC_HEADERS += $(libclisrcdir)/cldap/cldap.h diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index bf046745e6a..dbbabd6a6da 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -731,12 +731,12 @@ struct libnet_BecomeDC_state { struct libnet_BecomeDC_Callbacks callbacks; }; -static void becomeDC_recv_cldap(struct cldap_request *req); +static void becomeDC_recv_cldap(struct tevent_req *req); static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s) { struct composite_context *c = s->creq; - struct cldap_request *req; + struct tevent_req *req; s->cldap.io.in.dest_address = s->source_dsa.address; s->cldap.io.in.dest_port = lp_cldap_port(s->libnet->lp_ctx); @@ -749,25 +749,27 @@ static void becomeDC_send_cldap(struct libnet_BecomeDC_state *s) s->cldap.io.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; s->cldap.io.in.map_response = true; - s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx, - lp_iconv_convenience(s->libnet->lp_ctx)); - if (composite_nomem(s->cldap.sock, c)) return; + c->status = cldap_socket_init(s, s->libnet->event_ctx, + NULL, NULL, &s->cldap.sock);//TODO + if (!composite_is_ok(c)) return; - req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io); + req = cldap_netlogon_send(s, s->cldap.sock, &s->cldap.io); if (composite_nomem(req, c)) return; - req->async.fn = becomeDC_recv_cldap; - req->async.private_data = s; + tevent_req_set_callback(req, becomeDC_recv_cldap, s); } static void becomeDC_connect_ldap1(struct libnet_BecomeDC_state *s); -static void becomeDC_recv_cldap(struct cldap_request *req) +static void becomeDC_recv_cldap(struct tevent_req *req) { - struct libnet_BecomeDC_state *s = talloc_get_type(req->async.private_data, + struct libnet_BecomeDC_state *s = tevent_req_callback_data(req, struct libnet_BecomeDC_state); struct composite_context *c = s->creq; - c->status = cldap_netlogon_recv(req, s, &s->cldap.io); + c->status = cldap_netlogon_recv(req, + lp_iconv_convenience(s->libnet->lp_ctx), + s, &s->cldap.io); + talloc_free(req); if (!composite_is_ok(c)) return; s->cldap.netlogon = s->cldap.io.out.netlogon.data.nt5_ex; diff --git a/source4/libnet/libnet_site.c b/source4/libnet/libnet_site.c index 4a32ab92ed5..8a002b24a4b 100644 --- a/source4/libnet/libnet_site.c +++ b/source4/libnet/libnet_site.c @@ -56,8 +56,14 @@ NTSTATUS libnet_FindSite(TALLOC_CTX *ctx, struct libnet_context *lctx, struct li search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; search.in.map_response = true; - cldap = cldap_socket_init(tmp_ctx, lctx->event_ctx, lp_iconv_convenience(lctx->lp_ctx)); - status = cldap_netlogon(cldap, tmp_ctx, &search); + /* we want to use non async calls, so we're not passing an event context */ + status = cldap_socket_init(tmp_ctx, NULL, NULL, NULL, &cldap);//TODO + if (!NT_STATUS_IS_OK(status)) { + talloc_free(tmp_ctx); + r->out.error_string = NULL; + return status; + } + status = cldap_netlogon(cldap, lp_iconv_convenience(lctx->lp_ctx), tmp_ctx, &search); if (!NT_STATUS_IS_OK(status) || !search.out.netlogon.data.nt5_ex.client_site) { /* diff --git a/source4/libnet/libnet_unbecome_dc.c b/source4/libnet/libnet_unbecome_dc.c index 3f92daab281..e0e5e421151 100644 --- a/source4/libnet/libnet_unbecome_dc.c +++ b/source4/libnet/libnet_unbecome_dc.c @@ -250,12 +250,12 @@ struct libnet_UnbecomeDC_state { } dest_dsa; }; -static void unbecomeDC_recv_cldap(struct cldap_request *req); +static void unbecomeDC_recv_cldap(struct tevent_req *req); static void unbecomeDC_send_cldap(struct libnet_UnbecomeDC_state *s) { struct composite_context *c = s->creq; - struct cldap_request *req; + struct tevent_req *req; s->cldap.io.in.dest_address = s->source_dsa.address; s->cldap.io.in.dest_port = lp_cldap_port(s->libnet->lp_ctx); @@ -268,25 +268,27 @@ static void unbecomeDC_send_cldap(struct libnet_UnbecomeDC_state *s) s->cldap.io.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; s->cldap.io.in.map_response = true; - s->cldap.sock = cldap_socket_init(s, s->libnet->event_ctx, - lp_iconv_convenience(s->libnet->lp_ctx)); - if (composite_nomem(s->cldap.sock, c)) return; + c->status = cldap_socket_init(s, s->libnet->event_ctx, + NULL, NULL, &s->cldap.sock);//TODO + if (!composite_is_ok(c)) return; - req = cldap_netlogon_send(s->cldap.sock, &s->cldap.io); + req = cldap_netlogon_send(s, s->cldap.sock, &s->cldap.io); if (composite_nomem(req, c)) return; - req->async.fn = unbecomeDC_recv_cldap; - req->async.private_data = s; + tevent_req_set_callback(req, unbecomeDC_recv_cldap, s); } static void unbecomeDC_connect_ldap(struct libnet_UnbecomeDC_state *s); -static void unbecomeDC_recv_cldap(struct cldap_request *req) +static void unbecomeDC_recv_cldap(struct tevent_req *req) { - struct libnet_UnbecomeDC_state *s = talloc_get_type(req->async.private_data, + struct libnet_UnbecomeDC_state *s = tevent_req_callback_data(req, struct libnet_UnbecomeDC_state); struct composite_context *c = s->creq; - c->status = cldap_netlogon_recv(req, s, &s->cldap.io); + c->status = cldap_netlogon_recv(req, + lp_iconv_convenience(s->libnet->lp_ctx), + s, &s->cldap.io); + talloc_free(req); if (!composite_is_ok(c)) return; s->cldap.netlogon = s->cldap.io.out.netlogon.data.nt5_ex; diff --git a/source4/torture/ldap/cldap.c b/source4/torture/ldap/cldap.c index 1ddc628a5c6..98669288a8f 100644 --- a/source4/torture/ldap/cldap.c +++ b/source4/torture/ldap/cldap.c @@ -28,6 +28,7 @@ #include "torture/torture.h" #include "lib/ldb/include/ldb.h" #include "param/param.h" +#include "../lib/tsocket/tsocket.h" #define CHECK_STATUS(status, correct) torture_assert_ntstatus_equal(tctx, status, correct, "incorrect status") @@ -45,12 +46,21 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest) struct netlogon_samlogon_response n1; struct GUID guid; int i; + struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx); + struct tsocket_address *dest_addr; + int ret; - cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); + ret = tsocket_address_inet_from_strings(tctx, "ip", + dest, + lp_cldap_port(tctx->lp_ctx), + &dest_addr); + + status = cldap_socket_init(tctx, NULL, NULL, dest_addr, &cldap); + CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(search); - search.in.dest_address = dest; - search.in.dest_port = lp_cldap_port(tctx->lp_ctx); + search.in.dest_address = NULL;//dest; + search.in.dest_port = 0;//lp_cldap_port(tctx->lp_ctx); search.in.acct_control = -1; search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; search.in.map_response = true; @@ -59,7 +69,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest) printf("Trying without any attributes\n"); search = empty_search; - status = cldap_netlogon(cldap, tctx, &search); + status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); n1 = search.out.netlogon; @@ -72,7 +82,7 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest) for (i=0;i<256;i++) { search.in.version = i; printf("Trying netlogon level %d\n", i); - status = cldap_netlogon(cldap, tctx, &search); + status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); } @@ -80,19 +90,19 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest) for (i=0;i<31;i++) { search.in.version = (1<lp_ctx); - cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); + status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap); + CHECK_STATUS(status, NT_STATUS_OK); - printf("Printing out netlogon server type flags:\n"); + printf("Printing out netlogon server type flags: %s\n", dest); ZERO_STRUCT(search); search.in.dest_address = dest; @@ -251,7 +263,7 @@ static bool test_cldap_netlogon_flags(struct torture_context *tctx, search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; search.in.map_response = true; - status = cldap_netlogon(cldap, tctx, &search); + status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); n1 = search.out.netlogon; @@ -348,10 +360,12 @@ static bool test_cldap_netlogon_flag_ds_dns_forest(struct torture_context *tctx, struct cldap_netlogon search; uint32_t server_type; struct netlogon_samlogon_response n1; + struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(tctx->lp_ctx); bool result = true; - cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); + status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap); + CHECK_STATUS(status, NT_STATUS_OK); printf("Testing netlogon server type flag NBT_SERVER_DS_DNS_FOREST: "); @@ -362,7 +376,7 @@ static bool test_cldap_netlogon_flag_ds_dns_forest(struct torture_context *tctx, search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; search.in.map_response = true; - status = cldap_netlogon(cldap, tctx, &search); + status = cldap_netlogon(cldap, iconv_convenience, tctx, &search); CHECK_STATUS(status, NT_STATUS_OK); n1 = search.out.netlogon; @@ -423,7 +437,8 @@ static bool test_cldap_generic(struct torture_context *tctx, const char *dest) const char *attrs2[] = { "currentTime", "highestCommittedUSN", "netlogon", NULL }; const char *attrs3[] = { "netlogon", NULL }; - cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); + status = cldap_socket_init(tctx, NULL, NULL, NULL, &cldap); + CHECK_STATUS(status, NT_STATUS_OK); ZERO_STRUCT(search); search.in.dest_address = dest; diff --git a/source4/torture/ldap/cldapbench.c b/source4/torture/ldap/cldapbench.c index ae2cb808360..a422732b039 100644 --- a/source4/torture/ldap/cldapbench.c +++ b/source4/torture/ldap/cldapbench.c @@ -20,24 +20,28 @@ */ #include "includes.h" -#include "lib/events/events.h" +#include #include "libcli/cldap/cldap.h" #include "libcli/resolve/resolve.h" #include "torture/torture.h" #include "param/param.h" struct bench_state { + struct torture_context *tctx; int pass_count, fail_count; }; -static void request_netlogon_handler(struct cldap_request *req) +static void request_netlogon_handler(struct tevent_req *req) { struct cldap_netlogon io; - struct bench_state *state = talloc_get_type(req->async.private_data, struct bench_state); + struct bench_state *state = tevent_req_callback_data(req, struct bench_state); NTSTATUS status; TALLOC_CTX *tmp_ctx = talloc_new(NULL); io.in.version = 6; - status = cldap_netlogon_recv(req, tmp_ctx, &io); + status = cldap_netlogon_recv(req, + lp_iconv_convenience(state->tctx->lp_ctx), + tmp_ctx, &io); + talloc_free(req); if (NT_STATUS_IS_OK(status)) { state->pass_count++; } else { @@ -58,10 +62,13 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre int timelimit = torture_setting_int(tctx, "timelimit", 10); struct cldap_netlogon search; struct bench_state *state; + NTSTATUS status; - cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); + status = cldap_socket_init(tctx, tctx->ev, NULL, NULL, &cldap); + torture_assert_ntstatus_ok(tctx, status, "cldap_socket_init"); state = talloc_zero(tctx, struct bench_state); + state->tctx = tctx; ZERO_STRUCT(search); search.in.dest_address = address; @@ -72,11 +79,11 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre printf("Running CLDAP/netlogon for %d seconds\n", timelimit); while (timeval_elapsed(&tv) < timelimit) { while (num_sent - (state->pass_count+state->fail_count) < 10) { - struct cldap_request *req; - req = cldap_netlogon_send(cldap, &search); + struct tevent_req *req; + req = cldap_netlogon_send(state, cldap, &search); + + tevent_req_set_callback(req, request_netlogon_handler, state); - req->async.private_data = state; - req->async.fn = request_netlogon_handler; num_sent++; if (num_sent % 50 == 0) { if (torture_setting_bool(tctx, "progress", true)) { @@ -88,11 +95,11 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre } } - event_loop_once(cldap->event_ctx); + tevent_loop_once(tctx->ev); } while (num_sent != (state->pass_count + state->fail_count)) { - event_loop_once(cldap->event_ctx); + tevent_loop_once(tctx->ev); } printf("%.1f queries per second (%d failures) \n", @@ -103,13 +110,14 @@ static bool bench_cldap_netlogon(struct torture_context *tctx, const char *addre return ret; } -static void request_rootdse_handler(struct cldap_request *req) +static void request_rootdse_handler(struct tevent_req *req) { struct cldap_search io; - struct bench_state *state = talloc_get_type(req->async.private_data, struct bench_state); + struct bench_state *state = tevent_req_callback_data(req, struct bench_state); NTSTATUS status; TALLOC_CTX *tmp_ctx = talloc_new(NULL); status = cldap_search_recv(req, tmp_ctx, &io); + talloc_free(req); if (NT_STATUS_IS_OK(status)) { state->pass_count++; } else { @@ -130,8 +138,10 @@ static bool bench_cldap_rootdse(struct torture_context *tctx, const char *addres int timelimit = torture_setting_int(tctx, "timelimit", 10); struct cldap_search search; struct bench_state *state; + NTSTATUS status; - cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); + status = cldap_socket_init(tctx, tctx->ev, NULL, NULL, &cldap); + torture_assert_ntstatus_ok(tctx, status, "cldap_socket_init"); state = talloc_zero(tctx, struct bench_state); @@ -145,11 +155,11 @@ static bool bench_cldap_rootdse(struct torture_context *tctx, const char *addres printf("Running CLDAP/rootdse for %d seconds\n", timelimit); while (timeval_elapsed(&tv) < timelimit) { while (num_sent - (state->pass_count+state->fail_count) < 10) { - struct cldap_request *req; - req = cldap_search_send(cldap, &search); + struct tevent_req *req; + req = cldap_search_send(state, cldap, &search); + + tevent_req_set_callback(req, request_rootdse_handler, state); - req->async.private_data = state; - req->async.fn = request_rootdse_handler; num_sent++; if (num_sent % 50 == 0) { if (torture_setting_bool(tctx, "progress", true)) { diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c index 847b32827b8..1aaf914ceb8 100644 --- a/source4/torture/rpc/dssync.c +++ b/source4/torture/rpc/dssync.c @@ -273,7 +273,12 @@ static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx) struct cldap_socket *cldap; struct cldap_netlogon search; - cldap = cldap_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx)); + status = cldap_socket_init(ctx, NULL, NULL, NULL, &cldap); + if (!NT_STATUS_IS_OK(status)) { + printf("failed to setup cldap socket - %s\n", + nt_errstr(status)); + return false; + } r.in.bind_handle = &ctx->admin.drsuapi.bind_handle; r.in.level = 1; @@ -311,7 +316,7 @@ static bool test_GetInfo(struct torture_context *tctx, struct DsSyncTest *ctx) search.in.acct_control = -1; search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX; search.in.map_response = true; - status = cldap_netlogon(cldap, ctx, &search); + status = cldap_netlogon(cldap, lp_iconv_convenience(tctx->lp_ctx), ctx, &search); if (!NT_STATUS_IS_OK(status)) { const char *errstr = nt_errstr(status); ctx->site_name = talloc_asprintf(ctx, "%s", "Default-First-Site-Name"); -- cgit From 84a140f18722518eb0f40737085dd3b3958a3a02 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Mar 2009 17:43:11 +0100 Subject: move source4/libcli/cldap => libcli/cldap metze --- source4/headermap.txt | 2 +- source4/libcli/cldap/cldap.c | 1123 ------------------------------------------ source4/libcli/cldap/cldap.h | 133 ----- source4/libcli/config.mk | 7 - 4 files changed, 1 insertion(+), 1264 deletions(-) delete mode 100644 source4/libcli/cldap/cldap.c delete mode 100644 source4/libcli/cldap/cldap.h (limited to 'source4') diff --git a/source4/headermap.txt b/source4/headermap.txt index d0d0a575d83..280d60beb2f 100644 --- a/source4/headermap.txt +++ b/source4/headermap.txt @@ -25,7 +25,7 @@ lib/registry/registry.h: registry.h libcli/util/werror.h: core/werror.h libcli/util/doserr.h: core/doserr.h libcli/util/ntstatus.h: core/ntstatus.h -libcli/cldap/cldap.h: cldap.h +../libcli/cldap/cldap.h: cldap.h auth/credentials/credentials.h: credentials.h auth/credentials/credentials_krb5.h: credentials/krb5.h rpc_server/dcerpc_server.h: dcerpc_server.h diff --git a/source4/libcli/cldap/cldap.c b/source4/libcli/cldap/cldap.c deleted file mode 100644 index 0f2175b42dd..00000000000 --- a/source4/libcli/cldap/cldap.c +++ /dev/null @@ -1,1123 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - cldap client library - - Copyright (C) Andrew Tridgell 2005 - Copyright (C) Stefan Metzmacher 2009 - - 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 . -*/ - -/* - see RFC1798 for details of CLDAP - - basic properties - - carried over UDP on port 389 - - request and response matched by message ID - - request consists of only a single searchRequest element - - response can be in one of two forms - - a single searchResponse, followed by a searchResult - - a single searchResult -*/ - -#include "includes.h" -#include -#include "../lib/util/dlinklist.h" -#include "libcli/ldap/ldap.h" -#include "libcli/ldap/ldap_ndr.h" -#include "libcli/cldap/cldap.h" -#include "../lib/tsocket/tsocket.h" -#include "libcli/security/security.h" -#include "librpc/gen_ndr/ndr_nbt.h" -#include "../lib/util/asn1.h" -#include "../lib/util/tevent_ntstatus.h" - -/* - context structure for operations on cldap packets -*/ -struct cldap_socket { - /* the low level socket */ - struct tsocket_context *sock; - - /* - * Are we in connected mode, which means - * we get ICMP errors back instead of timing - * out requests. And we can only send requests - * to the connected peer. - */ - bool connected; - - /* - * we allow sync requests only, if the caller - * did not pass an event context to cldap_socket_init() - */ - struct { - bool allow_poll; - struct tevent_context *ctx; - } event; - - /* the queue for outgoing dgrams */ - struct tevent_queue *send_queue; - - /* do we have an async tsocket_recvfrom request pending */ - struct tevent_req *recv_subreq; - - struct { - /* a queue of pending search requests */ - struct cldap_search_state *list; - - /* mapping from message_id to pending request */ - struct idr_context *idr; - } searches; - - /* what to do with incoming request packets */ - struct { - void (*handler)(struct cldap_socket *, - void *private_data, - struct cldap_incoming *); - void *private_data; - } incoming; -}; - -struct cldap_search_state { - struct cldap_search_state *prev, *next; - - struct { - struct cldap_socket *cldap; - } caller; - - int message_id; - - struct { - uint32_t idx; - uint32_t delay; - uint32_t count; - struct tsocket_address *dest; - DATA_BLOB blob; - } request; - - struct { - struct cldap_incoming *in; - struct asn1_data *asn1; - } response; - - struct tevent_req *req; -}; - -static int cldap_socket_destructor(struct cldap_socket *c) -{ - tsocket_disconnect(c->sock); - - while (c->searches.list) { - struct cldap_search_state *s = c->searches.list; - DLIST_REMOVE(c->searches.list, s); - ZERO_STRUCT(s->caller); - } - - talloc_free(c->recv_subreq); - talloc_free(c->send_queue); - talloc_free(c->sock); - return 0; -} - -static void cldap_recvfrom_done(struct tevent_req *subreq); - -static bool cldap_recvfrom_setup(struct cldap_socket *c) -{ - if (c->recv_subreq) { - return true; - } - - if (!c->searches.list && !c->incoming.handler) { - return true; - } - - c->recv_subreq = tsocket_recvfrom_send(c->sock, c); - if (!c->recv_subreq) { - return false; - } - tevent_req_set_callback(c->recv_subreq, cldap_recvfrom_done, c); - - return true; -} - -static void cldap_recvfrom_stop(struct cldap_socket *c) -{ - if (!c->recv_subreq) { - return; - } - - if (c->searches.list || c->incoming.handler) { - return; - } - - talloc_free(c->recv_subreq); - c->recv_subreq = NULL; -} - -static void cldap_socket_recv_dgram(struct cldap_socket *c, - struct cldap_incoming *in); - -static void cldap_recvfrom_done(struct tevent_req *subreq) -{ - struct cldap_socket *c = tevent_req_callback_data(subreq, - struct cldap_socket); - struct cldap_incoming *in = NULL; - ssize_t ret; - - c->recv_subreq = NULL; - - in = talloc_zero(c, struct cldap_incoming); - if (!in) { - goto nomem; - } - - ret = tsocket_recvfrom_recv(subreq, - &in->recv_errno, - in, - &in->buf, - &in->src); - talloc_free(subreq); - subreq = NULL; - if (ret >= 0) { - in->len = ret; - } - if (ret == -1 && in->recv_errno == 0) { - in->recv_errno = EIO; - } - - /* this function should free or steal 'in' */ - cldap_socket_recv_dgram(c, in); - in = NULL; - - if (!cldap_recvfrom_setup(c)) { - goto nomem; - } - - return; - -nomem: - talloc_free(subreq); - talloc_free(in); - /*TODO: call a dead socket handler */ - return; -} - -/* - handle recv events on a cldap socket -*/ -static void cldap_socket_recv_dgram(struct cldap_socket *c, - struct cldap_incoming *in) -{ - DATA_BLOB blob; - struct asn1_data *asn1; - void *p; - struct cldap_search_state *search; - NTSTATUS status; - - if (in->recv_errno != 0) { - goto error; - } - - blob = data_blob_const(in->buf, in->len); - - asn1 = asn1_init(in); - if (!asn1) { - goto nomem; - } - - if (!asn1_load(asn1, blob)) { - goto nomem; - } - - in->ldap_msg = talloc(in, struct ldap_message); - if (in->ldap_msg == NULL) { - goto nomem; - } - - /* this initial decode is used to find the message id */ - status = ldap_decode(asn1, NULL, in->ldap_msg); - if (!NT_STATUS_IS_OK(status)) { - goto nterror; - } - - /* find the pending request */ - p = idr_find(c->searches.idr, in->ldap_msg->messageid); - if (p == NULL) { - if (!c->incoming.handler) { - goto done; - } - - /* this function should free or steal 'in' */ - c->incoming.handler(c, c->incoming.private_data, in); - return; - } - - search = talloc_get_type(p, struct cldap_search_state); - search->response.in = talloc_move(search, &in); - search->response.asn1 = asn1; - search->response.asn1->ofs = 0; - - tevent_req_done(search->req); - goto done; - -nomem: - in->recv_errno = ENOMEM; -error: - status = map_nt_error_from_unix(in->recv_errno); -nterror: - /* in connected mode the first pending search gets the error */ - if (!c->connected) { - /* otherwise we just ignore the error */ - goto done; - } - if (!c->searches.list) { - goto done; - } - tevent_req_nterror(c->searches.list->req, status); -done: - talloc_free(in); -} - -/* - initialise a cldap_sock -*/ -NTSTATUS cldap_socket_init(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - const struct tsocket_address *local_addr, - const struct tsocket_address *remote_addr, - struct cldap_socket **_cldap) -{ - struct cldap_socket *c = NULL; - struct tsocket_address *any = NULL; - NTSTATUS status; - int ret; - - c = talloc_zero(mem_ctx, struct cldap_socket); - if (!c) { - goto nomem; - } - - if (!ev) { - ev = tevent_context_init(c); - if (!ev) { - goto nomem; - } - c->event.allow_poll = true; - } - c->event.ctx = ev; - - if (!local_addr) { - ret = tsocket_address_inet_from_strings(c, "ipv4", - NULL, 0, - &any); - if (ret != 0) { - status = map_nt_error_from_unix(errno); - goto nterror; - } - local_addr = any; - } - - c->searches.idr = idr_init(c); - if (!c->searches.idr) { - goto nomem; - } - - ret = tsocket_address_create_socket(local_addr, - TSOCKET_TYPE_DGRAM, - c, &c->sock); - if (ret != 0) { - status = map_nt_error_from_unix(errno); - goto nterror; - } - talloc_free(any); - - tsocket_set_event_context(c->sock, c->event.ctx); - - if (remote_addr) { - ret = tsocket_connect(c->sock, remote_addr); - if (ret != 0) { - status = map_nt_error_from_unix(errno); - goto nterror; - } - c->connected = true; - } - - c->send_queue = tevent_queue_create(c, "cldap_send_queue"); - if (!c->send_queue) { - goto nomem; - } - - talloc_set_destructor(c, cldap_socket_destructor); - - *_cldap = c; - return NT_STATUS_OK; - -nomem: - status = NT_STATUS_NO_MEMORY; -nterror: - talloc_free(c); - return status; -} - -/* - setup a handler for incoming requests -*/ -NTSTATUS cldap_set_incoming_handler(struct cldap_socket *c, - void (*handler)(struct cldap_socket *, - void *private_data, - struct cldap_incoming *), - void *private_data) -{ - if (c->connected) { - return NT_STATUS_PIPE_CONNECTED; - } - - /* if sync requests are allowed, we don't allow an incoming handler */ - if (c->event.allow_poll) { - return NT_STATUS_INVALID_PIPE_STATE; - } - - c->incoming.handler = handler; - c->incoming.private_data = private_data; - - if (!cldap_recvfrom_setup(c)) { - ZERO_STRUCT(c->incoming); - return NT_STATUS_NO_MEMORY; - } - - return NT_STATUS_OK; -} - -struct cldap_reply_state { - struct tsocket_address *dest; - DATA_BLOB blob; -}; - -static void cldap_reply_state_destroy(struct tevent_req *req); - -/* - queue a cldap reply for send -*/ -NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io) -{ - struct cldap_reply_state *state = NULL; - struct ldap_message *msg; - DATA_BLOB blob1, blob2; - NTSTATUS status; - struct tevent_req *req; - - if (cldap->connected) { - return NT_STATUS_PIPE_CONNECTED; - } - - if (!io->dest) { - return NT_STATUS_INVALID_ADDRESS; - } - - state = talloc(cldap, struct cldap_reply_state); - NT_STATUS_HAVE_NO_MEMORY(state); - - state->dest = tsocket_address_copy(io->dest, state); - if (!state->dest) { - goto nomem; - } - - msg = talloc(state, struct ldap_message); - if (!msg) { - goto nomem; - } - - msg->messageid = io->messageid; - msg->controls = NULL; - - if (io->response) { - msg->type = LDAP_TAG_SearchResultEntry; - msg->r.SearchResultEntry = *io->response; - - if (!ldap_encode(msg, NULL, &blob1, state)) { - status = NT_STATUS_INVALID_PARAMETER; - goto failed; - } - } else { - blob1 = data_blob(NULL, 0); - } - - msg->type = LDAP_TAG_SearchResultDone; - msg->r.SearchResultDone = *io->result; - - if (!ldap_encode(msg, NULL, &blob2, state)) { - status = NT_STATUS_INVALID_PARAMETER; - goto failed; - } - talloc_free(msg); - - state->blob = data_blob_talloc(state, NULL, blob1.length + blob2.length); - if (!state->blob.data) { - goto nomem; - } - - memcpy(state->blob.data, blob1.data, blob1.length); - memcpy(state->blob.data+blob1.length, blob2.data, blob2.length); - data_blob_free(&blob1); - data_blob_free(&blob2); - - req = tsocket_sendto_queue_send(state, - cldap->sock, - cldap->send_queue, - state->blob.data, - state->blob.length, - state->dest); - if (!req) { - goto nomem; - } - /* the callback will just free the state, as we don't need a result */ - tevent_req_set_callback(req, cldap_reply_state_destroy, state); - - return NT_STATUS_OK; - -nomem: - status = NT_STATUS_NO_MEMORY; -failed: - talloc_free(state); - return status; -} - -static void cldap_reply_state_destroy(struct tevent_req *req) -{ - struct cldap_reply_state *state = tevent_req_callback_data(req, - struct cldap_reply_state); - - /* we don't want to know the result here, we just free the state */ - talloc_free(req); - talloc_free(state); -} - -static int cldap_search_state_destructor(struct cldap_search_state *s) -{ - if (s->caller.cldap) { - DLIST_REMOVE(s->caller.cldap->searches.list, s); - cldap_recvfrom_stop(s->caller.cldap); - ZERO_STRUCT(s->caller); - } - - return 0; -} - -static void cldap_search_state_queue_done(struct tevent_req *subreq); -static void cldap_search_state_wakeup_done(struct tevent_req *subreq); - -/* - queue a cldap reply for send -*/ -struct tevent_req *cldap_search_send(TALLOC_CTX *mem_ctx, - struct cldap_socket *cldap, - const struct cldap_search *io) -{ - struct tevent_req *req, *subreq; - struct cldap_search_state *state = NULL; - struct ldap_message *msg; - struct ldap_SearchRequest *search; - struct timeval now; - struct timeval end; - uint32_t i; - int ret; - - req = tevent_req_create(mem_ctx, &state, - struct cldap_search_state); - if (!req) { - return NULL; - } - state->req = req; - state->caller.cldap = cldap; - - if (io->in.dest_address) { - if (cldap->connected) { - tevent_req_nterror(req, NT_STATUS_PIPE_CONNECTED); - goto post; - } - ret = tsocket_address_inet_from_strings(state, - "ipv4", - io->in.dest_address, - io->in.dest_port, - &state->request.dest); - if (ret != 0) { - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); - goto post; - } - } else { - if (!cldap->connected) { - tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS); - goto post; - } - state->request.dest = NULL; - } - - state->message_id = idr_get_new_random(cldap->searches.idr, - state, UINT16_MAX); - if (state->message_id == -1) { - tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES); - goto post; - } - - msg = talloc(state, struct ldap_message); - if (tevent_req_nomem(msg, req)) { - goto post; - } - - msg->messageid = state->message_id; - msg->type = LDAP_TAG_SearchRequest; - msg->controls = NULL; - search = &msg->r.SearchRequest; - - search->basedn = ""; - search->scope = LDAP_SEARCH_SCOPE_BASE; - search->deref = LDAP_DEREFERENCE_NEVER; - search->timelimit = 0; - search->sizelimit = 0; - search->attributesonly = false; - search->num_attributes = str_list_length(io->in.attributes); - search->attributes = io->in.attributes; - search->tree = ldb_parse_tree(msg, io->in.filter); - if (tevent_req_nomem(search->tree, req)) { - goto post; - } - - if (!ldap_encode(msg, NULL, &state->request.blob, state)) { - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); - goto post; - } - talloc_free(msg); - - state->request.idx = 0; - state->request.delay = 10*1000*1000; - state->request.count = 3; - if (io->in.timeout > 0) { - state->request.delay = io->in.timeout * 1000 * 1000; - state->request.count = io->in.retries + 1; - } - - now = tevent_timeval_current(); - end = now; - for (i = 0; i < state->request.count; i++) { - end = tevent_timeval_add(&end, 0, state->request.delay); - } - - if (!tevent_req_set_endtime(req, state->caller.cldap->event.ctx, end)) { - tevent_req_nomem(NULL, req); - goto post; - } - - subreq = tsocket_sendto_queue_send(state, - state->caller.cldap->sock, - state->caller.cldap->send_queue, - state->request.blob.data, - state->request.blob.length, - state->request.dest); - if (tevent_req_nomem(subreq, req)) { - goto post; - } - tevent_req_set_callback(subreq, cldap_search_state_queue_done, req); - - DLIST_ADD_END(cldap->searches.list, state, struct cldap_search_state *); - talloc_set_destructor(state, cldap_search_state_destructor); - - return req; - - post: - return tevent_req_post(req, cldap->event.ctx); -} - -static void cldap_search_state_queue_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cldap_search_state *state = tevent_req_data(req, - struct cldap_search_state); - ssize_t ret; - int sys_errno = 0; - struct timeval next; - - ret = tsocket_sendto_queue_recv(subreq, &sys_errno); - talloc_free(subreq); - if (ret == -1) { - NTSTATUS status; - status = map_nt_error_from_unix(sys_errno); - DLIST_REMOVE(state->caller.cldap->searches.list, state); - ZERO_STRUCT(state->caller.cldap); - tevent_req_nterror(req, status); - return; - } - - state->request.idx++; - - /* wait for incoming traffic */ - if (!cldap_recvfrom_setup(state->caller.cldap)) { - tevent_req_nomem(NULL, req); - return; - } - - if (state->request.idx > state->request.count) { - /* we just wait for the response or a timeout */ - return; - } - - next = tevent_timeval_current_ofs(0, state->request.delay); - subreq = tevent_wakeup_send(state, - state->caller.cldap->event.ctx, - next); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, cldap_search_state_wakeup_done, req); -} - -static void cldap_search_state_wakeup_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cldap_search_state *state = tevent_req_data(req, - struct cldap_search_state); - bool ok; - - ok = tevent_wakeup_recv(subreq); - talloc_free(subreq); - if (!ok) { - tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); - return; - } - - subreq = tsocket_sendto_queue_send(state, - state->caller.cldap->sock, - state->caller.cldap->send_queue, - state->request.blob.data, - state->request.blob.length, - state->request.dest); - if (tevent_req_nomem(subreq, req)) { - return; - } - tevent_req_set_callback(subreq, cldap_search_state_queue_done, req); -} - -/* - receive a cldap reply -*/ -NTSTATUS cldap_search_recv(struct tevent_req *req, - TALLOC_CTX *mem_ctx, - struct cldap_search *io) -{ - struct cldap_search_state *state = tevent_req_data(req, - struct cldap_search_state); - struct ldap_message *ldap_msg; - NTSTATUS status; - - if (tevent_req_is_nterror(req, &status)) { - goto failed; - } - - ldap_msg = talloc(mem_ctx, struct ldap_message); - if (!ldap_msg) { - goto nomem; - } - - status = ldap_decode(state->response.asn1, NULL, ldap_msg); - if (!NT_STATUS_IS_OK(status)) { - goto failed; - } - - ZERO_STRUCT(io->out); - - /* the first possible form has a search result in first place */ - if (ldap_msg->type == LDAP_TAG_SearchResultEntry) { - io->out.response = talloc(mem_ctx, struct ldap_SearchResEntry); - if (!io->out.response) { - goto nomem; - } - *io->out.response = ldap_msg->r.SearchResultEntry; - - /* decode the 2nd part */ - status = ldap_decode(state->response.asn1, NULL, ldap_msg); - if (!NT_STATUS_IS_OK(status)) { - goto failed; - } - } - - if (ldap_msg->type != LDAP_TAG_SearchResultDone) { - status = NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); - goto failed; - } - - io->out.result = talloc(mem_ctx, struct ldap_Result); - if (!io->out.result) { - goto nomem; - } - *io->out.result = ldap_msg->r.SearchResultDone; - - if (io->out.result->resultcode != LDAP_SUCCESS) { - status = NT_STATUS_LDAP(io->out.result->resultcode); - goto failed; - } - - tevent_req_received(req); - return NT_STATUS_OK; - -nomem: - status = NT_STATUS_NO_MEMORY; -failed: - tevent_req_received(req); - return status; -} - - -/* - synchronous cldap search -*/ -NTSTATUS cldap_search(struct cldap_socket *cldap, - TALLOC_CTX *mem_ctx, - struct cldap_search *io) -{ - struct tevent_req *req; - NTSTATUS status; - - if (!cldap->event.allow_poll) { - return NT_STATUS_INVALID_PIPE_STATE; - } - - if (cldap->searches.list) { - return NT_STATUS_PIPE_BUSY; - } - - req = cldap_search_send(mem_ctx, cldap, io); - NT_STATUS_HAVE_NO_MEMORY(req); - - if (!tevent_req_poll(req, cldap->event.ctx)) { - talloc_free(req); - return NT_STATUS_INTERNAL_ERROR; - } - - status = cldap_search_recv(req, mem_ctx, io); - talloc_free(req); - - return status; -} - -struct cldap_netlogon_state { - struct cldap_search search; -}; - -static void cldap_netlogon_state_done(struct tevent_req *subreq); -/* - queue a cldap netlogon for send -*/ -struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx, - struct cldap_socket *cldap, - const struct cldap_netlogon *io) -{ - struct tevent_req *req, *subreq; - struct cldap_netlogon_state *state; - char *filter; - static const char * const attr[] = { "NetLogon", NULL }; - - req = tevent_req_create(mem_ctx, &state, - struct cldap_netlogon_state); - if (!req) { - return NULL; - } - - filter = talloc_asprintf(state, "(&(NtVer=%s)", - ldap_encode_ndr_uint32(state, io->in.version)); - if (tevent_req_nomem(filter, req)) { - goto post; - } - if (io->in.user) { - filter = talloc_asprintf_append_buffer(filter, "(User=%s)", io->in.user); - if (tevent_req_nomem(filter, req)) { - goto post; - } - } - if (io->in.host) { - filter = talloc_asprintf_append_buffer(filter, "(Host=%s)", io->in.host); - if (tevent_req_nomem(filter, req)) { - goto post; - } - } - if (io->in.realm) { - filter = talloc_asprintf_append_buffer(filter, "(DnsDomain=%s)", io->in.realm); - if (tevent_req_nomem(filter, req)) { - goto post; - } - } - if (io->in.acct_control != -1) { - filter = talloc_asprintf_append_buffer(filter, "(AAC=%s)", - ldap_encode_ndr_uint32(state, io->in.acct_control)); - if (tevent_req_nomem(filter, req)) { - goto post; - } - } - if (io->in.domain_sid) { - struct dom_sid *sid = dom_sid_parse_talloc(state, io->in.domain_sid); - if (tevent_req_nomem(sid, req)) { - goto post; - } - filter = talloc_asprintf_append_buffer(filter, "(domainSid=%s)", - ldap_encode_ndr_dom_sid(state, sid)); - if (tevent_req_nomem(filter, req)) { - goto post; - } - } - if (io->in.domain_guid) { - struct GUID guid; - NTSTATUS status; - status = GUID_from_string(io->in.domain_guid, &guid); - if (tevent_req_nterror(req, status)) { - goto post; - } - filter = talloc_asprintf_append_buffer(filter, "(DomainGuid=%s)", - ldap_encode_ndr_GUID(state, &guid)); - if (tevent_req_nomem(filter, req)) { - goto post; - } - } - filter = talloc_asprintf_append_buffer(filter, ")"); - if (tevent_req_nomem(filter, req)) { - goto post; - } - - if (io->in.dest_address) { - state->search.in.dest_address = talloc_strdup(state, - io->in.dest_address); - if (tevent_req_nomem(state->search.in.dest_address, req)) { - goto post; - } - state->search.in.dest_port = io->in.dest_port; - } else { - state->search.in.dest_address = NULL; - state->search.in.dest_port = 0; - } - state->search.in.filter = filter; - state->search.in.attributes = attr; - state->search.in.timeout = 2; - state->search.in.retries = 2; - - subreq = cldap_search_send(state, cldap, &state->search); - if (tevent_req_nomem(subreq, req)) { - goto post; - } - tevent_req_set_callback(subreq, cldap_netlogon_state_done, req); - - return req; -post: - return tevent_req_post(req, cldap->event.ctx); -} - -static void cldap_netlogon_state_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct cldap_netlogon_state *state = tevent_req_data(req, - struct cldap_netlogon_state); - NTSTATUS status; - - status = cldap_search_recv(subreq, state, &state->search); - talloc_free(subreq); - - if (tevent_req_nterror(req, status)) { - return; - } - - tevent_req_done(req); -} - -/* - receive a cldap netlogon reply -*/ -NTSTATUS cldap_netlogon_recv(struct tevent_req *req, - struct smb_iconv_convenience *iconv_convenience, - TALLOC_CTX *mem_ctx, - struct cldap_netlogon *io) -{ - struct cldap_netlogon_state *state = tevent_req_data(req, - struct cldap_netlogon_state); - NTSTATUS status; - DATA_BLOB *data; - - if (tevent_req_is_nterror(req, &status)) { - goto failed; - } - - if (state->search.out.response == NULL) { - status = NT_STATUS_NOT_FOUND; - goto failed; - } - - if (state->search.out.response->num_attributes != 1 || - strcasecmp(state->search.out.response->attributes[0].name, "netlogon") != 0 || - state->search.out.response->attributes[0].num_values != 1 || - state->search.out.response->attributes[0].values->length < 2) { - status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; - goto failed; - } - data = state->search.out.response->attributes[0].values; - - status = pull_netlogon_samlogon_response(data, mem_ctx, - iconv_convenience, - &io->out.netlogon); - if (!NT_STATUS_IS_OK(status)) { - goto failed; - } - - if (io->in.map_response) { - map_netlogon_samlogon_response(&io->out.netlogon); - } - - status = NT_STATUS_OK; -failed: - tevent_req_received(req); - return status; -} - -/* - sync cldap netlogon search -*/ -NTSTATUS cldap_netlogon(struct cldap_socket *cldap, - struct smb_iconv_convenience *iconv_convenience, - TALLOC_CTX *mem_ctx, - struct cldap_netlogon *io) -{ - struct tevent_req *req; - NTSTATUS status; - - if (!cldap->event.allow_poll) { - return NT_STATUS_INVALID_PIPE_STATE; - } - - if (cldap->searches.list) { - return NT_STATUS_PIPE_BUSY; - } - - req = cldap_netlogon_send(mem_ctx, cldap, io); - NT_STATUS_HAVE_NO_MEMORY(req); - - if (!tevent_req_poll(req, cldap->event.ctx)) { - talloc_free(req); - return NT_STATUS_INTERNAL_ERROR; - } - - status = cldap_netlogon_recv(req, iconv_convenience, mem_ctx, io); - talloc_free(req); - - return status; -} - - -/* - send an empty reply (used on any error, so the client doesn't keep waiting - or send the bad request again) -*/ -NTSTATUS cldap_empty_reply(struct cldap_socket *cldap, - uint32_t message_id, - struct tsocket_address *dest) -{ - NTSTATUS status; - struct cldap_reply reply; - struct ldap_Result result; - - reply.messageid = message_id; - reply.dest = dest; - reply.response = NULL; - reply.result = &result; - - ZERO_STRUCT(result); - - status = cldap_reply_send(cldap, &reply); - - return status; -} - -/* - send an error reply (used on any error, so the client doesn't keep waiting - or send the bad request again) -*/ -NTSTATUS cldap_error_reply(struct cldap_socket *cldap, - uint32_t message_id, - struct tsocket_address *dest, - int resultcode, - const char *errormessage) -{ - NTSTATUS status; - struct cldap_reply reply; - struct ldap_Result result; - - reply.messageid = message_id; - reply.dest = dest; - reply.response = NULL; - reply.result = &result; - - ZERO_STRUCT(result); - result.resultcode = resultcode; - result.errormessage = errormessage; - - status = cldap_reply_send(cldap, &reply); - - return status; -} - - -/* - send a netlogon reply -*/ -NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, - struct smb_iconv_convenience *iconv_convenience, - uint32_t message_id, - struct tsocket_address *dest, - uint32_t version, - struct netlogon_samlogon_response *netlogon) -{ - NTSTATUS status; - struct cldap_reply reply; - struct ldap_SearchResEntry response; - struct ldap_Result result; - TALLOC_CTX *tmp_ctx = talloc_new(cldap); - DATA_BLOB blob; - - status = push_netlogon_samlogon_response(&blob, tmp_ctx, - iconv_convenience, - netlogon); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(tmp_ctx); - return status; - } - reply.messageid = message_id; - reply.dest = dest; - reply.response = &response; - reply.result = &result; - - ZERO_STRUCT(result); - - response.dn = ""; - response.num_attributes = 1; - response.attributes = talloc(tmp_ctx, struct ldb_message_element); - NT_STATUS_HAVE_NO_MEMORY(response.attributes); - response.attributes->name = "netlogon"; - response.attributes->num_values = 1; - response.attributes->values = &blob; - - status = cldap_reply_send(cldap, &reply); - - talloc_free(tmp_ctx); - - return status; -} - diff --git a/source4/libcli/cldap/cldap.h b/source4/libcli/cldap/cldap.h deleted file mode 100644 index 111fa2cfc45..00000000000 --- a/source4/libcli/cldap/cldap.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - a async CLDAP library - - Copyright (C) Andrew Tridgell 2005 - - 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 . -*/ - -#include "../libcli/netlogon.h" - -struct ldap_message; -struct tsocket_address; -struct cldap_socket; - -struct cldap_incoming { - int recv_errno; - uint8_t *buf; - size_t len; - struct tsocket_address *src; - struct ldap_message *ldap_msg; -}; - -/* - a general cldap search request -*/ -struct cldap_search { - struct { - const char *dest_address; - uint16_t dest_port; - const char *filter; - const char * const *attributes; - int timeout; - int retries; - } in; - struct { - struct ldap_SearchResEntry *response; - struct ldap_Result *result; - } out; -}; - -NTSTATUS cldap_socket_init(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - const struct tsocket_address *local_addr, - const struct tsocket_address *remote_addr, - struct cldap_socket **_cldap); - -NTSTATUS cldap_set_incoming_handler(struct cldap_socket *cldap, - void (*handler)(struct cldap_socket *, - void *private_data, - struct cldap_incoming *), - void *private_data); -struct tevent_req *cldap_search_send(TALLOC_CTX *mem_ctx, - struct cldap_socket *cldap, - const struct cldap_search *io); -NTSTATUS cldap_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, - struct cldap_search *io); -NTSTATUS cldap_search(struct cldap_socket *cldap, TALLOC_CTX *mem_ctx, - struct cldap_search *io); - -/* - a general cldap reply -*/ -struct cldap_reply { - uint32_t messageid; - struct tsocket_address *dest; - struct ldap_SearchResEntry *response; - struct ldap_Result *result; -}; - -NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io); - -NTSTATUS cldap_empty_reply(struct cldap_socket *cldap, - uint32_t message_id, - struct tsocket_address *dst); -NTSTATUS cldap_error_reply(struct cldap_socket *cldap, - uint32_t message_id, - struct tsocket_address *dst, - int resultcode, - const char *errormessage); - -/* - a netlogon cldap request -*/ -struct cldap_netlogon { - struct { - const char *dest_address; - uint16_t dest_port; - const char *realm; - const char *host; - const char *user; - const char *domain_guid; - const char *domain_sid; - int acct_control; - uint32_t version; - bool map_response; - } in; - struct { - struct netlogon_samlogon_response netlogon; - } out; -}; - -struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx, - struct cldap_socket *cldap, - const struct cldap_netlogon *io); -NTSTATUS cldap_netlogon_recv(struct tevent_req *req, - struct smb_iconv_convenience *iconv_convenience, - TALLOC_CTX *mem_ctx, - struct cldap_netlogon *io); -NTSTATUS cldap_netlogon(struct cldap_socket *cldap, - struct smb_iconv_convenience *iconv_convenience, - TALLOC_CTX *mem_ctx, - struct cldap_netlogon *io); - -NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, - struct smb_iconv_convenience *iconv_convenience, - uint32_t message_id, - struct tsocket_address *dst, - uint32_t version, - struct netlogon_samlogon_response *netlogon); - diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index 1b87530af80..5b50bdfcbec 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -96,13 +96,6 @@ LIBCLI_DGRAM_OBJ_FILES = $(addprefix $(libclisrcdir)/dgram/, \ netlogon.o \ browse.o) -[SUBSYSTEM::LIBCLI_CLDAP] -PUBLIC_DEPENDENCIES = LIBCLI_LDAP -PRIVATE_DEPENDENCIES = LIBTSOCKET LIBSAMBA-UTIL UTIL_TEVENT LIBLDB LIBCLI_NETLOGON - -LIBCLI_CLDAP_OBJ_FILES = $(libclisrcdir)/cldap/cldap.o -# PUBLIC_HEADERS += $(libclisrcdir)/cldap/cldap.h - [SUBSYSTEM::LIBCLI_WREPL] PUBLIC_DEPENDENCIES = NDR_WINSREPL samba_socket LIBEVENTS LIBPACKET -- cgit