|
@@ -2,9 +2,14 @@ package common
|
|
|
|
|
|
import (
|
|
|
"crypto/tls"
|
|
|
+ "crypto/x509"
|
|
|
+ "fmt"
|
|
|
+ "io/ioutil"
|
|
|
+ "path/filepath"
|
|
|
"sync"
|
|
|
|
|
|
"github.com/drakkan/sftpgo/logger"
|
|
|
+ "github.com/drakkan/sftpgo/utils"
|
|
|
)
|
|
|
|
|
|
// CertManager defines a TLS certificate manager
|
|
@@ -12,7 +17,8 @@ type CertManager struct {
|
|
|
certPath string
|
|
|
keyPath string
|
|
|
sync.RWMutex
|
|
|
- cert *tls.Certificate
|
|
|
+ cert *tls.Certificate
|
|
|
+ rootCAs *x509.CertPool
|
|
|
}
|
|
|
|
|
|
// LoadCertificate loads the configured x509 key pair
|
|
@@ -39,6 +45,44 @@ func (m *CertManager) GetCertificateFunc() func(*tls.ClientHelloInfo) (*tls.Cert
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// GetRootCAs returns the set of root certificate authorities that servers
|
|
|
+// use if required to verify a client certificate
|
|
|
+func (m *CertManager) GetRootCAs() *x509.CertPool {
|
|
|
+ return m.rootCAs
|
|
|
+}
|
|
|
+
|
|
|
+// LoadRootCAs tries to load root CA certificate authorities from the given paths
|
|
|
+func (m *CertManager) LoadRootCAs(caCertificates []string, configDir string) error {
|
|
|
+ if len(caCertificates) == 0 {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ rootCAs := x509.NewCertPool()
|
|
|
+
|
|
|
+ for _, rootCA := range caCertificates {
|
|
|
+ if !utils.IsFileInputValid(rootCA) {
|
|
|
+ return fmt.Errorf("invalid root CA certificate %#v", rootCA)
|
|
|
+ }
|
|
|
+ if rootCA != "" && !filepath.IsAbs(rootCA) {
|
|
|
+ rootCA = filepath.Join(configDir, rootCA)
|
|
|
+ }
|
|
|
+ crt, err := ioutil.ReadFile(rootCA)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ if rootCAs.AppendCertsFromPEM(crt) {
|
|
|
+ logger.Debug(logSender, "", "TLS certificate authority %#v successfully loaded", rootCA)
|
|
|
+ } else {
|
|
|
+ err := fmt.Errorf("unable to load TLS certificate authority %#v", rootCA)
|
|
|
+ logger.Debug(logSender, "", "%v", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ m.rootCAs = rootCAs
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
// NewCertManager creates a new certificate manager
|
|
|
func NewCertManager(certificateFile, certificateKeyFile, logSender string) (*CertManager, error) {
|
|
|
manager := &CertManager{
|