summaryrefslogtreecommitdiff
path: root/source4/libnet/libnet_vampire.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2005-05-02 14:17:19 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:16:27 -0500
commit8bf57cf8f57be28831023c2218d358b24b705256 (patch)
treee18e07afa72a46e9c6c94b8faf1ee21650b2cc20 /source4/libnet/libnet_vampire.c
parent591ff7675dfe51f30029cb864df47bc8f6266494 (diff)
downloadsamba-8bf57cf8f57be28831023c2218d358b24b705256.tar.gz
samba-8bf57cf8f57be28831023c2218d358b24b705256.tar.bz2
samba-8bf57cf8f57be28831023c2218d358b24b705256.zip
r6573: Start on my project to implement an NT4 compatible BDC in Samba4.
This brings in a compatability layer for Samba3 in Samba4 - where we will start to define file formats and similar details. The 'net samdump' command uses 'password server = ' for now, and performs a similar task to Samba3's 'net rpc samsync'. Andrew Bartlett (This used to be commit 550f17f9924fe783917318753de7d1a388423908)
Diffstat (limited to 'source4/libnet/libnet_vampire.c')
-rw-r--r--source4/libnet/libnet_vampire.c225
1 files changed, 225 insertions, 0 deletions
diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c
new file mode 100644
index 0000000000..daf7bdfaed
--- /dev/null
+++ b/source4/libnet/libnet_vampire.c
@@ -0,0 +1,225 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include "includes.h"
+#include "libnet/libnet.h"
+#include "librpc/gen_ndr/ndr_netlogon.h"
+#include "librpc/gen_ndr/ndr_samr.h"
+
+static BOOL vampire_samdump_handle_user(TALLOC_CTX *mem_ctx,
+ struct creds_CredentialState *creds,
+ struct netr_DELTA_ENUM *delta)
+{
+ uint32_t rid = delta->delta_id_union.rid;
+ struct netr_DELTA_USER *user = delta->delta_union.user;
+ struct samr_Password lm_hash;
+ struct samr_Password nt_hash;
+ struct samr_Password *lm_hash_p = NULL;
+ struct samr_Password *nt_hash_p = NULL;
+ const char *username = user->account_name.string;
+ char *hex_lm_password;
+ char *hex_nt_password;
+
+ NTSTATUS nt_status;
+
+ if (user->lm_password_present) {
+ sam_rid_crypt(rid, user->lmpassword.hash, lm_hash.hash, 0);
+ lm_hash_p = &lm_hash;
+ }
+ if (user->nt_password_present) {
+ sam_rid_crypt(rid, user->ntpassword.hash, nt_hash.hash, 0);
+ nt_hash_p = &nt_hash;
+ }
+
+ if (user->user_private_info.SensitiveData) {
+ DATA_BLOB data;
+ struct netr_USER_KEYS keys;
+ data.data = user->user_private_info.SensitiveData;
+ data.length = user->user_private_info.DataLength;
+ creds_arcfour_crypt(creds, data.data, data.length);
+ nt_status = ndr_pull_struct_blob(&data, mem_ctx, &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS);
+ if (NT_STATUS_IS_OK(nt_status)) {
+ if (keys.keys.keys2.lmpassword.length == 16) {
+ sam_rid_crypt(rid, keys.keys.keys2.lmpassword.pwd.hash, lm_hash.hash, 0);
+ lm_hash_p = &lm_hash;
+ }
+ if (keys.keys.keys2.ntpassword.length == 16) {
+ sam_rid_crypt(rid, keys.keys.keys2.ntpassword.pwd.hash, nt_hash.hash, 0);
+ nt_hash_p = &nt_hash;
+ }
+ } else {
+ printf("Failed to parse Sensitive Data for %s:\n", username);
+ dump_data(10, data.data, data.length);
+ return False;
+ }
+ }
+
+ hex_lm_password = smbpasswd_sethexpwd(mem_ctx, lm_hash_p, user->acct_flags);
+ hex_nt_password = smbpasswd_sethexpwd(mem_ctx, nt_hash_p, user->acct_flags);
+
+ printf("%s:%d:%s:%s:%s:LCT-%08X\n", username,
+ rid, hex_lm_password, hex_nt_password,
+ smbpasswd_encode_acb_info(mem_ctx, user->acct_flags),
+ (unsigned int)nt_time_to_unix(user->last_password_change));
+
+ return True;
+}
+
+
+
+static NTSTATUS libnet_SamDump_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SamDump *r)
+{
+ NTSTATUS nt_status;
+ TALLOC_CTX *loop_ctx, *delta_ctx;
+ struct creds_CredentialState *creds;
+ struct netr_DatabaseSync dbsync;
+ struct cli_credentials *machine_account;
+ struct dcerpc_binding *b;
+ struct dcerpc_pipe *p;
+
+ /* TODO: This is bogus */
+ const char **bindings = lp_passwordserver();
+ const char *binding;
+
+ if (bindings && bindings[0]) {
+ binding = bindings[0];
+ }
+
+ machine_account = cli_credentials_init(mem_ctx);
+ if (!machine_account) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ cli_credentials_set_conf(machine_account);
+ nt_status = cli_credentials_set_machine_account(machine_account);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ r->netlogon.error_string = talloc_strdup(mem_ctx, "Could not obtain machine account password - are we joined to the domain?");
+ return nt_status;
+ }
+
+ if (cli_credentials_get_secure_channel_type(machine_account) != SEC_CHAN_BDC) {
+ r->netlogon.error_string
+ = talloc_asprintf(mem_ctx,
+ "Our join to domain %s is not as a BDC (%d), please rejoin as a BDC",
+ cli_credentials_get_secure_channel_type(machine_account),
+ cli_credentials_get_domain(machine_account));
+ return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+ }
+
+ /* Connect to DC (take a binding string for now) */
+
+ nt_status = dcerpc_parse_binding(mem_ctx, binding, &b);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ r->netlogon.error_string = talloc_asprintf(mem_ctx, "Bad binding string %s\n", binding);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* We like schannel */
+ b->flags &= ~DCERPC_AUTH_OPTIONS;
+ b->flags |= DCERPC_SCHANNEL | DCERPC_SEAL | DCERPC_SCHANNEL_128;
+
+ /* Setup schannel */
+ nt_status = dcerpc_pipe_connect_b(mem_ctx, &p, b,
+ DCERPC_NETLOGON_UUID,
+ DCERPC_NETLOGON_VERSION,
+ machine_account);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ /* call domain logon */
+
+ nt_status = dcerpc_schannel_creds(p->conn->security_state.generic_state, mem_ctx, &creds);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ dbsync.in.logon_server = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
+ dbsync.in.computername = cli_credentials_get_workstation(machine_account);
+ dbsync.in.preferredmaximumlength = (uint32_t)-1;
+ ZERO_STRUCT(dbsync.in.return_authenticator);
+
+ dbsync.in.sync_context = 0;
+ dbsync.in.database_id = SAM_DATABASE_DOMAIN;
+
+ do {
+ int d;
+ loop_ctx = talloc_named(mem_ctx, 0, "DatabaseSync loop context");
+ creds_client_authenticator(creds, &dbsync.in.credential);
+
+ nt_status = dcerpc_netr_DatabaseSync(p, loop_ctx, &dbsync);
+ if (!NT_STATUS_IS_OK(nt_status) &&
+ !NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES)) {
+ printf("DatabaseSync - %s\n", nt_errstr(nt_status));
+ return nt_status;
+ }
+
+ if (!creds_client_check(creds, &dbsync.out.return_authenticator.cred)) {
+ printf("Credential chaining failed\n");
+ }
+
+ dbsync.in.sync_context = dbsync.out.sync_context;
+
+ for (d=0; d < dbsync.out.delta_enum_array->num_deltas; d++) {
+ delta_ctx = talloc_named(loop_ctx, 0, "DatabaseSync delta context");
+ switch (dbsync.out.delta_enum_array->delta_enum[d].delta_type) {
+ case NETR_DELTA_USER:
+ if (!vampire_samdump_handle_user(delta_ctx,
+ creds,
+ &dbsync.out.delta_enum_array->delta_enum[d])) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ break;
+ }
+ talloc_free(delta_ctx);
+ }
+ talloc_free(loop_ctx);
+ } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
+ return NT_STATUS_OK;
+}
+
+NTSTATUS libnet_SamDump_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SamDump *r)
+{
+ NTSTATUS nt_status;
+ union libnet_SamDump r2;
+
+ r2.generic.level = LIBNET_SAMDUMP_NETLOGON;
+ r2.generic.error_string = NULL;
+ nt_status = libnet_SamDump(ctx, mem_ctx, &r2);
+ r->generic.error_string = r2.netlogon.error_string;
+
+
+ return nt_status;
+}
+
+NTSTATUS libnet_SamDump(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, union libnet_SamDump *r)
+{
+ switch (r->generic.level) {
+ case LIBNET_SAMDUMP_GENERIC:
+ return libnet_SamDump_generic(ctx, mem_ctx, r);
+ case LIBNET_SAMDUMP_NETLOGON:
+ return libnet_SamDump_netlogon(ctx, mem_ctx, r);
+ }
+
+ return NT_STATUS_INVALID_LEVEL;
+}