summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/auth/credentials/credentials_files.c4
-rw-r--r--source4/auth/credentials/credentials_krb5.c27
-rw-r--r--source4/auth/kerberos/kerberos_util.c58
-rw-r--r--source4/include/structs.h1
-rw-r--r--source4/libnet/config.mk1
-rw-r--r--source4/libnet/libnet_samdump_keytab.c144
-rw-r--r--source4/libnet/libnet_vampire.h6
-rw-r--r--source4/utils/net/net_vampire.c67
8 files changed, 264 insertions, 44 deletions
diff --git a/source4/auth/credentials/credentials_files.c b/source4/auth/credentials/credentials_files.c
index 1f7a7cf435..8d84e8cdb5 100644
--- a/source4/auth/credentials/credentials_files.c
+++ b/source4/auth/credentials/credentials_files.c
@@ -301,13 +301,13 @@ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
* (chewing CPU time) from the password */
keytab = ldb_msg_find_string(msgs[0], "krb5Keytab", NULL);
if (keytab) {
- cli_credentials_set_keytab(cred, keytab, CRED_SPECIFIED);
+ cli_credentials_set_keytab_name(cred, keytab, CRED_SPECIFIED);
} else {
keytab = ldb_msg_find_string(msgs[0], "privateKeytab", NULL);
if (keytab) {
keytab = talloc_asprintf(mem_ctx, "FILE:%s", private_path(mem_ctx, keytab));
if (keytab) {
- cli_credentials_set_keytab(cred, keytab, CRED_SPECIFIED);
+ cli_credentials_set_keytab_name(cred, keytab, CRED_SPECIFIED);
}
}
}
diff --git a/source4/auth/credentials/credentials_krb5.c b/source4/auth/credentials/credentials_krb5.c
index 173739e9b8..5f40ca1046 100644
--- a/source4/auth/credentials/credentials_krb5.c
+++ b/source4/auth/credentials/credentials_krb5.c
@@ -398,7 +398,7 @@ int cli_credentials_get_keytab(struct cli_credentials *cred,
return ENOMEM;
}
- ret = create_memory_keytab(mem_ctx, cred, smb_krb5_context, &ktc);
+ ret = smb_krb5_create_memory_keytab(mem_ctx, cred, smb_krb5_context, &ktc);
if (ret) {
talloc_free(mem_ctx);
return ret;
@@ -417,14 +417,13 @@ int cli_credentials_get_keytab(struct cli_credentials *cred,
/* Given the name of a keytab (presumably in the format
* FILE:/etc/krb5.keytab), open it and attach it */
-int cli_credentials_set_keytab(struct cli_credentials *cred,
- const char *keytab_name,
- enum credentials_obtained obtained)
+int cli_credentials_set_keytab_name(struct cli_credentials *cred,
+ const char *keytab_name,
+ enum credentials_obtained obtained)
{
krb5_error_code ret;
struct keytab_container *ktc;
struct smb_krb5_context *smb_krb5_context;
- krb5_keytab keytab;
TALLOC_CTX *mem_ctx;
if (cred->keytab_obtained >= obtained) {
@@ -441,24 +440,12 @@ int cli_credentials_set_keytab(struct cli_credentials *cred,
return ENOMEM;
}
- ret = krb5_kt_resolve(smb_krb5_context->krb5_context, keytab_name, &keytab);
+ ret = smb_krb5_open_keytab(mem_ctx, smb_krb5_context,
+ keytab_name, &ktc);
if (ret) {
- DEBUG(1,("failed to open krb5 keytab: %s\n",
- smb_get_krb5_error_message(smb_krb5_context->krb5_context,
- ret, mem_ctx)));
- talloc_free(mem_ctx);
return ret;
}
- ktc = talloc(mem_ctx, struct keytab_container);
- if (!ktc) {
- talloc_free(mem_ctx);
- return ENOMEM;
- }
-
- ktc->smb_krb5_context = talloc_reference(ktc, smb_krb5_context);
- ktc->keytab = keytab;
-
cred->keytab_obtained = obtained;
talloc_steal(cred, ktc);
@@ -492,7 +479,7 @@ int cli_credentials_update_keytab(struct cli_credentials *cred)
return ret;
}
- ret = update_keytab(mem_ctx, cred, smb_krb5_context, ktc);
+ ret = smb_krb5_update_keytab(mem_ctx, cred, smb_krb5_context, ktc);
talloc_free(mem_ctx);
return ret;
diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c
index a9ea6f9db3..d8c650b098 100644
--- a/source4/auth/kerberos/kerberos_util.c
+++ b/source4/auth/kerberos/kerberos_util.c
@@ -226,6 +226,32 @@ static int free_keytab(void *ptr) {
return 0;
}
+int smb_krb5_open_keytab(TALLOC_CTX *mem_ctx,
+ struct smb_krb5_context *smb_krb5_context,
+ const char *keytab_name, struct keytab_container **ktc)
+{
+ krb5_keytab keytab;
+ int ret;
+ ret = krb5_kt_resolve(smb_krb5_context->krb5_context, keytab_name, &keytab);
+ if (ret) {
+ DEBUG(1,("failed to open krb5 keytab: %s\n",
+ smb_get_krb5_error_message(smb_krb5_context->krb5_context,
+ ret, mem_ctx)));
+ return ret;
+ }
+
+ *ktc = talloc(mem_ctx, struct keytab_container);
+ if (!*ktc) {
+ return ENOMEM;
+ }
+
+ (*ktc)->smb_krb5_context = talloc_reference(*ktc, smb_krb5_context);
+ (*ktc)->keytab = keytab;
+ talloc_set_destructor(*ktc, free_keytab);
+
+ return 0;
+}
+
struct enctypes_container {
struct smb_krb5_context *smb_krb5_context;
krb5_enctype *enctypes;
@@ -574,10 +600,10 @@ static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
return ret;
}
-int update_keytab(TALLOC_CTX *parent_ctx,
- struct cli_credentials *machine_account,
- struct smb_krb5_context *smb_krb5_context,
- struct keytab_container *keytab_container)
+int smb_krb5_update_keytab(TALLOC_CTX *parent_ctx,
+ struct cli_credentials *machine_account,
+ struct smb_krb5_context *smb_krb5_context,
+ struct keytab_container *keytab_container)
{
krb5_error_code ret;
BOOL found_previous;
@@ -604,16 +630,15 @@ int update_keytab(TALLOC_CTX *parent_ctx,
return ret;
}
-int create_memory_keytab(TALLOC_CTX *parent_ctx,
- struct cli_credentials *machine_account,
- struct smb_krb5_context *smb_krb5_context,
- struct keytab_container **keytab_container)
+int smb_krb5_create_memory_keytab(TALLOC_CTX *parent_ctx,
+ struct cli_credentials *machine_account,
+ struct smb_krb5_context *smb_krb5_context,
+ struct keytab_container **keytab_container)
{
krb5_error_code ret;
TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
const char *rand_string;
const char *keytab_name;
- krb5_keytab keytab;
if (!mem_ctx) {
return ENOMEM;
}
@@ -633,23 +658,12 @@ int create_memory_keytab(TALLOC_CTX *parent_ctx,
return ENOMEM;
}
- /* Find the keytab */
- ret = krb5_kt_resolve(smb_krb5_context->krb5_context, keytab_name, &keytab);
+ ret = smb_krb5_open_keytab(mem_ctx, smb_krb5_context, keytab_name, keytab_container);
if (ret) {
- DEBUG(1,("failed to resolve keytab: %s: %s\n",
- keytab_name,
- smb_get_krb5_error_message(smb_krb5_context->krb5_context,
- ret, mem_ctx)));
- talloc_free(mem_ctx);
return ret;
}
- (*keytab_container)->smb_krb5_context = talloc_reference(*keytab_container, smb_krb5_context);
- (*keytab_container)->keytab = keytab;
-
- talloc_set_destructor(*keytab_container, free_keytab);
-
- ret = update_keytab(mem_ctx, machine_account, smb_krb5_context, *keytab_container);
+ ret = smb_krb5_update_keytab(mem_ctx, machine_account, smb_krb5_context, *keytab_container);
if (ret == 0) {
talloc_steal(parent_ctx, *keytab_container);
} else {
diff --git a/source4/include/structs.h b/source4/include/structs.h
index b6ccd0ce19..b652579edd 100644
--- a/source4/include/structs.h
+++ b/source4/include/structs.h
@@ -192,6 +192,7 @@ struct libnet_AddShare;
struct libnet_DelShare;
struct libnet_Lookup;
struct libnet_SamDump;
+struct libnet_SamDump_keytab;
struct libnet_SamSync;
struct libnet_samsync_ldb;
struct net_functable;
diff --git a/source4/libnet/config.mk b/source4/libnet/config.mk
index e998675fcb..fe68a8ef59 100644
--- a/source4/libnet/config.mk
+++ b/source4/libnet/config.mk
@@ -17,6 +17,7 @@ ADD_OBJ_FILES = \
libnet_join.o \
libnet_vampire.o \
libnet_samdump.o \
+ libnet_samdump_keytab.o \
libnet_samsync_ldb.o \
libnet_user.o \
libnet_share.o \
diff --git a/source4/libnet/libnet_samdump_keytab.c b/source4/libnet/libnet_samdump_keytab.c
new file mode 100644
index 0000000000..deaa282801
--- /dev/null
+++ b/source4/libnet/libnet_samdump_keytab.c
@@ -0,0 +1,144 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Extract kerberos keys from a remote SamSync server
+
+ 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"
+#include "system/kerberos.h"
+#include "auth/kerberos/kerberos.h"
+
+static NTSTATUS samdump_keytab_handle_user(TALLOC_CTX *mem_ctx,
+ const char *keytab_name,
+ struct creds_CredentialState *creds,
+ struct netr_DELTA_ENUM *delta)
+{
+ struct netr_DELTA_USER *user = delta->delta_union.user;
+ const char *username = user->account_name.string;
+ struct cli_credentials *credentials;
+ int ret;
+
+ if (!user->nt_password_present) {
+ /* We can't do anything here */
+ return NT_STATUS_OK;
+ }
+
+ credentials = cli_credentials_init(mem_ctx);
+ if (!credentials) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ cli_credentials_set_conf(credentials);
+ cli_credentials_set_username(credentials, username, CRED_SPECIFIED);
+
+ /* We really should consult ldap in the main SamSync code, and
+ * pass a value in here */
+ cli_credentials_set_kvno(credentials, 0);
+ cli_credentials_set_nt_hash(credentials, &user->ntpassword, CRED_SPECIFIED);
+ ret = cli_credentials_set_keytab_name(credentials, keytab_name, CRED_SPECIFIED);
+ if (ret) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ ret = cli_credentials_update_keytab(credentials);
+ if (ret) {
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS libnet_samdump_keytab_fn(TALLOC_CTX *mem_ctx,
+ void *private,
+ struct creds_CredentialState *creds,
+ enum netr_SamDatabaseID database,
+ struct netr_DELTA_ENUM *delta,
+ char **error_string)
+{
+ NTSTATUS nt_status = NT_STATUS_OK;
+ const char *keytab_name = private;
+
+ *error_string = NULL;
+ switch (delta->delta_type) {
+ case NETR_DELTA_USER:
+ {
+ /* not interested in builtin users */
+ if (database == SAM_DATABASE_DOMAIN) {
+ nt_status = samdump_keytab_handle_user(mem_ctx,
+ keytab_name,
+ creds,
+ delta);
+ break;
+ }
+ }
+ default:
+ /* Can't dump them all right now */
+ break;
+ }
+ return nt_status;
+}
+
+static NTSTATUS libnet_SamDump_keytab_netlogon(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_SamDump_keytab *r)
+{
+ NTSTATUS nt_status;
+ struct libnet_SamSync r2;
+
+ r2.error_string = NULL;
+ r2.delta_fn = libnet_samdump_keytab_fn;
+ r2.fn_ctx = r->keytab_name;
+ r2.machine_account = NULL; /* TODO: Create a machine account, fill this in, and the delete it */
+ nt_status = libnet_SamSync_netlogon(ctx, mem_ctx, &r2);
+ r->error_string = r2.error_string;
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ return nt_status;
+}
+
+
+
+static NTSTATUS libnet_SamDump_keytab_generic(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_SamDump_keytab *r)
+{
+ NTSTATUS nt_status;
+ struct libnet_SamDump_keytab r2;
+ r2.level = LIBNET_SAMDUMP_NETLOGON;
+ r2.error_string = NULL;
+ r2.keytab_name = r->keytab_name;
+ nt_status = libnet_SamDump_keytab(ctx, mem_ctx, &r2);
+ r->error_string = r2.error_string;
+
+ return nt_status;
+}
+
+NTSTATUS libnet_SamDump_keytab(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_SamDump_keytab *r)
+{
+ switch (r->level) {
+ case LIBNET_SAMDUMP_GENERIC:
+ return libnet_SamDump_keytab_generic(ctx, mem_ctx, r);
+ case LIBNET_SAMDUMP_NETLOGON:
+ return libnet_SamDump_keytab_netlogon(ctx, mem_ctx, r);
+ }
+
+ return NT_STATUS_INVALID_LEVEL;
+}
diff --git a/source4/libnet/libnet_vampire.h b/source4/libnet/libnet_vampire.h
index 8a588de48c..c8d569a97e 100644
--- a/source4/libnet/libnet_vampire.h
+++ b/source4/libnet/libnet_vampire.h
@@ -43,6 +43,12 @@ struct libnet_SamDump {
char *error_string;
};
+struct libnet_SamDump_keytab {
+ enum libnet_SamDump_level level;
+ char *keytab_name;
+ char *error_string;
+};
+
enum libnet_samsync_ldb_level {
LIBNET_SAMSYNC_LDB_GENERIC,
LIBNET_SAMSYNC_LDB_NETLOGON,
diff --git a/source4/utils/net/net_vampire.c b/source4/utils/net/net_vampire.c
index e898352cfc..75ad175c66 100644
--- a/source4/utils/net/net_vampire.c
+++ b/source4/utils/net/net_vampire.c
@@ -25,11 +25,77 @@
#include "libnet/libnet.h"
#include "librpc/gen_ndr/ndr_samr.h"
+static int net_samdump_keytab_usage(struct net_context *ctx, int argc, const char **argv)
+{
+ d_printf("net samdump keytab <keytab>\n");
+ return 0;
+}
+
+static int net_samdump_keytab_help(struct net_context *ctx, int argc, const char **argv)
+{
+ d_printf("Dumps kerberos keys of a domain into a keytab.\n");
+ return 0;
+}
+
+static int net_samdump_keytab(struct net_context *ctx, int argc, const char **argv)
+{
+ NTSTATUS status;
+ struct libnet_context *libnetctx;
+ struct libnet_SamDump_keytab r;
+
+ switch (argc) {
+ case 0:
+ return net_samdump_keytab_usage(ctx, argc, argv);
+ break;
+ case 1:
+ r.keytab_name = argv[0];
+ break;
+ }
+
+ libnetctx = libnet_context_init(NULL);
+ if (!libnetctx) {
+ return -1;
+ }
+ libnetctx->cred = ctx->credentials;
+
+ r.level = LIBNET_SAMDUMP_GENERIC;
+ r.error_string = NULL;
+
+ status = libnet_SamDump_keytab(libnetctx, ctx->mem_ctx, &r);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("libnet_SamDump returned %s: %s\n",
+ nt_errstr(status),
+ r.error_string));
+ return -1;
+ }
+
+ talloc_free(libnetctx);
+
+ return 0;
+}
+
+/* main function table */
+static const struct net_functable net_samdump_functable[] = {
+ {"keytab", "dump keys into a keytab\n", net_samdump_keytab, net_samdump_keytab_usage},
+ {NULL, NULL, NULL, NULL}
+};
+
int net_samdump(struct net_context *ctx, int argc, const char **argv)
{
NTSTATUS status;
struct libnet_context *libnetctx;
struct libnet_SamDump r;
+ int rc;
+
+ switch (argc) {
+ case 0:
+ break;
+ case 1:
+ default:
+ rc = net_run_function(ctx, argc, argv, net_samdump_functable,
+ net_samdump_usage);
+ return rc;
+ }
libnetctx = libnet_context_init(NULL);
if (!libnetctx) {
@@ -56,6 +122,7 @@ int net_samdump(struct net_context *ctx, int argc, const char **argv)
int net_samdump_usage(struct net_context *ctx, int argc, const char **argv)
{
d_printf("net samdump\n");
+ d_printf("net samdump keytab <keytab>\n");
return 0;
}