forked from ebhomengo/niki
1
0
Fork 0
niki/vendor/golang.org/x/crypto/acme/autocert/cache.go

236 lines
3.6 KiB
Go
Raw Normal View History

2024-02-18 10:42:21 +00:00
// Copyright 2016 The Go Authors. All rights reserved.
2024-02-18 10:42:21 +00:00
// Use of this source code is governed by a BSD-style
2024-02-18 10:42:21 +00:00
// license that can be found in the LICENSE file.
package autocert
import (
"context"
"errors"
"os"
"path/filepath"
)
// ErrCacheMiss is returned when a certificate is not found in cache.
2024-02-18 10:42:21 +00:00
var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss")
// Cache is used by Manager to store and retrieve previously obtained certificates
2024-02-18 10:42:21 +00:00
// and other account data as opaque blobs.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// Cache implementations should not rely on the key naming pattern. Keys can
2024-02-18 10:42:21 +00:00
// include any printable ASCII characters, except the following: \/:*?"<>|
2024-02-18 10:42:21 +00:00
type Cache interface {
2024-02-18 10:42:21 +00:00
// Get returns a certificate data for the specified key.
2024-02-18 10:42:21 +00:00
// If there's no such key, Get returns ErrCacheMiss.
2024-02-18 10:42:21 +00:00
Get(ctx context.Context, key string) ([]byte, error)
// Put stores the data in the cache under the specified key.
2024-02-18 10:42:21 +00:00
// Underlying implementations may use any data storage format,
2024-02-18 10:42:21 +00:00
// as long as the reverse operation, Get, results in the original data.
2024-02-18 10:42:21 +00:00
Put(ctx context.Context, key string, data []byte) error
// Delete removes a certificate data from the cache under the specified key.
2024-02-18 10:42:21 +00:00
// If there's no such key in the cache, Delete returns nil.
2024-02-18 10:42:21 +00:00
Delete(ctx context.Context, key string) error
}
// DirCache implements Cache using a directory on the local filesystem.
2024-02-18 10:42:21 +00:00
// If the directory does not exist, it will be created with 0700 permissions.
2024-02-18 10:42:21 +00:00
type DirCache string
// Get reads a certificate data from the specified file name.
2024-02-18 10:42:21 +00:00
func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) {
2024-02-18 10:42:21 +00:00
name = filepath.Join(string(d), filepath.Clean("/"+name))
2024-02-18 10:42:21 +00:00
var (
data []byte
err error
2024-02-18 10:42:21 +00:00
done = make(chan struct{})
)
2024-02-18 10:42:21 +00:00
go func() {
2024-02-18 10:42:21 +00:00
data, err = os.ReadFile(name)
2024-02-18 10:42:21 +00:00
close(done)
2024-02-18 10:42:21 +00:00
}()
2024-02-18 10:42:21 +00:00
select {
2024-02-18 10:42:21 +00:00
case <-ctx.Done():
2024-02-18 10:42:21 +00:00
return nil, ctx.Err()
2024-02-18 10:42:21 +00:00
case <-done:
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if os.IsNotExist(err) {
2024-02-18 10:42:21 +00:00
return nil, ErrCacheMiss
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return data, err
2024-02-18 10:42:21 +00:00
}
// Put writes the certificate data to the specified file name.
2024-02-18 10:42:21 +00:00
// The file will be created with 0600 permissions.
2024-02-18 10:42:21 +00:00
func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
2024-02-18 10:42:21 +00:00
if err := os.MkdirAll(string(d), 0700); err != nil {
2024-02-18 10:42:21 +00:00
return err
2024-02-18 10:42:21 +00:00
}
done := make(chan struct{})
2024-02-18 10:42:21 +00:00
var err error
2024-02-18 10:42:21 +00:00
go func() {
2024-02-18 10:42:21 +00:00
defer close(done)
2024-02-18 10:42:21 +00:00
var tmp string
2024-02-18 10:42:21 +00:00
if tmp, err = d.writeTempFile(name, data); err != nil {
2024-02-18 10:42:21 +00:00
return
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
defer os.Remove(tmp)
2024-02-18 10:42:21 +00:00
select {
2024-02-18 10:42:21 +00:00
case <-ctx.Done():
2024-02-18 10:42:21 +00:00
// Don't overwrite the file if the context was canceled.
2024-02-18 10:42:21 +00:00
default:
2024-02-18 10:42:21 +00:00
newName := filepath.Join(string(d), filepath.Clean("/"+name))
2024-02-18 10:42:21 +00:00
err = os.Rename(tmp, newName)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}()
2024-02-18 10:42:21 +00:00
select {
2024-02-18 10:42:21 +00:00
case <-ctx.Done():
2024-02-18 10:42:21 +00:00
return ctx.Err()
2024-02-18 10:42:21 +00:00
case <-done:
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return err
2024-02-18 10:42:21 +00:00
}
// Delete removes the specified file name.
2024-02-18 10:42:21 +00:00
func (d DirCache) Delete(ctx context.Context, name string) error {
2024-02-18 10:42:21 +00:00
name = filepath.Join(string(d), filepath.Clean("/"+name))
2024-02-18 10:42:21 +00:00
var (
err error
2024-02-18 10:42:21 +00:00
done = make(chan struct{})
)
2024-02-18 10:42:21 +00:00
go func() {
2024-02-18 10:42:21 +00:00
err = os.Remove(name)
2024-02-18 10:42:21 +00:00
close(done)
2024-02-18 10:42:21 +00:00
}()
2024-02-18 10:42:21 +00:00
select {
2024-02-18 10:42:21 +00:00
case <-ctx.Done():
2024-02-18 10:42:21 +00:00
return ctx.Err()
2024-02-18 10:42:21 +00:00
case <-done:
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
if err != nil && !os.IsNotExist(err) {
2024-02-18 10:42:21 +00:00
return err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return nil
2024-02-18 10:42:21 +00:00
}
// writeTempFile writes b to a temporary file, closes the file and returns its path.
2024-02-18 10:42:21 +00:00
func (d DirCache) writeTempFile(prefix string, b []byte) (name string, reterr error) {
2024-02-18 10:42:21 +00:00
// TempFile uses 0600 permissions
2024-02-18 10:42:21 +00:00
f, err := os.CreateTemp(string(d), prefix)
2024-02-18 10:42:21 +00:00
if err != nil {
2024-02-18 10:42:21 +00:00
return "", err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
defer func() {
2024-02-18 10:42:21 +00:00
if reterr != nil {
2024-02-18 10:42:21 +00:00
os.Remove(f.Name())
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}()
2024-02-18 10:42:21 +00:00
if _, err := f.Write(b); err != nil {
2024-02-18 10:42:21 +00:00
f.Close()
2024-02-18 10:42:21 +00:00
return "", err
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return f.Name(), f.Close()
2024-02-18 10:42:21 +00:00
}