Restructured log format in acme module

- Replaced all log.Println in acme module to system wide logger
- Fixed file manager path escape bug #274
This commit is contained in:
Toby Chui 2024-08-13 21:56:23 +08:00
parent a5ef6456c6
commit a7f89086d4
9 changed files with 63 additions and 54 deletions

View File

@ -38,7 +38,7 @@ func initACME() *acme.ACMEHandler {
port = getRandomPort(30000) port = getRandomPort(30000)
} }
return acme.NewACME("https://acme-v02.api.letsencrypt.org/directory", strconv.Itoa(port), sysdb) return acme.NewACME("https://acme-v02.api.letsencrypt.org/directory", strconv.Itoa(port), sysdb, SystemWideLogger)
} }
// create the special routing rule for ACME // create the special routing rule for ACME

View File

@ -11,7 +11,6 @@ import (
"encoding/pem" "encoding/pem"
"errors" "errors"
"fmt" "fmt"
"log"
"net" "net"
"net/http" "net/http"
"os" "os"
@ -26,6 +25,7 @@ import (
"github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/registration" "github.com/go-acme/lego/v4/registration"
"imuslab.com/zoraxy/mod/database" "imuslab.com/zoraxy/mod/database"
"imuslab.com/zoraxy/mod/info/logger"
"imuslab.com/zoraxy/mod/utils" "imuslab.com/zoraxy/mod/utils"
) )
@ -68,25 +68,31 @@ type ACMEHandler struct {
DefaultAcmeServer string DefaultAcmeServer string
Port string Port string
Database *database.Database Database *database.Database
Logger *logger.Logger
} }
// NewACME creates a new ACMEHandler instance. // NewACME creates a new ACMEHandler instance.
func NewACME(acmeServer string, port string, database *database.Database) *ACMEHandler { func NewACME(defaultAcmeServer string, port string, database *database.Database, logger *logger.Logger) *ACMEHandler {
return &ACMEHandler{ return &ACMEHandler{
DefaultAcmeServer: acmeServer, DefaultAcmeServer: defaultAcmeServer,
Port: port, Port: port,
Database: database, Database: database,
Logger: logger,
} }
} }
func (a *ACMEHandler) Logf(message string, err error) {
a.Logger.PrintAndLog("ACME", message, err)
}
// ObtainCert obtains a certificate for the specified domains. // ObtainCert obtains a certificate for the specified domains.
func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, caName string, caUrl string, skipTLS bool, useDNS bool) (bool, error) { func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email string, caName string, caUrl string, skipTLS bool, useDNS bool) (bool, error) {
log.Println("[ACME] Obtaining certificate...") a.Logf("Obtaining certificate for: "+strings.Join(domains, ", "), nil)
// generate private key // generate private key
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil { if err != nil {
log.Println(err) a.Logf("Private key generation failed", err)
return false, err return false, err
} }
@ -102,7 +108,7 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
// skip TLS verify if need // skip TLS verify if need
// Ref: https://github.com/go-acme/lego/blob/6af2c756ac73a9cb401621afca722d0f4112b1b8/lego/client_config.go#L74 // Ref: https://github.com/go-acme/lego/blob/6af2c756ac73a9cb401621afca722d0f4112b1b8/lego/client_config.go#L74
if skipTLS { if skipTLS {
log.Println("[INFO] Ignore TLS/SSL Verification Error for ACME Server") a.Logf("Ignoring TLS/SSL Verification Error for ACME Server", nil)
config.HTTPClient.Transport = &http.Transport{ config.HTTPClient.Transport = &http.Transport{
Proxy: http.ProxyFromEnvironment, Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{ DialContext: (&net.Dialer{
@ -129,16 +135,16 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
// if not custom ACME url, load it from ca.json // if not custom ACME url, load it from ca.json
if caName == "custom" { if caName == "custom" {
log.Println("[INFO] Using Custom ACME " + caUrl + " for CA Directory URL") a.Logf("Using Custom ACME "+caUrl+" for CA Directory URL", nil)
} else { } else {
caLinkOverwrite, err := loadCAApiServerFromName(caName) caLinkOverwrite, err := loadCAApiServerFromName(caName)
if err == nil { if err == nil {
config.CADirURL = caLinkOverwrite config.CADirURL = caLinkOverwrite
log.Println("[INFO] Using " + caLinkOverwrite + " for CA Directory URL") a.Logf("Using "+caLinkOverwrite+" for CA Directory URL", nil)
} else { } else {
// (caName == "" || caUrl == "") will use default acme // (caName == "" || caUrl == "") will use default acme
config.CADirURL = a.DefaultAcmeServer config.CADirURL = a.DefaultAcmeServer
log.Println("[INFO] Using Default ACME " + a.DefaultAcmeServer + " for CA Directory URL") a.Logf("[INFO] Using Default ACME "+a.DefaultAcmeServer+" for CA Directory URL", nil)
} }
} }
@ -146,7 +152,7 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
client, err := lego.NewClient(config) client, err := lego.NewClient(config)
if err != nil { if err != nil {
log.Println(err) a.Logf("Failed to spawn new ACME client from current config", err)
return false, err return false, err
} }
@ -164,32 +170,32 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
var dnsCredentials string var dnsCredentials string
err := a.Database.Read("acme", certificateName+"_dns_credentials", &dnsCredentials) err := a.Database.Read("acme", certificateName+"_dns_credentials", &dnsCredentials)
if err != nil { if err != nil {
log.Println(err) a.Logf("Read DNS credential failed", err)
return false, err return false, err
} }
var dnsProvider string var dnsProvider string
err = a.Database.Read("acme", certificateName+"_dns_provider", &dnsProvider) err = a.Database.Read("acme", certificateName+"_dns_provider", &dnsProvider)
if err != nil { if err != nil {
log.Println(err) a.Logf("Read DNS Provider failed", err)
return false, err return false, err
} }
provider, err := GetDnsChallengeProviderByName(dnsProvider, dnsCredentials) provider, err := GetDnsChallengeProviderByName(dnsProvider, dnsCredentials)
if err != nil { if err != nil {
log.Println(err) a.Logf("Unable to resolve DNS challenge provider", err)
return false, err return false, err
} }
err = client.Challenge.SetDNS01Provider(provider) err = client.Challenge.SetDNS01Provider(provider)
if err != nil { if err != nil {
log.Println(err) a.Logf("Failed to resolve DNS01 Provider", err)
return false, err return false, err
} }
} else { } else {
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", a.Port)) err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", a.Port))
if err != nil { if err != nil {
log.Println(err) a.Logf("Failed to resolve HTTP01 Provider", err)
return false, err return false, err
} }
} }
@ -205,7 +211,7 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
var reg *registration.Resource var reg *registration.Resource
// New users will need to register // New users will need to register
if client.GetExternalAccountRequired() { if client.GetExternalAccountRequired() {
log.Println("External Account Required for this ACME Provider.") a.Logf("External Account Required for this ACME Provider", nil)
// IF KID and HmacEncoded is overidden // IF KID and HmacEncoded is overidden
if !a.Database.TableExists("acme") { if !a.Database.TableExists("acme") {
@ -220,20 +226,18 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
var kid string var kid string
var hmacEncoded string var hmacEncoded string
err := a.Database.Read("acme", config.CADirURL+"_kid", &kid) err := a.Database.Read("acme", config.CADirURL+"_kid", &kid)
if err != nil { if err != nil {
log.Println(err) a.Logf("Failed to read kid from database", err)
return false, err return false, err
} }
err = a.Database.Read("acme", config.CADirURL+"_hmacEncoded", &hmacEncoded) err = a.Database.Read("acme", config.CADirURL+"_hmacEncoded", &hmacEncoded)
if err != nil { if err != nil {
log.Println(err) a.Logf("Failed to read HMAC from database", err)
return false, err return false, err
} }
log.Println("EAB Credential retrieved.", kid, hmacEncoded) a.Logf("EAB Credential retrieved: "+kid+" / "+hmacEncoded, nil)
if kid != "" && hmacEncoded != "" { if kid != "" && hmacEncoded != "" {
reg, err = client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{ reg, err = client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{
TermsOfServiceAgreed: true, TermsOfServiceAgreed: true,
@ -242,14 +246,14 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
}) })
} }
if err != nil { if err != nil {
log.Println(err) a.Logf("Register with external account binder failed", err)
return false, err return false, err
} }
//return false, errors.New("External Account Required for this ACME Provider.") //return false, errors.New("External Account Required for this ACME Provider.")
} else { } else {
reg, err = client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true}) reg, err = client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil { if err != nil {
log.Println(err) a.Logf("Unable to register client", err)
return false, err return false, err
} }
} }
@ -262,7 +266,7 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
} }
certificates, err := client.Certificate.Obtain(request) certificates, err := client.Certificate.Obtain(request)
if err != nil { if err != nil {
log.Println(err) a.Logf("Obtain certificate failed", err)
return false, err return false, err
} }
@ -270,12 +274,12 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
// private key, and a certificate URL. // private key, and a certificate URL.
err = os.WriteFile("./conf/certs/"+certificateName+".pem", certificates.Certificate, 0777) err = os.WriteFile("./conf/certs/"+certificateName+".pem", certificates.Certificate, 0777)
if err != nil { if err != nil {
log.Println(err) a.Logf("Failed to write public key to disk", err)
return false, err return false, err
} }
err = os.WriteFile("./conf/certs/"+certificateName+".key", certificates.PrivateKey, 0777) err = os.WriteFile("./conf/certs/"+certificateName+".key", certificates.PrivateKey, 0777)
if err != nil { if err != nil {
log.Println(err) a.Logf("Failed to write private key to disk", err)
return false, err return false, err
} }
@ -289,13 +293,13 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email
certInfoBytes, err := json.Marshal(certInfo) certInfoBytes, err := json.Marshal(certInfo)
if err != nil { if err != nil {
log.Println(err) a.Logf("Marshal certificate renew config failed", err)
return false, err return false, err
} }
err = os.WriteFile("./conf/certs/"+certificateName+".json", certInfoBytes, 0777) err = os.WriteFile("./conf/certs/"+certificateName+".json", certInfoBytes, 0777)
if err != nil { if err != nil {
log.Println(err) a.Logf("Failed to write certificate renew config to file", err)
return false, err return false, err
} }
@ -313,7 +317,7 @@ func (a *ACMEHandler) CheckCertificate() []string {
expiredCerts := []string{} expiredCerts := []string{}
if err != nil { if err != nil {
log.Println(err) a.Logf("Failed to load certificate folder", err)
return []string{} return []string{}
} }
@ -410,14 +414,14 @@ func (a *ACMEHandler) HandleRenewCertificate(w http.ResponseWriter, r *http.Requ
ca, err := utils.PostPara(r, "ca") ca, err := utils.PostPara(r, "ca")
if err != nil { if err != nil {
log.Println("[INFO] CA not set. Using default") a.Logf("CA not set. Using default", nil)
ca, caUrl = "", "" ca, caUrl = "", ""
} }
if ca == "custom" { if ca == "custom" {
caUrl, err = utils.PostPara(r, "caURL") caUrl, err = utils.PostPara(r, "caURL")
if err != nil { if err != nil {
log.Println("[INFO] Custom CA set but no URL provide, Using default") a.Logf("Custom CA set but no URL provide, Using default", nil)
ca, caUrl = "", "" ca, caUrl = "", ""
} }
} }
@ -465,7 +469,7 @@ func (a *ACMEHandler) HandleRenewCertificate(w http.ResponseWriter, r *http.Requ
func jsonEscape(i string) string { func jsonEscape(i string) string {
b, err := json.Marshal(i) b, err := json.Marshal(i)
if err != nil { if err != nil {
log.Println("Unable to escape json data: " + err.Error()) //log.Println("Unable to escape json data: " + err.Error())
return i return i
} }
s := string(b) s := string(b)

View File

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"log"
"net/http" "net/http"
"net/mail" "net/mail"
"os" "os"
@ -12,6 +11,7 @@ import (
"strings" "strings"
"time" "time"
"imuslab.com/zoraxy/mod/info/logger"
"imuslab.com/zoraxy/mod/utils" "imuslab.com/zoraxy/mod/utils"
) )
@ -36,6 +36,7 @@ type AutoRenewer struct {
RenewTickInterval int64 RenewTickInterval int64
EarlyRenewDays int //How many days before cert expire to renew certificate EarlyRenewDays int //How many days before cert expire to renew certificate
TickerstopChan chan bool TickerstopChan chan bool
Logger *logger.Logger //System wide logger
} }
type ExpiredCerts struct { type ExpiredCerts struct {
@ -45,7 +46,7 @@ type ExpiredCerts struct {
// Create an auto renew agent, require config filepath and auto scan & renew interval (seconds) // Create an auto renew agent, require config filepath and auto scan & renew interval (seconds)
// Set renew check interval to 0 for auto (1 day) // Set renew check interval to 0 for auto (1 day)
func NewAutoRenewer(config string, certFolder string, renewCheckInterval int64, earlyRenewDays int, AcmeHandler *ACMEHandler) (*AutoRenewer, error) { func NewAutoRenewer(config string, certFolder string, renewCheckInterval int64, earlyRenewDays int, AcmeHandler *ACMEHandler, logger *logger.Logger) (*AutoRenewer, error) {
if renewCheckInterval == 0 { if renewCheckInterval == 0 {
renewCheckInterval = 86400 //1 day renewCheckInterval = 86400 //1 day
} }
@ -87,6 +88,7 @@ func NewAutoRenewer(config string, certFolder string, renewCheckInterval int64,
AcmeHandler: AcmeHandler, AcmeHandler: AcmeHandler,
RenewerConfig: &renewerConfig, RenewerConfig: &renewerConfig,
RenewTickInterval: renewCheckInterval, RenewTickInterval: renewCheckInterval,
Logger: logger,
} }
if thisRenewer.RenewerConfig.Enabled { if thisRenewer.RenewerConfig.Enabled {
@ -100,6 +102,10 @@ func NewAutoRenewer(config string, certFolder string, renewCheckInterval int64,
return &thisRenewer, nil return &thisRenewer, nil
} }
func (a *AutoRenewer) Logf(message string, err error) {
a.Logger.PrintAndLog("CertRenew", message, err)
}
func (a *AutoRenewer) StartAutoRenewTicker() { func (a *AutoRenewer) StartAutoRenewTicker() {
//Stop the previous ticker if still running //Stop the previous ticker if still running
if a.TickerstopChan != nil { if a.TickerstopChan != nil {
@ -118,7 +124,7 @@ func (a *AutoRenewer) StartAutoRenewTicker() {
case <-done: case <-done:
return return
case <-ticker.C: case <-ticker.C:
log.Println("Check and renew certificates in progress") a.Logf("Check and renew certificates in progress", nil)
a.CheckAndRenewCertificates() a.CheckAndRenewCertificates()
} }
} }
@ -233,12 +239,12 @@ func (a *AutoRenewer) HandleAutoRenewEnable(w http.ResponseWriter, r *http.Reque
} }
a.RenewerConfig.Enabled = true a.RenewerConfig.Enabled = true
a.saveRenewConfigToFile() a.saveRenewConfigToFile()
log.Println("[ACME] ACME auto renew enabled") a.Logf("ACME auto renew enabled", nil)
a.StartAutoRenewTicker() a.StartAutoRenewTicker()
} else { } else {
a.RenewerConfig.Enabled = false a.RenewerConfig.Enabled = false
a.saveRenewConfigToFile() a.saveRenewConfigToFile()
log.Println("[ACME] ACME auto renew disabled") a.Logf("ACME auto renew disabled", nil)
a.StopAutoRenewTicker() a.StopAutoRenewTicker()
} }
} else { } else {
@ -283,7 +289,7 @@ func (a *AutoRenewer) CheckAndRenewCertificates() ([]string, error) {
certFolder := a.CertFolder certFolder := a.CertFolder
files, err := os.ReadDir(certFolder) files, err := os.ReadDir(certFolder)
if err != nil { if err != nil {
log.Println("Unable to renew certificates: " + err.Error()) a.Logf("Read certificate store failed", err)
return []string{}, err return []string{}, err
} }
@ -303,7 +309,7 @@ func (a *AutoRenewer) CheckAndRenewCertificates() ([]string, error) {
DNSName, err := ExtractDomains(certBytes) DNSName, err := ExtractDomains(certBytes)
if err != nil { if err != nil {
//Maybe self signed. Ignore this //Maybe self signed. Ignore this
log.Println("Encounted error when trying to resolve DNS name for cert " + file.Name()) a.Logf("Encounted error when trying to resolve DNS name for cert "+file.Name(), err)
continue continue
} }
@ -327,11 +333,10 @@ func (a *AutoRenewer) CheckAndRenewCertificates() ([]string, error) {
} }
if CertExpireSoon(certBytes, a.EarlyRenewDays) || CertIsExpired(certBytes) { if CertExpireSoon(certBytes, a.EarlyRenewDays) || CertIsExpired(certBytes) {
//This cert is expired //This cert is expired
DNSName, err := ExtractDomains(certBytes) DNSName, err := ExtractDomains(certBytes)
if err != nil { if err != nil {
//Maybe self signed. Ignore this //Maybe self signed. Ignore this
log.Println("Encounted error when trying to resolve DNS name for cert " + file.Name()) a.Logf("Encounted error when trying to resolve DNS name for cert "+file.Name(), err)
continue continue
} }
@ -358,7 +363,7 @@ func (a *AutoRenewer) Close() {
func (a *AutoRenewer) renewExpiredDomains(certs []*ExpiredCerts) ([]string, error) { func (a *AutoRenewer) renewExpiredDomains(certs []*ExpiredCerts) ([]string, error) {
renewedCertFiles := []string{} renewedCertFiles := []string{}
for _, expiredCert := range certs { for _, expiredCert := range certs {
log.Println("Renewing " + expiredCert.Filepath + " (Might take a few minutes)") a.Logf("Renewing "+expiredCert.Filepath+" (Might take a few minutes)", nil)
fileName := filepath.Base(expiredCert.Filepath) fileName := filepath.Base(expiredCert.Filepath)
certName := fileName[:len(fileName)-len(filepath.Ext(fileName))] certName := fileName[:len(fileName)-len(filepath.Ext(fileName))]
@ -366,10 +371,10 @@ func (a *AutoRenewer) renewExpiredDomains(certs []*ExpiredCerts) ([]string, erro
certInfoFilename := fmt.Sprintf("%s/%s.json", filepath.Dir(expiredCert.Filepath), certName) certInfoFilename := fmt.Sprintf("%s/%s.json", filepath.Dir(expiredCert.Filepath), certName)
certInfo, err := LoadCertInfoJSON(certInfoFilename) certInfo, err := LoadCertInfoJSON(certInfoFilename)
if err != nil { if err != nil {
log.Printf("Renew %s certificate error, can't get the ACME detail for cert: %v, trying org section as ca", certName, err) a.Logf("Renew "+certName+"certificate error, can't get the ACME detail for certificate, trying org section as ca", err)
if CAName, extractErr := ExtractIssuerNameFromPEM(expiredCert.Filepath); extractErr != nil { if CAName, extractErr := ExtractIssuerNameFromPEM(expiredCert.Filepath); extractErr != nil {
log.Printf("extract issuer name for cert error: %v, using default ca", extractErr) a.Logf("Extract issuer name for cert error, using default ca", err)
certInfo = &CertificateInfoJSON{} certInfo = &CertificateInfoJSON{}
} else { } else {
certInfo = &CertificateInfoJSON{AcmeName: CAName} certInfo = &CertificateInfoJSON{AcmeName: CAName}
@ -378,9 +383,9 @@ func (a *AutoRenewer) renewExpiredDomains(certs []*ExpiredCerts) ([]string, erro
_, err = a.AcmeHandler.ObtainCert(expiredCert.Domains, certName, a.RenewerConfig.Email, certInfo.AcmeName, certInfo.AcmeUrl, certInfo.SkipTLS, certInfo.UseDNS) _, err = a.AcmeHandler.ObtainCert(expiredCert.Domains, certName, a.RenewerConfig.Email, certInfo.AcmeName, certInfo.AcmeUrl, certInfo.SkipTLS, certInfo.UseDNS)
if err != nil { if err != nil {
log.Println("Renew " + fileName + "(" + strings.Join(expiredCert.Domains, ",") + ") failed: " + err.Error()) a.Logf("Renew "+fileName+"("+strings.Join(expiredCert.Domains, ",")+") failed", err)
} else { } else {
log.Println("Successfully renewed " + filepath.Base(expiredCert.Filepath)) a.Logf("Successfully renewed "+filepath.Base(expiredCert.Filepath), nil)
renewedCertFiles = append(renewedCertFiles, filepath.Base(expiredCert.Filepath)) renewedCertFiles = append(renewedCertFiles, filepath.Base(expiredCert.Filepath))
} }
} }

View File

@ -18,7 +18,7 @@ func (this *defaultDialer) Dial(address string) Socket {
if socket, err := net.DialTimeout("tcp", address, this.timeout); err == nil { if socket, err := net.DialTimeout("tcp", address, this.timeout); err == nil {
return socket return socket
} else { } else {
this.logger.Printf("[INFO] Unable to establish connection to [%s]: %s", address, err) this.logger.Printf("Unable to establish connection to [%s]: %s", address, err)
} }
return nil return nil

View File

@ -17,7 +17,7 @@ func (this *loggingInitializer) Initialize(client, server Socket) bool {
result := this.inner.Initialize(client, server) result := this.inner.Initialize(client, server)
if !result { if !result {
this.logger.Printf("[INFO] Connection failed [%s] -> [%s]", client.RemoteAddr(), server.RemoteAddr()) this.logger.Printf("Connection failed [%s] -> [%s]", client.RemoteAddr(), server.RemoteAddr())
} }
return result return result

View File

@ -6,7 +6,6 @@ import (
"embed" "embed"
"encoding/pem" "encoding/pem"
"io" "io"
"log"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -185,7 +184,6 @@ func (m *Manager) GetCert(helloInfo *tls.ClientHelloInfo) (*tls.Certificate, err
//Load the cert and serve it //Load the cert and serve it
cer, err := tls.LoadX509KeyPair(pubKey, priKey) cer, err := tls.LoadX509KeyPair(pubKey, priKey)
if err != nil { if err != nil {
log.Println(err)
return nil, nil return nil, nil
} }

View File

@ -3,7 +3,6 @@ package uptime
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"log"
"net/http" "net/http"
"net/http/cookiejar" "net/http/cookiejar"
"strconv" "strconv"
@ -242,7 +241,7 @@ func getWebsiteStatus(url string) (int, error) {
// Create a one-time use cookie jar to store cookies // Create a one-time use cookie jar to store cookies
jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
if err != nil { if err != nil {
log.Fatal(err) return 0, err
} }
client := http.Client{ client := http.Client{

View File

@ -44,7 +44,9 @@ func (fm *FileManager) HandleList(w http.ResponseWriter, r *http.Request) {
// Clean path to prevent path escape #274 // Clean path to prevent path escape #274
targetDir = filepath.ToSlash(filepath.Clean(targetDir)) targetDir = filepath.ToSlash(filepath.Clean(targetDir))
targetDir = strings.ReplaceAll(targetDir, "../", "") for strings.Contains(targetDir, "../") {
targetDir = strings.ReplaceAll(targetDir, "../", "")
}
// Open the target directory // Open the target directory
dirEntries, err := os.ReadDir(targetDir) dirEntries, err := os.ReadDir(targetDir)

View File

@ -285,6 +285,7 @@ func startupSequence() {
int64(*acmeAutoRenewInterval), int64(*acmeAutoRenewInterval),
*acmeCertAutoRenewDays, *acmeCertAutoRenewDays,
acmeHandler, acmeHandler,
SystemWideLogger,
) )
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)