serve_test.go 30 KB

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