From 2faf8c5dc46aa6cd45e91eaa74a83f07b227d44d Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Fri, 29 Jan 2016 01:01:21 +0100 Subject: TLS Solver --- cmd/acme/main.go | 13 ++++++---- solve_http.go | 11 +++++---- solve_tls.go | 73 ++++++++++++++++++++++++++------------------------------ 3 files changed, 49 insertions(+), 48 deletions(-) diff --git a/cmd/acme/main.go b/cmd/acme/main.go index a9d41af..95b1418 100644 --- a/cmd/acme/main.go +++ b/cmd/acme/main.go @@ -86,16 +86,21 @@ func main() { log.Fatal(err) } - httpSol := acme.NewHTTPSolver(conf.Defaults.Listen) - tlsSol := acme.NewTLSSolver(conf.Defaults.ListenTLS) + httpSol, err := acme.NewHTTPSolver(conf.Defaults.Listen) + if err != nil { + log.Fatal(err) + } + tlsSol, err := acme.NewTLSSolver(conf.Defaults.ListenTLS) + if err != nil { + log.Fatal(err) + } for k, des := range conf.Desire { if des.Webroot != "" { wrSol := acme.NewWebrootSolver(des.Webroot) des.RegisterSolver(acme.ChallengeHTTP, wrSol) } else { - //des.RegisterSolver(acme.ChallengeHTTP, httpSol) - _ = httpSol + des.RegisterSolver(acme.ChallengeHTTP, httpSol) } des.RegisterSolver(acme.ChallengeTLS, tlsSol) diff --git a/solve_http.go b/solve_http.go index d4f5635..0175760 100644 --- a/solve_http.go +++ b/solve_http.go @@ -11,16 +11,17 @@ type httpSolver struct { http.Server } -func NewHTTPSolver(addr string) Solver { - s := new(httpSolver) - s.Server = http.Server{Addr: addr} +func NewHTTPSolver(addr string) (Solver, error) { + s := &httpSolver{ + Server: http.Server{Addr: addr}, + } go s.ListenAndServe() - return s + return s, nil } func (s *httpSolver) Solve(token, keyAuth string) error { p := path.Join(WellKnown, token) - log.Println("solve http", p) + log.Println("solve http") http.HandleFunc(p, func(w http.ResponseWriter, r *http.Request) { io.WriteString(w, keyAuth) }) diff --git a/solve_tls.go b/solve_tls.go index 6b8869e..00ef6f0 100644 --- a/solve_tls.go +++ b/solve_tls.go @@ -8,25 +8,48 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/hex" + "errors" "log" "math/big" - "net" "net/http" "time" ) +var errNoCert = errors.New("no cert") + type tlsSolver struct { http.Server + sni map[string]*tls.Certificate +} + +func (s *tlsSolver) getCert(h *tls.ClientHelloInfo) (*tls.Certificate, error) { + if crt, ok := s.sni[h.ServerName]; ok { + return crt, nil + } + return nil, errNoCert } -func NewTLSSolver(addr string) Solver { - s := new(tlsSolver) - s.Server = http.Server{ - Addr: addr, - TLSConfig: &tls.Config{}, +func NewTLSSolver(addr string) (Solver, error) { + // we need at least one cert + dummy, err := newCert(sniName("")) + if err != nil { + return nil, err + } + + config := &tls.Config{ + Certificates: []tls.Certificate{dummy}, + //GetCertificate: s.getCert, } - go ListenAndServeSNI(&s.Server) - return s + s := &tlsSolver{ + Server: http.Server{ + Addr: addr, + TLSConfig: config, + }, + sni: make(map[string]*tls.Certificate), + } + s.Server.TLSConfig.GetCertificate = s.getCert + go s.ListenAndServeTLS("", "") + return s, nil } func newCert(domain string) (tls.Certificate, error) { @@ -73,43 +96,15 @@ func sniName(keyAuth string) string { func (s *tlsSolver) Solve(_, keyAuth string) error { log.Println("solve tls") - crt, err := newCert(sniName(keyAuth)) + name := sniName(keyAuth) + crt, err := newCert(name) if err != nil { return err } - s.TLSConfig.Certificates = append(s.TLSConfig.Certificates, crt) - s.TLSConfig.BuildNameToCertificate() - log.Printf(">>> %+v\n", s.TLSConfig.NameToCertificate) + s.sni[name] = &crt return nil } func (s *tlsSolver) Solved() error { return nil } - -func ListenAndServeSNI(srv *http.Server) error { - addr := srv.Addr - if addr == "" { - addr = ":https" - } - config := &tls.Config{} - if srv.TLSConfig != nil { - *config = *srv.TLSConfig - } - if config.NextProtos == nil { - config.NextProtos = []string{"http/1.1"} - } - // we need at least one cert - dummy, err := newCert(sniName("")) - if err != nil { - return err - } - config.Certificates = []tls.Certificate{dummy} - config.BuildNameToCertificate() - conn, err := net.Listen("tcp", addr) - if err != nil { - return err - } - tlsListener := tls.NewListener(conn, config) - return srv.Serve(tlsListener) -} -- cgit v1.2.3