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
check_topdomain(char *str)
check_topdomain(char *str, char **errormsg)
{
int i;
int dots = 0;
int chunklen = 0;
if (strlen(str) < 3)
if (strlen(str) < 3) {
if (errormsg) *errormsg = "Too short (< 3)";
return 1;
if (strlen(str) > 128)
}
if (strlen(str) > 128) {
if (errormsg) *errormsg = "Too long (> 128)";
return 1;
}
if (str[0] == '.') {
if (errormsg) *errormsg = "Starts with a dot";
return 1;
}
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
if (chunklen == 0) {
if (errormsg) *errormsg = "Consecutive dots";
return 1;
}
if (chunklen == 0 || chunklen > 63 || dots == 0)
if (chunklen > 63) {
if (errormsg) *errormsg = "Too long domain part (> 63)";
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;
}

View file

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

View file

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

View file

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

View file

@ -6,60 +6,85 @@
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 */
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
START_TEST(test_topdomain_length)
{
char *error;
/* 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"));
fail_unless(check_topdomain("", &error));
fail_if(strcmp("Too short (< 3)", error));
fail_unless(check_topdomain("a", &error));
fail_if(strcmp("Too short (< 3)", error));
fail_unless(check_topdomain(".a", &error));
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) */
fail_unless(check_topdomain(
"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(
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
"abcd12345.abcd12345.abcd12345.abcd12345.abcd12345."
"abcd12345.abcd12345.foo128xx"));
"abcd12345.abcd12345.foo128xx", &error));
}
END_TEST
START_TEST(test_topdomain_chunks)
{
char *error;
/* Must have at least one dot */
fail_if(check_topdomain("abcde.gh"));
fail_unless(check_topdomain("abcdefgh"));
fail_if(check_topdomain("abcde.gh", &error));
fail_unless(check_topdomain("abcdefgh", &error));
fail_if(strcmp("No dots", error));
/* 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 */
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 */
fail_unless(check_topdomain("123456789012345678901234567890"
"1234567890123456789012345678904444.com"));
fail_if(check_topdomain("123456789012345678901234567890"
"123456789012345678901234567890333.com"));
fail_unless(check_topdomain("abc.123456789012345678901234567890"
"1234567890123456789012345678904444.com"));
"123456789012345678901234567890333.com", &error));
fail_unless(check_topdomain("123456789012345678901234567890"
"1234567890123456789012345678904444.com", &error));
fail_if(strcmp("Too long domain part (> 63)", error));
fail_if(check_topdomain("abc.123456789012345678901234567890"
"123456789012345678901234567890333.com"));
"123456789012345678901234567890333.com", &error));
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"
"123456789012345678901234567890333"));
"123456789012345678901234567890333", &error));
fail_unless(check_topdomain("abc.123456789012345678901234567890"
"1234567890123456789012345678904444", &error));
fail_if(strcmp("Too long domain part (> 63)", error));
}
END_TEST