diff --git a/TODO b/TODO index 6f2d23202dbf12cc80bbc9df98801d789b108305..3917fd269147a01248bed17acd57ad276deea51d 100644 --- a/TODO +++ b/TODO @@ -15,7 +15,6 @@ Next (in order of descending priority/precedence): * Implement namespace support for variables extension (to complete include extension) * Update include extension to latest draft: - - Perform script name check - Implement global namespace - Allow placing the global command anywhere in the script - Implement required ManageSieve behavior diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c index 473c9e6c01689ef73e3cb127b359a457c4589ae7..4cfc4b96c9c7ea748c4e7dd7300a46387df45502 100644 --- a/src/lib-sieve/plugins/include/cmd-include.c +++ b/src/lib-sieve/plugins/include/cmd-include.c @@ -226,9 +226,9 @@ static bool cmd_include_validate script_name = sieve_ast_argument_strc(arg); - if ( strchr(script_name, '/') != NULL ) { + if ( !sieve_script_name_is_valid(script_name) ) { sieve_argument_validate_error(valdtr, arg, - "include: '/' not allowed in script name (%s)", + "include: invalid script name '%s'", str_sanitize(script_name, 80)); return FALSE; } diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c index 3d41d8f7948ab98d7a66a6240988c12e791c121c..bda41a77b6756df66181d343c621dfd77e237c4f 100644 --- a/src/lib-sieve/sieve-script.c +++ b/src/lib-sieve/sieve-script.c @@ -3,6 +3,8 @@ #include "lib.h" #include "compat.h" +#include "unichar.h" +#include "array.h" #include "istream.h" #include "eacces-error.h" @@ -21,6 +23,52 @@ #define SIEVE_READ_BLOCK_SIZE (1024*8) +/* + * Script name + */ + +bool sieve_script_name_is_valid(const char *scriptname) +{ + ARRAY_TYPE(unichars) uni_name; + unsigned int count, i; + const unichar_t *name_chars; + + /* Intialize array for unicode characters */ + t_array_init(&uni_name, strlen(scriptname)* 4); + + /* Convert UTF-8 to UCS4/UTF-32 */ + if ( uni_utf8_to_ucs4(scriptname, &uni_name) < 0 ) + return FALSE; + + /* Scan name for invalid characters */ + name_chars = array_get(&uni_name, &count); + for ( i = 0; i < count; i++ ) { + + /* 0000-001F; [CONTROL CHARACTERS] */ + if ( name_chars[i] <= 0x001f ) + return FALSE; + + /* 002F; SLASH */ + if ( name_chars[i] == 0x002f ) + return FALSE; + + /* 007F; DELETE */ + if ( name_chars[i] == 0x007f ) + return FALSE; + + /* 0080-009F; [CONTROL CHARACTERS] */ + if ( name_chars[i] >= 0x0080 && name_chars[i] <= 0x009f ) + return FALSE; + + /* 2028; LINE SEPARATOR */ + /* 2029; PARAGRAPH SEPARATOR */ + if ( name_chars[i] == 0x2028 || name_chars[i] == 0x2029 ) + return FALSE; + } + + return TRUE; +} + /* * Filename to name/name to filename */ diff --git a/src/lib-sieve/sieve-script.h b/src/lib-sieve/sieve-script.h index 2970e5fa48fb939a13d815244bfcd246c9a18db2..ebd8bc0e4b8c009fb7b1113d58eb76ce233bce28 100644 --- a/src/lib-sieve/sieve-script.h +++ b/src/lib-sieve/sieve-script.h @@ -8,6 +8,13 @@ #include <sys/types.h> + +/* + * Sieve script name + */ + +bool sieve_script_name_is_valid(const char *scriptname); + /* * Sieve script object */