diff options
-rw-r--r-- | source4/auth/credentials/credentials_files.c | 4 | ||||
-rw-r--r-- | source4/auth/credentials/credentials_krb5.c | 27 | ||||
-rw-r--r-- | source4/auth/kerberos/kerberos_util.c | 58 | ||||
-rw-r--r-- | source4/include/structs.h | 1 | ||||
-rw-r--r-- | source4/libnet/config.mk | 1 | ||||
-rw-r--r-- | source4/libnet/libnet_samdump_keytab.c | 144 | ||||
-rw-r--r-- | source4/libnet/libnet_vampire.h | 6 | ||||
-rw-r--r-- | source4/utils/net/net_vampire.c | 67 |
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; } |