Re: Remote program doesn't terminate when ssh session ends

2021-02-25 Thread Catalin Patulea
Years ago, I attempted to fix an issue that sounds a lot like this:
https://hg.ucc.asn.au/dropbear/rev/35183e8a7851

I believe the right way this works it that:
- ssh client closes session
- dropbear closes the read end of command's stdout pipe
- next time command writes to pipe, it receives SIGPIPE and dies
Thus I don't think dropbear needs to explicitly kill anything. but perhaps
the mechanism is somehow not working.

I would investigate this by running 'strace' on the remote host and seeing
if, after closing the session, 1) dropbear closes the pipe and 2) the
command tries to write to it and receives SIGPIPE.

On Thu, Feb 25, 2021 at 12:52 PM Grant Edwards 
wrote:

> I have a small ash script that prints memory statistics once a second:
>
> #!/bin/sh
>
> while true
> do
> date
> cat /proc/[0-9]*/stat |
> awk '$23 > 0 {printf "%5d %20s  %8d  %5d\n", $1, $2, $23, $24}' |
> sort -n
> sleep 60
> done
>
> When I run that remotely via dropbea:
>
> $ ssh root@10.0.0.99 ./showmem.sh
>
> Everything works as expected while the ssh session is active, but when
> I end the ssh connection, the shell script never terminates: it
> continues to run (indifinitely, AFAICT). I don't recall this happening
> when we used to use openssh's server. Is there any way to get dropbear
> to terminate a "child" program when the ssh session closes?
>
>
>
>
>


[PATCH] Handle invalid agent keys by skipping rather than exiting.

2015-01-01 Thread Catalin Patulea



dropbear-skip-bad-key.patch
Description: Binary data


Re: TOS byte on port forwarding-only connections

2014-07-13 Thread Catalin Patulea
On Tue, Jul 8, 2014 at 9:44 AM, Matt Johnston m...@ucc.asn.au wrote:
 I'm not really sure how to resolve it though. Maybe as a
 tradeoff the refcounting could just switch between LOWDELAY
 and no-tos-flags if there are TCP forwards going on, then
 BULK if there aren't TCP forwards?
Ok, so if I'm understanding correctly, the invariant would be something like:

if (connecting || ptys) tos = LOWDELAY;
else if (tcp_forwards) tos = 0;
else tos = BULK;

This might be implemented cleverly so that it's only reapplied on 0/1
transitions of ptys and tcp_forwards, but these would be the
high-level semantics?


[PATCH] Set IPTOS_LOWDELAY on PTY sessions only

2013-12-02 Thread Catalin Patulea
Signed-off-by: Catalin Patulea c...@vv.carleton.ca
---
 cli-chansession.c |  1 +
 dbutil.c  | 29 +
 dbutil.h  |  2 ++
 includes.h|  4 
 svr-chansession.c |  2 ++
 5 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/cli-chansession.c b/cli-chansession.c
index 0ee3e85..b99e073 100644
--- a/cli-chansession.c
+++ b/cli-chansession.c
@@ -369,6 +369,7 @@ static int cli_initchansess(struct Channel *channel) {
 
if (cli_opts.wantpty) {
send_chansess_pty_req(channel);
+   set_sock_priority(ses.sock_out);
}
 
send_chansess_shell_req(channel);
diff --git a/dbutil.c b/dbutil.c
index ce88731..4f15027 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -177,28 +177,41 @@ void dropbear_trace2(const char* format, ...) {
 }
 #endif /* DEBUG_TRACE */
 
-static void set_sock_priority(int sock) {
-
+void set_sock_nodelay(int sock) {
int val;
 
/* disable nagle */
val = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)val, sizeof(val));
+}
+
+void set_sock_priority(int sock) {
+
+   int val, rc;
 
/* set the TOS bit for either ipv4 or ipv6 */
 #ifdef IPTOS_LOWDELAY
val = IPTOS_LOWDELAY;
 #if defined(IPPROTO_IPV6)  defined(IPV6_TCLASS)
-   setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, (void*)val, sizeof(val));
+   rc = setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, (void*)val, 
sizeof(val));
+   if (rc  0)
+   dropbear_log(LOG_WARNING, Couldn't set IPV6_TCLASS (%s),
+   strerror(errno));
 #endif
-   setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)val, sizeof(val));
+   rc = setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)val, sizeof(val));
+   if (rc  0)
+   dropbear_log(LOG_WARNING, Couldn't set IP_TOS (%s),
+   strerror(errno));
 #endif
 
 #ifdef SO_PRIORITY
/* linux specific, sets QoS class.
 * 6 looks to be optimal for interactive traffic (see tc-prio(8) ). */
-   val = 6;
-   setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) val, sizeof(val));
+   val = TC_PRIO_INTERACTIVE;
+   rc = setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) val, 
sizeof(val));
+   if (rc  0)
+   dropbear_log(LOG_WARNING, Couldn't set SO_PRIORITY (%s),
+   strerror(errno));
 #endif
 
 }
@@ -290,7 +303,7 @@ int dropbear_listen(const char* address, const char* port,
}
 #endif
 
-   set_sock_priority(sock);
+   set_sock_nodelay(sock);
 
if (bind(sock, res-ai_addr, res-ai_addrlen)  0) {
err = errno;
@@ -429,7 +442,7 @@ int connect_remote(const char* remotehost, const char* 
remoteport,
TRACE((Error connecting: %s, strerror(err)))
} else {
/* Success */
-   set_sock_priority(sock);
+   set_sock_nodelay(sock);
}
 
freeaddrinfo(res0);
diff --git a/dbutil.h b/dbutil.h
index 7c7435c..7665845 100644
--- a/dbutil.h
+++ b/dbutil.h
@@ -66,6 +66,8 @@ void get_socket_address(int fd, char **local_host, char 
**local_port,
char **remote_host, char **remote_port, int host_lookup);
 void getaddrstring(struct sockaddr_storage* addr, 
char **ret_host, char **ret_port, int host_lookup);
+void set_sock_nodelay(int sock);
+void set_sock_priority(int sock);
 int dropbear_listen(const char* address, const char* port,
int *socks, unsigned int sockcount, char **errstring, int 
*maxfd);
 int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
diff --git a/includes.h b/includes.h
index 62a8d73..bae82f5 100644
--- a/includes.h
+++ b/includes.h
@@ -156,6 +156,10 @@ typedef unsigned int u_int32_t;
 typedef u_int32_t uint32_t;
 #endif /* HAVE_UINT32_T */
 
+#ifdef SO_PRIORITY
+#include linux/pkt_sched.h
+#endif
+
 #include fake-rfc2553.h
 
 #ifndef LOG_AUTHPRIV
diff --git a/svr-chansession.c b/svr-chansession.c
index b585a9a..b912eaf 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -580,6 +580,8 @@ static int sessionpty(struct ChanSess * chansess) {
/* Read the terminal modes */
get_termmodes(chansess);
 
+   set_sock_priority(ses.sock_out);
+
TRACE((leave sessionpty))
return DROPBEAR_SUCCESS;
 }
-- 
1.8.4.1



[PATCH] Fix TRACEs of cli_send_netcat_request

2013-11-25 Thread Catalin Patulea
Signed-off-by: Catalin Patulea c...@vv.carleton.ca
---
 cli-chansession.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/cli-chansession.c b/cli-chansession.c
index ed80453..0ee3e85 100644
--- a/cli-chansession.c
+++ b/cli-chansession.c
@@ -398,6 +398,7 @@ void cli_send_netcat_request() {
const unsigned char* source_host = 127.0.0.1;
const int source_port = 22;
 
+   TRACE((enter cli_send_netcat_request))
cli_opts.wantpty = 0;
 
if (send_msg_channel_open_init(STDIN_FILENO, cli_chan_netcat) 
@@ -414,7 +415,7 @@ void cli_send_netcat_request() {
buf_putint(ses.writepayload, source_port);
 
encrypt_packet();
-   TRACE((leave cli_send_chansess_request))
+   TRACE((leave cli_send_netcat_request))
 }
 #endif
 
-- 
1.8.4.1



Re: TOS byte for bulk transfers

2013-11-23 Thread Catalin Patulea
On Sat, Nov 23, 2013 at 4:26 PM, Dave Taht dave.t...@gmail.com wrote:
 While obsolete (don't use it!) , wondershaper was the root of all
 these systems a decade ago, and is a lot easier to study and
 understand than these successors.
Thanks for the pointers. Indeed, I use a simplified variant of
wondershaper at my gateway. TBF at the root to take control of the
queue, PRIO to respect the TOS byte, then FIFO in the low latency band
(I want it to starve anything else - which is exactly what happened),
fq_codel in the rest. In a sense, my gateway worked exactly as
intended - it's just that the application layer was giving it mixed
signals.

I guess the direction I'm trying to go is patching dropbear in some
way to cooperate better with this sort of shaping. In a way, I'm
asking, Matt, what kind of patch would you accept here?

Another idea that occurred to me offline (I swear, I only later
checked what OpenSSH does) would be to key off things like PTY
requests. Most likely those sessions are interactive, while others
that request a subsystem or no PTY are probably bulk.

In fact this is one of the main things OpenSSH does. There's two sides
to the story, so let me start client first:

http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/clientloop.c?rev=1.256
In client_session2_setup():
- packet_set_interactive(want_tty, ...)

http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/ssh.c?rev=1.393
In ssh_session():
- packet_set_interactive(interactive /* = request_pty_succeeded ||
x11_forwarding */,)

In ssh_session2_setup()
- packet_set_interactive(interactive /* = similar logic as ssh_session */)

and now server:

http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/session.c?rev=1.268
In do_exec_no_pty():
- packet_set_interactive(s-display != NULL, ...);
// Haven't verified where s-display comes from, but I get it amounts
to x11 forwarding is enabled.

In do_exec_pty():
- packet_set_interactive(1, ...);

packet_set_interactive just ends up doing setsockopt.

So there is precedent for doing a bit of cleverness at the application
layer to help the network layer.

For myself, just keying off pty requests would have been enough to
trigger the correct whole-system behaviour.

Matt, would you accept a patch that keys the TOS setting off PTY requests?


Re: TOS byte for bulk transfers

2013-11-23 Thread Catalin Patulea
On Sat, Nov 23, 2013 at 9:11 PM, Matt Johnston m...@ucc.asn.au wrote:
 Catalin Patulea c...@vv.carleton.ca wrote:
Matt, would you accept a patch that keys the TOS setting off
 PTY requests?
 Yes, I've been meaning to look at that.
Heads up, client and server TCP port forwards use the same utility
function, connect_remote, so changes in this area will also affect
those connections.

It seems sensible to me that they be downgraded to default TOS (00),
what do you think?


Re: autossh incompatibility with dropbear -y

2013-10-04 Thread Catalin Patulea
You could always write a small wrapper script that adds whatever
command-line arguments you need, and pass *that* to autossh.

#!/bin/sh
exec path/to/dropbear -y $@

On Fri, Oct 4, 2013 at 12:31 PM, Steve Newcomb s...@coolheads.com wrote:
 I'm using OpenWRT.  My router, whose IP address changes unpredictably,
 makes its ssh-listening port available on another host running at a
 stable IP address, using autossh/dropbear to create a reverse channel.

 Sometimes the host's key changes from time to time, which can stop the
 autossh process at a prompt (to nobody) to decide what to do about the
 change.

 Ordinary OpenSSH has a StrictHostKeyChecking option which can be used to
 bypass the so-called ask prompt and just make the connection regardless.

 By reading the source, I learned that Dropbear's ssh client evidently
 has a similar feature, the -y invocation option.  But I can't pass the
 -y to it via autossh because autossh doesn't approve of it.  Dropbear's
 ssh client also does not offer a config file utility, AFAIK.
 Dropbear evidently ignores all -o options, too; they wind up in a bit
 bucket called something like dummy.

 Does anybody know the answer, short of editing/recompiling autossh so it
 won't be so persnickety and just get out of the way?

 Steve Newcomb


Re: implementing e...@openssh.com

2013-08-01 Thread Catalin Patulea
Something else to note about e...@openssh.com is that OpenSSH only
sends this request to peer implementations which are whitelisted
(currently only OpenSSH*). Historicaly, other impls have been buggy
to the point of crashing when they receive e...@openssh.com, so they
set up this whitelist to reduce interop issues.

In fact dropbear is one of the bad impls, because when the client sees
a channel request it doesn't recognize, it always does
send_msg_channel_failure. It should instead look at 'wantreply' and if
it's FALSE, it should drop the request silently. The patch
dropbear-eow.patch fixes this.

But all this to say that vanilla OpenSSH cannot be used to test this
feature because it won't send e...@openssh.com. OpenSSH would need to
be patched to include dropbear in the whitelist for testing.

On Wed, Jul 24, 2013 at 9:21 PM, Catalin Patulea c...@vv.carleton.ca wrote:
 e...@openssh.com is an extension that allows EPIPE to propagate through
 SSH sessions. For example:
 ssh localhost cat /dev/urandom | /bin/true
 will very quickly exit because /bin/true does not consume its stdin.

 The mechanism is:
 - /bin/true calls exit(0), closing the last remaining ref to its stdin pipe
 - ssh tries to write() and gets EPIPE
 - ssh sends e...@openssh.com channel request to server
 - sshd handles e...@openssh.com by closing read side of its pipe
 - 'cat /etc/urandom' itself tries to write(), sees EPIPE and is killed
 by SIGPIPE

 dropbear doesn't implement this, so
 ./dbclient localhost cat /dev/urandom | /bin/true
 runs forever.

 e...@openssh.com is specified here:
 http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=HEAD;content-type=text/plain
 (section 2.1)

 I have a draft implementation of this in dropbear (attached), but
 there is one significant issue:

 In cli-session.c, stdin, stdout and stderr are dup()'ed in order to be
 able to restore file flags at the end of the session. This means that
 if the client gets e...@openssh.com from the server and close(0), this
 is actually not the last outstanding ref to the pipe. There's still an
 fd 4 or so, which means the writer actually doesn't see EPIPE. So a
 case like this is still broken:
 producer | ./dbclient host remote command that closes stdin

 On my ubuntu dev machine I could just comment the dup()/flags hack
 out, which made this work. But I'm not sure whether this is really
 still needed at all.

 What is the history behind this? The comment says:
 /* We store std{in,out,err}'s flags, so we can set them back on exit
  * (otherwise busybox's ash isn't happy */

 but that's not much detail and I'm not sure if it's really still needed.


implementing e...@openssh.com

2013-07-24 Thread Catalin Patulea
e...@openssh.com is an extension that allows EPIPE to propagate through
SSH sessions. For example:
ssh localhost cat /dev/urandom | /bin/true
will very quickly exit because /bin/true does not consume its stdin.

The mechanism is:
- /bin/true calls exit(0), closing the last remaining ref to its stdin pipe
- ssh tries to write() and gets EPIPE
- ssh sends e...@openssh.com channel request to server
- sshd handles e...@openssh.com by closing read side of its pipe
- 'cat /etc/urandom' itself tries to write(), sees EPIPE and is killed
by SIGPIPE

dropbear doesn't implement this, so
./dbclient localhost cat /dev/urandom | /bin/true
runs forever.

e...@openssh.com is specified here:
http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=HEAD;content-type=text/plain
(section 2.1)

I have a draft implementation of this in dropbear (attached), but
there is one significant issue:

In cli-session.c, stdin, stdout and stderr are dup()'ed in order to be
able to restore file flags at the end of the session. This means that
if the client gets e...@openssh.com from the server and close(0), this
is actually not the last outstanding ref to the pipe. There's still an
fd 4 or so, which means the writer actually doesn't see EPIPE. So a
case like this is still broken:
producer | ./dbclient host remote command that closes stdin

On my ubuntu dev machine I could just comment the dup()/flags hack
out, which made this work. But I'm not sure whether this is really
still needed at all.

What is the history behind this? The comment says:
/* We store std{in,out,err}'s flags, so we can set them back on exit
 * (otherwise busybox's ash isn't happy */

but that's not much detail and I'm not sure if it's really still needed.


dropbear-eow.patch
Description: Binary data


Re: dbclient half-close?

2013-07-13 Thread Catalin Patulea
Maybe the check on common-channel.c:338 should be against writefd
instead of readfd? This would get set by
close_chan_fd(channel-writefd) once recv_eof happens.

This patch indeed causes 'foo' to surface after input EOF:

diff -r 69cb561cc4c4 common-channel.c
--- a/common-channel.c Sat Jul 13 11:53:24 2013 +0300
+++ b/common-channel.c Sat Jul 13 12:50:41 2013 +0300
@@ -335,7 +335,7 @@
  }

  /* And if we can't receive any more data from them either, close up */
- if (channel-readfd == FD_CLOSED
+ if (channel-writefd == FD_CLOSED
   (ERRFD_IS_WRITE(channel) || channel-errfd == FD_CLOSED)
   !channel-sent_close
   close_allowed

On Sat, Jul 13, 2013 at 12:31 PM, Catalin Patulea c...@vv.carleton.ca wrote:
 Hi,

 I'm seeing a difference in how dbclient handles EOF on input compared
 to openssh client. openssh client propagates input EOF to the remote
 command, but continues pumping command stdout. dbclient seems to abort
 before flushing the stdout buffer.

 In the following examples, 1.2.3.4 is an openwrt router running
 dropbear server. The remote command is designed to wait for EOF, then
 output something to stdout.

 openssh client:
 $ ssh root@1.2.3.4 'cat; echo foo'
 ^D
 foo

 dbclient:
 $ ./dbclient root@1.2.3.4 'cat; echo foo'
 ^D
 no output

 I build dropbear with DEBUG_TRACE and these are the last few lines:
 TRACE (...): empty queue dequeing
 ^D
 TRACE (...): send normal readfd
 TRACE (...): enter send_msg_channel_data
 TRACE (...): enter send_msg_channel_data isextended 0 fd 0
 TRACE (...): maxlen 16375
 TRACE (...): CLOSE some fd 0
 TRACE (...): leave send_msg_channel_data: len 0 read err 17 or EOF for fd 0
 TRACE (...): enter send_msg_channel_eof
 TRACE (...): leave send_msg_channel_eof
 TRACE (...): sending close, readfd is closed
 TRACE (...): enter send_msg_channel_close 0xcbfdc0
 TRACE (...): enter cli_tty_cleanup
 TRACE (...): leave cli_tty_cleanup: not in raw mode
 TRACE (...): CLOSE some fd -1
 TRACE (...): CLOSE some fd 2

 I tried reading through the relevant sections of channel-common.c but
 I could use some guidance/background. Is this behaviour intentional?

 Catalin