From d100b4410ab933e21b4f3390f1b2f27d4e872442 Mon Sep 17 00:00:00 2001 From: Sam Hartman Date: Wed, 15 Sep 2010 17:13:41 +0000 Subject: [PATCH] kinit: add KDB keytab support This implements http://k5wiki.kerberos.org/Projects/What_does_God_need_with_a_password. If the KDB keytab is selected by command line options, then kinit will register the KDB keytab and open the database. This permits an administrator to obtain tickets as a user without knowing that user's password. As a result kinit links against libkadm5srv and libkdb5. Discussion is ongoing about whether this is desirable or about whether two versions of kinit are required. ticket: 6779 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24316 dc483132-0cff-0310-8789-dd5450dbe970 --- src/clients/kinit/Makefile.in | 6 +-- src/clients/kinit/extern.h | 7 ++++ src/clients/kinit/kinit.M | 8 +++- src/clients/kinit/kinit.c | 13 ++++++- src/clients/kinit/kinit_kdb.c | 70 +++++++++++++++++++++++++++++++++++ src/tests/t_general.py | 5 +++ 6 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 src/clients/kinit/extern.h create mode 100644 src/clients/kinit/kinit_kdb.c diff --git a/src/clients/kinit/Makefile.in b/src/clients/kinit/Makefile.in index 278794120..d60b1c7ae 100644 --- a/src/clients/kinit/Makefile.in +++ b/src/clients/kinit/Makefile.in @@ -5,7 +5,7 @@ DEFS= PROG_LIBPATH=-L$(TOPLIBD) PROG_RPATH=$(KRB5_LIBDIR) -SRCS=kinit.c +SRCS=kinit.c kinit_kdb.c ##WIN32##LOCALINCLUDES=-I$(BUILDTOP)\util\windows ##WIN32##DEFINES=-DGETOPT_LONG @@ -23,8 +23,8 @@ SRCS=kinit.c all-unix:: kinit ##WIN32##all-windows:: $(KINIT) -kinit: kinit.o $(KRB5_BASE_DEPLIBS) - $(CC_LINK) -o $@ kinit.o $(KRB5_BASE_LIBS) +kinit: kinit.o kinit_kdb.o $(KRB5_BASE_DEPLIBS) $(KADMSRV_DEPLIBS) + $(CC_LINK) -o $@ kinit.o kinit_kdb.o $(KADMSRV_LIBS) $(KRB5_BASE_LIBS) ##WIN32##$(KINIT): $(OUTPRE)kinit.obj $(BUILDTOP)\util\windows\$(OUTPRE)getopt.lib $(KLIB) $(CLIB) $(EXERES) ##WIN32## link $(EXE_LINKOPTS) -out:$@ $** advapi32.lib diff --git a/src/clients/kinit/extern.h b/src/clients/kinit/extern.h new file mode 100644 index 000000000..bdb962cec --- /dev/null +++ b/src/clients/kinit/extern.h @@ -0,0 +1,7 @@ +#ifndef _KINIT_EXTERN_H +#define _KINIT_EXTERN_H +krb5_error_code +kinit_kdb_init (krb5_context *pcontext, + char *realm); + +#endif diff --git a/src/clients/kinit/kinit.M b/src/clients/kinit/kinit.M index 1d434c0fb..80af95bbd 100644 --- a/src/clients/kinit/kinit.M +++ b/src/clients/kinit/kinit.M @@ -131,13 +131,17 @@ ticket cannot be renewed, even if the ticket is still within its renewable life. .TP \fB\-k\fP [\fB\-t\fP \fIkeytab_file\fP] -requests a host ticket, obtained from a key in the local host's +requests a ticket, obtained from a key in the local host's .I keytab file. The name and location of the keytab file may be specified with the .B \-t .I keytab_file -option; otherwise the default name and location will be used. +option; otherwise the default name and location will be used. By default a host ticket is requested but any principal may be specified. On a KDC, the special keytab location +.B KDB: +can be used to indicate that kinit should open the KDC database and +look up the key directly. This permits an administrator to obtain +tickets as any principal that supports password-based authentication. .TP \fB-n\fP Requests anonymous processing. Two types of anonymous principals are diff --git a/src/clients/kinit/kinit.c b/src/clients/kinit/kinit.c index 8eb059d3a..dca911aaa 100644 --- a/src/clients/kinit/kinit.c +++ b/src/clients/kinit/kinit.c @@ -31,6 +31,7 @@ #include "autoconf.h" #include "k5-platform.h" /* for asprintf */ #include +#include "extern.h" #include #include #include @@ -447,7 +448,7 @@ k5_begin(opts, k5) com_err(progname, code, "while initializing Kerberos 5 library"); return 0; } - errctx = k5->ctx; +errctx = k5->ctx; if (opts->k5_cache_name) { code = krb5_cc_resolve(k5->ctx, opts->k5_cache_name, &k5->cc); @@ -649,6 +650,16 @@ k5_kinit(opts, k5) if ((opts->action == INIT_KT) && opts->keytab_name) { + if (strncmp(opts->keytab_name, "KDB:", 3) == 0) { + code = kinit_kdb_init(&k5->ctx, + krb5_princ_realm(k5->ctx, k5->me)->data); + if (code != 0) { + com_err(progname, code, "while setting up KDB keytab for realm %s", + krb5_princ_realm(k5->ctx, k5->me)->data); + goto cleanup; + } + } + code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab); if (code != 0) { com_err(progname, code, "resolving keytab %s", diff --git a/src/clients/kinit/kinit_kdb.c b/src/clients/kinit/kinit_kdb.c new file mode 100644 index 000000000..972983a16 --- /dev/null +++ b/src/clients/kinit/kinit_kdb.c @@ -0,0 +1,70 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * clients/kinit/kinit_kdb.c + * + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + */ +/** + * @file kinit_kdb.c + * Operations to open the KDB and make the KDB key table available + * for kinit. + */ + + +#include +#include +#include +#include "extern.h" + +/**Server handle*/ +static void * server_handle; + +/** + *@internal Initialize KDB for given realm + * @param context pointer to context that will be re-initialized + * @@param realm name of realm to initialize + */ +krb5_error_code +kinit_kdb_init (krb5_context *pcontext, char *realm) +{ + kadm5_config_params config; + krb5_error_code retval = 0; + if (*pcontext) + krb5_free_context(*pcontext); + memset(&config, 0, sizeof config); + retval = kadm5_init_krb5_context(pcontext); + if (retval) + return retval; + config.mask = KADM5_CONFIG_REALM; + config.realm = realm; + retval = kadm5_init(*pcontext, "kinit", NULL /*pass*/, + "kinit", &config, + KADM5_STRUCT_VERSION, KADM5_API_VERSION_3, NULL, + &server_handle); + if (retval) + return retval; + retval = krb5_kt_register(*pcontext, &krb5_kt_kdb_ops); + return retval; +} diff --git a/src/tests/t_general.py b/src/tests/t_general.py index cb2fcbc74..a2953fefd 100755 --- a/src/tests/t_general.py +++ b/src/tests/t_general.py @@ -28,6 +28,11 @@ for realm in multipass_realms(create_host=False): realm.kinit('user/fast', fastpw, flags=['-T', realm.ccache]) realm.klist('user/fast@%s' % realm.realm) + # Test kinit against kdb keytab + realm.run_as_master([kinit, "-k", "-t", + "KDB:", realm.user_princ]) + + # Test kdestroy and klist of a non-existent ccache. realm.run_as_client([kdestroy]) output = realm.run_as_client([klist], expected_code=1) -- 2.26.2