diff --git a/src/protohttp.c b/src/protohttp.c index 8523e66..e5f0d08 100644 --- a/src/protohttp.c +++ b/src/protohttp.c @@ -38,30 +38,6 @@ #include #include -typedef struct protohttp_ctx protohttp_ctx_t; - -struct protohttp_ctx { - unsigned int seen_req_header : 1; /* 0 until request header complete */ - unsigned int seen_resp_header : 1; /* 0 until response hdr complete */ - unsigned int sent_http_conn_close : 1; /* 0 until Conn: close sent */ - unsigned int ocsp_denied : 1; /* 1 if OCSP was denied */ - - /* log strings from HTTP request */ - char *http_method; - char *http_uri; - char *http_host; - char *http_content_type; - - /* log strings from HTTP response */ - char *http_status_code; - char *http_status_text; - char *http_content_length; - - unsigned int not_valid : 1; /* 1 if cannot find HTTP on first line */ - unsigned int seen_keyword_count; - long long unsigned int seen_bytes; -}; - static void NONNULL(1) protohttp_log_connect(pxy_conn_ctx_t *ctx) { @@ -527,9 +503,11 @@ protohttp_validate_method(char *method return -1; } -static int NONNULL(1,2) -protohttp_validate(protohttp_ctx_t *http_ctx, pxy_conn_ctx_t *ctx) +int +protohttp_validate(pxy_conn_ctx_t *ctx) { + protohttp_ctx_t *http_ctx = ctx->protoctx->arg; + if (http_ctx->not_valid) { log_finest("Not http, validation failed previously"); return -1; @@ -629,7 +607,7 @@ protohttp_bev_readcb_src(struct bufferevent *bev, pxy_conn_ctx_t *ctx) } if (ctx->spec->opts->validate_proto && !ctx->protoctx->is_valid) { - if (protohttp_validate(http_ctx, ctx) == -1) { + if (protohttp_validate(ctx) == -1) { evbuffer_add(bufferevent_get_output(bev), proto_error, strlen(proto_error)); ctx->sent_protoerror_msg = 1; pxy_discard_inbuf(bev); @@ -787,8 +765,7 @@ protohttp_bev_readcb_dst(struct bufferevent *bev, pxy_conn_ctx_t *ctx) static void NONNULL(1) protohttp_bev_readcb_srvdst(UNUSED struct bufferevent *bev, UNUSED pxy_conn_ctx_t *ctx) { - log_err_printf("readcb called on srvdst\n"); - log_fine("readcb called on srvdst"); + log_err_level(LOG_ERR, "readcb called on srvdst"); } static void NONNULL(1) diff --git a/src/protohttp.h b/src/protohttp.h index 88d7b49..395b09d 100644 --- a/src/protohttp.h +++ b/src/protohttp.h @@ -32,6 +32,30 @@ #include "pxyconn.h" +typedef struct protohttp_ctx { + unsigned int seen_req_header : 1; /* 0 until request header complete */ + unsigned int seen_resp_header : 1; /* 0 until response hdr complete */ + unsigned int sent_http_conn_close : 1; /* 0 until Conn: close sent */ + unsigned int ocsp_denied : 1; /* 1 if OCSP was denied */ + + /* log strings from HTTP request */ + char *http_method; + char *http_uri; + char *http_host; + char *http_content_type; + + /* log strings from HTTP response */ + char *http_status_code; + char *http_status_text; + char *http_content_length; + + unsigned int not_valid : 1; /* 1 if cannot find HTTP on first line */ + unsigned int seen_keyword_count; + long long unsigned int seen_bytes; +} protohttp_ctx_t; + +int protohttp_validate(pxy_conn_ctx_t *) NONNULL(1); + protocol_t protohttp_setup(pxy_conn_ctx_t *) NONNULL(1); protocol_t protohttps_setup(pxy_conn_ctx_t *) NONNULL(1); diff --git a/src/protopop3.c b/src/protopop3.c index 51441ba..a695dc6 100644 --- a/src/protopop3.c +++ b/src/protopop3.c @@ -31,13 +31,6 @@ #include -typedef struct protopop3_ctx protopop3_ctx_t; - -struct protopop3_ctx { - unsigned int not_valid : 1; - unsigned int seen_command_count; -}; - // Size = 14 static char *protopop3_commands[] = { "CAPA", "USER", "PASS", "AUTH", "APOP", "STLS", "LIST", "STAT", "UIDL", "RETR", "DELE", "RSET", "TOP", "QUIT", "NOOP" }; @@ -63,7 +56,7 @@ protopop3_validate_command(char *packet, size_t packet_size return -1; } -static int NONNULL(1,2) +int protopop3_validate(pxy_conn_ctx_t *ctx, char *packet, size_t packet_size) { protopop3_ctx_t *pop3_ctx = ctx->protoctx->arg; diff --git a/src/protopop3.h b/src/protopop3.h index f4b67f6..845a65b 100644 --- a/src/protopop3.h +++ b/src/protopop3.h @@ -30,6 +30,13 @@ #include "pxyconn.h" +typedef struct protopop3_ctx { + unsigned int not_valid : 1; + unsigned int seen_command_count; +} protopop3_ctx_t; + +int protopop3_validate(pxy_conn_ctx_t *, char *, size_t) NONNULL(1,2); + protocol_t protopop3_setup(pxy_conn_ctx_t *) NONNULL(1); protocol_t protopop3s_setup(pxy_conn_ctx_t *) NONNULL(1); diff --git a/src/protosmtp.c b/src/protosmtp.c index 63c779d..789917c 100644 --- a/src/protosmtp.c +++ b/src/protosmtp.c @@ -32,13 +32,6 @@ #include -typedef struct protosmtp_ctx protosmtp_ctx_t; - -struct protosmtp_ctx { - unsigned int not_valid : 1; - unsigned int seen_command_count; -}; - // Size = 25 static char *protosmtp_commands[] = { "EHLO", "HELO", "AUTH", "MAIL", "MAIL FROM", "RCPT", "RCPT TO", "DATA", "SEND", "RSET", "QUIT", "ATRN", "ETRN", "TURN", "SAML", "SOML", "EXPN", "NOOP", "HELP", "ONEX", "BDAT", "BURL", "SUBMITTER", "VERB", "VRFY" }; @@ -50,6 +43,7 @@ protosmtp_validate_command(char *packet, size_t packet_size #endif /* DEBUG_PROXY */ ) { + // @attention We validate MAIL FROM and RCPT TO commands as MAIL and RCPT, since we use space as separator. size_t command_len = util_get_first_word_len(packet, packet_size); unsigned int i; @@ -65,7 +59,7 @@ protosmtp_validate_command(char *packet, size_t packet_size return -1; } -static int NONNULL(1,2) +int protosmtp_validate(pxy_conn_ctx_t *ctx, char *packet, size_t packet_size) { protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; @@ -92,12 +86,8 @@ protosmtp_validate(pxy_conn_ctx_t *ctx, char *packet, size_t packet_size) return 0; } -static int NONNULL(1,2) -protosmtp_validate_response(pxy_conn_ctx_t *ctx, char *packet -#ifdef DEBUG_PROXY - , size_t packet_size -#endif /* DEBUG_PROXY */ - ) +int +protosmtp_validate_response(pxy_conn_ctx_t *ctx, char *packet, size_t packet_size) { protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; @@ -106,9 +96,11 @@ protosmtp_validate_response(pxy_conn_ctx_t *ctx, char *packet return -1; } - char response[4]; - memcpy(response, packet, 3); - response[3] = '\0'; + size_t response_len = util_get_first_word_len(packet, packet_size); + + char response[response_len + 1]; + memcpy(response, packet, response_len); + response[response_len] = '\0'; unsigned int i = atoi(response); if (i >= 200 && i < 600) { @@ -136,11 +128,7 @@ protosmtp_try_validate_response(struct bufferevent *bev, pxy_conn_ctx_t *ctx, st free(packet); return -1; } - if (protosmtp_validate_response(ctx, packet -#ifdef DEBUG_PROXY - , packet_size -#endif /* DEBUG_PROXY */ - ) == -1) { + if (protosmtp_validate_response(ctx, packet, packet_size) == -1) { // Send message to the client: outbuf of src evbuffer_add(outbuf, PROTOERROR_MSG, PROTOERROR_MSG_LEN); ctx->sent_protoerror_msg = 1; diff --git a/src/protosmtp.h b/src/protosmtp.h index 1318ad0..9f439bc 100644 --- a/src/protosmtp.h +++ b/src/protosmtp.h @@ -30,6 +30,14 @@ #include "pxyconn.h" +typedef struct protosmtp_ctx { + unsigned int not_valid : 1; + unsigned int seen_command_count; +} protosmtp_ctx_t; + +int protosmtp_validate(pxy_conn_ctx_t *, char *, size_t) NONNULL(1,2); +int protosmtp_validate_response(pxy_conn_ctx_t *, char *, size_t) NONNULL(1,2); + protocol_t protosmtp_setup(pxy_conn_ctx_t *) NONNULL(1); protocol_t protosmtps_setup(pxy_conn_ctx_t *) NONNULL(1); diff --git a/src/prototcp.c b/src/prototcp.c index 2577fa6..db32c07 100644 --- a/src/prototcp.c +++ b/src/prototcp.c @@ -319,8 +319,7 @@ prototcp_bev_readcb_dst(struct bufferevent *bev, pxy_conn_ctx_t *ctx) static void NONNULL(1) prototcp_bev_readcb_srvdst(UNUSED struct bufferevent *bev, UNUSED pxy_conn_ctx_t *ctx) { - log_err_printf("readcb called on srvdst\n"); - log_fine("readcb called on srvdst"); + log_err_level(LOG_ERR, "readcb called on srvdst"); } static void NONNULL(1) diff --git a/src/proxy.c b/src/proxy.c index e679c4d..3ef836c 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -145,7 +145,7 @@ proxy_setup_proto(pxy_conn_ctx_t *ctx) return proto; } -static pxy_conn_ctx_t * MALLOC NONNULL(2,3,4) +pxy_conn_ctx_t * proxy_conn_ctx_new(evutil_socket_t fd, pxy_thrmgr_ctx_t *thrmgr, proxyspec_t *spec, global_t *global, diff --git a/src/proxy.h b/src/proxy.h index 73855cf..9767898 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -55,6 +55,7 @@ void proxy_loopbreak(proxy_ctx_t *, int) NONNULL(1); void proxy_free(proxy_ctx_t *) NONNULL(1); void proxy_listener_errorcb(struct evconnlistener *, UNUSED void *); +pxy_conn_ctx_t *proxy_conn_ctx_new(evutil_socket_t, pxy_thrmgr_ctx_t *, proxyspec_t *, global_t *, evutil_socket_t) MALLOC NONNULL(2,3,4); #endif /* !PROXY_H */ /* vim: set noet ft=c: */ diff --git a/src/util.c b/src/util.c index 96845ee..508339a 100644 --- a/src/util.c +++ b/src/util.c @@ -50,13 +50,14 @@ util_skipws(const char *s) size_t util_get_first_word_len(char *mem, size_t size) { - char *command_end; + char *end; // @attention The detection order of ws chars is important: space, tab, cr, and nl - if ((command_end = memchr(mem, ' ', size)) || - (command_end = memchr(mem, '\t', size)) || - (command_end = memchr(mem, '\r', size)) || - (command_end = memchr(mem, '\n', size))) { - return (size_t)(command_end - mem); + if ((end = memchr(mem, ' ', size)) || + (end = memchr(mem, '\t', size)) || + (end = memchr(mem, '\r', size)) || + (end = memchr(mem, '\n', size)) || + (end = memchr(mem, '\0', size))) { + return (size_t)(end - mem); } return size; } diff --git a/src/util.h b/src/util.h index 0dbcf5e..6cc6f61 100644 --- a/src/util.h +++ b/src/util.h @@ -34,7 +34,7 @@ #include char * util_skipws(const char *) NONNULL(1) PURE; -size_t util_get_first_word_len(char *packet, size_t packet_size) NONNULL(1); +size_t util_get_first_word_len(char *, size_t) NONNULL(1); #define util_max(a,b) ((a) > (b) ? (a) : (b)) diff --git a/tests/check/main.t.c b/tests/check/main.t.c index 24325b3..61f570e 100644 --- a/tests/check/main.t.c +++ b/tests/check/main.t.c @@ -81,6 +81,7 @@ Suite * url_suite(void); Suite * util_suite(void); Suite * pxythrmgr_suite(void); Suite * defaults_suite(void); +Suite * proto_suite(void); int main(UNUSED int argc, UNUSED char *argv[]) @@ -106,6 +107,7 @@ main(UNUSED int argc, UNUSED char *argv[]) srunner_add_suite(sr, util_suite()); srunner_add_suite(sr, pxythrmgr_suite()); srunner_add_suite(sr, defaults_suite()); + srunner_add_suite(sr, proto_suite()); srunner_run_all(sr, CK_NORMAL); nfail = srunner_ntests_failed(sr); srunner_free(sr); diff --git a/tests/check/proto.t.c b/tests/check/proto.t.c new file mode 100644 index 0000000..e174ff1 --- /dev/null +++ b/tests/check/proto.t.c @@ -0,0 +1,848 @@ +/*- + * SSLsplit - transparent SSL/TLS interception + * https://www.roe.ch/SSLsplit + * + * Copyright (c) 2017-2020, Soner Tari . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "protohttp.h" +#include "protopop3.h" +#include "protosmtp.h" + +#include + +static pxy_conn_ctx_t * +protohttp_init() +{ + global_t *global = global_new(); + pxy_thrmgr_ctx_t *thrmgr = pxy_thrmgr_new(global); + proxyspec_t *spec = proxyspec_new(global, "sslproxy"); + spec->http = 1; + return proxy_conn_ctx_new(0, thrmgr, spec, global, 0); +} + +START_TEST(protohttp_validate_01) +{ + pxy_conn_ctx_t *ctx = protohttp_init(); + protohttp_ctx_t *http_ctx = ctx->protoctx->arg; + + http_ctx->seen_keyword_count = 1; + int rv = protohttp_validate(ctx); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(http_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 1, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 0, "wrong seen_bytes"); +} +END_TEST + +START_TEST(protohttp_validate_02) +{ + pxy_conn_ctx_t *ctx = protohttp_init(); + protohttp_ctx_t *http_ctx = ctx->protoctx->arg; + + http_ctx->seen_keyword_count = 1; + http_ctx->http_method = "GET"; + int rv = protohttp_validate(ctx); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(http_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 1, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 0, "wrong seen_bytes"); +} +END_TEST + +START_TEST(protohttp_validate_03) +{ + pxy_conn_ctx_t *ctx = protohttp_init(); + protohttp_ctx_t *http_ctx = ctx->protoctx->arg; + + http_ctx->http_method = "GET"; + int rv = protohttp_validate(ctx); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(http_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 0, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 0, "wrong seen_bytes"); +} +END_TEST + +START_TEST(protohttp_validate_04) +{ + pxy_conn_ctx_t *ctx = protohttp_init(); + protohttp_ctx_t *http_ctx = ctx->protoctx->arg; + + http_ctx->http_method = "GET1"; + int rv = protohttp_validate(ctx); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(http_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 0, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 0, "wrong seen_bytes"); +} +END_TEST + +START_TEST(protohttp_validate_05) +{ + pxy_conn_ctx_t *ctx = protohttp_init(); + protohttp_ctx_t *http_ctx = ctx->protoctx->arg; + + http_ctx->seen_keyword_count = 1; + http_ctx->http_method = "GET1"; + int rv = protohttp_validate(ctx); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(http_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 1, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 0, "wrong seen_bytes"); + + rv = protohttp_validate(ctx); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(http_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 1, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 0, "wrong seen_bytes"); + + http_ctx->http_method = "GET"; + rv = protohttp_validate(ctx); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(http_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 1, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 0, "wrong seen_bytes"); +} +END_TEST + +START_TEST(protohttp_validate_06) +{ + pxy_conn_ctx_t *ctx = protohttp_init(); + protohttp_ctx_t *http_ctx = ctx->protoctx->arg; + + http_ctx->seen_keyword_count = 1; + http_ctx->http_method = "GET"; + int rv = protohttp_validate(ctx); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(http_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 1, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 0, "wrong seen_bytes"); + + rv = protohttp_validate(ctx); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(http_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 1, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 0, "wrong seen_bytes"); + + // Normally we don't call protohttp_validate() if ctx->protoctx->is_valid is set, + // So both not_valid and is_valid are set. + // This is for testing purposes only. + http_ctx->http_method = "GET1"; + rv = protohttp_validate(ctx); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(http_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 1, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 0, "wrong seen_bytes"); +} +END_TEST + +START_TEST(protohttp_validate_07) +{ + pxy_conn_ctx_t *ctx = protohttp_init(); + protohttp_ctx_t *http_ctx = ctx->protoctx->arg; + + http_ctx->seen_bytes = 8193; + int rv = protohttp_validate(ctx); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(http_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 0, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 8193, "wrong seen_bytes"); +} +END_TEST + +START_TEST(protohttp_validate_08) +{ + pxy_conn_ctx_t *ctx = protohttp_init(); + protohttp_ctx_t *http_ctx = ctx->protoctx->arg; + + http_ctx->seen_bytes = 8193; + http_ctx->seen_keyword_count = 1; + int rv = protohttp_validate(ctx); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(http_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 1, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 8193, "wrong seen_bytes"); +} +END_TEST + +START_TEST(protohttp_validate_09) +{ + pxy_conn_ctx_t *ctx = protohttp_init(); + protohttp_ctx_t *http_ctx = ctx->protoctx->arg; + + http_ctx->seen_bytes = 8193; + http_ctx->http_method = "GET"; + int rv = protohttp_validate(ctx); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(http_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 0, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 8193, "wrong seen_bytes"); +} +END_TEST + +START_TEST(protohttp_validate_10) +{ + pxy_conn_ctx_t *ctx = protohttp_init(); + protohttp_ctx_t *http_ctx = ctx->protoctx->arg; + + http_ctx->seen_bytes = 8193; + http_ctx->seen_keyword_count = 1; + http_ctx->http_method = "GET"; + int rv = protohttp_validate(ctx); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(http_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(http_ctx->seen_keyword_count == 1, "wrong seen_keyword_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + fail_unless(http_ctx->seen_bytes == 8193, "wrong seen_bytes"); +} +END_TEST + +static pxy_conn_ctx_t * +protopop3_init() +{ + global_t *global = global_new(); + pxy_thrmgr_ctx_t *thrmgr = pxy_thrmgr_new(global); + proxyspec_t *spec = proxyspec_new(global, "sslproxy"); + spec->pop3 = 1; + return proxy_conn_ctx_new(0, thrmgr, spec, global, 0); +} + +START_TEST(protopop3_validate_01) +{ + pxy_conn_ctx_t *ctx = protopop3_init(); + protopop3_ctx_t *pop3_ctx = ctx->protoctx->arg; + + char array01[] = {'C', 'A', 'P', 'A'}; + int rv = protopop3_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 1, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array02[] = {'U', 'S', 'E', 'R', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protopop3_validate(ctx, array02, sizeof(array02)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 2, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array03[] = {'P', 'A', 'S', 'S', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protopop3_validate(ctx, array03, sizeof(array03)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 3, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + + // Normally we don't call protopop3_validate() if ctx->protoctx->is_valid is set, + // so pop3_ctx->seen_command_count never goes above 3. + // This is for testing purposes only. + char array04[] = {'Q', 'U', 'I', 'T'}; + rv = protopop3_validate(ctx, array04, sizeof(array04)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 4, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); +} +END_TEST + +START_TEST(protopop3_validate_02) +{ + pxy_conn_ctx_t *ctx = protopop3_init(); + protopop3_ctx_t *pop3_ctx = ctx->protoctx->arg; + + char array01[] = {'C', 'A', 'P'}; + int rv = protopop3_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protopop3_validate_03) +{ + pxy_conn_ctx_t *ctx = protopop3_init(); + protopop3_ctx_t *pop3_ctx = ctx->protoctx->arg; + + char array01[] = {'C', 'A', 'P', 'A'}; + int rv = protopop3_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 1, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array02[] = {'U', 'S', 'E', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protopop3_validate(ctx, array02, sizeof(array02)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 1, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protopop3_validate_04) +{ + pxy_conn_ctx_t *ctx = protopop3_init(); + protopop3_ctx_t *pop3_ctx = ctx->protoctx->arg; + + char array01[] = {'C', 'A', 'P', 'A'}; + int rv = protopop3_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 1, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array02[] = {'U', 'S', 'E', 'R', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protopop3_validate(ctx, array02, sizeof(array02)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 2, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array03[] = {'P', 'A', 'S', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protopop3_validate(ctx, array03, sizeof(array03)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 2, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protopop3_validate_05) +{ + pxy_conn_ctx_t *ctx = protopop3_init(); + protopop3_ctx_t *pop3_ctx = ctx->protoctx->arg; + + char array01[] = {'C', 'A', 'P', 'A'}; + int rv = protopop3_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 1, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array02[] = {'U', 'S', 'E', 'R', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protopop3_validate(ctx, array02, sizeof(array02)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 2, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array03[] = {'P', 'A', 'S', 'S', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protopop3_validate(ctx, array03, sizeof(array03)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 3, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + + // Normally we don't call protopop3_validate() if ctx->protoctx->is_valid is set, + // So both not_valid and is_valid are set. + // This is for testing purposes only. + char array04[] = {'Q', 'U', 'I'}; + rv = protopop3_validate(ctx, array04, sizeof(array04)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 3, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + + // Again, this is for testing purposes only. + rv = protopop3_validate(ctx, array04, sizeof(array04)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 3, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); +} +END_TEST + +START_TEST(protopop3_validate_06) +{ + pxy_conn_ctx_t *ctx = protopop3_init(); + protopop3_ctx_t *pop3_ctx = ctx->protoctx->arg; + + char array01[] = {'C', 'A', 'P'}; + int rv = protopop3_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + rv = protopop3_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(pop3_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(pop3_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +static pxy_conn_ctx_t * +protosmtp_init() +{ + global_t *global = global_new(); + pxy_thrmgr_ctx_t *thrmgr = pxy_thrmgr_new(global); + proxyspec_t *spec = proxyspec_new(global, "sslproxy"); + spec->smtp = 1; + return proxy_conn_ctx_new(0, thrmgr, spec, global, 0); +} + +START_TEST(protosmtp_validate_01) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'E', 'H', 'L', 'O'}; + int rv = protosmtp_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 1, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array02[] = {'A', 'U', 'T', 'H', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protosmtp_validate(ctx, array02, sizeof(array02)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 2, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array03[] = {'M', 'A', 'I', 'L', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protosmtp_validate(ctx, array03, sizeof(array03)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 3, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + + // Normally we don't call protosmtp_validate() if ctx->protoctx->is_valid is set, + // so smtp_ctx->seen_command_count never goes above 3. + // This is for testing purposes only. + char array04[] = {'Q', 'U', 'I', 'T'}; + rv = protosmtp_validate(ctx, array04, sizeof(array04)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 4, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_02) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'E', 'H', 'L'}; + int rv = protosmtp_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_03) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'E', 'H', 'L', 'O'}; + int rv = protosmtp_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 1, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array02[] = {'A', 'U', 'T', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protosmtp_validate(ctx, array02, sizeof(array02)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 1, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_04) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'E', 'H', 'L', 'O'}; + int rv = protosmtp_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 1, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array02[] = {'A', 'U', 'T', 'H', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protosmtp_validate(ctx, array02, sizeof(array02)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 2, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array03[] = {'M', 'A', 'I', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protosmtp_validate(ctx, array03, sizeof(array03)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 2, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_05) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'E', 'H', 'L', 'O'}; + int rv = protosmtp_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 1, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array02[] = {'A', 'U', 'T', 'H', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protosmtp_validate(ctx, array02, sizeof(array02)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 2, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + char array03[] = {'M', 'A', 'I', 'L', ' ', 's', 'o', 'n', 'e', 'r'}; + rv = protosmtp_validate(ctx, array03, sizeof(array03)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 3, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + + // Normally we don't call protosmtp_validate() if ctx->protoctx->is_valid is set, + // So both not_valid and is_valid are set. + // This is for testing purposes only. + char array04[] = {'Q', 'U', 'I'}; + rv = protosmtp_validate(ctx, array04, sizeof(array04)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 3, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); + + // Again, this is for testing purposes only. + rv = protosmtp_validate(ctx, array04, sizeof(array04)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 3, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 1, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_06) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'E', 'H', 'L'}; + int rv = protosmtp_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + rv = protosmtp_validate(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_response_01) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'2', '2', '0', ' ', 's', 'm', 't', 'p'}; + int rv = protosmtp_validate_response(ctx, array01, sizeof(array01)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_response_02) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'1', '9', '9', ' ', 's', 'm', 't', 'p'}; + int rv = protosmtp_validate_response(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_response_03) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'6', '0', '0', ' ', 's', 'm', 't', 'p'}; + int rv = protosmtp_validate_response(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_response_04) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'2', '2', '0', ' ', 's', 'm', 't', 'p'}; + int rv = protosmtp_validate_response(ctx, array01, sizeof(array01)); + + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + rv = protosmtp_validate_response(ctx, array01, sizeof(array01)); + + // Normally we don't call protosmtp_validate_response() more than once. + // This is for testing purposes only. + fail_unless(rv == 0, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 0, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + // Normally we don't call protosmtp_validate_response() more than once, + // but smtp_ctx->not_valid should be set to 1. + // This is for testing purposes only. + char array02[] = {'1', '9', '9', ' ', 's', 'm', 't', 'p'}; + rv = protosmtp_validate_response(ctx, array02, sizeof(array02)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_response_05) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'1', '9', '9', ' ', 's', 'm', 't', 'p'}; + int rv = protosmtp_validate_response(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + // Normally we don't call protosmtp_validate_response() more than once. + // This is for testing purposes only. + rv = protosmtp_validate_response(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); + + // Normally we don't call protosmtp_validate_response() more than once, + // but smtp_ctx->not_valid should remain 1. + // This is for testing purposes only. + char array02[] = {'2', '2', '0', ' ', 's', 'm', 't', 'p'}; + rv = protosmtp_validate_response(ctx, array02, sizeof(array02)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_response_06) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'2', '2', '0', '0', ' ', 's', 'm', 't', 'p'}; + int rv = protosmtp_validate_response(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_response_07) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'1', '9', '9', '9', ' ', 's', 'm', 't', 'p'}; + int rv = protosmtp_validate_response(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +START_TEST(protosmtp_validate_response_08) +{ + pxy_conn_ctx_t *ctx = protosmtp_init(); + protosmtp_ctx_t *smtp_ctx = ctx->protoctx->arg; + + char array01[] = {'6', '0', '0', '0'}; + int rv = protosmtp_validate_response(ctx, array01, sizeof(array01)); + + fail_unless(rv == -1, "wrong return value"); + fail_unless(smtp_ctx->not_valid == 1, "wrong not_valid"); + fail_unless(smtp_ctx->seen_command_count == 0, "wrong seen_command_count"); + fail_unless(ctx->protoctx->is_valid == 0, "wrong is_valid"); +} +END_TEST + +Suite * +proto_suite(void) +{ + Suite *s; + TCase *tc; + + s = suite_create("proto"); + + tc = tcase_create("protohttp_validate"); + tcase_add_test(tc, protohttp_validate_01); + tcase_add_test(tc, protohttp_validate_02); + tcase_add_test(tc, protohttp_validate_03); + tcase_add_test(tc, protohttp_validate_04); + tcase_add_test(tc, protohttp_validate_05); + tcase_add_test(tc, protohttp_validate_06); + tcase_add_test(tc, protohttp_validate_07); + tcase_add_test(tc, protohttp_validate_08); + tcase_add_test(tc, protohttp_validate_09); + tcase_add_test(tc, protohttp_validate_10); + suite_add_tcase(s, tc); + + tc = tcase_create("protopop3_validate"); + tcase_add_test(tc, protopop3_validate_01); + tcase_add_test(tc, protopop3_validate_02); + tcase_add_test(tc, protopop3_validate_03); + tcase_add_test(tc, protopop3_validate_04); + tcase_add_test(tc, protopop3_validate_05); + tcase_add_test(tc, protopop3_validate_06); + suite_add_tcase(s, tc); + + tc = tcase_create("protosmtp_validate"); + tcase_add_test(tc, protosmtp_validate_01); + tcase_add_test(tc, protosmtp_validate_02); + tcase_add_test(tc, protosmtp_validate_03); + tcase_add_test(tc, protosmtp_validate_04); + tcase_add_test(tc, protosmtp_validate_05); + tcase_add_test(tc, protosmtp_validate_06); + suite_add_tcase(s, tc); + + tc = tcase_create("protosmtp_validate_response"); + tcase_add_test(tc, protosmtp_validate_response_01); + tcase_add_test(tc, protosmtp_validate_response_02); + tcase_add_test(tc, protosmtp_validate_response_03); + tcase_add_test(tc, protosmtp_validate_response_04); + tcase_add_test(tc, protosmtp_validate_response_05); + tcase_add_test(tc, protosmtp_validate_response_06); + tcase_add_test(tc, protosmtp_validate_response_07); + tcase_add_test(tc, protosmtp_validate_response_08); + suite_add_tcase(s, tc); + + return s; +} + +/* vim: set noet ft=c: */ diff --git a/tests/check/util.t.c b/tests/check/util.t.c index d290b42..7d6560c 100644 --- a/tests/check/util.t.c +++ b/tests/check/util.t.c @@ -3,6 +3,7 @@ * https://www.roe.ch/SSLsplit * * Copyright (c) 2009-2019, Daniel Roethlisberger . + * Copyright (c) 2017-2020, Soner Tari . * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -98,6 +99,98 @@ START_TEST(util_skipws_06) } END_TEST +START_TEST(util_get_first_word_len_01) +{ + size_t l; + + char array01[] = {'\0'}; + l = util_get_first_word_len(array01, sizeof(array01)); + fail_unless(l == 0, "wrong len for null = %d", l); + + char array02[] = {' '}; + l = util_get_first_word_len(array02, sizeof(array02)); + fail_unless(l == 0, "wrong len for space = %d", l); + + char array03[] = {'\t'}; + l = util_get_first_word_len(array03, sizeof(array03)); + fail_unless(l == 0, "wrong len for tab = %d", l); + + char array04[] = {'\r'}; + l = util_get_first_word_len(array04, sizeof(array04)); + fail_unless(l == 0, "wrong len for cr = %d", l); + + char array05[] = {'\n'}; + l = util_get_first_word_len(array05, sizeof(array05)); + fail_unless(l == 0, "wrong len for nl = %d", l); + + char array06[] = {'\t', '\r', '\n'}; + l = util_get_first_word_len(array06, sizeof(array06)); + fail_unless(l == 0, "wrong len for space, tab, cr, nl = %d", l); + + char array07[] = {'1'}; + l = util_get_first_word_len(array07, sizeof(array07)); + fail_unless(l == 1, "wrong len for 1 = %d", l); + + char array08[] = {'1', ' '}; + l = util_get_first_word_len(array08, sizeof(array08)); + fail_unless(l == 1, "wrong len for 1, space = %d", l); + + char array09[] = {'1', '\t'}; + l = util_get_first_word_len(array09, sizeof(array09)); + fail_unless(l == 1, "wrong len for 1, tab = %d", l); + + char array10[] = {'1', '\r'}; + l = util_get_first_word_len(array10, sizeof(array10)); + fail_unless(l == 1, "wrong len for 1, cr = %d", l); + + char array11[] = {'1', '\n'}; + l = util_get_first_word_len(array11, sizeof(array11)); + fail_unless(l == 1, "wrong len for 1, nl = %d", l); + + char array12[] = {'1', ' ', '\t', '\r', '\n'}; + l = util_get_first_word_len(array12, sizeof(array12)); + fail_unless(l == 1, "wrong len for 1, space, tab, cr, nl = %d", l); + + char array13[] = {'1', '\t', '\r', '\n'}; + l = util_get_first_word_len(array13, sizeof(array13)); + fail_unless(l == 1, "wrong len for 1, tab, cr, nl = %d", l); + + char array14[] = {'1', '\r', '\n'}; + l = util_get_first_word_len(array14, sizeof(array14)); + fail_unless(l == 1, "wrong len for 1, cr, nl = %d", l); + + char array15[] = {'1', '2', '\r', '\n'}; + l = util_get_first_word_len(array15, sizeof(array15)); + fail_unless(l == 2, "wrong len for 12, cr, nl = %d", l); + + char array16[] = {'1', '2'}; + l = util_get_first_word_len(array16, sizeof(array16)); + fail_unless(l == 2, "wrong len for 12 = %d", l); + + char array17[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; + l = util_get_first_word_len(array17, sizeof(array17)); + fail_unless(l == 10, "wrong len for 1234567890 = %d", l); + + char array18[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '\r', '\n'}; + l = util_get_first_word_len(array18, sizeof(array18)); + fail_unless(l == 10, "wrong len for 1234567890, cr, nl = %d", l); + + l = util_get_first_word_len(array18, 1); + fail_unless(l == 1, "wrong len for size 1 in 1234567890, cr, nl = %d", l); + + l = util_get_first_word_len(array18, 0); + fail_unless(l == 0, "wrong len for size 0 in 1234567890, cr, nl = %d", l); + + char array19[] = {'1', ' ', '2', '\r', '\n'}; + l = util_get_first_word_len(array19, sizeof(array19)); + fail_unless(l == 1, "wrong len for 1 2, cr, nl = %d", l); + + char array20[] = {' ', '1'}; + l = util_get_first_word_len(array20, sizeof(array20)); + fail_unless(l == 0, "wrong len for space, 1 = %d", l); +} +END_TEST + Suite * util_suite(void) { @@ -115,6 +208,10 @@ util_suite(void) tcase_add_test(tc, util_skipws_06); suite_add_tcase(s, tc); + tc = tcase_create("util_get_first_word_len"); + tcase_add_test(tc, util_get_first_word_len_01); + suite_add_tcase(s, tc); + return s; }