summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--acconfig.h33
-rw-r--r--configure.in58
-rw-r--r--debian/control2
-rwxr-xr-xdebian/rules14
-rw-r--r--h/config.h.in263
-rw-r--r--h/internal.h56
-rw-r--r--h/zephyr/zephyr.h10
-rw-r--r--lib/Makefile.in3
-rw-r--r--lib/ZCkAuth.c36
-rw-r--r--lib/ZFmtAuth.c70
-rw-r--r--lib/ZFmtNotice.c26
-rw-r--r--lib/ZFmtSmRaw.c23
-rw-r--r--lib/ZGetSender.c45
-rw-r--r--lib/ZInit.c45
-rw-r--r--lib/ZMkAuth.c188
-rw-r--r--lib/ZParseNot.c21
-rw-r--r--lib/Zinternal.c518
-rw-r--r--server/bdump.c229
-rw-r--r--server/class.c12
-rw-r--r--server/client.c10
-rw-r--r--server/dispatch.c60
-rw-r--r--server/kstuff.c811
-rw-r--r--server/main.c44
-rw-r--r--server/realm.c384
-rw-r--r--server/server.c8
-rw-r--r--server/subscr.c88
-rw-r--r--server/uloc.c17
-rw-r--r--server/zserver.h68
-rw-r--r--server/zsrv_conf.h4
-rw-r--r--server/zsrv_err.et2
-rw-r--r--zhm/zhm_client.c2
31 files changed, 2600 insertions, 550 deletions
diff --git a/acconfig.h b/acconfig.h
index 96eb3d1..b4ec827 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -4,6 +4,39 @@
/* Define to compile with Kerberos support. */
#undef HAVE_KRB4
+/* Define to compile with Kerberos v5 support. */
+#undef HAVE_KRB5
+
+/* Define to 1 if `enc_part2' is member of `krb5_ticket'. */
+#undef HAVE_KRB5_TICKET_ENC_PART2
+
+/* Define to 1 if `keyblock.enctype' is member of `krb5_creds'. */
+#undef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
+
+/* Define to 1 if you have the `krb5_c_make_checksum' function. */
+#undef HAVE_KRB5_C_MAKE_CHECKSUM
+
+/* Define to 1 if you have the `krb5_cc_set_default_name' function. */
+#undef HAVE_KRB5_CC_SET_DEFAULT_NAME
+
+/* Define to 1 if `krb5_auth_con_getauthenticator' takes a double pointer third arg. */
+#undef KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER
+
+/* Define to 1 if you have the <krb5_err.h> header file. */
+#undef HAVE_KRB5_ERR_H
+
+/* Define to 1 if you have the `krb5_free_data' function. */
+#undef HAVE_KRB5_FREE_DATA
+
+/* Define to 1 if you have the <krb5/ss.h> header file. */
+#undef HAVE_KRB5_SS_H
+
+/* Define to 1 if you have the `krb_get_err_text' function. */
+#undef HAVE_KRB_GET_ERR_TEXT
+
+/* Define to 1 if you have the `krb_log' function. */
+#undef HAVE_KRB_LOG
+
/* Define to compile with ares support. */
#undef HAVE_ARES
diff --git a/configure.in b/configure.in
index c894ab8..7985dae 100644
--- a/configure.in
+++ b/configure.in
@@ -37,7 +37,7 @@ AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS(fcntl.h paths.h termios.h sgtty.h unistd.h malloc.h)
AC_CHECK_HEADERS(sys/filio.h sys/ioctl.h sys/time.h sys/file.h sys/utsname.h)
-AC_CHECK_HEADERS(sys/select.h sys/msgbuf.h sys/cdefs.h)
+AC_CHECK_HEADERS(sys/select.h sys/msgbuf.h sys/cdefs.h krb5_err.h)
if test "$no_x" != "yes"; then
XCLIENTS=xzwrite
@@ -86,12 +86,13 @@ AC_SUBST(RLIB)
AC_SUBST(SLIB)
ATHENA_KRB4
+ATHENA_KRB5
ATHENA_HESIOD
ATHENA_REGEXP
ATHENA_ARES
ATHENA_UTIL_COM_ERR
ATHENA_UTIL_SS
-LIBS="$KRB4_LIBS $HESIOD_LIBS $LIBS"
+LIBS="$KRB5_LIBS $KRB4_LIBS $HESIOD_LIBS $LIBS"
dnl Checks for library functions.
AC_PROG_GCC_TRADITIONAL
@@ -100,6 +101,59 @@ AC_FUNC_GETPGRP
AC_FUNC_SETPGRP
AC_CHECK_FUNCS(putenv strchr memcpy memmove waitpid getlogin strerror random)
AC_CHECK_FUNCS(lrand48 gethostid getsid getpgid krb_get_err_text krb_log)
+AC_CHECK_FUNCS(krb5_free_data krb5_c_make_checksum krb5_cc_set_default_name)
+
+AC_MSG_CHECKING(for krb5_auth_con_getauthenticator taking double pointer)
+AC_CACHE_VAL(ac_cv_krb5_auth_con_getauthenticator_takes_double_pointer, [
+local_save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="${CPPFLAGS} ${KRB5_INC_FLAGS}"
+AC_TRY_COMPILE(
+[#define socklen_t int
+#define ssize_t int
+#include <krb5.h>
+krb5_error_code
+krb5_auth_con_getauthenticator(krb5_context context,
+ krb5_auth_context auth_context,
+ krb5_authenticator *authenticator);],
+[krb5_error_code foo = krb5_auth_con_getauthenticator(0, 0, 0);],
+ac_cv_krb5_auth_con_getauthenticator_takes_double_pointer=no,
+ac_cv_krb5_auth_con_getauthenticator_takes_double_pointer=yes)
+])
+CPPFLAGS="${local_save_CPPFLAGS}"
+if test "$ac_cv_krb5_auth_con_getauthenticator_takes_double_pointer" = yes; then
+ AC_DEFINE(KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER)dnl
+fi
+AC_MSG_RESULT($ac_cv_krb5_auth_con_getauthenticator_takes_double_pointer)
+
+AC_MSG_CHECKING(for enc_part2 in struct krb5_ticket)
+AC_CACHE_VAL(ac_cv_have_krb5_ticket_enc_part2, [
+local_save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="${CPPFLAGS} ${KRB5_INC_FLAGS}"
+AC_TRY_COMPILE(
+[#include <krb5.h>], [krb5_ticket _tkt; _tkt.enc_part2;],
+ac_cv_have_krb5_ticket_enc_part2=yes,
+ac_cv_have_krb5_ticket_enc_part2=no)
+])
+CPPFLAGS="${local_save_CPPFLAGS}"
+if test "$ac_cv_have_krb5_ticket_enc_part2" = yes; then
+ AC_DEFINE(HAVE_KRB5_TICKET_ENC_PART2)dnl
+fi
+AC_MSG_RESULT($ac_cv_have_krb5_ticket_enc_part2)
+
+AC_MSG_CHECKING(for enctype in struct krb5_keyblock)
+AC_CACHE_VAL(ac_cv_have_krb5_creds_keyblock_enctype, [
+local_save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="${CPPFLAGS} ${KRB5_INC_FLAGS}"
+AC_TRY_COMPILE(
+[#include <krb5.h>], [krb5_creds _creds; _creds.keyblock.enctype;],
+ac_cv_have_krb5_creds_keyblock_enctype=yes,
+ac_cv_have_krb5_creds_keyblock_enctype=no)
+])
+CPPFLAGS="${local_save_CPPFLAGS}"
+if test "$ac_cv_have_krb5_creds_keyblock_enctype" = yes; then
+ AC_DEFINE(HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE)dnl
+fi
+AC_MSG_RESULT($ac_cv_have_krb5_creds_keyblock_enctype)
AC_CONFIG_HEADER(h/config.h)
AC_OUTPUT(Makefile clients/Makefile clients/xzwrite/Makefile
diff --git a/debian/control b/debian/control
index a7d5058..df8502e 100644
--- a/debian/control
+++ b/debian/control
@@ -20,7 +20,7 @@ Description: The original "Instant Message" system libraries without Kerberos
Package: libzephyr3-krb
Section: libs
Architecture: any
-Depends: ${shlibs:Depends}, krb4-config
+Depends: ${shlibs:Depends}, krb5-config
Conflicts: libzephyr3
Provides: libzephyr3
Description: The original "Instant Message" system libraries with Kerberos
diff --git a/debian/rules b/debian/rules
index ffab880..41be8c0 100755
--- a/debian/rules
+++ b/debian/rules
@@ -51,9 +51,9 @@ configure-stamp:
dh_testdir
# Add here commands to configure the package.
-mkdir krb
- cd krb&&../configure --with-krb4=/usr $(CONFIGURE_ROOT)
+ cd krb&& CFLAGS=-g ../configure --with-krb4=/usr --with-krb5=/usr $(CONFIGURE_ROOT)
-mkdir no-krb
- cd no-krb&&../configure $(CONFIGURE_ROOT)
+ cd no-krb&& CFLAGS=-g ../configure $(CONFIGURE_ROOT)
touch configure-stamp
build: configure-stamp build-stamp
@@ -126,20 +126,11 @@ binary-arch: build install
dh_movefiles --sourcedir=debian/tmp-krb -plibzephyr3-krb -pzephyr-server-krb
dh_installdebconf
dh_installdocs
-# dh_installexamples
-# dh_installmenu
-# dh_installemacsen
-# dh_installpam
dh_installinit -pzephyr-clients --init-script=zhm --no-start
dh_installinit -pzephyr-server-krb --init-script=zephyrd
dh_installinit -pzephyr-server --init-script=zephyrd
-# dh_installcron
-# dh_installmanpages
-# dh_installinfo
-# dh_undocumented
dh_installchangelogs
dh_strip
-# dh_link
dh_compress
dh_fixperms
# You may want to make some executables suid here.
@@ -148,7 +139,6 @@ binary-arch: build install
cp debian/libzephyr3/DEBIAN/shlibs debian/libzephyr3-krb/DEBIAN/shlibs
dh_shlibdeps
dh_installdeb
-# dh_perl
dh_gencontrol
dh_md5sums
dh_builddeb
diff --git a/h/config.h.in b/h/config.h.in
index 1a3dd61..c962a5d 100644
--- a/h/config.h.in
+++ b/h/config.h.in
@@ -1,40 +1,42 @@
-/* h/config.h.in. Generated automatically from configure.in by autoheader. */
+/* h/config.h.in. Generated from configure.in by autoheader. */
+/* Define to compile with Hesiod support. */
+#undef HAVE_HESIOD
-/* Define if the `getpgrp' function takes no argument. */
-#undef GETPGRP_VOID
+/* Define to compile with Kerberos support. */
+#undef HAVE_KRB4
-/* Define to `int' if <sys/types.h> doesn't define. */
-#undef gid_t
+/* Define to compile with Kerberos v5 support. */
+#undef HAVE_KRB5
-/* Define if you don't have vprintf but do have _doprnt. */
-#undef HAVE_DOPRNT
+/* Define to 1 if `enc_part2' is member of `krb5_ticket'. */
+#undef HAVE_KRB5_TICKET_ENC_PART2
-/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
-#undef HAVE_SYS_WAIT_H
+/* Define to 1 if `keyblock.enctype' is member of `krb5_creds'. */
+#undef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
-/* Define if you have the vprintf function. */
-#undef HAVE_VPRINTF
+/* Define to 1 if you have the `krb5_c_make_checksum' function. */
+#undef HAVE_KRB5_C_MAKE_CHECKSUM
-/* Define as the return type of signal handlers (int or void). */
-#undef RETSIGTYPE
+/* Define to 1 if you have the `krb5_cc_set_default_name' function. */
+#undef HAVE_KRB5_CC_SET_DEFAULT_NAME
-/* Define if the `setpgrp' function takes no argument. */
-#undef SETPGRP_VOID
+/* Define to 1 if `krb5_auth_con_getauthenticator' takes a double pointer third arg. */
+#undef KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER
-/* Define if you have the ANSI C header files. */
-#undef STDC_HEADERS
+/* Define to 1 if you have the <krb5_err.h> header file. */
+#undef HAVE_KRB5_ERR_H
-/* Define to `int' if <sys/types.h> doesn't define. */
-#undef uid_t
+/* Define to 1 if you have the `krb5_free_data' function. */
+#undef HAVE_KRB5_FREE_DATA
-/* Define if the X Window System is missing or not being used. */
-#undef X_DISPLAY_MISSING
+/* Define to 1 if you have the <krb5/ss.h> header file. */
+#undef HAVE_KRB5_SS_H
-/* Define to compile with Hesiod support. */
-#undef HAVE_HESIOD
+/* Define to 1 if you have the `krb_get_err_text' function. */
+#undef HAVE_KRB_GET_ERR_TEXT
-/* Define to compile with Kerberos support. */
-#undef HAVE_KRB4
+/* Define to 1 if you have the `krb_log' function. */
+#undef HAVE_KRB_LOG
/* Define to compile with ares support. */
#undef HAVE_ARES
@@ -45,122 +47,223 @@
/* Define if you have the System Resource Controller library. */
#undef HAVE_SRC
+/* Define to "unsigned long" if your system headers don't. */
+#undef ulong
+
/* Define to a temporary directory on your system. */
#define FOUND_TMP "/var/tmp"
/* Define to the type of the host system. */
#define MACHINE_TYPE "unknown"
-/* The number of bytes in a int. */
-#undef SIZEOF_INT
+/* Define if `regcomp' exists and works. */
+#undef HAVE_REGCOMP
-/* The number of bytes in a long. */
-#undef SIZEOF_LONG
-/* The number of bytes in a short. */
-#undef SIZEOF_SHORT
+/* Define to 1 if the `getpgrp' function requires zero arguments. */
+#undef GETPGRP_VOID
-/* Define if you have the gethostid function. */
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `gethostid' function. */
#undef HAVE_GETHOSTID
-/* Define if you have the getlogin function. */
+/* Define to 1 if you have the `getlogin' function. */
#undef HAVE_GETLOGIN
-/* Define if you have the getpgid function. */
+/* Define to 1 if you have the `getpgid' function. */
#undef HAVE_GETPGID
-/* Define if you have the getsid function. */
+/* Define to 1 if you have the `getsid' function. */
#undef HAVE_GETSID
-/* Define if you have the krb_get_err_text function. */
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `krb5_cc_set_default_name' function. */
+#undef HAVE_KRB5_CC_SET_DEFAULT_NAME
+
+/* Define to 1 if you have the `krb5_c_make_checksum' function. */
+#undef HAVE_KRB5_C_MAKE_CHECKSUM
+
+/* Define to 1 if you have the <krb5_err.h> header file. */
+#undef HAVE_KRB5_ERR_H
+
+/* Define to 1 if you have the `krb5_free_data' function. */
+#undef HAVE_KRB5_FREE_DATA
+
+/* Define to 1 if you have the `krb_get_err_text' function. */
#undef HAVE_KRB_GET_ERR_TEXT
-/* Define if you have the krb_log function. */
+/* Define to 1 if you have the `krb_log' function. */
#undef HAVE_KRB_LOG
-/* Define if you have the lrand48 function. */
+/* Define to 1 if you have the `44bsd' library (-l44bsd). */
+#undef HAVE_LIB44BSD
+
+/* Define to 1 if you have the `curses' library (-lcurses). */
+#undef HAVE_LIBCURSES
+
+/* Define to 1 if you have the `dl' library (-ldl). */
+#undef HAVE_LIBDL
+
+/* Define to 1 if you have the `gen' library (-lgen). */
+#undef HAVE_LIBGEN
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define to 1 if you have the `readline' library (-lreadline). */
+#undef HAVE_LIBREADLINE
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define to 1 if you have the `w' library (-lw). */
+#undef HAVE_LIBW
+
+/* Define to 1 if you have the `lrand48' function. */
#undef HAVE_LRAND48
-/* Define if you have the memcpy function. */
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the `memcpy' function. */
#undef HAVE_MEMCPY
-/* Define if you have the memmove function. */
+/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
-/* Define if you have the putenv function. */
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define to 1 if you have the `putenv' function. */
#undef HAVE_PUTENV
-/* Define if you have the random function. */
+/* Define to 1 if you have the `random' function. */
#undef HAVE_RANDOM
-/* Define if you have the strchr function. */
-#undef HAVE_STRCHR
+/* Define to 1 if you have the <sgtty.h> header file. */
+#undef HAVE_SGTTY_H
-/* Define if you have the strerror function. */
-#undef HAVE_STRERROR
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
-/* Define if you have the waitpid function. */
-#undef HAVE_WAITPID
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
-/* Define if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
-/* Define if you have the <malloc.h> header file. */
-#undef HAVE_MALLOC_H
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
-/* Define if you have the <paths.h> header file. */
-#undef HAVE_PATHS_H
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
-/* Define if you have the <sgtty.h> header file. */
-#undef HAVE_SGTTY_H
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
-/* Define if you have the <sys/cdefs.h> header file. */
+/* Define to 1 if you have the <sys/cdefs.h> header file. */
#undef HAVE_SYS_CDEFS_H
-/* Define if you have the <sys/file.h> header file. */
+/* Define to 1 if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
-/* Define if you have the <sys/filio.h> header file. */
+/* Define to 1 if you have the <sys/filio.h> header file. */
#undef HAVE_SYS_FILIO_H
-/* Define if you have the <sys/ioctl.h> header file. */
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
-/* Define if you have the <sys/msgbuf.h> header file. */
+/* Define to 1 if you have the <sys/msgbuf.h> header file. */
#undef HAVE_SYS_MSGBUF_H
-/* Define if you have the <sys/select.h> header file. */
+/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
-/* Define if you have the <sys/time.h> header file. */
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
-/* Define if you have the <sys/utsname.h> header file. */
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/utsname.h> header file. */
#undef HAVE_SYS_UTSNAME_H
-/* Define if you have the <termios.h> header file. */
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
-/* Define if you have the <unistd.h> header file. */
+/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
-/* Define if you have the 44bsd library (-l44bsd). */
-#undef HAVE_LIB44BSD
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
-/* Define if you have the dl library (-ldl). */
-#undef HAVE_LIBDL
+/* Define to 1 if you have the `waitpid' function. */
+#undef HAVE_WAITPID
-/* Define if you have the gen library (-lgen). */
-#undef HAVE_LIBGEN
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
-/* Define if you have the nsl library (-lnsl). */
-#undef HAVE_LIBNSL
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
-/* Define if you have the resolv library (-lresolv). */
-#undef HAVE_LIBRESOLV
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
-/* Define if you have the socket library (-lsocket). */
-#undef HAVE_LIBSOCKET
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
-/* Define if you have the w library (-lw). */
-#undef HAVE_LIBW
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* Define to 1 if the `setpgrp' function takes no argument. */
+#undef SETPGRP_VOID
+
+/* The size of `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of `short', as computed by sizeof. */
+#undef SIZEOF_SHORT
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#undef X_DISPLAY_MISSING
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#undef YYTEXT_POINTER
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
diff --git a/h/internal.h b/h/internal.h
index f0b482c..403e85c 100644
--- a/h/internal.h
+++ b/h/internal.h
@@ -11,6 +11,10 @@
#include <krb_err.h>
#endif
+#ifdef HAVE_KRB5
+#include <krb5.h>
+#endif
+
#ifdef HAVE_HESIOD
#include <hesiod.h>
#endif
@@ -34,6 +38,13 @@
#define Z_NOTICETIMELIMIT 30 /* Time to wait for fragments */
#define Z_INITFILTERSIZE 30 /* Starting size of uid filter */
+#define Z_AUTHMODE_NONE 0 /* no authentication */
+#define Z_AUTHMODE_KRB4 1 /* authenticate using Kerberos V4 */
+#define Z_AUTHMODE_KRB5 2 /* authenticate using Kerberos V5 */
+
+#define Z_KEYUSAGE_CLT_CKSUM 1027 /* client->server notice checksum */
+#define Z_KEYUSAGE_SRV_CKSUM 1029 /* server->client notice checksum */
+
struct _Z_Hole {
struct _Z_Hole *next;
int first;
@@ -64,6 +75,11 @@ extern int __Zephyr_open; /* 0 if FD opened, 1 otherwise */
extern int __HM_set; /* 0 if dest addr set, 1 otherwise */
extern int __Zephyr_server; /* 0 if normal client, 1 if server or zhm */
+#ifdef HAVE_KRB5
+extern krb5_context Z_krb5_ctx;
+Code_t Z_krb5_lookup_cksumtype(krb5_enctype, krb5_cksumtype *);
+#endif
+
extern ZLocations_t *__locate_list;
extern int __locate_num;
extern int __locate_next;
@@ -97,6 +113,46 @@ Code_t Z_WaitForNotice __P((ZNotice_t *notice,
int (*pred) __P((ZNotice_t *, void *)), void *arg,
int timeout));
+
+Code_t Z_NewFormatHeader __P((ZNotice_t *, char *, int, int *, Z_AuthProc));
+Code_t Z_NewFormatAuthHeader __P((ZNotice_t *, char *, int, int *, Z_AuthProc));
+Code_t Z_NewFormatRawHeader __P((ZNotice_t *, char *, int, int *, char **,
+ int *, char **, char **));
+Code_t Z_AsciiFormatRawHeader __P((ZNotice_t *, char *, int, int *, char **,
+ int *, char **, char **));
+
void Z_gettimeofday(struct _ZTimeval *ztv, struct timezone *tz);
+
+#ifdef HAVE_KRB5
+int ZGetCreds(krb5_creds **creds_out);
+int ZGetCredsRealm(krb5_creds **creds_out, char *realm);
+Code_t Z_Checksum(krb5_data *cksumbuf, krb5_keyblock *keyblock, krb5_cksumtype cksumtype, char **asn1_data, int *asn1_len);
+Code_t Z_ExtractEncCksum(krb5_keyblock *keyblock, krb5_enctype *enctype, krb5_cksumtype *cksumtype);
+int Z_krb5_verify_cksum(krb5_keyblock *keyblock, krb5_data *cksumbuf, krb5_cksumtype cksumtype, char *asn1_data, int asn1_len);
+Code_t Z_InsertZcodeChecksum(krb5_keyblock *keyblock, ZNotice_t *notice,
+ char *buffer,
+ char *cksum_start, int cksum_len,
+ char *cstart, char *cend, int buffer_len,
+ int *length_ajdust);
+#endif
+
+#ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
+#define Z_keydata(keyblock) ((keyblock)->contents)
+#define Z_keylen(keyblock) ((keyblock)->length)
+#define Z_credskey(creds) (&(creds)->keyblock)
+#else
+#define Z_keydata(keyblock) ((keyblock)->keyvalue.data)
+#define Z_keylen(keyblock) ((keyblock)->keyvalue.length)
+#define Z_credskey(creds) (&(creds)->session)
+#endif
+
+#ifdef HAVE_KRB5_TICKET_ENC_PART2
+#define Z_tktprincp(tkt) ((tkt)->enc_part2 != 0)
+#define Z_tktprinc(tkt) ((tkt)->enc_part2->client)
+#else
+#define Z_tktprincp(tkt) ((tkt)->client != 0)
+#define Z_tktprinc(tkt) ((tkt)->client)
+#endif
+
#endif /* __INTERNAL_H__ */
diff --git a/h/zephyr/zephyr.h b/h/zephyr/zephyr.h
index 713e261..429663e 100644
--- a/h/zephyr/zephyr.h
+++ b/h/zephyr/zephyr.h
@@ -39,6 +39,7 @@
#define SERVER_SVCNAME "zephyr-clt"
#define SERVER_SERVICE "zephyr"
#define SERVER_INSTANCE "zephyr"
+#define SERVER_KRB5_SERVICE "zephyr"
#define ZVERSIONHDR "ZEPH"
#define ZVERSIONMAJOR 0
@@ -98,6 +99,7 @@ typedef struct _ZNotice_t {
char *z_multinotice;
ZUnique_Id_t z_multiuid;
ZChecksum_t z_checksum;
+ char *z_ascii_checksum;
int z_num_other_fields;
char *z_other_fields[Z_MAXOTHERFIELDS];
caddr_t z_message;
@@ -139,6 +141,8 @@ int ZCompareMultiUIDPred ZP((ZNotice_t *, void *));
/* Defines for ZFormatNotice, et al. */
typedef Code_t (*Z_AuthProc) ZP((ZNotice_t*, char *, int, int *));
Code_t ZMakeAuthentication ZP((ZNotice_t*, char *,int, int*));
+Code_t ZMakeZcodeAuthentication ZP((ZNotice_t*, char *,int, int*));
+Code_t ZMakeZcodeRealmAuthentication ZP((ZNotice_t*, char *,int, int*, char*));
char *ZGetSender ZP((void));
char *ZGetVariable ZP((char *));
@@ -152,6 +156,7 @@ Code_t ZParseNotice ZP((char*, int, ZNotice_t *));
Code_t ZReadAscii ZP((char*, int, unsigned char*, int));
Code_t ZReadAscii32 ZP((char *, int, unsigned long *));
Code_t ZReadAscii16 ZP((char *, int, unsigned short *));
+Code_t ZReadZcode ZP((unsigned char*, unsigned char*, int, int *));
Code_t ZSendPacket ZP((char*, int, int));
Code_t ZSendList ZP((ZNotice_t*, char *[], int, Z_AuthProc));
Code_t ZSrvSendList ZP((ZNotice_t*, char*[], int, Z_AuthProc, Code_t (*)()));
@@ -175,8 +180,12 @@ Code_t ZSrvSendRawList ZP((ZNotice_t*, char*[], int,
Code_t ZMakeAscii ZP((char*, int, unsigned char*, int));
Code_t ZMakeAscii32 ZP((char *, int, unsigned long));
Code_t ZMakeAscii16 ZP((char *, int, unsigned int));
+Code_t ZMakeZcode ZP((char*, int, unsigned char*, int));
+Code_t ZMakeZcode32 ZP((char *, int, unsigned long));
Code_t ZReceivePacket ZP((ZPacket_t, int*, struct sockaddr_in*));
Code_t ZCheckAuthentication ZP((ZNotice_t*, struct sockaddr_in*));
+Code_t ZCheckZcodeAuthentication ZP((ZNotice_t*, struct sockaddr_in*));
+Code_t ZCheckZcodeRealmAuthentication ZP((ZNotice_t*, struct sockaddr_in*, char *realm));
Code_t ZInitLocationInfo ZP((char *hostname, char *tty));
Code_t ZSetLocation ZP((char *exposure));
Code_t ZUnsetLocation ZP((void));
@@ -253,6 +262,7 @@ void ZSetDebug ZP((void (*)(ZCONST char *, va_list, void *), void *));
#define SRV_TIMEOUT 30
#define ZAUTH (ZMakeAuthentication)
+#define ZCAUTH (ZMakeZcodeAuthentication)
#define ZNOAUTH ((Z_AuthProc)0)
/* Packet strings */
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 5415797..40abb6e 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -39,7 +39,8 @@ OBJS = zephyr_err.lo ZAsyncLocate.lo ZCkAuth.lo ZCkIfNot.lo ZClosePort.lo \
ZPeekIfNot.lo ZPeekNot.lo ZPeekPkt.lo ZPending.lo ZReadAscii.lo \
ZRecvNot.lo ZRecvPkt.lo ZRetSubs.lo ZSendList.lo ZSendNot.lo \
ZSendPkt.lo ZSendRaw.lo ZSendRLst.lo ZSetDest.lo ZSetFD.lo ZSetSrv.lo \
- ZSubs.lo ZVariables.lo ZWait4Not.lo Zinternal.lo
+ ZSubs.lo ZVariables.lo ZWait4Not.lo Zinternal.lo ZMakeZcode.o \
+ ZReadZcode.o ZCkZaut.o
.SUFFIXES: .lo
diff --git a/lib/ZCkAuth.c b/lib/ZCkAuth.c
index 17fdc2b..4c83e6a 100644
--- a/lib/ZCkAuth.c
+++ b/lib/ZCkAuth.c
@@ -17,6 +17,10 @@ static char rcsid_ZCheckAuthentication_c[] =
#include <internal.h>
+#if defined(HAVE_KRB5) && !HAVE_KRB5_FREE_DATA
+#define krb5_free_data(ctx, dat) free((dat)->data)
+#endif
+
/* Check authentication of the notice.
If it looks authentic but fails the Kerberos check, return -1.
If it looks authentic and passes the Kerberos check, return 1.
@@ -28,30 +32,49 @@ static char rcsid_ZCheckAuthentication_c[] =
Code_t ZCheckAuthentication(notice, from)
ZNotice_t *notice;
struct sockaddr_in *from;
-{
-#ifdef HAVE_KRB4
+{
+#if 0
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
int result;
ZChecksum_t our_checksum;
+ C_Block *session;
+#ifdef HAVE_KRB5
+ krb5_creds *creds_out;
+#else
CREDENTIALS cred;
-
+#endif
/* If the value is already known, return it. */
if (notice->z_checked_auth != ZAUTH_UNSET)
return (notice->z_checked_auth);
if (!notice->z_auth)
return (ZAUTH_NO);
-
+
+#ifdef HAVE_KRB5
+ result = ZGetCreds(&creds_out);
+ if (result)
+ return ZAUTH_NO;
+ /* HOLDING: creds_out */
+
+ if (creds_out->keyblock.enctype != ENCTYPE_DES_CBC_CRC)
+ return (ZAUTH_NO);
+ session = (C_Block *)creds_out->keyblock.contents;
+
+#else
if ((result = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE,
__Zephyr_realm, &cred)) != 0)
return (ZAUTH_NO);
+ session = (C_Block *)cred.session;
+#endif
+
#ifdef NOENCRYPTION
our_checksum = 0;
#else
our_checksum = des_quad_cksum(notice->z_packet, NULL,
notice->z_default_format+
strlen(notice->z_default_format)+1-
- notice->z_packet, 0, cred.session);
+ notice->z_packet, 0, session);
#endif
/* if mismatched checksum, then the packet was corrupted */
return ((our_checksum == notice->z_checksum) ? ZAUTH_YES : ZAUTH_FAILED);
@@ -59,4 +82,7 @@ Code_t ZCheckAuthentication(notice, from)
#else
return (notice->z_auth ? ZAUTH_YES : ZAUTH_NO);
#endif
+#else
+ ZCheckZcodeAuthentication(notice, from);
+#endif
}
diff --git a/lib/ZFmtAuth.c b/lib/ZFmtAuth.c
index c2d8a00..97a70f2 100644
--- a/lib/ZFmtAuth.c
+++ b/lib/ZFmtAuth.c
@@ -16,7 +16,7 @@ static char rcsid_ZFormatAuthenticNotice_c[] = "$Id$";
#include <internal.h>
-#ifdef HAVE_KRB4
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
Code_t ZFormatAuthenticNotice(notice, buffer, buffer_len, len, session)
ZNotice_t *notice;
register char *buffer;
@@ -62,3 +62,71 @@ Code_t ZFormatAuthenticNotice(notice, buffer, buffer_len, len, session)
return (ZERR_NONE);
}
#endif
+
+#ifdef HAVE_KRB5
+Code_t ZFormatAuthenticNoticeV5(notice, buffer, buffer_len, len, keyblock)
+ ZNotice_t *notice;
+ register char *buffer;
+ register int buffer_len;
+ int *len;
+ krb5_keyblock *keyblock;
+{
+ ZNotice_t newnotice;
+ char *ptr;
+ int retval, hdrlen, hdr_adj;
+ krb5_enctype enctype;
+ krb5_cksumtype cksumtype;
+ int valid;
+ char *svcinst, *x, *y;
+ int key_len;
+ char *cksum_start, *cstart, *cend;
+ int cksum_len;
+
+ key_len = Z_keylen(keyblock);
+ retval = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
+ if (retval)
+ return (ZAUTH_FAILED);
+
+ if (key_len == 8 && (enctype == ENCTYPE_DES_CBC_CRC ||
+ enctype == ENCTYPE_DES_CBC_MD4 ||
+ enctype == ENCTYPE_DES_CBC_MD5)) {
+ C_Block tmp;
+ memcpy(&tmp, Z_keydata(keyblock), key_len);
+ return ZFormatAuthenticNotice(notice, buffer, buffer_len, len,
+ tmp);
+ }
+
+ newnotice = *notice;
+ newnotice.z_auth = 1;
+ newnotice.z_authent_len = 0;
+ newnotice.z_ascii_authent = "";
+
+ if ((retval = Z_NewFormatRawHeader(&newnotice, buffer, buffer_len,
+ &hdrlen,
+ &cksum_start, &cksum_len, &cstart,
+ &cend)) != ZERR_NONE)
+ return (retval);
+
+ retval = Z_InsertZcodeChecksum(keyblock, &newnotice, buffer,
+ cksum_start, cksum_len, cstart, cend,
+ buffer_len, &hdr_adj);
+ if (retval)
+ return retval;
+
+ hdrlen += hdr_adj;
+
+ ptr = buffer+hdrlen;
+
+ if (newnotice.z_message_len+hdrlen > buffer_len)
+ return (ZERR_PKTLEN);
+
+ (void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len);
+
+ *len = hdrlen+newnotice.z_message_len;
+
+ if (*len > Z_MAXPKTLEN)
+ return (ZERR_PKTLEN);
+
+ return (ZERR_NONE);
+}
+#endif
diff --git a/lib/ZFmtNotice.c b/lib/ZFmtNotice.c
index d7876d7..0b9ca39 100644
--- a/lib/ZFmtNotice.c
+++ b/lib/ZFmtNotice.c
@@ -41,3 +41,29 @@ Code_t ZFormatNotice(notice, buffer, ret_len, cert_routine)
return (ZERR_NONE);
}
+
+Code_t ZNewFormatNotice(notice, buffer, ret_len, cert_routine)
+ register ZNotice_t *notice;
+ char **buffer;
+ int *ret_len;
+ Z_AuthProc cert_routine;
+{
+ char header[Z_MAXHEADERLEN];
+ int hdrlen;
+ Code_t retval;
+
+ if ((retval = Z_NewFormatHeader(notice, header, sizeof(header), &hdrlen,
+ cert_routine)) != ZERR_NONE)
+ return (retval);
+
+ *ret_len = hdrlen+notice->z_message_len;
+
+ /* Length can never be zero, don't have to worry about malloc(0). */
+ if (!(*buffer = (char *) malloc((unsigned)*ret_len)))
+ return (ENOMEM);
+
+ (void) memcpy(*buffer, header, hdrlen);
+ (void) memcpy(*buffer+hdrlen, notice->z_message, notice->z_message_len);
+
+ return (ZERR_NONE);
+}
diff --git a/lib/ZFmtSmRaw.c b/lib/ZFmtSmRaw.c
index a9ce79d..0fcd74c 100644
--- a/lib/ZFmtSmRaw.c
+++ b/lib/ZFmtSmRaw.c
@@ -37,3 +37,26 @@ Code_t ZFormatSmallRawNotice(notice, buffer, ret_len)
return (ZERR_NONE);
}
+
+Code_t ZNewFormatSmallRawNotice(notice, buffer, ret_len)
+ ZNotice_t *notice;
+ ZPacket_t buffer;
+ int *ret_len;
+{
+ Code_t retval;
+ int hdrlen;
+
+ if ((retval = Z_AsciiFormatRawHeader(notice, buffer, Z_MAXHEADERLEN,
+ &hdrlen, NULL, NULL, NULL, NULL))
+ != ZERR_NONE)
+ return (retval);
+
+ *ret_len = hdrlen+notice->z_message_len;
+
+ if (*ret_len > Z_MAXPKTLEN)
+ return (ZERR_PKTLEN);
+
+ (void) memcpy(buffer+hdrlen, notice->z_message, notice->z_message_len);
+
+ return (ZERR_NONE);
+}
diff --git a/lib/ZGetSender.c b/lib/ZGetSender.c
index df5f3e2..c495cec 100644
--- a/lib/ZGetSender.c
+++ b/lib/ZGetSender.c
@@ -22,31 +22,62 @@ static const char rcsid_ZGetSender_c[] =
char *ZGetSender()
{
struct passwd *pw;
+ static char *sender = NULL;
+#ifdef HAVE_KRB5
+ krb5_ccache ccache;
+ krb5_principal principal;
+ char *prname;
+ int result;
+ char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ]; /*XXX*/
+#else
#ifdef HAVE_KRB4
char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
- static char sender[ANAME_SZ+INST_SZ+REALM_SZ+3] = "";
-#else
- static char sender[128] = "";
+#endif
#endif
/* Return it if already cached */
- if (*sender)
+ if (sender)
return (sender);
+#ifdef HAVE_KRB5
+ result = krb5_cc_default(Z_krb5_ctx, &ccache);
+ if (!result) {
+ result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &principal);
+ if (!result) {
+#if 0
+ krb5_unparse_name(Z_krb5_ctx, principal, &prname);
+ sender = strdup(prname);
+#else
+ krb5_524_conv_principal(Z_krb5_ctx, principal, pname, pinst, prealm);
+ sender = malloc(ANAME_SZ+INST_SZ+REALM_SZ+3);
+ if (sender)
+ (void) sprintf(sender, "%s%s%s@%s", pname, (pinst[0]?".":""),
+ pinst, prealm);
+#endif
+ krb5_free_principal(Z_krb5_ctx, principal);
+ }
+ krb5_cc_close(Z_krb5_ctx, ccache);
+ }
+#else
#ifdef HAVE_KRB4
if (krb_get_tf_fullname((char *)TKT_FILE, pname, pinst, prealm) == KSUCCESS)
{
- (void) sprintf(sender, "%s%s%s@%s", pname, (pinst[0]?".":""),
- pinst, prealm);
+ sender = malloc(ANAME_SZ+INST_SZ+REALM_SZ+3);
+ if (sender)
+ (void) sprintf(sender, "%s%s%s@%s", pname, (pinst[0]?".":""),
+ pinst, prealm);
return (sender);
}
#endif
+#endif
/* XXX a uid_t is a u_short (now), but getpwuid
* wants an int. AARGH! */
pw = getpwuid((int) getuid());
if (!pw)
return ("unknown");
- (void) sprintf(sender, "%s@%s", pw->pw_name, __Zephyr_realm);
+ sender = malloc(strlen(pw->pw_name) + strlen(__Zephyr_realm) + 2);
+ if (sender)
+ (void) sprintf(sender, "%s@%s", pw->pw_name, __Zephyr_realm);
return (sender);
}
diff --git a/lib/ZInit.c b/lib/ZInit.c
index 401f6db..16d266e 100644
--- a/lib/ZInit.c
+++ b/lib/ZInit.c
@@ -21,6 +21,12 @@ static char rcsid_ZInitialize_c[] =
#ifdef HAVE_KRB4
#include <krb_err.h>
#endif
+#ifdef HAVE_KRB5
+#include <krb5.h>
+#endif
+#ifdef HAVE_KRB5_ERR_H
+#include <krb5_err.h>
+#endif
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
@@ -36,13 +42,22 @@ Code_t ZInitialize()
int s, sinsize = sizeof(sin);
Code_t code;
ZNotice_t notice;
+#ifdef HAVE_KRB5
+ char **krealms = NULL;
+#else
#ifdef HAVE_KRB4
char *krealm = NULL;
int krbval;
char d1[ANAME_SZ], d2[INST_SZ];
+#endif
+#endif
+#ifdef HAVE_KRB4
initialize_krb_error_table();
#endif
+#ifdef HAVE_KRB5
+ initialize_krb5_error_table();
+#endif
initialize_zeph_error_table();
@@ -67,6 +82,11 @@ Code_t ZInitialize()
__Q_Tail = NULL;
__Q_Head = NULL;
+#ifdef HAVE_KRB5
+ if ((code = krb5_init_context(&Z_krb5_ctx)))
+ return(code);
+#endif
+
/* if the application is a server, there might not be a zhm. The
code will fall back to something which might not be "right",
but this is is ok, since none of the servers call krb_rd_req. */
@@ -85,9 +105,15 @@ Code_t ZInitialize()
If this code ever support a multiplexing zhm, this will have to
be made smarter, and probably per-message */
+#ifdef HAVE_KRB5
+ code = krb5_get_host_realm(Z_krb5_ctx, notice.z_message, &krealms);
+ if (code)
+ return(code);
+#else
#ifdef HAVE_KRB4
krealm = krb_realmofhost(notice.z_message);
#endif
+#endif
hostent = gethostbyname(notice.z_message);
if (hostent && hostent->h_addrtype == AF_INET)
memcpy(&servaddr, hostent->h_addr, sizeof(servaddr));
@@ -95,6 +121,24 @@ Code_t ZInitialize()
ZFreeNotice(&notice);
}
+#ifdef HAVE_KRB5
+ if (krealms) {
+ strcpy(__Zephyr_realm, krealms[0]);
+ krb5_free_host_realm(Z_krb5_ctx, krealms);
+ } else {
+ char *p; /* XXX define this somewhere portable */
+ /* XXX check ticket file here */
+ code = krb5_get_default_realm(Z_krb5_ctx, &p);
+ strcpy(__Zephyr_realm, p);
+#ifdef HAVE_KRB5_FREE_DEFAULT_REALM
+ krb5_free_default_realm(Z_krb5_ctx, p);
+#else
+ free(p);
+#endif
+ if (code)
+ return code;
+ }
+#else
#ifdef HAVE_KRB4
if (krealm) {
strcpy(__Zephyr_realm, krealm);
@@ -106,6 +150,7 @@ Code_t ZInitialize()
#else
strcpy(__Zephyr_realm, "local-realm");
#endif
+#endif
__My_addr.s_addr = INADDR_NONE;
if (servaddr.s_addr != INADDR_NONE) {
diff --git a/lib/ZMkAuth.c b/lib/ZMkAuth.c
index 5a6749c..92d0bd3 100644
--- a/lib/ZMkAuth.c
+++ b/lib/ZMkAuth.c
@@ -20,6 +20,10 @@ static const char rcsid_ZMakeAuthentication_c[] = "$Id$";
#include <krb_err.h>
#endif
+#if defined(HAVE_KRB5) && !HAVE_KRB5_FREE_DATA
+#define krb5_free_data(ctx, dat) free((dat)->data)
+#endif
+
Code_t ZResetAuthentication () {
return ZERR_NONE;
}
@@ -30,15 +34,39 @@ Code_t ZMakeAuthentication(notice, buffer, buffer_len, len)
int buffer_len;
int *len;
{
-#ifdef HAVE_KRB4
+#if 1
+ return ZMakeZcodeAuthentication(notice, buffer, buffer_len, len/*?XXX*/);
+#else
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
int result;
time_t now;
KTEXT_ST authent;
char *cstart, *cend;
ZChecksum_t checksum;
CREDENTIALS cred;
- extern unsigned long des_quad_cksum();
+ C_Block *session;
+#ifdef HAVE_KRB5
+ krb5_creds *creds_out;
+
+ result = ZGetCreds(&creds_out);
+ if (result)
+ return result;
+
+ result = krb5_524_convert_creds(Z_krb5_ctx, creds_out, &cred);
+ /* krb5_free_creds(Z_krb5_ctx, creds_out);*/
+ if (result)
+ return result;
+ /* HOLDING: creds_out */
+
+ if (creds_out->keyblock.enctype != ENCTYPE_DES_CBC_CRC)
+ return (KRB5_BAD_ENCTYPE);
+ session = (C_Block *)creds_out->keyblock.contents;
+ result = krb_mk_req_creds(&authent, &cred, 0);
+ if (result != MK_AP_OK)
+ return result + krb_err_base;
+#endif
+#ifndef HAVE_KRB5
result = krb_mk_req(&authent, SERVER_SERVICE,
SERVER_INSTANCE, __Zephyr_realm, 0);
if (result != MK_AP_OK)
@@ -48,6 +76,9 @@ Code_t ZMakeAuthentication(notice, buffer, buffer_len, len)
if (result != KSUCCESS)
return (result+krb_err_base);
+ session = (C_Block *)cred.session;
+#endif
+
notice->z_auth = 1;
notice->z_authent_len = authent.length;
notice->z_ascii_authent = (char *)malloc((unsigned)authent.length*3);
@@ -69,11 +100,11 @@ Code_t ZMakeAuthentication(notice, buffer, buffer_len, len)
return(result);
/* Compute a checksum over the header and message. */
- checksum = des_quad_cksum(buffer, NULL, cstart - buffer, 0, cred.session);
+ checksum = des_quad_cksum(buffer, NULL, cstart - buffer, 0, session);
checksum ^= des_quad_cksum(cend, NULL, buffer + *len - cend, 0,
- cred.session);
+ session);
checksum ^= des_quad_cksum(notice->z_message, NULL, notice->z_message_len,
- 0, cred.session);
+ 0, session);
notice->z_checksum = checksum;
ZMakeAscii32(cstart, buffer + buffer_len - cstart, checksum);
@@ -85,4 +116,151 @@ Code_t ZMakeAuthentication(notice, buffer, buffer_len, len)
notice->z_ascii_authent = "";
return (Z_FormatRawHeader(notice, buffer, buffer_len, len, NULL, NULL));
#endif
+#endif
}
+
+Code_t ZMakeZcodeAuthentication(notice, buffer, buffer_len, phdr_len)
+ register ZNotice_t *notice;
+ char *buffer;
+ int buffer_len;
+ int *phdr_len;
+{
+ return ZMakeZcodeRealmAuthentication(notice, buffer, buffer_len, phdr_len,
+ __Zephyr_realm);
+}
+
+Code_t ZMakeZcodeRealmAuthentication(notice, buffer, buffer_len, phdr_len,
+ realm)
+ register ZNotice_t *notice;
+ char *buffer;
+ int buffer_len;
+ int *phdr_len;
+ char *realm;
+{
+#ifdef HAVE_KRB5
+ krb5_error_code result;
+ krb5_creds *creds;
+ krb5_keyblock *keyblock;
+ krb5_enctype enctype;
+ krb5_cksumtype cksumtype;
+ krb5_auth_context authctx;
+ krb5_data *authent;
+ char *svcinst, *x, *y;
+ char *cksum_start, *cstart, *cend, *asn1_data;
+ int i, cksum_len, zcode_len, asn1_len, phdr_adj;
+
+ result = ZGetCredsRealm(&creds, realm);
+ if (result)
+ return result;
+ /* HOLDING: creds */
+
+ /* Figure out what checksum type to use */
+ keyblock = Z_credskey(creds);
+ /* HOLDING: creds */
+
+ /* Create the authenticator */
+ result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
+ if (result) {
+ krb5_free_creds(Z_krb5_ctx, creds);
+ return (result);
+ }
+
+ authent = (krb5_data *)malloc(sizeof(krb5_data));
+
+ /* HOLDING: creds, authctx */
+ result = krb5_mk_req_extended(Z_krb5_ctx, &authctx, 0 /* options */,
+ 0 /* in_data */, creds, authent);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ if (result) {
+ krb5_free_creds(Z_krb5_ctx, creds);
+ return (result);
+ }
+ /* HOLDING: creds, authent */
+
+ /* Encode the authenticator */
+ notice->z_auth = 1;
+ notice->z_authent_len = authent->length;
+ zcode_len = authent->length * 2 + 2; /* 2x growth plus Z and null */
+ notice->z_ascii_authent = (char *)malloc(zcode_len);
+ if (!notice->z_ascii_authent) {
+ krb5_free_data(Z_krb5_ctx, authent);
+ krb5_free_creds(Z_krb5_ctx, creds);
+ return (ENOMEM);
+ }
+ /* HOLDING: creds, authent, notice->z_ascii_authent */
+ result = ZMakeZcode(notice->z_ascii_authent, zcode_len,
+ authent->data, authent->length);
+ krb5_free_data(Z_krb5_ctx, authent);
+ if (result) {
+ free(notice->z_ascii_authent);
+ krb5_free_creds(Z_krb5_ctx, creds);
+ return (result);
+ }
+ /* HOLDING: creds, notice->z_ascii_authent */
+
+ /* format the notice header, with a zero checksum */
+ result = Z_NewFormatRawHeader(notice, buffer, buffer_len, phdr_len,
+ &cksum_start, &cksum_len, &cstart, &cend);
+ free(notice->z_ascii_authent);
+ notice->z_authent_len = 0;
+ if (result) {
+ krb5_free_creds(Z_krb5_ctx, creds);
+ return (result);
+ }
+ result = Z_InsertZcodeChecksum(keyblock, notice, buffer, cksum_start,
+ cksum_len, cstart, cend, buffer_len,
+ &phdr_adj);
+ krb5_free_creds(Z_krb5_ctx, creds);
+ if (result) {
+ return result;
+ }
+ *phdr_len += phdr_adj;
+
+ return (result);
+#endif /* HAVE_KRB5 */
+}
+
+#ifdef HAVE_KRB5
+int ZGetCreds(krb5_creds **creds_out) {
+ return ZGetCredsRealm(creds_out, __Zephyr_realm);
+}
+
+int ZGetCredsRealm(krb5_creds **creds_out, char *realm) {
+ krb5_creds creds_in;
+ krb5_ccache ccache; /* XXX make this a global or static?*/
+ int result;
+
+ result = krb5_cc_default(Z_krb5_ctx, &ccache);
+ if (result)
+ return result;
+
+ memset((char *)&creds_in, 0, sizeof(creds_in));
+ result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
+ strlen(realm),
+ realm,
+ SERVER_SERVICE, SERVER_INSTANCE, 0);
+ if (result) {
+ krb5_cc_close(Z_krb5_ctx, ccache);
+ return result;
+ }
+
+ result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client);
+ if (result) {
+ krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */
+ krb5_cc_close(Z_krb5_ctx, ccache);
+ return result;
+ }
+
+#ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
+ creds_in.keyblock.enctype = ENCTYPE_DES_CBC_CRC; /* XXX? */
+#else
+ creds_in.session.keytype = KEYTYPE_DES; /* XXX? */
+#endif
+
+ result = krb5_get_credentials(Z_krb5_ctx, 0, ccache, &creds_in, creds_out);
+ krb5_cc_close(Z_krb5_ctx, ccache);
+ krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* I also hope this is ok */
+
+ return result;
+}
+#endif
diff --git a/lib/ZParseNot.c b/lib/ZParseNot.c
index 7950e96..a198845 100644
--- a/lib/ZParseNot.c
+++ b/lib/ZParseNot.c
@@ -209,11 +209,22 @@ Code_t ZParseNotice(buffer, len, notice)
else
notice->z_default_format = "";
- if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
- BAD_PACKET;
- notice->z_checksum = temp;
- numfields--;
- ptr = next_field(ptr, end);
+ if (numfields && ptr < end) {
+ notice->z_ascii_checksum = ptr;
+
+ if (ZReadAscii32(ptr, end-ptr, &temp) == ZERR_BADFIELD)
+ notice->z_checksum = 0;
+ else
+ notice->z_checksum = temp;
+
+ numfields--;
+ ptr = next_field (ptr, end);
+ }
+ else
+ {
+ notice->z_ascii_checksum = "";
+ notice->z_checksum = 0;
+ }
if (numfields && ptr < end) {
notice->z_multinotice = ptr;
diff --git a/lib/Zinternal.c b/lib/Zinternal.c
index 0efcc56..4440dfe 100644
--- a/lib/Zinternal.c
+++ b/lib/Zinternal.c
@@ -44,9 +44,60 @@ int __subscriptions_num;
int __subscriptions_next;
int Z_discarded_packets = 0;
-#ifdef HAVE_KRB4
-C_Block __Zephyr_session;
-#endif
+#ifdef HAVE_KRB5
+/* This context is used throughout */
+krb5_context Z_krb5_ctx;
+
+static struct cksum_map_s {
+ krb5_enctype e;
+ krb5_cksumtype c;
+} cksum_map[] = {
+ /* per RFC1510 and draft-ietf-krb-wg-crypto-02.txt */
+ { ENCTYPE_NULL, CKSUMTYPE_RSA_MD5 },
+ { ENCTYPE_DES_CBC_CRC, CKSUMTYPE_RSA_MD5_DES },
+ { ENCTYPE_DES_CBC_MD4, CKSUMTYPE_RSA_MD4_DES },
+ { ENCTYPE_DES_CBC_MD5, CKSUMTYPE_RSA_MD5_DES },
+
+ /*
+ * The implementors hate us, and are inconsistent with names for
+ * most things defined after RFC1510. Note that des3-cbc-sha1
+ * and des3-cbc-sha1-kd are listed by number to avoid confusion
+ * caused by inconsistency between the names used in the specs
+ * and those used by implementations.
+ * -- jhutz, 30-Nov-2002
+ */
+
+ /* source lost in history (an expired internet-draft) */
+ { 5 /* des3-cbc-md5 */, 9 /* rsa-md5-des3 */ },
+ { 7 /* des3-cbc-sha1 */, 12 /* hmac-sha1-des3 */ },
+
+ /* per draft-ietf-krb-wg-crypto-02.txt */
+ { 16 /* des3-cbc-sha1-kd */, 12 /* hmac-sha1-des3-kd */ },
+
+ /* per draft-raeburn-krb-rijndael-krb-02.txt */
+ { 17 /* aes128-cts-hmac-sha1-96 */, 10 /* hmac-sha1-96-aes128 */ },
+ { 18 /* aes256-cts-hmac-sha1-96 */, 11 /* hmac-sha1-96-aes256 */ },
+
+ /* per draft-brezak-win2k-krb-rc4-hmac-04.txt */
+ { 23 /* rc4-hmac */, -138 /* hmac-md5 */ },
+ { 24 /* rc4-hmac-exp */, -138 /* hmac-md5 */ },
+};
+#define N_CKSUM_MAP (sizeof(cksum_map) / sizeof(struct cksum_map_s))
+
+Code_t Z_krb5_lookup_cksumtype(krb5_enctype e, krb5_cksumtype *c)
+{
+ int i;
+
+ for (i = 0; i < N_CKSUM_MAP; i++) {
+ if (cksum_map[i].e == e) {
+ *c = cksum_map[i].c;
+ return ZERR_NONE;
+ }
+ }
+ return KRB5_PROG_ETYPE_NOSUPP;
+}
+#endif /* HAVE_KRB5 */
+
char __Zephyr_realm[REALM_SZ];
#ifdef Z_DEBUG
@@ -58,6 +109,8 @@ void *__Z_debug_print_closure;
static int Z_AddField __P((char **ptr, char *field, char *end));
static int find_or_insert_uid __P((ZUnique_Id_t *uid, ZNotice_Kind_t kind));
+static Code_t Z_ZcodeFormatRawHeader __P((ZNotice_t *, char *, int, int *, char **,
+ int *, char **, char **, int cksumtype));
/* Find or insert uid in the old uids buffer. The buffer is a sorted
* circular queue. We make the assumption that most packets arrive in
@@ -633,6 +686,52 @@ Code_t Z_FormatHeader(notice, buffer, buffer_len, len, cert_routine)
return Z_FormatAuthHeader(notice, buffer, buffer_len, len, cert_routine);
}
+Code_t Z_NewFormatHeader(notice, buffer, buffer_len, len, cert_routine)
+ ZNotice_t *notice;
+ char *buffer;
+ int buffer_len;
+ int *len;
+ Z_AuthProc cert_routine;
+{
+ Code_t retval;
+ static char version[BUFSIZ]; /* default init should be all \0 */
+ struct sockaddr_in name;
+ struct timeval tv;
+ int namelen = sizeof(name);
+
+ if (!notice->z_sender)
+ notice->z_sender = ZGetSender();
+
+ if (notice->z_port == 0) {
+ if (ZGetFD() < 0) {
+ retval = ZOpenPort((u_short *)0);
+ if (retval != ZERR_NONE)
+ return (retval);
+ }
+ retval = getsockname(ZGetFD(), (struct sockaddr *) &name, &namelen);
+ if (retval != 0)
+ return (retval);
+ notice->z_port = name.sin_port;
+ }
+
+ notice->z_multinotice = "";
+
+ (void) gettimeofday(&tv, (struct timezone *)0);
+ notice->z_uid.tv.tv_sec = htonl((u_long) tv.tv_sec);
+ notice->z_uid.tv.tv_usec = htonl((u_long) tv.tv_usec);
+
+ (void) memcpy(&notice->z_uid.zuid_addr, &__My_addr, sizeof(__My_addr));
+
+ notice->z_multiuid = notice->z_uid;
+
+ if (!version[0])
+ (void) sprintf(version, "%s%d.%d", ZVERSIONHDR, ZVERSIONMAJOR,
+ ZVERSIONMINOR);
+ notice->z_version = version;
+
+ return Z_NewFormatAuthHeader(notice, buffer, buffer_len, len, cert_routine);
+}
+
Code_t Z_FormatAuthHeader(notice, buffer, buffer_len, len, cert_routine)
ZNotice_t *notice;
char *buffer;
@@ -652,6 +751,210 @@ Code_t Z_FormatAuthHeader(notice, buffer, buffer_len, len, cert_routine)
return ((*cert_routine)(notice, buffer, buffer_len, len));
}
+Code_t Z_NewFormatAuthHeader(notice, buffer, buffer_len, len, cert_routine)
+ ZNotice_t *notice;
+ char *buffer;
+ int buffer_len;
+ int *len;
+ Z_AuthProc cert_routine;
+{
+ if (!cert_routine) {
+ notice->z_auth = 0;
+ notice->z_authent_len = 0;
+ notice->z_ascii_authent = "";
+ notice->z_checksum = 0;
+ return (Z_FormatRawHeader(notice, buffer, buffer_len,
+ len, NULL, NULL));
+ }
+
+ return ((*cert_routine)(notice, buffer, buffer_len, len));
+}
+
+Code_t Z_NewFormatRawHeader(notice, buffer, buffer_len, hdr_len,
+ cksum_start, cksum_len, cstart, cend)
+ ZNotice_t *notice;
+ char *buffer;
+ int buffer_len;
+ int *hdr_len;
+ char **cksum_start;
+ int *cksum_len;
+ char **cstart, **cend;
+{
+ return(Z_ZcodeFormatRawHeader(notice, buffer, buffer_len, hdr_len,
+ cksum_start, cksum_len, cstart, cend, 0));
+}
+
+Code_t Z_AsciiFormatRawHeader(notice, buffer, buffer_len, hdr_len,
+ cksum_start, cksum_len, cstart, cend)
+ ZNotice_t *notice;
+ char *buffer;
+ int buffer_len;
+ int *hdr_len;
+ char **cksum_start;
+ int *cksum_len;
+ char **cstart, **cend;
+{
+ return(Z_ZcodeFormatRawHeader(notice, buffer, buffer_len, hdr_len,
+ cksum_start, cksum_len, cstart, cend, 1));
+}
+
+static Code_t Z_ZcodeFormatRawHeader(notice, buffer, buffer_len, hdr_len, cksum_start,
+ cksum_len, cstart, cend, cksumstyle)
+ ZNotice_t *notice;
+ char *buffer;
+ int buffer_len;
+ int *hdr_len;
+ char **cksum_start;
+ int *cksum_len;
+ char **cstart, **cend;
+ int cksumstyle;
+{
+ static char version_nogalaxy[BUFSIZ]; /* default init should be all \0 */
+ char newrecip[BUFSIZ];
+ char *ptr, *end;
+ int i;
+
+ if (!notice->z_class)
+ notice->z_class = "";
+
+ if (!notice->z_class_inst)
+ notice->z_class_inst = "";
+
+ if (!notice->z_opcode)
+ notice->z_opcode = "";
+
+ if (!notice->z_recipient)
+ notice->z_recipient = "";
+
+ if (!notice->z_default_format)
+ notice->z_default_format = "";
+
+ ptr = buffer;
+ end = buffer+buffer_len;
+
+ if (cksum_start)
+ *cksum_start = ptr;
+
+ (void) sprintf(version_nogalaxy, "%s%d.%d", ZVERSIONHDR,
+ ZVERSIONMAJOR, ZVERSIONMINOR);
+
+ notice->z_version = version_nogalaxy;
+
+ if (Z_AddField(&ptr, version_nogalaxy, end))
+ return (ZERR_HEADERLEN);
+
+ if (ZMakeAscii32(ptr, end-ptr,
+ Z_NUMFIELDS + notice->z_num_other_fields)
+ == ZERR_FIELDLEN)
+ return (ZERR_HEADERLEN);
+ ptr += strlen(ptr)+1;
+
+ if (ZMakeAscii32(ptr, end-ptr, notice->z_kind) == ZERR_FIELDLEN)
+ return (ZERR_HEADERLEN);
+ ptr += strlen(ptr)+1;
+
+ if (ZMakeAscii(ptr, end-ptr, (unsigned char *)&notice->z_uid,
+ sizeof(ZUnique_Id_t)) == ZERR_FIELDLEN)
+ return (ZERR_HEADERLEN);
+ ptr += strlen(ptr)+1;
+
+ if (ZMakeAscii16(ptr, end-ptr, ntohs(notice->z_port)) == ZERR_FIELDLEN)
+ return (ZERR_HEADERLEN);
+ ptr += strlen(ptr)+1;
+
+ if (ZMakeAscii32(ptr, end-ptr, notice->z_auth) == ZERR_FIELDLEN)
+ return (ZERR_HEADERLEN);
+ ptr += strlen(ptr)+1;
+
+ if (ZMakeAscii32(ptr, end-ptr, notice->z_authent_len) == ZERR_FIELDLEN)
+ return (ZERR_HEADERLEN);
+ ptr += strlen(ptr)+1;
+
+ if (Z_AddField(&ptr, notice->z_ascii_authent, end))
+ return (ZERR_HEADERLEN);
+ if (Z_AddField(&ptr, notice->z_class, end))
+ return (ZERR_HEADERLEN);
+ if (Z_AddField(&ptr, notice->z_class_inst, end))
+ return (ZERR_HEADERLEN);
+ if (Z_AddField(&ptr, notice->z_opcode, end))
+ return (ZERR_HEADERLEN);
+ if (Z_AddField(&ptr, notice->z_sender, end))
+ return (ZERR_HEADERLEN);
+ if (strchr(notice->z_recipient, '@') || !*notice->z_recipient) {
+ if (Z_AddField(&ptr, notice->z_recipient, end))
+ return (ZERR_HEADERLEN);
+ }
+ else {
+ if (strlen(notice->z_recipient) + strlen(__Zephyr_realm) + 2 >
+ sizeof(newrecip))
+ return (ZERR_HEADERLEN);
+ (void) sprintf(newrecip, "%s@%s", notice->z_recipient, __Zephyr_realm);
+ if (Z_AddField(&ptr, newrecip, end))
+ return (ZERR_HEADERLEN);
+ }
+ if (Z_AddField(&ptr, notice->z_default_format, end))
+ return (ZERR_HEADERLEN);
+
+ /* copy back the end pointer location for crypto checksum */
+ if (cstart)
+ *cstart = ptr;
+ if (cksumstyle == 1) {
+ if (Z_AddField(&ptr, notice->z_ascii_checksum, end))
+ return (ZERR_HEADERLEN);
+ } else {
+#ifdef xZCODE_K4SUM
+ if (ZMakeZcode32(ptr, end-ptr, notice->z_checksum) == ZERR_FIELDLEN)
+ return ZERR_HEADERLEN;
+#else
+ if (ZMakeAscii32(ptr, end-ptr, notice->z_checksum) == ZERR_FIELDLEN)
+ return (ZERR_HEADERLEN);
+#endif
+ ptr += strlen(ptr)+1;
+ }
+ if (cend)
+ *cend = ptr;
+
+ if (Z_AddField(&ptr, notice->z_multinotice, end))
+ return (ZERR_HEADERLEN);
+
+ if (ZMakeAscii(ptr, end-ptr, (unsigned char *)&notice->z_multiuid,
+ sizeof(ZUnique_Id_t)) == ZERR_FIELDLEN)
+ return (ZERR_HEADERLEN);
+ ptr += strlen(ptr)+1;
+
+ for (i=0;i<notice->z_num_other_fields;i++)
+ if (Z_AddField(&ptr, notice->z_other_fields[i], end))
+ return (ZERR_HEADERLEN);
+
+ if (cksum_len)
+ *cksum_len = ptr-*cksum_start;
+
+ *hdr_len = ptr-buffer;
+
+#if 0
+ {
+ printf("Z_FormatRawHeader output:\n");
+ for (i = 0; i < *hdr_len; i += 16) {
+ int i2;
+ printf("%03d:", i);
+ for (i2 = i; i2 < i+16 && i2 < *hdr_len; i2++)
+ printf(" %02x", buffer[i2] & 0xff);
+ for (; i2 < i+16; i2++)
+ printf(" ");
+ printf(" ");
+ for (i2 = i; i2 < i+16 && i2 < *hdr_len; i2++)
+ printf("%c",
+ ((buffer[i2] > 0 && buffer[i2] < 127 && isprint(buffer[i2]))
+ ? buffer[i2]
+ : '.'));
+ printf("\n");
+ }
+ }
+#endif
+
+ return (ZERR_NONE);
+}
+
Code_t Z_FormatRawHeader(notice, buffer, buffer_len, len, cstart, cend)
ZNotice_t *notice;
char *buffer;
@@ -742,7 +1045,7 @@ Code_t Z_FormatRawHeader(notice, buffer, buffer_len, len, cstart, cend)
if (cstart)
*cstart = ptr;
if (ZMakeAscii32(ptr, end-ptr, notice->z_checksum) == ZERR_FIELDLEN)
- return (ZERR_HEADERLEN);
+ return (ZERR_HEADERLEN);
ptr += strlen(ptr)+1;
if (cend)
*cend = ptr;
@@ -995,3 +1298,210 @@ void ZSetDebug(proc, arg)
}
#endif /* Z_DEBUG */
+#ifdef HAVE_KRB5
+Code_t Z_Checksum(krb5_data *cksumbuf, krb5_keyblock *keyblock,
+ krb5_cksumtype cksumtype,
+ char **asn1_data, int *asn1_len) {
+ krb5_error_code result;
+ char *data;
+ int len;
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+ krb5_checksum checksum;
+#else
+ Checksum checksum;
+ krb5_crypto cryptctx;
+#endif
+
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+ /* Create the checksum -- MIT crypto API */
+ result = krb5_c_make_checksum(Z_krb5_ctx, cksumtype,
+ keyblock, Z_KEYUSAGE_CLT_CKSUM,
+ cksumbuf, &checksum);
+ if (result)
+ return result;
+ /* HOLDING: checksum */
+
+ data = checksum.contents;
+ len = checksum.length;
+#else
+ /* Create the checksum -- heimdal crypto API */
+ result = krb5_crypto_init(Z_krb5_ctx, keyblock, keyblock->keytype,
+ &cryptctx);
+ if (result)
+ return result;
+
+ /* HOLDING: cryptctx */
+ result = krb5_create_checksum(Z_krb5_ctx, cryptctx,
+ Z_KEYUSAGE_CLT_CKSUM, cksumtype,
+ cksumbuf->data, cksumbuf->length,
+ &checksum);
+ krb5_crypto_destroy(Z_krb5_ctx, cryptctx);
+ if (result)
+ return result;
+
+ len = checksum.checksum.length;
+ data = checksum.checksum.data;
+ /* HOLDING: checksum */
+#endif
+
+ *asn1_data = malloc(len);
+ if (*asn1_data == NULL)
+ return errno;
+ memcpy(*asn1_data, data, len);
+ *asn1_len = len;
+
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+ krb5_free_checksum_contents(Z_krb5_ctx, &checksum);
+#else
+ free_Checksum(&checksum);
+#endif
+
+ return 0;
+}
+
+Code_t
+Z_InsertZcodeChecksum(krb5_keyblock *keyblock, ZNotice_t *notice,
+ char *buffer, char *cksum_start, int cksum_len,
+ char *cstart, char *cend, int buffer_len,
+ int *length_adjust)
+{
+ int plain_len; /* length of part not to be checksummed */
+ int cksum0_len; /* length of part before checksum */
+ int cksum1_len; /* length of part after checksum */
+ krb5_data cksumbuf;
+ krb5_data cksum;
+ char *key_data;
+ int key_len;
+ krb5_enctype enctype;
+ krb5_cksumtype cksumtype;
+ Code_t result;
+
+ key_data = Z_keydata(keyblock);
+ key_len = Z_keylen(keyblock);
+ result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
+ if (result)
+ return (ZAUTH_FAILED);
+
+ /* Assemble the things to be checksummed */
+ plain_len = cksum_start - buffer;
+ cksum0_len = cstart - cksum_start;
+ cksum1_len = (cksum_start + cksum_len) - cend;
+ memset(&cksumbuf, 0, sizeof(cksumbuf));
+ cksumbuf.length = cksum0_len + cksum1_len + notice->z_message_len;
+ cksumbuf.data = malloc(cksumbuf.length);
+ if (!cksumbuf.data)
+ return ENOMEM;
+ memcpy(cksumbuf.data, cksum_start, cksum0_len);
+ memcpy(cksumbuf.data + cksum0_len, cend, cksum1_len);
+ memcpy(cksumbuf.data + cksum0_len + cksum1_len,
+ notice->z_message, notice->z_message_len);
+ /* compute the checksum */
+ result = Z_Checksum(&cksumbuf, keyblock, cksumtype,
+ (char **)&cksum.data, &cksum.length);
+ if (result) {
+ free(cksumbuf.data);
+ return result;
+ }
+
+ /*
+ * OK.... we can zcode to a space starting at 'cstart',
+ * with a length of buffer_len - (plain_len + cksum_len).
+ * Then we tack on the end part, which is located at
+ * cksumbuf.data + cksum0_len and has length cksum1_len
+ */
+
+ result = ZMakeZcode(cstart, buffer_len - (plain_len + cksum_len),
+ cksum.data, cksum.length);
+ free(cksum.data);
+ if (!result) {
+ int zcode_len = strlen(cstart) + 1;
+ memcpy(cstart + zcode_len, cksumbuf.data + cksum0_len, cksum1_len);
+ *length_adjust = zcode_len - cksum_len + (cksum0_len + cksum1_len);
+ }
+ free(cksumbuf.data);
+ return result;
+}
+
+Code_t
+Z_ExtractEncCksum(krb5_keyblock *keyblock, krb5_enctype *enctype,
+ krb5_cksumtype *cksumtype) {
+#if HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
+ *enctype = keyblock->enctype;
+ return Z_krb5_lookup_cksumtype(*enctype, cksumtype);
+#else
+ unsigned int len;
+ ENCTYPE *val;
+ int i = 0;
+ Code_t result;
+
+ result = krb5_keytype_to_enctypes(Z_krb5_ctx, keyblock->keytype,
+ &len, &val);
+ if (result)
+ return result;
+
+ do {
+ if (i == len) break;
+ result = Z_krb5_lookup_cksumtype(val[i], cksumtype);
+ i++;
+ } while (result != 0);
+
+ if (result)
+ return result;
+
+ *enctype = val[i-1];
+#endif
+ return 0;
+}
+#endif
+
+#ifdef HAVE_KRB5
+/* returns 0 if invalid or losing, 1 if valid, *sigh* */
+int
+Z_krb5_verify_cksum(krb5_keyblock *keyblock, krb5_data *cksumbuf,
+ krb5_cksumtype cksumtype, char *asn1_data,
+ int asn1_len) {
+ krb5_error_code result;
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+ krb5_checksum checksum;
+ krb5_boolean valid;
+#else
+ krb5_crypto cryptctx;
+ Checksum checksum;
+ size_t xlen;
+#endif
+
+ memset(&checksum, 0, sizeof(checksum));
+#if HAVE_KRB5_C_MAKE_CHECKSUM
+ /* Verify the checksum -- MIT crypto API */
+ checksum.length = asn1_len;
+ checksum.contents = asn1_data;
+ checksum.checksum_type = cksumtype;
+ result = krb5_c_verify_checksum(Z_krb5_ctx,
+ keyblock, Z_KEYUSAGE_SRV_CKSUM,
+ cksumbuf, &checksum, &valid);
+ if (!result && valid)
+ return 1;
+ else
+ return 0;
+#else
+ checksum.checksum.length = asn1_len;
+ checksum.checksum.data = asn1_data;
+ checksum.cksumtype = cksumtype;
+
+ result = krb5_crypto_init(Z_krb5_ctx, keyblock, keyblock->keytype, &cryptctx);
+ if (result)
+ return result;
+
+ /* HOLDING: cryptctx */
+ result = krb5_verify_checksum(Z_krb5_ctx, cryptctx,
+ Z_KEYUSAGE_SRV_CKSUM,
+ cksumbuf->data, cksumbuf->length,
+ &checksum);
+ krb5_crypto_destroy(Z_krb5_ctx, cryptctx);
+ if (result)
+ return 0;
+ else
+ return 1;
+#endif
+}
+#endif
diff --git a/server/bdump.c b/server/bdump.c
index 22bf518..d997672 100644
--- a/server/bdump.c
+++ b/server/bdump.c
@@ -66,6 +66,12 @@ static int setup_file_pointers __P((void));
static void shutdown_file_pointers __P((void));
static void cleanup __P((Server *server));
+#ifdef HAVE_KRB5
+static long ticket5_time;
+#define TKT5LIFETIME 8*60*60
+#define tkt5_lifetime(val) (val)
+#endif
+
#ifdef HAVE_KRB4
static long ticket_time;
@@ -272,7 +278,12 @@ bdump_send()
}
/* Now begin the brain dump. */
-
+#ifdef HAVE_KRB5
+ { /* "server" side */
+ krb5_auth_context actx;
+
+ }
+#else /* HAVE_KRB5 */
#ifdef HAVE_KRB4
/* receive the authenticator */
retval = GetKerberosData(live_socket, from.sin_addr, &kdata,
@@ -311,6 +322,7 @@ bdump_send()
return;
}
#endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB5 */
retval = setup_file_pointers();
if (retval != 0) {
@@ -450,6 +462,109 @@ bdump_get_v12 (notice, auth, who, server)
/* Now begin the brain dump. */
+#ifdef HAVE_KRB5
+ if (get_tgt()) {
+ cleanup(server);
+ return;
+ }
+ { /* "client" side */
+ krb5_auth_context actx;
+ krb5_creds creds;
+ krb5_creds *credsp;
+ krb5_principal principal;
+ krb5_data data;
+ krb5_ap_rep_enc_part *rep;
+
+ memset((char *)&creds, 0, sizeof(creds));
+
+ retval = krb5_build_principal(Z_krb5_ctx, &principal,
+ strlen(ZGetRealm()),
+ ZGetRealm(),
+ SERVER_KRB5_SERVICE, SERVER_INSTANCE,
+ 0);
+ if (retval) {
+ syslog(LOG_ERR, "bdump_get: krb5_build_principal: %s", error_message(retval));
+ cleanup(server);
+ return;
+ }
+
+ retval = krb5_copy_principal(Z_krb5_ctx, principal, &creds.server);
+ if (retval) {
+ syslog(LOG_ERR, "bdump_get: krb5_copy_principal (server): %s", error_message(retval));
+ krb5_free_principal(Z_krb5_ctx, principal);
+ cleanup(server);
+ return;
+ }
+
+ retval = krb5_copy_principal(Z_krb5_ctx, principal, &creds.client);
+ krb5_free_principal(Z_krb5_ctx, principal);
+ if (retval) {
+ syslog(LOG_ERR, "bdump_get: krb5_copy_principal (client): %s", error_message(retval));
+ krb5_free_cred_contents(Z_krb5_ctx, &creds);
+ cleanup(server);
+ return;
+ }
+
+ retval = krb5_get_credentials(Z_krb5_ctx, 0, Z_krb5_ccache,
+ &creds, &credsp);
+ krb5_free_cred_contents(Z_krb5_ctx, &creds);
+ if (retval) {
+ syslog(LOG_ERR, "bdump_get: krb5_get_credentials: %s", error_message(retval));
+ cleanup(server);
+ return;
+ }
+
+ retval = krb5_auth_con_init(Z_krb5_ctx, &actx);
+ if (retval) {
+ syslog(LOG_ERR, "bdump_get: krb5_auth_con_init: %s", error_message(retval));
+ krb5_free_creds(Z_krb5_ctx, credsp);
+ cleanup(server);
+ return;
+ }
+
+ memset((char *)&data, 0, sizeof(krb5_data));
+ retval = krb5_mk_req_extended(Z_krb5_ctx, &actx, AP_OPTS_MUTUAL_REQUIRED|AP_OPTS_USE_SUBKEY,
+ NULL, credsp, &data);
+ if (retval) {
+ syslog(LOG_ERR, "bdump_get: krb5_mk_req_ext: %s", error_message(retval));
+ krb5_auth_con_free(Z_krb5_ctx, actx);
+ krb5_free_creds(Z_krb5_ctx, credsp);
+ cleanup(server);
+ return;
+ }
+ retval = SendKrb5Data(live_socket, &data);
+ krb5_free_creds(Z_krb5_ctx, credsp);
+ if (retval) {
+ syslog(LOG_ERR, "bdump_get: cannot send authenticator: %s",
+ error_message(retval));
+ krb5_free_data_contents(Z_krb5_ctx, &data);
+ krb5_auth_con_free(Z_krb5_ctx, actx);
+ cleanup(server);
+ return;
+ }
+ krb5_free_data_contents(Z_krb5_ctx, &data);
+ memset((char *)&data, 0, sizeof(krb5_data));
+ retval = GetKrb5Data(live_socket, &data);
+ if (retval) {
+ syslog(LOG_ERR, "bdump_get: cannot get auth response: %s",
+ error_message(retval));
+ krb5_auth_con_free(Z_krb5_ctx, actx);
+ cleanup(server);
+ return;
+ }
+ retval = krb5_rd_rep(Z_krb5_ctx, actx, &data, &rep);
+ free(data.data);
+ memset((char *)&data, 0, sizeof(krb5_data));
+ if (retval) {
+ syslog(LOG_ERR, "bdump_get: mutual authentication failed: %s",
+ error_message(retval));
+ krb5_auth_con_free(Z_krb5_ctx, actx);
+ cleanup(server);
+ return;
+ }
+
+ }
+#else
#ifdef HAVE_KRB4
/* send an authenticator */
if (get_tgt()) {
@@ -485,6 +600,7 @@ bdump_get_v12 (notice, auth, who, server)
return;
}
#endif /* HAVE_KRB4 */
+#endif
retval = setup_file_pointers();
if (retval != 0) {
syslog(LOG_WARNING, "bdump_get: can't set up file pointers: %s",
@@ -728,6 +844,54 @@ get_tgt()
des_key_sched(serv_key, serv_ksched.s);
#endif /* !NOENCRYPTION */
}
+#ifdef HAVE_KRB5
+ /* XXX */
+ if (ticket5_time < NOW - tkt5_lifetime(TKT5LIFETIME) + (15L * 60L)) {
+ krb5_keytab kt;
+ krb5_get_init_creds_opt opt;
+ krb5_creds cred;
+ krb5_principal principal;
+
+ memset(&cred, 0, sizeof(cred));
+
+ retval = krb5_build_principal(Z_krb5_ctx, &principal,
+ strlen(ZGetRealm()),
+ ZGetRealm(),
+ SERVER_KRB5_SERVICE, SERVER_INSTANCE,
+ 0);
+ if (retval) {
+ krb5_free_principal(Z_krb5_ctx, principal);
+ return(1);
+ }
+
+ krb5_get_init_creds_opt_init (&opt);
+ krb5_get_init_creds_opt_set_tkt_life (&opt, TKT5LIFETIME);
+
+ retval = krb5_kt_resolve(Z_krb5_ctx, keytab_file, &kt);
+ if (retval) return(1);
+
+ retval = krb5_get_init_creds_keytab (Z_krb5_ctx,
+ &cred,
+ principal,
+ kt,
+ 0,
+ NULL,
+ &opt);
+ krb5_free_principal(Z_krb5_ctx, principal);
+ krb5_kt_close(Z_krb5_ctx, kt);
+ if (retval) return(1);
+
+ retval = krb5_cc_initialize (Z_krb5_ctx, Z_krb5_ccache, cred.client);
+ if (retval) return(1);
+
+ retval = krb5_cc_store_cred (Z_krb5_ctx, Z_krb5_ccache, &cred);
+ if (retval) return(1);
+
+ ticket5_time = NOW;
+
+ krb5_free_cred_contents (Z_krb5_ctx, &cred);
+ }
+#endif
return(0);
}
#endif /* HAVE_KRB4 */
@@ -771,11 +935,17 @@ bdump_recv_loop(server)
Code_t retval;
Client *client = NULL;
struct sockaddr_in who;
-#ifdef HAVE_KRB4
+#ifdef HAVE_KRB5
+ char buf[512];
+ int blen;
+#endif
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
char *cp;
+#endif
+#ifdef HAVE_KRB4
C_Block cblock;
#endif /* HAVE_KRB4 */
- Realm *realm = NULL;
+ ZRealm *realm = NULL;
#if 1
zdbug((LOG_DEBUG, "bdump recv loop"));
@@ -853,6 +1023,52 @@ bdump_recv_loop(server)
syslog(LOG_ERR,"brl failed: %s", error_message(retval));
return retval;
}
+#ifdef HAVE_KRB5
+ client->session_keyblock = NULL;
+ if (*notice.z_class_inst) {
+ /* check out this session key I found */
+ cp = notice.z_message + strlen(notice.z_message) + 1;
+ if (*cp == '0') {
+ /* ****ing netascii; this is an encrypted DES keyblock
+ XXX this code should be conditionalized for server
+ transitions */
+ retval = krb5_init_keyblock(Z_krb5_ctx, ENCTYPE_DES_CBC_CRC,
+ sizeof(C_Block),
+ &client->session_keyblock);
+ if (retval) {
+ syslog(LOG_ERR, "brl failed to allocate DES keyblock: %s",
+ error_message(retval));
+ return retval;
+ }
+ retval = ZReadAscii(cp, strlen(cp), cblock, sizeof(C_Block));
+ if (retval != ZERR_NONE) {
+ syslog(LOG_ERR,"brl bad cblk read: %s (%s)",
+ error_message(retval), cp);
+ } else {
+ des_ecb_encrypt(cblock, client->session_keyblock->contents,
+ serv_ksched.s, DES_DECRYPT);
+ }
+ } else if (*cp == 'Z') { /* Zcode! Long live the new flesh! */
+ retval = ZReadZcode(cp, buf, sizeof(buf), &blen);
+ if (retval != ZERR_NONE) {
+ syslog(LOG_ERR,"brl bad cblk read: %s (%s)",
+ error_message(retval), cp);
+ } else {
+ retval = krb5_init_keyblock(Z_krb5_ctx,
+ ntohl(*(krb5_enctype *)&buf[0]),
+ ntohl(*(krb5_ui_4 *)&buf[4]),
+ &client->session_keyblock);
+ if (retval) {
+ syslog(LOG_ERR, "brl failed to allocate keyblock: %s",
+ error_message(retval));
+ return retval;
+ }
+ memcpy(client->session_keyblock->contents, &buf[8],
+ client->session_keyblock->length);
+ }
+ }
+ }
+#else
#ifdef HAVE_KRB4
memset(client->session_key, 0, sizeof(C_Block));
if (*notice.z_class_inst) {
@@ -872,6 +1088,7 @@ bdump_recv_loop(server)
}
}
#endif /* HAVE_KRB4 */
+#endif
} else if (strcmp(notice.z_opcode, CLIENT_SUBSCRIBE) == 0) {
/* a subscription packet */
if (!client) {
@@ -1138,7 +1355,13 @@ net_read(f, buf, len)
errno = 0;
cc = fread(buf, 1, len, f);
if (cc == 0)
+ {
+ if (feof(f))
+ return len2;
+ if (errno == 0)
+ errno = EIO;
return -1;
+ }
buf += cc;
len2 += cc;
len -= cc;
diff --git a/server/class.c b/server/class.c
index 6ccacae..0ce5da3 100644
--- a/server/class.c
+++ b/server/class.c
@@ -81,9 +81,9 @@ static const char rcsid_class_c[] =
static Triplet *triplet_bucket[HASHSIZE]; /* the hash table of pointers */
static Code_t remove_client __P((Triplet *triplet, Client *client,
- Realm *realm));
+ ZRealm *realm));
static Code_t insert_client __P((Triplet *triplet, Client *client,
- Realm *realm));
+ ZRealm *realm));
static Triplet *triplet_alloc __P((String *classname, String *inst,
String *recipient));
static void free_triplet __P((Triplet *));
@@ -117,7 +117,7 @@ Code_t
triplet_register(client, dest, realm)
Client *client;
Destination *dest;
- Realm *realm;
+ ZRealm *realm;
{
Triplet *triplet;
unsigned long hashval;
@@ -140,7 +140,7 @@ Code_t
triplet_deregister(client, dest, realm)
Client *client;
Destination *dest;
- Realm *realm;
+ ZRealm *realm;
{
Triplet *triplet;
int retval;
@@ -304,7 +304,7 @@ static Code_t
insert_client(triplet, client, realm)
Triplet *triplet;
Client *client;
- Realm *realm;
+ ZRealm *realm;
{
Client **clientp, **newclients;
int new_size;
@@ -348,7 +348,7 @@ insert_client(triplet, client, realm)
static Code_t remove_client(triplet, client, realm)
Triplet *triplet;
Client *client;
- Realm *realm;
+ ZRealm *realm;
{
Client **clientp;
diff --git a/server/client.c b/server/client.c
index 85918e7..9098ac0 100644
--- a/server/client.c
+++ b/server/client.c
@@ -84,9 +84,13 @@ client_register(notice, host, client_p, wantdefaults)
if (!client)
return ENOMEM;
memset(&client->addr, 0, sizeof(struct sockaddr_in));
-#ifdef KERBEROS
+#ifdef HAVE_KRB5
+ client->session_keyblock = NULL;
+#else
+#ifdef HAVE_KRB4
memset(&client->session_key, 0, sizeof(client->session_key));
#endif
+#endif
client->last_send = 0;
client->last_ack = NOW;
client->addr.sin_family = AF_INET;
@@ -122,6 +126,10 @@ client_deregister(client, flush)
nack_release(client);
subscr_cancel_client(client);
free_string(client->principal);
+#ifdef HAVE_KRB5
+ if (client->session_keyblock)
+ krb5_free_keyblock(Z_krb5_ctx, client->session_keyblock);
+#endif
if (flush)
uloc_flush_client(&client->addr);
free(client);
diff --git a/server/dispatch.c b/server/dispatch.c
index 493fcd4..09fa0c1 100644
--- a/server/dispatch.c
+++ b/server/dispatch.c
@@ -14,6 +14,7 @@
#include <zephyr/mit-copyright.h>
#include "zserver.h"
#include <sys/socket.h>
+#include <com_err.h>
#ifndef lint
#ifndef SABER
@@ -134,7 +135,7 @@ handle_packet()
int authentic; /* authentic flag */
Pending *pending; /* pending packet */
int from_server; /* packet is from another server */
- Realm *realm; /* foreign realm ptr */
+ ZRealm *realm; /* foreign realm ptr */
#ifdef DEBUG
static int first_time = 1;
#endif
@@ -201,8 +202,8 @@ handle_packet()
} else {
if (realm = realm_which_realm(&input_sin)) {
authentic = ZCheckRealmAuthentication(&new_notice,
- &input_sin,
- realm->name);
+ &input_sin,
+ realm->name);
} else
authentic = ZCheckAuthentication(&new_notice, &input_sin);
}
@@ -223,6 +224,7 @@ handle_packet()
}
}
+#if 0
if (whoisit.sin_port != hm_port && whoisit.sin_port != hm_srv_port &&
strcasecmp(new_notice.z_class, ZEPHYR_ADMIN_CLASS) != 0 &&
whoisit.sin_port != srv_addr.sin_port &&
@@ -231,6 +233,7 @@ handle_packet()
ntohs(whoisit.sin_port));
return;
}
+#endif
message_notices.val++;
dispatch(&new_notice, authentic, &whoisit, from_server);
@@ -251,7 +254,7 @@ dispatch(notice, auth, who, from_server)
String *notice_class;
struct sockaddr_in who2;
int authflag;
- Realm *realm;
+ ZRealm *realm;
char *cp;
#ifdef DEBUG
char dbg_buf[BUFSIZ];
@@ -353,7 +356,7 @@ sendit(notice, auth, who, external)
class = make_string(notice->z_class, 1);
if (realm_bound_for_realm(ZGetRealm(), notice->z_recipient)) {
- Realm *rlm;
+ ZRealm *rlm;
acl = class_get_acl(class);
if (acl != NULL) {
@@ -586,6 +589,7 @@ xmit_frag(notice, buf, len, waitforack)
return(ZERR_NONE);
}
+
/*
* Send the notice to the client. After transmitting, put it onto the
* not ack'ed list.
@@ -619,14 +623,23 @@ xmit(notice, dest, auth, client)
we are distributing authentic and
we have a pointer to auth info
*/
-#ifdef HAVE_KRB4
- retval = ZFormatAuthenticNotice(notice, noticepack, packlen, &packlen,
- client->session_key);
- if (retval != ZERR_NONE) {
- syslog(LOG_ERR, "xmit auth format: %s", error_message(retval));
- free(noticepack);
- return;
- }
+#ifdef HAVE_KRB5
+ retval = ZFormatAuthenticNoticeV5(notice, noticepack, packlen,
+ &packlen, client->session_keyblock);
+ if (retval != ZERR_NONE) {
+ syslog(LOG_ERR, "xmit auth format: %s", error_message(retval));
+ free(noticepack);
+ return;
+ }
+#else
+#if defined(HAVE_KRB4)
+ retval = ZFormatAuthenticNotice(notice, noticepack, packlen,
+ &packlen, client->session_key);
+ if (retval != ZERR_NONE) {
+ syslog(LOG_ERR, "xmit auth format: %s", error_message(retval));
+ free(noticepack);
+ return;
+ }
#else /* !HAVE_KRB4 */
notice->z_auth = 1;
retval = ZFormatSmallRawNotice(notice, noticepack, &packlen);
@@ -636,6 +649,7 @@ xmit(notice, dest, auth, client)
return;
}
#endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB5 */
} else {
notice->z_auth = 0;
notice->z_authent_len = 0;
@@ -1095,7 +1109,7 @@ control_dispatch(notice, auth, who, server)
Client *client;
Code_t retval;
int wantdefs;
- Realm *realm;
+ ZRealm *realm;
struct sockaddr_in newwho;
/*
@@ -1163,10 +1177,28 @@ control_dispatch(notice, auth, who, server)
clt_ack(notice, who, AUTH_FAILED);
return ZERR_NONE;
}
+#ifdef HAVE_KRB5
+ if (client->session_keyblock) {
+ krb5_free_keyblock_contents(Z_krb5_ctx, client->session_keyblock);
+ retval = krb5_copy_keyblock_contents(Z_krb5_ctx, ZGetSession(),
+ client->session_keyblock);
+ } else {
+ retval = krb5_copy_keyblock(Z_krb5_ctx, ZGetSession(),
+ &client->session_keyblock);
+ }
+ if (retval) {
+ syslog(LOG_WARNING, "keyblock copy failed in subscr: %s",
+ error_message(retval));
+ if (server == me_server)
+ nack(notice, who);
+ return ZERR_NONE;
+ }
+#else
#ifdef HAVE_KRB4
/* in case it's changed */
memcpy(client->session_key, ZGetSession(), sizeof(C_Block));
#endif
+#endif
retval = subscr_subscribe(client, notice, server);
if (retval != ZERR_NONE) {
syslog(LOG_WARNING, "subscr failed: %s", error_message(retval));
diff --git a/server/kstuff.c b/server/kstuff.c
index eff445d..b4b48d7 100644
--- a/server/kstuff.c
+++ b/server/kstuff.c
@@ -22,30 +22,6 @@ static const char rcsid_kstuff_c[] = "$Id$";
#ifdef HAVE_KRB4
-/* Keep a hash table mapping tickets to session keys, so we can do a fast
- * check of the cryptographic checksum without doing and DES decryptions.
- * Also remember the expiry time of the ticket, so that we can sweep the
- * table periodically. */
-
-#define HASHTAB_SIZE 4091
-
-typedef struct hash_entry Hash_entry;
-
-/* The ticket comes at the end, in a variable-length array. */
-struct hash_entry {
- C_Block session_key;
- time_t expires;
- char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4];
- Hash_entry *next;
- int ticket_len;
- unsigned char ticket[1];
-};
-
-Hash_entry *hashtab[HASHTAB_SIZE];
-
-static int hash_ticket __P((unsigned char *, int));
-static void add_session_key __P((KTEXT, C_Block, char *, time_t));
-static int find_session_key __P((KTEXT, C_Block, char *));
static ZChecksum_t compute_checksum __P((ZNotice_t *, C_Block));
static ZChecksum_t compute_rlm_checksum __P((ZNotice_t *, C_Block));
@@ -113,6 +89,10 @@ GetKerberosData(fd, haddr, kdata, service, srvtab)
* get the ticket and write it to the file descriptor
*/
+#if !defined(krb_err_base) && defined(ERROR_TABLE_BASE_krb)
+#define krb_err_base ERROR_TABLE_BASE_krb
+#endif
+
Code_t
SendKerberosData(fd, ticket, service, host)
int fd; /* file descriptor to write onto */
@@ -142,21 +122,93 @@ SendKerberosData(fd, ticket, service, host)
#endif /* HAVE_KRB4 */
+#ifdef HAVE_KRB5
+Code_t
+GetKrb5Data(int fd, krb5_data *data) {
+ char p[20];
+ int i;
+ unsigned char *dst;
+ Code_t retval;
+
+ for (i=0; i<20; i++) {
+ if (read(fd, &p[i], 1) != 1) {
+ syslog(LOG_WARNING,"bad read reply len");
+ return(KFAILURE);
+ }
+ if (p[i] == ' ') {
+ p[i] = '\0';
+ break;
+ }
+ }
+ if (i == 20 || strncmp(p, "V5-", 3) || !atoi(p+3)) {
+ syslog(LOG_WARNING,"bad reply len");
+ return ZSRV_PKSHORT;
+ }
+ data->length = atoi(p+3);
+ data->data = malloc(data->length);
+ if (! data->data) {
+ data->length = 0;
+ return errno;
+ }
+ dst=data->data;
+ for (i=0; i < data->length; i++) {
+ if (read(fd, dst++, 1) != 1) {
+ free(data->data);
+ memset((char *)data, 0, sizeof(krb5_data));
+ syslog(LOG_WARNING,"bad read reply string");
+ return ZSRV_PKSHORT;
+ }
+ }
+ return 0;
+}
+Code_t
+SendKrb5Data(int fd, krb5_data *data) {
+ char p[32];
+ int written, size_to_write;
+ sprintf(p, "V5-%d", data->length);
+ size_to_write = strlen (p);
+ if (size_to_write != (written = write(fd, p, size_to_write)) ||
+ data->length != (written = write(fd, data->data, data->length))) {
+ return (written < 0) ? errno : ZSRV_PKSHORT;
+ }
+ return 0;
+}
+#endif
+
Code_t
ZCheckRealmAuthentication(notice, from, realm)
ZNotice_t *notice;
struct sockaddr_in *from;
char *realm;
{
-#ifdef HAVE_KRB4
- int result;
- char rlmprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4];
- char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4];
- KTEXT_ST authent, ticket;
- AUTH_DAT dat;
- ZChecksum_t checksum;
- CREDENTIALS cred;
- C_Block session_key;
+#ifdef HAVE_KRB5
+ char *authbuf;
+ char rlmprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4+1024];
+ krb5_principal princ;
+ krb5_data packet;
+ krb5_ticket *tkt;
+ char *name;
+ krb5_error_code result;
+ krb5_principal server;
+ krb5_keytab keytabid = 0;
+ krb5_auth_context authctx;
+ krb5_keyblock *keyblock;
+ krb5_enctype enctype;
+ krb5_cksumtype cksumtype;
+ krb5_data cksumbuf;
+ int valid;
+ char *cksum0_base, *cksum1_base, *cksum2_base;
+ char *svcinst, *x, *y;
+ char *asn1_data, *key_data;
+ int asn1_len, key_len, cksum0_len, cksum1_len, cksum2_len;
+#ifdef KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER
+ krb5_authenticator *authenticator;
+#define KRB5AUTHENT authenticator
+#else
+ krb5_authenticator authenticator;
+#define KRB5AUTHENT &authenticator
+#endif
+ int len;
if (!notice->z_auth)
return ZAUTH_NO;
@@ -165,52 +217,537 @@ ZCheckRealmAuthentication(notice, from, realm)
if (notice->z_authent_len <= 0)
return ZAUTH_FAILED;
+ len = strlen(notice->z_ascii_authent)+1;
+ authbuf=malloc(len);
+
/* Read in the authentication data. */
- if (ZReadAscii(notice->z_ascii_authent,
- strlen(notice->z_ascii_authent)+1,
- (unsigned char *)authent.dat,
- notice->z_authent_len) == ZERR_BADFIELD) {
+ if (ZReadZcode(notice->z_ascii_authent,
+ authbuf,
+ len, &len) == ZERR_BADFIELD) {
return ZAUTH_FAILED;
}
- authent.length = notice->z_authent_len;
- (void) sprintf(rlmprincipal, "%s.%s@%s", SERVER_SERVICE,
+ (void) sprintf(rlmprincipal, "%s/%s@%s", SERVER_SERVICE,
SERVER_INSTANCE, realm);
- result = krb_rd_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
- from->sin_addr.s_addr, &dat, srvtab_file);
- if (result == RD_AP_OK) {
- sprintf(srcprincipal, "%s%s%s@%s", dat.pname, dat.pinst[0] ? "." : "",
- dat.pinst, dat.prealm);
- if (strcmp(rlmprincipal, srcprincipal))
- return ZAUTH_FAILED;
- } else {
- return ZAUTH_FAILED; /* didn't decode correctly */
+ packet.length = len;
+ packet.data = authbuf;
+
+ result = krb5_kt_resolve(Z_krb5_ctx,
+ keytab_file, &keytabid);
+ if (result) {
+ free(authbuf);
+ return (result);
}
- /* Check the cryptographic checksum. */
-#ifdef NOENCRYPTION
- checksum = 0;
+ /* HOLDING: authbuf, keytabid */
+ /* Create the auth context */
+ result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
+ if (result) {
+ krb5_kt_close(Z_krb5_ctx, keytabid);
+ free(authbuf);
+ return (result);
+ }
+
+ /* HOLDING: authbuf, authctx */
+ result = krb5_build_principal(Z_krb5_ctx, &server, strlen(__Zephyr_realm),
+ __Zephyr_realm, SERVER_SERVICE,
+ SERVER_INSTANCE, NULL);
+ if (!result) {
+ result = krb5_rd_req(Z_krb5_ctx, &authctx, &packet, server,
+ keytabid, 0, &tkt);
+ krb5_free_principal(Z_krb5_ctx, server);
+ }
+ krb5_kt_close(Z_krb5_ctx, keytabid);
+
+ if (result) {
+ if (result == KRB5KRB_AP_ERR_REPEAT)
+ syslog(LOG_DEBUG, "ZCheckRealmAuthentication: k5 auth failed: %s", error_message(result));
+ else
+ syslog(LOG_WARNING,"ZCheckRealmAuthentication: k5 auth failed: %s", error_message(result));
+ free(authbuf);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ return ZAUTH_FAILED;
+ }
+
+ /* HOLDING: authbuf, authctx, tkt */
+
+ if (tkt == 0 || !Z_tktprincp(tkt)) {
+ if (tkt)
+ krb5_free_ticket(Z_krb5_ctx, tkt);
+ free(authbuf);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ return ZAUTH_FAILED;
+ }
+
+ princ = Z_tktprinc(tkt);
+
+ if (princ == 0) {
+ krb5_free_ticket(Z_krb5_ctx, tkt);
+ free(authbuf);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ return ZAUTH_FAILED;
+ }
+
+ /* HOLDING: authbuf, authctx, tkt */
+ result = krb5_unparse_name(Z_krb5_ctx, princ, &name);
+ if (result) {
+ syslog(LOG_WARNING, "k5 unparse_name failed: %s",
+ error_message(result));
+ free(authbuf);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_ticket(Z_krb5_ctx, tkt);
+ return ZAUTH_FAILED;
+ }
+
+ krb5_free_ticket(Z_krb5_ctx, tkt);
+
+ /* HOLDING: authbuf, authctx, name */
+ if (strcmp(name, rlmprincipal)) {
+ syslog(LOG_WARNING, "k5 name mismatch: '%s' vs '%s'",
+ name, rlmprincipal);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ free(name);
+ free(authbuf);
+ return ZAUTH_FAILED;
+ }
+ free(name);
+ free(authbuf);
+
+ /* HOLDING: authctx */
+ /* Get an authenticator so we can get the keyblock */
+ result = krb5_auth_con_getauthenticator (Z_krb5_ctx, authctx,
+ &authenticator);
+ if(result) {
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ return result;
+ }
+
+ /* HOLDING: authctx, authenticator */
+ result = krb5_auth_con_getkey(Z_krb5_ctx, authctx, &keyblock);
+ if (result) {
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ return (ZAUTH_FAILED);
+ }
+
+ /* HOLDING: authctx, authenticator, keyblock */
+ /* Figure out what checksum type to use */
+ key_data = Z_keydata(keyblock);
+ key_len = Z_keylen(keyblock);
+ result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
+ if (result) {
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ return (ZAUTH_FAILED);
+ }
+ /* HOLDING: authctx, authenticator, keyblock */
+
+ /* Assemble the things to be checksummed */
+ /* first part is from start of packet through z_default_format:
+ * - z_version
+ * - z_num_other_fields
+ * - z_kind
+ * - z_uid
+ * - z_port
+ * - z_auth
+ * - z_authent_len
+ * - z_ascii_authent
+ * - z_class
+ * - z_class_inst
+ * - z_opcode
+ * - z_sender
+ * - z_recipient
+ * - z_default_format
+ */
+ cksum0_base = notice->z_packet;
+ x = notice->z_default_format;
+ cksum0_len = x + strlen(x) + 1 - cksum0_base;
+ /* second part is from z_multinotice through other fields:
+ * - z_multinotice
+ * - z_multiuid
+ * - z_other_fields[]
+ */
+ cksum1_base = notice->z_multinotice;
+ if (notice->z_num_other_fields)
+ x = notice->z_other_fields[notice->z_num_other_fields];
+ else
+ x = cksum1_base + strlen(cksum1_base) + 1; /* multiuid */
+ cksum1_len = x + strlen(x) + 1 - cksum1_base;
+
+ /* last part is the message body */
+ cksum2_base = notice->z_message;
+ cksum2_len = notice->z_message_len;
+
+ if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') &&
+ key_len == 8 &&
+ (enctype == ENCTYPE_DES_CBC_CRC ||
+ enctype == ENCTYPE_DES_CBC_MD4 ||
+ enctype == ENCTYPE_DES_CBC_MD5)) {
+ /* try old-format checksum (covers cksum0 only) */
+
+ ZChecksum_t our_checksum;
+
+ our_checksum = compute_rlm_checksum(notice, key_data);
+
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+
+ if (our_checksum == notice->z_checksum) {
+ return ZAUTH_YES;
+ } else
+ return ZAUTH_FAILED;
+ }
+
+ /* HOLDING: authctx, authenticator */
+
+ cksumbuf.length = cksum0_len + cksum1_len + cksum2_len;
+ cksumbuf.data = malloc(cksumbuf.length);
+ if (!cksumbuf.data) {
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ return ZAUTH_NO;
+ }
+ /* HOLDING: authctx, authenticator, cksumbuf.data */
+
+ memcpy(cksumbuf.data, cksum0_base, cksum0_len);
+ memcpy(cksumbuf.data + cksum0_len, cksum1_base, cksum1_len);
+ memcpy(cksumbuf.data + cksum0_len + cksum1_len,
+ cksum2_base, cksum2_len);
+
+ /* decode zcoded checksum */
+ /* The encoded form is always longer than the original */
+ asn1_len = strlen(notice->z_ascii_checksum) + 1;
+ asn1_data = malloc(asn1_len);
+ if (!asn1_data) {
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ free(cksumbuf.data);
+ return ZAUTH_FAILED;
+ }
+ /* HOLDING: authctx, authenticator, cksumbuf.data, asn1_data */
+ result = ZReadZcode(notice->z_ascii_checksum,
+ asn1_data, asn1_len, &asn1_len);
+ if (result != ZERR_NONE) {
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ free(asn1_data);
+ free(cksumbuf.data);
+ return ZAUTH_FAILED;
+ }
+ /* HOLDING: asn1_data, cksumbuf.data */
+
+ valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype, asn1_data, asn1_len);
+
+ free(asn1_data);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ free(cksumbuf.data);
+
+ if (valid)
+ return (ZAUTH_YES);
+ else
+ return (ZAUTH_FAILED);
#else
- checksum = compute_rlm_checksum(notice, dat.session);
+ return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO;
#endif
- if (checksum != notice->z_checksum) {
-#ifndef NOENCRYPTION
- checksum = compute_checksum(notice, dat.session);
- if (checksum != notice->z_checksum)
+}
+
+Code_t
+ZCheckAuthentication(notice, from)
+ ZNotice_t *notice;
+ struct sockaddr_in *from;
+{
+#ifdef HAVE_KRB5
+ char *authbuf;
+ krb5_principal princ;
+ krb5_data packet;
+ krb5_ticket *tkt;
+ char *name;
+ krb5_error_code result;
+ krb5_principal server;
+ krb5_keytab keytabid = 0;
+ krb5_auth_context authctx;
+ krb5_keyblock *keyblock;
+ krb5_enctype enctype;
+ krb5_cksumtype cksumtype;
+ krb5_data cksumbuf;
+ int valid;
+ char *cksum0_base, *cksum1_base, *cksum2_base;
+ char *svcinst, *x, *y;
+ char *asn1_data, *key_data;
+ int asn1_len, key_len, cksum0_len, cksum1_len, cksum2_len;
+#ifdef KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER
+ krb5_authenticator *authenticator;
+#define KRB5AUTHENT authenticator
+#else
+ krb5_authenticator authenticator;
+#define KRB5AUTHENT &authenticator
#endif
+ int len;
+
+ if (!notice->z_auth)
+ return ZAUTH_NO;
+
+ /* Check for bogus authentication data length. */
+ if (notice->z_authent_len <= 1)
+ return ZAUTH_FAILED;
+
+#ifdef HAVE_KRB4
+ if (notice->z_ascii_authent[0] != 'Z')
+ return ZCheckAuthentication4(notice, from);
+#endif
+
+ len = strlen(notice->z_ascii_authent)+1;
+ authbuf=malloc(len);
+
+ /* Read in the authentication data. */
+ if (ZReadZcode(notice->z_ascii_authent,
+ authbuf,
+ len, &len) == ZERR_BADFIELD) {
return ZAUTH_FAILED;
}
- return ZAUTH_YES;
+ packet.length = len;
+ packet.data = authbuf;
-#else /* !HAVE_KRB4 */
+ result = krb5_kt_resolve(Z_krb5_ctx,
+ keytab_file, &keytabid);
+ if (result) {
+ free(authbuf);
+ return (result);
+ }
+
+ /* HOLDING: authbuf, keytabid */
+ /* Create the auth context */
+ result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
+ if (result) {
+ krb5_kt_close(Z_krb5_ctx, keytabid);
+ free(authbuf);
+ return (result);
+ }
+
+ /* HOLDING: authbuf, authctx */
+ result = krb5_build_principal(Z_krb5_ctx, &server, strlen(__Zephyr_realm),
+ __Zephyr_realm, SERVER_SERVICE,
+ SERVER_INSTANCE, NULL);
+ if (!result) {
+ result = krb5_rd_req(Z_krb5_ctx, &authctx, &packet, server,
+ keytabid, 0, &tkt);
+ krb5_free_principal(Z_krb5_ctx, server);
+ }
+ krb5_kt_close(Z_krb5_ctx, keytabid);
+
+ if (result) {
+ if (result == KRB5KRB_AP_ERR_REPEAT)
+ syslog(LOG_DEBUG, "ZCheckAuthentication: k5 auth failed: %s", error_message(result));
+ else
+ syslog(LOG_WARNING,"ZCheckAuthentication: k5 auth failed: %s", error_message(result));
+ free(authbuf);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ return ZAUTH_FAILED;
+ }
+
+ /* HOLDING: authbuf, authctx, tkt */
+
+ if (tkt == 0 || !Z_tktprincp(tkt)) {
+ if (tkt)
+ krb5_free_ticket(Z_krb5_ctx, tkt);
+ free(authbuf);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ return ZAUTH_FAILED;
+ }
+ princ = Z_tktprinc(tkt);
+
+ if (princ == 0) {
+ krb5_free_ticket(Z_krb5_ctx, tkt);
+ free(authbuf);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ return ZAUTH_FAILED;
+ }
+
+ /* HOLDING: authbuf, authctx, tkt */
+ result = krb5_unparse_name(Z_krb5_ctx, princ, &name);
+ if (result) {
+ syslog(LOG_WARNING, "k5 unparse_name failed: %s",
+ error_message(result));
+ free(authbuf);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_ticket(Z_krb5_ctx, tkt);
+ return ZAUTH_FAILED;
+ }
+
+ krb5_free_ticket(Z_krb5_ctx, tkt);
+
+ /* HOLDING: authbuf, authctx, name */
+ if (strcmp(name, notice->z_sender)) {
+ syslog(LOG_WARNING, "k5 name mismatch: '%s' vs '%s'",
+ name, notice->z_sender);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ free(name);
+ free(authbuf);
+ return ZAUTH_FAILED;
+ }
+ free(name);
+ free(authbuf);
+
+ /* HOLDING: authctx */
+ /* Get an authenticator so we can get the keyblock */
+ result = krb5_auth_con_getauthenticator (Z_krb5_ctx, authctx,
+ &authenticator);
+ if(result) {
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ return result;
+ }
+
+ /* HOLDING: authctx, authenticator */
+ result = krb5_auth_con_getkey(Z_krb5_ctx, authctx, &keyblock);
+ if (result) {
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ return (ZAUTH_FAILED);
+ }
+
+ /* HOLDING: authctx, authenticator, keyblock */
+ /* Figure out what checksum type to use */
+ key_data = Z_keydata(keyblock);
+ key_len = Z_keylen(keyblock);
+ result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
+ if (result) {
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ return (ZAUTH_FAILED);
+ }
+ /* HOLDING: authctx, authenticator, keyblock */
+
+ ZSetSession(keyblock);
+
+ /* Assemble the things to be checksummed */
+ /* first part is from start of packet through z_default_format:
+ * - z_version
+ * - z_num_other_fields
+ * - z_kind
+ * - z_uid
+ * - z_port
+ * - z_auth
+ * - z_authent_len
+ * - z_ascii_authent
+ * - z_class
+ * - z_class_inst
+ * - z_opcode
+ * - z_sender
+ * - z_recipient
+ * - z_default_format
+ */
+ cksum0_base = notice->z_packet;
+ x = notice->z_default_format;
+ cksum0_len = x + strlen(x) + 1 - cksum0_base;
+ /* second part is from z_multinotice through other fields:
+ * - z_multinotice
+ * - z_multiuid
+ * - z_other_fields[]
+ */
+ cksum1_base = notice->z_multinotice;
+ if (notice->z_num_other_fields)
+ x = notice->z_other_fields[notice->z_num_other_fields];
+ else
+ x = cksum1_base + strlen(cksum1_base) + 1; /* multiuid */
+ cksum1_len = x + strlen(x) + 1 - cksum1_base;
+
+ /* last part is the message body */
+ cksum2_base = notice->z_message;
+ cksum2_len = notice->z_message_len;
+
+ if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') &&
+ key_len == 8 &&
+ (enctype == ENCTYPE_DES_CBC_CRC ||
+ enctype == ENCTYPE_DES_CBC_MD4 ||
+ enctype == ENCTYPE_DES_CBC_MD5)) {
+ /* try old-format checksum (covers cksum0 only) */
+
+ ZChecksum_t our_checksum;
+
+ our_checksum = compute_checksum(notice, key_data);
+
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+
+ if (our_checksum == notice->z_checksum)
+ return ZAUTH_YES;
+ else
+ return ZAUTH_FAILED;
+ }
+
+ /* HOLDING: authctx, authenticator */
+
+ cksumbuf.length = cksum0_len + cksum1_len + cksum2_len;
+ cksumbuf.data = malloc(cksumbuf.length);
+ if (!cksumbuf.data) {
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ return ZAUTH_NO;
+ }
+ /* HOLDING: authctx, authenticator, cksumbuf.data */
+
+ memcpy(cksumbuf.data, cksum0_base, cksum0_len);
+ memcpy(cksumbuf.data + cksum0_len, cksum1_base, cksum1_len);
+ memcpy(cksumbuf.data + cksum0_len + cksum1_len,
+ cksum2_base, cksum2_len);
+
+ /* decode zcoded checksum */
+ /* The encoded form is always longer than the original */
+ asn1_len = strlen(notice->z_ascii_checksum) + 1;
+ asn1_data = malloc(asn1_len);
+ if (!asn1_data) {
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ free(cksumbuf.data);
+ return ZAUTH_FAILED;
+ }
+ /* HOLDING: authctx, authenticator, cksumbuf.data, asn1_data */
+ result = ZReadZcode(notice->z_ascii_checksum,
+ asn1_data, asn1_len, &asn1_len);
+ if (result != ZERR_NONE) {
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ free(asn1_data);
+ free(cksumbuf.data);
+ return ZAUTH_FAILED;
+ }
+ /* HOLDING: asn1_data, cksumbuf.data, authctx, authenticator */
+
+ valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype, asn1_data, asn1_len);
+
+ free(asn1_data);
+ krb5_auth_con_free(Z_krb5_ctx, authctx);
+ krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
+ krb5_free_keyblock(Z_krb5_ctx, keyblock);
+ free(cksumbuf.data);
+
+ if (valid)
+ return (ZAUTH_YES);
+ else
+ return (ZAUTH_FAILED);
+#else
return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO;
#endif
}
+#undef KRB5AUTHENT
+
Code_t
-ZCheckAuthentication(notice, from)
+ZCheckAuthentication4(notice, from)
ZNotice_t *notice;
struct sockaddr_in *from;
{
@@ -221,6 +758,7 @@ ZCheckAuthentication(notice, from)
AUTH_DAT dat;
ZChecksum_t checksum;
C_Block session_key;
+ char instance[INST_SZ+1];
if (!notice->z_auth)
return ZAUTH_NO;
@@ -238,10 +776,13 @@ ZCheckAuthentication(notice, from)
}
authent.length = notice->z_authent_len;
- result = krb_rd_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
+ strcpy(instance, SERVER_INSTANCE);
+
+ /* We don't have the session key cached; do it the long way. */
+ result = krb_rd_req(&authent, SERVER_SERVICE, instance,
from->sin_addr.s_addr, &dat, srvtab_file);
if (result == RD_AP_OK) {
- memcpy(__Zephyr_session, dat.session, sizeof(C_Block));
+ ZSetSessionDES(&dat.session);
sprintf(srcprincipal, "%s%s%s@%s", dat.pname, dat.pinst[0] ? "." : "",
dat.pinst, dat.prealm);
if (strcmp(srcprincipal, notice->z_sender))
@@ -266,76 +807,8 @@ ZCheckAuthentication(notice, from)
#endif
}
-#ifdef HAVE_KRB4
-
-static int hash_ticket(p, len)
- unsigned char *p;
- int len;
-{
- unsigned long hashval = 0, g;
-
- for (; len > 0; p++, len--) {
- hashval = (hashval << 4) + *p;
- g = hashval & 0xf0000000;
- if (g) {
- hashval ^= g >> 24;
- hashval ^= g;
- }
- }
- return hashval % HASHTAB_SIZE;
-}
-
-static void add_session_key(ticket, session_key, srcprincipal, expires)
- KTEXT ticket;
- C_Block session_key;
- char *srcprincipal;
- time_t expires;
-{
- Hash_entry *entry;
- int hashval;
-
- /* If we can't allocate memory for the hash table entry, just forget
- * about it. */
- entry = (Hash_entry *) malloc(sizeof(Hash_entry) - 1 + ticket->length);
- if (!entry)
- return;
-
- /* Initialize the new entry. */
- memcpy(entry->session_key, session_key, sizeof(entry->session_key));
- strcpy(entry->srcprincipal, srcprincipal);
- entry->expires = expires;
- entry->ticket_len = ticket->length;
- memcpy(entry->ticket, ticket->dat, ticket->length * sizeof(unsigned char));
-
- /* Insert the new entry in the hash table. */
- hashval = hash_ticket(ticket->dat, ticket->length);
- entry->next = hashtab[hashval];
- hashtab[hashval] = entry;
-}
-
-static int find_session_key(ticket, key, srcprincipal)
- KTEXT ticket;
- C_Block key;
- char *srcprincipal;
-{
- unsigned char *dat;
- int hashval, len;
- Hash_entry *entry;
-
- dat = ticket->dat;
- len = ticket->length;
- hashval = hash_ticket(dat, len);
-
- for (entry = hashtab[hashval]; entry; entry = entry->next) {
- if (entry->ticket_len == len && memcmp(entry->ticket, dat, len) == 0) {
- memcpy(key, entry->session_key, sizeof(entry->session_key));
- strcpy(srcprincipal, entry->srcprincipal);
- return 0;
- }
- }
- return -1;
-}
+#ifdef HAVE_KRB4
static ZChecksum_t compute_checksum(notice, session_key)
ZNotice_t *notice;
C_Block session_key;
@@ -373,26 +846,68 @@ static ZChecksum_t compute_rlm_checksum(notice, session_key)
#endif
}
-void sweep_ticket_hash_table(arg)
- void *arg;
-{
- int i;
- Hash_entry **ptr, *entry;
-
- for (i = 0; i < HASHTAB_SIZE; i++) {
- ptr = &hashtab[i];
- while (*ptr) {
- entry = *ptr;
- if (entry->expires < NOW) {
- *ptr = entry->next;
- free(entry);
- } else {
- ptr = &(*ptr)->next;
- }
- }
+#ifdef HAVE_KRB5
+void
+ZSetSession(krb5_keyblock *keyblock) {
+#if 1
+ krb5_error_code result;
+
+ if (__Zephyr_keyblock) {
+ krb5_free_keyblock_contents(Z_krb5_ctx, __Zephyr_keyblock);
+ result = krb5_copy_keyblock_contents(Z_krb5_ctx, keyblock, __Zephyr_keyblock);
+ } else {
+ result = krb5_copy_keyblock(Z_krb5_ctx, keyblock, &__Zephyr_keyblock);
}
- timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL);
+
+ if (result) /*XXX we're out of memory? */
+ ;
+#else
+ memcpy(__Zephyr_session, Z_keydata(keyblock), sizeof(C_Block));
+#endif
}
+#endif
+#ifdef HAVE_KRB4
+void
+ZSetSessionDES(C_Block *key) {
+#ifdef HAVE_KRB5
+ Code_t result;
+#ifdef HAVE_KRB5_INIT_KEYBLOCK
+ if (__Zephyr_keyblock) {
+ krb5_free_keyblock(__Zephyr_keyblock);
+ __Zephyr_keyblock=NULL;
+ }
+ result = krb5_init_keyblock(Z_krb5_ctx, ENCTYPE_DES_CBC_CRC,
+ sizeof(C_Block)
+ &__Zephyr_keyblock);
+ if (result) /*XXX we're out of memory? */
+ return;
+
+ memcpy(Z_keydata(__Zephyr_keyblock), key, sizeof(C_Block));
+#else
+ krb5_keyblock *tmp, tmp_ss;
+ tmp = &tmp_ss;
+ Z_keylen(tmp)=sizeof(C_Block);
+ Z_keydata(tmp)=key;
+#if HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
+ tmp->enctype = ENCTYPE_DES_CBC_CRC;
+#else
+ tmp->keytype = KEYTYPE_DES;
+#endif
+ if (__Zephyr_keyblock) {
+ krb5_free_keyblock_contents(Z_krb5_ctx, __Zephyr_keyblock);
+ result = krb5_copy_keyblock_contents(Z_krb5_ctx, tmp,
+ __Zephyr_keyblock);
+ } else {
+ result = krb5_copy_keyblock(Z_krb5_ctx, tmp, &__Zephyr_keyblock);
+ }
+ if (result) /*XXX we're out of memory? */
+ ;
+#endif
+#else
+ memcpy(__Zephyr_session, key, sizeof(C_Block));
+#endif
+}
+#endif
#endif /* HAVE_KRB4 */
diff --git a/server/main.c b/server/main.c
index e160929..0f2aa4c 100644
--- a/server/main.c
+++ b/server/main.c
@@ -92,6 +92,10 @@ char *programname; /* set to the basename of argv[0] */
char myname[MAXHOSTNAMELEN]; /* my host name */
char list_file[128];
+#ifdef HAVE_KRB5
+char keytab_file[128];
+static char tkt5_file[256];
+#endif
#ifdef HAVE_KRB4
char srvtab_file[128];
char my_realm[REALM_SZ];
@@ -120,6 +124,15 @@ static int nofork;
struct in_addr my_addr;
char *bdump_version = "1.2";
+#ifdef HAVE_KRB5
+krb5_ccache Z_krb5_ccache;
+krb5_keyblock *__Zephyr_keyblock;
+#else
+#ifdef HAVE_KRB4
+C_Block __Zephyr_session;
+#endif
+#endif
+
int
main(argc, argv)
int argc;
@@ -142,6 +155,10 @@ main(argc, argv)
sprintf(srvtab_file, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_SRVTAB);
sprintf(tkt_file, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_TKFILE);
#endif
+#ifdef HAVE_KRB5
+ sprintf(keytab_file, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_KEYTAB);
+ sprintf(tkt5_file, "FILE:%s/zephyr/%s", SYSCONFDIR, ZEPHYR_TK5FILE);
+#endif
sprintf(acl_dir, "%s/zephyr/%s", SYSCONFDIR, ZEPHYR_ACL_DIR);
sprintf(subs_file, "%s/zephyr/%s", SYSCONFDIR, DEFAULT_SUBS_FILE);
@@ -293,9 +310,6 @@ main(argc, argv)
/* Reinitialize t_local now that initialization is done. */
gettimeofday(&t_local, NULL);
uptime = NOW;
-#ifdef HAVE_KRB4
- timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL);
-#endif
realm_wakeup();
#ifdef DEBUG_MALLOC
@@ -369,6 +383,7 @@ main(argc, argv)
static int
initialize()
{
+ int zero = 0;
if (do_net_setup())
return(1);
@@ -381,6 +396,20 @@ initialize()
ZSetServerState(1);
ZInitialize(); /* set up the library */
+#ifdef HAVE_KRB5
+ krb5_cc_resolve(Z_krb5_ctx, tkt5_file, &Z_krb5_ccache);
+#ifdef HAVE_KRB5_CC_SET_DEFAULT_NAME
+ krb5_cc_set_default_name(Z_krb5_ctx, tkt5_file);
+#else
+ {
+ /* Hack to make krb5_cc_default do something reasonable */
+ char *env=(char *)malloc(strlen(tkt5_file)+12);
+ if (!env) return(1);
+ sprintf(env, "KRB5CCNAME=%s", tkt5_file);
+ putenv(env);
+ }
+#endif
+#endif
#ifdef HAVE_KRB4
/* Override what Zinitialize set for ZGetRealm() */
if (*my_realm)
@@ -447,6 +476,13 @@ do_net_setup()
if (srv_socket < 0) {
syslog(LOG_ERR, "client_sock failed: %m");
return 1;
+ } else {
+#ifdef SO_BSDCOMPAT
+ int on = 1;
+
+ /* Prevent Linux from giving us socket errors we don't care about. */
+ setsockopt(srv_socket, SOL_SOCKET, SO_BSDCOMPAT, &on, sizeof(on));
+#endif
}
if (bind(srv_socket, (struct sockaddr *) &srv_addr,
sizeof(srv_addr)) < 0) {
@@ -633,7 +669,7 @@ reap(sig)
{
int pid, i = 0;
int oerrno = errno;
- Realm *rlm;
+ ZRealm *rlm;
#ifdef _POSIX_VERSION
int waitb;
#else
diff --git a/server/realm.c b/server/realm.c
index ecef9eb..ddfd057 100644
--- a/server/realm.c
+++ b/server/realm.c
@@ -3,17 +3,17 @@
Unacked *rlm_nacklist = NULL; /* not acked list for realm-realm
packets */
-Realm *otherrealms; /* points to an array of the known
+ZRealm *otherrealms; /* points to an array of the known
servers */
int nrealms = 0; /* number of other realms */
/*
* External Routines:
*
- * Realm *realm_which_realm(struct sockaddr_in *who)
+ * ZRealm *realm_which_realm(struct sockaddr_in *who)
* figures out if this packet came from another realm's server
*
- * Realm *realm_get_realm_by_pid(int pid)
+ * ZRealm *realm_get_realm_by_pid(int pid)
* figures out which realm a child handler was for
*
* void kill_realm_pids()
@@ -31,7 +31,7 @@ int nrealms = 0; /* number of other realms */
* int realm_sender_in_realm(char *realm, char *sender)
* figures out if sender is in realm
*
- * Realm *realm_get_realm_by_name(char *name)
+ * ZRealm *realm_get_realm_by_name(char *name)
* finds a realm struct from the realm array by name, tries expansion
*
* Code_t realm_dispatch(ZNotice_t *notice, int auth, struct sockaddr_in *who,
@@ -49,35 +49,34 @@ int nrealms = 0; /* number of other realms */
*
* Code_t realm_control_dispatch(ZNotice_t *notice, int auth,
* struct sockaddr_in *who, Server *server,
- * Realm *realm)
+ * ZRealm *realm)
* dispatches a foreign realm control message
*
* void realm_handoff(ZNotice_t *notice, int auth, struct sockaddr_in *who,
- * Realm *realm, int ack_to_sender)
+ * ZRealm *realm, int ack_to_sender)
* hands off a message to another realm
*
* void realm_dump_realms(File *fp)
* do a database dump of foreign realm info
*
*/
-static void realm_sendit __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender));
-static void realm_sendit_auth __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, Realm *realm, int ack_to_sender));
+static void realm_sendit __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, ZRealm *realm, int ack_to_sender));
+static Code_t realm_sendit_auth __P((ZNotice_t *notice, struct sockaddr_in *who, int auth, ZRealm *realm, int ack_to_sender));
static void rlm_ack __P((ZNotice_t *notice, Unacked *nacked));
static void rlm_nack_cancel __P((ZNotice_t *notice, struct sockaddr_in *who));
static void rlm_new_ticket __P(());
static void rlm_rexmit __P((void *arg));
-static Code_t realm_ulocate_dispatch __P((ZNotice_t *notice,int auth,struct sockaddr_in *who,Server *server,Realm *realm));
-static Code_t realm_new_server __P((struct sockaddr_in *, ZNotice_t *, Realm *));
-static Code_t realm_set_server __P((struct sockaddr_in *, Realm *));
+static Code_t realm_ulocate_dispatch __P((ZNotice_t *notice,int auth,struct sockaddr_in *who,Server *server,ZRealm *realm));
+static Code_t realm_new_server __P((struct sockaddr_in *, ZNotice_t *, ZRealm *));
+static Code_t realm_set_server __P((struct sockaddr_in *, ZRealm *));
#ifdef HAVE_KRB4
-static Code_t ticket_retrieve __P((Realm *realm));
+static Code_t ticket_retrieve __P((ZRealm *realm));
static int ticket_lookup __P((char *realm));
-static int ticket_expired __P((CREDENTIALS *cred));
#endif
static int
realm_get_idx_by_addr(realm, who)
- Realm *realm;
+ ZRealm *realm;
struct sockaddr_in *who;
{
struct sockaddr_in *addr;
@@ -95,7 +94,7 @@ char *
realm_expand_realm(realmname)
char *realmname;
{
- Realm *realm;
+ ZRealm *realm;
int a;
/* First, look for an exact match (case insensitive) */
@@ -120,11 +119,11 @@ char *realmname;
return(realmname);
}
-Realm *
+ZRealm *
realm_get_realm_by_pid(pid)
int pid;
{
- Realm *realm;
+ ZRealm *realm;
int a;
for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
@@ -137,7 +136,7 @@ realm_get_realm_by_pid(pid)
void
kill_realm_pids()
{
- Realm *realm;
+ ZRealm *realm;
int a;
for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
@@ -147,11 +146,11 @@ kill_realm_pids()
return;
}
-Realmname *
+ZRealmname *
get_realm_lists(file)
char *file;
{
- Realmname *rlm_list, *rlm;
+ ZRealmname *rlm_list, *rlm;
int ii, nused, ntotal;
FILE *fp;
char buf[REALM_SZ + MAXHOSTNAMELEN + 1]; /* one for newline */
@@ -159,11 +158,11 @@ get_realm_lists(file)
nused = 0;
if (!(fp = fopen(file, "r")))
- return((Realmname *)0);
+ return((ZRealmname *)0);
/* start with 16, realloc if necessary */
ntotal = 16;
- rlm_list = (Realmname *)malloc(ntotal * sizeof(Realmname));
+ rlm_list = (ZRealmname *)malloc(ntotal * sizeof(ZRealmname));
if (!rlm_list) {
syslog(LOG_CRIT, "get_realm_lists malloc");
abort();
@@ -197,9 +196,9 @@ get_realm_lists(file)
/* new realm */
if (nused + 1 >= ntotal) {
/* make more space */
- rlm_list = (Realmname *)realloc((char *)rlm_list,
+ rlm_list = (ZRealmname *)realloc((char *)rlm_list,
(unsigned)ntotal * 2 *
- sizeof(Realmname));
+ sizeof(ZRealmname));
if (!rlm_list) {
syslog(LOG_CRIT, "get_realm_lists realloc");
abort();
@@ -219,9 +218,9 @@ get_realm_lists(file)
}
}
if (nused + 1 >= ntotal) {
- rlm_list = (Realmname *)realloc((char *)rlm_list,
+ rlm_list = (ZRealmname *)realloc((char *)rlm_list,
(unsigned)(ntotal + 1) *
- sizeof(Realmname));
+ sizeof(ZRealmname));
if (!rlm_list) {
syslog(LOG_CRIT, "get_realm_lists realloc");
abort();
@@ -229,6 +228,7 @@ get_realm_lists(file)
}
*rlm_list[nused].name = '\0';
+ fclose(fp);
return(rlm_list);
}
@@ -282,7 +282,7 @@ realm_sender_in_realm(realm, sender)
return 0;
}
-sender_in_realm(notice)
+int sender_in_realm(notice)
ZNotice_t *notice;
{
char *realm;
@@ -295,11 +295,11 @@ sender_in_realm(notice)
return 0;
}
-Realm *
+ZRealm *
realm_which_realm(who)
struct sockaddr_in *who;
{
- Realm *realm;
+ ZRealm *realm;
struct sockaddr_in *addr;
int a, b;
@@ -316,12 +316,12 @@ realm_which_realm(who)
return 0;
}
-Realm *
+ZRealm *
realm_get_realm_by_name(name)
char *name;
{
int a;
- Realm *realm;
+ ZRealm *realm;
/* First, look for an exact match (case insensitive) */
for (realm = otherrealms, a = 0; a < nrealms; a++, realm++)
@@ -341,7 +341,7 @@ rlm_nack_cancel(notice, who)
register ZNotice_t *notice;
struct sockaddr_in *who;
{
- register Realm *which = realm_which_realm(who);
+ register ZRealm *which = realm_which_realm(who);
register Unacked *nacked, *next;
ZPacket_t retval;
@@ -424,7 +424,7 @@ realm_dispatch(notice, auth, who, server)
struct sockaddr_in *who;
Server *server;
{
- Realm *realm;
+ ZRealm *realm;
struct sockaddr_in newwho;
Code_t status = ZERR_NONE;
char rlm_recipient[REALM_SZ + 1];
@@ -490,8 +490,8 @@ void
realm_init()
{
Client *client;
- Realmname *rlmnames;
- Realm *rlm;
+ ZRealmname *rlmnames;
+ ZRealm *rlm;
int ii, jj, found;
struct in_addr *addresses;
struct hostent *hp;
@@ -508,7 +508,7 @@ realm_init()
for (nrealms = 0; *rlmnames[nrealms].name; nrealms++);
- otherrealms = (Realm *)malloc(nrealms * sizeof(Realm));
+ otherrealms = (ZRealm *)malloc(nrealms * sizeof(ZRealm));
if (!otherrealms) {
syslog(LOG_CRIT, "malloc failed in realm_init");
abort();
@@ -557,9 +557,13 @@ realm_init()
abort();
}
memset(&client->addr, 0, sizeof(struct sockaddr_in));
+#ifdef HAVE_KRB5
+ client->session_keyblock = NULL;
+#else
#ifdef HAVE_KRB4
memset(&client->session_key, 0, sizeof(client->session_key));
#endif
+#endif
sprintf(rlmprinc, "%s.%s@%s", SERVER_SERVICE, SERVER_INSTANCE,
rlm->name);
client->principal = make_string(rlmprinc, 0);
@@ -589,7 +593,7 @@ void
realm_deathgram(server)
Server *server;
{
- Realm *realm;
+ ZRealm *realm;
char rlm_recipient[REALM_SZ + 1];
int jj = 0;
@@ -628,7 +632,7 @@ realm_deathgram(server)
}
#endif
- if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZAUTH))
+ if ((retval = ZFormatNotice(&snotice, &pack, &packlen, ZCAUTH))
!= ZERR_NONE)
{
syslog(LOG_WARNING, "rlm_deathgram format: %s",
@@ -651,7 +655,7 @@ void
realm_wakeup()
{
int jj, found = 0;
- Realm *realm;
+ ZRealm *realm;
char rlm_recipient[REALM_SZ + 1];
for (jj = 1; jj < nservers; jj++) { /* skip limbo server */
@@ -721,7 +725,7 @@ realm_ulocate_dispatch(notice, auth, who, server, realm)
int auth;
struct sockaddr_in *who;
Server *server;
- Realm *realm;
+ ZRealm *realm;
{
register char *opcode = notice->z_opcode;
Code_t status;
@@ -761,7 +765,7 @@ realm_control_dispatch(notice, auth, who, server, realm)
int auth;
struct sockaddr_in *who;
Server *server;
- Realm *realm;
+ ZRealm *realm;
{
register char *opcode = notice->z_opcode;
Code_t status;
@@ -841,12 +845,12 @@ static Code_t
realm_new_server(sin, notice, realm)
struct sockaddr_in *sin;
ZNotice_t *notice;
- Realm *realm;
+ ZRealm *realm;
{
struct hostent *hp;
char suggested_server[MAXHOSTNAMELEN];
unsigned long addr;
- Realm *rlm;
+ ZRealm *rlm;
struct sockaddr_in sinaddr;
int srvidx;
@@ -877,9 +881,9 @@ realm_new_server(sin, notice, realm)
static Code_t
realm_set_server(sin, realm)
struct sockaddr_in *sin;
- Realm *realm;
+ ZRealm *realm;
{
- Realm *rlm;
+ ZRealm *rlm;
rlm = realm_which_realm(sin);
/* Not exactly */
@@ -894,7 +898,7 @@ realm_handoff(notice, auth, who, realm, ack_to_sender)
ZNotice_t *notice;
int auth;
struct sockaddr_in *who;
- Realm *realm;
+ ZRealm *realm;
int ack_to_sender;
{
#ifdef HAVE_KRB4
@@ -917,7 +921,7 @@ realm_handoff(notice, auth, who, realm, ack_to_sender)
zdbug((LOG_DEBUG, "realm_sendit to realm %s auth %d", realm->name, auth));
/* valid ticket available now, send the message */
- realm_sendit_auth(notice, who, auth, realm, ack_to_sender);
+ retval = realm_sendit_auth(notice, who, auth, realm, ack_to_sender);
#else /* HAVE_KRB4 */
realm_sendit(notice, who, auth, realm, ack_to_sender);
#endif /* HAVE_KRB4 */
@@ -928,7 +932,7 @@ realm_sendit(notice, who, auth, realm, ack_to_sender)
ZNotice_t *notice;
struct sockaddr_in *who;
int auth;
- Realm *realm;
+ ZRealm *realm;
int ack_to_sender;
{
caddr_t pack;
@@ -1009,7 +1013,7 @@ rlm_rexmit(arg)
{
Unacked *nackpacket = (Unacked *) arg;
Code_t retval;
- register Realm *realm;
+ register ZRealm *realm;
int new_srv_idx;
zdbug((LOG_DEBUG,"rlm_rexmit"));
@@ -1100,12 +1104,12 @@ realm_dump_realms(fp)
}
#ifdef HAVE_KRB4
-static void
+static Code_t
realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
ZNotice_t *notice;
int auth;
struct sockaddr_in *who;
- Realm *realm;
+ ZRealm *realm;
int ack_to_sender;
{
char *buffer, *ptr;
@@ -1115,33 +1119,27 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
Code_t retval;
Unacked *nacked;
char buf[1024], multi[64];
- CREDENTIALS cred;
- KTEXT_ST authent;
ZNotice_t partnotice, newnotice;
offset = 0;
- /* build an authent. first, make sure we have the ticket available */
- retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm->name, &cred);
- if (retval != GC_OK) {
- syslog(LOG_WARNING, "rlm_sendit_auth get_cred: %s",
- error_message(retval+krb_err_base));
- return;
+ buffer = (char *) malloc(sizeof(ZPacket_t));
+ if (!buffer) {
+ syslog(LOG_ERR, "realm_sendit_auth malloc");
+ return ENOMEM; /* DON'T put on nack list */
}
- retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
- realm->name, 1);
- if (retval != MK_AP_OK) {
- syslog(LOG_WARNING, "rlm_sendit_auth mk_req: %s",
- error_message(retval+krb_err_base));
- return;
- }
+ buffer_len = sizeof(ZPacket_t);
+
+ newnotice = *notice;
- retval = ZMakeAscii(buf, sizeof(buf), authent.dat, authent.length);
+ hdrlen = 0;
+ retval = ZMakeZcodeRealmAuthentication(&newnotice, buffer, buffer_len,
+ &hdrlen, realm->name);
if (retval != ZERR_NONE) {
- syslog(LOG_WARNING, "rlm_sendit_auth mk_ascii: %s",
+ syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s",
error_message(retval));
- return;
+ return (retval);
}
/* set the dest addr */
@@ -1149,45 +1147,7 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
if (retval != ZERR_NONE) {
syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s",
error_message(retval));
- return;
- }
-
- /* now format the notice, refragmenting if needed */
- newnotice = *notice;
- newnotice.z_auth = 1;
- newnotice.z_ascii_authent = buf;
- newnotice.z_authent_len = authent.length;
-
- buffer = (char *) malloc(sizeof(ZPacket_t));
- if (!buffer) {
- syslog(LOG_ERR, "realm_sendit_auth malloc");
- return; /* DON'T put on nack list */
- }
-
- buffer_len = sizeof(ZPacket_t);
-
- retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen, &ptr,
- NULL);
- if (retval != ZERR_NONE) {
- syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
- free(buffer);
- return;
- }
-
-#ifdef NOENCRYPTION
- newnotice.z_checksum = 0;
-#else
- newnotice.z_checksum =
- (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0,
- cred.session);
-#endif
-
- retval = Z_FormatRawHeader(&newnotice, buffer, buffer_len, &hdrlen,
- NULL, NULL);
- if (retval != ZERR_NONE) {
- syslog(LOG_WARNING, "rlm_sendit_auth raw: %s", error_message(retval));
- free(buffer);
- return;
+ return (retval);
}
/* This is not terribly pretty, but it does do its job.
@@ -1199,16 +1159,13 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
* but only the server uses it.
*/
- if ((newnotice.z_message_len+hdrlen > buffer_len) ||
- (newnotice.z_message_len+hdrlen > Z_MAXPKTLEN)) {
- /* Deallocate buffer, use a local one */
+ if ((notice->z_message_len+hdrlen > buffer_len) ||
+ (notice->z_message_len+hdrlen > Z_MAXPKTLEN)) {
+
+ /* Reallocate buffers inside the refragmenter */
free(buffer);
-
- partnotice = *notice;
- partnotice.z_auth = 1;
- partnotice.z_ascii_authent = buf;
- partnotice.z_authent_len = authent.length;
+ partnotice = *notice;
origoffset = 0;
origlen = notice->z_message_len;
@@ -1217,7 +1174,7 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
if (sscanf(notice->z_multinotice, "%d/%d", &origoffset,
&origlen) != 2) {
syslog(LOG_WARNING, "rlm_sendit_auth frag: parse failed");
- return;
+ return ZERR_BADFIELD;
}
#if 0
@@ -1252,33 +1209,19 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
buffer = (char *) malloc(sizeof(ZPacket_t));
if (!buffer) {
syslog(LOG_ERR, "realm_sendit_auth malloc");
- return; /* DON'T put on nack list */
+ return ENOMEM; /* DON'T put on nack list */
}
-
- retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len,
- &hdrlen, &ptr, NULL);
- if (retval != ZERR_NONE) {
- syslog(LOG_WARNING, "rlm_sendit_auth raw: %s",
- error_message(retval));
- free(buffer);
- return;
- }
-
-#ifdef NOENCRYPTION
- partnotice.z_checksum = 0;
-#else
- partnotice.z_checksum =
- (ZChecksum_t)des_quad_cksum(buffer, NULL, ptr - buffer, 0,
- cred.session);
-#endif
- retval = Z_FormatRawHeader(&partnotice, buffer, buffer_len,
- &hdrlen, NULL, NULL);
+ buffer_len = sizeof(ZPacket_t);
+
+ retval = ZMakeZcodeRealmAuthentication(&partnotice, buffer,
+ buffer_len, &hdrlen,
+ realm->name);
if (retval != ZERR_NONE) {
- syslog(LOG_WARNING, "rlm_sendit_auth raw: %s",
+ syslog(LOG_WARNING, "rlm_sendit_auth set addr: %s",
error_message(retval));
free(buffer);
- return;
+ return (retval);
}
ptr = buffer+hdrlen;
@@ -1292,14 +1235,14 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s",
error_message(retval));
free(buffer);
- return;
+ return(retval);
}
if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
/* no space: just punt */
syslog(LOG_ERR, "rlm_sendit_auth nack malloc");
free(buffer);
- return;
+ return ENOMEM;
}
nacked->rexmits = 0;
@@ -1326,35 +1269,30 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
if (!notice->z_message_len)
break;
}
-#if 0
- zdbug((LOG_DEBUG, "rlm_sendit_auth frag message sent"));
-#endif
- } else {
+ }
+ else {
/* This is easy, no further fragmentation needed */
ptr = buffer+hdrlen;
(void) memcpy(ptr, newnotice.z_message, newnotice.z_message_len);
- buffer_len = hdrlen+newnotice.z_message_len;
+ buffer_len = hdrlen+newnotice.z_message_len;
/* now send */
if ((retval = ZSendPacket(buffer, buffer_len, 0)) != ZERR_NONE) {
syslog(LOG_WARNING, "rlm_sendit_auth xmit: %s",
error_message(retval));
free(buffer);
- return;
+ return(retval);
}
-#if 0
- zdbug((LOG_DEBUG, "rlm_sendit_auth message sent"));
-#endif
/* now we've sent it, mark it as not ack'ed */
if (!(nacked = (Unacked *)malloc(sizeof(Unacked)))) {
/* no space: just punt */
syslog(LOG_ERR, "rlm_sendit_auth nack malloc");
free(buffer);
- return;
+ return 0;
}
nacked->rexmits = 0;
@@ -1375,61 +1313,103 @@ realm_sendit_auth(notice, who, auth, realm, ack_to_sender)
/* chain in */
LIST_INSERT(&rlm_nacklist, nacked);
}
- return;
-}
-
-static int
-ticket_expired(cred)
-CREDENTIALS *cred;
-{
-#ifdef HAVE_KRB_LIFE_TO_TIME
- return (krb_life_to_time(cred->issue_date, cred->lifetime) < NOW);
-#else /* HAVE_KRB_LIFE_TO_TIME */
- return (cred->issue_date + cred->lifetime*5*60 < NOW);
-#endif /* HAVE_KRB_LIFE_TO_TIME */
+ return 0;
}
static int
ticket_lookup(realm)
char *realm;
{
- CREDENTIALS cred;
- KTEXT_ST authent;
- int retval;
+ krb5_error_code result;
+ krb5_timestamp sec;
+ krb5_ccache ccache;
+ krb5_creds creds_in, *creds;
- retval = krb_get_cred(SERVER_SERVICE, SERVER_INSTANCE, realm, &cred);
- if (retval == GC_OK && !ticket_expired(&cred))
- /* good ticket */
- return(1);
+ result = krb5_cc_default(Z_krb5_ctx, &ccache);
+ if (result)
+ return 0;
+
+ memset(&creds_in, 0, sizeof(creds_in));
+
+ result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client);
+ if (result) {
+ krb5_cc_close(Z_krb5_ctx, ccache);
+ return 0;
+ }
+
+ result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
+ strlen(realm),
+ realm,
+ SERVER_KRB5_SERVICE, SERVER_INSTANCE, 0);
+ if (result) {
+ krb5_cc_close(Z_krb5_ctx, ccache);
+ return 0;
+ }
+
+ result = krb5_get_credentials(Z_krb5_ctx, 0 /* flags */, ccache,
+ &creds_in, &creds);
+ krb5_cc_close(Z_krb5_ctx, ccache);
+ /* good ticket? */
+
+ krb5_timeofday (Z_krb5_ctx, &sec);
+ krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* hope this is OK */
+ if ((result == 0) && (sec < creds->times.endtime)) {
+ krb5_free_creds(Z_krb5_ctx, creds);
+ return (1);
+ }
+ if (!result) krb5_free_creds(Z_krb5_ctx, creds);
return (0);
}
static Code_t
ticket_retrieve(realm)
- Realm *realm;
+ ZRealm *realm;
{
- int pid, retval = 0;
- KTEXT_ST authent;
+ int pid;
+ krb5_ccache ccache;
+ krb5_error_code result;
+ krb5_auth_context authctx;
+ krb5_creds creds_in, *creds;
get_tgt();
if (realm->child_pid)
/* Right idea. Basically, we haven't gotten it yet */
- return KRBET_KDC_AUTH_EXP;
-
- /* For Putrify */
- memset(&authent.dat,0,MAX_KTXT_LEN);
- authent.mbz=0;
+ return KRB5KRB_AP_ERR_TKT_EXPIRED;
if (realm->have_tkt) {
- retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
- realm->name, 0);
- if (retval == KSUCCESS) {
- return retval;
+ /* Get a pointer to the default ccache. We don't need to free this. */
+ result = krb5_cc_default(Z_krb5_ctx, &ccache);
+
+ /* GRRR. There's no allocator or constructor for krb5_creds */
+ /* GRRR. It would be nice if this API were documented at all */
+ memset(&creds_in, 0, sizeof(creds_in));
+
+ if (!result)
+ result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client);
+ /* construct the service principal */
+ if (!result)
+ result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
+ strlen(realm->name), realm->name,
+ SERVER_KRB5_SERVICE, SERVER_INSTANCE,
+ 0);
+
+ /* HOLDING: creds_in.server */
+
+ /* look up or get the credentials we need */
+ if (!result)
+ result = krb5_get_credentials(Z_krb5_ctx, 0 /* flags */, ccache,
+ &creds_in, &creds);
+ krb5_cc_close(Z_krb5_ctx, ccache);
+ krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* hope this is OK */
+ if (!result) {
+ krb5_free_creds(Z_krb5_ctx, creds);
+ return 0;
}
} else {
syslog(LOG_ERR, "tkt_rtrv: don't have ticket, but have no child");
+ result = KRB5KRB_AP_ERR_TKT_EXPIRED;
}
pid = fork();
@@ -1467,11 +1447,37 @@ ticket_retrieve(realm)
#endif
#endif
+ syslog(LOG_INFO, "tkt_rtrv running for %s", realm->name);
while (1) {
- retval = krb_mk_req(&authent, SERVER_SERVICE, SERVER_INSTANCE,
- realm->name, 0);
- if (retval == KSUCCESS)
+ /* Get a pointer to the default ccache. We don't need to free this. */
+ result = krb5_cc_default(Z_krb5_ctx, &ccache);
+
+ /* GRRR. There's no allocator or constructor for krb5_creds */
+ /* GRRR. It would be nice if this API were documented at all */
+ memset(&creds_in, 0, sizeof(creds_in));
+
+ if (!result)
+ result = krb5_cc_get_principal(Z_krb5_ctx, ccache, &creds_in.client);
+ /* construct the service principal */
+ if (!result)
+ result = krb5_build_principal(Z_krb5_ctx, &creds_in.server,
+ strlen(realm->name), realm->name,
+ SERVER_KRB5_SERVICE, SERVER_INSTANCE,
+ 0);
+
+ /* HOLDING: creds_in.server */
+
+ /* look up or get the credentials we need */
+ if (!result)
+ result = krb5_get_credentials(Z_krb5_ctx, 0 /* flags */, ccache,
+ &creds_in, &creds);
+ krb5_cc_close(Z_krb5_ctx, ccache);
+ krb5_free_cred_contents(Z_krb5_ctx, &creds_in); /* hope this is OK */
+ if (!result) {
+ krb5_free_creds(Z_krb5_ctx, creds);
+ syslog(LOG_INFO, "tkt_rtrv succeeded for %s", realm->name);
exit(0);
+ }
/* Sleep a little while before retrying */
sleep(30);
@@ -1479,10 +1485,10 @@ ticket_retrieve(realm)
} else {
realm->child_pid = pid;
realm->have_tkt = 0;
-
- syslog(LOG_WARNING, "tkt_rtrv: %s: %s", realm->name,
- krb_err_txt[retval]);
- return (retval+krb_err_base);
+
+ syslog(LOG_WARNING, "tkt_rtrv: %s: %d", realm->name,
+ result);
+ return (result);
}
}
#endif /* HAVE_KRB4 */
diff --git a/server/server.c b/server/server.c
index 5cce0ff..c2c6421 100644
--- a/server/server.c
+++ b/server/server.c
@@ -880,7 +880,7 @@ send_stats(who)
char **responses;
int num_resp;
char *vers, *pkts, *upt;
- Realm *realm;
+ ZRealm *realm;
int extrafields = 0;
#define NUM_FIXED 3 /* 3 fixed fields, plus server info */
@@ -1381,7 +1381,11 @@ server_forward(notice, auth, who)
syslog(LOG_CRIT, "srv_fwd malloc");
abort();
}
- retval = ZFormatSmallRawNotice(notice, pack, &packlen);
+ if (realm_which_realm(who)) {
+ retval = ZNewFormatSmallRawNotice(notice, pack, &packlen);
+ } else {
+ retval = ZFormatSmallRawNotice(notice, pack, &packlen);
+ }
if (retval != ZERR_NONE) {
syslog(LOG_WARNING, "srv_fwd format: %s", error_message(retval));
continue;
diff --git a/server/subscr.c b/server/subscr.c
index b5da880..49d3211 100644
--- a/server/subscr.c
+++ b/server/subscr.c
@@ -95,10 +95,10 @@ static char **subscr_marshal_subs __P((ZNotice_t *notice, int auth,
int *found));
static Destlist *subscr_copy_def_subs __P((char *person));
static Code_t subscr_realm_sendit __P((Client *who, Destlist *subs,
- ZNotice_t *notice, Realm *realm));
+ ZNotice_t *notice, ZRealm *realm));
static void subscr_unsub_realms __P((Destlist *newsubs));
static void subscr_unsub_sendit __P((Client *who, Destlist *subs,
- Realm *realm));
+ ZRealm *realm));
static int cl_match __P((Destlist*, Client *));
static int defaults_read = 0; /* set to 1 if the default subs
@@ -140,7 +140,7 @@ add_subscriptions(who, subs, notice, server)
Code_t retval;
Acl *acl;
String *sender;
- Realm *realm = NULL;
+ ZRealm *realm = NULL;
if (!subs)
return ZERR_NONE; /* no subscr -> no error */
@@ -187,18 +187,14 @@ add_subscriptions(who, subs, notice, server)
}
}
if (realm && !bdumping) {
- if (server && server == me_server) {
retval = subscr_realm_sendit(who, subs, notice, realm);
if (retval != ZERR_NONE) {
- free_subscriptions(subs);
- free_string(sender);
- return(retval);
- } else {
- /* free this one, will get from ADD */
free_subscription(subs);
- }
+ continue; /* the for loop */
} else {
/* Indicates we leaked traffic back to our realm */
+ free_subscription(subs); /* free this one, wil get from
+ ADD */
}
} else {
retval = triplet_register(who, &subs->dest, NULL);
@@ -333,7 +329,7 @@ subscr_cancel(sin, notice)
struct sockaddr_in *sin;
ZNotice_t *notice;
{
- Realm *realm;
+ ZRealm *realm;
Client *who;
Destlist *cancel_subs, *subs, *cancel_next, *client_subs, *client_next;
Code_t retval;
@@ -396,7 +392,7 @@ Code_t
subscr_realm_cancel(sin, notice, realm)
struct sockaddr_in *sin;
ZNotice_t *notice;
- Realm *realm;
+ ZRealm *realm;
{
Client *who;
Destlist *cancel_subs, *subs, *client_subs, *next, *next2;
@@ -452,7 +448,7 @@ subscr_cancel_client(client)
{
Destlist *subs, *next;
Code_t retval;
- Realm *realm;
+ ZRealm *realm;
#if 0
zdbug((LOG_DEBUG,"subscr_cancel_client %s",
@@ -557,7 +553,7 @@ subscr_marshal_subs(notice, auth, who, found)
zdbug((LOG_DEBUG, "subscr_marshal"));
#endif
*found = 0;
-
+
/* Note that the following code is an incredible crock! */
/* We cannot send multiple packets as acknowledgements to the client,
@@ -842,10 +838,15 @@ subscr_send_subs(client)
{
int i = 0;
Destlist *subs;
+#ifdef HAVE_KRB5
+ char buf[512];
+ char *bufp;
+#else
#ifdef HAVE_KRB4
char buf[512];
C_Block cblock;
#endif /* HAVE_KRB4 */
+#endif
char buf2[512];
char *list[7 * NUM_FIELDS];
int num = 0;
@@ -858,14 +859,45 @@ subscr_send_subs(client)
list[num++] = buf2;
+#ifdef HAVE_KRB5
+#ifdef HAVE_KRB4 /* XXX make this optional for server transition time */
+ if (client->session_keyblock->enctype == ENCTYPE_DES_CBC_CRC) {
+ bufp = malloc(client->session_keyblock->length);
+ if (bufp == NULL) {
+ syslog(LOG_WARNING, "subscr_send_subs: cannot allocate memory for DES keyblock: %m");
+ return errno;
+ }
+ des_ecb_encrypt(client->session_keyblock->contents, bufp, serv_ksched.s, DES_ENCRYPT);
+ retval = ZMakeAscii(buf, sizeof(buf), bufp, client->session_keyblock->length);
+ } else {
+#endif
+ bufp = malloc(client->session_keyblock->length + 8); /* + enctype
+ + length */
+ if (bufp == NULL) {
+ syslog(LOG_WARNING, "subscr_send_subs: cannot allocate memory for keyblock: %m");
+ return errno;
+ }
+ *(krb5_enctype *)&bufp[0] = htonl(client->session_keyblock->enctype);
+ *(krb5_ui_4 *)&bufp[4] = htonl(client->session_keyblock->length);
+ memcpy(&bufp[8], client->session_keyblock->contents, client->session_keyblock->length);
+
+ retval = ZMakeZcode(buf, sizeof(buf), bufp, client->session_keyblock->length + 8);
+#ifdef HAVE_KRB4
+ }
+#endif /* HAVE_KRB4 */
+#else /* HAVE_KRB5 */
#ifdef HAVE_KRB4
#ifdef NOENCRYPTION
memcpy(cblock, client->session_key, sizeof(C_Block));
-#else
+#else /* NOENCRYPTION */
des_ecb_encrypt(client->session_key, cblock, serv_ksched.s, DES_ENCRYPT);
-#endif
+#endif /* NOENCRYPTION */
retval = ZMakeAscii(buf, sizeof(buf), cblock, sizeof(C_Block));
+#endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB5 */
+
+#if defined(HAVE_KRB4) || defined(HAVE_KRB5)
if (retval != ZERR_NONE) {
#if 0
zdbug((LOG_DEBUG,"zmakeascii failed: %s", error_message(retval)));
@@ -876,7 +908,7 @@ subscr_send_subs(client)
zdbug((LOG_DEBUG, "cblock %s", buf));
#endif
}
-#endif /* HAVE_KRB4 */
+#endif /* HAVE_KRB4 || HAVE_KRB5*/
retval = bdump_send_list_tcp(SERVACK, &client->addr, ZEPHYR_ADMIN_CLASS,
num > 1 ? "CBLOCK" : "", ADMIN_NEWCLT,
client->principal->string, "", list, num);
@@ -1047,7 +1079,7 @@ subscr_realm_sendit(who, subs, notice, realm)
Client *who;
Destlist *subs;
ZNotice_t *notice;
- Realm *realm;
+ ZRealm *realm;
{
ZNotice_t snotice;
char *pack;
@@ -1132,7 +1164,7 @@ subscr_realm_sendit(who, subs, notice, realm)
static Code_t
subscr_add_raw(client, realm, newsubs)
Client *client;
- Realm *realm;
+ ZRealm *realm;
Destlist *newsubs;
{
Destlist *subs, *subs2, *subs3, **head;
@@ -1162,7 +1194,7 @@ subscr_add_raw(client, realm, newsubs)
}
} else {
if (!realm) {
- Realm *remrealm =
+ ZRealm *remrealm =
realm_get_realm_by_name(subs->dest.recip->string + 1);
if (remrealm) {
Destlist *sub = (Destlist *) malloc(sizeof(Destlist));
@@ -1190,7 +1222,7 @@ subscr_add_raw(client, realm, newsubs)
/* Called from bdump_recv_loop to decapsulate realm subs */
Code_t
subscr_realm(realm, notice)
- Realm *realm;
+ ZRealm *realm;
ZNotice_t *notice;
{
Destlist *newsubs;
@@ -1210,7 +1242,7 @@ static void
subscr_unsub_sendit(who, subs, realm)
Client *who;
Destlist *subs;
- Realm *realm;
+ ZRealm *realm;
{
ZNotice_t unotice;
Code_t retval;
@@ -1275,7 +1307,7 @@ subscr_unsub_sendit(who, subs, realm)
/* Called from bump_send_loop by way of realm_send_realms */
Code_t
subscr_send_realm_subs(realm)
- Realm *realm;
+ ZRealm *realm;
{
int i = 0;
Destlist *subs, *next;
@@ -1342,7 +1374,7 @@ subscr_send_realm_subs(realm)
Code_t
subscr_realm_subs(realm)
- Realm *realm;
+ ZRealm *realm;
{
int i = 0;
Destlist *subs, *next;
@@ -1431,7 +1463,7 @@ subscr_check_foreign_subs(notice, who, server, realm, newsubs)
ZNotice_t *notice;
struct sockaddr_in *who;
Server *server;
- Realm *realm;
+ ZRealm *realm;
Destlist *newsubs;
{
Destlist *subs, *subs2, *next;
@@ -1470,7 +1502,7 @@ subscr_check_foreign_subs(notice, who, server, realm, newsubs)
found = 0;
for (subs = newsubs; subs; subs = next) {
- Realm *rlm;
+ ZRealm *rlm;
next=subs->next;
if (subs->dest.recip->string[0] != '\0') {
rlm = realm_which_realm(who);
@@ -1566,7 +1598,7 @@ Code_t subscr_foreign_user(notice, who, server, realm)
ZNotice_t *notice;
struct sockaddr_in *who;
Server *server;
- Realm *realm;
+ ZRealm *realm;
{
Destlist *newsubs, *temp;
Acl *acl;
@@ -1640,7 +1672,7 @@ Code_t subscr_foreign_user(notice, who, server, realm)
temp->dest.recip = make_string(rlm_recipient, 0);
}
- status = subscr_add_raw(client, (Realm *)0, newsubs);
+ status = subscr_add_raw(client, (ZRealm *)0, newsubs);
} else if (!strcmp(snotice.z_opcode, REALM_REQ_SUBSCRIBE)) {
zdbug((LOG_DEBUG, "subscr_foreign_user REQ %s/%s", tp0, tp1));
status = subscr_check_foreign_subs(notice, who, server, realm, newsubs);
diff --git a/server/uloc.c b/server/uloc.c
index 0d7ea8e..66071cf 100644
--- a/server/uloc.c
+++ b/server/uloc.c
@@ -106,7 +106,7 @@ static int ul_equiv __P((Location *l1, Location *l2));
static void free_loc __P((Location *loc));
static void ulogin_locate_forward __P((ZNotice_t *notice,
- struct sockaddr_in *who, Realm *realm));
+ struct sockaddr_in *who, ZRealm *realm));
static Location *locations = NULL; /* ptr to first in array */
static int num_locs = 0; /* number in array */
@@ -241,7 +241,11 @@ ulogin_dispatch(notice, auth, who, server)
login_sendit(notice, auth, who, 1);
}
} else {
- syslog(LOG_ERR, "unknown ulog opcode %s", notice->z_opcode);
+ if (!strcmp(notice->z_opcode, LOGIN_USER_LOGIN))
+ zdbug((LOG_DEBUG, "ulog opcode from unknown foreign realm %s",
+ notice->z_opcode));
+ else
+ syslog(LOG_ERR, "unknown ulog opcode %s", notice->z_opcode);
if (server == me_server)
nack(notice, who);
return ZERR_NONE;
@@ -282,7 +286,7 @@ ulocate_dispatch(notice, auth, who, server)
Server *server;
{
char *cp;
- Realm *realm;
+ ZRealm *realm;
if (!strcmp(notice->z_opcode, LOCATE_LOCATE)) {
/* we are talking to a current-rev client; send an ack */
@@ -294,7 +298,7 @@ ulocate_dispatch(notice, auth, who, server)
ulogin_locate(notice, who, auth);
return ZERR_NONE;
} else {
- syslog(LOG_ERR, "unknown uloc opcode %s", notice->z_opcode);
+ syslog(LOG_ERR, "unknown uloc opcode %s", notice->z_opcode);
if (server == me_server)
nack(notice, who);
return ZERR_NONE;
@@ -441,6 +445,7 @@ uloc_send_locations()
default:
syslog(LOG_ERR,"broken location state %s/%d",
loc->user->string, (int) loc->exposure);
+ exposure_level = EXPOSE_OPSTAFF;
break;
}
retval = bdump_send_list_tcp(ACKED, &loc->addr, LOGIN_CLASS,
@@ -1004,7 +1009,7 @@ static void
ulogin_locate_forward(notice, who, realm)
ZNotice_t *notice;
struct sockaddr_in *who;
- Realm *realm;
+ ZRealm *realm;
{
ZNotice_t lnotice;
@@ -1018,7 +1023,7 @@ void
ulogin_realm_locate(notice, who, realm)
ZNotice_t *notice;
struct sockaddr_in *who;
- Realm *realm;
+ ZRealm *realm;
{
char **answer;
int found;
diff --git a/server/zserver.h b/server/zserver.h
index 221e26b..981a000 100644
--- a/server/zserver.h
+++ b/server/zserver.h
@@ -17,6 +17,9 @@
#include <zephyr/mit-copyright.h>
#include <internal.h>
+
+#include <com_err.h>
+
#include <arpa/inet.h>
#include "zsrv_err.h"
@@ -28,10 +31,19 @@
#include "access.h"
#include "acl.h"
-#ifdef HAVE_KRB4
+#if defined(HAVE_KRB5) || defined(HAVE_KRB4)
/* Kerberos-specific library interfaces used only by the server. */
+#ifdef HAVE_KRB5
+extern krb5_keyblock *__Zephyr_keyblock;
+#define ZGetSession() (__Zephyr_keyblock)
+void ZSetSession(krb5_keyblock *keyblock);
+Code_t ZFormatAuthenticNoticeV5 __P((ZNotice_t*, char*, int, int*, krb5_keyblock *));
+#else
extern C_Block __Zephyr_session;
#define ZGetSession() (__Zephyr_session)
+#endif
+void ZSetSessionDES(C_Block *key);
+
Code_t ZFormatAuthenticNotice __P((ZNotice_t*, char*, int, int*, C_Block));
#endif
@@ -67,9 +79,9 @@ typedef struct {
typedef struct _Destination Destination;
typedef struct _Destlist Destlist;
-typedef struct _Realm Realm;
-typedef struct _Realmname Realmname;
-typedef enum _Realm_state Realm_state;
+typedef struct _ZRealm ZRealm;
+typedef struct _ZRealmname ZRealmname;
+typedef enum _ZRealm_state ZRealm_state;
typedef struct _Client Client;
typedef struct _Triplet Triplet;
typedef enum _Server_state Server_state;
@@ -90,14 +102,14 @@ struct _Destlist {
struct _Destlist *next, **prev_p;
};
-enum _Realm_state {
- REALM_UP, /* Realm is up */
- REALM_TARDY, /* Realm due for a hello XXX */
- REALM_DEAD, /* Realm is considered dead */
- REALM_STARTING /* Realm is between dead and up */
+enum _ZRealm_state {
+ REALM_UP, /* ZRealm is up */
+ REALM_TARDY, /* ZRealm due for a hello XXX */
+ REALM_DEAD, /* ZRealm is considered dead */
+ REALM_STARTING /* ZRealm is between dead and up */
};
-struct _Realm {
+struct _ZRealm {
char name[REALM_SZ];
int count;
struct sockaddr_in *addrs;
@@ -107,10 +119,10 @@ struct _Realm {
Client *client;
int child_pid;
int have_tkt;
- Realm_state state;
+ ZRealm_state state;
};
-struct _Realmname {
+struct _ZRealmname {
char name[REALM_SZ];
char **servers;
int nused;
@@ -120,13 +132,17 @@ struct _Realmname {
struct _Client {
struct sockaddr_in addr; /* ipaddr/port of client */
Destlist *subs ; /* subscriptions */
+#ifdef HAVE_KRB5
+ krb5_keyblock *session_keyblock;
+#else
#ifdef HAVE_KRB4
C_Block session_key; /* session key for this client */
#endif /* HAVE_KRB4 */
+#endif
String *principal; /* krb principal of user */
int last_send; /* Counter for last sent packet. */
time_t last_ack; /* Time of last received ack */
- Realm *realm;
+ ZRealm *realm;
struct _Client *next, **prev_p;
};
@@ -215,9 +231,9 @@ int get_tgt __P((void));
extern String *class_control, *class_admin, *class_hm;
extern String *class_ulogin, *class_ulocate;
int ZDest_eq __P((Destination *d1, Destination *d2));
-Code_t triplet_register __P((Client *client, Destination *dest, Realm *realm));
+Code_t triplet_register __P((Client *client, Destination *dest, ZRealm *realm));
Code_t triplet_deregister __P((Client *client, Destination *dest,
- Realm *realm));
+ ZRealm *realm));
Code_t class_restrict __P((char *class, Acl *acl));
Code_t class_setup_restricted __P((char *class, Acl *acl));
Client **triplet_lookup __P((Destination *dest));
@@ -268,7 +284,7 @@ void sweep_ticket_hash_table __P((void *));
#ifndef NOENCRYPTION
Sched *check_key_sched_cache __P((des_cblock key));
void add_to_key_sched_cache __P((des_cblock key, Sched *sched));
-int krb_set_key __P((char *key, int cvt));
+/*int krb_set_key __P((void *key, int cvt));*/
/* int krb_rd_req __P((KTEXT authent, char *service, char *instance,
unsigned KRB_INT32 from_addr, AUTH_DAT *ad, char *fn)); */
int krb_find_ticket __P((KTEXT authent, KTEXT ticket));
@@ -297,7 +313,7 @@ Code_t server_adispatch __P((ZNotice_t *notice, int auth,
struct sockaddr_in *who, Server *server));
/* found in subscr.c */
-Code_t subscr_foreign_user __P((ZNotice_t *, struct sockaddr_in *, Server *, Realm *));
+Code_t subscr_foreign_user __P((ZNotice_t *, struct sockaddr_in *, Server *, ZRealm *));
Code_t subscr_cancel __P((struct sockaddr_in *sin, ZNotice_t *notice));
Code_t subscr_subscribe __P((Client *who, ZNotice_t *notice, Server *server));
Code_t subscr_send_subs __P((Client *client));
@@ -321,16 +337,16 @@ Code_t uloc_send_locations __P((void));
/* found in realm.c */
int realm_sender_in_realm __P((char *realm, char *sender));
int realm_bound_for_realm __P((char *realm, char *recip));
-Realm *realm_which_realm __P((struct sockaddr_in *who));
-Realm *realm_get_realm_by_name __P((char *name));
-Realm *realm_get_realm_by_pid __P((int));
-void realm_handoff(ZNotice_t *, int, struct sockaddr_in *, Realm *, int);
+ZRealm *realm_which_realm __P((struct sockaddr_in *who));
+ZRealm *realm_get_realm_by_name __P((char *name));
+ZRealm *realm_get_realm_by_pid __P((int));
+void realm_handoff(ZNotice_t *, int, struct sockaddr_in *, ZRealm *, int);
char *realm_expand_realm(char *);
void realm_init __P((void));
-Code_t ZCheckRealmAuthentication __P((ZNotice_t *, struct sockaddr_in *,
+Code_t ZCheckZRealmAuthentication __P((ZNotice_t *, struct sockaddr_in *,
char *));
Code_t realm_control_dispatch __P((ZNotice_t *, int, struct sockaddr_in *,
- Server *, Realm *));
+ Server *, ZRealm *));
void realm_shutdown __P((void));
void realm_deathgram __P((Server *));
@@ -355,6 +371,10 @@ extern int nfds; /* number to look at in select() */
extern int zdebug;
extern char myname[]; /* domain name of this host */
extern char list_file[];
+#ifdef HAVE_KRB5
+extern char keytab_file[];
+extern krb5_ccache Z_krb5_ccache;
+#endif
#ifdef HAVE_KRB4
extern char srvtab_file[];
extern char my_realm[];
@@ -385,7 +405,7 @@ extern int nservers; /* number of other servers*/
extern String *empty;
extern String *wildcard_instance;
-extern Realm *otherrealms;
+extern ZRealm *otherrealms;
extern int nrealms;
extern struct in_addr my_addr; /* my inet address */
diff --git a/server/zsrv_conf.h b/server/zsrv_conf.h
index 7b663da..5508e3a 100644
--- a/server/zsrv_conf.h
+++ b/server/zsrv_conf.h
@@ -18,6 +18,10 @@
#define SERVER_LIST_FILE "server.list"
#define REALM_LIST_FILE "realm.list"
+#ifdef HAVE_KRB5
+#define ZEPHYR_KEYTAB "krb5.keytab"
+#define ZEPHYR_TK5FILE "z5tkts"
+#endif
#ifdef HAVE_KRB4
#define ZEPHYR_SRVTAB "srvtab"
#define ZEPHYR_TKFILE "ztkts"
diff --git a/server/zsrv_err.et b/server/zsrv_err.et
index de48f21..36d6a3f 100644
--- a/server/zsrv_err.et
+++ b/server/zsrv_err.et
@@ -13,7 +13,7 @@ ec ZSRV_NOCLT,
ec ZSRV_NOSUB,
"No such subscription"
ec ZSRV_NOCLASS,
- "Class unkown"
+ "Class unknown"
ec ZSRV_CLASSXISTS,
"Class already registered"
ec ZSRV_CLASSRESTRICTED,
diff --git a/zhm/zhm_client.c b/zhm/zhm_client.c
index 6ee448b..0da6bee 100644
--- a/zhm/zhm_client.c
+++ b/zhm/zhm_client.c
@@ -74,7 +74,7 @@ void transmission_tower(notice, packet, pak_len)
Zperr(ret);
com_err("hm", ret, "setting destination");
}
- if ((ret = send_outgoing(notice)) != ZERR_NONE) {
+ if ((ret = ZSendPacket(packet, pak_len, 0)) != ZERR_NONE) {
Zperr(ret);
com_err("hm", ret, "while sending raw notice");
}