mirror of
https://github.com/moparisthebest/sslh
synced 2024-11-21 16:45:03 -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 <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)
|
||||||
|
2
common.h
2
common.h
@ -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
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
|
* 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 */
|
||||||
|
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
|
* 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);
|
||||||
|
36
sslh-fork.c
36
sslh-fork.c
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user