From: Stefan Schantl Date: Sun, 27 Feb 2011 15:57:04 +0000 (+0100) Subject: openssh: Update to 5.8p1. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=852f4e06c18a73c01fce4e7996252209728e8a5d;p=ipfire-3.x.git openssh: Update to 5.8p1. * Aktivate selinux support. * Aktivate audit support. * Add a bunch of patches to fix errors and provide new features. Fixes #130. --- diff --git a/pkgs/core/openssh/openssh.nm b/pkgs/core/openssh/openssh.nm index 046d96184..9ba7dc5f1 100644 --- a/pkgs/core/openssh/openssh.nm +++ b/pkgs/core/openssh/openssh.nm @@ -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 index 000000000..e9dc835ea --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-4.3p2-askpass-grab-info.patch @@ -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 index 000000000..ec93b87fd --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.1p1-askpass-progress.patch @@ -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 + #include + #include ++#include + #include + #include + +@@ -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 index 000000000..e314a05a2 --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.1p1-scp-manpage.patch @@ -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 index 000000000..96aaab1d0 --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.2p1-allow-ip-opts.patch @@ -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 index 000000000..f3e431eeb --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.2p1-edns.patch @@ -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 index 000000000..cac5d5e1d --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.5p1-x11.patch @@ -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 index 000000000..278dfa153 --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.6p1-exit-deadlock.patch @@ -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 index 000000000..9d7fce220 --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.6p1-keygen.patch @@ -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 index 000000000..f4560a944 --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.6p1-redhat.patch @@ -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 index 000000000..356adfaef --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.8p1-authorized-keys-command.patch @@ -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 + #include ++#include + + #include + #include +@@ -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 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 index 000000000..a0438ff6d --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.8p1-fingerprint.patch @@ -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 index 000000000..fcd05d78e --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.8p1-kuserok.patch @@ -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 index 000000000..525e6b534 --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.8p1-mls.patch @@ -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 + #include ++#include + #include ++#include ++#include ++ ++#ifdef HAVE_LINUX_AUDIT ++#include ++#include ++#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 index 000000000..378f3672c --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.8p1-randclean.patch @@ -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 index 000000000..f29ad9a08 --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.8p1-selinux-role.patch @@ -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 + #include + #include + +-/* 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 ++ * Copyright (c) 2006 Damien Miller ++ * ++ * 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 ++#include ++#include ++#include ++ ++#include "log.h" ++#include "xmalloc.h" ++#include "port-linux.h" ++#include "key.h" ++#include "hostfile.h" ++#include "auth.h" ++ ++#ifdef WITH_SELINUX ++#include ++#include ++#include ++ ++/* 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 index 000000000..6967cbdf6 --- /dev/null +++ b/pkgs/core/openssh/patches/openssh-5.8p1-selinux.patch @@ -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; + }