r6573: Start on my project to implement an NT4 compatible BDC in Samba4.
authorAndrew Bartlett <abartlet@samba.org>
Mon, 2 May 2005 14:17:19 +0000 (14:17 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:16:27 +0000 (13:16 -0500)
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

14 files changed:
source/include/structs.h
source/lib/basic.mk
source/lib/credentials.c
source/lib/samba3/README [new file with mode: 0644]
source/lib/samba3/smbpasswd.c [new file with mode: 0644]
source/lib/util_str.c
source/libnet/config.mk
source/libnet/libnet.h
source/libnet/libnet_vampire.c [new file with mode: 0644]
source/libnet/libnet_vampire.h [new file with mode: 0644]
source/passdb/secrets.c
source/utils/net/config.mk
source/utils/net/net.c
source/utils/net/net_vampire.c [new file with mode: 0644]

index 4e29ef8d507b848725b4c8cd158b5646c45c9145..c1998ee991d0904b4d82775206d4558d32576241 100644 (file)
@@ -201,3 +201,6 @@ struct wrepl_pull_table;
 struct wrepl_pull_names;
 
 struct arcfour_state;
+
+union libnet_SamDump;
+
index f0b2b05b6a4db2d16066ec9987eee26dcb1d1850..c1a34d39bb088a93545a808087b22d147cd4bc49 100644 (file)
@@ -40,6 +40,15 @@ INIT_OBJ_FILES = \
 # End SUBSYSTEM LIBCOMPRESION
 ################################################
 
+
+################################################
+# Start SUBSYSTEM LIBSAMBA3
+[SUBSYSTEM::LIBSAMBA3]
+INIT_OBJ_FILES = \
+               lib/samba3/smbpasswd.o
+# End SUBSYSTEM LIBSAMBA3
+################################################
+
 ##############################
 # Start SUBSYSTEM LIBBASIC
 [SUBSYSTEM::LIBBASIC]
index 64e3b9958d2cf2bfb504ddcfa47624f9c625152c..7e25fc780befcdacea88fe379e45b49939d37c49 100644 (file)
@@ -458,6 +458,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
                "samAccountName",
                "flatname",
                "realm",
+               "secureChannelType",
                NULL
        };
        
@@ -512,7 +513,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
        }
        
        sct = ldb_msg_find_int(msgs[0], "secureChannelType", 0);
-       if (!sct) {
+       if (sct) {
                cli_credentials_set_secure_channel_type(cred, sct);
        } else {
                DEBUG(1, ("Domain join for acocunt %s did not have a secureChannelType set!\n",
diff --git a/source/lib/samba3/README b/source/lib/samba3/README
new file mode 100644 (file)
index 0000000..cf55be0
--- /dev/null
@@ -0,0 +1,5 @@
+This directory contains various files and functions for the purpose of
+Samba3 import, migration and compatability.
+
+For example, the first file in this directory (smbpasswd.c) handles
+portions of the smbpasswd file format.
diff --git a/source/lib/samba3/smbpasswd.c b/source/lib/samba3/smbpasswd.c
new file mode 100644 (file)
index 0000000..587d038
--- /dev/null
@@ -0,0 +1,208 @@
+/* 
+   Unix SMB/CIFS implementation.
+   smbpasswd file format routines
+
+   Copyright (C) Andrew Tridgell 1992-1998 
+   Modified by Jeremy Allison 1995.
+   Modified by Gerald (Jerry) Carter 2000-2001
+   Copyright (C) Tim Potter 2001
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 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.
+*/
+
+/*! \file lib/smbpasswd.c
+
+   The smbpasswd file is used to store encrypted passwords in a similar
+   fashion to the /etc/passwd file.  The format is colon separated fields
+   with one user per line like so:
+
+   <username>:<uid>:<lanman hash>:<nt hash>:<acb info>:<last change time>
+
+   The username and uid must correspond to an entry in the /etc/passwd
+   file.  The lanman and nt password hashes are 32 hex digits corresponding
+   to the 16-byte lanman and nt hashes respectively.  
+
+   The password last change time is stored as a string of the format
+   LCD-<change time> where the change time is expressed as an 
+
+   'N'    No password
+   'D'    Disabled
+   'H'    Homedir required
+   'T'    Temp account.
+   'U'    User account (normal) 
+   'M'    MNS logon user account - what is this ? 
+   'W'    Workstation account
+   'S'    Server account 
+   'L'    Locked account
+   'X'    No Xpiry on password 
+   'I'    Interdomain trust account
+
+*/
+
+#include "includes.h"
+#include "librpc/gen_ndr/ndr_samr.h"
+#include "system/iconv.h"
+
+/*! Convert 32 hex characters into a 16 byte array. */
+
+struct samr_Password *smbpasswd_gethexpwd(TALLOC_CTX *mem_ctx, char *p)
+{
+       int i;
+       unsigned char   lonybble, hinybble;
+       const char     *hexchars = "0123456789ABCDEF";
+       char           *p1, *p2;
+        struct samr_Password *pwd = talloc(mem_ctx, struct samr_Password);
+
+       if (!p) return NULL;
+       
+       for (i = 0; i < (sizeof(pwd->hash) * 2); i += 2)
+       {
+               hinybble = toupper(p[i]);
+               lonybble = toupper(p[i + 1]);
+               
+               p1 = strchr_m(hexchars, hinybble);
+               p2 = strchr_m(hexchars, lonybble);
+               
+               if (!p1 || !p2)
+               {
+                        return (False);
+               }
+               
+               hinybble = PTR_DIFF(p1, hexchars);
+               lonybble = PTR_DIFF(p2, hexchars);
+               
+               pwd->hash[i / 2] = (hinybble << 4) | lonybble;
+       }
+       return pwd;
+}
+
+/*! Convert a 16-byte array into 32 hex characters. */
+       struct samr_Password *lm_hash_p = NULL;
+       struct samr_Password *nt_hash_p = NULL;
+
+char *smbpasswd_sethexpwd(TALLOC_CTX *mem_ctx, struct samr_Password *pwd, uint16_t acb_info)
+{
+       char *p;
+       if (pwd != NULL) {
+               int i;
+               p = talloc_array(mem_ctx, char, 33);
+               if (!p) {
+                       return NULL;
+               }
+
+               for (i = 0; i < sizeof(pwd->hash); i++)
+                       slprintf(&p[i*2], 3, "%02X", pwd->hash[i]);
+       } else {
+               if (acb_info & ACB_PWNOTREQ)
+                       p = talloc_strdup(mem_ctx, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");
+               else
+                       p = talloc_strdup(mem_ctx, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
+       }
+       return p;
+}
+
+/*! Decode the account control bits (ACB) info from a string. */
+
+uint16_t smbpasswd_decode_acb_info(const char *p)
+{
+       uint16_t acb_info = 0;
+       BOOL finished = False;
+
+       /*
+        * Check if the account type bits have been encoded after the
+        * NT password (in the form [NDHTUWSLXI]).
+        */
+
+       if (*p != '[') return 0;
+
+       for (p++; *p && !finished; p++)
+       {
+               switch (*p) {
+               case 'N': /* 'N'o password. */
+                       acb_info |= ACB_PWNOTREQ; 
+                       break;
+               case 'D': /* 'D'isabled. */
+                       acb_info |= ACB_DISABLED; 
+                       break; 
+               case 'H': /* 'H'omedir required. */
+                       acb_info |= ACB_HOMDIRREQ; 
+                       break;
+               case 'T': /* 'T'emp account. */
+                       acb_info |= ACB_TEMPDUP; 
+                       break;
+               case 'U': /* 'U'ser account (normal). */
+                       acb_info |= ACB_NORMAL;
+                       break;
+               case 'M': /* 'M'NS logon user account. What is this ? */
+                       acb_info |= ACB_MNS; 
+                       break; 
+               case 'W': /* 'W'orkstation account. */
+                       acb_info |= ACB_WSTRUST; 
+                       break; 
+               case 'S': /* 'S'erver account. */ 
+                       acb_info |= ACB_SVRTRUST; 
+                       break; 
+               case 'L': /* 'L'ocked account. */
+                       acb_info |= ACB_AUTOLOCK; 
+                       break; 
+               case 'X': /* No 'X'piry on password */
+                       acb_info |= ACB_PWNOEXP; 
+                       break; 
+               case 'I': /* 'I'nterdomain trust account. */
+                       acb_info |= ACB_DOMTRUST; 
+                       break; 
+
+               case ' ': 
+                       break;
+               case ':':
+               case '\n':
+               case '\0': 
+               case ']':
+               default:  
+                       finished = True;
+                       break;
+               }
+       }
+
+       return acb_info;
+}
+
+/*! Encode account control bits (ACBs) into a string. */
+
+char *smbpasswd_encode_acb_info(TALLOC_CTX *mem_ctx, uint16_t acb_info)
+{
+       char *acct_str = talloc_array(mem_ctx, char, 35);
+       size_t i = 0;
+
+       acct_str[i++] = '[';
+
+       if (acb_info & ACB_PWNOTREQ ) acct_str[i++] = 'N';
+       if (acb_info & ACB_DISABLED ) acct_str[i++] = 'D';
+       if (acb_info & ACB_HOMDIRREQ) acct_str[i++] = 'H';
+       if (acb_info & ACB_TEMPDUP  ) acct_str[i++] = 'T'; 
+       if (acb_info & ACB_NORMAL   ) acct_str[i++] = 'U';
+       if (acb_info & ACB_MNS      ) acct_str[i++] = 'M';
+       if (acb_info & ACB_WSTRUST  ) acct_str[i++] = 'W';
+       if (acb_info & ACB_SVRTRUST ) acct_str[i++] = 'S';
+       if (acb_info & ACB_AUTOLOCK ) acct_str[i++] = 'L';
+       if (acb_info & ACB_PWNOEXP  ) acct_str[i++] = 'X';
+       if (acb_info & ACB_DOMTRUST ) acct_str[i++] = 'I';
+
+       acct_str[i++] = ']';
+       acct_str[i++] = '\0';
+
+       return acct_str;
+}     
index dc39da50c7cadae8fc6786065ab9e9863691a576..5d12a01f6ea8c13140537e2bc537667aa0dd51b6 100644 (file)
@@ -395,6 +395,7 @@ char *StrnCpy(char *dest,const char *src,size_t n)
 
  valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
 
+
 **/
 size_t strhex_to_str(char *p, size_t len, const char *strhex)
 {
index 008dc7ea8ba6f2b797b17864847af4726441a1c6..3d3c4430cfbdd79853595f786d172cdd8d7add5c 100644 (file)
@@ -8,9 +8,10 @@ ADD_OBJ_FILES = \
                libnet/libnet_time.o \
                libnet/libnet_rpc.o \
                libnet/libnet_join.o \
+               libnet/libnet_vampire.o \
                libnet/libnet_user.o \
                libnet/userinfo.o \
                libnet/userman.o
-REQUIRED_SUBSYSTEMS = RPC_NDR_SAMR RPC_NDR_SRVSVC LIBCLI_COMPOSITE
+REQUIRED_SUBSYSTEMS = RPC_NDR_SAMR RPC_NDR_SRVSVC LIBCLI_COMPOSITE LIBSAMBA3
 # End SUBSYSTEM LIBNET
 #################################
index 5fb825df4d77cd3a8f9955cdc4910827af29bed9..bfe843952c3e2210101fcf4ea5b0414a1dd64773 100644 (file)
@@ -32,4 +32,5 @@ struct libnet_context {
 #include "libnet/libnet_time.h"
 #include "libnet/libnet_rpc.h"
 #include "libnet/libnet_join.h"
+#include "libnet/libnet_vampire.h"
 #include "libnet/libnet_user.h"
diff --git a/source/libnet/libnet_vampire.c b/source/libnet/libnet_vampire.c
new file mode 100644 (file)
index 0000000..daf7bdf
--- /dev/null
@@ -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;
+}
diff --git a/source/libnet/libnet_vampire.h b/source/libnet/libnet_vampire.h
new file mode 100644 (file)
index 0000000..22ac160
--- /dev/null
@@ -0,0 +1,40 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 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 "librpc/gen_ndr/ndr_netlogon.h"
+
+/* struct and enum for doing a remote domain join */
+enum libnet_SamDump_level {
+       LIBNET_SAMDUMP_GENERIC,
+       LIBNET_SAMDUMP_NETLOGON,
+};
+
+union libnet_SamDump {
+       struct {
+               enum libnet_SamDump_level level;
+               char *error_string;
+       } generic;
+
+       struct {
+               enum libnet_SamDump_level level;
+               char *error_string;
+       } netlogon;
+};
+
index d9501b866c0f5acba7033696fa2e5a43e8bb62d7..7bc7183b982144bb7a18ab5ac0f7d0ad33dd6a6a 100644 (file)
@@ -181,17 +181,28 @@ struct ldb_context *secrets_db_connect(TALLOC_CTX *mem_ctx)
 {
        char *path;
        struct ldb_context *ldb;
+       BOOL existed;
+       const char *init_ldif = 
+               "dn: @ATTRIBUTES\n" \
+               "computerName: CASE_INSENSITIVE\n" \
+               "flatname: CASE_INSENSITIVE\n";
 
        path = private_path(mem_ctx, "secrets.ldb");
        if (!path) {
                return NULL;
        }
        
+       existed = file_exists(path);
+       
        ldb = ldb_wrap_connect(mem_ctx, path, 0, NULL);
        talloc_free(path);
        if (!ldb) {
                return NULL;
        }
+       
+       if (!existed) {
+               gendb_add_ldif(ldb, init_ldif);
+       }
 
        return ldb;
 }
index 14b4683b9f3aece5bbfa2ab81363a65c4626095d..f68cf68c8c7c05de72a2a657223b2e05f7360b19 100644 (file)
@@ -8,6 +8,7 @@ OBJ_FILES = \
                utils/net/net_password.o \
                utils/net/net_time.o \
                utils/net/net_join.o \
+               utils/net/net_vampire.o \
                utils/net/net_user.o
 REQUIRED_SUBSYSTEMS = \
                CONFIG \
index 96ae23c7e4bd00d56c44aad2afbf073dba50be90..c7c6f7dec9fc9d4f47ffa1539367cd65132b6dd5 100644 (file)
@@ -105,6 +105,7 @@ static const struct net_functable net_functable[] = {
        {"password", "change password\n", net_password, net_password_usage},
        {"time", "get remote server's time\n", net_time, net_time_usage},
        {"join", "join a domain\n", net_join, net_join_usage},
+       {"samdump", "dump the sam of a domain\n", net_samdump, net_samdump_usage},
        {"user", "manage user accounts\n", net_user, net_user_usage},
        {NULL, NULL, NULL, NULL}
 };
diff --git a/source/utils/net/net_vampire.c b/source/utils/net/net_vampire.c
new file mode 100644 (file)
index 0000000..df2d847
--- /dev/null
@@ -0,0 +1,68 @@
+/* 
+   Samba Unix/Linux SMB client library 
+   Distributed SMB/CIFS Server Management Utility 
+
+   Copyright (C) 2004 Stefan Metzmacher <metze@samba.org>
+   Copyright (C) 2005 Andrew Bartlett <abartlet@samba.org>
+
+   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 "utils/net/net.h"
+#include "libnet/libnet.h"
+#include "librpc/gen_ndr/ndr_samr.h"
+
+int net_samdump(struct net_context *ctx, int argc, const char **argv) 
+{
+       NTSTATUS status;
+       struct libnet_context *libnetctx;
+       union libnet_SamDump r;
+
+       libnetctx = libnet_context_init();
+       if (!libnetctx) {
+               return -1;      
+       }
+       libnetctx->credentials = ctx->credentials;
+
+       /* prepare password change */
+       r.generic.level        = LIBNET_SAMDUMP_GENERIC;
+       r.generic.error_string = NULL;
+
+       /* do the domain join */
+       status = libnet_SamDump(libnetctx, ctx->mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("libnet_SamDump returned %s: %s\n",
+                        nt_errstr(status),
+                        r.generic.error_string));
+               return -1;
+       }
+
+       libnet_context_destroy(&libnetctx);
+
+       return 0;
+}
+
+int net_samdump_usage(struct net_context *ctx, int argc, const char **argv)
+{
+       d_printf("net samdump\n");
+       return 0;       
+}
+
+int net_samdump_help(struct net_context *ctx, int argc, const char **argv)
+{
+       d_printf("Dumps the sam of the domain we are joined to.\n");
+       return 0;       
+}