From 023838345ddb751e3b7143e87f0c123fc2703eac Mon Sep 17 00:00:00 2001 From: tjpcc Date: Fri, 8 Sep 2023 14:54:56 -0600 Subject: support an env var for allowlisting uploaders by cert fingerprint --- config.go | 20 +++++++++++--------- routes.go | 27 ++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/config.go b/config.go index 39d59bd..4be0790 100644 --- a/config.go +++ b/config.go @@ -6,6 +6,7 @@ import ( "os/signal" "os/user" "strconv" + "strings" "syscall" "tildegit.org/tjp/sliderule/logging" @@ -18,14 +19,20 @@ type config struct { tlsKeyFile string tlsCertFile string + + uploaderFingerprints []string } func configure() config { + fingerprints := strings.Split(os.Getenv("UPLOADER_FINGERPRINTS"), ",") + return config{ hostname: os.Getenv("HOST_NAME"), geminiRoot: os.Getenv("GEMINI_ROOT"), tlsKeyFile: os.Getenv("TLS_KEY_FILE"), tlsCertFile: os.Getenv("TLS_CERT_FILE"), + + uploaderFingerprints: fingerprints, } } @@ -56,16 +63,11 @@ func dropPrivileges() (bool, error) { func serverContext() (context.Context, logging.Logger, logging.Logger, logging.Logger, logging.Logger) { debug, info, warn, err := logging.DefaultLoggers() - ctx := signals(context.Background()) + ctx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGHUP) ctx = context.WithValue(ctx, "debuglog", debug) //nolint:staticcheck - ctx = context.WithValue(ctx, "infolog", info) //nolint:staticcheck - ctx = context.WithValue(ctx, "warnlog", warn) //nolint:staticcheck - ctx = context.WithValue(ctx, "errorlog", err) //nolint:staticcheck + ctx = context.WithValue(ctx, "infolog", info) //nolint:staticcheck + ctx = context.WithValue(ctx, "warnlog", warn) //nolint:staticcheck + ctx = context.WithValue(ctx, "errorlog", err) //nolint:staticcheck return ctx, debug, info, warn, err } - -func signals(ctx context.Context) context.Context { - ctx, _ = signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGHUP) - return ctx -} diff --git a/routes.go b/routes.go index 59e6ff4..0683924 100644 --- a/routes.go +++ b/routes.go @@ -2,7 +2,11 @@ package main import ( "context" + "crypto/sha256" + "crypto/x509" + "encoding/hex" "os" + "sort" "strings" sr "tildegit.org/tjp/sliderule" @@ -20,7 +24,7 @@ func geminiRouter(conf config) sr.Handler { router.Route( "/*", gemini.GeminiOnly(true)(sr.FallthroughHandler( - fs.TitanUpload(tlsauth.Allow, conf.geminiRoot)(postUploadRedirect), + fs.TitanUpload(tlsAuth(conf.uploaderFingerprints), conf.geminiRoot)(postUploadRedirect), fs.GeminiFileHandler(fsys), fs.GeminiDirectoryDefault(fsys, "index.gmi"), fs.GeminiDirectoryListing(fsys, nil), @@ -41,3 +45,24 @@ var postUploadRedirect = sr.HandlerFunc(func(ctx context.Context, request *sr.Re u.Scheme = "gemini" return gemini.Redirect(u.String()) }) + +func tlsAuth(uploaders []string) tlsauth.Approver { + sort.Strings(uploaders) + + return func(cert *x509.Certificate) bool { + raw := sha256.Sum256(cert.Raw) + user := hex.EncodeToString(raw[:]) + + _, found := sort.Find(len(uploaders), func(i int) int { + switch { + case uploaders[i] < user: + return 1 + case uploaders[i] == user: + return 0 + default: + return -1 + } + }) + return found + } +} -- cgit v1.2.3