From 8d76ab2544b89bf6fe09e8e5e16d4d1c24b1b0d6 Mon Sep 17 00:00:00 2001 From: Patrick Hener Date: Fri, 5 Jul 2024 15:30:19 +0200 Subject: [PATCH] Implement p12 feature and leave key and cert mechanism as is --- go.mod | 1 + go.sum | 2 ++ httpserver/error.go | 2 +- httpserver/server.go | 49 ++++++++++++++++++++++++++++++++++++------- httpserver/structs.go | 1 + main.go | 5 +++++ 6 files changed, 51 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index e88d8e6..f0936a6 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/sirupsen/logrus v1.9.3 golang.org/x/crypto v0.21.0 golang.org/x/net v0.23.0 + software.sslmate.com/src/go-pkcs12 v0.4.0 ) require ( diff --git a/go.sum b/go.sum index 7679413..f54e78f 100644 --- a/go.sum +++ b/go.sum @@ -46,3 +46,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k= +software.sslmate.com/src/go-pkcs12 v0.4.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= diff --git a/httpserver/error.go b/httpserver/error.go index 44bb5c5..9c40749 100644 --- a/httpserver/error.go +++ b/httpserver/error.go @@ -71,7 +71,7 @@ func (fs *FileServer) logStart(what string) { logger.Infof("SHA-256 Fingerprint: %+v\n", fs.Fingerprint256) logger.Infof("SHA-1 Fingerprint: %+v\n", fs.Fingerprint1) } else { - logger.Infof("Serving %s from %+v with ssl enabled server key: %+v, server cert: %+v\n", protocol, fs.Webroot, fs.MyKey, fs.MyCert) + logger.Infof("Serving %s from %+v with ssl enabled server key: %+v, server cert: %+v, server p12: %+v\n", protocol, fs.Webroot, fs.MyKey, fs.MyCert, fs.MyP12) logger.Info("You provided a certificate and might want to check the fingerprint nonetheless") logger.Infof("SHA-256 Fingerprint: %+v\n", fs.Fingerprint256) logger.Infof("SHA-1 Fingerprint: %+v\n", fs.Fingerprint1) diff --git a/httpserver/server.go b/httpserver/server.go index fa48785..2a512d3 100644 --- a/httpserver/server.go +++ b/httpserver/server.go @@ -7,14 +7,17 @@ import ( "log" "net" "net/http" + "os" "time" "github.com/gorilla/mux" + "github.com/howeyc/gopass" "github.com/patrickhener/goshs/ca" "github.com/patrickhener/goshs/clipboard" "github.com/patrickhener/goshs/logger" "github.com/patrickhener/goshs/ws" "golang.org/x/net/webdav" + "software.sslmate.com/src/go-pkcs12" ) // Start will start the file server @@ -111,17 +114,47 @@ func (fs *FileServer) Start(what string) { logger.Panic(server.ServeTLS(listener, "", "")) } else { if fs.MyCert == "" || fs.MyKey == "" { - logger.Fatal("You need to provide server.key and server.crt if -s and not -ss") + if fs.MyP12 == "" { + logger.Fatal("You need to provide either server.key and server.crt or server.p12 if -s and not -ss") + } } - fingerprint256, fingerprint1, err := ca.ParseAndSum(fs.MyCert) - if err != nil { - logger.Fatalf("Unable to start SSL enabled server: %+v\n", err) - } + var cert tls.Certificate + var fingerprint256, fingerprint1 string - cert, err := tls.LoadX509KeyPair(fs.MyCert, fs.MyKey) - if err != nil { - logger.Fatalf("Failed to load provided key or certificate: %+v\n", err) + if fs.MyP12 != "" { + p12, err := os.ReadFile("cert.p12") + if err != nil { + logger.Fatalf("Error reading pkcs12 file: %+v", err) + } + + fmt.Printf("Enter password for %+v: ", fs.MyP12) + password, err := gopass.GetPasswdMasked() + if err != nil { + logger.Fatalf("error reading password from stdin: %+v", err) + } + privKey, certificate, err := pkcs12.Decode(p12, string(password)) + if err != nil { + logger.Fatalf("error parsing the p12 file: %+v", err) + } + + cert = tls.Certificate{ + Certificate: [][]byte{certificate.Raw}, + PrivateKey: privKey, + Leaf: certificate, + } + + fingerprint256, fingerprint1 = ca.Sum(certificate.Raw) + } else { + fingerprint256, fingerprint1, err = ca.ParseAndSum(fs.MyCert) + if err != nil { + logger.Fatalf("Unable to start SSL enabled server: %+v\n", err) + } + + cert, err = tls.LoadX509KeyPair(fs.MyCert, fs.MyKey) + if err != nil { + logger.Fatalf("Failed to load provided key or certificate: %+v\n", err) + } } server.TLSConfig = &tls.Config{ diff --git a/httpserver/structs.go b/httpserver/structs.go index a53401a..6f1054f 100644 --- a/httpserver/structs.go +++ b/httpserver/structs.go @@ -50,6 +50,7 @@ type FileServer struct { LetsEncrypt bool MyKey string MyCert string + MyP12 string User string Pass string DropUser string diff --git a/main.go b/main.go index 13ddf06..c369039 100644 --- a/main.go +++ b/main.go @@ -27,6 +27,7 @@ var ( letsencrypt = false myKey = "" myCert = "" + myP12 = "" basicAuth = "" webdav = false webdavPort = 8001 @@ -66,6 +67,7 @@ TLS options: -ss, --self-signed Use a self-signed certificate -sk, --server-key Path to server key -sc, --server-cert Path to server certificate + -p12, --pkcs12 Path to server p12 -sl, --lets-encrypt Use Let's Encrypt as certification service -sld, --le-domains Domain(s) to request from Let's Encrypt (comma separated list) -sle, --le-email Email to use with Let's Encrypt @@ -115,6 +117,8 @@ func init() { flag.StringVar(&myKey, "server-key", myKey, "server key") flag.StringVar(&myCert, "sc", myCert, "server cert") flag.StringVar(&myCert, "server-cert", myCert, "server cert") + flag.StringVar(&myP12, "p12", myP12, "server p12") + flag.StringVar(&myP12, "pkcs12", myP12, "server p12") flag.StringVar(&basicAuth, "b", basicAuth, "basic auth") flag.StringVar(&basicAuth, "basic-auth", basicAuth, "basic auth") flag.BoolVar(&webdav, "w", webdav, "enable webdav") @@ -251,6 +255,7 @@ func main() { LetsEncrypt: letsencrypt, MyCert: myCert, MyKey: myKey, + MyP12: myP12, User: user, Pass: pass, DropUser: dropuser,