diff options
author | jpadkins <jacobpadkins@gmail.com> | 2017-03-17 22:32:44 +0300 |
---|---|---|
committer | jpadkins <jacobpadkins@gmail.com> | 2017-03-17 22:32:44 +0300 |
commit | 19e125587589d435a711594d9cd3860ae4c72d47 (patch) | |
tree | b9faafb3c36ac74ac7ee49e5a28e8178103fa4bd | |
parent | 8e8ddcc2a23abafff04f5b0efdd3a5b42d394ad2 (diff) | |
parent | b6772e9aade6c99ca248363f457ba95eda4a12e6 (diff) |
Merge remote-tracking branch 'upstream/feature/tls-error-investigation' into feature/smtp-auth-test
33 files changed, 550 insertions, 323 deletions
diff --git a/check/magma/core/system_check.c b/check/magma/core/system_check.c index 0812cb3a..6d5c4617 100644 --- a/check/magma/core/system_check.c +++ b/check/magma/core/system_check.c @@ -27,8 +27,8 @@ bool_t check_system_signames(void) { bool_t check_system_errnonames(void) { - chr_t buf[1024]; bool_t result = true; + chr_t *buffer1 = MEMORYBUF(1024), *buffer2 = MEMORYBUF(1024); if (!status()) { return result; @@ -37,7 +37,8 @@ bool_t check_system_errnonames(void) { for (uint64_t i = 1; i < _sys_nerr; i++) { // Errors 41 and 58 are aliases, and strerror will return unknown instead of the alias name.. - if (st_cmp_ci_starts(NULLER(strerror(i)), PLACER("Unknown", 7)) && st_cmp_cs_eq(NULLER(errno_name(i, buf, 1024)), NULLER(strerror(i)))) { + if (st_cmp_ci_starts(NULLER(strerror_r(i, buffer1, 1024)), PLACER("Unknown", 7)) && + st_cmp_cs_eq(NULLER(errno_name(i, buffer2, 1024)), NULLER(strerror_r(i, buffer2, 1024)))) { result = false; } } diff --git a/check/magma/servers/imap/imap_check.h b/check/magma/servers/imap/imap_check.h index 402faf6a..8ea8c10f 100644 --- a/check/magma/servers/imap/imap_check.h +++ b/check/magma/servers/imap/imap_check.h @@ -8,8 +8,8 @@ #define IMAP_CHECK_H /// imap_check_network.c -bool_t check_imap_client_read_lines_to_end(client_t* client, chr_t* token); -bool_t check_imap_network_basic_sthread(stringer_t* errmsg, uint32_t port); +bool_t check_imap_client_read_lines_to_end(client_t *client, chr_t *tag); +bool_t check_imap_network_basic_sthread(stringer_t *errmsg, uint32_t port); Suite * suite_check_imap(void); diff --git a/check/magma/servers/imap/imap_check_network.c b/check/magma/servers/imap/imap_check_network.c index 66781ebd..21192b51 100644 --- a/check/magma/servers/imap/imap_check_network.c +++ b/check/magma/servers/imap/imap_check_network.c @@ -1,5 +1,6 @@ + /** - * @file /magma/check/magma/servers/smtp/smtp_check_helpers.c + * @file /magma/check/magma/servers/imap/imap_check_helpers.c * * @brief Functions used to test IMAP connections over a network connection. * @@ -8,20 +9,19 @@ #include "magma_check.h" /** - * Calls client_read_line on a client until it finds a line matching "<token> OK" + * @brief Calls client_read_line on a client until it finds a line matching "<token> OK" * * @param client The client to read from (which should be connected to an IMAP server). * @param token The unique token that identifies the current imap command dialogue. * * @return Returns true if client_read_line was successful until the last line was found. - * specified in num and there was no error. Otherwise returns false. + * specified in num and there was no error. Otherwise returns false. */ -bool_t check_imap_client_read_lines_to_end(client_t *client, chr_t *token) { +bool_t check_imap_client_read_lines_to_end(client_t *client, chr_t *tag) { bool_t outcome = false; - stringer_t *last_line = st_merge("ss", NULLER(token), NULLER(" OK")); + stringer_t *last_line = st_merge("ss", NULLER(tag), NULLER(" OK")); - // TODO: Add a timeout mechanism to client_read_line and update this function. while (!outcome && client_read_line(client) > 0) { if (!st_cmp_cs_starts(&client->line, last_line)) outcome = true; } @@ -35,8 +35,8 @@ bool_t check_imap_network_basic_sthread(stringer_t *errmsg, uint32_t port) { client_t *client = NULL; // Check the initial response. - if (!(client = client_connect("localhost", port)) || client_read_line(client) <= 0 || (client->status != 1) || - st_cmp_cs_starts(&(client->line), NULLER("* OK"))) { + if (!(client = client_connect("localhost", port)) || !net_set_timeout(client->sockd, 20, 20) || + client_read_line(client) <= 0 || (client->status != 1) || st_cmp_cs_starts(&(client->line), NULLER("* OK"))) { st_sprint(errmsg, "Failed to connect with the IMAP server."); client_close(client); @@ -70,10 +70,19 @@ bool_t check_imap_network_basic_sthread(stringer_t *errmsg, uint32_t port) { return false; } - // Test the LOGOUT command. - else if (client_print(client, "A4 LOGOUT\r\n") <= 0 || !check_imap_client_read_lines_to_end(client, "A4") || + // Test the CLOSE command. + else if (client_print(client, "A4 CLOSE\r\n") <= 0 || !check_imap_client_read_lines_to_end(client, "A4") || client_status(client) != 1 || st_cmp_cs_starts(&(client->line), NULLER("A4 OK"))) { + st_sprint(errmsg, "Failed to return a successful state after CLOSE."); + client_close(client); + return false; + } + + // Test the LOGOUT command. + else if (client_print(client, "A5 LOGOUT\r\n") <= 0 || !check_imap_client_read_lines_to_end(client, "A5") || + client_status(client) != 1 || st_cmp_cs_starts(&(client->line), NULLER("A5 OK"))) { + st_sprint(errmsg, "Failed to return a successful state after LOGOUT."); client_close(client); return false; diff --git a/check/magma/servers/pop/pop_check.c b/check/magma/servers/pop/pop_check.c index d70ff331..613eb2d6 100644 --- a/check/magma/servers/pop/pop_check.c +++ b/check/magma/servers/pop/pop_check.c @@ -6,22 +6,42 @@ #include "magma_check.h" -START_TEST (check_pop_network_basic_s) { +START_TEST (check_pop_network_basic_tcp_s) { log_disable(); bool_t outcome = true; - server_t *server = NULL; + server_t *tcp = NULL; stringer_t *errmsg = MANAGEDBUF(1024); - if (!(server = servers_get_by_protocol(POP, false))) { - st_sprint(errmsg, "No POP servers were configured and available for testing."); + if (status() && !(tcp = servers_get_by_protocol(POP, false))) { + st_sprint(errmsg, "No POP servers were configured to support TCP connections."); outcome = false; } - else if (status()) { - outcome = check_pop_network_basic_sthread(errmsg, server->network.port); + else if (status() && check_pop_network_basic_sthread(errmsg, tcp->network.port, false)) { + outcome = false; + } + + log_test("POP / NETWORK / BASIC / TCP / SINGLE THREADED:", errmsg); + ck_assert_msg(outcome, st_char_get(errmsg)); +} +END_TEST + +START_TEST (check_pop_network_basic_tls_s) { + + log_disable(); + bool_t outcome = true; + server_t *tls = NULL; + stringer_t *errmsg = MANAGEDBUF(1024); + + if (status() && !(tls = servers_get_by_protocol(POP, true))) { + st_sprint(errmsg, "No POP servers were configured to support TLS connections."); + outcome = false; + } + else if (status() && !check_pop_network_basic_sthread(errmsg, tls->network.port, true)) { + outcome = false; } - log_test("POP / NETWORK / BASIC / SINGLE THREADED:", errmsg); + log_test("POP / NETWORK / BASIC / TLS / SINGLE THREADED:", errmsg); ck_assert_msg(outcome, st_char_get(errmsg)); } END_TEST @@ -30,7 +50,8 @@ Suite * suite_check_pop(void) { Suite *s = suite_create("\tPOP"); - suite_check_testcase(s, "POP", "POP Network Basic/S", check_pop_network_basic_s); + suite_check_testcase(s, "POP", "POP Network Basic / TCP/S", check_pop_network_basic_tcp_s); + suite_check_testcase(s, "POP", "POP Network Basic / TLS/S", check_pop_network_basic_tls_s); return s; } diff --git a/check/magma/servers/pop/pop_check.h b/check/magma/servers/pop/pop_check.h index ba55f524..dbc09d6c 100644 --- a/check/magma/servers/pop/pop_check.h +++ b/check/magma/servers/pop/pop_check.h @@ -9,7 +9,7 @@ /// pop_check_network.c bool_t check_pop_client_read_lines_to_end(client_t *client); -bool_t check_pop_network_basic_sthread(stringer_t *errmsg, uint32_t port); +bool_t check_pop_network_basic_sthread(stringer_t *errmsg, uint32_t port, bool_t secure); /// pop_check.c Suite * suite_check_pop(void); diff --git a/check/magma/servers/pop/pop_check_network.c b/check/magma/servers/pop/pop_check_network.c index 48c1dc58..16d84fc3 100644 --- a/check/magma/servers/pop/pop_check_network.c +++ b/check/magma/servers/pop/pop_check_network.c @@ -16,20 +16,20 @@ */ bool_t check_pop_client_read_lines_to_end(client_t *client) { - // TODO: Add a timeout mechanism to client_read_line and update this function. while (client_read_line(client) > 0) { if (!st_cmp_cs_eq(&(client->line), NULLER(".\r\n"))) return true; } return false; } -bool_t check_pop_network_basic_sthread(stringer_t *errmsg, uint32_t port) { +bool_t check_pop_network_basic_sthread(stringer_t *errmsg, uint32_t port, bool_t secure) { client_t *client = NULL; // Connect the client. - if (!(client = client_connect("localhost", port)) || client_read_line(client) <= 0 || - client_status(client) != 1 || st_cmp_cs_starts(&(client->line), NULLER("+OK"))) { + if (!(client = client_connect("localhost", port)) || (secure && client_secure(client)) || + !net_set_timeout(client->sockd, 20, 20) || client_read_line(client) <= 0 || client_status(client) != 1 || + st_cmp_cs_starts(&(client->line), NULLER("+OK"))) { st_sprint(errmsg, "Failed to connect with the POP server."); client_close(client); @@ -37,8 +37,8 @@ bool_t check_pop_network_basic_sthread(stringer_t *errmsg, uint32_t port) { } // Test the USER command. - if (client_print(client, "USER princess\r\n") <= 0 || client_read_line(client) <= 0 || - client_status(client) != 1 || st_cmp_cs_starts(&(client->line), NULLER("+OK"))) { + else if (client_print(client, "USER princess\r\n") != 15 || client_read_line(client) <= 0 || + client_status(client) != 1 || st_cmp_cs_starts(&(client->line), NULLER("+OK"))) { st_sprint(errmsg, "Failed to return a successful state after USER."); client_close(client); @@ -46,8 +46,8 @@ bool_t check_pop_network_basic_sthread(stringer_t *errmsg, uint32_t port) { } // Test the PASS command. - if (client_print(client, "PASS password\r\n") <= 0 || client_read_line(client) <= 0 || - client_status(client) != 1 || st_cmp_cs_starts(&(client->line), NULLER("+OK"))) { + else if (client_print(client, "PASS password\r\n") != 15 || client_read_line(client) <= 0 || + client_status(client) != 1 || st_cmp_cs_starts(&(client->line), NULLER("+OK"))) { st_sprint(errmsg, "Failed to return a successful state after USER."); client_close(client); @@ -55,8 +55,8 @@ bool_t check_pop_network_basic_sthread(stringer_t *errmsg, uint32_t port) { } // Test the LIST command. - if (client_print(client, "LIST\r\n") <= 0 || !check_pop_client_read_lines_to_end(client) || - client_status(client) != 1) { + else if (client_print(client, "LIST\r\n") != 6 || !check_pop_client_read_lines_to_end(client) || + client_status(client) != 1) { st_sprint(errmsg, "Failed to return a successful state after LIST."); client_close(client); @@ -64,8 +64,8 @@ bool_t check_pop_network_basic_sthread(stringer_t *errmsg, uint32_t port) { } // Test the RETR command. - if (client_print(client, "RETR 1\r\n") <= 0 || !check_pop_client_read_lines_to_end(client) || - client_status(client) != 1) { + else if (client_print(client, "RETR 1\r\n") != 8 || !check_pop_client_read_lines_to_end(client) || + client_status(client) != 1) { st_sprint(errmsg, "Failed to return a successful state after RETR."); client_close(client); @@ -73,8 +73,8 @@ bool_t check_pop_network_basic_sthread(stringer_t *errmsg, uint32_t port) { } // Test the DELE command. - if (client_print(client, "DELE 1\r\n") <= 0 || client_read_line(client) <= 0 || client_status(client) != 1 || - st_cmp_cs_starts(&(client->line), NULLER("+OK"))) { + else if (client_print(client, "DELE 1\r\n") != 8 || client_read_line(client) <= 0 || client_status(client) != 1 || + st_cmp_cs_starts(&(client->line), NULLER("+OK"))) { st_sprint(errmsg, "Failed to return a successful state after DELE."); client_close(client); @@ -82,8 +82,8 @@ bool_t check_pop_network_basic_sthread(stringer_t *errmsg, uint32_t port) { } // Test the QUIT command. - if (client_print(client, "QUIT 1\r\n") <= 0 || client_read_line(client) <= 0 || client_status(client) != 1 || - st_cmp_cs_starts(&(client->line), NULLER("+OK"))) { + else if (client_print(client, "QUIT 1\r\n") <= 0 || client_read_line(client) <= 0 || client_status(client) != 1 || + st_cmp_cs_starts(&(client->line), NULLER("+OK"))) { st_sprint(errmsg, "Failed to return a successful state after QUIT."); client_close(client); diff --git a/check/magma/servers/smtp/checkers_check.c b/check/magma/servers/smtp/checkers_check.c index aa9c3fbc..2fb00adf 100644 --- a/check/magma/servers/smtp/checkers_check.c +++ b/check/magma/servers/smtp/checkers_check.c @@ -90,63 +90,62 @@ bool_t check_smtp_checkers_greylist_sthread(stringer_t *errmsg) { bool_t check_smtp_checkers_regex_sthread(stringer_t *errmsg) { + struct re_pattern_buffer regbuff; + mm_wipe(®buff, sizeof(struct re_pattern_buffer)); chr_t *expressions[] = { - "85\\.155\\.166\\.44\\.dyn\\.user\\.ono\\.com\\", - "http\\:\\/\\/www\\.yourlogcabins\\.com\\", - "82\\.128\\.33\\.161\\]\\ \\(port\\=2680\\ helo\\=User\\)\\ by\\ 4\\.mx\\.freenet\\.de\\ with\\ esmtpa\\ \\(ID\\ danielch", - "\\[41\\.222\\.192\\.83\\]\\ \\(helo\\=User\\)\\ by\\ server45\\.serverparksteenbergen\\.nl\\ with\\ esmtpa\\ \\(Exim\\", - "server45\\.serverparksteenbergen\\.nl\\ \\(77\\.243\\.231\\.36", - "LU7FDZ\\", - "fresh\\", - "redbox\\", - "tiger\\", - "Vicodin\\ fling\\ medications\\", - "noreply\\@message\\.myspace\\.com\\", - "Subscription\\", - "Unsubscribe\\", - "http\\:\\/\\/www\\.ameba\\.jp\\/\\", - "lblanchard\\@ocean\\-institute\\.org\\", - "email\\.tcm\\.com\\", - "\\*\\.tcm\\.com\\", - "tcm\\.com\\", - "Turner\\ Classic\\", - "Turner\\ Classic\\", + "\\/\\^From\\:\\.\\*\\(gmxmagazin\\\\\\@gmx\\\\\\-gmbh\\\\\\.de\\|mailings\\\\\\@gmx\\\\\\-gmbh\\\\\\.de\\|\\.\\*gmxred\\.\\*\\|elsa", + "online836745\\@telkomsa\\.net\\,\\ adbplc78\\@gmail\\.com\\,\\ inside\\.all\\@uol\\.com\\.br\\,\\ a2\\-shark1\\.uol\\", + "ashley\\ madison\\ married\\ affair\\ wives\\ pleasurable\\ gal\\ nsa\\ fun\\ dangerous\\ risky\\ scared\\ cost\\", + "verify\\ credit\\ free\\ account\\ anonymous\\ info\\ revealing\\ phone\\ picture\\ Whats\\ whats\\ wats\\ wat\\", + "2\\.128\\.128\\.1\\]\\ \\(port\\=680\\ helo\\=User\\)\\ by\\ 4\\.mx\\.freenet\\.us\\ with\\ esmtpa\\ \\(ID\\ ch", + "\\[41\\.222\\.192\\.83\\]\\ \\(helo\\=User\\)\\ by\\ server45\\.serverpark\\.nl\\ with\\ esmtpa\\ \\(Exim\\", "LOTTERY\\ WINNER\\ WINNING\\ BLACKHOLED\\ SCAM\\ LUCKY\\ \\/LUCKY\\ WINNER\\/\\ WON\\ ONLINE\\", "lucky\\+winner\\ CONGRATULATION\\ CONGRATULATIONS\\ DEAL\\ CHEAP\\ WIN\\", - "Linda\\ Blanchard\\", - "online836745\\@telkomsa\\.net\\,\\ adbplc78\\@gmail\\.com\\,\\ inside\\.all\\@uol\\.com\\.br\\,\\ a2\\-shark1\\.uol\\", - "bra\\", - "\\ an\\", - "MortgageAssistance411\\", - "weekend\\ cash\\", + "\\\"Woodcraft\\\"\\ \\<Woodcraft\\@woodcraftnews\\.com\\>\\", + "server45\\.serverfarm\\.nl\\ \\(17\\.31\\.21\\.69", + "Receipt\\ for\\ your\\ PayPal\\ payment\\ to\\", + "45\\.155\\.169\\.44\\.dyn\\.user\\.com\\", + "Stop\\ paying\\ off\\ the\\ tobacco\\", + "noreply\\@message\\.myspace\\.com\\", + "http\\:\\/\\/www\\.ameba\\.com\\/\\", + "http\\:\\/\\/www\\.mycabin\\.com\\", + "Vicodin\\ fling\\ medications\\", + "obama\\@tax\\-institute\\.org\\", + "Start\\ on\\ a\\ new\\-career\\", + "R\\-help\\ Digest\\,\\ Vol\\", + "The\\ Pimsleur\\ Approach\\", "Manner\\ Shultz\\ Group\\", - "Finance\\ Depat\\.\\", - "LUMINEERS\\", + "Gordon\\,\\ you\\ have\\", + "Cambridge\\ SoundWorks\\", + "MortgageAssistance411\\", "Auto\\ Price\\ Finder\\", + "Mailer\\'s\\ graphics\\", + "Finance\\ Depat\\.\\", "flight\\ simulator\\", - "The\\ Pimsleur\\ Approach\\", - "Start\\ on\\ a\\ new\\-career\\", + "email\\.tcm\\.com\\", + "Linda\\ Blanchard\\", "World\\ Marketing\\", - "Stop\\ paying\\ off\\ the\\ tobacco\\", - "Mailer\\'s\\ graphics\\", + "Turner\\ Classic\\", + "\\*\\.tcm\\.com\\", "Dr\\.Oz\\-watch\\", - "verify\\ credit\\ free\\ account\\ anonymous\\ info\\ revealing\\ phone\\ picture\\ Whats\\ whats\\ wats\\ wat\\", "Do\\ you\\ know\\", - "Gordon\\,\\ you\\ have\\", - "rich\\", "Do\\ you\\ know\\", - "R\\-help\\ Digest\\,\\ Vol\\", - "\\\"Woodcraft\\\"\\ \\<Woodcraft\\@woodcraftnews\\.com\\>\\", - "Cambridge\\ SoundWorks\\", - "IZUALO\\", - "Receipt\\ for\\ your\\ PayPal\\ payment\\ to\\", - "ashley\\ madison\\ married\\ affair\\ wives\\ pleasurable\\ gal\\ nsa\\ fun\\ dangerous\\ risky\\ scared\\ cost\\", + "weekend\\ cash\\", + "Subscription\\", "eLoan\\ Plus\\", + "Unsubscribe\\", + "tcm\\.com\\", + "LUMINEERS\\", "cafepress\\", - "\\/\\^From\\:\\.\\*\\(gmxmagazin\\\\\\@gmx\\\\\\-gmbh\\\\\\.de\\|mailings\\\\\\@gmx\\\\\\-gmbh\\\\\\.de\\|\\.\\*gmxred\\.\\*\\|elsa" + "LU7FDZ\\", + "redbox\\", + "IZUALO\\", + "fresh\\", + "tiger\\", + "\\ an\\", + "rich\\", + "bra\\" }; - struct re_pattern_buffer regbuff; - mm_wipe(®buff, sizeof(struct re_pattern_buffer)); for (size_t i = 0; i < (sizeof(expressions)/sizeof(chr_t*)); i++) { if (regcomp(®buff, expressions[i], REG_ICASE) != 0) { diff --git a/check/magma/servers/smtp/smtp_check.c b/check/magma/servers/smtp/smtp_check.c index 6d1a1267..cd5b169b 100644 --- a/check/magma/servers/smtp/smtp_check.c +++ b/check/magma/servers/smtp/smtp_check.c @@ -59,11 +59,11 @@ START_TEST (check_smtp_checkers_filters_s) { bool_t outcome = true; stringer_t *errmsg = MANAGEDBUF(1024); - if (status()) outcome = check_smtp_checkers_regex_sthread(errmsg); - if (status() && outcome) outcome = check_smtp_checkers_filters_sthread(errmsg, SMTP_FILTER_ACTION_DELETE, -2); - if (status() && outcome) outcome = check_smtp_checkers_filters_sthread(errmsg, SMTP_FILTER_ACTION_MOVE, 2); - if (status() && outcome) outcome = check_smtp_checkers_filters_sthread(errmsg, SMTP_FILTER_ACTION_LABEL, 3); - if (status() && outcome) outcome = check_smtp_checkers_filters_sthread(errmsg, SMTP_FILTER_ACTION_MARK_READ, 4); + if (status()) outcome = check_smtp_checkers_regex_sthread(errmsg); + if (status() && outcome) outcome = check_smtp_checkers_filters_sthread(errmsg, SMTP_FILTER_ACTION_DELETE, -2); + if (status() && outcome) outcome = check_smtp_checkers_filters_sthread(errmsg, SMTP_FILTER_ACTION_MOVE, 2); + if (status() && outcome) outcome = check_smtp_checkers_filters_sthread(errmsg, SMTP_FILTER_ACTION_LABEL, 3); + if (status() && outcome) outcome = check_smtp_checkers_filters_sthread(errmsg, SMTP_FILTER_ACTION_MARK_READ, 4); log_test("SMTP / CHECKERS / FILTERS / SINGLE THREADED:", errmsg); ck_assert_msg(outcome, st_char_get(errmsg)); diff --git a/check/magma/servers/smtp/smtp_check_network.c b/check/magma/servers/smtp/smtp_check_network.c index 4c6b9b42..30ecb66a 100644 --- a/check/magma/servers/smtp/smtp_check_network.c +++ b/check/magma/servers/smtp/smtp_check_network.c @@ -18,7 +18,6 @@ */ bool_t check_smtp_client_read_line_to_end(client_t *client) { - // TODO: Add a timeout mechanism to client_read_line and update this function. while (client_read_line(client) > 0) { if (pl_char_get(client->line)[3] == ' ') return true; } @@ -31,8 +30,8 @@ bool_t check_smtp_network_simple_sthread(stringer_t *errmsg, uint32_t port) { client_t *client = NULL; // Test the connect banner. - if (!(client = client_connect("localhost", port)) || client_read_line(client) <= 0 || - client_status(client) != 1 || st_cmp_cs_starts(&(client->line), NULLER("220")) || + if (!(client = client_connect("localhost", port)) || !net_set_timeout(client->sockd, 20, 20) || + client_read_line(client) <= 0 || client_status(client) != 1 || st_cmp_cs_starts(&(client->line), NULLER("220")) || !st_search_cs(&(client->line), NULLER(" ESMTP "), &location)) { st_sprint(errmsg, "Failed to connect with the SMTP server."); diff --git a/lib/.cproject b/lib/.cproject index 4ce0714b..faf7ff38 100644 --- a/lib/.cproject +++ b/lib/.cproject @@ -64,7 +64,7 @@ </toolChain> </folderInfo> <sourceEntries> - <entry excluding="sources|check/|archives/|logs/|objects/|patches/|sources/clamav/libclamav/c++/llvm/|sources/mysql/vio/viosocket.c|sources/mysql/libmysql_r/viosocket.c|sources/clamav/win32/|sources/mysql/include/config-win.h|sources/mysql/include/config-netware.h|local/include/spf2/|sources/spf2/" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> + <entry excluding="check/|archives/|logs/|objects/|patches/|sources/clamav/libclamav/c++/llvm/|sources/mysql/vio/viosocket.c|sources/mysql/libmysql_r/viosocket.c|sources/clamav/win32/|sources/mysql/include/config-win.h|sources/mysql/include/config-netware.h|local/include/spf2/|sources/spf2/" flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name=""/> </sourceEntries> </configuration> </storageModule> diff --git a/src/core/host/host.h b/src/core/host/host.h index 1a74b8bb..d1e296d7 100644 --- a/src/core/host/host.h +++ b/src/core/host/host.h @@ -52,6 +52,20 @@ #define MAGMA_PROC_PATH "/proc" +typedef struct { + sa_family_t family; + union { + struct in_addr ip4; + struct in6_addr ip6; + void *ip; + }; +} ip_t; + +typedef struct { + uint32_t mask; + ip_t address; +} subnet_t; + // The spool_start function uses a for loop to validate the spool directory tree. If additional spool locations are enumerated, make sure that function is updated. enum { MAGMA_SPOOL_BASE = 0, @@ -98,7 +112,6 @@ const chr_t * color_yellow_intense(void); const chr_t * color_yellow_intense_bold(void); const chr_t * color_yellow_underline(void); - /// files.c stringer_t * file_load(char *name); int_t file_read(char *name, stringer_t *output); @@ -107,6 +120,12 @@ bool_t file_accessible(const chr_t *path); bool_t file_readwritable(const chr_t *path); bool_t file_world_accessible(const chr_t *path); +/// tcp.c +ip_t * tcp_addr_ip(int sockd, ip_t *output); +stringer_t * tcp_addr_st(int sockd, stringer_t *output); +int_t tcp_error(int error); +int_t tcp_status(int sockd); + /// host.c stringer_t * host_platform(stringer_t *output); stringer_t * host_version(stringer_t *output); diff --git a/src/core/host/tcp.c b/src/core/host/tcp.c new file mode 100644 index 00000000..ee9e6345 --- /dev/null +++ b/src/core/host/tcp.c @@ -0,0 +1,103 @@ + +/** + * @file /magma/src/core/host/tcp.c + * + * @brief Generic fuctions for interaction with TCP/IP socket connections. + * + */ + +#include "magma.h" + +/** + * @brief Determine whether the error is a permanent/fatal failure, or a transient error. + * @return return 0 for errors we should ignore, and -1 for permanent/fatal failures. + */ +int_t tcp_error(int error) { + + int_t result = 0; + + // These error numbers indicate a network connection issue. + if (error == EPIPE || error == ENETDOWN || error == ENETUNREACH || error == ENETUNREACH || + error == ENETRESET || error == ECONNABORTED || error == ECONNRESET || error == ENOTCONN || + error == ESHUTDOWN || error == ETIMEDOUT) { + result = -1; + } + + // Otherwise if recv returns a negative number, we log the result, while assuming the connection is still valid. Note + // that on some platforms EWOULDBLOCK and EAGAIN are technically identical, but we explicitly check for both so + // logic remains compatible with systems where they differ. + else if (result < 0 && (error != EWOULDBLOCK || error != EAGAIN || error != EINTR)) { + log_pedantic("Ambiguous TCP error code. { errno = %i / error = %s }", + error, strerror_r(error, MEMORYBUF(1024), 1024)); + } + + return result; +} + +/** + * @brief Determine whether the socket connection provided by sockd is still valid. + * @param sockd The socket connection being checked. + * @return return 0 for valid connections + */ +int_t tcp_status(int sockd) { + + struct stat info; + int result = 0, holder = 0, error = 0; + + errno = 0; + + if (sockd < 0 || fstat(sockd, &info) || !S_ISSOCK(info.st_mode)) { + result = -1; + } + + // In theory the PEEK flag will prevent this call from altering the socket buffer state, while the NOSIGNAL flag + // should cause it to return EPIPE if the connection is no longer valid. + else if ((holder = recv(sockd, MANAGEDBUF(64), 64, MSG_PEEK | MSG_DONTWAIT | MSG_NOSIGNAL)) <= 0) { + + // Duplicate the errno so the log pedantic statement below doesn't accidently overwrite it. + error = errno; + + // Determine whether the error number is fatal. + result = tcp_error(error); + } + + log_pedantic("tcp status = %i / errno = %i", result, error); + + return result; +} + +ip_t * tcp_addr_ip(int sockd, ip_t *output) { + + ip_t *result = NULL; + socklen_t len = sizeof(struct sockaddr_in6); + struct sockaddr *address = MEMORYBUF(sizeof(struct sockaddr_in6)); + + // Extract the socket structure. + if (getpeername(sockd, address, &len)) { + return NULL; + } + + // Allocate memory for the result, if necessary. + else if (!(result = output) && !(result = mm_alloc(sizeof(ip_t)))) { + return NULL; + } + + // Classify and copy to the IP information. + else if (len == sizeof(struct sockaddr_in6) && ((struct sockaddr_in6 *)address)->sin6_family == AF_INET6) { + mm_copy(&(result->ip6), &(((struct sockaddr_in6 *)address)->sin6_addr), sizeof(struct in6_addr)); + result->family = AF_INET6; + } + else if (len == sizeof(struct sockaddr_in) && ((struct sockaddr_in *)address)->sin_family == AF_INET) { + mm_copy(&(result->ip4), &(((struct sockaddr_in *)address)->sin_addr), sizeof(struct in_addr)); + result->family = AF_INET; + } + + return result; +} + +stringer_t * tcp_addr_st(int sockd, stringer_t *output) { + + ip_t ip; + + return ip_presentation(tcp_addr_ip(sockd, &ip), output); +} diff --git a/src/core/strings/strings.h b/src/core/strings/strings.h index bf36de5f..3e0418bb 100644 --- a/src/core/strings/strings.h +++ b/src/core/strings/strings.h @@ -124,7 +124,6 @@ uchr_t * st_uchar_get(stringer_t *s); void st_wipe(stringer_t *s); stringer_t * st_set(stringer_t *s, uint8_t set, size_t len); - // Creation/Destruction void st_free(stringer_t *s); //void st_cleanup(stringer_t *s); diff --git a/src/network/addresses.c b/src/network/addresses.c index a3909d6c..1fec8454 100644 --- a/src/network/addresses.c +++ b/src/network/addresses.c @@ -208,6 +208,7 @@ stringer_t * ip_presentation(ip_t *address, stringer_t *output) { if (!output || st_valid_tracked(opts)) { st_length_set(result, ns_length_get(st_char_get(result))); } + return result; } @@ -393,7 +394,7 @@ ip_t * con_addr(connection_t *con, ip_t *output) { socklen_t len = sizeof(struct sockaddr_in6); if (!(result = output) && !(result = mm_alloc(sizeof(ip_t)))) { - log_pedantic("The output buffer memory allocation request failed. {requested = %zu}", sizeof(ip_t)); + log_pedantic("The output buffer memory allocation request failed. { requested = %zu }", sizeof(ip_t)); return NULL; } @@ -407,7 +408,7 @@ ip_t * con_addr(connection_t *con, ip_t *output) { return NULL; } - // Classify and copy to the result. + // Classify and copy to the IP information. else if (len == sizeof(struct sockaddr_in6) && ((struct sockaddr_in6 *)address)->sin6_family == AF_INET6) { mm_copy(&(result->ip6), &(((struct sockaddr_in6 *)address)->sin6_addr), sizeof(struct in6_addr)); result->family = AF_INET6; diff --git a/src/network/clients.c b/src/network/clients.c index 090e5944..bb01ba59 100644 --- a/src/network/clients.c +++ b/src/network/clients.c @@ -7,11 +7,10 @@ #include "magma.h" - /** * @brief Get the status of a network client. * @param client a pointer to the network client object to be queried. - * @return -1 on error state, 0 for unknown status, or 1 if connected. + * @return -1 on network errors, 0 for an unknown status, 1 for connected, and 2 for a graceful shutdown. */ int_t client_status(client_t *client) { @@ -21,11 +20,25 @@ int_t client_status(client_t *client) { result = client->status; } + + // If the status is positive, and tls_status returns 0, we use the existing status state. + if (client && client->tls && client->status >= 0 && !tls_status(client->tls)) { + result = client->status; + } + // If the status is positive, and tcp_status returns 0, we use the existing status state. + else if (client && client->sockd != -1 && client->status >= 0 && !tcp_status(client->sockd)) { + result = client->status; + } + // We return -1 if the status is already negative, or connection is otherwise invalid. + else { + result = client->status = -1; + } + return result; } /** - * @brief Establish an ssl connection with a network client instance. + * @brief Establish an TLS connection with a network client instance. * @param client a pointer to the network client object to have its transport security upgraded. * @return -1 on failure or 0 on success. */ diff --git a/src/network/connections.c b/src/network/connections.c index af79933d..51f4853a 100644 --- a/src/network/connections.c +++ b/src/network/connections.c @@ -27,15 +27,24 @@ int_t con_secure(connection_t *con) { /** * @brief Return the status of a specified connection. * @param con the input client connection. - * @return -1 on error, 0 for unknown status, 1 for connected, or 2 if the socket has been shutting down. + * @return -1 on network errors, 0 for an unknown status, 1 for connected, and 2 for a graceful shutdown. */ int_t con_status(connection_t *con) { int_t result = -1; - if (con && con->network.sockd != -1) { + // If the status is positive, and tls_status returns 0, we use the existing status state. + if (con && con->network.tls && con->network.status >= 0 && !tls_status(con->network.tls)) { result = con->network.status; } + // If the status is positive, and tcp_status returns 0, we use the existing status state. + else if (con && con->network.sockd >= -1 && con->network.status >= 0 && !tcp_status(con->network.sockd)) { + result = con->network.status; + } + // We return -1 if the status is already negative, or connection is otherwise invalid. + else { + result = con->network.status = -1; + } return result; } @@ -120,6 +129,7 @@ void con_destroy(connection_t *con) { } st_cleanup(con->network.buffer); + mm_cleanup(con->network.reverse.ip); st_cleanup(con->network.reverse.domain); mutex_destroy(&(con->lock)); mm_free(con); @@ -201,8 +211,9 @@ connection_t * con_init(int cond, server_t *server) { return NULL; } - con->network.sockd = cond; con->server = server; + con->network.sockd = cond; + con->network.reverse.ip = tcp_addr_ip(cond, NULL); con_increment_refs(con); return con; diff --git a/src/network/network.h b/src/network/network.h index 54e276d3..73d3ceed 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -5,29 +5,7 @@ * @brief The types and functions for abstracting access to network functionality. */ -#if defined(GET_IP_T_DEFINITION) || !defined(MAGMA_NETWORK_H) - #ifndef GOT_IP_T_DEFINITION - typedef struct { - sa_family_t family; - union { - struct in_addr ip4; - struct in6_addr ip6; - void *ip; - }; - } ip_t; - - typedef struct { - uint32_t mask; - ip_t address; - } subnet_t; - #define GOT_IP_T_DEFINITION - #endif -#endif - - -#ifdef GET_IP_T_DEFINITION -#undef GET_IP_T_DEFINITION -#elif !defined(MAGMA_NETWORK_H) +#ifndef MAGMA_NETWORK_H #define MAGMA_NETWORK_H #include "meta.h" @@ -85,6 +63,7 @@ typedef struct { stringer_t *buffer; /* The connection buffer. */ struct { + ip_t *ip; int_t status; stringer_t *domain; } reverse; diff --git a/src/network/read.c b/src/network/read.c index 223e18ec..f259eb62 100644 --- a/src/network/read.c +++ b/src/network/read.c @@ -22,10 +22,11 @@ */ int64_t con_read_line(connection_t *con, bool_t block) { - ssize_t bytes; + int_t counter = 0; + ssize_t bytes = 0; bool_t line = false; - if (!con || con->network.sockd == -1) { + if (!con || con->network.sockd == -1 || con_status(con) < 0) { if (con) con->network.status = -1; return -1; } @@ -66,30 +67,23 @@ int64_t con_read_line(connection_t *con, bool_t block) { if (con->network.tls) { // If bytes is zero or below and the library isn't asking for another read, then an error occurred. - bytes = ssl_read(con->network.tls, st_char_get(con->network.buffer) + st_length_get(con->network.buffer), + bytes = tls_read(con->network.tls, st_char_get(con->network.buffer) + st_length_get(con->network.buffer), st_avail_get(con->network.buffer) - st_length_get(con->network.buffer), block); - if (bytes <= 0 && bytes != SSL_ERROR_WANT_READ) { + if (bytes < 0) { con->network.status = -1; return -1; } - else if (bytes <= 0) { - return 0; - } } else { bytes = recv(con->network.sockd, st_char_get(con->network.buffer) + st_length_get(con->network.buffer), st_avail_get(con->network.buffer) - st_length_get(con->network.buffer), (block ? 0 : MSG_DONTWAIT)); // Check for errors on non-SSL reads in the traditional way. - if (bytes <= 0 && errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) { + if (bytes <= 0 && tcp_status(con->network.sockd)) { con->network.status = -1; return -1; } - else if (!bytes) { - con->network.status = 2; - return -2; - } } @@ -102,7 +96,7 @@ int64_t con_read_line(connection_t *con, bool_t block) { line = true; } - } while (!line && st_length_get(con->network.buffer) != st_avail_get(con->network.buffer)); + } while (!line && block && counter++ < 128 && st_length_get(con->network.buffer) != st_avail_get(con->network.buffer) && status()); if (st_length_get(con->network.buffer) > 0) { con->network.status = 1; @@ -120,10 +114,11 @@ int64_t con_read_line(connection_t *con, bool_t block) { */ int64_t con_read(connection_t *con) { - ssize_t bytes; - bool_t blocking; + int_t counter = 0; + ssize_t bytes = 0; + bool_t blocking = true; - if (!con || con->network.sockd == -1) { + if (!con || con->network.sockd == -1 || con_status(con) < 0) { if (con) con->network.status = -1; return -1; } @@ -147,7 +142,9 @@ int64_t con_read(connection_t *con) { // Clear the line buffer. con->network.line = pl_null(); - return st_length_get(con->network.buffer); + if (st_length_get(con->network.buffer)) { + return st_length_get(con->network.buffer); + } } // Otherwise reset the buffer and line lengths to zero. @@ -163,10 +160,10 @@ int64_t con_read(connection_t *con) { // Read bytes off the network. If data is already in the buffer this should be a non-blocking read operation so we can // return the already buffered data without delay. if (con->network.tls) { - bytes = ssl_read(con->network.tls, st_char_get(con->network.buffer) + st_length_get(con->network.buffer), - st_avail_get(con->network.buffer) - st_length_get(con->network.buffer), blocking); + bytes = tls_read(con->network.tls, st_char_get(con->network.buffer) + st_length_get(con->network.buffer), + st_avail_get(con->network.buffer) - st_length_get(con->network.buffer), true); - if (!bytes && tls_status(con->network.tls)) { + if (bytes < 0) { con->network.status = -1; return -1; } @@ -175,20 +172,17 @@ int64_t con_read(connection_t *con) { bytes = recv(con->network.sockd, st_char_get(con->network.buffer) + st_length_get(con->network.buffer), st_avail_get(con->network.buffer) - st_length_get(con->network.buffer), blocking ? 0 : MSG_DONTWAIT); - if (bytes < 0 && errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) { - con->network.status = -1; - return -1; - } + if (bytes <= 0 && tcp_status(con->network.sockd)) { + con->network.status = -1; + return -1; + } } if (bytes > 0) { st_length_set(con->network.buffer, st_length_get(con->network.buffer) + bytes); - // Or break out of the loop because we've been shutdown. - } else if (!bytes) { - break; } - } while (blocking && !st_length_get(con->network.buffer)); + } while (blocking && counter++ < 128 && !st_length_get(con->network.buffer) && status()); // If there is data in the buffer process it. Otherwise if the buffer is empty and the connection appears to be closed // (as indicated by a return value of 0), then return -1 to let the caller know the connection is dead. @@ -203,7 +197,6 @@ int64_t con_read(connection_t *con) { return st_length_get(con->network.buffer); } -// LOW: If the buffer already contains a complete line and the socket status indicates a connection we should still perform a non-blocking read. /** * @brief Read a line of input from a network client session. * @@ -247,7 +240,7 @@ int64_t client_read_line(client_t *client) { // Read bytes off the network. Skip past any existing data in the buffer. if (client->tls) { - bytes = ssl_read(client->tls, st_char_get(client->buffer) + st_length_get(client->buffer), st_avail_get(client->buffer) - st_length_get(client->buffer), true); + bytes = tls_read(client->tls, st_char_get(client->buffer) + st_length_get(client->buffer), st_avail_get(client->buffer) - st_length_get(client->buffer), true); sslerr = SSL_get_error_d(client->tls, bytes); } else { @@ -331,7 +324,7 @@ int64_t client_read(client_t *client) { // Read bytes off the network. If data is already in the buffer this should be a non-blocking read operation so we can // return the already buffered data without delay. if (client->tls) { - bytes = ssl_read(client->tls, st_char_get(client->buffer) + st_length_get(client->buffer), st_avail_get(client->buffer) - st_length_get(client->buffer), blocking); + bytes = tls_read(client->tls, st_char_get(client->buffer) + st_length_get(client->buffer), st_avail_get(client->buffer) - st_length_get(client->buffer), blocking); sslerr = SSL_get_error_d(client->tls, bytes); } else { diff --git a/src/network/write.c b/src/network/write.c index c14e02a4..7964df04 100644 --- a/src/network/write.c +++ b/src/network/write.c @@ -22,11 +22,10 @@ */ int64_t con_write_bl(connection_t *con, char *block, size_t length) { + int_t counter = 0; ssize_t written, position = 0; - int sslerr = -1; - if (!con || con->network.sockd == -1) { - if (con) con->network.status = -1; + if (!con || con->network.sockd == -1 || con_status(con) < 0) { return -1; } else if (!block || !length) { @@ -34,54 +33,36 @@ int64_t con_write_bl(connection_t *con, char *block, size_t length) { return 0; } - // Loop until bytes have been written to the socket. + // Loop until all of the bytes have been sent to the client. do { if (con->network.tls) { - written = ssl_write(con->network.tls, block + position, length); - sslerr = SSL_get_error_d(con->network.tls, written); - } - else { - written = send(con->network.sockd, block + position, length, 0); - } - // Check for errors on SSL writes. - if (con->network.tls) { + written = tls_write(con->network.tls, block + position, length); - // If 0 bytes were written, and it wasn't related to a shutdown, or if < 0 was returned and there was no more data waiting to be written, it's an error. - if ((!written && sslerr != SSL_ERROR_NONE && sslerr != SSL_ERROR_ZERO_RETURN) || ((written < 0) && sslerr != SSL_ERROR_WANT_WRITE)) { + // Check for errors on SSL writes. + if (written < 0) { con->network.status = -1; return -1; } - else if (!written) { - con->network.status = 2; - return -2; - } - // Check for errors on non-SSL writes in the traditional way. } - else if (written < 0) { + else { + written = send(con->network.sockd, block + position, length, 0); - if (errno == ECONNRESET) { - con->network.status = 2; - return -2; - } - else if (errno != EAGAIN) { + // Check for errors on non-SSL writes in the traditional way. + if (written <= 0 && tcp_status(con->network.sockd)) { con->network.status = -1; return -1; } - } + // Handle progress by advancing our position tracker. if (written > 0) { length -= written; position += written; } - } while (length); - -#ifdef MAGMA_PEDANTIC - if (written < 0) log_pedantic("write = %li {%s}", written, strerror_r(errno, bufptr, buflen)); -#endif + } while (length && counter++ < 128 && status()); if (written > 0) { con->network.status = 1; @@ -211,7 +192,7 @@ int64_t client_write(client_t *client, stringer_t *s) { do { if (client->tls) { - written = ssl_write(client->tls, block + position, length); + written = tls_write(client->tls, block + position, length); sslerr = SSL_get_error_d(client->tls, written); } else { diff --git a/src/objects/sessions/sessions.c b/src/objects/sessions/sessions.c index 974ba14f..488366a3 100644 --- a/src/objects/sessions/sessions.c +++ b/src/objects/sessions/sessions.c @@ -385,7 +385,8 @@ session_t *sess_create(connection_t *con, stringer_t *path, stringer_t *applicat log_pedantic("Unable to initialize reference lock for new user session."); mm_free(output); return NULL; - } else if (!(output->compositions = inx_alloc(M_INX_LINKED, &sess_release_composition))) { + } + else if (!(output->compositions = inx_alloc(M_INX_LINKED, &sess_release_composition))) { log_pedantic("Unable to allocate space for user session's compositions."); mm_free(output); return NULL; diff --git a/src/providers/checkers/checkers.h b/src/providers/checkers/checkers.h index 70d2c279..4efe1976 100644 --- a/src/providers/checkers/checkers.h +++ b/src/providers/checkers/checkers.h @@ -8,9 +8,6 @@ #ifndef MAGMA_PROVIDERS_CHECKERS_H #define MAGMA_PROVIDERS_CHECKERS_H -#define GET_IP_T_DEFINITION -#include "network/network.h" - #define IP_RANDOMIZER_POOL 1024 #define IP_RANDOMIZER_PUSH_MIN 4 @@ -32,7 +29,6 @@ enum { FOREIGN = 1 }; - /// clamav.c bool_t lib_load_clamav(void); bool_t virus_start(void); @@ -67,7 +63,7 @@ chr_t * lib_version_dspam(void); bool_t lib_load_spf(void); const chr_t * lib_version_spf(void); bool_t spf_start(void); -int_t spf_check(ip_t *ip, stringer_t *helo, stringer_t *mailfrom); +int_t spf_check(void *ip, stringer_t *helo, stringer_t *mailfrom); void spf_stop(void); #endif diff --git a/src/providers/checkers/spf.c b/src/providers/checkers/spf.c index 5e798ddb..4e4875cd 100644 --- a/src/providers/checkers/spf.c +++ b/src/providers/checkers/spf.c @@ -109,10 +109,11 @@ void spf_stop(void) { * TODO: We really need to change these return values to account for 0 * @return -2 on spf check fail, -1 on other failure, and 1 on spf pass. */ -int_t spf_check(ip_t *ip, stringer_t *helo, stringer_t *mailfrom) { +int_t spf_check(void *ip, stringer_t *helo, stringer_t *mailfrom) { uint32_t item; placer_t domain; + ip_t *addr = ip; #ifdef MAGMA_SPF_DEBUG SPF_reason_t reason; #endif @@ -144,9 +145,9 @@ int_t spf_check(ip_t *ip, stringer_t *helo, stringer_t *mailfrom) { } // Set the IP address for the request. - else if ((ip->family == AF_INET && (error = SPF_request_set_ipv4_d(spf_request, ip->ip4)) != SPF_E_SUCCESS) || - (ip->family == AF_INET6 && (error = SPF_request_set_ipv6_d(spf_request, ip->ip6)) != SPF_E_SUCCESS) || - (ip->family != AF_INET && ip->family != AF_INET6)) { + else if ((addr->family == AF_INET && (error = SPF_request_set_ipv4_d(spf_request, addr->ip4)) != SPF_E_SUCCESS) || + (addr->family == AF_INET6 && (error = SPF_request_set_ipv6_d(spf_request, addr->ip6)) != SPF_E_SUCCESS) || + (addr->family != AF_INET && addr->family != AF_INET6)) { SPF_request_free_d(spf_request); pool_release(spf_pool, item); log_pedantic("SPF context configuration error. { error = %s }", SPF_strerror_d(error)); diff --git a/src/providers/cryptography/cryptography.h b/src/providers/cryptography/cryptography.h index b25b270c..aaae679a 100644 --- a/src/providers/cryptography/cryptography.h +++ b/src/providers/cryptography/cryptography.h @@ -86,6 +86,13 @@ typedef void * cipher_t; typedef char * cryptex_t; typedef stringer_t scramble_t; +// Allows the inclusion of this PRIME header without having to include the OpenSSL headers. +#ifdef HEADER_OPENSSL_TYPES_H +typedef SSL TLS; +#else +typedef void TLS; +#endif + /// ciphers.c cipher_t * cipher_id(int_t id); cipher_t * cipher_name(stringer_t *name); @@ -167,15 +174,15 @@ void ssl_thread_stop(void); bool_t ssl_verify_privkey(const char *keyfile); /// tls.c -int ssl_print(SSL *ssl, const char *format, va_list args); -int ssl_read(SSL *ssl, void *buffer, int length, bool_t block); +int tls_print(TLS *tls, const char *format, va_list args); +int tls_read(TLS *tls, void *buffer, int length, bool_t block); bool_t ssl_server_create(void *server, uint_t security_level); void ssl_server_destroy(void *server); -int ssl_write(SSL *ssl, const void *buffer, int length); +int tls_write(TLS *tls, const void *buffer, int length); void * tls_client_alloc(int_t sockd); -void tls_free(SSL *ssl); -SSL * tls_server_alloc(void *server, int sockd, int flags); -int tls_status(SSL *ssl); +void tls_free(TLS *tls); +TLS * tls_server_alloc(void *server, int sockd, int flags); +int tls_status(TLS *tls); /// random.c bool_t rand_start(void); diff --git a/src/providers/cryptography/openssl.c b/src/providers/cryptography/openssl.c index 9e57e939..4b6c1ee8 100644 --- a/src/providers/cryptography/openssl.c +++ b/src/providers/cryptography/openssl.c @@ -81,7 +81,8 @@ bool_t lib_load_openssl(void) { M_BIND(ERR_put_error), M_BIND(EVP_aes_256_gcm), M_BIND(EC_KEY_get_conv_form), M_BIND(EC_KEY_set_conv_form), M_BIND(BN_bn2mpi), M_BIND(BN_mpi2bn), M_BIND(BN_bn2dec), M_BIND(EC_POINT_mul), M_BIND(BN_CTX_new), M_BIND(BN_CTX_start), M_BIND(BN_CTX_free), M_BIND(EC_POINT_cmp), M_BIND(BN_cmp), M_BIND(ED25519_keypair), M_BIND(ED25519_sign), M_BIND(ED25519_verify), M_BIND(ED25519_keypair_from_seed), - M_BIND(CRYPTO_set_mem_functions), M_BIND(CRYPTO_set_locked_mem_functions), M_BIND(DH_check) + M_BIND(CRYPTO_set_mem_functions), M_BIND(CRYPTO_set_locked_mem_functions), M_BIND(DH_check), M_BIND(SSL_get_read_ahead), + M_BIND(SSL_set_read_ahead), M_BIND(SSL_peek) }; if (!lib_symbols(sizeof(openssl) / sizeof(symbol_t), openssl)) { diff --git a/src/providers/cryptography/tls.c b/src/providers/cryptography/tls.c index 1549ef00..fcc3e27c 100644 --- a/src/providers/cryptography/tls.c +++ b/src/providers/cryptography/tls.c @@ -8,13 +8,13 @@ #include "magma.h" /** - * @brief Setup an SSL CTX for a server. + * @brief Setup an TLS CTX for a server. * * @note The server is passed as a void pointer because the provider layer doesn't comprehend protocol specific * server instances. * - * @param server_t the SSL context will be assigned to the provided server context. - * @param security_level an integer which will be used to control how the SSL context is configured: + * @param server_t the TLS context will be assigned to the provided server context. + * @param security_level an integer which will be used to control how the TLS context is configured: * 0 = accept any type of SSL or TLS protocol version, and offer broad cipher support. * 1 = require TLSv1 and above, refuse SSLv2 and SSLv3 connections, use any reasonably secure cipher. * (reccomended) 2 = require TLSv1 and above, refuse SSLv2 and SSLv3 connections, only use ciphers which provide forward secrecy. @@ -83,6 +83,10 @@ bool_t ssl_server_create(void *server, uint_t security_level) { log_critical("Could not enable the automatic, default selection of the strongest curve."); return false; } + else if (SSL_CTX_ctrl_d(local->tls.context, SSL_CTRL_MODE, SSL_MODE_AUTO_RETRY, NULL) != SSL_MODE_AUTO_RETRY) { + log_critical("Could not enable automatic retry for read and write operations."); + return false; + } // High security connections get 4096 bit prime when generating a DH session key. else if (magma.iface.cryptography.dhparams_rotate && magma.iface.cryptography.dhparams_large_keys) { @@ -107,7 +111,7 @@ bool_t ssl_server_create(void *server, uint_t security_level) { } /** - * @brief Destroy an SSL context associated with a server. + * @brief Destroy an TLS context associated with a server. * @param server the server to be deactivated. * @return This function returns no value. */ @@ -127,14 +131,14 @@ void ssl_server_destroy(void *server) { } /** - * @brief Create an SSL session for a file descriptor, and accept the client TLS/SSL handshake. + * @brief Create a TLS session for a file descriptor, and accept the client TLS/SSL handshake. * @see SSL_accept() * @see BIO_new_socket() * @param server a server object which contains the underlying SSL context. * @param sockd the file descriptor of the TCP connection to be made SSL-ready. * @param flags passed to BIO_new_socket(), determines whether the socket is shut down when the BIO is freed. */ -SSL * tls_server_alloc(void *server, int sockd, int flags) { +TLS * tls_server_alloc(void *server, int sockd, int flags) { SSL *tls; BIO *bio; @@ -144,18 +148,20 @@ SSL * tls_server_alloc(void *server, int sockd, int flags) { #ifdef MAGMA_PEDANTIC if (!local) { log_pedantic("Passed a NULL server pointer."); - } else if (!local->tls.context) { + } + else if (!local->tls.context) { log_pedantic("Passed a NULL SSL context pointer."); } else if (sockd < 0) { - log_pedantic("Passed an invalid socket. {sockd = %i}", sockd); + log_pedantic("Passed an invalid socket. { sockd = %i }", sockd); } #endif if (!local || !local->tls.context || sockd < 0) { return NULL; - } else if (!(tls = SSL_new_d(local->tls.context)) || !(bio = BIO_new_socket_d(sockd, flags))) { - log_pedantic("SSL/BIO allocation error. {error = %s}", ssl_error_string(MEMORYBUF(256), 256)); + } + else if (!(tls = SSL_new_d(local->tls.context)) || !(bio = BIO_new_socket_d(sockd, flags))) { + log_pedantic("TLS/BIO allocation error. { error = %s }", ssl_error_string(MEMORYBUF(256), 256)); if (tls) { SSL_free_d(tls); @@ -167,7 +173,7 @@ SSL * tls_server_alloc(void *server, int sockd, int flags) { SSL_set_bio_d(tls, bio, bio); if ((result = SSL_accept_d(tls)) != 1) { - log_pedantic("SSL accept error. { accept = %i / error = %s }", result, ssl_error_string(MEMORYBUF(256), 256)); + log_pedantic("TLS accept error. { accept = %i / error = %s }", result, ssl_error_string(MEMORYBUF(256), 256)); SSL_free_d(tls); return NULL; } @@ -176,7 +182,7 @@ SSL * tls_server_alloc(void *server, int sockd, int flags) { } /** - * @brief Establish an SSL client wrapper around a socket descriptor. + * @brief Establish an TLS client wrapper around a socket descriptor. * @param sockd the file descriptor of the socket to have its transport security level upgraded. * @return NULL on failure or a pointer to the SSL handle of the file descriptor if SSL negotiation was successful. */ @@ -188,11 +194,11 @@ void * tls_client_alloc(int_t sockd) { long options = (SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_MODE_AUTO_RETRY); if (!(ctx = SSL_CTX_new_d(SSLv23_client_method_d()))) { - log_pedantic("Could not create a valid SSL context. {error = %s}", ssl_error_string(MEMORYBUF(512), 512)); + log_pedantic("Could not create a valid TLS context. { error = %s }", ssl_error_string(MEMORYBUF(512), 512)); return NULL; } else if ((SSL_CTX_ctrl_d(ctx, SSL_CTRL_OPTIONS, options, NULL) & options) != options) { - log_pedantic("Could set the options mask on the SSL context. {error = %s}", ssl_error_string(MEMORYBUF(512), 512)); + log_pedantic("Could set the options mask on the TLS context. { error = %s }", ssl_error_string(MEMORYBUF(512), 512)); SSL_CTX_free_d(ctx); return NULL; } @@ -206,12 +212,12 @@ void * tls_client_alloc(int_t sockd) { // SSL_CTX_set_verify(result.context, mode, cert_verify_callback); else if (!(result = SSL_new_d(ctx))) { - log_pedantic("Could create the SSL client connection context. {error = %s}", ssl_error_string(MEMORYBUF(512), 512)); + log_pedantic("Could create the TLS client connection context. { error = %s }", ssl_error_string(MEMORYBUF(512), 512)); SSL_CTX_free_d(ctx); return NULL; } else if (!(bio = BIO_new_socket_d(sockd, BIO_NOCLOSE))) { - log_pedantic("Could not create the SSL client BIO context. {error = %s}", ssl_error_string(MEMORYBUF(512), 512)); + log_pedantic("Could not create the TLS client BIO context. { error = %s }", ssl_error_string(MEMORYBUF(512), 512)); SSL_free_d(result); SSL_CTX_free_d(ctx); return NULL; @@ -221,7 +227,7 @@ void * tls_client_alloc(int_t sockd) { SSL_CTX_free_d(ctx); if (SSL_connect_d(result) != 1) { - log_pedantic("Could not establish an SSL connection with the client. {error = %s}", ssl_error_string(MEMORYBUF(512), 512)); + log_pedantic("Could not establish an TLS connection with the client. { error = %s }", ssl_error_string(MEMORYBUF(512), 512)); SSL_free_d(result); return NULL; } @@ -230,182 +236,260 @@ void * tls_client_alloc(int_t sockd) { } /** - * @brief Shutdown and free an SSL connection. - * @param ssl the SSL connection to be shut down. + * @brief Shutdown and free an TLS connection. + * @param TLS the TLS connection to be shut down. * @return This function returns no value. */ -void tls_free(SSL *ssl) { +void tls_free(TLS *tls) { #ifdef MAGMA_PEDANTIC - if (!ssl) { - log_pedantic("Passed a NULL SSL pointer."); + if (!tls) { + log_pedantic("Passed an invalid TLS pointer."); } #endif - if (ssl) { + if (tls) { ERR_remove_thread_state_d(0); - SSL_shutdown_d(ssl); - SSL_free_d(ssl); + SSL_shutdown_d(tls); + SSL_free_d(tls); } return; } /** - * @brief Checks whether an SSL tunnel has been shut down or not. + * @brief Checks whether a TLS connection has been shut down or not. * @see SSL_get_shutdown() - * @param ssl the SSL connection to be shut down. + * @param tls the TLS connection to be shut down. * @return 0 if the connection is alive and well, or SSL_SENT_SHUTDOWN/SSL_RECEIVED_SHUTDOWN */ -int tls_status(SSL *ssl) { +int tls_status(TLS *tls) { int_t result = 0; - if (ssl) { - result = SSL_get_shutdown_d(ssl); + + // Look for a clean shut down of the TLS connection. + if (tls) { + result = SSL_get_shutdown_d(tls); } + return result; } - /** - * @brief Read data from an SSL connection. - * @param ssl the SSL connection from which the data will be read. + * @brief Read data from a TLS connection. + * @param tls the TLS connection from which the data will be read. * @param buffer a pointer to the buffer where the read data will be stored. * @param length the length, in bytes, of the amount of data to be read. * @param block a boolean variable specifying whether the read operation should block. * @return -1 on failure, 0 if the connection has been closed, or the number of bytes read from the connection on success. */ -int ssl_read(SSL *ssl, void *buffer, int length, bool_t block) { +int tls_read(TLS *tls, void *buffer, int length, bool_t block) { - int result = 0, sslerr; + long popped = 0; + chr_t *message = MEMORYBUF(1024); + int result = 0, err = 0, local = 0; + stringer_t *merged = NULL, *ip = NULL; - if (!ssl || !buffer || !length) { - log_pedantic("Passed invalid data for the SSL_read function."); + errno = 0; + ERR_clear_error_d(); + + if (!tls || !buffer || !length) { + log_pedantic("Passed invalid parameters for a call to the TLS read function."); return -1; } - if (!block) { + // In the future, when we switch to OpenSSL v1.1.0 around the year ~2032, we should look into using an + // asynchronous SSL context to facilitate our non-blocking read/write operations. Look to configure the + // context using SSL_CTX_set_mode(SSL_CTX *ctx, long mode) with mode set to SSL_MODE_ASYNC. + else if (!block && (result = SSL_read_d(tls, buffer, length)) <= 0) { + + // Consult SSL_peek / SSL_want / SSL_get_read_ahead / SSL_set_read_ahead - // In the future, when we switch to OpenSSL v1.1.0 around the year ~2032, we should look into using an - // asynchronous SSL context to facilitate our non-blocking read/write operations. Look to configure the - // context using SSL_CTX_set_mode(SSL_CTX *ctx, long mode) with mode set to SSL_MODE_ASYNC. + log_pedantic("Non-blocking TLS read calls aren't fully implemented yet."); - // Method One. - //int fd = SSL_get_rfd_d(ssl); - //if (recv(fd, buffer, length, MSG_PEEK | MSG_DONTWAIT) != 0) { - result = SSL_read_d(ssl, buffer, length); - if (result <= 0 && (sslerr = SSL_get_error_d(ssl, result)) != SSL_ERROR_WANT_READ) { - ERR_error_string_n_d(sslerr, bufptr, buflen); - log_pedantic("SSL_read error. { result = %i / error = %s }", result, bufptr); + if ((err = SSL_get_error_d(tls, result)) != SSL_ERROR_WANT_READ) { + if ((local = errno) != 0) { + ip = tcp_addr_st(SSL_get_fd_d(tls), MANAGEDBUF(256)); + log_pedantic("TLS read error. { ip = %.*s / result = %i / errno = %i / message = %s }", + st_length_int(ip), st_char_get(ip), result, local, strerror_r(local, message, 1024)); + result = tcp_error(local); } else if (result < 0) { - result = 0; + ip = tcp_addr_st(SSL_get_fd_d(tls), MANAGEDBUF(256)); + log_pedantic("TLS read error. { ip = %.*s / result = %i / errno = 0 }", st_length_int(ip), st_char_get(ip), result); + } + else { + + // Loop through and create an error message using all of the errors in the TLS error queue. + while ((popped = ERR_get_error_d())) { + ERR_error_string_n_d(err, message, 1024); + merged = st_append_opts(1024, merged, st_quick(MANAGEDBUF(256), "%s( error = %li / message = %s ) ", + (merged ? "/ " : ""), popped, message)); + } + + if (!merged) { + ip = tcp_addr_st(SSL_get_fd_d(tls), MANAGEDBUF(256)); + log_pedantic("TLS read error. { ip = %.*s / result = %i / error = %i / message = NULL }", + st_length_int(ip), st_char_get(ip), result, err); + } + else { + ip = tcp_addr_st(SSL_get_fd_d(tls), MANAGEDBUF(256)); + log_pedantic("TLS read error. { ip = %.*s / result = %i / error = %i / message = %.*s }", + st_length_int(ip), st_char_get(ip), result, err, st_length_int(merged), st_char_get(merged)); + st_free(merged); + } } - //} - //else { - // result = 0; - //} - - // Method two. -// if (SSL_want_d(ssl) == SSL_READING || SSL_pending_d(ssl) > 0) { -// result = SSL_read_d(ssl, buffer, length); -// } - - // If our socket is blocking and we get this error it's not really an error.. it just means we need to try again. - - - } - else if (block && (result = SSL_read_d(ssl, buffer, length)) <= 0) { - if ((sslerr = SSL_get_error_d(ssl, result)) != SSL_ERROR_WANT_READ) { - ERR_error_string_n_d(sslerr, bufptr, buflen); - log_pedantic("SSL_read error. { result = %i / error = %s }", result, bufptr); - } - else { - result = 0; } - } - else if (result < 0) { - log_pedantic("SSL connection cleanly shutdown."); + else if (block && (result = SSL_read_d(tls, buffer, length)) <= 0) { + if ((err = SSL_get_error_d(tls, result)) != SSL_ERROR_WANT_READ) { + if ((local = errno) != 0) { + ip = tcp_addr_st(SSL_get_fd_d(tls), MANAGEDBUF(256)); + log_pedantic("TLS read error. { ip = %.*s / result = %i / errno = %i / message = %s }", + st_length_int(ip), st_char_get(ip), result, local, strerror_r(local, message, 1024)); + result = tcp_error(local); + } + else if (result < 0) { + ip = tcp_addr_st(SSL_get_fd_d(tls), MANAGEDBUF(256)); + log_pedantic("TLS read error. { ip = %.*s / result = %i / errno = 0 }", + st_length_int(ip), st_char_get(ip), result); + } + else { + + // Loop through and create an error message using all of the errors in the TLS error queue. + while ((popped = ERR_get_error_d())) { + ERR_error_string_n_d(err, message, 1024); + merged = st_append_opts(1024, merged, st_quick(MANAGEDBUF(256), "%s( error = %li / message = %s ) ", (merged ? "/ " : ""), popped, message)); + } + + if (!merged) { + ip = tcp_addr_st(SSL_get_fd_d(tls), MANAGEDBUF(256)); + log_pedantic("TLS read error. { ip = %.*s / result = %i / error = %i / message = NULL }", + st_length_int(ip), st_char_get(ip), result, err); + } + else { + log_pedantic("TLS read error. { ip = %.*s / result = %i / error = %i / message = %.*s }", + st_length_int(ip), st_char_get(ip), result, err, st_length_int(merged), st_char_get(merged)); + st_free(merged); + } + } + } } return result; } /** - * @brief Write data to an open SSL connection. - * @param ssl the SSL connection to which the data will be written. + * @brief Write data to an open TLS connection. + * @param tls the TLS connection to which the data will be written. * @param buffer a pointer to the buffer containing the data to be written. * @param length the length, in bytes, of the data to be written. - * @return -1 on error, or the number of bytes written to the SSL connection. + * @return -1 on error, or the number of bytes written to the TLS connection. */ -int ssl_write(SSL *ssl, const void *buffer, int length) { +int tls_write(TLS *tls, const void *buffer, int length) { + + long popped = 0; + chr_t *message = MEMORYBUF(1024); + int result = -1, err = 0, local = 0; + stringer_t *merged = NULL, *ip = NULL; - int result = -1, sslerr; + errno = 0; + ERR_clear_error_d(); - if (!ssl || !buffer || !length) { - log_pedantic("Passed invalid data for the SSL_write function."); + if (!tls || !buffer || !length) { + log_pedantic("Passed invalid parameters for a call to the TLS write function."); return -1; } - else if ((result = SSL_write_d(ssl, buffer, length)) <= 0) { + else if ((result = SSL_write_d(tls, buffer, length)) <= 0) { - // This might not really be an "error" ... - if ((sslerr = SSL_get_error_d(ssl, result)) != SSL_ERROR_WANT_WRITE) { - log_pedantic("SSL_write error. {sslerr = %i / error = %s}", sslerr, ssl_error_string(bufptr, buflen)); + if ((err = SSL_get_error_d(tls, result)) != SSL_ERROR_WANT_WRITE) { + if ((local = errno) != 0) { + ip = tcp_addr_st(SSL_get_fd_d(tls), MANAGEDBUF(256)); + log_pedantic("TLS write error. { ip = %.*s / result = %i / errno = %i / message = %s }", + st_length_int(ip), st_char_get(ip), result, local, strerror_r(local, message, 1024)); + result = tcp_error(local); + } + else if (result < 0) { + ip = tcp_addr_st(SSL_get_fd_d(tls), MANAGEDBUF(256)); + log_pedantic("TLS write error. { ip = %.*s / result = %i / errno = 0 }", st_length_int(ip), st_char_get(ip), result); + } + else { + + // Loop through and create an error message using all of the errors in the TLS error queue. + while ((popped = ERR_get_error_d())) { + ERR_error_string_n_d(err, message, 1024); + merged = st_append_opts(1024, merged, st_quick(MANAGEDBUF(256), "%s( error = %li / message = %s ) ", (merged ? "/ " : ""), popped, message)); + } + + if (!merged) { + ip = tcp_addr_st(SSL_get_fd_d(tls), MANAGEDBUF(256)); + log_pedantic("TLS write error. { ip = %.*s / result = %i / error = %i / message = NULL }", st_length_int(ip), st_char_get(ip), result, err); + } + else { + ip = tcp_addr_st(SSL_get_fd_d(tls), MANAGEDBUF(256)); + log_pedantic("TLS write error. { ip = %.*s / result = %i / error = %i / message = %.*s }", + st_length_int(ip), st_char_get(ip), result, err, st_length_int(merged), st_char_get(merged)); + st_free(merged); + } + } } - - } - else if (!result) { - log_pedantic("SSL connection cleanly shutdown."); } return result; } /** - * @brief Write formatted data to an SSL connection. - * @param ssl the SSL connection to which the data will be written. + * @brief Write formatted data to an TLS connection. + * @param tls the SSL connection to which the data will be written. * @param format a format string specifying the data to be written to the SSL connection. * @param va_list a variable argument list containing the data parameters associated with the format string. * @return -1 on error, or the number of bytes written to the SSL connection. */ -int ssl_print(SSL *ssl, const char *format, va_list args) { +int tls_print(SSL *tls, const char *format, va_list args) { - int result; - char *buffer; - size_t length; va_list copy; + size_t length = 0; + chr_t *buffer = NULL; + int result = 0, counter = 0, bytes = 0, position = 0; - if (!ssl) { - return -1; - } else if (!format) { - return 0; + if (!tls || !format) { + return (!tls ? -1 : 0); } - // We need to make a copy of the arguments list in case we need to run vsnprintf twice. + // We need to make a copy of the arguments so we can run vsnprintf twice. va_copy(copy, args); - // See if the string will fit inside the standard thread buffer. - if ((length = vsnprintf(bufptr, buflen, format, args)) < buflen) { - va_end(copy); - return ssl_write(ssl, bufptr, length); + // Calculate the length of the result so we can allocate an appropriately sized buffer. + length = vsnprintf(NULL, 0, format, copy); + va_end(copy); + + // Make sure the print function succeeded. + if (length <= 0) { + return length; } // Allocate a large enough buffer. else if (!(buffer = mm_alloc(length + 1))) { - va_end(copy); return -1; } - // Try building the string again. - else if (vsnprintf(buffer, length, format, copy) != length) { + // Build the output string. + else if (vsnprintf(buffer, length + 1, format, args) != length) { mm_free(buffer); - va_end(copy); return -1; } - result = ssl_write(ssl, buffer, length); - va_end(copy); + do { + + if ((bytes = tls_write(tls, buffer + position, length - position)) < 0) { + mm_free(buffer); + return -1; + } + + position += bytes; + + } while (position != length && counter++ < 128 && status()); + mm_free(buffer); return result; diff --git a/src/providers/dime/common/crypto.c b/src/providers/dime/common/crypto.c index e1aeceff..35fbc794 100644 --- a/src/providers/dime/common/crypto.c +++ b/src/providers/dime/common/crypto.c @@ -5,6 +5,8 @@ #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/rand.h> +#include <arpa/inet.h> +#include <sys/socket.h> #include "core/core.h" #include "providers/symbols.h" diff --git a/src/providers/dime/signet/keys.c b/src/providers/dime/signet/keys.c index 25454df1..8eab36dd 100644 --- a/src/providers/dime/signet/keys.c +++ b/src/providers/dime/signet/keys.c @@ -1,4 +1,5 @@ - +#include <arpa/inet.h> +#include <sys/socket.h> #include "core/core.h" #include "dime/common/misc.h" diff --git a/src/providers/symbols.c b/src/providers/symbols.c index 69e31e56..4327b8f3 100644 --- a/src/providers/symbols.c +++ b/src/providers/symbols.c @@ -228,6 +228,7 @@ BIO * (*SSL_get_wbio_d)(const SSL * ssl) = NULL; void (*EC_GROUP_free_d)(EC_GROUP *group) = NULL; void (*EC_POINT_free_d)(EC_POINT *point) = NULL; void (*X509_STORE_free_d)(X509_STORE *v) = NULL; +int (*SSL_get_read_ahead_d)(const SSL *s) = NULL; int (*DH_check_d)(const DH *dh, int *ret) = NULL; int (*EC_KEY_generate_key_d)(EC_KEY *key) = NULL; void (*ASN1_STRING_TABLE_cleanup_d)(void) = NULL; @@ -243,6 +244,7 @@ void (*OCSP_REQUEST_free_d)(OCSP_REQUEST *a) = NULL; const EVP_CIPHER * (*EVP_aes_256_gcm_d)(void) = NULL; int (*SSL_peek_d)(SSL *ssl,void *buf,int num) = NULL; const EVP_CIPHER * (*EVP_aes_256_cbc_d)(void) = NULL; +void (*SSL_set_read_ahead_d)(SSL *s, int yes) = NULL; EVP_CIPHER_CTX * (*EVP_CIPHER_CTX_new_d)(void) = NULL; int (*OCSP_check_nonce_d)(void *req, void *bs) = NULL; int (*X509_verify_cert_d)(X509_STORE_CTX *ctx) = NULL; diff --git a/src/providers/symbols.h b/src/providers/symbols.h index 0f07a283..2fe4da9c 100644 --- a/src/providers/symbols.h +++ b/src/providers/symbols.h @@ -328,6 +328,7 @@ extern BIO * (*SSL_get_wbio_d)(const SSL * ssl); extern void (*EC_GROUP_free_d)(EC_GROUP *group); extern void (*EC_POINT_free_d)(EC_POINT *point); extern void (*X509_STORE_free_d)(X509_STORE *v); +extern int (*SSL_get_read_ahead_d)(const SSL *s); extern int (*DH_check_d)(const DH *dh, int *ret); extern int (*EC_KEY_generate_key_d)(EC_KEY *key); extern void (*ASN1_STRING_TABLE_cleanup_d)(void); @@ -343,6 +344,7 @@ extern void (*OCSP_REQUEST_free_d)(OCSP_REQUEST *a); extern const EVP_CIPHER * (*EVP_aes_256_gcm_d)(void); extern const EVP_CIPHER * (*EVP_aes_256_cbc_d)(void); extern int (*SSL_peek_d)(SSL *ssl,void *buf,int num); +extern void (*SSL_set_read_ahead_d)(SSL *s, int yes); extern EVP_CIPHER_CTX * (*EVP_CIPHER_CTX_new_d)(void); extern int (*OCSP_check_nonce_d)(void *req, void *bs); extern int (*X509_verify_cert_d)(X509_STORE_CTX *ctx); diff --git a/src/servers/imap/fetch.c b/src/servers/imap/fetch.c index 2768f7b4..cfad6bcf 100644 --- a/src/servers/imap/fetch.c +++ b/src/servers/imap/fetch.c @@ -1360,9 +1360,11 @@ inx_t * imap_narrow_messages(inx_t *messages, uint64_t selected, stringer_t *ran // Parse the end. if (!pl_empty(end_token) && *(pl_char_get(end_token)) == '*') { asterisk = 1; - } else if (pl_empty(end_token)) { + } + else if (pl_empty(end_token)) { end = start; - } else { + } + else { if (!uint64_conv_st(&end_token, &end)) { log_pedantic("range parsing error = %.*s", st_length_int(range), st_char_get(range)); diff --git a/src/servers/imap/imap.c b/src/servers/imap/imap.c index 23403cf8..080cac18 100644 --- a/src/servers/imap/imap.c +++ b/src/servers/imap/imap.c @@ -1825,7 +1825,7 @@ void imap_capability(connection_t *con) { } /** - * @brief The main imap entry point for all inbound client connections, as dispatched by the generic protocol handler (display + * @brief The main IMAP entry point for all inbound client connections, as dispatched by the generic protocol handler (display * banner greeting). * * @param con a pointer to the connection object of the newly connected client. diff --git a/src/servers/imap/parse.c b/src/servers/imap/parse.c index e0e41cfc..73704333 100644 --- a/src/servers/imap/parse.c +++ b/src/servers/imap/parse.c @@ -119,6 +119,7 @@ imap_arguments_t * imap_get_ar_ar(imap_arguments_t *array, size_t element) { return result; } + /* // Mailbox names can contain base64 data that needs to be decoded. Base64 data is inside the &- characters. stringer_t * imap_string_to_mailbox(stringer_t *string) { @@ -138,7 +139,6 @@ stringer_t * imap_mailbox_to_string(stringer_t *mailbox) { */ - /** * @brief Extract the contents of an atomic string and advance the position of the parser stream. * @note This function scans a string, expecting printable ASCII characters until it encounters a space, \r, \n, (, or [. diff --git a/src/servers/smtp/smtp.c b/src/servers/smtp/smtp.c index 48b40ac6..c36c7c0f 100644 --- a/src/servers/smtp/smtp.c +++ b/src/servers/smtp/smtp.c @@ -193,10 +193,10 @@ void smtp_quit(connection_t *con) { if (con_status(con) == 2) { con_write_bl(con, "451 Unexpected connection shutdown detected. Goodbye.\r\n", 55); } - else if (con_status(con) >= 0) { + else if (con_status(con) > 0) { con_write_bl(con, "221 BYE\r\n", 9); } - else { + else if (con_status(con) == 0){ con_write_bl(con, "421 Network connection failure.\r\n", 33); } @@ -832,7 +832,7 @@ int_t smtp_data_read(connection_t *con, stringer_t **message) { buffer = st_char_get(result); read = con_read(con); - while (checker != 4 && status() && read > 0) { + while (checker != 4 && read > 0 && status()) { // Setup the stream. stream = st_data_get(con->network.buffer); @@ -937,7 +937,7 @@ int_t smtp_data_read(connection_t *con, stringer_t **message) { } // The server is shutting down or the client disconnected. - if (status() != 1) { + if (!status()) { st_free(result); return -3; } |