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;	  }  | 
