From 0232a800cf8d4f910d7c2c563f246e6d91f86d9c Mon Sep 17 00:00:00 2001 From: Matthew McPherrin Date: Fri, 31 Mar 2017 13:51:01 -0700 Subject: [PATCH 1/3] smtp hello as certigo --- starttls/starttls.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/starttls/starttls.go b/starttls/starttls.go index 63e8118..545a940 100644 --- a/starttls/starttls.go +++ b/starttls/starttls.go @@ -154,6 +154,11 @@ func GetConnectionState(startTLSType, connectName, connectTo, clientCert, client res <- connectResult{nil, err} return } + err = client.Hello("certigo") + if err != nil { + res <- connectResult{nil, err} + return + } err = client.StartTLS(tlsConfig) if err != nil { res <- connectResult{nil, err} From 60f1c25a947d40c78ec8b6532fdf2dfde19b8ed4 Mon Sep 17 00:00:00 2001 From: Matthew McPherrin Date: Fri, 31 Mar 2017 15:36:38 -0700 Subject: [PATCH 2/3] Add a --asuser flag which sets DB user & stmp EHLO hostname. --- main.go | 3 ++- starttls/starttls.go | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 7a43ab6..be102c1 100644 --- a/main.go +++ b/main.go @@ -50,6 +50,7 @@ var ( connectCert = connect.Flag("cert", "Client certificate chain for connecting to server (PEM).").ExistingFile() connectKey = connect.Flag("key", "Private key for client certificate, if not in same file (PEM).").ExistingFile() connectStartTLS = connect.Flag("start-tls", "Enable StartTLS protocol ('ldap', 'mysql', 'postgres', 'smtp' or 'ftp').").Short('t').PlaceHolder("PROTOCOL").Enum("mysql", "postgres", "psql", "smtp", "ldap", "ftp") + connectAs = connect.Flag("asuser", "With starttls, connect as this db user (or smtp ehlo)").Default("certigo").String() connectTimeout = connect.Flag("timeout", "Timeout for connecting to remote server (can be '5m', '1s', etc).").Default("5s").Duration() connectPem = connect.Flag("pem", "Write output as PEM blocks instead of human-readable format.").Short('m').Bool() connectJSON = connect.Flag("json", "Write output as machine-readable JSON format.").Short('j').Bool() @@ -104,7 +105,7 @@ func main() { } case connect.FullCommand(): // Get certs by connecting to a server - connState, err := starttls.GetConnectionState(*connectStartTLS, *connectName, *connectTo, *connectCert, *connectKey, *connectTimeout) + connState, err := starttls.GetConnectionState(*connectStartTLS, *connectName, *connectTo, *connectAs, *connectCert, *connectKey, *connectTimeout) if err != nil { fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSuffix(err.Error(), "\n")) os.Exit(1) diff --git a/starttls/starttls.go b/starttls/starttls.go index 545a940..e78cb0f 100644 --- a/starttls/starttls.go +++ b/starttls/starttls.go @@ -62,9 +62,9 @@ func tlsConfigForConnect(connectName, clientCert, clientKey string) (*tls.Config // GetConnectionState connects to a TLS server, returning the connection state. // Currently, startTLSType can be one of "mysql", "postgres" or "psql", or the // empty string, which does a normal TLS connection. connectTo specifies the -// address to connect to. connectName sets SNI. connectCert and connectKey are -// client certs -func GetConnectionState(startTLSType, connectName, connectTo, clientCert, clientKey string, timeout time.Duration) (*tls.ConnectionState, error) { +// address to connect to. connectName sets SNI. connectAs sets db username, smtp ehlo +// connectCert and connectKey are client certs +func GetConnectionState(startTLSType, connectName, connectTo, connectAs, clientCert, clientKey string, timeout time.Duration) (*tls.ConnectionState, error) { var state *tls.ConnectionState var err error var tlsConfig *tls.Config @@ -124,7 +124,7 @@ func GetConnectionState(startTLSType, connectName, connectTo, clientCert, client res <- connectResult{state, nil} case "mysql": mysql.RegisterTLSConfig("certigo", tlsConfig) - state, err = mysql.DumpTLS(fmt.Sprintf("certigo@tcp(%s)/?tls=certigo&timeout=%s", connectTo, timeout.String())) + state, err = mysql.DumpTLS(fmt.Sprintf("%s@tcp(%s)/?tls=certigo&timeout=%s", connectAs, connectTo, timeout.String())) if err != nil { res <- connectResult{nil, err} return @@ -132,7 +132,7 @@ func GetConnectionState(startTLSType, connectName, connectTo, clientCert, client res <- connectResult{state, nil} case "postgres", "psql": // Setting sslmode to "require" skips verification. - url := fmt.Sprintf("postgres://certigo@%s/?sslmode=require&connect_timeout=%d", connectTo, timeout/time.Second) + url := fmt.Sprintf("postgres://%s@%s/?sslmode=require&connect_timeout=%d", connectAs, connectTo, timeout/time.Second) if clientCert != "" { url += fmt.Sprintf("&sslcert=%s", clientCert) } @@ -154,7 +154,7 @@ func GetConnectionState(startTLSType, connectName, connectTo, clientCert, client res <- connectResult{nil, err} return } - err = client.Hello("certigo") + err = client.Hello(connectAs) if err != nil { res <- connectResult{nil, err} return From b61f9af0af33fd46526a48b54ae7c9f59285d54f Mon Sep 17 00:00:00 2001 From: Matthew McPherrin Date: Fri, 31 Mar 2017 23:57:29 -0700 Subject: [PATCH 3/3] Review feedback: Flag named --identity and a better description Validate --identity can only be used with --start-tls --- main.go | 8 ++++++-- starttls/starttls.go | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/main.go b/main.go index be102c1..29c6674 100644 --- a/main.go +++ b/main.go @@ -50,7 +50,7 @@ var ( connectCert = connect.Flag("cert", "Client certificate chain for connecting to server (PEM).").ExistingFile() connectKey = connect.Flag("key", "Private key for client certificate, if not in same file (PEM).").ExistingFile() connectStartTLS = connect.Flag("start-tls", "Enable StartTLS protocol ('ldap', 'mysql', 'postgres', 'smtp' or 'ftp').").Short('t').PlaceHolder("PROTOCOL").Enum("mysql", "postgres", "psql", "smtp", "ldap", "ftp") - connectAs = connect.Flag("asuser", "With starttls, connect as this db user (or smtp ehlo)").Default("certigo").String() + connectIdentity = connect.Flag("identity", "With --start-tls, sets the DB user or SMTP EHLO name").Default("certigo").String() connectTimeout = connect.Flag("timeout", "Timeout for connecting to remote server (can be '5m', '1s', etc).").Default("5s").Duration() connectPem = connect.Flag("pem", "Write output as PEM blocks instead of human-readable format.").Short('m').Bool() connectJSON = connect.Flag("json", "Write output as machine-readable JSON format.").Short('j').Bool() @@ -105,7 +105,11 @@ func main() { } case connect.FullCommand(): // Get certs by connecting to a server - connState, err := starttls.GetConnectionState(*connectStartTLS, *connectName, *connectTo, *connectAs, *connectCert, *connectKey, *connectTimeout) + if connectStartTLS == nil && connectIdentity != nil { + fmt.Fprintln(os.Stderr, "--identity can only be used with --start-tls") + os.Exit(1) + } + connState, err := starttls.GetConnectionState(*connectStartTLS, *connectName, *connectTo, *connectIdentity, *connectCert, *connectKey, *connectTimeout) if err != nil { fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSuffix(err.Error(), "\n")) os.Exit(1) diff --git a/starttls/starttls.go b/starttls/starttls.go index e78cb0f..a633c7a 100644 --- a/starttls/starttls.go +++ b/starttls/starttls.go @@ -64,7 +64,7 @@ func tlsConfigForConnect(connectName, clientCert, clientKey string) (*tls.Config // empty string, which does a normal TLS connection. connectTo specifies the // address to connect to. connectName sets SNI. connectAs sets db username, smtp ehlo // connectCert and connectKey are client certs -func GetConnectionState(startTLSType, connectName, connectTo, connectAs, clientCert, clientKey string, timeout time.Duration) (*tls.ConnectionState, error) { +func GetConnectionState(startTLSType, connectName, connectTo, identity, clientCert, clientKey string, timeout time.Duration) (*tls.ConnectionState, error) { var state *tls.ConnectionState var err error var tlsConfig *tls.Config @@ -124,7 +124,7 @@ func GetConnectionState(startTLSType, connectName, connectTo, connectAs, clientC res <- connectResult{state, nil} case "mysql": mysql.RegisterTLSConfig("certigo", tlsConfig) - state, err = mysql.DumpTLS(fmt.Sprintf("%s@tcp(%s)/?tls=certigo&timeout=%s", connectAs, connectTo, timeout.String())) + state, err = mysql.DumpTLS(fmt.Sprintf("%s@tcp(%s)/?tls=certigo&timeout=%s", identity, connectTo, timeout.String())) if err != nil { res <- connectResult{nil, err} return @@ -132,7 +132,7 @@ func GetConnectionState(startTLSType, connectName, connectTo, connectAs, clientC res <- connectResult{state, nil} case "postgres", "psql": // Setting sslmode to "require" skips verification. - url := fmt.Sprintf("postgres://%s@%s/?sslmode=require&connect_timeout=%d", connectAs, connectTo, timeout/time.Second) + url := fmt.Sprintf("postgres://%s@%s/?sslmode=require&connect_timeout=%d", identity, connectTo, timeout/time.Second) if clientCert != "" { url += fmt.Sprintf("&sslcert=%s", clientCert) } @@ -154,7 +154,7 @@ func GetConnectionState(startTLSType, connectName, connectTo, connectAs, clientC res <- connectResult{nil, err} return } - err = client.Hello(connectAs) + err = client.Hello(identity) if err != nil { res <- connectResult{nil, err} return