serve_test.go 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  1. package main
  2. import (
  3. "crypto/tls"
  4. "encoding/json"
  5. "io/ioutil"
  6. "os"
  7. "os/exec"
  8. "runtime"
  9. "strconv"
  10. "strings"
  11. "sync"
  12. "testing"
  13. "time"
  14. "github.com/flashmob/go-guerrilla"
  15. "github.com/flashmob/go-guerrilla/backends"
  16. "github.com/flashmob/go-guerrilla/log"
  17. test "github.com/flashmob/go-guerrilla/tests"
  18. "github.com/flashmob/go-guerrilla/tests/testcert"
  19. "github.com/spf13/cobra"
  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[string]bool{
  240. "config_change:backend_config": false,
  241. "config_change:backend_name": false,
  242. "server_change:new_server": 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[string]func(c *CmdConfig){}
  252. toUnsubscribeS := map[string]func(c *guerrilla.ServerConfig){}
  253. for event := range expectedEvents {
  254. // Put in anon func since range is overwriting event
  255. func(e string) {
  256. if strings.Index(e, "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.Error("did not change allowed_hosts, most likely because Bus.Subscribe(\"config_change:allowed_hosts\" didnt fire")
  637. }
  638. }
  639. // cleanup
  640. os.Truncate("../../tests/testlog", 0)
  641. os.Remove("configJsonD.json")
  642. os.Remove("./pidfile.pid")
  643. }
  644. // Test TLS config change event
  645. // start with configJsonD
  646. // should be able to STARTTLS to 127.0.0.1:2525 with no problems
  647. // generate new certs & reload config
  648. // should get a new tls event & able to STARTTLS with no problem
  649. func TestTLSConfigEvent(t *testing.T) {
  650. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  651. // pause for generated cert to output on slow machines
  652. time.Sleep(testPauseDuration)
  653. // did cert output?
  654. if _, err := os.Stat("../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  655. t.Error("Did not create cert ", err)
  656. }
  657. mainlog, _ = log.GetLogger("../../tests/testlog")
  658. // start the server by emulating the serve command
  659. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  660. conf := &CmdConfig{} // blank one
  661. conf.load([]byte(configJsonD)) // load configJsonD
  662. cmd := &cobra.Command{}
  663. configPath = "configJsonD.json"
  664. var serveWG sync.WaitGroup
  665. serveWG.Add(1)
  666. go func() {
  667. serve(cmd, []string{})
  668. serveWG.Done()
  669. }()
  670. time.Sleep(testPauseDuration)
  671. // Test STARTTLS handshake
  672. testTlsHandshake := func() {
  673. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  674. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  675. } else {
  676. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  677. expect := "250 mail.test.com Hello"
  678. if strings.Index(result, expect) != 0 {
  679. t.Error("Expected", expect, "but got", result)
  680. } else {
  681. if result, err = test.Command(conn, buffin, "STARTTLS"); err == nil {
  682. expect := "220 2.0.0 Ready to start TLS"
  683. if strings.Index(result, expect) != 0 {
  684. t.Error("Expected:", expect, "but got:", result)
  685. } else {
  686. tlsConn := tls.Client(conn, &tls.Config{
  687. InsecureSkipVerify: true,
  688. ServerName: "127.0.0.1",
  689. })
  690. if err := tlsConn.Handshake(); err != nil {
  691. t.Error("Failed to handshake", conf.AppConfig.Servers[0].ListenInterface)
  692. } else {
  693. conn = tlsConn
  694. mainlog.Info("TLS Handshake succeeded")
  695. }
  696. }
  697. }
  698. }
  699. }
  700. conn.Close()
  701. }
  702. }
  703. testTlsHandshake()
  704. if err := os.Remove("../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  705. t.Error("could not remove cert", err)
  706. }
  707. if err := os.Remove("../../tests/mail2.guerrillamail.com.key.pem"); err != nil {
  708. t.Error("could not remove key", err)
  709. }
  710. // generate a new cert
  711. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  712. // pause for generated cert to output
  713. time.Sleep(testPauseDuration)
  714. // did cert output?
  715. if _, err := os.Stat("../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  716. t.Error("Did not create cert ", err)
  717. }
  718. sigHup()
  719. time.Sleep(testPauseDuration * 2) // pause for config to reload
  720. testTlsHandshake()
  721. //time.Sleep(testPauseDuration)
  722. // send kill signal and wait for exit
  723. sigKill()
  724. serveWG.Wait()
  725. // did backend started as expected?
  726. fd, _ := os.Open("../../tests/testlog")
  727. if read, err := ioutil.ReadAll(fd); err == nil {
  728. logOutput := string(read)
  729. //fmt.Println(logOutput)
  730. if i := strings.Index(logOutput, "Server [127.0.0.1:2552] new TLS configuration loaded"); i < 0 {
  731. t.Error("did not change tls, most likely because Bus.Subscribe(\"server_change:tls_config\" didnt fire")
  732. }
  733. }
  734. // cleanup
  735. os.Truncate("../../tests/testlog", 0)
  736. os.Remove("configJsonD.json")
  737. os.Remove("./pidfile.pid")
  738. }
  739. // Test for missing TLS certificate, when starting or config reload
  740. func TestBadTLS(t *testing.T) {
  741. mainlog, _ = log.GetLogger("../../tests/testlog")
  742. if err := os.Remove("./../../tests/mail2.guerrillamail.com.cert.pem"); err != nil {
  743. mainlog.WithError(err).Error("could not remove ./../../tests/mail2.guerrillamail.com.cert.pem")
  744. } else {
  745. mainlog.Info("removed ./../../tests/mail2.guerrillamail.com.cert.pem")
  746. }
  747. // start the server by emulating the serve command
  748. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  749. conf := &CmdConfig{} // blank one
  750. conf.load([]byte(configJsonD)) // load configJsonD
  751. conf.Servers[0].Timeout = 1
  752. cmd := &cobra.Command{}
  753. configPath = "configJsonD.json"
  754. var serveWG sync.WaitGroup
  755. serveWG.Add(1)
  756. go func() {
  757. serve(cmd, []string{})
  758. serveWG.Done()
  759. }()
  760. time.Sleep(testPauseDuration)
  761. // Test STARTTLS handshake
  762. testTlsHandshake := func() {
  763. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  764. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  765. } else {
  766. conn.SetDeadline(time.Now().Add(time.Second))
  767. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  768. expect := "250 mail.test.com Hello"
  769. if strings.Index(result, expect) != 0 {
  770. t.Error("Expected", expect, "but got", result)
  771. } else {
  772. if result, err = test.Command(conn, buffin, "STARTTLS"); err == nil {
  773. expect := "220 2.0.0 Ready to start TLS"
  774. if strings.Index(result, expect) != 0 {
  775. t.Error("Expected:", expect, "but got:", result)
  776. } else {
  777. tlsConn := tls.Client(conn, &tls.Config{
  778. InsecureSkipVerify: true,
  779. ServerName: "127.0.0.1",
  780. })
  781. if err := tlsConn.Handshake(); err != nil {
  782. mainlog.Info("TLS Handshake failed")
  783. } else {
  784. t.Error("Handshake succeeded, expected it to fail", conf.AppConfig.Servers[0].ListenInterface)
  785. conn = tlsConn
  786. }
  787. }
  788. }
  789. }
  790. }
  791. conn.Close()
  792. }
  793. }
  794. testTlsHandshake()
  795. // write some trash data
  796. ioutil.WriteFile("./../../tests/mail2.guerrillamail.com.cert.pem", []byte("trash data"), 0664)
  797. ioutil.WriteFile("./../../tests/mail2.guerrillamail.com.key.pem", []byte("trash data"), 0664)
  798. // generate a new cert
  799. //testcert.GenerateCert("mail2.guerrillamail.com", "", 365 * 24 * time.Hour, false, 2048, "P256", "../../tests/")
  800. sigHup()
  801. time.Sleep(testPauseDuration) // pause for config to reload
  802. testTlsHandshake()
  803. time.Sleep(testPauseDuration)
  804. // send kill signal and wait for exit
  805. sigKill()
  806. serveWG.Wait()
  807. // did backend started as expected?
  808. fd, _ := os.Open("../../tests/testlog")
  809. if read, err := ioutil.ReadAll(fd); err == nil {
  810. logOutput := string(read)
  811. //fmt.Println(logOutput)
  812. if i := strings.Index(logOutput, "failed to load the new TLS configuration"); i < 0 {
  813. t.Error("did not detect TLS load failure")
  814. }
  815. }
  816. // cleanup
  817. os.Truncate("../../tests/testlog", 0)
  818. os.Remove("configJsonD.json")
  819. os.Remove("./pidfile.pid")
  820. }
  821. // Test for when the server config Timeout value changes
  822. // Start with configJsonD.json
  823. func TestSetTimeoutEvent(t *testing.T) {
  824. //mainlog, _ = log.GetLogger("../../tests/testlog")
  825. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  826. // start the server by emulating the serve command
  827. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  828. conf := &CmdConfig{} // blank one
  829. conf.load([]byte(configJsonD)) // load configJsonD
  830. cmd := &cobra.Command{}
  831. configPath = "configJsonD.json"
  832. var serveWG sync.WaitGroup
  833. serveWG.Add(1)
  834. go func() {
  835. serve(cmd, []string{})
  836. serveWG.Done()
  837. }()
  838. time.Sleep(testPauseDuration)
  839. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  840. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  841. } else {
  842. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  843. expect := "250 mail.test.com Hello"
  844. if strings.Index(result, expect) != 0 {
  845. t.Error("Expected", expect, "but got", result)
  846. }
  847. }
  848. }
  849. // set the timeout to 1 second
  850. newConf := conf // copy the cmdConfg
  851. newConf.Servers[0].Timeout = 1
  852. if jsonbytes, err := json.Marshal(newConf); err == nil {
  853. ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644)
  854. } else {
  855. t.Error(err)
  856. }
  857. // send a sighup signal to the server to reload config
  858. sigHup()
  859. time.Sleep(time.Millisecond * 1200) // pause for connection to timeout
  860. // so the connection we have opened should timeout by now
  861. // send kill signal and wait for exit
  862. sigKill()
  863. serveWG.Wait()
  864. // did backend started as expected?
  865. fd, _ := os.Open("../../tests/testlog")
  866. if read, err := ioutil.ReadAll(fd); err == nil {
  867. logOutput := string(read)
  868. //fmt.Println(logOutput)
  869. if i := strings.Index(logOutput, "i/o timeout"); i < 0 {
  870. t.Error("Connection to 127.0.0.1:2552 didn't timeout as expected")
  871. }
  872. }
  873. // cleanup
  874. os.Truncate("../../tests/testlog", 0)
  875. os.Remove("configJsonD.json")
  876. os.Remove("./pidfile.pid")
  877. }
  878. // Test debug level config change
  879. // Start in log_level = debug
  880. // Load config & start server
  881. func TestDebugLevelChange(t *testing.T) {
  882. //mainlog, _ = log.GetLogger("../../tests/testlog")
  883. testcert.GenerateCert("mail2.guerrillamail.com", "", 365*24*time.Hour, false, 2048, "P256", "../../tests/")
  884. // start the server by emulating the serve command
  885. ioutil.WriteFile("configJsonD.json", []byte(configJsonD), 0644)
  886. conf := &CmdConfig{} // blank one
  887. conf.load([]byte(configJsonD)) // load configJsonD
  888. conf.LogLevel = "debug"
  889. cmd := &cobra.Command{}
  890. configPath = "configJsonD.json"
  891. var serveWG sync.WaitGroup
  892. serveWG.Add(1)
  893. go func() {
  894. serve(cmd, []string{})
  895. serveWG.Done()
  896. }()
  897. time.Sleep(testPauseDuration)
  898. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  899. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  900. } else {
  901. if result, err := test.Command(conn, buffin, "HELO"); err == nil {
  902. expect := "250 mail.test.com Hello"
  903. if strings.Index(result, expect) != 0 {
  904. t.Error("Expected", expect, "but got", result)
  905. }
  906. }
  907. conn.Close()
  908. }
  909. // set the log_level to info
  910. newConf := conf // copy the cmdConfg
  911. newConf.LogLevel = "info"
  912. if jsonbytes, err := json.Marshal(newConf); err == nil {
  913. ioutil.WriteFile("configJsonD.json", []byte(jsonbytes), 0644)
  914. } else {
  915. t.Error(err)
  916. }
  917. // send a sighup signal to the server to reload config
  918. sigHup()
  919. time.Sleep(testPauseDuration) // log to change
  920. // connect again, this time we should see info
  921. if conn, buffin, err := test.Connect(conf.AppConfig.Servers[0], 20); err != nil {
  922. t.Error("Could not connect to server", conf.AppConfig.Servers[0].ListenInterface, err)
  923. } else {
  924. if result, err := test.Command(conn, buffin, "NOOP"); err == nil {
  925. expect := "200 2.0.0 OK"
  926. if strings.Index(result, expect) != 0 {
  927. t.Error("Expected", expect, "but got", result)
  928. }
  929. }
  930. conn.Close()
  931. }
  932. // send kill signal and wait for exit
  933. sigKill()
  934. serveWG.Wait()
  935. // did backend started as expected?
  936. fd, _ := os.Open("../../tests/testlog")
  937. if read, err := ioutil.ReadAll(fd); err == nil {
  938. logOutput := string(read)
  939. //fmt.Println(logOutput)
  940. if i := strings.Index(logOutput, "log level changed to [info]"); i < 0 {
  941. t.Error("Log level did not change to [info]")
  942. }
  943. // This should not be there:
  944. if i := strings.Index(logOutput, "Client sent: NOOP"); i != -1 {
  945. t.Error("Log level did not change to [info], we are still seeing debug messages")
  946. }
  947. }
  948. // cleanup
  949. os.Truncate("../../tests/testlog", 0)
  950. os.Remove("configJsonD.json")
  951. os.Remove("./pidfile.pid")
  952. }