diff options
-rw-r--r-- | source4/auth/kerberos/config.mk | 3 | ||||
-rw-r--r-- | source4/auth/kerberos/keytab_copy.c | 146 | ||||
-rw-r--r-- | source4/kdc/config.mk | 16 | ||||
-rw-r--r-- | source4/libnet/config.mk | 4 | ||||
-rw-r--r-- | source4/libnet/libnet.h | 1 | ||||
-rw-r--r-- | source4/libnet/libnet_export_keytab.c | 54 | ||||
-rw-r--r-- | source4/libnet/libnet_export_keytab.h | 28 | ||||
-rw-r--r-- | source4/utils/net/config.mk | 3 | ||||
-rw-r--r-- | source4/utils/net/net.c | 4 | ||||
-rw-r--r-- | source4/utils/net/net_export_keytab.c | 110 |
10 files changed, 361 insertions, 8 deletions
diff --git a/source4/auth/kerberos/config.mk b/source4/auth/kerberos/config.mk index 822bf398a7..609b036b64 100644 --- a/source4/auth/kerberos/config.mk +++ b/source4/auth/kerberos/config.mk @@ -12,7 +12,8 @@ KERBEROS_OBJ_FILES = $(addprefix $(authsrcdir)/kerberos/, \ kerberos_heimdal.o \ kerberos_pac.o \ gssapi_parse.o \ - krb5_init_context.o) + krb5_init_context.o \ + keytab_copy.o) $(eval $(call proto_header_template,$(authsrcdir)/kerberos/proto.h,$(KERBEROS_OBJ_FILES:.o=.c))) diff --git a/source4/auth/kerberos/keytab_copy.c b/source4/auth/kerberos/keytab_copy.c new file mode 100644 index 0000000000..ba4ea2bf39 --- /dev/null +++ b/source4/auth/kerberos/keytab_copy.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "includes.h" +#include "system/kerberos.h" +#include "auth/kerberos/kerberos.h" + +static const krb5_boolean verbose_flag = FALSE; + +static krb5_boolean +compare_keyblock(const krb5_keyblock *a, const krb5_keyblock *b) +{ + if(a->keytype != b->keytype || + a->keyvalue.length != b->keyvalue.length || + memcmp(a->keyvalue.data, b->keyvalue.data, a->keyvalue.length) != 0) + return FALSE; + return TRUE; +} + +krb5_error_code kt_copy (krb5_context context, const char *from, const char *to) +{ + krb5_error_code ret; + krb5_keytab src_keytab, dst_keytab; + krb5_kt_cursor cursor; + krb5_keytab_entry entry, dummy; + + ret = krb5_kt_resolve (context, from, &src_keytab); + if (ret) { + krb5_warn (context, ret, "resolving src keytab `%s'", from); + return 1; + } + + ret = krb5_kt_resolve (context, to, &dst_keytab); + if (ret) { + krb5_kt_close (context, src_keytab); + krb5_warn (context, ret, "resolving dst keytab `%s'", to); + return 1; + } + + ret = krb5_kt_start_seq_get (context, src_keytab, &cursor); + if (ret) { + krb5_warn (context, ret, "krb5_kt_start_seq_get %s", from); + goto out; + } + + if (verbose_flag) + fprintf(stderr, "copying %s to %s\n", from, to); + + while((ret = krb5_kt_next_entry(context, src_keytab, + &entry, &cursor)) == 0) { + char *name_str; + char *etype_str; + ret = krb5_unparse_name (context, entry.principal, &name_str); + if(ret) { + krb5_warn(context, ret, "krb5_unparse_name"); + name_str = NULL; /* XXX */ + } + ret = krb5_enctype_to_string(context, entry.keyblock.keytype, &etype_str); + if(ret) { + krb5_warn(context, ret, "krb5_enctype_to_string"); + etype_str = NULL; /* XXX */ + } + ret = krb5_kt_get_entry(context, dst_keytab, + entry.principal, + entry.vno, + entry.keyblock.keytype, + &dummy); + if(ret == 0) { + /* this entry is already in the new keytab, so no need to + copy it; if the keyblocks are not the same, something + is weird, so complain about that */ + if(!compare_keyblock(&entry.keyblock, &dummy.keyblock)) { + krb5_warnx(context, "entry with different keyvalue " + "already exists for %s, keytype %s, kvno %d", + name_str, etype_str, entry.vno); + } + krb5_kt_free_entry(context, &dummy); + krb5_kt_free_entry (context, &entry); + free(name_str); + free(etype_str); + continue; + } else if(ret != KRB5_KT_NOTFOUND) { + krb5_warn (context, ret, "%s: fetching %s/%s/%u", + to, name_str, etype_str, entry.vno); + krb5_kt_free_entry (context, &entry); + free(name_str); + free(etype_str); + break; + } + if (verbose_flag) + fprintf (stderr, "copying %s, keytype %s, kvno %d\n", name_str, + etype_str, entry.vno); + ret = krb5_kt_add_entry (context, dst_keytab, &entry); + krb5_kt_free_entry (context, &entry); + if (ret) { + krb5_warn (context, ret, "%s: adding %s/%s/%u", + to, name_str, etype_str, entry.vno); + free(name_str); + free(etype_str); + break; + } + free(name_str); + free(etype_str); + } + krb5_kt_end_seq_get (context, src_keytab, &cursor); + + out: + krb5_kt_close (context, src_keytab); + krb5_kt_close (context, dst_keytab); + if (ret == KRB5_KT_END) { + return 0; + } else if (ret == 0) { + return EINVAL; + } + return ret; +} diff --git a/source4/kdc/config.mk b/source4/kdc/config.mk index 03fa2db295..56199d6364 100644 --- a/source4/kdc/config.mk +++ b/source4/kdc/config.mk @@ -6,7 +6,7 @@ INIT_FUNCTION = server_service_kdc_init SUBSYSTEM = service PRIVATE_DEPENDENCIES = \ - HEIMDAL_KDC HDB_SAMBA4 LIBSAMBA-HOSTCONFIG + HEIMDAL_KDC HDB_SAMBA4 PAC_GLUE LIBSAMBA-HOSTCONFIG # End SUBSYSTEM KDC ####################### @@ -22,5 +22,17 @@ PRIVATE_DEPENDENCIES = \ # End SUBSYSTEM KDC ####################### -HDB_SAMBA4_OBJ_FILES = $(addprefix $(kdcsrcdir)/, hdb-samba4.o pac-glue.o) +HDB_SAMBA4_OBJ_FILES = $(addprefix $(kdcsrcdir)/, hdb-samba4.o) + +####################### +# Start SUBSYSTEM KDC +[SUBSYSTEM::PAC_GLUE] +CFLAGS = -Iheimdal/kdc -Iheimdal/lib/hdb +PRIVATE_DEPENDENCIES = \ + LIBLDB auth_sam auth_sam_reply CREDENTIALS \ + HEIMDAL_HDB LIBSAMBA-HOSTCONFIG +# End SUBSYSTEM KDC +####################### + +PAC_GLUE_OBJ_FILES = $(addprefix $(kdcsrcdir)/, pac-glue.o) $(eval $(call proto_header_template,$(kdcsrcdir)/pac_glue.h,$(HDB_SAMBA4_OBJ_FILES:.o=.c))) diff --git a/source4/libnet/config.mk b/source4/libnet/config.mk index 07d5434ebf..eede8c871d 100644 --- a/source4/libnet/config.mk +++ b/source4/libnet/config.mk @@ -1,5 +1,5 @@ [SUBSYSTEM::LIBSAMBA-NET] -PUBLIC_DEPENDENCIES = CREDENTIALS dcerpc dcerpc_samr RPC_NDR_LSA RPC_NDR_SRVSVC RPC_NDR_DRSUAPI LIBCLI_COMPOSITE LIBCLI_RESOLVE LIBCLI_FINDDCS LIBCLI_CLDAP LIBCLI_FINDDCS gensec_schannel LIBCLI_AUTH LIBNDR SMBPASSWD PROVISION LIBCLI_SAMSYNC +PUBLIC_DEPENDENCIES = CREDENTIALS dcerpc dcerpc_samr RPC_NDR_LSA RPC_NDR_SRVSVC RPC_NDR_DRSUAPI LIBCLI_COMPOSITE LIBCLI_RESOLVE LIBCLI_FINDDCS LIBCLI_CLDAP LIBCLI_FINDDCS gensec_schannel LIBCLI_AUTH LIBNDR SMBPASSWD PROVISION LIBCLI_SAMSYNC HDB_SAMBA4 LIBSAMBA-NET_OBJ_FILES = $(addprefix $(libnetsrcdir)/, \ libnet.o libnet_passwd.o libnet_time.o libnet_rpc.o \ @@ -7,7 +7,7 @@ LIBSAMBA-NET_OBJ_FILES = $(addprefix $(libnetsrcdir)/, \ libnet_vampire.o libnet_samdump.o libnet_samdump_keytab.o \ libnet_samsync_ldb.o libnet_user.o libnet_group.o libnet_share.o \ libnet_lookup.o libnet_domain.o userinfo.o groupinfo.o userman.o \ - groupman.o prereq_domain.o libnet_samsync.o) + groupman.o prereq_domain.o libnet_samsync.o libnet_export_keytab.o) $(eval $(call proto_header_template,$(libnetsrcdir)/libnet_proto.h,$(LIBSAMBA-NET_OBJ_FILES:.o=.c))) diff --git a/source4/libnet/libnet.h b/source4/libnet/libnet.h index 543a131806..9964a3f526 100644 --- a/source4/libnet/libnet.h +++ b/source4/libnet/libnet.h @@ -75,4 +75,5 @@ struct libnet_context { #include "libnet/libnet_share.h" #include "libnet/libnet_lookup.h" #include "libnet/libnet_domain.h" +#include "libnet/libnet_export_keytab.h" #include "libnet/libnet_proto.h" diff --git a/source4/libnet/libnet_export_keytab.c b/source4/libnet/libnet_export_keytab.c new file mode 100644 index 0000000000..43fd0aa30e --- /dev/null +++ b/source4/libnet/libnet_export_keytab.c @@ -0,0 +1,54 @@ +#include "includes.h" +#include "system/kerberos.h" +#include "auth/kerberos/kerberos.h" +#include <hdb.h> +#include "kdc/hdb-samba4.h" +#include "auth/kerberos/keytab_copy.h" +#include "libnet/libnet.h" + +NTSTATUS libnet_export_keytab(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_export_keytab *r) +{ + krb5_error_code ret; + struct smb_krb5_context *smb_krb5_context; + const char *from_keytab; + + /* Register hdb-samba4 hooks for use as a keytab */ + + struct hdb_samba4_context *hdb_samba4_context = talloc(mem_ctx, struct hdb_samba4_context); + if (!hdb_samba4_context) { + return NT_STATUS_NO_MEMORY; + } + + hdb_samba4_context->ev_ctx = ctx->event_ctx; + hdb_samba4_context->lp_ctx = ctx->lp_ctx; + + from_keytab = talloc_asprintf(hdb_samba4_context, "HDB:samba4&%p", hdb_samba4_context); + if (!from_keytab) { + return NT_STATUS_NO_MEMORY; + } + + ret = smb_krb5_init_context(ctx, ctx->event_ctx, ctx->lp_ctx, &smb_krb5_context); + if (ret) { + return NT_STATUS_NO_MEMORY; + } + + ret = krb5_plugin_register(smb_krb5_context->krb5_context, + PLUGIN_TYPE_DATA, "hdb", + &hdb_samba4); + if(ret) { + return NT_STATUS_NO_MEMORY; + } + + ret = krb5_kt_register(smb_krb5_context->krb5_context, &hdb_kt_ops); + if(ret) { + return NT_STATUS_NO_MEMORY; + } + + ret = kt_copy(smb_krb5_context->krb5_context, from_keytab, r->in.keytab_name); + if(ret) { + r->out.error_string = smb_get_krb5_error_message(smb_krb5_context->krb5_context, + ret, mem_ctx); + return NT_STATUS_UNSUCCESSFUL; + } + return NT_STATUS_OK; +} diff --git a/source4/libnet/libnet_export_keytab.h b/source4/libnet/libnet_export_keytab.h new file mode 100644 index 0000000000..194f8907a3 --- /dev/null +++ b/source4/libnet/libnet_export_keytab.h @@ -0,0 +1,28 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009 + + 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/>. +*/ + +struct libnet_export_keytab { + struct { + const char *keytab_name; + } in; + struct { + const char *error_string; + } out; +}; + diff --git a/source4/utils/net/config.mk b/source4/utils/net/config.mk index b2f0fcf6b1..ff8cb2c526 100644 --- a/source4/utils/net/config.mk +++ b/source4/utils/net/config.mk @@ -21,7 +21,8 @@ net_OBJ_FILES = $(addprefix $(utilssrcdir)/net/, \ net_time.o \ net_join.o \ net_vampire.o \ - net_user.o) + net_user.o \ + net_export_keytab.o) $(eval $(call proto_header_template,$(utilssrcdir)/net/net_proto.h,$(net_OBJ_FILES:.o=.c))) diff --git a/source4/utils/net/net.c b/source4/utils/net/net.c index d934403ade..a96c672dfd 100644 --- a/source4/utils/net/net.c +++ b/source4/utils/net/net.c @@ -104,11 +104,11 @@ static const struct net_functable net_functable[] = { {"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}, + {"export", "dump the sam of this domain\n", net_export, net_export_usage}, {"vampire", "join and syncronise an AD domain onto the local server\n", net_vampire, net_vampire_usage}, {"samsync", "synchronise into the local ldb the sam of an NT4 domain\n", net_samsync_ldb, net_samsync_ldb_usage}, {"user", "manage user accounts\n", net_user, net_user_usage}, - {"machinepw", "Get a machine password out of our SAM\n", net_machinepw, - net_machinepw_usage}, + {"machinepw", "Get a machine password out of our SAM\n", net_machinepw, net_machinepw_usage}, {NULL, NULL, NULL, NULL} }; diff --git a/source4/utils/net/net_export_keytab.c b/source4/utils/net/net_export_keytab.c new file mode 100644 index 0000000000..7f13278a9e --- /dev/null +++ b/source4/utils/net/net_export_keytab.c @@ -0,0 +1,110 @@ +/* + 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 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/net.h" +#include "libnet/libnet.h" +#include "param/param.h" + +static int net_export_keytab_usage(struct net_context *ctx, int argc, const char **argv) +{ + d_printf("net export keytab <keytab>\n"); + return 0; +} + +static int net_export_keytab_help(struct net_context *ctx, int argc, const char **argv) +{ + d_printf("Dumps kerberos keys of the domain into a keytab.\n"); + return 0; +} + +static int net_export_keytab(struct net_context *ctx, int argc, const char **argv) +{ + NTSTATUS status; + struct libnet_context *libnetctx; + struct libnet_export_keytab r; + + switch (argc) { + case 0: + return net_export_keytab_usage(ctx, argc, argv); + break; + case 1: + r.in.keytab_name = argv[0]; + break; + } + + libnetctx = libnet_context_init(ctx->event_ctx, ctx->lp_ctx); + if (!libnetctx) { + return -1; + } + libnetctx->cred = ctx->credentials; + + r.out.error_string = NULL; + + status = libnet_export_keytab(libnetctx, ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("libnet_export_keytab returned %s: %s\n", + nt_errstr(status), + r.out.error_string)); + return -1; + } + + talloc_free(libnetctx); + + return 0; +} + +/* main function table */ +static const struct net_functable net_export_functable[] = { + {"keytab", "dump keys into a keytab\n", net_export_keytab, net_export_keytab_usage}, + {NULL, NULL, NULL, NULL} +}; + +int net_export(struct net_context *ctx, int argc, const char **argv) +{ + int rc; + + switch (argc) { + case 0: + rc = net_export_usage(ctx, argc, argv); + return rc; + case 1: + default: + rc = net_run_function(ctx, argc, argv, net_export_functable, + net_export_usage); + return rc; + } + + return 0; +} + +int net_export_usage(struct net_context *ctx, int argc, const char **argv) +{ + d_printf("net export keytab <keytab>\n"); + return 0; +} + +int net_export_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; +} + |