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 56d4c4fe36..5a9926b6d1 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 898d913965..7883bccfe7 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 a30273fc66..7d2c7d0547 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 56eb7ce0c0..a4dfaea7eb 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 6860e56e7f..bd98a400be 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 f8029b246b..9e02c90396 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 add06522c6..1f22c39842 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 aea5d08c3f..f4ba6b7157 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 61c8009716..820fb7d39e 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 f4ba6b7157..4ebbaaeffc 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 820fb7d39e..7d14c0e502 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 9e02c90396..c16def09d2 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 1f22c39842..b7ee2386da 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 b7ee2386da..71c1ce9e99 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 733d12a443..2f4ab2c178 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 240a994f9d..8ad8f47cd6 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 048f255ffc..cb875c9eee 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 46f45a1bf3..eaefbd5148 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 11bec42737..3fd9a38e01 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 d1d5b842c3..3cc3ec2f25 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 4e7cdf5c3a..7f544b5922 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 d820983022..5f0293c681 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 6d898a128c..febfbe03ec 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 c16def09d2..2bdcc3fdaf 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 71c1ce9e99..5624e68d03 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 5624e68d03..c50cbfbaee 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 cb875c9eee..b7f2d3c410 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 3fd9a38e01..b522a56239 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 3cc3ec2f25..7c07c84740 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 db22a85492..062fa41889 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 9de5b1cc0c..d0d0a575d8 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 8ea9727ed3..a143604f33 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 240f2b1dc2..1a08cd21f9 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 0df35be6fd..33c0adc3b1 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 daa5060d07..7e867deff2 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 b18ba12b1f..0f2175b42d 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 8951daa775..111fa2cfc4 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 dc3431ab9f..1b87530af8 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 bf046745e6..dbbabd6a6d 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 4a32ab92ed..8a002b24a4 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 3f92daab28..e0e5e42115 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 1ddc628a5c..98669288a8 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 ae2cb80836..a422732b03 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 847b32827b..1aaf914ceb 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 d0d0a575d8..280d60beb2 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 0f2175b42d..0000000000 --- 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 111fa2cfc4..0000000000 --- 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 1b87530af8..5b50bdfcbe 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 From 722dc9eed3798db0d3795bdf70ce10e6d402705a Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 20 Mar 2009 00:33:43 +0100 Subject: pyldb: Improve exception message when a list is expected. --- source4/lib/ldb/pyldb.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'source4') diff --git a/source4/lib/ldb/pyldb.c b/source4/lib/ldb/pyldb.c index 81b960979f..7ff4bf4aad 100644 --- a/source4/lib/ldb/pyldb.c +++ b/source4/lib/ldb/pyldb.c @@ -469,19 +469,20 @@ static PyObject *py_ldb_get_default_basedn(PyLdbObject *self) return PyLdbDn_FromDn(dn); } -static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list) +static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list, + const char *paramname) { const char **ret; int i; if (!PyList_Check(list)) { - PyErr_SetString(PyExc_TypeError, "options is not a list"); + PyErr_Format(PyExc_TypeError, "%s is not a list", paramname); return NULL; } ret = talloc_array(NULL, const char *, PyList_Size(list)+1); for (i = 0; i < PyList_Size(list); i++) { PyObject *item = PyList_GetItem(list, i); if (!PyString_Check(item)) { - PyErr_SetString(PyExc_TypeError, "options should be strings"); + PyErr_Format(PyExc_TypeError, "%s should be strings", paramname); return NULL; } ret[i] = PyString_AsString(item); @@ -510,7 +511,7 @@ static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs) if (py_options == Py_None) { options = NULL; } else { - options = PyList_AsStringList(ldb, py_options); + options = PyList_AsStringList(ldb, py_options, "options"); if (options == NULL) return -1; } @@ -563,7 +564,7 @@ static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwa if (py_options == Py_None) { options = NULL; } else { - options = PyList_AsStringList(NULL, py_options); + options = PyList_AsStringList(NULL, py_options, "options"); if (options == NULL) return NULL; } @@ -813,7 +814,7 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar if (py_attrs == Py_None) { attrs = NULL; } else { - attrs = PyList_AsStringList(ldb_ctx, py_attrs); + attrs = PyList_AsStringList(ldb_ctx, py_attrs, "attrs"); if (attrs == NULL) return NULL; } @@ -828,7 +829,7 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar if (py_controls == Py_None) { parsed_controls = NULL; } else { - const char **controls = PyList_AsStringList(ldb_ctx, py_controls); + const char **controls = PyList_AsStringList(ldb_ctx, py_controls, "controls"); parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls); talloc_free(controls); } @@ -1129,7 +1130,7 @@ static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, P mod = self->mod; ret = ldb_build_search_req(&req, mod->ldb, NULL, PyLdbDn_AsDn(py_base), - scope, NULL /* expr */, py_attrs == Py_None?NULL:PyList_AsStringList(req, py_attrs), + scope, NULL /* expr */, py_attrs == Py_None?NULL:PyList_AsStringList(req, py_attrs, "attrs"), NULL /* controls */, NULL, NULL, NULL); PyErr_LDB_ERROR_IS_ERR_RAISE(ret, mod->ldb); -- cgit From ec9aeeab00584f4d3dfe9afb83dc1a77b8463b81 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 20 Mar 2009 01:29:31 +0100 Subject: Fix up minschema after the conversion from JavaScript. Pair programmed over the phone with Andrew :-) --- source4/scripting/bin/minschema | 165 +++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 88 deletions(-) (limited to 'source4') diff --git a/source4/scripting/bin/minschema b/source4/scripting/bin/minschema index e7d7ed4979..f2dfdcb564 100755 --- a/source4/scripting/bin/minschema +++ b/source4/scripting/bin/minschema @@ -3,9 +3,10 @@ # work out the minimal schema for a set of objectclasses # +import base64 import optparse - -import os, sys +import os +import sys # Find right directory when running from source tree sys.path.insert(0, "bin/python") @@ -54,10 +55,10 @@ if len(args) != 2: lp_ctx = sambaopts.get_loadparm() creds = credopts.get_credentials(lp_ctx) -ldb = Ldb(url, credentials=creds) +ldb = Ldb(url, credentials=creds, lp=lp_ctx) -objectclasses = [] -attributes = [] +objectclasses = {} +attributes = {} objectclasses_expanded = set() @@ -136,24 +137,25 @@ attrib_attrs = ["objectClass", def get_object_cn(ldb, name): attrs = ["cn"] - - res = ldb.search("(ldapDisplayName=%s)" % name, rootDse["schemaNamingContext"], SCOPE_SUBTREE, attrs) + res = ldb.search(expression="(ldapDisplayName=%s)" % name, base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE, attrs=attrs) assert len(res) == 1 - return res[0]["cn"] -class Objectclass: + +class Objectclass(dict): + def __init__(self, ldb, name): """create an objectclass object""" self.name = name - self.cn = get_object_cn(ldb, name) + self["cn"] = get_object_cn(ldb, name) + +class Attribute(dict): -class Attribute: def __init__(self, ldb, name): """create an attribute object""" self.name = name - self.cn = get_object_cn(ldb, name) + self["cn"] = get_object_cn(ldb, name) syntaxmap = dict() @@ -180,36 +182,38 @@ syntaxmap['2.5.5.17'] = '1.3.6.1.4.1.1466.115.121.1.40' def map_attribute_syntax(s): """map some attribute syntaxes from some apparently MS specific syntaxes to the standard syntaxes""" - if syntaxmap.has_key(s): + if s in list(syntaxmap): return syntaxmap[s] return s def fix_dn(dn): """fix a string DN to use ${SCHEMADN}""" - return dn.replace(rootDse["schemaNamingContext"], "${SCHEMADN}") + return dn.replace(rootDse["schemaNamingContext"][0], "${SCHEMADN}") def write_ldif_one(o, attrs): """dump an object as ldif""" - print "dn: CN=%s,${SCHEMADN}\n" % o["cn"] + print "dn: CN=%s,${SCHEMADN}" % o["cn"] for a in attrs: if not o.has_key(a): continue # special case for oMObjectClass, which is a binary object - if a == "oMObjectClass": - print "%s:: %s\n" % (a, o[a]) - continue v = o[a] - if isinstance(v, str): - v = [v] for j in v: - print "%s: %s\n" % (a, fix_dn(j)) - print "\n" + value = fix_dn(j) + if a == "oMObjectClass": + print "%s:: %s" % (a, base64.b64encode(value)) + elif a.endswith("GUID"): + print "%s: %s" % (a, ldb.schema_format_value(a, value)) + else: + print "%s: %s" % (a, value) + print "" + def write_ldif(o, attrs): """dump an array of objects as ldif""" - for i in o: + for n, i in o.items(): write_ldif_one(i, attrs) @@ -225,7 +229,7 @@ def find_objectclass_properties(ldb, o): """the properties of an objectclass""" res = ldb.search( expression="(ldapDisplayName=%s)" % o.name, - base=rootDse["schemaNamingContext"], scope=SCOPE_SUBTREE, attrs=class_attrs) + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE, attrs=class_attrs) assert(len(res) == 1) msg = res[0] for a in msg: @@ -235,15 +239,11 @@ def find_attribute_properties(ldb, o): """find the properties of an attribute""" res = ldb.search( expression="(ldapDisplayName=%s)" % o.name, - base=rootDse["schemaNamingContext"], scope=SCOPE_SUBTREE, + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE, attrs=attrib_attrs) assert(len(res) == 1) msg = res[0] for a in msg: - # special case for oMObjectClass, which is a binary object - if a == "oMObjectClass": - o[a] = ldb.encode(msg[a]) - continue o[a] = msg[a] @@ -254,15 +254,15 @@ def find_objectclass_auto(ldb, o): return testdn = create_testdn(o.exampleDN) - print "testdn is '%s'\n" % testdn + print "testdn is '%s'" % testdn ldif = "dn: " + testdn ldif += "\nobjectClass: " + o.name try: ldb.add(ldif) except LdbError, e: - print "error adding %s: %s\n" % (o.name, e) - print "%s\n" % ldif + print "error adding %s: %s" % (o.name, e) + print "%s" % ldif return res = ldb.search(base=testdn, scope=ldb.SCOPE_BASE) @@ -280,20 +280,20 @@ def expand_objectclass(ldb, o): "subClassOf"] res = ldb.search( expression="(&(objectClass=classSchema)(ldapDisplayName=%s))" % o.name, - base=rootDse["schemaNamingContext"], scope=SCOPE_SUBTREE, + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE, attrs=attrs) - print "Expanding class %s\n" % o.name + print >>sys.stderr, "Expanding class %s" % o.name assert(len(res) == 1) msg = res[0] - for a in attrs: - if not msg.has_key(aname): + for aname in attrs: + if not aname in msg: continue list = msg[aname] if isinstance(list, str): list = [msg[aname]] for name in list: if not objectclasses.has_key(name): - print "Found new objectclass '%s'\n" % name + print >>sys.stderr, "Found new objectclass '%s'" % name objectclasses[name] = Objectclass(ldb, name) @@ -320,13 +320,13 @@ def walk_dn(ldb, dn): try: res = ldb.search("objectClass=*", dn, SCOPE_BASE, attrs) except LdbError, e: - print "Unable to fetch allowedAttributes for '%s' - %r\n" % (dn, e) + print >>sys.stderr, "Unable to fetch allowedAttributes for '%s' - %r" % (dn, e) return allattrs = res[0]["allowedAttributes"] try: res = ldb.search("objectClass=*", dn, SCOPE_BASE, allattrs) except LdbError, e: - print "Unable to fetch all attributes for '%s' - %s\n" % (dn, e) + print >>sys.stderr, "Unable to fetch all attributes for '%s' - %s" % (dn, e) return msg = res[0] for a in msg: @@ -339,7 +339,7 @@ def walk_naming_context(ldb, namingContext): res = ldb.search("objectClass=*", namingContext, SCOPE_DEFAULT, ["objectClass"]) except LdbError, e: - print "Unable to fetch objectClasses for '%s' - %s\n" % (namingContext, e) + print >>sys.stderr, "Unable to fetch objectClasses for '%s' - %s" % (namingContext, e) return for msg in res: msg = res.msgs[r]["objectClass"] @@ -356,12 +356,9 @@ def trim_objectclass_attributes(ldb, objectclass): if objectclass.has_key("possibleInferiors"): possinf = objectclass["possibleInferiors"] newpossinf = [] - if isinstance(possinf, str): - possinf = [possinf] for x in possinf: if objectclasses.has_key(x): - newpossinf[n] = x - n+=1 + newpossinf.append(x) objectclass["possibleInferiors"] = newpossinf # trim systemMayContain, @@ -369,8 +366,6 @@ def trim_objectclass_attributes(ldb, objectclass): if objectclass.has_key("systemMayContain"): sysmay = objectclass["systemMayContain"] newsysmay = [] - if isinstance(sysmay, str): - sysmay = [sysmay] for x in sysmay: if not x in newsysmay: newsysmay.append(x) @@ -378,7 +373,7 @@ def trim_objectclass_attributes(ldb, objectclass): # trim mayContain, # remove duplicates - if not objectclass.has_key("mayContain"): + if objectclass.has_key("mayContain"): may = objectclass["mayContain"] newmay = [] if isinstance(may, str): @@ -388,30 +383,24 @@ def trim_objectclass_attributes(ldb, objectclass): newmay.append(x) objectclass["mayContain"] = newmay + def build_objectclass(ldb, name): """load the basic attributes of an objectClass""" attrs = ["name"] - try: - res = ldb.search( - expression="(&(objectClass=classSchema)(ldapDisplayName=%s))" % name, - base=rootDse["schemaNamingContext"], scope=SCOPE_SUBTREE, - attrs=attrs) - except LdbError, e: - print "unknown class '%s'\n" % name - return None + res = ldb.search( + expression="(&(objectClass=classSchema)(ldapDisplayName=%s))" % name, + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE, + attrs=attrs) if len(res) == 0: - print "unknown class '%s'\n" % name + print >>sys.stderr, "unknown class '%s'" % name return None return Objectclass(ldb, name) + def attribute_list(objectclass, attr1, attr2): """form a coalesced attribute list""" - a1 = objectclass[attr1] - a2 = objectclass[attr2] - if isinstance(a1, str): - a1 = [a1] - if isinstance(a2, str): - a2 = [a2] + a1 = list(objectclass.get(attr1, [])) + a2 = list(objectclass.get(attr2, [])) return a1 + a2 def aggregate_list(name, list): @@ -422,15 +411,15 @@ def aggregate_list(name, list): def write_aggregate_objectclass(objectclass): """write the aggregate record for an objectclass""" - print "objectClasses: ( %s NAME '%s' " % (objectclass.governsID, objectclass.name) + print "objectClasses: ( %s NAME '%s' " % (objectclass["governsID"], objectclass.name), if not objectclass.has_key('subClassOf'): - print "SUP %s " % objectclass['subClassOf'] - if objectclass.objectClassCategory == 1: - print "STRUCTURAL " - elif objectclass.objectClassCategory == 2: - print "ABSTRACT " - elif objectclass.objectClassCategory == 3: - print "AUXILIARY " + print "SUP %s " % objectclass['subClassOf'], + if objectclass["objectClassCategory"] == 1: + print "STRUCTURAL ", + elif objectclass["objectClassCategory"] == 2: + print "ABSTRACT ", + elif objectclass["objectClassCategory"] == 3: + print "AUXILIARY ", list = attribute_list(objectclass, "systemMustContain", "mustContain") aggregate_list("MUST", list) @@ -438,7 +427,7 @@ def write_aggregate_objectclass(objectclass): list = attribute_list(objectclass, "systemMayContain", "mayContain") aggregate_list("MAY", list) - print ")\n" + print ")" def write_aggregate_ditcontentrule(objectclass): @@ -447,12 +436,12 @@ def write_aggregate_ditcontentrule(objectclass): if list is None: return - print "dITContentRules: ( %s NAME '%s' " % (objectclass.governsID, objectclass.name) + print "dITContentRules: ( %s NAME '%s' " % (objectclass["governsID"], objectclass.name) aggregate_list("AUX", list) - may_list = None - must_list = None + may_list = [] + must_list = [] for c in list: list2 = attribute_list(objectclasses[c], @@ -470,11 +459,11 @@ def write_aggregate_ditcontentrule(objectclass): def write_aggregate_attribute(attrib): """write the aggregate record for an attribute""" print "attributeTypes: ( %s NAME '%s' SYNTAX '%s' " % ( - attrib.attributeID, attrib.name, - map_attribute_syntax(attrib.attributeSyntax)) - if attrib['isSingleValued'] == "TRUE": + attrib["attributeID"], attrib.name, + map_attribute_syntax(attrib["attributeSyntax"])) + if attrib.get('isSingleValued') == "TRUE": print "SINGLE-VALUE " - if attrib['systemOnly'] == "TRUE": + if attrib.get('systemOnly') == "TRUE": print "NO-USER-MODIFICATION " print ")\n" @@ -490,16 +479,16 @@ objectCategory: CN=SubSchema,${SCHEMADN} if not opts.dump_subschema_auto: return - for objectclass in objectclasses: + for objectclass in objectclasses.values(): write_aggregate_objectclass(objectclass) - for attr in attributes: + for attr in attributes.values(): write_aggregate_attribute(attr) - for objectclass in objectclasses: + for objectclass in objectclasses.values(): write_aggregate_ditcontentrule(objectclass) def load_list(file): """load a list from a file""" - return open(file, 'r').readlines() + return [l.strip("\n") for l in open(file, 'r').readlines()] # get the rootDSE res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"]) @@ -523,32 +512,32 @@ expanded = 0 # than necessary to recursively expand all classes # for inf in range(500): - for n in objectclasses: + for n, o in objectclasses.items(): if not n in objectclasses_expanded: - expand_objectclass(ldb, objectclasses[i]) + expand_objectclass(ldb, o) objectclasses_expanded.add(n) # # find objectclass properties # -for objectclass in objectclasses: +for name, objectclass in objectclasses.items(): find_objectclass_properties(ldb, objectclass) # # form the full list of attributes # -for objectclass in objectclasses: +for name, objectclass in objectclasses.items(): add_objectclass_attributes(ldb, objectclass) # and attribute properties -for attr in attributes: +for name, attr in attributes.items(): find_attribute_properties(ldb, attr) # # trim the 'may' attribute lists to those really needed # -for objectclass in objectclasses: +for name, objectclass in objectclasses.items(): trim_objectclass_attributes(ldb, objectclass) # -- cgit From 1dc5b90e86fdee2978f5608f483c3b11c86fb9bc Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 20 Mar 2009 16:26:42 +1100 Subject: s4:ldb Fix the paged_searches module This simplifies the code, removes presumptions about being the only control in the reply, and allows it to function against Windows 2008. For searches which did not require a paged result, the module was simply returning a failure when the compleated search did not include a paged result control. Andrew Bartlett --- source4/lib/ldb/modules/paged_searches.c | 109 +++++++++++++++---------------- 1 file changed, 51 insertions(+), 58 deletions(-) (limited to 'source4') diff --git a/source4/lib/ldb/modules/paged_searches.c b/source4/lib/ldb/modules/paged_searches.c index 01e77cb22c..70b880e2dd 100644 --- a/source4/lib/ldb/modules/paged_searches.c +++ b/source4/lib/ldb/modules/paged_searches.c @@ -2,6 +2,7 @@ ldb database library Copyright (C) Simo Sorce 2005-2008 + Copyright (C) Andrew Bartlett 2009 ** NOTE! The following LGPL license applies to the ldb ** library. This does NOT imply that all of Samba is released @@ -52,23 +53,40 @@ struct ps_context { char **saved_referrals; int num_referrals; + + struct ldb_request *down_req; }; -static int check_ps_continuation(struct ldb_request *req, struct ldb_reply *ares) +static int check_ps_continuation(struct ps_context *ac, struct ldb_request *req, struct ldb_reply *ares) { - struct ps_context *ac; - struct ldb_paged_control *rep_control, *req_control; + struct ldb_context *ldb; + struct ldb_control *rep_control, *req_control; + struct ldb_paged_control *paged_rep_control = NULL, *paged_req_control = NULL; + ldb = ldb_module_get_ctx(ac->module); - ac = talloc_get_type(req->context, struct ps_context); + rep_control = ldb_reply_get_control(ares, LDB_CONTROL_PAGED_RESULTS_OID); + if (rep_control) { + paged_rep_control = talloc_get_type(rep_control->data, struct ldb_paged_control); + } - /* look up our paged control */ - if (!ares->controls || strcmp(LDB_CONTROL_PAGED_RESULTS_OID, ares->controls[0]->oid) != 0) { - /* something wrong here */ - return LDB_ERR_OPERATIONS_ERROR; + req_control = ldb_request_get_control(req, LDB_CONTROL_PAGED_RESULTS_OID); + paged_req_control = talloc_get_type(req_control->data, struct ldb_paged_control); + + if (!rep_control || !paged_rep_control) { + if (paged_req_control->cookie) { + /* something wrong here - why give us a control back befre, but not one now? */ + ldb_set_errstring(ldb, "paged_searches: ERROR: We got back a control from a previous page, but this time no control was returned!"); + return LDB_ERR_OPERATIONS_ERROR; + } else { + /* No cookie recived yet, valid to just return the full data set */ + + /* we are done */ + ac->pending = false; + return LDB_SUCCESS; + } } - rep_control = talloc_get_type(ares->controls[0]->data, struct ldb_paged_control); - if (rep_control->cookie_len == 0) { + if (paged_rep_control->cookie_len == 0) { /* we are done */ ac->pending = false; return LDB_SUCCESS; @@ -79,21 +97,14 @@ static int check_ps_continuation(struct ldb_request *req, struct ldb_reply *ares /* if there's a reply control we must find a request * control matching it */ - if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, req->controls[0]->oid) != 0) { - /* something wrong here */ - return LDB_ERR_OPERATIONS_ERROR; - } - - req_control = talloc_get_type(req->controls[0]->data, struct ldb_paged_control); - - if (req_control->cookie) { - talloc_free(req_control->cookie); + if (paged_req_control->cookie) { + talloc_free(paged_req_control->cookie); } - req_control->cookie = talloc_memdup(req_control, - rep_control->cookie, - rep_control->cookie_len); - req_control->cookie_len = rep_control->cookie_len; + paged_req_control->cookie = talloc_memdup(req_control, + paged_rep_control->cookie, + paged_rep_control->cookie_len); + paged_req_control->cookie_len = paged_rep_control->cookie_len; ac->pending = true; return LDB_SUCCESS; @@ -141,8 +152,6 @@ static int send_referrals(struct ps_context *ac) return LDB_SUCCESS; } -static int ps_next_request(struct ps_context *ac); - static int ps_callback(struct ldb_request *req, struct ldb_reply *ares) { struct ps_context *ac; @@ -176,14 +185,15 @@ static int ps_callback(struct ldb_request *req, struct ldb_reply *ares) case LDB_REPLY_DONE: - ret = check_ps_continuation(req, ares); + ret = check_ps_continuation(ac, req, ares); if (ret != LDB_SUCCESS) { return ldb_module_done(ac->req, NULL, NULL, ret); } if (ac->pending) { - ret = ps_next_request(ac); + ret = ldb_next_request(ac->module, ac->down_req); + if (ret != LDB_SUCCESS) { return ldb_module_done(ac->req, NULL, NULL, ret); @@ -214,6 +224,8 @@ static int ps_search(struct ldb_module *module, struct ldb_request *req) struct ldb_context *ldb; struct private_data *private_data; struct ps_context *ac; + struct ldb_paged_control *control; + int ret; private_data = talloc_get_type(ldb_module_get_private(module), struct private_data); ldb = ldb_module_get_ctx(module); @@ -238,30 +250,9 @@ static int ps_search(struct ldb_module *module, struct ldb_request *req) ac->saved_referrals = NULL; ac->num_referrals = 0; - return ps_next_request(ac); -} - -static int ps_next_request(struct ps_context *ac) { - - struct ldb_context *ldb; - struct ldb_paged_control *control; - struct ldb_control **controls; - struct ldb_request *new_req; - int ret; - ldb = ldb_module_get_ctx(ac->module); - controls = talloc_array(ac, struct ldb_control *, 2); - if (!controls) { - return LDB_ERR_OPERATIONS_ERROR; - } - - controls[0] = talloc(controls, struct ldb_control); - if (!controls[0]) { - return LDB_ERR_OPERATIONS_ERROR; - } - - control = talloc(controls[0], struct ldb_paged_control); + control = talloc(ac, struct ldb_paged_control); if (!control) { return LDB_ERR_OPERATIONS_ERROR; } @@ -270,26 +261,28 @@ static int ps_next_request(struct ps_context *ac) { control->cookie = NULL; control->cookie_len = 0; - controls[0]->oid = LDB_CONTROL_PAGED_RESULTS_OID; - controls[0]->critical = 1; - controls[0]->data = control; - controls[1] = NULL; - - ret = ldb_build_search_req_ex(&new_req, ldb, ac, + ret = ldb_build_search_req_ex(&ac->down_req, ldb, ac, ac->req->op.search.base, ac->req->op.search.scope, ac->req->op.search.tree, ac->req->op.search.attrs, - controls, + ac->req->controls, ac, ps_callback, ac->req); if (ret != LDB_SUCCESS) { return ret; } - talloc_steal(new_req, controls); - return ldb_next_request(ac->module, new_req); + ret = ldb_request_add_control(ac->down_req, LDB_CONTROL_PAGED_RESULTS_OID, + true, control); + if (ret != LDB_SUCCESS) { + return ret; + } + + talloc_steal(ac->down_req, control); + + return ldb_next_request(ac->module, ac->down_req); } static int check_supported_paged(struct ldb_request *req, -- cgit From 6906c01cac226db508cd56a31b751eee3ac62bc9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 20 Mar 2009 16:25:01 +1100 Subject: s4:ldb Ensure to pass down options to LDB from python This is needed for things such as to load modules, like the paged_searches module. Andrew Bartlett --- source4/scripting/python/samba/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4') diff --git a/source4/scripting/python/samba/__init__.py b/source4/scripting/python/samba/__init__.py index a49e6e1ead..c5827b96e0 100644 --- a/source4/scripting/python/samba/__init__.py +++ b/source4/scripting/python/samba/__init__.py @@ -54,7 +54,7 @@ class Ldb(ldb.Ldb): functions see samdb.py. """ def __init__(self, url=None, session_info=None, credentials=None, - modules_dir=None, lp=None): + modules_dir=None, lp=None, options=None): """Open a Samba Ldb file. :param url: Optional LDB URL to open @@ -67,7 +67,7 @@ class Ldb(ldb.Ldb): modules-dir is used by default and that credentials and session_info can be passed through (required by some modules). """ - super(Ldb, self).__init__() + super(Ldb, self).__init__(options=options) if modules_dir is not None: self.set_modules_dir(modules_dir) @@ -90,7 +90,7 @@ class Ldb(ldb.Ldb): #self.set_debug(msg) if url is not None: - self.connect(url) + self.connect(url, options=options) def set_credentials(self, credentials): glue.ldb_set_credentials(self, credentials) -- cgit From 5bfed623f5115a774f47e1cdceed862c53cd40a1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 20 Mar 2009 13:55:43 +1100 Subject: s4:minschma Fix aggregate schema generation in minschema The conversion from EJS to python I did with Jelmer this morning was not quite complete, due mostly to the difference between print in EJS and python (python implies a newline). Andrew Bartlett --- source4/scripting/bin/minschema | 47 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 24 deletions(-) (limited to 'source4') diff --git a/source4/scripting/bin/minschema b/source4/scripting/bin/minschema index f2dfdcb564..4983502ba7 100755 --- a/source4/scripting/bin/minschema +++ b/source4/scripting/bin/minschema @@ -405,40 +405,40 @@ def attribute_list(objectclass, attr1, attr2): def aggregate_list(name, list): """write out a list in aggregate form""" - if list is None: - return - print "%s ( %s )" % (name, "$ ".join(list)) + if list == []: + return "" + return " %s ( %s )" % (name, " $ ".join(list)) def write_aggregate_objectclass(objectclass): """write the aggregate record for an objectclass""" - print "objectClasses: ( %s NAME '%s' " % (objectclass["governsID"], objectclass.name), + line = "objectClasses: ( %s NAME '%s' " % (objectclass["governsID"], objectclass.name) if not objectclass.has_key('subClassOf'): - print "SUP %s " % objectclass['subClassOf'], + line += "SUP %s" % objectclass['subClassOf'] if objectclass["objectClassCategory"] == 1: - print "STRUCTURAL ", + line += "STRUCTURAL" elif objectclass["objectClassCategory"] == 2: - print "ABSTRACT ", + line += "ABSTRACT" elif objectclass["objectClassCategory"] == 3: - print "AUXILIARY ", + line += "AUXILIARY" list = attribute_list(objectclass, "systemMustContain", "mustContain") - aggregate_list("MUST", list) + line += aggregate_list("MUST", list) list = attribute_list(objectclass, "systemMayContain", "mayContain") - aggregate_list("MAY", list) + line += aggregate_list("MAY", list) - print ")" + print line + " )" def write_aggregate_ditcontentrule(objectclass): """write the aggregate record for an ditcontentrule""" list = attribute_list(objectclass, "auxiliaryClass", "systemAuxiliaryClass") - if list is None: + if list == []: return - print "dITContentRules: ( %s NAME '%s' " % (objectclass["governsID"], objectclass.name) + line = "dITContentRules: ( %s NAME '%s'" % (objectclass["governsID"], objectclass.name) - aggregate_list("AUX", list) + line += aggregate_list("AUX", list) may_list = [] must_list = [] @@ -451,31 +451,30 @@ def write_aggregate_ditcontentrule(objectclass): "mustContain", "systemMustContain") must_list = must_list + list2 - aggregate_list("MUST", must_list) - aggregate_list("MAY", may_list) + line += aggregate_list("MUST", must_list) + line += aggregate_list("MAY", may_list) - print ")\n" + print line + " )" def write_aggregate_attribute(attrib): """write the aggregate record for an attribute""" - print "attributeTypes: ( %s NAME '%s' SYNTAX '%s' " % ( + line = "attributeTypes: ( %s NAME '%s' SYNTAX '%s' " % ( attrib["attributeID"], attrib.name, map_attribute_syntax(attrib["attributeSyntax"])) if attrib.get('isSingleValued') == "TRUE": - print "SINGLE-VALUE " + line += "SINGLE-VALUE " if attrib.get('systemOnly') == "TRUE": - print "NO-USER-MODIFICATION " + line += "NO-USER-MODIFICATION " - print ")\n" + print line + ")" def write_aggregate(): """write the aggregate record""" - print "dn: CN=Aggregate,${SCHEMADN}\n" + print "dn: CN=Aggregate,${SCHEMADN}" print """objectClass: top objectClass: subSchema -objectCategory: CN=SubSchema,${SCHEMADN} -""" +objectCategory: CN=SubSchema,${SCHEMADN}""" if not opts.dump_subschema_auto: return -- cgit From 653dd024a630af095277f5884add9246da399eb9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 20 Mar 2009 16:07:49 +1100 Subject: Add minschema like tool to extract and dump the full schema from AD --- source4/scripting/bin/fullschema | 191 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 source4/scripting/bin/fullschema (limited to 'source4') diff --git a/source4/scripting/bin/fullschema b/source4/scripting/bin/fullschema new file mode 100644 index 0000000000..02e90f6973 --- /dev/null +++ b/source4/scripting/bin/fullschema @@ -0,0 +1,191 @@ +#!/usr/bin/python +# +# work out the minimal schema for a set of objectclasses +# + +import base64 +import optparse +import os +import sys + +# Find right directory when running from source tree +sys.path.insert(0, "bin/python") + +import samba +from samba import getopt as options, Ldb +from ldb import SCOPE_SUBTREE, SCOPE_BASE, LdbError +import sys + +parser = optparse.OptionParser("fullschema ") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +credopts = options.CredentialsOptions(parser) +parser.add_option_group(credopts) +parser.add_option_group(options.VersionOptions(parser)) +parser.add_option("--verbose", help="Be verbose", action="store_true") +parser.add_option("--dump-classes", action="store_true") +parser.add_option("--dump-attributes", action="store_true") + +opts, args = parser.parse_args() +opts.dump_all = True + +if opts.dump_classes: + opts.dump_all = False +if opts.dump_attributes: + opts.dump_all = False +if opts.dump_all: + opts.dump_classes = True + opts.dump_attributes = True + +if len(args) != 1: + parser.print_usage() + sys.exit(1) + +url = args[0] + +lp_ctx = sambaopts.get_loadparm() + +creds = credopts.get_credentials(lp_ctx) +ldb = Ldb(url, credentials=creds, lp=lp_ctx, options=["modules:paged_searches"]) + +objectclasses = {} +attributes = {} + +# the attributes we need for objectclasses +class_attrs = ["objectClass", + "cn", + "subClassOf", + "governsID", + "possSuperiors", + "possibleInferiors", + "mayContain", + "mustContain", + "auxiliaryClass", + "rDNAttID", + "showInAdvancedViewOnly", + "adminDisplayName", + "adminDescription", + "objectClassCategory", + "lDAPDisplayName", + "schemaIDGUID", + "systemOnly", + "systemPossSuperiors", + "systemMayContain", + "systemMustContain", + "systemAuxiliaryClass", + "defaultSecurityDescriptor", + "systemFlags", + "defaultHidingValue", + "defaultObjectCategory", + + # this attributes are not used by w2k3 + "schemaFlagsEx", + "msDs-IntId", + "msDs-Schema-Extensions", + "classDisplayName", + "isDefunct"] + +attrib_attrs = ["objectClass", + "cn", + "attributeID", + "attributeSyntax", + "isSingleValued", + "rangeLower", + "rangeUpper", + "mAPIID", + "linkID", + "showInAdvancedViewOnly", + "adminDisplayName", + "oMObjectClass", + "adminDescription", + "oMSyntax", + "searchFlags", + "extendedCharsAllowed", + "lDAPDisplayName", + "schemaIDGUID", + "attributeSecurityGUID", + "systemOnly", + "systemFlags", + "isMemberOfPartialAttributeSet", + + # this attributes are not used by w2k3 + "schemaFlagsEx", + "msDs-IntId", + "msDs-Schema-Extensions", + "classDisplayName", + "isEphemeral", + "isDefunct"] + +# +# notes: +# +# objectClassCategory +# 1: structural +# 2: abstract +# 3: auxiliary + +class Objectclass(dict): + + def __init__(self, ldb, name): + """create an objectclass object""" + self.name = name + + +class Attribute(dict): + + def __init__(self, ldb, name): + """create an attribute object""" + self.name = name + self["cn"] = get_object_cn(ldb, name) + + + +def fix_dn(dn): + """fix a string DN to use ${SCHEMADN}""" + return dn.replace(rootDse["schemaNamingContext"][0], "${SCHEMADN}") + + +def write_ldif_one(o, attrs): + """dump an object as ldif""" + print "dn: CN=%s,${SCHEMADN}" % o["cn"] + for a in attrs: + if not o.has_key(a): + continue + # special case for oMObjectClass, which is a binary object + v = o[a] + for j in v: + value = fix_dn(j) + if a != "cn": + if a == "oMObjectClass": + print "%s:: %s" % (a, base64.b64encode(value)) + elif a.endswith("GUID"): + print "%s: %s" % (a, ldb.schema_format_value(a, value)) + else: + print "%s: %s" % (a, value) + print "" + + +# get the rootDSE +res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"]) +rootDse = res[0] + +if opts.dump_attributes: + res = ldb.search(expression="objectClass=attributeSchema", + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=attrib_attrs) + + for msg in res: + o = Objectclass(ldb, msg["ldapDisplayName"]) + for a in msg: + o[a] = msg[a] + write_ldif_one(o, attrib_attrs) + +if opts.dump_classes: + res = ldb.search(expression="objectClass=classSchema", + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=class_attrs) + + for msg in res: + o = Objectclass(ldb, msg["ldapDisplayName"]) + for a in msg: + o[a] = msg[a] + write_ldif_one(o, class_attrs) + -- cgit From f696bb81f8499443eee9815e7adf8dbb6810506a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 20 Mar 2009 16:18:40 +1100 Subject: s4: Remove autogenerated attributes from minschema and fullschema output These attributes will be generated by Samba on import, and do not need to be in the schema file. Andrew Bartlett --- source4/scripting/bin/fullschema | 14 -------------- source4/scripting/bin/minschema | 2 -- 2 files changed, 16 deletions(-) (limited to 'source4') diff --git a/source4/scripting/bin/fullschema b/source4/scripting/bin/fullschema index 02e90f6973..d3bf398e65 100644 --- a/source4/scripting/bin/fullschema +++ b/source4/scripting/bin/fullschema @@ -22,7 +22,6 @@ parser.add_option_group(sambaopts) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) parser.add_option_group(options.VersionOptions(parser)) -parser.add_option("--verbose", help="Be verbose", action="store_true") parser.add_option("--dump-classes", action="store_true") parser.add_option("--dump-attributes", action="store_true") @@ -48,9 +47,6 @@ lp_ctx = sambaopts.get_loadparm() creds = credopts.get_credentials(lp_ctx) ldb = Ldb(url, credentials=creds, lp=lp_ctx, options=["modules:paged_searches"]) -objectclasses = {} -attributes = {} - # the attributes we need for objectclasses class_attrs = ["objectClass", "cn", @@ -62,7 +58,6 @@ class_attrs = ["objectClass", "mustContain", "auxiliaryClass", "rDNAttID", - "showInAdvancedViewOnly", "adminDisplayName", "adminDescription", "objectClassCategory", @@ -94,7 +89,6 @@ attrib_attrs = ["objectClass", "rangeUpper", "mAPIID", "linkID", - "showInAdvancedViewOnly", "adminDisplayName", "oMObjectClass", "adminDescription", @@ -116,14 +110,6 @@ attrib_attrs = ["objectClass", "isEphemeral", "isDefunct"] -# -# notes: -# -# objectClassCategory -# 1: structural -# 2: abstract -# 3: auxiliary - class Objectclass(dict): def __init__(self, ldb, name): diff --git a/source4/scripting/bin/minschema b/source4/scripting/bin/minschema index 4983502ba7..c860495e96 100755 --- a/source4/scripting/bin/minschema +++ b/source4/scripting/bin/minschema @@ -72,7 +72,6 @@ class_attrs = ["objectClass", "mustContain", "auxiliaryClass", "rDNAttID", - "showInAdvancedViewOnly", "adminDisplayName", "adminDescription", "objectClassCategory", @@ -104,7 +103,6 @@ attrib_attrs = ["objectClass", "rangeUpper", "mAPIID", "linkID", - "showInAdvancedViewOnly", "adminDisplayName", "oMObjectClass", "adminDescription", -- cgit From 4a45b0da5743f76f77c812d03ee625af10fb2a54 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 20 Mar 2009 16:45:52 +1100 Subject: s4:ldb Allow paged_searches to be mixed with other controls I want to mix this with the server-side sort in particular. Andrew Bartlett --- source4/lib/ldb/modules/paged_searches.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4') diff --git a/source4/lib/ldb/modules/paged_searches.c b/source4/lib/ldb/modules/paged_searches.c index 70b880e2dd..c5430eb9bf 100644 --- a/source4/lib/ldb/modules/paged_searches.c +++ b/source4/lib/ldb/modules/paged_searches.c @@ -230,10 +230,10 @@ static int ps_search(struct ldb_module *module, struct ldb_request *req) private_data = talloc_get_type(ldb_module_get_private(module), struct private_data); ldb = ldb_module_get_ctx(module); - /* check if paging is supported and if there is a any control */ - if (!private_data || !private_data->paged_supported || req->controls) { + /* check if paging is supported */ + if (!private_data || !private_data->paged_supported) { /* do not touch this request paged controls not - * supported or explicit controls have been set or we + * supported or we * are just not setup yet */ return ldb_next_request(module, req); } -- cgit From 37f130fd89d02e77bf55cbd8da731d87bb4ab1e8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 20 Mar 2009 16:47:34 +1100 Subject: s4:fullschema Use server-side sort to make the output deterministic --- source4/scripting/bin/fullschema | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/scripting/bin/fullschema b/source4/scripting/bin/fullschema index d3bf398e65..41c45f30c8 100644 --- a/source4/scripting/bin/fullschema +++ b/source4/scripting/bin/fullschema @@ -157,7 +157,8 @@ rootDse = res[0] if opts.dump_attributes: res = ldb.search(expression="objectClass=attributeSchema", - base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=attrib_attrs) + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=attrib_attrs, + controls=["server_sort:1:0:cn"]) for msg in res: o = Objectclass(ldb, msg["ldapDisplayName"]) @@ -167,7 +168,8 @@ if opts.dump_attributes: if opts.dump_classes: res = ldb.search(expression="objectClass=classSchema", - base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=class_attrs) + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=class_attrs, + controls=["server_sort:1:0:cn"]) for msg in res: o = Objectclass(ldb, msg["ldapDisplayName"]) -- cgit From da46c371006d7cb5bceba790070d805b303ade98 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 20 Mar 2009 10:14:35 +0100 Subject: s4:build: include ../libcli/cldap/config.mk This fixes commit 84a140f18722518eb0f40737085dd3b3958a3a02, sorry! metze --- source4/main.mk | 1 + 1 file changed, 1 insertion(+) (limited to 'source4') diff --git a/source4/main.mk b/source4/main.mk index a143604f33..d7db0580e9 100644 --- a/source4/main.mk +++ b/source4/main.mk @@ -46,6 +46,7 @@ mkinclude torture/config.mk mkinclude librpc/config.mk mkinclude client/config.mk mkinclude libcli/config.mk +mkinclude ../libcli/cldap/config.mk mkinclude scripting/python/config.mk mkinclude kdc/config.mk mkinclude ../lib/smbconf/config.mk -- cgit From 2de464a7658f91d2d01087080b984d52c3483426 Mon Sep 17 00:00:00 2001 From: Matthias Dieter Wallnoefer Date: Fri, 20 Mar 2009 16:22:02 +0100 Subject: Fix uninstallman. Signed-off-by: Jelmer Vernooij --- source4/script/uninstallman.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/script/uninstallman.sh b/source4/script/uninstallman.sh index 9b087c68bb..edc1c47e4d 100755 --- a/source4/script/uninstallman.sh +++ b/source4/script/uninstallman.sh @@ -8,7 +8,7 @@ MANPAGES=$* for I in $MANPAGES do - SECTION=`echo -n $I | sed "s/.*\(.\)$/\1/" + SECTION=`echo -n $I | sed "s/.*\(.\)$/\1/"` FNAME=$MANDIR/man$SECTION/$I if test -f $FNAME; then echo Deleting $FNAME -- cgit