serve_test.go 33 KB

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