1
0
mirror of https://github.com/moparisthebest/sslh synced 2024-11-22 00:52:18 -05:00

Allow probes to say they cannot decide yet

This commit is contained in:
Ondřej Kuzník 2013-09-23 23:30:34 +01:00 committed by Yves Rutschle
parent c84a6af847
commit dbafd6510d
6 changed files with 46 additions and 34 deletions

View File

@ -8,6 +8,7 @@
#include <stdarg.h> #include <stdarg.h>
#include "common.h" #include "common.h"
#include "probe.h"
/* Added to make the code compilable under CYGWIN /* Added to make the code compilable under CYGWIN
* */ * */
@ -215,6 +216,7 @@ void init_cnx(struct connection *cnx)
memset(cnx, 0, sizeof(*cnx)); memset(cnx, 0, sizeof(*cnx));
cnx->q[0].fd = -1; cnx->q[0].fd = -1;
cnx->q[1].fd = -1; cnx->q[1].fd = -1;
cnx->proto = get_first_protocol();
} }
void dump_connection(struct connection *cnx) void dump_connection(struct connection *cnx)

View File

@ -69,6 +69,7 @@ struct queue {
struct connection { struct connection {
enum connection_state state; enum connection_state state;
time_t probe_timeout; time_t probe_timeout;
struct proto *proto;
/* q[0]: queue for external connection (client); /* q[0]: queue for external connection (client);
* q[1]: queue for internal connection (httpd or sshd); * q[1]: queue for internal connection (httpd or sshd);
@ -87,7 +88,6 @@ int connect_addr(struct addrinfo *addr, int fd_from, const char* cnx_name);
int fd2fd(struct queue *target, struct queue *from); int fd2fd(struct queue *target, struct queue *from);
char* sprintaddr(char* buf, size_t size, struct addrinfo *a); char* sprintaddr(char* buf, size_t size, struct addrinfo *a);
void resolve_name(struct addrinfo **out, char* fullname); void resolve_name(struct addrinfo **out, char* fullname);
struct proto* probe_client_protocol(struct connection *cnx);
void log_connection(struct connection *cnx); void log_connection(struct connection *cnx);
int check_access_rights(int in_socket, const char* service); int check_access_rights(int in_socket, const char* service);
void setup_signals(void); void setup_signals(void);

18
probe.c
View File

@ -238,7 +238,7 @@ static int regex_probe(const char *p, int len, struct proto *proto)
* write buffer of the connection and returns a pointer to the protocol * write buffer of the connection and returns a pointer to the protocol
* structure * structure
*/ */
struct proto* probe_client_protocol(struct connection *cnx) int probe_client_protocol(struct connection *cnx)
{ {
char buffer[BUFSIZ]; char buffer[BUFSIZ];
struct proto *p; struct proto *p;
@ -251,16 +251,19 @@ struct proto* probe_client_protocol(struct connection *cnx)
* function does not have to deal with a specific failure condition (the * function does not have to deal with a specific failure condition (the
* connection will just fail later normally). */ * connection will just fail later normally). */
if (n > 0) { if (n > 0) {
int res = PROBE_NEXT;
defer_write(&cnx->q[1], buffer, n); defer_write(&cnx->q[1], buffer, n);
for (p = protocols; p; p = p->next) { for (p = cnx->proto; p && res == PROBE_NEXT; p = p->next) {
if (! p->probe) continue; if (! p->probe) continue;
if (verbose) fprintf(stderr, "probing for %s\n", p->description); if (verbose) fprintf(stderr, "probing for %s\n", p->description);
if (p->probe(buffer, n, p)) {
if (verbose) fprintf(stderr, "probe %s successful\n", p->description); cnx->proto = p;
return p; res = p->probe(cnx->q[1].defered_data, cnx->q[1].defered_data_size, p);
}
} }
if (res != PROBE_NEXT)
return res;
} }
if (verbose) if (verbose)
@ -270,7 +273,8 @@ struct proto* probe_client_protocol(struct connection *cnx)
/* If none worked, return the first one affected (that's completely /* If none worked, return the first one affected (that's completely
* arbitrary) */ * arbitrary) */
return protocols; cnx->proto = protocols;
return PROBE_MATCH;
} }
/* Returns the structure for specified protocol or NULL if not found */ /* Returns the structure for specified protocol or NULL if not found */

View File

@ -49,7 +49,7 @@ void set_protocol_list(struct proto*);
* write buffer of the connection and returns a pointer to the protocol * write buffer of the connection and returns a pointer to the protocol
* structure * structure
*/ */
struct proto* probe_client_protocol(struct connection *cnx); int probe_client_protocol(struct connection *cnx);
/* set the protocol to connect to in case of timeout */ /* set the protocol to connect to in case of timeout */
void set_ontimeout(const char* name); void set_ontimeout(const char* name);

View File

@ -70,39 +70,43 @@ void start_shoveler(int in_socket)
fd_set fds; fd_set fds;
struct timeval tv; struct timeval tv;
struct addrinfo *saddr; struct addrinfo *saddr;
int res; int res = PROBE_AGAIN;
int out_socket; int out_socket;
struct connection cnx; struct connection cnx;
struct proto *prot;
init_cnx(&cnx); init_cnx(&cnx);
cnx.q[0].fd = in_socket;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(in_socket, &fds); FD_SET(in_socket, &fds);
memset(&tv, 0, sizeof(tv)); memset(&tv, 0, sizeof(tv));
tv.tv_sec = probing_timeout; tv.tv_sec = probing_timeout;
res = select(in_socket + 1, &fds, NULL, NULL, &tv);
if (res == -1)
perror("select");
cnx.q[0].fd = in_socket; while (res == PROBE_AGAIN) {
/* POSIX does not guarantee that tv will be updated, but the client can
* only postpone the inevitable for so long */
res = select(in_socket + 1, &fds, NULL, NULL, &tv);
if (res == -1)
perror("select");
if (FD_ISSET(in_socket, &fds)) { if (FD_ISSET(in_socket, &fds)) {
/* Received data: figure out what protocol it is */ /* Received data: figure out what protocol it is */
prot = probe_client_protocol(&cnx); res = probe_client_protocol(&cnx);
} else { } else {
/* Timed out: it's necessarily SSH */ /* Timed out: it's necessarily SSH */
prot = timeout_protocol(); cnx.proto = timeout_protocol();
break;
}
} }
saddr = prot->saddr; saddr = cnx.proto->saddr;
if (prot->service && if (cnx.proto->service &&
check_access_rights(in_socket, prot->service)) { check_access_rights(in_socket, cnx.proto->service)) {
exit(0); exit(0);
} }
/* Connect the target socket */ /* Connect the target socket */
out_socket = connect_addr(saddr, in_socket, prot->description); out_socket = connect_addr(saddr, in_socket, cnx.proto->description);
CHECK_RES_DIE(out_socket, "connect"); CHECK_RES_DIE(out_socket, "connect");
cnx.q[1].fd = out_socket; cnx.q[1].fd = out_socket;

View File

@ -210,7 +210,6 @@ void main_loop(int listen_sockets[], int num_addr_listen)
struct timeval tv; struct timeval tv;
int max_fd, in_socket, i, j, res; int max_fd, in_socket, i, j, res;
struct connection *cnx; struct connection *cnx;
struct proto *prot;
int num_cnx; /* Number of connections in *cnx */ int num_cnx; /* Number of connections in *cnx */
int num_probing = 0; /* Number of connections currently probing int num_probing = 0; /* Number of connections currently probing
* We use this to know if we need to time out of * We use this to know if we need to time out of
@ -303,26 +302,29 @@ void main_loop(int listen_sockets[], int num_addr_listen)
dump_connection(&cnx[i]); dump_connection(&cnx[i]);
exit(1); exit(1);
} }
num_probing--;
cnx[i].state = ST_SHOVELING;
/* If timed out it's SSH, otherwise the client sent /* If timed out it's SSH, otherwise the client sent
* data so probe the protocol */ * data so probe the protocol */
if ((cnx[i].probe_timeout < time(NULL))) { if ((cnx[i].probe_timeout < time(NULL))) {
prot = timeout_protocol(); cnx[i].proto = timeout_protocol();
} else { } else {
prot = probe_client_protocol(&cnx[i]); res = probe_client_protocol(&cnx[i]);
if (res == PROBE_AGAIN)
continue;
} }
num_probing--;
cnx[i].state = ST_SHOVELING;
/* libwrap check if required for this protocol */ /* libwrap check if required for this protocol */
if (prot->service && if (cnx[i].proto->service &&
check_access_rights(in_socket, prot->service)) { check_access_rights(in_socket, cnx[i].proto->service)) {
tidy_connection(&cnx[i], &fds_r, &fds_w); tidy_connection(&cnx[i], &fds_r, &fds_w);
res = -1; res = -1;
} else { } else {
res = connect_queue(&cnx[i], res = connect_queue(&cnx[i],
prot->saddr, cnx[i].proto->saddr,
prot->description, cnx[i].proto->description,
&fds_r, &fds_w); &fds_r, &fds_w);
} }