--- /dev/null
+package caches
+
+import (
+ "crypto/tls"
+ "sync"
+)
+
+var (
+ Accepted = make(map[string]string)
+ AcceptedM sync.RWMutex
+
+ Rejected = make(map[string]string)
+ RejectedM sync.RWMutex
+
+ HTTPAuthCache = make(map[string][2]string)
+ HTTPAuthCacheM sync.RWMutex
+
+ TLSAuthCache = make(map[string]*tls.Certificate)
+ TLSAuthCacheM sync.RWMutex
+)
[ -e certgen.cmd ] || redo certgen.cmd
-./certgen.cmd
+umask 077
+./certgen.cmd > $3
}
fifos.NoTAI = *notai
- fifos.FIFOs = *fifosDir
- fifos.Init()
+ fifos.Start(*fifosDir)
tofuproxy.Certs = *certs
tofuproxy.CCerts = *ccerts
tofuproxy.DNSSrv = *dnsSrv
@item
@strong{HTTP-based authorization} requests are intercepted and
user/password input dialogue is shown. It automatically loads
-@strong{initial form} values from @file{.netrc}.
+@strong{initial form} values from @strong{@file{.netrc}}.
@item
TLS @strong{client certificates} supported: separate dialogue window for
@item Point you HTTP/HTTPS clients to @code{http://localhost:8080}.
+@item
+If you want to use TLS client certificates, then place them to
+@file{-ccerts} directory.
+
@item Watch logs:
@example
@image{dialog,,,Example dialog,.webp}
-@item If you want to use TLS client certificates, then place them to
-@file{-ccerts} directory.
+@item
+To list currently accepted, rejected, HTTP authorized, TLS client
+authenticated hosts:
+
+@example
+$ cat fifos/list-@{accepted,rejected,http-auth,tls-auth@}
+@end example
+
+@item
+To remove knowledge of the host from any of the states mentioned above:
+
+@example
+$ echo www.example.com > fifos/del-tls-auth
+@end example
@end itemize
--- /dev/null
+/*
+tofuproxy -- HTTP proxy with TLS certificates management
+Copyright (C) 2021 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package fifos
+
+import (
+ "bufio"
+ "log"
+ "os"
+ "sync"
+)
+
+func del(l *sync.RWMutex, deleter func(string), p string) {
+ for {
+ fd, err := os.OpenFile(p, os.O_RDONLY, os.FileMode(0666))
+ if err != nil {
+ log.Fatalln(err)
+ }
+ var hosts []string
+ scanner := bufio.NewScanner(fd)
+ for scanner.Scan() {
+ t := scanner.Text()
+ if len(t) > 0 {
+ hosts = append(hosts, t)
+ }
+ }
+ fd.Close()
+ l.Lock()
+ for _, host := range hosts {
+ log.Printf("%s: deleting host %s\n", p, host)
+ deleter(host)
+ }
+ l.Unlock()
+ }
+}
-for f in cert dane err ok other redir req tls ; do
- [ -p $f ] || mkfifo $f
+for f in cert dane err http-auth non-ok ok redir req tls tls-auth various ; do
+ [ -p log-$f ] || mkfifo log-$f
+done
+for f in accepted http-auth rejected tls-auth ; do
+ [ -p list-$f ] || mkfifo list-$f
+ [ -p del-$f ] || mkfifo del-$f
done
--- /dev/null
+/*
+tofuproxy -- HTTP proxy with TLS certificates management
+Copyright (C) 2021 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 3 of the License.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package fifos
+
+import (
+ "crypto/x509"
+ "fmt"
+ "log"
+ "os"
+ "sync"
+
+ "go.stargrave.org/tofuproxy/caches"
+)
+
+func list(l *sync.RWMutex, m map[string]string, p string) {
+ for {
+ fd, err := os.OpenFile(p, os.O_WRONLY|os.O_APPEND, os.FileMode(0666))
+ if err != nil {
+ log.Fatalln(err)
+ }
+ l.RLock()
+ for host, hsh := range m {
+ if _, err = fd.WriteString(fmt.Sprintf("%s\t%s\n", host, hsh)); err != nil {
+ break
+ }
+ }
+ l.RUnlock()
+ fd.Close()
+ }
+}
+
+func listAccepted(p string) {
+ list(&caches.AcceptedM, caches.Accepted, p)
+}
+
+func listRejected(p string) {
+ list(&caches.RejectedM, caches.Rejected, p)
+}
+
+func listHTTPAuth(p string) {
+ for {
+ fd, err := os.OpenFile(p, os.O_WRONLY|os.O_APPEND, os.FileMode(0666))
+ if err != nil {
+ log.Fatalln(err)
+ }
+ caches.HTTPAuthCacheM.RLock()
+ for host, creds := range caches.HTTPAuthCache {
+ if _, err = fd.WriteString(fmt.Sprintf("%s\t%s\n", host, creds[0])); err != nil {
+ break
+ }
+ }
+ caches.HTTPAuthCacheM.RUnlock()
+ fd.Close()
+ }
+}
+
+func listTLSAuth(p string) {
+ for {
+ fd, err := os.OpenFile(p, os.O_WRONLY|os.O_APPEND, os.FileMode(0666))
+ if err != nil {
+ log.Fatalln(err)
+ }
+ caches.TLSAuthCacheM.RLock()
+ for host, tlsCert := range caches.TLSAuthCache {
+ cert, err := x509.ParseCertificate(tlsCert.Certificate[0])
+ if err != nil {
+ log.Fatalln(err)
+ }
+ if _, err = fd.WriteString(fmt.Sprintf("%s\t%s\n", host, cert.Subject)); err != nil {
+ break
+ }
+ }
+ caches.TLSAuthCacheM.RUnlock()
+ fd.Close()
+ }
+}
import (
"log"
"os"
- "path/filepath"
"time"
"go.cypherpunks.ru/tai64n/v2"
)
var (
- NoTAI bool
- FIFOs string
- SinkCert = make(chan string)
- SinkDANE = make(chan string)
- SinkErr = make(chan string)
- SinkOK = make(chan string)
- SinkOther = make(chan string)
- SinkRedir = make(chan string)
- SinkReq = make(chan string)
- SinkTLS = make(chan string)
+ NoTAI bool
+
+ LogCert = make(chan string)
+ LogDANE = make(chan string)
+ LogErr = make(chan string)
+ LogHTTPAuth = make(chan string)
+ LogNonOK = make(chan string)
+ LogOK = make(chan string)
+ LogRedir = make(chan string)
+ LogReq = make(chan string)
+ LogTLS = make(chan string)
+ LogTLSAuth = make(chan string)
+ LogVarious = make(chan string)
)
-func sinker(c chan string, p string) {
+func logger(c chan string, p string) {
tai := new(tai64n.TAI64N)
for {
fd, err := os.OpenFile(p, os.O_WRONLY|os.O_APPEND, os.FileMode(0666))
fd.Close()
}
}
-
-func Init() {
- go sinker(SinkCert, filepath.Join(FIFOs, "cert"))
- go sinker(SinkDANE, filepath.Join(FIFOs, "dane"))
- go sinker(SinkErr, filepath.Join(FIFOs, "err"))
- go sinker(SinkOK, filepath.Join(FIFOs, "ok"))
- go sinker(SinkOther, filepath.Join(FIFOs, "other"))
- go sinker(SinkRedir, filepath.Join(FIFOs, "redir"))
- go sinker(SinkReq, filepath.Join(FIFOs, "req"))
- go sinker(SinkTLS, filepath.Join(FIFOs, "tls"))
-}
multitail \
-wh 10 \
- -t "Certificates" -ci magenta -l "while :; do tai64nlocal < cert ; done" \
- -t "DANE" --label "DANE " -L "while :; do tai64nlocal < dane ; done" \
- -t "Errors" -ci red -L "while :; do tai64nlocal < err ; done" \
- -t "Responses" -ci green --label "< " -l "while :; do tai64nlocal < ok ; done" \
- -t "Others" -ci white -L "while :; do tai64nlocal < other ; done" \
- -t "Redirections" -ci cyan --label "R " -L "while :; do tai64nlocal < redir ; done" \
- -t "Requests" -ci blue --label "> " -L "while :; do tai64nlocal < req ; done" \
- -t "TLS connections" -ci yellow --label "S " -L "while :; do tai64nlocal < tls ; done"
+ -t "Trust" -ci magenta -l "while :; do tai64nlocal < log-cert ; done" \
+ -t "DANE" --label "DANE " -L "while :; do tai64nlocal < log-dane ; done" \
+ -t "Error" -ci red -L "while :; do tai64nlocal < log-err ; done" \
+ -t "HTTPAuth" -ci green --label "Auth " -L "while :; do tai64nlocal < log-http-auth ; done" \
+ -t "TLSAuth" -ci green --label "Auth " -l "while :; do tai64nlocal < log-tls-auth ; done" \
+ -t "Response non-OK" --label "< " -L "while :; do tai64nlocal < log-non-ok ; done" \
+ -t "Respone OK" -ci green --label "< " -L "while :; do tai64nlocal < log-ok ; done" \
+ -t "Redirect " -ci cyan --label "R " -L "while :; do tai64nlocal < log-redir ; done" \
+ -t "Request" -ci blue --label "> " -L "while :; do tai64nlocal < log-req ; done" \
+ -t "TLS connection" -ci yellow --label "S " -L "while :; do tai64nlocal < log-tls ; done" \
+ -t "Various" -ci yellow -L "while :; do tai64nlocal < log-various ; done"
--- /dev/null
+package fifos
+
+import (
+ "path/filepath"
+
+ "go.stargrave.org/tofuproxy/caches"
+)
+
+func Start(fifos string) {
+ go logger(LogCert, filepath.Join(fifos, "log-cert"))
+ go logger(LogDANE, filepath.Join(fifos, "log-dane"))
+ go logger(LogErr, filepath.Join(fifos, "log-err"))
+ go logger(LogHTTPAuth, filepath.Join(fifos, "log-http-auth"))
+ go logger(LogNonOK, filepath.Join(fifos, "log-non-ok"))
+ go logger(LogOK, filepath.Join(fifos, "log-ok"))
+ go logger(LogRedir, filepath.Join(fifos, "log-redir"))
+ go logger(LogReq, filepath.Join(fifos, "log-req"))
+ go logger(LogTLS, filepath.Join(fifos, "log-tls"))
+ go logger(LogTLSAuth, filepath.Join(fifos, "log-tls-auth"))
+ go logger(LogVarious, filepath.Join(fifos, "log-various"))
+
+ go listAccepted(filepath.Join(fifos, "list-accepted"))
+ go listHTTPAuth(filepath.Join(fifos, "list-http-auth"))
+ go listRejected(filepath.Join(fifos, "list-rejected"))
+ go listTLSAuth(filepath.Join(fifos, "list-tls-auth"))
+
+ go del(
+ &caches.AcceptedM, func(host string) { delete(caches.Accepted, host) },
+ filepath.Join(fifos, "del-accepted"),
+ )
+ go del(
+ &caches.HTTPAuthCacheM, func(host string) { delete(caches.HTTPAuthCache, host) },
+ filepath.Join(fifos, "del-http-auth"),
+ )
+ go del(
+ &caches.RejectedM, func(host string) { delete(caches.Rejected, host) },
+ filepath.Join(fifos, "del-rejected"),
+ )
+ go del(
+ &caches.TLSAuthCacheM, func(host string) { delete(caches.TLSAuthCache, host) },
+ filepath.Join(fifos, "del-tls-auth"),
+ )
+}
"os/exec"
"path/filepath"
"strings"
- "sync"
-)
-
-var (
- authCache = make(map[string][2]string)
- authCacheM sync.Mutex
)
func findInNetrc(host string) (string, string) {
fallthrough
case "font/otf", "font/ttf", "font/woff", "font/woff2":
http.NotFound(w, req)
- fifos.SinkOther <- fmt.Sprintf(
- "%s %s\t%d\tdeny fonts",
- req.Method,
- req.URL.String(),
- http.StatusNotFound,
- )
+ fifos.LogVarious <- fmt.Sprintf("%s %s\tdeny fonts", req.Method, req.URL)
resp.Body.Close()
return false, nil
}
resp.StatusCode, http.StatusText(resp.StatusCode),
redirType, location, location,
)))
- fifos.SinkRedir <- fmt.Sprintf(
- "%s %s\t%s\t%s", req.Method, resp.Status, req.URL.String(), location,
+ fifos.LogRedir <- fmt.Sprintf(
+ "%s %s\t%s\t%s", req.Method, req.URL, resp.Status, location,
)
return false, nil
}
) (bool, error) {
if IsSpy(host) {
http.NotFound(w, req)
- fifos.SinkOther <- fmt.Sprintf(
- "%s %s\t%d\tdeny spy",
- req.Method,
- req.URL.String(),
- http.StatusNotFound,
- )
+ fifos.LogVarious <- fmt.Sprintf("%s %s\tdeny spy", req.Method, req.URL)
return false, nil
}
return true, nil
w.Header().Add("Content-Type", "image/png")
w.WriteHeader(http.StatusOK)
w.Write(data)
- fifos.SinkOther <- fmt.Sprintf(
- "%s %s\t%d\t%s transcoded to PNG",
- req.Method,
- req.URL.String(),
- http.StatusOK,
- contentType,
+ fifos.LogVarious <- fmt.Sprintf(
+ "%s %s\t%s transcoded to PNG", req.Method, req.URL, contentType,
)
return false, nil
}
w.Header().Add("Content-Type", "image/png")
w.WriteHeader(http.StatusOK)
w.Write(data)
- fifos.SinkOther <- fmt.Sprintf(
- "%s %s\t%d\tWebP transcoded to PNG",
- req.Method,
- req.URL.String(),
- http.StatusOK,
- )
+ fifos.LogVarious <- fmt.Sprintf("%s %s\tWebP transcoded to PNG", req.Method, req.URL)
return false, nil
}
}
func dialTLS(ctx context.Context, network, addr string) (net.Conn, error) {
- host := strings.TrimSuffix(addr, ":443")
- ccg := ClientCertificateGetter{host}
+ host := strings.Split(addr, ":")[0]
+ ccg := ClientCertificateGetter{host: host}
cfg := tls.Config{
VerifyPeerCertificate: func(
rawCerts [][]byte,
var err error
conn, err = tls.Dial(network, addr, &cfg)
if err != nil {
- fifos.SinkErr <- fmt.Sprintf("%s\t%s", addr, dialErr.Error())
+ fifos.LogErr <- fmt.Sprintf("%s\t%s", addr, dialErr.Error())
return nil, err
}
}
connState := conn.ConnectionState()
- if connState.DidResume {
- fifos.SinkTLS <- fmt.Sprintf(
+ if !connState.DidResume {
+ fifos.LogTLS <- fmt.Sprintf(
"%s\t%s %s\t%s\t%s",
- strings.TrimSuffix(addr, ":443"),
+ addr,
ucspi.TLSVersion(connState.Version),
tls.CipherSuiteName(connState.CipherSuite),
spkiHash(connState.PeerCertificates[0]),
"strings"
"go.cypherpunks.ru/ucspi"
+ "go.stargrave.org/tofuproxy/caches"
"go.stargrave.org/tofuproxy/fifos"
)
type ClientCertificateGetter struct {
host string
+ auth bool
}
func (g *ClientCertificateGetter) get(
cri *tls.CertificateRequestInfo,
) (*tls.Certificate, error) {
+ caches.TLSAuthCacheM.RLock()
+ tlsCert := caches.TLSAuthCache[g.host]
+ caches.TLSAuthCacheM.RUnlock()
+ if tlsCert != nil {
+ return tlsCert, nil
+ }
var b bytes.Buffer
b.WriteString(fmt.Sprintf(`
wm title . "TLS client authentication: %s"
if err != nil {
return &tls.Certificate{}, nil
}
- fifos.SinkCert <- fmt.Sprintf("ClientAuth\t%s\t%s", g.host, certs[i].Subject)
+ fifos.LogTLSAuth <- fmt.Sprintf("%s\t%s", g.host, certs[i].Subject)
+ caches.TLSAuthCacheM.Lock()
+ caches.TLSAuthCache[g.host] = tlsCerts[i]
+ caches.TLSAuthCacheM.Unlock()
+ g.auth = true
return tlsCerts[i], nil
}
"time"
"github.com/dustin/go-humanize"
+ "go.stargrave.org/tofuproxy/caches"
"go.stargrave.org/tofuproxy/fifos"
"go.stargrave.org/tofuproxy/rounds"
)
) (bool, error)
func roundTrip(w http.ResponseWriter, req *http.Request) {
- fifos.SinkReq <- fmt.Sprintf("%s %s", req.Method, req.URL.String())
+ fifos.LogReq <- fmt.Sprintf("%s %s", req.Method, req.URL)
host := strings.TrimSuffix(req.URL.Host, ":443")
for _, round := range []Round{
rounds.RoundNoHead,
reqFlags := []string{}
unauthorized := false
- authCacheM.Lock()
- if creds, ok := authCache[req.URL.Host]; ok {
+ caches.HTTPAuthCacheM.RLock()
+ if creds, ok := caches.HTTPAuthCache[req.URL.Host]; ok {
req.SetBasicAuth(creds[0], creds[1])
+ fifos.LogHTTPAuth <- fmt.Sprintf("%s %s\t%s", req.Method, req.URL, creds[0])
unauthorized = true
}
- authCacheM.Unlock()
+ caches.HTTPAuthCacheM.RUnlock()
Retry:
resp, err := transport.RoundTrip(req)
if err != nil {
- fifos.SinkErr <- fmt.Sprintf("%s\t%s", req.URL.Host, err.Error())
+ fifos.LogErr <- fmt.Sprintf("%s\t%s", req.URL.Host, err.Error())
http.Error(w, err.Error(), http.StatusBadGateway)
return
}
if resp.StatusCode == http.StatusUnauthorized {
resp.Body.Close()
- authCacheM.Lock()
+ caches.HTTPAuthCacheM.Lock()
if unauthorized {
- delete(authCache, req.URL.Host)
+ delete(caches.HTTPAuthCache, req.URL.Host)
} else {
unauthorized = true
}
- fifos.SinkOther <- fmt.Sprintf("%s\tauthorization required", req.URL.Host)
+ fifos.LogVarious <- fmt.Sprintf(
+ "%s %s\tHTTP authorization required", req.Method, req.URL.Host,
+ )
user, pass, err := authDialog(host, resp.Header.Get("WWW-Authenticate"))
if err != nil {
- authCacheM.Unlock()
- fifos.SinkErr <- fmt.Sprintf("%s\t%s", req.URL.Host, err.Error())
+ caches.HTTPAuthCacheM.Unlock()
+ fifos.LogErr <- fmt.Sprintf("%s\t%s", req.URL.Host, err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- authCache[req.URL.Host] = [2]string{user, pass}
- authCacheM.Unlock()
+ caches.HTTPAuthCache[req.URL.Host] = [2]string{user, pass}
+ caches.HTTPAuthCacheM.Unlock()
req.SetBasicAuth(user, pass)
+ fifos.LogHTTPAuth <- fmt.Sprintf("%s %s\t%s", req.Method, req.URL, user)
goto Retry
}
if unauthorized {
resp.Body.Close()
msg := fmt.Sprintf(
"%s %s\t%s\t%s\t%s\t%s",
- req.Method,
- req.URL.String(),
+ req.Method, req.URL,
resp.Status,
resp.Header.Get("Content-Type"),
humanize.IBytes(uint64(n)),
strings.Join(reqFlags, ","),
)
if resp.StatusCode == http.StatusOK {
- fifos.SinkOK <- msg
+ fifos.LogOK <- msg
} else {
- fifos.SinkOther <- msg
+ fifos.LogNonOK <- msg
}
}
"sync"
"go.cypherpunks.ru/ucspi"
+ "go.stargrave.org/tofuproxy/caches"
"go.stargrave.org/tofuproxy/fifos"
)
CmdCerttool = "certtool"
CmdWish = "wish8.6"
- Certs string
- accepted = make(map[string]string)
- acceptedM sync.RWMutex
- rejected = make(map[string]string)
- rejectedM sync.RWMutex
- VerifyM sync.Mutex
+ Certs string
+ VerifyM sync.Mutex
)
func spkiHash(cert *x509.Certificate) string {
return hex.EncodeToString(hsh[:])
}
-func acceptedAdd(addr, h string) {
- acceptedM.Lock()
- accepted[addr] = h
- acceptedM.Unlock()
-}
-
-func rejectedAdd(addr, h string) {
- rejectedM.Lock()
- rejected[addr] = h
- rejectedM.Unlock()
-}
-
type ErrRejected struct {
addr string
}
certTheirHash := spkiHash(certTheir)
VerifyM.Lock()
defer VerifyM.Unlock()
- acceptedM.RLock()
- certOurHash := accepted[host]
- acceptedM.RUnlock()
+ caches.AcceptedM.RLock()
+ certOurHash := caches.Accepted[host]
+ caches.AcceptedM.RUnlock()
if certTheirHash == certOurHash {
return nil
}
- rejectedM.RLock()
- certOurHash = rejected[host]
- rejectedM.RUnlock()
+ caches.RejectedM.RLock()
+ certOurHash = caches.Rejected[host]
+ caches.RejectedM.RUnlock()
if certTheirHash == certOurHash {
return ErrRejected{host}
}
daneExists, daneMatched := dane(host, certTheir)
if daneExists {
if daneMatched {
- fifos.SinkDANE <- fmt.Sprintf("%s\tmatched", host)
+ fifos.LogDANE <- fmt.Sprintf("%s\tACK", host)
} else {
- fifos.SinkDANE <- fmt.Sprintf("%s\tNOT matched", host)
+ fifos.LogDANE <- fmt.Sprintf("%s\tNAK", host)
}
}
fn := filepath.Join(Certs, host)
certsOur, _, err := ucspi.CertPoolFromFile(fn)
if err == nil || dialErr != nil || (daneExists && !daneMatched) {
if certsOur != nil && certTheirHash == spkiHash(certsOur[0]) {
- acceptedAdd(host, certTheirHash)
+ caches.AcceptedM.Lock()
+ caches.Accepted[host] = certTheirHash
+ caches.AcceptedM.Unlock()
if bytes.Compare(certsOur[0].Raw, rawCerts[0]) != 0 {
- fifos.SinkCert <- fmt.Sprintf("Refresh\t%s\t%s", host, certTheirHash)
+ fifos.LogCert <- fmt.Sprintf("Refresh\t%s\t%s", host, certTheirHash)
goto CertUpdate
}
return nil
proc doOnce {} { exit 11 }
proc doReject {} { exit 12 }
button .bAccept -text "Accept" -bg green -command doAccept
-button .bOnce -text "Once" -command doOnce
+button .bOnce -text "Once" -bg green -command doOnce
button .bReject -text "Reject" -bg red -command doReject
grid .bAccept .bOnce .bReject
grid rowconfigure . 0 -weight 1
err = cmd.Run()
exitError, ok := err.(*exec.ExitError)
if !ok {
- fifos.SinkCert <- fmt.Sprintf("DENY\t%s\t%s", host, certTheirHash)
+ fifos.LogCert <- fmt.Sprintf("Reject\t%s\t%s", host, certTheirHash)
return ErrRejected{host}
}
switch exitError.ExitCode() {
case 10:
- fifos.SinkCert <- fmt.Sprintf("ADD\t%s\t%s", host, certTheirHash)
+ fifos.LogCert <- fmt.Sprintf("Accept\t%s\t%s", host, certTheirHash)
goto CertUpdate
case 11:
- fifos.SinkCert <- fmt.Sprintf("ONCE\t%s\t%s", host, certTheirHash)
- acceptedAdd(host, certTheirHash)
+ fifos.LogCert <- fmt.Sprintf("Once\t%s\t%s", host, certTheirHash)
+ caches.AcceptedM.Lock()
+ caches.Accepted[host] = certTheirHash
+ caches.AcceptedM.Unlock()
return nil
case 12:
- rejectedAdd(host, certTheirHash)
+ caches.RejectedM.Lock()
+ caches.Rejected[host] = certTheirHash
+ caches.RejectedM.Unlock()
fallthrough
default:
- fifos.SinkCert <- fmt.Sprintf("DENY\t%s\t%s", host, certTheirHash)
+ fifos.LogCert <- fmt.Sprintf("Reject\t%s\t%s", host, certTheirHash)
return ErrRejected{host}
}
} else {
if !os.IsNotExist(err) {
return err
}
- fifos.SinkCert <- fmt.Sprintf("TOFU\t%s\t%s", host, certTheirHash)
+ fifos.LogCert <- fmt.Sprintf("TOFU\t%s\t%s", host, certTheirHash)
}
CertUpdate:
tmp, err := os.CreateTemp(Certs, "")
}
tmp.Close()
os.Rename(tmp.Name(), fn)
- acceptedAdd(host, certTheirHash)
+ caches.AcceptedM.Lock()
+ caches.Accepted[host] = certTheirHash
+ caches.AcceptedM.Unlock()
return nil
}