diff --git a/common.c b/common.c index ab67cd7..2214d7e 100644 --- a/common.c +++ b/common.c @@ -166,7 +166,7 @@ int defer_write(struct queue *q, void* data, int data_size) if (verbose) fprintf(stderr, "**** writing deferred on fd %d\n", q->fd); - p = realloc(q->deferred_data, q->deferred_data_size + data_size); + p = realloc(q->begin_deferred_data, q->deferred_data_size + data_size); if (!p) { perror("realloc"); exit(1); diff --git a/probe.c b/probe.c index 69f51a2..79659e9 100644 --- a/probe.c +++ b/probe.c @@ -234,9 +234,9 @@ static int regex_probe(const char *p, int len, struct proto *proto) /* * Read the beginning of data coming from the client connection and check if - * it's a known protocol. Then leave the data on the deferred - * write buffer of the connection and returns a pointer to the protocol - * structure + * it's a known protocol. + * Return PROBE_AGAIN if not enough data, or PROBE_MATCH if it succeeded in + * which case cnx->proto is set to the appropriate protocol. */ int probe_client_protocol(struct connection *cnx) { @@ -260,7 +260,7 @@ int probe_client_protocol(struct connection *cnx) if (verbose) fprintf(stderr, "probing for %s\n", p->description); cnx->proto = p; - res = p->probe(cnx->q[1].deferred_data, cnx->q[1].deferred_data_size, p); + res = p->probe(cnx->q[1].begin_deferred_data, cnx->q[1].deferred_data_size, p); } if (res != PROBE_NEXT) return res; diff --git a/probe.h b/probe.h index eaf3fec..d79b795 100644 --- a/probe.h +++ b/probe.h @@ -6,9 +6,9 @@ #include "common.h" typedef enum { - PROBE_NEXT, - PROBE_MATCH, - PROBE_AGAIN, + PROBE_NEXT, /* Enough data, probe failed -- it's some other protocol */ + PROBE_MATCH, /* Enough data, probe successful -- it's the current protocol */ + PROBE_AGAIN, /* Not enough data for this probe, try again with more data */ } probe_result; struct proto; diff --git a/t b/t index 7bef47d..1aecbbf 100755 --- a/t +++ b/t @@ -18,6 +18,7 @@ my $pidfile = "/tmp/sslh_test.pid"; my $SSL_CNX = 1; my $SSH_SHY_CNX = 1; my $SSH_BOLD_CNX = 1; +my $SSH_PROBE_AGAIN = 1; my $SSL_MIX_SSH = 1; my $SSH_MIX_SSL = 1; my $BIG_MSG = 0; # This test is unreliable @@ -62,7 +63,7 @@ for my $binary (@binaries) { exit 0; } warn "spawned $sslh_pid\n"; - sleep 1; # valgrind can be heavy -- wait 5 seconds + sleep 5; # valgrind can be heavy -- wait 5 seconds my $test_data = "hello world\n"; @@ -108,6 +109,22 @@ for my $binary (@binaries) { } } +# Test: PROBE_AGAIN, incomplete first frame + if ($SSH_PROBE_AGAIN) { + print "***Test: incomplete SSH first frame\n"; + my $cnx_h = new IO::Socket::INET(PeerHost => "localhost:$sslh_port"); + warn "$!\n" unless $cnx_h; + if (defined $cnx_h) { + my $td = "SSH-2.0 testsuite\t$test_data"; + print $cnx_h substr $td, 0, 2; + sleep 1; + print $cnx_h substr $td, 2; + my $data = <$cnx_h>; + is($data, "ssh: $td", "Incomplete first SSH frame"); + } + } + + # Test: One SSL half-started then one SSH if ($SSL_MIX_SSH) { print "***Test: One SSL half-started then one SSH\n";