@marcel91200 / caddy Mirror · read-only / commits / bd17eb20
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

ci: Use golangci's github action for linting (#3794)

* ci: Use golangci's github action for linting Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix most of the staticcheck lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix the prealloc lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix the misspell lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix the varcheck lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix the errcheck lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix the bodyclose lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix the deadcode lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix the unused lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix the gosec lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix the gosimple lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix the ineffassign lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Fix the staticcheck lint errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Revert the misspell change, use a neutral English Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Remove broken golangci-lint CI job Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Re-add errantly-removed weakrand initialization Signed-off-by: Dave Henderson <dhenderson@gmail.com> * don't break the loop and return * Removing extra handling for null rootKey * unignore RegisterModule/RegisterAdapter Co-authored-by: Mohammed Al Sahaf <msaa1990@gmail.com> * single-line log message Co-authored-by: Matt Holt <mholt@users.noreply.github.com> * Fix lint after a1808b0dbf209c615e438a496d257ce5e3acdce2 was merged Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Revert ticker change, ignore it instead Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Ignore some of the write errors Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Remove blank line Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Use lifetime Signed-off-by: Dave Henderson <dhenderson@gmail.com> * close immediately Co-authored-by: Matt Holt <mholt@users.noreply.github.com> * Preallocate configVals Signed-off-by: Dave Henderson <dhenderson@gmail.com> * Update modules/caddytls/distributedstek/distributedstek.go Co-authored-by: Mohammed Al Sahaf <msaa1990@gmail.com> Co-authored-by: Matt Holt <mholt@users.noreply.github.com>

Dave Henderson committed Nov 22, 2020 at 16:50 UTC bd17eb205d6ac464c64eb888a6f4b57445b6c59c
41 files changed +256 -199
.github/workflows/ci.yml
-14
@@ -148,20 +148,6 @@ jobs:
148 env:
149 SSH_KEY: ${{ secrets.S390X_SSH_KEY }}
150
151 - # From https://github.com/reviewdog/action-golangci-lint
152 - golangci-lint:
153 - name: runner / golangci-lint
154 - runs-on: ubuntu-latest
155 - steps:
156 - - name: Checkout code into the Go module directory
157 - uses: actions/checkout@v2
158 -
159 - - name: Run golangci-lint
160 - uses: reviewdog/action-golangci-lint@v1
161 - # uses: docker://reviewdog/action-golangci-lint:v1 # pre-build docker image
162 - with:
163 - github_token: ${{ secrets.github_token }}
164 -
151 goreleaser-check:
152 runs-on: ubuntu-latest
153 steps:
.github/workflows/lint.yml new
+23
@@ -0,0 +1,23 @@
1 +name: Lint
2 +
3 +on:
4 + push:
5 + branches:
6 + - master
7 + pull_request:
8 + branches:
9 + - master
10 +
11 +jobs:
12 + # From https://github.com/golangci/golangci-lint-action
13 + golangci:
14 + name: lint
15 + runs-on: ubuntu-latest
16 + steps:
17 + - uses: actions/checkout@v2
18 + - name: golangci-lint
19 + uses: golangci/golangci-lint-action@v2
20 + with:
21 + version: v1.31
22 + # Optional: show only new issues if it's a pull request. The default value is `false`.
23 + # only-new-issues: true
.golangci.yml
+52 -5
@@ -1,21 +1,68 @@
1 linters-settings:
2 errcheck:
3 - ignore: fmt:.*,io/ioutil:^Read.*,github.com/caddyserver/caddy/v2/caddyconfig:RegisterAdapter,github.com/caddyserver/caddy/v2:RegisterModule
3 + ignore: fmt:.*,io/ioutil:^Read.*,go.uber.org/zap/zapcore:^Add.*
4 ignoretests: true
5 - misspell:
6 - locale: US
5
6 linters:
7 + disable-all: true
8 enable:
9 - bodyclose
11 - - prealloc
12 - - unconvert
10 + - deadcode
11 - errcheck
12 - gofmt
13 - goimports
14 - gosec
15 + - gosimple
16 + - govet
17 - ineffassign
18 - misspell
19 + - prealloc
20 + - staticcheck
21 + - structcheck
22 + - typecheck
23 + - unconvert
24 + - unused
25 + - varcheck
26 + # these are implicitly disabled:
27 + # - asciicheck
28 + # - depguard
29 + # - dogsled
30 + # - dupl
31 + # - exhaustive
32 + # - exportloopref
33 + # - funlen
34 + # - gci
35 + # - gochecknoglobals
36 + # - gochecknoinits
37 + # - gocognit
38 + # - goconst
39 + # - gocritic
40 + # - gocyclo
41 + # - godot
42 + # - godox
43 + # - goerr113
44 + # - gofumpt
45 + # - goheader
46 + # - golint
47 + # - gomnd
48 + # - gomodguard
49 + # - goprintffuncname
50 + # - interfacer
51 + # - lll
52 + # - maligned
53 + # - nakedret
54 + # - nestif
55 + # - nlreturn
56 + # - noctx
57 + # - nolintlint
58 + # - rowserrcheck
59 + # - scopelint
60 + # - sqlclosecheck
61 + # - stylecheck
62 + # - testpackage
63 + # - unparam
64 + # - whitespace
65 + # - wsl
66
67 run:
68 # default concurrency is a available CPU number.
admin.go
+5 -2
@@ -398,7 +398,10 @@ func (h adminHandler) handleError(w http.ResponseWriter, r *http.Request, err er
398
399 w.Header().Set("Content-Type", "application/json")
400 w.WriteHeader(apiErr.Code)
401 - json.NewEncoder(w).Encode(apiErr)
401 + encErr := json.NewEncoder(w).Encode(apiErr)
402 + if encErr != nil {
403 + Log().Named("admin.api").Error("failed to encode error response", zap.Error(encErr))
404 + }
405 }
406
407 // checkHost returns a handler that wraps next such that
@@ -838,7 +841,7 @@ var (
841 // will get deleted before the process gracefully exits.
842 func PIDFile(filename string) error {
843 pid := []byte(strconv.Itoa(os.Getpid()) + "\n")
841 - err := ioutil.WriteFile(filename, pid, 0644)
844 + err := ioutil.WriteFile(filename, pid, 0600)
845 if err != nil {
846 return err
847 }
caddyconfig/httpcaddyfile/builtins.go
+1 -1
@@ -356,7 +356,7 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
356 }
357
358 // begin building the final config values
359 - var configVals []ConfigValue
359 + configVals := []ConfigValue{}
360
361 // certificate loaders
362 if len(fileLoader) > 0 {
caddytest/caddytest.go
+5 -4
@@ -124,10 +124,10 @@ func (tc *Tester) initServer(rawConfig string, configType string) error {
124 return
125 }
126 defer res.Body.Close()
127 - body, err := ioutil.ReadAll(res.Body)
127 + body, _ := ioutil.ReadAll(res.Body)
128
129 var out bytes.Buffer
130 - json.Indent(&out, body, "", " ")
130 + _ = json.Indent(&out, body, "", " ")
131 tc.t.Logf("----------- failed with config -----------\n%s", out.String())
132 }
133 })
@@ -221,10 +221,11 @@ func isCaddyAdminRunning() error {
221 client := &http.Client{
222 Timeout: Default.LoadRequestTimeout,
223 }
224 - _, err := client.Get(fmt.Sprintf("http://localhost:%d/config/", Default.AdminPort))
224 + resp, err := client.Get(fmt.Sprintf("http://localhost:%d/config/", Default.AdminPort))
225 if err != nil {
226 return errors.New("caddy integration test caddy server not running. Expected to be listening on localhost:2019")
227 }
228 + resp.Body.Close()
229
230 return nil
231 }
@@ -272,7 +273,7 @@ func CreateTestingTransport() *http.Transport {
273 IdleConnTimeout: 90 * time.Second,
274 TLSHandshakeTimeout: 5 * time.Second,
275 ExpectContinueTimeout: 1 * time.Second,
275 - TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
276 + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec
277 }
278 }
279
cmd/commandfuncs.go
+1 -1
@@ -96,7 +96,7 @@ func cmdStart(fl Flags) (int, error) {
96 // started yet, and writing synchronously would result
97 // in a deadlock
98 go func() {
99 - stdinpipe.Write(expect)
99 + _, _ = stdinpipe.Write(expect)
100 stdinpipe.Close()
101 }()
102
cmd/main.go
+1
@@ -236,6 +236,7 @@ func watchConfigFile(filename, adapterName string) {
236 }
237
238 // begin poller
239 + //nolint:staticcheck
240 for range time.Tick(1 * time.Second) {
241 // get the file info
242 info, err := os.Stat(filename)
cmd/proc_posix.go deleted
-37
@@ -1,37 +0,0 @@
1 -// Copyright 2015 Matthew Holt and The Caddy Authors
2 -//
3 -// Licensed under the Apache License, Version 2.0 (the "License");
4 -// you may not use this file except in compliance with the License.
5 -// You may obtain a copy of the License at
6 -//
7 -// http://www.apache.org/licenses/LICENSE-2.0
8 -//
9 -// Unless required by applicable law or agreed to in writing, software
10 -// distributed under the License is distributed on an "AS IS" BASIS,
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 -// See the License for the specific language governing permissions and
13 -// limitations under the License.
14 -
15 -// +build !windows
16 -
17 -package caddycmd
18 -
19 -import (
20 - "fmt"
21 - "os"
22 - "path/filepath"
23 - "syscall"
24 -)
25 -
26 -func gracefullyStopProcess(pid int) error {
27 - fmt.Print("Graceful stop... ")
28 - err := syscall.Kill(pid, syscall.SIGINT)
29 - if err != nil {
30 - return fmt.Errorf("kill: %v", err)
31 - }
32 - return nil
33 -}
34 -
35 -func getProcessName() string {
36 - return filepath.Base(os.Args[0])
37 -}
cmd/proc_windows.go deleted
-44
@@ -1,44 +0,0 @@
1 -// Copyright 2015 Matthew Holt and The Caddy Authors
2 -//
3 -// Licensed under the Apache License, Version 2.0 (the "License");
4 -// you may not use this file except in compliance with the License.
5 -// You may obtain a copy of the License at
6 -//
7 -// http://www.apache.org/licenses/LICENSE-2.0
8 -//
9 -// Unless required by applicable law or agreed to in writing, software
10 -// distributed under the License is distributed on an "AS IS" BASIS,
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 -// See the License for the specific language governing permissions and
13 -// limitations under the License.
14 -
15 -package caddycmd
16 -
17 -import (
18 - "fmt"
19 - "os"
20 - "os/exec"
21 - "path/filepath"
22 - "strconv"
23 -)
24 -
25 -func gracefullyStopProcess(pid int) error {
26 - fmt.Print("Forceful stop... ")
27 - // process on windows will not stop unless forced with /f
28 - cmd := exec.Command("taskkill", "/pid", strconv.Itoa(pid), "/f")
29 - if err := cmd.Run(); err != nil {
30 - return fmt.Errorf("taskkill: %v", err)
31 - }
32 - return nil
33 -}
34 -
35 -// On Windows the app name passed in os.Args[0] will match how
36 -// caddy was started eg will match caddy or caddy.exe.
37 -// So return appname with .exe for consistency
38 -func getProcessName() string {
39 - base := filepath.Base(os.Args[0])
40 - if filepath.Ext(base) == "" {
41 - return base + ".exe"
42 - }
43 - return base
44 -}
go.sum
+2
@@ -354,6 +354,8 @@ github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
354 github.com/libdns/libdns v0.1.0 h1:0ctCOrVJsVzj53mop1angHp/pE3hmAhP7KiHvR0HD04=
355 github.com/libdns/libdns v0.1.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
356 github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
357 +github.com/lucas-clemente/quic-go v0.19.2 h1:w8BBYUx5Z+kNpeaOeQW/KzcNsKWhh4O6PeQhb0nURPg=
358 +github.com/lucas-clemente/quic-go v0.19.2/go.mod h1:ZUygOqIoai0ASXXLJ92LTnKdbqh9MHCLTX6Nr1jUrK0=
359 github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8=
360 github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
361 github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
listeners.go
+4 -4
@@ -129,9 +129,9 @@ func (fcl *fakeCloseListener) Accept() (net.Conn, error) {
129 if *fcl.deadline {
130 switch ln := fcl.Listener.(type) {
131 case *net.TCPListener:
132 - ln.SetDeadline(time.Time{})
132 + _ = ln.SetDeadline(time.Time{})
133 case *net.UnixListener:
134 - ln.SetDeadline(time.Time{})
134 + _ = ln.SetDeadline(time.Time{})
135 }
136 *fcl.deadline = false
137 }
@@ -167,9 +167,9 @@ func (fcl *fakeCloseListener) Close() error {
167 if !*fcl.deadline {
168 switch ln := fcl.Listener.(type) {
169 case *net.TCPListener:
170 - ln.SetDeadline(time.Now().Add(-1 * time.Minute))
170 + _ = ln.SetDeadline(time.Now().Add(-1 * time.Minute))
171 case *net.UnixListener:
172 - ln.SetDeadline(time.Now().Add(-1 * time.Minute))
172 + _ = ln.SetDeadline(time.Now().Add(-1 * time.Minute))
173 }
174 *fcl.deadline = true
175 }
logging.go
+1 -1
@@ -458,7 +458,7 @@ func (cl *CustomLog) buildCore() {
458 if cl.Sampling.Thereafter == 0 {
459 cl.Sampling.Thereafter = 100
460 }
461 - c = zapcore.NewSampler(c, cl.Sampling.Interval,
461 + c = zapcore.NewSamplerWithOptions(c, cl.Sampling.Interval,
462 cl.Sampling.First, cl.Sampling.Thereafter)
463 }
464 cl.core = c
modules/caddyhttp/app.go
+2
@@ -363,6 +363,7 @@ func (app *App) Start() error {
363 ErrorLog: serverLogger,
364 },
365 }
366 + //nolint:errcheck
367 go h3srv.Serve(h3ln)
368 app.h3servers = append(app.h3servers, h3srv)
369 app.h3listeners = append(app.h3listeners, h3ln)
@@ -391,6 +392,7 @@ func (app *App) Start() error {
392 zap.Bool("tls", useTLS),
393 )
394
395 + //nolint:errcheck
396 go s.Serve(ln)
397 app.servers = append(app.servers, s)
398 }
modules/caddyhttp/autohttps.go
+4 -1
@@ -523,7 +523,10 @@ func (app *App) createAutomationPolicies(ctx caddy.Context, internalNames []stri
523 // our base/catch-all policy - this will serve the
524 // public-looking names as well as any other names
525 // that don't match any other policy
526 - app.tlsApp.AddAutomationPolicy(basePolicy)
526 + err := app.tlsApp.AddAutomationPolicy(basePolicy)
527 + if err != nil {
528 + return err
529 + }
530 } else {
531 // a base policy already existed; we might have
532 // changed it, so re-provision it
modules/caddyhttp/caddyauth/basicauth.go
+1
@@ -240,6 +240,7 @@ func (c *Cache) makeRoom() {
240 // map with less code, this is a heavily skewed eviction
241 // strategy; generating random numbers is cheap and
242 // ensures a much better distribution.
243 + //nolint:gosec
244 rnd := weakrand.Intn(len(c.cache))
245 i := 0
246 for key := range c.cache {
modules/caddyhttp/caddyhttp.go
-4
@@ -18,18 +18,14 @@ import (
18 "bytes"
19 "encoding/json"
20 "io"
21 - weakrand "math/rand"
21 "net"
22 "net/http"
23 "strconv"
25 - "time"
24
25 "github.com/caddyserver/caddy/v2"
26 )
27
28 func init() {
31 - weakrand.Seed(time.Now().UnixNano())
32 -
29 caddy.RegisterModule(tlsPlaceholderWrapper{})
30 }
31
modules/caddyhttp/encode/encode.go
+1 -1
@@ -262,7 +262,7 @@ func acceptedEncodings(r *http.Request) []string {
262 return []string{}
263 }
264
265 - var prefs []encodingPreference
265 + prefs := []encodingPreference{}
266
267 for _, accepted := range strings.Split(acceptEncHeader, ",") {
268 parts := strings.Split(accepted, ";")
modules/caddyhttp/errors.go
+8 -2
@@ -16,14 +16,19 @@ package caddyhttp
16
17 import (
18 "fmt"
19 - mathrand "math/rand"
19 + weakrand "math/rand"
20 "path"
21 "runtime"
22 "strings"
23 + "time"
24
25 "github.com/caddyserver/caddy/v2"
26 )
27
28 +func init() {
29 + weakrand.Seed(time.Now().UnixNano())
30 +}
31 +
32 // Error is a convenient way for a Handler to populate the
33 // essential fields of a HandlerError. If err is itself a
34 // HandlerError, then any essential fields that are not
@@ -92,7 +97,8 @@ func randString(n int, sameCase bool) string {
97 }
98 b := make([]byte, n)
99 for i := range b {
95 - b[i] = dict[mathrand.Int63()%int64(len(dict))]
100 + //nolint:gosec
101 + b[i] = dict[weakrand.Int63()%int64(len(dict))]
102 }
103 return string(b)
104 }
modules/caddyhttp/fileserver/browse.go
+1 -1
@@ -82,7 +82,7 @@ func (fsrv *FileServer) serveBrowse(dirPath string, w http.ResponseWriter, r *ht
82 w.Header().Set("Content-Type", "text/html; charset=utf-8")
83 }
84
85 - buf.WriteTo(w)
85 + _, _ = buf.WriteTo(w)
86
87 return nil
88 }
modules/caddyhttp/fileserver/browselisting.go
+8 -12
@@ -30,10 +30,8 @@ import (
30 func (fsrv *FileServer) directoryListing(files []os.FileInfo, canGoUp bool, urlPath string, repl *caddy.Replacer) browseListing {
31 filesToHide := fsrv.transformHidePaths(repl)
32
33 - var (
34 - fileInfos []fileInfo
35 - dirCount, fileCount int
36 - )
33 + var dirCount, fileCount int
34 + fileInfos := []fileInfo{}
35
36 for _, f := range files {
37 name := f.Name()
@@ -109,10 +107,8 @@ type browseListing struct {
107 // Breadcrumbs returns l.Path where every element maps
108 // the link to the text to display.
109 func (l browseListing) Breadcrumbs() []crumb {
112 - var result []crumb
113 -
110 if len(l.Path) == 0 {
115 - return result
111 + return []crumb{}
112 }
113
114 // skip trailing slash
@@ -122,13 +118,13 @@ func (l browseListing) Breadcrumbs() []crumb {
118 }
119
120 parts := strings.Split(lpath, "/")
125 - for i := range parts {
126 - txt := parts[i]
127 - if i == 0 && parts[i] == "" {
128 - txt = "/"
121 + result := make([]crumb, len(parts))
122 + for i, p := range parts {
123 + if i == 0 && p == "" {
124 + p = "/"
125 }
126 lnk := strings.Repeat("../", len(parts)-i-1)
131 - result = append(result, crumb{Link: lnk, Text: txt})
127 + result[i] = crumb{Link: lnk, Text: p}
128 }
129
130 return result
modules/caddyhttp/fileserver/browselisting_test.go new
+40
@@ -0,0 +1,40 @@
1 +package fileserver
2 +
3 +import (
4 + "testing"
5 +)
6 +
7 +func TestBreadcrumbs(t *testing.T) {
8 + testdata := []struct {
9 + path string
10 + expected []crumb
11 + }{
12 + {"", []crumb{}},
13 + {"/", []crumb{{Text: "/"}}},
14 + {"foo/bar/baz", []crumb{
15 + {Link: "../../", Text: "foo"},
16 + {Link: "../", Text: "bar"},
17 + {Link: "", Text: "baz"},
18 + }},
19 + {"/qux/quux/corge/", []crumb{
20 + {Link: "../../../", Text: "/"},
21 + {Link: "../../", Text: "qux"},
22 + {Link: "../", Text: "quux"},
23 + {Link: "", Text: "corge"},
24 + }},
25 + }
26 +
27 + for _, d := range testdata {
28 + l := browseListing{Path: d.path}
29 + actual := l.Breadcrumbs()
30 + if len(actual) != len(d.expected) {
31 + t.Errorf("wrong size output, got %d elements but expected %d", len(actual), len(d.expected))
32 + continue
33 + }
34 + for i, c := range actual {
35 + if c != d.expected[i] {
36 + t.Errorf("got %#v but expected %#v at index %d", c, d.expected[i], i)
37 + }
38 + }
39 + }
40 +}
modules/caddyhttp/fileserver/staticfiles.go
+2 -1
@@ -249,7 +249,7 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next c
249 }
250 w.WriteHeader(statusCode)
251 if r.Method != http.MethodHead {
252 - io.Copy(w, file)
252 + _, _ = io.Copy(w, file)
253 }
254 return nil
255 }
@@ -278,6 +278,7 @@ func (fsrv *FileServer) openFile(filename string, w http.ResponseWriter) (*os.Fi
278 }
279 // maybe the server is under load and ran out of file descriptors?
280 // have client wait arbitrary seconds to help prevent a stampede
281 + //nolint:gosec
282 backoff := weakrand.Intn(maxBackoff-minBackoff) + minBackoff
283 w.Header().Set("Retry-After", strconv.Itoa(backoff))
284 return nil, caddyhttp.Error(http.StatusServiceUnavailable, err)
modules/caddyhttp/marshalers.go
+2 -1
@@ -75,7 +75,8 @@ func (t LoggableTLSConnState) MarshalLogObject(enc zapcore.ObjectEncoder) error
75 enc.AddUint16("version", t.Version)
76 enc.AddUint16("cipher_suite", t.CipherSuite)
77 enc.AddString("proto", t.NegotiatedProtocol)
78 - enc.AddBool("proto_mutual", t.NegotiatedProtocolIsMutual)
78 + // NegotiatedProtocolIsMutual is deprecated - it's always true
79 + enc.AddBool("proto_mutual", true)
80 enc.AddString("server_name", t.ServerName)
81 if len(t.PeerCertificates) > 0 {
82 enc.AddString("client_common_name", t.PeerCertificates[0].Subject.CommonName)
modules/caddyhttp/replacer.go
+2 -1
@@ -362,7 +362,8 @@ func getReqTLSReplacement(req *http.Request, key string) (interface{}, bool) {
362 case "proto":
363 return req.TLS.NegotiatedProtocol, true
364 case "proto_mutual":
365 - return req.TLS.NegotiatedProtocolIsMutual, true
365 + // req.TLS.NegotiatedProtocolIsMutual is deprecated - it's always true.
366 + return true, true
367 case "server_name":
368 return req.TLS.ServerName, true
369 }
modules/caddyhttp/reverseproxy/fastcgi/client.go
-7
@@ -242,13 +242,6 @@ func (c *FCGIClient) writeBeginRequest(role uint16, flags uint8) error {
242 return c.writeRecord(BeginRequest, b[:])
243 }
244
245 -func (c *FCGIClient) writeEndRequest(appStatus int, protocolStatus uint8) error {
246 - b := make([]byte, 8)
247 - binary.BigEndian.PutUint32(b, uint32(appStatus))
248 - b[4] = protocolStatus
249 - return c.writeRecord(EndRequest, b)
250 -}
251 -
245 func (c *FCGIClient) writePairs(recType uint8, pairs map[string]string) error {
246 w := newWriter(c, recType)
247 b := make([]byte, 8)
modules/caddyhttp/reverseproxy/healthchecks.go
+1 -1
@@ -263,7 +263,7 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, host H
263 }
264 defer func() {
265 // drain any remaining body so connection could be re-used
266 - io.Copy(ioutil.Discard, body)
266 + _, _ = io.Copy(ioutil.Discard, body)
267 resp.Body.Close()
268 }()
269
modules/caddyhttp/reverseproxy/httptransport.go
+1
@@ -173,6 +173,7 @@ func (h *HTTPTransport) NewTransport(ctx caddy.Context) (*http.Transport, error)
173 dialer.Resolver = &net.Resolver{
174 PreferGo: true,
175 Dial: func(ctx context.Context, _, _ string) (net.Conn, error) {
176 + //nolint:gosec
177 addr := h.Resolver.netAddrs[weakrand.Intn(len(h.Resolver.netAddrs))]
178 return d.DialContext(ctx, addr.Network, addr.JoinHostPort(0))
179 },
modules/caddyhttp/reverseproxy/reverseproxy.go
+4 -25
@@ -314,7 +314,7 @@ func (h *Handler) Cleanup() error {
314
315 // remove hosts from our config from the pool
316 for _, upstream := range h.Upstreams {
317 - hosts.Delete(upstream.String())
317 + _, _ = hosts.Delete(upstream.String())
318 }
319
320 return nil
@@ -339,7 +339,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyht
339 buf := bufPool.Get().(*bytes.Buffer)
340 buf.Reset()
341 defer bufPool.Put(buf)
342 - io.Copy(buf, r.Body)
342 + _, _ = io.Copy(buf, r.Body)
343 r.Body.Close()
344 r.Body = ioutil.NopCloser(buf)
345 }
@@ -518,7 +518,8 @@ func (h Handler) prepareRequest(req *http.Request) error {
518 // (This method is mostly the beginning of what was borrowed from the net/http/httputil package in the
519 // Go standard library which was used as the foundation.)
520 func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, di DialInfo, next caddyhttp.Handler) error {
521 - di.Upstream.Host.CountRequest(1)
521 + _ = di.Upstream.Host.CountRequest(1)
522 + //nolint:errcheck
523 defer di.Upstream.Host.CountRequest(-1)
524
525 // point the request to this upstream
@@ -742,16 +743,6 @@ func copyHeader(dst, src http.Header) {
743 }
744 }
745
745 -func cloneHeader(h http.Header) http.Header {
746 - h2 := make(http.Header, len(h))
747 - for k, vv := range h {
748 - vv2 := make([]string, len(vv))
749 - copy(vv2, vv)
750 - h2[k] = vv2
751 - }
752 - return h2
753 -}
754 -
746 func upgradeType(h http.Header) string {
747 if !httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade") {
748 return ""
@@ -759,18 +750,6 @@ func upgradeType(h http.Header) string {
750 return strings.ToLower(h.Get("Upgrade"))
751 }
752
762 -func singleJoiningSlash(a, b string) string {
763 - aslash := strings.HasSuffix(a, "/")
764 - bslash := strings.HasPrefix(b, "/")
765 - switch {
766 - case aslash && bslash:
767 - return a + b[1:]
768 - case !aslash && !bslash:
769 - return a + "/" + b
770 - }
771 - return a + b
772 -}
773 -
753 // removeConnectionHeaders removes hop-by-hop headers listed in the "Connection" header of h.
754 // See RFC 7230, section 6.1
755 func removeConnectionHeaders(h http.Header) {
modules/caddyhttp/reverseproxy/selectionpolicies.go
+1 -1
@@ -536,7 +536,7 @@ func hostByHashing(pool []*Upstream, s string) *Upstream {
536 // hash calculates a fast hash based on s.
537 func hash(s string) uint32 {
538 h := fnv.New32a()
539 - h.Write([]byte(s))
539 + _, _ = h.Write([]byte(s))
540 return h.Sum32()
541 }
542
modules/caddyhttp/reverseproxy/streaming.go
+8 -3
@@ -138,9 +138,9 @@ func (h Handler) copyResponse(dst io.Writer, src io.Reader, flushInterval time.D
138 }
139 }
140
141 - buf := streamingBufPool.Get().([]byte)
141 + buf := streamingBufPool.Get().(*[]byte)
142 defer streamingBufPool.Put(buf)
143 - _, err := h.copyBuffer(dst, src, buf)
143 + _, err := h.copyBuffer(dst, src, *buf)
144 return err
145 }
146
@@ -255,7 +255,12 @@ func (c switchProtocolCopier) copyToBackend(errc chan<- error) {
255
256 var streamingBufPool = sync.Pool{
257 New: func() interface{} {
258 - return make([]byte, defaultBufferSize)
258 + // The Pool's New function should generally only return pointer
259 + // types, since a pointer can be put into the return interface
260 + // value without an allocation
261 + // - (from the package docs)
262 + b := make([]byte, defaultBufferSize)
263 + return &b
264 },
265 }
266
modules/caddyhttp/reverseproxy/streaming_test.go new
+30
@@ -0,0 +1,30 @@
1 +package reverseproxy
2 +
3 +import (
4 + "bytes"
5 + "strings"
6 + "testing"
7 +)
8 +
9 +func TestHandlerCopyResponse(t *testing.T) {
10 + h := Handler{}
11 + testdata := []string{
12 + "",
13 + strings.Repeat("a", defaultBufferSize),
14 + strings.Repeat("123456789 123456789 123456789 12", 3000),
15 + }
16 + dst := bytes.NewBuffer(nil)
17 +
18 + for _, d := range testdata {
19 + src := bytes.NewBuffer([]byte(d))
20 + dst.Reset()
21 + err := h.copyResponse(dst, src, 0)
22 + if err != nil {
23 + t.Errorf("failed with error: %v", err)
24 + }
25 + out := dst.String()
26 + if out != d {
27 + t.Errorf("bad read: got %q", out)
28 + }
29 + }
30 +}
modules/caddyhttp/templates/tplcontext.go
+4 -1
@@ -270,7 +270,10 @@ func (templateContext) funcMarkdown(input interface{}) (string, error) {
270 buf.Reset()
271 defer bufPool.Put(buf)
272
273 - md.Convert([]byte(inputStr), buf)
273 + err := md.Convert([]byte(inputStr), buf)
274 + if err != nil {
275 + return "", err
276 + }
277
278 return buf.String(), nil
279 }
modules/caddypki/acmeserver/acmeserver.go
+5 -5
@@ -132,11 +132,11 @@ func (ash *Handler) Provision(ctx caddy.Context) error {
132 return err
133 }
134
135 - acmeAuth, err := acme.NewAuthority(
136 - auth.GetDatabase().(nosql.DB), // stores all the server state
137 - ash.Host, // used for directory links; TODO: not needed
138 - strings.Trim(ash.PathPrefix, "/"), // used for directory links
139 - auth) // configures the signing authority
135 + acmeAuth, err := acme.New(auth, acme.AuthorityOptions{
136 + DB: auth.GetDatabase().(nosql.DB), // stores all the server state
137 + DNS: ash.Host, // used for directory links; TODO: not needed
138 + Prefix: strings.Trim(ash.PathPrefix, "/"), // used for directory links
139 + })
140 if err != nil {
141 return err
142 }
modules/caddypki/ca.go
-8
@@ -309,14 +309,6 @@ func (ca CA) loadOrGenIntermediate(rootCert *x509.Certificate, rootKey interface
309 func (ca CA) genIntermediate(rootCert *x509.Certificate, rootKey interface{}) (interCert *x509.Certificate, interKey interface{}, err error) {
310 repl := ca.newReplacer()
311
312 - rootKeyPEM, err := ca.storage.Load(ca.storageKeyRootKey())
313 - if err != nil {
314 - return nil, nil, fmt.Errorf("loading root key to sign new intermediate: %v", err)
315 - }
316 - rootKey, err = pemDecodePrivateKey(rootKeyPEM)
317 - if err != nil {
318 - return nil, nil, fmt.Errorf("decoding root key: %v", err)
319 - }
312 interCert, interKey, err = generateIntermediate(repl.ReplaceAll(ca.IntermediateCommonName, ""), rootCert, rootKey)
313 if err != nil {
314 return nil, nil, fmt.Errorf("generating CA intermediate: %v", err)
modules/caddytls/connpolicy.go
+1
@@ -80,6 +80,7 @@ func (cp ConnectionPolicies) TLSConfig(ctx caddy.Context) *tls.Config {
80 }
81
82 return &tls.Config{
83 + MinVersion: tls.VersionTLS12,
84 GetConfigForClient: func(hello *tls.ClientHelloInfo) (*tls.Config, error) {
85 // filter policies by SNI first, if possible, to speed things up
86 // when there may be lots of policies
modules/caddytls/distributedstek/distributedstek.go
+6 -1
@@ -145,7 +145,12 @@ func (s *Provider) storeSTEK(dstek distributedSTEK) error {
145 // current STEK is outdated (NextRotation time is in the past),
146 // then it is rotated and persisted. The resulting STEK is returned.
147 func (s *Provider) getSTEK() (distributedSTEK, error) {
148 - s.storage.Lock(s.ctx, stekLockName)
148 + err := s.storage.Lock(s.ctx, stekLockName)
149 + if err != nil {
150 + return distributedSTEK{}, fmt.Errorf("failed to acquire storage lock: %v", err)
151 + }
152 +
153 + //nolint:errcheck
154 defer s.storage.Unlock(stekLockName)
155
156 // load the current STEKs from storage
modules/caddytls/folderloader.go
+16 -4
@@ -97,26 +97,38 @@ func x509CertFromCertAndKeyPEMFile(fpath string) (tls.Certificate, error) {
97
98 if derBlock.Type == "CERTIFICATE" {
99 // Re-encode certificate as PEM, appending to certificate chain
100 - pem.Encode(certBuilder, derBlock)
100 + err = pem.Encode(certBuilder, derBlock)
101 + if err != nil {
102 + return tls.Certificate{}, err
103 + }
104 } else if derBlock.Type == "EC PARAMETERS" {
105 // EC keys generated from openssl can be composed of two blocks:
106 // parameters and key (parameter block should come first)
107 if !foundKey {
108 // Encode parameters
106 - pem.Encode(keyBuilder, derBlock)
109 + err = pem.Encode(keyBuilder, derBlock)
110 + if err != nil {
111 + return tls.Certificate{}, err
112 + }
113
114 // Key must immediately follow
115 derBlock, bundle = pem.Decode(bundle)
116 if derBlock == nil || derBlock.Type != "EC PRIVATE KEY" {
117 return tls.Certificate{}, fmt.Errorf("%s: expected elliptic private key to immediately follow EC parameters", fpath)
118 }
113 - pem.Encode(keyBuilder, derBlock)
119 + err = pem.Encode(keyBuilder, derBlock)
120 + if err != nil {
121 + return tls.Certificate{}, err
122 + }
123 foundKey = true
124 }
125 } else if derBlock.Type == "PRIVATE KEY" || strings.HasSuffix(derBlock.Type, " PRIVATE KEY") {
126 // RSA key
127 if !foundKey {
119 - pem.Encode(keyBuilder, derBlock)
128 + err = pem.Encode(keyBuilder, derBlock)
129 + if err != nil {
130 + return tls.Certificate{}, err
131 + }
132 foundKey = true
133 }
134 } else {
modules/caddytls/internalissuer.go
+12 -4
@@ -27,6 +27,7 @@ import (
27 "github.com/caddyserver/caddy/v2/modules/caddypki"
28 "github.com/caddyserver/certmagic"
29 "github.com/smallstep/certificates/authority/provisioner"
30 + "go.uber.org/zap"
31 )
32
33 func init() {
@@ -51,7 +52,8 @@ type InternalIssuer struct {
52 // validate certificate chains.
53 SignWithRoot bool `json:"sign_with_root,omitempty"`
54
54 - ca *caddypki.CA
55 + ca *caddypki.CA
56 + logger *zap.Logger
57 }
58
59 // CaddyModule returns the Caddy module information.
@@ -64,6 +66,8 @@ func (InternalIssuer) CaddyModule() caddy.ModuleInfo {
66
67 // Provision sets up the issuer.
68 func (iss *InternalIssuer) Provision(ctx caddy.Context) error {
69 + iss.logger = ctx.Logger(iss)
70 +
71 // get a reference to the configured CA
72 appModule, err := ctx.App("pki")
73 if err != nil {
@@ -115,11 +119,15 @@ func (iss InternalIssuer) Issue(ctx context.Context, csr *x509.CertificateReques
119 // ensure issued certificate does not expire later than its issuer
120 lifetime := time.Duration(iss.Lifetime)
121 if time.Now().Add(lifetime).After(issuerCert.NotAfter) {
118 - // TODO: log this
119 - lifetime = issuerCert.NotAfter.Sub(time.Now())
122 + lifetime = time.Until(issuerCert.NotAfter)
123 + iss.logger.Warn("cert lifetime would exceed issuer NotAfter, clamping lifetime",
124 + zap.Duration("orig_lifetime", time.Duration(iss.Lifetime)),
125 + zap.Duration("lifetime", lifetime),
126 + zap.Time("not_after", issuerCert.NotAfter),
127 + )
128 }
129
122 - certChain, err := auth.Sign(csr, provisioner.SignOptions{}, customCertLifetime(iss.Lifetime))
130 + certChain, err := auth.Sign(csr, provisioner.SignOptions{}, customCertLifetime(caddy.Duration(lifetime)))
131 if err != nil {
132 return nil, err
133 }
modules/caddytls/tls.go
-2
@@ -498,8 +498,6 @@ var (
498 storageCleanMu sync.Mutex
499 )
500
501 -const automateKey = "automate"
502 -
501 // Interface guards
502 var (
503 _ caddy.App = (*TLS)(nil)
modules/caddytls/values.go
+1
@@ -122,6 +122,7 @@ var SupportedProtocols = map[string]uint16{
122 // unsupportedProtocols is a map of unsupported protocols.
123 // Used for logging only, not enforcement.
124 var unsupportedProtocols = map[string]uint16{
125 + //nolint:staticcheck
126 "ssl3.0": tls.VersionSSL30,
127 "tls1.0": tls.VersionTLS10,
128 "tls1.1": tls.VersionTLS11,