Fix lots of bugs and add dissector

Co-authored-by: Ezequiel Bellver <ebellver@itba.edu.ar>
Co-authored-by: Juan Barmasch <jbarmasch@itba.edu.ar>
This commit is contained in:
Santiago Lo Coco 2022-06-18 16:50:57 -03:00
parent f8aa3e12e3
commit 9cac4bf50d
18 changed files with 1313 additions and 439 deletions

1
.gitignore vendored
View File

@ -15,6 +15,7 @@ socks5d
client client
*.o *.o
a.out a.out
*.log
## Tests ## Tests
PVS-Studio.log PVS-Studio.log

View File

@ -1,4 +1,6 @@
CCFLAGS = -std=c11 -Wall -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough -pedantic -pedantic-errors -fsanitize=address -fno-omit-frame-pointer -g -D_POSIX_C_SOURCE=200809L CCFLAGS = -std=c11 -Wall -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough -pedantic -pedantic-errors -fsanitize=address -fno-omit-frame-pointer -g -D_POSIX_C_SOURCE=200809L
# CCFLAGS = -std=c11 -Wall -Wextra -Wno-unused-parameter -Wno-implicit-fallthrough -pedantic -pedantic-errors -fsanitize=address -fno-omit-frame-pointer -g -D_POSIX_C_SOURCE=200112L
LDFLAGS = -lpthread -lm LDFLAGS = -lpthread -lm
SERVER_SOURCES=src/args.c src/selector.c src/socks5nio.c src/confignio.c src/stm.c src/hello.c src/request.c src/netutils.c src/buffer.c src/server.c src/auth.c src/cmd.c src/parser.c src/parser_utils.c SERVER_SOURCES=src/args.c src/selector.c src/socks5nio.c src/confignio.c src/stm.c src/hello.c src/request.c src/netutils.c src/buffer.c src/server.c src/auth.c src/cmd.c src/parser.c src/parser_utils.c

View File

@ -42,11 +42,11 @@ Tabla de Contenidos
[X] 2. soportar autenticación usuario / contraseña [RFC1929]. [X] 2. soportar autenticación usuario / contraseña [RFC1929].
[-] 3. soportar de mínima conexiones salientes a a servicios TCP a [X] 3. soportar de mínima conexiones salientes a a servicios TCP a
direcciones IPv4, IPV6, o utilizando FQDN que resuelvan direcciones IPv4, IPV6, o utilizando FQDN que resuelvan
cualquiera de estos tipos de direcciones. cualquiera de estos tipos de direcciones.
[] 4. ser robusto en cuanto a las opciones de conexión (si se utiliza [X] 4. ser robusto en cuanto a las opciones de conexión (si se utiliza
un FQDN que resuelve a múltiples direcciones IP y una no está un FQDN que resuelve a múltiples direcciones IP y una no está
disponible debe intentar con otros). disponible debe intentar con otros).
@ -56,9 +56,9 @@ Tabla de Contenidos
[X] 6. implementar mecanismos que permitan recolectar métricas que [X] 6. implementar mecanismos que permitan recolectar métricas que
ayuden a monitorear la operación del sistema. ayuden a monitorear la operación del sistema.
[]A. cantidad de conexiones históricas [X]A. cantidad de conexiones históricas
[]B. cantidad de conexiones concurrentes [X]B. cantidad de conexiones concurrentes
[X]C. cantidad de bytes transferidos [X]C. cantidad de bytes transferidos
@ -80,7 +80,7 @@ Tabla de Contenidos
caso de que llega una queja externa y el administrador debe saber caso de que llega una queja externa y el administrador debe saber
quien fue el que se conectó a cierto sitio web y cuando. quien fue el que se conectó a cierto sitio web y cuando.
[] 9. monitorear el tráfico y generar un registro de credenciales de [X] 9. monitorear el tráfico y generar un registro de credenciales de
acceso (usuarios y passwords) de forma similar a ettercap por lo acceso (usuarios y passwords) de forma similar a ettercap por lo
menos para protocolo POP3. menos para protocolo POP3.
@ -93,7 +93,7 @@ Tabla de Contenidos
[X] 2. Utilizar sockets en modo no bloqueante multiplexada. [X] 2. Utilizar sockets en modo no bloqueante multiplexada.
3. Tener en cuenta todos los aspectos que hagan a la buena [] 3. Tener en cuenta todos los aspectos que hagan a la buena
performance, escalabilidad y disponibilidad del servidor. Se performance, escalabilidad y disponibilidad del servidor. Se
espera que se maneje de forma eficiente los flujos de información espera que se maneje de forma eficiente los flujos de información
(por ejemplo no cargar en memoria mensajes muy grandes, ser (por ejemplo no cargar en memoria mensajes muy grandes, ser

File diff suppressed because it is too large Load Diff

View File

@ -9,13 +9,29 @@ struct parser_event {
unsigned type; unsigned type;
/** caracteres asociados al evento */ /** caracteres asociados al evento */
uint8_t data[3]; uint8_t data[3];
/** cantidad de datos en el buffer `data' */ /** cantidad de datos en el buffer 'data' */
uint8_t n; uint8_t n;
/** lista de eventos: si es diferente de null ocurrieron varios eventos */ /** lista de eventos: si es diferente de null ocurrieron varios eventos */
struct parser_event *next; struct parser_event *next;
}; };
/* CDT del parser */
typedef struct parser {
/** tipificación para cada caracter */
const unsigned *classes;
/** definición de estados */
struct parser_definition *def;
/* estado actual */
unsigned state;
/* evento que se retorna */
struct parser_event e1;
/* evento que se retorna */
struct parser_event e2;
} parser;
/** describe una transición entre estados */ /** describe una transición entre estados */
struct parser_state_transition { struct parser_state_transition {
/* condición: un caracter o una clase de caracter. Por ej: '\r' */ /* condición: un caracter o una clase de caracter. Por ej: '\r' */
@ -34,14 +50,14 @@ static const unsigned ANY = 1 << 9;
/** declaración completa de una máquina de estados */ /** declaración completa de una máquina de estados */
struct parser_definition { struct parser_definition {
/** cantidad de estados */ /** cantidad de estados */
const unsigned states_count; unsigned states_count;
/** por cada estado, sus transiciones */ /** por cada estado, sus transiciones */
const struct parser_state_transition **states; struct parser_state_transition **states;
/** cantidad de estados por transición */ /** cantidad de estados por transición */
const size_t *states_n; size_t *states_n;
/** estado inicial */ /** estado inicial */
const unsigned start_state; unsigned start_state;
}; };
/** /**
@ -49,7 +65,7 @@ struct parser_definition {
* *
* `classes`: caracterización de cada caracter (256 elementos) * `classes`: caracterización de cada caracter (256 elementos)
*/ */
struct parser * parser_init(const unsigned *classes, const struct parser_definition *def); struct parser * parser_init(const unsigned *classes, struct parser_definition *def);
/** destruye el parser */ /** destruye el parser */
void parser_destroy(struct parser *p); void parser_destroy(struct parser *p);
@ -62,7 +78,7 @@ void parser_reset(struct parser *p);
* de parsing. Los eventos son reusado entre llamadas por lo que si se desea * de parsing. Los eventos son reusado entre llamadas por lo que si se desea
* capturar los datos se debe clonar. * capturar los datos se debe clonar.
*/ */
const struct parser_event * parser_feed(struct parser *p, const uint8_t c); struct parser_event * parser_feed(struct parser *p, const uint8_t c);
/** /**
* En caso de la aplicacion no necesite clases caracteres, se * En caso de la aplicacion no necesite clases caracteres, se

View File

@ -20,11 +20,11 @@ const char * parser_utils_strcmpi_event(const enum string_cmp_event_types type);
* *
* Si se recibe el evento `STRING_CMP_NEQ' el texto entrado no matchea. * Si se recibe el evento `STRING_CMP_NEQ' el texto entrado no matchea.
*/ */
struct parser_definition parser_utils_strcmpi(const char *s); struct parser_definition * parser_utils_strcmpi(const char *s);
/** /**
* libera recursos asociado a una llamada de `parser_utils_strcmpi' * libera recursos asociado a una llamada de `parser_utils_strcmpi'
*/ */
void parser_utils_strcmpi_destroy(const struct parser_definition *p); void parser_utils_strcmpi_destroy(struct parser_definition *p);
#endif #endif

View File

@ -59,7 +59,7 @@ struct request_parser {
enum socks_response_status { enum socks_response_status {
status_succeeded = 0x00, status_succeeded = 0x00,
status_general_SOCKS_server_failure = 0x01, status_general_SOCKS_server_failure = 0x01,
status_connectino_not_allowed_by_ruleset = 0x02, status_connection_not_allowed_by_ruleset = 0x02,
status_network_unreachable = 0x03, status_network_unreachable = 0x03,
status_host_unreachable = 0x04, status_host_unreachable = 0x04,
status_connection_refused = 0x05, status_connection_refused = 0x05,

View File

@ -7,5 +7,8 @@ bool get_auth_status();
bool set_auth_status(bool auth_status); bool set_auth_status(bool auth_status);
bool get_pass_dissector_status(); bool get_pass_dissector_status();
bool set_pass_dissector_status(bool pwd_dissector_status); bool set_pass_dissector_status(bool pwd_dissector_status);
uint64_t get_bytes_transferred();
uint32_t get_now_connect();
uint32_t get_total_connect();
#endif #endif

View File

@ -59,7 +59,7 @@ static void usage(const char *progname) {
void parse_args(const int argc, char ** argv, struct socks5args * args) { void parse_args(const int argc, char ** argv, struct socks5args * args) {
memset(args, 0, sizeof(*args)); memset(args, 0, sizeof(*args));
args->socks_addr = "0.0.0.0"; args->socks_addr = NULL;
args->socks_port = 1080; args->socks_port = 1080;
args->mng_addr = "127.0.0.1"; args->mng_addr = "127.0.0.1";
@ -69,7 +69,6 @@ void parse_args(const int argc, char ** argv, struct socks5args * args) {
int c; int c;
int nusers = 0; int nusers = 0;
while (true) { while (true) {
c = getopt(argc, argv, "hl:L:Np:P:u:v"); c = getopt(argc, argv, "hl:L:Np:P:u:v");
if (c == -1) if (c == -1)

View File

@ -74,8 +74,9 @@ uint8_t parse_args(int argc, char ** argv, uint8_t * buffer) {
buffer[7] = (uint8_t) (token>>8); buffer[7] = (uint8_t) (token>>8);
buffer[8] = (uint8_t) token; buffer[8] = (uint8_t) token;
for(int i=1; i<argc; ++i) for (int i = 1; i < argc; ++i) {
argv[i] = argv[i+1]; argv[i] = argv[i+1];
}
argc--; argc--;
c = getopt(argc, argv, "hmbtfsazrB:T:l:u:c:A:S:p:n:d:Z:"); c = getopt(argc, argv, "hmbtfsazrB:T:l:u:c:A:S:p:n:d:Z:");
@ -209,17 +210,53 @@ uint8_t parse_args(int argc, char ** argv, uint8_t * buffer) {
return buffer[9]; return buffer[9];
} }
void parse_response(char * buffer, uint8_t cmd) { void parse_response(uint8_t * buffer, uint8_t cmd) {
if (buffer[0] != 0x01) { if (buffer[0] != 0x01) {
fprintf(stderr, "Incorrect response version.\n"); fprintf(stderr, "Incorrect response version.\n");
} }
uint32_t now_conn = 0, total_conn = 0;
uint64_t bytes = 0;
switch (buffer[1]) { switch (buffer[1]) {
case RESPONSE_OK: case RESPONSE_OK:
fprintf(stdout, "Success.\n"); fprintf(stdout, "Success.\n");
switch (cmd) { switch (cmd) {
case CMD_GET_METRICS: case CMD_GET_METRICS:
fprintf(stdout, "Metrics: ...\n"); fprintf(stdout, "Metrics:\n");
total_conn += buffer[2];
total_conn <<= 24;
total_conn += buffer[3];
total_conn <<= 16;
total_conn += buffer[4];
total_conn <<= 8;
total_conn += buffer[5];
now_conn += buffer[6];
now_conn <<= 24;
now_conn += buffer[7];
now_conn <<= 16;
now_conn += buffer[8];
now_conn <<= 8;
now_conn += buffer[9];
bytes += buffer[10];
bytes <<= 56;
bytes += buffer[11];
bytes <<= 48;
bytes += buffer[12];
bytes <<= 40;
bytes += buffer[13];
bytes <<= 32;
bytes += buffer[14];
bytes <<= 24;
bytes += buffer[15];
bytes <<= 16;
bytes += buffer[16];
bytes <<= 8;
bytes += buffer[17];
fprintf(stdout, "\tTotal connections: %u\n\tCurrent connections: %u\n\tTotal bytes transferred: %lu\n", total_conn, now_conn, bytes);
break; break;
/* /*
case CMD_GET_BUFFER_SIZE: case CMD_GET_BUFFER_SIZE:
@ -260,6 +297,8 @@ void parse_response(char * buffer, uint8_t cmd) {
case CMD_CHANGE_PROXY_SERVER_STATUS: case CMD_CHANGE_PROXY_SERVER_STATUS:
case CMD_RESTART_PROXY_SERVER: case CMD_RESTART_PROXY_SERVER:
break; break;
default:
break;
} }
break; break;
case RESPONSE_INVALID_TOKEN: case RESPONSE_INVALID_TOKEN:
@ -271,6 +310,8 @@ void parse_response(char * buffer, uint8_t cmd) {
case RESPONSE_VERSION_NOT_SUPPORTED: case RESPONSE_VERSION_NOT_SUPPORTED:
fprintf(stdout, "Version not supported.\n"); fprintf(stdout, "Version not supported.\n");
break; break;
default:
break;
} }
} }
@ -302,17 +343,14 @@ int main(int argc, char **argv) {
err_msg = "Unable to send cmd"; err_msg = "Unable to send cmd";
goto finally; goto finally;
} }
char * recv_buffer = malloc(MAX_RECV_SIZE); uint8_t * recv_buffer = calloc(1, MAX_RECV_SIZE);
ssize_t received = recvfrom(client, recv_buffer, sizeof(recv_buffer), 0, NULL, NULL); ssize_t received = recvfrom(client, recv_buffer, MAX_RECV_SIZE, 0, NULL, NULL);
if (received < 0) { if (received < 0) {
err_msg = "Unable to receive cmd"; err_msg = "Unable to receive cmd";
goto finally; goto finally;
} }
recv_buffer[received] = 0;
parse_response(recv_buffer, cmd); parse_response(recv_buffer, cmd);
// printf("%s\n", recv_buffer);
// TODO cambiar la forma en la que imprimimos
err_msg = NULL; err_msg = NULL;
int ret = EXIT_SUCCESS; int ret = EXIT_SUCCESS;

View File

@ -180,9 +180,35 @@ ssize_t cmd_process(struct selector_key *key, buffer * b) {
return i; return i;
} }
uint64_t bytes;
uint32_t total_conn, now_conn;
buff[i++] = 0x00; buff[i++] = 0x00;
switch (d->cmd) { switch (d->cmd) {
case CMD_GET_METRICS: case CMD_GET_METRICS:
bytes = get_bytes_transferred();
now_conn = get_now_connect();
total_conn = get_total_connect();
buff[i++] = total_conn >> 24;
buff[i++] = (uint8_t) (total_conn >> 16);
buff[i++] = (uint8_t) (total_conn >> 8);
buff[i++] = (uint8_t) total_conn;
buff[i++] = now_conn >> 24;
buff[i++] = (uint8_t) (now_conn >> 16);
buff[i++] = (uint8_t) (now_conn >> 8);
buff[i++] = (uint8_t) now_conn;
buff[i++] = bytes >> 56;
buff[i++] = (uint8_t) (bytes >> 48);
buff[i++] = (uint8_t) (bytes >> 40);
buff[i++] = (uint8_t) (bytes >> 32);
buff[i++] = (uint8_t) (bytes >> 24);
buff[i++] = (uint8_t) (bytes >> 16);
buff[i++] = (uint8_t) (bytes >> 8);
buff[i++] = (uint8_t) bytes;
break; break;
// case CMD_GET_BUFFER_SIZE: // case CMD_GET_BUFFER_SIZE:
// break; // break;

View File

@ -70,7 +70,7 @@ extern const char * hello_error(const struct hello_parser *p) {
char * ret; char * ret;
switch (p->state) { switch (p->state) {
case hello_error_unsupported_version: case hello_error_unsupported_version:
ret = "unsupported version"; ret = "Unsupported version";
break; break;
default: default:
ret = ""; ret = "";

View File

@ -5,22 +5,7 @@
#include <string.h> #include <string.h>
#include "parser.h" #include "parser.h"
#include "parser_utils.h"
/* CDT del parser */
struct parser {
/** tipificación para cada caracter */
const unsigned *classes;
/** definición de estados */
const struct parser_definition *def;
/* estado actual */
unsigned state;
/* evento que se retorna */
struct parser_event e1;
/* evento que se retorna */
struct parser_event e2;
};
void parser_destroy(struct parser *p) { void parser_destroy(struct parser *p) {
if (p != NULL) { if (p != NULL) {
@ -28,7 +13,9 @@ void parser_destroy(struct parser *p) {
} }
} }
struct parser * parser_init(const unsigned *classes, const struct parser_definition *def) { #include <stdio.h>
struct parser * parser_init(const unsigned *classes, struct parser_definition *def) {
struct parser *ret = malloc(sizeof(*ret)); struct parser *ret = malloc(sizeof(*ret));
if (ret != NULL) { if (ret != NULL) {
memset(ret, 0, sizeof(*ret)); memset(ret, 0, sizeof(*ret));
@ -43,7 +30,7 @@ void parser_reset(struct parser *p) {
p->state = p->def->start_state; p->state = p->def->start_state;
} }
const struct parser_event * parser_feed(struct parser *p, const uint8_t c) { struct parser_event * parser_feed(struct parser *p, const uint8_t c) {
const unsigned type = p->classes[c]; const unsigned type = p->classes[c];
p->e1.next = p->e2.next = 0; p->e1.next = p->e2.next = 0;
@ -52,7 +39,7 @@ const struct parser_event * parser_feed(struct parser *p, const uint8_t c) {
const size_t n = p->def->states_n[p->state]; const size_t n = p->def->states_n[p->state];
bool matched = false; bool matched = false;
for(unsigned i = 0; i < n ; i++) { for (unsigned i = 0; i < n ; i++) {
const int when = state[i].when; const int when = state[i].when;
if (state[i].when <= 0xFF) { if (state[i].when <= 0xFF) {
matched = (c == when); matched = (c == when);
@ -82,4 +69,3 @@ static const unsigned classes[0xFF] = {0x00};
const unsigned * parser_no_classes(void) { const unsigned * parser_no_classes(void) {
return classes; return classes;
} }

View File

@ -41,35 +41,7 @@ static void neq(struct parser_event *ret, const uint8_t c) {
ret->data[0] = c; ret->data[0] = c;
} }
/* struct parser_definition * parser_utils_strcmpi(const char *s) {
* para comparar "foo" (length 3) necesitamos 3 + 2 estados.
* Los útimos dos, son el sumidero de comparación fallida, y
* el estado donde se llegó a la comparación completa.
*
* static const struct parser_state_transition ST_0 [] = {
* {.when = 'F', .dest = 1, .action1 = may_eq, },
* {.when = 'f', .dest = 1, .action1 = may_eq, },
* {.when = ANY, .dest = NEQ, .action1 = neq,},
* };
* static const struct parser_state_transition ST_1 [] = {
* {.when = 'O', .dest = 2, .action1 = may_eq, },
* {.when = 'o', .dest = 2, .action1 = may_eq, },
* {.when = ANY, .dest = NEQ, .action1 = neq,},
* };
* static const struct parser_state_transition ST_2 [] = {
* {.when = 'O', .dest = EQ, .action1 = eq, },
* {.when = 'o', .dest = EQ, .action1 = eq, },
* {.when = ANY, .dest = NEQ, .action1 = neq,},
* };
* static const struct parser_state_transition ST_EQ (3) [] = {
* {.when = ANY, .dest = NEQ, .action1 = neq,},
* };
* static const struct parser_state_transition ST_NEQ (4) [] = {
* {.when = ANY, .dest = NEQ, .action1 = neq,},
* };
*
*/
struct parser_definition parser_utils_strcmpi(const char *s) {
const size_t n = strlen(s); const size_t n = strlen(s);
struct parser_state_transition **states = calloc(n + 2, sizeof(*states)); struct parser_state_transition **states = calloc(n + 2, sizeof(*states));
@ -81,12 +53,15 @@ struct parser_definition parser_utils_strcmpi(const char *s) {
free(nstates); free(nstates);
free(transitions); free(transitions);
struct parser_definition def = { struct parser_definition * def = calloc(1, sizeof(struct parser_definition));
.start_state = 0,
.states_count = 0, // struct parser_definition def = {
.states = NULL, // .start_state = 0,
.states_n = NULL, // .states_count = 0,
}; // .states = NULL,
// .states_n = NULL,
// };
return def; return def;
} }
@ -125,18 +100,25 @@ struct parser_definition parser_utils_strcmpi(const char *s) {
nstates[(n + 1)] = 1; nstates[(n + 1)] = 1;
struct parser_definition def = { struct parser_definition * def = malloc(sizeof(*def));
.start_state = 0, def->start_state = 0;
.states_count = n + 2, def->states_count = n + 2;
.states = (const struct parser_state_transition **) states, def->states = (struct parser_state_transition **) states;
.states_n = (const size_t *) nstates, def->states_n = (size_t *) nstates;
};
// struct parser_definition def = {
// .start_state = 0,
// .states_count = n + 2,
// // .states = (const struct parser_state_transition **) states,
// // .states_n = (const size_t *) nstates,
// };
return def; return def;
} }
void parser_utils_strcmpi_destroy(const struct parser_definition *p) { void parser_utils_strcmpi_destroy(struct parser_definition *p) {
free((void *)p->states[0]); free((void *)p->states[0]);
free((void *)p->states); free((void *)p->states);
free((void *)p->states_n); free((void *)p->states_n);
free(p);
} }

View File

@ -3,6 +3,7 @@
#include <string.h> #include <string.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
#include "request.h" #include "request.h"
@ -155,7 +156,6 @@ static enum request_state request_parser_feed(struct request_parser * p, const u
bool request_is_done(const enum request_state state, bool * errored) { bool request_is_done(const enum request_state state, bool * errored) {
bool ret = true; bool ret = true;
switch (state) { switch (state) {
case request_error: case request_error:
case request_error_unsupported_version: case request_error_unsupported_version:

View File

@ -47,34 +47,87 @@ int main(int argc, char **argv) {
// TCP // TCP
// ------ // ------
unsigned char buf[sizeof(struct in6_addr)];
int domain = -1;
if (args->socks_addr != NULL) {
if (inet_pton(AF_INET, args->socks_addr, buf)) {
domain = AF_INET;
} else if (inet_pton(AF_INET6, args->socks_addr, buf)) {
domain = AF_INET6;
}
}
struct sockaddr_in addr; struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr)); int server;
addr.sin_family = AF_INET; if (domain == AF_INET || domain == -1) {
if (inet_pton(AF_INET, args->socks_addr, &addr.sin_addr) <= 0) { memset(&addr, 0, sizeof(addr));
err_msg = "Incorrect network address"; addr.sin_family = AF_INET;
goto finally; if (domain == AF_INET) {
} if (inet_pton(AF_INET, args->socks_addr, &addr.sin_addr) <= 0) {
// addr.sin_addr.s_addr = htonl(INADDR_ANY); err_msg = "Incorrect network address";
addr.sin_port = htons(args->socks_port); goto finally;
}
} else {
addr.sin_addr.s_addr = htonl(INADDR_ANY);
}
addr.sin_port = htons(args->socks_port);
const int server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server < 0) { if (server < 0) {
err_msg = "Unable to create TCP socket"; err_msg = "Unable to create TCP socket";
goto finally; goto finally;
}
fprintf(stdout, "Listening on TCP port %u\n", args->socks_port);
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
if (bind(server, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
err_msg = "Unable to bind TCP socket";
goto finally;
}
if (listen(server, 20) < 0) {
err_msg = "Unable to listen";
goto finally;
}
} }
fprintf(stdout, "Listening on TCP port %u\n", args->socks_port); struct sockaddr_in6 tcp_addr_ipv6;
int server_ipv6;
if (domain == AF_INET6 || domain == -1) {
memset(&tcp_addr_ipv6, 0, sizeof(tcp_addr_ipv6));
tcp_addr_ipv6.sin6_family = AF_INET6;
if (domain == AF_INET6) {
if (inet_pton(AF_INET6, args->socks_addr, &tcp_addr_ipv6.sin6_addr) <= 0) {
err_msg = "Incorrect network address";
goto finally;
}
} else {
tcp_addr_ipv6.sin6_addr = in6addr_any;
}
tcp_addr_ipv6.sin6_port = htons(args->socks_port);
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)); server_ipv6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (server_ipv6 < 0) {
err_msg = "Unable to create TCP ipv6 socket";
goto finally;
}
if (bind(server, (struct sockaddr *) &addr, sizeof(addr)) < 0) { fprintf(stdout, "Listening on TCP port %u\n", args->socks_port);
err_msg = "Unable to bind TCP socket";
goto finally;
}
if (listen(server, 20) < 0) { setsockopt(server_ipv6, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
err_msg = "Unable to listen"; setsockopt(server_ipv6, SOL_IPV6, IPV6_V6ONLY, &(int) { 1 }, sizeof(int));
goto finally;
if (bind(server_ipv6, (struct sockaddr *) &tcp_addr_ipv6, sizeof(tcp_addr_ipv6)) < 0) {
err_msg = "Unable to bind TCP ipv6 socket";
goto finally;
}
if (listen(server_ipv6, 20) < 0) {
err_msg = "Unable to listen";
goto finally;
}
} }
// ------ // ------
@ -99,7 +152,7 @@ int main(int argc, char **argv) {
fprintf(stdout, "Listening on UDP port %u\n", args->mng_port); fprintf(stdout, "Listening on UDP port %u\n", args->mng_port);
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int)); setsockopt(udp_server, SOL_SOCKET, SO_REUSEADDR, &(int){ 1 }, sizeof(int));
if (bind(udp_server, (struct sockaddr *) &udp_addr, sizeof(udp_addr)) < 0) { if (bind(udp_server, (struct sockaddr *) &udp_addr, sizeof(udp_addr)) < 0) {
err_msg = "Unable to bind UDP socket"; err_msg = "Unable to bind UDP socket";
@ -111,7 +164,6 @@ int main(int argc, char **argv) {
goto finally; goto finally;
} }
// struct config * config_ret = calloc(1, sizeof(struct config));
struct config * config_ret = malloc(sizeof(struct config)); struct config * config_ret = malloc(sizeof(struct config));
memset(config_ret, 0x00, sizeof(*config_ret)); memset(config_ret, 0x00, sizeof(*config_ret));
buffer_init(&config_ret->read_buffer, N(config_ret->raw_buff_a), config_ret->raw_buff_a); buffer_init(&config_ret->read_buffer, N(config_ret->raw_buff_a), config_ret->raw_buff_a);
@ -120,10 +172,6 @@ int main(int argc, char **argv) {
signal(SIGTERM, sigterm_handler); signal(SIGTERM, sigterm_handler);
signal(SIGINT, sigterm_handler); signal(SIGINT, sigterm_handler);
if (selector_fd_set_nio(server) == -1) {
err_msg = "Getting server socket flags";
goto finally;
}
const struct selector_init conf = { const struct selector_init conf = {
.signal = SIGALRM, .signal = SIGALRM,
.select_timeout = { .select_timeout = {
@ -147,10 +195,30 @@ int main(int argc, char **argv) {
.handle_write = NULL, .handle_write = NULL,
.handle_close = NULL, .handle_close = NULL,
}; };
ss = selector_register(selector, server, &socksv5, OP_READ, NULL); if (domain == AF_INET || domain == -1) {
if (ss != SELECTOR_SUCCESS) { if (selector_fd_set_nio(server) == -1) {
err_msg = "Registering fd"; err_msg = "Getting server socket flags";
goto finally; goto finally;
}
ss = selector_register(selector, server, &socksv5, OP_READ, NULL);
if (ss != SELECTOR_SUCCESS) {
err_msg = "Registering fd";
goto finally;
}
}
if (domain == AF_INET6 || domain == -1) {
if (selector_fd_set_nio(server_ipv6) == -1) {
err_msg = "Getting server socket flags";
goto finally;
}
ss = selector_register(selector, server_ipv6, &socksv5, OP_READ, NULL);
if (ss != SELECTOR_SUCCESS) {
err_msg = "Registering fd";
goto finally;
}
} }
if (selector_fd_set_nio(udp_server) == -1) { if (selector_fd_set_nio(udp_server) == -1) {
@ -181,6 +249,10 @@ int main(int argc, char **argv) {
err_msg = "Closing"; err_msg = "Closing";
} }
for (int i = 0; i < args->nusers; i++) {
free(args->users[i].name);
free(args->users[i].pass);
}
free(args); free(args);
free(config_ret); free(config_ret);
@ -221,9 +293,9 @@ int check_password(int idx, char * password) {
bool add_user(char * username, char * password) { bool add_user(char * username, char * password) {
if (args->nusers < MAX_USERS) { if (args->nusers < MAX_USERS) {
user_t * user = malloc(sizeof(user_t)); user_t * user = malloc(sizeof(user_t));
user->name = malloc(strlen(username)); user->name = malloc(strlen(username) + 1);
strcpy(user->name, username); strcpy(user->name, username);
user->pass = malloc(strlen(password)); user->pass = malloc(strlen(password) + 1);
strcpy(user->pass, password); strcpy(user->pass, password);
args->users[args->nusers] = *user; args->users[args->nusers] = *user;
args->nusers++; args->nusers++;
@ -236,7 +308,7 @@ bool modify_username(char * old_uname, char * new_uname) {
int idx = findUser(old_uname); int idx = findUser(old_uname);
if (idx == -1) if (idx == -1)
return false; return false;
args->users[idx].name = realloc(args->users[idx].name, strlen(new_uname)); args->users[idx].name = realloc(args->users[idx].name, strlen(new_uname) + 1);
strcpy(args->users[idx].name, new_uname); strcpy(args->users[idx].name, new_uname);
return true; return true;
} }
@ -245,7 +317,7 @@ bool modify_password(char * uname, char * new_pwd) {
int idx = findUser(uname); int idx = findUser(uname);
if (idx == -1) if (idx == -1)
return false; return false;
args->users[idx].pass = realloc(args->users[idx].pass, strlen(new_pwd)); args->users[idx].pass = realloc(args->users[idx].pass, strlen(new_pwd) + 1);
strcpy(args->users[idx].pass, new_pwd); strcpy(args->users[idx].pass, new_pwd);
return true; return true;
} }

View File

@ -20,19 +20,24 @@
#include "stm.h" #include "stm.h"
#include "socks5nio.h" #include "socks5nio.h"
#include "netutils.h" #include "netutils.h"
#include "parser.h"
#include "parser_utils.h"
#define N(x) (sizeof(x)/sizeof((x)[0])) #define N(x) (sizeof(x)/sizeof((x)[0]))
#define BUFF_SIZE 4096 // TODO: decidir tamaño del buffer (2048 muy lento para archivos grandes!!!) #define BUFF_SIZE 4096 // TODO: decidir tamaño del buffer (2048 muy lento para archivos grandes!!!)
#define POP3_COMMAND_ARG 249
// TODO: hacer que cambie con nuestro proto // TODO: hacer que cambie con nuestro proto
bool auth_active = true; bool auth_active = true;
bool pwd_dissector_active = false; bool pwd_dissector_active = false;
int total_connect = 0; uint32_t total_connect = 0;
int now_connect = 0; uint32_t now_connect = 0;
long long bytes_transferred = 0; uint64_t bytes_transferred = 0;
int buff_size = 4096; int buff_size = 4096;
int timeout = 10; int timeout = 10;
int user_log;
int connection_log;
/** maquina de estados general */ /** maquina de estados general */
enum socks_v5state { enum socks_v5state {
@ -50,6 +55,8 @@ enum socks_v5state {
COPY, COPY,
DONE, DONE,
HELLO_ERROR,
REQUEST_ERROR,
ERROR, ERROR,
}; };
@ -59,6 +66,7 @@ bool get_auth_status() {
bool set_auth_status(bool auth_status) { bool set_auth_status(bool auth_status) {
auth_active = auth_status; auth_active = auth_status;
return true;
} }
bool get_pass_dissector_status() { bool get_pass_dissector_status() {
@ -67,12 +75,21 @@ bool get_pass_dissector_status() {
bool set_pass_dissector_status(bool pwd_dissector_status) { bool set_pass_dissector_status(bool pwd_dissector_status) {
pwd_dissector_active = pwd_dissector_status; pwd_dissector_active = pwd_dissector_status;
return true;
} }
long long get_bytes_transferred() { uint64_t get_bytes_transferred() {
return bytes_transferred; return bytes_transferred;
} }
uint32_t get_now_connect() {
return now_connect;
}
uint32_t get_total_connect() {
return total_connect;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Definición de variables para cada estado // Definición de variables para cada estado
@ -122,6 +139,13 @@ struct copy {
buffer * rb, * wb; buffer * rb, * wb;
fd_interest duplex; fd_interest duplex;
struct parser * parser_user;
struct parser * parser_pass;
char * user;
char * pass;
bool user_done;
bool pass_done;
struct copy * other; struct copy * other;
}; };
@ -168,6 +192,8 @@ struct socks5 {
unsigned references; unsigned references;
bool parser;
struct socks5 * next; struct socks5 * next;
}; };
@ -176,6 +202,8 @@ static unsigned pool_size = 0;
static struct socks5 * pool = 0; static struct socks5 * pool = 0;
static const struct state_definition * socks5_describe_states(void); static const struct state_definition * socks5_describe_states(void);
static struct parser_definition * user = NULL;
static struct parser_definition * pass = NULL;
static struct socks5 * socks5_new(int client_fd) { static struct socks5 * socks5_new(int client_fd) {
struct socks5 * ret; struct socks5 * ret;
@ -193,6 +221,11 @@ static struct socks5 * socks5_new(int client_fd) {
} }
memset(ret, 0x00, sizeof(*ret)); memset(ret, 0x00, sizeof(*ret));
if (user == NULL && pass == NULL) {
user = parser_utils_strcmpi("user ");
pass = parser_utils_strcmpi("pass ");
}
ret->origin_fd = -1; ret->origin_fd = -1;
ret->client_fd = client_fd; ret->client_fd = client_fd;
ret->client_addr_len = sizeof(ret->client_addr); ret->client_addr_len = sizeof(ret->client_addr);
@ -202,6 +235,8 @@ static struct socks5 * socks5_new(int client_fd) {
ret->stm.states = socks5_describe_states(); ret->stm.states = socks5_describe_states();
stm_init(&ret->stm); stm_init(&ret->stm);
ret->parser = false;
buffer_init(&ret->read_buffer, N(ret->raw_buff_a), ret->raw_buff_a); buffer_init(&ret->read_buffer, N(ret->raw_buff_a), ret->raw_buff_a);
buffer_init(&ret->write_buffer, N(ret->raw_buff_b), ret->raw_buff_b); buffer_init(&ret->write_buffer, N(ret->raw_buff_b), ret->raw_buff_b);
@ -210,10 +245,27 @@ finally:
return ret; return ret;
} }
void parsers_def_destroy() {
if (user != NULL) {
parser_utils_strcmpi_destroy(user);
}
if (pass != NULL) {
parser_utils_strcmpi_destroy(pass);
}
}
void parsers_destroy(struct socks5 * s) {
if (s->parser) {
free(s->client.copy.user);
free(s->client.copy.pass);
parser_destroy(s->client.copy.parser_user);
parser_destroy(s->client.copy.parser_pass);
}
}
/** realmente destruye */ /** realmente destruye */
static void static void
socks5_destroy_(struct socks5* s) { socks5_destroy_(struct socks5 * s) {
if(s->origin_resolution != NULL) { if(s->origin_resolution != NULL) {
freeaddrinfo(s->origin_resolution); freeaddrinfo(s->origin_resolution);
s->origin_resolution = 0; s->origin_resolution = 0;
@ -226,9 +278,11 @@ socks5_destroy_(struct socks5* s) {
* y el pool de objetos. * y el pool de objetos.
*/ */
static void static void
socks5_destroy(struct socks5 *s) { socks5_destroy(struct socks5 * s) {
if (s != NULL) { if (s != NULL) {
if (s->references == 1) { if (s->references == 1) {
parsers_destroy(s);
now_connect--;
if(pool_size < max_pool) { if(pool_size < max_pool) {
s->next = pool; s->next = pool;
pool = s; pool = s;
@ -247,8 +301,9 @@ socksv5_pool_destroy(void) {
struct socks5 *next, *s; struct socks5 *next, *s;
for(s = pool; s != NULL ; s = next) { for(s = pool; s != NULL ; s = next) {
next = s->next; next = s->next;
free(s); socks5_destroy_(s);
} }
parsers_def_destroy();
} }
/** obtiene el struct (socks5 *) desde la llave de selección */ /** obtiene el struct (socks5 *) desde la llave de selección */
@ -279,6 +334,7 @@ void socksv5_passive_accept(struct selector_key *key) {
if(client == -1) { if(client == -1) {
goto fail; goto fail;
} }
if(selector_fd_set_nio(client) == -1) { if(selector_fd_set_nio(client) == -1) {
goto fail; goto fail;
} }
@ -295,7 +351,9 @@ void socksv5_passive_accept(struct selector_key *key) {
if(SELECTOR_SUCCESS != selector_register(key->s, client, &socks5_handler, OP_READ, state)) { if(SELECTOR_SUCCESS != selector_register(key->s, client, &socks5_handler, OP_READ, state)) {
goto fail; goto fail;
} }
return ; now_connect++;
total_connect++;
return;
fail: fail:
if(client != -1) { if(client != -1) {
close(client); close(client);
@ -369,7 +427,14 @@ static unsigned hello_read(struct selector_key * key) {
ret = ERROR; ret = ERROR;
} }
return error ? ERROR : ret; if (error) {
ret = HELLO_ERROR;
selector_set_interest_key(key, OP_WRITE);
}
// return error ? ERROR : ret;
return ret;
} }
/** procesamiento del mensaje `hello' */ /** procesamiento del mensaje `hello' */
@ -379,10 +444,10 @@ static unsigned hello_process(const struct hello_st * d) {
uint8_t m = d->method; uint8_t m = d->method;
const uint8_t r = (m == METHOD_NO_ACCEPTABLE_METHODS) ? 0xFF : m; const uint8_t r = (m == METHOD_NO_ACCEPTABLE_METHODS) ? 0xFF : m;
if (hello_marshall(d->wb, (enum socks_response_status) r) == -1) { if (hello_marshall(d->wb, (enum socks_response_status) r) == -1) {
ret = ERROR; ret = ERROR;
} }
if (METHOD_NO_ACCEPTABLE_METHODS == m) { if (METHOD_NO_ACCEPTABLE_METHODS == m) {
ret = ERROR; ret = HELLO_ERROR;
} }
return ret; return ret;
} }
@ -422,6 +487,11 @@ static unsigned hello_write(struct selector_key * key) {
return ret; return ret;
} }
static unsigned hello_write_error(struct selector_key * key) {
hello_write(key);
return ERROR;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// AUTH // AUTH
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -561,12 +631,13 @@ static unsigned request_read(struct selector_key * key) {
uint8_t * ptr; uint8_t * ptr;
size_t count; size_t count;
ssize_t n; ssize_t n;
int st;
ptr = buffer_write_ptr(b, &count); ptr = buffer_write_ptr(b, &count);
n = recv(key->fd, ptr, count, 0); n = recv(key->fd, ptr, count, 0);
if (n > 0) { if (n > 0) {
buffer_write_adv(b, n); buffer_write_adv(b, n);
int st = request_consume(b, &d->parser, &error); st = request_consume(b, &d->parser, &error);
if (request_is_done(st, 0)) { if (request_is_done(st, 0)) {
ret = request_process(key, d); ret = request_process(key, d);
} }
@ -574,7 +645,14 @@ static unsigned request_read(struct selector_key * key) {
ret = ERROR; ret = ERROR;
} }
return error ? ERROR : ret; if (error) {
request_marshall(d->wb, d->status);
ret = REQUEST_ERROR;
selector_set_interest_key(key, OP_WRITE);
}
// return error ? ERROR : ret;
return ret;
} }
static unsigned request_connect(struct selector_key * key, struct request_st * d); static unsigned request_connect(struct selector_key * key, struct request_st * d);
@ -622,9 +700,11 @@ static unsigned request_process(struct selector_key * key, struct request_st * d
} }
break; break;
} default: { } default: {
ret = REQUEST_WRITE;
d->status = status_address_type_not_supported; d->status = status_address_type_not_supported;
request_marshall(d->wb, d->status);
ret = REQUEST_ERROR;
selector_set_interest_key(key, OP_WRITE); selector_set_interest_key(key, OP_WRITE);
break;
} }
} }
break; break;
@ -632,7 +712,9 @@ static unsigned request_process(struct selector_key * key, struct request_st * d
case socks_req_cmd_associate: case socks_req_cmd_associate:
default: default:
d->status = status_command_not_supported; d->status = status_command_not_supported;
ret = REQUEST_WRITE; request_marshall(d->wb, d->status);
ret = REQUEST_ERROR;
selector_set_interest_key(key, OP_WRITE);
break; break;
} }
@ -657,10 +739,17 @@ static void * request_resolv_blocking(void * data) {
char buff[7]; char buff[7];
snprintf(buff, sizeof(buff), "%d", ntohs(s->client.request.request.dest_port)); snprintf(buff, sizeof(buff), "%d", ntohs(s->client.request.request.dest_port));
int ret = getaddrinfo(s->client.request.request.dest_addr.fqdn, buff, &hints, &s->origin_resolution);
getaddrinfo(s->client.request.request.dest_addr.fqdn, buff, &hints, &s->origin_resolution); if (ret != 0) {
switch (ret) {
// TODO:manejar el error de getaddrinfo case EAI_FAMILY:
s->client.request.status = status_address_type_not_supported;
case EAI_FAIL:
s->client.request.status = status_host_unreachable;
default:
break;
}
}
selector_notify_block(key->s, key->fd); selector_notify_block(key->s, key->fd);
free(data); free(data);
@ -670,18 +759,35 @@ static void * request_resolv_blocking(void * data) {
static unsigned request_resolv_done(struct selector_key * key) { static unsigned request_resolv_done(struct selector_key * key) {
struct request_st * d = &ATTACHMENT(key)->client.request; struct request_st * d = &ATTACHMENT(key)->client.request;
struct socks5 * s = ATTACHMENT(key); struct socks5 * s = ATTACHMENT(key);
unsigned int st = REQUEST_CONNECTING;
if (d->status == status_address_type_not_supported && d->status == status_host_unreachable)
return st;
if (s->origin_resolution == 0) { if (s->origin_resolution == 0) {
d->status = status_general_SOCKS_server_failure; d->status = status_general_SOCKS_server_failure;
} else { }
s->origin_domain = s->origin_resolution->ai_family; else {
s->origin_addr_len = s->origin_resolution->ai_addrlen; struct addrinfo * addr = s->origin_resolution;
memcpy(&s->origin_addr, s->origin_resolution->ai_addr, s->origin_resolution->ai_addrlen);
while (addr != NULL) {
s->origin_domain = addr->ai_family;
s->origin_addr_len = addr->ai_addrlen;
memcpy(&s->origin_addr, addr->ai_addr, addr->ai_addrlen);
st = request_connect(key, d);
if (d->status == status_succeeded) {
break;
}
else {
errno = 0;
}
addr = addr->ai_next;
}
freeaddrinfo(s->origin_resolution); freeaddrinfo(s->origin_resolution);
s->origin_resolution = 0; s->origin_resolution = 0;
} }
return st;
return request_connect(key, d);
} }
static unsigned request_connect(struct selector_key * key, struct request_st * d) { static unsigned request_connect(struct selector_key * key, struct request_st * d) {
@ -735,7 +841,6 @@ finally:
static void request_read_close(const unsigned state, struct selector_key * key) { static void request_read_close(const unsigned state, struct selector_key * key) {
struct request_st * d = &ATTACHMENT(key)->client.request; struct request_st * d = &ATTACHMENT(key)->client.request;
request_close(&d->parser); request_close(&d->parser);
} }
@ -789,6 +894,9 @@ void log_request(enum socks_response_status status, const struct sockaddr * clie
sockaddr_to_human(cbuff + len, N(cbuff) - len, origin_addr); sockaddr_to_human(cbuff + len, N(cbuff) - len, origin_addr);
fprintf(stdout, "%s\tstatus=%d\n", cbuff, status); fprintf(stdout, "%s\tstatus=%d\n", cbuff, status);
FILE * file = fopen("access.log", "a");
fprintf(file, "%s\tstatus=%d\n", cbuff, status);
fclose(file);
} }
static unsigned request_write(struct selector_key * key) { static unsigned request_write(struct selector_key * key) {
@ -826,6 +934,11 @@ static unsigned request_write(struct selector_key * key) {
return ret; return ret;
} }
static unsigned request_write_error(struct selector_key * key) {
request_write(key);
return ERROR;
}
static void copy_init(const unsigned state, struct selector_key * key) { static void copy_init(const unsigned state, struct selector_key * key) {
struct copy * d = &ATTACHMENT(key)->client.copy; struct copy * d = &ATTACHMENT(key)->client.copy;
@ -835,12 +948,30 @@ static void copy_init(const unsigned state, struct selector_key * key) {
d->duplex = OP_READ | OP_WRITE; d->duplex = OP_READ | OP_WRITE;
d->other = &ATTACHMENT(key)->orig.copy; d->other = &ATTACHMENT(key)->orig.copy;
// struct parser_definition * user = parser_utils_strcmpi("user");
// d->parser_user = parser_init(parser_no_classes(), user);
// struct parser_definition * pass = parser_utils_strcmpi("pass");
// d->parser_pass = parser_init(parser_no_classes(), pass);
// d->user = malloc(249);
// d->pass = malloc(249);
d->user_done = false;
d->pass_done = false;
d->parser_user = parser_init(parser_no_classes(), user);
d->parser_pass = parser_init(parser_no_classes(), pass);
d->user = malloc(249);
d->pass = malloc(249);
ATTACHMENT(key)->parser = true;
d = &ATTACHMENT(key)->orig.copy; d = &ATTACHMENT(key)->orig.copy;
d->fd = &ATTACHMENT(key)->origin_fd; d->fd = &ATTACHMENT(key)->origin_fd;
d->rb = &ATTACHMENT(key)->write_buffer; d->rb = &ATTACHMENT(key)->write_buffer;
d->wb = &ATTACHMENT(key)->read_buffer; d->wb = &ATTACHMENT(key)->read_buffer;
d->duplex = OP_READ | OP_WRITE; d->duplex = OP_READ | OP_WRITE;
d->other = &ATTACHMENT(key)->client.copy; d->other = &ATTACHMENT(key)->client.copy;
d->parser_user = NULL;
d->parser_pass = NULL;
} }
static unsigned copy_compute_interests(fd_selector s, struct copy * d) { static unsigned copy_compute_interests(fd_selector s, struct copy * d) {
@ -880,6 +1011,7 @@ static unsigned copy_r(struct selector_key * key) {
uint8_t * ptr = buffer_write_ptr(b, &size); uint8_t * ptr = buffer_write_ptr(b, &size);
n = recv(key->fd, ptr, size, 0); n = recv(key->fd, ptr, size, 0);
if (n <= 0) { if (n <= 0) {
shutdown(*d->fd, SHUT_RD); shutdown(*d->fd, SHUT_RD);
d->duplex &= ~OP_READ; d->duplex &= ~OP_READ;
if (*d->other->fd != -1) { if (*d->other->fd != -1) {
@ -888,6 +1020,50 @@ static unsigned copy_r(struct selector_key * key) {
} }
} else { } else {
buffer_write_adv(b, n); buffer_write_adv(b, n);
if (d->parser_user != NULL && pwd_dissector_active) {
struct parser_event * st = NULL;
for (int i = 0, k = 0; i < n; i++) {
if (st != NULL && st->type == STRING_CMP_NEQ) {
parser_reset(d->parser_user);
parser_reset(d->parser_pass);
}
if ((st == NULL || st->type != STRING_CMP_EQ) && !d->user_done) {
st = parser_feed(d->parser_user, *(ptr + i));
}
else if (st == NULL || st->type != STRING_CMP_EQ) {
st = parser_feed(d->parser_pass, *(ptr + i));
}
else if (!d->user_done && st->type == STRING_CMP_EQ) {
d->user[k++] = *(ptr + i);
if (*(ptr + i) == '\n') {
d->user_done = true;
d->user[k - 2] = 0;
k = 0;
}
}
else if (!d->pass_done && st->type == STRING_CMP_EQ) {
if (*(ptr + i) == '\n') {
d->pass_done = true;
d->pass[k - 1] = 0;
char buff[SOCKADDR_TO_HUMAN_MIN + 2] = {0};
sockaddr_to_human(buff, N(buff), (struct sockaddr *) &ATTACHMENT(key)->origin_addr);
fprintf(stdout, "%s -> USER: %s - PASS: %s\n", buff, d->user, d->pass);
FILE * file = fopen("passwords.log", "a");
fprintf(file, "%s -> USER: %s - PASS: %s\n", buff, d->user, d->pass);
fclose(file);
d->user_done = false;
d->pass_done = false;
parser_reset(d->parser_user);
parser_reset(d->parser_pass);
}
d->pass[k++] = *(ptr + i);
}
}
parser_reset(d->parser_user);
parser_reset(d->parser_pass);
}
} }
copy_compute_interests(key->s, d); copy_compute_interests(key->s, d);
copy_compute_interests(key->s, d->other); copy_compute_interests(key->s, d->other);
@ -907,6 +1083,7 @@ static unsigned copy_w(struct selector_key * key) {
unsigned ret = COPY; unsigned ret = COPY;
uint8_t * ptr = buffer_read_ptr(b, &size); uint8_t * ptr = buffer_read_ptr(b, &size);
n = send(key->fd, ptr, size, MSG_NOSIGNAL); n = send(key->fd, ptr, size, MSG_NOSIGNAL);
if (n == -1) { if (n == -1) {
shutdown(*d->fd, SHUT_WR); shutdown(*d->fd, SHUT_WR);
@ -967,6 +1144,12 @@ static const struct state_definition client_statbl[] = {
.on_write_ready = copy_w, .on_write_ready = copy_w,
}, { }, {
.state = DONE, .state = DONE,
}, {
.state = HELLO_ERROR,
.on_write_ready = hello_write_error,
}, {
.state = REQUEST_ERROR,
.on_write_ready = request_write_error,
}, { }, {
.state = ERROR, .state = ERROR,
} }

View File

@ -1,6 +1,7 @@
// This is a personal academic project. Dear PVS-Studio, please check it. // This is a personal academic project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include "stm.h" #include "stm.h"
#define N(x) (sizeof(x)/sizeof((x)[0])) #define N(x) (sizeof(x)/sizeof((x)[0]))