diff options
author | Günther Deschner <gd@samba.org> | 2008-06-27 15:36:19 +0200 |
---|---|---|
committer | Günther Deschner <gd@samba.org> | 2008-07-01 10:02:01 +0200 |
commit | 9b0e3bb0c36abd9396f07de988e5c402d8503681 (patch) | |
tree | 34dd41e6540be60d4b47bffde4af4d0cab939d77 /source3/libnet | |
parent | fc836440a5c4ad1a3a5f0de0e64b4cd83e28e3c9 (diff) | |
download | samba-9b0e3bb0c36abd9396f07de988e5c402d8503681.tar.gz samba-9b0e3bb0c36abd9396f07de988e5c402d8503681.tar.bz2 samba-9b0e3bb0c36abd9396f07de988e5c402d8503681.zip |
net_vampire: add code to vampire to a Kerberos keytab file using DRSUAPI.
Guenther
(This used to be commit 0ef420c3a478a8adce7483f14b45e9995bfa5e5d)
Diffstat (limited to 'source3/libnet')
-rw-r--r-- | source3/libnet/libnet_dssync.h | 6 | ||||
-rw-r--r-- | source3/libnet/libnet_dssync_keytab.c | 240 |
2 files changed, 246 insertions, 0 deletions
diff --git a/source3/libnet/libnet_dssync.h b/source3/libnet/libnet_dssync.h index 6a56566c19..c98e650fcc 100644 --- a/source3/libnet/libnet_dssync.h +++ b/source3/libnet/libnet_dssync.h @@ -39,3 +39,9 @@ struct dssync_context { char *result_message; char *error_message; }; + +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); 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 <gd@samba.org> 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 "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 (; i<pwd_history_len; i++) { + + 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, &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) */ |