|
|
674526 |
diff -up openssh-6.6p1/channels.c.security openssh-6.6p1/channels.c
|
|
|
674526 |
--- openssh-6.6p1/channels.c.security 2015-07-01 19:27:08.521162690 +0200
|
|
|
674526 |
+++ openssh-6.6p1/channels.c 2015-07-01 19:27:08.597162521 +0200
|
|
|
674526 |
@@ -151,6 +151,9 @@ static char *x11_saved_proto = NULL;
|
|
|
674526 |
static char *x11_saved_data = NULL;
|
|
|
674526 |
static u_int x11_saved_data_len = 0;
|
|
|
674526 |
|
|
|
674526 |
+/* Deadline after which all X11 connections are refused */
|
|
|
674526 |
+static u_int x11_refuse_time;
|
|
|
674526 |
+
|
|
|
674526 |
/*
|
|
|
674526 |
* Fake X11 authentication data. This is what the server will be sending us;
|
|
|
674526 |
* we should replace any occurrences of this by the real data.
|
|
|
674526 |
@@ -894,6 +897,13 @@ x11_open_helper(Buffer *b)
|
|
|
674526 |
u_char *ucp;
|
|
|
674526 |
u_int proto_len, data_len;
|
|
|
674526 |
|
|
|
674526 |
+ /* Is this being called after the refusal deadline? */
|
|
|
674526 |
+ if (x11_refuse_time != 0 && (u_int)monotime() >= x11_refuse_time) {
|
|
|
674526 |
+ verbose("Rejected X11 connection after ForwardX11Timeout "
|
|
|
674526 |
+ "expired");
|
|
|
674526 |
+ return -1;
|
|
|
674526 |
+ }
|
|
|
674526 |
+
|
|
|
674526 |
/* Check if the fixed size part of the packet is in buffer. */
|
|
|
674526 |
if (buffer_len(b) < 12)
|
|
|
674526 |
return 0;
|
|
|
674526 |
@@ -1457,6 +1467,12 @@ channel_set_reuseaddr(int fd)
|
|
|
674526 |
error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno));
|
|
|
674526 |
}
|
|
|
674526 |
|
|
|
674526 |
+void
|
|
|
674526 |
+channel_set_x11_refuse_time(u_int refuse_time)
|
|
|
674526 |
+{
|
|
|
674526 |
+ x11_refuse_time = refuse_time;
|
|
|
674526 |
+}
|
|
|
674526 |
+
|
|
|
674526 |
/*
|
|
|
674526 |
* This socket is listening for connections to a forwarded TCP/IP port.
|
|
|
674526 |
*/
|
|
|
674526 |
diff -up openssh-6.6p1/channels.h.security openssh-6.6p1/channels.h
|
|
|
674526 |
--- openssh-6.6p1/channels.h.security 2015-07-01 19:27:08.597162521 +0200
|
|
|
674526 |
+++ openssh-6.6p1/channels.h 2015-07-01 19:43:32.900950560 +0200
|
|
|
674526 |
@@ -279,6 +279,7 @@ int permitopen_port(const char *);
|
|
|
674526 |
|
|
|
674526 |
/* x11 forwarding */
|
|
|
674526 |
|
|
|
674526 |
+void channel_set_x11_refuse_time(u_int);
|
|
|
674526 |
int x11_connect_display(void);
|
|
|
674526 |
int x11_create_display_inet(int, int, int, u_int *, int **);
|
|
|
674526 |
void x11_input_open(int, u_int32_t, void *);
|
|
|
674526 |
diff -up openssh-6.6p1/clientloop.c.security openssh-6.6p1/clientloop.c
|
|
|
674526 |
--- openssh-6.6p1/clientloop.c.security 2015-07-01 19:27:08.540162648 +0200
|
|
|
674526 |
+++ openssh-6.6p1/clientloop.c 2015-07-01 19:44:51.139761508 +0200
|
|
|
674526 |
@@ -164,7 +164,7 @@ static int connection_in; /* Connection
|
|
|
674526 |
static int connection_out; /* Connection to server (output). */
|
|
|
674526 |
static int need_rekeying; /* Set to non-zero if rekeying is requested. */
|
|
|
674526 |
static int session_closed; /* In SSH2: login session closed. */
|
|
|
674526 |
-static int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
|
|
|
674526 |
+static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
|
|
|
674526 |
|
|
|
674526 |
static void client_init_dispatch(void);
|
|
|
674526 |
int session_ident = -1;
|
|
|
674526 |
@@ -302,7 +302,8 @@ client_x11_display_valid(const char *dis
|
|
|
674526 |
return 1;
|
|
|
674526 |
}
|
|
|
674526 |
|
|
|
674526 |
-#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
|
|
|
674526 |
+#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
|
|
|
674526 |
+#define X11_TIMEOUT_SLACK 60
|
|
|
674526 |
void
|
|
|
674526 |
client_x11_get_proto(const char *display, const char *xauth_path,
|
|
|
674526 |
u_int trusted, u_int timeout, char **_proto, char **_data)
|
|
|
674526 |
@@ -315,7 +316,7 @@ client_x11_get_proto(const char *display
|
|
|
674526 |
int got_data = 0, generated = 0, do_unlink = 0, i;
|
|
|
674526 |
char *xauthdir, *xauthfile;
|
|
|
674526 |
struct stat st;
|
|
|
674526 |
- u_int now;
|
|
|
674526 |
+ u_int now, x11_timeout_real;
|
|
|
674526 |
|
|
|
674526 |
xauthdir = xauthfile = NULL;
|
|
|
674526 |
*_proto = proto;
|
|
|
674526 |
@@ -348,6 +349,15 @@ client_x11_get_proto(const char *display
|
|
|
674526 |
xauthdir = xmalloc(MAXPATHLEN);
|
|
|
674526 |
xauthfile = xmalloc(MAXPATHLEN);
|
|
|
674526 |
mktemp_proto(xauthdir, MAXPATHLEN);
|
|
|
674526 |
+ /*
|
|
|
674526 |
+ * The authentication cookie should briefly outlive
|
|
|
674526 |
+ * ssh's willingness to forward X11 connections to
|
|
|
674526 |
+ * avoid nasty fail-open behaviour in the X server.
|
|
|
674526 |
+ */
|
|
|
674526 |
+ if (timeout >= UINT_MAX - X11_TIMEOUT_SLACK)
|
|
|
674526 |
+ x11_timeout_real = UINT_MAX;
|
|
|
674526 |
+ else
|
|
|
674526 |
+ x11_timeout_real = timeout + X11_TIMEOUT_SLACK;
|
|
|
674526 |
if (mkdtemp(xauthdir) != NULL) {
|
|
|
674526 |
do_unlink = 1;
|
|
|
674526 |
snprintf(xauthfile, MAXPATHLEN, "%s/xauthfile",
|
|
|
674526 |
@@ -355,17 +365,20 @@ client_x11_get_proto(const char *display
|
|
|
674526 |
snprintf(cmd, sizeof(cmd),
|
|
|
674526 |
"%s -f %s generate %s " SSH_X11_PROTO
|
|
|
674526 |
" untrusted timeout %u 2>" _PATH_DEVNULL,
|
|
|
674526 |
- xauth_path, xauthfile, display, timeout);
|
|
|
674526 |
+ xauth_path, xauthfile, display,
|
|
|
674526 |
+ x11_timeout_real);
|
|
|
674526 |
debug2("x11_get_proto: %s", cmd);
|
|
|
674526 |
- if (system(cmd) == 0)
|
|
|
674526 |
- generated = 1;
|
|
|
674526 |
if (x11_refuse_time == 0) {
|
|
|
674526 |
now = monotime() + 1;
|
|
|
674526 |
if (UINT_MAX - timeout < now)
|
|
|
674526 |
x11_refuse_time = UINT_MAX;
|
|
|
674526 |
else
|
|
|
674526 |
x11_refuse_time = now + timeout;
|
|
|
674526 |
+ channel_set_x11_refuse_time(
|
|
|
674526 |
+ x11_refuse_time);
|
|
|
674526 |
}
|
|
|
674526 |
+ if (system(cmd) == 0)
|
|
|
674526 |
+ generated = 1;
|
|
|
674526 |
}
|
|
|
674526 |
}
|
|
|
674526 |
|
|
|
674526 |
@@ -1884,7 +1897,7 @@ client_request_x11(const char *request_t
|
|
|
674526 |
"malicious server.");
|
|
|
674526 |
return NULL;
|
|
|
674526 |
}
|
|
|
674526 |
- if (x11_refuse_time != 0 && monotime() >= x11_refuse_time) {
|
|
|
674526 |
+ if (x11_refuse_time != 0 && (u_int)monotime() >= x11_refuse_time) {
|
|
|
674526 |
verbose("Rejected X11 connection after ForwardX11Timeout "
|
|
|
674526 |
"expired");
|
|
|
674526 |
return NULL;
|
|
|
674526 |
diff -up openssh-6.6p1/ssh-agent.c.security openssh-6.6p1/ssh-agent.c
|
|
|
674526 |
--- openssh-6.6p1/ssh-agent.c.security 2015-07-01 19:27:08.597162521 +0200
|
|
|
674526 |
+++ openssh-6.6p1/ssh-agent.c 2015-07-01 19:42:35.691088800 +0200
|
|
|
674526 |
@@ -64,6 +64,9 @@
|
|
|
674526 |
#include <time.h>
|
|
|
674526 |
#include <string.h>
|
|
|
674526 |
#include <unistd.h>
|
|
|
674526 |
+#ifdef HAVE_UTIL_H
|
|
|
674526 |
+#include <util.h>
|
|
|
674526 |
+#endif
|
|
|
674526 |
|
|
|
674526 |
#include "xmalloc.h"
|
|
|
674526 |
#include "ssh.h"
|
|
|
674526 |
@@ -129,8 +130,12 @@ char socket_name[MAXPATHLEN];
|
|
|
674526 |
char socket_dir[MAXPATHLEN];
|
|
|
674526 |
|
|
|
674526 |
/* locking */
|
|
|
674526 |
+#define LOCK_SIZE 32
|
|
|
674526 |
+#define LOCK_SALT_SIZE 16
|
|
|
674526 |
+#define LOCK_ROUNDS 1
|
|
|
674526 |
int locked = 0;
|
|
|
674526 |
-char *lock_passwd = NULL;
|
|
|
674526 |
+char lock_passwd[LOCK_SIZE];
|
|
|
674526 |
+char lock_salt[LOCK_SALT_SIZE];
|
|
|
674526 |
|
|
|
674526 |
extern char *__progname;
|
|
|
674526 |
|
|
|
674526 |
@@ -548,22 +553,45 @@ send:
|
|
|
674526 |
static void
|
|
|
674526 |
process_lock_agent(SocketEntry *e, int lock)
|
|
|
674526 |
{
|
|
|
674526 |
- int success = 0;
|
|
|
674526 |
- char *passwd;
|
|
|
674526 |
+ int success = 0, delay;
|
|
|
674526 |
+ char *passwd, passwdhash[LOCK_SIZE];
|
|
|
674526 |
+ static u_int fail_count = 0;
|
|
|
674526 |
+ size_t pwlen;
|
|
|
674526 |
|
|
|
674526 |
passwd = buffer_get_string(&e->request, NULL);
|
|
|
674526 |
- if (locked && !lock && strcmp(passwd, lock_passwd) == 0) {
|
|
|
674526 |
- locked = 0;
|
|
|
674526 |
- explicit_bzero(lock_passwd, strlen(lock_passwd));
|
|
|
674526 |
- free(lock_passwd);
|
|
|
674526 |
- lock_passwd = NULL;
|
|
|
674526 |
- success = 1;
|
|
|
674526 |
+ pwlen = strlen(passwd);
|
|
|
674526 |
+ if (pwlen == 0) {
|
|
|
674526 |
+ debug("empty password not supported");
|
|
|
674526 |
+ } else if (locked && !lock) {
|
|
|
674526 |
+ if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt),
|
|
|
674526 |
+ passwdhash, sizeof(passwdhash), LOCK_ROUNDS) < 0)
|
|
|
674526 |
+ fatal("bcrypt_pbkdf");
|
|
|
674526 |
+ if (timingsafe_bcmp(passwdhash, lock_passwd, LOCK_SIZE) == 0) {
|
|
|
674526 |
+ debug("agent unlocked");
|
|
|
674526 |
+ locked = 0;
|
|
|
674526 |
+ fail_count = 0;
|
|
|
674526 |
+ explicit_bzero(lock_passwd, sizeof(lock_passwd));
|
|
|
674526 |
+ success = 1;
|
|
|
674526 |
+ } else {
|
|
|
674526 |
+ /* delay in 0.1s increments up to 10s */
|
|
|
674526 |
+ if (fail_count < 100)
|
|
|
674526 |
+ fail_count++;
|
|
|
674526 |
+ delay = 100000 * fail_count;
|
|
|
674526 |
+ debug("unlock failed, delaying %0.1lf seconds",
|
|
|
674526 |
+ (double)delay/1000000);
|
|
|
674526 |
+ usleep(delay);
|
|
|
674526 |
+ }
|
|
|
674526 |
+ explicit_bzero(passwdhash, sizeof(passwdhash));
|
|
|
674526 |
} else if (!locked && lock) {
|
|
|
674526 |
+ debug("agent locked");
|
|
|
674526 |
locked = 1;
|
|
|
674526 |
- lock_passwd = xstrdup(passwd);
|
|
|
674526 |
+ arc4random_buf(lock_salt, sizeof(lock_salt));
|
|
|
674526 |
+ if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt),
|
|
|
674526 |
+ lock_passwd, sizeof(lock_passwd), LOCK_ROUNDS) < 0)
|
|
|
674526 |
+ fatal("bcrypt_pbkdf");
|
|
|
674526 |
success = 1;
|
|
|
674526 |
}
|
|
|
674526 |
- explicit_bzero(passwd, strlen(passwd));
|
|
|
674526 |
+ explicit_bzero(passwd, pwlen);
|
|
|
674526 |
free(passwd);
|
|
|
674526 |
|
|
|
674526 |
buffer_put_int(&e->output, 1);
|