]> git.ipfire.org Git - ipfire-3.x.git/commitdiff
openssh: Update to 5.8p1.
authorStefan Schantl <stefan.schantl@ipfire.org>
Sun, 27 Feb 2011 15:57:04 +0000 (16:57 +0100)
committerStefan Schantl <stefan.schantl@ipfire.org>
Sun, 27 Feb 2011 15:57:04 +0000 (16:57 +0100)
* Aktivate selinux support.
* Aktivate audit support.
* Add a bunch of patches to fix errors and provide new features.

Fixes #130.

17 files changed:
pkgs/core/openssh/openssh.nm
pkgs/core/openssh/patches/openssh-4.3p2-askpass-grab-info.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.1p1-askpass-progress.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.1p1-scp-manpage.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.2p1-allow-ip-opts.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.2p1-edns.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.5p1-x11.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.6p1-exit-deadlock.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.6p1-keygen.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.6p1-redhat.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.8p1-authorized-keys-command.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.8p1-fingerprint.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.8p1-kuserok.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.8p1-mls.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.8p1-randclean.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.8p1-selinux-role.patch [new file with mode: 0644]
pkgs/core/openssh/patches/openssh-5.8p1-selinux.patch [new file with mode: 0644]

index 046d96184bf0a9a42f85c3858f1735924a8fd7d4..9ba7dc5f14483d42920640d37e4634fd1678d29f 100644 (file)
@@ -25,8 +25,8 @@
 include $(PKGROOT)/Include
 
 PKG_NAME       = openssh
-PKG_VER        = 5.4p1
-PKG_REL        = 2
+PKG_VER        = 5.8p1
+PKG_REL        = 3
 
 PKG_MAINTAINER =
 PKG_GROUP      = Application/Internet
@@ -34,7 +34,8 @@ PKG_URL        = http://www.openssh.com/portable.html
 PKG_LICENSE    = MIT
 PKG_SUMMARY    = An open source implementation of SSH protocol versions 1 and 2.
 
-PKG_BUILD_DEPS+= libselinux-devel openssl-devel pam-devel zlib-devel
+PKG_BUILD_DEPS+= audit-devel libselinux-devel nss-devel openssl-devel pam-devel \
+       zlib-devel
 PKG_DEPS-openssh = openssh-clients=$(THISVER) openssh-server=$(THISVER)
 
 define PKG_DESCRIPTION
@@ -71,6 +72,24 @@ PKG_FILES-openssh-clients       = \
        /usr/bin/ \
        /usr/lib/ \
        /usr/share/
+
+# Apply patches in a special order
+PKG_PATCHES   = openssh-5.6p1-redhat.patch
+PKG_PATCHES   += openssh-5.8p1-fingerprint.patch
+PKG_PATCHES   += openssh-5.8p1-authorized-keys-command.patch
+PKG_PATCHES   += openssh-5.8p1-selinux.patch
+PKG_PATCHES   += openssh-5.8p1-selinux-role.patch
+PKG_PATCHES   += openssh-5.8p1-mls.patch
+PKG_PATCHES   += openssh-5.6p1-keygen.patch
+PKG_PATCHES   += openssh-5.2p1-allow-ip-opts.patch
+PKG_PATCHES   += openssh-5.8p1-randclean.patch
+PKG_PATCHES   += openssh-5.8p1-kuserok.patch
+PKG_PATCHES   += openssh-5.5p1-x11.patch
+PKG_PATCHES   += openssh-5.6p1-exit-deadlock.patch
+PKG_PATCHES   += openssh-5.1p1-askpass-progress.patch
+PKG_PATCHES   += openssh-4.3p2-askpass-grab-info.patch
+PKG_PATCHES   += openssh-5.2p1-edns.patch
+PKG_PATCHES   += openssh-5.1p1-scp-manpage.patch
        
 CONFIGURE_OPTIONS += \
        --sysconfdir=/etc/ssh \
@@ -79,7 +98,9 @@ CONFIGURE_OPTIONS += \
        --with-md5-passwords \
        --with-privsep-path=/var/lib/sshd \
        --with-pam \
-       --with-selinux
+       --with-selinux \
+       --with-nss \
+       --with-audit=linux
 
 define STAGE_INSTALL_CMDS
        -mkdir -pv $(BUILDROOT)/etc/ssh
diff --git a/pkgs/core/openssh/patches/openssh-4.3p2-askpass-grab-info.patch b/pkgs/core/openssh/patches/openssh-4.3p2-askpass-grab-info.patch
new file mode 100644 (file)
index 0000000..e9dc835
--- /dev/null
@@ -0,0 +1,18 @@
+--- openssh-4.3p2/contrib/gnome-ssh-askpass2.c.grab-info       2006-07-17 15:10:11.000000000 +0200
++++ openssh-4.3p2/contrib/gnome-ssh-askpass2.c 2006-07-17 15:25:04.000000000 +0200
+@@ -65,9 +65,12 @@
+       err = gtk_message_dialog_new(NULL, 0,
+                                    GTK_MESSAGE_ERROR,
+                                    GTK_BUTTONS_CLOSE,
+-                                   "Could not grab %s. "
+-                                   "A malicious client may be eavesdropping "
+-                                   "on your session.", what);
++                                   "SSH password dialog could not grab the %s input.\n"
++                                   "This might be caused by application such as screensaver, "
++                                   "however it could also mean that someone may be eavesdropping "
++                                   "on your session.\n"
++                                   "Either close the application which grabs the %s or "
++                                   "log out and log in again to prevent this from happening.", what, what);
+       gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER);
+       gtk_label_set_line_wrap(GTK_LABEL((GTK_MESSAGE_DIALOG(err))->label),
+                               TRUE);
diff --git a/pkgs/core/openssh/patches/openssh-5.1p1-askpass-progress.patch b/pkgs/core/openssh/patches/openssh-5.1p1-askpass-progress.patch
new file mode 100644 (file)
index 0000000..ec93b87
--- /dev/null
@@ -0,0 +1,79 @@
+diff -up openssh-5.1p1/contrib/gnome-ssh-askpass2.c.progress openssh-5.1p1/contrib/gnome-ssh-askpass2.c
+--- openssh-5.1p1/contrib/gnome-ssh-askpass2.c.progress        2008-07-23 19:05:26.000000000 +0200
++++ openssh-5.1p1/contrib/gnome-ssh-askpass2.c 2008-07-23 19:05:26.000000000 +0200
+@@ -53,6 +53,7 @@
+ #include <string.h>
+ #include <unistd.h>
+ #include <X11/Xlib.h>
++#include <glib.h>
+ #include <gtk/gtk.h>
+ #include <gdk/gdkx.h>
+@@ -83,13 +84,24 @@ ok_dialog(GtkWidget *entry, gpointer dia
+       gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
+ }
++static void
++move_progress(GtkWidget *entry, gpointer progress)
++{
++      gdouble step;
++      g_return_if_fail(GTK_IS_PROGRESS_BAR(progress));
++      
++      step = g_random_double_range(0.03, 0.1);
++      gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progress), step);
++      gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress));
++}
++
+ static int
+ passphrase_dialog(char *message)
+ {
+       const char *failed;
+       char *passphrase, *local;
+       int result, grab_tries, grab_server, grab_pointer;
+-      GtkWidget *dialog, *entry;
++      GtkWidget *dialog, *entry, *progress, *hbox;
+       GdkGrabStatus status;
+       grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL);
+@@ -102,13 +114,31 @@ passphrase_dialog(char *message)
+                                       "%s",
+                                       message);
++      hbox = gtk_hbox_new(FALSE, 0);
++      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE,
++          FALSE, 0);
++      gtk_widget_show(hbox);
++
+       entry = gtk_entry_new();
+-      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), entry, FALSE,
++      gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE,
+           FALSE, 0);
++      gtk_entry_set_width_chars(GTK_ENTRY(entry), 2);
+       gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
+       gtk_widget_grab_focus(entry);
+       gtk_widget_show(entry);
++      hbox = gtk_hbox_new(FALSE, 0);
++      gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE,
++          FALSE, 8);
++      gtk_widget_show(hbox);
++
++      progress = gtk_progress_bar_new();
++      
++      gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), "Passphrase length hidden intentionally");
++      gtk_box_pack_start(GTK_BOX(hbox), progress, TRUE,
++          TRUE, 5);
++      gtk_widget_show(progress);
++
+       gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH");
+       gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
+       gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
+@@ -119,6 +149,8 @@ passphrase_dialog(char *message)
+       gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
+       g_signal_connect(G_OBJECT(entry), "activate",
+                        G_CALLBACK(ok_dialog), dialog);
++      g_signal_connect(G_OBJECT(entry), "changed",
++                       G_CALLBACK(move_progress), progress);
+       gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
diff --git a/pkgs/core/openssh/patches/openssh-5.1p1-scp-manpage.patch b/pkgs/core/openssh/patches/openssh-5.1p1-scp-manpage.patch
new file mode 100644 (file)
index 0000000..e314a05
--- /dev/null
@@ -0,0 +1,18 @@
+diff -up openssh-5.1p1/scp.1.manpage openssh-5.1p1/scp.1
+--- openssh-5.1p1/scp.1.manpage        2008-07-12 09:12:49.000000000 +0200
++++ openssh-5.1p1/scp.1        2008-07-23 19:18:15.000000000 +0200
+@@ -66,6 +66,14 @@ treating file names containing
+ as host specifiers.
+ Copies between two remote hosts are also permitted.
+ .Pp
++When copying a source file to a target file which already exists,
++.Nm 
++will replace the contents of the target file (keeping the inode).
++.Pp
++If the target file does not yet exist, an empty file with the target
++file name is created, then filled with the source file contents.
++No attempt is made at "near-atomic" transfer using temporary files.
++.Pp
+ The options are as follows:
+ .Bl -tag -width Ds
+ .It Fl 1
diff --git a/pkgs/core/openssh/patches/openssh-5.2p1-allow-ip-opts.patch b/pkgs/core/openssh/patches/openssh-5.2p1-allow-ip-opts.patch
new file mode 100644 (file)
index 0000000..96aaab1
--- /dev/null
@@ -0,0 +1,37 @@
+diff -up openssh-5.2p1/canohost.c.ip-opts openssh-5.2p1/canohost.c
+--- openssh-5.2p1/canohost.c.ip-opts   2009-02-14 06:28:21.000000000 +0100
++++ openssh-5.2p1/canohost.c   2009-09-01 15:31:29.000000000 +0200
+@@ -169,12 +169,27 @@ check_ip_options(int sock, char *ipaddr)
+       option_size = sizeof(options);
+       if (getsockopt(sock, ipproto, IP_OPTIONS, options,
+           &option_size) >= 0 && option_size != 0) {
+-              text[0] = '\0';
+-              for (i = 0; i < option_size; i++)
+-                      snprintf(text + i*3, sizeof(text) - i*3,
+-                          " %2.2x", options[i]);
+-              fatal("Connection from %.100s with IP options:%.800s",
+-                  ipaddr, text);
++              i = 0;
++              do {
++                      switch (options[i]) {
++                              case 0:
++                              case 1:
++                                      ++i;
++                                      break;
++                              case 131:
++                              case 137:
++                              /* Fail, fatally, if we detect either loose or strict
++                               * source routing options. */
++                                      text[0] = '\0';
++                                      for (i = 0; i < option_size; i++)
++                                              snprintf(text + i*3, sizeof(text) - i*3,
++                                                      " %2.2x", options[i]);
++                                      fatal("Connection from %.100s with IP options:%.800s",
++                                              ipaddr, text);
++                              default:
++                                      i += options[i + 1];
++                      }
++              } while (i < option_size);
+       }
+ #endif /* IP_OPTIONS */
+ }
diff --git a/pkgs/core/openssh/patches/openssh-5.2p1-edns.patch b/pkgs/core/openssh/patches/openssh-5.2p1-edns.patch
new file mode 100644 (file)
index 0000000..f3e431e
--- /dev/null
@@ -0,0 +1,72 @@
+diff -up openssh-5.2p1/dns.c.rh205842 openssh-5.2p1/dns.c
+--- openssh-5.2p1/dns.c.rh205842       2009-07-27 16:25:28.000000000 +0200
++++ openssh-5.2p1/dns.c        2009-07-27 16:40:59.000000000 +0200
+@@ -176,6 +176,7 @@ verify_host_key_dns(const char *hostname
+ {
+       u_int counter;
+       int result;
++      unsigned int rrset_flags = 0;
+       struct rrsetinfo *fingerprints = NULL;
+       u_int8_t hostkey_algorithm;
+@@ -199,8 +200,19 @@ verify_host_key_dns(const char *hostname
+               return -1;
+       }
++      /*
++       * Original getrrsetbyname function, found on OpenBSD for example,
++       * doesn't accept any flag and prerequisite for obtaining AD bit in
++       * DNS response is set by "options edns0" in resolv.conf.
++       *
++       * Our version is more clever and use RRSET_FORCE_EDNS0 flag.
++       */
++#ifndef HAVE_GETRRSETBYNAME
++      rrset_flags |= RRSET_FORCE_EDNS0;
++#endif
+       result = getrrsetbyname(hostname, DNS_RDATACLASS_IN,
+-          DNS_RDATATYPE_SSHFP, 0, &fingerprints);
++          DNS_RDATATYPE_SSHFP, rrset_flags, &fingerprints);
++
+       if (result) {
+               verbose("DNS lookup error: %s", dns_result_totext(result));
+               return -1;
+diff -up openssh-5.2p1/openbsd-compat/getrrsetbyname.c.rh205842 openssh-5.2p1/openbsd-compat/getrrsetbyname.c
+--- openssh-5.2p1/openbsd-compat/getrrsetbyname.c.rh205842     2009-07-27 16:22:23.000000000 +0200
++++ openssh-5.2p1/openbsd-compat/getrrsetbyname.c      2009-07-27 16:41:55.000000000 +0200
+@@ -209,8 +209,8 @@ getrrsetbyname(const char *hostname, uns
+               goto fail;
+       }
+-      /* don't allow flags yet, unimplemented */
+-      if (flags) {
++      /* Allow RRSET_FORCE_EDNS0 flag only. */
++      if ((flags & !RRSET_FORCE_EDNS0) != 0) {
+               result = ERRSET_INVAL;
+               goto fail;
+       }
+@@ -226,9 +226,9 @@ getrrsetbyname(const char *hostname, uns
+ #endif /* DEBUG */
+ #ifdef RES_USE_DNSSEC
+-      /* turn on DNSSEC if EDNS0 is configured */
+-      if (_resp->options & RES_USE_EDNS0)
+-              _resp->options |= RES_USE_DNSSEC;
++      /* turn on DNSSEC if required  */
++      if (flags & RRSET_FORCE_EDNS0)
++              _resp->options |= (RES_USE_EDNS0|RES_USE_DNSSEC);
+ #endif /* RES_USE_DNSEC */
+       /* make query */
+diff -up openssh-5.2p1/openbsd-compat/getrrsetbyname.h.rh205842 openssh-5.2p1/openbsd-compat/getrrsetbyname.h
+--- openssh-5.2p1/openbsd-compat/getrrsetbyname.h.rh205842     2009-07-27 16:35:02.000000000 +0200
++++ openssh-5.2p1/openbsd-compat/getrrsetbyname.h      2009-07-27 16:36:09.000000000 +0200
+@@ -72,6 +72,9 @@
+ #ifndef RRSET_VALIDATED
+ # define RRSET_VALIDATED      1
+ #endif
++#ifndef RRSET_FORCE_EDNS0
++# define RRSET_FORCE_EDNS0    0x0001
++#endif
+ /*
+  * Return codes for getrrsetbyname()
diff --git a/pkgs/core/openssh/patches/openssh-5.5p1-x11.patch b/pkgs/core/openssh/patches/openssh-5.5p1-x11.patch
new file mode 100644 (file)
index 0000000..cac5d5e
--- /dev/null
@@ -0,0 +1,54 @@
+diff -up openssh-5.3p1/channels.c.bz595935 openssh-5.3p1/channels.c
+--- openssh-5.3p1/channels.c.bz595935  2010-08-12 14:19:28.000000000 +0200
++++ openssh-5.3p1/channels.c   2010-08-12 14:33:51.000000000 +0200
+@@ -3185,7 +3185,7 @@ x11_create_display_inet(int x11_display_
+ }
+ static int
+-connect_local_xsocket_path(const char *pathname)
++connect_local_xsocket_path(const char *pathname, int len)
+ {
+       int sock;
+       struct sockaddr_un addr;
+@@ -3195,11 +3195,14 @@ connect_local_xsocket_path(const char *p
+               error("socket: %.100s", strerror(errno));
+       memset(&addr, 0, sizeof(addr));
+       addr.sun_family = AF_UNIX;
+-      strlcpy(addr.sun_path, pathname, sizeof addr.sun_path);
+-      if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0)
++      if (len <= 0)
++              return -1;
++      if (len > sizeof addr.sun_path)
++              len = sizeof addr.sun_path;
++      memcpy(addr.sun_path, pathname, len);
++      if (connect(sock, (struct sockaddr *)&addr, sizeof addr - (sizeof addr.sun_path - len) ) == 0)
+               return sock;
+       close(sock);
+-      error("connect %.100s: %.100s", addr.sun_path, strerror(errno));
+       return -1;
+ }
+@@ -3207,8 +3210,21 @@ static int
+ connect_local_xsocket(u_int dnr)
+ {
+       char buf[1024];
+-      snprintf(buf, sizeof buf, _PATH_UNIX_X, dnr);
+-      return connect_local_xsocket_path(buf);
++      int len;
++#ifdef linux
++      int ret;
++#endif
++      len = snprintf(buf + 1, sizeof (buf) - 1, _PATH_UNIX_X, dnr);
++#ifdef linux
++      /* try abstract socket first */
++      buf[0] = '\0';
++      if ((ret = connect_local_xsocket_path(buf, len + 1)) >= 0)
++              return ret;
++#endif
++      if ((ret = connect_local_xsocket_path(buf + 1, len)) >= 0)
++              return ret;
++      error("connect %.100s: %.100s", buf + 1, strerror(errno));
++      return -1;
+ }
+ int
diff --git a/pkgs/core/openssh/patches/openssh-5.6p1-exit-deadlock.patch b/pkgs/core/openssh/patches/openssh-5.6p1-exit-deadlock.patch
new file mode 100644 (file)
index 0000000..278dfa1
--- /dev/null
@@ -0,0 +1,14 @@
+diff -up openssh-5.6p1/channels.c.exit-deadlock openssh-5.6p1/channels.c
+--- openssh-5.6p1/channels.c.exit-deadlock     2010-08-05 15:09:48.000000000 +0200
++++ openssh-5.6p1/channels.c   2010-08-23 12:41:43.000000000 +0200
+@@ -1647,6 +1647,10 @@ channel_handle_wfd(Channel *c, fd_set *r
+       u_int dlen, olen = 0;
+       int len;
++      if(c->wfd != -1 && buffer_len(&c->output) > 0 && c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
++              debug("channel %d: forcing write", c->self);
++              FD_SET(c->wfd, writeset);
++      }
+       /* Send buffered output data to the socket. */
+       if (c->wfd != -1 &&
+           FD_ISSET(c->wfd, writeset) &&
diff --git a/pkgs/core/openssh/patches/openssh-5.6p1-keygen.patch b/pkgs/core/openssh/patches/openssh-5.6p1-keygen.patch
new file mode 100644 (file)
index 0000000..9d7fce2
--- /dev/null
@@ -0,0 +1,80 @@
+diff -up openssh-5.6p1/ssh-keygen.0.keygen openssh-5.6p1/ssh-keygen.0
+--- openssh-5.6p1/ssh-keygen.0.keygen  2010-08-22 16:30:03.000000000 +0200
++++ openssh-5.6p1/ssh-keygen.0 2010-08-23 12:37:19.000000000 +0200
+@@ -4,7 +4,7 @@ NAME
+      ssh-keygen - authentication key generation, management and conversion
+ SYNOPSIS
+-     ssh-keygen [-q] [-b bits] -t type [-N new_passphrase] [-C comment]
++     ssh-keygen [-q] [-o] [-b bits] -t type [-N new_passphrase] [-C comment]
+                 [-f output_keyfile]
+      ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
+      ssh-keygen -i [-m key_format] [-f input_keyfile]
+@@ -232,6 +232,8 @@ DESCRIPTION
+      -q      Silence ssh-keygen.  Used by /etc/rc when creating a new key.
++     -o      Overwrite the key without prompting user.
++
+      -R hostname
+              Removes all keys belonging to hostname from a known_hosts file.
+              This option is useful to delete hashed hosts (see the -H option
+diff -up openssh-5.6p1/ssh-keygen.1.keygen openssh-5.6p1/ssh-keygen.1
+--- openssh-5.6p1/ssh-keygen.1.keygen  2010-08-05 05:05:32.000000000 +0200
++++ openssh-5.6p1/ssh-keygen.1 2010-08-23 12:36:25.000000000 +0200
+@@ -47,6 +47,7 @@
+ .Bk -words
+ .Nm ssh-keygen
+ .Op Fl q
++.Op Fl o
+ .Op Fl b Ar bits
+ .Fl t Ar type
+ .Op Fl N Ar new_passphrase
+@@ -397,6 +398,8 @@ Silence
+ Used by
+ .Pa /etc/rc
+ when creating a new key.
++.It Fl o
++Overwrite the key without prompting user.
+ .It Fl R Ar hostname
+ Removes all keys belonging to
+ .Ar hostname
+diff -up openssh-5.6p1/ssh-keygen.c.keygen openssh-5.6p1/ssh-keygen.c
+--- openssh-5.6p1/ssh-keygen.c.keygen  2010-08-05 05:05:32.000000000 +0200
++++ openssh-5.6p1/ssh-keygen.c 2010-08-23 12:34:40.000000000 +0200
+@@ -72,6 +72,7 @@ int change_passphrase = 0;
+ int change_comment = 0;
+ int quiet = 0;
++int overwrite = 0;
+ int log_level = SYSLOG_LEVEL_INFO;
+@@ -1798,7 +1799,7 @@ main(int argc, char **argv)
+               exit(1);
+       }
+-      while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:"
++      while ((opt = getopt(argc, argv, "degiqopclBHLhvxXyF:b:f:t:D:I:P:m:N:n:"
+           "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) {
+               switch (opt) {
+               case 'b':
+@@ -1878,6 +1879,9 @@ main(int argc, char **argv)
+               case 'q':
+                       quiet = 1;
+                       break;
++              case 'o':
++                      overwrite = 1;
++                      break;
+               case 'e':
+               case 'x':
+                       /* export key */
+@@ -2124,7 +2128,7 @@ main(int argc, char **argv)
+               }
+       }
+       /* If the file already exists, ask the user to confirm. */
+-      if (stat(identity_file, &st) >= 0) {
++      if (!overwrite && stat(identity_file, &st) >= 0) {
+               char yesno[3];
+               printf("%s already exists.\n", identity_file);
+               printf("Overwrite (y/n)? ");
diff --git a/pkgs/core/openssh/patches/openssh-5.6p1-redhat.patch b/pkgs/core/openssh/patches/openssh-5.6p1-redhat.patch
new file mode 100644 (file)
index 0000000..f4560a9
--- /dev/null
@@ -0,0 +1,99 @@
+diff -up openssh-5.6p1/ssh_config.redhat openssh-5.6p1/ssh_config
+--- openssh-5.6p1/ssh_config.redhat    2010-01-12 09:40:27.000000000 +0100
++++ openssh-5.6p1/ssh_config   2010-09-03 15:21:17.000000000 +0200
+@@ -45,3 +45,14 @@
+ #   PermitLocalCommand no
+ #   VisualHostKey no
+ #   ProxyCommand ssh -q -W %h:%p gateway.example.com
++Host *
++      GSSAPIAuthentication yes
++# If this option is set to yes then remote X11 clients will have full access
++# to the original X11 display. As virtually no X11 client supports the untrusted
++# mode correctly we set this to yes.
++      ForwardX11Trusted yes
++# Send locale-related environment variables
++      SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES 
++      SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT 
++      SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE
++      SendEnv XMODIFIERS
+diff -up openssh-5.6p1/sshd_config.0.redhat openssh-5.6p1/sshd_config.0
+--- openssh-5.6p1/sshd_config.0.redhat 2010-08-23 05:24:16.000000000 +0200
++++ openssh-5.6p1/sshd_config.0        2010-09-03 15:23:20.000000000 +0200
+@@ -537,9 +537,9 @@ DESCRIPTION
+      SyslogFacility
+              Gives the facility code that is used when logging messages from
+-             sshd(8).  The possible values are: DAEMON, USER, AUTH, LOCAL0,
+-             LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.  The
+-             default is AUTH.
++             sshd(8).  The possible values are: DAEMON, USER, AUTH, AUTHPRIV,
++             LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
++             The default is AUTH.
+      TCPKeepAlive
+              Specifies whether the system should send TCP keepalive messages
+diff -up openssh-5.6p1/sshd_config.5.redhat openssh-5.6p1/sshd_config.5
+--- openssh-5.6p1/sshd_config.5.redhat 2010-07-02 05:37:17.000000000 +0200
++++ openssh-5.6p1/sshd_config.5        2010-09-03 15:21:17.000000000 +0200
+@@ -919,7 +919,7 @@ Note that this option applies to protoco
+ .It Cm SyslogFacility
+ Gives the facility code that is used when logging messages from
+ .Xr sshd 8 .
+-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
++The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2,
+ LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+ The default is AUTH.
+ .It Cm TCPKeepAlive
+diff -up openssh-5.6p1/sshd_config.redhat openssh-5.6p1/sshd_config
+--- openssh-5.6p1/sshd_config.redhat   2009-10-11 12:51:09.000000000 +0200
++++ openssh-5.6p1/sshd_config  2010-09-03 15:21:17.000000000 +0200
+@@ -31,6 +31,7 @@
+ # Logging
+ # obsoletes QuietMode and FascistLogging
+ #SyslogFacility AUTH
++SyslogFacility AUTHPRIV
+ #LogLevel INFO
+ # Authentication:
+@@ -58,9 +59,11 @@
+ # To disable tunneled clear text passwords, change to no here!
+ #PasswordAuthentication yes
+ #PermitEmptyPasswords no
++PasswordAuthentication yes
+ # Change to no to disable s/key passwords
+ #ChallengeResponseAuthentication yes
++ChallengeResponseAuthentication no
+ # Kerberos options
+ #KerberosAuthentication no
+@@ -70,7 +73,9 @@
+ # GSSAPI options
+ #GSSAPIAuthentication no
++GSSAPIAuthentication yes
+ #GSSAPICleanupCredentials yes
++GSSAPICleanupCredentials yes
+ # Set this to 'yes' to enable PAM authentication, account processing, 
+ # and session processing. If this is enabled, PAM authentication will 
+@@ -82,11 +87,19 @@
+ # PAM authentication, then enable this but set PasswordAuthentication
+ # and ChallengeResponseAuthentication to 'no'.
+ #UsePAM no
++UsePAM yes
++
++# Accept locale-related environment variables
++AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
++AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
++AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
++AcceptEnv XMODIFIERS
+ #AllowAgentForwarding yes
+ #AllowTcpForwarding yes
+ #GatewayPorts no
+ #X11Forwarding no
++X11Forwarding yes
+ #X11DisplayOffset 10
+ #X11UseLocalhost yes
+ #PrintMotd yes
diff --git a/pkgs/core/openssh/patches/openssh-5.8p1-authorized-keys-command.patch b/pkgs/core/openssh/patches/openssh-5.8p1-authorized-keys-command.patch
new file mode 100644 (file)
index 0000000..356adfa
--- /dev/null
@@ -0,0 +1,447 @@
+diff -up openssh-5.8p1/auth2-pubkey.c.akc openssh-5.8p1/auth2-pubkey.c
+--- openssh-5.8p1/auth2-pubkey.c.akc   2011-02-10 13:21:27.000000000 +0100
++++ openssh-5.8p1/auth2-pubkey.c       2011-02-10 13:21:28.000000000 +0100
+@@ -27,6 +27,7 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include <sys/wait.h>
+ #include <fcntl.h>
+ #include <pwd.h>
+@@ -268,27 +269,15 @@ match_principals_file(char *file, struct
+ /* return 1 if user allows given key */
+ static int
+-user_key_allowed2(struct passwd *pw, Key *key, char *file)
++user_search_key_in_file(FILE *f, char *file, Key* key, struct passwd *pw)
+ {
+       char line[SSH_MAX_PUBKEY_BYTES];
+       const char *reason;
+       int found_key = 0;
+-      FILE *f;
+       u_long linenum = 0;
+       Key *found;
+       char *fp;
+-      /* Temporarily use the user's uid. */
+-      temporarily_use_uid(pw);
+-
+-      debug("trying public key file %s", file);
+-      f = auth_openkeyfile(file, pw, options.strict_modes);
+-
+-      if (!f) {
+-              restore_uid();
+-              return 0;
+-      }
+-
+       found_key = 0;
+       found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
+@@ -381,8 +370,6 @@ user_key_allowed2(struct passwd *pw, Key
+                       break;
+               }
+       }
+-      restore_uid();
+-      fclose(f);
+       key_free(found);
+       if (!found_key)
+               debug2("key not found");
+@@ -444,13 +431,191 @@ user_cert_trusted_ca(struct passwd *pw, 
+       return ret;
+ }
+-/* check whether given key is in .ssh/authorized_keys* */
++/* return 1 if user allows given key */
++static int
++user_key_allowed2(struct passwd *pw, Key *key, char *file)
++{
++      FILE *f;
++      int found_key = 0;
++
++      /* Temporarily use the user's uid. */
++      temporarily_use_uid(pw);
++
++      debug("trying public key file %s", file);
++      f = auth_openkeyfile(file, pw, options.strict_modes);
++
++      if (f) {
++              found_key = user_search_key_in_file (f, file, key, pw);
++              fclose(f);
++      }
++
++      restore_uid();
++      return found_key;
++}
++
++#ifdef WITH_AUTHORIZED_KEYS_COMMAND
++
++#define WHITESPACE " \t\r\n"
++
++/* return 1 if user allows given key */
++static int
++user_key_via_command_allowed2(struct passwd *pw, Key *key)
++{
++      FILE *f;
++      int found_key = 0;
++      char *progname = NULL;
++      char *cp;
++      struct passwd *runas_pw;
++      struct stat st;
++      int childdescriptors[2], i;
++      pid_t pstat, pid, child;
++
++      if (options.authorized_keys_command == NULL || options.authorized_keys_command[0] != '/')
++              return -1;
++
++      /* get the run as identity from config */
++      runas_pw = (options.authorized_keys_command_runas == NULL)? pw
++          : getpwnam (options.authorized_keys_command_runas);
++      if (!runas_pw) {
++              error("%s: getpwnam(\"%s\"): %s", __func__,
++                  options.authorized_keys_command_runas, strerror(errno));
++              return 0;
++      }
++
++      /* Temporarily use the specified uid. */
++      if (runas_pw->pw_uid != 0)
++              temporarily_use_uid(runas_pw);
++
++      progname = xstrdup(options.authorized_keys_command);
++
++      debug3("%s: checking program '%s'", __func__, progname);
++
++      if (stat (progname, &st) < 0) {
++              error("%s: stat(\"%s\"): %s", __func__,
++                  progname, strerror(errno));
++              goto go_away;
++      }
++
++      if (st.st_uid != 0 || (st.st_mode & 022) != 0) {
++              error("bad ownership or modes for AuthorizedKeysCommand \"%s\"",
++                  progname);
++              goto go_away;
++      }
++
++      if (!S_ISREG(st.st_mode)) {
++              error("AuthorizedKeysCommand \"%s\" is not a regular file",
++                  progname);
++              goto go_away;
++      }
++
++      /*
++       * Descend the path, checking that each component is a
++       * root-owned directory with strict permissions.
++       */
++      do {
++              if ((cp = strrchr(progname, '/')) == NULL)
++                      break;
++              else 
++                      *cp = '\0';
++      
++              debug3("%s: checking component '%s'", __func__, (*progname == '\0' ? "/" : progname));
++
++              if (stat((*progname == '\0' ? "/" : progname), &st) != 0) {
++                      error("%s: stat(\"%s\"): %s", __func__,
++                          progname, strerror(errno));
++                      goto go_away;
++              }
++              if (st.st_uid != 0 || (st.st_mode & 022) != 0) {
++                      error("bad ownership or modes for AuthorizedKeysCommand path component \"%s\"",
++                          progname);
++                      goto go_away;
++              }
++              if (!S_ISDIR(st.st_mode)) {
++                      error("AuthorizedKeysCommand path component \"%s\" is not a directory",
++                          progname);
++                      goto go_away;
++              }
++      } while (1);
++
++      /* open the pipe and read the keys */
++      if (pipe(childdescriptors)) {
++              error("failed to pipe(2) for AuthorizedKeysCommand: %s",
++                  strerror(errno));
++              goto go_away;
++      }
++
++      child = fork();
++      if (child == -1) {
++              error("failed to fork(2) for AuthorizedKeysCommand: %s",
++                  strerror(errno));
++              goto go_away;
++      } else if (child == 0) {
++              /* we're in the child process here -- we should never return from this block. */
++              /* permanently drop privs in child process */
++              if (runas_pw->pw_uid != 0) {
++                      restore_uid();
++                      permanently_set_uid(runas_pw);
++              }
++
++              close(childdescriptors[0]);
++              /* put the write end of the pipe on stdout (FD 1) */
++              if (dup2(childdescriptors[1], 1) == -1) {
++                      error("failed to dup2(2) from AuthorizedKeysCommand: %s",
++                          strerror(errno));
++                      _exit(127);
++              }
++
++              debug3("about to execl() AuthorizedKeysCommand: \"%s\" \"%s\"", options.authorized_keys_command, pw->pw_name);
++              /* see session.c:child_close_fds() */
++              for (i = 3; i < 64; ++i) {
++                      close(i);
++              }
++
++              execl(options.authorized_keys_command, options.authorized_keys_command, pw->pw_name, NULL);
++
++              /* if we got here, it didn't work */
++              error("failed to execl AuthorizedKeysCommand: %s", strerror(errno)); /* this won't work because we closed the fds above */
++              _exit(127);
++      }
++      
++      close(childdescriptors[1]);
++      f = fdopen(childdescriptors[0], "r");
++      if (!f) {
++              error("%s: could not buffer FDs from AuthorizedKeysCommand (\"%s\", \"r\"): %s", __func__,
++                  options.authorized_keys_command, strerror (errno));
++              goto go_away;
++      }
++
++      found_key = user_search_key_in_file (f, options.authorized_keys_command, key, pw);
++      fclose (f);
++      do {
++              pid = waitpid(child, &pstat, 0);
++      } while (pid == -1 && errno == EINTR);
++
++      /* what about the return value from the child process? */
++go_away:
++      if (progname)
++              xfree (progname);
++
++      if (runas_pw->pw_uid != 0)
++              restore_uid();
++      return found_key;
++}
++#endif
++
++/* check whether given key is in <AuthorizedKeysCommand or .ssh/authorized_keys* */
+ int
+ user_key_allowed(struct passwd *pw, Key *key)
+ {
+       int success;
+       char *file;
++#ifdef WITH_AUTHORIZED_KEYS_COMMAND
++      success = user_key_via_command_allowed2(pw, key);
++      if (success > 0)
++              return success;
++#endif
++
+       if (auth_key_is_revoked(key))
+               return 0;
+       if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
+diff -up openssh-5.8p1/configure.ac.akc openssh-5.8p1/configure.ac
+--- openssh-5.8p1/configure.ac.akc     2011-02-10 13:21:28.000000000 +0100
++++ openssh-5.8p1/configure.ac 2011-02-10 13:21:28.000000000 +0100
+@@ -1422,6 +1422,18 @@ AC_ARG_WITH(audit,
+       esac ]
+ )
++# Check whether user wants AuthorizedKeysCommand support
++AKC_MSG="no"
++AC_ARG_WITH(authorized-keys-command,
++      [  --with-authorized-keys-command      Enable AuthorizedKeysCommand support],
++      [
++              if test "x$withval" != "xno" ; then
++                      AC_DEFINE([WITH_AUTHORIZED_KEYS_COMMAND], 1, [Enable AuthorizedKeysCommand support])
++                      AKC_MSG="yes"
++              fi
++      ]
++)
++
+ dnl    Checks for library functions. Please keep in alphabetical order
+ AC_CHECK_FUNCS( \
+       arc4random \
+@@ -4325,6 +4337,7 @@ echo "                   SELinux support
+ echo "                 Smartcard support: $SCARD_MSG"
+ echo "                     S/KEY support: $SKEY_MSG"
+ echo "              TCP Wrappers support: $TCPW_MSG"
++echo "     AuthorizedKeysCommand support: $AKC_MSG"
+ echo "              MD5 password support: $MD5_MSG"
+ echo "                   libedit support: $LIBEDIT_MSG"
+ echo "  Solaris process contract support: $SPC_MSG"
+diff -up openssh-5.8p1/servconf.c.akc openssh-5.8p1/servconf.c
+--- openssh-5.8p1/servconf.c.akc       2011-02-10 13:21:28.000000000 +0100
++++ openssh-5.8p1/servconf.c   2011-02-10 13:28:21.000000000 +0100
+@@ -134,6 +134,8 @@ initialize_server_options(ServerOptions 
+       options->num_permitted_opens = -1;
+       options->adm_forced_command = NULL;
+       options->chroot_directory = NULL;
++      options->authorized_keys_command = NULL;
++      options->authorized_keys_command_runas = NULL;
+       options->zero_knowledge_password_authentication = -1;
+       options->revoked_keys_file = NULL;
+       options->trusted_user_ca_keys = NULL;
+@@ -331,6 +333,7 @@ typedef enum {
+       sZeroKnowledgePasswordAuthentication, sHostCertificate,
+       sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
+       sKexAlgorithms, sIPQoS,
++      sAuthorizedKeysCommand, sAuthorizedKeysCommandRunAs,
+       sDeprecated, sUnsupported
+ } ServerOpCodes;
+@@ -456,6 +459,13 @@ static struct {
+       { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
+       { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
+       { "ipqos", sIPQoS, SSHCFG_ALL },
++#ifdef WITH_AUTHORIZED_KEYS_COMMAND
++      { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
++      { "authorizedkeyscommandrunas", sAuthorizedKeysCommandRunAs, SSHCFG_ALL },
++#else
++      { "authorizedkeyscommand", sUnsupported, SSHCFG_ALL },
++      { "authorizedkeyscommandrunas", sUnsupported, SSHCFG_ALL },
++#endif
+       { NULL, sBadOption, 0 }
+ };
+@@ -1406,6 +1416,20 @@ process_server_config_line(ServerOptions
+               }
+               break;
++      case sAuthorizedKeysCommand:
++              len = strspn(cp, WHITESPACE);
++              if (*activep && options->authorized_keys_command == NULL)
++                      options->authorized_keys_command = xstrdup(cp + len);
++              return 0;
++
++      case sAuthorizedKeysCommandRunAs:
++              charptr = &options->authorized_keys_command_runas;
++
++              arg = strdelim(&cp);
++              if (*activep && *charptr == NULL)
++                      *charptr = xstrdup(arg);
++              break;
++
+       case sDeprecated:
+               logit("%s line %d: Deprecated option %s",
+                   filename, linenum, arg);
+@@ -1499,6 +1523,8 @@ copy_set_server_options(ServerOptions *d
+       M_CP_INTOPT(gss_authentication);
+       M_CP_INTOPT(rsa_authentication);
+       M_CP_INTOPT(pubkey_authentication);
++      M_CP_STROPT(authorized_keys_command);
++      M_CP_STROPT(authorized_keys_command_runas);
+       M_CP_INTOPT(kerberos_authentication);
+       M_CP_INTOPT(hostbased_authentication);
+       M_CP_INTOPT(hostbased_uses_name_from_packet_only);
+@@ -1753,6 +1779,8 @@ dump_config(ServerOptions *o)
+       dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
+       dump_cfg_string(sAuthorizedPrincipalsFile,
+           o->authorized_principals_file);
++      dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
++      dump_cfg_string(sAuthorizedKeysCommandRunAs, o->authorized_keys_command_runas);
+       /* string arguments requiring a lookup */
+       dump_cfg_string(sLogLevel, log_level_name(o->log_level));
+diff -up openssh-5.8p1/servconf.h.akc openssh-5.8p1/servconf.h
+--- openssh-5.8p1/servconf.h.akc       2011-02-10 13:21:28.000000000 +0100
++++ openssh-5.8p1/servconf.h   2011-02-10 13:21:28.000000000 +0100
+@@ -161,6 +161,8 @@ typedef struct {
+       char   *revoked_keys_file;
+       char   *trusted_user_ca_keys;
+       char   *authorized_principals_file;
++      char   *authorized_keys_command;
++      char   *authorized_keys_command_runas;
+ }       ServerOptions;
+ void   initialize_server_options(ServerOptions *);
+diff -up openssh-5.8p1/sshd_config.0.akc openssh-5.8p1/sshd_config.0
+--- openssh-5.8p1/sshd_config.0.akc    2011-02-10 13:21:28.000000000 +0100
++++ openssh-5.8p1/sshd_config.0        2011-02-10 13:21:28.000000000 +0100
+@@ -71,6 +71,23 @@ DESCRIPTION
+              See PATTERNS in ssh_config(5) for more information on patterns.
++     AuthorizedKeysCommand
++
++             Specifies a program to be used for lookup of the user's
++           public keys.  The program will be invoked with its first
++           argument the name of the user being authorized, and should produce 
++           on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS 
++           in sshd(8)).  By default (or when set to the empty string) there is no
++           AuthorizedKeysCommand run.  If the AuthorizedKeysCommand does not successfully
++           authorize the user, authorization falls through to the
++           AuthorizedKeysFile.  Note that this option has an effect
++           only with PubkeyAuthentication turned on.
++
++     AuthorizedKeysCommandRunAs
++             Specifies the user under whose account the AuthorizedKeysCommand is run.
++             Empty string (the default value) means the user being authorized
++             is used.
++
+      AuthorizedKeysFile
+              Specifies the file that contains the public keys that can be used
+              for user authentication.  The format is described in the
+@@ -398,7 +415,8 @@ DESCRIPTION
+              Only a subset of keywords may be used on the lines following a
+              Match keyword.  Available keywords are AllowAgentForwarding,
+-             AllowTcpForwarding, AuthorizedKeysFile, AuthorizedPrincipalsFile,
++             AllowTcpForwarding, AuthorizedKeysFile, AuthorizedKeysCommand,
++             AuthorizedKeysCommandRunAs, AuthorizedPrincipalsFile,
+              Banner, ChrootDirectory, ForceCommand, GatewayPorts,
+              GSSAPIAuthentication, HostbasedAuthentication,
+              HostbasedUsesNameFromPacketOnly, KbdInteractiveAuthentication,
+diff -up openssh-5.8p1/sshd_config.5.akc openssh-5.8p1/sshd_config.5
+--- openssh-5.8p1/sshd_config.5.akc    2011-02-10 13:21:28.000000000 +0100
++++ openssh-5.8p1/sshd_config.5        2011-02-10 13:21:28.000000000 +0100
+@@ -703,6 +703,8 @@ Available keywords are
+ .Cm AllowAgentForwarding ,
+ .Cm AllowTcpForwarding ,
+ .Cm AuthorizedKeysFile ,
++.Cm AuthorizedKeysCommand ,
++.Cm AuthorizedKeysCommandRunAs ,
+ .Cm AuthorizedPrincipalsFile ,
+ .Cm Banner ,
+ .Cm ChrootDirectory ,
+@@ -715,6 +717,7 @@ Available keywords are
+ .Cm KerberosAuthentication ,
+ .Cm MaxAuthTries ,
+ .Cm MaxSessions ,
++.Cm PubkeyAuthentication ,
+ .Cm PasswordAuthentication ,
+ .Cm PermitEmptyPasswords ,
+ .Cm PermitOpen ,
+@@ -917,6 +920,20 @@ Specifies a list of revoked public keys.
+ Keys listed in this file will be refused for public key authentication.
+ Note that if this file is not readable, then public key authentication will
+ be refused for all users.
++.It Cm AuthorizedKeysCommand
++Specifies a program to be used for lookup of the user's
++public keys.  The program will be invoked with its first
++argument the name of the user being authorized, and should produce 
++on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS 
++in sshd(8)).  By default (or when set to the empty string) there is no
++AuthorizedKeysCommand run.  If the AuthorizedKeysCommand does not successfully
++authorize the user, authorization falls through to the
++AuthorizedKeysFile.  Note that this option has an effect
++only with PubkeyAuthentication turned on.
++.It Cm AuthorizedKeysCommandRunAs
++Specifies the user under whose account the AuthorizedKeysCommand is run. Empty
++string (the default value) means the user being authorized is used.
++.Dq 
+ .It Cm RhostsRSAAuthentication
+ Specifies whether rhosts or /etc/hosts.equiv authentication together
+ with successful RSA host authentication is allowed.
+diff -up openssh-5.8p1/sshd_config.akc openssh-5.8p1/sshd_config
+--- openssh-5.8p1/sshd_config.akc      2011-02-10 13:21:28.000000000 +0100
++++ openssh-5.8p1/sshd_config  2011-02-10 13:21:28.000000000 +0100
+@@ -46,6 +46,8 @@ SyslogFacility AUTHPRIV
+ #RSAAuthentication yes
+ #PubkeyAuthentication yes
+ #AuthorizedKeysFile   .ssh/authorized_keys
++#AuthorizedKeysCommand none
++#AuthorizedKeysCommandRunAs nobody
+ # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
+ #RhostsRSAAuthentication no
diff --git a/pkgs/core/openssh/patches/openssh-5.8p1-fingerprint.patch b/pkgs/core/openssh/patches/openssh-5.8p1-fingerprint.patch
new file mode 100644 (file)
index 0000000..a0438ff
--- /dev/null
@@ -0,0 +1,421 @@
+diff -up openssh-5.8p1/auth2-hostbased.c.fingerprint openssh-5.8p1/auth2-hostbased.c
+--- openssh-5.8p1/auth2-hostbased.c.fingerprint        2010-08-05 05:04:50.000000000 +0200
++++ openssh-5.8p1/auth2-hostbased.c    2011-02-25 09:17:18.000000000 +0100
+@@ -196,16 +196,18 @@ hostbased_key_allowed(struct passwd *pw,
+       if (host_status == HOST_OK) {
+               if (key_is_cert(key)) {
+-                      fp = key_fingerprint(key->cert->signature_key,
+-                          SSH_FP_MD5, SSH_FP_HEX);
++                      fp = key_selected_fingerprint(key->cert->signature_key,
++                          SSH_FP_HEX);
+                       verbose("Accepted certificate ID \"%s\" signed by "
+-                          "%s CA %s from %s@%s", key->cert->key_id,
+-                          key_type(key->cert->signature_key), fp,
++                          "%s CA %s%s from %s@%s", key->cert->key_id,
++                          key_type(key->cert->signature_key),
++                          key_fingerprint_prefix(), fp,
+                           cuser, lookup);
+               } else {
+-                      fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+-                      verbose("Accepted %s public key %s from %s@%s",
+-                          key_type(key), fp, cuser, lookup);
++                      fp = key_selected_fingerprint(key, SSH_FP_HEX);
++                      verbose("Accepted %s public key %s%s from %s@%s",
++                          key_type(key), key_fingerprint_prefix(),
++                          fp, cuser, lookup);
+               }
+               xfree(fp);
+       }
+diff -up openssh-5.8p1/auth2-pubkey.c.fingerprint openssh-5.8p1/auth2-pubkey.c
+--- openssh-5.8p1/auth2-pubkey.c.fingerprint   2010-12-01 01:50:14.000000000 +0100
++++ openssh-5.8p1/auth2-pubkey.c       2011-02-25 09:17:18.000000000 +0100
+@@ -319,10 +319,10 @@ user_key_allowed2(struct passwd *pw, Key
+                               continue;
+                       if (!key_is_cert_authority)
+                               continue;
+-                      fp = key_fingerprint(found, SSH_FP_MD5,
+-                          SSH_FP_HEX);
+-                      debug("matching CA found: file %s, line %lu, %s %s",
+-                          file, linenum, key_type(found), fp);
++                      fp = key_selected_fingerprint(found, SSH_FP_HEX);
++                      debug("matching CA found: file %s, line %lu, %s %s%s",
++                          file, linenum, key_type(found),
++                          key_fingerprint_prefix(), fp);
+                       /*
+                        * If the user has specified a list of principals as
+                        * a key option, then prefer that list to matching
+@@ -362,9 +362,9 @@ user_key_allowed2(struct passwd *pw, Key
+                       found_key = 1;
+                       debug("matching key found: file %s, line %lu",
+                           file, linenum);
+-                      fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+-                      verbose("Found matching %s key: %s",
+-                          key_type(found), fp);
++                      fp = key_selected_fingerprint(found, SSH_FP_HEX);
++                      verbose("Found matching %s key: %s%s",
++                          key_type(found), key_fingerprint_prefix(), fp);
+                       xfree(fp);
+                       break;
+               }
+@@ -388,13 +388,13 @@ user_cert_trusted_ca(struct passwd *pw, 
+       if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)
+               return 0;
+-      ca_fp = key_fingerprint(key->cert->signature_key,
+-          SSH_FP_MD5, SSH_FP_HEX);
++      ca_fp = key_selected_fingerprint(key->cert->signature_key, SSH_FP_HEX);
+       if (key_in_file(key->cert->signature_key,
+           options.trusted_user_ca_keys, 1) != 1) {
+-              debug2("%s: CA %s %s is not listed in %s", __func__,
+-                  key_type(key->cert->signature_key), ca_fp,
++              debug2("%s: CA %s%s %s is not listed in %s", __func__,
++                  key_type(key->cert->signature_key),
++                  key_fingerprint_prefix(), ca_fp,
+                   options.trusted_user_ca_keys);
+               goto out;
+       }
+diff -up openssh-5.8p1/auth.c.fingerprint openssh-5.8p1/auth.c
+--- openssh-5.8p1/auth.c.fingerprint   2010-12-01 02:21:51.000000000 +0100
++++ openssh-5.8p1/auth.c       2011-02-25 09:17:18.000000000 +0100
+@@ -639,9 +639,10 @@ auth_key_is_revoked(Key *key)
+               return 1;
+       case 1:
+               /* Key revoked */
+-              key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
++              key_fp = key_selected_fingerprint(key, SSH_FP_HEX);
+               error("WARNING: authentication attempt with a revoked "
+-                  "%s key %s ", key_type(key), key_fp);
++                  "%s key %s%s ", key_type(key),
++                  key_fingerprint_prefix(), key_fp);
+               xfree(key_fp);
+               return 1;
+       }
+diff -up openssh-5.8p1/auth-rsa.c.fingerprint openssh-5.8p1/auth-rsa.c
+--- openssh-5.8p1/auth-rsa.c.fingerprint       2010-12-04 23:01:47.000000000 +0100
++++ openssh-5.8p1/auth-rsa.c   2011-02-25 09:17:18.000000000 +0100
+@@ -318,9 +318,9 @@ auth_rsa(Authctxt *authctxt, BIGNUM *cli
+        * options; this will be reset if the options cause the
+        * authentication to be rejected.
+        */
+-      fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+-      verbose("Found matching %s key: %s",
+-          key_type(key), fp);
++      fp = key_selected_fingerprint(key, SSH_FP_HEX);
++      verbose("Found matching %s key: %s%s",
++          key_type(key), key_fingerprint_prefix(), fp);
+       xfree(fp);
+       key_free(key);
+diff -up openssh-5.8p1/key.c.fingerprint openssh-5.8p1/key.c
+--- openssh-5.8p1/key.c.fingerprint    2011-02-04 01:48:34.000000000 +0100
++++ openssh-5.8p1/key.c        2011-02-25 09:18:16.000000000 +0100
+@@ -594,6 +594,34 @@ key_fingerprint(Key *k, enum fp_type dgs
+       return retval;
+ }
++enum fp_type
++key_fingerprint_selection(void)
++{
++      static enum fp_type rv;
++      static char rv_defined = 0;
++      char *env;
++
++      if (!rv_defined) {
++              env = getenv("SSH_FINGERPRINT_TYPE");
++              rv = (env && !strcmp (env, "sha")) ?
++                      SSH_FP_SHA1 : SSH_FP_MD5;
++              rv_defined = 1;
++      }
++      return rv;
++}
++
++char *
++key_selected_fingerprint(Key *k, enum fp_rep dgst_rep)
++{
++      return key_fingerprint(k, key_fingerprint_selection(), dgst_rep);
++}
++
++char *
++key_fingerprint_prefix(void)
++{
++      return key_fingerprint_selection() == SSH_FP_SHA1 ? "sha1:" : "";
++}
++
+ /*
+  * Reads a multiple-precision integer in decimal from the buffer, and advances
+  * the pointer.  The integer must already be initialized.  This function is
+diff -up openssh-5.8p1/key.h.fingerprint openssh-5.8p1/key.h
+--- openssh-5.8p1/key.h.fingerprint    2010-11-05 00:19:49.000000000 +0100
++++ openssh-5.8p1/key.h        2011-02-25 09:17:18.000000000 +0100
+@@ -96,6 +96,9 @@ int           key_equal_public(const Key *, cons
+ int            key_equal(const Key *, const Key *);
+ char          *key_fingerprint(Key *, enum fp_type, enum fp_rep);
+ u_char                *key_fingerprint_raw(Key *, enum fp_type, u_int *);
++enum fp_type   key_fingerprint_selection(void);
++char          *key_selected_fingerprint(Key *, enum fp_rep);
++char          *key_fingerprint_prefix(void);
+ const char    *key_type(const Key *);
+ const char    *key_cert_type(const Key *);
+ int            key_write(const Key *, FILE *);
+diff -up openssh-5.8p1/ssh-add.c.fingerprint openssh-5.8p1/ssh-add.c
+--- openssh-5.8p1/ssh-add.c.fingerprint        2010-11-11 04:17:02.000000000 +0100
++++ openssh-5.8p1/ssh-add.c    2011-02-25 09:17:18.000000000 +0100
+@@ -280,10 +280,10 @@ list_identities(AuthenticationConnection
+                   key = ssh_get_next_identity(ac, &comment, version)) {
+                       had_identities = 1;
+                       if (do_fp) {
+-                              fp = key_fingerprint(key, SSH_FP_MD5,
+-                                  SSH_FP_HEX);
+-                              printf("%d %s %s (%s)\n",
+-                                  key_size(key), fp, comment, key_type(key));
++                              fp = key_selected_fingerprint(key, SSH_FP_HEX);
++                              printf("%d %s%s %s (%s)\n",
++                                  key_size(key), key_fingerprint_prefix(),
++                                  fp, comment, key_type(key));
+                               xfree(fp);
+                       } else {
+                               if (!key_write(key, stdout))
+diff -up openssh-5.8p1/ssh-agent.c.fingerprint openssh-5.8p1/ssh-agent.c
+--- openssh-5.8p1/ssh-agent.c.fingerprint      2010-12-01 01:50:35.000000000 +0100
++++ openssh-5.8p1/ssh-agent.c  2011-02-25 09:17:18.000000000 +0100
+@@ -199,9 +199,9 @@ confirm_key(Identity *id)
+       char *p;
+       int ret = -1;
+-      p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+-      if (ask_permission("Allow use of key %s?\nKey fingerprint %s.",
+-          id->comment, p))
++      p = key_selected_fingerprint(id->key, SSH_FP_HEX);
++      if (ask_permission("Allow use of key %s?\nKey fingerprint %s%s.",
++          id->comment, key_fingerprint_prefix(), p))
+               ret = 0;
+       xfree(p);
+diff -up openssh-5.8p1/sshconnect2.c.fingerprint openssh-5.8p1/sshconnect2.c
+--- openssh-5.8p1/sshconnect2.c.fingerprint    2010-12-01 02:21:51.000000000 +0100
++++ openssh-5.8p1/sshconnect2.c        2011-02-25 09:17:18.000000000 +0100
+@@ -590,8 +590,9 @@ input_userauth_pk_ok(int type, u_int32_t
+                   key->type, pktype);
+               goto done;
+       }
+-      fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+-      debug2("input_userauth_pk_ok: fp %s", fp);
++      fp = key_selected_fingerprint(key, SSH_FP_HEX);
++      debug2("input_userauth_pk_ok: fp %s%s",
++          key_fingerprint_prefix(), fp);
+       xfree(fp);
+       /*
+@@ -1203,8 +1204,9 @@ sign_and_send_pubkey(Authctxt *authctxt,
+       int have_sig = 1;
+       char *fp;
+-      fp = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+-      debug3("sign_and_send_pubkey: %s %s", key_type(id->key), fp);
++      fp = key_selected_fingerprint(id->key, SSH_FP_HEX);
++      debug3("sign_and_send_pubkey: %s %s%s", key_type(id->key),
++          key_fingerprint_prefix(), fp);
+       xfree(fp);
+       if (key_to_blob(id->key, &blob, &bloblen) == 0) {
+diff -up openssh-5.8p1/sshconnect.c.fingerprint openssh-5.8p1/sshconnect.c
+--- openssh-5.8p1/sshconnect.c.fingerprint     2011-01-16 13:17:59.000000000 +0100
++++ openssh-5.8p1/sshconnect.c 2011-02-25 09:17:18.000000000 +0100
+@@ -798,10 +798,10 @@ check_host_key(char *hostname, struct so
+                                   "key for IP address '%.128s' to the list "
+                                   "of known hosts.", type, ip);
+               } else if (options.visual_host_key) {
+-                      fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+-                      ra = key_fingerprint(host_key, SSH_FP_MD5,
+-                          SSH_FP_RANDOMART);
+-                      logit("Host key fingerprint is %s\n%s\n", fp, ra);
++                      fp = key_selected_fingerprint(host_key, SSH_FP_HEX);
++                      ra = key_selected_fingerprint(host_key, SSH_FP_RANDOMART);
++                      logit("Host key fingerprint is %s%s\n%s\n",
++                          key_fingerprint_prefix(), fp, ra);
+                       xfree(ra);
+                       xfree(fp);
+               }
+@@ -838,9 +838,8 @@ check_host_key(char *hostname, struct so
+                       else
+                               snprintf(msg1, sizeof(msg1), ".");
+                       /* The default */
+-                      fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+-                      ra = key_fingerprint(host_key, SSH_FP_MD5,
+-                          SSH_FP_RANDOMART);
++                      fp = key_selected_fingerprint(host_key, SSH_FP_HEX);
++                      ra = key_selected_fingerprint(host_key, SSH_FP_RANDOMART);
+                       msg2[0] = '\0';
+                       if (options.verify_host_key_dns) {
+                               if (matching_host_key_dns)
+@@ -855,10 +854,11 @@ check_host_key(char *hostname, struct so
+                       snprintf(msg, sizeof(msg),
+                           "The authenticity of host '%.200s (%s)' can't be "
+                           "established%s\n"
+-                          "%s key fingerprint is %s.%s%s\n%s"
++                          "%s key fingerprint is %s%s.%s%s\n%s"
+                           "Are you sure you want to continue connecting "
+                           "(yes/no)? ",
+-                          host, ip, msg1, type, fp,
++                          host, ip, msg1, type,
++                          key_fingerprint_prefix(), fp,
+                           options.visual_host_key ? "\n" : "",
+                           options.visual_host_key ? ra : "",
+                           msg2);
+@@ -1104,8 +1104,9 @@ verify_host_key(char *host, struct socka
+       int flags = 0;
+       char *fp;
+-      fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
+-      debug("Server host key: %s %s", key_type(host_key), fp);
++      fp = key_selected_fingerprint(host_key, SSH_FP_HEX);
++      debug("Server host key: %s %s%s", key_type(host_key),
++          key_fingerprint_prefix(), fp);
+       xfree(fp);
+       /* XXX certs are not yet supported for DNS */
+@@ -1214,14 +1215,15 @@ show_other_keys(struct hostkeys *hostkey
+                       continue;
+               if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
+                       continue;
+-              fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX);
+-              ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART);
++              fp = key_selected_fingerprint(found->key, SSH_FP_HEX);
++              ra = key_selected_fingerprint(found->key, SSH_FP_RANDOMART);
+               logit("WARNING: %s key found for host %s\n"
+                   "in %s:%lu\n"
+-                  "%s key fingerprint %s.",
++                  "%s key fingerprint %s%s.",
+                   key_type(found->key),
+                   found->host, found->file, found->line,
+-                  key_type(found->key), fp);
++                  key_type(found->key),
++                  key_fingerprint_prefix(), fp);
+               if (options.visual_host_key)
+                       logit("%s", ra);
+               xfree(ra);
+@@ -1236,7 +1238,7 @@ warn_changed_key(Key *host_key)
+ {
+       char *fp;
+-      fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
++      fp = key_selected_fingerprint(host_key, SSH_FP_HEX);
+       error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+       error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
+@@ -1244,8 +1246,8 @@ warn_changed_key(Key *host_key)
+       error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
+       error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
+       error("It is also possible that a host key has just been changed.");
+-      error("The fingerprint for the %s key sent by the remote host is\n%s.",
+-          key_type(host_key), fp);
++      error("The fingerprint for the %s key sent by the remote host is\n%s%s.",
++          key_type(host_key),key_fingerprint_prefix(),  fp);
+       error("Please contact your system administrator.");
+       xfree(fp);
+diff -up openssh-5.8p1/ssh-keygen.c.fingerprint openssh-5.8p1/ssh-keygen.c
+--- openssh-5.8p1/ssh-keygen.c.fingerprint     2011-01-11 07:20:31.000000000 +0100
++++ openssh-5.8p1/ssh-keygen.c 2011-02-25 09:17:18.000000000 +0100
+@@ -714,13 +714,14 @@ do_fingerprint(struct passwd *pw)
+ {
+       FILE *f;
+       Key *public;
+-      char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
++      char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra, *pfx;
+       int i, skip = 0, num = 0, invalid = 1;
+       enum fp_rep rep;
+       enum fp_type fptype;
+       struct stat st;
+-      fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
++      fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fingerprint_selection();
++      pfx =    print_bubblebabble ? "" : key_fingerprint_prefix();
+       rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
+       if (!have_identity)
+@@ -732,8 +733,8 @@ do_fingerprint(struct passwd *pw)
+       public = key_load_public(identity_file, &comment);
+       if (public != NULL) {
+               fp = key_fingerprint(public, fptype, rep);
+-              ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
+-              printf("%u %s %s (%s)\n", key_size(public), fp, comment,
++              ra = key_selected_fingerprint(public, SSH_FP_RANDOMART);
++              printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp, comment,
+                   key_type(public));
+               if (log_level >= SYSLOG_LEVEL_VERBOSE)
+                       printf("%s\n", ra);
+@@ -798,8 +799,8 @@ do_fingerprint(struct passwd *pw)
+               }
+               comment = *cp ? cp : comment;
+               fp = key_fingerprint(public, fptype, rep);
+-              ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
+-              printf("%u %s %s (%s)\n", key_size(public), fp,
++              ra = key_selected_fingerprint(public, SSH_FP_RANDOMART);
++              printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp,
+                   comment ? comment : "no comment", key_type(public));
+               if (log_level >= SYSLOG_LEVEL_VERBOSE)
+                       printf("%s\n", ra);
+@@ -823,13 +824,15 @@ printhost(FILE *f, const char *name, Key
+       if (print_fingerprint) {
+               enum fp_rep rep;
+               enum fp_type fptype;
+-              char *fp, *ra;
++              char *fp, *ra, *pfx;
+-              fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5;
++              fptype = print_bubblebabble ? SSH_FP_SHA1 : key_fingerprint_selection();
++              pfx =    print_bubblebabble ? "" : key_fingerprint_prefix();
+               rep =    print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX;
++
+               fp = key_fingerprint(public, fptype, rep);
+-              ra = key_fingerprint(public, SSH_FP_MD5, SSH_FP_RANDOMART);
+-              printf("%u %s %s (%s)\n", key_size(public), fp, name,
++              ra = key_selected_fingerprint(public, SSH_FP_RANDOMART);
++              printf("%u %s%s %s (%s)\n", key_size(public), pfx, fp, name,
+                   key_type(public));
+               if (log_level >= SYSLOG_LEVEL_VERBOSE)
+                       printf("%s\n", ra);
+@@ -1695,16 +1698,17 @@ do_show_cert(struct passwd *pw)
+               fatal("%s is not a certificate", identity_file);
+       v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00;
+-      key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
+-      ca_fp = key_fingerprint(key->cert->signature_key,
+-          SSH_FP_MD5, SSH_FP_HEX);
++      key_fp = key_selected_fingerprint(key, SSH_FP_HEX);
++      ca_fp = key_selected_fingerprint(key->cert->signature_key, SSH_FP_HEX);
+       printf("%s:\n", identity_file);
+       printf("        Type: %s %s certificate\n", key_ssh_name(key),
+           key_cert_type(key));
+-      printf("        Public key: %s %s\n", key_type(key), key_fp);
+-      printf("        Signing CA: %s %s\n",
+-          key_type(key->cert->signature_key), ca_fp);
++      printf("        Public key: %s %s%s\n", key_type(key),
++          key_fingerprint_prefix(), key_fp);
++      printf("        Signing CA: %s %s%s\n",
++          key_type(key->cert->signature_key),
++          key_fingerprint_prefix(), ca_fp);
+       printf("        Key ID: \"%s\"\n", key->cert->key_id);
+       if (!v00) {
+               printf("        Serial: %llu\n",
+@@ -2249,13 +2253,12 @@ passphrase_again:
+       fclose(f);
+       if (!quiet) {
+-              char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX);
+-              char *ra = key_fingerprint(public, SSH_FP_MD5,
+-                  SSH_FP_RANDOMART);
++              char *fp = key_selected_fingerprint(public, SSH_FP_HEX);
++              char *ra = key_selected_fingerprint(public, SSH_FP_RANDOMART);
+               printf("Your public key has been saved in %s.\n",
+                   identity_file);
+               printf("The key fingerprint is:\n");
+-              printf("%s %s\n", fp, comment);
++              printf("%s%s %s\n", key_fingerprint_prefix(), fp, comment);
+               printf("The key's randomart image is:\n");
+               printf("%s\n", ra);
+               xfree(ra);
diff --git a/pkgs/core/openssh/patches/openssh-5.8p1-kuserok.patch b/pkgs/core/openssh/patches/openssh-5.8p1-kuserok.patch
new file mode 100644 (file)
index 0000000..fcd05d7
--- /dev/null
@@ -0,0 +1,167 @@
+diff -up openssh-5.8p1/auth-krb5.c.kuserok openssh-5.8p1/auth-krb5.c
+--- openssh-5.8p1/auth-krb5.c.kuserok  2009-12-21 00:49:22.000000000 +0100
++++ openssh-5.8p1/auth-krb5.c  2011-02-14 09:15:12.000000000 +0100
+@@ -54,6 +54,20 @@
+ extern ServerOptions   options;
++int
++ssh_krb5_kuserok(krb5_context krb5_ctx, krb5_principal krb5_user, const char *client)
++{
++      if (options.use_kuserok)
++              return krb5_kuserok(krb5_ctx, krb5_user, client);
++      else {
++              char kuser[65];
++
++              if (krb5_aname_to_localname(krb5_ctx, krb5_user, sizeof(kuser), kuser))
++                      return 0;
++              return strcmp(kuser, client) == 0;
++      }
++}
++
+ static int
+ krb5_init(void *context)
+ {
+@@ -146,7 +160,7 @@ auth_krb5_password(Authctxt *authctxt, c
+       if (problem)
+               goto out;
+-      if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
++      if (!ssh_krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
+               problem = -1;
+               goto out;
+       }
+diff -up openssh-5.8p1/gss-serv-krb5.c.kuserok openssh-5.8p1/gss-serv-krb5.c
+--- openssh-5.8p1/gss-serv-krb5.c.kuserok      2006-09-01 07:38:36.000000000 +0200
++++ openssh-5.8p1/gss-serv-krb5.c      2011-02-14 09:15:12.000000000 +0100
+@@ -57,6 +57,7 @@ extern ServerOptions options;
+ #endif
+ static krb5_context krb_context = NULL;
++extern int ssh_krb5_kuserok(krb5_context, krb5_principal, const char *);
+ /* Initialise the krb5 library, for the stuff that GSSAPI won't do */
+@@ -97,7 +98,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client
+                   krb5_get_err_text(krb_context, retval));
+               return 0;
+       }
+-      if (krb5_kuserok(krb_context, princ, name)) {
++      if (ssh_krb5_kuserok(krb_context, princ, name)) {
+               retval = 1;
+               logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
+                   name, (char *)client->displayname.value);
+diff -up openssh-5.8p1/servconf.c.kuserok openssh-5.8p1/servconf.c
+--- openssh-5.8p1/servconf.c.kuserok   2011-02-14 09:15:12.000000000 +0100
++++ openssh-5.8p1/servconf.c   2011-02-14 09:20:22.000000000 +0100
+@@ -142,6 +142,7 @@ initialize_server_options(ServerOptions 
+       options->authorized_principals_file = NULL;
+       options->ip_qos_interactive = -1;
+       options->ip_qos_bulk = -1;
++      options->use_kuserok = -1;
+ }
+ void
+@@ -291,6 +292,8 @@ fill_default_server_options(ServerOption
+       if (use_privsep == -1)
+               use_privsep = 1;
++      if (options->use_kuserok == -1)
++              options->use_kuserok = 1;
+ #ifndef HAVE_MMAP
+       if (use_privsep && options->compression == 1) {
+               error("This platform does not support both privilege "
+@@ -312,7 +315,7 @@ typedef enum {
+       sPermitRootLogin, sLogFacility, sLogLevel,
+       sRhostsRSAAuthentication, sRSAAuthentication,
+       sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
+-      sKerberosGetAFSToken,
++      sKerberosGetAFSToken, sKerberosUseKuserok,
+       sKerberosTgtPassing, sChallengeResponseAuthentication,
+       sPasswordAuthentication, sKbdInteractiveAuthentication,
+       sListenAddress, sAddressFamily,
+@@ -381,11 +384,13 @@ static struct {
+ #else
+       { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+ #endif
++      { "kerberosusekuserok", sKerberosUseKuserok, SSHCFG_ALL },
+ #else
+       { "kerberosauthentication", sUnsupported, SSHCFG_ALL },
+       { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
+       { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
+       { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
++      { "kerberosusekuserok", sUnsupported, SSHCFG_ALL },
+ #endif
+       { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
+       { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
+@@ -1341,6 +1346,10 @@ process_server_config_line(ServerOptions
+               *activep = value;
+               break;
++      case sKerberosUseKuserok:
++              intptr = &options->use_kuserok;
++              goto parse_flag;
++
+       case sPermitOpen:
+               arg = strdelim(&cp);
+               if (!arg || *arg == '\0')
+@@ -1544,6 +1553,7 @@ copy_set_server_options(ServerOptions *d
+       M_CP_INTOPT(max_authtries);
+       M_CP_INTOPT(ip_qos_interactive);
+       M_CP_INTOPT(ip_qos_bulk);
++      M_CP_INTOPT(use_kuserok);
+       M_CP_STROPT(banner);
+       if (preauth)
+@@ -1764,6 +1774,7 @@ dump_config(ServerOptions *o)
+       dump_cfg_fmtint(sUseDNS, o->use_dns);
+       dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
+       dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
++      dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok);
+       /* string arguments */
+       dump_cfg_string(sPidFile, o->pid_file);
+diff -up openssh-5.8p1/servconf.h.kuserok openssh-5.8p1/servconf.h
+--- openssh-5.8p1/servconf.h.kuserok   2011-02-14 09:15:12.000000000 +0100
++++ openssh-5.8p1/servconf.h   2011-02-14 09:15:12.000000000 +0100
+@@ -157,6 +157,7 @@ typedef struct {
+       int     num_permitted_opens;
++      int     use_kuserok;
+       char   *chroot_directory;
+       char   *revoked_keys_file;
+       char   *trusted_user_ca_keys;
+diff -up openssh-5.8p1/sshd_config.5.kuserok openssh-5.8p1/sshd_config.5
+--- openssh-5.8p1/sshd_config.5.kuserok        2011-02-14 09:15:12.000000000 +0100
++++ openssh-5.8p1/sshd_config.5        2011-02-14 09:17:11.000000000 +0100
+@@ -574,6 +574,10 @@ Specifies whether to automatically destr
+ file on logout.
+ The default is
+ .Dq yes .
++.It Cm KerberosUseKuserok
++Specifies whether to look at .k5login file for user's aliases.
++The default is
++.Dq yes .
+ .It Cm KexAlgorithms
+ Specifies the available KEX (Key Exchange) algorithms.
+ Multiple algorithms must be comma-separated.
+@@ -715,6 +719,7 @@ Available keywords are
+ .Cm HostbasedUsesNameFromPacketOnly ,
+ .Cm KbdInteractiveAuthentication ,
+ .Cm KerberosAuthentication ,
++.Cm KerberosUseKuserok ,
+ .Cm MaxAuthTries ,
+ .Cm MaxSessions ,
+ .Cm PubkeyAuthentication ,
+diff -up openssh-5.8p1/sshd_config.kuserok openssh-5.8p1/sshd_config
+--- openssh-5.8p1/sshd_config.kuserok  2011-02-14 09:15:12.000000000 +0100
++++ openssh-5.8p1/sshd_config  2011-02-14 09:15:12.000000000 +0100
+@@ -73,6 +73,7 @@ ChallengeResponseAuthentication no
+ #KerberosOrLocalPasswd yes
+ #KerberosTicketCleanup yes
+ #KerberosGetAFSToken no
++#KerberosUseKuserok yes
+ # GSSAPI options
+ #GSSAPIAuthentication no
diff --git a/pkgs/core/openssh/patches/openssh-5.8p1-mls.patch b/pkgs/core/openssh/patches/openssh-5.8p1-mls.patch
new file mode 100644 (file)
index 0000000..525e6b5
--- /dev/null
@@ -0,0 +1,400 @@
+diff -up openssh-5.8p1/misc.c.mls openssh-5.8p1/misc.c
+--- openssh-5.8p1/misc.c.mls   2011-01-13 02:21:36.000000000 +0100
++++ openssh-5.8p1/misc.c       2011-02-12 15:05:06.000000000 +0100
+@@ -427,6 +427,7 @@ char *
+ colon(char *cp)
+ {
+       int flag = 0;
++      int start = 1;
+       if (*cp == ':')         /* Leading colon is part of file name. */
+               return NULL;
+@@ -442,6 +443,13 @@ colon(char *cp)
+                       return (cp);
+               if (*cp == '/')
+                       return NULL;
++              if (start) {
++              /* Slash on beginning or after dots only denotes file name. */
++                      if (*cp == '/')
++                              return (0);
++                      if (*cp != '.')
++                              start = 0;
++              }
+       }
+       return NULL;
+ }
+diff -up openssh-5.8p1/openbsd-compat/port-linux.c.mls openssh-5.8p1/openbsd-compat/port-linux.c
+--- openssh-5.8p1/openbsd-compat/port-linux.c.mls      2011-02-12 15:05:06.000000000 +0100
++++ openssh-5.8p1/openbsd-compat/port-linux.c  2011-02-12 15:09:23.000000000 +0100
+@@ -40,13 +40,164 @@
+ #ifdef WITH_SELINUX
+ #include <selinux/selinux.h>
+ #include <selinux/flask.h>
++#include <selinux/context.h>
+ #include <selinux/get_context_list.h>
++#include <selinux/get_default_type.h>
++#include <selinux/av_permissions.h>
++
++#ifdef HAVE_LINUX_AUDIT
++#include <libaudit.h>
++#include <unistd.h>
++#endif
+ extern ServerOptions options;
+ extern Authctxt *the_authctxt;
+ extern int inetd_flag;
+ extern int rexeced_flag;
++/* Send audit message */
++static int
++send_audit_message(int success, security_context_t default_context,
++                     security_context_t selected_context)
++{
++      int rc=0;
++#ifdef HAVE_LINUX_AUDIT
++      char *msg = NULL;
++      int audit_fd = audit_open();
++      security_context_t default_raw=NULL;
++      security_context_t selected_raw=NULL;
++      rc = -1;
++      if (audit_fd < 0) {
++              if (errno == EINVAL || errno == EPROTONOSUPPORT ||
++                                      errno == EAFNOSUPPORT)
++                              return 0; /* No audit support in kernel */
++              error("Error connecting to audit system.");
++              return rc;
++      }
++      if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) {
++              error("Error translating default context.");
++              default_raw = NULL;
++      }
++      if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) {
++              error("Error translating selected context.");
++              selected_raw = NULL;
++      }
++      if (asprintf(&msg, "sshd: default-context=%s selected-context=%s",
++                   default_raw ? default_raw : (default_context ? default_context: "?"),
++                   selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) {
++              error("Error allocating memory.");
++              goto out;
++      }
++      if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
++                                 msg, NULL, NULL, NULL, success) <= 0) {
++              error("Error sending audit message.");
++              goto out;
++      }
++      rc = 0;
++      out:
++      free(msg);
++      freecon(default_raw);
++      freecon(selected_raw);
++      close(audit_fd);
++#endif
++      return rc;
++}
++
++static int
++mls_range_allowed(security_context_t src, security_context_t dst)
++{
++      struct av_decision avd;
++      int retval;
++      unsigned int bit = CONTEXT__CONTAINS;
++
++      debug("%s: src:%s dst:%s", __func__, src, dst);
++      retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd);
++      if (retval || ((bit & avd.allowed) != bit))
++              return 0;
++
++      return 1;
++}
++
++static int
++get_user_context(const char *sename, const char *role, const char *lvl,
++      security_context_t *sc) {
++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
++      if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) {
++              /* User may have requested a level completely outside of his 
++                 allowed range. We get a context just for auditing as the
++                 range check below will certainly fail for default context. */
++#endif
++              if (get_default_context(sename, NULL, sc) != 0) {
++                      *sc = NULL;
++                      return -1;
++              }
++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
++      }
++#endif
++      if (role != NULL && role[0]) {
++              context_t con;
++              char *type=NULL;
++              if (get_default_type(role, &type) != 0) {
++                      error("get_default_type: failed to get default type for '%s'",
++                              role);
++                      goto out;
++              }
++              con = context_new(*sc);
++              if (!con) {
++                      goto out;
++              }
++              context_role_set(con, role);
++              context_type_set(con, type);
++              freecon(*sc);
++              *sc = strdup(context_str(con));
++              context_free(con);
++              if (!*sc) 
++                      return -1;
++      }
++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
++      if (lvl != NULL && lvl[0]) {
++              /* verify that the requested range is obtained */
++              context_t con;
++              security_context_t obtained_raw;
++              security_context_t requested_raw;
++              con = context_new(*sc);
++              if (!con) {
++                      goto out;
++              }
++              context_range_set(con, lvl);
++              if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) {
++                      context_free(con);
++                      goto out;
++              }
++              if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) {
++                      freecon(obtained_raw);
++                      context_free(con);
++                      goto out;
++              }
++
++              debug("get_user_context: obtained context '%s' requested context '%s'",
++                      obtained_raw, requested_raw);
++              if (strcmp(obtained_raw, requested_raw)) {
++                      /* set the context to the real requested one but fail */
++                      freecon(requested_raw);
++                      freecon(obtained_raw);
++                      freecon(*sc);
++                      *sc = strdup(context_str(con));
++                      context_free(con);
++                      return -1;
++              }
++              freecon(requested_raw);
++              freecon(obtained_raw);
++              context_free(con);
++      }
++#endif
++      return 0;
++      out:
++      freecon(*sc);
++      *sc = NULL;
++      return -1;
++}
++
+ static void
+ ssh_selinux_get_role_level(char **role, const char **level)
+ {
+@@ -65,14 +216,16 @@ ssh_selinux_get_role_level(char **role, 
+ }
+ /* Return the default security context for the given username */
+-static security_context_t
+-ssh_selinux_getctxbyname(char *pwname)
++static int
++ssh_selinux_getctxbyname(char *pwname,
++      security_context_t *default_sc, security_context_t *user_sc)
+ {
+       security_context_t sc = NULL;
+       char *sename, *lvl;
+       char *role;
+       const char *reqlvl;
+       int r = 0;
++      context_t con;
+       ssh_selinux_get_role_level(&role, &reqlvl);
+ #ifdef HAVE_GETSEUSERBYNAME
+@@ -82,38 +235,63 @@ ssh_selinux_getctxbyname(char *pwname)
+       }
+ #else
+       sename = pwname;
+-      lvl = NULL;
++      lvl = "";
+ #endif
+       if (r == 0) {
+ #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+-              if (role != NULL && role[0])
+-                      r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc);
+-              else
+-                      r = get_default_context_with_level(sename, lvl, NULL, &sc);
++              r = get_default_context_with_level(sename, lvl, NULL, default_sc);
+ #else
+-              if (role != NULL && role[0])
+-                      r = get_default_context_with_role(sename, role, NULL, &sc);
+-              else
+-                      r = get_default_context(sename, NULL, &sc);
++              r = get_default_context(sename, NULL, default_sc);
+ #endif
+       }
+-      if (r != 0) {
+-              switch (security_getenforce()) {
+-              case -1:
+-                      fatal("%s: ssh_selinux_getctxbyname: "
+-                          "security_getenforce() failed", __func__);
+-              case 0:
+-                      error("%s: Failed to get default SELinux security "
+-                          "context for %s", __func__, pwname);
+-                      break;
+-              default:
+-                      fatal("%s: Failed to get default SELinux security "
+-                          "context for %s (in enforcing mode)",
+-                          __func__, pwname);
++      if (r == 0) {
++              /* If launched from xinetd, we must use current level */
++              if (inetd_flag && !rexeced_flag) {
++                      security_context_t sshdsc=NULL;
++
++                      if (getcon_raw(&sshdsc) < 0)
++                              fatal("failed to allocate security context");
++
++                      if ((con=context_new(sshdsc)) == NULL)
++                              fatal("failed to allocate selinux context");
++                      reqlvl = context_range_get(con);
++                      freecon(sshdsc);
++                      if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0)
++                          /* we actually don't change level */
++                          reqlvl = "";
++
++                      debug("%s: current connection level '%s'", __func__, reqlvl);
++              }
++              
++              if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) {
++                      r = get_user_context(sename, role, reqlvl, user_sc);
++              
++                      if (r == 0 && reqlvl != NULL && reqlvl[0]) {
++                              security_context_t default_level_sc = *default_sc;
++                              if (role != NULL && role[0]) {
++                                      if (get_user_context(sename, role, lvl, &default_level_sc) < 0)
++                                              default_level_sc = *default_sc;
++                              }
++                              /* verify that the requested range is contained in the user range */
++                              if (mls_range_allowed(default_level_sc, *user_sc)) {
++                                      logit("permit MLS level %s (user range %s)", reqlvl, lvl);
++                              } else {
++                                      r = -1;
++                                      error("deny MLS level %s (user range %s)", reqlvl, lvl);
++                              }
++                              if (default_level_sc != *default_sc)
++                                      freecon(default_level_sc);
++                      }
++              } else {
++                      *user_sc = *default_sc;
+               }
+       }
++      if (r != 0) {
++              error("%s: Failed to get default SELinux security "
++                  "context for %s", __func__, pwname);
++      }
+ #ifdef HAVE_GETSEUSERBYNAME
+       if (sename != NULL)
+@@ -121,8 +299,12 @@ ssh_selinux_getctxbyname(char *pwname)
+       if (lvl != NULL)
+               xfree(lvl);
+ #endif
+-
+-      return (sc);
++      if (role != NULL)
++              xfree(role);
++      if (con)
++              context_free(con);
++ 
++      return (r);
+ }
+ /* Setup environment variables for pam_selinux */
+@@ -160,6 +342,8 @@ void
+ ssh_selinux_setup_exec_context(char *pwname)
+ {
+       security_context_t user_ctx = NULL;
++      int r = 0;
++      security_context_t default_ctx = NULL;
+       if (!ssh_selinux_enabled())
+               return;
+@@ -184,22 +368,45 @@ ssh_selinux_setup_exec_context(char *pwn
+       debug3("%s: setting execution context", __func__);
+-      user_ctx = ssh_selinux_getctxbyname(pwname);
+-      if (setexeccon(user_ctx) != 0) {
++      r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx);
++      if (r >= 0) {
++              r = setexeccon(user_ctx);
++              if (r < 0) {
++                      error("%s: Failed to set SELinux execution context %s for %s",
++                          __func__, user_ctx, pwname);
++              } 
++#ifdef HAVE_SETKEYCREATECON
++              else if (setkeycreatecon(user_ctx) < 0) {
++                      error("%s: Failed to set SELinux keyring creation context %s for %s",
++                          __func__, user_ctx, pwname);
++              }
++#endif
++      }
++      if (user_ctx == NULL) {
++              user_ctx = default_ctx;
++      }
++      if (r < 0 || user_ctx != default_ctx) {
++              /* audit just the case when user changed a role or there was
++                 a failure */
++              send_audit_message(r >= 0, default_ctx, user_ctx);
++      }
++      if (r < 0) {
+               switch (security_getenforce()) {
+               case -1:
+                       fatal("%s: security_getenforce() failed", __func__);
+               case 0:
+-                      error("%s: Failed to set SELinux execution "
+-                          "context for %s", __func__, pwname);
++                      error("%s: SELinux failure. Continuing in permissive mode.",
++                          __func__);
+                       break;
+               default:
+-                      fatal("%s: Failed to set SELinux execution context "
+-                          "for %s (in enforcing mode)", __func__, pwname);
++                      fatal("%s: SELinux failure. Aborting connection.",
++                          __func__);
+               }
+       }
+-      if (user_ctx != NULL)
++      if (user_ctx != NULL && user_ctx != default_ctx)
+               freecon(user_ctx);
++      if (default_ctx != NULL)
++              freecon(default_ctx);
+       debug3("%s: done", __func__);
+ }
+@@ -217,7 +424,10 @@ ssh_selinux_setup_pty(char *pwname, cons
+       debug3("%s: setting TTY context on %s", __func__, tty);
+-      user_ctx = ssh_selinux_getctxbyname(pwname);
++      if (getexeccon(&user_ctx) < 0) {
++              error("%s: getexeccon: %s", __func__, strerror(errno));
++              goto out;
++      }
+       /* XXX: should these calls fatal() upon failure in enforcing mode? */
+diff -up openssh-5.8p1/sshd.c.mls openssh-5.8p1/sshd.c
+--- openssh-5.8p1/sshd.c.mls   2011-02-12 15:05:05.000000000 +0100
++++ openssh-5.8p1/sshd.c       2011-02-12 15:05:06.000000000 +0100
+@@ -2011,6 +2011,9 @@ main(int ac, char **av)
+               restore_uid();
+       }
+ #endif
++#ifdef WITH_SELINUX
++      ssh_selinux_setup_exec_context(authctxt->pw->pw_name);
++#endif
+ #ifdef USE_PAM
+       if (options.use_pam) {
+               do_pam_setcred(1);
diff --git a/pkgs/core/openssh/patches/openssh-5.8p1-randclean.patch b/pkgs/core/openssh/patches/openssh-5.8p1-randclean.patch
new file mode 100644 (file)
index 0000000..378f367
--- /dev/null
@@ -0,0 +1,13 @@
+diff -up openssh-5.8p1/entropy.c.randclean openssh-5.8p1/entropy.c
+--- openssh-5.8p1/entropy.c.randclean  2011-01-13 11:05:29.000000000 +0100
++++ openssh-5.8p1/entropy.c    2011-02-14 00:26:31.000000000 +0100
+@@ -159,6 +159,9 @@ init_rng(void)
+               fatal("OpenSSL version mismatch. Built against %lx, you "
+                   "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
++      /* clean the PRNG status when exiting the program */
++      atexit(RAND_cleanup);
++
+ #ifndef OPENSSL_PRNG_ONLY
+       original_uid = getuid();
+       original_euid = geteuid();
diff --git a/pkgs/core/openssh/patches/openssh-5.8p1-selinux-role.patch b/pkgs/core/openssh/patches/openssh-5.8p1-selinux-role.patch
new file mode 100644 (file)
index 0000000..f29ad9a
--- /dev/null
@@ -0,0 +1,611 @@
+diff -up openssh-5.8p1/auth1.c.role openssh-5.8p1/auth1.c
+--- openssh-5.8p1/auth1.c.role 2010-08-31 14:36:39.000000000 +0200
++++ openssh-5.8p1/auth1.c      2011-02-12 14:34:11.000000000 +0100
+@@ -384,6 +384,9 @@ do_authentication(Authctxt *authctxt)
+ {
+       u_int ulen;
+       char *user, *style = NULL;
++#ifdef WITH_SELINUX
++      char *role=NULL;
++#endif
+       /* Get the name of the user that we wish to log in as. */
+       packet_read_expect(SSH_CMSG_USER);
+@@ -392,11 +395,24 @@ do_authentication(Authctxt *authctxt)
+       user = packet_get_cstring(&ulen);
+       packet_check_eom();
++#ifdef WITH_SELINUX
++      if ((role = strchr(user, '/')) != NULL)
++              *role++ = '\0';
++#endif
++
+       if ((style = strchr(user, ':')) != NULL)
+               *style++ = '\0';
++#ifdef WITH_SELINUX
++      else
++              if (role && (style = strchr(role, ':')) != NULL)
++                      *style++ = '\0';
++#endif
+       authctxt->user = user;
+       authctxt->style = style;
++#ifdef WITH_SELINUX
++      authctxt->role = role;
++#endif
+       /* Verify that the user is a valid user. */
+       if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
+diff -up openssh-5.8p1/auth2.c.role openssh-5.8p1/auth2.c
+--- openssh-5.8p1/auth2.c.role 2010-08-31 14:36:39.000000000 +0200
++++ openssh-5.8p1/auth2.c      2011-02-12 14:34:11.000000000 +0100
+@@ -216,6 +216,9 @@ input_userauth_request(int type, u_int32
+       Authctxt *authctxt = ctxt;
+       Authmethod *m = NULL;
+       char *user, *service, *method, *style = NULL;
++#ifdef WITH_SELINUX
++      char *role = NULL;
++#endif
+       int authenticated = 0;
+       if (authctxt == NULL)
+@@ -227,6 +230,11 @@ input_userauth_request(int type, u_int32
+       debug("userauth-request for user %s service %s method %s", user, service, method);
+       debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
++#ifdef WITH_SELINUX
++      if ((role = strchr(user, '/')) != NULL)
++              *role++ = 0;
++#endif
++
+       if ((style = strchr(user, ':')) != NULL)
+               *style++ = 0;
+@@ -252,8 +260,15 @@ input_userauth_request(int type, u_int32
+                   use_privsep ? " [net]" : "");
+               authctxt->service = xstrdup(service);
+               authctxt->style = style ? xstrdup(style) : NULL;
+-              if (use_privsep)
++#ifdef WITH_SELINUX
++              authctxt->role = role ? xstrdup(role) : NULL;
++#endif
++              if (use_privsep) {
+                       mm_inform_authserv(service, style);
++#ifdef WITH_SELINUX
++                      mm_inform_authrole(role);
++#endif
++              }
+               userauth_banner();
+       } else if (strcmp(user, authctxt->user) != 0 ||
+           strcmp(service, authctxt->service) != 0) {
+diff -up openssh-5.8p1/auth2-gss.c.role openssh-5.8p1/auth2-gss.c
+--- openssh-5.8p1/auth2-gss.c.role     2007-12-02 12:59:45.000000000 +0100
++++ openssh-5.8p1/auth2-gss.c  2011-02-12 14:34:11.000000000 +0100
+@@ -258,6 +258,7 @@ input_gssapi_mic(int type, u_int32_t ple
+       Authctxt *authctxt = ctxt;
+       Gssctxt *gssctxt;
+       int authenticated = 0;
++      char *micuser;
+       Buffer b;
+       gss_buffer_desc mic, gssbuf;
+       u_int len;
+@@ -270,7 +271,13 @@ input_gssapi_mic(int type, u_int32_t ple
+       mic.value = packet_get_string(&len);
+       mic.length = len;
+-      ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service,
++#ifdef WITH_SELINUX
++      if (authctxt->role && (strlen(authctxt->role) > 0))
++              xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role);
++      else
++#endif
++              micuser = authctxt->user;
++      ssh_gssapi_buildmic(&b, micuser, authctxt->service,
+           "gssapi-with-mic");
+       gssbuf.value = buffer_ptr(&b);
+@@ -282,6 +289,8 @@ input_gssapi_mic(int type, u_int32_t ple
+               logit("GSSAPI MIC check failed");
+       buffer_free(&b);
++      if (micuser != authctxt->user)
++              xfree(micuser);
+       xfree(mic.value);
+       authctxt->postponed = 0;
+diff -up openssh-5.8p1/auth2-hostbased.c.role openssh-5.8p1/auth2-hostbased.c
+--- openssh-5.8p1/auth2-hostbased.c.role       2011-02-12 14:34:10.000000000 +0100
++++ openssh-5.8p1/auth2-hostbased.c    2011-02-12 14:34:11.000000000 +0100
+@@ -106,7 +106,15 @@ userauth_hostbased(Authctxt *authctxt)
+       buffer_put_string(&b, session_id2, session_id2_len);
+       /* reconstruct packet */
+       buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+-      buffer_put_cstring(&b, authctxt->user);
++#ifdef WITH_SELINUX
++      if (authctxt->role) {
++              buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1);
++              buffer_append(&b, authctxt->user, strlen(authctxt->user));
++              buffer_put_char(&b, '/');
++              buffer_append(&b, authctxt->role, strlen(authctxt->role));
++      } else 
++#endif
++              buffer_put_cstring(&b, authctxt->user);
+       buffer_put_cstring(&b, service);
+       buffer_put_cstring(&b, "hostbased");
+       buffer_put_string(&b, pkalg, alen);
+diff -up openssh-5.8p1/auth2-pubkey.c.role openssh-5.8p1/auth2-pubkey.c
+--- openssh-5.8p1/auth2-pubkey.c.role  2011-02-12 14:34:11.000000000 +0100
++++ openssh-5.8p1/auth2-pubkey.c       2011-02-12 14:34:11.000000000 +0100
+@@ -122,7 +122,15 @@ userauth_pubkey(Authctxt *authctxt)
+               }
+               /* reconstruct packet */
+               buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+-              buffer_put_cstring(&b, authctxt->user);
++#ifdef WITH_SELINUX
++              if (authctxt->role) {
++                      buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1);
++                      buffer_append(&b, authctxt->user, strlen(authctxt->user));
++                      buffer_put_char(&b, '/');
++                      buffer_append(&b, authctxt->role, strlen(authctxt->role));
++              } else 
++#endif
++                      buffer_put_cstring(&b, authctxt->user);
+               buffer_put_cstring(&b,
+                   datafellows & SSH_BUG_PKSERVICE ?
+                   "ssh-userauth" :
+diff -up openssh-5.8p1/auth.h.role openssh-5.8p1/auth.h
+--- openssh-5.8p1/auth.h.role  2011-02-12 14:34:10.000000000 +0100
++++ openssh-5.8p1/auth.h       2011-02-12 14:34:11.000000000 +0100
+@@ -58,6 +58,9 @@ struct Authctxt {
+       char            *service;
+       struct passwd   *pw;            /* set if 'valid' */
+       char            *style;
++#ifdef WITH_SELINUX
++      char            *role;
++#endif
+       void            *kbdintctxt;
+       void            *jpake_ctx;
+ #ifdef BSD_AUTH
+diff -up openssh-5.8p1/auth-pam.c.role openssh-5.8p1/auth-pam.c
+--- openssh-5.8p1/auth-pam.c.role      2009-07-12 14:07:21.000000000 +0200
++++ openssh-5.8p1/auth-pam.c   2011-02-12 14:34:11.000000000 +0100
+@@ -1069,7 +1069,7 @@ is_pam_session_open(void)
+  * during the ssh authentication process.
+  */
+ int
+-do_pam_putenv(char *name, char *value)
++do_pam_putenv(char *name, const char *value)
+ {
+       int ret = 1;
+ #ifdef HAVE_PAM_PUTENV
+diff -up openssh-5.8p1/auth-pam.h.role openssh-5.8p1/auth-pam.h
+--- openssh-5.8p1/auth-pam.h.role      2004-09-11 14:17:26.000000000 +0200
++++ openssh-5.8p1/auth-pam.h   2011-02-12 14:34:11.000000000 +0100
+@@ -38,7 +38,7 @@ void do_pam_session(void);
+ void do_pam_set_tty(const char *);
+ void do_pam_setcred(int );
+ void do_pam_chauthtok(void);
+-int do_pam_putenv(char *, char *);
++int do_pam_putenv(char *, const char *);
+ char ** fetch_pam_environment(void);
+ char ** fetch_pam_child_environment(void);
+ void free_pam_environment(char **);
+diff -up openssh-5.8p1/monitor.c.role openssh-5.8p1/monitor.c
+--- openssh-5.8p1/monitor.c.role       2011-02-12 14:34:11.000000000 +0100
++++ openssh-5.8p1/monitor.c    2011-02-12 14:34:11.000000000 +0100
+@@ -138,6 +138,9 @@ int mm_answer_sign(int, Buffer *);
+ int mm_answer_pwnamallow(int, Buffer *);
+ int mm_answer_auth2_read_banner(int, Buffer *);
+ int mm_answer_authserv(int, Buffer *);
++#ifdef WITH_SELINUX
++int mm_answer_authrole(int, Buffer *);
++#endif
+ int mm_answer_authpassword(int, Buffer *);
+ int mm_answer_bsdauthquery(int, Buffer *);
+ int mm_answer_bsdauthrespond(int, Buffer *);
+@@ -218,6 +221,9 @@ struct mon_table mon_dispatch_proto20[] 
+     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
+     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
+     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
++#ifdef WITH_SELINUX
++    {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole},
++#endif
+     {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
+     {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
+ #ifdef USE_PAM
+@@ -703,6 +709,9 @@ mm_answer_pwnamallow(int sock, Buffer *m
+       else {
+               /* Allow service/style information on the auth context */
+               monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
++#ifdef WITH_SELINUX
++              monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1);
++#endif
+               monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
+       }
+@@ -747,6 +756,25 @@ mm_answer_authserv(int sock, Buffer *m)
+       return (0);
+ }
++#ifdef WITH_SELINUX
++int
++mm_answer_authrole(int sock, Buffer *m)
++{
++      monitor_permit_authentications(1);
++
++      authctxt->role = buffer_get_string(m, NULL);
++      debug3("%s: role=%s",
++          __func__, authctxt->role);
++
++      if (strlen(authctxt->role) == 0) {
++              xfree(authctxt->role);
++              authctxt->role = NULL;
++      }
++
++      return (0);
++}
++#endif
++
+ int
+ mm_answer_authpassword(int sock, Buffer *m)
+ {
+@@ -1112,7 +1140,7 @@ static int
+ monitor_valid_userblob(u_char *data, u_int datalen)
+ {
+       Buffer b;
+-      char *p;
++      char *p, *r;
+       u_int len;
+       int fail = 0;
+@@ -1138,6 +1166,8 @@ monitor_valid_userblob(u_char *data, u_i
+       if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+               fail++;
+       p = buffer_get_string(&b, NULL);
++      if ((r = strchr(p, '/')) != NULL)
++              *r = '\0';
+       if (strcmp(authctxt->user, p) != 0) {
+               logit("wrong user name passed to monitor: expected %s != %.100s",
+                   authctxt->user, p);
+@@ -1169,7 +1199,7 @@ monitor_valid_hostbasedblob(u_char *data
+     char *chost)
+ {
+       Buffer b;
+-      char *p;
++      char *p, *r;
+       u_int len;
+       int fail = 0;
+@@ -1186,6 +1216,8 @@ monitor_valid_hostbasedblob(u_char *data
+       if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+               fail++;
+       p = buffer_get_string(&b, NULL);
++      if ((r = strchr(p, '/')) != NULL)
++              *r = '\0';
+       if (strcmp(authctxt->user, p) != 0) {
+               logit("wrong user name passed to monitor: expected %s != %.100s",
+                   authctxt->user, p);
+diff -up openssh-5.8p1/monitor.h.role openssh-5.8p1/monitor.h
+--- openssh-5.8p1/monitor.h.role       2011-02-12 14:34:11.000000000 +0100
++++ openssh-5.8p1/monitor.h    2011-02-12 14:34:11.000000000 +0100
+@@ -31,6 +31,9 @@
+ enum monitor_reqtype {
+       MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
+       MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
++#ifdef WITH_SELINUX
++      MONITOR_REQ_AUTHROLE,
++#endif
+       MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
+       MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
+       MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER,
+diff -up openssh-5.8p1/monitor_wrap.c.role openssh-5.8p1/monitor_wrap.c
+--- openssh-5.8p1/monitor_wrap.c.role  2011-02-12 14:34:11.000000000 +0100
++++ openssh-5.8p1/monitor_wrap.c       2011-02-12 14:34:11.000000000 +0100
+@@ -298,6 +298,25 @@ mm_inform_authserv(char *service, char *
+       buffer_free(&m);
+ }
++/* Inform the privileged process about role */
++
++#ifdef WITH_SELINUX
++void
++mm_inform_authrole(char *role)
++{
++      Buffer m;
++
++      debug3("%s entering", __func__);
++
++      buffer_init(&m);
++      buffer_put_cstring(&m, role ? role : "");
++
++      mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m);
++
++      buffer_free(&m);
++}
++#endif
++
+ /* Do the password authentication */
+ int
+ mm_auth_password(Authctxt *authctxt, char *password)
+diff -up openssh-5.8p1/monitor_wrap.h.role openssh-5.8p1/monitor_wrap.h
+--- openssh-5.8p1/monitor_wrap.h.role  2011-02-12 14:34:11.000000000 +0100
++++ openssh-5.8p1/monitor_wrap.h       2011-02-12 14:34:11.000000000 +0100
+@@ -41,6 +41,9 @@ int mm_is_monitor(void);
+ DH *mm_choose_dh(int, int, int);
+ int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
+ void mm_inform_authserv(char *, char *);
++#ifdef WITH_SELINUX
++void mm_inform_authrole(char *);
++#endif
+ struct passwd *mm_getpwnamallow(const char *);
+ char *mm_auth2_read_banner(void);
+ int mm_auth_password(struct Authctxt *, char *);
+diff -up openssh-5.8p1/openbsd-compat/Makefile.in.role openssh-5.8p1/openbsd-compat/Makefile.in
+--- openssh-5.8p1/openbsd-compat/Makefile.in.role      2010-10-07 13:19:24.000000000 +0200
++++ openssh-5.8p1/openbsd-compat/Makefile.in   2011-02-12 14:34:11.000000000 +0100
+@@ -20,7 +20,7 @@ OPENBSD=base64.o basename.o bindresvport
+ COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o
+-PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o
++PORTS=port-aix.o port-irix.o port-linux.o port-linux_part_2.o port-solaris.o port-tun.o port-uw.o
+ .c.o:
+       $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+diff -up openssh-5.8p1/openbsd-compat/port-linux.c.role openssh-5.8p1/openbsd-compat/port-linux.c
+--- openssh-5.8p1/openbsd-compat/port-linux.c.role     2011-02-12 14:34:11.000000000 +0100
++++ openssh-5.8p1/openbsd-compat/port-linux.c  2011-02-12 14:37:31.000000000 +0100
+@@ -31,48 +31,73 @@
+ #include "log.h"
+ #include "xmalloc.h"
++#include "servconf.h"
+ #include "port-linux.h"
++#include "key.h"
++#include "hostfile.h"
++#include "auth.h"
+ #ifdef WITH_SELINUX
+ #include <selinux/selinux.h>
+ #include <selinux/flask.h>
+ #include <selinux/get_context_list.h>
+-/* Wrapper around is_selinux_enabled() to log its return value once only */
+-int
+-ssh_selinux_enabled(void)
+-{
+-      static int enabled = -1;
++extern ServerOptions options;
++extern Authctxt *the_authctxt;
++extern int inetd_flag;
++extern int rexeced_flag;
+-      if (enabled == -1) {
+-              enabled = (is_selinux_enabled() == 1);
+-              debug("SELinux support %s", enabled ? "enabled" : "disabled");
++static void
++ssh_selinux_get_role_level(char **role, const char **level)
++{
++      *role = NULL;
++      *level = NULL;
++      if (the_authctxt) {
++              if (the_authctxt->role != NULL) {
++                      char *slash;
++                      *role = xstrdup(the_authctxt->role);
++                      if ((slash = strchr(*role, '/')) != NULL) {
++                              *slash = '\0';
++                              *level = slash + 1;
++                      }
++              }
+       }
+-
+-      return (enabled);
+ }
+ /* Return the default security context for the given username */
+ static security_context_t
+ ssh_selinux_getctxbyname(char *pwname)
+ {
+-      security_context_t sc;
+-      char *sename = NULL, *lvl = NULL;
+-      int r;
++      security_context_t sc = NULL;
++      char *sename, *lvl;
++      char *role;
++      const char *reqlvl;
++      int r = 0;
++      ssh_selinux_get_role_level(&role, &reqlvl);
+ #ifdef HAVE_GETSEUSERBYNAME
+-      if (getseuserbyname(pwname, &sename, &lvl) != 0)
+-              return NULL;
++      if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) {
++              sename = NULL;
++              lvl = NULL;
++      }
+ #else
+       sename = pwname;
+       lvl = NULL;
+ #endif
++      if (r == 0) {
+ #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
+-      r = get_default_context_with_level(sename, lvl, NULL, &sc);
++              if (role != NULL && role[0])
++                      r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc);
++              else
++                      r = get_default_context_with_level(sename, lvl, NULL, &sc);
+ #else
+-      r = get_default_context(sename, NULL, &sc);
++              if (role != NULL && role[0])
++                      r = get_default_context_with_role(sename, role, NULL, &sc);
++              else
++                      r = get_default_context(sename, NULL, &sc);
+ #endif
++      }
+       if (r != 0) {
+               switch (security_getenforce()) {
+@@ -100,6 +125,36 @@ ssh_selinux_getctxbyname(char *pwname)
+       return (sc);
+ }
++/* Setup environment variables for pam_selinux */
++static int
++ssh_selinux_setup_pam_variables(void)
++{
++      const char *reqlvl;
++      char *role;
++      char *use_current;
++      int rv;
++
++      debug3("%s: setting execution context", __func__);
++
++      ssh_selinux_get_role_level(&role, &reqlvl);
++
++      rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : "");
++      
++      if (inetd_flag && !rexeced_flag) {
++              use_current = "1";
++      } else {
++              use_current = "";
++              rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: "");
++      }
++
++      rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current);
++
++      if (role != NULL)
++              xfree(role);
++      
++      return rv;
++}
++
+ /* Set the execution context to the default for the specified user */
+ void
+ ssh_selinux_setup_exec_context(char *pwname)
+@@ -109,6 +164,24 @@ ssh_selinux_setup_exec_context(char *pwn
+       if (!ssh_selinux_enabled())
+               return;
++      if (options.use_pam) {
++              /* do not compute context, just setup environment for pam_selinux */
++              if (ssh_selinux_setup_pam_variables()) {
++                      switch (security_getenforce()) {
++                      case -1:
++                              fatal("%s: security_getenforce() failed", __func__);
++                      case 0:
++                              error("%s: SELinux PAM variable setup failure. Continuing in permissive mode.",
++                                  __func__);
++                      break;
++                      default:
++                              fatal("%s: SELinux PAM variable setup failure. Aborting connection.",
++                                  __func__);
++                      }
++              }
++              return;
++      }
++
+       debug3("%s: setting execution context", __func__);
+       user_ctx = ssh_selinux_getctxbyname(pwname);
+@@ -206,21 +279,6 @@ ssh_selinux_change_context(const char *n
+       xfree(newctx);
+ }
+-void
+-ssh_selinux_setfscreatecon(const char *path)
+-{
+-      security_context_t context;
+-
+-      if (!ssh_selinux_enabled())
+-              return;
+-      if (path == NULL) {
+-              setfscreatecon(NULL);
+-              return;
+-      }
+-      if (matchpathcon(path, 0700, &context) == 0)
+-              setfscreatecon(context);
+-}
+-
+ #endif /* WITH_SELINUX */
+ #ifdef LINUX_OOM_ADJUST
+diff -up openssh-5.8p1/openbsd-compat/port-linux_part_2.c.role openssh-5.8p1/openbsd-compat/port-linux_part_2.c
+--- openssh-5.8p1/openbsd-compat/port-linux_part_2.c.role      2011-02-12 14:34:11.000000000 +0100
++++ openssh-5.8p1/openbsd-compat/port-linux_part_2.c   2011-02-12 14:34:11.000000000 +0100
+@@ -0,0 +1,75 @@
++/* $Id: port-linux.c,v 1.11.4.2 2011/02/04 00:43:08 djm Exp $ */
++
++/*
++ * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com>
++ * Copyright (c) 2006 Damien Miller <djm@openbsd.org>
++ *
++ * Permission to use, copy, modify, and distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++/*
++ * Linux-specific portability code - just SELinux support at present
++ */
++
++#include "includes.h"
++
++#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST)
++#include <errno.h>
++#include <stdarg.h>
++#include <string.h>
++#include <stdio.h>
++
++#include "log.h"
++#include "xmalloc.h"
++#include "port-linux.h"
++#include "key.h"
++#include "hostfile.h"
++#include "auth.h"
++
++#ifdef WITH_SELINUX
++#include <selinux/selinux.h>
++#include <selinux/flask.h>
++#include <selinux/get_context_list.h>
++
++/* Wrapper around is_selinux_enabled() to log its return value once only */
++int
++ssh_selinux_enabled(void)
++{
++      static int enabled = -1;
++
++      if (enabled == -1) {
++              enabled = (is_selinux_enabled() == 1);
++              debug("SELinux support %s", enabled ? "enabled" : "disabled");
++      }
++
++      return (enabled);
++}
++
++void
++ssh_selinux_setfscreatecon(const char *path)
++{
++      security_context_t context;
++
++      if (!ssh_selinux_enabled())
++              return;
++      if (path == NULL) {
++              setfscreatecon(NULL);
++              return;
++      }
++      if (matchpathcon(path, 0700, &context) == 0)
++              setfscreatecon(context);
++}
++
++#endif /* WITH_SELINUX */
++
++#endif /* WITH_SELINUX || LINUX_OOM_ADJUST */
diff --git a/pkgs/core/openssh/patches/openssh-5.8p1-selinux.patch b/pkgs/core/openssh/patches/openssh-5.8p1-selinux.patch
new file mode 100644 (file)
index 0000000..6967cbd
--- /dev/null
@@ -0,0 +1,12 @@
+diff -up openssh-5.8p1/openbsd-compat/port-linux.c.selinux openssh-5.8p1/openbsd-compat/port-linux.c
+--- openssh-5.8p1/openbsd-compat/port-linux.c.selinux  2011-02-12 09:38:45.000000000 +0100
++++ openssh-5.8p1/openbsd-compat/port-linux.c  2011-02-12 09:39:10.000000000 +0100
+@@ -213,7 +213,7 @@ ssh_selinux_setfscreatecon(const char *p
+       if (!ssh_selinux_enabled())
+               return;
+-      if (path == NULL)
++      if (path == NULL) {
+               setfscreatecon(NULL);
+               return;
+       }