From 9b0e3bb0c36abd9396f07de988e5c402d8503681 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 27 Jun 2008 15:36:19 +0200 Subject: net_vampire: add code to vampire to a Kerberos keytab file using DRSUAPI. Guenther (This used to be commit 0ef420c3a478a8adce7483f14b45e9995bfa5e5d) --- source3/libnet/libnet_dssync_keytab.c | 240 ++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 source3/libnet/libnet_dssync_keytab.c (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c new file mode 100644 index 0000000000..132a58d353 --- /dev/null +++ b/source3/libnet/libnet_dssync_keytab.c @@ -0,0 +1,240 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Guenther Deschner 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "libnet/libnet.h" + +#if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) + +/**************************************************************** +****************************************************************/ + +static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, + struct libnet_keytab_context *ctx, + struct drsuapi_DsReplicaObjectListItemEx *cur) +{ + NTSTATUS status = NT_STATUS_OK; + uchar nt_passwd[16]; + struct libnet_keytab_entry entry; + DATA_BLOB *blob; + int i = 0; + struct drsuapi_DsReplicaAttribute *attr; + bool got_pwd = false; + + char *upn = NULL; + char *name = NULL; + uint32_t kvno = 0; + uint32_t uacc = 0; + uint32_t sam_type = 0; + + uint32_t pwd_history_len = 0; + uint8_t *pwd_history = NULL; + + ZERO_STRUCT(nt_passwd); + + for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) { + + attr = &cur->object.attribute_ctr.attributes[i]; + + if (attr->value_ctr.num_values != 1) { + continue; + } + + if (!attr->value_ctr.values[0].blob) { + continue; + } + + blob = attr->value_ctr.values[0].blob; + + switch (attr->attid) { + case DRSUAPI_ATTRIBUTE_unicodePwd: + + if (blob->length != 16) { + break; + } + + memcpy(&nt_passwd, blob->data, 16); + got_pwd = true; + + /* pick the kvno from the meta_data version, + * thanks, metze, for explaining this */ + + if (!cur->meta_data_ctr) { + break; + } + if (cur->meta_data_ctr->count != + cur->object.attribute_ctr.num_attributes) { + break; + } + kvno = cur->meta_data_ctr->meta_data[i].version; + break; + case DRSUAPI_ATTRIBUTE_ntPwdHistory: + pwd_history_len = blob->length / 16; + pwd_history = blob->data; + break; + case DRSUAPI_ATTRIBUTE_msDS_KeyVersionNumber: + kvno = IVAL(blob->data, 0); + break; + case DRSUAPI_ATTRIBUTE_userPrincipalName: + pull_string_talloc(mem_ctx, NULL, 0, &upn, + blob->data, blob->length, + STR_UNICODE); + break; + case DRSUAPI_ATTRIBUTE_sAMAccountName: + pull_string_talloc(mem_ctx, NULL, 0, &name, + blob->data, blob->length, + STR_UNICODE); + break; + case DRSUAPI_ATTRIBUTE_sAMAccountType: + sam_type = IVAL(blob->data, 0); + break; + case DRSUAPI_ATTRIBUTE_userAccountControl: + uacc = IVAL(blob->data, 0); + break; + default: + break; + } + } + + if (!got_pwd || !name) { + return NT_STATUS_OK; + } + + DEBUG(1,("#%02d: %s:%d, ", ctx->count, name, kvno)); + DEBUGADD(1,("sAMAccountType: 0x%08x, userAccountControl: 0x%08x ", + sam_type, uacc)); + if (upn) { + DEBUGADD(1,("upn: %s", upn)); + } + DEBUGADD(1,("\n")); + + entry.kvno = kvno; + entry.name = talloc_strdup(mem_ctx, name); + entry.principal = talloc_asprintf(mem_ctx, "%s@%s", + name, ctx->dns_domain_name); + entry.password = data_blob_talloc(mem_ctx, nt_passwd, 16); + NT_STATUS_HAVE_NO_MEMORY(entry.name); + NT_STATUS_HAVE_NO_MEMORY(entry.principal); + NT_STATUS_HAVE_NO_MEMORY(entry.password.data); + + ADD_TO_ARRAY(mem_ctx, struct libnet_keytab_entry, entry, + &ctx->entries, &ctx->count); + + if ((kvno < 0) && (kvno < pwd_history_len)) { + return status; + } + + /* add password history */ + + /* skip first entry */ + if (got_pwd) { + kvno--; + i = 1; + } else { + i = 0; + } + + for (; idns_domain_name); + entry.password = data_blob_talloc(mem_ctx, &pwd_history[i*16], 16); + NT_STATUS_HAVE_NO_MEMORY(entry.name); + NT_STATUS_HAVE_NO_MEMORY(entry.principal); + NT_STATUS_HAVE_NO_MEMORY(entry.password.data); + + ADD_TO_ARRAY(mem_ctx, struct libnet_keytab_entry, entry, + &ctx->entries, &ctx->count); + } + + return status; +} + +/**************************************************************** +****************************************************************/ + +NTSTATUS libnet_dssync_dump_keytab(TALLOC_CTX *mem_ctx, + struct drsuapi_DsReplicaObjectListItemEx *cur, + struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr, + bool last_query, + struct dssync_context *ctx) +{ + NTSTATUS status = NT_STATUS_OK; + krb5_error_code ret = 0; + static struct libnet_keytab_context *keytab_ctx = NULL; + + if (!keytab_ctx) { + ret = libnet_keytab_init(mem_ctx, + ctx->output_filename, + &keytab_ctx); + if (ret) { + status = krb5_to_nt_status(ret); + goto out; + } + + keytab_ctx->dns_domain_name = ctx->dns_domain_name; + } + + for (; cur; cur = cur->next_object) { + status = parse_object(mem_ctx, keytab_ctx, cur); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + } + + if (last_query) { + + ret = libnet_keytab_add(keytab_ctx); + if (ret) { + status = krb5_to_nt_status(ret); + ctx->error_message = talloc_asprintf(mem_ctx, + "Failed to add entries to keytab %s: %s", + keytab_ctx->keytab_name, error_message(ret)); + goto out; + } + + ctx->result_message = talloc_asprintf(mem_ctx, + "Vampired %d accounts to keytab %s", + keytab_ctx->count, + keytab_ctx->keytab_name); + + TALLOC_FREE(keytab_ctx); + } + + return NT_STATUS_OK; + out: + TALLOC_FREE(keytab_ctx); + + return status; +} + +#else + +NTSTATUS libnet_dssync_dump_keytab(TALLOC_CTX *mem_ctx, + struct drsuapi_DsReplicaObjectListItemEx *cur, + struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr, + bool last_query, + struct dssync_context *ctx) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +#endif /* defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) */ -- cgit From 16c2190b149a2232aa49a16a41e570410edd2eaf Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 16 Jul 2008 17:12:04 +0200 Subject: dssync: replace the processing_fn by startup/process/finish ops. This remove static a variable for the keytab context in the keytab processing function and simplifies the signature. The keytab context is instead in the new private data member of the dssync_context struct. This is in preparation of adding support for keeping track of the up-to-date-ness vector, in order to be able to sync diffs instead of the whole database. Michael (This used to be commit c51c3339f35e3bd921080d2e226e2422fc23e1e6) --- source3/libnet/libnet_dssync_keytab.c | 113 ++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 46 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 132a58d353..d59efe74fb 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -22,6 +22,48 @@ #if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) +static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx) +{ + krb5_error_code ret = 0; + struct libnet_keytab_context *keytab_ctx; + + ret = libnet_keytab_init(mem_ctx, ctx->output_filename, &keytab_ctx); + if (ret) { + return krb5_to_nt_status(ret); + } + + keytab_ctx->dns_domain_name = ctx->dns_domain_name; + ctx->private_data = keytab_ctx; + + return NT_STATUS_OK; +} + +static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx) +{ + NTSTATUS status = NT_STATUS_OK; + krb5_error_code ret = 0; + struct libnet_keytab_context *keytab_ctx = + (struct libnet_keytab_context *)ctx->private_data; + + ret = libnet_keytab_add(keytab_ctx); + if (ret) { + status = krb5_to_nt_status(ret); + ctx->error_message = talloc_asprintf(mem_ctx, + "Failed to add entries to keytab %s: %s", + keytab_ctx->keytab_name, error_message(ret)); + goto done; + } + + ctx->result_message = talloc_asprintf(mem_ctx, + "Vampired %d accounts to keytab %s", + keytab_ctx->count, + keytab_ctx->keytab_name); + +done: + TALLOC_FREE(keytab_ctx); + return status; +} + /**************************************************************** ****************************************************************/ @@ -171,27 +213,14 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, /**************************************************************** ****************************************************************/ -NTSTATUS libnet_dssync_dump_keytab(TALLOC_CTX *mem_ctx, - struct drsuapi_DsReplicaObjectListItemEx *cur, - struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr, - bool last_query, - struct dssync_context *ctx) +static NTSTATUS keytab_process_objects(struct dssync_context *ctx, + TALLOC_CTX *mem_ctx, + struct drsuapi_DsReplicaObjectListItemEx *cur, + struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr) { NTSTATUS status = NT_STATUS_OK; - krb5_error_code ret = 0; - static struct libnet_keytab_context *keytab_ctx = NULL; - - if (!keytab_ctx) { - ret = libnet_keytab_init(mem_ctx, - ctx->output_filename, - &keytab_ctx); - if (ret) { - status = krb5_to_nt_status(ret); - goto out; - } - - keytab_ctx->dns_domain_name = ctx->dns_domain_name; - } + struct libnet_keytab_context *keytab_ctx = + (struct libnet_keytab_context *)ctx->private_data; for (; cur; cur = cur->next_object) { status = parse_object(mem_ctx, keytab_ctx, cur); @@ -200,41 +229,33 @@ NTSTATUS libnet_dssync_dump_keytab(TALLOC_CTX *mem_ctx, } } - if (last_query) { - - ret = libnet_keytab_add(keytab_ctx); - if (ret) { - status = krb5_to_nt_status(ret); - ctx->error_message = talloc_asprintf(mem_ctx, - "Failed to add entries to keytab %s: %s", - keytab_ctx->keytab_name, error_message(ret)); - goto out; - } - - ctx->result_message = talloc_asprintf(mem_ctx, - "Vampired %d accounts to keytab %s", - keytab_ctx->count, - keytab_ctx->keytab_name); - - TALLOC_FREE(keytab_ctx); - } - - return NT_STATUS_OK; out: - TALLOC_FREE(keytab_ctx); - return status; } #else -NTSTATUS libnet_dssync_dump_keytab(TALLOC_CTX *mem_ctx, - struct drsuapi_DsReplicaObjectListItemEx *cur, - struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr, - bool last_query, - struct dssync_context *ctx) +static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx) { return NT_STATUS_NOT_SUPPORTED; } +static NTSTATUS keytab_process_objects(struct dssync_context *ctx, + TALLOC_CTX *mem_ctx, + struct drsuapi_DsReplicaObjectListItemEx *cur, + struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr) +{ + return NT_STATUS_NOT_SUPPORTED; +} #endif /* defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) */ + +const struct dssync_ops libnet_dssync_keytab_ops = { + .startup = keytab_startup, + .process_objects = keytab_process_objects, + .finish = keytab_finish, +}; -- cgit From 2473888daa3a732fdb7ae69729ab7e3490ffac64 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 16 Jul 2008 23:08:40 +0200 Subject: dssync keytab: refactor adding entry to keytab_context out into new function add_to_keytab_entries() Michael (This used to be commit 79151db6eae234a1f9e5131b7776689a4f03a0ef) --- source3/libnet/libnet_dssync_keytab.c | 38 ++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index d59efe74fb..c502211b45 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -22,6 +22,29 @@ #if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) +static NTSTATUS add_to_keytab_entries(TALLOC_CTX *mem_ctx, + struct libnet_keytab_context *ctx, + uint32_t kvno, + const char *name, + DATA_BLOB blob) +{ + struct libnet_keytab_entry entry; + + entry.kvno = kvno; + entry.name = talloc_strdup(mem_ctx, name); + entry.principal = talloc_asprintf(mem_ctx, "%s@%s", + name, ctx->dns_domain_name); + entry.password = blob; + NT_STATUS_HAVE_NO_MEMORY(entry.name); + NT_STATUS_HAVE_NO_MEMORY(entry.principal); + NT_STATUS_HAVE_NO_MEMORY(entry.password.data); + + ADD_TO_ARRAY(mem_ctx, struct libnet_keytab_entry, entry, + &ctx->entries, &ctx->count); + + return NT_STATUS_OK; +} + static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx) { krb5_error_code ret = 0; @@ -166,17 +189,12 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, } DEBUGADD(1,("\n")); - entry.kvno = kvno; - entry.name = talloc_strdup(mem_ctx, name); - entry.principal = talloc_asprintf(mem_ctx, "%s@%s", - name, ctx->dns_domain_name); - entry.password = data_blob_talloc(mem_ctx, nt_passwd, 16); - NT_STATUS_HAVE_NO_MEMORY(entry.name); - NT_STATUS_HAVE_NO_MEMORY(entry.principal); - NT_STATUS_HAVE_NO_MEMORY(entry.password.data); + status = add_to_keytab_entries(mem_ctx, ctx, kvno, name, + data_blob_talloc(mem_ctx, nt_passwd, 16)); - ADD_TO_ARRAY(mem_ctx, struct libnet_keytab_entry, entry, - &ctx->entries, &ctx->count); + if (!NT_STATUS_IS_OK(status)) { + return status; + } if ((kvno < 0) && (kvno < pwd_history_len)) { return status; -- cgit From c1b9eb278fcc37cc9d286c830236af4532a5bf76 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 16 Jul 2008 23:10:20 +0200 Subject: dssync keytab: add check for success of ADD_TO_ARRAY(). Michael (This used to be commit e6f6e61da46f02bb2676c705974adc26bdfa2623) --- source3/libnet/libnet_dssync_keytab.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index c502211b45..a2ce8ddcaa 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -41,6 +41,7 @@ static NTSTATUS add_to_keytab_entries(TALLOC_CTX *mem_ctx, ADD_TO_ARRAY(mem_ctx, struct libnet_keytab_entry, entry, &ctx->entries, &ctx->count); + NT_STATUS_HAVE_NO_MEMORY(ctx->entries); return NT_STATUS_OK; } -- cgit From 764691fdd141c5f362594dfcf54034f37e727fea Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 16 Jul 2008 23:12:31 +0200 Subject: dssync keytab: add prefix parameter to add_to_keytab_entries() for flexibility. This will allow to construct principals of the form PREFIX/name@domain Michael (This used to be commit 7dd32b56a65574db95f4a0e136f54bd73862c59f) --- source3/libnet/libnet_dssync_keytab.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index a2ce8ddcaa..eb3a936bcd 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -26,13 +26,16 @@ static NTSTATUS add_to_keytab_entries(TALLOC_CTX *mem_ctx, struct libnet_keytab_context *ctx, uint32_t kvno, const char *name, + const char *prefix, DATA_BLOB blob) { struct libnet_keytab_entry entry; entry.kvno = kvno; entry.name = talloc_strdup(mem_ctx, name); - entry.principal = talloc_asprintf(mem_ctx, "%s@%s", + entry.principal = talloc_asprintf(mem_ctx, "%s%s%s@%s", + prefix ? prefix : "", + prefix ? "/" : "", name, ctx->dns_domain_name); entry.password = blob; NT_STATUS_HAVE_NO_MEMORY(entry.name); @@ -190,7 +193,7 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, } DEBUGADD(1,("\n")); - status = add_to_keytab_entries(mem_ctx, ctx, kvno, name, + status = add_to_keytab_entries(mem_ctx, ctx, kvno, name, NULL, data_blob_talloc(mem_ctx, nt_passwd, 16)); if (!NT_STATUS_IS_OK(status)) { -- cgit From 7bd3ea0b6f53ff90af4483d5a27bb4986e8e1209 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 24 Jul 2008 00:30:07 +0200 Subject: dssync keytab: use add_to_keytab_entries() for pwd history in parse_object(). Michael (This used to be commit 61f071de92a7011c70f72dc31fef4430ffb1515a) --- source3/libnet/libnet_dssync_keytab.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index eb3a936bcd..b1f0a35d8b 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -100,7 +100,6 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, { NTSTATUS status = NT_STATUS_OK; uchar nt_passwd[16]; - struct libnet_keytab_entry entry; DATA_BLOB *blob; int i = 0; struct drsuapi_DsReplicaAttribute *attr; @@ -215,18 +214,11 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, } for (; idns_domain_name); - entry.password = data_blob_talloc(mem_ctx, &pwd_history[i*16], 16); - NT_STATUS_HAVE_NO_MEMORY(entry.name); - NT_STATUS_HAVE_NO_MEMORY(entry.principal); - NT_STATUS_HAVE_NO_MEMORY(entry.password.data); - - ADD_TO_ARRAY(mem_ctx, struct libnet_keytab_entry, entry, - &ctx->entries, &ctx->count); + status = add_to_keytab_entries(mem_ctx, ctx, kvno--, name, NULL, + data_blob_talloc(mem_ctx, &pwd_history[i*16], 16)); + if (!NT_STATUS_IS_OK(status)) { + break; + } } return status; -- cgit From 0db26805da4f62c313237e762a81cebbe0f0357c Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 17 Jul 2008 00:54:35 +0200 Subject: dssync keytab: add support for keeping track of the up-to-date-ness vector. The startup operation should get the old up-to-date-ness vector from the backend and the finish operation should store the new vector to the backend after replication. This adds the change of the signatures of the operations ot the dssync_ops struct and the implementation for the keytab ops. The up-to-date-ness vector is stored under the principal constructed as UTDV/$naming_context_dn@$dns_domain_name. The vector is still uninterpreted in libnet_dssync_process(). This will be the next step... This code is essentially by Metze. Michael (This used to be commit 01318fb27a1aa9e5fed0d4dd882a123ab568ac37) --- source3/libnet/libnet_dssync_keytab.c | 65 ++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index b1f0a35d8b..37a4a4e88e 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -19,6 +19,7 @@ #include "includes.h" #include "libnet/libnet.h" +#include "librpc/gen_ndr/ndr_drsblobs.h" #if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) @@ -49,10 +50,14 @@ static NTSTATUS add_to_keytab_entries(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx) +static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, + struct replUpToDateVectorBlob **pold_utdv) { krb5_error_code ret = 0; struct libnet_keytab_context *keytab_ctx; + struct libnet_keytab_entry *entry; + struct replUpToDateVectorBlob *old_utdv = NULL; + char *principal; ret = libnet_keytab_init(mem_ctx, ctx->output_filename, &keytab_ctx); if (ret) { @@ -62,16 +67,66 @@ static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx) keytab_ctx->dns_domain_name = ctx->dns_domain_name; ctx->private_data = keytab_ctx; + principal = talloc_asprintf(mem_ctx, "UTDV/%s@%s", + ctx->nc_dn, ctx->dns_domain_name); + NT_STATUS_HAVE_NO_MEMORY(principal); + + entry = libnet_keytab_search(keytab_ctx, principal, 0, mem_ctx); + if (entry) { + enum ndr_err_code ndr_err; + old_utdv = talloc(mem_ctx, struct replUpToDateVectorBlob); + + ndr_err = ndr_pull_struct_blob(&entry->password, old_utdv, + old_utdv, + (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + NTSTATUS status = ndr_map_error2ntstatus(ndr_err); + ctx->error_message = talloc_asprintf(mem_ctx, + "Failed to pull UpToDateVector: %s", + nt_errstr(status)); + return status; + } + + NDR_PRINT_DEBUG(replUpToDateVectorBlob, old_utdv); + } + + if (pold_utdv) { + *pold_utdv = old_utdv; + } + return NT_STATUS_OK; } -static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx) +static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, + struct replUpToDateVectorBlob *new_utdv) { NTSTATUS status = NT_STATUS_OK; krb5_error_code ret = 0; struct libnet_keytab_context *keytab_ctx = (struct libnet_keytab_context *)ctx->private_data; + if (new_utdv) { + enum ndr_err_code ndr_err; + DATA_BLOB blob; + + NDR_PRINT_DEBUG(replUpToDateVectorBlob, new_utdv); + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, new_utdv, + (ndr_push_flags_fn_t)ndr_push_replUpToDateVectorBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + ctx->error_message = talloc_asprintf(mem_ctx, + "Failed to push UpToDateVector: %s", + nt_errstr(status)); + goto done; + } + + status = add_to_keytab_entries(mem_ctx, keytab_ctx, 0, + ctx->nc_dn, "UTDV", blob); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + } + ret = libnet_keytab_add(keytab_ctx); if (ret) { status = krb5_to_nt_status(ret); @@ -249,12 +304,14 @@ static NTSTATUS keytab_process_objects(struct dssync_context *ctx, #else -static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx) +static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, + struct replUpToDateVectorBlob **pold_utdv) { return NT_STATUS_NOT_SUPPORTED; } -static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx) +static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, + struct replUpToDateVectorBlob *new_utdv) { return NT_STATUS_NOT_SUPPORTED; } -- cgit From 9f6af6fe7c36f12c6871ba654ee470d2ff951803 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 17 Jul 2008 11:54:32 +0200 Subject: dssync keytab: wrap printing of the uptodate vector in DEBUGLEVEL >= 10 checks Michael (This used to be commit 7fabe2567d0bd12fe3ade1d00b94b6c403fe79b5) --- source3/libnet/libnet_dssync_keytab.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 37a4a4e88e..ac94d24447 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -87,7 +87,9 @@ static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, return status; } - NDR_PRINT_DEBUG(replUpToDateVectorBlob, old_utdv); + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(replUpToDateVectorBlob, old_utdv); + } } if (pold_utdv) { @@ -109,7 +111,10 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, enum ndr_err_code ndr_err; DATA_BLOB blob; - NDR_PRINT_DEBUG(replUpToDateVectorBlob, new_utdv); + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(replUpToDateVectorBlob, new_utdv); + } + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, new_utdv, (ndr_push_flags_fn_t)ndr_push_replUpToDateVectorBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { -- cgit From 55791799b54e947c6ef825a05a0d141fc1436b9e Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 17 Jul 2008 13:32:19 +0200 Subject: dssync: skip analysis of the msDS_KeyVersionNumber attribute: It is a calculated attribute that won't get distributed via replication. Michael (This used to be commit d75b7a2052f1e447f2b3b63fdb054abef4403edf) --- source3/libnet/libnet_dssync_keytab.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index ac94d24447..350aa03320 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -216,9 +216,6 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, pwd_history_len = blob->length / 16; pwd_history = blob->data; break; - case DRSUAPI_ATTRIBUTE_msDS_KeyVersionNumber: - kvno = IVAL(blob->data, 0); - break; case DRSUAPI_ATTRIBUTE_userPrincipalName: pull_string_talloc(mem_ctx, NULL, 0, &upn, blob->data, blob->length, -- cgit From 363fd6e2971358b86b6e35dd71d2e3154a20106a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 28 Jul 2008 14:42:30 +0200 Subject: dssync keytab: add store enctypes in the libnet_keytype_entry structs. Still unused by the libnet_keytab_add() function. This will follow. In preparation of supporting multiple encryption types in libnet_dssync_keytab. Michael (This used to be commit 447b8b1122a35d4bc0ec0f88fb46d18cddcf6eb9) --- source3/libnet/libnet_dssync_keytab.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 350aa03320..cc53c983af 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -28,6 +28,7 @@ static NTSTATUS add_to_keytab_entries(TALLOC_CTX *mem_ctx, uint32_t kvno, const char *name, const char *prefix, + const krb5_enctype enctype, DATA_BLOB blob) { struct libnet_keytab_entry entry; @@ -38,6 +39,7 @@ static NTSTATUS add_to_keytab_entries(TALLOC_CTX *mem_ctx, prefix ? prefix : "", prefix ? "/" : "", name, ctx->dns_domain_name); + entry.enctype = enctype; entry.password = blob; NT_STATUS_HAVE_NO_MEMORY(entry.name); NT_STATUS_HAVE_NO_MEMORY(entry.principal); @@ -126,7 +128,8 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, } status = add_to_keytab_entries(mem_ctx, keytab_ctx, 0, - ctx->nc_dn, "UTDV", blob); + ctx->nc_dn, "UTDV", + ENCTYPE_NULL, blob); if (!NT_STATUS_IS_OK(status)) { goto done; } @@ -250,6 +253,7 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, DEBUGADD(1,("\n")); status = add_to_keytab_entries(mem_ctx, ctx, kvno, name, NULL, + ENCTYPE_ARCFOUR_HMAC, data_blob_talloc(mem_ctx, nt_passwd, 16)); if (!NT_STATUS_IS_OK(status)) { @@ -272,6 +276,7 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, for (; i Date: Tue, 29 Jul 2008 10:16:37 +0200 Subject: libnet keytab: add enctype parameter to libnet_keytab_search(). Not really used yet. Note: callers use ENCTYPE_ARCFOUR_HMAC enctype for UTDV (for now). This is what is currently stored. This is to be changed to ENCTYPE_NULL. Michael (This used to be commit cb91d07413430e0e0a16846d2c44aae8c165400e) --- source3/libnet/libnet_dssync_keytab.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index cc53c983af..526bb73647 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -73,7 +73,8 @@ static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, ctx->nc_dn, ctx->dns_domain_name); NT_STATUS_HAVE_NO_MEMORY(principal); - entry = libnet_keytab_search(keytab_ctx, principal, 0, mem_ctx); + entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_ARCFOUR_HMAC, + mem_ctx); if (entry) { enum ndr_err_code ndr_err; old_utdv = talloc(mem_ctx, struct replUpToDateVectorBlob); @@ -129,7 +130,8 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, status = add_to_keytab_entries(mem_ctx, keytab_ctx, 0, ctx->nc_dn, "UTDV", - ENCTYPE_NULL, blob); + ENCTYPE_ARCFOUR_HMAC, + blob); if (!NT_STATUS_IS_OK(status)) { goto done; } -- cgit From 8003c93a278d5f892bd3bca032a00985e7012703 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 29 Jul 2008 10:17:15 +0200 Subject: dssync keytab: add debugging output when skipping an object. Michael (This used to be commit f3c110097f2f6c5dd329f2ca595644c6a368a552) --- source3/libnet/libnet_dssync_keytab.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 526bb73647..e6cf08933d 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -242,7 +242,13 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, } } - if (!got_pwd || !name) { + if (!name) { + DEBUG(10, ("no name (sAMAccountName) found - skipping.\n")); + return NT_STATUS_OK; + } + + if (!got_pwd) { + DEBUG(10, ("no password (unicodePwd) found - skipping.\n")); return NT_STATUS_OK; } -- cgit From 7d7e8907ca8720a5803e367f2fbedd582defbe15 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 29 Jul 2008 12:54:46 +0200 Subject: dssync keytab: fix comma placement in debug output Michael (This used to be commit d21ea83f9392c8fa002d5b924dddca4190e82d09) --- source3/libnet/libnet_dssync_keytab.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index e6cf08933d..6784326baf 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -253,10 +253,10 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, } DEBUG(1,("#%02d: %s:%d, ", ctx->count, name, kvno)); - DEBUGADD(1,("sAMAccountType: 0x%08x, userAccountControl: 0x%08x ", + DEBUGADD(1,("sAMAccountType: 0x%08x, userAccountControl: 0x%08x", sam_type, uacc)); if (upn) { - DEBUGADD(1,("upn: %s", upn)); + DEBUGADD(1,(", upn: %s", upn)); } DEBUGADD(1,("\n")); -- cgit From 31c67f939f37bb77a55dcbb28d8e2f17555131e1 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 29 Jul 2008 12:55:19 +0200 Subject: dssync keytab: add parsing and logging of servicePrincipalName-s As with the userPrincipalName, this is for debugging purposes only (for now..). Michael (This used to be commit 7a1d526cba4c93bb858a60d04b6486507fc25398) --- source3/libnet/libnet_dssync_keytab.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 6784326baf..0d17fdad3d 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -171,6 +171,8 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, bool got_pwd = false; char *upn = NULL; + char **spn = NULL; + uint32_t num_spns = 0; char *name = NULL; uint32_t kvno = 0; uint32_t uacc = 0; @@ -185,6 +187,19 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, attr = &cur->object.attribute_ctr.attributes[i]; + if (attr->attid == DRSUAPI_ATTRIBUTE_servicePrincipalName) { + uint32_t count; + num_spns = attr->value_ctr.num_values; + spn = TALLOC_ARRAY(mem_ctx, char *, num_spns); + for (count = 0; count < num_spns; count++) { + blob = attr->value_ctr.values[count].blob; + pull_string_talloc(spn, NULL, 0, + &spn[count], + blob->data, blob->length, + STR_UNICODE); + } + } + if (attr->value_ctr.num_values != 1) { continue; } @@ -258,6 +273,13 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, if (upn) { DEBUGADD(1,(", upn: %s", upn)); } + if (num_spns > 0) { + DEBUGADD(1, (", spns: [")); + for (i = 0; i < num_spns; i++) { + DEBUGADD(1, ("%s%s", spn[i], + (i+1 == num_spns)?"]":", ")); + } + } DEBUGADD(1,("\n")); status = add_to_keytab_entries(mem_ctx, ctx, kvno, name, NULL, -- cgit From 86f91a2ba149c05f292aedf764ce83bcb49e5e57 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 29 Jul 2008 14:13:37 +0200 Subject: dssync keytab: remove old UpToDateNess vectors from keytab before storing new one. Michael (This used to be commit 717bd6f6c3ec94e3b8b5845c43717a5fbd41c38f) --- source3/libnet/libnet_dssync_keytab.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 0d17fdad3d..cfcbb6f34c 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -113,6 +113,7 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, if (new_utdv) { enum ndr_err_code ndr_err; DATA_BLOB blob; + char *principal; if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(replUpToDateVectorBlob, new_utdv); @@ -135,6 +136,24 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, if (!NT_STATUS_IS_OK(status)) { goto done; } + + principal = talloc_asprintf(mem_ctx, "UTDV/%s@%s", + ctx->nc_dn, ctx->dns_domain_name); + if (!principal) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + ret = libnet_keytab_remove_entries(keytab_ctx, principal, + 0, ENCTYPE_ARCFOUR_HMAC); + if (ret) { + status = krb5_to_nt_status(ret); + ctx->error_message = talloc_asprintf(mem_ctx, + "Failed to remove old UTDV entries from " + "keytab %s: %s", keytab_ctx->keytab_name, + error_message(ret)); + goto done; + } } ret = libnet_keytab_add(keytab_ctx); -- cgit From d74f57826aaa697745e8abc7537325963f2698b2 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 29 Jul 2008 14:15:07 +0200 Subject: dssync keytab: log the DN of the object to be parsed. For debugging purposes. Michael (This used to be commit 6913919e3a36ebff87a882ba589d36bcd0781ee6) --- source3/libnet/libnet_dssync_keytab.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index cfcbb6f34c..4875e8e5fa 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -202,6 +202,8 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, ZERO_STRUCT(nt_passwd); + DEBUG(3, ("parsing object '%s'\n", cur->object.identifier->dn)); + for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) { attr = &cur->object.attribute_ctr.attributes[i]; -- cgit From e1fee8ca6deaa58dab80030826ce48725f5099e2 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 29 Jul 2008 15:23:12 +0200 Subject: dssync keytab: store the UpToDate vector with ENCTYPE_NULL. Michael (This used to be commit 9fbc3d49035123ec11cc2248f0b14661dd1e9b2d) --- source3/libnet/libnet_dssync_keytab.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 4875e8e5fa..03d5bf2348 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -73,7 +73,7 @@ static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, ctx->nc_dn, ctx->dns_domain_name); NT_STATUS_HAVE_NO_MEMORY(principal); - entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_ARCFOUR_HMAC, + entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_NULL, mem_ctx); if (entry) { enum ndr_err_code ndr_err; @@ -131,7 +131,7 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, status = add_to_keytab_entries(mem_ctx, keytab_ctx, 0, ctx->nc_dn, "UTDV", - ENCTYPE_ARCFOUR_HMAC, + ENCTYPE_NULL, blob); if (!NT_STATUS_IS_OK(status)) { goto done; @@ -145,7 +145,7 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, } ret = libnet_keytab_remove_entries(keytab_ctx, principal, - 0, ENCTYPE_ARCFOUR_HMAC); + 0, ENCTYPE_NULL); if (ret) { status = krb5_to_nt_status(ret); ctx->error_message = talloc_asprintf(mem_ctx, -- cgit From f6bc42d80c2e9350ca5ccf46887267d6509a2c76 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 29 Jul 2008 18:05:13 +0200 Subject: dssync keytab: move handling of removal of duplicates to libnet_keytab_add_entry(). This makes libnet_keytab_remove_entries static and moves it up. libnet_keytab_add_entry() now removes the duplicates in advance. No special handling neede for the UTDV - this is also needed for other entries... Michael (This used to be commit 3c463745445f6b64017918f442bf1021be219e83) --- source3/libnet/libnet_dssync_keytab.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 03d5bf2348..4bd4a79a00 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -113,7 +113,6 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, if (new_utdv) { enum ndr_err_code ndr_err; DATA_BLOB blob; - char *principal; if (DEBUGLEVEL >= 10) { NDR_PRINT_DEBUG(replUpToDateVectorBlob, new_utdv); @@ -136,24 +135,6 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, if (!NT_STATUS_IS_OK(status)) { goto done; } - - principal = talloc_asprintf(mem_ctx, "UTDV/%s@%s", - ctx->nc_dn, ctx->dns_domain_name); - if (!principal) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - ret = libnet_keytab_remove_entries(keytab_ctx, principal, - 0, ENCTYPE_NULL); - if (ret) { - status = krb5_to_nt_status(ret); - ctx->error_message = talloc_asprintf(mem_ctx, - "Failed to remove old UTDV entries from " - "keytab %s: %s", keytab_ctx->keytab_name, - error_message(ret)); - goto done; - } } ret = libnet_keytab_add(keytab_ctx); -- cgit From 260bbf13d20fa94923dc8841a06267bf0ea102a7 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Tue, 29 Jul 2008 18:07:07 +0200 Subject: dssync keytab: store the samaccountname in the keytab for diff replication. When retreiving a diff replication, the sAMAccountName attribute is usually not replicated. So in order to build the principle, we need to store the sAMAccounName in the keytab, referenced by the DN of the object, so that it can be retrieved if necessary. It is stored in the form of SAMACCOUNTNAME/object_dn@dns_domain_name with kvno=0 and ENCTYPE_NONE. Michael (This used to be commit 54e2dc1f4e0e2c7a6dcb171e51a608d831c8946e) --- source3/libnet/libnet_dssync_keytab.c | 60 ++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 5 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 4bd4a79a00..db98f63d1b 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -170,6 +170,7 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, struct drsuapi_DsReplicaAttribute *attr; bool got_pwd = false; + char *object_dn = NULL; char *upn = NULL; char **spn = NULL; uint32_t num_spns = 0; @@ -183,7 +184,12 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, ZERO_STRUCT(nt_passwd); - DEBUG(3, ("parsing object '%s'\n", cur->object.identifier->dn)); + object_dn = talloc_strdup(mem_ctx, cur->object.identifier->dn); + if (!object_dn) { + return NT_STATUS_NO_MEMORY; + } + + DEBUG(3, ("parsing object '%s'\n", object_dn)); for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) { @@ -259,13 +265,57 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, } } - if (!name) { - DEBUG(10, ("no name (sAMAccountName) found - skipping.\n")); + if (!got_pwd) { + DEBUG(10, ("no password (unicodePwd) found - skipping.\n")); return NT_STATUS_OK; } - if (!got_pwd) { - DEBUG(10, ("no password (unicodePwd) found - skipping.\n")); + if (name) { + status = add_to_keytab_entries(mem_ctx, ctx, 0, object_dn, + "SAMACCOUNTNAME", + ENCTYPE_NULL, + data_blob_talloc(mem_ctx, name, + strlen(name) + 1)); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } else { + /* look into keytab ... */ + struct libnet_keytab_entry *entry = NULL; + char *principal = NULL; + + DEBUG(10, ("looking for SAMACCOUNTNAME/%s@%s in keytayb...\n", + object_dn, ctx->dns_domain_name)); + + principal = talloc_asprintf(mem_ctx, "%s/%s@%s", + "SAMACCOUNTNAME", + object_dn, + ctx->dns_domain_name); + if (!principal) { + DEBUG(1, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; + } + entry = libnet_keytab_search(ctx, principal, 0, ENCTYPE_NULL, + mem_ctx); + if (entry) { + name = (char *)TALLOC_MEMDUP(mem_ctx, + entry->password.data, + entry->password.length); + if (!name) { + DEBUG(1, ("talloc failed!")); + return NT_STATUS_NO_MEMORY; + } else { + DEBUG(10, ("found name %s\n", name)); + } + TALLOC_FREE(entry); + } else { + DEBUG(10, ("entry not found\n")); + } + TALLOC_FREE(principal); + } + + if (!name) { + DEBUG(10, ("no name (sAMAccountName) found - skipping.\n")); return NT_STATUS_OK; } -- cgit From 982759357f8bd9b4c261f342108f106ead2d5a25 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 31 Jul 2008 12:25:06 +0200 Subject: dssync keytab: support storing kerberos keys from supplemental credentials. Michael (This used to be commit 50b1673289f5c147bdb4953f3511a7afe783758c) --- source3/libnet/libnet_dssync_keytab.c | 186 ++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index db98f63d1b..d74ee3dbdb 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -159,6 +159,106 @@ done: /**************************************************************** ****************************************************************/ +static NTSTATUS parse_supplemental_credentials(TALLOC_CTX *mem_ctx, + const DATA_BLOB *blob, + struct package_PrimaryKerberosCtr3 **pkb3, + struct package_PrimaryKerberosCtr4 **pkb4) +{ + NTSTATUS status; + enum ndr_err_code ndr_err; + struct supplementalCredentialsBlob scb; + struct supplementalCredentialsPackage *scpk = NULL; + DATA_BLOB scpk_blob; + struct package_PrimaryKerberosBlob *pkb; + bool newer_keys = false; + uint32_t j; + + ndr_err = ndr_pull_struct_blob_all(blob, mem_ctx, &scb, + (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + goto done; + } + if (scb.sub.signature != + SUPPLEMENTAL_CREDENTIALS_SIGNATURE) + { + if (DEBUGLEVEL >= 10) { + NDR_PRINT_DEBUG(supplementalCredentialsBlob, &scb); + } + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + for (j=0; j < scb.sub.num_packages; j++) { + if (strcmp("Primary:Kerberos-Newer-Keys", + scb.sub.packages[j].name) == 0) + { + scpk = &scb.sub.packages[j]; + if (!scpk->data || !scpk->data[0]) { + scpk = NULL; + continue; + } + newer_keys = true; + break; + } else if (strcmp("Primary:Kerberos", + scb.sub.packages[j].name) == 0) + { + /* + * grab this but don't break here: + * there might still be newer-keys ... + */ + scpk = &scb.sub.packages[j]; + if (!scpk->data || !scpk->data[0]) { + scpk = NULL; + } + } + } + + if (!scpk) { + /* no data */ + status = NT_STATUS_OK; + goto done; + } + + scpk_blob = strhex_to_data_blob(mem_ctx, scpk->data); + if (!scpk_blob.data) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + pkb = TALLOC_ZERO_P(mem_ctx, struct package_PrimaryKerberosBlob); + if (!pkb) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + ndr_err = ndr_pull_struct_blob(&scpk_blob, mem_ctx, pkb, + (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + goto done; + } + + if (!newer_keys && pkb->version != 3) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + if (newer_keys && pkb->version != 4) { + status = NT_STATUS_INVALID_PARAMETER; + goto done; + } + + if (pkb->version == 4 && pkb4) { + *pkb4 = &pkb->ctr.ctr4; + } else if (pkb->version == 3 && pkb3) { + *pkb3 = &pkb->ctr.ctr3; + } + + status = NT_STATUS_OK; + +done: + return status; +} + static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, struct libnet_keytab_context *ctx, struct drsuapi_DsReplicaObjectListItemEx *cur) @@ -170,6 +270,9 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, struct drsuapi_DsReplicaAttribute *attr; bool got_pwd = false; + struct package_PrimaryKerberosCtr3 *pkb3 = NULL; + struct package_PrimaryKerberosCtr4 *pkb4 = NULL; + char *object_dn = NULL; char *upn = NULL; char **spn = NULL; @@ -260,6 +363,17 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, case DRSUAPI_ATTRIBUTE_userAccountControl: uacc = IVAL(blob->data, 0); break; + case DRSUAPI_ATTRIBUTE_supplementalCredentials: + status = parse_supplemental_credentials(mem_ctx, + blob, + &pkb3, + &pkb4); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2, ("parsing of supplemental " + "credentials failed: %s\n", + nt_errstr(status))); + } + break; default: break; } @@ -342,6 +456,78 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, return status; } + /* add kerberos keys (if any) */ + + if (pkb4) { + for (i=0; i < pkb4->num_keys; i++) { + if (!pkb4->keys[i].value) { + continue; + } + status = add_to_keytab_entries(mem_ctx, ctx, kvno, + name, + NULL, + pkb4->keys[i].keytype, + *pkb4->keys[i].value); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + for (i=0; i < pkb4->num_old_keys; i++) { + if (!pkb4->old_keys[i].value) { + continue; + } + status = add_to_keytab_entries(mem_ctx, ctx, kvno - 1, + name, + NULL, + pkb4->old_keys[i].keytype, + *pkb4->old_keys[i].value); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + for (i=0; i < pkb4->num_older_keys; i++) { + if (!pkb4->older_keys[i].value) { + continue; + } + status = add_to_keytab_entries(mem_ctx, ctx, kvno - 2, + name, + NULL, + pkb4->older_keys[i].keytype, + *pkb4->older_keys[i].value); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + } + + if (pkb3) { + for (i=0; i < pkb3->num_keys; i++) { + if (!pkb3->keys[i].value) { + continue; + } + status = add_to_keytab_entries(mem_ctx, ctx, kvno, name, + NULL, + pkb3->keys[i].keytype, + *pkb3->keys[i].value); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + for (i=0; i < pkb3->num_old_keys; i++) { + if (!pkb3->old_keys[i].value) { + continue; + } + status = add_to_keytab_entries(mem_ctx, ctx, kvno - 1, + name, + NULL, + pkb3->old_keys[i].keytype, + *pkb3->old_keys[i].value); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + } + if ((kvno < 0) && (kvno < pwd_history_len)) { return status; } -- cgit From efd89b46d6a66e4a4d17e7cdc400e9e3890b7970 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 31 Jul 2008 22:53:41 +0200 Subject: dssync keytab: when not in single object replication mode, use object dn list as write filter. I.e. only the passwords and keys of those objects whose dns are provided are written to the keytab file. Others are skippded. Michael (This used to be commit a013f926ae5aadf64e02ef9254306e32aea79e80) --- source3/libnet/libnet_dssync_keytab.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index d74ee3dbdb..2558e1d801 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -554,6 +554,24 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx, return status; } +static bool dn_is_in_object_list(struct dssync_context *ctx, + const char *dn) +{ + uint32_t count; + + if (ctx->object_count == 0) { + return true; + } + + for (count = 0; count < ctx->object_count; count++) { + if (strequal(ctx->object_dns[count], dn)) { + return true; + } + } + + return false; +} + /**************************************************************** ****************************************************************/ @@ -567,6 +585,16 @@ static NTSTATUS keytab_process_objects(struct dssync_context *ctx, (struct libnet_keytab_context *)ctx->private_data; for (; cur; cur = cur->next_object) { + /* + * When not in single object replication mode, + * the object_dn list is used as a positive write filter. + */ + if (!ctx->single_object_replication && + !dn_is_in_object_list(ctx, cur->object.identifier->dn)) + { + continue; + } + status = parse_object(mem_ctx, keytab_ctx, cur); if (!NT_STATUS_IS_OK(status)) { goto out; -- cgit From 10225fbef737217d3e1b88bdfcbf4e62dff3cadd Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 1 Aug 2008 00:09:28 +0200 Subject: dssync: add clean_old_entries flag to dssync_ctx. Initialize it to false. And pass it down to the libnet_keytab context in libnet_dssync_keytab.c:keytab_startup(). Unused yet. Michael Note: This might not be not 100% clean design to put this into the toplevel dssync context while it is keytab specific. But then, on the other hand, other imaginable backends might want to use this flag, too... (This used to be commit 12e884f227e240860e49f9e41d8c1f45e10ad3be) --- source3/libnet/libnet_dssync_keytab.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 2558e1d801..51156cbdba 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -67,6 +67,7 @@ static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, } keytab_ctx->dns_domain_name = ctx->dns_domain_name; + keytab_ctx->clean_old_entries = ctx->clean_old_entries; ctx->private_data = keytab_ctx; principal = talloc_asprintf(mem_ctx, "UTDV/%s@%s", -- cgit From a5d4b540e27bc716efa2f72a6013ab841eeca140 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 1 Aug 2008 14:26:46 +0200 Subject: libnet dssync: add my C after dssync keytab changes. Michael (This used to be commit 9391aec8d4600c685b14d3cd1624f8758f2cc80d) --- source3/libnet/libnet_dssync_keytab.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 51156cbdba..e40e353088 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. Copyright (C) Guenther Deschner 2008 + Copyright (C) Michael Adam 2008 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -- cgit From 4c6e9662b8360692f8ee8c36287ec8aa0b9d831a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 1 Aug 2008 17:09:08 +0200 Subject: dssync keytab: add comment header explaining add_to_keytab_entries(). Michael (This used to be commit 1072bd9f96ff3853e5ff58239123fc8c76a99063) --- source3/libnet/libnet_dssync_keytab.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index e40e353088..71fc7147df 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -24,6 +24,10 @@ #if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) +/** + * Internal helper function to add data to the list + * of keytab entries. It builds the prefix from the input. + */ static NTSTATUS add_to_keytab_entries(TALLOC_CTX *mem_ctx, struct libnet_keytab_context *ctx, uint32_t kvno, -- cgit From 84ee630ee973189ca9f2ce2afe4987998aaeccc7 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 1 Aug 2008 17:10:59 +0200 Subject: libnet dssync: fix memory allocation for error/result messages. Use the libnet_dssync_context as a talloc context for the result_message and error_message string members. Using the passed in mem_ctx makes the implicit assumption that mem_ctx is at least as long-lived as the libnet_dssync_context, which is wrong. Michael (This used to be commit 635baf6b7d2a1822ceb48aa4bc47569ef19d51cc) --- source3/libnet/libnet_dssync_keytab.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/libnet/libnet_dssync_keytab.c') diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 71fc7147df..6ba2c3aa41 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -90,7 +90,7 @@ static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); - ctx->error_message = talloc_asprintf(mem_ctx, + ctx->error_message = talloc_asprintf(ctx, "Failed to pull UpToDateVector: %s", nt_errstr(status)); return status; @@ -128,7 +128,7 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, (ndr_push_flags_fn_t)ndr_push_replUpToDateVectorBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); - ctx->error_message = talloc_asprintf(mem_ctx, + ctx->error_message = talloc_asprintf(ctx, "Failed to push UpToDateVector: %s", nt_errstr(status)); goto done; @@ -146,13 +146,13 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, ret = libnet_keytab_add(keytab_ctx); if (ret) { status = krb5_to_nt_status(ret); - ctx->error_message = talloc_asprintf(mem_ctx, + ctx->error_message = talloc_asprintf(ctx, "Failed to add entries to keytab %s: %s", keytab_ctx->keytab_name, error_message(ret)); goto done; } - ctx->result_message = talloc_asprintf(mem_ctx, + ctx->result_message = talloc_asprintf(ctx, "Vampired %d accounts to keytab %s", keytab_ctx->count, keytab_ctx->keytab_name); -- cgit