File screen-4.1.0-krb5.patch of Package screen-rhel

diff -urN screen-4.1.0/src/config.h.in screen-4.1.0-krb5/src/config.h.in
--- screen-4.1.0/src/config.h.in	2012-03-07 12:09:23.000000000 +0100
+++ screen-4.1.0-krb5/src/config.h.in	2019-02-03 22:15:11.289849143 +0100
@@ -723,3 +723,9 @@
 
 /* Define to 1 if you need to in order for `stat' and other things to work. */
 #undef _POSIX_SOURCE
+
+/*
+ * define HAVE_KRB5 if your system supports MIT Kerberos 5 or
+ * equivalent.
+ */
+#undef HAVE_KRB5
diff -urN screen-4.1.0/src/configure.in screen-4.1.0-krb5/src/configure.in
--- screen-4.1.0/src/configure.in	2019-02-03 21:48:06.804102399 +0100
+++ screen-4.1.0-krb5/src/configure.in	2019-02-03 22:26:47.915319541 +0100
@@ -877,6 +877,17 @@
   LIBS="$LIBS -lutempter"
 fi
 
+dnl    **** Kerberos ****
+AC_ARG_WITH(krb5, [  --with-krb5[=dir]         Use Kerberos 5 (optionally installed in dir)])
+if test "$with_krb5" != no -a -n "$with_krb5"; then
+	if test "$with_krb5" != yes; then
+		CFLAGS="$CFLAGS -I${with_krb5}/include"
+		LDFLAGS="$LDFLAGS -L${with_krb5}/lib"
+	fi
+	LIBS="$LIBS -lkrb5"
+	AC_DEFINE([HAVE_KRB5], 1, [Define to enable Kerberos features.])
+fi
+
 dnl
 dnl    ****  loadav  ****
 dnl
diff -urN screen-4.1.0/src/kerberos.c screen-4.1.0-krb5/src/kerberos.c
--- screen-4.1.0/src/kerberos.c	1970-01-01 01:00:00.000000000 +0100
+++ screen-4.1.0-krb5/src/kerberos.c	2019-02-03 22:00:24.583095583 +0100
@@ -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 HAVE_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 screen-4.1.0/src/Makefile.in screen-4.1.0-krb5/src/Makefile.in
--- screen-4.1.0/src/Makefile.in	2012-03-07 12:05:35.000000000 +0100
+++ screen-4.1.0-krb5/src/Makefile.in	2019-02-03 22:07:50.659253513 +0100
@@ -65,12 +65,12 @@
 	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 \
+	list_generic.o list_display.o list_window.o kerberos.o \
 	sched.o teln.o nethack.o encoding.o canvas.o layout.o viewport.o
 
 all:	screen
@@ -353,4 +353,6 @@
 list_generic.o: list_generic.h list_generic.c layer.h
 list_display.o: list_generic.h list_display.c layer.h
 list_window.o: list_generic.h list_window.c window.h layer.h
+kerberos.o: 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-4.1.0/src/screen.c screen-4.1.0-krb5/src/screen.c
--- screen-4.1.0/src/screen.c	2019-02-03 21:58:17.680425122 +0100
+++ screen-4.1.0-krb5/src/screen.c	2019-02-03 22:00:24.587095662 +0100
@@ -1413,6 +1413,10 @@
 #endif
   FinishRc(RcFileName);
 
+#ifdef HAVE_KRB5
+  krb_init();
+#endif
+
   debug2("UID %d  EUID %d\n", (int)getuid(), (int)geteuid());
   if (windows == NULL)
     {
@@ -1822,6 +1826,9 @@
       xsetegid(eff_gid);
 #endif
     }
+#ifdef HAVE_KRB5
+  krb_cleanup();
+#endif
   for (display = displays; display; display = display->d_next)
     {
       if (D_status)
openSUSE Build Service is sponsored by