Merge pull request #2 from zombie/openssh:rosa2014.1

7.3p1 update with Mageia Fixes
This commit is contained in:
dsilakov 2016-10-05 12:43:36 +04:00
commit fcb0d6c05b
29 changed files with 9115 additions and 4 deletions

View file

@ -0,0 +1,12 @@
diff -up openssh-5.8p2/ssh-keyscan.c.sigpipe openssh-5.8p2/ssh-keyscan.c
--- openssh-5.8p2/ssh-keyscan.c.sigpipe 2011-08-23 18:30:33.873025916 +0200
+++ openssh-5.8p2/ssh-keyscan.c 2011-08-23 18:32:24.574025362 +0200
@@ -715,6 +715,8 @@ main(int argc, char **argv)
fdlim_set(maxfd);
fdcon = xcalloc(maxfd, sizeof(con));
+ signal(SIGPIPE, SIG_IGN);
+
read_wait_nfdset = howmany(maxfd, NFDBITS);
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask));

View file

@ -0,0 +1,24 @@
diff -up openssh-5.9p0/ssh.1.ipv6man openssh-5.9p0/ssh.1
--- openssh-5.9p0/ssh.1.ipv6man 2011-08-05 22:17:32.000000000 +0200
+++ openssh-5.9p0/ssh.1 2011-08-31 13:08:34.880024485 +0200
@@ -1400,6 +1400,8 @@ manual page for more information.
.Nm
exits with the exit status of the remote command or with 255
if an error occurred.
+.Sh IPV6
+IPv6 address can be used everywhere where IPv4 address. In all entries must be the IPv6 address enclosed in square brackets. Note: The square brackets are metacharacters for the shell and must be escaped in shell.
.Sh SEE ALSO
.Xr scp 1 ,
.Xr sftp 1 ,
diff -up openssh-5.9p0/sshd.8.ipv6man openssh-5.9p0/sshd.8
--- openssh-5.9p0/sshd.8.ipv6man 2011-08-05 22:17:32.000000000 +0200
+++ openssh-5.9p0/sshd.8 2011-08-31 13:10:34.129039094 +0200
@@ -940,6 +940,8 @@ concurrently for different ports, this c
started last).
The content of this file is not sensitive; it can be world-readable.
.El
+.Sh IPV6
+IPv6 address can be used everywhere where IPv4 address. In all entries must be the IPv6 address enclosed in square brackets. Note: The square brackets are metacharacters for the shell and must be escaped in shell.
.Sh SEE ALSO
.Xr scp 1 ,
.Xr sftp 1 ,

View file

@ -0,0 +1,21 @@
diff -up openssh-6.1p1/sshconnect2.c.canohost openssh-6.1p1/sshconnect2.c
--- openssh-6.1p1/sshconnect2.c.canohost 2012-10-30 10:52:59.593301692 +0100
+++ openssh-6.1p1/sshconnect2.c 2012-10-30 11:01:12.870301632 +0100
@@ -699,12 +699,15 @@ userauth_gssapi(Authctxt *authctxt)
static u_int mech = 0;
OM_uint32 min;
int ok = 0;
- const char *gss_host;
+ const char *gss_host = NULL;
if (options.gss_server_identity)
gss_host = options.gss_server_identity;
- else if (options.gss_trust_dns)
+ else if (options.gss_trust_dns) {
gss_host = get_canonical_hostname(1);
+ if ( strcmp( gss_host, "UNKNOWN" ) == 0 )
+ gss_host = authctxt->host;
+ }
else
gss_host = authctxt->host;

156
openssh-6.2p1-vendor.patch Normal file
View file

@ -0,0 +1,156 @@
diff -up openssh-7.0p1/configure.ac.vendor openssh-7.0p1/configure.ac
--- openssh-7.0p1/configure.ac.vendor 2015-08-12 11:14:54.102628399 +0200
+++ openssh-7.0p1/configure.ac 2015-08-12 11:14:54.129628356 +0200
@@ -4776,6 +4776,12 @@ AC_ARG_WITH([lastlog],
fi
]
)
+AC_ARG_ENABLE(vendor-patchlevel,
+ [ --enable-vendor-patchlevel=TAG specify a vendor patch level],
+ [AC_DEFINE_UNQUOTED(SSH_VENDOR_PATCHLEVEL,[SSH_RELEASE "-" "$enableval"],[Define to your vendor patch level, if it has been modified from the upstream source release.])
+ SSH_VENDOR_PATCHLEVEL="$enableval"],
+ [AC_DEFINE(SSH_VENDOR_PATCHLEVEL,SSH_RELEASE,[Define to your vendor patch level, if it has been modified from the upstream source release.])
+ SSH_VENDOR_PATCHLEVEL=none])
dnl lastlog, [uw]tmpx? detection
dnl NOTE: set the paths in the platform section to avoid the
@@ -5038,6 +5044,7 @@ echo " Translate v4 in v6 hack
echo " BSD Auth support: $BSD_AUTH_MSG"
echo " Random number source: $RAND_MSG"
echo " Privsep sandbox style: $SANDBOX_STYLE"
+echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL"
echo ""
diff -up openssh-7.0p1/servconf.c.vendor openssh-7.0p1/servconf.c
--- openssh-7.0p1/servconf.c.vendor 2015-08-11 10:57:29.000000000 +0200
+++ openssh-7.0p1/servconf.c 2015-08-12 11:15:33.201565712 +0200
@@ -149,6 +149,7 @@ initialize_server_options(ServerOptions
options->max_authtries = -1;
options->max_sessions = -1;
options->banner = NULL;
+ options->show_patchlevel = -1;
options->use_dns = -1;
options->client_alive_interval = -1;
options->client_alive_count_max = -1;
@@ -335,6 +336,8 @@ fill_default_server_options(ServerOption
options->ip_qos_bulk = IPTOS_THROUGHPUT;
if (options->version_addendum == NULL)
options->version_addendum = xstrdup("");
+ if (options->show_patchlevel == -1)
+ options->show_patchlevel = 0;
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
options->fwd_opts.streamlocal_bind_mask = 0177;
if (options->fwd_opts.streamlocal_bind_unlink == -1)
@@ -407,7 +410,7 @@ typedef enum {
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes,
sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
- sBanner, sUseDNS, sHostbasedAuthentication,
+ sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
sHostKeyAlgorithms,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
@@ -529,6 +532,7 @@ static struct {
{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
{ "maxsessions", sMaxSessions, SSHCFG_ALL },
{ "banner", sBanner, SSHCFG_ALL },
+ { "showpatchlevel", sShowPatchLevel, SSHCFG_GLOBAL },
{ "usedns", sUseDNS, SSHCFG_GLOBAL },
{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
@@ -1389,6 +1393,10 @@ process_server_config_line(ServerOptions
multistate_ptr = multistate_privsep;
goto parse_multistate;
+ case sShowPatchLevel:
+ intptr = &options->show_patchlevel;
+ goto parse_flag;
+
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_users >= MAX_ALLOW_USERS)
@@ -2266,6 +2274,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sUseLogin, o->use_login);
dump_cfg_fmtint(sCompression, o->compression);
dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
+ dump_cfg_fmtint(sShowPatchLevel, o->show_patchlevel);
dump_cfg_fmtint(sUseDNS, o->use_dns);
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding);
diff -up openssh-7.0p1/servconf.h.vendor openssh-7.0p1/servconf.h
--- openssh-7.0p1/servconf.h.vendor 2015-08-11 10:57:29.000000000 +0200
+++ openssh-7.0p1/servconf.h 2015-08-12 11:14:54.130628355 +0200
@@ -155,6 +155,7 @@ typedef struct {
int max_authtries;
int max_sessions;
char *banner; /* SSH-2 banner message */
+ int show_patchlevel; /* Show vendor patch level to clients */
int use_dns;
int client_alive_interval; /*
* poke the client this often to
diff -up openssh-7.0p1/sshd_config.0.vendor openssh-7.0p1/sshd_config.0
--- openssh-7.0p1/sshd_config.0.vendor 2015-08-12 11:14:54.125628363 +0200
+++ openssh-7.0p1/sshd_config.0 2015-08-12 11:14:54.130628355 +0200
@@ -841,6 +841,11 @@ DESCRIPTION
Defines the number of bits in the ephemeral protocol version 1
server key. The default and minimum value is 1024.
+ ShowPatchLevel
+ Specifies whether sshd will display the specific patch level of
+ the binary in the server identification string. The patch level
+ is set at compile-time. The default is M-bM-^@M-^\noM-bM-^@M-^].
+
StreamLocalBindMask
Sets the octal file creation mode mask (umask) used when creating
a Unix-domain socket file for local or remote port forwarding.
diff -up openssh-7.0p1/sshd_config.5.vendor openssh-7.0p1/sshd_config.5
--- openssh-7.0p1/sshd_config.5.vendor 2015-08-12 11:14:54.125628363 +0200
+++ openssh-7.0p1/sshd_config.5 2015-08-12 11:14:54.131628353 +0200
@@ -1411,6 +1411,13 @@ This option applies to protocol version
.It Cm ServerKeyBits
Defines the number of bits in the ephemeral protocol version 1 server key.
The default and minimum value is 1024.
+.It Cm ShowPatchLevel
+Specifies whether
+.Nm sshd
+will display the patch level of the binary in the identification string.
+The patch level is set at compile-time.
+The default is
+.Dq no .
.It Cm StreamLocalBindMask
Sets the octal file creation mode mask
.Pq umask
diff -up openssh-7.0p1/sshd_config.vendor openssh-7.0p1/sshd_config
--- openssh-7.0p1/sshd_config.vendor 2015-08-12 11:14:54.125628363 +0200
+++ openssh-7.0p1/sshd_config 2015-08-12 11:14:54.131628353 +0200
@@ -119,6 +119,7 @@ UsePrivilegeSeparation sandbox # Defaul
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
+#ShowPatchLevel no
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
diff -up openssh-7.0p1/sshd.c.vendor openssh-7.0p1/sshd.c
--- openssh-7.0p1/sshd.c.vendor 2015-08-12 11:14:54.100628403 +0200
+++ openssh-7.0p1/sshd.c 2015-08-12 11:14:54.131628353 +0200
@@ -432,7 +432,7 @@ sshd_exchange_identification(int sock_in
}
xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s",
- major, minor, SSH_VERSION,
+ major, minor, (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION,
*options.version_addendum == '\0' ? "" : " ",
options.version_addendum, newline);
@@ -1749,7 +1749,8 @@ main(int ac, char **av)
exit(1);
}
- debug("sshd version %s, %s", SSH_VERSION,
+ debug("sshd version %s, %s",
+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION,
#ifdef WITH_OPENSSL
SSLeay_version(SSLEAY_VERSION)
#else

View file

@ -0,0 +1,101 @@
diff -up openssh-5.9p1/cipher-ctr.c.ctr-evp openssh-5.9p1/cipher-ctr.c
--- openssh-5.9p1/cipher-ctr.c.ctr-evp 2012-01-11 09:24:06.000000000 +0100
+++ openssh-5.9p1/cipher-ctr.c 2012-01-11 15:54:04.675956600 +0100
@@ -38,7 +38,7 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, in
struct ssh_aes_ctr_ctx
{
- AES_KEY aes_ctx;
+ EVP_CIPHER_CTX ecbctx;
u_char aes_counter[AES_BLOCK_SIZE];
};
@@ -63,21 +63,42 @@ ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char
{
struct ssh_aes_ctr_ctx *c;
size_t n = 0;
- u_char buf[AES_BLOCK_SIZE];
+ u_char ctrbuf[AES_BLOCK_SIZE*256];
+ u_char buf[AES_BLOCK_SIZE*256];
if (len == 0)
return (1);
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
return (0);
- while ((len--) > 0) {
+ for (; len > 0; len -= sizeof(u_int)) {
+ u_int r,a,b;
+
if (n == 0) {
- AES_encrypt(c->aes_counter, buf, &c->aes_ctx);
- ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
+ int outl, i, buflen;
+
+ buflen = MIN(len, sizeof(ctrbuf));
+
+ for(i = 0; i < buflen; i += AES_BLOCK_SIZE) {
+ memcpy(&ctrbuf[i], c->aes_counter, AES_BLOCK_SIZE);
+ ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE);
+ }
+
+ EVP_EncryptUpdate(&c->ecbctx, buf, &outl,
+ ctrbuf, buflen);
}
- *(dest++) = *(src++) ^ buf[n];
- n = (n + 1) % AES_BLOCK_SIZE;
+
+ memcpy(&a, src, sizeof(a));
+ memcpy(&b, &buf[n], sizeof(b));
+ r = a ^ b;
+ memcpy(dest, &r, sizeof(r));
+ src += sizeof(a);
+ dest += sizeof(r);
+
+ n = (n + sizeof(b)) % sizeof(buf);
}
+ memset(ctrbuf, '\0', sizeof(ctrbuf));
+ memset(buf, '\0', sizeof(buf));
return (1);
}
@@ -91,9 +112,28 @@ ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, co
c = xmalloc(sizeof(*c));
EVP_CIPHER_CTX_set_app_data(ctx, c);
}
- if (key != NULL)
- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
- &c->aes_ctx);
+
+ EVP_CIPHER_CTX_init(&c->ecbctx);
+
+ if (key != NULL) {
+ const EVP_CIPHER *cipher;
+ switch(EVP_CIPHER_CTX_key_length(ctx)*8) {
+ case 128:
+ cipher = EVP_aes_128_ecb();
+ break;
+ case 192:
+ cipher = EVP_aes_192_ecb();
+ break;
+ case 256:
+ cipher = EVP_aes_256_ecb();
+ break;
+ default:
+ fatal("ssh_aes_ctr_init: wrong aes key length");
+ }
+ if(!EVP_EncryptInit_ex(&c->ecbctx, cipher, NULL, key, NULL))
+ fatal("ssh_aes_ctr_init: cannot initialize aes encryption");
+ EVP_CIPHER_CTX_set_padding(&c->ecbctx, 0);
+ }
if (iv != NULL)
memcpy(c->aes_counter, iv, AES_BLOCK_SIZE);
return (1);
@@ -105,6 +145,7 @@ ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx)
struct ssh_aes_ctr_ctx *c;
if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
+ EVP_CIPHER_CTX_cleanup(&c->ecbctx);
memset(c, 0, sizeof(*c));
free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);

View file

@ -0,0 +1,16 @@
diff --git a/scp.c b/scp.c
index d98fa67..25d347b 100644
--- a/scp.c
+++ b/scp.c
@@ -638,7 +638,10 @@ toremote(char *targ, int argc, char **argv)
addargs(&alist, "%s", ssh_program);
addargs(&alist, "-x");
addargs(&alist, "-oClearAllForwardings=yes");
- addargs(&alist, "-n");
+ if (isatty(fileno(stdin)))
+ addargs(&alist, "-t");
+ else
+ addargs(&alist, "-n");
for (j = 0; j < remote_remote_args.num; j++) {
addargs(&alist, "%s",
remote_remote_args.list[j]);

View file

@ -0,0 +1,54 @@
diff -up openssh-6.8p1/compat.c.cisco-dh openssh-6.8p1/compat.c
--- openssh-6.8p1/compat.c.cisco-dh 2015-03-17 06:49:20.000000000 +0100
+++ openssh-6.8p1/compat.c 2015-03-19 12:57:58.862606969 +0100
@@ -167,6 +167,7 @@ compat_datafellows(const char *version)
SSH_BUG_SCANNER },
{ "Probe-*",
SSH_BUG_PROBE },
+ { "Cisco-*", SSH_BUG_MAX4096DH },
{ NULL, 0 }
};
diff -up openssh-6.8p1/compat.h.cisco-dh openssh-6.8p1/compat.h
--- openssh-6.8p1/compat.h.cisco-dh 2015-03-17 06:49:20.000000000 +0100
+++ openssh-6.8p1/compat.h 2015-03-19 12:57:58.862606969 +0100
@@ -60,6 +60,7 @@
#define SSH_NEW_OPENSSH 0x04000000
#define SSH_BUG_DYNAMIC_RPORT 0x08000000
#define SSH_BUG_CURVE25519PAD 0x10000000
+#define SSH_BUG_MAX4096DH 0x20000000
void enable_compat13(void);
void enable_compat20(void);
diff -up openssh-6.8p1/kexgexc.c.cisco-dh openssh-6.8p1/kexgexc.c
--- openssh-6.8p1/kexgexc.c.cisco-dh 2015-03-19 12:57:58.862606969 +0100
+++ openssh-6.8p1/kexgexc.c 2015-03-19 13:11:52.320519969 +0100
@@ -64,8 +64,27 @@ kexgex_client(struct ssh *ssh)
kex->min = DH_GRP_MIN;
kex->max = DH_GRP_MAX;
+
+ /* Servers with MAX4096DH need a preferred size (nbits) <= 4096.
+ * We need to also ensure that min < nbits < max */
+
+ if (datafellows & SSH_BUG_MAX4096DH) {
+ /* The largest min for these servers is 4096 */
+ kex->min = MIN(kex->min, 4096);
+ }
+
kex->nbits = nbits;
- if (ssh->compat & SSH_OLD_DHGEX) {
+ kex->nbits = MIN(nbits, kex->max);
+ kex->nbits = MAX(nbits, kex->min);
+
+ if (ssh->compat & SSH_BUG_MAX4096DH) {
+ /* Cannot have a nbits > 4096 for these servers */
+ kex->nbits = MIN(kex->nbits, 4096);
+ /* nbits has to be powers of two */
+ if (kex->nbits == 3072)
+ kex->nbits = 4096;
+ }
+ if (ssh->compat & SSH_OLD_DHGEX) { /* Old GEX request */
/* Old GEX request */
if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST_OLD))
!= 0 ||

View file

@ -0,0 +1,24 @@
diff --git a/misc.c b/misc.c
index 2f11de4..36402d1 100644
--- a/misc.c
+++ b/misc.c
@@ -396,7 +396,7 @@ hpdelim(char **cp)
return NULL;
else
s++;
- } else if ((s = strpbrk(s, ":/")) == NULL)
+ } else if ((s = strpbrk(s, ":")) == NULL)
s = *cp + strlen(*cp); /* skip to end (see first case below) */
switch (*s) {
@@ -405,7 +405,6 @@ hpdelim(char **cp)
break;
case ':':
- case '/':
*s = '\0'; /* terminate */
*cp = s + 1;
break;
--
2.1.0

View file

@ -0,0 +1,14 @@
--- a/scp.c
+++ a/scp.c
@@ -1084,6 +1084,10 @@ sink(int argc, char **argv)
free(vect[0]);
continue;
}
+ if (buf[0] == 'C' && ! exists && np[strlen(np)-1] == '/') {
+ errno = ENOTDIR;
+ goto bad;
+ }
omode = mode;
mode |= S_IWUSR;
if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
--

View file

@ -0,0 +1,39 @@
diff -up openssh/sshd.c.ip-opts openssh/sshd.c
--- openssh/sshd.c.ip-opts 2016-07-25 13:58:48.998507834 +0200
+++ openssh/sshd.c 2016-07-25 14:01:28.346469878 +0200
@@ -1507,12 +1507,29 @@ check_ip_options(struct ssh *ssh)
if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts,
&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", opts[i]);
- fatal("Connection from %.100s port %d with IP opts: %.800s",
- ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), text);
+ i = 0;
+ do {
+ switch (opts[i]) {
+ case 0:
+ case 1:
+ ++i;
+ break;
+ case 130:
+ case 133:
+ case 134:
+ i += opts[i + 1];
+ break;
+ default:
+ /* 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", opts[i]);
+ fatal("Connection from %.100s port %d with IP options:%.800s",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), text);
+ }
+ } while (i < option_size);
}
return;
#endif /* IP_OPTIONS */

View file

@ -0,0 +1,250 @@
diff -up openssh-6.8p1/Makefile.in.ctr-cavs openssh-6.8p1/Makefile.in
--- openssh-6.8p1/Makefile.in.ctr-cavs 2015-03-18 11:22:05.493289018 +0100
+++ openssh-6.8p1/Makefile.in 2015-03-18 11:22:44.504196316 +0100
@@ -28,6 +28,7 @@ SSH_KEYSIGN=$(libexecdir)/ssh-keysign
SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper
SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper
SSH_KEYCAT=$(libexecdir)/ssh-keycat
+CTR_CAVSTEST=$(libexecdir)/ctr-cavstest
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
@@ -66,7 +67,7 @@ EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT)
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT)
LIBOPENSSH_OBJS=\
ssh_api.o \
@@ -194,6 +195,9 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l
ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o
$(LD) -o $@ ssh-keycat.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(KEYCATLIBS) $(SSHLIBS)
+ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o
+ $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
+
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
@@ -326,6 +330,7 @@ install-files:
$(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \
fi
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT)
+ $(INSTALL) -m 0755 $(STRIP_OPT) ctr-cavstest$(EXEEXT) $(DESTDIR)$(libexecdir)/ctr-cavstest$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c
--- openssh-6.8p1/ctr-cavstest.c.ctr-cavs 2015-03-18 11:22:05.521288952 +0100
+++ openssh-6.8p1/ctr-cavstest.c 2015-03-18 11:22:05.521288952 +0100
@@ -0,0 +1,208 @@
+/*
+ *
+ * invocation (all of the following are equal):
+ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6
+ * ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt --data a6deca405eef2e8e4609abf3c3ccf4a6 --iv 00000000000000000000000000000000
+ * echo -n a6deca405eef2e8e4609abf3c3ccf4a6 | ./ctr-cavstest --algo aes128-ctr --key 987212980144b6a632e864031f52dacc --mode encrypt
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "xmalloc.h"
+#include "log.h"
+#include "cipher.h"
+
+/* compatibility with old or broken OpenSSL versions */
+#include "openbsd-compat/openssl-compat.h"
+
+void usage(void) {
+ fprintf(stderr, "Usage: ctr-cavstest --algo <ssh-crypto-algorithm>\n"
+ " --key <hexadecimal-key> --mode <encrypt|decrypt>\n"
+ " [--iv <hexadecimal-iv>] --data <hexadecimal-data>\n\n"
+ "Hexadecimal output is printed to stdout.\n"
+ "Hexadecimal input data can be alternatively read from stdin.\n");
+ exit(1);
+}
+
+void *fromhex(char *hex, size_t *len)
+{
+ unsigned char *bin;
+ char *p;
+ size_t n = 0;
+ int shift = 4;
+ unsigned char out = 0;
+ unsigned char *optr;
+
+ bin = xmalloc(strlen(hex)/2);
+ optr = bin;
+
+ for (p = hex; *p != '\0'; ++p) {
+ unsigned char c;
+
+ c = *p;
+ if (isspace(c))
+ continue;
+
+ if (c >= '0' && c <= '9') {
+ c = c - '0';
+ } else if (c >= 'A' && c <= 'F') {
+ c = c - 'A' + 10;
+ } else if (c >= 'a' && c <= 'f') {
+ c = c - 'a' + 10;
+ } else {
+ /* truncate on nonhex cipher */
+ break;
+ }
+
+ out |= c << shift;
+ shift = (shift + 4) % 8;
+
+ if (shift) {
+ *(optr++) = out;
+ out = 0;
+ ++n;
+ }
+ }
+
+ *len = n;
+ return bin;
+}
+
+#define READ_CHUNK 4096
+#define MAX_READ_SIZE 1024*1024*100
+char *read_stdin(void)
+{
+ char *buf;
+ size_t n, total = 0;
+
+ buf = xmalloc(READ_CHUNK);
+
+ do {
+ n = fread(buf + total, 1, READ_CHUNK, stdin);
+ if (n < READ_CHUNK) /* terminate on short read */
+ break;
+
+ total += n;
+ buf = xreallocarray(buf, total + READ_CHUNK, 1);
+ } while(total < MAX_READ_SIZE);
+ return buf;
+}
+
+int main (int argc, char *argv[])
+{
+
+ const struct sshcipher *c;
+ struct sshcipher_ctx cc;
+ char *algo = "aes128-ctr";
+ char *hexkey = NULL;
+ char *hexiv = "00000000000000000000000000000000";
+ char *hexdata = NULL;
+ char *p;
+ int i;
+ int encrypt = 1;
+ void *key;
+ size_t keylen;
+ void *iv;
+ size_t ivlen;
+ void *data;
+ size_t datalen;
+ void *outdata;
+
+ for (i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "--algo") == 0) {
+ algo = argv[++i];
+ } else if (strcmp(argv[i], "--key") == 0) {
+ hexkey = argv[++i];
+ } else if (strcmp(argv[i], "--mode") == 0) {
+ ++i;
+ if (argv[i] == NULL) {
+ usage();
+ }
+ if (strncmp(argv[i], "enc", 3) == 0) {
+ encrypt = 1;
+ } else if (strncmp(argv[i], "dec", 3) == 0) {
+ encrypt = 0;
+ } else {
+ usage();
+ }
+ } else if (strcmp(argv[i], "--iv") == 0) {
+ hexiv = argv[++i];
+ } else if (strcmp(argv[i], "--data") == 0) {
+ hexdata = argv[++i];
+ }
+ }
+
+ if (hexkey == NULL || algo == NULL) {
+ usage();
+ }
+
+ SSLeay_add_all_algorithms();
+
+ c = cipher_by_name(algo);
+ if (c == NULL) {
+ fprintf(stderr, "Error: unknown algorithm\n");
+ return 2;
+ }
+
+ if (hexdata == NULL) {
+ hexdata = read_stdin();
+ } else {
+ hexdata = xstrdup(hexdata);
+ }
+
+ key = fromhex(hexkey, &keylen);
+
+ if (keylen != 16 && keylen != 24 && keylen == 32) {
+ fprintf(stderr, "Error: unsupported key length\n");
+ return 2;
+ }
+
+ iv = fromhex(hexiv, &ivlen);
+
+ if (ivlen != 16) {
+ fprintf(stderr, "Error: unsupported iv length\n");
+ return 2;
+ }
+
+ data = fromhex(hexdata, &datalen);
+
+ if (data == NULL || datalen == 0) {
+ fprintf(stderr, "Error: no data to encrypt/decrypt\n");
+ return 2;
+ }
+
+ cipher_init(&cc, c, key, keylen, iv, ivlen, encrypt);
+
+ free(key);
+ free(iv);
+
+ outdata = malloc(datalen);
+ if(outdata == NULL) {
+ fprintf(stderr, "Error: memory allocation failure\n");
+ return 2;
+ }
+
+ cipher_crypt(&cc, 0, outdata, data, datalen, 0, 0);
+
+ free(data);
+
+ cipher_cleanup(&cc);
+
+ for (p = outdata; datalen > 0; ++p, --datalen) {
+ printf("%02X", (unsigned char)*p);
+ }
+
+ free(outdata);
+
+ printf("\n");
+ return 0;
+}
+

482
openssh-6.6p1-keycat.patch Normal file
View file

@ -0,0 +1,482 @@
diff -up openssh/auth2-pubkey.c.keycat openssh/auth2-pubkey.c
--- openssh/auth2-pubkey.c.keycat 2015-06-24 10:57:50.158849606 +0200
+++ openssh/auth2-pubkey.c 2015-06-24 11:04:23.989868638 +0200
@@ -490,6 +490,14 @@ subprocess(const char *tag, struct passw
_exit(1);
}
+#ifdef WITH_SELINUX
+ if (sshd_selinux_setup_env_variables() < 0) {
+ error ("failed to copy environment: %s",
+ strerror(errno));
+ _exit(127);
+ }
+#endif
+
execve(av[0], av, child_env);
error("%s exec \"%s\": %s", tag, command, strerror(errno));
_exit(127);
diff -up openssh/HOWTO.ssh-keycat.keycat openssh/HOWTO.ssh-keycat
--- openssh/HOWTO.ssh-keycat.keycat 2015-06-24 10:57:50.157849608 +0200
+++ openssh/HOWTO.ssh-keycat 2015-06-24 10:57:50.157849608 +0200
@@ -0,0 +1,12 @@
+The ssh-keycat retrieves the content of the ~/.ssh/authorized_keys
+of an user in any environment. This includes environments with
+polyinstantiation of home directories and SELinux MLS policy enabled.
+
+To use ssh-keycat, set these options in /etc/ssh/sshd_config file:
+ AuthorizedKeysCommand /usr/libexec/openssh/ssh-keycat
+ AuthorizedKeysCommandUser root
+
+Do not forget to enable public key authentication:
+ PubkeyAuthentication yes
+
+
diff -up openssh/Makefile.in.keycat openssh/Makefile.in
--- openssh/Makefile.in.keycat 2015-06-24 10:57:50.152849621 +0200
+++ openssh/Makefile.in 2015-06-24 10:57:50.157849608 +0200
@@ -27,6 +27,7 @@ SFTP_SERVER=$(libexecdir)/sftp-server
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper
SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper
+SSH_KEYCAT=$(libexecdir)/ssh-keycat
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
@@ -52,6 +52,7 @@ K5LIBS=@K5LIBS@
GSSLIBS=@GSSLIBS@
SSHLIBS=@SSHLIBS@
SSHDLIBS=@SSHDLIBS@
+KEYCATLIBS=@KEYCATLIBS@
LIBEDIT=@LIBEDIT@
AR=@AR@
AWK=@AWK@
@@ -65,7 +66,7 @@ EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT)
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT)
LIBOPENSSH_OBJS=\
ssh_api.o \
@@ -190,6 +191,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT)
ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o sshbuf-getput-basic.o ssherr.o
$(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o sshbuf-getput-basic.o ssherr.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
+ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o
+ $(LD) -o $@ ssh-keycat.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(KEYCATLIBS) $(SSHLIBS)
+
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
@@ -321,6 +325,7 @@ install-files:
$(INSTALL) -m 0700 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \
$(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \
fi
+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
diff -up openssh/openbsd-compat/port-linux.h.keycat openssh/openbsd-compat/port-linux.h
--- openssh/openbsd-compat/port-linux.h.keycat 2015-06-24 10:57:50.150849626 +0200
+++ openssh/openbsd-compat/port-linux.h 2015-06-24 10:57:50.160849601 +0200
@@ -25,8 +25,10 @@ void ssh_selinux_setup_pty(char *, const
void ssh_selinux_change_context(const char *);
void ssh_selinux_setfscreatecon(const char *);
+int sshd_selinux_enabled(void);
void sshd_selinux_copy_context(void);
void sshd_selinux_setup_exec_context(char *);
+int sshd_selinux_setup_env_variables(void);
#endif
#ifdef LINUX_OOM_ADJUST
diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/port-linux-sshd.c
--- openssh/openbsd-compat/port-linux-sshd.c.keycat 2015-06-24 10:57:50.150849626 +0200
+++ openssh/openbsd-compat/port-linux-sshd.c 2015-06-24 10:57:50.159849603 +0200
@@ -54,6 +54,20 @@ extern Authctxt *the_authctxt;
extern int inetd_flag;
extern int rexeced_flag;
+/* Wrapper around is_selinux_enabled() to log its return value once only */
+int
+sshd_selinux_enabled(void)
+{
+ static int enabled = -1;
+
+ if (enabled == -1) {
+ enabled = (is_selinux_enabled() == 1);
+ debug("SELinux support %s", enabled ? "enabled" : "disabled");
+ }
+
+ return (enabled);
+}
+
/* Send audit message */
static int
sshd_selinux_send_audit_message(int success, security_context_t default_context,
@@ -308,7 +322,7 @@ sshd_selinux_getctxbyname(char *pwname,
/* Setup environment variables for pam_selinux */
static int
-sshd_selinux_setup_pam_variables(void)
+sshd_selinux_setup_variables(int(*set_it)(char *, const char *))
{
const char *reqlvl;
char *role;
@@ -319,16 +333,16 @@ sshd_selinux_setup_pam_variables(void)
ssh_selinux_get_role_level(&role, &reqlvl);
- rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : "");
+ rv = set_it("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 || set_it("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: "");
}
- rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current);
+ rv = rv || set_it("SELINUX_USE_CURRENT_RANGE", use_current);
if (role != NULL)
free(role);
@@ -336,6 +350,24 @@ sshd_selinux_setup_pam_variables(void)
return rv;
}
+static int
+sshd_selinux_setup_pam_variables(void)
+{
+ return sshd_selinux_setup_variables(do_pam_putenv);
+}
+
+static int
+do_setenv(char *name, const char *value)
+{
+ return setenv(name, value, 1);
+}
+
+int
+sshd_selinux_setup_env_variables(void)
+{
+ return sshd_selinux_setup_variables(do_setenv);
+}
+
/* Set the execution context to the default for the specified user */
void
sshd_selinux_setup_exec_context(char *pwname)
@@ -344,7 +376,7 @@ sshd_selinux_setup_exec_context(char *pw
int r = 0;
security_context_t default_ctx = NULL;
- if (!ssh_selinux_enabled())
+ if (!sshd_selinux_enabled())
return;
if (options.use_pam) {
@@ -415,7 +447,7 @@ sshd_selinux_copy_context(void)
{
security_context_t *ctx;
- if (!ssh_selinux_enabled())
+ if (!sshd_selinux_enabled())
return;
if (getexeccon((security_context_t *)&ctx) != 0) {
diff -up openssh/platform.c.keycat openssh/platform.c
--- openssh/platform.c.keycat 2015-06-24 10:57:50.147849633 +0200
+++ openssh/platform.c 2015-06-24 10:57:50.160849601 +0200
@@ -103,7 +103,7 @@ platform_setusercontext(struct passwd *p
{
#ifdef WITH_SELINUX
/* Cache selinux status for later use */
- (void)ssh_selinux_enabled();
+ (void)sshd_selinux_enabled();
#endif
#ifdef USE_SOLARIS_PROJECTS
diff -up openssh/ssh-keycat.c.keycat openssh/ssh-keycat.c
--- openssh/ssh-keycat.c.keycat 2015-06-24 10:57:50.161849599 +0200
+++ openssh/ssh-keycat.c 2015-06-24 10:57:50.161849599 +0200
@@ -0,0 +1,238 @@
+/*
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ * Written by Tomas Mraz <tmraz@redhat.com>
+*/
+
+#define _GNU_SOURCE
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <security/pam_appl.h>
+
+#include "uidswap.h"
+#include "misc.h"
+
+#define ERR_USAGE 1
+#define ERR_PAM_START 2
+#define ERR_OPEN_SESSION 3
+#define ERR_CLOSE_SESSION 4
+#define ERR_PAM_END 5
+#define ERR_GETPWNAM 6
+#define ERR_MEMORY 7
+#define ERR_OPEN 8
+#define ERR_FILE_MODE 9
+#define ERR_FDOPEN 10
+#define ERR_STAT 11
+#define ERR_WRITE 12
+#define ERR_PAM_PUTENV 13
+#define BUFLEN 4096
+
+/* Just ignore the messages in the conversation function */
+static int
+dummy_conv(int num_msg, const struct pam_message **msgm,
+ struct pam_response **response, void *appdata_ptr)
+{
+ struct pam_response *rsp;
+
+ (void)msgm;
+ (void)appdata_ptr;
+
+ if (num_msg <= 0)
+ return PAM_CONV_ERR;
+
+ /* Just allocate the array as empty responses */
+ rsp = calloc (num_msg, sizeof (struct pam_response));
+ if (rsp == NULL)
+ return PAM_CONV_ERR;
+
+ *response = rsp;
+ return PAM_SUCCESS;
+}
+
+static struct pam_conv conv = {
+ dummy_conv,
+ NULL
+};
+
+char *
+make_auth_keys_name(const struct passwd *pwd)
+{
+ char *fname;
+
+ if (asprintf(&fname, "%s/.ssh/authorized_keys", pwd->pw_dir) < 0)
+ return NULL;
+
+ return fname;
+}
+
+int
+dump_keys(const char *user)
+{
+ struct passwd *pwd;
+ int fd = -1;
+ FILE *f = NULL;
+ char *fname = NULL;
+ int rv = 0;
+ char buf[BUFLEN];
+ size_t len;
+ struct stat st;
+
+ if ((pwd = getpwnam(user)) == NULL) {
+ return ERR_GETPWNAM;
+ }
+
+ if ((fname = make_auth_keys_name(pwd)) == NULL) {
+ return ERR_MEMORY;
+ }
+
+ temporarily_use_uid(pwd);
+
+ if ((fd = open(fname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) {
+ rv = ERR_OPEN;
+ goto fail;
+ }
+
+ if (fstat(fd, &st) < 0) {
+ rv = ERR_STAT;
+ goto fail;
+ }
+
+ if (!S_ISREG(st.st_mode) ||
+ (st.st_uid != pwd->pw_uid && st.st_uid != 0)) {
+ rv = ERR_FILE_MODE;
+ goto fail;
+ }
+
+ unset_nonblock(fd);
+
+ if ((f = fdopen(fd, "r")) == NULL) {
+ rv = ERR_FDOPEN;
+ goto fail;
+ }
+
+ fd = -1;
+
+ while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
+ rv = fwrite(buf, 1, len, stdout) != len ? ERR_WRITE : 0;
+ }
+
+fail:
+ if (fd != -1)
+ close(fd);
+ if (f != NULL)
+ fclose(f);
+ free(fname);
+ restore_uid();
+ return rv;
+}
+
+static const char *env_names[] = { "SELINUX_ROLE_REQUESTED",
+ "SELINUX_LEVEL_REQUESTED",
+ "SELINUX_USE_CURRENT_RANGE"
+};
+
+extern char **environ;
+
+int
+set_pam_environment(pam_handle_t *pamh)
+{
+ int i;
+ size_t j;
+
+ for (j = 0; j < sizeof(env_names)/sizeof(env_names[0]); ++j) {
+ int len = strlen(env_names[j]);
+
+ for (i = 0; environ[i] != NULL; ++i) {
+ if (strncmp(env_names[j], environ[i], len) == 0 &&
+ environ[i][len] == '=') {
+ if (pam_putenv(pamh, environ[i]) != PAM_SUCCESS)
+ return ERR_PAM_PUTENV;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ pam_handle_t *pamh = NULL;
+ int retval;
+ int ev = 0;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <user-name>\n", argv[0]);
+ return ERR_USAGE;
+ }
+
+ retval = pam_start("ssh-keycat", argv[1], &conv, &pamh);
+ if (retval != PAM_SUCCESS) {
+ return ERR_PAM_START;
+ }
+
+ ev = set_pam_environment(pamh);
+ if (ev != 0)
+ goto finish;
+
+ retval = pam_open_session(pamh, PAM_SILENT);
+ if (retval != PAM_SUCCESS) {
+ ev = ERR_OPEN_SESSION;
+ goto finish;
+ }
+
+ ev = dump_keys(argv[1]);
+
+ retval = pam_close_session(pamh, PAM_SILENT);
+ if (retval != PAM_SUCCESS) {
+ ev = ERR_CLOSE_SESSION;
+ }
+
+finish:
+ retval = pam_end (pamh,retval);
+ if (retval != PAM_SUCCESS) {
+ ev = ERR_PAM_END;
+ }
+ return ev;
+}
diff --git a/configure.ac b/configure.ac
index 3bbccfd..6481f1f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2952,6 +2952,7 @@ AC_ARG_WITH([pam],
PAM_MSG="yes"
SSHDLIBS="$SSHDLIBS -lpam"
+ KEYCATLIBS="$KEYCATLIBS -lpam"
AC_DEFINE([USE_PAM], [1],
[Define if you want to enable PAM support])
@@ -3105,6 +3106,7 @@
;;
*)
SSHDLIBS="$SSHDLIBS -ldl"
+ KEYCATLIBS="$KEYCATLIBS -ldl"
;;
esac
fi
@@ -4042,6 +4044,7 @@ AC_ARG_WITH([selinux],
)
AC_SUBST([SSHLIBS])
AC_SUBST([SSHDLIBS])
+AC_SUBST([KEYCATLIBS])
# Check whether user wants Kerberos 5 support
KRB5_MSG="no"
@@ -5031,6 +5034,9 @@ fi
if test ! -z "${SSHLIBS}"; then
echo " +for ssh: ${SSHLIBS}"
fi
+if test ! -z "${KEYCATLIBS}"; then
+echo " +for ssh-keycat: ${KEYCATLIBS}"
+fi
echo ""

View file

@ -0,0 +1,26 @@
diff --git a/authfile.c b/authfile.c
index e93d867..4fc5b3d 100644
--- a/authfile.c
+++ b/authfile.c
@@ -32,6 +32,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <grp.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -207,6 +208,13 @@ sshkey_perm_ok(int fd, const char *filename)
#ifdef HAVE_CYGWIN
if (check_ntsec(filename))
#endif
+ if (st.st_mode & 040) {
+ struct group *gr;
+
+ if ((gr = getgrnam("ssh_keys")) && (st.st_gid == gr->gr_gid))
+ st.st_mode &= ~040;
+ }
+
if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) {
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");

288
openssh-6.6p1-kuserok.patch Normal file
View file

@ -0,0 +1,288 @@
diff -up openssh-7.0p1/auth-krb5.c.kuserok openssh-7.0p1/auth-krb5.c
--- openssh-7.0p1/auth-krb5.c.kuserok 2015-08-11 10:57:29.000000000 +0200
+++ openssh-7.0p1/auth-krb5.c 2015-08-12 11:26:21.874536127 +0200
@@ -55,6 +55,21 @@
extern ServerOptions options;
+int
+ssh_krb5_kuserok(krb5_context krb5_ctx, krb5_principal krb5_user, const char *client,
+ int k5login_exists)
+{
+ if (options.use_kuserok || !k5login_exists)
+ 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)
{
@@ -158,8 +173,9 @@ auth_krb5_password(Authctxt *authctxt, c
if (problem)
goto out;
- if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
- authctxt->pw->pw_name)) {
+ /* Use !options.use_kuserok here to make ssh_krb5_kuserok() not
+ * depend on the existance of .k5login */
+ if (!ssh_krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, authctxt->pw->pw_name, !options.use_kuserok)) {
problem = -1;
goto out;
}
diff -up openssh-7.0p1/gss-serv-krb5.c.kuserok openssh-7.0p1/gss-serv-krb5.c
--- openssh-7.0p1/gss-serv-krb5.c.kuserok 2015-08-12 11:26:21.868536137 +0200
+++ openssh-7.0p1/gss-serv-krb5.c 2015-08-12 11:26:21.875536126 +0200
@@ -67,6 +67,7 @@ static int ssh_gssapi_krb5_cmdok(krb5_pr
int);
static krb5_context krb_context = NULL;
+extern int ssh_krb5_kuserok(krb5_context, krb5_principal, const char *, int);
/* Initialise the krb5 library, for the stuff that GSSAPI won't do */
@@ -92,6 +93,103 @@ ssh_gssapi_krb5_init(void)
* Returns true if the user is OK to log in, otherwise returns 0
*/
+/* The purpose of the function is to find out if a Kerberos principal is
+ * allowed to log in as the given local user. This is a general problem with
+ * Kerberized services because by design the Kerberos principals are
+ * completely independent from the local user names. This is one of the
+ * reasons why Kerberos is working well on different operating systems like
+ * Windows and UNIX/Linux. Nevertheless a relationship between a Kerberos
+ * principal and a local user name must be established because otherwise every
+ * access would be granted for every principal with a valid ticket.
+ *
+ * Since it is a general issue libkrb5 provides some functions for
+ * applications to find out about the relationship between the Kerberos
+ * principal and a local user name. They are krb5_kuserok() and
+ * krb5_aname_to_localname().
+ *
+ * krb5_kuserok() can be used to "Determine if a principal is authorized to
+ * log in as a local user" (from the MIT Kerberos documentation of this
+ * function). Which is exactly what we are looking for and should be the
+ * preferred choice. It accepts the Kerberos principal and a local user name
+ * and let libkrb5 or its plugins determine if they relate to each other or
+ * not.
+ *
+ * krb5_aname_to_localname() can use used to "Convert a principal name to a
+ * local name" (from the MIT Kerberos documentation of this function). It
+ * accepts a Kerberos principle and returns a local name and it is up to the
+ * application to do any additional checks. There are two issues using
+ * krb5_aname_to_localname(). First, since POSIX user names are case
+ * sensitive, the calling application in general has no other choice than
+ * doing a case-sensitive string comparison between the name returned by
+ * krb5_aname_to_localname() and the name used at the login prompt. When the
+ * users are provided by a case in-sensitive server, e.g. Active Directory,
+ * this might lead to login failures because the user typing the name at the
+ * login prompt might not be aware of the right case. Another issue might be
+ * caused if there are multiple alias names available for a single user. E.g.
+ * the canonical name of a user is user@group.department.example.com but there
+ * exists a shorter login name, e.g. user@example.com, to safe typing at the
+ * login prompt. Here krb5_aname_to_localname() can only return the canonical
+ * name, but if the short alias is used at the login prompt authentication
+ * will fail as well. All this can be avoided by using krb5_kuserok() and
+ * configuring krb5.conf or using a suitable plugin to meet the needs of the
+ * given environment.
+ *
+ * The Fedora and RHEL version of openssh contain two patches which modify the
+ * access control behavior:
+ * - openssh-6.6p1-kuserok.patch
+ * - openssh-6.6p1-force_krb.patch
+ *
+ * openssh-6.6p1-kuserok.patch adds a new option KerberosUseKuserok for
+ * sshd_config which controls if krb5_kuserok() is used to check if the
+ * principle is authorized or if krb5_aname_to_localname() should be used.
+ * The reason to add this patch was that krb5_kuserok() by default checks if
+ * a .k5login file exits in the users home-directory. With this the user can
+ * give access to his account for any given principal which might be
+ * in violation with company policies and it would be useful if this can be
+ * rejected. Nevertheless the patch ignores the fact that krb5_kuserok() does
+ * no only check .k5login but other sources as well and checking .k5login can
+ * be disabled for all applications in krb5.conf as well. With this new
+ * option KerberosUseKuserok set to 'no' (and this is the default for RHEL7
+ * and Fedora 21) openssh can only use krb5_aname_to_localname() with the
+ * restrictions mentioned above.
+ *
+ * openssh-6.6p1-force_krb.patch adds a ksu like behaviour to ssh, i.e. when
+ * using GSSAPI authentication only commands configured in the .k5user can be
+ * executed. Here the wrong assumption that krb5_kuserok() only checks
+ * .k5login is made as well. In contrast ksu checks .k5login directly and
+ * does not use krb5_kuserok() which might be more useful for the given
+ * purpose. Additionally this patch is not synced with
+ * openssh-6.6p1-kuserok.patch.
+ *
+ * The current patch tries to restore the usage of krb5_kuserok() so that e.g.
+ * localauth plugins can be used. It does so by adding a forth parameter to
+ * ssh_krb5_kuserok() which indicates whether .k5login exists or not. If it
+ * does not exists krb5_kuserok() is called even if KerberosUseKuserok is set
+ * to 'no' because the intent of the option is to not check .k5login and if it
+ * does not exists krb5_kuserok() returns a result without checking .k5login.
+ * If .k5login does exists and KerberosUseKuserok is 'no' we fall back to
+ * krb5_aname_to_localname(). This is in my point of view an acceptable
+ * limitation and does not break the current behaviour.
+ *
+ * Additionally with this patch ssh_krb5_kuserok() is called in
+ * ssh_gssapi_krb5_cmdok() instead of only krb5_aname_to_localname() is
+ * neither .k5login nor .k5users exists to allow plugin evaluation via
+ * krb5_kuserok() as well.
+ *
+ * I tried to keep the patch as minimal as possible, nevertheless I see some
+ * areas for improvement which, if they make sense, have to be evaluated
+ * carefully because they might change existing behaviour and cause breaks
+ * during upgrade:
+ * - I wonder if disabling .k5login usage make sense in sshd or if it should
+ * be better disabled globally in krb5.conf
+ * - if really needed openssh-6.6p1-kuserok.patch should be fixed to really
+ * only disable checking .k5login and maybe .k5users
+ * - the ksu behaviour should be configurable and maybe check the .k5login and
+ * .k5users files directly like ksu itself does
+ * - to make krb5_aname_to_localname() more useful an option for sshd to use
+ * the canonical name (the one returned by getpwnam()) instead of the name
+ * given at the login prompt might be useful */
+
static int
ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
{
@@ -116,7 +214,8 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client
/* NOTE: .k5login and .k5users must opened as root, not the user,
* because if they are on a krb5-protected filesystem, user credentials
* to access these files aren't available yet. */
- if (krb5_kuserok(krb_context, princ, name) && k5login_exists) {
+ if (ssh_krb5_kuserok(krb_context, princ, name, k5login_exists)
+ && k5login_exists) {
retval = 1;
logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
name, (char *)client->displayname.value);
@@ -171,9 +270,8 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri
snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir);
/* If both .k5login and .k5users DNE, self-login is ok. */
if (!k5login_exists && (access(file, F_OK) == -1)) {
- return (krb5_aname_to_localname(krb_context, principal,
- sizeof(kuser), kuser) == 0) &&
- (strcmp(kuser, luser) == 0);
+ return ssh_krb5_kuserok(krb_context, principal, luser,
+ k5login_exists);
}
if ((fp = fopen(file, "r")) == NULL) {
int saved_errno = errno;
diff -up openssh-7.0p1/servconf.c.kuserok openssh-7.0p1/servconf.c
--- openssh-7.0p1/servconf.c.kuserok 2015-08-12 11:26:21.865536141 +0200
+++ openssh-7.0p1/servconf.c 2015-08-12 11:27:14.126454598 +0200
@@ -172,6 +172,7 @@ initialize_server_options(ServerOptions
options->ip_qos_bulk = -1;
options->version_addendum = NULL;
options->fingerprint_hash = -1;
+ options->use_kuserok = -1;
}
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
@@ -350,6 +351,8 @@ fill_default_server_options(ServerOption
options->fwd_opts.streamlocal_bind_unlink = 0;
if (options->fingerprint_hash == -1)
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
+ if (options->use_kuserok == -1)
+ options->use_kuserok = 1;
assemble_algorithms(options);
@@ -404,7 +407,7 @@ typedef enum {
sKeyRegenerationTime, sPermitRootLogin, sLogFacility, sLogLevel,
sRhostsRSAAuthentication, sRSAAuthentication,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
- sKerberosGetAFSToken,
+ sKerberosGetAFSToken, sKerberosUseKuserok,
sKerberosTgtPassing, sChallengeResponseAuthentication,
sPasswordAuthentication, sKbdInteractiveAuthentication,
sListenAddress, sAddressFamily,
@@ -483,11 +486,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 },
@@ -1671,6 +1676,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')
@@ -2023,6 +2032,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_INTOPT(rekey_limit);
M_CP_INTOPT(rekey_interval);
@@ -2304,6 +2314,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
+ dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok);
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);
diff -up openssh-7.0p1/servconf.h.kuserok openssh-7.0p1/servconf.h
--- openssh-7.0p1/servconf.h.kuserok 2015-08-12 11:26:21.865536141 +0200
+++ openssh-7.0p1/servconf.h 2015-08-12 11:26:21.876536124 +0200
@@ -180,6 +180,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-7.0p1/sshd_config.5.kuserok openssh-7.0p1/sshd_config.5
--- openssh-7.0p1/sshd_config.5.kuserok 2015-08-12 11:26:21.867536138 +0200
+++ openssh-7.0p1/sshd_config.5 2015-08-12 11:26:21.877536123 +0200
@@ -872,6 +872,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.
@@ -1116,6 +1120,7 @@ Available keywords are
.Cm IPQoS ,
.Cm KbdInteractiveAuthentication ,
.Cm KerberosAuthentication ,
+.Cm KerberosUseKuserok ,
.Cm MaxAuthTries ,
.Cm MaxSessions ,
.Cm PasswordAuthentication ,
diff -up openssh-7.0p1/sshd_config.kuserok openssh-7.0p1/sshd_config
--- openssh-7.0p1/sshd_config.kuserok 2015-08-12 11:26:21.867536138 +0200
+++ openssh-7.0p1/sshd_config 2015-08-12 11:26:21.876536124 +0200
@@ -87,6 +87,7 @@ ChallengeResponseAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
+#KerberosUseKuserok yes
# GSSAPI options
GSSAPIAuthentication yes

2332
openssh-6.7p1-audit.patch Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,140 @@
diff -up openssh/configure.ac.tcp_wrappers openssh/configure.ac
--- openssh/configure.ac.tcp_wrappers 2015-06-24 11:41:04.519293694 +0200
+++ openssh/configure.ac 2015-06-24 11:41:04.556293600 +0200
@@ -1448,6 +1448,62 @@ AC_ARG_WITH([skey],
]
)
+# Check whether user wants TCP wrappers support
+TCPW_MSG="no"
+AC_ARG_WITH([tcp-wrappers],
+ [ --with-tcp-wrappers[[=PATH]] Enable tcpwrappers support (optionally in PATH)],
+ [
+ if test "x$withval" != "xno" ; then
+ saved_LIBS="$LIBS"
+ saved_LDFLAGS="$LDFLAGS"
+ saved_CPPFLAGS="$CPPFLAGS"
+ if test -n "${withval}" && \
+ test "x${withval}" != "xyes"; then
+ if test -d "${withval}/lib"; then
+ if test -n "${need_dash_r}"; then
+ LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
+ else
+ LDFLAGS="-L${withval}/lib ${LDFLAGS}"
+ fi
+ else
+ if test -n "${need_dash_r}"; then
+ LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
+ else
+ LDFLAGS="-L${withval} ${LDFLAGS}"
+ fi
+ fi
+ if test -d "${withval}/include"; then
+ CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
+ else
+ CPPFLAGS="-I${withval} ${CPPFLAGS}"
+ fi
+ fi
+ LIBS="-lwrap $LIBS"
+ AC_MSG_CHECKING([for libwrap])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <tcpd.h>
+int deny_severity = 0, allow_severity = 0;
+ ]], [[
+ hosts_access(0);
+ ]])], [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([LIBWRAP], [1],
+ [Define if you want
+ TCP Wrappers support])
+ SSHDLIBS="$SSHDLIBS -lwrap"
+ TCPW_MSG="yes"
+ ], [
+ AC_MSG_ERROR([*** libwrap missing])
+
+ ])
+ LIBS="$saved_LIBS"
+ fi
+ ]
+)
+
# Check whether user wants to use ldns
LDNS_MSG="no"
AC_ARG_WITH(ldns,
@@ -5034,6 +5090,7 @@ echo " KerberosV support
echo " SELinux support: $SELINUX_MSG"
echo " Smartcard support: $SCARD_MSG"
echo " S/KEY support: $SKEY_MSG"
+echo " TCP Wrappers support: $TCPW_MSG"
echo " MD5 password support: $MD5_MSG"
echo " libedit support: $LIBEDIT_MSG"
echo " Solaris process contract support: $SPC_MSG"
diff -up openssh/sshd.8.tcp_wrappers openssh/sshd.8
--- openssh/sshd.8.tcp_wrappers 2015-06-24 11:41:04.527293674 +0200
+++ openssh/sshd.8 2015-06-24 11:41:04.556293600 +0200
@@ -860,6 +860,12 @@ the user's home directory becomes access
This file should be writable only by the user, and need not be
readable by anyone else.
.Pp
+.It Pa /etc/hosts.allow
+.It Pa /etc/hosts.deny
+Access controls that should be enforced by tcp-wrappers are defined here.
+Further details are described in
+.Xr hosts_access 5 .
+.Pp
.It Pa /etc/hosts.equiv
This file is for host-based authentication (see
.Xr ssh 1 ) .
@@ -983,6 +989,7 @@ IPv6 address can be used everywhere wher
.Xr ssh-keygen 1 ,
.Xr ssh-keyscan 1 ,
.Xr chroot 2 ,
+.Xr hosts_access 5 ,
.Xr login.conf 5 ,
.Xr moduli 5 ,
.Xr sshd_config 5 ,
diff -up openssh/sshd.c.tcp_wrappers openssh/sshd.c
--- openssh/sshd.c.tcp_wrappers 2015-06-24 11:41:04.549293618 +0200
+++ openssh/sshd.c 2015-06-24 11:41:53.331169536 +0200
@@ -125,6 +125,13 @@
#include "version.h"
#include "ssherr.h"
+#ifdef LIBWRAP
+#include <tcpd.h>
+#include <syslog.h>
+int allow_severity;
+int deny_severity;
+#endif /* LIBWRAP */
+
#ifndef O_NOCTTY
#define O_NOCTTY 0
#endif
@@ -2158,6 +2165,24 @@ main(int ac, char **av)
#ifdef SSH_AUDIT_EVENTS
audit_connection_from(remote_ip, remote_port);
#endif
+#ifdef LIBWRAP
+ allow_severity = options.log_facility|LOG_INFO;
+ deny_severity = options.log_facility|LOG_WARNING;
+ /* Check whether logins are denied from this host. */
+ if (packet_connection_is_on_socket()) {
+ struct request_info req;
+
+ request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);
+ fromhost(&req);
+
+ if (!hosts_access(&req)) {
+ debug("Connection refused by tcp wrapper");
+ refuse(&req);
+ /* NOTREACHED */
+ fatal("libwrap refuse returns");
+ }
+ }
+#endif /* LIBWRAP */
/* Log the connection. */
laddr = get_local_ipaddr(sock_in);

View file

@ -0,0 +1,614 @@
diff -up openssh-6.8p1/Makefile.in.kdf-cavs openssh-6.8p1/Makefile.in
--- openssh-6.8p1/Makefile.in.kdf-cavs 2015-03-18 11:23:46.346049359 +0100
+++ openssh-6.8p1/Makefile.in 2015-03-18 11:24:20.395968445 +0100
@@ -29,6 +29,7 @@ SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-h
SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper
SSH_KEYCAT=$(libexecdir)/ssh-keycat
CTR_CAVSTEST=$(libexecdir)/ctr-cavstest
+SSH_CAVS=$(libexecdir)/ssh-cavs
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
@@ -67,7 +68,7 @@ EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT)
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) ssh-cavs$(EXEEXT)
LIBOPENSSH_OBJS=\
ssh_api.o \
@@ -198,6 +199,9 @@ ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHD
ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o
$(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS)
+ssh-cavs$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-cavs.o
+ $(LD) -o $@ ssh-cavs.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o
$(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
@@ -331,6 +335,8 @@ install-files:
fi
$(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) ctr-cavstest$(EXEEXT) $(DESTDIR)$(libexecdir)/ctr-cavstest$(EXEEXT)
+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-cavs$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-cavs$(EXEEXT)
+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-cavs_driver.pl $(DESTDIR)$(libexecdir)/ssh-cavs_driver.pl
$(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c
--- openssh-6.8p1/ssh-cavs.c.kdf-cavs 2015-03-18 11:23:46.348049354 +0100
+++ openssh-6.8p1/ssh-cavs.c 2015-03-18 11:23:46.348049354 +0100
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2015, Stephan Mueller <smueller@chronox.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL2
+ * are required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+
+#include "xmalloc.h"
+#include "buffer.h"
+#include "key.h"
+#include "cipher.h"
+#include "kex.h"
+#include "packet.h"
+
+static int bin_char(unsigned char hex)
+{
+ if (48 <= hex && 57 >= hex)
+ return (hex - 48);
+ if (65 <= hex && 70 >= hex)
+ return (hex - 55);
+ if (97 <= hex && 102 >= hex)
+ return (hex - 87);
+ return 0;
+}
+
+/*
+ * Convert hex representation into binary string
+ * @hex input buffer with hex representation
+ * @hexlen length of hex
+ * @bin output buffer with binary data
+ * @binlen length of already allocated bin buffer (should be at least
+ * half of hexlen -- if not, only a fraction of hexlen is converted)
+ */
+static void hex2bin(const char *hex, size_t hexlen,
+ unsigned char *bin, size_t binlen)
+{
+ size_t i = 0;
+ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
+
+ for (i = 0; i < chars; i++) {
+ bin[i] = bin_char(hex[(i*2)]) << 4;
+ bin[i] |= bin_char(hex[((i*2)+1)]);
+ }
+}
+
+/*
+ * Allocate sufficient space for binary representation of hex
+ * and convert hex into bin
+ *
+ * Caller must free bin
+ * @hex input buffer with hex representation
+ * @hexlen length of hex
+ * @bin return value holding the pointer to the newly allocated buffer
+ * @binlen return value holding the allocated size of bin
+ *
+ * return: 0 on success, !0 otherwise
+ */
+static int hex2bin_alloc(const char *hex, size_t hexlen,
+ unsigned char **bin, size_t *binlen)
+{
+ unsigned char *out = NULL;
+ size_t outlen = 0;
+
+ if (!hexlen)
+ return -EINVAL;
+
+ outlen = (hexlen + 1) / 2;
+
+ out = calloc(1, outlen);
+ if (!out)
+ return -errno;
+
+ hex2bin(hex, hexlen, out, outlen);
+ *bin = out;
+ *binlen = outlen;
+ return 0;
+}
+
+static char hex_char_map_l[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+static char hex_char_map_u[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+static char hex_char(unsigned int bin, int u)
+{
+ if (bin < sizeof(hex_char_map_l))
+ return (u) ? hex_char_map_u[bin] : hex_char_map_l[bin];
+ return 'X';
+}
+
+/*
+ * Convert binary string into hex representation
+ * @bin input buffer with binary data
+ * @binlen length of bin
+ * @hex output buffer to store hex data
+ * @hexlen length of already allocated hex buffer (should be at least
+ * twice binlen -- if not, only a fraction of binlen is converted)
+ * @u case of hex characters (0=>lower case, 1=>upper case)
+ */
+static void bin2hex(const unsigned char *bin, size_t binlen,
+ char *hex, size_t hexlen, int u)
+{
+ size_t i = 0;
+ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
+
+ for (i = 0; i < chars; i++) {
+ hex[(i*2)] = hex_char((bin[i] >> 4), u);
+ hex[((i*2)+1)] = hex_char((bin[i] & 0x0f), u);
+ }
+}
+
+struct kdf_cavs {
+ unsigned char *K;
+ size_t Klen;
+ unsigned char *H;
+ size_t Hlen;
+ unsigned char *session_id;
+ size_t session_id_len;
+
+ unsigned int iv_len;
+ unsigned int ek_len;
+ unsigned int ik_len;
+};
+
+static int sshkdf_cavs(struct kdf_cavs *test)
+{
+ int ret = 0;
+ struct kex kex;
+ BIGNUM *Kbn = NULL;
+ int mode = 0;
+ struct newkeys *ctoskeys;
+ struct newkeys *stockeys;
+ struct ssh *ssh = NULL;
+
+#define HEXOUTLEN 500
+ char hex[HEXOUTLEN];
+
+ memset(&kex, 0, sizeof(struct kex));
+
+ Kbn = BN_new();
+ BN_bin2bn(test->K, test->Klen, Kbn);
+ if (!Kbn) {
+ printf("cannot convert K into BIGNUM\n");
+ ret = 1;
+ goto out;
+ }
+
+ kex.session_id = test->session_id;
+ kex.session_id_len = test->session_id_len;
+
+ /* setup kex */
+
+ /* select the right hash based on struct ssh_digest digests */
+ switch (test->ik_len) {
+ case 20:
+ kex.hash_alg = 2;
+ break;
+ case 32:
+ kex.hash_alg = 3;
+ break;
+ case 48:
+ kex.hash_alg = 4;
+ break;
+ case 64:
+ kex.hash_alg = 5;
+ break;
+ default:
+ printf("Wrong hash type %u\n", test->ik_len);
+ ret = 1;
+ goto out;
+ }
+
+ /* implement choose_enc */
+ for (mode = 0; mode < 2; mode++) {
+ kex.newkeys[mode] = calloc(1, sizeof(struct newkeys));
+ if (!kex.newkeys[mode]) {
+ printf("allocation of newkeys failed\n");
+ ret = 1;
+ goto out;
+ }
+ kex.newkeys[mode]->enc.iv_len = test->iv_len;
+ kex.newkeys[mode]->enc.key_len = test->ek_len;
+ kex.newkeys[mode]->enc.block_size = (test->iv_len == 64) ? 8 : 16;
+ kex.newkeys[mode]->mac.key_len = test->ik_len;
+ }
+
+ /* implement kex_choose_conf */
+ kex.we_need = kex.newkeys[0]->enc.key_len;
+ if (kex.we_need < kex.newkeys[0]->enc.block_size)
+ kex.we_need = kex.newkeys[0]->enc.block_size;
+ if (kex.we_need < kex.newkeys[0]->enc.iv_len)
+ kex.we_need = kex.newkeys[0]->enc.iv_len;
+ if (kex.we_need < kex.newkeys[0]->mac.key_len)
+ kex.we_need = kex.newkeys[0]->mac.key_len;
+
+ /* MODE_OUT (1) -> server to client
+ * MODE_IN (0) -> client to server */
+ kex.server = 1;
+
+ /* do it */
+ if ((ssh = ssh_packet_set_connection(NULL, -1, -1)) == NULL){
+ printf("Allocation error\n");
+ goto out;
+ }
+ ssh->kex = &kex;
+ kex_derive_keys_bn(ssh, test->H, test->Hlen, Kbn);
+
+ ctoskeys = kex.newkeys[0];
+ stockeys = kex.newkeys[1];
+
+ /* get data */
+ memset(hex, 0, HEXOUTLEN);
+ bin2hex(ctoskeys->enc.iv, (size_t)ctoskeys->enc.iv_len,
+ hex, HEXOUTLEN, 0);
+ printf("Initial IV (client to server) = %s\n", hex);
+ memset(hex, 0, HEXOUTLEN);
+ bin2hex(stockeys->enc.iv, (size_t)stockeys->enc.iv_len,
+ hex, HEXOUTLEN, 0);
+ printf("Initial IV (server to client) = %s\n", hex);
+
+ memset(hex, 0, HEXOUTLEN);
+ bin2hex(ctoskeys->enc.key, (size_t)ctoskeys->enc.key_len,
+ hex, HEXOUTLEN, 0);
+ printf("Encryption key (client to server) = %s\n", hex);
+ memset(hex, 0, HEXOUTLEN);
+ bin2hex(stockeys->enc.key, (size_t)stockeys->enc.key_len,
+ hex, HEXOUTLEN, 0);
+ printf("Encryption key (server to client) = %s\n", hex);
+
+ memset(hex, 0, HEXOUTLEN);
+ bin2hex(ctoskeys->mac.key, (size_t)ctoskeys->mac.key_len,
+ hex, HEXOUTLEN, 0);
+ printf("Integrity key (client to server) = %s\n", hex);
+ memset(hex, 0, HEXOUTLEN);
+ bin2hex(stockeys->mac.key, (size_t)stockeys->mac.key_len,
+ hex, HEXOUTLEN, 0);
+ printf("Integrity key (server to client) = %s\n", hex);
+
+ free(ctoskeys);
+ free(stockeys);
+
+out:
+ if (Kbn)
+ BN_free(Kbn);
+ if (kex.newkeys[0])
+ free(kex.newkeys[0]);
+ if (kex.newkeys[1])
+ free(kex.newkeys[1]);
+ if (ssh)
+ ssh_packet_close(ssh);
+ return ret;
+}
+
+static void usage(void)
+{
+ fprintf(stderr, "\nOpenSSH KDF CAVS Test\n\n");
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\t-K\tShared secret string\n");
+ fprintf(stderr, "\t-H\tHash string\n");
+ fprintf(stderr, "\t-s\tSession ID string\n");
+ fprintf(stderr, "\t-i\tIV length to be generated\n");
+ fprintf(stderr, "\t-e\tEncryption key length to be generated\n");
+ fprintf(stderr, "\t-m\tMAC key length to be generated\n");
+}
+
+/*
+ * Test command example:
+ * ./ssh-cavs -K 0055d50f2d163cc07cd8a93cc7c3430c30ce786b572c01ad29fec7597000cf8618d664e2ec3dcbc8bb7a1a7eb7ef67f61cdaf291625da879186ac0a5cb27af571b59612d6a6e0627344d846271959fda61c78354aa498773d59762f8ca2d0215ec590d8633de921f920d41e47b3de6ab9a3d0869e1c826d0e4adebf8e3fb646a15dea20a410b44e969f4b791ed6a67f13f1b74234004d5fa5e87eff7abc32d49bbdf44d7b0107e8f10609233b7e2b7eff74a4daf25641de7553975dac6ac1e5117df6f6dbaa1c263d23a6c3e5a3d7d49ae8a828c1e333ac3f85fbbf57b5c1a45be45e43a7be1a4707eac779b8285522d1f531fe23f890fd38a004339932b93eda4 -H d3ab91a850febb417a25d892ec48ed5952c7a5de -s d3ab91a850febb417a25d892ec48ed5952c7a5de -i 8 -e 24 -m 20
+ *
+ * Initial IV (client to server) = 4bb320d1679dfd3a
+ * Initial IV (server to client) = 43dea6fdf263a308
+ * Encryption key (client to server) = 13048cc600b9d3cf9095aa6cf8e2ff9cf1c54ca0520c89ed
+ * Encryption key (server to client) = 1e483c5134e901aa11fc4e0a524e7ec7b75556148a222bb0
+ * Integrity key (client to server) = ecef63a092b0dcc585bdc757e01b2740af57d640
+ * Integrity key (server to client) = 7424b05f3c44a72b4ebd281fb71f9cbe7b64d479
+ */
+int main(int argc, char *argv[])
+{
+ struct kdf_cavs test;
+ int ret = 1;
+ int opt = 0;
+
+ memset(&test, 0, sizeof(struct kdf_cavs));
+ while((opt = getopt(argc, argv, "K:H:s:i:e:m:")) != -1)
+ {
+ size_t len = 0;
+ switch(opt)
+ {
+ /*
+ * CAVS K is MPINT
+ * we want a hex (i.e. the caller must ensure the
+ * following transformations already happened):
+ * 1. cut off first four bytes
+ * 2. if most significant bit of value is
+ * 1, prepend 0 byte
+ */
+ case 'K':
+ len = strlen(optarg);
+ ret = hex2bin_alloc(optarg, len,
+ &test.K, &test.Klen);
+ if (ret)
+ goto out;
+ break;
+ case 'H':
+ len = strlen(optarg);
+ ret = hex2bin_alloc(optarg, len,
+ &test.H, &test.Hlen);
+ if (ret)
+ goto out;
+ break;
+ case 's':
+ len = strlen(optarg);
+ ret = hex2bin_alloc(optarg, len,
+ &test.session_id,
+ &test.session_id_len);
+ if (ret)
+ goto out;
+ break;
+ case 'i':
+ test.iv_len = strtoul(optarg, NULL, 10);
+ break;
+ case 'e':
+ test.ek_len = strtoul(optarg, NULL, 10);
+ break;
+ case 'm':
+ test.ik_len = strtoul(optarg, NULL, 10);
+ break;
+ default:
+ usage();
+ goto out;
+ }
+ }
+
+ ret = sshkdf_cavs(&test);
+
+out:
+ if (test.session_id)
+ free(test.session_id);
+ if (test.K)
+ free(test.K);
+ if (test.H)
+ free(test.H);
+ return ret;
+
+}
diff -up openssh-6.8p1/ssh-cavs_driver.pl.kdf-cavs openssh-6.8p1/ssh-cavs_driver.pl
--- openssh-6.8p1/ssh-cavs_driver.pl.kdf-cavs 2015-03-18 11:23:46.348049354 +0100
+++ openssh-6.8p1/ssh-cavs_driver.pl 2015-03-18 11:23:46.348049354 +0100
@@ -0,0 +1,184 @@
+#!/usr/bin/env perl
+#
+# CAVS test driver for OpenSSH
+#
+# Copyright (C) 2015, Stephan Mueller <smueller@chronox.de>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# NO WARRANTY
+#
+# BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+# FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+# OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+# PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+# OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+# TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+# PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+# REPAIR OR CORRECTION.
+#
+# IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+# WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+# REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+# INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+# OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+# TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+# YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+# PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGES.
+#
+use strict;
+use warnings;
+use IPC::Open2;
+
+# Executing a program by feeding STDIN and retrieving
+# STDOUT
+# $1: data string to be piped to the app on STDIN
+# rest: program and args
+# returns: STDOUT of program as string
+sub pipe_through_program($@) {
+ my $in = shift;
+ my @args = @_;
+
+ my ($CO, $CI);
+ my $pid = open2($CO, $CI, @args);
+
+ my $out = "";
+ my $len = length($in);
+ my $first = 1;
+ while (1) {
+ my $rin = "";
+ my $win = "";
+ # Output of prog is FD that we read
+ vec($rin,fileno($CO),1) = 1;
+ # Input of prog is FD that we write
+ # check for $first is needed because we can have NULL input
+ # that is to be written to the app
+ if ( $len > 0 || $first) {
+ (vec($win,fileno($CI),1) = 1);
+ $first=0;
+ }
+ # Let us wait for 100ms
+ my $nfound = select(my $rout=$rin, my $wout=$win, undef, 0.1);
+ if ( $wout ) {
+ my $written = syswrite($CI, $in, $len);
+ die "broken pipe" if !defined $written;
+ $len -= $written;
+ substr($in, 0, $written) = "";
+ if ($len <= 0) {
+ close $CI or die "broken pipe: $!";
+ }
+ }
+ if ( $rout ) {
+ my $tmp_out = "";
+ my $bytes_read = sysread($CO, $tmp_out, 4096);
+ $out .= $tmp_out;
+ last if ($bytes_read == 0);
+ }
+ }
+ close $CO or die "broken pipe: $!";
+ waitpid $pid, 0;
+
+ return $out;
+}
+
+# Parser of CAVS test vector file
+# $1: Test vector file
+# $2: Output file for test results
+# return: nothing
+sub parse($$) {
+ my $infile = shift;
+ my $outfile = shift;
+
+ my $out = "";
+
+ my $K = "";
+ my $H = "";
+ my $session_id = "";
+ my $ivlen = 0;
+ my $eklen = "";
+ my $iklen = "";
+
+ open(IN, "<$infile");
+ while(<IN>) {
+
+ my $line = $_;
+ chomp($line);
+ $line =~ s/\r//;
+
+ if ($line =~ /\[SHA-1\]/) {
+ $iklen = 20;
+ } elsif ($line =~ /\[SHA-256\]/) {
+ $iklen = 32;
+ } elsif ($line =~ /\[SHA-384\]/) {
+ $iklen = 48;
+ } elsif ($line =~ /\[SHA-512\]/) {
+ $iklen = 64;
+ } elsif ($line =~ /^\[IV length\s*=\s*(.*)\]/) {
+ $ivlen = $1;
+ $ivlen = $ivlen / 8;
+ } elsif ($line =~ /^\[encryption key length\s*=\s*(.*)\]/) {
+ $eklen = $1;
+ $eklen = $eklen / 8;
+ } elsif ($line =~ /^K\s*=\s*(.*)/) {
+ $K = $1;
+ $K = substr($K, 8);
+ $K = "00" . $K;
+ } elsif ($line =~ /^H\s*=\s*(.*)/) {
+ $H = $1;
+ } elsif ($line =~ /^session_id\s*=\s*(.*)/) {
+ $session_id = $1;
+ }
+ $out .= $line . "\n";
+
+ if ($K ne "" && $H ne "" && $session_id ne "" &&
+ $ivlen ne "" && $eklen ne "" && $iklen > 0) {
+ $out .= pipe_through_program("", "./ssh-cavs -H $H -K $K -s $session_id -i $ivlen -e $eklen -m $iklen");
+
+ $K = "";
+ $H = "";
+ $session_id = "";
+ }
+ }
+ close IN;
+ $out =~ s/\n/\r\n/g; # make it a dos file
+ open(OUT, ">$outfile") or die "Cannot create output file $outfile: $?";
+ print OUT $out;
+ close OUT;
+}
+
+############################################################
+#
+# let us pretend to be C :-)
+sub main() {
+
+ my $infile=$ARGV[0];
+ die "Error: Test vector file $infile not found" if (! -f $infile);
+
+ my $outfile = $infile;
+ # let us add .rsp regardless whether we could strip .req
+ $outfile =~ s/\.req$//;
+ $outfile .= ".rsp";
+ if (-f $outfile) {
+ die "Output file $outfile could not be removed: $?"
+ unless unlink($outfile);
+ }
+ print STDERR "Performing tests from source file $infile with results stored in destination file $outfile\n";
+
+ # Do the job
+ parse($infile, $outfile);
+}
+
+###########################################
+# Call it
+main();
+1;

2721
openssh-6.7p1-ldap.patch Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,81 @@
diff -up openssh-6.8p1/sftp-server.8.sftp-force-mode openssh-6.8p1/sftp-server.8
--- openssh-6.8p1/sftp-server.8.sftp-force-mode 2015-03-17 06:49:20.000000000 +0100
+++ openssh-6.8p1/sftp-server.8 2015-03-18 13:18:05.898306477 +0100
@@ -38,6 +38,7 @@
.Op Fl P Ar blacklisted_requests
.Op Fl p Ar whitelisted_requests
.Op Fl u Ar umask
+.Op Fl m Ar force_file_perms
.Ek
.Nm
.Fl Q Ar protocol_feature
@@ -138,6 +139,10 @@ Sets an explicit
.Xr umask 2
to be applied to newly-created files and directories, instead of the
user's default mask.
+.It Fl m Ar force_file_perms
+Sets explicit file permissions to be applied to newly-created files instead
+of the default or client requested mode. Numeric values include:
+777, 755, 750, 666, 644, 640, etc. Option -u is ineffective if -m is set.
.El
.Pp
On some systems,
diff -up openssh-6.8p1/sftp-server.c.sftp-force-mode openssh-6.8p1/sftp-server.c
--- openssh-6.8p1/sftp-server.c.sftp-force-mode 2015-03-18 13:18:05.883306513 +0100
+++ openssh-6.8p1/sftp-server.c 2015-03-18 13:18:36.697232193 +0100
@@ -70,6 +70,10 @@ struct sshbuf *oqueue;
/* Version of client */
static u_int version;
+/* Force file permissions */
+int permforce = 0;
+long permforcemode;
+
/* SSH2_FXP_INIT received */
static int init_done;
@@ -693,6 +697,10 @@ process_open(u_int32_t id)
debug3("request %u: open flags %d", id, pflags);
flags = flags_from_portable(pflags);
mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666;
+ if (permforce == 1) { /* Force perm if -m is set */
+ mode = permforcemode;
+ (void)umask(0); /* so umask does not interfere */
+ }
logit("open \"%s\" flags %s mode 0%o",
name, string_from_portable(pflags), mode);
if (readonly &&
@@ -1495,7 +1503,7 @@ sftp_server_usage(void)
fprintf(stderr,
"usage: %s [-ehR] [-d start_directory] [-f log_facility] "
"[-l log_level]\n\t[-P blacklisted_requests] "
- "[-p whitelisted_requests] [-u umask]\n"
+ "[-p whitelisted_requests] [-u umask] [-m force_file_perms]\n"
" %s -Q protocol_feature\n",
__progname, __progname);
exit(1);
@@ -1520,7 +1528,7 @@ sftp_server_main(int argc, char **argv,
pw = pwcopy(user_pw);
while (!skipargs && (ch = getopt(argc, argv,
- "d:f:l:P:p:Q:u:cehR")) != -1) {
+ "d:f:l:P:p:Q:u:m:cehR")) != -1) {
switch (ch) {
case 'Q':
if (strcasecmp(optarg, "requests") != 0) {
@@ -1580,6 +1588,15 @@ sftp_server_main(int argc, char **argv,
fatal("Invalid umask \"%s\"", optarg);
(void)umask((mode_t)mask);
break;
+ case 'm':
+ /* Force permissions on file received via sftp */
+ permforce = 1;
+ permforcemode = strtol(optarg, &cp, 8);
+ if (permforcemode < 0 || permforcemode > 0777 ||
+ *cp != '\0' || (permforcemode == 0 &&
+ errno != 0))
+ fatal("Invalid file mode \"%s\"", optarg);
+ break;
case 'h':
default:
sftp_server_usage();

View file

@ -0,0 +1,25 @@
diff --git a/servconf.c b/servconf.c
index ad5869b..0255ed3 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1910,6 +1910,8 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
dst->n = src->n; \
} while (0)
+ u_int i;
+
M_CP_INTOPT(password_authentication);
M_CP_INTOPT(gss_authentication);
M_CP_INTOPT(rsa_authentication);
@@ -1947,8 +1949,10 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
} while(0)
#define M_CP_STRARRAYOPT(n, num_n) do {\
if (src->num_n != 0) { \
+ for (i = 0; i < dst->num_n; i++) \
+ free(dst->n[i]); \
for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \
- dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \
+ dst->n[dst->num_n] = src->n[dst->num_n]; \
} \
} while(0)

View file

@ -0,0 +1,27 @@
diff -up openssh/servconf.c.sshdt openssh/servconf.c
--- openssh/servconf.c.sshdt 2015-06-24 11:42:29.041078704 +0200
+++ openssh/servconf.c 2015-06-24 11:44:39.734745802 +0200
@@ -2317,7 +2317,7 @@ dump_config(ServerOptions *o)
dump_cfg_string(sXAuthLocation, o->xauth_location);
dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT);
dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC);
- dump_cfg_string(sBanner, o->banner);
+ dump_cfg_string(sBanner, o->banner != NULL ? o->banner : "none");
dump_cfg_string(sForceCommand, o->adm_forced_command);
dump_cfg_string(sChrootDirectory, o->chroot_directory);
dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
diff -up openssh/ssh.1.sshdt openssh/ssh.1
--- openssh/ssh.1.sshdt 2015-06-24 11:42:19.565102807 +0200
+++ openssh/ssh.1 2015-06-24 11:42:29.042078701 +0200
@@ -441,7 +441,11 @@ For full details of the options listed b
.It GatewayPorts
.It GlobalKnownHostsFile
.It GSSAPIAuthentication
+.It GSSAPIKeyExchange
+.It GSSAPIClientIdentity
.It GSSAPIDelegateCredentials
+.It GSSAPIRenewalForcesRekey
+.It GSSAPITrustDNS
.It HashKnownHosts
.It Host
.It HostbasedAuthentication

View file

@ -0,0 +1,75 @@
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-6.9p1/ssh_config openssh-6.9p1-config/ssh_config
--- openssh-6.9p1/ssh_config 2015-07-01 04:35:31.000000000 +0200
+++ openssh-6.9p1-config/ssh_config 2015-07-09 19:44:32.092075229 +0200
@@ -19,7 +19,7 @@
# Host *
# ForwardAgent no
-# ForwardX11 no
+ForwardX11 yes
# RhostsRSAAuthentication no
# RSAAuthentication yes
# PasswordAuthentication yes
@@ -46,3 +46,13 @@
# VisualHostKey no
# ProxyCommand ssh -q -W %h:%p gateway.example.com
# RekeyLimit 1G 1h
+
+# 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
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-6.9p1/sshd_config openssh-6.9p1-config/sshd_config
--- openssh-6.9p1/sshd_config 2015-07-01 04:35:31.000000000 +0200
+++ openssh-6.9p1-config/sshd_config 2015-07-09 22:00:17.505998501 +0200
@@ -3,7 +3,7 @@
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
-# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
+# This sshd was compiled with PATH=_OPENSSH_PATH_
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
@@ -21,10 +21,10 @@
# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
-#HostKey /etc/ssh/ssh_host_rsa_key
+HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
-#HostKey /etc/ssh/ssh_host_ecdsa_key
-#HostKey /etc/ssh/ssh_host_ed25519_key
+HostKey /etc/ssh/ssh_host_ecdsa_key
+HostKey /etc/ssh/ssh_host_ed25519_key
# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
@@ -94,12 +94,20 @@
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
-#UsePAM no
+# Warning: when running under systemd, and PAM usage is disabled, restarting
+# SSH service will likely kill off any ssh connections, including the
+# current one
+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
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
-#X11Forwarding no
+X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes

View file

@ -0,0 +1,143 @@
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 89a1762..fe98e08 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1251,4 +1251,48 @@ mm_audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, &m);
buffer_free(&m);
}
+
+int mm_forward_audit_messages(int fdin)
+{
+ u_char buf[4];
+ u_int blen, msg_len;
+ Buffer m;
+ int ret = 0;
+
+ debug3("%s: entering", __func__);
+ buffer_init(&m);
+ do {
+ blen = atomicio(read, fdin, buf, sizeof(buf));
+ if (blen == 0) /* closed pipe */
+ break;
+ if (blen != sizeof(buf)) {
+ error("%s: Failed to read the buffer from child", __func__);
+ ret = -1;
+ break;
+ }
+
+ msg_len = get_u32(buf);
+ if (msg_len > 256 * 1024)
+ fatal("%s: read: bad msg_len %d", __func__, msg_len);
+ buffer_clear(&m);
+ buffer_append_space(&m, msg_len);
+ if (atomicio(read, fdin, buffer_ptr(&m), msg_len) != msg_len) {
+ error("%s: Failed to read the the buffer conent from the child", __func__);
+ ret = -1;
+ break;
+ }
+ if (atomicio(vwrite, pmonitor->m_recvfd, buf, blen) != blen ||
+ atomicio(vwrite, pmonitor->m_recvfd, buffer_ptr(&m), msg_len) != msg_len) {
+ error("%s: Failed to write the messag to the monitor", __func__);
+ ret = -1;
+ break;
+ }
+ } while (1);
+ buffer_free(&m);
+ return ret;
+}
+void mm_set_monitor_pipe(int fd)
+{
+ pmonitor->m_recvfd = fd;
+}
#endif /* SSH_AUDIT_EVENTS */
diff --git a/monitor_wrap.h b/monitor_wrap.h
index e73134e..fbfe395 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -86,6 +86,8 @@ void mm_audit_unsupported_body(int);
void mm_audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t);
void mm_audit_session_key_free_body(int, pid_t, uid_t);
void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t);
+int mm_forward_audit_messages(int);
+void mm_set_monitor_pipe(int);
#endif
struct Session;
diff --git a/session.c b/session.c
index 8949fd1..9afb764 100644
--- a/session.c
+++ b/session.c
@@ -159,6 +159,10 @@ static Session *sessions = NULL;
login_cap_t *lc;
#endif
+#ifdef SSH_AUDIT_EVENTS
+int paudit[2];
+#endif
+
static int is_child = 0;
static int in_chroot = 0;
static int have_dev_log = 1;
@@ -875,6 +879,8 @@ do_exec(Session *s, const char *command)
}
if (s->command != NULL && s->ptyfd == -1)
s->command_handle = PRIVSEP(audit_run_command(s->command));
+ if (pipe(paudit) < 0)
+ fatal("pipe: %s", strerror(errno));
#endif
if (s->ttyfd != -1)
ret = do_exec_pty(s, command);
@@ -890,6 +896,20 @@ do_exec(Session *s, const char *command)
*/
buffer_clear(&loginmsg);
+#ifdef SSH_AUDIT_EVENTS
+ close(paudit[1]);
+ if (use_privsep && ret == 0) {
+ /*
+ * Read the audit messages from forked child and send them
+ * back to monitor. We don't want to communicate directly,
+ * because the messages might get mixed up.
+ * Continue after the pipe gets closed (all messages sent).
+ */
+ ret = mm_forward_audit_messages(paudit[0]);
+ }
+ close(paudit[0]);
+#endif /* SSH_AUDIT_EVENTS */
+
return ret;
}
@@ -1707,12 +1727,28 @@ do_child(Session *s, const char *command)
struct passwd *pw = s->pw;
int r = 0;
+#ifdef SSH_AUDIT_EVENTS
+ int pparent = paudit[1];
+ close(paudit[0]);
+ /* Hack the monitor pipe to avoid race condition with parent */
+ if (use_privsep)
+ mm_set_monitor_pipe(pparent);
+#endif
+
/* remove hostkey from the child's memory */
- destroy_sensitive_data(1);
- /* Don't audit this - both us and the parent would be talking to the
- monitor over a single socket, with no synchronization. */
+ destroy_sensitive_data(use_privsep);
+ /*
+ * We can audit this, because wer hacked the pipe to direct the
+ * messages over postauth child. But this message requires answer
+ * which we can't do using one-way pipe.
+ */
packet_destroy_all(0, 1);
+#ifdef SSH_AUDIT_EVENTS
+ /* Notify parent that we are done */
+ close(pparent);
+#endif
+
/* Force a password change */
if (s->authctxt->force_pwchange) {
do_setusercontext(pw);

53
openssh-7.2p2-x11.patch Normal file
View file

@ -0,0 +1,53 @@
diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c
--- openssh-7.2p2/channels.c.x11 2016-03-09 19:04:48.000000000 +0100
+++ openssh-7.2p2/channels.c 2016-06-03 10:42:04.775164520 +0200
@@ -3990,21 +3990,24 @@ 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;
+ if (len <= 0)
+ return -1;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
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 > 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;
}
@@ -4012,8 +4015,18 @@ 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, ret;
+ 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

281
openssh-7.3p1-entropy.patch Normal file
View file

@ -0,0 +1,281 @@
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/entropy.c openssh-7.3p1-entropy/entropy.c
--- openssh-7.3p1/entropy.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-entropy/entropy.c 2016-08-07 19:07:15.628010962 +0200
@@ -229,6 +229,9 @@
memset(buf, '\0', sizeof(buf));
#endif /* OPENSSL_PRNG_ONLY */
+#ifdef __linux__
+ linux_seed();
+#endif /* __linux__ */
if (RAND_status() != 1)
fatal("PRNG is not seeded");
}
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/openbsd-compat/Makefile.in openssh-7.3p1-entropy/openbsd-compat/Makefile.in
--- openssh-7.3p1/openbsd-compat/Makefile.in 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-entropy/openbsd-compat/Makefile.in 2016-08-07 19:08:32.515457998 +0200
@@ -20,7 +20,7 @@
COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-err.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o kludge-fd_set.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-prng.o port-solaris.o port-tun.o port-uw.o
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/openbsd-compat/port-linux.h openssh-7.3p1-entropy/openbsd-compat/port-linux.h
--- openssh-7.3p1/openbsd-compat/port-linux.h 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-entropy/openbsd-compat/port-linux.h 2016-08-07 19:07:15.631010941 +0200
@@ -32,4 +32,6 @@
void oom_adjust_setup(void);
#endif
+void linux_seed(void);
+
#endif /* ! _PORT_LINUX_H */
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/openbsd-compat/port-linux-prng.c openssh-7.3p1-entropy/openbsd-compat/port-linux-prng.c
--- openssh-7.3p1/openbsd-compat/port-linux-prng.c 1970-01-01 01:00:00.000000000 +0100
+++ openssh-7.3p1-entropy/openbsd-compat/port-linux-prng.c 2016-08-07 19:07:15.628010962 +0200
@@ -0,0 +1,59 @@
+/* $Id: port-linux.c,v 1.11.4.2 2011/02/04 00:43:08 djm Exp $ */
+
+/*
+ * Copyright (c) 2011 Jan F. Chadima <jchadima@redhat.com>
+ *
+ * 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 - prng support
+ */
+
+#include "includes.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <openssl/rand.h>
+
+#include "log.h"
+#include "xmalloc.h"
+#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */
+#include "servconf.h"
+#include "port-linux.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+
+void
+linux_seed(void)
+{
+ char *env = getenv("SSH_USE_STRONG_RNG");
+ char *random = "/dev/random";
+ size_t len, ienv, randlen = 14;
+
+ if (!env || !strcmp(env, "0"))
+ random = "/dev/urandom";
+ else if ((ienv = atoi(env)) > randlen)
+ randlen = ienv;
+
+ errno = 0;
+ if ((len = RAND_load_file(random, randlen)) != randlen) {
+ if (errno)
+ fatal ("cannot read from %s, %s", random, strerror(errno));
+ else
+ fatal ("EOF reading %s", random);
+ }
+}
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/ssh.1 openssh-7.3p1-entropy/ssh.1
--- openssh-7.3p1/ssh.1 2016-08-07 19:06:14.524453823 +0200
+++ openssh-7.3p1-entropy/ssh.1 2016-08-07 19:07:15.629010955 +0200
@@ -1441,6 +1441,23 @@
.Cm PermitUserEnvironment
option in
.Xr sshd_config 5 .
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.It Ev SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa ~/.rhosts
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/ssh-add.0 openssh-7.3p1-entropy/ssh-add.0
--- openssh-7.3p1/ssh-add.0 2016-08-01 04:01:34.000000000 +0200
+++ openssh-7.3p1-entropy/ssh-add.0 2016-08-07 19:07:15.628010962 +0200
@@ -88,6 +88,16 @@
Identifies the path of a UNIX-domain socket used to communicate
with the agent.
+ SSH_USE_STRONG_RNG
+ The reseeding of the OpenSSL random generator is usually done
+ from /dev/urandom. If the SSH_USE_STRONG_RNG environment vari-
+ able is set to value other than 0 the OpenSSL random generator is
+ reseeded from /dev/random. The number of bytes read is defined
+ by the SSH_USE_STRONG_RNG value. Minimum is 14 bytes. This set-
+ ting is not recommended on the computers without the hardware
+ random generator because insufficient entropy causes the connec-
+ tion to be blocked until enough entropy is available.
+
FILES
~/.ssh/identity
Contains the protocol version 1 RSA authentication identity of
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/ssh-add.1 openssh-7.3p1-entropy/ssh-add.1
--- openssh-7.3p1/ssh-add.1 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-entropy/ssh-add.1 2016-08-07 19:07:15.628010962 +0200
@@ -171,6 +171,20 @@
Identifies the path of a
.Ux Ns -domain
socket used to communicate with the agent.
+.It Ev SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
.El
.Sh FILES
.Bl -tag -width Ds
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/ssh-agent.1 openssh-7.3p1-entropy/ssh-agent.1
--- openssh-7.3p1/ssh-agent.1 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-entropy/ssh-agent.1 2016-08-07 19:07:15.628010962 +0200
@@ -201,6 +201,24 @@
These sockets should only be readable by the owner.
The sockets should get automatically removed when the agent exits.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/sshd.8 openssh-7.3p1-entropy/sshd.8
--- openssh-7.3p1/sshd.8 2016-08-07 19:06:14.524453823 +0200
+++ openssh-7.3p1-entropy/sshd.8 2016-08-07 19:07:15.629010955 +0200
@@ -977,6 +977,24 @@
started last).
The content of this file is not sensitive; it can be world-readable.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh IPV6
IPv6 address can be used everywhere where IPv4 address. In all entries must be the IPv6 address enclosed in square brackets. Note: The square brackets are metacharacters for the shell and must be escaped in shell.
.Sh SEE ALSO
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/ssh-keygen.1 openssh-7.3p1-entropy/ssh-keygen.1
--- openssh-7.3p1/ssh-keygen.1 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-entropy/ssh-keygen.1 2016-08-07 19:07:15.629010955 +0200
@@ -848,6 +848,24 @@
The file format is described in
.Xr moduli 5 .
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/ssh-keysign.8 openssh-7.3p1-entropy/ssh-keysign.8
--- openssh-7.3p1/ssh-keysign.8 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-entropy/ssh-keysign.8 2016-08-07 19:07:15.629010955 +0200
@@ -80,6 +80,24 @@
If these files exist they are assumed to contain public certificate
information corresponding with the private keys above.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 14 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-keygen 1 ,

View file

@ -0,0 +1,513 @@
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/auth2.c openssh-7.3p1-expose-pam/auth2.c
--- openssh-7.3p1/auth2.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-expose-pam/auth2.c 2016-08-07 19:29:05.288169736 +0200
@@ -293,6 +293,7 @@
const char *submethod)
{
char *methods;
+ char *prev_auth_details;
int partial = 0;
if (!authctxt->valid && authenticated)
@@ -323,6 +324,18 @@
if (authctxt->postponed)
return;
+ if (authenticated || partial) {
+ prev_auth_details = authctxt->auth_details;
+ xasprintf(&authctxt->auth_details, "%s%s%s%s%s",
+ prev_auth_details ? prev_auth_details : "",
+ prev_auth_details ? ", " : "", method,
+ authctxt->last_details ? ": " : "",
+ authctxt->last_details ? authctxt->last_details : "");
+ free(prev_auth_details);
+ }
+ free(authctxt->last_details);
+ authctxt->last_details = NULL;
+
#ifdef USE_PAM
if (options.use_pam && authenticated) {
if (!PRIVSEP(do_pam_account())) {
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/auth2-gss.c openssh-7.3p1-expose-pam/auth2-gss.c
--- openssh-7.3p1/auth2-gss.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-expose-pam/auth2-gss.c 2016-08-07 19:33:42.819666662 +0200
@@ -278,9 +278,15 @@
else
logit("GSSAPI MIC check failed");
+ if (authenticated)
+ authctxt->last_details = ssh_gssapi_get_displayname();
+
buffer_free(&b);
free(mic.value);
+ if (authenticated)
+ authctxt->last_details = ssh_gssapi_get_displayname();
+
authctxt->postponed = 0;
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/auth2-hostbased.c openssh-7.3p1-expose-pam/auth2-hostbased.c
--- openssh-7.3p1/auth2-hostbased.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-expose-pam/auth2-hostbased.c 2016-08-07 19:29:05.290169717 +0200
@@ -60,7 +60,7 @@
{
Buffer b;
Key *key = NULL;
- char *pkalg, *cuser, *chost, *service;
+ char *pkalg, *cuser, *chost, *service, *pubkey;
u_char *pkblob, *sig;
u_int alen, blen, slen;
int pktype;
@@ -132,15 +132,21 @@
buffer_dump(&b);
#endif
- pubkey_auth_info(authctxt, key,
- "client user \"%.100s\", client host \"%.100s\"", cuser, chost);
+ pubkey = sshkey_format_oneline(key, options.fingerprint_hash);
+ auth_info(authctxt,
+ "%s, client user \"%.100s\", client host \"%.100s\"",
+ pubkey, cuser, chost);
/* test for allowed key and correct signature */
authenticated = 0;
if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
- buffer_len(&b))) == 1)
+ buffer_len(&b))) == 1) {
authenticated = 1;
+ authctxt->last_details = pubkey;
+ } else {
+ free(pubkey);
+ }
buffer_free(&b);
done:
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/auth2-pubkey.c openssh-7.3p1-expose-pam/auth2-pubkey.c
--- openssh-7.3p1/auth2-pubkey.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-expose-pam/auth2-pubkey.c 2016-08-07 19:29:05.290169717 +0200
@@ -79,7 +79,7 @@
{
Buffer b;
Key *key = NULL;
- char *pkalg, *userstyle, *fp = NULL;
+ char *pkalg, *userstyle, *pubkey, *fp = NULL;
u_char *pkblob, *sig;
u_int alen, blen, slen;
int have_sig, pktype;
@@ -171,7 +171,8 @@
#ifdef DEBUG_PK
buffer_dump(&b);
#endif
- pubkey_auth_info(authctxt, key, NULL);
+ pubkey = sshkey_format_oneline(key, options.fingerprint_hash);
+ auth_info(authctxt, "%s", pubkey);
/* test for correct signature */
authenticated = 0;
@@ -179,9 +180,12 @@
PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
buffer_len(&b))) == 1) {
authenticated = 1;
+ authctxt->last_details = pubkey;
/* Record the successful key to prevent reuse */
auth2_record_userkey(authctxt, key);
key = NULL; /* Don't free below */
+ } else {
+ free(pubkey);
}
buffer_free(&b);
free(sig);
@@ -222,7 +226,7 @@
void
pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
{
- char *fp, *extra;
+ char *extra, *pubkey;
va_list ap;
int i;
@@ -232,27 +236,13 @@
i = vasprintf(&extra, fmt, ap);
va_end(ap);
if (i < 0 || extra == NULL)
- fatal("%s: vasprintf failed", __func__);
+ fatal("%s: vasprintf failed", __func__);
}
- if (key_is_cert(key)) {
- fp = sshkey_fingerprint(key->cert->signature_key,
- options.fingerprint_hash, SSH_FP_DEFAULT);
- auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
- key_type(key), key->cert->key_id,
- (unsigned long long)key->cert->serial,
- key_type(key->cert->signature_key),
- fp == NULL ? "(null)" : fp,
- extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
- free(fp);
- } else {
- fp = sshkey_fingerprint(key, options.fingerprint_hash,
- SSH_FP_DEFAULT);
- auth_info(authctxt, "%s %s%s%s", key_type(key),
- fp == NULL ? "(null)" : fp,
- extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
- free(fp);
- }
+ pubkey = sshkey_format_oneline(key, options.fingerprint_hash);
+ auth_info(authctxt, "%s%s%s", pubkey, extra == NULL ? "" : ", ",
+ extra == NULL ? "" : extra);
+ free(pubkey);
free(extra);
}
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/auth.h openssh-7.3p1-expose-pam/auth.h
--- openssh-7.3p1/auth.h 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-expose-pam/auth.h 2016-08-07 19:29:05.291169708 +0200
@@ -81,6 +81,9 @@
struct sshkey **prev_userkeys;
u_int nprev_userkeys;
+
+ char *last_details;
+ char *auth_details;
};
/*
* Every authentication method has to handle authentication requests for
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/auth-pam.c openssh-7.3p1-expose-pam/auth-pam.c
--- openssh-7.3p1/auth-pam.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-expose-pam/auth-pam.c 2016-08-07 19:29:05.291169708 +0200
@@ -684,6 +684,11 @@
return (NULL);
}
+ /* Notify PAM about any already successful auth methods */
+ if (options.expose_auth_methods >= EXPOSE_AUTHMETH_PAMONLY &&
+ authctxt->auth_details)
+ do_pam_putenv("SSH_USER_AUTH", authctxt->auth_details);
+
ctxt = xcalloc(1, sizeof *ctxt);
/* Start the authentication thread */
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/gss-serv.c openssh-7.3p1-expose-pam/gss-serv.c
--- openssh-7.3p1/gss-serv.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-expose-pam/gss-serv.c 2016-08-07 19:29:05.292169699 +0200
@@ -356,6 +356,16 @@
}
/* Privileged */
+char*
+ssh_gssapi_get_displayname(void)
+{
+ if (gssapi_client.displayname.length != 0 &&
+ gssapi_client.displayname.value != NULL)
+ return strdup((char *)gssapi_client.displayname.value);
+ return NULL;
+}
+
+/* Privileged */
int
ssh_gssapi_userok(char *user)
{
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/monitor.c openssh-7.3p1-expose-pam/monitor.c
--- openssh-7.3p1/monitor.c 2016-08-07 19:28:17.665620825 +0200
+++ openssh-7.3p1-expose-pam/monitor.c 2016-08-07 19:29:05.292169699 +0200
@@ -336,6 +336,7 @@
{
struct mon_table *ent;
int authenticated = 0, partial = 0;
+ char *prev_auth_details;
debug3("preauth child monitor started");
@@ -369,6 +370,18 @@
auth_submethod = NULL;
authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
+ if (authenticated) {
+ prev_auth_details = authctxt->auth_details;
+ xasprintf(&authctxt->auth_details, "%s%s%s%s%s",
+ prev_auth_details ? prev_auth_details : "",
+ prev_auth_details ? ", " : "", auth_method,
+ authctxt->last_details ? ": " : "",
+ authctxt->last_details ? authctxt->last_details : "");
+ free(prev_auth_details);
+ }
+ free(authctxt->last_details);
+ authctxt->last_details = NULL;
+
/* Special handling for multiple required authentications */
if (options.num_auth_methods != 0) {
if (!compat20)
@@ -1460,6 +1473,10 @@
debug3("%s: key %p signature %s",
__func__, key, (verified == 1) ? "verified" : "unverified");
+ if (verified == 1)
+ authctxt->last_details = sshkey_format_oneline(key,
+ options.fingerprint_hash);
+
/* If auth was successful then record key to ensure it isn't reused */
if (verified == 1 && key_blobtype == MM_USERKEY)
auth2_record_userkey(authctxt, key);
@@ -2085,6 +2102,9 @@
auth_method = "gssapi-with-mic";
+ if (authenticated)
+ authctxt->last_details = ssh_gssapi_get_displayname();
+
/* Monitor loop will terminate if authenticated */
return (authenticated);
}
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/servconf.c openssh-7.3p1-expose-pam/servconf.c
--- openssh-7.3p1/servconf.c 2016-08-07 19:28:17.677620710 +0200
+++ openssh-7.3p1-expose-pam/servconf.c 2016-08-07 19:32:19.025403136 +0200
@@ -170,6 +170,7 @@
options->ip_qos_bulk = -1;
options->version_addendum = NULL;
options->fingerprint_hash = -1;
+ options->expose_auth_methods = -1;
}
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
@@ -356,6 +357,8 @@
options->fwd_opts.streamlocal_bind_unlink = 0;
if (options->fingerprint_hash == -1)
options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
+ if (options->expose_auth_methods == -1)
+ options->expose_auth_methods = EXPOSE_AUTHMETH_NEVER;
assemble_algorithms(options);
@@ -441,6 +444,7 @@
sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
sStreamLocalBindMask, sStreamLocalBindUnlink,
sAllowStreamLocalForwarding, sFingerprintHash,
+ sExposeAuthenticationMethods,
sDeprecated, sUnsupported
} ServerOpCodes;
@@ -584,6 +588,7 @@
{ "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
{ "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
{ "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL },
+ { "exposeauthenticationmethods", sExposeAuthenticationMethods, SSHCFG_ALL },
{ NULL, sBadOption, 0 }
};
@@ -973,6 +978,12 @@
{ "local", FORWARD_LOCAL },
{ NULL, -1 }
};
+static const struct multistate multistate_exposeauthmeth[] = {
+ { "never", EXPOSE_AUTHMETH_NEVER },
+ { "pam-only", EXPOSE_AUTHMETH_PAMONLY },
+ { "pam-and-env", EXPOSE_AUTHMETH_PAMENV },
+ { NULL, -1}
+};
int
process_server_config_line(ServerOptions *options, char *line,
@@ -1887,6 +1898,11 @@
options->fingerprint_hash = value;
break;
+ case sExposeAuthenticationMethods:
+ intptr = &options->expose_auth_methods;
+ multistate_ptr = multistate_exposeauthmeth;
+ goto parse_multistate;
+
case sDeprecated:
logit("%s line %d: Deprecated option %s",
filename, linenum, arg);
@@ -2044,6 +2060,7 @@
M_CP_INTOPT(ip_qos_bulk);
M_CP_INTOPT(rekey_limit);
M_CP_INTOPT(rekey_interval);
+ M_CP_INTOPT(expose_auth_methods);
/*
* The bind_mask is a mode_t that may be unsigned, so we can't use
@@ -2160,6 +2177,8 @@
return fmt_multistate_int(val, multistate_tcpfwd);
case sFingerprintHash:
return ssh_digest_alg_name(val);
+ case sExposeAuthenticationMethods:
+ return fmt_multistate_int(val, multistate_exposeauthmeth);
case sProtocol:
switch (val) {
case SSH_PROTO_1:
@@ -2350,6 +2369,7 @@
dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
+ dump_cfg_fmtint(sExposeAuthenticationMethods, o->expose_auth_methods);
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/servconf.h openssh-7.3p1-expose-pam/servconf.h
--- openssh-7.3p1/servconf.h 2016-08-07 19:28:17.660620873 +0200
+++ openssh-7.3p1-expose-pam/servconf.h 2016-08-07 19:29:05.294169680 +0200
@@ -48,6 +48,11 @@
#define FORWARD_LOCAL (1<<1)
#define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL)
+/* Expose AuthenticationMethods */
+#define EXPOSE_AUTHMETH_NEVER 0
+#define EXPOSE_AUTHMETH_PAMONLY 1
+#define EXPOSE_AUTHMETH_PAMENV 2
+
#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */
#define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */
@@ -196,6 +201,8 @@
char *auth_methods[MAX_AUTH_METHODS];
int fingerprint_hash;
+
+ int expose_auth_methods; /* EXPOSE_AUTHMETH_* above */
} ServerOptions;
/* Information about the incoming connection as used by Match */
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/session.c openssh-7.3p1-expose-pam/session.c
--- openssh-7.3p1/session.c 2016-08-07 19:28:17.666620815 +0200
+++ openssh-7.3p1-expose-pam/session.c 2016-08-07 19:29:05.295169670 +0200
@@ -1160,6 +1160,12 @@
}
*var_val++ = '\0';
+ if (options.expose_auth_methods < EXPOSE_AUTHMETH_PAMENV &&
+ strcmp(var_name, "SSH_USER_AUTH") == 0) {
+ free(var_name);
+ continue;
+ }
+
debug3("Copy environment: %s=%s", var_name, var_val);
child_set_env(env, envsize, var_name, var_val);
@@ -1342,6 +1348,11 @@
}
#endif /* USE_PAM */
+ if (options.expose_auth_methods >= EXPOSE_AUTHMETH_PAMENV &&
+ s->authctxt->auth_details)
+ child_set_env(&env, &envsize, "SSH_USER_AUTH",
+ s->authctxt->auth_details);
+
if (auth_sock_name != NULL)
child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
auth_sock_name);
@@ -2773,6 +2784,9 @@
if (authctxt == NULL)
return;
+ free(authctxt->auth_details);
+ authctxt->auth_details = NULL;
+
#ifdef USE_PAM
if (options.use_pam) {
sshpam_cleanup();
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/ssh.1 openssh-7.3p1-expose-pam/ssh.1
--- openssh-7.3p1/ssh.1 2016-08-07 19:28:17.674620739 +0200
+++ openssh-7.3p1-expose-pam/ssh.1 2016-08-07 19:29:05.295169670 +0200
@@ -1420,6 +1420,10 @@
This variable contains the original command line if a forced command
is executed.
It can be used to extract the original arguments.
+.It Ev SSH_USER_AUTH
+This variable contains, for SSH2 only, a comma-separated list of authentication
+methods that were successfuly used to authenticate. When possible, these
+methods are extended with detailed information on the credential used.
.It Ev SSH_TTY
This is set to the name of the tty (path to the device) associated
with the current shell or command.
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/sshd_config.5 openssh-7.3p1-expose-pam/sshd_config.5
--- openssh-7.3p1/sshd_config.5 2016-08-07 19:28:17.661620863 +0200
+++ openssh-7.3p1-expose-pam/sshd_config.5 2016-08-07 19:29:05.296169661 +0200
@@ -579,6 +579,21 @@
See PATTERNS in
.Xr ssh_config 5
for more information on patterns.
+.It Cm ExposeAuthenticationMethods
+When using SSH2, this option controls the exposure of the list of
+successful authentication methods to PAM during the authentication
+and to the shell environment via the
+.Cm SSH_USER_AUTH
+variable. See the description of this variable for more details.
+Valid options are:
+.Dq never
+(Do not expose successful authentication methods),
+.Dq pam-only
+(Only expose them to PAM during authentication, not afterwards),
+.Dq pam-and-env
+(Expose them to PAM and keep them in the shell environment).
+The default is
+.Dq never .
.It Cm FingerprintHash
Specifies the hash algorithm used when logging key fingerprints.
Valid options are:
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/ssh-gss.h openssh-7.3p1-expose-pam/ssh-gss.h
--- openssh-7.3p1/ssh-gss.h 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-expose-pam/ssh-gss.h 2016-08-07 19:30:15.338519247 +0200
@@ -124,6 +124,7 @@
/* In the server */
OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
int ssh_gssapi_userok(char *name);
+char* ssh_gssapi_get_displayname(void);
OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
void ssh_gssapi_do_child(char ***, u_int *);
void ssh_gssapi_cleanup_creds(void);
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/sshkey.c openssh-7.3p1-expose-pam/sshkey.c
--- openssh-7.3p1/sshkey.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-expose-pam/sshkey.c 2016-08-07 19:29:05.297169652 +0200
@@ -58,6 +58,7 @@
#define SSHKEY_INTERNAL
#include "sshkey.h"
#include "match.h"
+#include "xmalloc.h"
/* openssh private key file format */
#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
@@ -1189,6 +1190,30 @@
return retval;
}
+char *
+sshkey_format_oneline(const struct sshkey *key, int dgst_alg)
+{
+ char *fp, *result;
+
+ if (sshkey_is_cert(key)) {
+ fp = sshkey_fingerprint(key->cert->signature_key, dgst_alg,
+ SSH_FP_DEFAULT);
+ xasprintf(&result, "%s ID %s (serial %llu) CA %s %s",
+ sshkey_type(key), key->cert->key_id,
+ (unsigned long long)key->cert->serial,
+ sshkey_type(key->cert->signature_key),
+ fp == NULL ? "(null)" : fp);
+ free(fp);
+ } else {
+ fp = sshkey_fingerprint(key, dgst_alg, SSH_FP_DEFAULT);
+ xasprintf(&result, "%s %s", sshkey_type(key),
+ fp == NULL ? "(null)" : fp);
+ free(fp);
+ }
+
+ return result;
+}
+
#ifdef WITH_SSH1
/*
* Reads a multiple-precision integer in decimal from the buffer, and advances
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/sshkey.h openssh-7.3p1-expose-pam/sshkey.h
--- openssh-7.3p1/sshkey.h 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-expose-pam/sshkey.h 2016-08-07 19:29:05.298169642 +0200
@@ -123,6 +123,7 @@
int, enum sshkey_fp_rep);
int sshkey_fingerprint_raw(const struct sshkey *k,
int, u_char **retp, size_t *lenp);
+char *sshkey_format_oneline(const struct sshkey *k, int dgst_alg);
const char *sshkey_type(const struct sshkey *);
const char *sshkey_cert_type(const struct sshkey *);
int sshkey_write(const struct sshkey *, FILE *);

View file

@ -0,0 +1,275 @@
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/log.c openssh-7.3p1-log-in-chroot/log.c
--- openssh-7.3p1/log.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-log-in-chroot/log.c 2016-08-07 19:22:31.491195708 +0200
@@ -250,6 +250,11 @@
void
log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
{
+ log_init_handler(av0, level, facility, on_stderr, 1);
+}
+
+void
+log_init_handler(char *av0, LogLevel level, SyslogFacility facility, int on_stderr, int reset_handler) {
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
struct syslog_data sdata = SYSLOG_DATA_INIT;
#endif
@@ -273,8 +278,10 @@
exit(1);
}
- log_handler = NULL;
- log_handler_ctx = NULL;
+ if (reset_handler) {
+ log_handler = NULL;
+ log_handler_ctx = NULL;
+ }
log_on_stderr = on_stderr;
if (on_stderr)
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/log.h openssh-7.3p1-log-in-chroot/log.h
--- openssh-7.3p1/log.h 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-log-in-chroot/log.h 2016-08-07 19:22:31.492195697 +0200
@@ -49,6 +49,7 @@
typedef void (log_handler_fn)(LogLevel, const char *, void *);
void log_init(char *, LogLevel, SyslogFacility, int);
+void log_init_handler(char *, LogLevel, SyslogFacility, int, int);
void log_change_level(LogLevel);
int log_is_on_stderr(void);
void log_redirect_stderr_to(const char *);
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/monitor.c openssh-7.3p1-log-in-chroot/monitor.c
--- openssh-7.3p1/monitor.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-log-in-chroot/monitor.c 2016-08-07 19:22:31.493195686 +0200
@@ -343,6 +343,8 @@
close(pmonitor->m_log_sendfd);
pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
+ pmonitor->m_state = "preauth";
+
authctxt = _authctxt;
memset(authctxt, 0, sizeof(*authctxt));
@@ -447,6 +449,8 @@
close(pmonitor->m_recvfd);
pmonitor->m_recvfd = -1;
+ pmonitor->m_state = "postauth";
+
monitor_set_child_handler(pmonitor->m_pid);
signal(SIGHUP, &monitor_child_handler);
signal(SIGTERM, &monitor_child_handler);
@@ -539,7 +543,7 @@
if (log_level_name(level) == NULL)
fatal("%s: invalid log level %u (corrupted message?)",
__func__, level);
- do_log2(level, "%s [preauth]", msg);
+ do_log2(level, "%s [%s]", msg, pmonitor->m_state);
buffer_free(&logmsg);
free(msg);
@@ -1958,13 +1962,28 @@
(ssh_packet_comp_free_func *)mm_zfree);
}
+ mon->m_state = "";
+
return mon;
}
void
-monitor_reinit(struct monitor *mon)
+monitor_reinit(struct monitor *mon, const char *chroot_dir)
{
- monitor_openfds(mon, 0);
+ struct stat dev_log_stat;
+ char *dev_log_path;
+ int do_logfds = 0;
+
+ if (chroot_dir != NULL) {
+ xasprintf(&dev_log_path, "%s/dev/log", chroot_dir);
+
+ if (stat(dev_log_path, &dev_log_stat) != 0) {
+ debug("%s: /dev/log doesn't exist in %s chroot - will try to log via monitor using [postauth] suffix", __func__, chroot_dir);
+ do_logfds = 1;
+ }
+ free(dev_log_path);
+ }
+ monitor_openfds(mon, do_logfds);
}
#ifdef GSSAPI
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/monitor.h openssh-7.3p1-log-in-chroot/monitor.h
--- openssh-7.3p1/monitor.h 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-log-in-chroot/monitor.h 2016-08-07 19:22:31.493195686 +0200
@@ -77,10 +77,11 @@
struct mm_master *m_zlib;
struct kex **m_pkex;
pid_t m_pid;
+ char *m_state;
};
struct monitor *monitor_init(void);
-void monitor_reinit(struct monitor *);
+void monitor_reinit(struct monitor *, const char *);
void monitor_sync(struct monitor *);
struct Authctxt;
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/session.c openssh-7.3p1-log-in-chroot/session.c
--- openssh-7.3p1/session.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-log-in-chroot/session.c 2016-08-07 19:23:24.961601311 +0200
@@ -162,6 +162,7 @@
static int is_child = 0;
static int in_chroot = 0;
+static int have_dev_log = 1;
/* Name and directory of socket for authentication agent forwarding. */
static char *auth_sock_name = NULL;
@@ -529,8 +530,8 @@
is_child = 1;
/* Child. Reinitialize the log since the pid has changed. */
- log_init(__progname, options.log_level,
- options.log_facility, log_stderr);
+ log_init_handler(__progname, options.log_level,
+ options.log_facility, log_stderr, have_dev_log);
/*
* Create a new session and process group since the 4.4BSD
@@ -698,8 +699,8 @@
close(ptymaster);
/* Child. Reinitialize the log because the pid has changed. */
- log_init(__progname, options.log_level,
- options.log_facility, log_stderr);
+ log_init_handler(__progname, options.log_level,
+ options.log_facility, log_stderr, have_dev_log);
/* Close the master side of the pseudo tty. */
close(ptyfd);
@@ -805,6 +806,7 @@
int ret;
const char *forced = NULL, *tty = NULL;
char session_type[1024];
+ struct stat dev_log_stat;
if (options.adm_forced_command) {
original_command = command;
@@ -839,6 +841,10 @@
tty += 5;
}
+ if (lstat("/dev/log", &dev_log_stat) != 0) {
+ have_dev_log = 0;
+ }
+
verbose("Starting session: %s%s%s for %s from %.200s port %d id %d",
session_type,
tty == NULL ? "" : " on ",
@@ -1671,14 +1677,6 @@
* descriptors left by system functions. They will be closed later.
*/
endpwent();
-
- /*
- * Close any extra open file descriptors so that we don't have them
- * hanging around in clients. Note that we want to do this after
- * initgroups, because at least on Solaris 2.3 it leaves file
- * descriptors open.
- */
- closefrom(STDERR_FILENO + 1);
}
/*
@@ -1825,8 +1823,6 @@
exit(1);
}
- closefrom(STDERR_FILENO + 1);
-
if (!options.use_login)
do_rc_files(s, shell);
@@ -1853,7 +1849,7 @@
#ifdef WITH_SELINUX
ssh_selinux_change_context("sftpd_t");
#endif
- exit(sftp_server_main(i, argv, s->pw));
+ exit(sftp_server_main(i, argv, s->pw, have_dev_log));
}
fflush(NULL);
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/sftp.h openssh-7.3p1-log-in-chroot/sftp.h
--- openssh-7.3p1/sftp.h 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-log-in-chroot/sftp.h 2016-08-07 19:22:31.496195652 +0200
@@ -97,5 +97,5 @@
struct passwd;
-int sftp_server_main(int, char **, struct passwd *);
+int sftp_server_main(int, char **, struct passwd *, int);
void sftp_server_cleanup_exit(int) __attribute__((noreturn));
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/sftp-server.c openssh-7.3p1-log-in-chroot/sftp-server.c
--- openssh-7.3p1/sftp-server.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-log-in-chroot/sftp-server.c 2016-08-07 19:22:31.496195652 +0200
@@ -1498,7 +1498,7 @@
}
int
-sftp_server_main(int argc, char **argv, struct passwd *user_pw)
+sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handler)
{
fd_set *rset, *wset;
int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
@@ -1512,7 +1512,7 @@
ssh_malloc_init(); /* must be called before any mallocs */
__progname = ssh_get_progname(argv[0]);
- log_init(__progname, log_level, log_facility, log_stderr);
+ log_init_handler(__progname, log_level, log_facility, log_stderr, reset_handler);
pw = pwcopy(user_pw);
@@ -1583,7 +1583,7 @@
}
}
- log_init(__progname, log_level, log_facility, log_stderr);
+ log_init_handler(__progname, log_level, log_facility, log_stderr, reset_handler);
/*
* On platforms where we can, avoid making /proc/self/{mem,maps}
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/sftp-server-main.c openssh-7.3p1-log-in-chroot/sftp-server-main.c
--- openssh-7.3p1/sftp-server-main.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-log-in-chroot/sftp-server-main.c 2016-08-07 19:22:31.495195663 +0200
@@ -49,5 +49,5 @@
return 1;
}
- return (sftp_server_main(argc, argv, user_pw));
+ return (sftp_server_main(argc, argv, user_pw, 0));
}
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/sshd.c openssh-7.3p1-log-in-chroot/sshd.c
--- openssh-7.3p1/sshd.c 2016-08-07 19:22:07.254471533 +0200
+++ openssh-7.3p1-log-in-chroot/sshd.c 2016-08-07 19:22:31.497195640 +0200
@@ -744,7 +744,7 @@
}
/* New socket pair */
- monitor_reinit(pmonitor);
+ monitor_reinit(pmonitor, options.chroot_directory);
pmonitor->m_pid = fork();
if (pmonitor->m_pid == -1)
@@ -762,6 +762,11 @@
close(pmonitor->m_sendfd);
pmonitor->m_sendfd = -1;
+ close(pmonitor->m_log_recvfd);
+ pmonitor->m_log_recvfd = -1;
+
+ if (pmonitor->m_log_sendfd != -1)
+ set_log_handler(mm_log_handler, pmonitor);
/* Demote the private keys to public keys. */
demote_sensitive_data();

View file

@ -0,0 +1,314 @@
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/clientloop.c openssh-7.3p1-show-more-fingerprints/clientloop.c
--- openssh-7.3p1/clientloop.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-show-more-fingerprints/clientloop.c 2016-08-07 19:27:25.650122678 +0200
@@ -2235,7 +2235,7 @@
if (ctx->keys_seen[i] != 2)
continue;
if ((fp = sshkey_fingerprint(ctx->keys[i],
- options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
+ options.fingerprint_hash[0], SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint failed", __func__);
do_log2(loglevel, "Learned new hostkey: %s %s",
sshkey_type(ctx->keys[i]), fp);
@@ -2243,7 +2243,7 @@
}
for (i = 0; i < ctx->nold; i++) {
if ((fp = sshkey_fingerprint(ctx->old_keys[i],
- options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
+ options.fingerprint_hash[0], SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint failed", __func__);
do_log2(loglevel, "Deprecating obsolete hostkey: %s %s",
sshkey_type(ctx->old_keys[i]), fp);
@@ -2286,7 +2286,7 @@
(r = hostfile_replace_entries(options.user_hostfiles[0],
ctx->host_str, ctx->ip_str, ctx->keys, ctx->nkeys,
options.hash_known_hosts, 0,
- options.fingerprint_hash)) != 0)
+ options.fingerprint_hash[0])) != 0)
error("%s: hostfile_replace_entries failed: %s",
__func__, ssh_err(r));
}
@@ -2399,7 +2399,7 @@
error("%s: parse key: %s", __func__, ssh_err(r));
goto out;
}
- fp = sshkey_fingerprint(key, options.fingerprint_hash,
+ fp = sshkey_fingerprint(key, options.fingerprint_hash[0],
SSH_FP_DEFAULT);
debug3("%s: received %s key %s", __func__,
sshkey_type(key), fp);
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/readconf.c openssh-7.3p1-show-more-fingerprints/readconf.c
--- openssh-7.3p1/readconf.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-show-more-fingerprints/readconf.c 2016-08-07 19:27:25.651122668 +0200
@@ -1623,16 +1623,18 @@
goto parse_string;
case oFingerprintHash:
- intptr = &options->fingerprint_hash;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.",
- filename, linenum);
- if ((value = ssh_digest_alg_by_name(arg)) == -1)
- fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
- filename, linenum, arg);
- if (*activep && *intptr == -1)
- *intptr = value;
+ if (*activep && options->num_fingerprint_hash == 0)
+ while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+ value = ssh_digest_alg_by_name(arg);
+ if (value == -1)
+ fatal("%s line %d: unknown fingerprints algorithm specs: %s.",
+ filename, linenum, arg);
+ if (options->num_fingerprint_hash >= SSH_DIGEST_MAX)
+ fatal("%s line %d: too many fingerprints algorithm specs.",
+ filename, linenum);
+ options->fingerprint_hash[
+ options->num_fingerprint_hash++] = value;
+ }
break;
case oUpdateHostkeys:
@@ -1854,7 +1856,7 @@
options->canonicalize_fallback_local = -1;
options->canonicalize_hostname = -1;
options->revoked_host_keys = NULL;
- options->fingerprint_hash = -1;
+ options->num_fingerprint_hash = 0;
options->update_hostkeys = -1;
options->hostbased_key_types = NULL;
options->pubkey_key_types = NULL;
@@ -2041,8 +2043,10 @@
options->canonicalize_fallback_local = 1;
if (options->canonicalize_hostname == -1)
options->canonicalize_hostname = SSH_CANONICALISE_NO;
- if (options->fingerprint_hash == -1)
- options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
+ if (options->num_fingerprint_hash == 0) {
+ options->fingerprint_hash[options->num_fingerprint_hash++] = SSH_DIGEST_SHA256;
+ options->fingerprint_hash[options->num_fingerprint_hash++] = SSH_DIGEST_MD5;
+ }
if (options->update_hostkeys == -1)
options->update_hostkeys = 0;
if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 ||
@@ -2428,6 +2432,17 @@
}
static void
+dump_cfg_fmtarray(OpCodes code, u_int count, int *vals)
+{
+ u_int i;
+
+ printf("%s", lookup_opcode_name(code));
+ for (i = 0; i < count; i++)
+ printf(" %s", fmt_intarg(code, vals[i]));
+ printf("\n");
+}
+
+static void
dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
{
u_int i;
@@ -2503,7 +2518,6 @@
dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
- dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
dump_cfg_fmtint(oForwardAgent, o->forward_agent);
dump_cfg_fmtint(oForwardX11, o->forward_x11);
dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
@@ -2573,6 +2587,7 @@
dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
+ dump_cfg_fmtarray(oFingerprintHash, o->num_fingerprint_hash, o->fingerprint_hash);
/* Special cases */
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/readconf.h openssh-7.3p1-show-more-fingerprints/readconf.h
--- openssh-7.3p1/readconf.h 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-show-more-fingerprints/readconf.h 2016-08-07 19:27:25.651122668 +0200
@@ -21,6 +21,7 @@
#define MAX_SEND_ENV 256
#define SSH_MAX_HOSTS_FILES 32
#define MAX_CANON_DOMAINS 32
+#define MAX_SSH_DIGESTS 32
#define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path)
struct allowed_cname {
@@ -156,7 +157,8 @@
char *revoked_host_keys;
- int fingerprint_hash;
+ int num_fingerprint_hash;
+ int fingerprint_hash[MAX_SSH_DIGESTS];
int update_hostkeys; /* one of SSH_UPDATE_HOSTKEYS_* */
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/ssh_config.5 openssh-7.3p1-show-more-fingerprints/ssh_config.5
--- openssh-7.3p1/ssh_config.5 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-show-more-fingerprints/ssh_config.5 2016-08-07 19:27:25.651122668 +0200
@@ -725,13 +725,13 @@
The default is
.Dq no .
.It Cm FingerprintHash
-Specifies the hash algorithm used when displaying key fingerprints.
+Specifies the hash algorithms used when displaying key fingerprints.
Valid options are:
.Dq md5
and
.Dq sha256 .
The default is
-.Dq sha256 .
+.Dq "sha256 md5".
.It Cm ForwardAgent
Specifies whether the connection to the authentication agent (if any)
will be forwarded to the remote machine.
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/sshconnect2.c openssh-7.3p1-show-more-fingerprints/sshconnect2.c
--- openssh-7.3p1/sshconnect2.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-show-more-fingerprints/sshconnect2.c 2016-08-07 19:27:25.652122658 +0200
@@ -612,7 +612,7 @@
key->type, pktype);
goto done;
}
- if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
+ if ((fp = sshkey_fingerprint(key, options.fingerprint_hash[0],
SSH_FP_DEFAULT)) == NULL)
goto done;
debug2("input_userauth_pk_ok: fp %s", fp);
@@ -1050,7 +1050,7 @@
int matched, ret = -1, have_sig = 1;
char *fp;
- if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
+ if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash[0],
SSH_FP_DEFAULT)) == NULL)
return 0;
debug3("%s: %s %s", __func__, key_type(id->key), fp);
@@ -1732,7 +1732,7 @@
goto out;
}
- if ((fp = sshkey_fingerprint(private, options.fingerprint_hash,
+ if ((fp = sshkey_fingerprint(private, options.fingerprint_hash[0],
SSH_FP_DEFAULT)) == NULL) {
error("%s: sshkey_fingerprint failed", __func__);
goto out;
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/sshconnect.c openssh-7.3p1-show-more-fingerprints/sshconnect.c
--- openssh-7.3p1/sshconnect.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-show-more-fingerprints/sshconnect.c 2016-08-07 19:27:25.654122639 +0200
@@ -923,9 +923,9 @@
"of known hosts.", type, ip);
} else if (options.visual_host_key) {
fp = sshkey_fingerprint(host_key,
- options.fingerprint_hash, SSH_FP_DEFAULT);
+ options.fingerprint_hash[0], SSH_FP_DEFAULT);
ra = sshkey_fingerprint(host_key,
- options.fingerprint_hash, SSH_FP_RANDOMART);
+ options.fingerprint_hash[0], SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
logit("Host key fingerprint is %s\n%s", fp, ra);
@@ -967,12 +967,6 @@
else
snprintf(msg1, sizeof(msg1), ".");
/* The default */
- fp = sshkey_fingerprint(host_key,
- options.fingerprint_hash, SSH_FP_DEFAULT);
- ra = sshkey_fingerprint(host_key,
- options.fingerprint_hash, SSH_FP_RANDOMART);
- if (fp == NULL || ra == NULL)
- fatal("%s: sshkey_fingerprint fail", __func__);
msg2[0] = '\0';
if (options.verify_host_key_dns) {
if (matching_host_key_dns)
@@ -986,16 +980,28 @@
}
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"
+ "established%s\n", host, ip, msg1);
+ for (i = 0; i < options.num_fingerprint_hash; i++) {
+ fp = sshkey_fingerprint(host_key,
+ options.fingerprint_hash[i], SSH_FP_DEFAULT);
+ ra = sshkey_fingerprint(host_key,
+ options.fingerprint_hash[i], SSH_FP_RANDOMART);
+ if (fp == NULL || ra == NULL)
+ fatal("%s: sshkey_fingerprint fail", __func__);
+ len = strlen(msg);
+ snprintf(msg+len, sizeof(msg)-len,
+ "%s key fingerprint is %s.%s%s\n%s",
+ type, fp,
+ options.visual_host_key ? "\n" : "",
+ options.visual_host_key ? ra : "",
+ msg2);
+ free(ra);
+ free(fp);
+ }
+ len = strlen(msg);
+ snprintf(msg+len, sizeof(msg)-len,
"Are you sure you want to continue connecting "
- "(yes/no)? ",
- host, ip, msg1, type, fp,
- options.visual_host_key ? "\n" : "",
- options.visual_host_key ? ra : "",
- msg2);
- free(ra);
- free(fp);
+ "(yes/no)? ");
if (!confirm(msg))
goto fail;
hostkey_trusted = 1; /* user explicitly confirmed */
@@ -1245,7 +1251,7 @@
struct sshkey *plain = NULL;
if ((fp = sshkey_fingerprint(host_key,
- options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
+ options.fingerprint_hash[0], SSH_FP_DEFAULT)) == NULL) {
error("%s: fingerprint host key: %s", __func__, ssh_err(r));
r = -1;
goto out;
@@ -1253,7 +1259,7 @@
if (sshkey_is_cert(host_key)) {
if ((cafp = sshkey_fingerprint(host_key->cert->signature_key,
- options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
+ options.fingerprint_hash[0], SSH_FP_DEFAULT)) == NULL) {
error("%s: fingerprint CA key: %s",
__func__, ssh_err(r));
r = -1;
@@ -1433,9 +1439,9 @@
if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
continue;
fp = sshkey_fingerprint(found->key,
- options.fingerprint_hash, SSH_FP_DEFAULT);
+ options.fingerprint_hash[0], SSH_FP_DEFAULT);
ra = sshkey_fingerprint(found->key,
- options.fingerprint_hash, SSH_FP_RANDOMART);
+ options.fingerprint_hash[0], SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
logit("WARNING: %s key found for host %s\n"
@@ -1458,7 +1464,7 @@
{
char *fp;
- fp = sshkey_fingerprint(host_key, options.fingerprint_hash,
+ fp = sshkey_fingerprint(host_key, options.fingerprint_hash[0],
SSH_FP_DEFAULT);
if (fp == NULL)
fatal("%s: sshkey_fingerprint fail", __func__);
diff -Naur -x '*.rej' -x '*.orig' -x '*~' openssh-7.3p1/ssh-keysign.c openssh-7.3p1-show-more-fingerprints/ssh-keysign.c
--- openssh-7.3p1/ssh-keysign.c 2016-07-28 00:54:27.000000000 +0200
+++ openssh-7.3p1-show-more-fingerprints/ssh-keysign.c 2016-08-07 19:27:25.652122658 +0200
@@ -285,7 +285,7 @@
}
}
if (!found) {
- if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
+ if ((fp = sshkey_fingerprint(key, options.fingerprint_hash[0],
SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint failed", __progname);
fatal("no matching hostkey found for key %s %s",

View file

@ -23,13 +23,13 @@
Summary: OpenSSH free Secure Shell (SSH) implementation
Name: openssh
Version: 7.2p2
Version: 7.3p1
Release: 1
License: BSD
Group: Networking/Remote access
Url: http://www.openssh.com/
Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/%{name}-%{version}.tar.gz
Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/%{name}-%{version}.tar.gz.asc
Source0: http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/%{name}-%{version}.tar.gz
Source1: http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/%{name}-%{version}.tar.gz.asc
# ssh-copy-id taken from debian, with "usage" added
Source3: ssh-copy-id
Source9: README.sftpfilecontrol
@ -69,6 +69,11 @@ Patch17: openssh-5.1p1-askpass-progress.patch
Patch18: openssh-4.3p2-askpass-grab-info.patch
Patch19: openssh-4.0p1-exit-deadlock.patch
Patch20: openssh-7.1p1-debian-restore-tcp-wrappers.patch
Patch21: openssh-7.2p2-x11.patch
Patch22: openssh-7.3p1-entropy.patch
Patch23: openssh-7.3p1-expose-pam.patch
Patch24: openssh-7.3p1-log-in-chroot.patch
Patch25: openssh-7.3p1-show-more-fingerprints.patch
BuildRequires: groff-base
BuildRequires: pam-devel
BuildRequires: tcp_wrappers-devel
@ -209,7 +214,7 @@ echo "This patch is broken or needs to be updated/rediffed"; exit 1
%patch12 -p1 -b .peak
install %{SOURCE21} .
%endif
%patch13 -p1 -b .canohost
# %patch13 -p1 -b .canohost
%if %{with audit}
%patch14 -p1 -b .audit
%endif
@ -217,6 +222,11 @@ install %{SOURCE21} .
%patch18 -p1 -b .grab-info
%patch19 -p1 -b .exit-deadlock
%patch20 -p1 -b .tcp_wrappers
%patch21 -p1 -b .sshdt
# %patch22 -p1 -b .sftp-force-mode
%patch23 -p1 -b .memory
%patch24 -p1 -b .fingerprint
%patch25 -p1 -b .expose-pam
install %{SOURCE12} .