From 93fe863f2ddc08174af28f09f898f4544e606f4e Mon Sep 17 00:00:00 2001 From: Patrick Hener Date: Thu, 11 Jul 2024 14:29:08 +0200 Subject: [PATCH 1/2] implement ca certificate based authentication --- httpserver/helper.go | 17 +++++++++++++++++ httpserver/server.go | 11 +++++++++++ httpserver/structs.go | 1 + main.go | 18 +++++++++++++++--- 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/httpserver/helper.go b/httpserver/helper.go index 6cfe921..2b7d4f7 100644 --- a/httpserver/helper.go +++ b/httpserver/helper.go @@ -1,7 +1,11 @@ package httpserver import ( + "crypto/tls" + "crypto/x509" "io/fs" + "net/http" + "os" "strings" "github.com/patrickhener/goshs/logger" @@ -36,3 +40,16 @@ func (files *FileServer) PrintEmbeddedFiles() { } } + +func (files *FileServer) AddCertAuth(server *http.Server) { + logger.Infof("Using certificate auth with ca certificate: %+v", files.CACert) + caCert, err := os.ReadFile(files.CACert) + if err != nil { + logger.Fatalf("error reading the ca certificate for cert based client authentication: %+v", err) + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + server.TLSConfig.ClientCAs = caCertPool + server.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert +} diff --git a/httpserver/server.go b/httpserver/server.go index c10cddb..1326aff 100644 --- a/httpserver/server.go +++ b/httpserver/server.go @@ -104,6 +104,12 @@ func (fs *FileServer) Start(what string) { logger.Fatalf("Unable to start SSL enabled server: %+v\n", err) } server.TLSConfig = serverTLSConf + + // If client-cert auth add it to TLS Config of server + if fs.CACert != "" { + fs.AddCertAuth(&server) + } + fs.Fingerprint256 = fingerprint256 fs.Fingerprint1 = fingerprint1 fs.logStart(what) @@ -162,6 +168,11 @@ func (fs *FileServer) Start(what string) { MinVersion: tls.VersionTLS12, } + // If client-cert auth add it to TLS Config of server + if fs.CACert != "" { + fs.AddCertAuth(&server) + } + fs.Fingerprint256 = fingerprint256 fs.Fingerprint1 = fingerprint1 fs.logStart(what) diff --git a/httpserver/structs.go b/httpserver/structs.go index 6f1054f..d5e2c08 100644 --- a/httpserver/structs.go +++ b/httpserver/structs.go @@ -53,6 +53,7 @@ type FileServer struct { MyP12 string User string Pass string + CACert string DropUser string Version string Fingerprint256 string diff --git a/main.go b/main.go index 641458c..8ef6068 100644 --- a/main.go +++ b/main.go @@ -29,6 +29,7 @@ var ( myCert = "" myP12 = "" basicAuth = "" + certAuth = "" webdav = false webdavPort = 8001 uploadOnly = false @@ -75,8 +76,9 @@ TLS options: -slt, --le-tls Port to use for Let's Encrypt TLS ALPN Challenge (default: 443) Authentication options: - -b, --basic-auth Use basic authentication (user:pass - user can be empty) - -H, --hash Hash a password for file based ACLs + -b, --basic-auth Use basic authentication (user:pass - user can be empty) + -ca, --cert-auth Use certificate based authentication - provide ca certificate + -H, --hash Hash a password for file based ACLs Misc options: -u --user Drop privs to user (unix only) (default: current user) @@ -121,6 +123,8 @@ func init() { flag.StringVar(&myP12, "pkcs12", myP12, "server p12") flag.StringVar(&basicAuth, "b", basicAuth, "basic auth") flag.StringVar(&basicAuth, "basic-auth", basicAuth, "basic auth") + flag.StringVar(&certAuth, "ca", certAuth, "cert auth") + flag.StringVar(&certAuth, "cert-auth", certAuth, "cert auth") flag.BoolVar(&webdav, "w", webdav, "enable webdav") flag.BoolVar(&webdav, "webdav", webdav, "enable webdav") flag.IntVar(&webdavPort, "wp", webdavPort, "webdav port") @@ -191,7 +195,14 @@ func init() { // Sanity check if cli mode is combined with auth and tls if cli && (!ssl || basicAuth == "") { - logger.Fatal("With cli mode you need to enable basic auth and tls for security reasons.") + if cli && (!ssl || certAuth == "") { + logger.Fatal("With cli mode you need to enable basic/cert auth and tls for security reasons.") + } + } + + // Sanity check if CA mode enabled you will also need TLS enabled in some way + if certAuth != "" && !ssl { + logger.Fatal("To use certificate based authentication with a CA cert you will need tls in any mode (-ss, -sk/-sc, -p12, -sl)") } if webdav { @@ -258,6 +269,7 @@ func main() { MyP12: myP12, User: user, Pass: pass, + CACert: certAuth, DropUser: dropuser, UploadOnly: uploadOnly, ReadOnly: readOnly, From 89f38014de52e1d9a77112b426742213f2de2399 Mon Sep 17 00:00:00 2001 From: Patrick Hener Date: Thu, 11 Jul 2024 14:31:27 +0200 Subject: [PATCH 2/2] version and README --- README.md | 6 ++++-- main.go | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6b2b8c1..f843575 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Version](https://img.shields.io/badge/Version-v0.4.0-green) +![Version](https://img.shields.io/badge/Version-v0.4.1-green) [![GitHub](https://img.shields.io/github/license/patrickhener/goshs)](https://github.com/patrickhener/goshs/blob/master/LICENSE) ![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/patrickhener/goshs) [![GitHub issues](https://img.shields.io/github/issues-raw/patrickhener/goshs)](https://github.com/patrickhener/goshs/issues) @@ -26,7 +26,9 @@ For a detailed documentation go to [goshs.de](https://goshs.de) * Delete files * Individually * Bulk delete -* Basic Authentication +* Authentication + * Basic Authentication + * Certificate Based Authentication via Client Certificate * Transport Layer Security (HTTPS) * self-signed * let's encrypt diff --git a/main.go b/main.go index 8ef6068..87050a4 100644 --- a/main.go +++ b/main.go @@ -15,7 +15,7 @@ import ( "github.com/patrickhener/goshs/utils" ) -const goshsVersion = "v0.4.0" +const goshsVersion = "v0.4.1" var ( port = 8000