Skip to content

Commit

Permalink
Issue #28 - add new TLS configuration options (#110)
Browse files Browse the repository at this point in the history
* Issue #28 - add new TLS configuration options 

Adds ability to select ciphers, protocols, curves, client auth policy and set a custom certificate authority pool

Note: This change breaks existing TLS configurations, please see docs for the new TLS options https://github.com/flashmob/go-guerrilla/wiki/Configuration
  • Loading branch information
flashmob committed May 28, 2018
1 parent 1175076 commit 9cec012
Show file tree
Hide file tree
Showing 17 changed files with 587 additions and 216 deletions.
5 changes: 3 additions & 2 deletions .travis.yml
@@ -1,9 +1,10 @@
language: go
sudo: false
go:
- 1.5
- 1.6
- 1.7
- 1.8
- 1.9
- 1.10.x
- master

install:
Expand Down
2 changes: 2 additions & 0 deletions README.md
@@ -1,6 +1,8 @@

[![Build Status](https://travis-ci.org/flashmob/go-guerrilla.svg?branch=master)](https://travis-ci.org/flashmob/go-guerrilla)

Breaking change: The structure of the config has recently changed to accommodate more advanced TLS settings.

Go-Guerrilla SMTP Daemon
====================

Expand Down
2 changes: 1 addition & 1 deletion api.go
Expand Up @@ -93,7 +93,7 @@ func (d *Daemon) LoadConfig(path string) (AppConfig, error) {
var ac AppConfig
data, err := ioutil.ReadFile(path)
if err != nil {
return ac, fmt.Errorf("Could not read config file: %s", err.Error())
return ac, fmt.Errorf("could not read config file: %s", err.Error())
}
err = ac.Load(data)
if err != nil {
Expand Down
30 changes: 17 additions & 13 deletions api_test.go
Expand Up @@ -133,13 +133,15 @@ func TestSMTPLoadFile(t *testing.T) {
"is_enabled" : true,
"host_name":"mail.guerrillamail.com",
"max_size": 100017,
"private_key_file":"config_test.go",
"public_key_file":"config_test.go",
"timeout":160,
"listen_interface":"127.0.0.1:2526",
"start_tls_on":false,
"tls_always_on":false,
"max_clients": 2
"max_clients": 2,
"tls" : {
"private_key_file":"config_test.go",
"public_key_file":"config_test.go",
"start_tls_on":false,
"tls_always_on":false
}
}
]
}
Expand All @@ -161,13 +163,15 @@ func TestSMTPLoadFile(t *testing.T) {
"is_enabled" : true,
"host_name":"mail.guerrillamail.com",
"max_size": 100017,
"private_key_file":"config_test.go",
"public_key_file":"config_test.go",
"timeout":160,
"listen_interface":"127.0.0.1:2526",
"start_tls_on":false,
"tls_always_on":false,
"max_clients": 2
"max_clients": 2,
"tls" : {
"private_key_file":"config_test.go",
"public_key_file":"config_test.go",
"start_tls_on":false,
"tls_always_on":false
}
}
]
}
Expand Down Expand Up @@ -310,9 +314,9 @@ func TestSetConfigError(t *testing.T) {

// lets add a new server with bad TLS
sc.ListenInterface = "127.0.0.1:2527"
sc.StartTLSOn = true
sc.PublicKeyFile = "tests/testlog" // totally wrong :->
sc.PublicKeyFile = "tests/testlog" // totally wrong :->
sc.TLS.StartTLSOn = true
sc.TLS.PublicKeyFile = "tests/testlog" // totally wrong :->
sc.TLS.PrivateKeyFile = "tests/testlog" // totally wrong :->

cfg.Servers = append(cfg.Servers, sc)

Expand Down
2 changes: 1 addition & 1 deletion backends/p_guerrilla_db_redis.go
Expand Up @@ -319,7 +319,7 @@ func (g *GuerrillaDBAndRedisBackend) sqlConnect() (*sql.DB, error) {
// do we have access?
_, err = db.Query("SELECT mail_id FROM " + g.config.Table + " LIMIT 1")
if err != nil {
Log().Error("cannot select table", err)
Log().Error("cannot select table:", err)
return nil, err
}
return db, nil
Expand Down
9 changes: 6 additions & 3 deletions backends/p_sql.go
Expand Up @@ -246,9 +246,12 @@ func SQL() Decorator {
recipient,
s.ip2bint(e.RemoteIP).Bytes(), // ip_addr store as varbinary(16)
trimToLimit(e.MailFrom.String(), 255), // return_path
e.TLS, // is_tls
mid, // message_id
replyTo, // reply_to
// is_tls
e.TLS,
// message_id
mid,
// reply_to
replyTo,
sender,
)

Expand Down
2 changes: 1 addition & 1 deletion client.go
Expand Up @@ -178,7 +178,7 @@ func (c *client) getID() uint64 {
// UpgradeToTLS upgrades a client connection to TLS
func (client *client) upgradeToTLS(tlsConfig *tls.Config) error {
var tlsConn *tls.Conn
// load the config thread-safely
// wrap client.conn in a new TLS server side connection
tlsConn = tls.Server(client.conn, tlsConfig)
// Call handshake here to get any handshake error before reading starts
err := tlsConn.Handshake()
Expand Down
145 changes: 94 additions & 51 deletions cmd/guerrillad/serve_test.go
Expand Up @@ -43,27 +43,31 @@ var configJsonA = `
"is_enabled" : true,
"host_name":"mail.test.com",
"max_size": 1000000,
"private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"timeout":180,
"listen_interface":"127.0.0.1:3536",
"start_tls_on":true,
"tls_always_on":false,
"max_clients": 1000,
"log_file" : "../../tests/testlog"
"log_file" : "../../tests/testlog",
"tls" : {
"private_key_file":"../../tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"start_tls_on":true,
"tls_always_on":false
}
},
{
"is_enabled" : false,
"host_name":"enable.test.com",
"max_size": 1000000,
"private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"timeout":180,
"listen_interface":"127.0.0.1:2228",
"start_tls_on":true,
"tls_always_on":false,
"max_clients": 1000,
"log_file" : "../../tests/testlog"
"log_file" : "../../tests/testlog",
"tls" : {
"private_key_file":"../../tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"start_tls_on":true,
"tls_always_on":false
}
}
]
}
Expand Down Expand Up @@ -92,20 +96,22 @@ var configJsonB = `
"is_enabled" : true,
"host_name":"mail.test.com",
"max_size": 1000000,
"private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"timeout":180,
"listen_interface":"127.0.0.1:3536",
"start_tls_on":true,
"tls_always_on":false,
"max_clients": 1000,
"log_file" : "../../tests/testlog"
"log_file" : "../../tests/testlog",
"tls" : {
"private_key_file":"../../tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"start_tls_on":true,
"tls_always_on":false
}
}
]
}
`

// backend_name changed, is guerrilla-redis-db + added a server
// added a server
var configJsonC = `
{
"log_file" : "../../tests/testlog",
Expand All @@ -118,46 +124,49 @@ var configJsonC = `
"guerrillamail.net",
"guerrillamail.org"
],
"backend_name": "guerrilla-redis-db",
"backend_config" :
{
"sql_driver": "mysql",
"sql_dsn": "root:ok@tcp(127.0.0.1:3306)/gmail_mail?readTimeout=10&writeTimeout=10",
"sql_dsn": "root:ok@tcp(127.0.0.1:3306)/gmail_mail?readTimeout=10s&writeTimeout=10s",
"mail_table":"new_mail",
"redis_interface" : "127.0.0.1:6379",
"redis_expire_seconds" : 7200,
"save_workers_size" : 3,
"primary_mail_host":"sharklasers.com",
"save_workers_size" : 1,
"save_process": "HeadersParser|Debugger",
"log_received_mails": true
"save_process": "HeadersParser|Debugger",
"log_received_mails": true
},
"servers" : [
{
"is_enabled" : true,
"host_name":"mail.test.com",
"max_size": 1000000,
"private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"timeout":180,
"listen_interface":"127.0.0.1:25",
"start_tls_on":true,
"tls_always_on":false,
"max_clients": 1000,
"log_file" : "../../tests/testlog"
"log_file" : "../../tests/testlog",
"tls" : {
"private_key_file":"../../tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"start_tls_on":true,
"tls_always_on":false
}
},
{
"is_enabled" : true,
"host_name":"mail.test.com",
"max_size":1000000,
"private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"timeout":180,
"listen_interface":"127.0.0.1:465",
"start_tls_on":false,
"tls_always_on":true,
"max_clients":500,
"log_file" : "../../tests/testlog"
"log_file" : "../../tests/testlog",
"tls" : {
"private_key_file":"../../tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"start_tls_on":false,
"tls_always_on":true
}
}
]
}
Expand Down Expand Up @@ -186,27 +195,31 @@ var configJsonD = `
"is_enabled" : true,
"host_name":"mail.test.com",
"max_size": 1000000,
"private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"timeout":180,
"listen_interface":"127.0.0.1:2552",
"start_tls_on":true,
"tls_always_on":false,
"max_clients": 1000,
"log_file" : "../../tests/testlog"
"log_file" : "../../tests/testlog",
"tls" : {
"private_key_file":"../../tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"start_tls_on":true,
"tls_always_on":false
}
},
{
"is_enabled" : true,
"host_name":"secure.test.com",
"max_size":1000000,
"private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"timeout":180,
"listen_interface":"127.0.0.1:4655",
"start_tls_on":false,
"tls_always_on":true,
"max_clients":500,
"log_file" : "../../tests/testlog"
"log_file" : "../../tests/testlog",
"tls" : {
"private_key_file":"../../tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"start_tls_on":false,
"tls_always_on":true
}
}
]
}
Expand All @@ -231,7 +244,7 @@ var configJsonE = `
"save_process": "GuerrillaRedisDB",
"log_received_mails" : true,
"sql_driver": "mysql",
"sql_dsn": "root:secret@tcp(127.0.0.1:3306)/gmail_mail?readTimeout=10&writeTimeout=10",
"sql_dsn": "root:secret@tcp(127.0.0.1:3306)/gmail_mail?readTimeout=10s&writeTimeout=10s",
"mail_table":"new_mail",
"redis_interface" : "127.0.0.1:6379",
"redis_expire_seconds" : 7200,
Expand All @@ -243,27 +256,31 @@ var configJsonE = `
"is_enabled" : true,
"host_name":"mail.test.com",
"max_size": 1000000,
"private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"timeout":180,
"listen_interface":"127.0.0.1:2552",
"start_tls_on":true,
"tls_always_on":false,
"max_clients": 1000,
"log_file" : "../../tests/testlog"
"log_file" : "../../tests/testlog",
"tls" : {
"private_key_file":"../../tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"start_tls_on":true,
"tls_always_on":false
}
},
{
"is_enabled" : true,
"host_name":"secure.test.com",
"max_size":1000000,
"private_key_file":"../..//tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"timeout":180,
"listen_interface":"127.0.0.1:4655",
"start_tls_on":false,
"tls_always_on":true,
"max_clients":500,
"log_file" : "../../tests/testlog"
"log_file" : "../../tests/testlog",
"tls" : {
"private_key_file":"../../tests/mail2.guerrillamail.com.key.pem",
"public_key_file":"../../tests/mail2.guerrillamail.com.cert.pem",
"start_tls_on":false,
"tls_always_on":true
}
}
]
}
Expand Down Expand Up @@ -667,6 +684,32 @@ func TestServerStopEvent(t *testing.T) {

}

// just a utility for debugging when using the debugger, skipped by default
func TestDebug(t *testing.T) {

t.SkipNow()
conf := guerrilla.ServerConfig{ListenInterface: "127.0.0.1:2526"}
if conn, buffin, err := test.Connect(conf, 20); err != nil {
t.Error("Could not connect to new server", conf.ListenInterface, err)
} else {
if result, err := test.Command(conn, buffin, "HELO"); err == nil {
expect := "250 mai1.guerrillamail.com Hello"
if strings.Index(result, expect) != 0 {
t.Error("Expected", expect, "but got", result)
} else {
if result, err = test.Command(conn, buffin, "RCPT TO:test@grr.la"); err == nil {
expect := "250 2.1.5 OK"
if strings.Index(result, expect) != 0 {
t.Error("Expected:", expect, "but got:", result)
}
}
}
}
conn.Close()

}
}

// Start with configJsonD.json,
// then connect to 127.0.0.1:4655 & HELO & try RCPT TO with an invalid host [grr.la]
// then change the config to enable add new host [grr.la] to allowed_hosts
Expand Down

0 comments on commit 9cec012

Please sign in to comment.