summaryrefslogtreecommitdiff
path: root/tls-getcerts.go
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2017-02-10 00:41:17 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2017-02-10 00:41:17 -0500
commit770215dbfdffd0a37d0c051092ae441070eec260 (patch)
tree110161ccaa5bfa127e4c56055dcbfdb4a869ff9c /tls-getcerts.go
parent7af911f4d1f24883dcf78b43f1327442f86c9737 (diff)
learn SMTP STARTTLS
Diffstat (limited to 'tls-getcerts.go')
-rw-r--r--tls-getcerts.go47
1 files changed, 47 insertions, 0 deletions
diff --git a/tls-getcerts.go b/tls-getcerts.go
index d598d27..d386b90 100644
--- a/tls-getcerts.go
+++ b/tls-getcerts.go
@@ -8,6 +8,7 @@ import (
"fmt"
"io"
"net"
+ "net/textproto"
"net/url"
"os"
"strings"
@@ -62,6 +63,47 @@ func xmppStartTLS(connRaw net.Conn, host string) error {
return nil
}
+// smtpCmd is a convenience function that sends a command, and reads
+// (but discards) the response
+func smtpCmd(tp *textproto.Conn, expectCode int, format string, args ...interface{}) error {
+ id, err := tp.Cmd(format, args...)
+ if err != nil {
+ return err
+ }
+ tp.StartResponse(id)
+ defer tp.EndResponse(id)
+ _, _, err = tp.ReadResponse(expectCode)
+ return err
+}
+
+func smtpStartTLS(connRaw net.Conn, host string) error {
+ tp := textproto.NewConn(connRaw)
+
+ // let the server introduce itself
+ _, _, err := tp.ReadResponse(220)
+ if err != nil {
+ return err
+ }
+ // introduce ourself
+ localhost, err := os.Hostname()
+ if err != nil {
+ localhost = "localhost"
+ }
+ err = smtpCmd(tp, 250, "EHLO %s", localhost)
+ if err != nil {
+ err := smtpCmd(tp, 250, "HELO %s", localhost)
+ if err != nil {
+ return err
+ }
+ }
+ // starttls
+ err = smtpCmd(tp, 220, "STARTTLS")
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
func getcert(socket string) (*x509.Certificate, error) {
u, err := url.Parse(socket)
if err != nil {
@@ -85,6 +127,11 @@ func getcert(socket string) (*x509.Certificate, error) {
if err != nil {
return nil, err
}
+ case "/smtp":
+ err = smtpStartTLS(connRaw, host)
+ if err != nil {
+ return nil, err
+ }
default:
return nil, fmt.Errorf("Unknown negotiation path: %q", u.Path)
}