From 999b69d176a967aad8b6a871632d1869757181aa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 1 Oct 2008 02:27:09 +0200 Subject: s4:gensec: pass down want_features to the spnego backend mech metze --- source4/auth/gensec/gensec.c | 8 +++++++- source4/auth/gensec/gensec.h | 2 ++ source4/auth/gensec/spnego.c | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/auth/gensec/gensec.c b/source4/auth/gensec/gensec.c index 0edb34d740..5d57383d2a 100644 --- a/source4/auth/gensec/gensec.c +++ b/source4/auth/gensec/gensec.c @@ -490,6 +490,7 @@ static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx, NT_STATUS_HAVE_NO_MEMORY(*gensec_security); (*gensec_security)->ops = NULL; + (*gensec_security)->private_data = NULL; ZERO_STRUCT((*gensec_security)->target); ZERO_STRUCT((*gensec_security)->peer_addr); @@ -525,6 +526,7 @@ _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx, (*gensec_security)->private_data = NULL; (*gensec_security)->subcontext = true; + (*gensec_security)->want_features = parent->want_features; (*gensec_security)->event_ctx = parent->event_ctx; (*gensec_security)->msg_ctx = parent->msg_ctx; (*gensec_security)->lp_ctx = parent->lp_ctx; @@ -1015,7 +1017,11 @@ _PUBLIC_ NTSTATUS gensec_update_recv(struct gensec_update_request *req, TALLOC_C _PUBLIC_ void gensec_want_feature(struct gensec_security *gensec_security, uint32_t feature) { - gensec_security->want_features |= feature; + if (!gensec_security->ops || !gensec_security->ops->want_feature) { + gensec_security->want_features |= feature; + return; + } + gensec_security->ops->want_feature(gensec_security, feature); } /** diff --git a/source4/auth/gensec/gensec.h b/source4/auth/gensec/gensec.h index 84fc26d127..0b31882ddd 100644 --- a/source4/auth/gensec/gensec.h +++ b/source4/auth/gensec/gensec.h @@ -133,6 +133,8 @@ struct gensec_security_ops { NTSTATUS (*session_key)(struct gensec_security *gensec_security, DATA_BLOB *session_key); NTSTATUS (*session_info)(struct gensec_security *gensec_security, struct auth_session_info **session_info); + void (*want_feature)(struct gensec_security *gensec_security, + uint32_t feature); bool (*have_feature)(struct gensec_security *gensec_security, uint32_t feature); bool enabled; diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c index 1855e0583d..bf991616bd 100644 --- a/source4/auth/gensec/spnego.c +++ b/source4/auth/gensec/spnego.c @@ -1094,6 +1094,20 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA return NT_STATUS_INVALID_PARAMETER; } +static void gensec_spnego_want_feature(struct gensec_security *gensec_security, + uint32_t feature) +{ + struct spnego_state *spnego_state = (struct spnego_state *)gensec_security->private_data; + + if (!spnego_state || !spnego_state->sub_sec_security) { + gensec_security->want_features |= feature; + return; + } + + gensec_want_feature(spnego_state->sub_sec_security, + feature); +} + static bool gensec_spnego_have_feature(struct gensec_security *gensec_security, uint32_t feature) { @@ -1133,6 +1147,7 @@ static const struct gensec_security_ops gensec_spnego_security_ops = { .unwrap_packets = gensec_spnego_unwrap_packets, .session_key = gensec_spnego_session_key, .session_info = gensec_spnego_session_info, + .want_feature = gensec_spnego_want_feature, .have_feature = gensec_spnego_have_feature, .enabled = true, .priority = GENSEC_SPNEGO -- cgit From 9e492b1ba2ccf2d7c62ef7295b33260687e3aeae Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 6 Oct 2008 19:39:53 +0200 Subject: s4:rpc_server: tell the gensec layer that we want to do header signing Note: header signing is still off by default, as the gensec backends don't support it together with seal yet. metze --- source4/rpc_server/dcesrv_auth.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4') diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c index 52d5631cfd..bef7e4be78 100644 --- a/source4/rpc_server/dcesrv_auth.c +++ b/source4/rpc_server/dcesrv_auth.c @@ -95,6 +95,10 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call) return false; } + if (call->conn->state_flags & DCESRV_CALL_STATE_FLAG_HEADER_SIGNING) { + gensec_want_feature(auth->gensec_security, GENSEC_FEATURE_SIGN_PKT_HEADER); + } + return true; } -- cgit From c412a930ad19da866503e6d8ccb71fb3191fc6d2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 3 Oct 2008 16:25:59 -0700 Subject: Fix Domain Trust creation with Windows 2008 (and many other tools) A dITConentRules attribute (unlike objectClasses) must not contain a 'SUP'. The ADSI layer in Windows would download the whole schema, and validate it. Thanks to the team at Microsoft for very long debugging session to find this. Andrew Bartlett --- source4/dsdb/schema/schema_description.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/dsdb/schema/schema_description.c b/source4/dsdb/schema/schema_description.c index 6884c5284e..e152f44b97 100644 --- a/source4/dsdb/schema/schema_description.c +++ b/source4/dsdb/schema/schema_description.c @@ -309,7 +309,11 @@ char *schema_class_to_dITContentRule(TALLOC_CTX *mem_ctx, const struct dsdb_clas class->lDAPDisplayName, (const char **)aux_class_list, NULL, - class->subClassOf, + NULL, /* Must not specify a + * SUP (subclass) in + * ditContentRules + * per MS-ADTS + * 3.1.1.3.1.1.1 */ -1, must_attr_list, may_attr_list); talloc_free(tmp_ctx); return schema_description; -- cgit From 7d9f18609b25463d306c0c150fe0da7f065860fd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 3 Oct 2008 16:36:04 -0700 Subject: Remove DESCRIPTION from generated schema lines. This is not permitted in the AD aggregate schema, and more trouble than it is worth in the OpenLDAP schema due to escaping issues. Andrew Bartlett --- source4/dsdb/schema/schema_description.c | 21 +-------------------- source4/utils/ad2oLschema.c | 14 ++++++++++---- 2 files changed, 11 insertions(+), 24 deletions(-) (limited to 'source4') diff --git a/source4/dsdb/schema/schema_description.c b/source4/dsdb/schema/schema_description.c index e152f44b97..c3c37b4653 100644 --- a/source4/dsdb/schema/schema_description.c +++ b/source4/dsdb/schema/schema_description.c @@ -33,7 +33,6 @@ char *schema_attribute_description(TALLOC_CTX *mem_ctx, const char *seperator, const char *oid, const char *name, - const char *description, const char *equality, const char *substring, const char *syntax, @@ -46,15 +45,6 @@ char *schema_attribute_description(TALLOC_CTX *mem_ctx, "NAME '%s'%s", name, seperator); IF_NULL_FAIL_RET(schema_entry); - if (description) { -#if 0 - /* Need a way to escape ' characters from the description */ - schema_entry = talloc_asprintf_append(schema_entry, - "DESC '%s'%s", description, seperator); - IF_NULL_FAIL_RET(schema_entry); -#endif - } - if (equality) { schema_entry = talloc_asprintf_append(schema_entry, "EQUALITY %s%s", equality, seperator); @@ -104,7 +94,7 @@ char *schema_attribute_to_description(TALLOC_CTX *mem_ctx, const struct dsdb_att " ", attribute->attributeID_oid, attribute->lDAPDisplayName, - NULL, NULL, NULL, talloc_asprintf(tmp_ctx, "'%s'", syntax), + NULL, NULL, talloc_asprintf(tmp_ctx, "'%s'", syntax), attribute->isSingleValued, attribute->systemOnly); talloc_free(tmp_ctx); @@ -149,7 +139,6 @@ char *schema_class_description(TALLOC_CTX *mem_ctx, const char *oid, const char *name, const char **auxillary_classes, - const char *description, const char *subClassOf, int objectClassCategory, char **must, @@ -164,12 +153,6 @@ char *schema_class_description(TALLOC_CTX *mem_ctx, "NAME '%s'%s", name, seperator); IF_NULL_FAIL_RET(schema_entry); - if (description) { - schema_entry = talloc_asprintf_append(schema_entry, - "DESC '%s'%s", description, seperator); - IF_NULL_FAIL_RET(schema_entry); - } - if (auxillary_classes) { schema_entry = talloc_asprintf_append(schema_entry, "AUX ( "); @@ -262,7 +245,6 @@ char *schema_class_to_description(TALLOC_CTX *mem_ctx, const struct dsdb_class * " ", class->governsID_oid, class->lDAPDisplayName, - NULL, NULL, class->subClassOf, class->objectClassCategory, @@ -308,7 +290,6 @@ char *schema_class_to_dITContentRule(TALLOC_CTX *mem_ctx, const struct dsdb_clas class->governsID_oid, class->lDAPDisplayName, (const char **)aux_class_list, - NULL, NULL, /* Must not specify a * SUP (subclass) in * ditContentRules diff --git a/source4/utils/ad2oLschema.c b/source4/utils/ad2oLschema.c index 3c2ffe7a00..c579112b45 100644 --- a/source4/utils/ad2oLschema.c +++ b/source4/utils/ad2oLschema.c @@ -221,7 +221,6 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum dsdb_sch for (attribute=schema->attributes; attribute; attribute = attribute->next) { const char *name = attribute->lDAPDisplayName; - const char *description = attribute->adminDescription; const char *oid = attribute->attributeID_oid; const char *syntax = attribute->attributeSyntax_oid; const char *equality = NULL, *substring = NULL; @@ -270,7 +269,16 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum dsdb_sch } } - schema_entry = schema_attribute_description(mem_ctx, target, seperator, oid, name, description, equality, substring, syntax, single_value, false); + schema_entry = schema_attribute_description(mem_ctx, + target, + seperator, + oid, + name, + equality, + substring, + syntax, + single_value, + false); if (schema_entry == NULL) { ret.failures++; @@ -291,7 +299,6 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum dsdb_sch /* This is already sorted to have 'top' and similar classes first */ for (objectclass=schema->classes; objectclass; objectclass = objectclass->next) { const char *name = objectclass->lDAPDisplayName; - const char *description = objectclass->adminDescription; const char *oid = objectclass->governsID_oid; const char *subClassOf = objectclass->subClassOf; int objectClassCategory = objectclass->objectClassCategory; @@ -356,7 +363,6 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum dsdb_sch oid, name, NULL, - description, subClassOf, objectClassCategory, must, -- cgit From c0240d78351e489c5aca7e729aac045157080088 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 4 Oct 2008 10:25:46 -0700 Subject: Remove compleatly bogus rename test in partitions module. --- source4/dsdb/samdb/ldb_modules/partition.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'source4') diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 8e4483a78e..b452b66d56 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -589,7 +589,6 @@ static int partition_delete(struct ldb_module *module, struct ldb_request *req) /* rename */ static int partition_rename(struct ldb_module *module, struct ldb_request *req) { - int i, matched = -1; /* Find backend */ struct dsdb_control_current_partition *backend, *backend2; @@ -619,22 +618,6 @@ static int partition_rename(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_AFFECTS_MULTIPLE_DSAS; } - for (i=0; data && data->partitions && data->partitions[i]; i++) { - if (ldb_dn_compare_base(data->partitions[i]->dn, req->op.rename.olddn) == 0) { - matched = i; - } - } - - if (matched > 0) { - ldb_asprintf_errstring(module->ldb, - "Cannot rename from %s to %s, subtree rename would cross partition %s: %s", - ldb_dn_get_linearized(req->op.rename.olddn), - ldb_dn_get_linearized(req->op.rename.newdn), - ldb_dn_get_linearized(data->partitions[matched]->dn), - ldb_strerror(LDB_ERR_AFFECTS_MULTIPLE_DSAS)); - return LDB_ERR_AFFECTS_MULTIPLE_DSAS; - } - return partition_replicate(module, req, req->op.rename.olddn); } -- cgit From 8256717c766fb8e145c2f4b5acb3502f4d7c57d9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 30 Sep 2008 14:24:58 -0700 Subject: Implement 'type unknown' names in the CrackNames code. This guesses the type by running each of the possible options. Andrew Bartlett --- source4/dsdb/samdb/cracknames.c | 58 ++++++++++++++++++++++++++------ source4/librpc/idl/drsuapi.idl | 2 +- source4/torture/rpc/drsuapi_cracknames.c | 1 + 3 files changed, 50 insertions(+), 11 deletions(-) (limited to 'source4') diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c index e02e8d81a6..ca87159c58 100644 --- a/source4/dsdb/samdb/cracknames.c +++ b/source4/dsdb/samdb/cracknames.c @@ -356,15 +356,7 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, const char *result_filter = NULL; struct ldb_dn *name_dn = NULL; - struct smb_krb5_context *smb_krb5_context; - ret = smb_krb5_init_context(mem_ctx, - ldb_get_event_context(sam_ctx), - (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"), - &smb_krb5_context); - - if (ret) { - return WERR_NOMEM; - } + struct smb_krb5_context *smb_krb5_context = NULL; info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR; info1->dns_domain_name = NULL; @@ -380,6 +372,30 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, /* here we need to set the domain_filter and/or the result_filter */ switch (format_offered) { + case DRSUAPI_DS_NAME_FORMAT_UNKNOWN: + { + int i; + enum drsuapi_DsNameFormat formats[] = { + DRSUAPI_DS_NAME_FORMAT_FQDN_1779, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, + DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT, DRSUAPI_DS_NAME_FORMAT_CANONICAL, + DRSUAPI_DS_NAME_FORMAT_GUID, DRSUAPI_DS_NAME_FORMAT_DISPLAY, + DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL, + DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY, + DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX + }; + WERROR werr; + for (i=0; i < ARRAY_SIZE(formats); i++) { + werr = DsCrackNameOneName(sam_ctx, mem_ctx, format_flags, formats[i], format_desired, name, info1); + if (!W_ERROR_IS_OK(werr)) { + return werr; + } + if (info1->status != DRSUAPI_DS_NAME_STATUS_NOT_FOUND) { + return werr; + } + } + return werr; + } + case DRSUAPI_DS_NAME_FORMAT_CANONICAL: case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX: { @@ -534,6 +550,16 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL: { krb5_principal principal; char *unparsed_name; + + ret = smb_krb5_init_context(mem_ctx, + ldb_get_event_context(sam_ctx), + (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"), + &smb_krb5_context); + + if (ret) { + return WERR_NOMEM; + } + ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal); if (ret) { info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; @@ -560,6 +586,16 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, krb5_principal principal; char *unparsed_name_short; char *service; + + ret = smb_krb5_init_context(mem_ctx, + ldb_get_event_context(sam_ctx), + (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"), + &smb_krb5_context); + + if (ret) { + return WERR_NOMEM; + } + ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal); if (ret == 0 && principal->name.name_string.len < 2) { info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; @@ -1265,7 +1301,7 @@ NTSTATUS crack_auto_name_to_nt4_name(TALLOC_CTX *mem_ctx, const char **nt4_domain, const char **nt4_account) { - uint32_t format_offered = DRSUAPI_DS_NAME_FORMAT_UKNOWN; + uint32_t format_offered = DRSUAPI_DS_NAME_FORMAT_UNKNOWN; /* Handle anonymous bind */ if (!name || !*name) { @@ -1282,6 +1318,8 @@ NTSTATUS crack_auto_name_to_nt4_name(TALLOC_CTX *mem_ctx, format_offered = DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT; } else if (strchr_m(name, '/')) { format_offered = DRSUAPI_DS_NAME_FORMAT_CANONICAL; + } else { + return NT_STATUS_NO_SUCH_USER; } return crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, format_offered, name, nt4_domain, nt4_account); diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl index 76858b2d5c..a41bc9cf19 100644 --- a/source4/librpc/idl/drsuapi.idl +++ b/source4/librpc/idl/drsuapi.idl @@ -877,7 +877,7 @@ interface drsuapi } drsuapi_DsNameFlags; typedef [v1_enum] enum { - DRSUAPI_DS_NAME_FORMAT_UKNOWN = 0, + DRSUAPI_DS_NAME_FORMAT_UNKNOWN = 0, DRSUAPI_DS_NAME_FORMAT_FQDN_1779 = 1, DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT = 2, DRSUAPI_DS_NAME_FORMAT_DISPLAY = 3, diff --git a/source4/torture/rpc/drsuapi_cracknames.c b/source4/torture/rpc/drsuapi_cracknames.c index fbda69df57..a9a614953d 100644 --- a/source4/torture/rpc/drsuapi_cracknames.c +++ b/source4/torture/rpc/drsuapi_cracknames.c @@ -39,6 +39,7 @@ static bool test_DsCrackNamesMatrix(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, bool ret = true; struct drsuapi_DsCrackNames r; enum drsuapi_DsNameFormat formats[] = { + DRSUAPI_DS_NAME_FORMAT_UNKNOWN, DRSUAPI_DS_NAME_FORMAT_FQDN_1779, DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT, DRSUAPI_DS_NAME_FORMAT_DISPLAY, -- cgit From 8cdb3ebe27814629cb17d2a438c89780c5cecfdf Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 1 Oct 2008 13:10:11 -0700 Subject: Clarify use of manual parsers in trustInOutBlob (drsblobs.idl) --- source4/librpc/idl/drsblobs.idl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'source4') diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl index 31fe8a359e..4274d2000a 100644 --- a/source4/librpc/idl/drsblobs.idl +++ b/source4/librpc/idl/drsblobs.idl @@ -409,21 +409,23 @@ interface drsblobs { [size_is(1)] AuthenticationInformation array[]; } AuthenticationInformationArray; + /* This is nopull,nopush because we pass count down to the + * manual parser of AuthenticationInformationArray */ typedef [public,nopull,nopush,noprint,gensize] struct { uint32 count; [relative] AuthenticationInformationArray *current; [relative] AuthenticationInformationArray *previous; } trustAuthInOutBlob; + void decode_trustAuthInOut( + [in] trustAuthInOutBlob blob + ); + typedef [public,gensize] struct { uint32 count; [relative] AuthenticationInformation *current[count]; } trustCurrentPasswords; - void decode_trustAuthInOut( - [in] trustAuthInOutBlob blob - ); - typedef [public,nopull] struct { uint8 confounder[512]; [subcontext(0),subcontext_size(outgoing_size)] trustCurrentPasswords outgoing; -- cgit From 8e1c0470d72ca85d837bbdd4aec0ca2f27a7a29f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 1 Oct 2008 13:10:35 -0700 Subject: Add in secure channel type used by AD trusts --- source4/librpc/idl/misc.idl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source4') diff --git a/source4/librpc/idl/misc.idl b/source4/librpc/idl/misc.idl index 8331977398..791b86466c 100644 --- a/source4/librpc/idl/misc.idl +++ b/source4/librpc/idl/misc.idl @@ -30,9 +30,11 @@ interface misc /* Only SEC_CHAN_WKSTA can forward requests to other domains. */ typedef [public] enum { - SEC_CHAN_WKSTA = 2, - SEC_CHAN_DOMAIN = 4, - SEC_CHAN_BDC = 6 + SEC_CHAN_NULL = 0, + SEC_CHAN_WKSTA = 2, + SEC_CHAN_DNS_DOMAIN = 3, + SEC_CHAN_DOMAIN = 4, + SEC_CHAN_BDC = 6 } netr_SchannelType; /* SAM database types */ -- cgit From 99d0eb4fb701c500f0175ca9a38482160bdb08e4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 1 Oct 2008 13:11:11 -0700 Subject: Make RPC-LSA test for enumeration conditions more strict --- source4/torture/rpc/lsa.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'source4') diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c index efbdecab13..245ed1e41b 100644 --- a/source4/torture/rpc/lsa.c +++ b/source4/torture/rpc/lsa.c @@ -1899,7 +1899,11 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p, /* NO_MORE_ENTRIES is allowed */ if (NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES)) { - return true; + if (domains.count == 0) { + return true; + } + printf("EnumTrustDom failed - should have returned 0 trusted domains with 'NT_STATUS_NO_MORE_ENTRIES'\n"); + return false; } else if (NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)) { /* Windows 2003 gets this off by one on the first run */ if (r.out.domains->count < 3 || r.out.domains->count > 4) { @@ -1950,7 +1954,11 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p, /* NO_MORE_ENTRIES is allowed */ if (NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES)) { - return true; + if (domains_ex.count == 0) { + return true; + } + printf("EnumTrustDomainsEx failed - should have returned 0 trusted domains with 'NT_STATUS_NO_MORE_ENTRIES'\n"); + return false; } else if (NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)) { /* Windows 2003 gets this off by one on the first run */ if (r_ex.out.domains->count < 3 || r_ex.out.domains->count > 4) { @@ -2115,7 +2123,7 @@ static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p, /* Try different trust types too */ - /* 1 == downleven (NT4), 2 == uplevel (ADS), 3 == MIT (kerberos but not AD) */ + /* 1 == downlevel (NT4), 2 == uplevel (ADS), 3 == MIT (kerberos but not AD) */ trustinfo.trust_type = (((i / 3) + 1) % 3) + 1; trustinfo.trust_attributes = LSA_TRUST_ATTRIBUTE_USES_RC4_ENCRYPTION; @@ -2160,6 +2168,7 @@ static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p, printf("QueryTrustedDomainInfo level 1 failed - %s\n", nt_errstr(status)); ret = false; } else if (!q.out.info) { + printf("QueryTrustedDomainInfo level 1 failed to return an info pointer\n"); ret = false; } else { if (strcmp(q.out.info->info_ex.netbios_name.string, trustinfo.netbios_name.string) != 0) { @@ -2188,11 +2197,13 @@ static bool test_CreateTrustedDomainEx2(struct dcerpc_pipe *p, /* now that we have some domains to look over, we can test the enum calls */ if (!test_EnumTrustDom(p, mem_ctx, handle)) { + printf("test_EnumTrustDom failed\n"); ret = false; } for (i=0; i<12; i++) { if (!test_DeleteTrustedDomainBySid(p, mem_ctx, handle, domsid[i])) { + printf("test_DeleteTrustedDomainBySid failed\n"); ret = false; } } -- cgit From 1a29fd1cf5436c850c7de180668a7a33f9b034d8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 1 Oct 2008 13:12:15 -0700 Subject: Store trusted domain passwords in the LSA server --- source4/rpc_server/lsa/dcesrv_lsa.c | 68 ++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) (limited to 'source4') diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index 5e3be84cc5..836fd8dc62 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -727,13 +727,46 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return NT_STATUS_INVALID_PARAMETER; } + + if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) { + if (auth_struct.incoming.count > 1) { + return NT_STATUS_INVALID_PARAMETER; + } + } } if (auth_struct.incoming.count) { + int i; + struct trustAuthInOutBlob incoming; + + incoming.count = auth_struct.incoming.count; + incoming.current = talloc(mem_ctx, struct AuthenticationInformationArray); + if (!incoming.current) { + return NT_STATUS_NO_MEMORY; + } + + incoming.current->array = *auth_struct.incoming.current; + if (!incoming.current->array) { + return NT_STATUS_NO_MEMORY; + } + + incoming.previous = talloc(mem_ctx, struct AuthenticationInformationArray); + if (!incoming.previous) { + return NT_STATUS_NO_MEMORY; + } + incoming.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, incoming.count); + if (!incoming.previous->array) { + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < incoming.count; i++) { + incoming.previous->array[i].LastUpdateTime = 0; + incoming.previous->array[i].AuthType = 0; + } ndr_err = ndr_push_struct_blob(&trustAuthIncoming, mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), - &auth_struct.incoming, - (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords); + &incoming, + (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return NT_STATUS_INVALID_PARAMETER; } @@ -742,10 +775,37 @@ static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dc } if (auth_struct.outgoing.count) { + int i; + struct trustAuthInOutBlob outgoing; + + outgoing.count = auth_struct.outgoing.count; + outgoing.current = talloc(mem_ctx, struct AuthenticationInformationArray); + if (!outgoing.current) { + return NT_STATUS_NO_MEMORY; + } + + outgoing.current->array = *auth_struct.outgoing.current; + if (!outgoing.current->array) { + return NT_STATUS_NO_MEMORY; + } + + outgoing.previous = talloc(mem_ctx, struct AuthenticationInformationArray); + if (!outgoing.previous) { + return NT_STATUS_NO_MEMORY; + } + outgoing.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, outgoing.count); + if (!outgoing.previous->array) { + return NT_STATUS_NO_MEMORY; + } + + for (i = 0; i < outgoing.count; i++) { + outgoing.previous->array[i].LastUpdateTime = 0; + outgoing.previous->array[i].AuthType = 0; + } ndr_err = ndr_push_struct_blob(&trustAuthOutgoing, mem_ctx, lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx), - &auth_struct.outgoing, - (ndr_push_flags_fn_t)ndr_push_trustDomainPasswords); + &outgoing, + (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return NT_STATUS_INVALID_PARAMETER; } -- cgit From 320d402180ac2d8505aec2664feaddbd63e5b17e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 1 Oct 2008 13:31:22 -0700 Subject: Start implementing AD-style trusted domains in Samba4's NETLOGON server --- source4/rpc_server/netlogon/dcerpc_netlogon.c | 52 +++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'source4') diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index d5f7d2afae..b948d1210e 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -87,6 +87,9 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca const char *attrs[] = {"unicodePwd", "userAccountControl", "objectSid", NULL}; + const char *trust_dom_attrs[] = {"flatname", NULL}; + const char *account_name; + ZERO_STRUCTP(r->out.credentials); *r->out.rid = 0; *r->out.negotiate_flags = *r->in.negotiate_flags; @@ -101,10 +104,54 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca if (sam_ctx == NULL) { return NT_STATUS_INVALID_SYSTEM_SERVICE; } + + if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) { + char *encoded_account = ldb_binary_encode_string(mem_ctx, r->in.account_name); + char *flatname; + if (!encoded_account) { + return NT_STATUS_NO_MEMORY; + } + + /* Kill the trailing dot */ + if (encoded_account[strlen(encoded_account)-1] == '.') { + encoded_account[strlen(encoded_account)-1] = '\0'; + } + + /* pull the user attributes */ + num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, trust_dom_attrs, + "(&(trustPartner=%s)(objectclass=trustedDomain))", + encoded_account); + + if (num_records == 0) { + DEBUG(3,("Couldn't find trust [%s] in samdb.\n", + encoded_account)); + return NT_STATUS_ACCESS_DENIED; + } + + if (num_records > 1) { + DEBUG(0,("Found %d records matching user [%s]\n", num_records, r->in.account_name)); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + flatname = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL); + if (!flatname) { + /* No flatname for this trust - we can't proceed */ + return NT_STATUS_ACCESS_DENIED; + } + account_name = talloc_asprintf(mem_ctx, "%s$", flatname); + + if (!account_name) { + return NT_STATUS_NO_MEMORY; + } + + } else { + account_name = r->in.account_name; + } + /* pull the user attributes */ num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs, "(&(sAMAccountName=%s)(objectclass=user))", - r->in.account_name); + ldb_binary_encode_string(mem_ctx, account_name)); if (num_records == 0) { DEBUG(3,("Couldn't find user [%s] in samdb.\n", @@ -130,7 +177,8 @@ static NTSTATUS dcesrv_netr_ServerAuthenticate3(struct dcesrv_call_state *dce_ca DEBUG(1, ("Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x\n", user_account_control)); return NT_STATUS_ACCESS_DENIED; } - } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN) { + } else if (r->in.secure_channel_type == SEC_CHAN_DOMAIN || + r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) { if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) { DEBUG(1, ("Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x\n", user_account_control)); -- cgit From 912209ac84395ef0e2fca0556b1e4bec34367b5c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 1 Oct 2008 16:00:33 -0700 Subject: Use the trust password version as kvno for trusts in Kerberos. --- source4/kdc/hdb-samba4.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source4') diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c index d7317f17d4..818c4a12fd 100644 --- a/source4/kdc/hdb-samba4.c +++ b/source4/kdc/hdb-samba4.c @@ -717,6 +717,7 @@ static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db, enum ndr_err_code ndr_err; int i, ret, trust_direction_flags; + uint32_t kvno; private = talloc(mem_ctx, struct hdb_ldb_private); if (!private) { @@ -764,6 +765,12 @@ static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db, goto out; } + for (i=0; i < password_blob.count; i++) { + if (password_blob.current->array[i].AuthType == TRUST_AUTH_TYPE_VERSION) { + entry_ex->entry.kvno = password_blob.current->array[i].AuthInfo.version.version; + } + } + for (i=0; i < password_blob.count; i++) { if (password_blob.current->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) { password_utf16 = data_blob_const(password_blob.current->array[i].AuthInfo.clear.password, -- cgit From 6a5547742f0b87017e4d21c80ec8facece6688d0 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 2 Oct 2008 11:29:34 -0700 Subject: Allow the PAC to be passed along during cross-realm authentication --- source4/heimdal/kdc/krb5tgs.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'source4') diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c index 19dff5e01d..d557da2a5b 100644 --- a/source4/heimdal/kdc/krb5tgs.c +++ b/source4/heimdal/kdc/krb5tgs.c @@ -1393,6 +1393,8 @@ tgs_build_reply(krb5_context context, char opt_str[128]; int signedpath = 0; + Key *tkey; + memset(&sessionkey, 0, sizeof(sessionkey)); memset(&adtkt, 0, sizeof(adtkt)); krb5_data_zero(&rspac); @@ -1630,26 +1632,22 @@ server_lookup: } /* check PAC if not cross realm and if there is one */ - if (!cross_realm) { - Key *tkey; - - ret = hdb_enctype2key(context, &krbtgt->entry, - krbtgt_etype, &tkey); - if(ret) { - kdc_log(context, config, 0, + ret = hdb_enctype2key(context, &krbtgt->entry, + krbtgt_etype, &tkey); + if(ret) { + kdc_log(context, config, 0, "Failed to find key for krbtgt PAC check"); - goto out; - } + goto out; + } - ret = check_PAC(context, config, cp, - client, server, ekey, &tkey->key, - tgt, &rspac, &signedpath); - if (ret) { - kdc_log(context, config, 0, - "Verify PAC failed for %s (%s) from %s with %s", - spn, cpn, from, krb5_get_err_text(context, ret)); - goto out; - } + ret = check_PAC(context, config, cp, + client, server, ekey, &tkey->key, + tgt, &rspac, &signedpath); + if (ret) { + kdc_log(context, config, 0, + "Verify PAC failed for %s (%s) from %s with %s", + spn, cpn, from, krb5_get_err_text(context, ret)); + goto out; } /* also check the krbtgt for signature */ -- cgit From c3b28c7a81c04a0f019b6c1e543a65d6d48b0b2c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 2 Oct 2008 11:30:14 -0700 Subject: Fix cross-realm authentication in Samba4's KDC. --- source4/kdc/hdb-samba4.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source4') diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c index 818c4a12fd..5b7f55822e 100644 --- a/source4/kdc/hdb-samba4.c +++ b/source4/kdc/hdb-samba4.c @@ -758,7 +758,7 @@ static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db, goto out; } - ndr_err = ndr_pull_struct_blob_all(password_val, mem_ctx, private->iconv_convenience, &password_blob, + ndr_err = ndr_pull_struct_blob(password_val, mem_ctx, private->iconv_convenience, &password_blob, (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { ret = EINVAL; @@ -813,6 +813,8 @@ static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db, entry_ex->entry.keys.len++; } + entry_ex->entry.principal = malloc(sizeof(*(entry_ex->entry.principal))); + ret = copy_Principal(principal, entry_ex->entry.principal); if (ret) { krb5_clear_error_string(context); @@ -1155,7 +1157,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, principal, HDB_SAMBA4_ENT_TYPE_KRBTGT, msg[0], realm_ref_msg_1[0], entry_ex); if (ret != 0) { - krb5_warnx(context, "LDB_fetch: message2entry failed"); + krb5_warnx(context, "LDB_fetch: self krbtgt message2entry failed"); } return ret; @@ -1193,7 +1195,7 @@ static krb5_error_code LDB_fetch_krbtgt(krb5_context context, HDB *db, principal, direction, msg[0], entry_ex); if (ret != 0) { - krb5_warnx(context, "LDB_fetch: message2entry failed"); + krb5_warnx(context, "LDB_fetch: trust_message2entry failed"); } return ret; -- cgit From e0a4d7f467d9727563adaaa97961edd06886490e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 3 Oct 2008 16:36:49 -0700 Subject: Set default trust kvno to -1 --- source4/kdc/hdb-samba4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4') diff --git a/source4/kdc/hdb-samba4.c b/source4/kdc/hdb-samba4.c index 5b7f55822e..51f464cd09 100644 --- a/source4/kdc/hdb-samba4.c +++ b/source4/kdc/hdb-samba4.c @@ -717,7 +717,6 @@ static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db, enum ndr_err_code ndr_err; int i, ret, trust_direction_flags; - uint32_t kvno; private = talloc(mem_ctx, struct hdb_ldb_private); if (!private) { @@ -765,6 +764,7 @@ static krb5_error_code LDB_trust_message2entry(krb5_context context, HDB *db, goto out; } + entry_ex->entry.kvno = -1; for (i=0; i < password_blob.count; i++) { if (password_blob.current->array[i].AuthType == TRUST_AUTH_TYPE_VERSION) { entry_ex->entry.kvno = password_blob.current->array[i].AuthInfo.version.version; -- cgit