mirror of
https://github.com/moparisthebest/sslh
synced 2024-11-24 18:12:17 -05:00
Allow probes to say they cannot decide yet
This commit is contained in:
parent
c84a6af847
commit
dbafd6510d
2
common.c
2
common.c
@ -8,6 +8,7 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "probe.h"
|
||||
|
||||
/* Added to make the code compilable under CYGWIN
|
||||
* */
|
||||
@ -215,6 +216,7 @@ void init_cnx(struct connection *cnx)
|
||||
memset(cnx, 0, sizeof(*cnx));
|
||||
cnx->q[0].fd = -1;
|
||||
cnx->q[1].fd = -1;
|
||||
cnx->proto = get_first_protocol();
|
||||
}
|
||||
|
||||
void dump_connection(struct connection *cnx)
|
||||
|
2
common.h
2
common.h
@ -69,6 +69,7 @@ struct queue {
|
||||
struct connection {
|
||||
enum connection_state state;
|
||||
time_t probe_timeout;
|
||||
struct proto *proto;
|
||||
|
||||
/* q[0]: queue for external connection (client);
|
||||
* 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);
|
||||
char* sprintaddr(char* buf, size_t size, struct addrinfo *a);
|
||||
void resolve_name(struct addrinfo **out, char* fullname);
|
||||
struct proto* probe_client_protocol(struct connection *cnx);
|
||||
void log_connection(struct connection *cnx);
|
||||
int check_access_rights(int in_socket, const char* service);
|
||||
void setup_signals(void);
|
||||
|
18
probe.c
18
probe.c
@ -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
|
||||
* structure
|
||||
*/
|
||||
struct proto* probe_client_protocol(struct connection *cnx)
|
||||
int probe_client_protocol(struct connection *cnx)
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
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
|
||||
* connection will just fail later normally). */
|
||||
if (n > 0) {
|
||||
int res = PROBE_NEXT;
|
||||
|
||||
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 (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);
|
||||
return p;
|
||||
}
|
||||
|
||||
cnx->proto = p;
|
||||
res = p->probe(cnx->q[1].defered_data, cnx->q[1].defered_data_size, p);
|
||||
}
|
||||
if (res != PROBE_NEXT)
|
||||
return res;
|
||||
}
|
||||
|
||||
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
|
||||
* arbitrary) */
|
||||
return protocols;
|
||||
cnx->proto = protocols;
|
||||
return PROBE_MATCH;
|
||||
}
|
||||
|
||||
/* Returns the structure for specified protocol or NULL if not found */
|
||||
|
2
probe.h
2
probe.h
@ -49,7 +49,7 @@ void set_protocol_list(struct proto*);
|
||||
* write buffer of the connection and returns a pointer to the protocol
|
||||
* 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 */
|
||||
void set_ontimeout(const char* name);
|
||||
|
36
sslh-fork.c
36
sslh-fork.c
@ -70,39 +70,43 @@ void start_shoveler(int in_socket)
|
||||
fd_set fds;
|
||||
struct timeval tv;
|
||||
struct addrinfo *saddr;
|
||||
int res;
|
||||
int res = PROBE_AGAIN;
|
||||
int out_socket;
|
||||
struct connection cnx;
|
||||
struct proto *prot;
|
||||
|
||||
init_cnx(&cnx);
|
||||
cnx.q[0].fd = in_socket;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(in_socket, &fds);
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
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)) {
|
||||
/* Received data: figure out what protocol it is */
|
||||
prot = probe_client_protocol(&cnx);
|
||||
} else {
|
||||
/* Timed out: it's necessarily SSH */
|
||||
prot = timeout_protocol();
|
||||
if (FD_ISSET(in_socket, &fds)) {
|
||||
/* Received data: figure out what protocol it is */
|
||||
res = probe_client_protocol(&cnx);
|
||||
} else {
|
||||
/* Timed out: it's necessarily SSH */
|
||||
cnx.proto = timeout_protocol();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
saddr = prot->saddr;
|
||||
if (prot->service &&
|
||||
check_access_rights(in_socket, prot->service)) {
|
||||
saddr = cnx.proto->saddr;
|
||||
if (cnx.proto->service &&
|
||||
check_access_rights(in_socket, cnx.proto->service)) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* 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");
|
||||
|
||||
cnx.q[1].fd = out_socket;
|
||||
|
@ -210,7 +210,6 @@ void main_loop(int listen_sockets[], int num_addr_listen)
|
||||
struct timeval tv;
|
||||
int max_fd, in_socket, i, j, res;
|
||||
struct connection *cnx;
|
||||
struct proto *prot;
|
||||
int num_cnx; /* Number of connections in *cnx */
|
||||
int num_probing = 0; /* Number of connections currently probing
|
||||
* 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]);
|
||||
exit(1);
|
||||
}
|
||||
num_probing--;
|
||||
cnx[i].state = ST_SHOVELING;
|
||||
|
||||
/* If timed out it's SSH, otherwise the client sent
|
||||
* data so probe the protocol */
|
||||
if ((cnx[i].probe_timeout < time(NULL))) {
|
||||
prot = timeout_protocol();
|
||||
cnx[i].proto = timeout_protocol();
|
||||
} 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 */
|
||||
if (prot->service &&
|
||||
check_access_rights(in_socket, prot->service)) {
|
||||
if (cnx[i].proto->service &&
|
||||
check_access_rights(in_socket, cnx[i].proto->service)) {
|
||||
tidy_connection(&cnx[i], &fds_r, &fds_w);
|
||||
res = -1;
|
||||
} else {
|
||||
res = connect_queue(&cnx[i],
|
||||
prot->saddr,
|
||||
prot->description,
|
||||
cnx[i].proto->saddr,
|
||||
cnx[i].proto->description,
|
||||
&fds_r, &fds_w);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user