Add starttls for smtp, imap and ftp (#36)

This commit is contained in:
Rob Best
2020-06-22 16:50:21 +01:00
committed by GitHub
parent 1c8bd16057
commit 89eff28fac
9 changed files with 501 additions and 30 deletions

View File

@@ -17,7 +17,7 @@ type TCPServer struct {
stopCh chan struct{}
}
// StartTLS starts a listener that performs a TLS handshake
// StartTLS starts a listener that performs an immediate TLS handshake
func (t *TCPServer) StartTLS() {
go func() {
ln := tls.NewListener(t.Listener, t.TLS)
@@ -39,6 +39,103 @@ func (t *TCPServer) StartTLS() {
}()
}
// StartSMTP starts a listener that negotiates a TLS connection with an smtp
// client using STARTTLS
func (t *TCPServer) StartSMTP() {
go func() {
conn, err := t.Listener.Accept()
if err != nil {
panic(fmt.Sprintf("Error accepting on socket: %s", err))
}
defer conn.Close()
if err := conn.SetDeadline(time.Now().Add(5 * time.Second)); err != nil {
panic("Error setting deadline")
}
fmt.Fprintf(conn, "220 ESMTP StartTLS pseudo-server\n")
if _, e := fmt.Fscanf(conn, "EHLO prober\n"); e != nil {
panic("Error in dialog. No EHLO received.")
}
fmt.Fprintf(conn, "250-pseudo-server.example.net\n")
fmt.Fprintf(conn, "250-STARTTLS\n")
fmt.Fprintf(conn, "250 DSN\n")
if _, e := fmt.Fscanf(conn, "STARTTLS\n"); e != nil {
panic("Error in dialog. No (TLS) STARTTLS received.")
}
fmt.Fprintf(conn, "220 2.0.0 Ready to start TLS\n")
// Upgrade to TLS.
tlsConn := tls.Server(conn, t.TLS)
if err := tlsConn.Handshake(); err != nil {
log.Errorln(err)
}
defer tlsConn.Close()
t.stopCh <- struct{}{}
}()
}
// StartFTP starts a listener that negotiates a TLS connection with an ftp
// client using AUTH TLS
func (t *TCPServer) StartFTP() {
go func() {
conn, err := t.Listener.Accept()
if err != nil {
panic(fmt.Sprintf("Error accepting on socket: %s", err))
}
defer conn.Close()
fmt.Fprintf(conn, "220 Test FTP Service\n")
if _, e := fmt.Fscanf(conn, "AUTH TLS\n"); e != nil {
panic("Error in dialog. No AUTH TLS received.")
}
fmt.Fprintf(conn, "234 AUTH command ok. Expecting TLS Negotiation.\n")
// Upgrade to TLS.
tlsConn := tls.Server(conn, t.TLS)
if err := tlsConn.Handshake(); err != nil {
log.Errorln(err)
}
defer tlsConn.Close()
t.stopCh <- struct{}{}
}()
}
// StartIMAP starts a listener that negotiates a TLS connection with an imap
// client using STARTTLS
func (t *TCPServer) StartIMAP() {
go func() {
conn, err := t.Listener.Accept()
if err != nil {
panic(fmt.Sprintf("Error accepting on socket: %s", err))
}
defer conn.Close()
fmt.Fprintf(conn, "* OK XIMAP ready for requests\n")
if _, e := fmt.Fscanf(conn, ". CAPABILITY\n"); e != nil {
panic("Error in dialog. No . CAPABILITY received.")
}
fmt.Fprintf(conn, "* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN STARTTLS\n")
fmt.Fprintf(conn, ". OK CAPABILITY completed.\n")
if _, e := fmt.Fscanf(conn, ". STARTTLS\n"); e != nil {
panic("Error in dialog. No . STARTTLS received.")
}
fmt.Fprintf(conn, ". OK Begin TLS negotiation now.\n")
// Upgrade to TLS.
tlsConn := tls.Server(conn, t.TLS)
if err := tlsConn.Handshake(); err != nil {
log.Errorln(err)
}
defer tlsConn.Close()
t.stopCh <- struct{}{}
}()
}
// Close stops the server and closes the listener
func (t *TCPServer) Close() {
<-t.stopCh