1
0

serve_test.go 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. package main
  2. import (
  3. "crypto/tls"
  4. "encoding/json"
  5. "github.com/flashmob/go-guerrilla"
  6. "github.com/flashmob/go-guerrilla/backends"
  7. "github.com/flashmob/go-guerrilla/log"
  8. test "github.com/flashmob/go-guerrilla/tests"
  9. "github.com/flashmob/go-guerrilla/tests/testcert"
  10. "github.com/spf13/cobra"
  11. "io/ioutil"
  12. "os"
  13. "os/exec"
  14. "runtime"
  15. "strconv"
  16. "strings"
  17. "sync"
  18. "testing"
  19. "time"
  20. )
  21. var configJsonA = `
  22. {
  23. "log_file" : "../../tests/testlog",
  24. "log_level" : "debug",
  25. "pid_file" : "./pidfile.pid",
  26. "allowed_hosts": [
  27. "guerrillamail.com",
  28. "guerrillamailblock.com",
  29. "sharklasers.com",
  30. "guerrillamail.net",
  31. "guerrillamail.org"
  32. ],
  33. "backend_name": "dummy",
  34. "backend_config": {
  35. "log_received_mails": true
  36. },
  37. "servers" : [
  38. {
  39. "is_enabled" : true,
  40. "host_name":"mail.test.com",
  41. "max_size": 1000000,
  42. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  43. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  44. "timeout":180,
  45. "listen_interface":"127.0.0.1:25",
  46. "start_tls_on":true,
  47. "tls_always_on":false,
  48. "max_clients": 1000,
  49. "log_file" : "../../tests/testlog"
  50. },
  51. {
  52. "is_enabled" : false,
  53. "host_name":"enable.test.com",
  54. "max_size": 1000000,
  55. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  56. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  57. "timeout":180,
  58. "listen_interface":"127.0.0.1:2228",
  59. "start_tls_on":true,
  60. "tls_always_on":false,
  61. "max_clients": 1000,
  62. "log_file" : "../../tests/testlog"
  63. }
  64. ]
  65. }
  66. `
  67. // backend config changed, log_received_mails is false
  68. var configJsonB = `
  69. {
  70. "log_file" : "../../tests/testlog",
  71. "log_level" : "debug",
  72. "pid_file" : "./pidfile2.pid",
  73. "allowed_hosts": [
  74. "guerrillamail.com",
  75. "guerrillamailblock.com",
  76. "sharklasers.com",
  77. "guerrillamail.net",
  78. "guerrillamail.org"
  79. ],
  80. "backend_name": "dummy",
  81. "backend_config": {
  82. "log_received_mails": false
  83. },
  84. "servers" : [
  85. {
  86. "is_enabled" : true,
  87. "host_name":"mail.test.com",
  88. "max_size": 1000000,
  89. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  90. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  91. "timeout":180,
  92. "listen_interface":"127.0.0.1:25",
  93. "start_tls_on":true,
  94. "tls_always_on":false,
  95. "max_clients": 1000,
  96. "log_file" : "../../tests/testlog"
  97. }
  98. ]
  99. }
  100. `
  101. // backend_name changed, is guerrilla-redis-db + added a server
  102. var configJsonC = `
  103. {
  104. "log_file" : "../../tests/testlog",
  105. "log_level" : "debug",
  106. "pid_file" : "./pidfile.pid",
  107. "allowed_hosts": [
  108. "guerrillamail.com",
  109. "guerrillamailblock.com",
  110. "sharklasers.com",
  111. "guerrillamail.net",
  112. "guerrillamail.org"
  113. ],
  114. "backend_name": "guerrilla-redis-db",
  115. "backend_config" :
  116. {
  117. "mysql_db":"gmail_mail",
  118. "mysql_host":"127.0.0.1:3306",
  119. "mysql_pass":"ok",
  120. "mysql_user":"root",
  121. "mail_table":"new_mail",
  122. "redis_interface" : "127.0.0.1:6379",
  123. "redis_expire_seconds" : 7200,
  124. "save_workers_size" : 3,
  125. "primary_mail_host":"sharklasers.com"
  126. },
  127. "servers" : [
  128. {
  129. "is_enabled" : true,
  130. "host_name":"mail.test.com",
  131. "max_size": 1000000,
  132. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  133. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  134. "timeout":180,
  135. "listen_interface":"127.0.0.1:25",
  136. "start_tls_on":true,
  137. "tls_always_on":false,
  138. "max_clients": 1000,
  139. "log_file" : "../../tests/testlog"
  140. },
  141. {
  142. "is_enabled" : true,
  143. "host_name":"mail.test.com",
  144. "max_size":1000000,
  145. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  146. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  147. "timeout":180,
  148. "listen_interface":"127.0.0.1:465",
  149. "start_tls_on":false,
  150. "tls_always_on":true,
  151. "max_clients":500,
  152. "log_file" : "../../tests/testlog"
  153. }
  154. ]
  155. }
  156. `
  157. // adds 127.0.0.1:4655, a secure server
  158. var configJsonD = `
  159. {
  160. "log_file" : "../../tests/testlog",
  161. "log_level" : "debug",
  162. "pid_file" : "./pidfile.pid",
  163. "allowed_hosts": [
  164. "guerrillamail.com",
  165. "guerrillamailblock.com",
  166. "sharklasers.com",
  167. "guerrillamail.net",
  168. "guerrillamail.org"
  169. ],
  170. "backend_name": "dummy",
  171. "backend_config": {
  172. "log_received_mails": false
  173. },
  174. "servers" : [
  175. {
  176. "is_enabled" : true,
  177. "host_name":"mail.test.com",
  178. "max_size": 1000000,
  179. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  180. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  181. "timeout":180,
  182. "listen_interface":"127.0.0.1:2552",
  183. "start_tls_on":true,
  184. "tls_always_on":false,
  185. "max_clients": 1000,
  186. "log_file" : "../../tests/testlog"
  187. },
  188. {
  189. "is_enabled" : true,
  190. "host_name":"secure.test.com",
  191. "max_size":1000000,
  192. "private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
  193. "public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
  194. "timeout":180,
  195. "listen_interface":"127.0.0.1:4655",
  196. "start_tls_on":false,
  197. "tls_always_on":true,
  198. "max_clients":500,
  199. "log_file" : "../../tests/testlog"
  200. }
  201. ]
  202. }
  203. `
  204. const testPauseDuration = time.Millisecond * 600
  205. // reload config
  206. func sigHup() {
  207. if data, err := ioutil.ReadFile("pidfile.pid"); err == nil {
  208. mainlog.Infof("pid read is %s", data)
  209. ecmd := exec.Command("kill", "-HUP", string(data))
  210. _, err = ecmd.Output()
  211. if err != nil {
  212. mainlog.Infof("could not SIGHUP", err)
  213. }
  214. } else {
  215. mainlog.WithError(err).Info("sighup - Could not read pidfle")
  216. }
  217. }
  218. // shutdown after calling serve()
  219. func sigKill() {
  220. if data, err := ioutil.ReadFile("pidfile.pid"); err == nil {
  221. mainlog.Infof("pid read is %s", data)
  222. ecmd := exec.Command("kill", string(data))
  223. _, err = ecmd.Output()
  224. if err != nil {
  225. mainlog.Infof("could not sigkill", err)
  226. }
  227. } else {
  228. mainlog.WithError(err).Info("sigKill - Could not read pidfle")
  229. }
  230. }
  231. // make sure that we get all the config change events
  232. func TestCmdConfigChangeEvents(t *testing.T) {
  233. oldconf := &CmdConfig{}
  234. oldconf.load([]byte(configJsonA))
  235. newconf := &CmdConfig{}
  236. newconf.load([]byte(configJsonB))
  237. newerconf := &CmdConfig{}
  238. newerconf.load([]byte(configJsonC))
  239. expectedEvents := map[guerrilla.Event]bool{
  240. guerrilla.EventConfigBackendConfig: false,
  241. guerrilla.EventConfigBackendName: false,
  242. guerrilla.EventConfigEvServerNew: false,
  243. }
  244. mainlog, _ = log.GetLogger("off")
  245. bcfg := backends.BackendConfig{"log_received_mails": true}
  246. backend, err := backends.New("dummy", bcfg, mainlog)
  247. app, err := guerrilla.New(&oldconf.AppConfig, backend, mainlog)
  248. if err != nil {
  249. //log.Info("Failed to create new app", err)
  250. }
  251. toUnsubscribe := map[guerrilla.Event]func(c *CmdConfig){}
  252. toUnsubscribeS := map[guerrilla.Event]func(c *guerrilla.ServerConfig){}
  253. for event := range expectedEvents {
  254. // Put in anon func since range is overwriting event
  255. func(e guerrilla.Event) {
  256. if strings.Index(e.String(), "server_change") == 0 {
  257. f := func(c *guerrilla.ServerConfig) {
  258. expectedEvents[e] = true
  259. }
  260. app.Subscribe(event, f)
  261. toUnsubscribeS[event] = f
  262. } else {
  263. f := func(c *CmdConfig) {
  264. expectedEvents[e] = true
  265. }
  266. app.Subscribe(event, f)
  267. toUnsubscribe[event] = f
  268. }
  269. }(event)
  270. }
  271. // emit events
  272. newconf.emitChangeEvents(oldconf, app)
  273. newerconf.emitChangeEvents(newconf, app)
  274. // unsubscribe
  275. for unevent, unfun := range toUnsubscribe {
  276. app.Unsubscribe(unevent, unfun)
  277. }
  278. for event, val := range expectedEvents {
  279. if val == false {
  280. t.Error("Did not fire config change event:", event)
  281. t.FailNow()
  282. break
  283. }
  284. }
  285. // cleanup
  286. os.Truncate("../../tests/testlog", 0)
  287. }
  288. // start server, change config, send SIG HUP, confirm that the pidfile changed & backend reloaded
  289. func TestServe(t *testing.T) {
  290. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  291. mainlog, _ = log.GetLogger("../../tests/testlog")
  292. ioutil.WriteFile("configJsonA.json", []byte(configJsonA), 0644)
  293. cmd := &cobra.Command{}
  294. configPath = "configJsonA.json"
  295. var serveWG sync.WaitGroup
  296. serveWG.Add(1)
  297. go func() {
  298. serve(cmd, []string{})
  299. serveWG.Done()
  300. }()
  301. time.Sleep(testPauseDuration)
  302. data, err := ioutil.ReadFile("pidfile.pid")
  303. if err != nil {
  304. t.Error("error reading pidfile.pid", err)
  305. t.FailNow()
  306. }
  307. _, err = strconv.Atoi(string(data))
  308. if err != nil {
  309. t.Error("could not parse pidfile.pid", err)
  310. t.FailNow()
  311. }
  312. // change the config file
  313. ioutil.WriteFile("configJsonA.json", []byte(configJsonB), 0644)
  314. // test SIGHUP via the kill command
  315. // Would not work on windows as kill is not available.
  316. // TODO: Implement an alternative test for windows.
  317. if runtime.GOOS != "windows" {
  318. ecmd := exec.Command("kill", "-HUP", string(data))
  319. _, err = ecmd.Output()
  320. if err != nil {
  321. t.Error("could not SIGHUP", err)
  322. t.FailNow()
  323. }
  324. time.Sleep(testPauseDuration) // allow sighup to do its job
  325. // did the pidfile change as expected?
  326. if _, err := os.Stat("./pidfile2.pid"); os.IsNotExist(err) {
  327. t.Error("pidfile not changed after sighup SIGHUP", err)
  328. }
  329. }
  330. // send kill signal and wait for exit
  331. sigKill()
  332. serveWG.Wait()
  333. // did backend started as expected?
  334. fd, err := os.Open("../../tests/testlog")
  335. if err != nil {
  336. t.Error(err)
  337. }
  338. if read, err := ioutil.ReadAll(fd); err == nil {
  339. logOutput := string(read)
  340. if i := strings.Index(logOutput, "Backend started:dummy"); i < 0 {
  341. t.Error("Dummy backend not restared")
  342. }
  343. }
  344. // cleanup
  345. os.Truncate("../../tests/testlog", 0)
  346. os.Remove("configJsonA.json")
  347. os.Remove("./pidfile.pid")
  348. os.Remove("./pidfile2.pid")
  349. }
  350. // Start with configJsonA.json,
  351. // then add a new server to it (127.0.0.1:2526),
  352. // then SIGHUP (to reload config & trigger config update events),
  353. // then connect to it & HELO.
  354. func TestServerAddEvent(t *testing.T) {
  355. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  356. mainlog, _ = log.GetLogger("../../tests/testlog")
  357. // start the server by emulating the serve command
  358. ioutil.WriteFile("configJsonA.json", []byte(configJsonA), 0644)
  359. cmd := &cobra.Command{}
  360. configPath = "configJsonA.json"
  361. var serveWG sync.WaitGroup
  362. serveWG.Add(1)
  363. go func() {
  364. serve(cmd, []string{})
  365. serveWG.Done()
  366. }()
  367. time.Sleep(testPauseDuration) // allow the server to start
  368. // now change the config by adding a server
  369. conf := &CmdConfig{} // blank one
  370. conf.load([]byte(configJsonA)) // load configJsonA
  371. newServer := conf.Servers[0] // copy the first server config
  372. newServer.ListenInterface = "127.0.0.1:2526" // change it
  373. newConf := conf // copy the cmdConfg
  374. newConf.Servers = append(newConf.Servers, newServer) // add the new server
  375. if jsonbytes, err := json.Marshal(newConf); err == nil {
  376. //fmt.Println(string(jsonbytes))
  377. ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644)
  378. }
  379. // send a sighup signal to the server
  380. sigHup()
  381. time.Sleep(testPauseDuration) // pause for config to reload
  382. if conn, buffin, err := test.Connect(newServer, 20); err != nil {
  383. t.Error("Could not connect to new server", newServer.ListenInterface)
  384. } else {
  385. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  386. expect := "250 mail.test.com Hello"
  387. if strings.Index(result, expect) != 0 {
  388. t.Error("Expected", expect, "but got", result)
  389. }
  390. } else {
  391. t.Error(err)
  392. }
  393. }
  394. // send kill signal and wait for exit
  395. sigKill()
  396. serveWG.Wait()
  397. // did backend started as expected?
  398. fd, _ := os.Open("../../tests/testlog")
  399. if read, err := ioutil.ReadAll(fd); err == nil {
  400. logOutput := string(read)
  401. //fmt.Println(logOutput)
  402. if i := strings.Index(logOutput, "New server added [127.0.0.1:2526]"); i < 0 {
  403. t.Error("Did not add [127.0.0.1:2526], most likely because Bus.Subscribe(\"server_change:new_server\" didnt fire")
  404. }
  405. }
  406. // cleanup
  407. os.Truncate("../../tests/testlog", 0)
  408. os.Remove("configJsonA.json")
  409. os.Remove("./pidfile.pid")
  410. }
  411. // Start with configJsonA.json,
  412. // then change the config to enable 127.0.0.1:2228,
  413. // then write the new config,
  414. // then SIGHUP (to reload config & trigger config update events),
  415. // then connect to 127.0.0.1:2228 & HELO.
  416. func TestServerStartEvent(t *testing.T) {
  417. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  418. mainlog, _ = log.GetLogger("../../tests/testlog")
  419. // start the server by emulating the serve command
  420. ioutil.WriteFile("configJsonA.json", []byte(configJsonA), 0644)
  421. cmd := &cobra.Command{}
  422. configPath = "configJsonA.json"
  423. var serveWG sync.WaitGroup
  424. serveWG.Add(1)
  425. go func() {
  426. serve(cmd, []string{})
  427. serveWG.Done()
  428. }()
  429. time.Sleep(testPauseDuration)
  430. // now change the config by adding a server
  431. conf := &CmdConfig{} // blank one
  432. conf.load([]byte(configJsonA)) // load configJsonA
  433. newConf := conf // copy the cmdConfg
  434. newConf.Servers[1].IsEnabled = true
  435. if jsonbytes, err := json.Marshal(newConf); err == nil {
  436. //fmt.Println(string(jsonbytes))
  437. ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644)
  438. } else {
  439. t.Error(err)
  440. }
  441. // send a sighup signal to the server
  442. sigHup()
  443. time.Sleep(testPauseDuration) // pause for config to reload
  444. if conn, buffin, err := test.Connect(newConf.Servers[1], 20); err != nil {
  445. t.Error("Could not connect to new server", newConf.Servers[1].ListenInterface)
  446. } else {
  447. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  448. expect := "250 enable.test.com Hello"
  449. if strings.Index(result, expect) != 0 {
  450. t.Error("Expected", expect, "but got", result)
  451. }
  452. } else {
  453. t.Error(err)
  454. }
  455. }
  456. // send kill signal and wait for exit
  457. sigKill()
  458. serveWG.Wait()
  459. // did backend started as expected?
  460. fd, _ := os.Open("../../tests/testlog")
  461. if read, err := ioutil.ReadAll(fd); err == nil {
  462. logOutput := string(read)
  463. //fmt.Println(logOutput)
  464. if i := strings.Index(logOutput, "Starting server [127.0.0.1:2228]"); i < 0 {
  465. t.Error("did not add [127.0.0.1:2228], most likely because Bus.Subscribe(\"server_change:start_server\" didnt fire")
  466. }
  467. }
  468. // cleanup
  469. os.Truncate("../../tests/testlog", 0)
  470. os.Remove("configJsonA.json")
  471. os.Remove("./pidfile.pid")
  472. }
  473. // Start with configJsonA.json,
  474. // then change the config to enable 127.0.0.1:2228,
  475. // then write the new config,
  476. // then SIGHUP (to reload config & trigger config update events),
  477. // then connect to 127.0.0.1:2228 & HELO.
  478. // then change the config to dsiable 127.0.0.1:2228,
  479. // then SIGHUP (to reload config & trigger config update events),
  480. // then connect to 127.0.0.1:2228 - it should not connect
  481. func TestServerStopEvent(t *testing.T) {
  482. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  483. mainlog, _ = log.GetLogger("../../tests/testlog")
  484. // start the server by emulating the serve command
  485. ioutil.WriteFile("configJsonA.json", []byte(configJsonA), 0644)
  486. cmd := &cobra.Command{}
  487. configPath = "configJsonA.json"
  488. var serveWG sync.WaitGroup
  489. serveWG.Add(1)
  490. go func() {
  491. serve(cmd, []string{})
  492. serveWG.Done()
  493. }()
  494. time.Sleep(testPauseDuration)
  495. // now change the config by enabling a server
  496. conf := &CmdConfig{} // blank one
  497. conf.load([]byte(configJsonA)) // load configJsonA
  498. newConf := conf // copy the cmdConfg
  499. newConf.Servers[1].IsEnabled = true
  500. if jsonbytes, err := json.Marshal(newConf); err == nil {
  501. //fmt.Println(string(jsonbytes))
  502. ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644)
  503. } else {
  504. t.Error(err)
  505. }
  506. // send a sighup signal to the server
  507. sigHup()
  508. time.Sleep(testPauseDuration) // pause for config to reload
  509. if conn, buffin, err := test.Connect(newConf.Servers[1], 20); err != nil {
  510. t.Error("Could not connect to new server", newConf.Servers[1].ListenInterface)
  511. } else {
  512. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  513. expect := "250 enable.test.com Hello"
  514. if strings.Index(result, expect) != 0 {
  515. t.Error("Expected", expect, "but got", result)
  516. }
  517. } else {
  518. t.Error(err)
  519. }
  520. conn.Close()
  521. }
  522. // now disable the server
  523. newerConf := newConf // copy the cmdConfg
  524. newerConf.Servers[1].IsEnabled = false
  525. if jsonbytes, err := json.Marshal(newerConf); err == nil {
  526. //fmt.Println(string(jsonbytes))
  527. ioutil.WriteFile("configJsonA.json", []byte(jsonbytes), 0644)
  528. } else {
  529. t.Error(err)
  530. }
  531. // send a sighup signal to the server
  532. sigHup()
  533. time.Sleep(testPauseDuration) // pause for config to reload
  534. // it should not connect to the server
  535. if _, _, err := test.Connect(newConf.Servers[1], 20); err == nil {
  536. t.Error("127.0.0.1:2228 was disabled, but still accepting connections", newConf.Servers[1].ListenInterface)
  537. }
  538. // send kill signal and wait for exit
  539. sigKill()
  540. serveWG.Wait()
  541. // did backend started as expected?
  542. fd, _ := os.Open("../../tests/testlog")
  543. if read, err := ioutil.ReadAll(fd); err == nil {
  544. logOutput := string(read)
  545. //fmt.Println(logOutput)
  546. if i := strings.Index(logOutput, "Server [127.0.0.1:2228] stopped"); i < 0 {
  547. t.Error("did not stop [127.0.0.1:2228], most likely because Bus.Subscribe(\"server_change:stop_server\" didnt fire")
  548. }
  549. }
  550. // cleanup
  551. os.Truncate("../../tests/testlog", 0)
  552. os.Remove("configJsonA.json")
  553. os.Remove("./pidfile.pid")
  554. }
  555. // Start with configJsonD.json,
  556. // then connect to 127.0.0.1:4655 & HELO & try RCPT TO with an invalid host [grr.la]
  557. // then change the config to enable add new host [grr.la] to allowed_hosts
  558. // then write the new config,
  559. // then SIGHUP (to reload config & trigger config update events),
  560. // connect to 127.0.0.1:4655 & HELO & try RCPT TO, grr.la should work
  561. func TestAllowedHostsEvent(t *testing.T) {
  562. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  563. mainlog, _ = log.GetLogger("../../tests/testlog")
  564. // start the server by emulating the serve command
  565. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  566. conf := &CmdConfig{} // blank one
  567. conf.load([]byte(configJsonD)) // load configJsonD
  568. cmd := &cobra.Command{}
  569. configPath = "configJsonD.json"
  570. var serveWG sync.WaitGroup
  571. time.Sleep(testPauseDuration)
  572. serveWG.Add(1)
  573. go func() {
  574. serve(cmd, []string{})
  575. serveWG.Done()
  576. }()
  577. time.Sleep(testPauseDuration)
  578. // now connect and try RCPT TO with an invalid host
  579. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[1], 20); err != nil {
  580. t.Error("Could not connect to new server", conf.AppConfig.Servers[1].ListenInterface, err)
  581. } else {
  582. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  583. expect := "250 secure.test.com Hello"
  584. if strings.Index(result, expect) != 0 {
  585. t.Error("Expected", expect, "but got", result)
  586. } else {
  587. if result, err = test.Command(conn, buffin, "RCPT TO:[email protected]"); err == nil {
  588. expect := "454 4.1.1 Error: Relay access denied: grr.la"
  589. if strings.Index(result, expect) != 0 {
  590. t.Error("Expected:", expect, "but got:", result)
  591. }
  592. }
  593. }
  594. }
  595. conn.Close()
  596. }
  597. // now change the config by adding a host to allowed hosts
  598. newConf := conf // copy the cmdConfg
  599. newConf.AllowedHosts = append(newConf.AllowedHosts, "grr.la")
  600. if jsonbytes, err := json.Marshal(newConf); err == nil {
  601. ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644)
  602. } else {
  603. t.Error(err)
  604. }
  605. // send a sighup signal to the server to reload config
  606. sigHup()
  607. time.Sleep(testPauseDuration) // pause for config to reload
  608. // now repeat the same conversion, RCPT TO should be accepted
  609. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[1], 20); err != nil {
  610. t.Error("Could not connect to new server", conf.AppConfig.Servers[1].ListenInterface, err)
  611. } else {
  612. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  613. expect := "250 secure.test.com Hello"
  614. if strings.Index(result, expect) != 0 {
  615. t.Error("Expected", expect, "but got", result)
  616. } else {
  617. if result, err = test.Command(conn, buffin, "RCPT TO:[email protected]"); err == nil {
  618. expect := "250 2.1.5 OK"
  619. if strings.Index(result, expect) != 0 {
  620. t.Error("Expected:", expect, "but got:", result)
  621. }
  622. }
  623. }
  624. }
  625. conn.Close()
  626. }
  627. // send kill signal and wait for exit
  628. sigKill()
  629. serveWG.Wait()
  630. // did backend started as expected?
  631. fd, _ := os.Open("../../tests/testlog")
  632. if read, err := ioutil.ReadAll(fd); err == nil {
  633. logOutput := string(read)
  634. //fmt.Println(logOutput)
  635. if i := strings.Index(logOutput, "allowed_hosts config changed, a new list was set"); i < 0 {
  636. t.Errorf("did not change allowed_hosts, most likely because Bus.Subscribe(\"%s\" didnt fire",
  637. guerrilla.EventConfigAllowedHosts)
  638. }
  639. }
  640. // cleanup
  641. os.Truncate("../../tests/testlog", 0)
  642. os.Remove("configJsonD.json")
  643. os.Remove("./pidfile.pid")
  644. }
  645. // Test TLS config change event
  646. // start with configJsonD
  647. // should be able to STARTTLS to 127.0.0.1:2525 with no problems
  648. // generate new certs & reload config
  649. // should get a new tls event & able to STARTTLS with no problem
  650. func TestTLSConfigEvent(t *testing.T) {
  651. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  652. // pause for generated cert to output on slow machines
  653. time.Sleep(testPauseDuration)
  654. // did cert output?
  655. if _, err := os.Stat("../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  656. t.Error("Did not create cert ", err)
  657. }
  658. mainlog, _ = log.GetLogger("../../tests/testlog")
  659. // start the server by emulating the serve command
  660. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  661. conf := &CmdConfig{} // blank one
  662. conf.load([]byte(configJsonD)) // load configJsonD
  663. cmd := &cobra.Command{}
  664. configPath = "configJsonD.json"
  665. var serveWG sync.WaitGroup
  666. serveWG.Add(1)
  667. go func() {
  668. serve(cmd, []string{})
  669. serveWG.Done()
  670. }()
  671. time.Sleep(testPauseDuration)
  672. // Test STARTTLS handshake
  673. testTlsHandshake := func() {
  674. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  675. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  676. } else {
  677. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  678. expect := "250 mail.test.com Hello"
  679. if strings.Index(result, expect) != 0 {
  680. t.Error("Expected", expect, "but got", result)
  681. } else {
  682. if result, err = test.Command(conn, buffin, "STARTTLS"); err == nil {
  683. expect := "220 2.0.0 Ready to start TLS"
  684. if strings.Index(result, expect) != 0 {
  685. t.Error("Expected:", expect, "but got:", result)
  686. } else {
  687. tlsConn := tls.Client(conn, &tls.Config{
  688. InsecureSkipVerify: true,
  689. ServerName: "127.0.0.1",
  690. })
  691. if err := tlsConn.Handshake(); err != nil {
  692. t.Error("Failed to handshake", conf.AppConfig.Servers[0].ListenInterface)
  693. } else {
  694. conn = tlsConn
  695. mainlog.Info("TLS Handshake succeeded")
  696. }
  697. }
  698. }
  699. }
  700. }
  701. conn.Close()
  702. }
  703. }
  704. testTlsHandshake()
  705. if err := os.Remove("../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  706. t.Error("could not remove cert", err)
  707. }
  708. if err := os.Remove("../../tests/mail2.guerrillamail.com.key.pem"); err != nil {
  709. t.Error("could not remove key", err)
  710. }
  711. // generate a new cert
  712. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  713. // pause for generated cert to output
  714. time.Sleep(testPauseDuration)
  715. // did cert output?
  716. if _, err := os.Stat("../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  717. t.Error("Did not create cert ", err)
  718. }
  719. sigHup()
  720. time.Sleep(testPauseDuration * 2) // pause for config to reload
  721. testTlsHandshake()
  722. //time.Sleep(testPauseDuration)
  723. // send kill signal and wait for exit
  724. sigKill()
  725. serveWG.Wait()
  726. // did backend started as expected?
  727. fd, _ := os.Open("../../tests/testlog")
  728. if read, err := ioutil.ReadAll(fd); err == nil {
  729. logOutput := string(read)
  730. //fmt.Println(logOutput)
  731. if i := strings.Index(logOutput, "Server [127.0.0.1:2552] new TLS configuration loaded"); i < 0 {
  732. t.Error("did not change tls, most likely because Bus.Subscribe(\"server_change:tls_config\" didnt fire")
  733. }
  734. }
  735. // cleanup
  736. os.Truncate("../../tests/testlog", 0)
  737. os.Remove("configJsonD.json")
  738. os.Remove("./pidfile.pid")
  739. }
  740. // Testing starting a server with a bad TLS config
  741. // It should not start, return exit code 1
  742. func TestBadTLSStart(t *testing.T) {
  743. // Need to run the test in a different process by executing a command
  744. // because the serve() does os.Exit when starting with a bad TLS config
  745. if os.Getenv("BE_CRASHER") == "1" {
  746. // do the test
  747. // first, remove the good certs, if any
  748. if err := os.Remove("./../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  749. mainlog.WithError(err).Error("could not remove ./../../tests/mail2.guerrillamail.com.cert.pem")
  750. } else {
  751. mainlog.Info("removed ./../../tests/mail2.guerrillamail.com.cert.pem")
  752. }
  753. // next run the server
  754. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  755. conf := &CmdConfig{} // blank one
  756. conf.load([]byte(configJsonD)) // load configJsonD
  757. cmd := &cobra.Command{}
  758. configPath = "configJsonD.json"
  759. var serveWG sync.WaitGroup
  760. serveWG.Add(1)
  761. go func() {
  762. serve(cmd, []string{})
  763. serveWG.Done()
  764. }()
  765. time.Sleep(testPauseDuration)
  766. sigKill()
  767. serveWG.Wait()
  768. return
  769. }
  770. cmd := exec.Command(os.Args[0], "-test.run=TestBadTLSStart")
  771. cmd.Env = append(os.Environ(), "BE_CRASHER=1")
  772. err := cmd.Run()
  773. if e, ok := err.(*exec.ExitError); ok && !e.Success() {
  774. return
  775. }
  776. t.Error("Server started with a bad TLS config, was expecting exit status 1")
  777. // cleanup
  778. os.Truncate("../../tests/testlog", 0)
  779. os.Remove("configJsonD.json")
  780. os.Remove("./pidfile.pid")
  781. }
  782. // Test config reload with a bad TLS config
  783. // It should ignore the config reload, keep running with old settings
  784. func TestBadTLSReload(t *testing.T) {
  785. mainlog, _ = log.GetLogger("../../tests/testlog")
  786. // start with a good vert
  787. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  788. // start the server by emulating the serve command
  789. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  790. conf := &CmdConfig{} // blank one
  791. conf.load([]byte(configJsonD)) // load configJsonD
  792. cmd := &cobra.Command{}
  793. configPath = "configJsonD.json"
  794. var serveWG sync.WaitGroup
  795. serveWG.Add(1)
  796. go func() {
  797. serve(cmd, []string{})
  798. serveWG.Done()
  799. }()
  800. time.Sleep(testPauseDuration)
  801. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  802. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  803. } else {
  804. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  805. expect := "250 mail.test.com Hello"
  806. if strings.Index(result, expect) != 0 {
  807. t.Error("Expected", expect, "but got", result)
  808. }
  809. }
  810. }
  811. // write some trash data
  812. ioutil.WriteFile("./../../tests/mail2.guerrillamail.com.cert.pem", []byte("trash data"), 0664)
  813. ioutil.WriteFile("./../../tests/mail2.guerrillamail.com.key.pem", []byte("trash data"), 0664)
  814. newConf := conf // copy the cmdConfg
  815. if jsonbytes, err := json.Marshal(newConf); err == nil {
  816. ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644)
  817. } else {
  818. t.Error(err)
  819. }
  820. // send a sighup signal to the server to reload config
  821. sigHup()
  822. time.Sleep(testPauseDuration) // pause for config to reload
  823. // we should still be able to to talk to it
  824. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  825. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  826. } else {
  827. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  828. expect := "250 mail.test.com Hello"
  829. if strings.Index(result, expect) != 0 {
  830. t.Error("Expected", expect, "but got", result)
  831. }
  832. }
  833. }
  834. sigKill()
  835. serveWG.Wait()
  836. // did config reload fail as expected?
  837. fd, _ := os.Open("../../tests/testlog")
  838. if read, err := ioutil.ReadAll(fd); err == nil {
  839. logOutput := string(read)
  840. //fmt.Println(logOutput)
  841. if i := strings.Index(logOutput, "cannot use TLS config for"); i < 0 {
  842. t.Error("[127.0.0.1:2552] did not reject our tls config as expected")
  843. }
  844. }
  845. // cleanup
  846. os.Truncate("../../tests/testlog", 0)
  847. os.Remove("configJsonD.json")
  848. os.Remove("./pidfile.pid")
  849. }
  850. // Test for when the server config Timeout value changes
  851. // Start with configJsonD.json
  852. func TestSetTimeoutEvent(t *testing.T) {
  853. mainlog, _ = log.GetLogger("../../tests/testlog")
  854. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  855. // start the server by emulating the serve command
  856. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  857. conf := &CmdConfig{} // blank one
  858. conf.load([]byte(configJsonD)) // load configJsonD
  859. cmd := &cobra.Command{}
  860. configPath = "configJsonD.json"
  861. var serveWG sync.WaitGroup
  862. serveWG.Add(1)
  863. go func() {
  864. serve(cmd, []string{})
  865. serveWG.Done()
  866. }()
  867. time.Sleep(testPauseDuration)
  868. // set the timeout to 1 second
  869. newConf := conf // copy the cmdConfg
  870. newConf.Servers[0].Timeout = 1
  871. if jsonbytes, err := json.Marshal(newConf); err == nil {
  872. ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644)
  873. } else {
  874. t.Error(err)
  875. }
  876. // send a sighup signal to the server to reload config
  877. sigHup()
  878. time.Sleep(testPauseDuration) // config reload
  879. var waitTimeout sync.WaitGroup
  880. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  881. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  882. } else {
  883. waitTimeout.Add(1)
  884. go func() {
  885. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  886. expect := "250 mail.test.com Hello"
  887. if strings.Index(result, expect) != 0 {
  888. t.Error("Expected", expect, "but got", result)
  889. } else {
  890. b := make([]byte, 1024)
  891. conn.Read(b)
  892. }
  893. }
  894. waitTimeout.Done()
  895. }()
  896. }
  897. // wait for timeout
  898. waitTimeout.Wait()
  899. // so the connection we have opened should timeout by now
  900. // send kill signal and wait for exit
  901. sigKill()
  902. serveWG.Wait()
  903. // did backend started as expected?
  904. fd, _ := os.Open("../../tests/testlog")
  905. if read, err := ioutil.ReadAll(fd); err == nil {
  906. logOutput := string(read)
  907. //fmt.Println(logOutput)
  908. if i := strings.Index(logOutput, "i/o timeout"); i < 0 {
  909. t.Error("Connection to 127.0.0.1:2552 didn't timeout as expected")
  910. }
  911. }
  912. // cleanup
  913. os.Truncate("../../tests/testlog", 0)
  914. os.Remove("configJsonD.json")
  915. os.Remove("./pidfile.pid")
  916. }
  917. // Test debug level config change
  918. // Start in log_level = debug
  919. // Load config & start server
  920. func TestDebugLevelChange(t *testing.T) {
  921. //mainlog, _ = log.GetLogger("../../tests/testlog")
  922. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  923. // start the server by emulating the serve command
  924. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  925. conf := &CmdConfig{} // blank one
  926. conf.load([]byte(configJsonD)) // load configJsonD
  927. conf.LogLevel = "debug"
  928. cmd := &cobra.Command{}
  929. configPath = "configJsonD.json"
  930. var serveWG sync.WaitGroup
  931. serveWG.Add(1)
  932. go func() {
  933. serve(cmd, []string{})
  934. serveWG.Done()
  935. }()
  936. time.Sleep(testPauseDuration)
  937. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  938. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  939. } else {
  940. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  941. expect := "250 mail.test.com Hello"
  942. if strings.Index(result, expect) != 0 {
  943. t.Error("Expected", expect, "but got", result)
  944. }
  945. }
  946. conn.Close()
  947. }
  948. // set the log_level to info
  949. newConf := conf // copy the cmdConfg
  950. newConf.LogLevel = "info"
  951. if jsonbytes, err := json.Marshal(newConf); err == nil {
  952. ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644)
  953. } else {
  954. t.Error(err)
  955. }
  956. // send a sighup signal to the server to reload config
  957. sigHup()
  958. time.Sleep(testPauseDuration) // log to change
  959. // connect again, this time we should see info
  960. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  961. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  962. } else {
  963. if result, err := test.Command(conn, buffin, "NOOP"); err == nil {
  964. expect := "200 2.0.0 OK"
  965. if strings.Index(result, expect) != 0 {
  966. t.Error("Expected", expect, "but got", result)
  967. }
  968. }
  969. conn.Close()
  970. }
  971. // send kill signal and wait for exit
  972. sigKill()
  973. serveWG.Wait()
  974. // did backend started as expected?
  975. fd, _ := os.Open("../../tests/testlog")
  976. if read, err := ioutil.ReadAll(fd); err == nil {
  977. logOutput := string(read)
  978. //fmt.Println(logOutput)
  979. if i := strings.Index(logOutput, "log level changed to [info]"); i < 0 {
  980. t.Error("Log level did not change to [info]")
  981. }
  982. // This should not be there:
  983. if i := strings.Index(logOutput, "Client sent: NOOP"); i != -1 {
  984. t.Error("Log level did not change to [info], we are still seeing debug messages")
  985. }
  986. }
  987. // cleanup
  988. os.Truncate("../../tests/testlog", 0)
  989. os.Remove("configJsonD.json")
  990. os.Remove("./pidfile.pid")
  991. }