From 706140a1dcc5220739bde0f17afcb32ebc0c130a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Jul 2008 09:36:24 +1000 Subject: Make invalid 'member' detection work again. This defines a rootdn globally, and due to OpenLDAP bugs, gives it manage access to the whole database. This makes the memberOf module able to validate the links again, now we have database ACLs. Andrew Bartlett (This used to be commit 9fe3e9f09f89fd92f8a16768e53391ff5f8489ec) --- source4/setup/slapd.conf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source4/setup/slapd.conf b/source4/setup/slapd.conf index 495847f7fe..4dcfd2aba7 100644 --- a/source4/setup/slapd.conf +++ b/source4/setup/slapd.conf @@ -32,6 +32,7 @@ access to dn.subtree="cn=samba" access to dn.subtree="${DOMAINDN}" by dn=cn=samba-admin,cn=samba manage + by dn=cn=manager manage by * none password-hash {CLEARTEXT} @@ -40,6 +41,8 @@ include ${LDAPDIR}/modules.conf defaultsearchbase ${DOMAINDN} +rootdn cn=Manager + ${REFINT_CONFIG} ${MEMBEROF_CONFIG} @@ -47,6 +50,7 @@ ${MEMBEROF_CONFIG} database ldif suffix cn=Samba directory ${LDAPDIR}/db/samba +rootdn cn=Manager,cn=Samba database hdb -- cgit From ca46ad25b8ee43d50383cefb804694fe27595d33 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Jul 2008 11:18:21 +1000 Subject: Fix ldb_map to add/remove the same 'extra' objectclass The code previously added data->add_objectClass, but only removed the fixed objectclass of extensibleObject. Found by the ldap.py test. Andrew Bartlett (This used to be commit 4fa15c3173a997fa0b9041161d81e742e1fdb41c) --- source4/lib/ldb/ldb_map/ldb_map.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c index 9c189feb11..b3f639dc67 100644 --- a/source4/lib/ldb/ldb_map/ldb_map.c +++ b/source4/lib/ldb/ldb_map/ldb_map.c @@ -810,6 +810,7 @@ static struct ldb_val map_objectclass_convert_remote(struct ldb_module *module, /* Generate a local message with a mapped objectClass. */ static struct ldb_message_element *map_objectclass_generate_local(struct ldb_module *module, void *mem_ctx, const char *local_attr, const struct ldb_message *remote) { + const struct ldb_map_context *data = map_get_context(module); struct ldb_message_element *el, *oc; struct ldb_val val; int i; @@ -844,10 +845,10 @@ static struct ldb_message_element *map_objectclass_generate_local(struct ldb_mod el->values[i] = map_objectclass_convert_remote(module, el->values, &oc->values[i]); } - val.data = (uint8_t *)talloc_strdup(el->values, "extensibleObject"); + val.data = (uint8_t *)talloc_strdup(el->values, data->add_objectclass); val.length = strlen((char *)val.data); - /* Remove last value if it was "extensibleObject" */ + /* Remove last value if it was the string in data->add_objectclass (eg samba4top, extensibleObject) */ if (ldb_val_equal_exact(&val, &el->values[i-1])) { el->num_values--; el->values = talloc_realloc(el, el->values, struct ldb_val, el->num_values); -- cgit From f4cae6a9131b303980cf23b971be407a1215345d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Jul 2008 11:18:54 +1000 Subject: Sleep longer in the hope that the OpenLDAP backend might catch up (This used to be commit 63c80c885dc3fb2228f082be8db752bb29e3962e) --- source4/lib/ldb/tests/python/ldap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py index 0dc514aeaf..042469602c 100755 --- a/source4/lib/ldb/tests/python/ldap.py +++ b/source4/lib/ldb/tests/python/ldap.py @@ -579,7 +579,7 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """ self.assertEquals(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)) self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) - time.sleep(2) + time.sleep(4) print "Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes" res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE) @@ -835,7 +835,7 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """ ldb.delete(("CN=ldaptestuser2,CN=Users," + self.base_dn)) - time.sleep(2) + time.sleep(4) attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"] print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete" -- cgit From e16b2242e5f4702ad2800cd7bed46bcea2c1d4ac Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Jul 2008 12:05:53 +1000 Subject: Remove bogus test in 'enum trusted domains' LSA server. The change to the RPC-LSA test proves that when the remote server has 0 trusted domains, it will return NT_STATUS_NO_MORE_ENTRIES, not NT_STATUS_OK. Andrew Bartlett (This used to be commit 40a55b34c2ce75267cf004dc4cfb8153c061e66b) --- source4/rpc_server/lsa/dcesrv_lsa.c | 6 ------ source4/torture/rpc/lsa.c | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index eb60f426d8..f02e2325a0 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -1130,9 +1130,6 @@ static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALL if (count == -1) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } - if (count == 0 || r->in.max_size == 0) { - return NT_STATUS_OK; - } /* convert to lsa_TrustInformation format */ entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count); @@ -1218,9 +1215,6 @@ static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_ca if (count == -1) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } - if (count == 0 || r->in.max_size == 0) { - return NT_STATUS_OK; - } /* convert to lsa_DomainInformation format */ entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count); diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index a4e702f759..e6102f0a82 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -1822,6 +1822,19 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p, printf("\nTesting EnumTrustDom\n"); + r.in.handle = handle; + r.in.resume_handle = &resume_handle; + r.in.max_size = 0; + r.out.domains = &domains; + r.out.resume_handle = &resume_handle; + + enum_status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r); + + if (!(NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES) || NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES))) { + printf("EnumTrustDom of zero size failed - %s\n", nt_errstr(enum_status)); + return false; + } + do { r.in.handle = handle; r.in.resume_handle = &resume_handle; @@ -1848,12 +1861,30 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p, return false; } + if (domains.count == 0) { + printf("EnumTrustDom failed - should have returned 'NT_STATUS_NO_MORE_ENTRIES' for 0 trusted domains\n"); + return false; + } + ret &= test_query_each_TrustDom(p, mem_ctx, handle, &domains); } while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES))); printf("\nTesting EnumTrustedDomainsEx\n"); + r_ex.in.handle = handle; + r_ex.in.resume_handle = &resume_handle; + r_ex.in.max_size = LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER * 3; + r_ex.out.domains = &domains_ex; + r_ex.out.resume_handle = &resume_handle; + + enum_status = dcerpc_lsa_EnumTrustedDomainsEx(p, mem_ctx, &r_ex); + + if (!(NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES) || NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES))) { + printf("EnumTrustedDomainEx of zero size failed - %s\n", nt_errstr(enum_status)); + return false; + } + resume_handle = 0; do { r_ex.in.handle = handle; @@ -1884,6 +1915,11 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p, return false; } + if (domains_ex.count == 0) { + printf("EnumTrustDomainEx failed - should have returned 'NT_STATUS_NO_MORE_ENTRIES' for 0 trusted domains\n"); + return false; + } + ret &= test_query_each_TrustDomEx(p, mem_ctx, handle, &domains_ex); } while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES))); @@ -1906,6 +1942,10 @@ static bool test_CreateTrustedDomain(struct dcerpc_pipe *p, printf("Testing CreateTrustedDomain for 12 domains\n"); + if (!test_EnumTrustDom(p, mem_ctx, handle)) { + ret = false; + } + for (i=0; i< 12; i++) { char *trust_name = talloc_asprintf(mem_ctx, "torturedom%02d", i); char *trust_sid = talloc_asprintf(mem_ctx, "S-1-5-21-97398-379795-100%02d", i); -- cgit From d626a26374744849f1bc431e02dd5329594589a1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Jul 2008 13:42:07 +1000 Subject: Rename structures to better match the names in the WSPP IDL. The 'comment' element in a number of domain structures is called oem_information. This was picked up actually because with OpenLDAP doing the schema checking, it noticed that 'comment' was not a valid attribute. The rename tries to keep this consistant in both the LDB mappings and IDL, so we don't make the same mistake in future. This has no real schema impact, as this value isn't actually used for anything, as 'comment' was not used in the provision. Andrew Bartlett (This used to be commit 65dc0d536590d055a5ee775606ac90ee5fcaee9a) --- source4/libnet/libnet_samsync_ldb.c | 2 +- source4/librpc/idl/netlogon.idl | 2 +- source4/librpc/idl/samr.idl | 18 +++++----- source4/rpc_server/samr/dcesrv_samr.c | 66 +++++++++++++++++------------------ source4/torture/rpc/samr.c | 40 ++++++++++----------- source4/torture/rpc/samsync.c | 8 ++--- 6 files changed, 68 insertions(+), 68 deletions(-) diff --git a/source4/libnet/libnet_samsync_ldb.c b/source4/libnet/libnet_samsync_ldb.c index b223a74a31..c72aef7d70 100644 --- a/source4/libnet/libnet_samsync_ldb.c +++ b/source4/libnet/libnet_samsync_ldb.c @@ -198,7 +198,7 @@ static NTSTATUS samsync_ldb_handle_domain(TALLOC_CTX *mem_ctx, } samdb_msg_add_string(state->sam_ldb, mem_ctx, - msg, "oEMInformation", domain->comment.string); + msg, "oEMInformation", domain->oem_information.string); samdb_msg_add_int64(state->sam_ldb, mem_ctx, msg, "forceLogoff", domain->force_logoff_time); diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl index 6da496a486..d8f7d2f7e6 100644 --- a/source4/librpc/idl/netlogon.idl +++ b/source4/librpc/idl/netlogon.idl @@ -403,7 +403,7 @@ interface netlogon typedef struct { lsa_String domain_name; - lsa_String comment; + lsa_String oem_information; /* comment */ dlong force_logoff_time; uint16 min_password_length; uint16 password_history_length; diff --git a/source4/librpc/idl/samr.idl b/source4/librpc/idl/samr.idl index 3a11ab752c..b6cce38196 100644 --- a/source4/librpc/idl/samr.idl +++ b/source4/librpc/idl/samr.idl @@ -208,7 +208,7 @@ import "misc.idl", "lsa.idl", "security.idl"; typedef struct { NTTIME force_logoff_time; - lsa_String comment; + lsa_String oem_information; /* comment */ lsa_String domain_name; lsa_String primary; /* PDC name if this is a BDC */ udlong sequence_num; @@ -218,15 +218,15 @@ import "misc.idl", "lsa.idl", "security.idl"; uint32 num_users; uint32 num_groups; uint32 num_aliases; - } samr_DomInfo2; + } samr_DomGeneralInformation; typedef struct { NTTIME force_logoff_time; } samr_DomInfo3; typedef struct { - lsa_String comment; - } samr_DomInfo4; + lsa_String oem_information; /* comment */ + } samr_DomOEMInformation; typedef struct { lsa_String domain_name; @@ -250,11 +250,11 @@ import "misc.idl", "lsa.idl", "security.idl"; } samr_DomInfo9; typedef struct { - samr_DomInfo2 info2; + samr_DomGeneralInformation general; hyper lockout_duration; hyper lockout_window; uint16 lockout_threshold; - } samr_DomInfo11; + } samr_DomGeneralInformation2; typedef struct { hyper lockout_duration; @@ -271,15 +271,15 @@ import "misc.idl", "lsa.idl", "security.idl"; typedef [switch_type(uint16)] union { [case(1)] samr_DomInfo1 info1; - [case(2)] samr_DomInfo2 info2; + [case(2)] samr_DomGeneralInformation general; [case(3)] samr_DomInfo3 info3; - [case(4)] samr_DomInfo4 info4; + [case(4)] samr_DomOEMInformation oem; [case(5)] samr_DomInfo5 info5; [case(6)] samr_DomInfo6 info6; [case(7)] samr_DomInfo7 info7; [case(8)] samr_DomInfo8 info8; [case(9)] samr_DomInfo9 info9; - [case(11)] samr_DomInfo11 info11; + [case(11)] samr_DomGeneralInformation2 general2; [case(12)] samr_DomInfo12 info12; [case(13)] samr_DomInfo13 info13; } samr_DomainInfo; diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index 8ee77a6a30..e54d518f76 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -521,10 +521,10 @@ static NTSTATUS dcesrv_samr_info_DomInfo1(struct samr_domain_state *state, /* return DomInfo2 */ -static NTSTATUS dcesrv_samr_info_DomInfo2(struct samr_domain_state *state, - TALLOC_CTX *mem_ctx, - struct ldb_message **dom_msgs, - struct samr_DomInfo2 *info) +static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state *state, + TALLOC_CTX *mem_ctx, + struct ldb_message **dom_msgs, + struct samr_DomGeneralInformation *info) { /* This pulls the NetBIOS name from the cn=NTDS Settings,cn=,.... @@ -538,7 +538,7 @@ static NTSTATUS dcesrv_samr_info_DomInfo2(struct samr_domain_state *state, info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff", 0x8000000000000000LL); - info->comment.string = samdb_result_string(dom_msgs[0], "comment", NULL); + info->oem_information.string = samdb_result_string(dom_msgs[0], "oEMInformation", NULL); info->domain_name.string = state->domain_name; info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount", @@ -592,12 +592,12 @@ static NTSTATUS dcesrv_samr_info_DomInfo3(struct samr_domain_state *state, /* return DomInfo4 */ -static NTSTATUS dcesrv_samr_info_DomInfo4(struct samr_domain_state *state, +static NTSTATUS dcesrv_samr_info_DomOEMInformation(struct samr_domain_state *state, TALLOC_CTX *mem_ctx, struct ldb_message **dom_msgs, - struct samr_DomInfo4 *info) + struct samr_DomOEMInformation *info) { - info->comment.string = samdb_result_string(dom_msgs[0], "comment", NULL); + info->oem_information.string = samdb_result_string(dom_msgs[0], "oEMInformation", NULL); return NT_STATUS_OK; } @@ -700,13 +700,13 @@ static NTSTATUS dcesrv_samr_info_DomInfo9(struct samr_domain_state *state, /* return DomInfo11 */ -static NTSTATUS dcesrv_samr_info_DomInfo11(struct samr_domain_state *state, +static NTSTATUS dcesrv_samr_info_DomGeneralInformation2(struct samr_domain_state *state, TALLOC_CTX *mem_ctx, struct ldb_message **dom_msgs, - struct samr_DomInfo11 *info) + struct samr_DomGeneralInformation2 *info) { NTSTATUS status; - status = dcesrv_samr_info_DomInfo2(state, mem_ctx, dom_msgs, &info->info2); + status = dcesrv_samr_info_DomGeneralInformation(state, mem_ctx, dom_msgs, &info->general); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -792,7 +792,7 @@ static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, case 2: { static const char * const attrs2[] = {"forceLogoff", - "comment", + "oEMInformation", "modifiedCount", "fSMORoleOwner", NULL}; @@ -808,7 +808,7 @@ static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, } case 4: { - static const char * const attrs2[] = {"comment", + static const char * const attrs2[] = {"oEMInformation", NULL}; attrs = attrs2; break; @@ -843,7 +843,7 @@ static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, break; case 11: { - static const char * const attrs2[] = { "comment", "forceLogoff", + static const char * const attrs2[] = { "oEMInformation", "forceLogoff", "modifiedCount", "lockoutDuration", "lockOutObservationWindow", @@ -886,42 +886,42 @@ static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call, switch (r->in.level) { case 1: return dcesrv_samr_info_DomInfo1(d_state, mem_ctx, dom_msgs, - &r->out.info->info1); + &r->out.info->info1); case 2: - return dcesrv_samr_info_DomInfo2(d_state, mem_ctx, dom_msgs, - &r->out.info->info2); + return dcesrv_samr_info_DomGeneralInformation(d_state, mem_ctx, dom_msgs, + &r->out.info->general); case 3: return dcesrv_samr_info_DomInfo3(d_state, mem_ctx, dom_msgs, - &r->out.info->info3); + &r->out.info->info3); case 4: - return dcesrv_samr_info_DomInfo4(d_state, mem_ctx, dom_msgs, - &r->out.info->info4); + return dcesrv_samr_info_DomOEMInformation(d_state, mem_ctx, dom_msgs, + &r->out.info->oem); case 5: return dcesrv_samr_info_DomInfo5(d_state, mem_ctx, dom_msgs, - &r->out.info->info5); + &r->out.info->info5); case 6: return dcesrv_samr_info_DomInfo6(d_state, mem_ctx, dom_msgs, - &r->out.info->info6); + &r->out.info->info6); case 7: return dcesrv_samr_info_DomInfo7(d_state, mem_ctx, dom_msgs, - &r->out.info->info7); + &r->out.info->info7); case 8: return dcesrv_samr_info_DomInfo8(d_state, mem_ctx, dom_msgs, - &r->out.info->info8); + &r->out.info->info8); case 9: return dcesrv_samr_info_DomInfo9(d_state, mem_ctx, dom_msgs, - &r->out.info->info9); + &r->out.info->info9); case 11: - return dcesrv_samr_info_DomInfo11(d_state, mem_ctx, dom_msgs, - &r->out.info->info11); + return dcesrv_samr_info_DomGeneralInformation2(d_state, mem_ctx, dom_msgs, + &r->out.info->general2); case 12: return dcesrv_samr_info_DomInfo12(d_state, mem_ctx, dom_msgs, - &r->out.info->info12); + &r->out.info->info12); case 13: return dcesrv_samr_info_DomInfo13(d_state, mem_ctx, dom_msgs, - &r->out.info->info13); + &r->out.info->info13); } - + return NT_STATUS_INVALID_INFO_CLASS; } @@ -962,10 +962,10 @@ static NTSTATUS dcesrv_samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TA SET_INT64 (msg, info1.min_password_age, "minPwdAge"); break; case 3: - SET_UINT64 (msg, info3.force_logoff_time, "forceLogoff"); + SET_UINT64 (msg, info3.force_logoff_time, "forceLogoff"); break; case 4: - SET_STRING(msg, info4.comment, "comment"); + SET_STRING(msg, oem.oem_information, "oEMInformation"); break; case 6: @@ -2997,7 +2997,7 @@ static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TA case 1: { static const char * const attrs2[] = {"sAMAccountName", "displayName", - "primaryGroupID", "description", + "primaryroupID", "description", "comment", NULL}; attrs = attrs2; break; diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c index 55c75ba270..6afda6e9b5 100644 --- a/source4/torture/rpc/samr.c +++ b/source4/torture/rpc/samr.c @@ -3595,17 +3595,17 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, switch (r.in.level) { case 1: case 4: - if (dom_info.out.info->info2.num_users < r.in.start_idx) { + if (dom_info.out.info->general.num_users < r.in.start_idx) { printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n", - r.in.start_idx, dom_info.out.info->info2.num_groups, - dom_info.out.info->info2.domain_name.string); + r.in.start_idx, dom_info.out.info->general.num_groups, + dom_info.out.info->general.domain_name.string); ret = false; } if (!seen_testuser) { struct policy_handle user_handle; if (NT_STATUS_IS_OK(test_OpenUser_byname(p, mem_ctx, handle, TEST_ACCOUNT_NAME, &user_handle))) { printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n", - dom_info.out.info->info2.domain_name.string); + dom_info.out.info->general.domain_name.string); ret = false; test_samr_handle_Close(p, mem_ctx, &user_handle); } @@ -3613,10 +3613,10 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, break; case 3: case 5: - if (dom_info.out.info->info2.num_groups != r.in.start_idx) { + if (dom_info.out.info->general.num_groups != r.in.start_idx) { printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n", - r.in.start_idx, dom_info.out.info->info2.num_groups, - dom_info.out.info->info2.domain_name.string); + r.in.start_idx, dom_info.out.info->general.num_groups, + dom_info.out.info->general.domain_name.string); ret = false; } @@ -3745,7 +3745,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, s.in.level = 4; s.in.info = talloc(mem_ctx, union samr_DomainInfo); - s.in.info->info4.comment.string = domain_comment; + s.in.info->oem.oem_information.string = domain_comment; status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s); if (!NT_STATUS_IS_OK(status)) { printf("SetDomainInfo level %u (set comment) failed - %s\n", @@ -3769,26 +3769,26 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, switch (levels[i]) { case 2: - if (strcmp(r.out.info->info2.comment.string, domain_comment) != 0) { - printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n", - levels[i], r.out.info->info2.comment.string, domain_comment); + if (strcmp(r.out.info->general.oem_information.string, domain_comment) != 0) { + printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n", + levels[i], r.out.info->general.oem_information.string, domain_comment); ret = false; } - if (!r.out.info->info2.primary.string) { + if (!r.out.info->general.primary.string) { printf("QueryDomainInfo level %u returned no PDC name\n", levels[i]); ret = false; - } else if (r.out.info->info2.role == SAMR_ROLE_DOMAIN_PDC) { - if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), r.out.info->info2.primary.string) != 0) { + } else if (r.out.info->general.role == SAMR_ROLE_DOMAIN_PDC) { + if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), r.out.info->general.primary.string) != 0) { printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n", - levels[i], r.out.info->info2.primary.string, dcerpc_server_name(p)); + levels[i], r.out.info->general.primary.string, dcerpc_server_name(p)); } } break; case 4: - if (strcmp(r.out.info->info4.comment.string, domain_comment) != 0) { - printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n", - levels[i], r.out.info->info4.comment.string, domain_comment); + if (strcmp(r.out.info->oem.oem_information.string, domain_comment) != 0) { + printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n", + levels[i], r.out.info->oem.oem_information.string, domain_comment); ret = false; } break; @@ -3800,9 +3800,9 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, } break; case 11: - if (strcmp(r.out.info->info11.info2.comment.string, domain_comment) != 0) { + if (strcmp(r.out.info->general2.general.oem_information.string, domain_comment) != 0) { printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n", - levels[i], r.out.info->info11.info2.comment.string, domain_comment); + levels[i], r.out.info->general2.general.oem_information.string, domain_comment); ret = false; } break; diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c index 7114756460..1e76de1dd2 100644 --- a/source4/torture/rpc/samsync.c +++ b/source4/torture/rpc/samsync.c @@ -346,9 +346,9 @@ static bool samsync_handle_domain(TALLOC_CTX *mem_ctx, struct samsync_state *sam TEST_STRING_EQUAL(q[5].out.info->info5.domain_name, domain->domain_name); - TEST_STRING_EQUAL(q[2].out.info->info2.comment, domain->comment); - TEST_STRING_EQUAL(q[4].out.info->info4.comment, domain->comment); - TEST_TIME_EQUAL(q[2].out.info->info2.force_logoff_time, domain->force_logoff_time); + TEST_STRING_EQUAL(q[2].out.info->general.oem_information, domain->oem_information); + TEST_STRING_EQUAL(q[4].out.info->oem.oem_information, domain->oem_information); + TEST_TIME_EQUAL(q[2].out.info->general.force_logoff_time, domain->force_logoff_time); TEST_TIME_EQUAL(q[3].out.info->info3.force_logoff_time, domain->force_logoff_time); TEST_TIME_EQUAL(q[1].out.info->info1.min_password_length, domain->min_password_length); @@ -1487,7 +1487,7 @@ bool torture_rpc_samsync(struct torture_context *torture) s.in.level = 4; s.in.info = talloc(mem_ctx, union samr_DomainInfo); - s.in.info->info4.comment.string + s.in.info->oem.oem_information.string = talloc_asprintf(mem_ctx, "Tortured by Samba4: %s", timestring(mem_ctx, time(NULL))); -- cgit From ecc13c3b1f203e5f6b3d7d5bfc50ba2ec2a4b9c8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 21 Jul 2008 15:00:18 +1000 Subject: Fix winbindd not to sit in a busy loop... Clearly winbindd in Samba4 has not ever been run against windows, as when we fixed the Samba4 server not to cause XP to loop like this, Samba4's own client starts looping... Andrew Bartlett (This used to be commit 9741772190a85c7c42c17ff24a4aa3f53fbc9f3a) --- source4/winbind/wb_cmd_list_trustdom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source4/winbind/wb_cmd_list_trustdom.c b/source4/winbind/wb_cmd_list_trustdom.c index 8d0c1bd947..fe98ce2f6a 100644 --- a/source4/winbind/wb_cmd_list_trustdom.c +++ b/source4/winbind/wb_cmd_list_trustdom.c @@ -159,7 +159,8 @@ static void cmd_list_trustdoms_recv_doms(struct rpc_request *req) state->r.out.domains->domains[i].sid); } - if (NT_STATUS_IS_OK(state->ctx->status)) { + if (NT_STATUS_IS_OK(state->ctx->status) || NT_STATUS_EQUAL(state->ctx->status, NT_STATUS_NO_MORE_ENTRIES)) { + state->ctx->status = NT_STATUS_OK; composite_done(state->ctx); return; } -- cgit From 24b03e1080b5acbe8086bbc22091ecb1af642619 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 21 Jul 2008 12:47:08 +0200 Subject: Properly cast array length in print functions. (This used to be commit f321240fa91fa19c1131f119c42f64897d220682) --- source4/pidl/lib/Parse/Pidl/Expr.pm | 72 ++++++++++++------------ source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm | 2 +- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/source4/pidl/lib/Parse/Pidl/Expr.pm b/source4/pidl/lib/Parse/Pidl/Expr.pm index 4e02be0575..5524374fae 100644 --- a/source4/pidl/lib/Parse/Pidl/Expr.pm +++ b/source4/pidl/lib/Parse/Pidl/Expr.pm @@ -1127,7 +1127,7 @@ sub new { [#Rule 2 'exp', 1, sub -#line 22 "pidl/expr.yp" +#line 22 "./pidl/expr.yp" { "\"$_[1]\"" } ], [#Rule 3 @@ -1139,199 +1139,199 @@ sub [#Rule 5 'exp', 2, sub -#line 25 "pidl/expr.yp" +#line 25 "./pidl/expr.yp" { "~$_[2]" } ], [#Rule 6 'exp', 3, sub -#line 26 "pidl/expr.yp" +#line 26 "./pidl/expr.yp" { "$_[1] + $_[3]" } ], [#Rule 7 'exp', 3, sub -#line 27 "pidl/expr.yp" +#line 27 "./pidl/expr.yp" { "$_[1] - $_[3]" } ], [#Rule 8 'exp', 3, sub -#line 28 "pidl/expr.yp" +#line 28 "./pidl/expr.yp" { "$_[1] * $_[3]" } ], [#Rule 9 'exp', 3, sub -#line 29 "pidl/expr.yp" +#line 29 "./pidl/expr.yp" { "$_[1] % $_[3]" } ], [#Rule 10 'exp', 3, sub -#line 30 "pidl/expr.yp" +#line 30 "./pidl/expr.yp" { "$_[1] < $_[3]" } ], [#Rule 11 'exp', 3, sub -#line 31 "pidl/expr.yp" +#line 31 "./pidl/expr.yp" { "$_[1] > $_[3]" } ], [#Rule 12 'exp', 3, sub -#line 32 "pidl/expr.yp" +#line 32 "./pidl/expr.yp" { "$_[1] | $_[3]" } ], [#Rule 13 'exp', 3, sub -#line 33 "pidl/expr.yp" +#line 33 "./pidl/expr.yp" { "$_[1] == $_[3]" } ], [#Rule 14 'exp', 3, sub -#line 34 "pidl/expr.yp" +#line 34 "./pidl/expr.yp" { "$_[1] <= $_[3]" } ], [#Rule 15 'exp', 3, sub -#line 35 "pidl/expr.yp" +#line 35 "./pidl/expr.yp" { "$_[1] => $_[3]" } ], [#Rule 16 'exp', 3, sub -#line 36 "pidl/expr.yp" +#line 36 "./pidl/expr.yp" { "$_[1] << $_[3]" } ], [#Rule 17 'exp', 3, sub -#line 37 "pidl/expr.yp" +#line 37 "./pidl/expr.yp" { "$_[1] >> $_[3]" } ], [#Rule 18 'exp', 3, sub -#line 38 "pidl/expr.yp" +#line 38 "./pidl/expr.yp" { "$_[1] != $_[3]" } ], [#Rule 19 'exp', 3, sub -#line 39 "pidl/expr.yp" +#line 39 "./pidl/expr.yp" { "$_[1] || $_[3]" } ], [#Rule 20 'exp', 3, sub -#line 40 "pidl/expr.yp" +#line 40 "./pidl/expr.yp" { "$_[1] && $_[3]" } ], [#Rule 21 'exp', 3, sub -#line 41 "pidl/expr.yp" +#line 41 "./pidl/expr.yp" { "$_[1] & $_[3]" } ], [#Rule 22 'exp', 5, sub -#line 42 "pidl/expr.yp" +#line 42 "./pidl/expr.yp" { "$_[1]?$_[3]:$_[5]" } ], [#Rule 23 'exp', 2, sub -#line 43 "pidl/expr.yp" +#line 43 "./pidl/expr.yp" { "~$_[1]" } ], [#Rule 24 'exp', 2, sub -#line 44 "pidl/expr.yp" +#line 44 "./pidl/expr.yp" { "not $_[1]" } ], [#Rule 25 'exp', 3, sub -#line 45 "pidl/expr.yp" +#line 45 "./pidl/expr.yp" { "$_[1] / $_[3]" } ], [#Rule 26 'exp', 2, sub -#line 46 "pidl/expr.yp" +#line 46 "./pidl/expr.yp" { "-$_[2]" } ], [#Rule 27 'exp', 2, sub -#line 47 "pidl/expr.yp" +#line 47 "./pidl/expr.yp" { "&$_[2]" } ], [#Rule 28 'exp', 3, sub -#line 48 "pidl/expr.yp" +#line 48 "./pidl/expr.yp" { "$_[1]^$_[3]" } ], [#Rule 29 'exp', 3, sub -#line 49 "pidl/expr.yp" +#line 49 "./pidl/expr.yp" { "($_[2])" } ], [#Rule 30 'possible_pointer', 1, sub -#line 53 "pidl/expr.yp" +#line 53 "./pidl/expr.yp" { $_[0]->_Lookup($_[1]) } ], [#Rule 31 'possible_pointer', 2, sub -#line 54 "pidl/expr.yp" +#line 54 "./pidl/expr.yp" { $_[0]->_Dereference($_[2]); "*$_[2]" } ], [#Rule 32 'var', 1, sub -#line 57 "pidl/expr.yp" +#line 57 "./pidl/expr.yp" { $_[0]->_Use($_[1]) } ], [#Rule 33 'var', 3, sub -#line 58 "pidl/expr.yp" +#line 58 "./pidl/expr.yp" { $_[0]->_Use("$_[1].$_[3]") } ], [#Rule 34 'var', 3, sub -#line 59 "pidl/expr.yp" +#line 59 "./pidl/expr.yp" { "($_[2])" } ], [#Rule 35 'var', 3, sub -#line 60 "pidl/expr.yp" +#line 60 "./pidl/expr.yp" { $_[0]->_Use("*$_[1]"); $_[1]."->".$_[3] } ], [#Rule 36 'func', 4, sub -#line 64 "pidl/expr.yp" +#line 64 "./pidl/expr.yp" { "$_[1]($_[3])" } ], [#Rule 37 'opt_args', 0, sub -#line 65 "pidl/expr.yp" +#line 65 "./pidl/expr.yp" { "" } ], [#Rule 38 @@ -1349,7 +1349,7 @@ sub [#Rule 42 'args', 3, sub -#line 68 "pidl/expr.yp" +#line 68 "./pidl/expr.yp" { "$_[1], $_[3]" } ] ], @@ -1357,7 +1357,7 @@ sub bless($self,$class); } -#line 71 "pidl/expr.yp" +#line 71 "./pidl/expr.yp" package Parse::Pidl::Expr; diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm index 0d1806a0fa..a0de1f127a 100644 --- a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm +++ b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm @@ -770,7 +770,7 @@ sub ParseElementPrint($$$$) } else { my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}"; - $self->pidl("ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", $length);"); + $self->pidl("ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", (int)$length);"); $self->pidl("ndr->depth++;"); $self->pidl("for ($counter=0;$counter<$length;$counter++) {"); $self->indent; -- cgit From fb3e663678be412df4668b05e76480908da2c080 Mon Sep 17 00:00:00 2001 From: Matthias Dieter Wallnöfer Date: Tue, 22 Jul 2008 11:06:47 +1000 Subject: Improve DNS and Group poicy configurations. - fixes bug #4813 (simplify DNS setup) - This reworks the named.conf to be a fully fledged include - This also moves the documentation into named.txt - improves bug #4900 (Group policy support in Samba) - by creating an empty GPT.INI - fixes bug #5582 (DNS: Enhanced zone file) - This is now closer to the zone file AD creates committed by Andrew Bartlett (This used to be commit 74d684f6b329d7dd573cdc55e16bb8e629474b02) --- source4/scripting/python/samba/provision.py | 5 ++- source4/setup/named.conf | 63 ++++++----------------------- source4/setup/named.txt | 46 +++++++++++++++++++++ source4/setup/provision.zone | 7 +++- 4 files changed, 68 insertions(+), 53 deletions(-) create mode 100644 source4/setup/named.txt diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 6eb47c8595..40b61a0ac4 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -1043,6 +1043,7 @@ def provision(setup_dir, message, session_info, policy_path = os.path.join(paths.sysvol, names.dnsdomain, "Policies", "{" + policyguid + "}") os.makedirs(policy_path, 0755) + open(os.path.join(policy_path, "GPT.INI"), 'w').write("") os.makedirs(os.path.join(policy_path, "Machine"), 0755) os.makedirs(os.path.join(policy_path, "User"), 0755) if not os.path.isdir(paths.netlogon): @@ -1081,12 +1082,11 @@ def provision(setup_dir, message, session_info, hostip6=hostip6, hostname=names.hostname, dnspass=dnspass, realm=names.realm, domainguid=domainguid, hostguid=hostguid) - message("Please install the zone located in %s into your DNS server" % paths.dns) create_named_conf(paths.namedconf, setup_path, realm=names.realm, dnsdomain=names.dnsdomain, private_dir=paths.private_dir, keytab_name=paths.dns_keytab) - message("See %s for example configuration statements for secure GSS-TSIG updates" % paths.namedconf) + message("See %s for an example configuration include file for BIND" % paths.namedconf) create_krb5_conf(paths.krb5conf, setup_path, dnsdomain=names.dnsdomain, hostname=names.hostname, realm=names.realm) @@ -1394,6 +1394,7 @@ def create_named_conf(path, setup_path, realm, dnsdomain, "REALM_WC": "*." + ".".join(realm.split(".")[1:]), "DNS_KEYTAB": keytab_name, "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name), + "PRIVATE_DIR": private_dir, }) def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm): diff --git a/source4/setup/named.conf b/source4/setup/named.conf index 4f98bbd914..0b087069c7 100644 --- a/source4/setup/named.conf +++ b/source4/setup/named.conf @@ -1,12 +1,15 @@ +# This file should be included in your main BIND configuration file # -# Insert these snippets into your named.conf or bind.conf to configure -# the BIND nameserver. -# +# For example with +# include "${PRIVATE_DIR}/named.conf"; -# You should always include the actual forward zone configuration: zone "${DNSDOMAIN}." IN { type master; - file "${DNSDOMAIN}.zone"; + file "${PRIVATE_DIR}/${DNSDOMAIN}.zone"; + /* + * Attention: Not all BIND versions support "ms-self". The instead use + * of allow-update { any; }; is another, but less secure possibility. + */ update-policy { /* * A rather long description here, as the "ms-self" option does @@ -44,6 +47,8 @@ zone "${DNSDOMAIN}." IN { # The reverse zone configuration is optional. The following example assumes a # subnet of 192.168.123.0/24: + +/* zone "123.168.192.in-addr.arpa" in { type master; file "123.168.192.in-addr.arpa.zone"; @@ -51,54 +56,12 @@ zone "123.168.192.in-addr.arpa" in { grant ${REALM_WC} wildcard *.123.168.192.in-addr.arpa. PTR; }; }; +*/ + # Note that the reverse zone file is not created during the provision process. -# The most recent BIND version (9.5.0a5 or later) supports secure GSS-TSIG +# The most recent BIND versions (9.5.0a5 or later) support secure GSS-TSIG # updates. If you are running an earlier version of BIND, or if you do not wish # to use secure GSS-TSIG updates, you may remove the update-policy sections in # both examples above. -# If you are running a capable version of BIND and you wish to support secure -# GSS-TSIG updates, you must make the following configuration changes: - -# - Insert the following lines into the options {} section of your named.conf -# file: -tkey-gssapi-credential "DNS/${DNSDOMAIN}"; -tkey-domain "${REALM}"; - -# - Modify BIND init scripts to pass the location of the generated keytab file. -# Fedora 8 & later provide a variable named KEYTAB_FILE in /etc/sysconfig/named -# for this purpose: -KEYTAB_FILE="${DNS_KEYTAB_ABS}" -# Note that the Fedora scripts translate KEYTAB_FILE behind the scenes into a -# variable named KRB5_KTNAME, which is ultimately passed to the BIND daemon. If -# your distribution does not provide a variable like KEYTAB_FILE to pass a -# keytab file to the BIND daemon, a workaround is to place the following line in -# BIND's sysconfig file or in the init script for BIND: -export KRB5_KTNAME="${DNS_KEYTAB_ABS}" - -# - Set appropriate ownership and permissions on the ${DNS_KEYTAB} file. Note -# that most distributions have BIND configured to run under a non-root user -# account. For example, Fedora 9 runs BIND as the user "named" once the daemon -# relinquishes its rights. Therefore, the file ${DNS_KEYTAB} must be readable -# by the user that BIND run as. If BIND is running as a non-root user, the -# "${DNS_KEYTAB}" file must have its permissions altered to allow the daemon to -# read it. Under Fedora 9, execute the following commands: -chgrp named ${DNS_KEYTAB_ABS} -chmod g+r ${DNS_KEYTAB_ABS} - -# - Ensure the BIND zone file(s) that will be dynamically updated are in a -# directory where the BIND daemon can write. When BIND performs dynamic -# updates, it not only needs to update the zone file itself but it must also -# create a journal (.jnl) file to track the dynamic updates as they occur. -# Under Fedora 9, the /var/named directory can not be written to by the "named" -# user. However, the directory /var/named/dynamic directory does provide write -# access. Therefore the zone files were placed under the /var/named/dynamic -# directory. The file directives in both example zone statements at the -# beginning of this file were changed by prepending the directory "dynamic/". - -# - If SELinux is enabled, ensure that all files have the appropriate SELinux -# file contexts. The ${DNS_KEYTAB} file must be accessible by the BIND daemon -# and should have a SELinux type of named_conf_t. This can be set with the -# following command: -chcon -t named_conf_t ${DNS_KEYTAB_ABS} diff --git a/source4/setup/named.txt b/source4/setup/named.txt new file mode 100644 index 0000000000..c1e6b3a9ee --- /dev/null +++ b/source4/setup/named.txt @@ -0,0 +1,46 @@ +# Additional informations for DNS setup using BIND + +# If you are running a capable version of BIND and you wish to support secure +# GSS-TSIG updates, you must make the following configuration changes: + +# - Insert the following lines into the options {} section of your named.conf +# file: +tkey-gssapi-credential "DNS/${DNSDOMAIN}"; +tkey-domain "${REALM}"; + +# - Modify BIND init scripts to pass the location of the generated keytab file. +# Fedora 8 & later provide a variable named KEYTAB_FILE in /etc/sysconfig/named +# for this purpose: +KEYTAB_FILE="${DNS_KEYTAB_ABS}" +# Note that the Fedora scripts translate KEYTAB_FILE behind the scenes into a +# variable named KRB5_KTNAME, which is ultimately passed to the BIND daemon. If +# your distribution does not provide a variable like KEYTAB_FILE to pass a +# keytab file to the BIND daemon, a workaround is to place the following line in +# BIND's sysconfig file or in the init script for BIND: +export KRB5_KTNAME="${DNS_KEYTAB_ABS}" + +# - Set appropriate ownership and permissions on the ${DNS_KEYTAB} file. Note +# that most distributions have BIND configured to run under a non-root user +# account. For example, Fedora 9 runs BIND as the user "named" once the daemon +# relinquishes its rights. Therefore, the file ${DNS_KEYTAB} must be readable +# by the user that BIND run as. If BIND is running as a non-root user, the +# "${DNS_KEYTAB}" file must have its permissions altered to allow the daemon to +# read it. Under Fedora 9, execute the following commands: +chgrp named ${DNS_KEYTAB_ABS} +chmod g+r ${DNS_KEYTAB_ABS} + +# - Ensure the BIND zone file(s) that will be dynamically updated are in a +# directory where the BIND daemon can write. When BIND performs dynamic +# updates, it not only needs to update the zone file itself but it must also +# create a journal (.jnl) file to track the dynamic updates as they occur. +# Under Fedora 9, the /var/named directory can not be written to by the "named" +# user. However, the directory /var/named/dynamic directory does provide write +# access. Therefore the zone files were placed under the /var/named/dynamic +# directory. The file directives in both example zone statements at the +# beginning of this file were changed by prepending the directory "dynamic/". + +# - If SELinux is enabled, ensure that all files have the appropriate SELinux +# file contexts. The ${DNS_KEYTAB} file must be accessible by the BIND daemon +# and should have a SELinux type of named_conf_t. This can be set with the +# following command: +chcon -t named_conf_t ${DNS_KEYTAB_ABS} diff --git a/source4/setup/provision.zone b/source4/setup/provision.zone index 28c1c29762..17ae3bb47a 100644 --- a/source4/setup/provision.zone +++ b/source4/setup/provision.zone @@ -14,10 +14,12 @@ ${HOSTIP6_BASE_LINE} ; ${HOSTIP6_HOST_LINE} ${HOSTNAME} IN A ${HOSTIP} -${HOSTGUID}._msdcs IN CNAME ${HOSTNAME} +gc._msdcs IN CNAME ${HOSTNAME} +${HOSTGUID}._msdcs IN CNAME ${HOSTNAME} ; ; global catalog servers _gc._tcp IN SRV 0 100 3268 ${HOSTNAME} +_gc._tcp.${DEFAULTSITE}._sites IN SRV 0 100 3268 ${HOSTNAME} _ldap._tcp.gc._msdcs IN SRV 0 100 389 ${HOSTNAME} _ldap._tcp.${DEFAULTSITE}._sites.gc._msdcs IN SRV 0 100 389 ${HOSTNAME} ; @@ -25,12 +27,15 @@ _ldap._tcp.${DEFAULTSITE}._sites.gc._msdcs IN SRV 0 100 389 ${HOSTNAME} _ldap._tcp IN SRV 0 100 389 ${HOSTNAME} _ldap._tcp.dc._msdcs IN SRV 0 100 389 ${HOSTNAME} _ldap._tcp.pdc._msdcs IN SRV 0 100 389 ${HOSTNAME} +_ldap._tcp.${DOMAINGUID} IN SRV 0 100 389 ${HOSTNAME} _ldap._tcp.${DOMAINGUID}.domains._msdcs IN SRV 0 100 389 ${HOSTNAME} +_ldap._tcp.${DEFAULTSITE}._sites IN SRV 0 100 389 ${HOSTNAME} _ldap._tcp.${DEFAULTSITE}._sites.dc._msdcs IN SRV 0 100 389 ${HOSTNAME} ; ; krb5 servers _kerberos._tcp IN SRV 0 100 88 ${HOSTNAME} _kerberos._tcp.dc._msdcs IN SRV 0 100 88 ${HOSTNAME} +_kerberos._tcp.${DEFAULTSITE}._sites IN SRV 0 100 88 ${HOSTNAME} _kerberos._tcp.${DEFAULTSITE}._sites.dc._msdcs IN SRV 0 100 88 ${HOSTNAME} _kerberos._udp IN SRV 0 100 88 ${HOSTNAME} ; MIT kpasswd likes to lookup this name on password change -- cgit From c9c296b6bbe178502e8aded8fa5e38a0f338ee18 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 22 Jul 2008 11:09:18 +1000 Subject: Install'named.txt' to private/ as documentation. This document is much more use when subbed with all the right things. Andrew Bartlett (This used to be commit 136a85599815670c807f212d7d4003ec53a13729) --- source4/scripting/python/samba/provision.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 40b61a0ac4..4b310381ef 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -244,6 +244,7 @@ def provision_paths_from_lp(lp, dnsdomain): paths.templates = os.path.join(paths.private_dir, "templates.ldb") paths.dns = os.path.join(paths.private_dir, dnsdomain + ".zone") paths.namedconf = os.path.join(paths.private_dir, "named.conf") + paths.namedtxt = os.path.join(paths.private_dir, "named.txt") paths.krb5conf = os.path.join(paths.private_dir, "krb5.conf") paths.winsdb = os.path.join(paths.private_dir, "wins.ldb") paths.s4_ldapi_path = os.path.join(paths.private_dir, "ldapi") @@ -1084,9 +1085,13 @@ def provision(setup_dir, message, session_info, domainguid=domainguid, hostguid=hostguid) create_named_conf(paths.namedconf, setup_path, realm=names.realm, + dnsdomain=names.dnsdomain, private_dir=paths.private_dir) + + create_named_txt(paths.namedtxt, setup_path, realm=names.realm, dnsdomain=names.dnsdomain, private_dir=paths.private_dir, keytab_name=paths.dns_keytab) message("See %s for an example configuration include file for BIND" % paths.namedconf) + message("and %s for further documentation required for secure DNS updates" % paths.namedtxt) create_krb5_conf(paths.krb5conf, setup_path, dnsdomain=names.dnsdomain, hostname=names.hostname, realm=names.realm) @@ -1376,7 +1381,7 @@ def create_zone_file(path, setup_path, dnsdomain, domaindn, def create_named_conf(path, setup_path, realm, dnsdomain, - private_dir, keytab_name): + private_dir): """Write out a file containing zone statements suitable for inclusion in a named.conf file (including GSS-TSIG configuration). @@ -1392,9 +1397,28 @@ def create_named_conf(path, setup_path, realm, dnsdomain, "DNSDOMAIN": dnsdomain, "REALM": realm, "REALM_WC": "*." + ".".join(realm.split(".")[1:]), + "PRIVATE_DIR": private_dir + }) + +def create_named_txt(path, setup_path, realm, dnsdomain, + private_dir, keytab_name): + """Write out a file containing zone statements suitable for inclusion in a + named.conf file (including GSS-TSIG configuration). + + :param path: Path of the new named.conf file. + :param setup_path: Setup path function. + :param realm: Realm name + :param dnsdomain: DNS Domain name + :param private_dir: Path to private directory + :param keytab_name: File name of DNS keytab file + """ + + setup_file(setup_path("named.txt"), path, { + "DNSDOMAIN": dnsdomain, + "REALM": realm, "DNS_KEYTAB": keytab_name, "DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name), - "PRIVATE_DIR": private_dir, + "PRIVATE_DIR": private_dir }) def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm): -- cgit From a819f4e88c9398dbac17d102ad8b58e1a5f02df3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 21 Jul 2008 13:05:23 +0200 Subject: s3 cli_do_rpc_ndr does not use PI_* anymore (This used to be commit e625c6b2516111002c99239c1a2188c6d5d87ab6) --- source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm | 1 - 1 file changed, 1 deletion(-) diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm b/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm index 87ed29b54e..d2ab407eb0 100644 --- a/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm +++ b/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm @@ -153,7 +153,6 @@ sub ParseFunction($$$) $self->pidl(""); $self->pidl("status = cli_do_rpc_ndr(cli,"); $self->pidl("\t\t\tmem_ctx,"); - $self->pidl("\t\t\tPI_$uif,"); $self->pidl("\t\t\t&ndr_table_$if,"); $self->pidl("\t\t\t$ufn,"); $self->pidl("\t\t\t&r);"); -- cgit From 2abe5e9240af3970f0f06a492bb520a569cd77b0 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 22 Jul 2008 11:37:32 +0200 Subject: drsuapi.idl: add drsuapi_DsBindInfo48. This is necessary to make DsGetNcChanges work with win2008. Michael (This used to be commit dd278b069b8683a0e3721ebb7d0de06d2bc1c86f) --- source4/librpc/idl/drsuapi.idl | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl index b9cff5d11d..c0d82babc4 100644 --- a/source4/librpc/idl/drsuapi.idl +++ b/source4/librpc/idl/drsuapi.idl @@ -73,6 +73,15 @@ interface drsuapi uint32 repl_epoch; } drsuapi_DsBindInfo28; + /* this is used by w2k8 */ + typedef struct { + drsuapi_SupportedExtensions supported_extensions; + GUID site_guid; + uint32 u1; + uint32 repl_epoch; + uint32 unknown[5]; + } drsuapi_DsBindInfo48; + typedef struct { [flag(NDR_REMAINING)] DATA_BLOB info; } drsuapi_DsBindInfoFallBack; @@ -80,6 +89,7 @@ interface drsuapi typedef [nodiscriminant] union { [case(24)][subcontext(4)] drsuapi_DsBindInfo24 info24; [case(28)][subcontext(4)] drsuapi_DsBindInfo28 info28; + [case(48)][subcontext(4)] drsuapi_DsBindInfo48 info48; [default][subcontext(4)] drsuapi_DsBindInfoFallBack FallBack; } drsuapi_DsBindInfo; -- cgit From e7785a371a1881eb1ad5ee6cf8d2de2b4537fa39 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 22 Jul 2008 12:46:04 +0200 Subject: drsuapi.idl: the last 16 bytes in DsBindInfo48 ar the GUID of the config dn. This bit seems not to be documented in the WSPP docs. Michael (This used to be commit 705f79bd0a5e93daa0cb11b5dcca36e75c75df93) --- source4/librpc/idl/drsuapi.idl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl index c0d82babc4..96cb56ba3d 100644 --- a/source4/librpc/idl/drsuapi.idl +++ b/source4/librpc/idl/drsuapi.idl @@ -79,7 +79,8 @@ interface drsuapi GUID site_guid; uint32 u1; uint32 repl_epoch; - uint32 unknown[5]; + uint32 unknown; + GUID config_dn_guid; } drsuapi_DsBindInfo48; typedef struct { -- cgit From 901e764fa75030c22e4bda37e384dc074bcceb08 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 22 Jul 2008 13:07:55 +0200 Subject: drsuapi.idl: add drsuapi_SupportedExtensionsExt bitfield. This knowledge is obtained from the wspp-docs (section 5.35). Michael (This used to be commit f5afb695045b1a2f3b8c00a4d82d40e8e50726c9) --- source4/librpc/idl/drsuapi.idl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl index 96cb56ba3d..ee1f5c8139 100644 --- a/source4/librpc/idl/drsuapi.idl +++ b/source4/librpc/idl/drsuapi.idl @@ -58,6 +58,11 @@ interface drsuapi DRSUAPI_SUPPORTED_EXTENSION_80000000 = 0x80000000 } drsuapi_SupportedExtensions; + typedef [bitmap32bit] bitmap { + DRSUAPI_SUPPORTED_EXTENSION_ADAM = 0x00000001, + DRSUAPI_SUPPORTED_EXTENSION_LH_BETA2 = 0x00000002 + } drsuapi_SupportedExtensionsExt; + /* this is used by w2k */ typedef struct { drsuapi_SupportedExtensions supported_extensions; @@ -79,7 +84,7 @@ interface drsuapi GUID site_guid; uint32 u1; uint32 repl_epoch; - uint32 unknown; + drsuapi_SupportedExtensionsExt supported_extensions_ext; GUID config_dn_guid; } drsuapi_DsBindInfo48; -- cgit From e184b70768881ed9a4e957de630047ca292bc96e Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 22 Jul 2008 15:33:26 +0200 Subject: drsuapi.idl: change the u1 field in DsBindInfo* to "pid". According to the WSPP docs, section 5.35, this is the "process identifyer" of the client. It is meant for informational and debugging purposes only and its assignment is implementation specific. Michael (This used to be commit 579306eb5b58b6c1142b3c489e4bcf6da50810d6) --- source4/librpc/idl/drsuapi.idl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl index ee1f5c8139..c19da4fa19 100644 --- a/source4/librpc/idl/drsuapi.idl +++ b/source4/librpc/idl/drsuapi.idl @@ -67,14 +67,14 @@ interface drsuapi typedef struct { drsuapi_SupportedExtensions supported_extensions; GUID site_guid; - uint32 u1; + uint32 pid; } drsuapi_DsBindInfo24; /* this is used by w2k3 */ typedef struct { drsuapi_SupportedExtensions supported_extensions; GUID site_guid; - uint32 u1; + uint32 pid; uint32 repl_epoch; } drsuapi_DsBindInfo28; @@ -82,7 +82,7 @@ interface drsuapi typedef struct { drsuapi_SupportedExtensions supported_extensions; GUID site_guid; - uint32 u1; + uint32 pid; uint32 repl_epoch; drsuapi_SupportedExtensionsExt supported_extensions_ext; GUID config_dn_guid; @@ -1425,7 +1425,7 @@ interface drsuapi GUID bind_guid; NTTIME_1sec bind_time; [flag(NDR_BIG_ENDIAN)] ipv4address client_ip_address; - uint32 u5; /* this is the same value the client used as u1 in the DsBindInfoX struct */ + uint32 u5; /* this is the same value the client used as pid in the DsBindInfoX struct */ } drsuapi_DsReplicaConnection04; typedef struct { -- cgit From 7fba6c649ba36ca5b76dcfed7b773567c9933077 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 22 Jul 2008 15:35:23 +0200 Subject: Change occurrences of the u1 member of DsBindInfo* to pid after idl change. Michael (This used to be commit b91bbc5fe4a47e5823be6be5f2f203f1f14105de) --- source4/dsdb/repl/drepl_out_helpers.c | 2 +- source4/dsdb/repl/drepl_service.c | 2 +- source4/libnet/libnet_become_dc.c | 6 +++--- source4/libnet/libnet_unbecome_dc.c | 4 ++-- source4/rpc_server/drsuapi/dcesrv_drsuapi.c | 15 +++++++++------ source4/torture/rpc/dssync.c | 6 +++--- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c index 281e5691e2..0700867543 100644 --- a/source4/dsdb/repl/drepl_out_helpers.c +++ b/source4/dsdb/repl/drepl_out_helpers.c @@ -142,7 +142,7 @@ static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req) info24 = &st->bind_r.out.bind_info->info.info24; st->drsuapi->remote_info28.supported_extensions = info24->supported_extensions; st->drsuapi->remote_info28.site_guid = info24->site_guid; - st->drsuapi->remote_info28.u1 = info24->u1; + st->drsuapi->remote_info28.pid = info24->pid; st->drsuapi->remote_info28.repl_epoch = 0; break; } diff --git a/source4/dsdb/repl/drepl_service.c b/source4/dsdb/repl/drepl_service.c index e485c50a47..3611258ca5 100644 --- a/source4/dsdb/repl/drepl_service.c +++ b/source4/dsdb/repl/drepl_service.c @@ -104,7 +104,7 @@ static WERROR dreplsrv_connect_samdb(struct dreplsrv_service *service, struct lo /* TODO: fill in site_guid */ bind_info28->site_guid = GUID_zero(); /* TODO: find out how this is really triggered! */ - bind_info28->u1 = 0; + bind_info28->pid = 0; bind_info28->repl_epoch = 0; return WERR_OK; diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index 3fece1a9ba..556ba8045d 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -1604,9 +1604,9 @@ static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s, bind_info28->site_guid = s->dest_dsa.site_guid; if (s->domain.behavior_version == 2) { /* TODO: find out how this is really triggered! */ - bind_info28->u1 = 528; + bind_info28->pid = 528; } else { - bind_info28->u1 = 516; + bind_info28->pid = 516; } bind_info28->repl_epoch = 0; @@ -1636,7 +1636,7 @@ static WERROR becomeDC_drsuapi_bind_recv(struct libnet_BecomeDC_state *s, info24 = &drsuapi->bind_r.out.bind_info->info.info24; drsuapi->remote_info28.supported_extensions = info24->supported_extensions; drsuapi->remote_info28.site_guid = info24->site_guid; - drsuapi->remote_info28.u1 = info24->u1; + drsuapi->remote_info28.pid = info24->pid; drsuapi->remote_info28.repl_epoch = 0; break; } diff --git a/source4/libnet/libnet_unbecome_dc.c b/source4/libnet/libnet_unbecome_dc.c index cff919018a..e01af25f3f 100644 --- a/source4/libnet/libnet_unbecome_dc.c +++ b/source4/libnet/libnet_unbecome_dc.c @@ -574,7 +574,7 @@ static void unbecomeDC_drsuapi_bind_send(struct libnet_UnbecomeDC_state *s) bind_info28 = &s->drsuapi.local_info28; bind_info28->supported_extensions = 0; bind_info28->site_guid = GUID_zero(); - bind_info28->u1 = 508; + bind_info28->pid = 508; bind_info28->repl_epoch = 0; s->drsuapi.bind_info_ctr.length = 28; @@ -612,7 +612,7 @@ static void unbecomeDC_drsuapi_bind_recv(struct rpc_request *req) info24 = &s->drsuapi.bind_r.out.bind_info->info.info24; s->drsuapi.remote_info28.supported_extensions = info24->supported_extensions; s->drsuapi.remote_info28.site_guid = info24->site_guid; - s->drsuapi.remote_info28.u1 = info24->u1; + s->drsuapi.remote_info28.pid = info24->pid; s->drsuapi.remote_info28.repl_epoch = 0; break; } diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c index e0a222e767..bbb78cb778 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c @@ -45,7 +45,7 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C struct ldb_result *ntds_res; struct ldb_dn *ntds_dn; static const char *ntds_attrs[] = { "ms-DS-ReplicationEpoch", NULL }; - uint32_t u1; + uint32_t pid; uint32_t repl_epoch; int ret; @@ -98,9 +98,12 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C repl_epoch = samdb_result_uint(ntds_res->msgs[0], "ms-DS-ReplicationEpoch", 0); /* - * TODO: find out what this is... + * The "process identifier" of the client. + * According to the WSPP docs, sectin 5.35, this is + * for informational and debugging purposes only. + * The assignment is implementation specific. */ - u1 = 0; + pid = 0; /* * store the clients bind_guid @@ -119,7 +122,7 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C info24 = &r->in.bind_info->info.info24; b_state->remote_info28.supported_extensions = info24->supported_extensions; b_state->remote_info28.site_guid = info24->site_guid; - b_state->remote_info28.u1 = info24->u1; + b_state->remote_info28.pid = info24->pid; b_state->remote_info28.repl_epoch = 0; break; } @@ -171,8 +174,8 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS; #endif b_state->local_info28.site_guid = site_guid; - b_state->local_info28.u1 = u1; - b_state->local_info28.repl_epoch = repl_epoch; + b_state->local_info28.pid = pid; + b_state->local_info28.repl_epoch = repl_epoch; /* * allocate the return bind_info diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c index 053f78e99b..35fd4df845 100644 --- a/source4/torture/rpc/dssync.c +++ b/source4/torture/rpc/dssync.c @@ -104,7 +104,7 @@ static struct DsSyncTest *test_create_context(struct torture_context *tctx) our_bind_info28->supported_extensions = 0xFFFFFFFF; our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3; our_bind_info28->site_guid = GUID_zero(); - our_bind_info28->u1 = 0; + our_bind_info28->pid = 0; our_bind_info28->repl_epoch = 1; our_bind_info_ctr = &ctx->admin.drsuapi.our_bind_info_ctr; @@ -153,7 +153,7 @@ static struct DsSyncTest *test_create_context(struct torture_context *tctx) our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS; } our_bind_info28->site_guid = GUID_zero(); - our_bind_info28->u1 = 508; + our_bind_info28->pid = 508; our_bind_info28->repl_epoch = 0; our_bind_info_ctr = &ctx->new_dc.drsuapi.our_bind_info_ctr; @@ -210,7 +210,7 @@ static bool _test_DsBind(struct torture_context *tctx, info24 = &b->req.out.bind_info->info.info24; b->peer_bind_info28.supported_extensions= info24->supported_extensions; b->peer_bind_info28.site_guid = info24->site_guid; - b->peer_bind_info28.u1 = info24->u1; + b->peer_bind_info28.pid = info24->pid; b->peer_bind_info28.repl_epoch = 0; break; } -- cgit From e0bd9e82eae6dc3623a247b4294659faeb23a20d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Jul 2008 13:49:00 +1000 Subject: Explain where some other OIDs are allocated. This is an odd place for an OID registry - we perhaps need a central wiki page. Andrew Bartlett (This used to be commit 1c909973977ae117703c1ccf7589acc4625e76e5) --- source4/setup/schema_samba4.ldif | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif index 21d17c5caa..3e129e4f6b 100644 --- a/source4/setup/schema_samba4.ldif +++ b/source4/setup/schema_samba4.ldif @@ -3,9 +3,15 @@ # ## Samba4 OID allocation from Samba3's examples/LDAP/samba.schema ## 1.3.6.1.4.1.7165.4.1.x - attributetypes + ## 1.3.6.1.4.1.7165.4.2.x - objectclasses + ## 1.3.6.1.4.1.7165.4.3.x - LDB/LDAP Controls +### see dsdb/samdb/samdb.h + ## 1.3.6.1.4.1.7165.4.4.x - LDB/LDAP Extended Operations +### see dsdb/samdb/samdb.h + ## 1.3.6.1.4.1.7165.4.255.x - mapped OIDs due to conflicts between AD and standards-track # # -- cgit From d6fdd13dec854c681ad047d104ccfc2bf0ca5de5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Jul 2008 16:14:20 +1000 Subject: Remove the 'accoc_group_id' check in the RPC server. This check breaks more than it fixes, and while technically not correct, is the best solution we have at this time. Otherwise, SCHANNEL binds from WinXP fail. Andrew Bartlett (This used to be commit f8628fa330abcd50923d995d5bda1f4811582ea9) --- source4/rpc_server/dcerpc_server.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index d8dafd61f6..91ae5fcd94 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -534,9 +534,20 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) uint32_t context_id; const struct dcesrv_interface *iface; +#if 0 + /* It is not safe to enable this check - windows clients + * (WinXP in particular) will use it for NETLOGON calls, for + * the subsequent SCHANNEL bind. It turns out that NETLOGON + * calls include no policy handles, so it is safe there. Let + * the failure occour on the attempt to reuse a poilcy handle, + * rather than here */ + + /* Association groups allow policy handles to be shared across + * multiple client connections. We don't implement this yet. */ if (call->pkt.u.bind.assoc_group_id != 0) { return dcesrv_bind_nak(call, 0); } +#endif if (call->pkt.u.bind.num_contexts < 1 || call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) { -- cgit From 768515f4ad13785729fcd4df7cecaede39b7409a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 23 Jul 2008 16:19:54 +1000 Subject: The SMB session key must not be more than 16 bytes in SAMR (and presumably LSA). Tests show that Vista requires the sesion key to be truncated for a domain join. Andrew Bartlett (This used to be commit af629a3738298d27eb2dbecf466ceb503cec9638) --- source4/librpc/rpc/dcerpc_util.c | 14 ++++++++++++-- source4/rpc_server/dcerpc_server.c | 11 ++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 71c6d5f2cc..32646e85b0 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -647,11 +647,21 @@ NTSTATUS dcerpc_generic_session_key(struct dcerpc_connection *c, /* fetch the user session key - may be default (above) or the SMB session key + + The key is always truncated to 16 bytes */ _PUBLIC_ NTSTATUS dcerpc_fetch_session_key(struct dcerpc_pipe *p, - DATA_BLOB *session_key) + DATA_BLOB *session_key) { - return p->conn->security_state.session_key(p->conn, session_key); + NTSTATUS status; + status = p->conn->security_state.session_key(p->conn, session_key); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + session_key->length = MIN(session_key->length, 16); + + return NT_STATUS_OK; } diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index d8dafd61f6..fb487dfdcf 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -270,11 +270,20 @@ NTSTATUS dcesrv_generic_session_key(struct dcesrv_connection *p, /* fetch the user session key - may be default (above) or the SMB session key + + The key is always truncated to 16 bytes */ _PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p, DATA_BLOB *session_key) { - return p->auth_state.session_key(p, session_key); + NTSTATUS status = p->auth_state.session_key(p, session_key); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + session_key->length = MIN(session_key->length, 16); + + return NT_STATUS_OK; } -- cgit From 945eedc4c1b578d22707d070eacfab82f5619a04 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 17 Jul 2008 13:36:59 +0200 Subject: libnet/become_dc: add a comment and explain why it's important to specify krb5 metze (This used to be commit 26d1f9366d8611af1a69095b4cede2d2c95c982d) --- source4/libnet/libnet_become_dc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index 556ba8045d..31a9206d86 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -1516,6 +1516,15 @@ static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s, drsuapi->s = s; if (!drsuapi->binding) { + /* + * Note: It's important to pass 'krb5' as auth_type here + * otherwise the replication will not work with + * Windows 2000. If NTLMSSP is used Windows 2000 + * returns garbage in the DsGetNCChanges() response + * if encrypted password attributes would be in the response. + * That means the replication of the schema and configuration + * partition works fine, but it fails for the domain partition. + */ if (lp_parm_bool(s->libnet->lp_ctx, NULL, "become_dc", "print", false)) { binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[krb5,print,seal]", s->source_dsa.dns_name); if (composite_nomem(binding_str, c)) return; -- cgit From 935a7b3389615cadce4defa610b74072a286eac4 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 23 Jul 2008 11:05:24 +0200 Subject: smbtorture: add support for the DSBindInfo48 to the RPC-DSSYNC test. Michael (This used to be commit 67a99e445871861945fd0a45784cffb358bdccf3) --- source4/torture/rpc/dssync.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c index 35fd4df845..6b82b6bf0f 100644 --- a/source4/torture/rpc/dssync.c +++ b/source4/torture/rpc/dssync.c @@ -214,6 +214,15 @@ static bool _test_DsBind(struct torture_context *tctx, b->peer_bind_info28.repl_epoch = 0; break; } + case 48: { + struct drsuapi_DsBindInfo48 *info48; + info48 = &b->req.out.bind_info->info.info48; + b->peer_bind_info28.supported_extensions= info48->supported_extensions; + b->peer_bind_info28.site_guid = info48->site_guid; + b->peer_bind_info28.pid = info48->pid; + b->peer_bind_info28.repl_epoch = info48->repl_epoch; + break; + } case 28: b->peer_bind_info28 = b->req.out.bind_info->info.info28; break; -- cgit From a9c3f4700c16e50b963b83bed9b9699f4e37322c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 23 Jul 2008 11:06:50 +0200 Subject: smbtorture: add a warning for unknown BindInfo length to the RPC-DSSYNC test Michael (This used to be commit 7ee99105ea3a50d8ee2c83ecd39e834ed9efb98c) --- source4/torture/rpc/dssync.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c index 6b82b6bf0f..3279047c6a 100644 --- a/source4/torture/rpc/dssync.c +++ b/source4/torture/rpc/dssync.c @@ -226,6 +226,9 @@ static bool _test_DsBind(struct torture_context *tctx, case 28: b->peer_bind_info28 = b->req.out.bind_info->info.info28; break; + default: + printf("DsBind - warning: unknown BindInfo length: %u\n", + b->req.out.bind_info->length); } } -- cgit From 5bb679aa0fe87b5dd7f7c82d09157bc93b8b54cb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 14:41:16 +0200 Subject: rpc_server: be more strict with the incoming assoc_group_id Allow 0 and 0x12345678 only. This fixes the RPC-HANDLES test. metze (This used to be commit c123e597cc84685abf2b0d3564e1a26d80bbef2f) --- source4/rpc_server/dcerpc_server.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index a2ca897981..ac36825acd 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -543,20 +543,20 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) uint32_t context_id; const struct dcesrv_interface *iface; -#if 0 - /* It is not safe to enable this check - windows clients - * (WinXP in particular) will use it for NETLOGON calls, for - * the subsequent SCHANNEL bind. It turns out that NETLOGON - * calls include no policy handles, so it is safe there. Let - * the failure occour on the attempt to reuse a poilcy handle, - * rather than here */ - - /* Association groups allow policy handles to be shared across - * multiple client connections. We don't implement this yet. */ - if (call->pkt.u.bind.assoc_group_id != 0) { + /* + * Association groups allow policy handles to be shared across + * multiple client connections. We don't implement this yet. + * + * So we just allow 0 if the client wants to create a new + * association group. + * + * And we allow the 0x12345678 value, we give away as + * assoc_group_id back to the clients + */ + if (call->pkt.u.bind.assoc_group_id != 0 && + call->pkt.u.bind.assoc_group_id != 0x12345678) { return dcesrv_bind_nak(call, 0); } -#endif if (call->pkt.u.bind.num_contexts < 1 || call->pkt.u.bind.ctx_list[0].num_transfer_syntaxes < 1) { -- cgit From 734d0c0a5def566ad8a8167c81e06bd9b31b4645 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 14:06:36 +0200 Subject: RPC-DSSYNC: print 'supplementalCredentials' more verbosely metze (This used to be commit 6a7637b12e4a34915a53e81a0f47571da21fdc5a) --- source4/torture/rpc/dssync.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c index 3279047c6a..822cd088f1 100644 --- a/source4/torture/rpc/dssync.c +++ b/source4/torture/rpc/dssync.c @@ -23,6 +23,7 @@ #include "includes.h" #include "lib/cmdline/popt_common.h" #include "librpc/gen_ndr/ndr_drsuapi_c.h" +#include "librpc/gen_ndr/ndr_drsblobs.h" #include "libcli/cldap/cldap.h" #include "libcli/ldap/ldap_client.h" #include "torture/torture.h" @@ -526,6 +527,8 @@ static void test_analyse_objects(struct torture_context *tctx, DEBUGADD(0,("ATTR: %s enc.length=%lu plain.length=%lu\n", name, (long)enc_data->length, (long)plain_data.length)); if (plain_data.length) { + enum ndr_err_code ndr_err; + struct supplementalCredentialsBlob scb; dump_data(0, plain_data.data, plain_data.length); if (save_values_dir) { char *fname; @@ -541,6 +544,13 @@ static void test_analyse_objects(struct torture_context *tctx, } talloc_free(fname); } + + ndr_err = ndr_pull_struct_blob_all(&plain_data, tctx, + lp_iconv_convenience(tctx->lp_ctx), &scb, + (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob); + if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NDR_PRINT_DEBUG(supplementalCredentialsBlob, &scb); + } } else { dump_data(0, enc_data->data, enc_data->length); } -- cgit From 75cdaa4c84485bccb27ad6e09281248077b243c3 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 18:34:14 +0200 Subject: hdb-ldb: fix crash bug in the error path metze (This used to be commit ac02d6a0f765e3b66fb6796f129edb1a348ecd84) --- source4/kdc/hdb-ldb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c index 70e578ee0d..8c5a1f53e9 100644 --- a/source4/kdc/hdb-ldb.c +++ b/source4/kdc/hdb-ldb.c @@ -325,6 +325,7 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context, if (!use) continue; key.mkvno = 0; + key.salt = NULL; if (pkb3->salt.string) { DATA_BLOB salt; -- cgit From b4e9e8954a3467203f2ec4bb5c7b7b580f47ef36 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 18:46:24 +0200 Subject: hdb-ldb: fix comment about padding metze (This used to be commit ca28d05b11e602e0f98cda0e02f973562c199dc6) --- source4/kdc/hdb-ldb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c index 8c5a1f53e9..656849334a 100644 --- a/source4/kdc/hdb-ldb.c +++ b/source4/kdc/hdb-ldb.c @@ -249,7 +249,7 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context, } talloc_steal(mem_ctx, blob.data); - /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */ + /* we cannot use ndr_pull_struct_blob_all() here, as w2k and w2k3 add padding bytes */ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, iconv_convenience, &_pkb, (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { -- cgit From bcb0db3634680fdaf1d037545fafe7509ed72ad9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 18:31:45 +0200 Subject: password_hash: don't add zero padding as w2k8 also don't add it metze (This used to be commit 26e9169d454349795ad0bc64d7f65059541ab89e) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 3e442b6341..2dddb26550 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -925,16 +925,6 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) nt_errstr(status)); return LDB_ERR_OPERATIONS_ERROR; } - /* - * TODO: - * - * This is ugly, but we want to generate the same blob as - * w2k and w2k3...we should handle this in the idl - */ - if (!data_blob_append(io->ac, &pkb_blob, zero16, sizeof(zero16))) { - ldb_oom(io->ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } pkb_hexstr = data_blob_hex_string(io->ac, &pkb_blob); if (!pkb_hexstr) { ldb_oom(io->ac->module->ldb); -- cgit From bb12c78d44f005bad9524af86ce9a1b2b98f16ad Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 13:53:03 +0200 Subject: drsblobs.idl: rename unknown1 -> reserved metze (This used to be commit 9a70b2237d4fdd523edfbca0329ad35e71faf998) --- source4/librpc/idl/drsblobs.idl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl index f8cbdac8c5..2f9819a10c 100644 --- a/source4/librpc/idl/drsblobs.idl +++ b/source4/librpc/idl/drsblobs.idl @@ -205,7 +205,7 @@ interface drsblobs { typedef struct { [value(2*strlen_m(name))] uint16 name_len; [value(strlen(data))] uint16 data_len; - uint16 unknown1; /* 2 for name = 'Packages', 1 for name = 'Primary:*' */ + uint16 reserved; /* 2 for 'Packages', 1 for 'Primary:*', but should be ignored */ [charset(UTF16)] uint8 name[name_len]; /* * the data field contains data as HEX strings -- cgit From 69d3f0e602893875118878a4b11c2a65f9d4090c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 12:00:42 +0200 Subject: password_hash: ignore reserved value, but still set it like windows does metze (This used to be commit 5b860572686167d0291161f6597f143e538e2f3a) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 2dddb26550..e149009948 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -446,10 +446,6 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, } for (i=0; i < old_scb->sub.num_packages; i++) { - if (old_scb->sub.packages[i].unknown1 != 0x00000001) { - continue; - } - if (strcmp("Primary:Kerberos", old_scb->sub.packages[i].name) != 0) { continue; } @@ -931,7 +927,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return LDB_ERR_OPERATIONS_ERROR; } pk->name = "Primary:Kerberos"; - pk->unknown1 = 1; + pk->reserved = 1; pk->data = pkb_hexstr; /* @@ -962,7 +958,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return LDB_ERR_OPERATIONS_ERROR; } pd->name = "Primary:WDigest"; - pd->unknown1 = 1; + pd->reserved = 1; pd->data = pdb_hexstr; /* @@ -991,7 +987,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return LDB_ERR_OPERATIONS_ERROR; } pc->name = "Primary:CLEARTEXT"; - pc->unknown1 = 1; + pc->reserved = 1; pc->data = pcb_hexstr; } @@ -1016,7 +1012,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return LDB_ERR_OPERATIONS_ERROR; } pp->name = "Packages"; - pp->unknown1 = 2; + pp->reserved = 2; pp->data = pb_hexstr; /* -- cgit From ecdd13389fd1b262024fe663a57da11f8a84e239 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 13:06:32 +0200 Subject: drsblobs.idl: fix idl for supplementalCredentialsSubBlob metze (This used to be commit 24c5b10136f6e640832193aaf9e6d7e865c288bc) --- source4/librpc/idl/drsblobs.idl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl index 2f9819a10c..4829952cf8 100644 --- a/source4/librpc/idl/drsblobs.idl +++ b/source4/librpc/idl/drsblobs.idl @@ -228,11 +228,16 @@ interface drsblobs { [charset(DOS)] uint8 data[data_len]; } supplementalCredentialsPackage; - /* this are 0x30 (48) whitespaces (0x20) followed by 'P' (0x50) */ - const string SUPPLEMENTAL_CREDENTIALS_PREFIX = " P"; + /* this are 0x30 (48) whitespaces (0x20) */ + const string SUPPLEMENTAL_CREDENTIALS_PREFIX = " "; + + typedef [flag(NDR_PAHEX)] enum { + SUPPLEMENTAL_CREDENTIALS_SIGNATURE = 0x0050 + } supplementalCredentialsSignature; typedef [gensize] struct { - [value(SUPPLEMENTAL_CREDENTIALS_PREFIX),charset(UTF16)] uint16 prefix[0x31]; + [value(SUPPLEMENTAL_CREDENTIALS_PREFIX),charset(UTF16)] uint16 prefix[0x30]; + [value(SUPPLEMENTAL_CREDENTIALS_SIGNATURE)] supplementalCredentialsSignature signature; uint16 num_packages; supplementalCredentialsPackage packages[num_packages]; } supplementalCredentialsSubBlob; -- cgit From fbea02accfa8f92d84d0f2cb17847dac1519aa87 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 13:31:14 +0200 Subject: password_hash: check the SUPPLEMENTAL_CREDENTIALS_SIGNATURE metze (This used to be commit 19b8c8e37bafab050ab61266c35006efada2947c) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index e149009948..59ec18e546 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -876,7 +876,9 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* if there's an old supplementaCredentials blob then parse it */ if (io->o.supplemental) { - ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), &_old_scb, + ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac, + lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), + &_old_scb, (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); @@ -887,7 +889,14 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) return LDB_ERR_OPERATIONS_ERROR; } - old_scb = &_old_scb; + if (_old_scb.sub.signature == SUPPLEMENTAL_CREDENTIALS_SIGNATURE) { + old_scb = &_old_scb; + } else { + ldb_debug(io->ac->module->ldb, LDB_DEBUG_ERROR, + "setup_supplemental_field: " + "supplementalCredentialsBlob signature[0x%04X] expected[0x%04X]", + _old_scb.sub.signature, SUPPLEMENTAL_CREDENTIALS_SIGNATURE); + } } if (io->domain->store_cleartext && -- cgit From fa40b0709ab60476d295837e73a1326bb056fc73 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 13:41:51 +0200 Subject: hdb-ldb: check the SUPPLEMENTAL_CREDENTIALS_SIGNATURE metze (This used to be commit 7219740ef434091617c6bb727374251987ff2a62) --- source4/kdc/hdb-ldb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c index 656849334a..4b47dbf259 100644 --- a/source4/kdc/hdb-ldb.c +++ b/source4/kdc/hdb-ldb.c @@ -221,6 +221,12 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context, goto out; } + if (scb.sub.signature != SUPPLEMENTAL_CREDENTIALS_SIGNATURE) { + NDR_PRINT_DEBUG(supplementalCredentialsBlob, &scb); + ret = EINVAL; + goto out; + } + for (i=0; i < scb.sub.num_packages; i++) { if (scb.sub.packages[i].unknown1 != 0x00000001) { continue; -- cgit From e3434f8995ef834a1b8f452060544862b2a9642b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 08:53:34 +0200 Subject: drsblobs.idl: fix unknowns in package_PrimaryKerberos idl metze (This used to be commit da9ceb2bf17f964334d9317829d40483e2c04b10) --- source4/librpc/idl/drsblobs.idl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl index 4829952cf8..ec29c2732d 100644 --- a/source4/librpc/idl/drsblobs.idl +++ b/source4/librpc/idl/drsblobs.idl @@ -269,23 +269,25 @@ interface drsblobs { } package_PrimaryKerberosString; typedef struct { + [value(0)] uint16 reserved1; + [value(0)] uint16 reserved2; + [value(0)] uint32 reserved3; uint32 keytype; [value((value?value->length:0))] uint32 value_len; [relative,subcontext(0),subcontext_size(value_len),flag(NDR_REMAINING)] DATA_BLOB *value; - [value(0)] uint32 unknown1; - [value(0)] uint32 unknown2; } package_PrimaryKerberosKey; typedef struct { uint16 num_keys; uint16 num_old_keys; package_PrimaryKerberosString salt; - [value(0)] uint32 unknown1; - [value(0)] uint32 unknown2; package_PrimaryKerberosKey keys[num_keys]; package_PrimaryKerberosKey old_keys[num_old_keys]; - udlong unknown3[num_keys]; - udlong unknown3_old[num_old_keys]; + [value(0)] uint32 padding1; + [value(0)] uint32 padding2; + [value(0)] uint32 padding3; + [value(0)] uint32 padding4; + [value(0)] uint32 padding5; } package_PrimaryKerberosCtr3; typedef [nodiscriminant] union { -- cgit From e0f04e36ad415d7396fea7d43eb1d0db53d53a69 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 10:05:43 +0200 Subject: password_hash: fix callers after idl change for package_PrimaryKerberos metze (This used to be commit 1bf552856f3a930c4716ceb73d9ba9adf7502d3d) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 59ec18e546..5bbae2c164 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -336,11 +336,6 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - pkb3->unknown3 = talloc_zero_array(io->ac, uint64_t, pkb3->num_keys); - if (!pkb3->unknown3) { - ldb_oom(io->ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } if (lp_parm_bool(ldb_get_opaque(io->ac->module->ldb, "loadparm"), NULL, "password_hash", "create_aes_key", false)) { /* @@ -438,7 +433,6 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, /* initialize the old keys to zero */ pkb3->num_old_keys = 0; pkb3->old_keys = NULL; - pkb3->unknown3_old = NULL; /* if there're no old keys, then we're done */ if (!old_scb) { @@ -499,7 +493,6 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, /* fill in the old keys */ pkb3->num_old_keys = old_pkb3->num_keys; pkb3->old_keys = old_pkb3->keys; - pkb3->unknown3_old = old_pkb3->unknown3; return LDB_SUCCESS; } -- cgit From b783b28d70d787d7524e8afd54c24ef6f3f8bf54 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 18:32:49 +0200 Subject: password_hash: simplify the logic if we have cleartext we always generate the hashes metze (This used to be commit 5edff84429ef0d03b47a438e18861d26c97e17b6) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 5bbae2c164..8dd4e1e76b 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -1071,7 +1071,7 @@ static int setup_password_fields(struct setup_password_fields_io *io) return LDB_ERR_UNWILLING_TO_PERFORM; } - if (io->n.cleartext && !io->n.nt_hash) { + if (io->n.cleartext) { struct samr_Password *hash; hash = talloc(io->ac, struct samr_Password); @@ -1092,7 +1092,7 @@ static int setup_password_fields(struct setup_password_fields_io *io) } } - if (io->n.cleartext && !io->n.lm_hash) { + if (io->n.cleartext) { struct samr_Password *hash; hash = talloc(io->ac, struct samr_Password); -- cgit From 12ac4c5666d56dc806a613584fa72e7c2f29c34e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 18:27:36 +0200 Subject: password_hash: split the generation of krb5 keys into a different function metze (This used to be commit 4ad73a0bf8952783d3d9a7339c0c4fd8ca28981a) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 161 +++++++++++-------------- 1 file changed, 69 insertions(+), 92 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 8dd4e1e76b..9996e89cc6 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -140,6 +140,9 @@ struct setup_password_fields_io { struct samr_Password *nt_history; uint32_t lm_history_len; struct samr_Password *lm_history; + const char *salt; + DATA_BLOB des_md5; + DATA_BLOB des_crc; struct ldb_val supplemental; NTTIME last_set; uint32_t kvno; @@ -216,21 +219,12 @@ static int setup_lm_fields(struct setup_password_fields_io *io) return LDB_SUCCESS; } -static int setup_primary_kerberos(struct setup_password_fields_io *io, - const struct supplementalCredentialsBlob *old_scb, - struct package_PrimaryKerberosBlob *pkb) +static int setup_kerberos_keys(struct setup_password_fields_io *io) { krb5_error_code krb5_ret; Principal *salt_principal; krb5_salt salt; krb5_keyblock key; - uint32_t k=0; - struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3; - struct supplementalCredentialsPackage *old_scp = NULL; - struct package_PrimaryKerberosBlob _old_pkb; - struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL; - uint32_t i; - enum ndr_err_code ndr_err; /* Many, many thanks to lukeh@padl.com for this * algorithm, described in his Nov 10 2004 mail to @@ -290,7 +284,7 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, } if (krb5_ret) { ldb_asprintf_errstring(io->ac->module->ldb, - "setup_primary_kerberos: " + "setup_kerberos_keys: " "generation of a salting principal failed: %s", smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); return LDB_ERR_OPERATIONS_ERROR; @@ -304,131 +298,107 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal); if (krb5_ret) { ldb_asprintf_errstring(io->ac->module->ldb, - "setup_primary_kerberos: " + "setup_kerberos_keys: " "generation of krb5_salt failed: %s", smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); return LDB_ERR_OPERATIONS_ERROR; } /* create a talloc copy */ - pkb3->salt.string = talloc_strndup(io->ac, - salt.saltvalue.data, - salt.saltvalue.length); + io->g.salt = talloc_strndup(io->ac, + salt.saltvalue.data, + salt.saltvalue.length); krb5_free_salt(io->smb_krb5_context->krb5_context, salt); - if (!pkb3->salt.string) { - ldb_oom(io->ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - salt.saltvalue.data = discard_const(pkb3->salt.string); - salt.saltvalue.length = strlen(pkb3->salt.string); - - /* - * prepare generation of keys - * - * ENCTYPE_AES256_CTS_HMAC_SHA1_96 (disabled by default) - * ENCTYPE_DES_CBC_MD5 - * ENCTYPE_DES_CBC_CRC - * - * NOTE: update num_keys when you add another enctype! - */ - pkb3->num_keys = 3; - pkb3->keys = talloc_array(io->ac, struct package_PrimaryKerberosKey, pkb3->num_keys); - if (!pkb3->keys) { + if (!io->g.salt) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } + salt.saltvalue.data = discard_const(io->g.salt); + salt.saltvalue.length = strlen(io->g.salt); - if (lp_parm_bool(ldb_get_opaque(io->ac->module->ldb, "loadparm"), NULL, "password_hash", "create_aes_key", false)) { - /* - * TODO: - * - * w2k and w2k3 doesn't support AES, so we'll not include - * the AES key here yet. - * - * Also we don't have an example supplementalCredentials blob - * from Windows Longhorn Server with AES support - * - */ /* - * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of + * create ENCTYPE_DES_CBC_MD5 key out of * the salt and the cleartext password */ krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, - ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_DES_CBC_MD5, io->n.cleartext, salt, &key); - pkb3->keys[k].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; - pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB); - if (!pkb3->keys[k].value) { - krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - ldb_oom(io->ac->module->ldb); + if (krb5_ret) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_kerberos_keys: " + "generation of a des-cbc-md5 key failed: %s", + smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); return LDB_ERR_OPERATIONS_ERROR; } - *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value, - key.keyvalue.data, - key.keyvalue.length); + io->g.des_md5 = data_blob_talloc(io->ac, + key.keyvalue.data, + key.keyvalue.length); krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - if (!pkb3->keys[k].value->data) { + if (!io->g.des_md5.data) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - k++; -} /* - * create ENCTYPE_DES_CBC_MD5 key out of + * create ENCTYPE_DES_CBC_CRC key out of * the salt and the cleartext password */ krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, - ENCTYPE_DES_CBC_MD5, + ENCTYPE_DES_CBC_CRC, io->n.cleartext, salt, &key); - pkb3->keys[k].keytype = ENCTYPE_DES_CBC_MD5; - pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB); - if (!pkb3->keys[k].value) { - krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - ldb_oom(io->ac->module->ldb); + if (krb5_ret) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_kerberos_keys: " + "generation of a des-cbc-crc key failed: %s", + smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); return LDB_ERR_OPERATIONS_ERROR; } - *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value, - key.keyvalue.data, - key.keyvalue.length); + io->g.des_crc = data_blob_talloc(io->ac, + key.keyvalue.data, + key.keyvalue.length); krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - if (!pkb3->keys[k].value->data) { + if (!io->g.des_crc.data) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - k++; + + return LDB_SUCCESS; +} + +static int setup_primary_kerberos(struct setup_password_fields_io *io, + const struct supplementalCredentialsBlob *old_scb, + struct package_PrimaryKerberosBlob *pkb) +{ + struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3; + struct supplementalCredentialsPackage *old_scp = NULL; + struct package_PrimaryKerberosBlob _old_pkb; + struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL; + uint32_t i; + enum ndr_err_code ndr_err; /* - * create ENCTYPE_DES_CBC_CRC key out of - * the salt and the cleartext password + * prepare generation of keys + * + * ENCTYPE_DES_CBC_MD5 + * ENCTYPE_DES_CBC_CRC */ - krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, - ENCTYPE_DES_CBC_CRC, - io->n.cleartext, - salt, - &key); - pkb3->keys[k].keytype = ENCTYPE_DES_CBC_CRC; - pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB); - if (!pkb3->keys[k].value) { - krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - ldb_oom(io->ac->module->ldb); - return LDB_ERR_OPERATIONS_ERROR; - } - *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value, - key.keyvalue.data, - key.keyvalue.length); - krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); - if (!pkb3->keys[k].value->data) { + pkb3->salt.string = io->g.salt; + pkb3->num_keys = 2; + pkb3->keys = talloc_array(io->ac, + struct package_PrimaryKerberosKey, + pkb3->num_keys); + if (!pkb3->keys) { ldb_oom(io->ac->module->ldb); return LDB_ERR_OPERATIONS_ERROR; } - k++; - /* fix up key number */ - pkb3->num_keys = k; + pkb3->keys[0].keytype = ENCTYPE_DES_CBC_MD5; + pkb3->keys[0].value = &io->g.des_md5; + pkb3->keys[1].keytype = ENCTYPE_DES_CBC_CRC; + pkb3->keys[1].value = &io->g.des_crc; /* initialize the old keys to zero */ pkb3->num_old_keys = 0; @@ -1110,6 +1080,13 @@ static int setup_password_fields(struct setup_password_fields_io *io) } } + if (io->n.cleartext) { + ret = setup_kerberos_keys(io); + if (ret != 0) { + return ret; + } + } + ret = setup_nt_fields(io); if (ret != 0) { return ret; -- cgit From b3d6c5ee31bed1a921ddb3387892d7e82808592d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 18:54:21 +0200 Subject: password_hash: order the supplementalCredentials Packages in the same order like windows metze (This used to be commit ca9cd81a1798fb15195566422b3cad7c282fce89) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 68 +++++++++++++++++++++----- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 9996e89cc6..8d63aed0f5 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -804,30 +804,41 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) struct supplementalCredentialsBlob scb; struct supplementalCredentialsBlob _old_scb; struct supplementalCredentialsBlob *old_scb = NULL; - /* Packages + (Kerberos, WDigest and maybe CLEARTEXT) */ - uint32_t num_packages = 1 + 2; + /* Packages + (Kerberos, WDigest and CLEARTEXT) */ + uint32_t num_names = 0; + const char *names[1+3]; + uint32_t num_packages = 0; struct supplementalCredentialsPackage packages[1+3]; - struct supplementalCredentialsPackage *pp = &packages[0]; - struct supplementalCredentialsPackage *pk = &packages[1]; - struct supplementalCredentialsPackage *pd = &packages[2]; - struct supplementalCredentialsPackage *pc = NULL; + /* Packages */ + struct supplementalCredentialsPackage *pp = NULL; struct package_PackagesBlob pb; DATA_BLOB pb_blob; char *pb_hexstr; + /* Primary:Kerberos */ + const char **nk = NULL; + struct supplementalCredentialsPackage *pk = NULL; struct package_PrimaryKerberosBlob pkb; DATA_BLOB pkb_blob; char *pkb_hexstr; + /* Primary:WDigest */ + const char **nd = NULL; + struct supplementalCredentialsPackage *pd = NULL; struct package_PrimaryWDigestBlob pdb; DATA_BLOB pdb_blob; char *pdb_hexstr; + /* Primary:CLEARTEXT */ + const char **nc = NULL; + struct supplementalCredentialsPackage *pc = NULL; struct package_PrimaryCLEARTEXTBlob pcb; DATA_BLOB pcb_blob; char *pcb_hexstr; int ret; enum ndr_err_code ndr_err; uint8_t zero16[16]; + bool do_cleartext = false; ZERO_STRUCT(zero16); + ZERO_STRUCT(names); if (!io->n.cleartext) { /* @@ -864,17 +875,46 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) if (io->domain->store_cleartext && (io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { - pc = &packages[3]; - num_packages++; + do_cleartext = true; } - /* Kerberos, WDigest, CLEARTEXT and termination(counted by the Packages element) */ - pb.names = talloc_zero_array(io->ac, const char *, num_packages); + /* + * The ordering is this + * + * Primary:Kerberos + * Primary:WDigest + * Primary:CLEARTEXT (optional) + * + * And the 'Packages' package is insert before the last + * other package. + */ + + /* Primary:Kerberos */ + nk = &names[num_names++]; + pk = &packages[num_packages++]; + + if (!do_cleartext) { + /* Packages */ + pp = &packages[num_packages++]; + } + + /* Primary:WDigest */ + nd = &names[num_names++]; + pd = &packages[num_packages++]; + + if (do_cleartext) { + /* Packages */ + pp = &packages[num_packages++]; + + /* Primary:CLEARTEXT */ + nc = &names[num_names++]; + pc = &packages[num_packages++]; + } /* * setup 'Primary:Kerberos' element */ - pb.names[0] = "Kerberos"; + *nk = "Kerberos"; ret = setup_primary_kerberos(io, old_scb, &pkb); if (ret != LDB_SUCCESS) { @@ -905,7 +945,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* * setup 'Primary:WDigest' element */ - pb.names[1] = "WDigest"; + *nd = "WDigest"; ret = setup_primary_wdigest(io, old_scb, &pdb); if (ret != LDB_SUCCESS) { @@ -937,7 +977,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) * setup 'Primary:CLEARTEXT' element */ if (pc) { - pb.names[2] = "CLEARTEXT"; + *nc = "CLEARTEXT"; pcb.cleartext = io->n.cleartext; @@ -966,6 +1006,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* * setup 'Packages' element */ + pb.names = names; ndr_err = ndr_push_struct_blob(&pb_blob, io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), &pb, @@ -990,6 +1031,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* * setup 'supplementalCredentials' value */ + ZERO_STRUCT(scb); scb.sub.num_packages = num_packages; scb.sub.packages = packages; -- cgit From 28a7e6f125070f288a9ca191ed7110f81891dc09 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 12:28:07 +0200 Subject: drsblobs.idl: add idl for Primary:Kerberos-Newer-Keys blob in supplementalCredentials metze (This used to be commit 97b7901afbccc9647ad2958d4cf12300de2655d1) --- source4/librpc/idl/drsblobs.idl | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl index ec29c2732d..c876ae7fed 100644 --- a/source4/librpc/idl/drsblobs.idl +++ b/source4/librpc/idl/drsblobs.idl @@ -215,6 +215,9 @@ interface drsblobs { * as non termiated UTF16 strings with * a UTF16 NULL byte as separator * + * 'Primary:Kerberos-Newer-Keys': + * ... + * * 'Primary:Kerberos': * ... * @@ -303,6 +306,40 @@ interface drsblobs { [in] package_PrimaryKerberosBlob blob ); + typedef struct { + [value(0)] uint32 unknown1; + [value(0)] uint32 unknown2; + [value(0x00001000)] uint32 unknown3; /* could the the iterator for the AES key creation */ + uint32 keytype; + [value((value?value->length:0))] uint32 value_len; + [relative,subcontext(0),subcontext_size(value_len),flag(NDR_REMAINING)] DATA_BLOB *value; + } package_PrimaryKerberosNewerKey; + + typedef struct { + uint16 num_keys; + [value(0)] uint16 unknown1; + uint16 num_old_keys1; + uint16 num_old_keys2; + package_PrimaryKerberosString salt; + [value(0x00001000)] uint32 unknown2; /* could the the iterator for the AES key creation */ + package_PrimaryKerberosNewerKey keys[num_keys]; + package_PrimaryKerberosNewerKey old_keys1[num_old_keys1]; + package_PrimaryKerberosNewerKey old_keys2[num_old_keys2]; + } package_PrimaryKerberosNewerCtr4; + + typedef [nodiscriminant] union { + [case(4)] package_PrimaryKerberosNewerCtr4 ctr4; + } package_PrimaryKerberosNewerCtr; + + typedef [public] struct { + [value(4)] uint32 version; + [switch_is(version)] package_PrimaryKerberosNewerCtr ctr; + } package_PrimaryKerberosNewerBlob; + + void decode_PrimaryKerberosNewer( + [in] package_PrimaryKerberosNewerBlob blob + ); + typedef [public] struct { [flag(STR_NOTERM|NDR_REMAINING)] string cleartext; } package_PrimaryCLEARTEXTBlob; -- cgit From 0842eb25a196ae9551fd93c25cbd3901df3ec537 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2008 18:47:27 +0200 Subject: hdb-ldb: try to find Primary:Kerberos-Newer-Keys and fallback to Primary:Kerberos Now provide AES tickets if we find the keys in the supplementalCredentials attribute metze (This used to be commit 8300259f103f8cfe014988fad0f7ee0d49bb1ac2) --- source4/kdc/hdb-ldb.c | 130 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 114 insertions(+), 16 deletions(-) diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c index 4b47dbf259..9960085b1a 100644 --- a/source4/kdc/hdb-ldb.c +++ b/source4/kdc/hdb-ldb.c @@ -190,9 +190,12 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context, struct samr_Password *hash; const struct ldb_val *sc_val; struct supplementalCredentialsBlob scb; - struct supplementalCredentialsPackage *scp = NULL; + struct supplementalCredentialsPackage *scpk = NULL; + struct supplementalCredentialsPackage *scpkn = NULL; struct package_PrimaryKerberosBlob _pkb; struct package_PrimaryKerberosCtr3 *pkb3 = NULL; + struct package_PrimaryKerberosNewerBlob _pknb; + struct package_PrimaryKerberosNewerCtr4 *pkb4 = NULL; uint32_t i; uint32_t allocated_keys = 0; @@ -228,27 +231,61 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context, } for (i=0; i < scb.sub.num_packages; i++) { - if (scb.sub.packages[i].unknown1 != 0x00000001) { - continue; + if (strcmp("Primary:Kerberos-Newer-Keys", scb.sub.packages[i].name) == 0) { + scpkn = &scb.sub.packages[i]; + if (!scpkn->data || !scpkn->data[0]) { + scpkn = NULL; + continue; + } + break; + } else if (strcmp("Primary:Kerberos", scb.sub.packages[i].name) == 0) { + scpk = &scb.sub.packages[i]; + if (!scpk->data || !scpk->data[0]) { + scpk = NULL; + } + /* + * we don't break here in hope to find + * a Kerberos-Newer-Keys package + */ } + } + } + /* Primary:Kerberos-Newer-Keys element of supplementalCredentials */ + if (scpkn) { + DATA_BLOB blob; - if (strcmp("Primary:Kerberos", scb.sub.packages[i].name) != 0) { - continue; - } + blob = strhex_to_data_blob(scpkn->data); + if (!blob.data) { + ret = ENOMEM; + goto out; + } + talloc_steal(mem_ctx, blob.data); - if (!scb.sub.packages[i].data || !scb.sub.packages[i].data[0]) { - continue; - } + /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */ + ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, iconv_convenience, &_pknb, + (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosNewerBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + krb5_set_error_string(context, "LDB_message2entry_keys: could not parse package_PrimaryKerberosNewerBlob"); + krb5_warnx(context, "LDB_message2entry_keys: could not parse package_PrimaryKerberosNewerBlob"); + ret = EINVAL; + goto out; + } - scp = &scb.sub.packages[i]; - break; + if (_pknb.version != 4) { + krb5_set_error_string(context, "LDB_message2entry_keys: could not parse PrimaryKerberosNewer not version 4"); + krb5_warnx(context, "LDB_message2entry_keys: could not parse PrimaryKerberosNewer not version 4"); + ret = EINVAL; + goto out; } - } - /* Primary:Kerberos element of supplementalCredentials */ - if (scp) { + + pkb4 = &_pknb.ctr.ctr4; + + allocated_keys += pkb4->num_keys; + } else if (scpk) { + /* Fallback to Primary:Kerberos element of supplementalCredentials */ DATA_BLOB blob; - blob = strhex_to_data_blob(scp->data); + blob = strhex_to_data_blob(scpk->data); if (!blob.data) { ret = ENOMEM; goto out; @@ -310,7 +347,68 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context, entry_ex->entry.keys.len++; } - if (pkb3) { + if (pkb4) { + for (i=0; i < pkb4->num_keys; i++) { + bool use = true; + Key key; + + if (!pkb4->keys[i].value) continue; + + if (userAccountControl & UF_USE_DES_KEY_ONLY) { + switch (pkb4->keys[i].keytype) { + case ENCTYPE_DES_CBC_CRC: + case ENCTYPE_DES_CBC_MD5: + break; + default: + use = false; + break; + } + } + + if (!use) continue; + + key.mkvno = 0; + key.salt = NULL; + + if (pkb4->salt.string) { + DATA_BLOB salt; + + salt = data_blob_string_const(pkb4->salt.string); + + key.salt = calloc(1, sizeof(*key.salt)); + if (key.salt == NULL) { + ret = ENOMEM; + goto out; + } + + key.salt->type = hdb_pw_salt; + + ret = krb5_data_copy(&key.salt->salt, salt.data, salt.length); + if (ret) { + free(key.salt); + key.salt = NULL; + goto out; + } + } + + ret = krb5_keyblock_init(context, + pkb4->keys[i].keytype, + pkb4->keys[i].value->data, + pkb4->keys[i].value->length, + &key.key); + if (ret) { + if (key.salt) { + free_Salt(key.salt); + free(key.salt); + key.salt = NULL; + } + goto out; + } + + entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key; + entry_ex->entry.keys.len++; + } + } else if (pkb3) { for (i=0; i < pkb3->num_keys; i++) { bool use = true; Key key; -- cgit From 34b10077f9ca742b72ad37c86357d0f16ed68ee7 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 23 Jul 2008 09:35:19 +0200 Subject: password_hash: add generation of the Primary:Kerberos-Newer-Keys blob But it's still of by default until we now what triggers this generation. It could be that the value is always generated but the KDC only uses it when in a specific funtional level, but it could also be that it's only generated in a specific functional level. metze (This used to be commit 08618bbd508ede0bb9e1922fae562cffdca41cbd) --- source4/dsdb/samdb/ldb_modules/password_hash.c | 219 ++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 3 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index 8d63aed0f5..413ec12479 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -141,6 +141,8 @@ struct setup_password_fields_io { uint32_t lm_history_len; struct samr_Password *lm_history; const char *salt; + DATA_BLOB aes_256; + DATA_BLOB aes_128; DATA_BLOB des_md5; DATA_BLOB des_crc; struct ldb_val supplemental; @@ -315,6 +317,56 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io) salt.saltvalue.data = discard_const(io->g.salt); salt.saltvalue.length = strlen(io->g.salt); + /* + * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of + * the salt and the cleartext password + */ + krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + io->n.cleartext, + salt, + &key); + if (krb5_ret) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_kerberos_keys: " + "generation of a aes256-cts-hmac-sha1-96 key failed: %s", + smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); + return LDB_ERR_OPERATIONS_ERROR; + } + io->g.aes_256 = data_blob_talloc(io->ac, + key.keyvalue.data, + key.keyvalue.length); + krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); + if (!io->g.aes_256.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* + * create ENCTYPE_AES128_CTS_HMAC_SHA1_96 key out of + * the salt and the cleartext password + */ + krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + io->n.cleartext, + salt, + &key); + if (krb5_ret) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_kerberos_keys: " + "generation of a aes128-cts-hmac-sha1-96 key failed: %s", + smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac)); + return LDB_ERR_OPERATIONS_ERROR; + } + io->g.aes_128 = data_blob_talloc(io->ac, + key.keyvalue.data, + key.keyvalue.length); + krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key); + if (!io->g.aes_128.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + /* * create ENCTYPE_DES_CBC_MD5 key out of * the salt and the cleartext password @@ -467,6 +519,117 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io, return LDB_SUCCESS; } +static int setup_primary_kerberos_newer(struct setup_password_fields_io *io, + const struct supplementalCredentialsBlob *old_scb, + struct package_PrimaryKerberosNewerBlob *pkb) +{ + struct package_PrimaryKerberosNewerCtr4 *pkb4 = &pkb->ctr.ctr4; + struct supplementalCredentialsPackage *old_scp = NULL; + struct package_PrimaryKerberosNewerBlob _old_pkb; + struct package_PrimaryKerberosNewerCtr4 *old_pkb4 = NULL; + uint32_t i; + enum ndr_err_code ndr_err; + + /* + * prepare generation of keys + * + * ENCTYPE_AES256_CTS_HMAC_SHA1_96 + * ENCTYPE_AES128_CTS_HMAC_SHA1_96 + * ENCTYPE_DES_CBC_MD5 + * ENCTYPE_DES_CBC_CRC + */ + pkb4->salt.string = io->g.salt; + pkb4->num_keys = 4; + pkb4->keys = talloc_array(io->ac, + struct package_PrimaryKerberosNewerKey, + pkb4->num_keys); + if (!pkb4->keys) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + pkb4->keys[0].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; + pkb4->keys[0].value = &io->g.aes_256; + pkb4->keys[1].keytype = ENCTYPE_AES128_CTS_HMAC_SHA1_96; + pkb4->keys[1].value = &io->g.aes_128; + pkb4->keys[2].keytype = ENCTYPE_DES_CBC_MD5; + pkb4->keys[2].value = &io->g.des_md5; + pkb4->keys[3].keytype = ENCTYPE_DES_CBC_CRC; + pkb4->keys[3].value = &io->g.des_crc; + + /* initialize the old keys to zero */ + pkb4->num_old_keys1 = 0; + pkb4->old_keys1 = NULL; + pkb4->num_old_keys2 = 0; + pkb4->old_keys2 = NULL; + + /* if there're no old keys, then we're done */ + if (!old_scb) { + return LDB_SUCCESS; + } + + for (i=0; i < old_scb->sub.num_packages; i++) { + if (strcmp("Primary:Kerberos-Newer-Keys", old_scb->sub.packages[i].name) != 0) { + continue; + } + + if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) { + continue; + } + + old_scp = &old_scb->sub.packages[i]; + break; + } + /* Primary:Kerberos element of supplementalCredentials */ + if (old_scp) { + DATA_BLOB blob; + + blob = strhex_to_data_blob(old_scp->data); + if (!blob.data) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + talloc_steal(io->ac, blob.data); + + /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */ + ndr_err = ndr_pull_struct_blob(&blob, io->ac, + lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), + &_old_pkb, + (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosNewerBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_primary_kerberos_newer: " + "failed to pull old package_PrimaryKerberosNewerBlob: %s", + nt_errstr(status)); + return LDB_ERR_OPERATIONS_ERROR; + } + + if (_old_pkb.version != 4) { + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_primary_kerberos: " + "package_PrimaryKerberosNewerBlob version[%u] expected[4]", + _old_pkb.version); + return LDB_ERR_OPERATIONS_ERROR; + } + + old_pkb4 = &_old_pkb.ctr.ctr4; + } + + /* if we didn't found the old keys we're done */ + if (!old_pkb4) { + return LDB_SUCCESS; + } + + /* fill in the old keys */ + pkb4->num_old_keys1 = old_pkb4->num_keys; + pkb4->old_keys1 = old_pkb4->keys; + pkb4->num_old_keys2 = old_pkb4->num_old_keys1; + pkb4->old_keys2 = old_pkb4->old_keys1; + + return LDB_SUCCESS; +} + static int setup_primary_wdigest(struct setup_password_fields_io *io, const struct supplementalCredentialsBlob *old_scb, struct package_PrimaryWDigestBlob *pdb) @@ -804,16 +967,22 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) struct supplementalCredentialsBlob scb; struct supplementalCredentialsBlob _old_scb; struct supplementalCredentialsBlob *old_scb = NULL; - /* Packages + (Kerberos, WDigest and CLEARTEXT) */ + /* Packages + (Kerberos-Newer-Keys, Kerberos, WDigest and CLEARTEXT) */ uint32_t num_names = 0; - const char *names[1+3]; + const char *names[1+4]; uint32_t num_packages = 0; - struct supplementalCredentialsPackage packages[1+3]; + struct supplementalCredentialsPackage packages[1+4]; /* Packages */ struct supplementalCredentialsPackage *pp = NULL; struct package_PackagesBlob pb; DATA_BLOB pb_blob; char *pb_hexstr; + /* Primary:Kerberos-Newer-Keys */ + const char **nkn = NULL; + struct supplementalCredentialsPackage *pkn = NULL; + struct package_PrimaryKerberosNewerBlob pknb; + DATA_BLOB pknb_blob; + char *pknb_hexstr; /* Primary:Kerberos */ const char **nk = NULL; struct supplementalCredentialsPackage *pk = NULL; @@ -835,6 +1004,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) int ret; enum ndr_err_code ndr_err; uint8_t zero16[16]; + bool do_newer_keys = false; bool do_cleartext = false; ZERO_STRUCT(zero16); @@ -873,6 +1043,10 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) } } + /* TODO: do the correct check for this, it maybe depends on the functional level? */ + do_newer_keys = lp_parm_bool(ldb_get_opaque(io->ac->module->ldb, "loadparm"), + NULL, "password_hash", "create_aes_key", false); + if (io->domain->store_cleartext && (io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) { do_cleartext = true; @@ -881,6 +1055,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) /* * The ordering is this * + * Primary:Kerberos-Newer-Keys (optional) * Primary:Kerberos * Primary:WDigest * Primary:CLEARTEXT (optional) @@ -888,6 +1063,11 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) * And the 'Packages' package is insert before the last * other package. */ + if (do_newer_keys) { + /* Primary:Kerberos-Newer-Keys */ + nkn = &names[num_names++]; + pkn = &packages[num_packages++]; + } /* Primary:Kerberos */ nk = &names[num_names++]; @@ -911,6 +1091,39 @@ static int setup_supplemental_field(struct setup_password_fields_io *io) pc = &packages[num_packages++]; } + if (pkn) { + /* + * setup 'Primary:Kerberos-Newer-Keys' element + */ + *nkn = "Kerberos-Newer-Keys"; + + ret = setup_primary_kerberos_newer(io, old_scb, &pknb); + if (ret != LDB_SUCCESS) { + return ret; + } + + ndr_err = ndr_push_struct_blob(&pknb_blob, io->ac, + lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), + &pknb, + (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosNewerBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + ldb_asprintf_errstring(io->ac->module->ldb, + "setup_supplemental_field: " + "failed to push package_PrimaryKerberosNeverBlob: %s", + nt_errstr(status)); + return LDB_ERR_OPERATIONS_ERROR; + } + pknb_hexstr = data_blob_hex_string(io->ac, &pknb_blob); + if (!pknb_hexstr) { + ldb_oom(io->ac->module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + pkn->name = "Primary:Kerberos-Newer-Keys"; + pkn->reserved = 1; + pkn->data = pknb_hexstr; + } + /* * setup 'Primary:Kerberos' element */ -- cgit From f9e61979244d94600261be4898f1091b00406c6f Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 23 Jul 2008 14:07:06 +0200 Subject: dsdb: teach dreplsrv_out_drsuapi_bind_recv() knowledge of DsBindInfo48. To make it work against w2k8. Michael (This used to be commit a8aea9274170a2b472c45c97a4904bd299d2a92e) --- source4/dsdb/repl/drepl_out_helpers.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c index 0700867543..345e3db1ab 100644 --- a/source4/dsdb/repl/drepl_out_helpers.c +++ b/source4/dsdb/repl/drepl_out_helpers.c @@ -146,6 +146,15 @@ static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req) st->drsuapi->remote_info28.repl_epoch = 0; break; } + case 48: { + struct drsuapi_DsBindInfo48 *info48; + info48 = &st->bind_r.out.bind_info->info.info48; + st->drsuapi->remote_info28.supported_extensions = info48->supported_extensions; + st->drsuapi->remote_info28.site_guid = info48->site_guid; + st->drsuapi->remote_info28.pid = info48->pid; + st->drsuapi->remote_info28.repl_epoch = info48->repl_epoch; + break; + } case 28: st->drsuapi->remote_info28 = st->bind_r.out.bind_info->info.info28; break; -- cgit From 46bb8aa357ba11ff79af0281b749e70706774217 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 23 Jul 2008 15:18:57 +0200 Subject: libnet_become_cd: teach becomeDC_drsuapi_bind_recv() DsBindInfo48. To work with w2k8. Michael (This used to be commit 7d80fab912576923c7474d77b8ed960b01296914) --- source4/libnet/libnet_become_dc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index 31a9206d86..067f76d6b8 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -1649,6 +1649,15 @@ static WERROR becomeDC_drsuapi_bind_recv(struct libnet_BecomeDC_state *s, drsuapi->remote_info28.repl_epoch = 0; break; } + case 48: { + struct drsuapi_DsBindInfo48 *info48; + info48 = &drsuapi->bind_r.out.bind_info->info.info48; + drsuapi->remote_info28.supported_extensions = info48->supported_extensions; + drsuapi->remote_info28.site_guid = info48->site_guid; + drsuapi->remote_info28.pid = info48->pid; + drsuapi->remote_info28.repl_epoch = info48->repl_epoch; + break; + } case 28: drsuapi->remote_info28 = drsuapi->bind_r.out.bind_info->info.info28; break; -- cgit From e269804b04c3658fb6228ba104a0b61cf24139c8 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 23 Jul 2008 15:21:44 +0200 Subject: libnet_unbecome_dc: teach unbecomeDC_drsuapi_bind_recv() DsBindInfo48. ..to work agains w2k8. Michael (This used to be commit 97e8d5813df19cae294b6de2a880606f0f8c2c59) --- source4/libnet/libnet_unbecome_dc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source4/libnet/libnet_unbecome_dc.c b/source4/libnet/libnet_unbecome_dc.c index e01af25f3f..4463569e71 100644 --- a/source4/libnet/libnet_unbecome_dc.c +++ b/source4/libnet/libnet_unbecome_dc.c @@ -616,6 +616,15 @@ static void unbecomeDC_drsuapi_bind_recv(struct rpc_request *req) s->drsuapi.remote_info28.repl_epoch = 0; break; } + case 48: { + struct drsuapi_DsBindInfo48 *info48; + info48 = &s->drsuapi.bind_r.out.bind_info->info.info48; + s->drsuapi.remote_info28.supported_extensions = info48->supported_extensions; + s->drsuapi.remote_info28.site_guid = info48->site_guid; + s->drsuapi.remote_info28.pid = info48->pid; + s->drsuapi.remote_info28.repl_epoch = info48->repl_epoch; + break; + } case 28: s->drsuapi.remote_info28 = s->drsuapi.bind_r.out.bind_info->info.info28; break; -- cgit From 1f20ca14cc1a2604a7af41e6ca03852f0398d88a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 23 Jul 2008 15:34:45 +0200 Subject: drsuapi: always set the pid field of the outgoing DsBindInfo to 0. This is for debugging and informational purposes only. The assignment is implementation specific. (WSPP docs, sec. 5.35). Michael (This used to be commit 1f5704e2dee5900e8d1d87699b76f67c0e12854e) --- source4/libnet/libnet_become_dc.c | 7 +------ source4/libnet/libnet_unbecome_dc.c | 2 +- source4/torture/rpc/dssync.c | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index 067f76d6b8..6a13974236 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -1611,12 +1611,7 @@ static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s, bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS; #endif bind_info28->site_guid = s->dest_dsa.site_guid; - if (s->domain.behavior_version == 2) { - /* TODO: find out how this is really triggered! */ - bind_info28->pid = 528; - } else { - bind_info28->pid = 516; - } + bind_info28->pid = 0; bind_info28->repl_epoch = 0; drsuapi->bind_info_ctr.length = 28; diff --git a/source4/libnet/libnet_unbecome_dc.c b/source4/libnet/libnet_unbecome_dc.c index 4463569e71..6a42fa2370 100644 --- a/source4/libnet/libnet_unbecome_dc.c +++ b/source4/libnet/libnet_unbecome_dc.c @@ -574,7 +574,7 @@ static void unbecomeDC_drsuapi_bind_send(struct libnet_UnbecomeDC_state *s) bind_info28 = &s->drsuapi.local_info28; bind_info28->supported_extensions = 0; bind_info28->site_guid = GUID_zero(); - bind_info28->pid = 508; + bind_info28->pid = 0; bind_info28->repl_epoch = 0; s->drsuapi.bind_info_ctr.length = 28; diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c index 822cd088f1..2930a9b1f9 100644 --- a/source4/torture/rpc/dssync.c +++ b/source4/torture/rpc/dssync.c @@ -154,7 +154,7 @@ static struct DsSyncTest *test_create_context(struct torture_context *tctx) our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS; } our_bind_info28->site_guid = GUID_zero(); - our_bind_info28->pid = 508; + our_bind_info28->pid = 0; our_bind_info28->repl_epoch = 0; our_bind_info_ctr = &ctx->new_dc.drsuapi.our_bind_info_ctr; -- cgit From c71030bd04eee5f50be56ac2460393dfbe2fdd23 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 23 Jul 2008 17:54:25 +0200 Subject: libnet_become_cd: add boolean option "become_dc:force krb5" to control krb5 auth. This allows controlling whether krb5 auth is forced for the rpc bind in libnet_become_dc. It defaults to "yes". For Windows 2000, DsGetNCChanges only krb5 auth works due to a bug in Windows (it returns garbage - a positive object count is returned along with first object == NULL). For Windows 2008, on the other hand, krb5 auth does not work currently due to the lack of support for AES keys. (Metze is working on that.) Michael (This used to be commit af85aad8147b85a0b9ea2ccc66b8f04efdfe5cf3) --- source4/libnet/libnet_become_dc.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index 6a13974236..8b7fd57780 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -1516,22 +1516,30 @@ static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s, drsuapi->s = s; if (!drsuapi->binding) { + char *krb5_str = ""; + char *print_str = ""; /* - * Note: It's important to pass 'krb5' as auth_type here - * otherwise the replication will not work with - * Windows 2000. If NTLMSSP is used Windows 2000 - * returns garbage in the DsGetNCChanges() response + * Note: Replication only works with Windows 2000 when 'krb5' is + * passed as auth_type here. If NTLMSSP is used, Windows + * 2000 returns garbage in the DsGetNCChanges() response * if encrypted password attributes would be in the response. * That means the replication of the schema and configuration * partition works fine, but it fails for the domain partition. */ - if (lp_parm_bool(s->libnet->lp_ctx, NULL, "become_dc", "print", false)) { - binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[krb5,print,seal]", s->source_dsa.dns_name); - if (composite_nomem(binding_str, c)) return; - } else { - binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[krb5,seal]", s->source_dsa.dns_name); - if (composite_nomem(binding_str, c)) return; + if (lp_parm_bool(s->libnet->lp_ctx, NULL, "become_dc", + "force krb5", true)) + { + krb5_str = "krb5,"; } + if (lp_parm_bool(s->libnet->lp_ctx, NULL, "become_dc", + "print", false)) + { + print_str = "print,"; + } + binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[%s%sseal]", + s->source_dsa.dns_name, + krb5_str, print_str); + if (composite_nomem(binding_str, c)) return; c->status = dcerpc_parse_binding(s, binding_str, &drsuapi->binding); talloc_free(binding_str); if (!composite_is_ok(c)) return; -- cgit From db36f37b8f324ca2a45b05800d4abfb72c566447 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 23 Jul 2008 16:23:31 +0200 Subject: libnet_become_dc: send msDS_Behavior_Version == 3 (win2k8) in DsAddEntry instead of version 2 (win2k3). This makes the NET-API-BECOME-DC test work against windows 2003 and 2008. Michael (This used to be commit a7bfa1fb1bc6fb8e412990b7ff4c3ce9bc55099d) --- source4/dsdb/common/flags.h | 1 + source4/libnet/libnet_become_dc.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/source4/dsdb/common/flags.h b/source4/dsdb/common/flags.h index 36111418e2..e8802fdf9c 100644 --- a/source4/dsdb/common/flags.h +++ b/source4/dsdb/common/flags.h @@ -122,3 +122,4 @@ #define DS_BEHAVIOR_WIN2000 0 #define DS_BEHAVIOR_WIN2003_INTERIM 1 #define DS_BEHAVIOR_WIN2003 2 +#define DS_BEHAVIOR_WIN2008 3 diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index 8b7fd57780..1ce067c321 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -2104,7 +2104,7 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s) vd[0] = data_blob_talloc(vd, NULL, 4); if (composite_nomem(vd[0].data, c)) return; - SIVAL(vd[0].data, 0, DS_BEHAVIOR_WIN2003); + SIVAL(vd[0].data, 0, DS_BEHAVIOR_WIN2008); vs[0].blob = &vd[0]; -- cgit From f619e08f8be7c3a20a71b679e73a7b7f57247f82 Mon Sep 17 00:00:00 2001 From: Anatoliy Atanasov Date: Wed, 23 Jul 2008 09:59:17 +0300 Subject: Handle schema reloading request. The ldif for that operation looks like this: dn: changetype: Modify add: schemaUpdateNow schemaUpdateNow: 1 It uses the rootdse's object functional attribute schemaUpdateNow. In rootdse_modify() this command is being recognized and it is send as extended operation with DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID. In the partition module its dispatched to the schema_fsmo module. The request is processed in the schema_fsmo module by schema_fsmo_extended(). (This used to be commit 39f9184ddf215f2b512319211c0a05702218ef87) --- source4/dsdb/samdb/ldb_modules/partition.c | 49 +++++++++++++++++++++ source4/dsdb/samdb/ldb_modules/rootdse.c | 47 ++++++++++++++++++-- source4/dsdb/samdb/ldb_modules/schema_fsmo.c | 64 +++++++++++++++++++++++++++- source4/dsdb/samdb/samdb.h | 2 + 4 files changed, 158 insertions(+), 4 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 22826e4f33..9285d6d0d8 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -699,6 +699,50 @@ static int partition_extended_replicated_objects(struct ldb_module *module, stru return partition_replicate(module, req, ext->partition_dn); } +static int partition_extended_schema_update_now(struct ldb_module *module, struct ldb_request *req) +{ + struct dsdb_control_current_partition *partition; + struct partition_private_data *data; + struct ldb_dn *schema_dn; + struct partition_context *ac; + struct ldb_module *backend; + int ret; + + schema_dn = talloc_get_type(req->op.extended.data, struct ldb_dn); + if (!schema_dn) { + ldb_debug(module->ldb, LDB_DEBUG_FATAL, "partition_extended: invalid extended data\n"); + return LDB_ERR_PROTOCOL_ERROR; + } + + data = talloc_get_type(module->private_data, struct partition_private_data); + if (!data) { + return LDB_ERR_OPERATIONS_ERROR; + } + + partition = find_partition( data, schema_dn ); + if (!partition) { + return ldb_next_request(module, req); + } + + ac = partition_init_handle(req, module); + if (!ac) { + return LDB_ERR_OPERATIONS_ERROR; + } + + backend = make_module_for_next_request(req, module->ldb, partition->module); + if (!backend) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_request_add_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID, false, partition); + if (ret != LDB_SUCCESS) { + return ret; + } + + return ldb_next_request(backend, req); +} + + /* extended */ static int partition_extended(struct ldb_module *module, struct ldb_request *req) { @@ -708,6 +752,11 @@ static int partition_extended(struct ldb_module *module, struct ldb_request *req return partition_extended_replicated_objects(module, req); } + /* forward schemaUpdateNow operation to schema_fsmo module*/ + if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) == 0) { + return partition_extended_schema_update_now( module, req ); + } + /* * as the extended operation has no dn * we need to send it to all partitions diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c index 75f99a139d..97491a2ae3 100644 --- a/source4/dsdb/samdb/ldb_modules/rootdse.c +++ b/source4/dsdb/samdb/ldb_modules/rootdse.c @@ -391,9 +391,50 @@ static int rootdse_init(struct ldb_module *module) return ldb_next_init(module); } +static int rootdse_modify(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_result *ext_res; + int ret; + struct ldb_dn *schema_dn; + struct ldb_message_element *schemaUpdateNowAttr; + + /* + If dn is not "" we should let it pass through + */ + if (!ldb_dn_is_null(req->op.mod.message->dn)) { + return ldb_next_request(module, req); + } + + /* + dn is empty so check for schemaUpdateNow attribute + "The type of modification and values specified in the LDAP modify operation do not matter." MSDN + */ + schemaUpdateNowAttr = ldb_msg_find_element(req->op.mod.message, "schemaUpdateNow"); + if (!schemaUpdateNowAttr) { + return LDB_ERR_OPERATIONS_ERROR; + } + + schema_dn = samdb_schema_dn(module->ldb); + if (!schema_dn) { + ldb_reset_err_string(module->ldb); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, + "rootdse_modify: no schema dn present: (skip ldb_extended call)\n"); + return ldb_next_request(module, req); + } + + ret = ldb_extended(module->ldb, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID, schema_dn, &ext_res); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + talloc_free(ext_res); + return ret; +} + _PUBLIC_ const struct ldb_module_ops ldb_rootdse_module_ops = { .name = "rootdse", - .init_context = rootdse_init, - .search = rootdse_search, - .request = rootdse_request + .init_context = rootdse_init, + .search = rootdse_search, + .request = rootdse_request, + .modify = rootdse_modify }; diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c index a397228723..2acc5c0af4 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c +++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c @@ -148,8 +148,70 @@ static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } +static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *req) +{ + WERROR status; + struct ldb_dn *schema_dn; + struct dsdb_schema *schema; + char *error_string = NULL; + int ret; + TALLOC_CTX *mem_ctx; + + if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) { + return ldb_next_request(module, req); + } + + schema_dn = samdb_schema_dn(module->ldb); + if (!schema_dn) { + ldb_reset_err_string(module->ldb); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, + "schema_fsmo_extended: no schema dn present: (skip schema loading)\n"); + return ldb_next_request(module, req); + } + + mem_ctx = talloc_new(module); + if (!mem_ctx) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = dsdb_schema_from_schema_dn(mem_ctx, module->ldb, + lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")), + schema_dn, &schema, &error_string); + + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + ldb_reset_err_string(module->ldb); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, + "schema_fsmo_extended: no schema head present: (skip schema loading)\n"); + talloc_free(mem_ctx); + return ldb_next_request(module, req); + } + + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(module->ldb, + "schema_fsmo_extended: dsdb_schema load failed: %s", + error_string); + talloc_free(mem_ctx); + return ldb_next_request(module, req); + } + + /* Replace the old schema*/ + ret = dsdb_set_schema(module->ldb, schema); + if (ret != LDB_SUCCESS) { + ldb_debug_set(module->ldb, LDB_DEBUG_FATAL, + "schema_fsmo_extended: dsdb_set_schema() failed: %d:%s", + ret, ldb_strerror(ret)); + talloc_free(mem_ctx); + return ret; + } + + talloc_free(mem_ctx); + return LDB_SUCCESS; +} + _PUBLIC_ const struct ldb_module_ops ldb_schema_fsmo_module_ops = { .name = "schema_fsmo", .init_context = schema_fsmo_init, - .add = schema_fsmo_add + .add = schema_fsmo_add, + .extended = schema_fsmo_extended }; diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h index 75aa819ccd..b8a3e16d46 100644 --- a/source4/dsdb/samdb/samdb.h +++ b/source4/dsdb/samdb/samdb.h @@ -90,4 +90,6 @@ struct dsdb_pdc_fsmo { struct ldb_dn *master_dn; }; +#define DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID "1.3.6.1.4.1.7165.4.4.2" + #endif /* __SAMDB_H__ */ -- cgit From 05583308fe8278f1bc0c815e23cf5e470a81e12f Mon Sep 17 00:00:00 2001 From: Anatoliy Atanasov Date: Mon, 21 Jul 2008 17:04:49 +0300 Subject: dsdb_create_prefix_mapping() implementation checks for existing prefix maping in ldb. if one not found it creates a mapping for it and updates the prefixMap schema attribute in ldb. (This used to be commit bbe895db7144b192981fad9ab6bbd3ebacb8d299) --- source4/dsdb/schema/schema_init.c | 293 +++++++++++++++++++++++++++++++++----- 1 file changed, 257 insertions(+), 36 deletions(-) diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index 71d952b944..2ec5ad34b1 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -267,19 +267,146 @@ WERROR dsdb_verify_oid_mappings_drsuapi(const struct dsdb_schema *schema, const } WERROR dsdb_map_oid2int(const struct dsdb_schema *schema, const char *in, uint32_t *out) +{ + return dsdb_find_prefix_for_oid(schema->num_prefixes, schema->prefixes, in, out); +} + + +WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CTX *mem_ctx, const char **out) { uint32_t i; for (i=0; i < schema->num_prefixes; i++) { + const char *val; + if (schema->prefixes[i].id != (in & 0xFFFF0000)) { + continue; + } + + val = talloc_asprintf(mem_ctx, "%s%u", + schema->prefixes[i].oid, + in & 0xFFFF); + W_ERROR_HAVE_NO_MEMORY(val); + + *out = val; + return WERR_OK; + } + + return WERR_DS_NO_MSDS_INTID; +} + +/* + * this function is called from within a ldb transaction from the schema_fsmo module + */ +WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid) +{ + WERROR status; + uint32_t num_prefixes; + struct dsdb_schema_oid_prefix *prefixes; + struct ldb_val ndr_blob; + TALLOC_CTX *mem_ctx; + uint32_t out; + + mem_ctx = talloc_new(ldb); + W_ERROR_HAVE_NO_MEMORY(mem_ctx); + + /* Read prefixes from disk*/ + status = dsdb_read_prefixes_from_ldb( mem_ctx, ldb, &num_prefixes, &prefixes ); + if (!W_ERROR_IS_OK(status)) { + DEBUG(0,("dsdb_create_prefix_mapping: dsdb_read_prefixes_from_ldb failed\n")); + talloc_free(mem_ctx); + return status; + } + + /* Check if there is a prefix for the oid in the prefixes array*/ + status = dsdb_find_prefix_for_oid( num_prefixes, prefixes, full_oid, &out ); + if (W_ERROR_IS_OK(status)) { + /* prefix found*/ + talloc_free(mem_ctx); + return status; + } + /* Update prefix map in ldb*/ + /* Update the prefixes */ + status = dsdb_prefix_map_update(mem_ctx, &num_prefixes, &prefixes, full_oid); + if (!W_ERROR_IS_OK(status)) { + DEBUG(0,("dsdb_create_prefix_mapping: dsdb_prefix_map_update failed\n")); + talloc_free(mem_ctx); + return status; + } + /* Convert prefixes in ndr blob*/ + status = dsdb_write_prefixes_to_ndr( mem_ctx, ldb, num_prefixes, prefixes, &ndr_blob ); + if (!W_ERROR_IS_OK(status)) { + DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ndr failed\n")); + talloc_free(mem_ctx); + return status; + } + + /* Update prefixMap in ldb*/ + status = dsdb_write_prefixes_to_ldb( mem_ctx, ldb, &ndr_blob ); + if (!W_ERROR_IS_OK(status)) { + DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ldb failed\n")); + talloc_free(mem_ctx); + return status; + } + + talloc_free(mem_ctx); + return status; +} + +WERROR dsdb_prefix_map_update(TALLOC_CTX *mem_ctx, uint32_t *num_prefixes, struct dsdb_schema_oid_prefix **prefixes, const char *oid) +{ + uint32_t new_num_prefixes, index_new_prefix, new_entry_id; + const char* lastDotOffset; + size_t size; + + new_num_prefixes = *num_prefixes + 1; + index_new_prefix = *num_prefixes; + new_entry_id = (*num_prefixes)<<16; + + /* Extract the prefix from the oid*/ + lastDotOffset = strrchr(oid, '.'); + if (lastDotOffset == NULL) { + DEBUG(0,("dsdb_prefix_map_update: failed to find the last dot\n")); + return WERR_NOT_FOUND; + } + + /* Calculate the size of the remainig string that should be the prefix of it */ + size = strlen(oid) - strlen(lastDotOffset); + if (size <= 0) { + DEBUG(0,("dsdb_prefix_map_update: size of the remaining string invalid\n")); + return WERR_FOOBAR; + } + /* Add one because we need to copy the dot */ + size += 1; + + /* Create a spot in the prefixMap for one more prefix*/ + (*prefixes) = talloc_realloc(mem_ctx, *prefixes, struct dsdb_schema_oid_prefix, new_num_prefixes); + W_ERROR_HAVE_NO_MEMORY(*prefixes); + + /* Add the new prefix entry*/ + (*prefixes)[index_new_prefix].id = new_entry_id; + (*prefixes)[index_new_prefix].oid = talloc_strndup(mem_ctx, oid, size); + (*prefixes)[index_new_prefix].oid_len = strlen((*prefixes)[index_new_prefix].oid); + + /* Increase num_prefixes because new prefix has been added */ + ++(*num_prefixes); + + return WERR_OK; +} + +WERROR dsdb_find_prefix_for_oid(uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, const char *in, uint32_t *out) +{ + uint32_t i; + + for (i=0; i < num_prefixes; i++) { const char *val_str; char *end_str; unsigned val; - if (strncmp(schema->prefixes[i].oid, in, schema->prefixes[i].oid_len) != 0) { + if (strncmp(prefixes[i].oid, in, prefixes[i].oid_len) != 0) { continue; } - val_str = in + schema->prefixes[i].oid_len; + val_str = in + prefixes[i].oid_len; end_str = NULL; errno = 0; @@ -305,58 +432,152 @@ WERROR dsdb_map_oid2int(const struct dsdb_schema *schema, const char *in, uint32 return WERR_INVALID_PARAM; } - *out = schema->prefixes[i].id | val; + *out = prefixes[i].id | val; return WERR_OK; } return WERR_DS_NO_MSDS_INTID; } -WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CTX *mem_ctx, const char **out) +WERROR dsdb_write_prefixes_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldb_val *ndr_blob) { + struct ldb_message msg; + struct ldb_dn *schema_dn; + struct ldb_message_element el; + int ret; + + schema_dn = samdb_schema_dn(ldb); + if (!schema_dn) { + DEBUG(0,("dsdb_write_prefixes_to_ldb: no schema dn present\n")); + return WERR_FOOBAR; + } + + el.num_values = 1; + el.values = ndr_blob; + el.flags = LDB_FLAG_MOD_REPLACE; + el.name = talloc_strdup(mem_ctx, "prefixMap"); + + msg.dn = ldb_dn_copy(mem_ctx, schema_dn); + msg.num_elements = 1; + msg.elements = ⪙ + + ret = ldb_modify( ldb, &msg ); + if (ret != 0) { + DEBUG(0,("dsdb_write_prefixes_to_ldb: ldb_modify failed\n")); + return WERR_FOOBAR; + } + + return WERR_OK; +} + +WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes) +{ + struct prefixMapBlob *blob; + enum ndr_err_code ndr_err; uint32_t i; + const struct ldb_val *prefix_val; + struct ldb_dn *schema_dn; + struct ldb_result *schema_res; + int ret; + static const char *schema_attrs[] = { + "prefixMap", + NULL + }; - for (i=0; i < schema->num_prefixes; i++) { - const char *val; - if (schema->prefixes[i].id != (in & 0xFFFF0000)) { - continue; - } + schema_dn = samdb_schema_dn(ldb); + if (!schema_dn) { + DEBUG(0,("dsdb_read_prefixes_from_ldb: no schema dn present\n")); + return WERR_FOOBAR; + } - val = talloc_asprintf(mem_ctx, "%s%u", - schema->prefixes[i].oid, - in & 0xFFFF); - W_ERROR_HAVE_NO_MEMORY(val); + ret = ldb_search(ldb, schema_dn, LDB_SCOPE_BASE,NULL, schema_attrs,&schema_res); + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map present\n")); + return WERR_FOOBAR; + } else if (ret != LDB_SUCCESS) { + DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the schema head\n")); + return WERR_FOOBAR; + } - *out = val; - return WERR_OK; + prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap"); + if (!prefix_val) { + DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefixMap attribute found\n")); + return WERR_FOOBAR; } - return WERR_DS_NO_MSDS_INTID; + blob = talloc(mem_ctx, struct prefixMapBlob); + W_ERROR_HAVE_NO_MEMORY(blob); + + ndr_err = ndr_pull_struct_blob(prefix_val, blob, + lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), + blob, + (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0,("dsdb_read_prefixes_from_ldb: ndr_pull_struct_blob failed\n")); + talloc_free(blob); + return WERR_FOOBAR; + } + + if (blob->version != PREFIX_MAP_VERSION_DSDB) { + DEBUG(0,("dsdb_read_prefixes_from_ldb: blob->version incorect\n")); + talloc_free(blob); + return WERR_FOOBAR; + } + + *num_prefixes = blob->ctr.dsdb.num_mappings; + *prefixes = talloc_array(mem_ctx, struct dsdb_schema_oid_prefix, *num_prefixes); + if(!(*prefixes)) { + talloc_free(blob); + return WERR_NOMEM; + } + for (i=0; i < blob->ctr.dsdb.num_mappings; i++) { + (*prefixes)[i].id = blob->ctr.dsdb.mappings[i].id_prefix<<16; + (*prefixes)[i].oid = talloc_strdup(mem_ctx, blob->ctr.dsdb.mappings[i].oid.oid); + (*prefixes)[i].oid = talloc_asprintf_append((*prefixes)[i].oid, "."); + (*prefixes)[i].oid_len = strlen(blob->ctr.dsdb.mappings[i].oid.oid); + } + + talloc_free(blob); + return WERR_OK; } -/* - * this function is called from within a ldb transaction from the schema_fsmo module - */ -WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid) + +WERROR dsdb_write_prefixes_to_ndr(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, struct ldb_val *out) { - /* - * TODO: - * - (maybe) read the old prefixMap attribute and parse it - * - * - recheck the prefix doesn't exist (because the ldb - * has maybe a more uptodate value than schem->prefixes - * - * - calculate a new mapping for the oid prefix of full_oid - * - store the new prefixMap attribute - * - * - (maybe) update schema->prefixes - * or - * - better find a way to indicate a schema reload, - * so that other processes also notice the schema change - */ - return WERR_NOT_SUPPORTED; + struct prefixMapBlob *blob; + enum ndr_err_code ndr_err; + uint32_t i; + + blob = talloc_zero(mem_ctx, struct prefixMapBlob); + W_ERROR_HAVE_NO_MEMORY(blob); + + blob->version = PREFIX_MAP_VERSION_DSDB; + blob->ctr.dsdb.num_mappings = num_prefixes; + blob->ctr.dsdb.mappings = talloc_realloc(blob, + blob->ctr.dsdb.mappings, + struct drsuapi_DsReplicaOIDMapping, + blob->ctr.dsdb.num_mappings); + if (!blob->ctr.dsdb.mappings) { + return WERR_NOMEM; + } + + for (i=0; i < num_prefixes; i++) { + blob->ctr.dsdb.mappings[i].id_prefix = prefixes[i].id>>16; + blob->ctr.dsdb.mappings[i].oid.oid = talloc_strdup(blob->ctr.dsdb.mappings, prefixes[i].oid); + } + + ndr_err = ndr_push_struct_blob(out, ldb, + lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), + blob, + (ndr_push_flags_fn_t)ndr_push_prefixMapBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return WERR_FOOBAR; + } + + return WERR_OK; } + #define GET_STRING_LDB(msg, attr, mem_ctx, p, elem, strict) do { \ (p)->elem = samdb_result_string(msg, attr, NULL);\ if (strict && (p)->elem == NULL) { \ -- cgit