diff --git a/src/acme.go b/src/acme.go index bfa98fc..2a7a61b 100644 --- a/src/acme.go +++ b/src/acme.go @@ -38,7 +38,7 @@ func initACME() *acme.ACMEHandler { 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 diff --git a/src/mod/acme/acme.go b/src/mod/acme/acme.go index a5040c2..a8916e3 100644 --- a/src/mod/acme/acme.go +++ b/src/mod/acme/acme.go @@ -11,7 +11,6 @@ import ( "encoding/pem" "errors" "fmt" - "log" "net" "net/http" "os" @@ -26,6 +25,7 @@ import ( "github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/registration" "imuslab.com/zoraxy/mod/database" + "imuslab.com/zoraxy/mod/info/logger" "imuslab.com/zoraxy/mod/utils" ) @@ -68,25 +68,31 @@ type ACMEHandler struct { DefaultAcmeServer string Port string Database *database.Database + Logger *logger.Logger } // 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{ - DefaultAcmeServer: acmeServer, + DefaultAcmeServer: defaultAcmeServer, Port: port, 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. 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 privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { - log.Println(err) + a.Logf("Private key generation failed", err) return false, err } @@ -102,7 +108,7 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email // skip TLS verify if need // Ref: https://github.com/go-acme/lego/blob/6af2c756ac73a9cb401621afca722d0f4112b1b8/lego/client_config.go#L74 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{ Proxy: http.ProxyFromEnvironment, 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 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 { caLinkOverwrite, err := loadCAApiServerFromName(caName) if err == nil { config.CADirURL = caLinkOverwrite - log.Println("[INFO] Using " + caLinkOverwrite + " for CA Directory URL") + a.Logf("Using "+caLinkOverwrite+" for CA Directory URL", nil) } else { // (caName == "" || caUrl == "") will use default acme 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) if err != nil { - log.Println(err) + a.Logf("Failed to spawn new ACME client from current config", err) return false, err } @@ -164,32 +170,32 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email var dnsCredentials string err := a.Database.Read("acme", certificateName+"_dns_credentials", &dnsCredentials) if err != nil { - log.Println(err) + a.Logf("Read DNS credential failed", err) return false, err } var dnsProvider string err = a.Database.Read("acme", certificateName+"_dns_provider", &dnsProvider) if err != nil { - log.Println(err) + a.Logf("Read DNS Provider failed", err) return false, err } provider, err := GetDnsChallengeProviderByName(dnsProvider, dnsCredentials) if err != nil { - log.Println(err) + a.Logf("Unable to resolve DNS challenge provider", err) return false, err } err = client.Challenge.SetDNS01Provider(provider) if err != nil { - log.Println(err) + a.Logf("Failed to resolve DNS01 Provider", err) return false, err } } else { err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", a.Port)) if err != nil { - log.Println(err) + a.Logf("Failed to resolve HTTP01 Provider", err) return false, err } } @@ -205,7 +211,7 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email var reg *registration.Resource // New users will need to register 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 !a.Database.TableExists("acme") { @@ -220,20 +226,18 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email var kid string var hmacEncoded string err := a.Database.Read("acme", config.CADirURL+"_kid", &kid) - if err != nil { - log.Println(err) + a.Logf("Failed to read kid from database", err) return false, err } err = a.Database.Read("acme", config.CADirURL+"_hmacEncoded", &hmacEncoded) - if err != nil { - log.Println(err) + a.Logf("Failed to read HMAC from database", err) return false, err } - log.Println("EAB Credential retrieved.", kid, hmacEncoded) + a.Logf("EAB Credential retrieved: "+kid+" / "+hmacEncoded, nil) if kid != "" && hmacEncoded != "" { reg, err = client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{ TermsOfServiceAgreed: true, @@ -242,14 +246,14 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email }) } if err != nil { - log.Println(err) + a.Logf("Register with external account binder failed", err) return false, err } //return false, errors.New("External Account Required for this ACME Provider.") } else { reg, err = client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true}) if err != nil { - log.Println(err) + a.Logf("Unable to register client", err) return false, err } } @@ -262,7 +266,7 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email } certificates, err := client.Certificate.Obtain(request) if err != nil { - log.Println(err) + a.Logf("Obtain certificate failed", err) return false, err } @@ -270,12 +274,12 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email // private key, and a certificate URL. err = os.WriteFile("./conf/certs/"+certificateName+".pem", certificates.Certificate, 0777) if err != nil { - log.Println(err) + a.Logf("Failed to write public key to disk", err) return false, err } err = os.WriteFile("./conf/certs/"+certificateName+".key", certificates.PrivateKey, 0777) if err != nil { - log.Println(err) + a.Logf("Failed to write private key to disk", err) return false, err } @@ -289,13 +293,13 @@ func (a *ACMEHandler) ObtainCert(domains []string, certificateName string, email certInfoBytes, err := json.Marshal(certInfo) if err != nil { - log.Println(err) + a.Logf("Marshal certificate renew config failed", err) return false, err } err = os.WriteFile("./conf/certs/"+certificateName+".json", certInfoBytes, 0777) if err != nil { - log.Println(err) + a.Logf("Failed to write certificate renew config to file", err) return false, err } @@ -313,7 +317,7 @@ func (a *ACMEHandler) CheckCertificate() []string { expiredCerts := []string{} if err != nil { - log.Println(err) + a.Logf("Failed to load certificate folder", err) return []string{} } @@ -410,14 +414,14 @@ func (a *ACMEHandler) HandleRenewCertificate(w http.ResponseWriter, r *http.Requ ca, err := utils.PostPara(r, "ca") if err != nil { - log.Println("[INFO] CA not set. Using default") + a.Logf("CA not set. Using default", nil) ca, caUrl = "", "" } if ca == "custom" { caUrl, err = utils.PostPara(r, "caURL") 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 = "", "" } } @@ -465,7 +469,7 @@ func (a *ACMEHandler) HandleRenewCertificate(w http.ResponseWriter, r *http.Requ func jsonEscape(i string) string { b, err := json.Marshal(i) if err != nil { - log.Println("Unable to escape json data: " + err.Error()) + //log.Println("Unable to escape json data: " + err.Error()) return i } s := string(b) diff --git a/src/mod/acme/autorenew.go b/src/mod/acme/autorenew.go index 02de955..e318e8a 100644 --- a/src/mod/acme/autorenew.go +++ b/src/mod/acme/autorenew.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "log" "net/http" "net/mail" "os" @@ -12,6 +11,7 @@ import ( "strings" "time" + "imuslab.com/zoraxy/mod/info/logger" "imuslab.com/zoraxy/mod/utils" ) @@ -36,6 +36,7 @@ type AutoRenewer struct { RenewTickInterval int64 EarlyRenewDays int //How many days before cert expire to renew certificate TickerstopChan chan bool + Logger *logger.Logger //System wide logger } type ExpiredCerts struct { @@ -45,7 +46,7 @@ type ExpiredCerts struct { // Create an auto renew agent, require config filepath and auto scan & renew interval (seconds) // 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 { renewCheckInterval = 86400 //1 day } @@ -87,6 +88,7 @@ func NewAutoRenewer(config string, certFolder string, renewCheckInterval int64, AcmeHandler: AcmeHandler, RenewerConfig: &renewerConfig, RenewTickInterval: renewCheckInterval, + Logger: logger, } if thisRenewer.RenewerConfig.Enabled { @@ -100,6 +102,10 @@ func NewAutoRenewer(config string, certFolder string, renewCheckInterval int64, return &thisRenewer, nil } +func (a *AutoRenewer) Logf(message string, err error) { + a.Logger.PrintAndLog("CertRenew", message, err) +} + func (a *AutoRenewer) StartAutoRenewTicker() { //Stop the previous ticker if still running if a.TickerstopChan != nil { @@ -118,7 +124,7 @@ func (a *AutoRenewer) StartAutoRenewTicker() { case <-done: return case <-ticker.C: - log.Println("Check and renew certificates in progress") + a.Logf("Check and renew certificates in progress", nil) a.CheckAndRenewCertificates() } } @@ -233,12 +239,12 @@ func (a *AutoRenewer) HandleAutoRenewEnable(w http.ResponseWriter, r *http.Reque } a.RenewerConfig.Enabled = true a.saveRenewConfigToFile() - log.Println("[ACME] ACME auto renew enabled") + a.Logf("ACME auto renew enabled", nil) a.StartAutoRenewTicker() } else { a.RenewerConfig.Enabled = false a.saveRenewConfigToFile() - log.Println("[ACME] ACME auto renew disabled") + a.Logf("ACME auto renew disabled", nil) a.StopAutoRenewTicker() } } else { @@ -283,7 +289,7 @@ func (a *AutoRenewer) CheckAndRenewCertificates() ([]string, error) { certFolder := a.CertFolder files, err := os.ReadDir(certFolder) if err != nil { - log.Println("Unable to renew certificates: " + err.Error()) + a.Logf("Read certificate store failed", err) return []string{}, err } @@ -303,7 +309,7 @@ func (a *AutoRenewer) CheckAndRenewCertificates() ([]string, error) { DNSName, err := ExtractDomains(certBytes) if err != nil { //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 } @@ -327,11 +333,10 @@ func (a *AutoRenewer) CheckAndRenewCertificates() ([]string, error) { } if CertExpireSoon(certBytes, a.EarlyRenewDays) || CertIsExpired(certBytes) { //This cert is expired - DNSName, err := ExtractDomains(certBytes) if err != nil { //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 } @@ -358,7 +363,7 @@ func (a *AutoRenewer) Close() { func (a *AutoRenewer) renewExpiredDomains(certs []*ExpiredCerts) ([]string, error) { renewedCertFiles := []string{} 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) 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) certInfo, err := LoadCertInfoJSON(certInfoFilename) 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 { - 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{} } else { 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) 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 { - log.Println("Successfully renewed " + filepath.Base(expiredCert.Filepath)) + a.Logf("Successfully renewed "+filepath.Base(expiredCert.Filepath), nil) renewedCertFiles = append(renewedCertFiles, filepath.Base(expiredCert.Filepath)) } } diff --git a/src/mod/forwardproxy/cproxy/default_dialer.go b/src/mod/forwardproxy/cproxy/default_dialer.go index dce5da2..be93152 100644 --- a/src/mod/forwardproxy/cproxy/default_dialer.go +++ b/src/mod/forwardproxy/cproxy/default_dialer.go @@ -18,7 +18,7 @@ func (this *defaultDialer) Dial(address string) Socket { if socket, err := net.DialTimeout("tcp", address, this.timeout); err == nil { return socket } 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 diff --git a/src/mod/forwardproxy/cproxy/logging_initializer.go b/src/mod/forwardproxy/cproxy/logging_initializer.go index 37d5d72..db6861a 100644 --- a/src/mod/forwardproxy/cproxy/logging_initializer.go +++ b/src/mod/forwardproxy/cproxy/logging_initializer.go @@ -17,7 +17,7 @@ func (this *loggingInitializer) Initialize(client, server Socket) bool { result := this.inner.Initialize(client, server) 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 diff --git a/src/mod/tlscert/tlscert.go b/src/mod/tlscert/tlscert.go index ba6443d..9f1269a 100644 --- a/src/mod/tlscert/tlscert.go +++ b/src/mod/tlscert/tlscert.go @@ -6,7 +6,6 @@ import ( "embed" "encoding/pem" "io" - "log" "os" "path/filepath" "strings" @@ -185,7 +184,6 @@ func (m *Manager) GetCert(helloInfo *tls.ClientHelloInfo) (*tls.Certificate, err //Load the cert and serve it cer, err := tls.LoadX509KeyPair(pubKey, priKey) if err != nil { - log.Println(err) return nil, nil } diff --git a/src/mod/uptime/uptime.go b/src/mod/uptime/uptime.go index 1d01814..44eeef9 100644 --- a/src/mod/uptime/uptime.go +++ b/src/mod/uptime/uptime.go @@ -3,7 +3,6 @@ package uptime import ( "encoding/json" "errors" - "log" "net/http" "net/http/cookiejar" "strconv" @@ -242,7 +241,7 @@ func getWebsiteStatus(url string) (int, error) { // Create a one-time use cookie jar to store cookies jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) if err != nil { - log.Fatal(err) + return 0, err } client := http.Client{ diff --git a/src/mod/webserv/filemanager/filemanager.go b/src/mod/webserv/filemanager/filemanager.go index 761daef..2d5b0ae 100644 --- a/src/mod/webserv/filemanager/filemanager.go +++ b/src/mod/webserv/filemanager/filemanager.go @@ -44,7 +44,9 @@ func (fm *FileManager) HandleList(w http.ResponseWriter, r *http.Request) { // Clean path to prevent path escape #274 targetDir = filepath.ToSlash(filepath.Clean(targetDir)) - targetDir = strings.ReplaceAll(targetDir, "../", "") + for strings.Contains(targetDir, "../") { + targetDir = strings.ReplaceAll(targetDir, "../", "") + } // Open the target directory dirEntries, err := os.ReadDir(targetDir) diff --git a/src/start.go b/src/start.go index 43a8597..5cc12bc 100644 --- a/src/start.go +++ b/src/start.go @@ -285,6 +285,7 @@ func startupSequence() { int64(*acmeAutoRenewInterval), *acmeCertAutoRenewDays, acmeHandler, + SystemWideLogger, ) if err != nil { log.Fatal(err)