diff --git a/imap.go b/imap.go new file mode 100644 index 0000000..b8dee1f --- /dev/null +++ b/imap.go @@ -0,0 +1,10 @@ +package maddy + +import ( + "github.com/mholt/caddy/caddyfile" + imapserver "github.com/emersion/go-imap/server" +) + +func newIMAPServer(tokens map[string][]caddyfile.Token) server { + return imapserver.New(nil) +} diff --git a/maddy.go b/maddy.go index 158725b..bcb4324 100644 --- a/maddy.go +++ b/maddy.go @@ -1,15 +1,18 @@ package maddy import ( + "crypto/tls" "fmt" "log" "net" "github.com/mholt/caddy/caddyfile" - imapserver "github.com/emersion/go-imap/server" - "github.com/emersion/go-smtp" ) +type server interface { + Serve(net.Listener) error +} + var Directives = []string{ "bind", "tls", @@ -21,6 +24,8 @@ var Directives = []string{ } func Start(blocks []caddyfile.ServerBlock) error { + done := make(chan error, 1) + for _, block := range blocks { var proto string var adresses []Address @@ -40,37 +45,43 @@ func Start(blocks []caddyfile.ServerBlock) error { adresses = append(adresses, addr) } - // TODO: parse directives - + var s server switch proto { case "imap": - s := imapserver.New(nil) // TODO - - for _, addr := range adresses { - l, err := net.Listen("tcp", fmt.Sprintf("%s:%s", addr.Host, addr.Port)) - if err != nil { - return fmt.Errorf("Cannot listen: %v", err) - } - - log.Println("IMAP server listening on", l.Addr().String()) - go s.Serve(l) - } + s = newIMAPServer(block.Tokens) case "smtp": - s := smtp.NewServer(nil) // TODO - - for _, addr := range adresses { - l, err := net.Listen("tcp", fmt.Sprintf("%s:%s", addr.Host, addr.Port)) - if err != nil { - return fmt.Errorf("Cannot listen: %v", err) - } - - log.Println("SMTP server listening on", l.Addr().String()) - go s.Serve(l) - } + s = newSMTPServer(block.Tokens) default: return fmt.Errorf("Unsupported protocol %q", proto) } + + var tlsConfig *tls.Config + if tokens, ok := block.Tokens["tls"]; ok { + var err error + tlsConfig, err = getTLSConfig(caddyfile.NewDispenserTokens("", tokens)) + if err != nil { + return err + } + } + + for _, addr := range adresses { + var l net.Listener + var err error + l, err = net.Listen("tcp", fmt.Sprintf("%s:%s", addr.Host, addr.Port)) + if err != nil { + return fmt.Errorf("Cannot listen: %v", err) + } + + if tlsConfig != nil { + l = tls.NewListener(l, tlsConfig) + } + + log.Printf("%s server listening on %s\n", proto, l.Addr().String()) + go func() { + done <- s.Serve(l) + }() + } } - select {} + return <-done } diff --git a/smtp.go b/smtp.go new file mode 100644 index 0000000..a0055c7 --- /dev/null +++ b/smtp.go @@ -0,0 +1,10 @@ +package maddy + +import ( + "github.com/mholt/caddy/caddyfile" + "github.com/emersion/go-smtp" +) + +func newSMTPServer(tokens map[string][]caddyfile.Token) server { + return smtp.NewServer(nil) +} diff --git a/tls.go b/tls.go new file mode 100644 index 0000000..5ef4360 --- /dev/null +++ b/tls.go @@ -0,0 +1,39 @@ +package maddy + +import ( + "crypto/tls" + "fmt" + + "github.com/mholt/caddy/caddyfile" +) + +func getTLSConfig(d caddyfile.Dispenser) (*tls.Config, error) { + config := new(tls.Config) + + for d.Next() { + args := d.RemainingArgs() + switch len(args) { + case 1: + switch args[0] { + case "off": + return nil, nil + case "self_signed": + if err := makeSelfSignedCert(config); err != nil { + return nil, err + } + } + case 2: + if cert, err := tls.LoadX509KeyPair(args[0], args[1]); err != nil { + return nil, err + } else { + config.Certificates = append(config.Certificates, cert) + } + } + } + + return config, nil +} + +func makeSelfSignedCert(config *tls.Config) error { + return fmt.Errorf("Not yet implemented") +}