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 \
$(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 \
policy.o \
extern.o \
replay.o \
- kdc_authdata.o \
- kerberos_v4.o
+ kdc_authdata.o
RT_OBJS= rtest.o \
kdc_util.o \
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
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 +++
#
$(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
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
+++ /dev/null
-.\" 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)
+++ /dev/null
-/*
- * 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 <kenh@cmf.nrl.navy.mil>
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <ctype.h>
-#include <errno.h>
-#include <netdb.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-
-#include <krb5.h>
-#include <kadm5/admin.h>
-#include <com_err.h>
-#include <kerberosIV/krb.h>
-#include <kerberosIV/des.h>
-#include <k5-platform.h>
-
-#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/<cell name>@<realm name>
- */
- 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*/
-}
#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))
+++ /dev/null
-/*
- * 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 <stdarg.h>
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <signal.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#ifdef TIME_WITH_SYS_TIME
-#include <time.h>
-#endif
-#else
-#include <time.h>
-#endif
-#include <sys/file.h>
-#include <ctype.h>
-#include <syslog.h>
-#include <string.h>
-#include <errno.h>
-
-/* v4 include files:
- */
-#include <krb.h>
-#include <des.h>
-#include <klog.h>
-#include <prot.h>
-#include <krb_db.h>
-
-#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; i<v4mode_table_nents; i++) {
- if (!strcasecmp(string, v4mode_table[i].v4_specifier)) {
- found = 1;
- kdc_v4 = v4mode_table[i].mode;
- break;
- }
- }
-
- if(!found) {
- /* It is considered fatal if we request a mode that is not found */
- com_err(program_name, 0, "invalid v4_mode %s", string);
- exit(1);
- }
- return;
-}
-
-void enable_v4_crossrealm ( char *programname) {
- allow_v4_crossrealm = 1;
- krb5_klog_syslog(LOG_ERR, "Enabling v4 cross-realm compatibility; this is a known security hole");
-}
-
-krb5_error_code
-process_v4(const krb5_data *pkt, const krb5_fulladdr *client_fulladdr,
- krb5_data **resp)
-{
- struct sockaddr_in client_sockaddr;
- krb5_address *addr = client_fulladdr->address;
- 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 */
.B \-r
.I realm
] [
-.B \-4
-.I v4mode
-] [
.B \-n
]
.br
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
#include <netinet/in.h>
#endif
-#ifdef KRB5_KRB4_COMPAT
-#include <des.h>
-#endif
-
#if defined(NEED_DAEMON_PROTO)
extern int daemon(int, int);
#endif
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.
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:
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);
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)) {
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);
#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]);
}
}
-#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.
*/