The branch, v3-3-test has been updated
       via  ee6e422c0e035aa4779fa718bb6f142827cc2de0 (commit)
      from  e884304206b512a1ffc70b7a4da8db3c6dfd4f11 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-3-test


- Log -----------------------------------------------------------------
commit ee6e422c0e035aa4779fa718bb6f142827cc2de0
Author: Günther Deschner <[EMAIL PROTECTED]>
Date:   Wed Jun 18 12:52:00 2008 +0200

    net_vampire: add code to vampire a SAM database to a keytab file.
    
    Guenther

-----------------------------------------------------------------------

Summary of changes:
 source/Makefile.in                    |    1 +
 source/libnet/libnet_samsync.c        |    3 +
 source/libnet/libnet_samsync.h        |    8 +-
 source/libnet/libnet_samsync_keytab.c |  319 +++++++++++++++++++++++++++++++++
 source/utils/net_proto.h              |    9 +
 source/utils/net_rpc.c                |    9 +
 source/utils/net_rpc_samsync.c        |   77 ++++++++-
 7 files changed, 423 insertions(+), 3 deletions(-)
 create mode 100644 source/libnet/libnet_samsync_keytab.c


Changeset truncated at 500 lines:

diff --git a/source/Makefile.in b/source/Makefile.in
index 67d4ed1..4f680cc 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -896,6 +896,7 @@ LIBNET_OBJ = libnet/libnet_join.o \
             libnet/libnet_samsync_ldif.o \
             libnet/libnet_samsync_passdb.o \
             libnet/libnet_samsync_display.o \
+            libnet/libnet_samsync_keytab.o \
             librpc/gen_ndr/ndr_libnet_join.o
 
 NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_help.o \
diff --git a/source/libnet/libnet_samsync.c b/source/libnet/libnet_samsync.c
index e170acc..dcf5f9c 100644
--- a/source/libnet/libnet_samsync.c
+++ b/source/libnet/libnet_samsync.c
@@ -254,6 +254,9 @@ static const char *samsync_debug_str(TALLOC_CTX *mem_ctx,
                case NET_SAMSYNC_MODE_FETCH_LDIF:
                        action = "Fetching (to ldif)";
                        break;
+               case NET_SAMSYNC_MODE_FETCH_KEYTAB:
+                       action = "Fetching (to keytab)";
+                       break;
                default:
                        action = "Unknown";
                        break;
diff --git a/source/libnet/libnet_samsync.h b/source/libnet/libnet_samsync.h
index de0225c..8559043 100644
--- a/source/libnet/libnet_samsync.h
+++ b/source/libnet/libnet_samsync.h
@@ -21,7 +21,8 @@
 enum net_samsync_mode {
        NET_SAMSYNC_MODE_FETCH_PASSDB = 0,
        NET_SAMSYNC_MODE_FETCH_LDIF = 1,
-       NET_SAMSYNC_MODE_DUMP = 2
+       NET_SAMSYNC_MODE_FETCH_KEYTAB = 2,
+       NET_SAMSYNC_MODE_DUMP = 3
 };
 
 struct samsync_context;
@@ -65,3 +66,8 @@ NTSTATUS display_sam_entries(TALLOC_CTX *mem_ctx,
                             struct netr_DELTA_ENUM_ARRAY *r,
                             NTSTATUS status,
                             struct samsync_context *ctx);
+NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx,
+                                 enum netr_SamDatabaseID database_id,
+                                 struct netr_DELTA_ENUM_ARRAY *r,
+                                 NTSTATUS status,
+                                 struct samsync_context *ctx);
diff --git a/source/libnet/libnet_samsync_keytab.c 
b/source/libnet/libnet_samsync_keytab.c
new file mode 100644
index 0000000..2208a71
--- /dev/null
+++ b/source/libnet/libnet_samsync_keytab.c
@@ -0,0 +1,319 @@
+/*
+   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 "utils/net.h"
+
+#if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC)
+
+/****************************************************************
+****************************************************************/
+
+struct samsync_keytab_entry {
+       const char *name;
+       const char *principal;
+       DATA_BLOB password;
+       uint32_t kvno;
+};
+
+struct samsync_keytab_context {
+       krb5_context context;
+       krb5_keytab keytab;
+       const char *keytab_name;
+       ADS_STRUCT *ads;
+       const char *dns_domain_name;
+       uint8_t zero_buf[16];
+       uint32_t count;
+       struct samsync_keytab_entry *entries;
+};
+
+/****************************************************************
+****************************************************************/
+
+static int keytab_close(struct samsync_keytab_context *ctx)
+{
+       if (!ctx) {
+               return 0;
+       }
+
+       if (ctx->keytab && ctx->context) {
+               krb5_kt_close(ctx->context, ctx->keytab);
+       }
+
+       if (ctx->context) {
+               krb5_free_context(ctx->context);
+       }
+
+       if (ctx->ads) {
+               ads_destroy(&ctx->ads);
+       }
+
+       TALLOC_FREE(ctx);
+
+       return 0;
+}
+
+/****************************************************************
+****************************************************************/
+
+static krb5_error_code keytab_init(TALLOC_CTX *mem_ctx,
+                                  const char *keytab_name,
+                                  struct samsync_keytab_context **ctx)
+{
+       krb5_error_code ret = 0;
+       krb5_context context = NULL;
+       krb5_keytab keytab = NULL;
+       const char *keytab_string = NULL;
+
+       struct samsync_keytab_context *r;
+
+       r = TALLOC_ZERO_P(mem_ctx, struct samsync_keytab_context);
+       if (!r) {
+               return ENOMEM;
+       }
+
+       talloc_set_destructor(r, keytab_close);
+
+       initialize_krb5_error_table();
+       ret = krb5_init_context(&context);
+       if (ret) {
+               DEBUG(1,("keytab_init: could not krb5_init_context: %s\n",
+                       error_message(ret)));
+               return ret;
+       }
+
+       ret = smb_krb5_open_keytab(context, keytab_name, true, &keytab);
+       if (ret) {
+               DEBUG(1,("keytab_init: smb_krb5_open_keytab failed (%s)\n",
+                       error_message(ret)));
+               krb5_free_context(context);
+               return ret;
+       }
+
+       ret = smb_krb5_keytab_name(mem_ctx, context, keytab, &keytab_string);
+       if (ret) {
+               krb5_kt_close(context, keytab);
+               krb5_free_context(context);
+               return ret;
+       }
+
+       r->context = context;
+       r->keytab = keytab;
+       r->keytab_name = keytab_string;
+
+       *ctx = r;
+
+       return 0;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS keytab_ad_connect(TALLOC_CTX *mem_ctx,
+                                 const char *domain_name,
+                                 const char *username,
+                                 const char *password,
+                                 struct samsync_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 krb5_error_code keytab_add(struct samsync_keytab_context *ctx)
+{
+       krb5_error_code ret = 0;
+       krb5_enctype enctypes[2] = { ENCTYPE_ARCFOUR_HMAC, 0 };
+       int i;
+
+       for (i=0; i<ctx->count; i++) {
+
+               struct samsync_keytab_entry *entry = &ctx->entries[i];
+               krb5_data password;
+               krb5_kvno kvno;
+
+               kvno = ads_get_kvno(ctx->ads, entry->name);
+
+               password.data = (char *)entry->password.data;
+               password.length = entry->password.length;
+
+               ret = smb_krb5_kt_add_entry(ctx->context,
+                                           ctx->keytab,
+                                           kvno,
+                                           entry->principal,
+                                           enctypes,
+                                           password,
+                                           true);
+               if (ret) {
+                       DEBUG(1,("keytab_add: Failed to add entry to keytab 
file\n"));
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS fetch_sam_entry_keytab(TALLOC_CTX *mem_ctx,
+                                      enum netr_SamDatabaseID database_id,
+                                      uint32_t rid,
+                                      struct netr_DELTA_USER *r,
+                                      NTSTATUS status,
+                                      struct samsync_keytab_context *ctx)
+{
+       uchar nt_passwd[16];
+       struct samsync_keytab_entry *entry;
+
+       if (memcmp(r->ntpassword.hash, ctx->zero_buf, 16) == 0) {
+               return NT_STATUS_OK;
+       }
+
+       entry = TALLOC_ZERO_P(mem_ctx, struct samsync_keytab_entry);
+       NT_STATUS_HAVE_NO_MEMORY(entry);
+
+       sam_pwd_hash(rid, r->ntpassword.hash, nt_passwd, 0);
+
+       entry->name = talloc_strdup(mem_ctx, r->account_name.string);
+       entry->principal = talloc_asprintf(mem_ctx, "[EMAIL PROTECTED]",
+                                          r->account_name.string,
+                                          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);
+
+       ADD_TO_ARRAY(mem_ctx, struct samsync_keytab_entry, *entry,
+                    &ctx->entries, &ctx->count);
+
+       return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx,
+                                 enum netr_SamDatabaseID database_id,
+                                 struct netr_DELTA_ENUM_ARRAY *r,
+                                 NTSTATUS result,
+                                 struct samsync_context *ctx)
+{
+       NTSTATUS status = NT_STATUS_OK;
+       krb5_error_code ret = 0;
+       struct samsync_keytab_context *keytab_ctx = NULL;
+       int i;
+
+       ret = keytab_init(mem_ctx, ctx->output_filename, &keytab_ctx);
+       if (ret) {
+               status = krb5_to_nt_status(ret);
+               goto out;
+       }
+
+       status = keytab_ad_connect(mem_ctx,
+                                  ctx->domain_name,
+                                  ctx->username,
+                                  ctx->password,
+                                  keytab_ctx);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+
+       for (i = 0; i < r->num_deltas; i++) {
+
+               if (r->delta_enum[i].delta_type != NETR_DELTA_USER) {
+                       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,
+                                               result,
+                                               keytab_ctx);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto out;
+               }
+       }
+
+       ret = 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);
+ out:
+       TALLOC_FREE(keytab_ctx);
+
+       return status;
+}
+
+#else
+
+NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx,
+                                 enum netr_SamDatabaseID database_id,
+                                 struct netr_DELTA_ENUM_ARRAY *r,
+                                 NTSTATUS result,
+                                 struct samsync_context *ctx)
+{
+       return NT_STATUS_NOT_SUPPORTED;
+}
+
+#endif /* defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) */
diff --git a/source/utils/net_proto.h b/source/utils/net_proto.h
index a370d3d..10b1e47 100644
--- a/source/utils/net_proto.h
+++ b/source/utils/net_proto.h
@@ -368,6 +368,15 @@ NTSTATUS rpc_vampire_ldif_internals(struct net_context *c,
                                    TALLOC_CTX *mem_ctx,
                                    int argc,
                                    const char **argv);
+NTSTATUS rpc_vampire_keytab_internals(struct net_context *c,
+                                     const DOM_SID *domain_sid,
+                                     const char *domain_name,
+                                     struct cli_state *cli,
+                                     struct rpc_pipe_client *pipe_hnd,
+                                     TALLOC_CTX *mem_ctx,
+                                     int argc,
+                                     const char **argv);
+int rpc_vampire_keytab(struct net_context *c, int argc, const char **argv);
 
 /* The following definitions come from utils/net_rpc_service.c  */
 
diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c
index 6a7c638..19566bd 100644
--- a/source/utils/net_rpc.c
+++ b/source/utils/net_rpc.c
@@ -6818,6 +6818,15 @@ static int rpc_vampire(struct net_context *c, int argc, 
const char **argv)
                        "net rpc vampire ldif\n"
                        "    Dump remote SAM database to LDIF file or stdout"
                },
+               {
+                       "keytab",
+                       rpc_vampire_keytab,
+                       NET_TRANSPORT_RPC,
+                       "Dump remote SAM database to Kerberos Keytab",
+                       "net rpc vampire keytab\n"
+                       "    Dump remote SAM database to Kerberos keytab file"
+               },
+
                {NULL, NULL, 0, NULL, NULL}
        };
 
diff --git a/source/utils/net_rpc_samsync.c b/source/utils/net_rpc_samsync.c
index c941338..e4aa343 100644
--- a/source/utils/net_rpc_samsync.c
+++ b/source/utils/net_rpc_samsync.c
@@ -73,11 +73,13 @@ NTSTATUS rpc_samdump_internals(struct net_context *c,
 
 int rpc_vampire_usage(struct net_context *c, int argc, const char **argv)
 {
-       d_printf("net rpc vampire [ldif [<ldif-filename>] [options]\n"
+       d_printf("net rpc vampire ([ldif [<ldif-filename>] | [keytab] 
[<keytab-filename]) [options]\n"
                 "\t to pull accounts from a remote PDC where we are a BDC\n"
                 "\t\t no args puts accounts in local passdb from smb.conf\n"
                 "\t\t ldif - put accounts in ldif format (file defaults to "
-                "/tmp/tmp.ldif\n");
+                "/tmp/tmp.ldif)\n"
+                "\t\t keytab - put account passwords in krb5 keytab (defaults "
+                "to system keytab)\n");
 
        net_common_flags_usage(c, argc, argv);
        return -1;
@@ -226,3 +228,74 @@ int rpc_vampire_ldif(struct net_context *c, int argc, 
const char **argv)
        return run_rpc_command(c, NULL, PI_NETLOGON, 0, 
rpc_vampire_ldif_internals,
                               argc, argv);
 }
+
+
+NTSTATUS rpc_vampire_keytab_internals(struct net_context *c,
+                                     const DOM_SID *domain_sid,
+                                     const char *domain_name,
+                                     struct cli_state *cli,
+                                     struct rpc_pipe_client *pipe_hnd,
+                                     TALLOC_CTX *mem_ctx,
+                                     int argc,
+                                     const char **argv)
+{
+       NTSTATUS status;
+       struct samsync_context *ctx = NULL;
+
+       status = libnet_samsync_init_context(mem_ctx,
+                                            domain_sid,
+                                            &ctx);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (argc >= 1) {
+               ctx->output_filename = argv[0];
+       }
+
+       ctx->mode               = NET_SAMSYNC_MODE_FETCH_KEYTAB;
+       ctx->cli                = pipe_hnd;
+       ctx->delta_fn           = fetch_sam_entries_keytab;
+       ctx->domain_name        = domain_name;
+       ctx->username           = c->opt_user_name;
+       ctx->password           = c->opt_password;
+
+       /* fetch domain */
+       status = libnet_samsync(SAM_DATABASE_DOMAIN, ctx);
+
+       if (!NT_STATUS_IS_OK(status) && ctx->error_message) {
+               d_fprintf(stderr, "%s\n", ctx->error_message);
+               goto out;
+       }
+
+       if (ctx->result_message) {
+               d_fprintf(stdout, "%s\n", ctx->result_message);
+       }
+
+ out:
+       TALLOC_FREE(ctx);
+
+       return status;
+}
+
+/**
+ * Basic function for 'net rpc vampire keytab'
+ *
+ * @param c    A net_context structure
+ * @param argc  Standard main() style argc
+ * @param argc  Standard main() style argv.  Initial components are already
+ *              stripped
+ **/
+
+int rpc_vampire_keytab(struct net_context *c, int argc, const char **argv)
+{
+       if (c->display_usage) {


-- 
Samba Shared Repository

Reply via email to