diff options
author | Andrew Bartlett <abartlet@samba.org> | 2010-08-10 08:25:02 +1000 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2010-08-13 09:08:27 -0400 |
commit | 71d80e6be0687ac7c2f3caab5e7b8caf400fe37e (patch) | |
tree | a30d558e704bac324809908c55a93bc17cb0c436 /source3/libnet/libnet_samsync_keytab.c.orig | |
parent | fff6fa72ffa7890cee516bd7e65b50bdb8daf51d (diff) | |
download | samba-71d80e6be0687ac7c2f3caab5e7b8caf400fe37e.tar.gz samba-71d80e6be0687ac7c2f3caab5e7b8caf400fe37e.tar.bz2 samba-71d80e6be0687ac7c2f3caab5e7b8caf400fe37e.zip |
s3-krb5 Only build ADS support if arcfour-hmac-md5 is available
Modern Kerberos implementations have either defines or enums for these
key types, which makes doing #ifdef difficult. This shows up in files
such as libnet_samsync_keytab.c, the bulk of which is not compiled on
current Fedora 12, for example.
The downside is that this makes Samba unconditionally depend on the
arcfour-hmac-md5 encryption type at build time. We will no longer
support libraries that only support the DES based encryption types.
However, the single-DES types that are supported in common with AD are
already painfully weak - so much so that they are disabled by default
in modern Kerberos libraries.
If not found, ADS support will not be compiled in.
This means that our 'net ads join' will no longer set the
ACB_USE_DES_KEY_ONLY flag, and we will always try to use
arcfour-hmac-md5.
A future improvement would be to remove the use of the DES encryption
types totally, but this would require that any ACB_USE_DES_KEY_ONLY
flag be removed from existing joins.
Andrew Bartlett
Signed-off-by: Simo Sorce <idra@samba.org>
Diffstat (limited to 'source3/libnet/libnet_samsync_keytab.c.orig')
-rw-r--r-- | source3/libnet/libnet_samsync_keytab.c.orig | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/source3/libnet/libnet_samsync_keytab.c.orig b/source3/libnet/libnet_samsync_keytab.c.orig new file mode 100644 index 0000000000..134922392c --- /dev/null +++ b/source3/libnet/libnet_samsync_keytab.c.orig @@ -0,0 +1,305 @@ +/* + Unix SMB/CIFS implementation. + dump the remote SAM using rpc samsync operations + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "smb_krb5.h" +#include "ads.h" +#include "libnet/libnet_keytab.h" +#include "libnet/libnet_samsync.h" + +#if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) + +/**************************************************************** +****************************************************************/ + +static NTSTATUS keytab_ad_connect(TALLOC_CTX *mem_ctx, + const char *domain_name, + const char *username, + const char *password, + struct libnet_keytab_context *ctx) +{ + NTSTATUS status; + ADS_STATUS ad_status; + ADS_STRUCT *ads; + struct netr_DsRGetDCNameInfo *info = NULL; + const char *dc; + + status = dsgetdcname(mem_ctx, NULL, domain_name, NULL, NULL, 0, &info); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + dc = strip_hostname(info->dc_unc); + + ads = ads_init(NULL, domain_name, dc); + NT_STATUS_HAVE_NO_MEMORY(ads); + + if (getenv(KRB5_ENV_CCNAME) == NULL) { + setenv(KRB5_ENV_CCNAME, "MEMORY:libnet_samsync_keytab", 1); + } + + ads->auth.user_name = SMB_STRDUP(username); + ads->auth.password = SMB_STRDUP(password); + + ad_status = ads_connect_user_creds(ads); + if (!ADS_ERR_OK(ad_status)) { + return NT_STATUS_UNSUCCESSFUL; + } + + ctx->ads = ads; + + ctx->dns_domain_name = talloc_strdup_upper(mem_ctx, ads->config.realm); + NT_STATUS_HAVE_NO_MEMORY(ctx->dns_domain_name); + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS fetch_sam_entry_keytab(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + uint32_t rid, + struct netr_DELTA_USER *r, + struct libnet_keytab_context *ctx) +{ + NTSTATUS status; + uint32_t kvno = 0; + DATA_BLOB blob; + + if (memcmp(r->ntpassword.hash, ctx->zero_buf, 16) == 0) { + return NT_STATUS_OK; + } + + kvno = ads_get_kvno(ctx->ads, r->account_name.string); + blob = data_blob_const(r->ntpassword.hash, 16); + + status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, + kvno, + r->account_name.string, + NULL, + ENCTYPE_ARCFOUR_HMAC, + blob); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS init_keytab(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t *sequence_num) +{ + krb5_error_code ret = 0; + NTSTATUS status; + struct libnet_keytab_context *keytab_ctx = NULL; + struct libnet_keytab_entry *entry; + uint64_t old_sequence_num = 0; + const char *principal = NULL; + + ret = libnet_keytab_init(mem_ctx, ctx->output_filename, &keytab_ctx); + if (ret) { + return krb5_to_nt_status(ret); + } + + keytab_ctx->clean_old_entries = ctx->clean_old_entries; + ctx->private_data = keytab_ctx; + + status = keytab_ad_connect(mem_ctx, + ctx->domain_name, + ctx->username, + ctx->password, + keytab_ctx); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(keytab_ctx); + return status; + } + + principal = talloc_asprintf(mem_ctx, "SEQUENCE_NUM@%s", + keytab_ctx->dns_domain_name); + NT_STATUS_HAVE_NO_MEMORY(principal); + + entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_NULL, + mem_ctx); + if (entry && (entry->password.length == 8)) { + old_sequence_num = BVAL(entry->password.data, 0); + } + + if (sequence_num) { + *sequence_num = old_sequence_num; + } + + return status; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM_ARRAY *r, + uint64_t *sequence_num, + struct samsync_context *ctx) +{ + struct libnet_keytab_context *keytab_ctx = + (struct libnet_keytab_context *)ctx->private_data; + + NTSTATUS status = NT_STATUS_OK; + int i; + + for (i = 0; i < r->num_deltas; i++) { + + switch (r->delta_enum[i].delta_type) { + case NETR_DELTA_USER: + break; + case NETR_DELTA_DOMAIN: + if (sequence_num) { + *sequence_num = + r->delta_enum[i].delta_union.domain->sequence_num; + } + continue; + case NETR_DELTA_MODIFY_COUNT: + if (sequence_num) { + *sequence_num = + *r->delta_enum[i].delta_union.modified_count; + } + continue; + default: + continue; + } + + status = fetch_sam_entry_keytab(mem_ctx, database_id, + r->delta_enum[i].delta_id_union.rid, + r->delta_enum[i].delta_union.user, + keytab_ctx); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + } + out: + return status; +} + +/**************************************************************** +****************************************************************/ + +static NTSTATUS close_keytab(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t sequence_num) +{ + struct libnet_keytab_context *keytab_ctx = + (struct libnet_keytab_context *)ctx->private_data; + krb5_error_code ret; + NTSTATUS status; + struct libnet_keytab_entry *entry; + uint64_t old_sequence_num = 0; + const char *principal = NULL; + + principal = talloc_asprintf(mem_ctx, "SEQUENCE_NUM@%s", + keytab_ctx->dns_domain_name); + NT_STATUS_HAVE_NO_MEMORY(principal); + + + entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_NULL, + mem_ctx); + if (entry && (entry->password.length == 8)) { + old_sequence_num = BVAL(entry->password.data, 0); + } + + + if (sequence_num > old_sequence_num) { + DATA_BLOB blob; + blob = data_blob_talloc_zero(mem_ctx, 8); + SBVAL(blob.data, 0, sequence_num); + + status = libnet_keytab_add_to_keytab_entries(mem_ctx, keytab_ctx, + 0, + "SEQUENCE_NUM", + NULL, + ENCTYPE_NULL, + blob); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + } + + ret = libnet_keytab_add(keytab_ctx); + if (ret) { + status = krb5_to_nt_status(ret); + ctx->error_message = talloc_asprintf(ctx, + "Failed to add entries to keytab %s: %s", + keytab_ctx->keytab_name, error_message(ret)); + TALLOC_FREE(keytab_ctx); + return status; + } + + ctx->result_message = talloc_asprintf(ctx, + "Vampired %d accounts to keytab %s", + keytab_ctx->count, + keytab_ctx->keytab_name); + + status = NT_STATUS_OK; + + done: + TALLOC_FREE(keytab_ctx); + + return status; +} + +#else + +static NTSTATUS init_keytab(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t *sequence_num) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +static NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx, + enum netr_SamDatabaseID database_id, + struct netr_DELTA_ENUM_ARRAY *r, + uint64_t *sequence_num, + struct samsync_context *ctx) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +static NTSTATUS close_keytab(TALLOC_CTX *mem_ctx, + struct samsync_context *ctx, + enum netr_SamDatabaseID database_id, + uint64_t sequence_num) +{ + return NT_STATUS_NOT_SUPPORTED; +} + +#endif /* defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) */ + +const struct samsync_ops libnet_samsync_keytab_ops = { + .startup = init_keytab, + .process_objects = fetch_sam_entries_keytab, + .finish = close_keytab +}; |