diff --git a/main.go b/main.go index 7a43ab6..29c6674 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") + 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() @@ -104,7 +105,11 @@ func main() { } case connect.FullCommand(): // Get certs by connecting to a server - connState, err := starttls.GetConnectionState(*connectStartTLS, *connectName, *connectTo, *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 63e8118..a633c7a 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, 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, 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", identity, 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", identity, connectTo, timeout/time.Second) if clientCert != "" { url += fmt.Sprintf("&sslcert=%s", clientCert) } @@ -154,6 +154,11 @@ func GetConnectionState(startTLSType, connectName, connectTo, clientCert, client res <- connectResult{nil, err} return } + err = client.Hello(identity) + if err != nil { + res <- connectResult{nil, err} + return + } err = client.StartTLS(tlsConfig) if err != nil { res <- connectResult{nil, err}