From bd4db645bb84d47898348d91cc5b16b63512643a Mon Sep 17 00:00:00 2001 From: James Hillyerd Date: Sun, 3 Nov 2013 20:53:37 -0800 Subject: [PATCH] ValidateLocalPart: Handle backslash quoted chars --- smtpd/utils.go | 17 ++++++++++++++++- smtpd/utils_test.go | 18 +++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/smtpd/utils.go b/smtpd/utils.go index 133c1bb..4d5a582 100644 --- a/smtpd/utils.go +++ b/smtpd/utils.go @@ -104,26 +104,41 @@ func ValidateLocalPart(local string) bool { } prev := byte('.') + inCharQuote := false for i := 0; i < length; i++ { c := local[i] switch { case ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'): // Letters are OK + inCharQuote = false case '0' <= c && c <= '9': // Numbers are OK + inCharQuote = false case bytes.IndexByte([]byte("!#$%&'*+-/=?^_`{|}~"), c) >= 0: // These specials can be used unquoted + inCharQuote = false case c == '.': // A single period is OK if prev == '.' { // Sequence of periods is not permitted return false } - default: + case c == '\\': + inCharQuote = true + case c > 127: return false + default: + if ! inCharQuote { + return false + } + inCharQuote = false } prev = c } + if inCharQuote { + // Can't end with unused backslash quote + return false + } return true } diff --git a/smtpd/utils_test.go b/smtpd/utils_test.go index 47940e8..6f4e642 100644 --- a/smtpd/utils_test.go +++ b/smtpd/utils_test.go @@ -63,11 +63,27 @@ func TestValidateLocal(t *testing.T) { {"FirstLast", true, "Mixed case permitted"}, {"user123", true, "Numbers permitted"}, {"a!#$%&'*+-/=?^_`{|}~", true, "Any of !#$%&'*+-/=?^_`{|}~ are permitted"}, - {"james@mail", false, "Unquoted @ not permitted"}, {"first.last", true, "Embedded period is permitted"}, {"first..last", false, "Sequence of periods is not allowed"}, {".user", false, "Cannot lead with a period"}, {"user.", false, "Cannot end with a period"}, + {"james@mail", false, "Unquoted @ not permitted"}, + {"first last", false, "Unquoted space not permitted"}, + {"no,commas", false, "Unquoted comma not allowed"}, + {"t[es]t", false, "Unquoted square brackets not allowed"}, + {"james\\", false, "Cannot end with backslash quote"}, + {"james\\@mail", true, "Quoted @ permitted"}, + {"quoted\\ space", true, "Quoted space permitted"}, + {"no\\,commas", true, "Quoted comma is OK"}, + {"t\\[es\\]t", true, "Quoted brackets are OK"}, + {"user\\name", true, "Should be able to quote a-z"}, + {"USER\\NAME", true, "Should be able to quote A-Z"}, + {"user\\1", true, "Should be able to quote a digit"}, + {"one\\$\\|", true, "Should be able to quote plain specials"}, + {"return\\\r", true, "Should be able to quote ASCII control chars"}, + {"high\\\x80", false, "Should not accept > 7-bit quoted chars"}, + //{"\"james\"", true, "Quoted a-z is permitted"}, + {"user+mailbox", true, "RFC3696 test case should be valid"}, {"customer/department=shipping", true, "RFC3696 test case should be valid"}, {"$A12345", true, "RFC3696 test case should be valid"},