Move error message generation into topdomain check method

Change isalpha() to a-z check to avoid locale issues
This commit is contained in:
Erik Ekman 2014-05-31 10:06:44 +02:00
parent 9bb2323f84
commit 3914d37c99
5 changed files with 94 additions and 47 deletions

View File

@ -324,34 +324,62 @@ read_password(char *buf, size_t len)
} }
int int
check_topdomain(char *str) check_topdomain(char *str, char **errormsg)
{ {
int i; int i;
int dots = 0; int dots = 0;
int chunklen = 0; int chunklen = 0;
if (strlen(str) < 3) if (strlen(str) < 3) {
if (errormsg) *errormsg = "Too short (< 3)";
return 1; return 1;
if (strlen(str) > 128) }
if (strlen(str) > 128) {
if (errormsg) *errormsg = "Too long (> 128)";
return 1; return 1;
}
if (str[0] == '.') {
if (errormsg) *errormsg = "Starts with a dot";
return 1;
}
for( i = 0; i < strlen(str); i++) { for( i = 0; i < strlen(str); i++) {
if(str[i] == '.') { if(str[i] == '.') {
dots++; dots++;
/* This will also catch the case where topdomain starts with a dot */ if (chunklen == 0) {
if (chunklen == 0 || chunklen > 63) if (errormsg) *errormsg = "Consecutive dots";
return 1;
chunklen = 0;
} else
chunklen++;
if( isalpha(str[i]) || isdigit(str[i]) || str[i] == '-' || str[i] == '.' )
continue;
else
return 1; return 1;
} }
if (chunklen > 63) {
if (chunklen == 0 || chunklen > 63 || dots == 0) if (errormsg) *errormsg = "Too long domain part (> 63)";
return 1; return 1;
}
chunklen = 0;
} else {
chunklen++;
}
if( (str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') ||
isdigit(str[i]) || str[i] == '-' || str[i] == '.' ) {
continue;
} else {
if (errormsg) *errormsg = "Contains illegal character (allowed: [a-zA-Z0-9-.])";
return 1;
}
}
if (dots == 0) {
if (errormsg) *errormsg = "No dots";
return 1;
}
if (chunklen == 0) {
if (errormsg) *errormsg = "Ends with a dot";
return 1;
}
if (chunklen > 63) {
if (errormsg) *errormsg = "Too long domain part (> 63)";
return 1;
}
return 0; return 0;
} }

View File

@ -120,7 +120,7 @@ void do_pidfile(char *);
void read_password(char*, size_t); void read_password(char*, size_t);
int check_topdomain(char *); int check_topdomain(char *, char **);
#if defined(WINDOWS32) || defined(ANDROID) #if defined(WINDOWS32) || defined(ANDROID)
#ifndef ANDROID #ifndef ANDROID

View File

@ -120,6 +120,7 @@ main(int argc, char **argv)
{ {
char *nameserv_host; char *nameserv_host;
char *topdomain; char *topdomain;
char *errormsg;
#ifndef WINDOWS32 #ifndef WINDOWS32
struct passwd *pw; struct passwd *pw;
#endif #endif
@ -149,6 +150,7 @@ main(int argc, char **argv)
nameserv_host = NULL; nameserv_host = NULL;
topdomain = NULL; topdomain = NULL;
errormsg = NULL;
#ifndef WINDOWS32 #ifndef WINDOWS32
pw = NULL; pw = NULL;
#endif #endif
@ -309,14 +311,8 @@ main(int argc, char **argv)
/* NOTREACHED */ /* NOTREACHED */
} }
if (strlen(topdomain) <= 128) { if(check_topdomain(topdomain, &errormsg)) {
if(check_topdomain(topdomain)) { warnx("Invalid topdomain: %s", errormsg);
warnx("Topdomain contains invalid characters.\n");
usage();
/* NOTREACHED */
}
} else {
warnx("Use a topdomain max 128 chars long.\n");
usage(); usage();
/* NOTREACHED */ /* NOTREACHED */
} }

View File

@ -2233,6 +2233,7 @@ main(int argc, char **argv)
{ {
extern char *__progname; extern char *__progname;
char *listen_ip; char *listen_ip;
char *errormsg;
#ifndef WINDOWS32 #ifndef WINDOWS32
struct passwd *pw; struct passwd *pw;
#endif #endif
@ -2267,6 +2268,7 @@ main(int argc, char **argv)
#ifndef WINDOWS32 #ifndef WINDOWS32
pw = NULL; pw = NULL;
#endif #endif
errormsg = NULL;
username = NULL; username = NULL;
newroot = NULL; newroot = NULL;
context = NULL; context = NULL;
@ -2403,14 +2405,10 @@ main(int argc, char **argv)
} }
topdomain = strdup(argv[1]); topdomain = strdup(argv[1]);
if (strlen(topdomain) <= 128) { if(check_topdomain(topdomain, &errormsg)) {
if(check_topdomain(topdomain)) { warnx("Invalid topdomain: %s", errormsg);
warnx("Topdomain contains invalid characters.");
usage();
}
} else {
warnx("Use a topdomain max 128 chars long.");
usage(); usage();
/* NOTREACHED */
} }
if (username != NULL) { if (username != NULL) {

View File

@ -6,60 +6,85 @@
START_TEST(test_topdomain_ok) START_TEST(test_topdomain_ok)
{ {
fail_if(check_topdomain("foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com")); char *error;
fail_if(check_topdomain("foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", &error));
/* Not allowed to start with dot */ /* Not allowed to start with dot */
fail_unless(check_topdomain(".foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com")); fail_unless(check_topdomain(".foo.0123456789.qwertyuiop.asdfghjkl.zxcvbnm.com", &error));
fail_if(strcmp("Starts with a dot", error));
/* Test missing error msg ptr */
fail_unless(check_topdomain(".foo", NULL));
} }
END_TEST END_TEST
START_TEST(test_topdomain_length) START_TEST(test_topdomain_length)
{ {
char *error;
/* Test empty and too short */ /* Test empty and too short */
fail_unless(check_topdomain("")); fail_unless(check_topdomain("", &error));
fail_unless(check_topdomain("a")); fail_if(strcmp("Too short (< 3)", error));
fail_unless(check_topdomain(".a")); fail_unless(check_topdomain("a", &error));
fail_unless(check_topdomain("a.")); fail_if(strcmp("Too short (< 3)", error));
fail_unless(check_topdomain("ab")); fail_unless(check_topdomain(".a", &error));
fail_if(check_topdomain("a.b")); fail_if(strcmp("Too short (< 3)", error));
fail_unless(check_topdomain("a.", &error));
fail_if(strcmp("Too short (< 3)", error));
fail_unless(check_topdomain("ab", &error));
fail_if(strcmp("Too short (< 3)", error));
fail_if(check_topdomain("a.b", &error));
fail_if(strcmp("Too short (< 3)", error));
/* Test too long (over 128, need rest of space for data) */ /* Test too long (over 128, need rest of space for data) */
fail_unless(check_topdomain( fail_unless(check_topdomain(
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
"abcd12345.abcd12345.foo129xxx")); "abcd12345.abcd12345.foo129xxx", &error));
fail_if(strcmp("Too long (> 128)", error));
fail_if(check_topdomain( fail_if(check_topdomain(
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345." "abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
"abcd12345.abcd12345.foo128xx")); "abcd12345.abcd12345.foo128xx", &error));
} }
END_TEST END_TEST
START_TEST(test_topdomain_chunks) START_TEST(test_topdomain_chunks)
{ {
char *error;
/* Must have at least one dot */ /* Must have at least one dot */
fail_if(check_topdomain("abcde.gh")); fail_if(check_topdomain("abcde.gh", &error));
fail_unless(check_topdomain("abcdefgh")); fail_unless(check_topdomain("abcdefgh", &error));
fail_if(strcmp("No dots", error));
/* Not two consecutive dots */ /* Not two consecutive dots */
fail_unless(check_topdomain("abc..defgh")); fail_unless(check_topdomain("abc..defgh", &error));
fail_if(strcmp("Consecutive dots", error));
/* Not end with a dots */ /* Not end with a dots */
fail_unless(check_topdomain("abc.defgh.")); fail_unless(check_topdomain("abc.defgh.", &error));
fail_if(strcmp("Ends with a dot", error));
/* No chunk longer than 63 chars */ /* No chunk longer than 63 chars */
fail_unless(check_topdomain("123456789012345678901234567890"
"1234567890123456789012345678904444.com"));
fail_if(check_topdomain("123456789012345678901234567890" fail_if(check_topdomain("123456789012345678901234567890"
"123456789012345678901234567890333.com")); "123456789012345678901234567890333.com", &error));
fail_unless(check_topdomain("abc.123456789012345678901234567890" fail_unless(check_topdomain("123456789012345678901234567890"
"1234567890123456789012345678904444.com")); "1234567890123456789012345678904444.com", &error));
fail_if(strcmp("Too long domain part (> 63)", error));
fail_if(check_topdomain("abc.123456789012345678901234567890" fail_if(check_topdomain("abc.123456789012345678901234567890"
"123456789012345678901234567890333.com")); "123456789012345678901234567890333.com", &error));
fail_unless(check_topdomain("abc.123456789012345678901234567890" fail_unless(check_topdomain("abc.123456789012345678901234567890"
"1234567890123456789012345678904444")); "1234567890123456789012345678904444.com", &error));
fail_if(strcmp("Too long domain part (> 63)", error));
fail_if(check_topdomain("abc.123456789012345678901234567890" fail_if(check_topdomain("abc.123456789012345678901234567890"
"123456789012345678901234567890333")); "123456789012345678901234567890333", &error));
fail_unless(check_topdomain("abc.123456789012345678901234567890"
"1234567890123456789012345678904444", &error));
fail_if(strcmp("Too long domain part (> 63)", error));
} }
END_TEST END_TEST