not actually hooked in yet, but getting it in so we can work with it.
--- /dev/null
+#
+# $Id$
+#
+
+include $(top_srcdir)/Makefile.am.common
+
+noinst_LTLIBRARIES = librxgkclient.la librxgkserver.la
+
+noinst_PROGRAMS = test_client test_server
+
+INCLUDES += -I. \
+ -I$(srcdir) \
+ -I../include \
+ -I$(srcdir)/../include \
+ -I.. -I$(srcdir)/.. \
+ $(INC_roken) \
+ $(KRB5_INC_FLAGS)
+
+librxgkclient_la_SOURCES = \
+ rxgk_locl.h \
+ rxgk_proto.h \
+ rxgk_clnt.c \
+ rxgk_info.c \
+ rxgk_crpc.c \
+ rxgk_crkrb.c \
+ rxgk_common.c \
+ rxgk_proto.ydr.c \
+ rxgk_proto.cs.c
+
+librxgkserver_la_SOURCES = \
+ rxgk_locl.h \
+ rxgk_proto.h \
+ rxgk_serv.c \
+ rxgk_info.c \
+ rxgk_srpc.c \
+ rxgk_crkrb.c \
+ rxgk_common.c \
+ rxgk_proto.ydr.c \
+ rxgk_proto.ss.c
+
+LIBYDR = \
+ rxgk_proto.cs.c \
+ rxgk_proto.ss.c \
+ rxgk_proto.ydr.c \
+ rxgk_proto.h \
+ rxgk_proto.cs.h \
+ rxgk_proto.ss.h
+
+LIBTYDR = \
+ test.cs.h \
+ test.ss.h \
+ test.ss.c \
+ test.cs.c \
+ test.ydr.c \
+ test.h
+
+common_LDADD = \
+ ../rx/librx.la \
+ -L../lwp -llwp $(PLWP_LIB_FLAGS) \
+ $(KRB5_LIB_FLAGS)
+
+test_client_SOURCES = test_client.c test.cs.c
+test_server_SOURCES = test_server.c test.ss.c
+
+test_client_LDADD = librxgkclient.la $(common_LDADD)
+test_server_LDADD = librxgkserver.la $(common_LDADD)
+
+$(librxgkclient_la_OBJECTS) $(librxgkserver_la_OBJECTS): $(LIBYDR)
+
+$(test_server_OBJECTS) $(test_client_OBJECTS): $(LIBTYDR)
+
+$(LIBYDR): rxgk_proto.xg
+ ../ydr/ydr $(srcdir)/rxgk_proto.xg
+
+$(LIBTYDR): test.xg
+ ../ydr/ydr $(srcdir)/test.xg
+
+CLEANFILES = $(LIBYDR) $(LIBTYDR)
+
+LDADD = $(KRB5_LIB_FLAGS)
--- /dev/null
+# Makefile.in generated by automake 1.8.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# $Id$
+#
+
+# $Id$
+
+# $Id$
+
+
+SOURCES = $(librxgkclient_la_SOURCES) $(librxgkserver_la_SOURCES) $(test_client_SOURCES) $(test_server_SOURCES)
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(top_srcdir)/Makefile.am.common \
+ $(top_srcdir)/cf/Makefile.am.common
+noinst_PROGRAMS = test_client$(EXEEXT) test_server$(EXEEXT)
+subdir = rxgk
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/cf/__extentions__.m4 \
+ $(top_srcdir)/cf/arla-canonical.m4 \
+ $(top_srcdir)/cf/arla-openssl-compat.m4 \
+ $(top_srcdir)/cf/broken-getaddrinfo.m4 \
+ $(top_srcdir)/cf/broken-getnameinfo.m4 \
+ $(top_srcdir)/cf/broken-glob.m4 \
+ $(top_srcdir)/cf/broken-realloc.m4 \
+ $(top_srcdir)/cf/broken-snprintf.m4 $(top_srcdir)/cf/broken.m4 \
+ $(top_srcdir)/cf/broken2.m4 \
+ $(top_srcdir)/cf/bsd-func-lockmgr.m4 \
+ $(top_srcdir)/cf/bsd-func-lockstatus.m4 \
+ $(top_srcdir)/cf/bsd-func-selrecord.m4 \
+ $(top_srcdir)/cf/bsd-func-suser.m4 \
+ $(top_srcdir)/cf/bsd-func-vfs-getnewfsid.m4 \
+ $(top_srcdir)/cf/bsd-header-vnode-if-h.m4 \
+ $(top_srcdir)/cf/bsd-uvm-only.m4 \
+ $(top_srcdir)/cf/bsd-vfs-busy.m4 \
+ $(top_srcdir)/cf/bsd-vfs-object-create.m4 \
+ $(top_srcdir)/cf/bsd-vget.m4 $(top_srcdir)/cf/bsd-vop-lock.m4 \
+ $(top_srcdir)/cf/c-attribute.m4 $(top_srcdir)/cf/c-function.m4 \
+ $(top_srcdir)/cf/check-declaration.m4 \
+ $(top_srcdir)/cf/check-dirsiz.m4 \
+ $(top_srcdir)/cf/check-glibc.m4 $(top_srcdir)/cf/check-kafs.m4 \
+ $(top_srcdir)/cf/check-kerberos.m4 \
+ $(top_srcdir)/cf/check-kernel-func.m4 \
+ $(top_srcdir)/cf/check-kernel-funcs.m4 \
+ $(top_srcdir)/cf/check-kernel-var.m4 \
+ $(top_srcdir)/cf/check-kernel-vop-t.m4 \
+ $(top_srcdir)/cf/check-kernel.m4 $(top_srcdir)/cf/check-lfs.m4 \
+ $(top_srcdir)/cf/check-man.m4 \
+ $(top_srcdir)/cf/check-netinet-ip-and-tcp.m4 \
+ $(top_srcdir)/cf/check-roken.m4 $(top_srcdir)/cf/check-sl.m4 \
+ $(top_srcdir)/cf/check-var.m4 $(top_srcdir)/cf/check-x.m4 \
+ $(top_srcdir)/cf/db.m4 $(top_srcdir)/cf/elf-object-format.m4 \
+ $(top_srcdir)/cf/find-func-no-libs.m4 \
+ $(top_srcdir)/cf/find-func-no-libs2.m4 \
+ $(top_srcdir)/cf/find-func.m4 \
+ $(top_srcdir)/cf/find-if-not-broken.m4 \
+ $(top_srcdir)/cf/func-ntohl.m4 \
+ $(top_srcdir)/cf/have-kernel-struct-field.m4 \
+ $(top_srcdir)/cf/have-linux-kernel-type.m4 \
+ $(top_srcdir)/cf/have-linux-kernel-types.m4 \
+ $(top_srcdir)/cf/have-struct-field.m4 \
+ $(top_srcdir)/cf/have-type.m4 $(top_srcdir)/cf/have-types.m4 \
+ $(top_srcdir)/cf/header-dirent-dir-h.m4 \
+ $(top_srcdir)/cf/kafs-settoken-rxkad.m4 \
+ $(top_srcdir)/cf/kernel-have-def.m4 \
+ $(top_srcdir)/cf/kernel-need-proto.m4 \
+ $(top_srcdir)/cf/kernel.m4 $(top_srcdir)/cf/krb-bigendian.m4 \
+ $(top_srcdir)/cf/krb-func-getlogin.m4 \
+ $(top_srcdir)/cf/krb-ipv6.m4 \
+ $(top_srcdir)/cf/krb-struct-spwd.m4 \
+ $(top_srcdir)/cf/krb-struct-winsize.m4 \
+ $(top_srcdir)/cf/krb-sys-aix.m4 \
+ $(top_srcdir)/cf/krb-version.m4 \
+ $(top_srcdir)/cf/linux-func-init-mutex.m4 \
+ $(top_srcdir)/cf/linux-getattr-three-args.m4 \
+ $(top_srcdir)/cf/mips-abi.m4 $(top_srcdir)/cf/misc.m4 \
+ $(top_srcdir)/cf/need-proto.m4 \
+ $(top_srcdir)/cf/osf-func-ubc-lookup.m4 \
+ $(top_srcdir)/cf/osf-func-vfs-name-hash.m4 \
+ $(top_srcdir)/cf/prog-cc-flags.m4 \
+ $(top_srcdir)/cf/proto-compat.m4 \
+ $(top_srcdir)/cf/retsigtype.m4 $(top_srcdir)/cf/roken-frag.m4 \
+ $(top_srcdir)/cf/subst-val.m4 $(top_srcdir)/cf/test-package.m4 \
+ $(top_srcdir)/cf/try-compile-kernel.m4 \
+ $(top_srcdir)/cf/try-cpp-kernel.m4 \
+ $(top_srcdir)/cf/type-iovec.m4 $(top_srcdir)/cf/type-msghdr.m4 \
+ $(top_srcdir)/cf/werror.m4 $(top_srcdir)/cf/wflags.m4 \
+ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/include/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+librxgkclient_la_LIBADD =
+am_librxgkclient_la_OBJECTS = rxgk_clnt.lo rxgk_info.lo rxgk_crpc.lo \
+ rxgk_crkrb.lo rxgk_common.lo rxgk_proto.ydr.lo \
+ rxgk_proto.cs.lo
+librxgkclient_la_OBJECTS = $(am_librxgkclient_la_OBJECTS)
+librxgkserver_la_LIBADD =
+am_librxgkserver_la_OBJECTS = rxgk_serv.lo rxgk_info.lo rxgk_srpc.lo \
+ rxgk_crkrb.lo rxgk_common.lo rxgk_proto.ydr.lo \
+ rxgk_proto.ss.lo
+librxgkserver_la_OBJECTS = $(am_librxgkserver_la_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+am_test_client_OBJECTS = test_client.$(OBJEXT) test.cs.$(OBJEXT)
+test_client_OBJECTS = $(am_test_client_OBJECTS)
+am__DEPENDENCIES_1 =
+am__DEPENDENCIES_2 = ../rx/librx.la $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+test_client_DEPENDENCIES = librxgkclient.la $(am__DEPENDENCIES_2)
+am_test_server_OBJECTS = test_server.$(OBJEXT) test.ss.$(OBJEXT)
+test_server_OBJECTS = $(am_test_server_OBJECTS)
+test_server_DEPENDENCIES = librxgkserver.la $(am__DEPENDENCIES_2)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(librxgkclient_la_SOURCES) $(librxgkserver_la_SOURCES) \
+ $(test_client_SOURCES) $(test_server_SOURCES)
+DIST_SOURCES = $(librxgkclient_la_SOURCES) $(librxgkserver_la_SOURCES) \
+ $(test_client_SOURCES) $(test_server_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AFS_EXTRA_DEFS = @AFS_EXTRA_DEFS@
+AFS_EXTRA_LD = @AFS_EXTRA_LD@
+AFS_EXTRA_LIBS = @AFS_EXTRA_LIBS@
+AFS_EXTRA_OBJS = @AFS_EXTRA_OBJS@
+AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@
+AMTAR = @AMTAR@
+AR = @AR@
+ARLACACHEDIR = @ARLACACHEDIR@
+ARLACONFFILE = @ARLACONFFILE@
+ARLA_CONF_HIGHBYTES = @ARLA_CONF_HIGHBYTES@
+ARLA_CONF_HIGHVNODES = @ARLA_CONF_HIGHVNODES@
+ARLA_CONF_LOWBYTES = @ARLA_CONF_LOWBYTES@
+ARLA_CONF_LOWVNODES = @ARLA_CONF_LOWVNODES@
+ARLA_KNFS = @ARLA_KNFS@
+ARLA_LOCAL_ROKEN_FALSE = @ARLA_LOCAL_ROKEN_FALSE@
+ARLA_LOCAL_ROKEN_TRUE = @ARLA_LOCAL_ROKEN_TRUE@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BSDMAKE = @BSDMAKE@
+BSD_WERROR = @BSD_WERROR@
+CANONICAL_HOST = @CANONICAL_HOST@
+CATMAN = @CATMAN@
+CATMANEXT = @CATMANEXT@
+CATMAN_FALSE = @CATMAN_FALSE@
+CATMAN_TRUE = @CATMAN_TRUE@
+CC = @CC@
+CFLAGS = @CFLAGS@
+COMERR_CPPFLAGS = @COMERR_CPPFLAGS@
+COM_APPLE_KERNEL_BSD = @COM_APPLE_KERNEL_BSD@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DBLIB = @DBLIB@
+DCE_FALSE = @DCE_FALSE@
+DCE_TRUE = @DCE_TRUE@
+DEFS = @DEFS@
+DEPEND_sl = @DEPEND_sl@
+DIR_roken = @DIR_roken@
+DIR_sl = @DIR_sl@
+DVI2PS = @DVI2PS@
+DVIPS = @DVIPS@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FBSD5_FALSE = @FBSD5_FALSE@
+FBSD5_TRUE = @FBSD5_TRUE@
+FFLAGS = @FFLAGS@
+FREEBSD_GENSETDEFS = @FREEBSD_GENSETDEFS@
+GCC = @GCC@
+GROFF = @GROFF@
+GUILE_GTK = @GUILE_GTK@
+HAVE_DB1_FALSE = @HAVE_DB1_FALSE@
+HAVE_DB1_TRUE = @HAVE_DB1_TRUE@
+HAVE_DB3_FALSE = @HAVE_DB3_FALSE@
+HAVE_DB3_TRUE = @HAVE_DB3_TRUE@
+HAVE_NDBM_FALSE = @HAVE_NDBM_FALSE@
+HAVE_NDBM_TRUE = @HAVE_NDBM_TRUE@
+INCLUDES_roken = @INCLUDES_roken@
+INCLUDE_readline = @INCLUDE_readline@
+INC_roken = @INC_roken@
+INC_sl = @INC_sl@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+KAFS_CPPFLAGS = @KAFS_CPPFLAGS@
+KAFS_LIBS = @KAFS_LIBS@
+KERNEL_CC = @KERNEL_CC@
+KERNEL_CFLAGS = @KERNEL_CFLAGS@
+KERNEL_CPPFLAGS = @KERNEL_CPPFLAGS@
+KERNEL_HDRS = @KERNEL_HDRS@
+KERNEL_INCLUDE = @KERNEL_INCLUDE@
+KERNEL_LD = @KERNEL_LD@
+KERNEL_LD_FLAGS = @KERNEL_LD_FLAGS@
+KERNEL_SRCS = @KERNEL_SRCS@
+KRB4_FALSE = @KRB4_FALSE@
+KRB4_INC_DIR = @KRB4_INC_DIR@
+KRB4_INC_FLAGS = @KRB4_INC_FLAGS@
+KRB4_LIB_DIR = @KRB4_LIB_DIR@
+KRB4_LIB_FLAGS = @KRB4_LIB_FLAGS@
+KRB4_LIB_LIBS = @KRB4_LIB_LIBS@
+KRB4_TRUE = @KRB4_TRUE@
+KRB5_FALSE = @KRB5_FALSE@
+KRB5_INC_DIR = @KRB5_INC_DIR@
+KRB5_INC_FLAGS = @KRB5_INC_FLAGS@
+KRB5_LIB_DIR = @KRB5_LIB_DIR@
+KRB5_LIB_FLAGS = @KRB5_LIB_FLAGS@
+KRB5_LIB_LIBS = @KRB5_LIB_LIBS@
+KRB5_TRUE = @KRB5_TRUE@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_NDBM = @LIB_NDBM@
+LIB_bswap16 = @LIB_bswap16@
+LIB_bswap32 = @LIB_bswap32@
+LIB_crypt = @LIB_crypt@
+LIB_db_create = @LIB_db_create@
+LIB_dbm_firstkey = @LIB_dbm_firstkey@
+LIB_dbopen = @LIB_dbopen@
+LIB_dn_expand = @LIB_dn_expand@
+LIB_el_init = @LIB_el_init@
+LIB_freeaddrinfo = @LIB_freeaddrinfo@
+LIB_gai_strerror = @LIB_gai_strerror@
+LIB_getaddrinfo = @LIB_getaddrinfo@
+LIB_gethostbyname = @LIB_gethostbyname@
+LIB_gethostbyname2 = @LIB_gethostbyname2@
+LIB_getnameinfo = @LIB_getnameinfo@
+LIB_getsockopt = @LIB_getsockopt@
+LIB_hstrerror = @LIB_hstrerror@
+LIB_pidfile = @LIB_pidfile@
+LIB_pthread_create = @LIB_pthread_create@
+LIB_readline = @LIB_readline@
+LIB_res_init = @LIB_res_init@
+LIB_res_nsearch = @LIB_res_nsearch@
+LIB_res_search = @LIB_res_search@
+LIB_roken = @LIB_roken@
+LIB_setsockopt = @LIB_setsockopt@
+LIB_sl = @LIB_sl@
+LIB_socket = @LIB_socket@
+LIB_syslog = @LIB_syslog@
+LIB_tgetent = @LIB_tgetent@
+LINUX_IA64_FALSE = @LINUX_IA64_FALSE@
+LINUX_IA64_TRUE = @LINUX_IA64_TRUE@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LWP_C = @LWP_C@
+LWP_H = @LWP_H@
+LWP_O = @LWP_O@
+LWP_PROCESS = @LWP_PROCESS@
+LWP_REDZONE_FALSE = @LWP_REDZONE_FALSE@
+LWP_REDZONE_TRUE = @LWP_REDZONE_TRUE@
+MACOSX_FALSE = @MACOSX_FALSE@
+MACOSX_TRUE = @MACOSX_TRUE@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MAKE_X_PROGS_BIN = @MAKE_X_PROGS_BIN@
+MILKO_ROOT = @MILKO_ROOT@
+MODLOAD = @MODLOAD@
+MODULE = @MODULE@
+MODUNLOAD = @MODUNLOAD@
+NNPFS_AFS_READDIR_FALSE = @NNPFS_AFS_READDIR_FALSE@
+NNPFS_AFS_READDIR_TRUE = @NNPFS_AFS_READDIR_TRUE@
+NNPFS_SRCS = @NNPFS_SRCS@
+NNPFS_SUBDIR = @NNPFS_SUBDIR@
+NROFF = @NROFF@
+OBJEXT = @OBJEXT@
+OSF1_FALSE = @OSF1_FALSE@
+OSF1_TRUE = @OSF1_TRUE@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PLWP_INC_FLAGS = @PLWP_INC_FLAGS@
+PLWP_LIB_FLAGS = @PLWP_LIB_FLAGS@
+RANLIB = @RANLIB@
+ROKEN_H = @ROKEN_H@
+RXKAD_FALSE = @RXKAD_FALSE@
+RXKAD_LIBS = @RXKAD_LIBS@
+RXKAD_TRUE = @RXKAD_TRUE@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SL_H = @SL_H@
+STRIP = @STRIP@
+SYMORDER = @SYMORDER@
+SYS = @SYS@
+TEXI2DVI = @TEXI2DVI@
+TEXI2HTML = @TEXI2HTML@
+TEXI2PDF = @TEXI2PDF@
+VERSION = @VERSION@
+VNODE_IF_H = @VNODE_IF_H@
+VOID_RETSIGTYPE = @VOID_RETSIGTYPE@
+WFLAGS = @WFLAGS@
+WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@
+WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+YACC = @YACC@
+YDR_CPPFLAGS = @YDR_CPPFLAGS@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+ac_cv_prog_getconf = @ac_cv_prog_getconf@
+am__leading_dot = @am__leading_dot@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+chmod = @chmod@
+datadir = @datadir@
+do_roken_rename_FALSE = @do_roken_rename_FALSE@
+do_roken_rename_TRUE = @do_roken_rename_TRUE@
+editline_OBJS = @editline_OBJS@
+editline_dir = @editline_dir@
+exec_prefix = @exec_prefix@
+have_err_h_FALSE = @have_err_h_FALSE@
+have_err_h_TRUE = @have_err_h_TRUE@
+have_fnmatch_h_FALSE = @have_fnmatch_h_FALSE@
+have_fnmatch_h_TRUE = @have_fnmatch_h_TRUE@
+have_glob_h_FALSE = @have_glob_h_FALSE@
+have_glob_h_TRUE = @have_glob_h_TRUE@
+have_ifaddrs_h_FALSE = @have_ifaddrs_h_FALSE@
+have_ifaddrs_h_TRUE = @have_ifaddrs_h_TRUE@
+have_vis_h_FALSE = @have_vis_h_FALSE@
+have_vis_h_TRUE = @have_vis_h_TRUE@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+SUFFIXES = .et .h .x .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .x
+INCLUDES = -I$(top_builddir)/include $(INCLUDES_roken) $(INC_roken) -I. \
+ -I$(srcdir) \
+ -I../include \
+ -I$(srcdir)/../include \
+ -I.. -I$(srcdir)/.. \
+ $(INC_roken) \
+ $(KRB5_INC_FLAGS)
+
+@do_roken_rename_TRUE@ROKEN_RENAME = -DROKEN_RENAME
+AM_CFLAGS = $(WFLAGS)
+CP = cp
+buildinclude = $(top_builddir)/include
+LIB_XauReadAuth = @LIB_XauReadAuth@
+LIB_dlopen = @LIB_dlopen@
+LIB_getattr = @LIB_getattr@
+LIB_getpwent_r = @LIB_getpwent_r@
+LIB_getpwnam_r = @LIB_getpwnam_r@
+LIB_logout = @LIB_logout@
+LIB_logwtmp = @LIB_logwtmp@
+LIB_odm_initialize = @LIB_odm_initialize@
+LIB_openpty = @LIB_openpty@
+LIB_setpcred = @LIB_setpcred@
+HESIODLIB = @HESIODLIB@
+HESIODINCLUDE = @HESIODINCLUDE@
+INCLUDE_hesiod = @INCLUDE_hesiod@
+LIB_hesiod = @LIB_hesiod@
+INCLUDE_krb4 = @INCLUDE_krb4@
+LIB_krb4 = @LIB_krb4@
+INCLUDE_openldap = @INCLUDE_openldap@
+LIB_openldap = @LIB_openldap@
+NROFF_MAN = groff -mandoc -Tascii
+CHECK_LOCAL = $(PROGRAMS)
+noinst_LTLIBRARIES = librxgkclient.la librxgkserver.la
+librxgkclient_la_SOURCES = \
+ rxgk_locl.h \
+ rxgk_proto.h \
+ rxgk_clnt.c \
+ rxgk_info.c \
+ rxgk_crpc.c \
+ rxgk_crkrb.c \
+ rxgk_common.c \
+ rxgk_proto.ydr.c \
+ rxgk_proto.cs.c
+
+librxgkserver_la_SOURCES = \
+ rxgk_locl.h \
+ rxgk_proto.h \
+ rxgk_serv.c \
+ rxgk_info.c \
+ rxgk_srpc.c \
+ rxgk_crkrb.c \
+ rxgk_common.c \
+ rxgk_proto.ydr.c \
+ rxgk_proto.ss.c
+
+LIBYDR = \
+ rxgk_proto.cs.c \
+ rxgk_proto.ss.c \
+ rxgk_proto.ydr.c \
+ rxgk_proto.h \
+ rxgk_proto.cs.h \
+ rxgk_proto.ss.h
+
+LIBTYDR = \
+ test.cs.h \
+ test.ss.h \
+ test.ss.c \
+ test.cs.c \
+ test.ydr.c \
+ test.h
+
+common_LDADD = \
+ ../rx/librx.la \
+ -L../lwp -llwp $(PLWP_LIB_FLAGS) \
+ $(KRB5_LIB_FLAGS)
+
+test_client_SOURCES = test_client.c test.cs.c
+test_server_SOURCES = test_server.c test.ss.c
+test_client_LDADD = librxgkclient.la $(common_LDADD)
+test_server_LDADD = librxgkserver.la $(common_LDADD)
+CLEANFILES = $(LIBYDR) $(LIBTYDR)
+LDADD = $(KRB5_LIB_FLAGS)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .et .h .x .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .x .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps rxgk/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign --ignore-deps rxgk/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" = "$$p" && dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+librxgkclient.la: $(librxgkclient_la_OBJECTS) $(librxgkclient_la_DEPENDENCIES)
+ $(LINK) $(librxgkclient_la_LDFLAGS) $(librxgkclient_la_OBJECTS) $(librxgkclient_la_LIBADD) $(LIBS)
+librxgkserver.la: $(librxgkserver_la_OBJECTS) $(librxgkserver_la_DEPENDENCIES)
+ $(LINK) $(librxgkserver_la_LDFLAGS) $(librxgkserver_la_OBJECTS) $(librxgkserver_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+test_client$(EXEEXT): $(test_client_OBJECTS) $(test_client_DEPENDENCIES)
+ @rm -f test_client$(EXEEXT)
+ $(LINK) $(test_client_LDFLAGS) $(test_client_OBJECTS) $(test_client_LDADD) $(LIBS)
+test_server$(EXEEXT): $(test_server_OBJECTS) $(test_server_DEPENDENCIES)
+ @rm -f test_server$(EXEEXT)
+ $(LINK) $(test_server_LDFLAGS) $(test_server_OBJECTS) $(test_server_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+.c.o:
+ $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$tags$$unique" \
+ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(mkdir_p) $(distdir)/.. $(distdir)/../cf
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$(top_distdir)" distdir="$(distdir)" \
+ dist-hook
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local
+
+install-exec-am:
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am all-local check check-am check-local \
+ clean clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-noinstPROGRAMS ctags distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-data-local install-exec \
+ install-exec-am install-info install-info-am install-man \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-info-am
+
+
+install-suid-programs:
+ @foo='$(bin_SUIDS)'; \
+ for file in $$foo; do \
+ x=$(DESTDIR)$(bindir)/$$file; \
+ if chown 0:0 $$x && chmod u+s $$x; then :; else \
+ echo "*"; \
+ echo "* Failed to install $$x setuid root"; \
+ echo "*"; \
+ fi; done
+
+install-exec-hook: install-suid-programs
+
+install-build-headers:: $(include_HEADERS) $(build_HEADERZ)
+ @foo='$(include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ)'; \
+ for f in $$foo; do \
+ f=`basename $$f`; \
+ if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \
+ else file="$$f"; fi; \
+ if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \
+ : ; else \
+ echo " $(CP) $$file $(buildinclude)/$$f"; \
+ $(CP) $$file $(buildinclude)/$$f; \
+ fi ; \
+ done
+
+all-local: install-build-headers
+
+check-local::
+ @if test '$(CHECK_LOCAL)'; then \
+ foo='$(CHECK_LOCAL)'; else \
+ foo='$(PROGRAMS)'; fi; \
+ if test "$$foo"; then \
+ failed=0; all=0; \
+ for i in $$foo; do \
+ all=`expr $$all + 1`; \
+ if ./$$i --version > /dev/null 2>&1; then \
+ echo "PASS: $$i"; \
+ else \
+ echo "FAIL: $$i"; \
+ failed=`expr $$failed + 1`; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="$$failed of $$all tests failed"; \
+ fi; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ fi
+
+.x.c:
+ @cmp -s $< $@ 2> /dev/null || cp $< $@
+#NROFF_MAN = nroff -man
+.1.cat1:
+ $(NROFF_MAN) $< > $@
+.3.cat3:
+ $(NROFF_MAN) $< > $@
+.5.cat5:
+ $(NROFF_MAN) $< > $@
+.8.cat8:
+ $(NROFF_MAN) $< > $@
+
+dist-cat1-mans:
+ @foo='$(man1_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.1) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat1/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat3-mans:
+ @foo='$(man3_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.3) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat3/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat5-mans:
+ @foo='$(man5_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.5) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat5/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat8-mans:
+ @foo='$(man8_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.8) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat8/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans
+
+install-cat-mans: install-man
+ $(SHELL) $(top_srcdir)/cf/install-catman.sh "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS)
+
+install-data-local: install-cat-mans
+
+.et.h:
+ $(COMPILE_ET) $<
+.et.c:
+ $(COMPILE_ET) $<
+
+.x.c:
+ @cmp -s $< $@ 2> /dev/null || cp $< $@
+
+check-local::
+ @foo='$(CHECK_LOCAL)'; \
+ if test "$$foo"; then \
+ failed=0; all=0; \
+ for i in $$foo; do \
+ all=`expr $$all + 1`; \
+ if ./$$i --version > /dev/null 2>&1; then \
+ echo "PASS: $$i"; \
+ else \
+ echo "FAIL: $$i"; \
+ failed=`expr $$failed + 1`; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="$$failed of $$all tests failed"; \
+ fi; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ fi
+
+$(librxgkclient_la_OBJECTS) $(librxgkserver_la_OBJECTS): $(LIBYDR)
+
+$(test_server_OBJECTS) $(test_client_OBJECTS): $(LIBTYDR)
+
+$(LIBYDR): rxgk_proto.xg
+ ../ydr/ydr $(srcdir)/rxgk_proto.xg
+
+$(LIBTYDR): test.xg
+ ../ydr/ydr $(srcdir)/test.xg
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+$Id$
+
+Overview
+========
+
+- RX crypto class
+
+ rxgk is a new crypto class, mostly since the interface need to
+ be changed in the ktc for openafs anyway (at least binary
+ interface).
+
+ rxgk (krb5) can be used when the kdc returns a non des enctype.
+
+- Layers
+
+ There are two layer, the transport layer that is authentiation
+ mechamism independent, and the authentiation layer.
+
+ The glue between the authentiation layer and the transport
+ layer is the RXGK authenticator.
+
+- RXGK authenticator
+
+ The only reson for the RXGK authenticator exists is that there
+ are not fragmentation in the Challange/Response protocol in
+ Rx. This limits the authentization in Rx to MTU sized packages.
+
+- RXGK authenticator lifetime
+
+ The server has a local key that is used to encrypt the gk
+ authenticators. The local key is semi stateful, the
+ server need to remember the old keys al long as there are
+ valid RXGK authenticators held by any client. New RXGK
+ authenticators can be fetched at any time but might require
+ user input.
+
+- Getting RXGK authenticator
+
+ the authenticator is fetched using a service rx_null on the
+ same port as the server the client wants to talk too.
+
+transport layer
+===============
+
+- Key derivation
+
+ Each connection get separate key for each connection/epoch.
+ Each direction get a separate key for each direction.
+
+ S = Session key
+ CN = connection key
+ counter = key generation (nonce)
+ K{server} = Key from server direction
+ K{client} = Key from client direction
+
+ X{cn} = epoch{32} | cid{32} | key_counter{64}
+
+ CN = random-to-key(pseudo-random(S, X{cn})
+
+ K{server} = KD(CN, 0) { key used on data from server }
+ K{client} = KD(CN, 1) { key used on data from client }
+
+ Checksum field in the header (spare1) is always set to the
+ lower 4 bits of the key_counter field. Ie server may not
+ request rekeying faster the (4 * rc_max_seq_skew) packets.
+
+ K depends on {S,epoch,cid,key_counter}
+
+- Rekeying
+
+ Rekeing is needed since kcrypt assumes that data isn't
+ encrypted for the 2**48 messages with the same key.
+
+- Challenge/Response
+
+ When the client is unknown to the server it sends a challenge
+ with opcode RXKG_OPCODE_CHALLENGE (nonce).
+
+ The client the send back a rxgk authenticator and the
+ encrypted nounce.
+
+- Wire protocol
+
+ crypt mode
+
+ Each packet are encrypted as [KCRYPTO] specifies. The data is
+ prefixed with parts of the rx header that matter.
+
+ auth mode
+
+ Each packet are checksumed as [KCRYPTO] specifies. The data is
+ prefixed with parts of the rx header that matter [4]. In auth
+ mode the rx header subsitute is not sent over write to save
+ space.
+
+ The part of the header that is checksumed are these fields:
+
+ uint32_t callid
+ uint32_t seqno
+ uint32_t serialno
+ uint8_t userstatus
+ uint8_t someflags (RX_PRESET_FLAGS)
+ uint8_t serviceid
+
+Authentication RPCs
+===================
+
+- Information RPCs
+
+ To be later specified.
+
+ There is an information API to, with a RXGK authenticator, the
+ client can verify what authentiation mechamisms is supported,
+ both insecure and authenticated.
+
+- Kerberos 5 to rxgk authenticator RPCs
+
+ key{KerbS} - kerberos session subkey key
+
+ The mutual auth data in the RXGK_EstablishKrb5Context is
+ encrypted with the key{KerbS} key.
+
+ Client sends acceptable enctypes and nonce to the server in
+ challenge.
+
+ Server sends back key(auth-cred-key) and nonce + 1 to the
+ client together with a RXGK authenticator cred encrypted with
+ key{KerbS}.
+
+ auth-cred is protected by key{gkkey}
+
+ key{S} = key{auth-cred-key}
+
+- GSS-API to rxgk authenticator RPCs
+
+ To be later specified.
+
+========
+
+Code assumptions:
+
+ L.NXS.SE realm
+
+ gkkey@L.NXS.SE and afs@L.NXS.SE key exists in default keytab
+
+========
+implementation/higher level issues
+
+
+- RXGK_AUTH_CRED needs checking
+
+ [ 2. should we use the session key or the a random octet
+ string generatated by the server, the key(auth-cred-key) below ]
+
+ [ 3. ac_principal: gss exported name ? this to make it idependant
+ of kerberos 5. Problem with gss name only specifed gss-mechs
+ can be used. Server local so it can really be anything the
+ server wants it to be. Need to be kept short so it will fit on
+ one MTU. Also see {{10}}. ]
+
+ The RXGK authenticator is fetch by doing either the RXGK
+ GSSAPI rpc's or the RXGK_EstablishKrb5Context rpc to the RXGK
+ service on the same port as the service that rxgk
+ secures. Doing the RPC call gives you a gk authenticator and a
+ key(S) that is valid for one server. The input to GSSAPI rpc
+ and EstablishKrb5Context are mech specific.
+
+ GSS-API
+ [ 11. see rxgss how this should me implemented ... ]
+
+exported auth name
+
+ all mech's need to have a rxgk name to krb4 name function
+ until pts is changed to support rxgk names.
+
+ [ 10. Proposal: the protection interface have GKNAME to
+ AFS/PTS named RPCs.
+
+ In this proposal all names are mapped to one AFS username.
+
+ For example, gss exported named KRB5:lha@SU.SE, krb5 native
+ lha@SU.SE and krb5 native krb5 lha@KTH.SE all map to the same
+ afs username `lha'.
+
+
+ Also see {{3}}. ]
+
+
+TODO:
+
+- Auth mode
+
+- Pass length since krb encryption doesn't preserve length (some enctypes does)
+
+ [ 8. Is this really needed, packets are always send full ]
+
+- More tests
+
+ More the MTU since rpcs
+ Stored packets packets, compare generate packages
+ Check other checksum
+
+
+DEPRICATED IDEAS
+
+- Diffrent keys for fileservers
+
+ I think we should ignore this for rxgk/kerberos 5 or do
+ "fileserver groups" as discuss on Pittsburgh so this will
+ happen. For "fileserver groups" a get groups rpc should be
+ added to the vlserver (this will make non rx afslogs harder
+ to implement) and in the first version we just insert a rpc
+ stub that return one name only, "default", or something
+ equally silly.
+
+ The reson you want to have diffrent keys for fileservers are
+
+ - increased security (more keys, less data encrypted with the
+ same key, one server compromised doesn't compromise all servers)
+
+ - give a fileserver to someone else that you not trust
+ to have the master key
+
+ Depricated since we can get consensus, rxgk/gssapi will/must solve
+ the problem.
--- /dev/null
+/* -*- C -*- */
+
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#ifndef __RXGK_H
+#define __RXGK_H
+
+/* Is this really large enough for a krb5 ticket? */
+#define MAXKRB5TICKETLEN 1024
+
+typedef char rxgk_level;
+#define rxgk_auth 0 /* rxgk_clear + protected packet length */
+#define rxgk_crypt 1 /* rxgk_crypt + encrypt packet payload */
+
+int32_t
+rxgk_GetServerInfo(struct rx_connection *, rxgk_level *,
+ uint32_t *, char *, size_t, char *, size_t, int32_t *);
+
+struct rx_securityClass *
+rxgk_NewServerSecurityObject (/*rxgk_level*/ int min_level,
+ const char *princ,
+ void *appl_data,
+ int (*get_key)(void *data, const char *principal,
+ int enctype, int kvno,
+ krb5_keyblock *key),
+ int (*user_ok)(const char *name,
+ const char *realm,
+ int kvno),
+ uint32_t serviceId);
+
+struct rx_securityClass *
+rxgk_k5_NewClientSecurityObject (/*rxgk_level*/ int level,
+ krb5_keyblock *sessionkey,
+ int32_t kvno,
+ int ticketLen,
+ void *ticket,
+ uint32_t serviceId,
+ krb5_context context);
+
+int
+rxgk_default_get_key(void *, const char *, int, int, krb5_keyblock *);
+
+/* XXX these are not com_err error, MAKE THIS com_err's */
+#define RXGKINCONSISTENCY (19270400L)
+#define RXGKPACKETSHORT (19270401L)
+#define RXGKLEVELFAIL (19270402L)
+#define RXGKTICKETLEN (19270403L)
+#define RXGKOUTOFSEQUENCE (19270404L)
+#define RXGKNOAUTH (19270405L)
+#define RXGKBADKEY (19270406L)
+#define RXGKBADTICKET (19270407L)
+#define RXGKUNKNOWNKEY (19270408L)
+#define RXGKEXPIRED (19270409L)
+#define RXGKSEALEDINCON (19270410L)
+#define RXGKDATALEN (19270411L)
+#define RXGKILLEGALLEVEL (19270412L)
+
+#endif /* __RXGK_H */
--- /dev/null
+/*
+ * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "rxgk_locl.h"
+
+RCSID("$Id$");
+
+/* Security object specific client data */
+typedef struct rxgk_clnt_class {
+ struct rx_securityClass klass;
+ krb5_context context;
+ rxgk_level level;
+ krb5_keyblock krb_key;
+ key_stuff k;
+ int32_t kvno;
+ RXGK_Token ticket;
+ uint32_t serviceId;
+#if 0
+ RXGK_rxtransport_key contrib;
+#endif
+} rxgk_clnt_class;
+
+/* Per connection specific client data */
+typedef struct clnt_con_data {
+ RXGK_Token auth_token;
+ int32_t auth_token_kvno;
+ end_stuff e;
+} clnt_con_data;
+
+static
+int
+client_NewConnection(struct rx_securityClass *obj_, struct rx_connection *con)
+{
+ rxgk_clnt_class *obj = (rxgk_clnt_class *) obj_;
+ clnt_con_data *cdat;
+ int ret;
+
+ assert(con->securityData == 0);
+ obj->klass.refCount++;
+ cdat = (clnt_con_data *) osi_Alloc(sizeof(clnt_con_data));
+ cdat->e.bytesReceived = cdat->e.packetsReceived = 0;
+ cdat->e.bytesSent = cdat->e.packetsSent = 0;
+
+ con->securityData = (char *) cdat;
+ rx_nextCid += RX_MAXCALLS;
+ con->epoch = rx_epoch;
+ con->cid = rx_nextCid;
+ cdat->auth_token.len = 0;
+ cdat->auth_token.val = NULL;
+
+ ret = rxgk5_get_auth_token(obj->context,
+ rx_HostOf(con->peer), rx_PortOf(con->peer),
+ obj->serviceId,
+ &obj->ticket, &cdat->auth_token,
+ &obj->krb_key,
+ &obj->k.ks_key,
+ &cdat->auth_token_kvno);
+ if (ret) {
+ osi_Free(cdat, sizeof(clnt_con_data));
+ return ret;
+ }
+
+ /* XXX derive crypto key */
+
+ ret = krb5_crypto_init(obj->k.ks_context,
+ &obj->k.ks_key, obj->k.ks_key.keytype,
+ &obj->k.ks_crypto);
+ if (ret)
+ goto out;
+
+#if 0
+ obj->contrib.server_keycontribution.val = "";
+ obj->contrib.server_keycontribution.len = 0;
+
+ obj->contrib.client_keycontribution.len = rxgk_key_contrib_size;
+ obj->contrib.client_keycontribution.val = malloc(rxgk_key_contrib_size);
+ if (obj->contrib.client_keycontribution.val == NULL)
+ goto out;
+
+ {
+ int i;
+
+ for (i = 0; i < rxgk_key_contrib_size; i++)
+ obj->contrib.client_keycontribution.val[i] = arc4random(); /*XXX*/
+ }
+
+ ret = rxgk_derive_transport_key(obj->k.ks_context,
+ &obj->k.ks_key,
+ &obj->contrib,
+ &obj->k.ks_skey);
+ if (ret)
+ return ret;
+#endif
+
+ ret = krb5_crypto_init (obj->context, &obj->k.ks_skey,
+ obj->k.ks_skey.keytype,
+ &obj->k.ks_scrypto);
+ if (ret)
+ return ret;
+
+ ret = rxgk_set_conn(con, obj->k.ks_key.keytype,
+ obj->level == rxgk_crypt ? 1 : 0);
+
+ out:
+ if (ret) {
+ if (obj->k.ks_crypto)
+ krb5_crypto_destroy(obj->k.ks_context, obj->k.ks_crypto);
+ obj->k.ks_crypto = NULL;
+ krb5_free_keyblock_contents(obj->k.ks_context, &obj->k.ks_skey);
+ memset(&obj->k.ks_skey, 0, sizeof(obj->k.ks_skey));
+ osi_Free(cdat->auth_token.val, cdat->auth_token.len);
+ osi_Free(cdat, sizeof(clnt_con_data));
+ return ret;
+ }
+
+ return 0;
+}
+
+static
+int
+client_Close(struct rx_securityClass *obj_)
+{
+ rxgk_clnt_class *obj = (rxgk_clnt_class *) obj_;
+ obj->klass.refCount--;
+ if (obj->klass.refCount <= 0)
+ {
+ osi_Free(obj->ticket.val, obj->ticket.len);
+ osi_Free(obj, sizeof(rxgk_clnt_class));
+ }
+ return 0;
+}
+
+static
+int
+client_DestroyConnection(struct rx_securityClass *obj,
+ struct rx_connection *con)
+{
+ clnt_con_data *cdat = (clnt_con_data *)con->securityData;
+
+ if (cdat)
+ osi_Free(cdat, sizeof(clnt_con_data));
+ return client_Close(obj);
+}
+
+/*
+ * Receive a challange and respond.
+ */
+static
+int
+client_GetResponse(const struct rx_securityClass *obj_,
+ const struct rx_connection *con,
+ struct rx_packet *pkt)
+{
+ rxgk_clnt_class *obj = (rxgk_clnt_class *) obj_;
+ clnt_con_data *cdat = (clnt_con_data *)con->securityData;
+ key_stuff *k = &obj->k;
+ struct RXGK_Challenge c;
+ struct RXGK_Response r;
+ struct RXGK_Response_Crypt rc;
+ char bufrc[RXGK_RESPONSE_CRYPT_SIZE];
+ char bufr[RXGK_RESPONSE_MAX_SIZE];
+ krb5_data data;
+ size_t len;
+ int ret;
+ char *p;
+
+ memset(&r, 0, sizeof(r));
+ memset(&rc, 0, sizeof(rc));
+
+ /* Get challenge */
+ if (rx_SlowReadPacket(pkt, 0, sizeof(c), &c) != sizeof(c))
+ return RXGKPACKETSHORT;
+
+ if (ntohl(c.rc_version) != RXGK_VERSION)
+ return RXGKINCONSISTENCY;
+
+ if (ntohl(c.rc_min_level) > obj->level)
+ return RXGKLEVELFAIL;
+
+ if (c.rc_opcode == htonl(RXKG_OPCODE_CHALLENGE)) {
+ ;
+ } else if (c.rc_opcode == htonl(RXKG_OPCODE_REKEY)) {
+ /* XXX decode ydr_encode_RXGK_ReKey_Crypt info */
+ return RXGKINCONSISTENCY;
+#if 0
+ ret = rxgk_derive_transport_key(obj->k.ks_context,
+ &obj->k.ks_key,
+ &obj->contrib,
+ &obj->k.ks_skey);
+ if (ret)
+ return ret;
+
+ ret = krb5_crypto_init (obj->context, &obj->k.ks_skey,
+ obj->k.ks_skey.keytype,
+ &obj->k.ks_scrypto);
+ if (ret)
+ return ret;
+#endif
+ } else
+ return RXGKINCONSISTENCY;
+
+ rc.nonce = ntohl(c.rc_nonce) + 1;
+ rc.epoch = con->epoch;
+ rc.cid = con->cid & RX_CIDMASK;
+ rxi_GetCallNumberVector(con, rc.call_numbers);
+#if 0
+ rc.security_index = con->securityIndex;
+#endif
+ rc.level = obj->level;
+#if 0
+ rc.last_seq = 0; /* XXX */
+#endif
+ rc.key_version = 0;
+#if 0
+ rc.contrib = obj->contrib; /* XXX copy_RXGK_rxtransport_key */
+#endif
+
+ {
+ int i;
+ for (i = 0; i < RX_MAXCALLS; i++) {
+ if (rc.call_numbers[i] < 0)
+ return RXGKINCONSISTENCY;
+ }
+ }
+ len = sizeof(bufrc);
+ p = ydr_encode_RXGK_Response_Crypt(&rc, bufrc, &len);
+ if (p == NULL)
+ return RXGKINCONSISTENCY;
+ len = sizeof(bufrc) - len;
+
+ ret = krb5_encrypt(obj->context, k->ks_crypto,
+ RXGK_CLIENT_ENC_CHALLENGE, bufrc, len, &data);
+ if (ret)
+ return ret;
+
+ r.rr_version = RXGK_VERSION;
+ r.rr_auth_token_kvno = cdat->auth_token_kvno;
+ r.rr_auth_token.val = cdat->auth_token.val;
+ r.rr_auth_token.len = cdat->auth_token.len;
+ r.rr_ctext.val = data.data;
+ r.rr_ctext.len = data.length;
+
+ len = sizeof(bufr);
+ p = ydr_encode_RXGK_Response(&r, bufr, &len);
+ len = sizeof(bufr) - len;
+ krb5_data_free(&data);
+
+ if (p == NULL)
+ return RXGKINCONSISTENCY;
+
+ if (rx_SlowWritePacket(pkt, 0, len, bufr) != len)
+ return RXGKPACKETSHORT;
+ rx_SetDataSize(pkt, len);
+
+ return 0;
+}
+
+/*
+ * Checksum and/or encrypt packet.
+ */
+static
+int
+client_PreparePacket(struct rx_securityClass *obj_,
+ struct rx_call *call,
+ struct rx_packet *pkt)
+{
+ rxgk_clnt_class *obj = (rxgk_clnt_class *) obj_;
+ key_stuff *k = &obj->k;
+ struct rx_connection *con = rx_ConnectionOf(call);
+ end_stuff *e = &((clnt_con_data *) con->securityData)->e;
+
+ return rxgk_prepare_packet(pkt, con, obj->level, k, e);
+}
+
+/*
+ * Verify checksums and/or decrypt packet.
+ */
+static
+int
+client_CheckPacket(struct rx_securityClass *obj_,
+ struct rx_call *call,
+ struct rx_packet *pkt)
+{
+ rxgk_clnt_class *obj = (rxgk_clnt_class *) obj_;
+ key_stuff *k = &obj->k;
+ struct rx_connection *con = rx_ConnectionOf(call);
+ end_stuff *e = &((clnt_con_data *) con->securityData)->e;
+
+ return rxgk_check_packet(pkt, con, obj->level, k, e);
+}
+
+static
+int
+client_GetStats(const struct rx_securityClass *obj,
+ const struct rx_connection *con,
+ struct rx_securityObjectStats *st)
+{
+ clnt_con_data *cdat = (clnt_con_data *) con->securityData;
+
+ st->type = rxgk_disipline;
+ st->level = ((rxgk_clnt_class *)obj)->level;
+ st->flags = rxgk_checksummed;
+ if (cdat == 0)
+ st->flags |= rxgk_unallocated;
+ {
+ st->bytesReceived = cdat->e.bytesReceived;
+ st->packetsReceived = cdat->e.packetsReceived;
+ st->bytesSent = cdat->e.bytesSent;
+ st->packetsSent = cdat->e.packetsSent;
+ }
+ return 0;
+}
+
+static
+struct rx_securityOps client_ops = {
+ client_Close,
+ client_NewConnection,
+ client_PreparePacket,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ client_GetResponse,
+ NULL,
+ client_CheckPacket,
+ client_DestroyConnection,
+ client_GetStats,
+ NULL,
+ NULL,
+ NULL,
+};
+
+int rxgk_EpochWasSet = 0;
+
+int rxgk_min_level = rxgk_crypt; /* rxgk_{auth,crypt} */ /* XXX */
+
+struct rx_securityClass *
+rxgk_k5_NewClientSecurityObject(/*rxgk_level*/ int level,
+ krb5_keyblock *key,
+ int32_t kvno,
+ int ticket_len,
+ void *ticket,
+ uint32_t serviceId,
+ krb5_context context)
+{
+ rxgk_clnt_class *obj;
+ static int inited = 0;
+ int ret;
+
+ if (level < rxgk_min_level)
+ level = rxgk_min_level; /* Boost security level */
+
+ if (!inited) {
+ rx_SetEpoch(arc4random());
+ inited = 1;
+ }
+
+ obj = (rxgk_clnt_class *) osi_Alloc(sizeof(rxgk_clnt_class));
+ obj->klass.refCount = 1;
+ obj->klass.ops = &client_ops;
+
+ obj->klass.privateData = (char *) obj;
+
+ obj->context = context;
+ obj->level = level;
+ obj->kvno = kvno;
+ obj->serviceId = serviceId;
+
+ ret = krb5_copy_keyblock_contents(context, key, &obj->krb_key);
+ if (ret) {
+ osi_Free(obj, sizeof(rxgk_clnt_class));
+ return NULL;
+ }
+
+ memset(&obj->k.ks_key, 0, sizeof(obj->k.ks_key));
+ obj->k.ks_crypto = NULL;
+
+ memset(&obj->k.ks_skey, 0, sizeof(obj->k.ks_skey));
+ obj->k.ks_scrypto = NULL;
+ obj->k.ks_context = context;
+
+ obj->ticket.len = ticket_len;
+ obj->ticket.val = osi_Alloc(ticket_len);
+ memcpy(obj->ticket.val, ticket, obj->ticket.len);
+
+ return &obj->klass;
+}
--- /dev/null
+/*
+ * Copyright (c) 2002 - 2004, Stockholms universitet
+ * (Stockholm University, Stockholm Sweden)
+ * All rights reserved.
+ *
+ * Redistribution is not permitted
+ */
+
+#include "rxgk_locl.h"
+
+RCSID("$Id$");
+
+#include <errno.h>
+
+#include <rx/rx.h>
+#include "rxgk_proto.h"
+
+/*
+ *
+ */
+
+int rxgk_key_contrib_size = 16;
+
+/*
+ *
+ */
+
+int
+rxk5_mutual_auth_client_generate(krb5_context context, krb5_keyblock *key,
+ uint32_t number,
+ RXGK_Token *challage_token)
+{
+ krb5_crypto crypto;
+ krb5_data data;
+ RXGK_CHALLENGE_TOKEN ct;
+ char buf[RXGK_CHALLENGE_TOKEN_MAX_SIZE];
+ size_t sz;
+ int ret;
+
+ data.data = NULL;
+
+ ret = krb5_crypto_init (context, key, key->keytype, &crypto);
+ if (ret)
+ return ret;
+
+ ct.ct_version = RXGK_CR_TOKEN_VERSION;
+ ct.ct_nonce = number;
+ ct.ct_enctype.val = malloc(sizeof(ct.ct_enctype.val[0]));
+ ct.ct_enctype.len = 1;
+ if (ct.ct_enctype.val == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+ ct.ct_enctype.val[0] = RXGK_CRYPTO_DES_CBC_CRC;
+
+ sz = RXGK_CHALLENGE_TOKEN_MAX_SIZE;
+ if (ydr_encode_RXGK_CHALLENGE_TOKEN(&ct, buf, &sz) == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+ sz = RXGK_CHALLENGE_TOKEN_MAX_SIZE - sz;
+
+ ret = krb5_encrypt(context, crypto, 0, buf, sz, &data);
+ if (ret)
+ goto out;
+
+ challage_token->val = malloc(data.length);
+ if (challage_token->val == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+
+ challage_token->len = data.length;
+ memcpy(challage_token->val, data.data, data.length);
+
+ out:
+ ydr_free_RXGK_CHALLENGE_TOKEN(&ct);
+ if (data.data)
+ krb5_data_free(&data);
+ krb5_crypto_destroy(context, crypto);
+ return ret;
+}
+
+/*
+ *
+ */
+
+int
+rxk5_mutual_auth_client_check(krb5_context context, krb5_keyblock *key,
+ uint32_t number,
+ const RXGK_Token *challage_token,
+ krb5_keyblock *rxsession_key)
+{
+ krb5_crypto crypto;
+ krb5_data data;
+ RXGK_REPLY_TOKEN rt;
+ size_t sz;
+ int ret;
+
+ memset(&rt, 0, sizeof(rt));
+ memset(rxsession_key, 0, sizeof(*rxsession_key));
+
+ ret = krb5_crypto_init (context, key, key->keytype, &crypto);
+ if (ret)
+ return ret;
+
+ /* Decrypt ticket */
+ data.data = NULL;
+ ret = krb5_decrypt(context, crypto, 0,
+ challage_token->val, challage_token->len,
+ &data);
+ if (ret)
+ goto out;
+
+ sz = data.length;
+ if (ydr_decode_RXGK_REPLY_TOKEN(&rt, data.data, &sz) == NULL) {
+ ret = RXGKSEALEDINCON;
+ goto out;
+ }
+
+ if (rt.rt_nonce != number + 1) {
+ ret = RXGKSEALEDINCON;
+ goto out2;
+ }
+
+ if (rt.rt_error != 0) {
+ ret = rt.rt_error;
+ goto out2;
+ }
+
+#if 1
+ /* XXX check rt_enctype */
+ ret = rxgk_random_to_key(rt.rt_enctype,
+ rt.rt_key.val, rt.rt_key.len,
+ rxsession_key);
+#else
+ ret = krb5_copy_keyblock_contents(context, key, rxsession_key);
+#endif
+
+ out2:
+ ydr_free_RXGK_REPLY_TOKEN(&rt);
+ out:
+ if (data.data)
+ krb5_data_free(&data);
+ krb5_crypto_destroy(context, crypto);
+
+ return ret;
+}
+
+/*
+ *
+ */
+
+int
+rxk5_mutual_auth_server(krb5_context context, krb5_keyblock *key,
+ const RXGK_Token *challage_token,
+ int *session_enctype,
+ void **session_key, size_t *session_key_size,
+ RXGK_Token *reply_token)
+{
+ krb5_crypto crypto;
+ krb5_data data;
+ krb5_keyblock keyblock;
+ RXGK_CHALLENGE_TOKEN ct;
+ RXGK_REPLY_TOKEN rt;
+ char buf[RXGK_REPLY_TOKEN_MAX_SIZE];
+ size_t sz;
+ int ret;
+
+ memset(&rt, 0, sizeof(rt));
+ memset(&ct, 0, sizeof(ct));
+
+ *session_enctype = 0;
+ *session_key = NULL;
+ *session_key_size = 0;
+
+ keyblock.keyvalue.data = NULL;
+
+ sz = RXGK_CHALLENGE_TOKEN_MAX_SIZE - sz;
+
+ ret = krb5_crypto_init (context, key, key->keytype, &crypto);
+ if (ret)
+ return ret;
+
+ /* Decrypt ticket */
+ data.data = NULL;
+ ret = krb5_decrypt(context, crypto, 0,
+ challage_token->val, challage_token->len,
+ &data);
+ if (ret)
+ goto out;
+
+ sz = data.length;
+ if (ydr_decode_RXGK_CHALLENGE_TOKEN(&ct, data.data, &sz) == NULL) {
+ memset(&ct, 0, sizeof(ct));
+ ret = ENOMEM;
+ goto out;
+ }
+ sz = data.length - sz;
+
+ krb5_data_free(&data);
+ data.data = NULL;
+
+ if (ct.ct_version < RXGK_CR_TOKEN_VERSION) {
+ ret = RXGKSEALEDINCON;
+ goto out;
+ } else
+ ret = 0;
+
+ /* XXX choose best enctype, not just the one we use now */
+ {
+ int i;
+
+ for (i = 0; i < ct.ct_enctype.len ; i++) {
+ if (ct.ct_enctype.val[i] == key->keytype)
+ break;
+ }
+
+ if (i == ct.ct_enctype.len)
+ ret = RXGKSEALEDINCON;
+ }
+
+ rt.rt_version = RXGK_CR_TOKEN_VERSION;
+ rt.rt_nonce = ct.ct_nonce + 1;
+
+ rt.rt_key.len = 0;
+ rt.rt_key.val = NULL;
+ rt.rt_error = ret;
+
+ if (ret == 0) {
+ ret = krb5_generate_random_keyblock(context,
+ key->keytype,
+ &keyblock);
+ if (ret == 0) {
+ rt.rt_enctype = keyblock.keytype;
+ rt.rt_key.len = keyblock.keyvalue.length;
+ rt.rt_key.val = keyblock.keyvalue.data;
+
+ *session_enctype = keyblock.keytype;
+ *session_key_size = keyblock.keyvalue.length;
+ *session_key = malloc(keyblock.keyvalue.length);
+ if (*session_key == NULL)
+ abort();
+ memcpy(*session_key, keyblock.keyvalue.data,
+ keyblock.keyvalue.length);
+ } else {
+ rt.rt_error = ret;
+ }
+ }
+
+ sz = RXGK_REPLY_TOKEN_MAX_SIZE;
+ if (ydr_encode_RXGK_REPLY_TOKEN(&rt, buf, &sz) == 0) {
+ ret = ENOMEM;
+ goto out;
+ }
+ sz = RXGK_REPLY_TOKEN_MAX_SIZE - sz;
+
+ memset(rt.rt_key.val, 0, rt.rt_key.len);
+
+ data.data = NULL;
+ ret = krb5_encrypt(context, crypto, 0, buf, sz, &data);
+ if (ret)
+ goto out;
+
+ reply_token->val = malloc(data.length);
+ if (reply_token->val == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+
+ reply_token->len = data.length;
+ memcpy(reply_token->val, data.data, data.length);
+
+ out:
+ ydr_free_RXGK_CHALLENGE_TOKEN(&ct);
+ /* ydr_free_RXGK_REPLY_TOKEN(&rt); */
+
+ if (data.data)
+ krb5_data_free(&data);
+ if (keyblock.keyvalue.data)
+ krb5_free_keyblock_contents(context, &keyblock);
+ krb5_crypto_destroy(context, crypto);
+ return ret;
+}
+
+/*
+ *
+ */
+
+void
+rxgk_getheader(struct rx_packet *pkt, struct rxgk_header_data *h)
+{
+ uint32_t t;
+
+ /* Collect selected packet fields */
+ h->call_number = htonl(pkt->header.callNumber);
+ t = ((pkt->header.cid & RX_CHANNELMASK) << (32 - RX_CIDSHIFT))
+ | ((pkt->header.seq & 0x3fffffff));
+ h->channel_and_seq = htonl(t);
+}
+
+/*
+ *
+ */
+
+#if 0
+int
+rxgk_derive_transport_key(krb5_context context,
+ krb5_keyblock *rx_conn_key,
+ RXGK_rxtransport_key *keycontrib,
+ krb5_keyblock *rkey)
+{
+ krb5_error_code ret;
+
+ /* XXX heimdal broken doesn't implement derive key for des encrypes */
+
+ switch (rx_conn_key->keytype) {
+ case RXGK_CRYPTO_DES_CBC_CRC:
+ case RXGK_CRYPTO_DES_CBC_MD4:
+ case RXGK_CRYPTO_DES_CBC_MD5:
+ ret = krb5_copy_keyblock_contents(context, rx_conn_key, rkey);
+ if (ret)
+ abort();
+
+ break;
+ default: {
+ char rxk_enc[RXGK_RXTRANSPORT_KEY_MAX_SIZE];
+ size_t sz;
+ krb5_keyblock *key;
+
+ sz = RXGK_RXTRANSPORT_KEY_MAX_SIZE;
+ if (ydr_encode_RXGK_rxtransport_key(keycontrib, rxk_enc, &sz) == NULL)
+ return EINVAL;
+
+ sz = RXGK_RXTRANSPORT_KEY_MAX_SIZE - sz;
+
+ ret = krb5_derive_key (context,
+ rx_conn_key,
+ rx_conn_key->keytype,
+ rxk_enc,
+ sz,
+ &key);
+ if (ret)
+ abort();
+
+ ret = krb5_copy_keyblock_contents(context, key, rkey);
+ if (ret)
+ abort();
+
+ krb5_free_keyblock(context, key);
+ break;
+ }
+ }
+
+ return ret;
+}
+#endif
+
+/*
+ *
+ */
+
+
+/* XXX replace me */
+
+int
+rxgk_random_to_key(int enctype,
+ void *random_data, int random_sz,
+ krb5_keyblock *key)
+{
+ memset(key, 0, sizeof(*key));
+
+ switch (enctype) {
+ case RXGK_CRYPTO_DES_CBC_CRC:
+ case RXGK_CRYPTO_DES_CBC_MD4:
+ case RXGK_CRYPTO_DES_CBC_MD5:
+ if (random_sz != 8)
+ return RXGKINCONSISTENCY;
+ break;
+ default:
+ return RXGKINCONSISTENCY;
+ }
+
+ key->keyvalue.data = malloc(random_sz);
+ if (key->keyvalue.data == NULL)
+ return ENOMEM;
+ memcpy(key->keyvalue.data, random_data, random_sz);
+ key->keyvalue.length = random_sz;
+ key->keytype = enctype;
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2002 - 2004, Stockholms universitet
+ * (Stockholm University, Stockholm Sweden)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the university nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Heimdal implementation of the rxgk wire encryption
+ */
+
+#include "rxgk_locl.h"
+#include <errno.h>
+
+RCSID("$Id$");
+
+struct _rxg_key_type {
+ char *name;
+ int enctype;
+ int blocklen;
+ int checksumlen;
+ int confounderlen;
+};
+
+static struct _rxg_key_type ktypes[] = {
+ { "des-cbc-crc", RXGK_CRYPTO_DES_CBC_CRC,
+ 8, 4, 8,
+ },
+ { "des-cbc-md5", RXGK_CRYPTO_DES_CBC_MD5,
+ 8, 24, 8,
+ }
+};
+
+static struct _rxg_key_type *
+_rxg_find_enctype(int enctype)
+{
+ struct _rxg_key_type *key;
+
+ for (key = ktypes; key->name != NULL; key++)
+ if (key->enctype == enctype)
+ return key;
+ return NULL;
+}
+
+int
+rxgk_set_conn(struct rx_connection *con, int enctype, int enc)
+{
+ struct _rxg_key_type *key;
+
+ key = _rxg_find_enctype(enctype);
+ if (key == NULL)
+ return ENOENT;
+
+ if (enc) {
+ rx_SetSecurityHeaderSize(con, key->checksumlen + key->confounderlen +
+ RXGK_HEADER_DATA_SIZE);
+
+ rx_SetSecurityMaxTrailerSize(con, key->blocklen);
+ } else {
+ rx_SetSecurityHeaderSize(con,
+ key->checksumlen + RXGK_HEADER_DATA_SIZE);
+ rx_SetSecurityMaxTrailerSize(con, 0);
+ }
+ return 0;
+}
+
+/*
+ *
+ */
+
+static int
+uiomove_to(struct rx_packet *pkt, u_int pre, u_int off, void **p, u_int *rlen)
+{
+ u_int len;
+ void *ptr;
+
+ len = rx_GetDataSize(pkt);
+ *rlen = len + pre;
+
+ ptr = malloc(*rlen);
+ if (ptr == NULL)
+ return ENOMEM;
+
+ *p = ptr;
+
+ ptr = (char *)ptr + pre;
+
+ if (rx_SlowReadPacket(pkt, off, len, ptr) != len) {
+ free(p);
+ *p = NULL;
+ return RXGKPACKETSHORT;
+ }
+
+ return 0;
+}
+
+/*
+ *
+ */
+
+static int
+uiomove_from(struct rx_packet *pkt, u_int off, void *ptr, u_int len)
+{
+ if (rx_SlowWritePacket(pkt, off, len, ptr) != len)
+ return RXGKPACKETSHORT;
+ rx_SetDataSize(pkt, len + off);
+
+ return 0;
+}
+
+/*
+ *
+ */
+int
+rxgk_prepare_packet(struct rx_packet *pkt, struct rx_connection *con,
+ int level, key_stuff *k, end_stuff *e)
+{
+ int ret, keyusage;
+
+
+
+ if (k->ks_scrypto == NULL)
+ return RXGKSEALEDINCON;
+
+ if (level == rxgk_crypt) {
+ krb5_data data;
+ struct rxgk_header_data hdr;
+ u_int len;
+ void *p;
+
+ if (rx_IsClientConn(con))
+ keyusage = RXGK_CLIENT_ENC_PACKETS;
+ else
+ keyusage = RXGK_SERVER_ENC_PACKETS;
+
+ ret = uiomove_to(pkt, RXGK_HEADER_DATA_SIZE,
+ rx_GetSecurityHeaderSize(con),
+ &p, &len);
+ if (ret)
+ return ret;
+
+ rxgk_getheader(pkt, &hdr);
+ memcpy(p, &hdr, sizeof(hdr));
+
+ ret = krb5_encrypt(k->ks_context, k->ks_scrypto,
+ keyusage, p, len, &data);
+ if (ret) {
+ free(p);
+ return ret;
+ }
+
+ ret = uiomove_from(pkt, 0, data.data, data.length);
+
+ krb5_data_free(&data);
+ free(p);
+
+ } else if (level == rxgk_auth) {
+ if (rx_IsClientConn(con))
+ keyusage = RXGK_CLIENT_CKSUM_PACKETS;
+ else
+ keyusage = RXGK_SERVER_CKSUM_PACKETS;
+
+ abort();
+ } else
+ abort();
+
+ return ret;
+}
+
+/*
+ *
+ */
+int
+rxgk_check_packet(struct rx_packet *pkt, struct rx_connection *con,
+ int level, key_stuff *k, end_stuff *e)
+{
+ int ret, keyusage;
+
+ if (k->ks_scrypto == NULL)
+ return RXGKSEALEDINCON;
+
+ ret = 0;
+
+ if (level == rxgk_crypt) {
+ krb5_data data;
+ struct rxgk_header_data hdr;
+ u_int len;
+ void *p;
+
+ if (rx_IsClientConn(con))
+ keyusage = RXGK_SERVER_ENC_PACKETS;
+ else
+ keyusage = RXGK_CLIENT_ENC_PACKETS;
+
+ ret = uiomove_to(pkt, 0, 0, &p, &len);
+ if (ret)
+ return ret;
+
+ ret = krb5_decrypt(k->ks_context, k->ks_scrypto,
+ keyusage, p, len, &data);
+ if (ret) {
+ free(p);
+ return ret;
+ }
+
+ ret = uiomove_from(pkt, rx_GetSecurityHeaderSize(con) -
+ RXGK_HEADER_DATA_SIZE,
+ data.data, data.length);
+ if (ret == 0) {
+ rxgk_getheader(pkt, &hdr);
+ if (memcmp(&hdr, data.data, sizeof(hdr)) != 0)
+ ret = RXGKSEALEDINCON;
+ }
+
+ krb5_data_free(&data);
+ free(p);
+ } else if (level == rxgk_auth) {
+ if (rx_IsClientConn(con))
+ keyusage = RXGK_SERVER_CKSUM_PACKETS;
+ else
+ keyusage = RXGK_CLIENT_CKSUM_PACKETS;
+
+
+ abort();
+ } else
+ abort();
+
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (c) 2002 - 2004, Stockholms universitet
+ * (Stockholm University, Stockholm Sweden)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the university nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "rxgk_locl.h"
+
+RCSID("$Id$");
+
+#include <openssl/md5.h>
+#include <openssl/des.h>
+
+#include <errno.h>
+
+/*
+ * krb5 non-des encrypting:
+ *
+ * +------------+----------+-------+---------+-----+
+ * | confounder | checksum | rxhdr | msg-seq | pad |
+ * +------------+----------+-------+---------+-----+
+ *
+ * krb5 non-des checksuming only:
+ *
+ * +----------+-------+---------+
+ * | checksum | rxhdr | msg-seq |
+ * +----------+-------+---------+
+ *
+ * XXX THIS SHOULD BE FIXED
+ * so, the checksuming only case includes unnessery data right
+ * now but I don't care since that makes it easier for me to
+ * share code between the two cases.
+ *
+ */
+
+struct rxg_key_type;
+
+struct rxg_des_keystuff {
+ des_cblock key;
+ des_key_schedule sched;
+ des_key_schedule chksum;
+ des_cblock iv[RX_MAXCALLS];
+};
+
+struct rxg_key {
+ struct rxg_key_type *type;
+ rxgk_level level;
+ union {
+ struct rxg_des_keystuff des;
+ } key;
+};
+
+#define RXG_MAX_CHECKSUM_SIZE 128
+
+struct rxg_con {
+ struct rxg_key key;
+ struct rxg_key_type *type;
+};
+
+int
+rxg_PacketCheckSum(struct rxg_key_type *, struct rx_packet *,
+ struct rxg_key *, void *, size_t, int);
+int
+rxg_check_packet(struct rx_packet *pkt,
+ struct rx_connection *con,
+ int clear,
+ struct rxg_con *kc);
+int
+rxg_prepare_packet(struct rx_packet *pkt,
+ struct rx_connection *con,
+ int clear,
+ struct rxg_con *kc);
+
+static void rxg_des_enc(void *, size_t, struct rxg_key *, void *, int);
+static void des_setup_iv(struct rx_packet *, struct rxg_key *, void *);
+static void des_prepare_key(struct rxg_key *, void *);
+static int checksum_pkt_md5_des(struct rx_packet *, struct rxg_key *,
+ void *, size_t, int);
+struct rxg_key_type * rxg_find_enctype(int);
+
+struct rxg_key_type {
+ char *name;
+ int enctype;
+ int keylen;
+ int blocklen;
+ int checksumlen;
+ int confounderlen;
+ int ivsize;
+ void (*prepare_key)(struct rxg_key *, void *key);
+ void (*setup_iv)(struct rx_packet *, struct rxg_key *, void *iv);
+ void (*encrypt)(void *, size_t, struct rxg_key *, void *, int);
+ int (*cksum_pkt)(struct rx_packet *, struct rxg_key *,void *,size_t,int);
+};
+
+static struct rxg_key_type ktypes[] = {
+ { "des-cbc-crc", RXGK_CRYPTO_DES_CBC_MD5,
+ 8, 8, 24, 8, 8,
+ des_prepare_key, des_setup_iv, rxg_des_enc, checksum_pkt_md5_des
+ }
+};
+
+struct rxg_key_type *
+rxg_find_enctype(int enctype)
+{
+ struct rxg_key_type *key;
+
+ for (key = ktypes; key->name != NULL; key++)
+ if (key->enctype == enctype)
+ return key;
+ return NULL;
+}
+
+static void
+rxg_des_enc(void *io, size_t sz, struct rxg_key *key, void *iv, int enc)
+{
+ struct rxg_des_keystuff *ks = &key->key.des;
+
+ assert((sz % 8) == 0);
+ des_cbc_encrypt(io, io, sz, ks->sched, iv, enc);
+}
+
+static void
+des_prepare_key(struct rxg_key *key, void *keym)
+{
+ struct rxg_des_keystuff *ks;
+ des_cblock cksumkey;
+ int i;
+
+ ks = &key->key.des;
+
+ memset(ks, 0, sizeof(*ks));
+
+ memcpy(ks->key, keym, sizeof(des_cblock));
+ des_set_key(&ks->key, ks->sched);
+ memset(ks->iv, 0, sizeof(ks->iv));
+
+ for (i = 0; i < 8; i++)
+ cksumkey[i] = ((char *)keym)[i] ^ 0xF0;
+
+ des_set_key(&cksumkey, ks->chksum);
+}
+
+static void
+des_setup_iv(struct rx_packet *pkt, struct rxg_key *key, void *iv)
+{
+ memset(iv, 0, sizeof(des_cblock));
+}
+
+static void
+rxg_random_data(void *ptr, size_t sz)
+{
+ memset(ptr, 0, sz);
+ abort();
+}
+
+
+static int
+encrypt_pkt(struct rxg_key_type *kt, struct rx_packet *pkt,
+ struct rxg_key *key, int encrypt)
+{
+ u_int len = rx_GetDataSize(pkt);
+ struct iovec *frag;
+ void *iv;
+
+ if ((iv = malloc(kt->ivsize)) == NULL)
+ return ENOMEM;
+
+ (kt->setup_iv)(pkt, key, iv);
+
+ assert((len % kt->blocklen) == 0);
+
+ for (frag = &pkt->wirevec[1]; len; frag++)
+ {
+ int iov_len = frag->iov_len;
+ uint32_t *iov_bas = (uint32_t *) frag->iov_base;
+ if (iov_len == 0) {
+ memset(iv, 0, kt->ivsize);
+ free(iv);
+ return RXGKPACKETSHORT; /* Length mismatch */
+ }
+ if (len < iov_len)
+ iov_len = len; /* Don't process to much data */
+
+ assert((iov_len % kt->blocklen) == 0);
+
+ (*kt->encrypt)(iov_bas, iov_len, key, iv, encrypt);
+ len -= iov_len;
+ }
+ memset(iv, 0, kt->ivsize);
+ free(iv);
+ return 0;
+}
+
+#define MAXCONFOUNDER 50
+
+struct variable_header_data {
+ /* Data that changes per packet */
+ uint32_t call_number;
+ uint32_t channel_and_seq;
+};
+
+static void
+getheader(struct rx_packet *pkt, struct variable_header_data *h)
+{
+ uint32_t t;
+
+ /* Collect selected packet fields */
+ h->call_number = htonl(pkt->header.callNumber);
+ t = ((pkt->header.cid & RX_CHANNELMASK) << (32 - RX_CIDSHIFT))
+ | ((pkt->header.seq & 0x3fffffff));
+ h->channel_and_seq = htonl(t);
+}
+
+
+/* des-cbc(key XOR 0xF0F0F0F0F0F0F0F0, conf | rsa-md5(conf | msg)) */
+
+static int
+checksum_pkt_md5_des(struct rx_packet *pkt, struct rxg_key *key,
+ void *checksum, size_t checksumlen, int encrypt)
+{
+ struct rxg_des_keystuff *ks;
+ u_int len = rx_GetDataSize(pkt);
+ struct iovec *frag;
+ des_cblock iv;
+ MD5_CTX c;
+ int cksumsz;
+
+ ks = &key->key.des;
+ cksumsz = key->type->checksumlen;
+
+ assert(cksumsz == 24);
+
+ memset(&iv, 0, sizeof(iv));
+
+ MD5_Init(&c);
+
+ for (frag = &pkt->wirevec[1]; len; frag++)
+ {
+ int iov_len = frag->iov_len;
+ char *iov_bas = (char *) frag->iov_base;
+
+ if (iov_len == 0)
+ return RXGKPACKETSHORT; /* Length mismatch */
+ if (len < iov_len)
+ iov_len = len; /* Don't process to much data */
+
+ MD5_Update(&c, iov_bas, iov_len);
+ len -= iov_len;
+ }
+ MD5_Final(checksum, &c);
+
+ des_cbc_encrypt(checksum, checksum, cksumsz, ks->chksum, &iv, 1);
+
+ return 0;
+}
+
+
+int
+rxg_PacketCheckSum(struct rxg_key_type *kt, struct rx_packet *pkt,
+ struct rxg_key *key, void *cksum, size_t cksumsz,
+ int encrypt)
+{
+ (*kt->cksum_pkt)(pkt, key, cksum, cksumsz, encrypt);
+ return 0;
+}
+
+int
+rxg_check_packet(struct rx_packet *pkt,
+ struct rx_connection *con,
+ int encrypt,
+ struct rxg_con *kc)
+{
+ struct variable_header_data hd;
+ char sum[RXG_MAX_CHECKSUM_SIZE];
+ char sum2[RXG_MAX_CHECKSUM_SIZE];
+ char *base;
+ int ret;
+
+ if (rx_GetPacketCksum(pkt) != 0)
+ return RXGKSEALEDINCON;
+
+ if (encrypt) {
+ ret = encrypt_pkt(kc->type, pkt, &kc->key, 0);
+ if (ret)
+ return ret;
+ }
+
+ base = pkt->wirevec[1].iov_base;
+ if (encrypt)
+ base += kc->type->confounderlen;
+ memcpy(sum, base, kc->type->checksumlen);
+ memset(base, 0, kc->type->checksumlen);
+
+ ret = rxg_PacketCheckSum(kc->type, pkt, &kc->key, sum2,
+ kc->type->checksumlen, 0);
+ if (ret)
+ return ret;
+
+ if (memcmp(sum2, sum, kc->type->checksumlen) != 0)
+ return RXGKSEALEDINCON;
+
+ getheader(pkt, &hd);
+
+ if (memcmp(base + kc->type->checksumlen, &hd, sizeof(hd)) != 0)
+ return RXGKSEALEDINCON;
+
+ return 0;
+}
+
+int
+rxg_prepare_packet(struct rx_packet *pkt,
+ struct rx_connection *con,
+ int encrypt,
+ struct rxg_con *kc)
+{
+ char sum[RXG_MAX_CHECKSUM_SIZE];
+ u_int len = rx_GetDataSize(pkt);
+ int diff, ret;
+ struct variable_header_data hd;
+ char *base;
+
+ /* checksum in rx header is defined to 0 in rxgss */
+ rx_SetPacketCksum(pkt, 0);
+
+ /*
+ * First we fixup the packet size, its assumed that the checksum
+ * need to to the operation on blocklen too
+ */
+
+ len += rx_GetSecurityHeaderSize(con); /* Extended pkt len */
+
+ if (encrypt) {
+ if ((diff = (len % kc->type->blocklen)) != 0) {
+ rxi_RoundUpPacket(pkt, diff);
+ len += diff;
+ }
+ }
+ rx_SetDataSize(pkt, len); /* Set extended packet length */
+
+ diff = kc->type->checksumlen + RXGK_HEADER_DATA_SIZE;
+ if (encrypt)
+ diff += kc->type->confounderlen;
+
+ if (pkt->wirevec[1].iov_len < diff)
+ return RXGKPACKETSHORT;
+
+ base = pkt->wirevec[1].iov_base;
+ if (encrypt) {
+ rxg_random_data(base, kc->type->confounderlen);
+ base += kc->type->confounderlen;
+ }
+ memset(base, 0, kc->type->checksumlen);
+ base += kc->type->checksumlen;
+ getheader(pkt, &hd);
+ memcpy(base, &hd, sizeof(hd));
+
+ /* computer and store checksum of packet */
+ ret = rxg_PacketCheckSum(kc->type, pkt, &kc->key,
+ sum, kc->type->checksumlen, 1);
+ if (ret)
+ return ret;
+
+ base = pkt->wirevec[1].iov_base;
+ if (encrypt)
+ base += kc->type->confounderlen;
+ memcpy(base, sum, kc->type->checksumlen);
+
+ if (!encrypt)
+ return 0;
+
+ return encrypt_pkt(kc->type, pkt, &kc->key, 1);
+}
+
+int
+rxgk_set_conn(struct rx_connection *con, int enctype, int enc)
+{
+ struct rxg_key_type *key;
+
+ key = rxg_find_enctype(enctype);
+ if (key)
+ return ENOENT;
+
+ if (enc) {
+ rx_SetSecurityHeaderSize(con, key->checksumlen + key->confounderlen +
+ RXGK_HEADER_DATA_SIZE);
+ rx_SetSecurityMaxTrailerSize(con, key->blocklen);
+ } else {
+ rx_SetSecurityHeaderSize(con,
+ key->checksumlen + RXGK_HEADER_DATA_SIZE);
+ rx_SetSecurityMaxTrailerSize(con, 0);
+ }
+ return 0;
+}
+
+
+int
+rxgk_prepare_packet(struct rx_packet *pkt, struct rx_connection *con,
+ int level, key_stuff *k, end_stuff *e)
+{
+ return 0;
+}
+
+int
+rxgk_check_packet(struct rx_packet *pkt, struct rx_connection *con,
+ int level, key_stuff *k, end_stuff *e)
+{
+ return 0;
+}
+
+
+#if 0
+
+int
+main(int argc, char **argv)
+{
+ krb5_encrypt();
+ return 0;
+}
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2002 - 2004, Stockholms universitet
+ * (Stockholm University, Stockholm Sweden)
+ * All rights reserved.
+ *
+ * Redistribution is not permitted
+ */
+
+#include "rxgk_locl.h"
+
+RCSID("$Id$");
+
+#include <rx/rx.h>
+#include "rxgk_proto.h"
+#include "rxgk_proto.cs.h"
+
+#include <errno.h>
+
+int
+rxgk5_get_auth_token(krb5_context context, uint32_t addr, int port,
+ uint32_t serviceId,
+ RXGK_Token *token,
+ RXGK_Token *auth_token, krb5_keyblock *key,
+ krb5_keyblock *skey,
+ int32_t *kvno)
+{
+ struct rx_securityClass *secobj;
+ struct rx_connection *conn;
+ RXGK_Token challange, reply_token;
+ uint32_t num;
+ int ret;
+
+ memset(skey, 0, sizeof(*skey));
+
+ secobj = rxnull_NewClientSecurityObject();
+
+ conn = rx_NewConnection(addr, port, serviceId, secobj, 0);
+ if (conn == NULL)
+ return ENETDOWN;
+
+ num = arc4random();
+
+ ret = rxk5_mutual_auth_client_generate(context, key, num, &challange);
+ if (ret) {
+ rx_DestroyConnection(conn);
+ return ret;
+ }
+
+ ret = RXGK_EstablishKrb5Context(conn, token, &challange,
+ &reply_token, kvno, auth_token);
+ if (ret) {
+ rx_DestroyConnection(conn);
+ return ret;
+ }
+
+ ret = rxk5_mutual_auth_client_check(context, key, num, &reply_token, skey);
+
+ rx_DestroyConnection(conn);
+
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (c) 1995 - 1998, 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "rxgk_locl.h"
+
+RCSID("$Id$");
+
+int32_t
+rxgk_GetServerInfo(struct rx_connection *con,
+ rxgk_level *level,
+ uint32_t *expiration,
+ char *name, size_t name_size,
+ char *cell, size_t cell_size,
+ int32_t *kvno)
+{
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+
+ if (cdat && cdat->authenticated
+ && (time(0) < cdat->expires))
+ {
+ if (level)
+ *level = cdat->cur_level;
+ if (expiration)
+ *expiration = cdat->expires;
+ return 0;
+ }
+ else
+ return RXGKNOAUTH;
+}
--- /dev/null
+/*
+ * Copyright (c) 1995 - 1998, 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id$ */
+
+#ifndef __RXGK_LOCL_H
+#define __RXGK_LOCL_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include <krb5.h>
+#include "rxgk_proto.h"
+
+#ifdef NDEBUG
+#ifndef assert
+#define assert(e) ((void)0)
+#endif
+#else
+#ifndef assert
+#define assert(e) ((e) ? (void)0 : (void)osi_Panic("assert(%s) failed: file %s, line %d\n", #e, __FILE__, __LINE__, #e))
+#endif
+#endif
+
+#undef RCSID
+#include <rx/rx.h>
+#include <rx/rx_null.h>
+#undef RCSID
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
+
+extern int rx_epoch, rx_nextCid;
+
+#include "rxgk.h"
+
+#define rxgk_disipline 3
+
+#define rxgk_unallocated 1
+#define rxgk_authenticated 2
+#define rxgk_expired 4
+#define rxgk_checksummed 8
+
+typedef struct key_stuff {
+ krb5_context ks_context;
+ krb5_keyblock ks_key;
+ uint32_t ks_recv_seqnum;
+ krb5_keyblock ks_skey;
+ krb5_crypto ks_crypto; /* rx session key */
+ krb5_crypto ks_scrypto; /* rx stream key */
+} key_stuff;
+
+typedef struct end_stuff {
+ /* need 64 bit counters */
+ uint32_t bytesReceived, packetsReceived, bytesSent, packetsSent;
+} end_stuff;
+
+extern int rxgk_key_contrib_size;
+
+int
+rxgk_prepare_packet(struct rx_packet *pkt, struct rx_connection *con,
+ int level, key_stuff *k, end_stuff *e);
+
+int
+rxgk_check_packet(struct rx_packet *pkt, struct rx_connection *con,
+ int level, key_stuff *k, end_stuff *e);
+
+/* Per connection specific server data */
+typedef struct serv_con_data {
+ end_stuff e;
+ key_stuff k;
+ uint32_t expires;
+ uint32_t nonce;
+ rxgk_level cur_level; /* Starts at min_level and can only increase */
+ char authenticated;
+} serv_con_data;
+
+/* rxgk */
+
+int
+rxgk5_get_auth_token(krb5_context context, uint32_t addr, int port,
+ uint32_t serviceId,
+ RXGK_Token *token,
+ RXGK_Token *auth_token, krb5_keyblock *key,
+ krb5_keyblock *skey,
+ int32_t *kvno);
+
+int
+rxk5_mutual_auth_client_generate(krb5_context context, krb5_keyblock *key,
+ uint32_t number,
+ RXGK_Token *challage_token);
+int
+rxk5_mutual_auth_client_check(krb5_context context, krb5_keyblock *key,
+ uint32_t number,
+ const RXGK_Token *reply_token,
+ krb5_keyblock *rxsession_key);
+int
+rxk5_mutual_auth_server(krb5_context context, krb5_keyblock *key,
+ const RXGK_Token *challage_token,
+ int *enctype,
+ void **session_key, size_t *session_key_size,
+ RXGK_Token *reply_token);
+
+int
+rxgk_set_conn(struct rx_connection *, int, int);
+
+int
+rxgk_decode_auth_token(void *data, size_t len, struct RXGK_AUTH_CRED *c);
+
+void
+rxgk_getheader(struct rx_packet *pkt, struct rxgk_header_data *h);
+
+int
+rxgk_server_init(void);
+
+#if 0
+int
+rxgk_derive_transport_key(krb5_context context,
+ krb5_keyblock *rx_conn_key,
+ RXGK_rxtransport_key *keycontrib,
+ krb5_keyblock *rkey);
+#endif
+
+int
+rxgk_random_to_key(int, void *, int, krb5_keyblock *);
+
+#endif /* __RXGK_LOCL_H */
--- /dev/null
+/* hej emacs det h{r {r en -*- c -*- fil */
+
+/*
+ * Copyright (c) 2002 - 2004, Stockholms Universitet
+ * (Stockholm University, Stockholm Sweden)
+ * All rights reserved.
+ *
+ * Redistribution is not permitted
+ */
+
+/* $Id$ */
+
+package RXGK_
+
+const RXGK_MAX_TOKEN_LEN = 65536;
+const RXGK_MAX_AUTHTOKEN = 256;
+
+/* ctext is limited by mtu since its part of responce */
+const RXGK_MAX_CTEXT = 768;
+
+const RXGK_SERVICE_ID = 34567;
+
+#define RXGK_ESTABLISH_KRB5_CONTEXT 1
+#define RXGK_ESTABLISH_GSS_CONTEXT 2
+#define RXGK_EXCHANGE_GSS_KEYS 3
+
+typedef opaque RXGK_Token<RXGK_MAX_TOKEN_LEN>;
+
+/*
+ *
+ */
+
+const RXGK_KEY_VERSION = 1;
+const RXGK_KEY_MAXSIZE = 256;
+const RXGK_KEY_MAXPRINCIPAL = 640;
+const RXGK_KEY_ENCTYPES = 32;
+
+/*
+ * Challange token in the
+ */
+
+const RXGK_CR_TOKEN_VERSION = 1;
+
+struct RXGK_CHALLENGE_TOKEN {
+ afs_int32 ct_version;
+ afs_uint32 ct_nonce;
+ afs_uint32 ct_enctype<RXGK_KEY_ENCTYPES>; /* listed in order of pref */
+};
+
+/*
+ * Reply token in the EstablishKrb5Context
+ */
+
+struct RXGK_REPLY_TOKEN {
+ afs_int32 rt_version;
+ afs_int32 rt_flags; /* other support ops */
+ afs_int32 rt_error;
+ afs_uint32 rt_nonce;
+ afs_uint32 rt_enctype;
+ opaque rt_key<RXGK_KEY_MAXSIZE>;
+};
+
+/*
+ * Rx auth cred equivalent
+ */
+
+struct RXGK_AUTH_CRED {
+ afs_int32 ac_version; /* version of format of RXGK_AUTH_CRED */
+ string ac_principal<RXGK_KEY_MAXPRINCIPAL>; /* prefixed with mech */
+ afs_int32 ac_starttime;
+ afs_int32 ac_endtime;
+ afs_int32 ac_enctype;
+ opaque ac_key<RXGK_KEY_MAXSIZE>;
+};
+
+/*
+ * This is part of the rxs challange/response exchange. Its somewhat
+ * complicated since it support rekeying of a data stream.
+ */
+
+const RXGK_VERSION = 3;
+
+const RXKG_OPCODE_CHALLENGE = 1;
+const RXKG_OPCODE_REKEY = 2;
+
+struct RXGK_Challenge {
+ afs_uint32 rc_version;
+ afs_uint32 rc_nonce;
+ afs_uint32 rc_opcode;
+ afs_uint32 rc_max_seq_skew; /* packets accepted when rekey */
+ afs_uint32 rc_min_level;
+};
+
+/* is the auth_token EstablishKrb5Context returned */
+struct RXGK_Response {
+ afs_uint32 rr_version;
+ afs_uint32 rr_auth_token_kvno;
+ opaque rr_auth_token<RXGK_MAX_AUTHTOKEN>;
+ opaque rr_ctext<RXGK_MAX_CTEXT>;
+};
+
+struct RXGK_Response_Crypt {
+ afs_uint32 nonce;
+ afs_uint32 epoch;
+ afs_uint32 cid;
+ afs_uint32 call_numbers[4];
+ afs_uint32 level;
+ afs_uint32 key_version;
+ afs_uint32 key_counter_hi;
+ afs_uint32 key_counter_lo;
+};
+
+/*
+ * Kerberos crypto framework enctypes
+ */
+
+const RXGK_CRYPTO_NULL = 0;
+const RXGK_CRYPTO_DES_CBC_CRC = 1;
+const RXGK_CRYPTO_DES_CBC_MD4 = 2;
+const RXGK_CRYPTO_DES_CBC_MD5 = 4;
+const RXGK_CRYPTO_DES3_SHA1_KD = 16;
+
+const RXGK_CRYPTO_CKSUM_RSA_DES_MD5 = 8;
+
+const RXGK_CLIENT_TO_SERVER = 0;
+const RXGK_SERVER_TO_CLIENT = 1;
+
+const RXGK_CLIENT_ENC_CHALLENGE = 1026;
+const RXGK_SERVER_ENC_REKEY = 1026;
+const RXGK_CLIENT_ENC_PACKETS = 1027;
+const RXGK_CLIENT_CKSUM_PACKETS = 1028;
+const RXGK_SERVER_ENC_PACKETS = 1029;
+const RXGK_SERVER_CKSUM_PACKETS = 1030;
+
+/*
+ * In packet protection since header isn't checksum-ed
+ */
+
+struct rxgk_header_data {
+ uint32_t call_number;
+ uint32_t channel_and_seq;
+};
+
+/*
+ * rx connection key
+ */
+
+struct RXGK_rxconn_key {
+ afs_uint32 rxk_cid;
+ afs_uint32 rxk_epoch;
+};
+
+#if 0
+
+const RXGK_MAX_KEYCONTRIB= 256; /* MUST only be used from server->client */
+
+struct RXGK_ReKey {
+ opaque rk_ctext<RXGK_MAX_CTEXT>;
+};
+
+struct RXGK_ReKey_Crypt {
+ afs_int32 rkc_version;
+ afs_int32 rkc_max_seq_num;
+ afs_int32 rkc_kvno; /* 16 bit number */
+ opaque rkc_keycontribution<RXGK_MAX_KEYCONTRIB>;
+};
+
+/* rx transport key */
+
+struct RXGK_rxtransport_key {
+ opaque client_keycontribution<RXGK_MAX_KEYCONTRIB>;
+ opaque server_keycontribution<RXGK_MAX_KEYCONTRIB>;
+};
+
+#endif
+
+/*
+ * kerberos auth_token
+ */
+
+EstablishKrb5Context(IN RXGK_Token *token,
+ IN RXGK_Token *challenge_token,
+ OUT RXGK_Token *reply_token,
+ OUT int32_t *auth_token_kvno,
+ OUT RXGK_Token *auth_token) = RXGK_ESTABLISH_KRB5_CONTEXT;
+
+/*
+ * Add gss stuff here
+ */
+
+#if 0
+
+EstablishGssContext(IN RXGK_Token *in_token,
+ OUT RXGK_Token *out_token) = RXGK_ESTABLISH_GSS_CONTEXT;
+
+ExchangeGSSKeys(IN RXGK_Token *challenge_token,
+ OUT RXGK_Token *reply_token,
+ OUT int32_t *auth_token_kvno,
+ OUT RXGK_Token *auth_token) = RXGK_EXCHANGE_GSS_KEYS;
+
+#endif
+
--- /dev/null
+/*
+ * Copyright (c) 1995 - 1998, 2002 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "rxgk_locl.h"
+
+RCSID("$Id$");
+
+#include <errno.h>
+
+#include "rxgk_proto.ss.h"
+
+/* Security object specific server data */
+typedef struct rxgk_serv_class {
+ struct rx_securityClass klass;
+ rxgk_level min_level;
+ char *principal;
+ char *service_principal;
+ void *appl_data;
+ int (*get_key)(void *, const char *, int, int, krb5_keyblock *);
+ int (*user_ok)(const char *name, const char *realm, int kvno);
+ uint32_t serviceId;
+} rxgk_serv_class;
+
+extern krb5_context gk_context;
+extern krb5_crypto gk_crypto;
+
+static int
+server_NewConnection(struct rx_securityClass *obj, struct rx_connection *con)
+{
+ serv_con_data *cdat;
+ assert(con->securityData == 0);
+ assert(gk_context != NULL);
+ obj->refCount++;
+ con->securityData = (char *) osi_Alloc(sizeof(serv_con_data));
+ memset(con->securityData, 0x0, sizeof(serv_con_data));
+ cdat = (serv_con_data *)con->securityData;
+ cdat->k.ks_context = gk_context;
+ return 0;
+}
+
+static int
+server_Close(struct rx_securityClass *obj)
+{
+ obj->refCount--;
+ if (obj->refCount <= 0)
+ osi_Free(obj, sizeof(rxgk_serv_class));
+ return 0;
+}
+
+static
+int
+server_DestroyConnection(struct rx_securityClass *obj,
+ struct rx_connection *con)
+{
+ serv_con_data *cdat = (serv_con_data *)con->securityData;
+
+ if (cdat)
+ osi_Free(cdat, sizeof(serv_con_data));
+ return server_Close(obj);
+}
+
+/*
+ * Check whether a connection authenticated properly.
+ * Zero is good (authentication succeeded).
+ */
+static int
+server_CheckAuthentication(struct rx_securityClass *obj,
+ struct rx_connection *con)
+{
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+
+ if (cdat)
+ return !cdat->authenticated;
+ else
+ return RXGKNOAUTH;
+}
+
+/*
+ * Select a nonce for later use.
+ */
+static
+int
+server_CreateChallenge(struct rx_securityClass *obj_,
+ struct rx_connection *con)
+{
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+
+ cdat->nonce = arc4random();
+ cdat->authenticated = 0;
+ return 0;
+}
+
+/*
+ * Wrap the nonce in a challenge packet.
+ */
+static int
+server_GetChallenge(const struct rx_securityClass *obj_,
+ const struct rx_connection *con,
+ struct rx_packet *pkt)
+{
+ rxgk_serv_class *obj = (rxgk_serv_class *) obj_;
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+ struct RXGK_Challenge c;
+ int initial_challage = 1;
+
+ c.rc_version = htonl(RXGK_VERSION);
+ c.rc_nonce = htonl(cdat->nonce);
+ c.rc_max_seq_skew = htonl(200); /* XXX */
+ c.rc_min_level = htonl(obj->min_level);
+
+ if (initial_challage) {
+ /* Make challenge */
+ c.rc_opcode = htonl(RXKG_OPCODE_CHALLENGE);
+
+ /* Stuff into packet */
+ if (rx_SlowWritePacket(pkt, 0, sizeof(c), &c) != sizeof(c))
+ return RXGKPACKETSHORT;
+ rx_SetDataSize(pkt, sizeof(c));
+#if 0
+ } else {
+ RXGK_ReKey rk;
+ RXGK_ReKey_Crypt rkc;
+ char bufrk[RXGK_REKEY_MAX_SIZE];
+ char bufrkc[RXGK_REKEY_CRYPT_MAX_SIZE];
+ krb5_data data;
+ size_t sz;
+ int ret;
+ key_stuff *k = &cdat->k;
+
+ memset(&rk, 0, sizeof(rk));
+ memset(&rkc, 0, sizeof(rkc));
+
+ c.rc_opcode = htonl(RXKG_OPCODE_REKEY);
+
+ if (rx_SlowWritePacket(pkt, 0, sizeof(c), &c) != sizeof(c))
+ return RXGKPACKETSHORT;
+
+ rkc.rkc_version = RXGK_VERSION;
+ rkc.rkc_max_seq_num = 200; /* XXX */
+ rkc.rkc_kvno = /* current_key + 1 */ 1;
+ rkc.rkc_keycontribution.len = 0; /* XXX */
+ rkc.rkc_keycontribution.val = NULL;
+
+ sz = RXGK_REKEY_CRYPT_MAX_SIZE;
+ if (ydr_encode_RXGK_ReKey_Crypt(&rkc, bufrkc, &sz) == NULL)
+ return RXGKPACKETSHORT;
+ sz = RXGK_REKEY_CRYPT_MAX_SIZE - sz;
+
+ ret = krb5_encrypt(k->ks_context, k->ks_crypto,
+ RXGK_SERVER_ENC_REKEY, bufrkc, sz, &data);
+ if (ret)
+ return ret;
+
+ rk.rk_ctext.val = data.data;
+ rk.rk_ctext.len = data.length;
+
+ sz = RXGK_REKEY_MAX_SIZE;
+ if (ydr_encode_RXGK_ReKey(&rk, bufrk, &sz) == NULL) {
+ krb5_data_free(&data);
+ return RXGKPACKETSHORT;
+ }
+ sz = RXGK_REKEY_MAX_SIZE - sz;
+
+ krb5_data_free(&data);
+
+ if (rx_SlowWritePacket(pkt, sizeof(c), sz, bufrk) != sz)
+ return RXGKPACKETSHORT;
+
+ rx_SetDataSize(pkt, sizeof(c) + sz);
+#endif
+ }
+ return 0;
+}
+
+/*
+ * Process a response to a challange.
+ */
+static int
+server_CheckResponse(struct rx_securityClass *obj_,
+ struct rx_connection *con,
+ struct rx_packet *pkt)
+{
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+
+ struct RXGK_Response r;
+ struct RXGK_Response_Crypt rc;
+ struct RXGK_AUTH_CRED c;
+ char response[RXGK_RESPONSE_MAX_SIZE];
+ size_t len, len2;
+ int ret;
+ krb5_context context = cdat->k.ks_context;
+ krb5_data data;
+
+ memset(&r, 0, sizeof(r));
+ memset(&c, 0, sizeof(r));
+
+ len = rx_SlowReadPacket(pkt, 0, sizeof(response), response);
+ if (len <= 0)
+ return RXGKPACKETSHORT;
+
+ len2 = len;
+ if (ydr_decode_RXGK_Response(&r, response, &len2) == NULL) {
+ ret = RXGKPACKETSHORT;
+ goto out;
+ }
+
+ ret = rxgk_decode_auth_token(r.rr_auth_token.val, r.rr_auth_token.len, &c);
+ if (ret)
+ goto out;
+
+ ret = rxgk_random_to_key(c.ac_enctype, c.ac_key.val, c.ac_key.len,
+ &cdat->k.ks_key);
+ if (ret)
+ goto out;
+
+ cdat->k.ks_crypto = NULL; /* XXX */
+ ret = krb5_crypto_init(context, &cdat->k.ks_key, cdat->k.ks_key.keytype,
+ &cdat->k.ks_crypto);
+ if (ret)
+ goto out2;
+
+
+ ret = krb5_decrypt(context, cdat->k.ks_crypto, RXGK_CLIENT_ENC_CHALLENGE,
+ r.rr_ctext.val, r.rr_ctext.len, &data);
+ if (ret)
+ goto out2;
+
+ len = data.length;
+ if (ydr_decode_RXGK_Response_Crypt(&rc, data.data, &len) == NULL) {
+ krb5_data_free(&data);
+ goto out2;
+ }
+
+ krb5_data_free(&data);
+
+ if (rc.epoch != con->epoch
+ || rc.cid != (con->cid & RX_CIDMASK)
+#if 0
+ || rc.security_index != con->securityIndex
+#endif
+ ) {
+ ret = RXGKSEALEDINCON;
+ goto out2;
+ }
+
+ {
+ int i;
+ for (i = 0; i < RX_MAXCALLS; i++)
+ {
+ if (rc.call_numbers[i] < 0) {
+ ret = RXGKSEALEDINCON;
+ goto out2;
+ }
+ }
+
+ }
+
+ if (rc.nonce != cdat->nonce + 1) {
+ ret = RXGKOUTOFSEQUENCE;
+ goto out2;
+ }
+
+ /* XXX */
+ if (rc.level != rxgk_crypt) {
+ ret = RXGKLEVELFAIL;
+ goto out2;
+ }
+
+ if ((rc.level != rxgk_auth && rc.level != rxgk_crypt) ||
+ rc.level < cdat->cur_level)
+ {
+ ret = RXGKLEVELFAIL;
+ goto out2;
+ }
+
+#if 0
+ ret = rxgk_derive_transport_key(context, &cdat->k.ks_key,
+ &rc.contrib, &cdat->k.ks_skey);
+ if (ret)
+ goto out2;
+#endif
+
+ ret = krb5_crypto_init (context, &cdat->k.ks_skey,
+ cdat->k.ks_skey.keytype,
+ &cdat->k.ks_scrypto);
+ if (ret)
+ goto out2;
+
+ rxi_SetCallNumberVector(con, rc.call_numbers);
+
+ cdat->authenticated = 1;
+ cdat->expires = c.ac_endtime;
+ cdat->cur_level = rc.level;
+
+ rxgk_set_conn(con, cdat->k.ks_key.keytype,
+ rc.level == rxgk_crypt ? 1 : 0);
+
+ out2:
+ if (ret) {
+ krb5_free_keyblock_contents(context, &cdat->k.ks_key);
+ if (cdat->k.ks_crypto)
+ krb5_crypto_destroy(context, cdat->k.ks_crypto);
+ cdat->k.ks_crypto = NULL;
+ }
+
+ out:
+
+ ydr_free_RXGK_AUTH_CRED(&c);
+ ydr_free_RXGK_Response(&r);
+
+ return ret;
+}
+
+/*
+ * Checksum and/or encrypt packet
+ */
+static int
+server_PreparePacket(struct rx_securityClass *obj_,
+ struct rx_call *call,
+ struct rx_packet *pkt)
+{
+ struct rx_connection *con = rx_ConnectionOf(call);
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+ key_stuff *k = &cdat->k;
+ end_stuff *e = &cdat->e;
+
+ return rxgk_prepare_packet(pkt, con, cdat->cur_level, k, e);
+}
+
+/*
+ * Verify checksum and/or decrypt packet.
+ */
+static int
+server_CheckPacket(struct rx_securityClass *obj_,
+ struct rx_call *call,
+ struct rx_packet *pkt)
+{
+ struct rx_connection *con = rx_ConnectionOf(call);
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+ key_stuff *k = &cdat->k;
+ end_stuff *e = &cdat->e;
+
+ if (time(0) > cdat->expires) /* Use fast time package instead??? */
+ return RXGKEXPIRED;
+
+ return rxgk_check_packet(pkt, con, cdat->cur_level, k, e);
+}
+
+static int
+server_GetStats(const struct rx_securityClass *obj_,
+ const struct rx_connection *con,
+ struct rx_securityObjectStats *st)
+{
+ rxgk_serv_class *obj = (rxgk_serv_class *) obj_;
+ serv_con_data *cdat = (serv_con_data *) con->securityData;
+
+ st->type = rxgk_disipline;
+ st->level = obj->min_level;
+ st->flags = rxgk_checksummed;
+ if (cdat == 0)
+ st->flags |= rxgk_unallocated;
+ {
+ st->bytesReceived = cdat->e.bytesReceived;
+ st->packetsReceived = cdat->e.packetsReceived;
+ st->bytesSent = cdat->e.bytesSent;
+ st->packetsSent = cdat->e.packetsSent;
+ st->expires = cdat->expires;
+ st->level = cdat->cur_level;
+ if (cdat->authenticated)
+ st->flags |= rxgk_authenticated;
+ }
+ return 0;
+}
+
+static
+void
+free_context(void)
+{
+ return;
+}
+
+static
+int
+server_NewService(const struct rx_securityClass *obj_,
+ struct rx_service *service,
+ int reuse)
+{
+ rxgk_serv_class *obj = (rxgk_serv_class *) obj_;
+
+ if (service->serviceId == obj->serviceId)
+ return 0;
+
+ if (!reuse) {
+ struct rx_securityClass *sec[2];
+ struct rx_service *secservice;
+
+ sec[0] = rxnull_NewServerSecurityObject();
+ sec[1] = NULL;
+
+ secservice = rx_NewService (service->servicePort,
+ obj->serviceId,
+ "rxgk",
+ sec, 1,
+ RXGK_ExecuteRequest);
+
+ secservice->destroyConnProc = free_context;
+ rx_setServiceRock(secservice, obj->principal);
+ }
+ return 0;
+}
+
+
+static struct rx_securityOps server_ops = {
+ server_Close,
+ server_NewConnection,
+ server_PreparePacket,
+ NULL,
+ server_CheckAuthentication,
+ server_CreateChallenge,
+ server_GetChallenge,
+ NULL,
+ server_CheckResponse,
+ server_CheckPacket,
+ server_DestroyConnection,
+ server_GetStats,
+ server_NewService,
+};
+
+struct rx_securityClass *
+rxgk_NewServerSecurityObject(/*rxgk_level*/ int min_level,
+ const char *principal,
+ void *appl_data,
+ int (*get_key)(void *data, const char *principal,
+ int enctype, int kvno,
+ krb5_keyblock *key),
+ int (*user_ok)(const char *name,
+ const char *realm,
+ int kvno),
+ uint32_t serviceId)
+{
+ rxgk_serv_class *obj;
+ int ret;
+
+ if (get_key == NULL || principal == NULL)
+ return NULL;
+
+ ret = rxgk_server_init();
+ if (ret)
+ return NULL;
+
+ obj = (rxgk_serv_class *) osi_Alloc(sizeof(rxgk_serv_class));
+ obj->klass.refCount = 1;
+ obj->klass.ops = &server_ops;
+ obj->klass.privateData = (char *) obj;
+
+ obj->min_level = min_level;
+ obj->appl_data = appl_data;
+ obj->get_key = get_key;
+ obj->user_ok = user_ok;
+ obj->principal = strdup(principal);
+ if (obj->principal == NULL) {
+ osi_Free(obj, sizeof(rxgk_serv_class));
+ return NULL;
+ }
+ obj->serviceId = serviceId;
+
+ return &obj->klass;
+}
--- /dev/null
+/*
+ * Copyright (c) 2002 - 2004, Stockholms universitet
+ * (Stockholm University, Stockholm Sweden)
+ * All rights reserved.
+ *
+ * Redistribution is not permitted
+ */
+
+#include "rxgk_locl.h"
+
+RCSID("$Id$");
+
+#include <errno.h>
+
+#include <rx/rx.h>
+#include "rxgk_proto.h"
+#include "rxgk_proto.ss.h"
+
+/* XXX need to pthread lock these */
+krb5_context gk_context;
+static krb5_keyblock gk_key;
+krb5_crypto gk_crypto;
+static int gk_kvno;
+
+static int
+get_key(const char *keytab_string, const char *p, int enctype, int kvno,
+ krb5_keyblock *key)
+{
+ krb5_error_code ret;
+ krb5_keytab keytab;
+ krb5_principal princ;
+ char keytab_buf[256];
+ krb5_keytab_entry ktentry;
+
+ ret = krb5_parse_name(gk_context, p, &princ);
+ if (ret)
+ return ret;
+
+ if (keytab_string == NULL) {
+ ret = krb5_kt_default_name (gk_context, keytab_buf,sizeof(keytab_buf));
+ if (ret)
+ krb5_err(gk_context, 1, ret, "resolving keytab %s", keytab_string);
+ keytab_string = keytab_buf;
+ }
+ ret = krb5_kt_resolve(gk_context, keytab_string, &keytab);
+ if (ret)
+ krb5_err(gk_context, 1, ret, "resolving keytab %s", keytab_string);
+
+ ret = krb5_kt_get_entry (gk_context, keytab, princ, kvno,
+ enctype, &ktentry);
+ if (ret)
+ krb5_err(gk_context, 1, ret, "krb5_kt_get_entry %s", p);
+
+ krb5_copy_keyblock_contents(gk_context, &ktentry.keyblock, key);
+ /* ktentry.vno */
+
+ krb5_kt_free_entry(gk_context, &ktentry);
+
+ krb5_kt_close(gk_context, keytab);
+
+ krb5_free_principal(gk_context, princ);
+
+ return ret;
+}
+
+int
+rxgk_default_get_key(void *data, const char *p, int enctype, int kvno,
+ krb5_keyblock *key)
+{
+ int ret;
+
+ ret = rxgk_server_init();
+ if (ret)
+ return ret;
+
+ return get_key(NULL, p, enctype, kvno, key);
+}
+
+
+int
+rxgk_server_init(void)
+{
+ static int inited = 0;
+ int ret;
+
+ if (inited)
+ return 0;
+
+ if (krb5_init_context(&gk_context))
+ return EINVAL;
+
+ ret = get_key(NULL, "gkkey@L.NXS.SE", 0, 0, &gk_key); /* XXX */
+ if (ret) {
+ krb5_free_context(gk_context);
+ gk_context = NULL;
+ return ret;
+ }
+
+ ret = krb5_crypto_init(gk_context, &gk_key, gk_key.keytype,
+ &gk_crypto);
+ if (ret) {
+ krb5_free_keyblock_contents(gk_context, &gk_key);
+ krb5_free_context(gk_context);
+ gk_context = NULL;
+ return ret;
+ }
+
+
+ inited = 1;
+
+ return 0;
+}
+
+static int
+build_auth_token(krb5_context context, const char *princ,
+ int32_t start, int32_t end,
+ krb5_keyblock *key,
+ int session_enctype,
+ void *session_key, size_t session_key_size,
+ int32_t *auth_token_kvno, RXGK_Token *auth_token)
+{
+ struct RXGK_AUTH_CRED cred;
+ krb5_data data;
+ void *ptr;
+ int sz, ret;
+
+ sz = RXGK_AUTH_CRED_MAX_SIZE;
+ ptr = malloc(sz);
+ if (ptr == NULL)
+ return ENOMEM;
+
+ cred.ac_version = RXGK_KEY_VERSION;
+ strlcpy(cred.ac_principal, princ, sizeof(cred.ac_principal));
+ cred.ac_starttime = start;
+ cred.ac_endtime = end;
+ cred.ac_enctype = session_enctype;
+ cred.ac_key.len = session_key_size;
+ cred.ac_key.val = session_key;
+
+ if (ydr_encode_RXGK_AUTH_CRED(&cred, ptr, &sz) == NULL) {
+ free(ptr);
+ return EINVAL;
+ }
+ sz = RXGK_AUTH_CRED_MAX_SIZE - sz;
+
+ ret = krb5_encrypt(context, gk_crypto, 0, ptr, sz, &data);
+ if (ret) {
+ free(ptr);
+ return ret;
+ }
+
+ if (data.length > RXGK_AUTH_CRED_MAX_SIZE) {
+ free(ptr);
+ return EINVAL;
+ }
+
+ memcpy(ptr, data.data, data.length);
+
+ auth_token->len = data.length;
+ auth_token->val = ptr;
+ *auth_token_kvno = gk_kvno;
+
+ krb5_data_free(&data);
+
+ return 0;
+}
+
+int
+rxgk_decode_auth_token(void *val, size_t len, RXGK_AUTH_CRED *c)
+{
+ krb5_data data;
+ size_t sz;
+ int ret;
+
+ memset(c, 0, sizeof(*c));
+
+ ret = krb5_decrypt(gk_context, gk_crypto, 0, val, len, &data);
+ if (ret)
+ return ret;
+
+ sz = data.length;
+ if (ydr_decode_RXGK_AUTH_CRED(c, data.data, &sz) == NULL) {
+ if (c->ac_key.val)
+ free(c->ac_key.val);
+ memset(c, 0, sizeof(*c));
+ ret = RXGKBADTICKET;
+ }
+
+ krb5_data_free(&data);
+
+ return ret;
+}
+
+/* XXX share */
+
+static int
+decode_v5(krb5_context context,
+ int (*get_key)(void *appl_data, const char *p, int enctype,
+ int kvno, krb5_keyblock *key),
+ void *appl_data,
+ const char *princ,
+ char *ticket,
+ int32_t ticket_len,
+ /* OUT parms */
+ krb5_principal *p,
+ krb5_keyblock *key,
+ int32_t *starts,
+ int32_t *expires)
+{
+ krb5_keyblock serv_key;
+ int code;
+ size_t siz;
+
+ Ticket t5; /* Must free */
+ EncTicketPart decr_part; /* Must free */
+ krb5_data plain; /* Must free */
+ krb5_crypto crypto; /* Must free */
+
+ memset(&t5, 0x0, sizeof(t5));
+ memset(&decr_part, 0x0, sizeof(decr_part));
+ krb5_data_zero(&plain);
+ memset(&serv_key, 0, sizeof(serv_key));
+ crypto = NULL;
+
+ code = decode_Ticket(ticket, ticket_len, &t5, &siz);
+ if (code != 0)
+ goto bad_ticket;
+
+ code = (*get_key)(appl_data, princ,
+ t5.enc_part.etype, t5.tkt_vno, &serv_key);
+ if (code)
+ goto unknown_key;
+
+ code = krb5_crypto_init (context, &serv_key, t5.enc_part.etype,
+ &crypto);
+ krb5_free_keyblock_contents(context, &serv_key);
+ if (code)
+ goto bad_ticket;
+
+ /* Decrypt ticket */
+ code = krb5_decrypt(context,
+ crypto,
+ 0,
+ t5.enc_part.cipher.data,
+ t5.enc_part.cipher.length,
+ &plain);
+
+ if (code)
+ goto bad_ticket;
+
+ /* Decode ticket */
+ code = decode_EncTicketPart(plain.data, plain.length, &decr_part, &siz);
+ if (code != 0)
+ goto bad_ticket;
+
+ /* principal */
+ code = principalname2krb5_principal(p, decr_part.cname, decr_part.crealm);
+ if (code)
+ goto bad_ticket;
+
+ /* Extract session key */
+ code = krb5_copy_keyblock_contents(context, &decr_part.key, key);
+ if (code)
+ goto bad_ticket;
+
+ /* Check lifetimes and host addresses, flags etc */
+ {
+ time_t now = time(0); /* Use fast time package instead??? */
+ time_t start = decr_part.authtime;
+ if (decr_part.starttime)
+ start = *decr_part.starttime;
+ if (start - now > context->max_skew || decr_part.flags.invalid)
+ goto no_auth;
+ if (now > decr_part.endtime)
+ goto tkt_expired;
+ *starts = start;
+ *expires = decr_part.endtime;
+ }
+
+#if 0
+ /* Check host addresses */
+#endif
+
+ cleanup:
+ free_Ticket(&t5);
+ free_EncTicketPart(&decr_part);
+ krb5_data_free(&plain);
+ if (crypto)
+ krb5_crypto_destroy(context, crypto);
+ if (code) {
+ krb5_free_principal(context, *p);
+ *p = NULL;
+ }
+ return code;
+
+ unknown_key:
+ code = RXGKUNKNOWNKEY;
+ goto cleanup;
+ no_auth:
+ code = RXGKNOAUTH;
+ goto cleanup;
+ tkt_expired:
+ code = RXGKEXPIRED;
+ goto cleanup;
+ bad_ticket:
+ code = RXGKBADTICKET;
+ goto cleanup;
+}
+
+int
+SRXGK_EstablishKrb5Context(struct rx_call *call,
+ const RXGK_Token *token,
+ const RXGK_Token *challage_token,
+ RXGK_Token *reply_token,
+ int32_t *auth_token_kvno,
+ RXGK_Token *auth_token)
+{
+ krb5_principal principal;
+ krb5_keyblock key;
+ int32_t starts, expires;
+ char *cprinc, *sprinc;
+ void *session_key;
+ size_t session_key_size;
+ int session_enctype;
+ int ret;
+
+ ret = rxgk_server_init();
+ if (ret)
+ return ret;
+
+ if ((sprinc = rx_getServiceRock(call->conn->service)) == NULL)
+ return EINVAL;
+
+ session_key = NULL;
+
+ key.keyvalue.data = NULL;
+
+ auth_token->len = reply_token->len = 0;
+ auth_token->val = reply_token->val = NULL;
+
+ ret = decode_v5(gk_context, rxgk_default_get_key, NULL, sprinc,
+ token->val, token->len,
+ &principal, &key, &starts, &expires);
+ if (ret)
+ goto out;
+
+ ret = rxk5_mutual_auth_server(gk_context,
+ &key,
+ challage_token,
+ &session_enctype,
+ &session_key,
+ &session_key_size,
+ reply_token);
+ if (ret)
+ goto out;
+
+ ret = krb5_unparse_name(gk_context, principal, &cprinc);
+ if (ret)
+ goto out;
+
+ ret = build_auth_token(gk_context, cprinc, starts, expires, &key,
+ session_enctype, session_key, session_key_size,
+ auth_token_kvno, auth_token);
+
+ free(cprinc);
+
+ out:
+ if (session_key) {
+ memset(session_key, 0, session_key_size);
+ free(session_key);
+ }
+ if (key.keyvalue.data != NULL)
+ krb5_free_keyblock_contents(gk_context, &key);
+
+ if (ret) {
+ if (reply_token->val)
+ free(reply_token->val);
+ reply_token->len = 0;
+ reply_token->val = NULL;
+
+ if (auth_token->val)
+ free(auth_token->val);
+ auth_token->len = 0;
+ auth_token->val = NULL;
+ }
+
+ return ret;
+}
--- /dev/null
+/* hej emacs det h{r {r en -*- c -*- fil */
+
+/*
+ * Copyright (c) 2002, Stockholms Universitet
+ * (Stockholm University, Stockholm Sweden)
+ * All rights reserved.
+ *
+ * Redistribution is not permitted
+ */
+
+/* $Id$ */
+
+package TEST_
+
+const TEST_DEFAULT_PORT = 7009;
+
+const TEST_RXGK_SERVICE = 64000;
+
+const TEST_SERVICE_ID = 10;
+
+get_hundraelva(OUT afs_int32 *foo, OUT string bar<100>) = 18;
--- /dev/null
+/*
+ * Copyright (c) 2002 - 2004, Stockholms universitet
+ * (Stockholm University, Stockholm Sweden)
+ * All rights reserved.
+ *
+ * Redistribution is not permitted
+ */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+
+#include "rxgk_locl.h"
+#include "rxgk_proto.cs.h"
+#include "test.cs.h"
+
+RCSID("$Id$");
+
+/*
+ *
+ */
+
+static u_long
+str2addr (const char *s)
+{
+ struct in_addr server;
+ struct hostent *h;
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+ if (inet_addr(s) != INADDR_NONE)
+ return inet_addr(s);
+ h = gethostbyname (s);
+ if (h != NULL) {
+ memcpy (&server, h->h_addr_list[0], sizeof(server));
+ return server.s_addr;
+ }
+ return 0;
+}
+
+
+static int
+get_krb5_token(krb5_context ctx, krb5_keyblock **key, RXGK_Token *token)
+{
+ krb5_error_code ret;
+ krb5_creds in_creds, *out_creds;
+ krb5_ccache id;
+ char *realm = "L.NXS.SE";
+ int realm_len = strlen(realm);
+
+ memset(token, 0, sizeof(*token));
+
+ ret = krb5_cc_default (ctx, &id);
+ if (ret)
+ return ret;
+
+ memset(&in_creds, 0, sizeof(in_creds));
+ ret = krb5_build_principal(ctx, &in_creds.server,
+ realm_len, realm, "afs", NULL);
+ if(ret)
+ return ret;
+ ret = krb5_build_principal(ctx, &in_creds.client,
+ realm_len, realm, "lha", NULL);
+ if(ret){
+ krb5_free_principal(ctx, in_creds.server);
+ return ret;
+ }
+ in_creds.session.keytype = KEYTYPE_DES; /* XXX */
+ ret = krb5_get_credentials(ctx, 0, id, &in_creds, &out_creds);
+ krb5_free_principal(ctx, in_creds.server);
+ krb5_free_principal(ctx, in_creds.client);
+ if(ret)
+ return ret;
+
+ token->val = malloc(out_creds->ticket.length);
+ if (token->val == NULL) {
+ krb5_free_creds(ctx, out_creds);
+ return ENOMEM;
+ }
+ token->len = out_creds->ticket.length;
+ memcpy(token->val, out_creds->ticket.data, out_creds->ticket.length);
+
+ ret = krb5_copy_keyblock(ctx, &out_creds->session, key);
+
+ krb5_free_creds(ctx, out_creds);
+
+ return ret;
+}
+
+/*
+ *
+ */
+
+static void
+test_est_context(krb5_context context, uint32_t addr, int port,
+ RXGK_Token *ticket, krb5_keyblock *key)
+{
+ RXGK_Token auth_token;
+ krb5_keyblock skey;
+ int32_t kvno;
+ int ret;
+
+ /* kernel */
+
+ ret = rxgk5_get_auth_token(context, addr, port,
+ TEST_RXGK_SERVICE,
+ ticket, &auth_token, key, &skey, &kvno);
+ if (ret)
+ errx(1, "rxgk5_get_auth_token: %d", ret);
+
+ printf("EstablishKrb5Context succeeded "
+ "len: %d, version: %d, enctype: %d\n",
+ auth_token.len, kvno, skey.keytype);
+}
+
+static void
+test_rxgk_conn(krb5_context context, uint32_t addr, int port,
+ RXGK_Token *ticket, krb5_keyblock *key)
+{
+ struct rx_securityClass *secobj;
+ struct rx_connection *conn;
+ int ret;
+ char bar[100];
+ int32_t a111;
+
+ secobj = rxgk_k5_NewClientSecurityObject(rxgk_crypt,
+ key,
+ 0,
+ ticket->len,
+ ticket->val,
+ TEST_RXGK_SERVICE,
+ context);
+
+ conn = rx_NewConnection(addr, port, TEST_SERVICE_ID, secobj, 4);
+ if (conn == NULL)
+ errx(1, "NewConnection");
+
+ ret = TEST_get_hundraelva(conn, &a111, bar);
+
+ rx_DestroyConnection(conn);
+
+ if (ret)
+ errx(1, "TEST_get_hundraelva: %d", ret);
+
+ printf("get_hundraelva return %d (should be 111) (bar = \"%s\")\n",
+ (int)a111, bar);
+}
+
+
+/*
+ *
+ */
+
+int
+main(int argc, char **argv)
+{
+ RXGK_Token ticket;
+ krb5_context context;
+ krb5_keyblock *key;
+ int port, ret;
+ uint32_t addr;
+ char *saddr;
+ PROCESS pid;
+
+ setprogname(argv[0]);
+
+ port = htons(TEST_DEFAULT_PORT);
+ saddr = "127.0.0.1";
+
+ krb5_init_context(&context);
+
+ LWP_InitializeProcessSupport (LWP_NORMAL_PRIORITY, &pid);
+
+ ret = rx_Init (0);
+ if (ret)
+ errx (1, "rx_Init failed");
+
+ addr = str2addr(saddr);
+
+ ret = get_krb5_token(context, &key, &ticket);
+ if (ret)
+ errx(1, "get_krb5_token: %d", ret);
+
+ if (0) {
+ test_est_context(context, addr, port, &ticket, key);
+ } else {
+ test_rxgk_conn(context, addr, port, &ticket, key);
+ }
+
+ rx_Finalize();
+
+ krb5_free_keyblock(context, key);
+ krb5_free_context(context);
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2002 - 2004, Stockholms universitet
+ * (Stockholm University, Stockholm Sweden)
+ * All rights reserved.
+ *
+ * Redistribution is not permitted
+ */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <netdb.h>
+
+#include "rxgk_locl.h"
+#include "rxgk_proto.ss.h"
+#include "test.ss.h"
+
+RCSID("$Id$");
+
+/*
+ *
+ */
+
+int
+STEST_get_hundraelva(struct rx_call *call, int32_t *foo, char *bar)
+{
+ *foo = 111;
+ snprintf(bar, 100, "hej");
+ return 0;
+}
+
+/*
+ *
+ */
+
+int
+main(int argc, char **argv)
+{
+ struct rx_securityClass *secureobj[5];
+ struct rx_service *service;
+ int secureindex;
+ PROCESS pid;
+ int port = htons(TEST_DEFAULT_PORT);
+ int ret;
+
+ LWP_InitializeProcessSupport (LWP_NORMAL_PRIORITY, &pid);
+
+ ret = rx_Init (port);
+ if (ret)
+ errx (1, "rx_Init failed");
+
+ secureindex = 5;
+ memset(secureobj, 0, sizeof(secureobj));
+ secureobj[4] =
+ rxgk_NewServerSecurityObject(rxgk_auth,
+ "afs@L.NXS.SE",
+ NULL,
+ rxgk_default_get_key,
+ NULL,
+ TEST_RXGK_SERVICE);
+
+ service = rx_NewService (0,
+ TEST_SERVICE_ID,
+ "rxgk-test",
+ secureobj,
+ secureindex,
+ TEST_ExecuteRequest);
+ if (service == NULL)
+ errx(1, "Cant create server");
+
+ rx_StartServer(1) ;
+
+ return 0;
+}