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)
openSUSE Build Service is sponsored by