File krb5.diff of Package screen
diff -urN ./config.h.in ./config.h.in
--- ./config.h.in 2012-06-11 17:54:33.000000000 +0200
+++ ./config.h.in 2013-04-19 11:49:16.000000000 +0200
@@ -283,6 +283,12 @@
* (You may also need to add -lpam to LIBS in the Makefile.)
*/
#undef USE_PAM
+
+/*
+ * Define USE_KRB5 if your system uses Kerberos tickets and you want
+ * screen to use a private ticket cache and automatically renew it.
+ */
+#undef USE_KRB5
/*
* Define CHECK_SCREEN_W if you want screen to set TERM to screen-w
diff -urN ./configure.in ./configure.in
--- ./configure.in 2014-04-26 12:58:35.000000000 +0200
+++ ./configure.in 2014-08-29 16:42:09.000000000 +0200
@@ -1287,6 +1287,18 @@
if test "$enable_rxvt_osc" = "yes"; then
AC_DEFINE(RXVT_OSC)
fi
+AC_ARG_ENABLE(krb5, [ --enable-krb5 enable Kerberos 5 support])
+if test "$enable_krb5" = "yes"; then
+ AC_MSG_CHECKING(for Kerberos support)
+ oldlibs="$LIBS"
+ LIBS="$LIBS -lkrb5"
+ AC_TRY_LINK([#include <krb5.h>], [
+ krb5_context context;
+ krb5_init_context(&context);
+ krb5_free_context(context)
+ ], AC_MSG_RESULT(yes);AC_DEFINE(USE_KRB5, 1, [Enable Kerberos 5 support]),
+ AC_MSG_RESULT(no);LIBS="$oldlibs")
+fi
dnl
dnl **** the end ****
diff -urN ./kerberos.c ./kerberos.c
--- ./kerberos.c 1970-01-01 01:00:00.000000000 +0100
+++ ./kerberos.c 2013-04-19 11:49:16.000000000 +0200
@@ -0,0 +1,207 @@
+/* Copyright (c) 2005
+ * Fredrik Tolf (fredrik@dolda2000.com)
+ * Copyright (c) 2013
+ * Robbert Eggermont (R.Eggermont@tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING); if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ ****************************************************************
+ */
+
+#include "config.h"
+#ifdef USE_KRB5
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <krb5.h>
+
+#include "screen.h"
+#include "extern.h"
+
+#define KRB5_OK 0
+#define SAFETY_MARGIN 5
+#define MIN_TIMEOUT (60 * 60)
+
+static int krb_enabled = 0;
+static struct event krb_ev;
+static char krb5ccname[40];
+static void krb_renew(struct event *, char *);
+
+void
+krb_error(krb5_context const context, krb5_error_code const error_code, char const *const custom_msg)
+{
+ char const *const error_msg = krb5_get_error_message(context, error_code);
+ Msg(0, "%s: %s", custom_msg, error_msg);
+ krb5_free_error_message(context, error_msg);
+ return;
+}
+
+void
+krb_init()
+{
+ krb5_error_code retval = 0;
+ krb5_context context;
+ krb5_ccache origcache = NULL;
+ krb5_ccache ccache = NULL;
+ krb5_principal principal = NULL;
+ krb5_creds creds;
+ char *const ccname = krb5ccname + 5; /* Filename without leading "FILE:" */
+ int krb5cc = -1;
+ time_t timeout = MIN_TIMEOUT; /* Retry timeout in case of an error */
+
+ /* Create Kerberos context */
+ retval = krb5_init_context(&context);
+ if (retval == KRB5_OK) {
+ /* Create our own unique credentials cache */
+ snprintf(krb5ccname, sizeof(krb5ccname), "FILE:/tmp/krb5cc_%u_XXXXXX", (unsigned int) getuid());
+ krb5cc = mkstemp(ccname); /* krb5_cc_new_unique is unusable: /tmp/tktXXXXXX */
+ if (krb5cc != -1) {
+ close(krb5cc);
+
+ /*
+ * We have Kerberos and our own credentials cache. From this point on,
+ * failures don't have to be permanent (the credentials cache can be
+ * manipulated from the outside), so we enable the Kerberos renewal.
+ */
+ krb_enabled = 1;
+
+ /* Copy Kerberos credentials from the original ticket cache */
+ retval = krb5_cc_default(context, &origcache);
+ if (retval == KRB5_OK) {
+ retval = krb5_cc_get_principal(context, origcache, &principal);
+ if (retval == KRB5_OK) {
+ retval = krb5_get_renewed_creds(context, &creds, principal, origcache, NULL);
+ if (retval == KRB5_OK) {
+ retval = krb5_cc_resolve(context, krb5ccname, &ccache);
+ if (retval == KRB5_OK) {
+ retval = krb5_cc_initialize(context, ccache, principal);
+ if (retval == KRB5_OK) {
+ retval = krb5_cc_store_cred(context, ccache, &creds);
+ if (retval == KRB5_OK) {
+ Msg(0, "Renewed Kerberos credentials successfully.");
+ timeout = (time_t)creds.times.endtime - time(NULL) - 2 * MIN_TIMEOUT - SAFETY_MARGIN; /* Set timeout to 2 MIN_TIMEOUT intervals (plus a small SAFETY_MARGIN) before the credentials expire, so in case the next renewal fails we can do 2 retries before the credentials really expire. */
+ if (timeout < MIN_TIMEOUT) timeout = MIN_TIMEOUT; /* Credentials (almost) expired; no point to retry so fast. */
+ } else { /* krb5_cc_store_cred */
+ krb_error(context, retval, "Could not store new credentials");
+ krb5_cc_destroy(context, ccache); /* Cache file in unknown state */
+ }
+ } else krb_error(context, retval, "Could not initialize new credentials cache"); /* krb5_cc_initialize */
+ krb5_cc_close(context, ccache); /* Clean up krb5_cc_resolve */
+ } else krb_error(context, retval, "Could not resolve new credentials cache"); /* krb5_cc_resolve */
+ krb5_free_cred_contents(context, &creds); /* Clean up krb5_get_renewed_credentials */
+ } else krb_error(context, retval, "Could not renew credentials"); /* krb5_get_renewed_credentials */
+ krb5_free_principal(context, principal); /* Clean up krb5_cc_get_principal */
+ } else krb_error(context, retval, "Could not get Kerberos principal from credentials cache"); /* krb5_cc_get_principal */
+ krb5_cc_close(context, origcache); /* Clean up krb5_cc_default */
+ } else krb_error(context, retval, "Could not get Kerberos credentials cache"); /* krb5_cc_default */
+
+ /* Pass the Kerberos credentials cache name to the child processess */
+ xsetenv("KRB5CCNAME", krb5ccname);
+ MakeNewEnv();
+
+ /* Start Kerberos ticket renewal timer */
+ memset(&krb_ev, 0, sizeof(krb_ev));
+ krb_ev.type = EV_TIMEOUT;
+ krb_ev.handler = krb_renew;
+ SetTimeout(&krb_ev, timeout * 1000); /* Milliseconds */
+ evenq(&krb_ev);
+
+ } else Msg(errno, "Could not create Kerberos credentials cache file %s.", ccname); /* mkstemp */
+ krb5_free_context(context); /* Clean up krb5_init_context */
+ } else krb_error(context, retval, "Could not initialize Kerberos library"); /* krb5_init_context */
+
+ return;
+}
+
+static void
+krb_renew(ev, data)
+struct event *ev;
+char *data;
+{
+ krb5_error_code retval = 0;
+ krb5_context context;
+ krb5_ccache ccache;
+ krb5_principal principal;
+ krb5_creds creds;
+ time_t timeout = MIN_TIMEOUT; /* Retry timeout in case of an error */
+
+ /* Renew credentials */
+ retval = krb5_init_context(&context);
+ if (retval == KRB5_OK) {
+ retval = krb5_cc_resolve(context, krb5ccname, &ccache);
+ if (retval == KRB5_OK) {
+ retval = krb5_cc_get_principal(context, ccache, &principal);
+ if (retval == KRB5_OK) {
+ retval = krb5_get_renewed_creds(context, &creds, principal, ccache, NULL);
+ if (retval == KRB5_OK) {
+ retval = krb5_cc_initialize(context, ccache, principal);
+ if (retval == KRB5_OK) {
+ retval = krb5_cc_store_cred(context, ccache, &creds);
+ if (retval == KRB5_OK) {
+ Msg(0, "Renewed Kerberos credentials successfully.");
+ timeout = (time_t)creds.times.endtime - time(NULL) - 2 * MIN_TIMEOUT - SAFETY_MARGIN; /* Set timeout to 2 MIN_TIMEOUT intervals (plus a small SAFETY_MARGIN) before the credentials expire, so in case the next renewal fails we can do 2 retries before the credentials really expire. */
+ if (timeout < MIN_TIMEOUT) timeout = MIN_TIMEOUT; /* Credentials (almost) expired; no point to retry so fast. */
+ } else { /* krb5_cc_store_cred */
+ krb_error(context, retval, "Could not store new credentials");
+ krb5_cc_destroy(context, ccache); /* Cache file in unknown state */
+ }
+ } else krb_error(context, retval, "Could not initialize new credentials cache"); /* krb5_cc_initialize */
+ krb5_free_cred_contents(context, &creds); /* Clean up krb5_get_renewed_credentials */
+ } else krb_error(context, retval, "Could not renew credentials"); /* krb5_get_renewed_credentials */
+ krb5_free_principal(context, principal); /* Clean up krb5_cc_get_principal */
+ } else krb_error(context, retval, "Could not get Kerberos principal from credentials cache"); /* krb5_cc_get_principal */
+ krb5_cc_close(context, ccache); /* Clean up krb5_cc_default */
+ } else krb_error(context, retval, "Could not get Kerberos credentials cache"); /* krb5_cc_default */
+ krb5_free_context(context); /* Clean up krb5_init_context */
+ } else krb_error(context, retval, "Could not initialize Kerberos library"); /* krb5_init_context */
+
+ /* Re-enqueue */
+ SetTimeout(ev, timeout * 1000); /* Milliseconds */
+ evenq(ev);
+
+ return;
+}
+
+void
+krb_cleanup()
+{
+ krb5_error_code retval = 0;
+ krb5_context context;
+ krb5_ccache ccache;
+
+ if (krb_enabled) {
+ retval = krb5_init_context(&context);
+ if (retval == KRB5_OK) {
+ retval = krb5_cc_resolve(context, krb5ccname, &ccache);
+ if (retval == KRB5_OK) {
+ retval = krb5_cc_destroy(context, ccache);
+ if (retval == KRB5_OK) {
+ Msg(0, "Kerberos credentials cache destroyed.");
+ } else krb_error(context, retval, "Could not destroy Kerberos credentials cache"); /* krb5_cc_destroy */
+ } else krb_error(context, retval, "Could not get Kerberos credentials cache"); /* krb5_cc_default */
+ krb5_free_context(context); /* Clean up krb5_init_context */
+ } else krb_error(context, retval, "Could not initialize Kerberos library"); /* krb5_init_context */
+ }
+
+ return;
+}
+
+#endif
diff -urN ./Makefile.in ./Makefile.in
--- ./Makefile.in 2012-06-11 17:54:33.000000000 +0200
+++ ./Makefile.in 2013-04-19 12:08:24.000000000 +0200
@@ -65,13 +65,13 @@
termcap.c input.c attacher.c pty.c process.c display.c comm.c \
kmapdef.c acls.c braille.c braille_tsi.c logfile.c layer.c \
sched.c teln.c nethack.c encoding.c canvas.c layout.c viewport.c \
- list_display.c list_generic.c list_window.c
+ list_display.c list_generic.c list_window.c kerberos.c
OFILES= screen.o ansi.o fileio.o mark.o misc.o resize.o socket.o \
search.o tty.o term.o window.o utmp.o loadav.o putenv.o help.o \
termcap.o input.o attacher.o pty.o process.o display.o comm.o \
kmapdef.o acls.o braille.o braille_tsi.o logfile.o layer.o \
list_generic.o list_display.o list_window.o \
- sched.o teln.o nethack.o encoding.o canvas.o layout.o viewport.o
+ sched.o teln.o nethack.o encoding.o canvas.o layout.o viewport.o kerberos.o
all: screen
@@ -353,4 +353,6 @@
list_generic.o: list_generic.h list_generic.c layer.h screen.h osdef.h
list_display.o: list_generic.h list_display.c layer.h screen.h osdef.h
list_window.o: list_generic.h list_window.c window.h layer.h screen.h osdef.h
+kerberos.o: layout.h viewport.h canvas.h kerberos.c config.h screen.h os.h osdef.h ansi.h sched.h acls.h \
+ comm.h layer.h term.h image.h display.h window.h extern.h
diff -urN ./screen.c ./screen.c
--- ./screen.c 2012-06-08 17:20:18.000000000 +0200
+++ ./screen.c 2013-04-19 11:49:16.000000000 +0200
@@ -1424,6 +1424,10 @@
#endif
FinishRc(RcFileName);
+#ifdef USE_KRB5
+ krb_init();
+#endif
+
debug2("UID %d EUID %d\n", (int)getuid(), (int)geteuid());
if (windows == NULL)
{
@@ -1833,6 +1837,9 @@
xsetegid(eff_gid);
#endif
}
+#ifdef USE_KRB5
+ krb_cleanup();
+#endif
for (display = displays; display; display = display->d_next)
{
if (D_status)