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)