From 6ee51c5cc1b9dba8155c3565356d49261f04edcb Mon Sep 17 00:00:00 2001 From: Nicola Murino Date: Wed, 1 Dec 2021 17:53:19 +0100 Subject: [PATCH] kms: remove support for compat secrets also document how to activate the deprecated builtin provider --- README.md | 2 +- docs/kms.md | 2 +- httpd/httpd.go | 2 +- httpd/httpd_test.go | 16 +++++------ kms/kms.go | 9 ------ util/util.go | 69 --------------------------------------------- 6 files changed, 11 insertions(+), 89 deletions(-) diff --git a/README.md b/README.md index 554e6bc7..56a4e0ea 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Docker Pulls](https://img.shields.io/docker/pulls/drakkan/sftpgo)](https://hub.docker.com/r/drakkan/sftpgo) [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go) -Fully featured and highly configurable SFTP server with optional HTTP, FTP/S and WebDAV support, written in Go. +Fully featured and highly configurable SFTP server with optional HTTP, FTP/S and WebDAV support. Several storage backends are supported: local filesystem, encrypted local filesystem, S3 (compatible) Object Storage, Google Cloud Storage, Azure Blob Storage, SFTP. ## Features diff --git a/docs/kms.md b/docs/kms.md index 8392fe97..98bdcceb 100644 --- a/docs/kms.md +++ b/docs/kms.md @@ -19,7 +19,7 @@ We first generate a random key, then the per-object encryption key is derived fr 1. a master key is provided: the encryption key is derived using the HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as defined in [RFC 5869](http://tools.ietf.org/html/rfc5869) 2. no master key is provided: the encryption key is derived as simple hash of the random key. This is the default configuration. -For compatibility with SFTPGo versions 1.2.x and before we also support encryption based on `AES-256-GCM`. The data encrypted with this algorithm will never use the master key to keep backward compatibility. +For compatibility with SFTPGo versions 1.2.x and before we also support encryption based on `AES-256-GCM`. The data encrypted with this algorithm will never use the master key to keep backward compatibility. You can activate it using `builtin://` as `url` but this is not recommended. ### Cloud providers diff --git a/httpd/httpd.go b/httpd/httpd.go index e63af524..53acd419 100644 --- a/httpd/httpd.go +++ b/httpd/httpd.go @@ -144,7 +144,7 @@ const ( maxRequestSize = 1048576 // 1MB maxLoginBodySize = 262144 // 256 KB httpdMaxEditFileSize = 1048576 // 1 MB - maxMultipartMem = 8388608 // 8MB + maxMultipartMem = 10485760 // 10 MB osWindows = "windows" otpHeaderCode = "X-SFTPGO-OTP" ) diff --git a/httpd/httpd_test.go b/httpd/httpd_test.go index 58b120cc..52e2a154 100644 --- a/httpd/httpd_test.go +++ b/httpd/httpd_test.go @@ -2857,14 +2857,6 @@ func TestSecretObject(t *testing.T) { require.Equal(t, kms.SecretStatusPlain, s.GetStatus()) require.Equal(t, "test data", s.GetPayload()) require.Empty(t, s.GetKey()) - - oldFormat := "$aes$5b97e3a3324a2f53e2357483383367c0$0ed3132b584742ab217866219da633266782b69b13e50ebc6ddfb7c4fbf2f2a414c6d5f813" - s, err = kms.GetSecretFromCompatString(oldFormat) - require.NoError(t, err) - require.True(t, s.IsValid()) - require.Equal(t, kms.SecretStatusPlain, s.GetStatus()) - require.Equal(t, "test data", s.GetPayload()) - require.Empty(t, s.GetKey()) } func TestSecretObjectCompatibility(t *testing.T) { @@ -8988,6 +8980,10 @@ func TestShareUncompressed(t *testing.T) { checkResponseCode(t, http.StatusOK, rr) assert.Equal(t, "application/octet-stream", rr.Header().Get("Content-Type")) + share, err = dataprovider.ShareExists(objectID, user.Username) + assert.NoError(t, err) + assert.Equal(t, 2, share.UsedTokens) + user.Permissions["/"] = []string{dataprovider.PermListItems, dataprovider.PermUpload} user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "") assert.NoError(t, err) @@ -8998,6 +8994,10 @@ func TestShareUncompressed(t *testing.T) { rr = executeRequest(req) checkResponseCode(t, http.StatusForbidden, rr) + share, err = dataprovider.ShareExists(objectID, user.Username) + assert.NoError(t, err) + assert.Equal(t, 2, share.UsedTokens) + user.Permissions["/"] = []string{dataprovider.PermAny} user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "") assert.NoError(t, err) diff --git a/kms/kms.go b/kms/kms.go index 7daad444..ebce5fda 100644 --- a/kms/kms.go +++ b/kms/kms.go @@ -125,15 +125,6 @@ func NewPlainSecret(payload string) *Secret { return NewSecret(SecretStatusPlain, payload, "", "") } -// GetSecretFromCompatString returns a secret from the previous format -func GetSecretFromCompatString(secret string) (*Secret, error) { - plain, err := util.DecryptData(secret) - if err != nil { - return &Secret{}, errMalformedCiphertext - } - return NewSecret(SecretStatusPlain, plain, "", ""), nil -} - // Initialize configures the KMS support func (c *Configuration) Initialize() error { if c.Secrets.MasterKeyString != "" { diff --git a/util/util.go b/util/util.go index a04c14d7..0c13d22a 100644 --- a/util/util.go +++ b/util/util.go @@ -3,8 +3,6 @@ package util import ( "bytes" - "crypto/aes" - "crypto/cipher" "crypto/ecdsa" "crypto/ed25519" "crypto/elliptic" @@ -12,7 +10,6 @@ import ( "crypto/rsa" "crypto/tls" "crypto/x509" - "encoding/hex" "encoding/pem" "errors" "fmt" @@ -154,72 +151,6 @@ func NilIfEmpty(s string) *string { return &s } -// EncryptData encrypts data using the given key -func EncryptData(data string) (string, error) { - var result string - key := make([]byte, 16) - if _, err := io.ReadFull(rand.Reader, key); err != nil { - return result, err - } - keyHex := hex.EncodeToString(key) - block, err := aes.NewCipher([]byte(keyHex)) - if err != nil { - return result, err - } - gcm, err := cipher.NewGCM(block) - if err != nil { - return result, err - } - nonce := make([]byte, gcm.NonceSize()) - if _, err = io.ReadFull(rand.Reader, nonce); err != nil { - return result, err - } - ciphertext := gcm.Seal(nonce, nonce, []byte(data), nil) - result = fmt.Sprintf("$aes$%s$%x", keyHex, ciphertext) - return result, err -} - -// RemoveDecryptionKey returns encrypted data without the decryption key -func RemoveDecryptionKey(encryptData string) string { - vals := strings.Split(encryptData, "$") - if len(vals) == 4 { - return fmt.Sprintf("$%v$%v", vals[1], vals[3]) - } - return encryptData -} - -// DecryptData decrypts data encrypted using EncryptData -func DecryptData(data string) (string, error) { - var result string - vals := strings.Split(data, "$") - if len(vals) != 4 { - return "", errors.New("data to decrypt is not in the correct format") - } - key := vals[2] - encrypted, err := hex.DecodeString(vals[3]) - if err != nil { - return result, err - } - block, err := aes.NewCipher([]byte(key)) - if err != nil { - return result, err - } - gcm, err := cipher.NewGCM(block) - if err != nil { - return result, err - } - nonceSize := gcm.NonceSize() - if len(encrypted) < nonceSize { - return result, errors.New("malformed ciphertext") - } - nonce, ciphertext := encrypted[:nonceSize], encrypted[nonceSize:] - plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) - if err != nil { - return result, err - } - return string(plaintext), nil -} - // GenerateRSAKeys generate rsa private and public keys and write the // private key to specified file and the public key to the specified // file adding the .pub suffix