diff --git a/src/common.c b/src/common.c index 6b74c64..b4772bb 100644 --- a/src/common.c +++ b/src/common.c @@ -326,18 +326,34 @@ read_password(char *buf, size_t len) int check_topdomain(char *str) { - int i; + int i; + int dots = 0; + int chunklen = 0; - if(str[0] == '.') /* special case */ - return 1; + if (strlen(str) < 3) + return 1; + if (strlen(str) > 128) + return 1; - for( i = 0; i < strlen(str); i++) { - if( isalpha(str[i]) || isdigit(str[i]) || str[i] == '-' || str[i] == '.' ) - continue; - else - return 1; - } - return 0; + for( i = 0; i < strlen(str); i++) { + if(str[i] == '.') { + dots++; + /* This will also catch the case where topdomain starts with a dot */ + if (chunklen == 0 || chunklen > 63) + return 1; + chunklen = 0; + } else + chunklen++; + if( isalpha(str[i]) || isdigit(str[i]) || str[i] == '-' || str[i] == '.' ) + continue; + else + return 1; + } + + if (chunklen == 0 || chunklen > 63 || dots == 0) + return 1; + + return 0; } #if defined(WINDOWS32) || defined(ANDROID) diff --git a/tests/common.c b/tests/common.c index 92f2d4c..9c84e4a 100644 --- a/tests/common.c +++ b/tests/common.c @@ -4,6 +4,65 @@ #include #include +START_TEST(test_topdomain_ok) +{ + fail_if(check_topdomain("foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com")); + + /* Not allowed to start with dot */ + fail_unless(check_topdomain(".foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com")); +} +END_TEST + +START_TEST(test_topdomain_length) +{ + /* Test empty and too short */ + fail_unless(check_topdomain("")); + fail_unless(check_topdomain("a")); + fail_unless(check_topdomain(".a")); + fail_unless(check_topdomain("a.")); + fail_unless(check_topdomain("ab")); + fail_if(check_topdomain("a.b")); + + /* Test too long (over 128, need rest of space for data) */ + fail_unless(check_topdomain( + "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." + "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." + "abcd12345.abcd12345.foo129xxx")); + fail_if(check_topdomain( + "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." + "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." + "abcd12345.abcd12345.foo128xx")); +} +END_TEST + +START_TEST(test_topdomain_chunks) +{ + /* Must have at least one dot */ + fail_if(check_topdomain("abcde.gh")); + fail_unless(check_topdomain("abcdefgh")); + + /* Not two consecutive dots */ + fail_unless(check_topdomain("abc..defgh")); + + /* Not end with a dots */ + fail_unless(check_topdomain("abc.defgh.")); + + /* No chunk longer than 63 chars */ + fail_unless(check_topdomain("123456789012345678901234567890" + "1234567890123456789012345678904444.com")); + fail_if(check_topdomain("123456789012345678901234567890" + "123456789012345678901234567890333.com")); + fail_unless(check_topdomain("abc.123456789012345678901234567890" + "1234567890123456789012345678904444.com")); + fail_if(check_topdomain("abc.123456789012345678901234567890" + "123456789012345678901234567890333.com")); + fail_unless(check_topdomain("abc.123456789012345678901234567890" + "1234567890123456789012345678904444")); + fail_if(check_topdomain("abc.123456789012345678901234567890" + "123456789012345678901234567890333")); +} +END_TEST + START_TEST(test_parse_format_ipv4) { char *host = "192.168.2.10"; @@ -102,6 +161,9 @@ test_common_create_tests() int sock; tc = tcase_create("Common"); + tcase_add_test(tc, test_topdomain_ok); + tcase_add_test(tc, test_topdomain_length); + tcase_add_test(tc, test_topdomain_chunks); tcase_add_test(tc, test_parse_format_ipv4); tcase_add_test(tc, test_parse_format_ipv4_listen_all);