From b03dd7a3955864c7f84742ac37a97cf00bcd786e Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Mon, 15 Dec 2008 18:32:44 +0000 Subject: [PATCH] In the KDC, remove krb4 request handling support and fakeka code ticket: 6303 status: open git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@21448 dc483132-0cff-0310-8789-dd5450dbe970 --- src/kdc/Makefile.in | 36 +- src/kdc/dispatch.c | 4 - src/kdc/fakeka.M | 111 ---- src/kdc/fakeka.c | 1397 ----------------------------------------- src/kdc/kdc_util.h | 10 - src/kdc/kerberos_v4.c | 1188 ----------------------------------- src/kdc/krb5kdc.M | 20 - src/kdc/main.c | 46 +- 8 files changed, 9 insertions(+), 2803 deletions(-) delete mode 100644 src/kdc/fakeka.M delete mode 100644 src/kdc/fakeka.c delete mode 100644 src/kdc/kerberos_v4.c diff --git a/src/kdc/Makefile.in b/src/kdc/Makefile.in index ecba3275d..c7ecf4bfc 100644 --- a/src/kdc/Makefile.in +++ b/src/kdc/Makefile.in @@ -12,15 +12,13 @@ RUN_SETUP = @KRB5_RUN_ENV@ PROG_LIBPATH=-L$(TOPLIBD) $(KRB4_LIBPATH) KDB5_LIB_DEPS=$(DL_LIB) $(THREAD_LINKOPTS) PROG_RPATH=$(KRB5_LIBDIR) -FAKEKA=@FAKEKA@ DEFS=-DLIBDIR=\"$(KRB5_LIBDIR)\" -#EXTRADEPSRCS= fakeka.c -all:: krb5kdc rtest $(FAKEKA) +all:: krb5kdc rtest # DEFINES = -DBACKWARD_COMPAT $(KRB4DEF) -LOCALINCLUDES = @KRB4_INCLUDES@ -I. +LOCALINCLUDES = -I. SRCS= \ kdc5_err.c \ $(srcdir)/dispatch.c \ @@ -33,8 +31,7 @@ SRCS= \ $(srcdir)/policy.c \ $(srcdir)/extern.c \ $(srcdir)/replay.c \ - $(srcdir)/kdc_authdata.c \ - $(srcdir)/kerberos_v4.c + $(srcdir)/kdc_authdata.c OBJS= \ kdc5_err.o \ @@ -48,8 +45,7 @@ OBJS= \ policy.o \ extern.o \ replay.o \ - kdc_authdata.o \ - kerberos_v4.o + kdc_authdata.o RT_OBJS= rtest.o \ kdc_util.o \ @@ -64,15 +60,12 @@ kdc5_err.h: kdc5_err.et kdc5_err.o: kdc5_err.h -krb5kdc: $(OBJS) $(KADMSRV_DEPLIBS) $(KRB4COMPAT_DEPLIBS) $(APPUTILS_DEPLIB) - $(CC_LINK) -o krb5kdc $(OBJS) $(KADMSRV_LIBS) $(KRB4COMPAT_LIBS) $(APPUTILS_LIB) +krb5kdc: $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB) + $(CC_LINK) -o krb5kdc $(OBJS) $(KADMSRV_LIBS) $(KRB5_BASE_LIBS) $(APPUTILS_LIB) rtest: $(RT_OBJS) $(KDB5_DEPLIBS) $(KADM_COMM_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o rtest $(RT_OBJS) $(KDB5_LIBS) $(KADM_COMM_LIBS) $(KRB5_BASE_LIBS) -fakeka: fakeka.o $(KADMSRV_DEPLIBS) $(KRB4COMPAT_DEPLIBS) $(APPUTILS_DEPLIB) - $(CC_LINK) -o fakeka fakeka.o $(KADMSRV_LIBS) $(KRB4COMPAT_LIBS) $(APPUTILS_LIB) - check-unix:: rtest KRB5_CONFIG=$(SRCTOP)/config-files/krb5.conf ; export KRB5_CONFIG ;\ $(RUN_SETUP) $(VALGRIND) $(srcdir)/rtscript > test.out @@ -82,14 +75,9 @@ check-unix:: rtest install:: $(INSTALL_PROGRAM) krb5kdc ${DESTDIR}$(SERVER_BINDIR)/krb5kdc $(INSTALL_DATA) $(srcdir)/krb5kdc.M ${DESTDIR}$(SERVER_MANDIR)/krb5kdc.8 - f=$(FAKEKA); \ - if test -n "$$f" ; then \ - $(INSTALL_PROGRAM) $$f ${DESTDIR}$(SERVER_BINDIR)/$$f; \ - $(INSTALL_DATA) $(srcdir)/fakeka.M ${DESTDIR}$(SERVER_MANDIR)/fakeka.8; \ - fi clean:: - $(RM) kdc5_err.h kdc5_err.c krb5kdc rtest.o rtest fakeka.o fakeka + $(RM) kdc5_err.h kdc5_err.c krb5kdc rtest.o rtest # +++ Dependency line eater +++ # @@ -221,13 +209,3 @@ $(OUTPRE)kdc_authdata.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ extern.h kdc_authdata.c kdc_util.h -$(OUTPRE)kerberos_v4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ - $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ - $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ - $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ - $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ - $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ - $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/krb5.h \ - $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ - $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ - kerberos_v4.c diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c index ac0eb485d..77415af82 100644 --- a/src/kdc/dispatch.c +++ b/src/kdc/dispatch.c @@ -99,10 +99,6 @@ dispatch(krb5_data *pkt, const krb5_fulladdr *from, krb5_data **response) krb5_free_kdc_req(kdc_context, as_req); } } -#ifdef KRB5_KRB4_COMPAT - else if (pkt->data[0] == 4) /* old version */ - retval = process_v4(pkt, from, response); -#endif else retval = KRB5KRB_AP_ERR_MSG_TYPE; #ifndef NOCACHE diff --git a/src/kdc/fakeka.M b/src/kdc/fakeka.M deleted file mode 100644 index 80ea0153a..000000000 --- a/src/kdc/fakeka.M +++ /dev/null @@ -1,111 +0,0 @@ -.\" kdc/fakeka.M -.\" -.\" Copyright 2005 by the Massachusetts Institute of Technology. -.\" -.\" 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. -.\" " -.TH FAKEKA 8 -.SH NAME -fakeka \- Fake kaserver for AFS clients -.SH SYNOPSIS -\fBfakeka\fP [\fB\-dm\fP] [\fB\-c\fP \fIcell\fP] [\fB\-f\fP \fIforwarder\fP] -[\fB\-l\fP \fBfacility\fP] [\fB\-p\fP \fBport\fP] [\fB\-r\fP \fIrealm\fP] -.br -.SH DESCRIPTION -.I fakeka -is a fake kaserver that speaks just enough of the AFS RX protocol to make -klog work. It is used in conjunction with a Kerberos V5 KDC to support -existing AFS clients, and is usually used with ka-forwarder. -.I fakeka -must run on the same host as your Kerberos V5 KDC, since it needs access -to the KDC database. ka-forwarder should run on each of your AFS database -servers, pointing to your Kerberos V5 KDCs. -.I fakeka -should then be running on each of the KDCs, with the AFS database servers -listed as arguments to the -.B -f -option. -.PP -Note that principals you wish to use -.I fakeka -with must have either a V4-style key (des:v4) or an AFS-style key -(des:afs3). V5 enctypes won't work. -.SH OPTIONS -.TP -\fB\-c\fP \fIcell\fP -The AFS cell for which -.I fakeka -will be handling requests. If not given, this defaults to the same as the -Kerberos V5 realm (see -.B \-r -below). -.TP -.B \-d -Enables debugging. When this flag is given, -.I fakeka -will run in the foreground and print debugging information to standard -error. Overrides -.BR \-m . -.TP -\fB\-f\fP \fIforwarder\fP -Allows forwarded requests from -.IR forwarder , -which is generally an AFS database server running ka-forwarder. This -option can be given multiple times (up to 10). Each system running -ka-forwarder should be specified with the -.B \-f -flag or forwarded requests from that host will not be answered. (The -forwarders append their own address to the packet. -.TP -\fB\-l\fP \fIfacility\fP -Log actions via syslog with the given -.I facility -rather than the default of LOG_DAEMON. -.I facility -must be one of KERN, USER, MAIL, DAEMON, AUTH, LPR, NEWS, UUCP, CRON, -LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, or LOCAL7. This -option is case-sensitive. Not all of these facilities may be available, -depending on what pre-defined syslog facilities your system provides. -.TP -.B \-m -Fork and background when starting. You will usually always want to give -this flag. -.TP -\fB\-p\fP \fIport\fP -Listen on the specified port rather than the default of 7004 (which is -what klog expects). -.I port -may be a number or a service name from -.IR /etc/services . -.TP -\fB\-r\fP \fIrealm\fP -The Kerberos V5 realm to which the requests are being translated. The -default is the local default realm. -.SH EXAMPLES -Handle requests for a local cell whose name matches the local realm, -accepting forwarded queries from afs1.example.com and afs2.example.com: -.IP "" 4 -fakeka -m -f afs1.example.com -f afs2.example.com -.PP -If the cell name doesn't match the realm name, -.B \-c -would need to be added, specifying the cell name. -.SH SEE ALSO -ka-forwarder(8) diff --git a/src/kdc/fakeka.c b/src/kdc/fakeka.c deleted file mode 100644 index 39916647c..000000000 --- a/src/kdc/fakeka.c +++ /dev/null @@ -1,1397 +0,0 @@ -/* - * COPYRIGHT NOTICE - * Copyright (c) 1994 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - * - * Converted to Kerberos 5 by Ken Hornstein - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_MEMORY_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#ifndef LINT -static char rcsid[]= - "$Id$"; -#endif - -/* - * Misc macros - */ - -#define PAD_TO(x, a) (((u_long)(x) + (a) - 1) & ~((a) - 1)) -#define min(a, b) ((a) < (b) ? (a) : (b)) -#define MAXFORWARDERS 10 -#define HEADER_LEN 8 - -/* - * Error values from kautils.h - * - * The security errors are: - * KABADTICKET, KABADSERVER, KABADUSER, and KACLOCKSKEW - */ - -#define KADATABASEINCONSISTENT (180480L) -#define KANOENT (180484L) -#define KABADREQUEST (180490L) -#define KABADTICKET (180504L) -#define KABADSERVER (180507L) -#define KABADUSER (180508L) -#define KACLOCKSKEW (180514L) -#define KAINTERNALERROR (180518L) - - -/* - * Type definitions - */ - -typedef struct packet { - char *base; - int len; - char data[1024]; -} *packet_t; - -typedef struct rx_header { - u_int rx_epoch; - u_int rx_cid; - u_int rx_callnum; - u_int rx_seq; - u_int rx_serial; - u_char rx_type; - u_char rx_flags; - u_char rx_userstatus; - u_char rx_securityindex; - u_short rx_spare; - u_short rx_service; - u_int rx_request; -} *rx_t; - - -/* - * Global vars - */ - -char *progname = "fakeka"; /* needed by libkdb.a */ -char *localrealm = NULL; -char *localcell = NULL; -krb5_timestamp req_time; -kadm5_config_params realm_params; -int debug = 0; - - -/* - * This is a table for the "infamous" CMU ticket lifetime conversion. If - * the lifetime is greater than 128, use this table - */ -#define MAX_TICKET_LIFETIME 2592000 -static long cmu_seconds[] = -{ - 38400, 41055, 43894, 46929, 50174, 53643, 57352, 61318, - 65558, 70091, 74937, 80119, 85658, 91581, 97914, 104684, - 111922, 119661, 127935, 136781, 146239, 156350, 167161, 178720, - 191077, 204289, 218415, 233517, 249663, 266926, 285383, 305116, - 326213, 348769, 372885, 398668, 426233, 455705, 487215, 520903, - 556921, 595430, 636600, 680618, 727679, 777995, 831789, 889303, - 950794, 1016536, 1086825, 1161973, 1242317, 1328217, 1420057, 1518246, - 1623225, 1735463, 1855462, 1983757, 2120924, 2267575, 2424366, 2591999, - 0 -}; - -#if __STDC__ -/* - * Prototypes for all the functions we define - */ - -void perrorexit(char *); -void pexit(char *); -char *kaerror(int); -int get_princ_key(krb5_context, void *, kadm5_principal_ent_t, des_cblock, - des_key_schedule); -int check_princ(krb5_context, void *, char *, char *, kadm5_principal_ent_t); - -int make_reply_packet(krb5_context, void *, packet_t, int, int, int, - char *, char *, char *, char *, - des_cblock, des_key_schedule, char *); - -int Authenticate(krb5_context, void *, char *, packet_t, packet_t); -int GetTicket(krb5_context, void *, char *, packet_t, packet_t); -void process(krb5_context, void *, char *, packet_t, packet_t); -#endif - - -/* - * Helpers for exiting with errors - */ - -void perrorexit(str) -char *str; -{ - perror(str); - exit(1); -} - -void pexit(str) -char *str; -{ - printf("%s\n", str); - exit(1); -} - - -/* - * Translate error codes into strings. - */ - -char *kaerror(e) -int e; -{ - static char buf[1024]; - - switch (e) { - case KADATABASEINCONSISTENT: - return "database is inconsistent"; - case KANOENT: - return "principal does not exist"; - case KABADREQUEST: - return "request was malformed (bad password)"; - case KABADTICKET: - return "ticket was malformed, invalid, or expired"; - case KABADSERVER: - return "cannot issue tickets for this service"; - case KABADUSER: - return "principal expired"; - case KACLOCKSKEW: - return "client time is too far skewed"; - case KAINTERNALERROR: - return "internal error in fakeka, help!"; - default: - snprintf(buf, sizeof(buf), "impossible error code %d, help!", e); - return buf; - } - /*NOTREACHED*/ -} - -/* - * Syslog facilities - */ -typedef struct { - int num; - char *string; -} facility_mapping; - -static facility_mapping mappings[] = { -#ifdef LOG_KERN - { LOG_KERN, "KERN" }, -#endif -#ifdef LOG_USER - { LOG_USER, "USER" }, -#endif -#ifdef LOG_MAIL - { LOG_MAIL, "MAIL" }, -#endif -#ifdef LOG_DAEMON - { LOG_DAEMON, "DAEMON" }, -#endif -#ifdef LOG_AUTH - { LOG_AUTH, "AUTH" }, -#endif -#ifdef LOG_LPR - { LOG_LPR, "LPR" }, -#endif -#ifdef LOG_NEWS - { LOG_NEWS, "NEWS" }, -#endif -#ifdef LOG_UUCP - { LOG_UUCP, "UUCP" }, -#endif -#ifdef LOG_CRON - { LOG_CRON, "CRON" }, -#endif -#ifdef LOG_LOCAL0 - { LOG_LOCAL0, "LOCAL0" }, -#endif -#ifdef LOG_LOCAL1 - { LOG_LOCAL1, "LOCAL1" }, -#endif -#ifdef LOG_LOCAL2 - { LOG_LOCAL2, "LOCAL2" }, -#endif -#ifdef LOG_LOCAL3 - { LOG_LOCAL3, "LOCAL3" }, -#endif -#ifdef LOG_LOCAL4 - { LOG_LOCAL4, "LOCAL4" }, -#endif -#ifdef LOG_LOCAL5 - { LOG_LOCAL5, "LOCAL5" }, -#endif -#ifdef LOG_LOCAL6 - { LOG_LOCAL6, "LOCAL6" }, -#endif -#ifdef LOG_LOCAL7 - { LOG_LOCAL7, "LOCAL7" }, -#endif - { 0, NULL } -}; - - -/* - * Get the principal's key and key schedule from the db record. - * - * Life is more complicated in the V5 world. Since we can have different - * encryption types, we have to make sure that we get back a DES key. - * Also, we have to try to get back a AFS3 or V4 salted key, since AFS - * doesn't know about a V5 style salt. - */ - -int get_princ_key(context, handle, p, k, s) -krb5_context context; -void *handle; -kadm5_principal_ent_t p; -des_cblock k; -des_key_schedule s; -{ - int rv; - krb5_keyblock kb; - kadm5_ret_t retval; - - /* - * We need to call kadm5_decrypt_key to decrypt the key data - * from the principal record. We _must_ have a encryption type - * of DES_CBC_CRC, and we prefer having a salt type of AFS 3 (but - * a V4 salt will work as well). If that fails, then return any - * type of key we can find. - * - * Note that since this uses kadm5_decrypt_key, it means it has to - * be compiled with the kadm5srv library. - */ - - if ((retval = kadm5_decrypt_key(handle, p, ENCTYPE_DES_CBC_CRC, - KRB5_KDB_SALTTYPE_AFS3, 0, &kb, - NULL, NULL))) - if ((retval = kadm5_decrypt_key(handle, p, ENCTYPE_DES_CBC_CRC, - KRB5_KDB_SALTTYPE_V4, 0, &kb, - NULL, NULL))) - if ((retval = kadm5_decrypt_key(handle, p, ENCTYPE_DES_CBC_CRC, - -1, 0, &kb, NULL, NULL))) { - syslog(LOG_ERR, "Couldn't find any matching key: %s", - error_message(retval)); - return KAINTERNALERROR; - } - - /* - * Copy the data from our krb5_keyblock to the des_cblock. Make sure - * the size of our key matches the V4/AFS des_cblock. - */ - - if (kb.length != sizeof(des_cblock)) { - krb5_free_keyblock_contents(context, &kb); - syslog(LOG_ERR, "Principal key size of %d didn't match C_Block size" - " %d", kb.length, sizeof(des_cblock)); - return KAINTERNALERROR; - } - - memcpy((char *) k, (char *) kb.contents, sizeof(des_cblock)); - - krb5_free_keyblock_contents(context, &kb); - - /* - * Calculate the des key schedule - */ - - rv = des_key_sched(k, s); - if (rv) { - memset((void *) k, 0, sizeof(k)); - memset((void *)s, 0, sizeof(s)); - return KAINTERNALERROR; - } - return 0; -} - - -/* - * Fetch principal from db and validate it. - * - * Note that this always fetches the key data from the principal (but it - * doesn't decrypt it). - */ - -int check_princ(context, handle, name, inst, p) -krb5_context context; -void *handle; -char *name, *inst; -kadm5_principal_ent_t p; -{ - krb5_principal princ; - krb5_error_code code; - kadm5_ret_t retcode; - - /* - * Screen out null principals. They are causing crashes here - * under HPUX-10.20. - vwelch@ncsa.uiuc.edu 1/6/98 - */ - if (!name || (name[0] == '\0')) { - syslog(LOG_ERR, "screening out null principal"); - return KANOENT; - } - - /* - * Build a principal from the name and instance (the realm is always - * the same). - */ - - if ((code = krb5_build_principal_ext(context, &princ, strlen(localrealm), - localrealm, strlen(name), name, - strlen(inst), inst, 0))) { - syslog(LOG_ERR, "could not build principal: %s", error_message(code)); - return KAINTERNALERROR; - } - - /* - * Fetch the principal from the database -- also fetch the key data. - * Note that since this retrieves the key data, it has to be linked with - * the kadm5srv library. - */ - - if ((retcode = kadm5_get_principal(handle, princ, p, - KADM5_PRINCIPAL_NORMAL_MASK | - KADM5_KEY_DATA))) { - if (retcode == KADM5_UNK_PRINC) { - krb5_free_principal(context, princ); - syslog(LOG_INFO, "principal %s.%s does not exist", name, inst); - return KANOENT; - } else { - krb5_free_principal(context, princ); - syslog(LOG_ERR, "kadm5_get_principal failed: %s", - error_message(retcode)); - return KAINTERNALERROR; - } - } - - krb5_free_principal(context, princ); - - /* - * Check various things - taken from the KDC code. - * - * Since we're essentially bypassing the KDC, we need to make sure - * that we don't give out a ticket that we shouldn't. - */ - - /* - * Has the principal expired? - */ - - if (p->princ_expire_time && p->princ_expire_time < req_time) { - kadm5_free_principal_ent(handle, p); - return KABADUSER; - } - - /* - * Has the principal's password expired? Note that we don't - * check for the PWCHANGE_SERVICE flag here, since we don't - * support password changing. We do support the REQUIRES_PWCHANGE - * flag, though. - */ - - if ((p->pw_expiration && p->pw_expiration < req_time) || - (p->attributes & KRB5_KDB_REQUIRES_PWCHANGE)) { - kadm5_free_principal_ent(handle, p); - return KABADUSER; - } - - /* - * See if the principal is locked out - */ - - if (p->attributes & KRB5_KDB_DISALLOW_ALL_TIX) { - kadm5_free_principal_ent(handle, p); - return KABADUSER; - } - - /* - * There's no way we can handle hardware preauth, so - * disallow tickets with this flag set. - */ - - if (p->attributes & KRB5_KDB_REQUIRES_HW_AUTH) { - kadm5_free_principal_ent(handle, p); - return KABADUSER; - } - - /* - * Must be okay, then - */ - - return 0; -} - - -/* - * Create an rx reply packet in "packet" using the provided data. - * The caller is responsible for zeroing key and sched. - */ - -int make_reply_packet(context, handle, reply, challenge_response, start_time, - end_time, cname, cinst, sname, sinst, key, sched, label) -krb5_context context; -void *handle; -packet_t reply; -int challenge_response, start_time, end_time; -char *cname, *cinst, *sname, *sinst; -des_cblock key; -des_key_schedule sched; -char *label; -{ - int rv, n, maxn, v4life, *enclenp, *ticklenp; - u_char *p, *enc, *ticket; - kadm5_principal_ent_rec cprinc, sprinc; - des_cblock skey, new_session_key; - des_key_schedule ssched; - krb5_deltat lifetime; - - rv = 0; - - rv = check_princ(context, handle, cname, cinst, &cprinc); - if (rv) - return rv; - - rv = check_princ(context, handle, sname, sinst, &sprinc); - if (rv) { - kadm5_free_principal_ent(handle, &cprinc); - return rv; - } - - /* - * Bound ticket lifetime by max lifetimes of user and service. - * - * Since V5 already stores everything in Unix epoch timestamps like - * AFS, these calculations are much simpler. - */ - - lifetime = end_time - start_time; - lifetime = min(lifetime, cprinc.max_life); - lifetime = min(lifetime, sprinc.max_life); - lifetime = min(lifetime, realm_params.max_life); - - end_time = start_time + lifetime; - - /* - * But we have to convert back to V4-style lifetimes - */ - - v4life = lifetime / 300; - if (v4life > 127) { - /* - * Use the CMU algorithm instead - */ - long *clist = cmu_seconds; - while (*clist && *clist < lifetime) clist++; - v4life = 128 + (clist - cmu_seconds); - } - - /* - * If this is for afs and the instance is the local cell name - * then we assume we added the instance in GetTickets to - * identify the afs key in the kerberos database. This is for - * cases where the afs cell name is different from the kerberos - * realm name. We now want to remove the instance so it doesn't - * cause klog to barf. - */ - if (!strcmp(sname, "afs") && (strcasecmp(sinst, localcell) == 0)) - sinst[0] = '\0'; - - /* - * All the data needed to construct the ticket is ready, so do it. - */ - - p = (unsigned char *) reply->base; - maxn = reply->len; - n = 0; - -#define ERR(x) do { rv = x ; goto error; } while (0) -#define ADVANCE(x) { if ((n += x) > maxn) ERR(KAINTERNALERROR); else p += x;} -#define PUT_CHAR(x) { *p = (x); ADVANCE(1); } -#define PUT_INT(x) { int q = ntohl(x); memcpy(p, (char *)&q, 4); ADVANCE(4); } -#define PUT_STR(x) { strcpy((char *) p, x); ADVANCE(strlen(x) + 1); } - - ADVANCE(28); - PUT_INT(0x2bc); - - enclenp = (int *)p; - PUT_INT(0); /* filled in later */ - - enc = p; - PUT_INT(0); - PUT_INT(challenge_response); - - /* - * new_session_key is created here, and remains in the clear - * until just before we return. - */ - des_new_random_key(new_session_key); - memcpy(p, new_session_key, 8); - - ADVANCE(8); - PUT_INT(start_time); - PUT_INT(end_time); - PUT_INT(sprinc.kvno); - - ticklenp = (int *)p; - PUT_INT(0); /* filled in later */ - - PUT_STR(cname); - PUT_STR(cinst); - PUT_STR(""); - PUT_STR(sname); - PUT_STR(sinst); - - ticket = p; - PUT_CHAR(0); /* flags, always 0 */ - PUT_STR(cname); - PUT_STR(cinst); - PUT_STR(""); - PUT_INT(0); /* would be ip address */ - - memcpy(p, new_session_key, 8); - - ADVANCE(8); - - PUT_CHAR(v4life); - PUT_INT(start_time); - PUT_STR(sname); - PUT_STR(sinst); - - ADVANCE(PAD_TO(p - ticket, 8) - (p - ticket)); - - *ticklenp = ntohl(p - ticket); - - rv = get_princ_key(context, handle, &sprinc, skey, ssched); - if (rv) - return rv; - des_pcbc_encrypt((C_Block *) ticket, (C_Block *) ticket, p - ticket, - ssched, (C_Block *) skey, ENCRYPT); - memset(skey, 0, sizeof(skey)); - memset(ssched, 0, sizeof(ssched)); - - PUT_STR(label); /* "tgsT" or "gtkt" */ - ADVANCE(-1); /* back up over string terminator */ - - ADVANCE(PAD_TO(p - enc, 8) - (p - enc)); -#undef ERR -#undef ADVANCE -#undef PUT_CHAR -#undef PUT_INT -#undef PUT_STR - - *enclenp = ntohl(p - enc); - des_pcbc_encrypt((C_Block *) enc, (C_Block *) enc, p - enc, sched, - (C_Block *) key, ENCRYPT); - reply->len = n; - - error: - memset(new_session_key, 0, sizeof(new_session_key)); - kadm5_free_principal_ent(handle, &cprinc); - kadm5_free_principal_ent(handle, &sprinc); - - return rv; -} - -#define ERR(x) do { rv = x; goto error; } while (0) -#define ADVANCE(x) { if ((n += x) > maxn) ERR(KABADREQUEST); else p += x; } -#define GET_INT(x) { int q; memcpy((char *)&q, p, 4); x = ntohl(q); ADVANCE(4); } -#define GET_CHAR(x) { x = *p; ADVANCE(1); } -#define GET_PSTR(x) \ - { \ - GET_INT(len); \ - if (len > sizeof(x) - 1) ERR(KABADREQUEST); \ - memcpy(x, p, len); \ - x[len] = 0; \ - ADVANCE(PAD_TO(len, 4)); \ - } - -#define GET_STR(x) \ - { \ - len = strlen(p); \ - if (len > sizeof(x) - 1) ERR(KABADREQUEST); \ - strcpy(x, p); \ - ADVANCE(len + 1); \ - } - - -/* - * Process an Authenticate request. - */ - -int Authenticate(context, handle, from, req, reply) -krb5_context context; -void *handle; -char *from; -packet_t req, reply; -{ - int rv, n, maxn; - int len, start_time, end_time, challenge; - char name[ANAME_SZ+1], inst[INST_SZ+1], *p; - kadm5_principal_ent_rec cprinc; - des_cblock ckey; - des_key_schedule csched; - int free_princ_ent = 0; - - rv = 0; - - p = req->base; - maxn = req->len; - n = 0; - - ADVANCE(32); - - GET_PSTR(name); - GET_PSTR(inst); - - if (debug) - fprintf(stderr, "Authenticating %s.%s\n", name, inst); - - rv = check_princ(context, handle, name, inst, &cprinc); - if (rv) - ERR(rv); - - free_princ_ent = 1; - - GET_INT(start_time); - GET_INT(end_time); - - GET_INT(len); - if (len != 8) - ERR(KABADREQUEST); - - /* - * ckey and csched are set here and remain in the clear - * until just before we return. - */ - - rv = get_princ_key(context, handle, &cprinc, ckey, csched); - if (rv) - ERR(rv); - des_pcbc_encrypt((C_Block *) p, (C_Block *) p, 8, csched, - (C_Block *) ckey, DECRYPT); - - GET_INT(challenge); - - rv = memcmp(p, "gTGS", 4); - if (rv) - ERR(KABADREQUEST); - ADVANCE(4); - - /* ignore the rest */ - ADVANCE(8); - - /* - * We have all the data from the request, now generate the reply. - */ - - rv = make_reply_packet(context, handle, reply, challenge + 1, start_time, - end_time, name, inst, "krbtgt", localcell, - ckey, csched, "tgsT"); - error: - memset(ckey, 0, sizeof(ckey)); - memset(csched, 0, sizeof(csched)); - - syslog(LOG_INFO, "authenticate: %s.%s from %s", name, inst, from); - if (rv) { - syslog(LOG_INFO, "... failed due to %s", kaerror(rv)); - } - if (free_princ_ent) - kadm5_free_principal_ent(handle, &cprinc); - return rv; -} - - -/* - * Process a GetTicket rpc. - */ - -int GetTicket(context, handle, from, req, reply) -krb5_context context; -void *handle; -char *from; -packet_t req, reply; -{ - int rv, n, maxn, len, ticketlen; - char *p; - u_int kvno, start_time, end_time, times[2], flags, ipaddr; - u_int tgt_start_time, tgt_end_time, lifetime; - char rname[ANAME_SZ+1], rinst[INST_SZ+1]; /* requested principal */ - char sname[ANAME_SZ+1], sinst[INST_SZ+1]; /* service principal (TGT) */ - char cname[ANAME_SZ+1], cinst[INST_SZ+1]; /* client principal */ - char cell[REALM_SZ+1], realm[REALM_SZ+1]; - char enctimes[8 + 1], ticket[1024]; - u_char tgt_lifetime; - kadm5_principal_ent_rec cprinc; - des_cblock ckey, session_key; - des_key_schedule csched, session_sched; - int free_princ_ent = 0; - - rv = 0; - - /* - * Initialize these so we don't crash trying to print them in - * case they don't get filled in. - */ - strlcpy(rname, "Unknown", sizeof(rname)); - strlcpy(rinst, "Unknown", sizeof(rinst)); - strlcpy(sname, "Unknown", sizeof(sname)); - strlcpy(sinst, "Unknown", sizeof(sinst)); - strlcpy(cname, "Unknown", sizeof(cname)); - strlcpy(cinst, "Unknown", sizeof(cinst)); - strlcpy(cell, "Unknown", sizeof(cell)); - strlcpy(realm, "Unknown", sizeof(realm)); - - p = req->base; - maxn = req->len; - n = 0; - - ADVANCE(32); - - GET_INT(kvno); - - GET_PSTR(cell); - if (!cell[0]) - strlcpy(cell, localcell, sizeof(cell)); - - if (debug) - fprintf(stderr, "Cell is %s\n", cell); - - memset(ticket, 0, sizeof(ticket)); - GET_PSTR(ticket); - ticketlen = len; /* hacky hack hack */ - GET_PSTR(rname); - GET_PSTR(rinst); - - if (debug) - fprintf(stderr, "Request for %s/%s\n", rname, rinst); - - GET_PSTR(enctimes); /* still encrypted */ - if (len != 8) /* hack and hack again */ - ERR(KABADREQUEST); - - /* ignore the rest */ - ADVANCE(8); - - /* - * That's it for the packet, now decode the embedded ticket. - */ - - rv = check_princ(context, handle, "krbtgt", cell, &cprinc); - if (rv) - ERR(rv); - - free_princ_ent = 1; - - rv = get_princ_key(context, handle, &cprinc, ckey, csched); - if (rv) - ERR(rv); - des_pcbc_encrypt((C_Block *) ticket, (C_Block *) ticket, ticketlen, csched, - (C_Block *) ckey, DECRYPT); - memset(ckey, 0, sizeof(ckey)); - memset(csched, 0, sizeof(csched)); - - /* - * The ticket's session key is now in the clear in the ticket buffer. - * We zero it just before returning. - */ - - p = ticket; - maxn = ticketlen; - n = 0; - - GET_CHAR(flags); - GET_STR(cname); - GET_STR(cinst); - GET_STR(realm); - GET_INT(ipaddr); - memcpy(session_key, p, 8); - ADVANCE(8); - - GET_CHAR(tgt_lifetime); - GET_INT(tgt_start_time); - GET_STR(sname); - GET_STR(sinst); - - if (debug) - fprintf(stderr, - "ticket: %s.%s@%s for %s.%s\n", - cname, cinst, realm, sname, sinst); - - /* - * ok, we've got the ticket unpacked. - * now decrypt the start and end times. - */ - - rv = des_key_sched(session_key, session_sched); - if (rv) - ERR(KABADTICKET); - - des_ecb_encrypt((C_Block *) enctimes, (C_Block *) times, session_sched, - DECRYPT); - start_time = ntohl(times[0]); - end_time = ntohl(times[1]); - - /* - * All the info we need is now available. - * Now validate the request. - */ - - /* - * This translator requires that the flags and IP address - * in the ticket be zero, because we always set them that way, - * and we want to accept only tickets that we generated. - * - * Are the flags and IP address fields 0? - */ - if (flags || ipaddr) { - if (debug) - fprintf(stderr, "ERROR: flags or ipaddr field non-zero\n"); - ERR(KABADTICKET); - } - /* - * Is the supplied ticket a tgt? - */ - if (strcmp(sname, "krbtgt")) { - if (debug) - fprintf(stderr, "ERROR: not for krbtgt service\n"); - ERR(KABADTICKET); - } - - /* - * This translator does not allow MIT-style cross-realm access. - * Is this a cross-realm ticket? - */ - if (strcasecmp(sinst, localcell)) { - if (debug) - fprintf(stderr, - "ERROR: Service instance (%s) differs from local cell\n", - sinst); - ERR(KABADTICKET); - } - - /* - * This translator does not issue cross-realm tickets, - * since klog doesn't use this feature. - * Is the request for a cross-realm ticket? - */ - if (strcasecmp(cell, localcell)) { - if (debug) - fprintf(stderr, "ERROR: Cell %s != local cell", cell); - ERR(KABADTICKET); - } - - /* - * Even if we later decide to issue cross-realm tickets, - * we should not permit "realm hopping". - * This means that the client's realm should match - * the realm of the tgt with whose key we are supposed - * to decrypt the ticket. I think. - */ - if (*realm && strcasecmp(realm, cell)) { - if (debug) - fprintf(stderr, "ERROR: Realm %s != cell %s\n", realm, cell); - ERR(KABADTICKET); - } - - /* - * This translator issues service tickets only for afs, - * since klog is the only client that should be using it. - * Is the requested service afs? - * - * Note: to make EMT work, we're allowing tickets for emt/admin and - * adm/admin. - */ - if (! ((strcmp(rname, "afs") == 0 && ! *rinst) || - (strcmp(rname, "emt") == 0 && strcmp(rinst, "admin") == 0) || - (strcmp(rname, "adm") == 0 && strcmp(rinst, "admin") == 0))) - ERR(KABADSERVER); - - /* - * If the local realm name and cell name differ and the user - * is in the local cell and has requested a ticket of afs. (no - * instance, then we actually want to get a ticket for - * afs/@ - */ - if ((strcmp(rname, "afs") == 0) && !*rinst && - strcmp(localrealm, localcell) && - (strcasecmp(cell, localcell) == 0)) { - char *c; - - strlcpy(rinst, localcell, sizeof(rinst)); - - for (c = rinst; *c != NULL; c++) - *c = (char) tolower( (int) *c); - - if (debug) - fprintf(stderr, "Getting ticket for afs/%s\n", localcell); - } - - /* - * Even if we later decide to issue service tickets for - * services other than afs, we should still disallow - * the "changepw" and "krbtgt" services. - */ - if (!strcmp(rname, "changepw") || !strcmp(rname, "krbtgt")) - ERR(KABADSERVER); - - /* - * Is the tgt valid yet? (ie. is the start time in the future) - */ - if (req_time < tgt_start_time - CLOCK_SKEW) { - if (debug) - fprintf(stderr, "ERROR: Ticket not yet valid\n"); - ERR(KABADTICKET); - } - - /* - * Has the tgt expired? (ie. is the end time in the past) - * - * Sigh, convert from V4 lifetimes back to Unix epoch times. - */ - - if (tgt_lifetime < 128) - tgt_end_time = tgt_start_time + tgt_lifetime * 300; - else if (tgt_lifetime < 192) - tgt_end_time = tgt_start_time + cmu_seconds[tgt_lifetime - 128]; - else - tgt_end_time = tgt_start_time + MAX_TICKET_LIFETIME; - - if (tgt_end_time < req_time) { - if (debug) - fprintf(stderr, "ERROR: Ticket expired\n"); - ERR(KABADTICKET); - } - - /* - * This translator uses the requested start time as a cheesy - * authenticator, since the KA protocol does not have an - * explicit authenticator. We can do this since klog always - * requests a start time equal to the current time. - * - * Is the requested start time approximately now? - */ - if (abs(req_time - start_time) > CLOCK_SKEW) - ERR(KACLOCKSKEW); - - /* - * The new ticket's lifetime is the minimum of: - * 1. remainder of tgt's lifetime - * 2. requested lifetime - * - * This is further limited by the client and service's max lifetime - * in make_reply_packet(). - */ - - lifetime = tgt_end_time - req_time; - lifetime = min(lifetime, end_time - start_time); - end_time = req_time + lifetime; - - /* - * We have all the data from the request, now generate the reply. - */ - - rv = make_reply_packet(context, handle, reply, 0, start_time, end_time, - cname, cinst, rname, rinst, - session_key, session_sched, "gtkt"); - error: - memset(ticket, 0, sizeof(ticket)); - memset(session_key, 0, sizeof(session_key)); - memset(session_sched, 0, sizeof(session_sched)); - - if (free_princ_ent) - kadm5_free_principal_ent(handle, &cprinc); - - syslog(LOG_INFO, "getticket: %s.%s from %s for %s.%s", - cname, cinst, from, rname, rinst); - if (rv) { - syslog(LOG_INFO, "... failed due to %s", kaerror(rv)); - } - return rv; -} - - -#undef ERR -#undef ADVANCE -#undef GET_INT -#undef GET_PSTR -#undef GET_STR - -/* - * Convert the request into a reply. - * Returns 0 on success. - */ - -void process(context, handle, from, req, reply) -krb5_context context; -void *handle; -char *from; -packet_t req, reply; -{ - int rv; - rx_t req_rx = (rx_t)req->base; - rx_t reply_rx = (rx_t)reply->base; - int service, request; - - service = ntohs(req_rx->rx_service); - request = ntohl(req_rx->rx_request); - - /* ignore everything but type 1 */ - if (req_rx->rx_type != 1) { - reply->len = 0; - return; - } - - /* copy the rx header and change the flags */ - *reply_rx = *req_rx; - reply_rx->rx_flags = 4; - - rv = -1; - - if (service == 0x2db && (request == 0x15 || request == 0x16)) { - if (debug) - fprintf(stderr, "Handling Authenticate request\n"); - rv = Authenticate(context, handle, from, req, reply); - } - if (service == 0x2dc && request == 0x17) { - if (debug) - fprintf(stderr, "Handling GetTicket request\n"); - rv = GetTicket(context, handle, from, req, reply); - } -/* - if (service == 0x2db && request == 0x1) { - rv = Authenticate_old(from, req, reply); - } - if (service == 0x2dc && request == 0x3) { - rv = GetTicket_old(from, req, reply); - } - */ - if (rv == -1) { - syslog(LOG_INFO, "bogus request %d/%d", service, request); - rv = KABADREQUEST; - } - - if (rv) { - /* send the error back to rx */ - reply->len = sizeof (*reply_rx); - - reply_rx->rx_type = 4; - reply_rx->rx_flags = 0; - reply_rx->rx_request = ntohl(rv); - } -} - - -int main(argc, argv) -int argc; -char **argv; -{ - int s, rv, ch, mflag = 0; - u_short port; - struct sockaddr_in sin; - int forwarders[MAXFORWARDERS], num_forwarders; - krb5_context context; - krb5_error_code code; - krb5_keyblock mkey; - krb5_principal master_princ; - kadm5_principal_ent_rec master_princ_rec; - void *handle; - facility_mapping *mapping; - int facility = LOG_DAEMON; - - extern char *optarg; - - port = 7004; - num_forwarders = 0; - - /* - * Parse args. - */ - while ((ch = getopt(argc, argv, "c:df:l:mp:r:")) != -1) { - switch (ch) { - case 'c': - localcell = optarg; - break; - case 'd': - debug++; - break; - case 'f': { - struct hostent *hp; - - if (num_forwarders++ >= MAXFORWARDERS) - pexit("too many forwarders\n"); - - hp = gethostbyname(optarg); - if (!hp) { - printf("unknown host %s\n", optarg); - exit(1); - } - forwarders[num_forwarders - 1] = *(int *)hp->h_addr; - - break; - } - case 'l': - for (mapping = mappings; mapping->string != NULL; mapping++) - if (strcmp(mapping->string, optarg) == 0) - break; - - if (mapping->string == NULL) { - printf("Unknown facility \"%s\"\n", optarg); - exit(1); - } - - facility = mapping->num; - break; - case 'm': - mflag = 1; - break; - case 'p': - if (isdigit(*optarg)) { - port = atoi(optarg); - } - else { - struct servent *sp; - - sp = getservbyname(optarg, "udp"); - if (!sp) { - printf("unknown service %s\n", optarg); - exit(1); - } - port = sp->s_port; - } - break; - case 'r': - localrealm = optarg; - break; - default: - printf("usage: %s [-c cell] [-d] [-f forwarder-host] [-l facility ] [-p port] [-r realm]\n", - argv[0]); - exit(1); - } - } - - openlog("fakeka", LOG_PID, facility); - - port = htons(port); - - /* - * Set up the socket. - */ - - s = socket(AF_INET, SOCK_DGRAM, 0); - if (s < 0) - perrorexit("Couldn't create socket"); - set_cloexec_fd(s); - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = 0; - sin.sin_port = port; - - rv = bind(s, (struct sockaddr *)&sin, sizeof(sin)); - if (rv < 0) - perrorexit("Couldn't bind socket"); - - /* - * Initialize kerberos stuff and kadm5 stuff. - */ - - if ((code = krb5int_init_context_kdc(&context))) { - com_err(argv[0], code, "while initializing Kerberos"); - exit(1); - } - - if (!localrealm && (code = krb5_get_default_realm(context, &localrealm))) { - com_err(argv[0], code, "while getting local realm"); - exit(1); - } - - if (!localcell) - localcell = localrealm; - - if ((code = kadm5_init_with_password(progname, NULL, KADM5_ADMIN_SERVICE, - NULL, KADM5_STRUCT_VERSION, - KADM5_API_VERSION_2, - (char **) NULL, /* db_args */ - &handle))) { - com_err(argv[0], code, "while initializing Kadm5"); - exit(1); - } - - if ((code = kadm5_get_config_params(context, 1, NULL, - &realm_params))) { - com_err(argv[0], code, "while getting realm parameters"); - exit(1); - } - - if (! (realm_params.mask & KADM5_CONFIG_MAX_LIFE)) { - fprintf(stderr, "Cannot determine maximum ticket lifetime\n"); - exit(1); - } - - /* - * We need to initialize the random number generator for DES. Use - * the master key to do this. - */ - - if ((code = krb5_parse_name(context, realm_params.mask & - KADM5_CONFIG_MKEY_NAME ? - realm_params.mkey_name : "K/M", - &master_princ))) { - com_err(argv[0], code, "while parsing master key name"); - exit(1); - } - - if ((code = kadm5_get_principal(handle, master_princ, &master_princ_rec, - KADM5_KEY_DATA))) { - com_err(argv[0], code, "while getting master key data"); - exit(1); - } - - if ((code = kadm5_decrypt_key(handle, &master_princ_rec, - ENCTYPE_DES_CBC_CRC, -1, 0, &mkey, NULL, - NULL))) { - com_err(argv[0], code, "while decrypting the master key"); - exit(1); - } - - des_init_random_number_generator(mkey.contents); - - krb5_free_keyblock_contents(context, &mkey); - - kadm5_free_principal_ent(handle, &master_princ_rec); - - krb5_free_principal(context, master_princ); - - /* - * Fork and go into the background, if requested - */ - - if (!debug && mflag && daemon(0, 0)) { - com_err(argv[0], errno, "while detaching from tty"); - } - - /* - * rpc server loop. - */ - - for (;;) { - struct packet req, reply; - int sinlen, packetlen, i, forwarded; - char *from; - - sinlen = sizeof(sin); - forwarded = 0; - - memset(req.data, 0, sizeof(req.data)); - rv = recvfrom(s, req.data, sizeof(req.data), - 0, (struct sockaddr *)&sin, &sinlen); - - if (rv < 0) { - syslog(LOG_ERR, "recvfrom failed: %m"); - sleep(1); - continue; - } - packetlen = rv; - - for (i = 0; i < num_forwarders; i++) { - if (sin.sin_addr.s_addr == forwarders[i]) { - forwarded = 1; - break; - } - } - - if ((code = krb5_timeofday(context, &req_time))) { - syslog(LOG_ERR, "krb5_timeofday failed: %s", - error_message(code)); - continue; - } - - memset(reply.data, 0, sizeof(reply.data)); - req.len = packetlen; - req.base = req.data; - reply.base = reply.data; - reply.len = sizeof(reply.data); - - if (forwarded) { - struct in_addr ia; - - memcpy(&ia.s_addr, req.data, 4); - from = inet_ntoa(ia); - /* - * copy the forwarder header and adjust the bases and lengths. - */ - memcpy(reply.data, req.data, HEADER_LEN); - req.base += HEADER_LEN; - req.len -= HEADER_LEN; - reply.base += HEADER_LEN; - reply.len -= HEADER_LEN; - } - else { - from = inet_ntoa(sin.sin_addr); - } - - process(context, handle, from, &req, &reply); - - if (reply.len == 0) - continue; - - if (forwarded) { - /* re-adjust the length to account for the forwarder header */ - reply.len += HEADER_LEN; - } - - rv = sendto(s, reply.data, reply.len, - 0, (struct sockaddr *)&sin, sinlen); - if (rv < 0) { - syslog(LOG_ERR, "sendto failed: %m"); - sleep(1); - } - } - /*NOTREACHED*/ -} diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index b535acd81..ca644ac6d 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -192,16 +192,6 @@ get_principal (krb5_context kcontext, #define setflag(flagfield, flag) (flagfield |= (flag)) #define clear(flagfield, flag) (flagfield &= ~(flag)) -#ifdef KRB5_KRB4_COMPAT -krb5_error_code process_v4 (const krb5_data *, - const krb5_fulladdr *, - krb5_data **); -void process_v4_mode (const char *, const char *); -void enable_v4_crossrealm(char *); -#else -#define process_v4(foo,bar,quux,foobar) KRB5KRB_AP_ERR_BADVERSION -#endif - #ifndef min #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) diff --git a/src/kdc/kerberos_v4.c b/src/kdc/kerberos_v4.c deleted file mode 100644 index a0c74a18b..000000000 --- a/src/kdc/kerberos_v4.c +++ /dev/null @@ -1,1188 +0,0 @@ -/* - * kdc/kerberos_v4.c - * - * Copyright 1985, 1986, 1987, 1988,1991,2007 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. - * - */ - -#include "autoconf.h" -#ifdef KRB5_KRB4_COMPAT -#define BACKWARD_COMPAT - -#include "k5-int.h" -#include "kdc_util.h" -#include "adm_proto.h" - -#include - -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_TIME_H -#include -#ifdef TIME_WITH_SYS_TIME -#include -#endif -#else -#include -#endif -#include -#include -#include -#include -#include - -/* v4 include files: - */ -#include -#include -#include -#include -#include - -#ifdef NEED_SWAB_PROTO -extern void swab(const void *, void *, size_t ); -#endif - -static int compat_decrypt_key (krb5_key_data *, C_Block, - krb5_keyblock *, int); -static int kerb_get_principal (char *, char *, Principal *, - int *, krb5_keyblock *, krb5_kvno, - int, krb5_deltat *); -static int check_princ (char *, char *, int, Principal *, - krb5_keyblock *, int, krb5_deltat *); - -static char * v4_klog (int, const char *, ...) -#if !defined(__cplusplus) && (__GNUC__ > 2) - __attribute__((__format__(__printf__, 2, 3))) -#endif - ; -#define klog v4_klog - -/* Byte ordering */ -/*#define MSB_FIRST 0 / * 68000, IBM RT/PC */ -/*#define LSB_FIRST 1 / * Vax, PC8086 */ -#if defined K5_LE -# define HOST_BYTE_ORDER 1 -#elif defined K5_BE -# define HOST_BYTE_ORDER 0 -#else -static int krbONE = 1; -# define HOST_BYTE_ORDER (* (char *) &krbONE) -#endif - -#ifndef BACKWARD_COMPAT -static Key_schedule master_key_schedule; -static C_Block master_key; -#endif - -static struct timeval kerb_time; -static Principal a_name_data; /* for requesting user */ -static Principal s_name_data; /* for services requested */ -static C_Block session_key; - -static char log_text[512]; -static char *lt; - -/* fields within the received request packet */ -static u_char req_msg_type; -static u_char req_version; -static char *req_name_ptr; -static char *req_inst_ptr; -static char *req_realm_ptr; - -static krb5_ui_4 req_time_ws; - -static char local_realm[REALM_SZ]; - -static long n_auth_req; -static long n_appl_req; - -static long pause_int = -1; - -static void hang(void); - - -/* v4/v5 backwards-compatibility stub routines, - * which allow the v5 server to handle v4 packets - * by invoking substantially-unaltered v4 server code. - * this is only necessary during the installation's conversion to v5. - * process_v4() is invoked by v5's dispatch() routine; - * when the v4 server needs to access the v5 database, - * it calls the other stubs. - * - * until all kerberized application-programs are updated, - * this approach inflates the v5 server's code size, - * but it's easier to debug than a concurrent, subordinate v4 server would be. - */ - -/* - * v5 include files: - */ -#include "com_err.h" -#include "extern.h" /* to pick up master_princ */ - -static krb5_data *kerberos_v4 (struct sockaddr_in *, KTEXT); -static krb5_data *kerb_err_reply (struct sockaddr_in *, KTEXT, long, char *); -static int set_tgtkey (char *, krb5_kvno, krb5_boolean); - -/* Attributes converted from V5 to V4 - internal representation */ -#define V4_KDB_REQUIRES_PREAUTH 0x1 -#define V4_KDB_DISALLOW_ALL_TIX 0x2 -#define V4_KDB_REQUIRES_PWCHANGE 0x4 -#define V4_KDB_DISALLOW_SVR 0x8 - -/* v4 compatibitly mode switch */ -#define KDC_V4_NONE 0 /* Don't even respond to packets */ -#define KDC_V4_DISABLE 1 /* V4 requests return an error */ -#define KDC_V4_FULL 2 /* Preauth required go through */ -#define KDC_V4_NOPREAUTH 3 /* Preauth required disallowed */ - -#define KDC_V4_DEFAULT_MODE KDC_V4_NONE -/* Flag on how to handle v4 */ -static int kdc_v4; - -struct v4mode_lookup_entry { - int mode; /* Mode setting */ - const char * v4_specifier; /* How to recognize it */ -}; - -static const struct v4mode_lookup_entry v4mode_table[] = { -/* mode input specifier */ -{ KDC_V4_NONE, "none" }, -{ KDC_V4_DISABLE, "disable" }, -{ KDC_V4_FULL, "full" }, -{ KDC_V4_NOPREAUTH, "nopreauth" } -}; - -static const int v4mode_table_nents = sizeof(v4mode_table)/ - sizeof(v4mode_table[0]); - -static int allow_v4_crossrealm = 0; - -void process_v4_mode(const char *program_name, const char *string) -{ - int i, found; - - found = 0; - kdc_v4 = KDC_V4_DEFAULT_MODE; - - if(!string) return; /* Set to default mode */ - - for (i=0; iaddress; - krb5_error_code retval; - krb5_timestamp now; - KTEXT_ST v4_pkt; - char *lrealm; - - /* Check if disabled completely */ - if (kdc_v4 == KDC_V4_NONE) { - (void) klog(L_KRB_PERR, "Disabled KRB V4 request"); - return KRB5KDC_ERR_BAD_PVNO; - } - - - if ((retval = krb5_timeofday(kdc_context, &now))) - return(retval); - kerb_time.tv_sec = now; - - if (!*local_realm) { /* local-realm name already set up */ - lrealm = master_princ->realm.data; - if (master_princ->realm.length < sizeof(local_realm)) { - memcpy(local_realm, lrealm, master_princ->realm.length); - local_realm[master_princ->realm.length] = '\0'; - } else - retval = KRB5_CONFIG_NOTENUFSPACE; - } - /* convert client_fulladdr to client_sockaddr: - */ - client_sockaddr.sin_family = AF_INET; - client_sockaddr.sin_port = client_fulladdr->port; - if (client_fulladdr->address->addrtype != ADDRTYPE_INET) { - klog(L_KRB_PERR, "got krb4 request from non-ipv4 address"); - client_sockaddr.sin_addr.s_addr = 0; - } else - memcpy(&client_sockaddr.sin_addr, addr->contents, - sizeof client_sockaddr.sin_addr); - memset( client_sockaddr.sin_zero, 0, sizeof client_sockaddr.sin_zero); - - /* convert v5 packet structure to v4's. - * this copy is gross, but necessary: - */ - if (pkt->length > MAX_KTXT_LEN) { - (void) klog(L_KRB_PERR, "V4 request too long."); - return KRB5KRB_ERR_FIELD_TOOLONG; - } - memset( &v4_pkt, 0, sizeof(v4_pkt)); - v4_pkt.length = pkt->length; - v4_pkt.mbz = 0; - memcpy( v4_pkt.dat, pkt->data, pkt->length); - - *resp = kerberos_v4( &client_sockaddr, &v4_pkt); - return(retval); -} - -static char * v4_klog( int type, const char *format, ...) -{ - int logpri = LOG_INFO; - va_list pvar; - va_start(pvar, format); - - switch (type) { - case L_ERR_SEXP: - case L_ERR_NKY: - case L_ERR_NUN: - case L_ERR_UNK: - case L_KRB_PERR: - logpri = LOG_ERR; - case L_INI_REQ: - case L_NTGT_INTK: - case L_TKT_REQ: - case L_APPL_REQ: - strlcpy(log_text, "PROCESS_V4:", sizeof(log_text)); - vsnprintf(log_text+strlen(log_text), - sizeof(log_text) - strlen(log_text), - format, pvar); - krb5_klog_syslog(logpri, "%s", log_text); - default: - /* ignore the other types... */ - ; - } - va_end(pvar); - return(log_text); -} - -static -krb5_data *make_response(const char *msg, int len) -{ - krb5_data *response; - - if ( !(response = (krb5_data *) malloc( sizeof *response))) { - return 0; - } - if ( !(response->data = (char *) malloc( len))) { - krb5_free_data(kdc_context, response); - return 0; - } - response->length = len; - memcpy( response->data, msg, len); - return response; -} -static void -hang(void) -{ - if (pause_int == -1) { - klog(L_KRB_PERR, "Kerberos will pause so as not to loop init"); - /* for (;;) - pause(); */ - } else { - char buf[256]; - snprintf(buf, sizeof(buf), - "Kerberos will wait %d seconds before dying so as not to loop init", - (int) pause_int); - klog(L_KRB_PERR, buf); - sleep((unsigned) pause_int); - klog(L_KRB_PERR, "Do svedania....\n"); - /* exit(1); */ - } -} -#define kdb_encrypt_key( in, out, mk, mks, e_d_flag) -#define LONGLEN 4 -#define K4KDC_ENCTYPE_OK(e) \ -((e) == ENCTYPE_DES_CBC_CRC \ - || (e) == ENCTYPE_DES_CBC_MD4 \ - || (e) == ENCTYPE_DES_CBC_MD5 \ - || (e) == ENCTYPE_DES_CBC_RAW) - -/* take a v5 keyblock, masquerading as a v4 key, - * decrypt it, and convert the resulting v5 keyblock - * to a real v4 key. - * this is ugly, but it saves changing more v4 code. - * - * Also, keep old krb5_keyblock around in case we want to use it later. - */ -static int -compat_decrypt_key (krb5_key_data *in5, unsigned char *out4, - krb5_keyblock *out5, int issrv) -{ - krb5_error_code retval; - - out5->contents = NULL; - memset(out4, 0, sizeof(out4)); - retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_keyblock, - in5, out5, NULL); - if (retval) { - lt = klog(L_DEATH_REQ, "KDC can't decrypt principal's key."); - out5->contents = NULL; - return(retval); - } - if (K4KDC_ENCTYPE_OK(out5->enctype)) { - if (out5->length == KRB5_MIT_DES_KEYSIZE) - memcpy(out4, out5->contents, out5->length); - else { - lt = klog(L_DEATH_REQ, "internal keysize error in kdc"); - krb5_free_keyblock_contents(kdc_context, out5); - out5->contents = NULL; - retval = -1; - } - } else { - if (!issrv) { - lt = klog(L_DEATH_REQ, "incompatible principal key type."); - krb5_free_keyblock_contents(kdc_context, out5); - out5->contents = NULL; - retval = -1; - } else { - /* KLUDGE! If it's a non-raw des3 key, bash its enctype */ - if (out5->enctype == ENCTYPE_DES3_CBC_SHA1 ) - out5->enctype = ENCTYPE_DES3_CBC_RAW; - } - } - return(retval); -} - -/* array of name-components + NULL ptr - */ - -/* - * Previously this code returned either a v4 key or a v5 key and you - * could tell from the enctype of the v5 key whether the v4 key was - * useful. Now we return both keys so the code can try both des3 and - * des decryption. We fail if the ticket doesn't have a v4 key. - * Also, note as a side effect, the v5 key is basically useless in - * the client case. It is still returned so the caller can free it. - */ -static int -kerb_get_principal(char *name, char *inst, /* could have wild cards */ - Principal *principal, - int *more, /* more tuples than room for */ - krb5_keyblock *k5key, krb5_kvno kvno, - int issrv, /* true if retrieving a service key */ - krb5_deltat *k5life) -{ - /* Note that this structure should not be passed to the - krb5_free* functions, because the pointers within it point - to data with other references. */ - krb5_principal search; - - krb5_db_entry entries; /* filled in by krb5_db_get_principal() */ - int nprinc; /* how many found */ - krb5_boolean more5; /* are there more? */ - C_Block k; - short toggle = 0; - unsigned long *date; - char* text; - struct tm *tp; - krb5_key_data *pkey; - krb5_error_code retval; - - *more = 0; - /* begin setting up the principal structure - * with the first info we have: - */ - memcpy( principal->name, name, 1 + strlen( name)); - memcpy( principal->instance, inst, 1 + strlen( inst)); - - /* the principal-name format changed between v4 & v5: - * v4: name.instance@realm - * v5: realm/name/instance - * in v5, null instance means the null-component doesn't exist. - */ - - if ((retval = krb5_425_conv_principal(kdc_context, name, inst, - local_realm, &search))) - return(0); - - /* The krb4 support in the KDC is not thread-safe yet, so maintain - the global lock until that gets fixed. */ - if ((retval = get_principal_locked(kdc_context, search, &entries, - &nprinc, &more5))) { - krb5_free_principal(kdc_context, search); - return(0); - } - principal->key_low = principal->key_high = 0; - krb5_free_principal(kdc_context, search); - - if (nprinc < 1) { - *more = (int)more5 || (nprinc > 1); - return(nprinc); - } - - if (!issrv) { - if (krb5_dbe_find_enctype(kdc_context, - &entries, - ENCTYPE_DES_CBC_CRC, - KRB5_KDB_SALTTYPE_V4, - kvno, - &pkey) && - krb5_dbe_find_enctype(kdc_context, - &entries, - ENCTYPE_DES_CBC_CRC, - -1, - kvno, - &pkey)) { - lt = klog(L_KRB_PERR, - "KDC V4: principal %s.%s isn't V4 compatible", - name, inst); - krb5_db_free_principal(kdc_context, &entries, nprinc); - return(0); - } - } else { - if ( krb5_dbe_find_enctype(kdc_context, &entries, - ENCTYPE_DES_CBC_CRC, - KRB5_KDB_SALTTYPE_V4, kvno, &pkey) && - krb5_dbe_find_enctype(kdc_context, &entries, - ENCTYPE_DES_CBC_CRC, - -1, kvno, &pkey)) { - lt = klog(L_KRB_PERR, - "KDC V4: failed to find key for %s.%s #%d", - name, inst, kvno); - krb5_db_free_principal(kdc_context, &entries, nprinc); - return(0); - } - } - - if (!compat_decrypt_key(pkey, k, k5key, issrv)) { - memcpy( &principal->key_low, k, LONGLEN); - memcpy( &principal->key_high, (krb5_ui_4 *) k + 1, LONGLEN); - } - memset(k, 0, sizeof k); - if (issrv) { - krb5_free_keyblock_contents (kdc_context, k5key); - if (krb5_dbe_find_enctype(kdc_context, &entries, - ENCTYPE_DES3_CBC_RAW, - -1, kvno, &pkey) && - krb5_dbe_find_enctype(kdc_context, &entries, - ENCTYPE_DES3_CBC_SHA1, - -1, kvno, &pkey) && - krb5_dbe_find_enctype(kdc_context, &entries, - ENCTYPE_DES_CBC_CRC, - KRB5_KDB_SALTTYPE_V4, kvno, &pkey) && - krb5_dbe_find_enctype(kdc_context, &entries, - ENCTYPE_DES_CBC_CRC, - -1, kvno, &pkey)) { - lt = klog(L_KRB_PERR, - "KDC V4: failed to find key for %s.%s #%d (after having found it once)", - name, inst, kvno); - krb5_db_free_principal(kdc_context, &entries, nprinc); - return(0); - } - compat_decrypt_key(pkey, k, k5key, issrv); - memset (k, 0, sizeof k); - } - - - /* - * Convert v5's entries struct to v4's Principal struct: - * v5's time-unit for lifetimes is 1 sec, while v4 uses 5 minutes, - * and gets weirder above (128 * 300) seconds. - */ - principal->max_life = krb_time_to_life(0, entries.max_life); - if (k5life != NULL) - *k5life = entries.max_life; - /* - * This is weird, but the intent is that the expiration is the minimum - * of the principal expiration and key expiration - */ - principal->exp_date = (unsigned long) - entries.expiration && entries.pw_expiration ? - min(entries.expiration, entries.pw_expiration) : - (entries.pw_expiration ? entries.pw_expiration : - entries.expiration); -/* principal->mod_date = (unsigned long) entries.mod_date; */ -/* Set the master key version to 1. It's not really useful because all keys - * will be encrypted in the same master key version, and digging out the - * actual key version will be harder than it's worth --proven */ -/* principal->kdc_key_ver = entries.mkvno; */ - principal->kdc_key_ver = 1; - principal->key_version = pkey->key_data_kvno; - /* We overload the attributes with the relevant v5 ones */ - principal->attributes = 0; - if (isflagset(entries.attributes, KRB5_KDB_REQUIRES_HW_AUTH) || - isflagset(entries.attributes, KRB5_KDB_REQUIRES_PRE_AUTH)) { - principal->attributes |= V4_KDB_REQUIRES_PREAUTH; - } - if (isflagset(entries.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) { - principal->attributes |= V4_KDB_DISALLOW_ALL_TIX; - } - if (issrv && isflagset(entries.attributes, KRB5_KDB_DISALLOW_SVR)) { - principal->attributes |= V4_KDB_DISALLOW_SVR; - } - if (isflagset(entries.attributes, KRB5_KDB_REQUIRES_PWCHANGE)) { - principal->attributes |= V4_KDB_REQUIRES_PWCHANGE; - } - - /* set up v4 format of each date's text: */ - for ( date = &principal->exp_date, text = principal->exp_date_txt; - toggle ^= 1; - date = &principal->mod_date, text = principal->mod_date_txt) { - tp = localtime( (time_t *) date); - snprintf(text, sizeof(principal->mod_date_txt), "%4d-%02d-%02d", - tp->tm_year > 1900 ? tp->tm_year : tp->tm_year + 1900, - tp->tm_mon + 1, tp->tm_mday); /* January is 0, not 1 */ - } - /* - * free the storage held by the v5 entry struct, - * which was allocated by krb5_db_get_principal(). - * this routine clears the keyblock's contents for us. - */ - krb5_db_free_principal(kdc_context, &entries, nprinc); - *more = (int) more5 || (nprinc > 1); - return( nprinc); -} - -static void str_length_check(char *str, int max_size) -{ - int i; - char *cp; - - for (i=0, cp = str; i < max_size-1; i++, cp++) { - if (*cp == 0) - return; - } - *cp = 0; -} - -static krb5_data * -kerberos_v4(struct sockaddr_in *client, KTEXT pkt) -{ - static KTEXT_ST rpkt_st; - KTEXT rpkt = &rpkt_st; - static KTEXT_ST ciph_st; - KTEXT ciph = &ciph_st; - static KTEXT_ST tk_st; - KTEXT tk = &tk_st; - static KTEXT_ST auth_st; - KTEXT auth = &auth_st; - AUTH_DAT ad_st; - AUTH_DAT *ad = &ad_st; - krb5_data *response = 0; - - static struct in_addr client_host; - static int msg_byte_order; - static int swap_bytes; - static u_char k_flags; - /* char *p_name, *instance; */ - int lifetime = 0; - int i; - C_Block key; - Key_schedule key_s; - char *ptr; - - krb5_keyblock k5key; - krb5_kvno kvno; - krb5_deltat sk5life, ck5life; - KRB4_32 v4endtime, v4req_end; - - k5key.contents = NULL; /* in case we have to free it */ - - ciph->length = 0; - - client_host = client->sin_addr; - - /* eval macros and correct the byte order and alignment as needed */ - req_version = pkt_version(pkt); /* 1 byte, version */ - req_msg_type = pkt_msg_type(pkt); /* 1 byte, Kerberos msg type */ - - /* set these to point to something safe */ - req_name_ptr = req_inst_ptr = req_realm_ptr = ""; - - /* check if disabled, but we tell client */ - if (kdc_v4 == KDC_V4_DISABLE) { - lt = klog(L_KRB_PERR, - "KRB will not handle v4 request from %s", - inet_ntoa(client_host)); - /* send an error reply */ - req_name_ptr = req_inst_ptr = req_realm_ptr = ""; - return kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt); - } - - /* check packet version */ - if (req_version != KRB_PROT_VERSION) { - lt = klog(L_KRB_PERR, - "KRB prot version mismatch: KRB =%d request = %d", - KRB_PROT_VERSION, req_version); - /* send an error reply */ - req_name_ptr = req_inst_ptr = req_realm_ptr = ""; - return kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt); - } - msg_byte_order = req_msg_type & 1; - - swap_bytes = 0; - if (msg_byte_order != HOST_BYTE_ORDER) { - swap_bytes++; - } - klog(L_KRB_PINFO, - "Prot version: %d, Byte order: %d, Message type: %d", - (int) req_version, msg_byte_order, req_msg_type); - - switch (req_msg_type & ~1) { - - case AUTH_MSG_KDC_REQUEST: - { - int req_life; /* Requested liftime */ - unsigned int request_backdate = 0; /*How far to backdate - in seconds.*/ - char *service; /* Service name */ - char *instance; /* Service instance */ -#ifdef notdef - int kerno; /* Kerberos error number */ -#endif - n_auth_req++; - tk->length = 0; - k_flags = 0; /* various kerberos flags */ - - - /* set up and correct for byte order and alignment */ - req_name_ptr = (char *) pkt_a_name(pkt); - str_length_check(req_name_ptr, ANAME_SZ); - req_inst_ptr = (char *) pkt_a_inst(pkt); - str_length_check(req_inst_ptr, INST_SZ); - req_realm_ptr = (char *) pkt_a_realm(pkt); - str_length_check(req_realm_ptr, REALM_SZ); - memcpy(&req_time_ws, pkt_time_ws(pkt), sizeof(req_time_ws)); - /* time has to be diddled */ - if (swap_bytes) { - swap_u_long(req_time_ws); - } - ptr = (char *) pkt_time_ws(pkt) + 4; - - req_life = (*ptr++) & 0xff; - - service = ptr; - str_length_check(service, SNAME_SZ); - instance = ptr + strlen(service) + 1; - str_length_check(instance, INST_SZ); - - rpkt = &rpkt_st; - - klog(L_INI_REQ, - "Initial ticket request Host: %s User: \"%s\" \"%s\"", - inet_ntoa(client_host), req_name_ptr, req_inst_ptr); - - if ((i = check_princ(req_name_ptr, req_inst_ptr, 0, - &a_name_data, &k5key, 0, &ck5life))) { - response = kerb_err_reply(client, pkt, i, "check_princ failed"); - a_name_data.key_low = a_name_data.key_high = 0; - krb5_free_keyblock_contents(kdc_context, &k5key); - return response; - } - /* don't use k5key for client */ - krb5_free_keyblock_contents(kdc_context, &k5key); - tk->length = 0; /* init */ - if (strcmp(service, "krbtgt")) - klog(L_NTGT_INTK, - "INITIAL request from %s.%s for %s.%s", req_name_ptr, - req_inst_ptr, service, instance); - /* this does all the checking */ - if ((i = check_princ(service, instance, lifetime, - &s_name_data, &k5key, 1, &sk5life))) { - response = kerb_err_reply(client, pkt, i, "check_princ failed"); - a_name_data.key_high = a_name_data.key_low = 0; - s_name_data.key_high = s_name_data.key_low = 0; - krb5_free_keyblock_contents(kdc_context, &k5key); - return response; - } - /* Bound requested lifetime with service and user */ - v4req_end = krb_life_to_time(kerb_time.tv_sec, req_life); - v4req_end = min(v4req_end, kerb_time.tv_sec + ck5life); - v4req_end = min(v4req_end, kerb_time.tv_sec + sk5life); - lifetime = krb_time_to_life(kerb_time.tv_sec, v4req_end); - v4endtime = krb_life_to_time(kerb_time.tv_sec, lifetime); - /* - * Adjust issue time backwards if necessary, due to - * roundup in krb_time_to_life(). - */ - if (v4endtime > v4req_end) - request_backdate = v4endtime - v4req_end; - -#ifdef NOENCRYPTION - memset(session_key, 0, sizeof(C_Block)); -#else - /* random session key */ - des_new_random_key(session_key); -#endif - - /* unseal server's key from master key */ - memcpy( key, &s_name_data.key_low, 4); - memcpy( ((krb5_ui_4 *) key) + 1, &s_name_data.key_high, 4); - - s_name_data.key_low = s_name_data.key_high = 0; - kdb_encrypt_key(key, key, master_key, - master_key_schedule, DECRYPT); - /* construct and seal the ticket */ - /* We always issue des tickets; the 3des tickets are a broken hack*/ - krb_create_ticket(tk, k_flags, a_name_data.name, - a_name_data.instance, local_realm, - client_host.s_addr, (char *) session_key, - lifetime, kerb_time.tv_sec - request_backdate, - s_name_data.name, s_name_data.instance, - key); - - krb5_free_keyblock_contents(kdc_context, &k5key); - memset(key, 0, sizeof(key)); - memset(key_s, 0, sizeof(key_s)); - - /* - * get the user's key, unseal it from the server's key, and - * use it to seal the cipher - */ - - /* a_name_data.key_low a_name_data.key_high */ - memcpy( key, &a_name_data.key_low, 4); - memcpy( ((krb5_ui_4 *) key) + 1, &a_name_data.key_high, 4); - a_name_data.key_low= a_name_data.key_high = 0; - - /* unseal the a_name key from the master key */ - kdb_encrypt_key(key, key, master_key, - master_key_schedule, DECRYPT); - - create_ciph(ciph, session_key, s_name_data.name, - s_name_data.instance, local_realm, lifetime, - s_name_data.key_version, tk, kerb_time.tv_sec, key); - - /* clear session key */ - memset(session_key, 0, sizeof(session_key)); - - memset(key, 0, sizeof(key)); - - - - /* always send a reply packet */ - rpkt = create_auth_reply(req_name_ptr, req_inst_ptr, - req_realm_ptr, req_time_ws, 0, a_name_data.exp_date, - a_name_data.key_version, ciph); - response = make_response((char *) rpkt->dat, rpkt->length); - memset(&a_name_data, 0, sizeof(a_name_data)); - memset(&s_name_data, 0, sizeof(s_name_data)); - break; - } - case AUTH_MSG_APPL_REQUEST: - { - krb5_ui_4 time_ws; /* Workstation time */ - int req_life; /* Requested liftime */ - char *service; /* Service name */ - char *instance; /* Service instance */ - int kerno = 0; /* Kerberos error number */ - unsigned int request_backdate = 0; /*How far to backdate - in seconds.*/ - char tktrlm[REALM_SZ]; - - n_appl_req++; - tk->length = 0; - k_flags = 0; /* various kerberos flags */ - - auth->mbz = 0; /* pkt->mbz already zeroed */ - auth->length = 4 + strlen((char *)pkt->dat + 3); - if (auth->length + 1 >= MAX_KTXT_LEN) { - lt = klog(L_KRB_PERR, - "APPL request with realm length too long from %s", - inet_ntoa(client_host)); - return kerb_err_reply(client, pkt, RD_AP_INCON, - "realm length too long"); - } - - auth->length += (int) *(pkt->dat + auth->length) + - (int) *(pkt->dat + auth->length + 1) + 2; - if (auth->length > MAX_KTXT_LEN) { - lt = klog(L_KRB_PERR, - "APPL request with funky tkt or req_id length from %s", - inet_ntoa(client_host)); - return kerb_err_reply(client, pkt, RD_AP_INCON, - "funky tkt or req_id length"); - } - - memcpy(auth->dat, pkt->dat, auth->length); - - strncpy(tktrlm, (char *)auth->dat + 3, REALM_SZ); - tktrlm[REALM_SZ-1] = '\0'; - kvno = (krb5_kvno)auth->dat[2]; - if ((!allow_v4_crossrealm)&&strcmp(tktrlm, local_realm) != 0) { - lt = klog(L_ERR_UNK, - "Cross realm ticket from %s denied by policy,", tktrlm); - return kerb_err_reply(client, pkt, - KERB_ERR_PRINCIPAL_UNKNOWN, lt); - } - if (set_tgtkey(tktrlm, kvno, 0)) { - lt = klog(L_ERR_UNK, - "FAILED set_tgtkey realm %s, kvno %d. Host: %s ", - tktrlm, kvno, inet_ntoa(client_host)); - /* no better error code */ - return kerb_err_reply(client, pkt, - KERB_ERR_PRINCIPAL_UNKNOWN, lt); - } - kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr, - ad, 0); - if (kerno) { - if (set_tgtkey(tktrlm, kvno, 1)) { - lt = klog(L_ERR_UNK, - "FAILED 3des set_tgtkey realm %s, kvno %d. Host: %s ", - tktrlm, kvno, inet_ntoa(client_host)); - /* no better error code */ - return kerb_err_reply(client, pkt, - KERB_ERR_PRINCIPAL_UNKNOWN, lt); - } - kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr, - ad, 0); - } - - if (kerno) { - klog(L_ERR_UNK, "FAILED krb_rd_req from %s: %s", - inet_ntoa(client_host), krb_get_err_text(kerno)); - req_name_ptr = req_inst_ptr = req_realm_ptr = ""; - return kerb_err_reply(client, pkt, kerno, "krb_rd_req failed"); - } - ptr = (char *) pkt->dat + auth->length; - - memcpy(&time_ws, ptr, 4); - ptr += 4; - - req_life = (*ptr++) & 0xff; - - service = ptr; - str_length_check(service, SNAME_SZ); - instance = ptr + strlen(service) + 1; - str_length_check(instance, INST_SZ); - - klog(L_APPL_REQ, "APPL Request %s.%s@%s on %s for %s.%s", - ad->pname, ad->pinst, ad->prealm, - inet_ntoa(client_host), service, instance); - req_name_ptr = ad->pname; - req_inst_ptr = ad->pinst; - req_realm_ptr = ad->prealm; - - if (strcmp(ad->prealm, tktrlm)) { - return kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN, - "Can't hop realms"); - } - if (!strcmp(service, "changepw")) { - return kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN, - "Can't authorize password changed based on TGT"); - } - kerno = check_princ(service, instance, req_life, - &s_name_data, &k5key, 1, &sk5life); - if (kerno) { - response = kerb_err_reply(client, pkt, kerno, - "check_princ failed"); - s_name_data.key_high = s_name_data.key_low = 0; - krb5_free_keyblock_contents(kdc_context, &k5key); - return response; - } - /* Bound requested lifetime with service and user */ - v4endtime = krb_life_to_time((KRB4_32)ad->time_sec, ad->life); - v4req_end = krb_life_to_time(kerb_time.tv_sec, req_life); - v4req_end = min(v4endtime, v4req_end); - v4req_end = min(v4req_end, kerb_time.tv_sec + sk5life); - - lifetime = krb_time_to_life(kerb_time.tv_sec, v4req_end); - v4endtime = krb_life_to_time(kerb_time.tv_sec, lifetime); - /* - * Adjust issue time backwards if necessary, due to - * roundup in krb_time_to_life(). - */ - if (v4endtime > v4req_end) - request_backdate = v4endtime - v4req_end; - - /* unseal server's key from master key */ - memcpy(key, &s_name_data.key_low, 4); - memcpy(((krb5_ui_4 *) key) + 1, &s_name_data.key_high, 4); - s_name_data.key_low = s_name_data.key_high = 0; - kdb_encrypt_key(key, key, master_key, - master_key_schedule, DECRYPT); - /* construct and seal the ticket */ - -#ifdef NOENCRYPTION - memset(session_key, 0, sizeof(C_Block)); -#else - /* random session key */ - des_new_random_key(session_key); -#endif - - /* ALways issue des tickets*/ - krb_create_ticket(tk, k_flags, ad->pname, ad->pinst, - ad->prealm, client_host.s_addr, - (char *) session_key, lifetime, - kerb_time.tv_sec - request_backdate, - s_name_data.name, s_name_data.instance, - key); - krb5_free_keyblock_contents(kdc_context, &k5key); - memset(key, 0, sizeof(key)); - memset(key_s, 0, sizeof(key_s)); - - create_ciph(ciph, session_key, service, instance, - local_realm, - lifetime, s_name_data.key_version, tk, - kerb_time.tv_sec, ad->session); - - /* clear session key */ - memset(session_key, 0, sizeof(session_key)); - - memset(ad->session, 0, sizeof(ad->session)); - - rpkt = create_auth_reply(ad->pname, ad->pinst, - ad->prealm, time_ws, - 0, 0, 0, ciph); - response = make_response((char *) rpkt->dat, rpkt->length); - memset(&s_name_data, 0, sizeof(s_name_data)); - break; - } - - -#ifdef notdef_DIE - case AUTH_MSG_DIE: - { - lt = klog(L_DEATH_REQ, - "Host: %s User: \"%s\" \"%s\" Kerberos killed", - inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0); - exit(0); - } -#endif /* notdef_DIE */ - - default: - { - lt = klog(L_KRB_PERR, - "Unknown message type: %d from %s port %u", - req_msg_type, inet_ntoa(client_host), - ntohs(client->sin_port)); - break; - } - } - return response; -} - - - -/* - * kerb_er_reply creates an error reply packet and sends it to the - * client. - */ - -static krb5_data * -kerb_err_reply(struct sockaddr_in *client, KTEXT pkt, long int err, char *string) -{ - static KTEXT_ST e_pkt_st; - KTEXT e_pkt = &e_pkt_st; - static char e_msg[128]; - - snprintf(e_msg, sizeof(e_msg), "\nKerberos error -- %s", string); - cr_err_reply(e_pkt, req_name_ptr, req_inst_ptr, req_realm_ptr, - req_time_ws, err, e_msg); - return make_response((char *) e_pkt->dat, e_pkt->length); -} - -static int -check_princ(char *p_name, char *instance, int lifetime, Principal *p, - krb5_keyblock *k5key, int issrv, krb5_deltat *k5life) -{ - static int n; - static int more; - /* long trans; */ - - n = kerb_get_principal(p_name, instance, p, &more, k5key, 0, - issrv, k5life); - klog(L_ALL_REQ, - "Principal: \"%s\", Instance: \"%s\" Lifetime = %d n = %d", - p_name, instance, lifetime, n); - - if (n < 0) { - lt = klog(L_KRB_PERR, "Database unavailable!"); - p->key_high = p->key_low = 0; - hang(); - } - - /* - * if more than one p_name, pick one, randomly create a session key, - * compute maximum lifetime, lookup authorizations if applicable, - * and stuff into cipher. - */ - if (n == 0) { - /* service unknown, log error, skip to next request */ - lt = klog(L_ERR_UNK, "UNKNOWN \"%s\" \"%s\"", p_name, instance); - return KERB_ERR_PRINCIPAL_UNKNOWN; - } - if (more) { - /* not unique, log error */ - lt = klog(L_ERR_NUN, "Principal NOT UNIQUE \"%s\" \"%s\"", - p_name, instance); - return KERB_ERR_PRINCIPAL_NOT_UNIQUE; - } - - /* - * Check our V5 stuff first. - */ - - /* - * Does the principal have REQUIRES_PWCHANGE set? - */ - if (isflagset(p->attributes, V4_KDB_REQUIRES_PWCHANGE)) { - lt = klog(L_ERR_SEXP, "V5 REQUIRES_PWCHANGE set " - "\"%s\" \"%s\"", p_name, instance); - return KERB_ERR_NAME_EXP; - } - - /* - * Does the principal have DISALLOW_ALL_TIX set? - */ - if (isflagset(p->attributes, V4_KDB_DISALLOW_ALL_TIX)) { - lt = klog(L_ERR_SEXP, "V5 DISALLOW_ALL_TIX set: " - "\"%s\" \"%s\"", p_name, instance); - /* Not sure of a better error to return */ - return KERB_ERR_NAME_EXP; - } - - if (isflagset(p->attributes, V4_KDB_DISALLOW_SVR)) { - lt = klog(L_ERR_SEXP, "V5 DISALLOW_SVR set: " - "\"%s\" \"%s\"", p_name, instance); - /* Not sure of a better error to return */ - return KERB_ERR_NAME_EXP; - } - - /* - * Does the principal require preauthentication? - */ - if ((kdc_v4 == KDC_V4_NOPREAUTH) && - isflagset(p->attributes, V4_KDB_REQUIRES_PREAUTH)) { - lt = klog(L_ERR_SEXP, "V5 REQUIRES_PREAUTH set: " - "\"%s\" \"%s\"", p_name, instance); - /* Not sure of a better error to return */ - return KERB_ERR_AUTH_EXP; -/* return KERB_ERR_NAME_EXP;*/ - } - - /* If the user's key is null, we want to return an error */ - if (k5key->contents != NULL && K4KDC_ENCTYPE_OK(k5key->enctype)) { - if ((p->key_low == 0) && (p->key_high == 0)) { - /* User has a null key */ - lt = klog(L_ERR_NKY, "Null key \"%s\" \"%s\"", p_name, instance); - return KERB_ERR_NULL_KEY; - } - } - /* make sure the service hasn't expired */ - if (((u_long) p->exp_date != 0)&& - ((u_long) p->exp_date <(u_long) kerb_time.tv_sec)) { - /* service did expire, log it */ - char timestr[40]; - struct tm *tm; - time_t t = p->exp_date; - - tm = localtime(&t); - if (!strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm)) - timestr[0] = '\0'; - lt = klog(L_ERR_SEXP, - "EXPIRED \"%s\" \"%s\" %s", p->name, p->instance, timestr); - return KERB_ERR_NAME_EXP; - } - /* ok is zero */ - return 0; -} - - -/* Set the key for krb_rd_req so we can check tgt */ -static int -set_tgtkey(char *r, krb5_kvno kvno, krb5_boolean use_3des) -{ - int n; - static char lastrealm[REALM_SZ] = ""; - static int last_kvno = 0; - static krb5_boolean last_use_3des = 0; - static int more; - Principal p_st; - Principal *p = &p_st; - C_Block key; - krb5_keyblock k5key; - - k5key.contents = NULL; - if (!strcmp(lastrealm, r) && last_kvno == kvno && last_use_3des == use_3des) - return (KSUCCESS); - -/* log("Getting key for %s", r); */ - - n = kerb_get_principal("krbtgt", r, p, &more, &k5key, kvno, 1, NULL); - if (n == 0) - return (KFAILURE); - - if (isflagset(p->attributes, V4_KDB_DISALLOW_ALL_TIX)) { - lt = klog(L_ERR_SEXP, - "V5 DISALLOW_ALL_TIX set: \"krbtgt\" \"%s\"", r); - krb5_free_keyblock_contents(kdc_context, &k5key); - return KFAILURE; - } - - if (isflagset(p->attributes, V4_KDB_DISALLOW_SVR)) { - lt = klog(L_ERR_SEXP, "V5 DISALLOW_SVR set: \"krbtgt\" \"%s\"", r); - krb5_free_keyblock_contents(kdc_context, &k5key); - return KFAILURE; - } - - if (use_3des&&!K4KDC_ENCTYPE_OK(k5key.enctype)) { - krb_set_key_krb5(kdc_context, &k5key); - strncpy(lastrealm, r, sizeof(lastrealm) - 1); - lastrealm[sizeof(lastrealm) - 1] = '\0'; - last_kvno = kvno; - last_use_3des = use_3des; - } else { - /* unseal tgt key from master key */ - memcpy(key, &p->key_low, 4); - memcpy(((krb5_ui_4 *) key) + 1, &p->key_high, 4); - kdb_encrypt_key(key, key, master_key, - master_key_schedule, DECRYPT); - krb_set_key((char *) key, 0); - strncpy(lastrealm, r, sizeof(lastrealm) - 1); - lastrealm[sizeof(lastrealm) - 1] = '\0'; - last_kvno = kvno; - } - krb5_free_keyblock_contents(kdc_context, &k5key); - return (KSUCCESS); -} - -#else /* KRB5_KRB4_COMPAT */ -#include "k5-int.h" -#endif /* KRB5_KRB4_COMPAT */ diff --git a/src/kdc/krb5kdc.M b/src/kdc/krb5kdc.M index e8758dade..80e232023 100644 --- a/src/kdc/krb5kdc.M +++ b/src/kdc/krb5kdc.M @@ -47,9 +47,6 @@ krb5kdc \- Kerberos V5 KDC .B \-r .I realm ] [ -.B \-4 -.I v4mode -] [ .B \-n ] .br @@ -131,23 +128,6 @@ option specifies that the master database password should be fetched from the keyboard rather than from a file on disk. .PP The -.B \-4 -option specifies how the KDC responds to kerberos IV requests for -tickets. The command line option overrides the value in the KDC -profile. The possible values are -.I none, -.I disable, -.I full -or -.I nopreauth. -These instruct the KDC to not respond to V4 packets, to -respond with a version skew error, to issue tickets for all database -entries, and to issue tickets for all but preauthentication required -database entries respectively. The default behaviour is as if -.I none -was specified. -.PP -The .B \-n option specifies that the KDC does not put itself in the background and does not disassociate itself from the terminal. In normal diff --git a/src/kdc/main.c b/src/kdc/main.c index 9416cbbd8..fabaca9b2 100644 --- a/src/kdc/main.c +++ b/src/kdc/main.c @@ -45,10 +45,6 @@ #include #endif -#ifdef KRB5_KRB4_COMPAT -#include -#endif - #if defined(NEED_DAEMON_PROTO) extern int daemon(int, int); #endif @@ -310,9 +306,6 @@ init_realm(char *progname, kdc_realm_t *rdp, char *realm, if (!rkey_init_done) { krb5_data seed; -#ifdef KRB5_KRB4_COMPAT - krb5_keyblock temp_key; -#endif /* * If all that worked, then initialize the random key * generators. @@ -325,17 +318,6 @@ init_realm(char *progname, kdc_realm_t *rdp, char *realm, KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed))) goto whoops; -#ifdef KRB5_KRB4_COMPAT - if ((kret = krb5_c_make_random_key(rdp->realm_context, - ENCTYPE_DES_CBC_CRC, &temp_key))) { - com_err(progname, kret, - "while initializing V4 random key generator"); - goto whoops; - } - - (void) des_init_random_number_generator(temp_key.contents); - krb5_free_keyblock_contents(rdp->realm_context, &temp_key); -#endif rkey_init_done = 1; } whoops: @@ -405,7 +387,7 @@ setup_sam(void) void usage(char *name) { - fprintf(stderr, "usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname]\n\t\t[-R replaycachename] [-m] [-k masterenctype] [-M masterkeyname]\n\t\t[-p port] [-4 v4mode] [-X] [-n]\n" + fprintf(stderr, "usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname]\n\t\t[-R replaycachename] [-m] [-k masterenctype] [-M masterkeyname]\n\t\t[-p port] [-n]\n" "\nwhere,\n\t[-x db_args]* - Any number of database specific arguments. Look at\n" "\t\t\teach database module documentation for supported\n\t\t\targuments\n", name); @@ -431,9 +413,6 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) char **db_args = NULL; int db_args_size = 0; -#ifdef KRB5_KRB4_COMPAT - char *v4mode = 0; -#endif extern char *optarg; if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) { @@ -445,11 +424,6 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) hierarchy[1] = "kdc_tcp_ports"; if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports)) default_tcp_ports = 0; -#ifdef KRB5_KRB4_COMPAT - hierarchy[1] = "v4_mode"; - if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &v4mode)) - v4mode = 0; -#endif /* aprof_init can return 0 with aprof == NULL */ if (aprof) krb5_aprof_finish(aprof); @@ -559,17 +533,9 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) #endif break; case '4': -#ifdef KRB5_KRB4_COMPAT - if (v4mode) - free(v4mode); - v4mode = strdup(optarg); -#endif break; case 'X': -#ifdef KRB5_KRB4_COMPAT - enable_v4_crossrealm(argv[0]); -#endif - break; + break; case '?': default: usage(argv[0]); @@ -577,14 +543,6 @@ initialize_realms(krb5_context kcontext, int argc, char **argv) } } -#ifdef KRB5_KRB4_COMPAT - /* - * Setup the v4 mode - */ - process_v4_mode(argv[0], v4mode); - free(v4mode); -#endif - /* * Check to see if we processed any realms. */ -- 2.26.2