server_test.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. package guerrilla
  2. import (
  3. "os"
  4. "testing"
  5. "bufio"
  6. "net/textproto"
  7. "strings"
  8. "sync"
  9. "crypto/tls"
  10. "fmt"
  11. "github.com/flashmob/go-guerrilla/backends"
  12. "github.com/flashmob/go-guerrilla/log"
  13. "github.com/flashmob/go-guerrilla/mail"
  14. "github.com/flashmob/go-guerrilla/mocks"
  15. "io/ioutil"
  16. "net"
  17. )
  18. // getMockServerConfig gets a mock ServerConfig struct used for creating a new server
  19. func getMockServerConfig() *ServerConfig {
  20. sc := &ServerConfig{
  21. IsEnabled: true, // not tested here
  22. Hostname: "saggydimes.test.com",
  23. MaxSize: 1024, // smtp message max size
  24. TLS: ServerTLSConfig{
  25. PrivateKeyFile: "./tests/mail.guerrillamail.com.key.pem",
  26. PublicKeyFile: "./tests/mail.guerrillamail.com.cert.pem",
  27. StartTLSOn: true,
  28. AlwaysOn: false,
  29. },
  30. Timeout: 5,
  31. ListenInterface: "127.0.0.1:2529",
  32. MaxClients: 30, // not tested here
  33. LogFile: "./tests/testlog",
  34. }
  35. return sc
  36. }
  37. // getMockServerConn gets a new server using sc. Server will be using a mocked TCP connection
  38. // using the dummy backend
  39. // RCP TO command only allows test.com host
  40. func getMockServerConn(sc *ServerConfig, t *testing.T) (*mocks.Conn, *server) {
  41. var logOpenError error
  42. var mainlog log.Logger
  43. mainlog, logOpenError = log.GetLogger(sc.LogFile, "debug")
  44. if logOpenError != nil {
  45. mainlog.WithError(logOpenError).Errorf("Failed creating a logger for mock conn [%s]", sc.ListenInterface)
  46. }
  47. backend, err := backends.New(
  48. backends.BackendConfig{"log_received_mails": true, "save_workers_size": 1},
  49. mainlog)
  50. if err != nil {
  51. t.Error("new dummy backend failed because:", err)
  52. }
  53. server, err := newServer(sc, backend, mainlog)
  54. if err != nil {
  55. //t.Error("new server failed because:", err)
  56. } else {
  57. server.setAllowedHosts([]string{"test.com"})
  58. }
  59. conn := mocks.NewConn()
  60. return conn, server
  61. }
  62. // test the RootCAs tls config setting
  63. var rootCAPK = `-----BEGIN CERTIFICATE-----
  64. MIIDqjCCApKgAwIBAgIJALh2TrsBR5MiMA0GCSqGSIb3DQEBCwUAMGkxCzAJBgNV
  65. BAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEhMB8G
  66. A1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhv
  67. c3QwIBcNMTgwNTE4MDYzOTU2WhgPMjExODA0MjQwNjM5NTZaMGkxCzAJBgNVBAYT
  68. AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEhMB8GA1UE
  69. CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhvc3Qw
  70. ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCcb0ulYT1o5ysor5UtWYW
  71. q/ZY3PyK3/4YBZq5JoX4xk7GNQQ+3p/Km7QPoBXfgjFLZXEV2R0bE5hHMXfLa5Xb
  72. 64acb9VqCqDvPFXcaNP4rEdBKDVN2p0PEi917tcKBSrZn5Yl+iOhtcBpQDvhHgn/
  73. 9MdmIAKB3+yK+4l9YhT40XfDXCQqzfg4XcNaEgTzZHcDJz+KjWJuJChprcx27MTI
  74. Ndxs9nmFA2rK16rjgjtwjZ4t9dXsljdOcx59s6dIQ0GnEM8qdKxi/vEx4+M/hbGf
  75. v7H75LsuKRrVJINAmfy9fmc6VAXjFU0ZVxGK5eVnzsh/hY08TSSrlCCKAJpksjJz
  76. AgMBAAGjUzBRMB0GA1UdDgQWBBSZsYWs+8FYe4z4c6LLmFB4TeeV/jAfBgNVHSME
  77. GDAWgBSZsYWs+8FYe4z4c6LLmFB4TeeV/jAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
  78. SIb3DQEBCwUAA4IBAQAcXt/FaILkOCMj8bTUx42vi2N9ZTiEuRbYi24IyGOokbDR
  79. pSsIxiz+HDPUuX6/X/mHidl24aS9wdv5JTXMr44/BeGK1WC7gMueZBxAqONpaG1Q
  80. VU0e3q1YwXKcupKQ7kVWl0fuY3licv0+s4zBcTLKkmWAYqsb/n0KtCMyqewi+Rqa
  81. Zj5Z3OcWOq9Ad9fZWKcG8k/sgeTk9z0X1mZcEyWWxqsUmxvN+SdWLoug1xJVVbMN
  82. CipZ0vBIi9KOhQgzuIFhoTcd6myUtov52/EFqlX6UuFpY2gEWw/f/yu+SI08v4w9
  83. KwxgAKBkhx2JYZKtu1EsPIMDyS0aahcDnHqnrGAi
  84. -----END CERTIFICATE-----`
  85. var clientPrvKey = `-----BEGIN RSA PRIVATE KEY-----
  86. MIIEowIBAAKCAQEA5ZLmMBdKkVyVmN0VhDSFGvgKp24ejHPCv+wfuf3vlU9cwKfH
  87. R3vejleZAVRcidscfA0Jsub/Glsr0XwecagtpvTI+Fp1ik6sICOz+VW3958qaAi8
  88. TjbUMjcDHJeSLcjr725CH5uIvhRzR+daYaJQhAcL2MEt8M9WIF6AjtDZEH9R6oM8
  89. t5FkO0amImlnipYXNBFghmzkZzfGXXRQLw2A+u6keLcjCrn9h2BaofGIjQfYcu/3
  90. fH4cIFR4z/soGKameqnCUz7dWmbf4tAI+8QR0VXXBKhiHDm98tPSeH994hC52Uul
  91. rjEVcM5Uox5hazS2PK06oSc1YuFZONqeeGqj6wIDAQABAoIBADERzRHKaK3ZVEBw
  92. QQEZGLpC+kP/TZhHxgCvv7hJhsQrSnADbJzi5RcXsiSOm5j7tILvZntO1IgVpLAK
  93. D5fLkrZ069/pteXyGuhjuTw6DjBnXPEPrPAq2ABDse6SlzQiFgv/TTLkU74NMPbV
  94. hIQJ5ZvSxb12zRMDviz9Bg2ApmTX6k2iPjQBnEHgKzb64IdMcEb5HE1qNt0v0lRA
  95. sGBMZZKQWbt2m0pSbAbnB3S9GcpJkRgFFMdTaUScIWO6ICT2hBP2pw2/4M2Zrmlt
  96. bsyWu9uswBzhvu+/pg2E66V6mji0EzDMlXqjlO5jro6t7P33t1zkd/i/ykKmtDLp
  97. IpR94UECgYEA9Y4EIjOyaBWJ6TRQ6a/tehGPbwIOgvEiTYXRJqdU49qn/i4YZjSm
  98. F4iibJz+JeOIQXSwa9F7gRlaspIuHgIJoer7BrITMuhr+afqMLkxK0pijul/qAbm
  99. HdpFn8IxjpNu4/GoAENbEVy50SMST9yWh5ulEkHHftd4/NJKoJQ2PZ8CgYEA71bb
  100. lFVh1MFclxRKECmpyoqUAzwGlMoHJy/jaBYuWG4X7rzxqDRrgPH3as6gXpRiSZ+K
  101. 5fC+wcU7dKnHtJOkBDk6J5ev2+hbwg+yq3w4+l3bPDvf2TJyXjXjRDZo12pxFD58
  102. ybCOF6ItbIDXqT5pvo3PMjgMwu1Ycie+h6hA3jUCgYEAsq93XpQT/R2/T44cWxEE
  103. VFG2+GacvLhP5+26ttAJPA1/Nb3BT458Vp+84iCT6GpcWpVZU/wKTXVvxIYPPRLq
  104. g4MEzGiFBASRngiMqIv6ta/ZbHmJxXHPvmV5SLn9aezrQsA1KovZFxdMuF03FBpH
  105. B8NBKbnoO+r8Ra2ZVKTFm60CgYAZw8Dpi/N3IsWj4eRDLyj/C8H5Qyn2NHVmq4oQ
  106. d2rPzDI5Wg+tqs7z15hp4Ap1hAW8pTcfn7X5SBEpculzr/0VE1AGWRbuVmoiTuxN
  107. 95ZupVHnfw6O5BZZu/VWL4FDx0qbAksOrznso2G+b3RH3NcnUz69yjjddw1xZIPn
  108. OJ6bDQKBgDUcWYu/2amU18D5vJpppUgRq2084WPUeXsaniTbmWfOC8NAn8CKLY0N
  109. V4yGSu98apDuqEVqL0VFQEgqK+5KTvRdXXYi36XYRbbVUgV13xveq2YTvjNbPM60
  110. QWG9YmgH7hVYGusuh5nQeS0qiIpwyws2H5mBVrGXrQ1Xb0MLWj8/
  111. -----END RSA PRIVATE KEY-----`
  112. // signed using the Root (rootCAPK)
  113. var clientPubKey = `-----BEGIN CERTIFICATE-----
  114. MIIDWDCCAkACCQCHoh4OvUySOzANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQGEwJV
  115. UzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxITAfBgNVBAoM
  116. GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDESMBAGA1UEAwwJbG9jYWxob3N0MCAX
  117. DTE4MDUxODA2NDQ0NVoYDzMwMTcwOTE4MDY0NDQ1WjBxMQswCQYDVQQGEwJVUzET
  118. MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEhMB8G
  119. A1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDDAlsb2NhbGhv
  120. c3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDlkuYwF0qRXJWY3RWE
  121. NIUa+Aqnbh6Mc8K/7B+5/e+VT1zAp8dHe96OV5kBVFyJ2xx8DQmy5v8aWyvRfB5x
  122. qC2m9Mj4WnWKTqwgI7P5Vbf3nypoCLxONtQyNwMcl5ItyOvvbkIfm4i+FHNH51ph
  123. olCEBwvYwS3wz1YgXoCO0NkQf1Hqgzy3kWQ7RqYiaWeKlhc0EWCGbORnN8ZddFAv
  124. DYD67qR4tyMKuf2HYFqh8YiNB9hy7/d8fhwgVHjP+ygYpqZ6qcJTPt1aZt/i0Aj7
  125. xBHRVdcEqGIcOb3y09J4f33iELnZS6WuMRVwzlSjHmFrNLY8rTqhJzVi4Vk42p54
  126. aqPrAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIQmlo8iCpyYggkbpfDmThBPHfy1
  127. cZcCi/tRFoFe1ccwn2ezLMIKmW38ZebiroawwqrZgU6AP+dMxVKLMjpyLPSrpFKa
  128. 3o/LbVF7qMfH8/y2q8t7javd6rxoENH9uxLyHhauzI1iWy0whoDWBNiZrPBTBCjq
  129. jDGZARZqGyrPeXi+RNe1cMvZCxAFy7gqEtWFLWWrp0gYNPvxkHhhQBrUcF+8T/Nf
  130. 9G4hKZSN/KAgC0CNBVuNrdyNc3l8H66BfwwL5X0+pesBYZM+MEfmBZOo+p7OWx2r
  131. ug8tR8eSL1vGleONtFRBUVG7NbtjhBf9FhvPZcSRR10od/vWHku9E01i4xg=
  132. -----END CERTIFICATE-----`
  133. func truncateIfExists(filename string) error {
  134. if _, err := os.Stat(filename); !os.IsNotExist(err) {
  135. return os.Truncate(filename, 0)
  136. }
  137. return nil
  138. }
  139. func deleteIfExists(filename string) error {
  140. if _, err := os.Stat(filename); !os.IsNotExist(err) {
  141. return os.Remove(filename)
  142. }
  143. return nil
  144. }
  145. func cleanTestArtifacts(t *testing.T) {
  146. if err := deleteIfExists("rootca.test.pem"); err != nil {
  147. t.Error(err)
  148. }
  149. if err := deleteIfExists("client.test.key"); err != nil {
  150. t.Error(err)
  151. }
  152. if err := deleteIfExists("client.test.pem"); err != nil {
  153. t.Error(err)
  154. }
  155. if err := deleteIfExists("./tests/mail.guerrillamail.com.key.pem"); err != nil {
  156. t.Error(err)
  157. }
  158. if err := deleteIfExists("./tests/mail.guerrillamail.com.cert.pem"); err != nil {
  159. t.Error(err)
  160. }
  161. if err := deleteIfExists("./tests/different-go-guerrilla.pid"); err != nil {
  162. t.Error(err)
  163. }
  164. if err := deleteIfExists("./tests/go-guerrilla.pid"); err != nil {
  165. t.Error(err)
  166. }
  167. if err := deleteIfExists("./tests/go-guerrilla2.pid"); err != nil {
  168. t.Error(err)
  169. }
  170. if err := deleteIfExists("./tests/pidfile.pid"); err != nil {
  171. t.Error(err)
  172. }
  173. if err := deleteIfExists("./tests/pidfile2.pid"); err != nil {
  174. t.Error(err)
  175. }
  176. if err := truncateIfExists("./tests/testlog"); err != nil {
  177. t.Error(err)
  178. }
  179. if err := truncateIfExists("./tests/testlog2"); err != nil {
  180. t.Error(err)
  181. }
  182. }
  183. func TestTLSConfig(t *testing.T) {
  184. defer cleanTestArtifacts(t)
  185. if err := ioutil.WriteFile("rootca.test.pem", []byte(rootCAPK), 0644); err != nil {
  186. t.Fatal("couldn't create rootca.test.pem file.", err)
  187. return
  188. }
  189. if err := ioutil.WriteFile("client.test.key", []byte(clientPrvKey), 0644); err != nil {
  190. t.Fatal("couldn't create client.test.key file.", err)
  191. return
  192. }
  193. if err := ioutil.WriteFile("client.test.pem", []byte(clientPubKey), 0644); err != nil {
  194. t.Fatal("couldn't create client.test.pem file.", err)
  195. return
  196. }
  197. s := server{}
  198. s.setConfig(&ServerConfig{
  199. TLS: ServerTLSConfig{
  200. StartTLSOn: true,
  201. PrivateKeyFile: "client.test.key",
  202. PublicKeyFile: "client.test.pem",
  203. RootCAs: "rootca.test.pem",
  204. ClientAuthType: "NoClientCert",
  205. Curves: []string{"P521", "P384"},
  206. Ciphers: []string{"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"},
  207. Protocols: []string{"tls1.0", "tls1.2"},
  208. },
  209. })
  210. if err := s.configureSSL(); err != nil {
  211. t.Error(err)
  212. }
  213. c := s.tlsConfigStore.Load().(*tls.Config)
  214. if len(c.CurvePreferences) != 2 {
  215. t.Error("c.CurvePreferences should have two elements")
  216. } else if c.CurvePreferences[0] != tls.CurveP521 && c.CurvePreferences[1] != tls.CurveP384 {
  217. t.Error("c.CurvePreferences curves not setup")
  218. }
  219. if strings.Index(string(c.RootCAs.Subjects()[0]), "Mountain View") == -1 {
  220. t.Error("c.RootCAs not correctly set")
  221. }
  222. if c.ClientAuth != tls.NoClientCert {
  223. t.Error("c.ClientAuth should be tls.NoClientCert")
  224. }
  225. if len(c.CipherSuites) != 2 {
  226. t.Error("c.CipherSuites length should be 2")
  227. }
  228. if c.CipherSuites[0] != tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 && c.CipherSuites[1] != tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA {
  229. t.Error("c.CipherSuites not correctly set ")
  230. }
  231. if c.MinVersion != tls.VersionTLS10 {
  232. t.Error("c.MinVersion should be tls.VersionTLS10")
  233. }
  234. if c.MaxVersion != tls.VersionTLS12 {
  235. t.Error("c.MinVersion should be tls.VersionTLS10")
  236. }
  237. if c.PreferServerCipherSuites != false {
  238. t.Error("PreferServerCipherSuites should be false")
  239. }
  240. }
  241. func TestHandleClient(t *testing.T) {
  242. var mainlog log.Logger
  243. var logOpenError error
  244. defer cleanTestArtifacts(t)
  245. sc := getMockServerConfig()
  246. mainlog, logOpenError = log.GetLogger(sc.LogFile, "debug")
  247. if logOpenError != nil {
  248. mainlog.WithError(logOpenError).Errorf("Failed creating a logger for mock conn [%s]", sc.ListenInterface)
  249. }
  250. conn, server := getMockServerConn(sc, t)
  251. // call the serve.handleClient() func in a goroutine.
  252. client := NewClient(conn.Server, 1, mainlog, mail.NewPool(5))
  253. var wg sync.WaitGroup
  254. wg.Add(1)
  255. go func() {
  256. server.handleClient(client)
  257. wg.Done()
  258. }()
  259. // Wait for the greeting from the server
  260. r := textproto.NewReader(bufio.NewReader(conn.Client))
  261. line, _ := r.ReadLine()
  262. // fmt.Println(line)
  263. w := textproto.NewWriter(bufio.NewWriter(conn.Client))
  264. if err := w.PrintfLine("HELO test.test.com"); err != nil {
  265. t.Error(err)
  266. }
  267. line, _ = r.ReadLine()
  268. //fmt.Println(line)
  269. if err := w.PrintfLine("QUIT"); err != nil {
  270. t.Error(err)
  271. }
  272. line, _ = r.ReadLine()
  273. //fmt.Println("line is:", line)
  274. expected := "221 2.0.0 Bye"
  275. if strings.Index(line, expected) != 0 {
  276. t.Error("expected", expected, "but got:", line)
  277. }
  278. wg.Wait() // wait for handleClient to exit
  279. }
  280. func TestXClient(t *testing.T) {
  281. var mainlog log.Logger
  282. var logOpenError error
  283. defer cleanTestArtifacts(t)
  284. sc := getMockServerConfig()
  285. sc.XClientOn = true
  286. mainlog, logOpenError = log.GetLogger(sc.LogFile, "debug")
  287. if logOpenError != nil {
  288. mainlog.WithError(logOpenError).Errorf("Failed creating a logger for mock conn [%s]", sc.ListenInterface)
  289. }
  290. conn, server := getMockServerConn(sc, t)
  291. // call the serve.handleClient() func in a goroutine.
  292. client := NewClient(conn.Server, 1, mainlog, mail.NewPool(5))
  293. var wg sync.WaitGroup
  294. wg.Add(1)
  295. go func() {
  296. server.handleClient(client)
  297. wg.Done()
  298. }()
  299. // Wait for the greeting from the server
  300. r := textproto.NewReader(bufio.NewReader(conn.Client))
  301. line, _ := r.ReadLine()
  302. // fmt.Println(line)
  303. w := textproto.NewWriter(bufio.NewWriter(conn.Client))
  304. if err := w.PrintfLine("HELO test.test.com"); err != nil {
  305. t.Error(err)
  306. }
  307. line, _ = r.ReadLine()
  308. //fmt.Println(line)
  309. if err := w.PrintfLine("XCLIENT ADDR=212.96.64.216 NAME=[UNAVAILABLE]"); err != nil {
  310. t.Error(err)
  311. }
  312. line, _ = r.ReadLine()
  313. if client.RemoteIP != "212.96.64.216" {
  314. t.Error("client.RemoteIP should be 212.96.64.216, but got:", client.RemoteIP)
  315. }
  316. expected := "250 2.1.0 OK"
  317. if strings.Index(line, expected) != 0 {
  318. t.Error("expected", expected, "but got:", line)
  319. }
  320. // try malformed input
  321. if err := w.PrintfLine("XCLIENT c"); err != nil {
  322. t.Error(err)
  323. }
  324. line, _ = r.ReadLine()
  325. expected = "250 2.1.0 OK"
  326. if strings.Index(line, expected) != 0 {
  327. t.Error("expected", expected, "but got:", line)
  328. }
  329. if err := w.PrintfLine("QUIT"); err != nil {
  330. t.Error(err)
  331. }
  332. line, _ = r.ReadLine()
  333. wg.Wait() // wait for handleClient to exit
  334. }
  335. // The backend gateway should time out after 1 second because it sleeps for 2 sec.
  336. // The transaction should wait until finished, and then test to see if we can do
  337. // a second transaction
  338. func TestGatewayTimeout(t *testing.T) {
  339. defer cleanTestArtifacts(t)
  340. bcfg := backends.BackendConfig{
  341. "save_workers_size": 1,
  342. "save_process": "HeadersParser|Debugger",
  343. "log_received_mails": true,
  344. "primary_mail_host": "example.com",
  345. "gw_save_timeout": "1s",
  346. "gw_val_rcpt_timeout": "1s",
  347. "sleep_seconds": 2,
  348. }
  349. cfg := &AppConfig{
  350. LogFile: log.OutputOff.String(),
  351. AllowedHosts: []string{"grr.la"},
  352. }
  353. cfg.BackendConfig = bcfg
  354. d := Daemon{Config: cfg}
  355. err := d.Start()
  356. if err != nil {
  357. t.Error("server didn't start")
  358. } else {
  359. conn, err := net.Dial("tcp", "127.0.0.1:2525")
  360. if err != nil {
  361. return
  362. }
  363. in := bufio.NewReader(conn)
  364. str, err := in.ReadString('\n')
  365. if err != nil {
  366. t.Error(err)
  367. }
  368. if _, err := fmt.Fprint(conn, "HELO host\r\n"); err != nil {
  369. t.Error(err)
  370. }
  371. str, err = in.ReadString('\n')
  372. // perform 2 transactions
  373. // both should panic.
  374. for i := 0; i < 2; i++ {
  375. if _, err := fmt.Fprint(conn, "MAIL FROM:<[email protected]>r\r\n"); err != nil {
  376. t.Error(err)
  377. }
  378. if str, err = in.ReadString('\n'); err != nil {
  379. t.Error(err)
  380. }
  381. if _, err := fmt.Fprint(conn, "RCPT TO:<[email protected]>\r\n"); err != nil {
  382. t.Error(err)
  383. }
  384. if str, err = in.ReadString('\n'); err != nil {
  385. t.Error(err)
  386. }
  387. if _, err := fmt.Fprint(conn, "DATA\r\n"); err != nil {
  388. t.Error(err)
  389. }
  390. if str, err = in.ReadString('\n'); err != nil {
  391. t.Error(err)
  392. }
  393. if _, err := fmt.Fprint(conn, "Subject: Test subject\r\n"); err != nil {
  394. t.Error(err)
  395. }
  396. if _, err := fmt.Fprint(conn, "\r\n"); err != nil {
  397. t.Error(err)
  398. }
  399. if _, err := fmt.Fprint(conn, "A an email body\r\n"); err != nil {
  400. t.Error(err)
  401. }
  402. if _, err := fmt.Fprint(conn, ".\r\n"); err != nil {
  403. t.Error(err)
  404. }
  405. str, err = in.ReadString('\n')
  406. expect := "transaction timeout"
  407. if err != nil {
  408. t.Error(err)
  409. } else if strings.Index(str, expect) == -1 {
  410. t.Error("Expected the reply to have'", expect, "'but got", str)
  411. }
  412. }
  413. _ = str
  414. d.Shutdown()
  415. }
  416. }
  417. // The processor will panic and gateway should recover from it
  418. func TestGatewayPanic(t *testing.T) {
  419. defer cleanTestArtifacts(t)
  420. bcfg := backends.BackendConfig{
  421. "save_workers_size": 1,
  422. "save_process": "HeadersParser|Debugger",
  423. "log_received_mails": true,
  424. "primary_mail_host": "example.com",
  425. "gw_save_timeout": "2s",
  426. "gw_val_rcpt_timeout": "2s",
  427. "sleep_seconds": 1,
  428. }
  429. cfg := &AppConfig{
  430. LogFile: log.OutputOff.String(),
  431. AllowedHosts: []string{"grr.la"},
  432. }
  433. cfg.BackendConfig = bcfg
  434. d := Daemon{Config: cfg}
  435. err := d.Start()
  436. if err != nil {
  437. t.Error("server didn't start")
  438. } else {
  439. conn, err := net.Dial("tcp", "127.0.0.1:2525")
  440. if err != nil {
  441. return
  442. }
  443. in := bufio.NewReader(conn)
  444. if _, err := in.ReadString('\n'); err != nil {
  445. t.Error(err)
  446. }
  447. if _, err := fmt.Fprint(conn, "HELO host\r\n"); err != nil {
  448. t.Error(err)
  449. }
  450. if _, err = in.ReadString('\n'); err != nil {
  451. t.Error(err)
  452. }
  453. // perform 2 transactions
  454. // both should timeout. The reason why 2 is because we want to make
  455. // sure that the client waits until processing finishes, and the
  456. // timeout event is captured.
  457. for i := 0; i < 2; i++ {
  458. if _, err := fmt.Fprint(conn, "MAIL FROM:<[email protected]>r\r\n"); err != nil {
  459. t.Error(err)
  460. }
  461. if _, err = in.ReadString('\n'); err != nil {
  462. t.Error(err)
  463. }
  464. if _, err := fmt.Fprint(conn, "RCPT TO:<[email protected]>\r\n"); err != nil {
  465. t.Error(err)
  466. }
  467. if _, err = in.ReadString('\n'); err != nil {
  468. t.Error(err)
  469. }
  470. if _, err := fmt.Fprint(conn, "DATA\r\n"); err != nil {
  471. t.Error(err)
  472. }
  473. if _, err = in.ReadString('\n'); err != nil {
  474. t.Error(err)
  475. }
  476. if _, err := fmt.Fprint(conn, "Subject: Test subject\r\n"); err != nil {
  477. t.Error(err)
  478. }
  479. if _, err := fmt.Fprint(conn, "\r\n"); err != nil {
  480. t.Error(err)
  481. }
  482. if _, err := fmt.Fprint(conn, "A an email body\r\n"); err != nil {
  483. t.Error(err)
  484. }
  485. if _, err := fmt.Fprint(conn, ".\r\n"); err != nil {
  486. t.Error(err)
  487. }
  488. if str, err := in.ReadString('\n'); err != nil {
  489. t.Error(err)
  490. } else {
  491. expect := "storage failed"
  492. if strings.Index(str, expect) == -1 {
  493. t.Error("Expected the reply to have'", expect, "'but got", str)
  494. }
  495. }
  496. }
  497. d.Shutdown()
  498. }
  499. }
  500. func TestAllowsHosts(t *testing.T) {
  501. defer cleanTestArtifacts(t)
  502. s := server{}
  503. allowedHosts := []string{
  504. "spam4.me",
  505. "grr.la",
  506. "newhost.com",
  507. "example.*",
  508. "*.test",
  509. "wild*.card",
  510. "multiple*wild*cards.*",
  511. }
  512. s.setAllowedHosts(allowedHosts)
  513. testTable := map[string]bool{
  514. "spam4.me": true,
  515. "dont.match": false,
  516. "example.com": true,
  517. "another.example.com": false,
  518. "anything.test": true,
  519. "wild.card": true,
  520. "wild.card.com": false,
  521. "multipleXwildXcards.com": true,
  522. }
  523. for host, allows := range testTable {
  524. if res := s.allowsHost(host); res != allows {
  525. t.Error(host, ": expected", allows, "but got", res)
  526. }
  527. }
  528. // only wildcard - should match anything
  529. s.setAllowedHosts([]string{"*"})
  530. if !s.allowsHost("match.me") {
  531. t.Error("match.me: expected true but got false")
  532. }
  533. // turns off
  534. s.setAllowedHosts([]string{"."})
  535. if !s.allowsHost("match.me") {
  536. t.Error("match.me: expected true but got false")
  537. }
  538. // no wilcards
  539. s.setAllowedHosts([]string{"grr.la", "example.com"})
  540. }