sync code with last improvements from OpenBSD
This commit is contained in:
parent
4ee2459da1
commit
12cd8aa4a2
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: dt_prov_static.c,v 1.21 2023/08/14 08:33:24 mpi Exp $ */
|
/* $OpenBSD: dt_prov_static.c,v 1.22 2023/08/28 14:50:01 bluhm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Martin Pieuchot <mpi@openbsd.org>
|
* Copyright (c) 2019 Martin Pieuchot <mpi@openbsd.org>
|
||||||
@ -100,6 +100,7 @@ DT_STATIC_PROBE3(refcnt, ifaddr, "void *", "int", "int");
|
|||||||
DT_STATIC_PROBE3(refcnt, ifmaddr, "void *", "int", "int");
|
DT_STATIC_PROBE3(refcnt, ifmaddr, "void *", "int", "int");
|
||||||
DT_STATIC_PROBE3(refcnt, inpcb, "void *", "int", "int");
|
DT_STATIC_PROBE3(refcnt, inpcb, "void *", "int", "int");
|
||||||
DT_STATIC_PROBE3(refcnt, rtentry, "void *", "int", "int");
|
DT_STATIC_PROBE3(refcnt, rtentry, "void *", "int", "int");
|
||||||
|
DT_STATIC_PROBE3(refcnt, syncache, "void *", "int", "int");
|
||||||
DT_STATIC_PROBE3(refcnt, tdb, "void *", "int", "int");
|
DT_STATIC_PROBE3(refcnt, tdb, "void *", "int", "int");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -152,6 +153,7 @@ struct dt_probe *const dtps_static[] = {
|
|||||||
&_DT_STATIC_P(refcnt, ifmaddr),
|
&_DT_STATIC_P(refcnt, ifmaddr),
|
||||||
&_DT_STATIC_P(refcnt, inpcb),
|
&_DT_STATIC_P(refcnt, inpcb),
|
||||||
&_DT_STATIC_P(refcnt, rtentry),
|
&_DT_STATIC_P(refcnt, rtentry),
|
||||||
|
&_DT_STATIC_P(refcnt, syncache),
|
||||||
&_DT_STATIC_P(refcnt, tdb),
|
&_DT_STATIC_P(refcnt, tdb),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tcp_input.c,v 1.389 2023/07/06 09:15:23 bluhm Exp $ */
|
/* $OpenBSD: tcp_input.c,v 1.390 2023/08/28 14:50:01 bluhm Exp $ */
|
||||||
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
|
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -192,7 +192,6 @@ void syn_cache_put(struct syn_cache *);
|
|||||||
void syn_cache_rm(struct syn_cache *);
|
void syn_cache_rm(struct syn_cache *);
|
||||||
int syn_cache_respond(struct syn_cache *, struct mbuf *, uint64_t);
|
int syn_cache_respond(struct syn_cache *, struct mbuf *, uint64_t);
|
||||||
void syn_cache_timer(void *);
|
void syn_cache_timer(void *);
|
||||||
void syn_cache_reaper(void *);
|
|
||||||
void syn_cache_insert(struct syn_cache *, struct tcpcb *);
|
void syn_cache_insert(struct syn_cache *, struct tcpcb *);
|
||||||
void syn_cache_reset(struct sockaddr *, struct sockaddr *,
|
void syn_cache_reset(struct sockaddr *, struct sockaddr *,
|
||||||
struct tcphdr *, u_int);
|
struct tcphdr *, u_int);
|
||||||
@ -3091,6 +3090,7 @@ int tcp_syn_cache_limit = TCP_SYN_HASH_SIZE*TCP_SYN_BUCKET_SIZE;
|
|||||||
int tcp_syn_bucket_limit = 3*TCP_SYN_BUCKET_SIZE;
|
int tcp_syn_bucket_limit = 3*TCP_SYN_BUCKET_SIZE;
|
||||||
int tcp_syn_use_limit = 100000;
|
int tcp_syn_use_limit = 100000;
|
||||||
|
|
||||||
|
struct pool syn_cache_pool;
|
||||||
struct syn_cache_set tcp_syn_cache[2];
|
struct syn_cache_set tcp_syn_cache[2];
|
||||||
int tcp_syn_cache_active;
|
int tcp_syn_cache_active;
|
||||||
|
|
||||||
@ -3138,25 +3138,27 @@ syn_cache_rm(struct syn_cache *sc)
|
|||||||
TAILQ_REMOVE(&sc->sc_buckethead->sch_bucket, sc, sc_bucketq);
|
TAILQ_REMOVE(&sc->sc_buckethead->sch_bucket, sc, sc_bucketq);
|
||||||
sc->sc_tp = NULL;
|
sc->sc_tp = NULL;
|
||||||
LIST_REMOVE(sc, sc_tpq);
|
LIST_REMOVE(sc, sc_tpq);
|
||||||
|
refcnt_rele(&sc->sc_refcnt);
|
||||||
sc->sc_buckethead->sch_length--;
|
sc->sc_buckethead->sch_length--;
|
||||||
timeout_del(&sc->sc_timer);
|
if (timeout_del(&sc->sc_timer))
|
||||||
|
refcnt_rele(&sc->sc_refcnt);
|
||||||
sc->sc_set->scs_count--;
|
sc->sc_set->scs_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
syn_cache_put(struct syn_cache *sc)
|
syn_cache_put(struct syn_cache *sc)
|
||||||
{
|
{
|
||||||
|
if (refcnt_rele(&sc->sc_refcnt) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
m_free(sc->sc_ipopts);
|
m_free(sc->sc_ipopts);
|
||||||
if (sc->sc_route4.ro_rt != NULL) {
|
if (sc->sc_route4.ro_rt != NULL) {
|
||||||
rtfree(sc->sc_route4.ro_rt);
|
rtfree(sc->sc_route4.ro_rt);
|
||||||
sc->sc_route4.ro_rt = NULL;
|
sc->sc_route4.ro_rt = NULL;
|
||||||
}
|
}
|
||||||
timeout_set(&sc->sc_timer, syn_cache_reaper, sc);
|
pool_put(&syn_cache_pool, sc);
|
||||||
timeout_add(&sc->sc_timer, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pool syn_cache_pool;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't estimate RTT with SYNs, so each packet starts with the default
|
* We don't estimate RTT with SYNs, so each packet starts with the default
|
||||||
* RTT and each timer step has a fixed timeout value.
|
* RTT and each timer step has a fixed timeout value.
|
||||||
@ -3166,9 +3168,8 @@ do { \
|
|||||||
TCPT_RANGESET((sc)->sc_rxtcur, \
|
TCPT_RANGESET((sc)->sc_rxtcur, \
|
||||||
TCPTV_SRTTDFLT * tcp_backoff[(sc)->sc_rxtshift], TCPTV_MIN, \
|
TCPTV_SRTTDFLT * tcp_backoff[(sc)->sc_rxtshift], TCPTV_MIN, \
|
||||||
TCPTV_REXMTMAX); \
|
TCPTV_REXMTMAX); \
|
||||||
if (!timeout_initialized(&(sc)->sc_timer)) \
|
if (timeout_add_msec(&(sc)->sc_timer, (sc)->sc_rxtcur)) \
|
||||||
timeout_set_proc(&(sc)->sc_timer, syn_cache_timer, (sc)); \
|
refcnt_take(&(sc)->sc_refcnt); \
|
||||||
timeout_add_msec(&(sc)->sc_timer, (sc)->sc_rxtcur); \
|
|
||||||
} while (/*CONSTCOND*/0)
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -3306,6 +3307,7 @@ syn_cache_insert(struct syn_cache *sc, struct tcpcb *tp)
|
|||||||
SYN_CACHE_TIMER_ARM(sc);
|
SYN_CACHE_TIMER_ARM(sc);
|
||||||
|
|
||||||
/* Link it from tcpcb entry */
|
/* Link it from tcpcb entry */
|
||||||
|
refcnt_take(&sc->sc_refcnt);
|
||||||
LIST_INSERT_HEAD(&tp->t_sc, sc, sc_tpq);
|
LIST_INSERT_HEAD(&tp->t_sc, sc, sc_tpq);
|
||||||
|
|
||||||
/* Put it into the bucket. */
|
/* Put it into the bucket. */
|
||||||
@ -3336,10 +3338,11 @@ syn_cache_timer(void *arg)
|
|||||||
{
|
{
|
||||||
struct syn_cache *sc = arg;
|
struct syn_cache *sc = arg;
|
||||||
uint64_t now;
|
uint64_t now;
|
||||||
|
int lastref;
|
||||||
|
|
||||||
NET_LOCK();
|
NET_LOCK();
|
||||||
if (sc->sc_flags & SCF_DEAD)
|
if (sc->sc_flags & SCF_DEAD)
|
||||||
goto out;
|
goto freeit;
|
||||||
|
|
||||||
now = tcp_now();
|
now = tcp_now();
|
||||||
|
|
||||||
@ -3364,26 +3367,28 @@ syn_cache_timer(void *arg)
|
|||||||
sc->sc_rxtshift++;
|
sc->sc_rxtshift++;
|
||||||
SYN_CACHE_TIMER_ARM(sc);
|
SYN_CACHE_TIMER_ARM(sc);
|
||||||
|
|
||||||
out:
|
/*
|
||||||
|
* Decrement reference of this timer. We know there is another timer
|
||||||
|
* as we just added it. So just deref, free is not necessary.
|
||||||
|
*/
|
||||||
|
lastref = refcnt_rele(&sc->sc_refcnt);
|
||||||
|
KASSERT(lastref == 0);
|
||||||
|
(void)lastref;
|
||||||
NET_UNLOCK();
|
NET_UNLOCK();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dropit:
|
dropit:
|
||||||
tcpstat_inc(tcps_sc_timed_out);
|
tcpstat_inc(tcps_sc_timed_out);
|
||||||
syn_cache_rm(sc);
|
syn_cache_rm(sc);
|
||||||
|
/* Decrement reference of the timer and free object after remove. */
|
||||||
|
lastref = refcnt_rele(&sc->sc_refcnt);
|
||||||
|
KASSERT(lastref == 0);
|
||||||
|
(void)lastref;
|
||||||
|
freeit:
|
||||||
syn_cache_put(sc);
|
syn_cache_put(sc);
|
||||||
NET_UNLOCK();
|
NET_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
syn_cache_reaper(void *arg)
|
|
||||||
{
|
|
||||||
struct syn_cache *sc = arg;
|
|
||||||
|
|
||||||
pool_put(&syn_cache_pool, (sc));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove syn cache created by the specified tcb entry,
|
* Remove syn cache created by the specified tcb entry,
|
||||||
* because this does not make sense to keep them
|
* because this does not make sense to keep them
|
||||||
@ -3826,6 +3831,8 @@ syn_cache_add(struct sockaddr *src, struct sockaddr *dst, struct tcphdr *th,
|
|||||||
m_free(ipopts);
|
m_free(ipopts);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
refcnt_init_trace(&sc->sc_refcnt, DT_REFCNT_IDX_SYNCACHE);
|
||||||
|
timeout_set_proc(&sc->sc_timer, syn_cache_timer, sc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill in the cache, and put the necessary IP and TCP
|
* Fill in the cache, and put the necessary IP and TCP
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tcp_var.h,v 1.169 2023/07/06 09:15:24 bluhm Exp $ */
|
/* $OpenBSD: tcp_var.h,v 1.170 2023/08/28 14:50:02 bluhm Exp $ */
|
||||||
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
|
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -236,6 +236,7 @@ union syn_cache_sa {
|
|||||||
|
|
||||||
struct syn_cache {
|
struct syn_cache {
|
||||||
TAILQ_ENTRY(syn_cache) sc_bucketq; /* link on bucket list */
|
TAILQ_ENTRY(syn_cache) sc_bucketq; /* link on bucket list */
|
||||||
|
struct refcnt sc_refcnt; /* ref count list and timer */
|
||||||
struct timeout sc_timer; /* rexmt timer */
|
struct timeout sc_timer; /* rexmt timer */
|
||||||
union { /* cached route */
|
union { /* cached route */
|
||||||
struct route route4;
|
struct route route4;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: refcnt.h,v 1.11 2023/07/06 19:46:53 kn Exp $ */
|
/* $OpenBSD: refcnt.h,v 1.12 2023/08/28 14:50:02 bluhm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 David Gwynne <dlg@openbsd.org>
|
* Copyright (c) 2015 David Gwynne <dlg@openbsd.org>
|
||||||
@ -49,7 +49,8 @@ unsigned int refcnt_read(struct refcnt *);
|
|||||||
#define DT_REFCNT_IDX_IFMADDR 3
|
#define DT_REFCNT_IDX_IFMADDR 3
|
||||||
#define DT_REFCNT_IDX_INPCB 4
|
#define DT_REFCNT_IDX_INPCB 4
|
||||||
#define DT_REFCNT_IDX_RTENTRY 5
|
#define DT_REFCNT_IDX_RTENTRY 5
|
||||||
#define DT_REFCNT_IDX_TDB 6
|
#define DT_REFCNT_IDX_SYNCACHE 6
|
||||||
|
#define DT_REFCNT_IDX_TDB 7
|
||||||
|
|
||||||
#endif /* _KERNEL */
|
#endif /* _KERNEL */
|
||||||
|
|
||||||
|
@ -104,6 +104,39 @@ http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.o
|
|||||||
|
|
||||||
This is identical to curve25519-sha256 as later published in RFC8731.
|
This is identical to curve25519-sha256 as later published in RFC8731.
|
||||||
|
|
||||||
|
1.9 transport: ping facility
|
||||||
|
|
||||||
|
OpenSSH implements a transport level ping message SSH2_MSG_PING
|
||||||
|
and a corresponding SSH2_MSG_PONG reply.
|
||||||
|
|
||||||
|
#define SSH2_MSG_PING 192
|
||||||
|
#define SSH2_MSG_PONG 193
|
||||||
|
|
||||||
|
The ping message is simply:
|
||||||
|
|
||||||
|
byte SSH_MSG_PING
|
||||||
|
string data
|
||||||
|
|
||||||
|
The reply copies the data (which may be the empty string) from the
|
||||||
|
ping:
|
||||||
|
|
||||||
|
byte SSH_MSG_PONG
|
||||||
|
string data
|
||||||
|
|
||||||
|
Replies are sent in order. They are sent immediately except when rekeying
|
||||||
|
is in progress, in which case they are queued until rekeying completes.
|
||||||
|
|
||||||
|
The server advertises support for these messages using the
|
||||||
|
SSH2_MSG_EXT_INFO mechanism (RFC8308), with the following message:
|
||||||
|
|
||||||
|
string "ping@openssh.com"
|
||||||
|
string "0" (version)
|
||||||
|
|
||||||
|
The ping/reply message is implemented at the transport layer rather
|
||||||
|
than as a named global or channel request to allow pings with very
|
||||||
|
short packet lengths, which would not be possible with other
|
||||||
|
approaches.
|
||||||
|
|
||||||
2. Connection protocol changes
|
2. Connection protocol changes
|
||||||
|
|
||||||
2.1. connection: Channel write close extension "eow@openssh.com"
|
2.1. connection: Channel write close extension "eow@openssh.com"
|
||||||
@ -712,4 +745,4 @@ master instance and later clients.
|
|||||||
OpenSSH extends the usual agent protocol. These changes are documented
|
OpenSSH extends the usual agent protocol. These changes are documented
|
||||||
in the PROTOCOL.agent file.
|
in the PROTOCOL.agent file.
|
||||||
|
|
||||||
$OpenBSD: PROTOCOL,v 1.48 2022/11/07 01:53:01 dtucker Exp $
|
$OpenBSD: PROTOCOL,v 1.49 2023/08/28 03:28:43 djm Exp $
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: auth2.c,v 1.166 2023/03/08 04:43:12 guenther Exp $ */
|
/* $OpenBSD: auth2.c,v 1.167 2023/08/28 09:48:11 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -208,6 +208,7 @@ input_service_request(int type, u_int32_t seq, struct ssh *ssh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define MIN_FAIL_DELAY_SECONDS 0.005
|
#define MIN_FAIL_DELAY_SECONDS 0.005
|
||||||
|
#define MAX_FAIL_DELAY_SECONDS 5.0
|
||||||
static double
|
static double
|
||||||
user_specific_delay(const char *user)
|
user_specific_delay(const char *user)
|
||||||
{
|
{
|
||||||
@ -233,6 +234,12 @@ ensure_minimum_time_since(double start, double seconds)
|
|||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
double elapsed = monotime_double() - start, req = seconds, remain;
|
double elapsed = monotime_double() - start, req = seconds, remain;
|
||||||
|
|
||||||
|
if (elapsed > MAX_FAIL_DELAY_SECONDS) {
|
||||||
|
debug3_f("elapsed %0.3lfms exceeded the max delay "
|
||||||
|
"requested %0.3lfms)", elapsed*1000, req*1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* if we've already passed the requested time, scale up */
|
/* if we've already passed the requested time, scale up */
|
||||||
while ((remain = seconds - elapsed) < 0.0)
|
while ((remain = seconds - elapsed) < 0.0)
|
||||||
seconds *= 2;
|
seconds *= 2;
|
||||||
@ -317,7 +324,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
|
|||||||
debug2("input_userauth_request: try method %s", method);
|
debug2("input_userauth_request: try method %s", method);
|
||||||
authenticated = m->userauth(ssh, method);
|
authenticated = m->userauth(ssh, method);
|
||||||
}
|
}
|
||||||
if (!authctxt->authenticated)
|
if (!authctxt->authenticated && strcmp(method, "none") != 0)
|
||||||
ensure_minimum_time_since(tstart,
|
ensure_minimum_time_since(tstart,
|
||||||
user_specific_delay(authctxt->user));
|
user_specific_delay(authctxt->user));
|
||||||
userauth_finish(ssh, authenticated, method, NULL);
|
userauth_finish(ssh, authenticated, method, NULL);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: clientloop.c,v 1.392 2023/04/03 08:10:54 dtucker Exp $ */
|
/* $OpenBSD: clientloop.c,v 1.394 2023/08/28 04:06:52 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -498,6 +498,128 @@ server_alive_check(struct ssh *ssh)
|
|||||||
schedule_server_alive_check();
|
schedule_server_alive_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try to send a dummy keystroke */
|
||||||
|
static int
|
||||||
|
send_chaff(struct ssh *ssh)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if ((ssh->kex->flags & KEX_HAS_PING) == 0)
|
||||||
|
return 0;
|
||||||
|
/* XXX probabilistically send chaff? */
|
||||||
|
/*
|
||||||
|
* a SSH2_MSG_CHANNEL_DATA payload is 9 bytes:
|
||||||
|
* 4 bytes channel ID + 4 bytes string length + 1 byte string data
|
||||||
|
* simulate that here.
|
||||||
|
*/
|
||||||
|
if ((r = sshpkt_start(ssh, SSH2_MSG_PING)) != 0 ||
|
||||||
|
(r = sshpkt_put_cstring(ssh, "PING!")) != 0 ||
|
||||||
|
(r = sshpkt_send(ssh)) != 0)
|
||||||
|
fatal_fr(r, "send packet");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Performs keystroke timing obfuscation. Returns non-zero if the
|
||||||
|
* output fd should be polled.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
obfuscate_keystroke_timing(struct ssh *ssh, struct timespec *timeout)
|
||||||
|
{
|
||||||
|
static int active;
|
||||||
|
static struct timespec next_interval, chaff_until;
|
||||||
|
struct timespec now, tmp;
|
||||||
|
int just_started = 0, had_keystroke = 0;
|
||||||
|
static unsigned long long nchaff;
|
||||||
|
char *stop_reason = NULL;
|
||||||
|
long long n;
|
||||||
|
|
||||||
|
monotime_ts(&now);
|
||||||
|
|
||||||
|
if (options.obscure_keystroke_timing_interval <= 0)
|
||||||
|
return 1; /* disabled in config */
|
||||||
|
|
||||||
|
if (!channel_still_open(ssh) || quit_pending) {
|
||||||
|
/* Stop if no channels left of we're waiting for one to close */
|
||||||
|
stop_reason = "no active channels";
|
||||||
|
} else if (ssh_packet_is_rekeying(ssh)) {
|
||||||
|
/* Stop if we're rekeying */
|
||||||
|
stop_reason = "rekeying started";
|
||||||
|
} else if (!ssh_packet_interactive_data_to_write(ssh) &&
|
||||||
|
ssh_packet_have_data_to_write(ssh)) {
|
||||||
|
/* Stop if the output buffer has more than a few keystrokes */
|
||||||
|
stop_reason = "output buffer filling";
|
||||||
|
} else if (active && ssh_packet_have_data_to_write(ssh)) {
|
||||||
|
/* Still in active mode and have a keystroke queued. */
|
||||||
|
had_keystroke = 1;
|
||||||
|
} else if (active) {
|
||||||
|
if (timespeccmp(&now, &chaff_until, >=)) {
|
||||||
|
/* Stop if there have been no keystrokes for a while */
|
||||||
|
stop_reason = "chaff time expired";
|
||||||
|
} else if (timespeccmp(&now, &next_interval, >=)) {
|
||||||
|
/* Otherwise if we were due to send, then send chaff */
|
||||||
|
if (send_chaff(ssh))
|
||||||
|
nchaff++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stop_reason != NULL) {
|
||||||
|
active = 0;
|
||||||
|
debug3_f("stopping: %s (%llu chaff packets sent)",
|
||||||
|
stop_reason, nchaff);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're in interactive mode, and only have a small amount
|
||||||
|
* of outbound data, then we assume that the user is typing
|
||||||
|
* interactively. In this case, start quantising outbound packets to
|
||||||
|
* fixed time intervals to hide inter-keystroke timing.
|
||||||
|
*/
|
||||||
|
if (!active && ssh_packet_interactive_data_to_write(ssh)) {
|
||||||
|
debug3_f("starting: interval %d",
|
||||||
|
options.obscure_keystroke_timing_interval);
|
||||||
|
just_started = had_keystroke = active = 1;
|
||||||
|
nchaff = 0;
|
||||||
|
ms_to_timespec(&tmp, options.obscure_keystroke_timing_interval);
|
||||||
|
timespecadd(&now, &tmp, &next_interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't hold off if obfuscation inactive */
|
||||||
|
if (!active)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (had_keystroke) {
|
||||||
|
/*
|
||||||
|
* Arrange to send chaff packets for a random interval after
|
||||||
|
* the last keystroke was sent.
|
||||||
|
*/
|
||||||
|
ms_to_timespec(&tmp, SSH_KEYSTROKE_CHAFF_MIN_MS +
|
||||||
|
arc4random_uniform(SSH_KEYSTROKE_CHAFF_RNG_MS));
|
||||||
|
timespecadd(&now, &tmp, &chaff_until);
|
||||||
|
}
|
||||||
|
|
||||||
|
ptimeout_deadline_monotime_tsp(timeout, &next_interval);
|
||||||
|
|
||||||
|
if (just_started)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Don't arm output fd for poll until the timing interval has elapsed */
|
||||||
|
if (timespeccmp(&now, &next_interval, <))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Calculate number of intervals missed since the last check */
|
||||||
|
n = (now.tv_sec - next_interval.tv_sec) * 1000LL * 1000 * 1000;
|
||||||
|
n += now.tv_nsec - next_interval.tv_nsec;
|
||||||
|
n /= options.obscure_keystroke_timing_interval * 1000LL * 1000;
|
||||||
|
n = (n < 0) ? 1 : n + 1;
|
||||||
|
|
||||||
|
/* Advance to the next interval */
|
||||||
|
ms_to_timespec(&tmp, options.obscure_keystroke_timing_interval * n);
|
||||||
|
timespecadd(&now, &tmp, &next_interval);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Waits until the client can do something (some data becomes available on
|
* Waits until the client can do something (some data becomes available on
|
||||||
* one of the file descriptors).
|
* one of the file descriptors).
|
||||||
@ -508,7 +630,7 @@ client_wait_until_can_do_something(struct ssh *ssh, struct pollfd **pfdp,
|
|||||||
int *conn_in_readyp, int *conn_out_readyp)
|
int *conn_in_readyp, int *conn_out_readyp)
|
||||||
{
|
{
|
||||||
struct timespec timeout;
|
struct timespec timeout;
|
||||||
int ret;
|
int ret, oready;
|
||||||
u_int p;
|
u_int p;
|
||||||
|
|
||||||
*conn_in_readyp = *conn_out_readyp = 0;
|
*conn_in_readyp = *conn_out_readyp = 0;
|
||||||
@ -528,11 +650,14 @@ client_wait_until_can_do_something(struct ssh *ssh, struct pollfd **pfdp,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oready = obfuscate_keystroke_timing(ssh, &timeout);
|
||||||
|
|
||||||
/* Monitor server connection on reserved pollfd entries */
|
/* Monitor server connection on reserved pollfd entries */
|
||||||
(*pfdp)[0].fd = connection_in;
|
(*pfdp)[0].fd = connection_in;
|
||||||
(*pfdp)[0].events = POLLIN;
|
(*pfdp)[0].events = POLLIN;
|
||||||
(*pfdp)[1].fd = connection_out;
|
(*pfdp)[1].fd = connection_out;
|
||||||
(*pfdp)[1].events = ssh_packet_have_data_to_write(ssh) ? POLLOUT : 0;
|
(*pfdp)[1].events = (oready && ssh_packet_have_data_to_write(ssh)) ?
|
||||||
|
POLLOUT : 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for something to happen. This will suspend the process until
|
* Wait for something to happen. This will suspend the process until
|
||||||
@ -549,7 +674,7 @@ client_wait_until_can_do_something(struct ssh *ssh, struct pollfd **pfdp,
|
|||||||
ssh_packet_get_rekey_timeout(ssh));
|
ssh_packet_get_rekey_timeout(ssh));
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = poll(*pfdp, *npfd_activep, ptimeout_get_ms(&timeout));
|
ret = ppoll(*pfdp, *npfd_activep, ptimeout_get_tsp(&timeout), NULL);
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
/*
|
/*
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: kex.c,v 1.180 2023/08/21 21:16:18 tobhe Exp $ */
|
/* $OpenBSD: kex.c,v 1.181 2023/08/28 03:28:43 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -477,12 +477,14 @@ kex_send_ext_info(struct ssh *ssh)
|
|||||||
return SSH_ERR_ALLOC_FAIL;
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
/* XXX filter algs list by allowed pubkey/hostbased types */
|
/* XXX filter algs list by allowed pubkey/hostbased types */
|
||||||
if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
|
if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
|
||||||
(r = sshpkt_put_u32(ssh, 2)) != 0 ||
|
(r = sshpkt_put_u32(ssh, 3)) != 0 ||
|
||||||
(r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
|
(r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
|
||||||
(r = sshpkt_put_cstring(ssh, algs)) != 0 ||
|
(r = sshpkt_put_cstring(ssh, algs)) != 0 ||
|
||||||
(r = sshpkt_put_cstring(ssh,
|
(r = sshpkt_put_cstring(ssh,
|
||||||
"publickey-hostbound@openssh.com")) != 0 ||
|
"publickey-hostbound@openssh.com")) != 0 ||
|
||||||
(r = sshpkt_put_cstring(ssh, "0")) != 0 ||
|
(r = sshpkt_put_cstring(ssh, "0")) != 0 ||
|
||||||
|
(r = sshpkt_put_cstring(ssh, "ping@openssh.com")) != 0 ||
|
||||||
|
(r = sshpkt_put_cstring(ssh, "0")) != 0 ||
|
||||||
(r = sshpkt_send(ssh)) != 0) {
|
(r = sshpkt_send(ssh)) != 0) {
|
||||||
error_fr(r, "compose");
|
error_fr(r, "compose");
|
||||||
goto out;
|
goto out;
|
||||||
@ -512,6 +514,23 @@ kex_send_newkeys(struct ssh *ssh)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check whether an ext_info value contains the expected version string */
|
||||||
|
static int
|
||||||
|
kex_ext_info_check_ver(struct kex *kex, const char *name,
|
||||||
|
const u_char *val, size_t len, const char *want_ver, u_int flag)
|
||||||
|
{
|
||||||
|
if (memchr(val, '\0', len) != NULL) {
|
||||||
|
error("SSH2_MSG_EXT_INFO: %s value contains nul byte", name);
|
||||||
|
return SSH_ERR_INVALID_FORMAT;
|
||||||
|
}
|
||||||
|
debug_f("%s=<%s>", name, val);
|
||||||
|
if (strcmp(val, want_ver) == 0)
|
||||||
|
kex->flags |= flag;
|
||||||
|
else
|
||||||
|
debug_f("unsupported version of %s extension", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
|
kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
|
||||||
{
|
{
|
||||||
@ -542,6 +561,8 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
|
|||||||
/* Ensure no \0 lurking in value */
|
/* Ensure no \0 lurking in value */
|
||||||
if (memchr(val, '\0', vlen) != NULL) {
|
if (memchr(val, '\0', vlen) != NULL) {
|
||||||
error_f("nul byte in %s", name);
|
error_f("nul byte in %s", name);
|
||||||
|
free(name);
|
||||||
|
free(val);
|
||||||
return SSH_ERR_INVALID_FORMAT;
|
return SSH_ERR_INVALID_FORMAT;
|
||||||
}
|
}
|
||||||
debug_f("%s=<%s>", name, val);
|
debug_f("%s=<%s>", name, val);
|
||||||
@ -549,18 +570,18 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
|
|||||||
val = NULL;
|
val = NULL;
|
||||||
} else if (strcmp(name,
|
} else if (strcmp(name,
|
||||||
"publickey-hostbound@openssh.com") == 0) {
|
"publickey-hostbound@openssh.com") == 0) {
|
||||||
/* XXX refactor */
|
if ((r = kex_ext_info_check_ver(kex, name, val, vlen,
|
||||||
/* Ensure no \0 lurking in value */
|
"0", KEX_HAS_PUBKEY_HOSTBOUND)) != 0) {
|
||||||
if (memchr(val, '\0', vlen) != NULL) {
|
free(name);
|
||||||
error_f("nul byte in %s", name);
|
free(val);
|
||||||
return SSH_ERR_INVALID_FORMAT;
|
return r;
|
||||||
}
|
}
|
||||||
debug_f("%s=<%s>", name, val);
|
} else if (strcmp(name, "ping@openssh.com") == 0) {
|
||||||
if (strcmp(val, "0") == 0)
|
if ((r = kex_ext_info_check_ver(kex, name, val, vlen,
|
||||||
kex->flags |= KEX_HAS_PUBKEY_HOSTBOUND;
|
"0", KEX_HAS_PING)) != 0) {
|
||||||
else {
|
free(name);
|
||||||
debug_f("unsupported version of %s extension",
|
free(val);
|
||||||
name);
|
return r;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
debug_f("%s (unrecognised)", name);
|
debug_f("%s (unrecognised)", name);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: kex.h,v 1.118 2023/03/06 12:14:48 dtucker Exp $ */
|
/* $OpenBSD: kex.h,v 1.119 2023/08/28 03:28:43 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
@ -104,6 +104,7 @@ enum kex_exchange {
|
|||||||
#define KEX_HAS_PUBKEY_HOSTBOUND 0x0004
|
#define KEX_HAS_PUBKEY_HOSTBOUND 0x0004
|
||||||
#define KEX_RSA_SHA2_256_SUPPORTED 0x0008 /* only set in server for now */
|
#define KEX_RSA_SHA2_256_SUPPORTED 0x0008 /* only set in server for now */
|
||||||
#define KEX_RSA_SHA2_512_SUPPORTED 0x0010 /* only set in server for now */
|
#define KEX_RSA_SHA2_512_SUPPORTED 0x0010 /* only set in server for now */
|
||||||
|
#define KEX_HAS_PING 0x0020
|
||||||
|
|
||||||
struct sshenc {
|
struct sshenc {
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: misc.c,v 1.186 2023/08/18 01:37:41 djm Exp $ */
|
/* $OpenBSD: misc.c,v 1.187 2023/08/28 03:31:16 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2005-2020 Damien Miller. All rights reserved.
|
* Copyright (c) 2005-2020 Damien Miller. All rights reserved.
|
||||||
@ -2792,22 +2792,33 @@ ptimeout_deadline_ms(struct timespec *pt, long ms)
|
|||||||
ptimeout_deadline_tsp(pt, &p);
|
ptimeout_deadline_tsp(pt, &p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Specify a poll/ppoll deadline at wall clock monotime 'when' (timespec) */
|
||||||
|
void
|
||||||
|
ptimeout_deadline_monotime_tsp(struct timespec *pt, struct timespec *when)
|
||||||
|
{
|
||||||
|
struct timespec now, t;
|
||||||
|
|
||||||
|
monotime_ts(&now);
|
||||||
|
|
||||||
|
if (timespeccmp(&now, when, >=)) {
|
||||||
|
/* 'when' is now or in the past. Timeout ASAP */
|
||||||
|
pt->tv_sec = 0;
|
||||||
|
pt->tv_nsec = 0;
|
||||||
|
} else {
|
||||||
|
timespecsub(when, &now, &t);
|
||||||
|
ptimeout_deadline_tsp(pt, &t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Specify a poll/ppoll deadline at wall clock monotime 'when' */
|
/* Specify a poll/ppoll deadline at wall clock monotime 'when' */
|
||||||
void
|
void
|
||||||
ptimeout_deadline_monotime(struct timespec *pt, time_t when)
|
ptimeout_deadline_monotime(struct timespec *pt, time_t when)
|
||||||
{
|
{
|
||||||
struct timespec now, t;
|
struct timespec t;
|
||||||
|
|
||||||
t.tv_sec = when;
|
t.tv_sec = when;
|
||||||
t.tv_nsec = 0;
|
t.tv_nsec = 0;
|
||||||
monotime_ts(&now);
|
ptimeout_deadline_monotime_tsp(pt, &t);
|
||||||
|
|
||||||
if (timespeccmp(&now, &t, >=))
|
|
||||||
ptimeout_deadline_sec(pt, 0);
|
|
||||||
else {
|
|
||||||
timespecsub(&t, &now, &t);
|
|
||||||
ptimeout_deadline_tsp(pt, &t);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a poll(2) timeout value in milliseconds */
|
/* Get a poll(2) timeout value in milliseconds */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: misc.h,v 1.104 2023/08/18 01:37:41 djm Exp $ */
|
/* $OpenBSD: misc.h,v 1.105 2023/08/28 03:31:16 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -212,6 +212,7 @@ struct timespec;
|
|||||||
void ptimeout_init(struct timespec *pt);
|
void ptimeout_init(struct timespec *pt);
|
||||||
void ptimeout_deadline_sec(struct timespec *pt, long sec);
|
void ptimeout_deadline_sec(struct timespec *pt, long sec);
|
||||||
void ptimeout_deadline_ms(struct timespec *pt, long ms);
|
void ptimeout_deadline_ms(struct timespec *pt, long ms);
|
||||||
|
void ptimeout_deadline_monotime_tsp(struct timespec *pt, struct timespec *when);
|
||||||
void ptimeout_deadline_monotime(struct timespec *pt, time_t when);
|
void ptimeout_deadline_monotime(struct timespec *pt, time_t when);
|
||||||
int ptimeout_get_ms(struct timespec *pt);
|
int ptimeout_get_ms(struct timespec *pt);
|
||||||
struct timespec *ptimeout_get_tsp(struct timespec *pt);
|
struct timespec *ptimeout_get_tsp(struct timespec *pt);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: packet.c,v 1.310 2023/04/06 03:21:31 djm Exp $ */
|
/* $OpenBSD: packet.c,v 1.312 2023/08/28 03:31:16 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -1034,6 +1034,8 @@ int
|
|||||||
ssh_packet_log_type(u_char type)
|
ssh_packet_log_type(u_char type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case SSH2_MSG_PING:
|
||||||
|
case SSH2_MSG_PONG:
|
||||||
case SSH2_MSG_CHANNEL_DATA:
|
case SSH2_MSG_CHANNEL_DATA:
|
||||||
case SSH2_MSG_CHANNEL_EXTENDED_DATA:
|
case SSH2_MSG_CHANNEL_EXTENDED_DATA:
|
||||||
case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
|
case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
|
||||||
@ -1654,7 +1656,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
|||||||
goto out;
|
goto out;
|
||||||
if (ssh_packet_log_type(*typep))
|
if (ssh_packet_log_type(*typep))
|
||||||
debug3("receive packet: type %u", *typep);
|
debug3("receive packet: type %u", *typep);
|
||||||
if (*typep < SSH2_MSG_MIN || *typep >= SSH2_MSG_LOCAL_MIN) {
|
if (*typep < SSH2_MSG_MIN) {
|
||||||
if ((r = sshpkt_disconnect(ssh,
|
if ((r = sshpkt_disconnect(ssh,
|
||||||
"Invalid ssh2 packet type: %d", *typep)) != 0 ||
|
"Invalid ssh2 packet type: %d", *typep)) != 0 ||
|
||||||
(r = ssh_packet_write_wait(ssh)) != 0)
|
(r = ssh_packet_write_wait(ssh)) != 0)
|
||||||
@ -1689,6 +1691,8 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
|||||||
u_int reason, seqnr;
|
u_int reason, seqnr;
|
||||||
int r;
|
int r;
|
||||||
u_char *msg;
|
u_char *msg;
|
||||||
|
const u_char *d;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
msg = NULL;
|
msg = NULL;
|
||||||
@ -1732,6 +1736,21 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
|||||||
debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
|
debug("Received SSH2_MSG_UNIMPLEMENTED for %u",
|
||||||
seqnr);
|
seqnr);
|
||||||
break;
|
break;
|
||||||
|
case SSH2_MSG_PING:
|
||||||
|
if ((r = sshpkt_get_string_direct(ssh, &d, &len)) != 0)
|
||||||
|
return r;
|
||||||
|
DBG(debug("Received SSH2_MSG_PING len %zu", len));
|
||||||
|
if ((r = sshpkt_start(ssh, SSH2_MSG_PONG)) != 0 ||
|
||||||
|
(r = sshpkt_put_string(ssh, d, len)) != 0 ||
|
||||||
|
(r = sshpkt_send(ssh)) != 0)
|
||||||
|
return r;
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_PONG:
|
||||||
|
if ((r = sshpkt_get_string_direct(ssh,
|
||||||
|
NULL, &len)) != 0)
|
||||||
|
return r;
|
||||||
|
DBG(debug("Received SSH2_MSG_PONG len %zu", len));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2041,6 +2060,18 @@ ssh_packet_not_very_much_data_to_write(struct ssh *ssh)
|
|||||||
return sshbuf_len(ssh->state->output) < 128 * 1024;
|
return sshbuf_len(ssh->state->output) < 128 * 1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns true when there are at most a few keystrokes of data to write
|
||||||
|
* and the connection is in interactive mode.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
ssh_packet_interactive_data_to_write(struct ssh *ssh)
|
||||||
|
{
|
||||||
|
return ssh->state->interactive_mode &&
|
||||||
|
sshbuf_len(ssh->state->output) < 256;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ssh_packet_set_tos(struct ssh *ssh, int tos)
|
ssh_packet_set_tos(struct ssh *ssh, int tos)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: packet.h,v 1.94 2022/01/22 00:49:34 djm Exp $ */
|
/* $OpenBSD: packet.h,v 1.95 2023/08/28 03:31:16 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -139,6 +139,7 @@ int ssh_packet_write_poll(struct ssh *);
|
|||||||
int ssh_packet_write_wait(struct ssh *);
|
int ssh_packet_write_wait(struct ssh *);
|
||||||
int ssh_packet_have_data_to_write(struct ssh *);
|
int ssh_packet_have_data_to_write(struct ssh *);
|
||||||
int ssh_packet_not_very_much_data_to_write(struct ssh *);
|
int ssh_packet_not_very_much_data_to_write(struct ssh *);
|
||||||
|
int ssh_packet_interactive_data_to_write(struct ssh *);
|
||||||
|
|
||||||
int ssh_packet_connection_is_on_socket(struct ssh *);
|
int ssh_packet_connection_is_on_socket(struct ssh *);
|
||||||
int ssh_packet_remaining(struct ssh *);
|
int ssh_packet_remaining(struct ssh *);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: readconf.c,v 1.380 2023/07/17 06:16:33 djm Exp $ */
|
/* $OpenBSD: readconf.c,v 1.381 2023/08/28 03:31:16 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -162,7 +162,7 @@ typedef enum {
|
|||||||
oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
|
oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
|
||||||
oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
|
oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
|
||||||
oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
|
oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
|
||||||
oEnableEscapeCommandline,
|
oEnableEscapeCommandline, oObscureKeystrokeTiming,
|
||||||
oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
|
oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
|
||||||
} OpCodes;
|
} OpCodes;
|
||||||
|
|
||||||
@ -311,6 +311,7 @@ static struct {
|
|||||||
{ "knownhostscommand", oKnownHostsCommand },
|
{ "knownhostscommand", oKnownHostsCommand },
|
||||||
{ "requiredrsasize", oRequiredRSASize },
|
{ "requiredrsasize", oRequiredRSASize },
|
||||||
{ "enableescapecommandline", oEnableEscapeCommandline },
|
{ "enableescapecommandline", oEnableEscapeCommandline },
|
||||||
|
{ "obscurekeystroketiming", oObscureKeystrokeTiming },
|
||||||
|
|
||||||
{ NULL, oBadOption }
|
{ NULL, oBadOption }
|
||||||
};
|
};
|
||||||
@ -2257,6 +2258,48 @@ parse_pubkey_algos:
|
|||||||
intptr = &options->required_rsa_size;
|
intptr = &options->required_rsa_size;
|
||||||
goto parse_int;
|
goto parse_int;
|
||||||
|
|
||||||
|
case oObscureKeystrokeTiming:
|
||||||
|
value = -1;
|
||||||
|
while ((arg = argv_next(&ac, &av)) != NULL) {
|
||||||
|
if (value != -1) {
|
||||||
|
error("%s line %d: invalid arguments",
|
||||||
|
filename, linenum);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (strcmp(arg, "yes") == 0 ||
|
||||||
|
strcmp(arg, "true") == 0)
|
||||||
|
value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
|
||||||
|
else if (strcmp(arg, "no") == 0 ||
|
||||||
|
strcmp(arg, "false") == 0)
|
||||||
|
value = 0;
|
||||||
|
else if (strncmp(arg, "interval:", 9) == 0) {
|
||||||
|
if ((errstr = atoi_err(arg + 9,
|
||||||
|
&value)) != NULL) {
|
||||||
|
error("%s line %d: integer value %s.",
|
||||||
|
filename, linenum, errstr);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (value <= 0 || value > 1000) {
|
||||||
|
error("%s line %d: value out of range.",
|
||||||
|
filename, linenum);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error("%s line %d: unsupported argument \"%s\"",
|
||||||
|
filename, linenum, arg);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value == -1) {
|
||||||
|
error("%s line %d: missing argument",
|
||||||
|
filename, linenum);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
intptr = &options->obscure_keystroke_timing_interval;
|
||||||
|
if (*activep && *intptr == -1)
|
||||||
|
*intptr = value;
|
||||||
|
break;
|
||||||
|
|
||||||
case oDeprecated:
|
case oDeprecated:
|
||||||
debug("%s line %d: Deprecated option \"%s\"",
|
debug("%s line %d: Deprecated option \"%s\"",
|
||||||
filename, linenum, keyword);
|
filename, linenum, keyword);
|
||||||
@ -2507,6 +2550,7 @@ initialize_options(Options * options)
|
|||||||
options->known_hosts_command = NULL;
|
options->known_hosts_command = NULL;
|
||||||
options->required_rsa_size = -1;
|
options->required_rsa_size = -1;
|
||||||
options->enable_escape_commandline = -1;
|
options->enable_escape_commandline = -1;
|
||||||
|
options->obscure_keystroke_timing_interval = -1;
|
||||||
options->tag = NULL;
|
options->tag = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2701,6 +2745,10 @@ fill_default_options(Options * options)
|
|||||||
options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
|
options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
|
||||||
if (options->enable_escape_commandline == -1)
|
if (options->enable_escape_commandline == -1)
|
||||||
options->enable_escape_commandline = 0;
|
options->enable_escape_commandline = 0;
|
||||||
|
if (options->obscure_keystroke_timing_interval == -1) {
|
||||||
|
options->obscure_keystroke_timing_interval =
|
||||||
|
SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
|
||||||
|
}
|
||||||
|
|
||||||
/* Expand KEX name lists */
|
/* Expand KEX name lists */
|
||||||
all_cipher = cipher_alg_list(',', 0);
|
all_cipher = cipher_alg_list(',', 0);
|
||||||
@ -3243,6 +3291,16 @@ lookup_opcode_name(OpCodes code)
|
|||||||
static void
|
static void
|
||||||
dump_cfg_int(OpCodes code, int val)
|
dump_cfg_int(OpCodes code, int val)
|
||||||
{
|
{
|
||||||
|
if (code == oObscureKeystrokeTiming) {
|
||||||
|
if (val == 0) {
|
||||||
|
printf("%s no\n", lookup_opcode_name(code));
|
||||||
|
return;
|
||||||
|
} else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) {
|
||||||
|
printf("%s yes\n", lookup_opcode_name(code));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
}
|
||||||
printf("%s %d\n", lookup_opcode_name(code), val);
|
printf("%s %d\n", lookup_opcode_name(code), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3393,6 +3451,8 @@ dump_client_config(Options *o, const char *host)
|
|||||||
dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
|
dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
|
||||||
dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
|
dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
|
||||||
dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
|
dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
|
||||||
|
dump_cfg_int(oObscureKeystrokeTiming,
|
||||||
|
o->obscure_keystroke_timing_interval);
|
||||||
|
|
||||||
/* String options */
|
/* String options */
|
||||||
dump_cfg_string(oBindAddress, o->bind_address);
|
dump_cfg_string(oBindAddress, o->bind_address);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: readconf.h,v 1.151 2023/07/17 04:08:31 djm Exp $ */
|
/* $OpenBSD: readconf.h,v 1.152 2023/08/28 03:31:16 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -180,6 +180,7 @@ typedef struct {
|
|||||||
|
|
||||||
int required_rsa_size; /* minimum size of RSA keys */
|
int required_rsa_size; /* minimum size of RSA keys */
|
||||||
int enable_escape_commandline; /* ~C commandline */
|
int enable_escape_commandline; /* ~C commandline */
|
||||||
|
int obscure_keystroke_timing_interval;
|
||||||
|
|
||||||
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
|
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
|
||||||
} Options;
|
} Options;
|
||||||
@ -222,6 +223,11 @@ typedef struct {
|
|||||||
#define SSH_STRICT_HOSTKEY_YES 2
|
#define SSH_STRICT_HOSTKEY_YES 2
|
||||||
#define SSH_STRICT_HOSTKEY_ASK 3
|
#define SSH_STRICT_HOSTKEY_ASK 3
|
||||||
|
|
||||||
|
/* ObscureKeystrokes parameters */
|
||||||
|
#define SSH_KEYSTROKE_DEFAULT_INTERVAL_MS 20
|
||||||
|
#define SSH_KEYSTROKE_CHAFF_MIN_MS 1024
|
||||||
|
#define SSH_KEYSTROKE_CHAFF_RNG_MS 2048
|
||||||
|
|
||||||
const char *kex_default_pk_alg(void);
|
const char *kex_default_pk_alg(void);
|
||||||
char *ssh_connection_hash(const char *thishost, const char *host,
|
char *ssh_connection_hash(const char *thishost, const char *host,
|
||||||
const char *portstr, const char *user);
|
const char *portstr, const char *user);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh2.h,v 1.20 2023/08/14 03:37:00 djm Exp $ */
|
/* $OpenBSD: ssh2.h,v 1.21 2023/08/28 03:28:43 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
@ -108,6 +108,10 @@
|
|||||||
#define SSH2_MSG_KEX_ECDH_INIT 30
|
#define SSH2_MSG_KEX_ECDH_INIT 30
|
||||||
#define SSH2_MSG_KEX_ECDH_REPLY 31
|
#define SSH2_MSG_KEX_ECDH_REPLY 31
|
||||||
|
|
||||||
|
/* transport layer: OpenSSH extensions */
|
||||||
|
#define SSH2_MSG_PING 192
|
||||||
|
#define SSH2_MSG_PONG 193
|
||||||
|
|
||||||
/* user authentication: generic */
|
/* user authentication: generic */
|
||||||
|
|
||||||
#define SSH2_MSG_USERAUTH_REQUEST 50
|
#define SSH2_MSG_USERAUTH_REQUEST 50
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh_config.5,v 1.383 2023/07/17 05:36:14 jsg Exp $
|
.\" $OpenBSD: ssh_config.5,v 1.386 2023/08/28 09:52:09 djm Exp $
|
||||||
.Dd $Mdocdate: July 17 2023 $
|
.Dd $Mdocdate: August 28 2023 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -1359,6 +1359,25 @@ or
|
|||||||
Specifies the number of password prompts before giving up.
|
Specifies the number of password prompts before giving up.
|
||||||
The argument to this keyword must be an integer.
|
The argument to this keyword must be an integer.
|
||||||
The default is 3.
|
The default is 3.
|
||||||
|
.It Cm ObscureKeystrokeTiming
|
||||||
|
Specifies whether
|
||||||
|
.Xr ssh 1
|
||||||
|
should try to obscure inter-keystroke timings from passive observers of
|
||||||
|
network traffic.
|
||||||
|
If enabled, then for interactive sessions,
|
||||||
|
.Xr ssh 1
|
||||||
|
will send keystrokes at fixed intervals of a few tens of milliseconds
|
||||||
|
and will send fake keystroke packets for some time after typing ceases.
|
||||||
|
The argument to this keyword must be
|
||||||
|
.Cm yes ,
|
||||||
|
.Cm no
|
||||||
|
or an interval specifier of the form
|
||||||
|
.Cm interval:milliseconds
|
||||||
|
(e.g.\&
|
||||||
|
.Cm interval:80
|
||||||
|
for 80 milliseconds).
|
||||||
|
The default is to obscure keystrokes using a 20ms packet interval.
|
||||||
|
Note that smaller intervals will result in higher fake keystroke packet rates.
|
||||||
.It Cm PasswordAuthentication
|
.It Cm PasswordAuthentication
|
||||||
Specifies whether to use password authentication.
|
Specifies whether to use password authentication.
|
||||||
The argument to this keyword must be
|
The argument to this keyword must be
|
||||||
|
Loading…
Reference in New Issue
Block a user