Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit 310b94d

Browse files
committed
[CBR-470] Ensure 600 file permission on generated x509 certificates and keys
It is of the utmost importance that those files aren't readable by anyone but the user generating them. Files are generated upon start and used to secure the communication between cardano-sl and its clients (e.g. Daedalus) Note that, we do assume that users are able to secure their own environment from potential adversary services, so this is really about preventing one user to have access to certificates of another user.
1 parent f273cb7 commit 310b94d

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

x509/cardano-sl-x509.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ library
3131
, bytestring
3232
, cryptonite
3333
, data-default-class
34+
, directory
3435
, filepath
3536
, hourglass
3637
, ip

x509/src/Data/X509/Extra.hs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ import Data.X509.CertificateStore (CertificateStore,
5050
import Data.X509.Validation
5151
import Net.IPv4 (IPv4 (..))
5252
import Net.IPv6 (IPv6 (..))
53+
import System.Directory (removeFile, renameFile)
54+
import System.FilePath (splitFileName, (<.>))
55+
import System.IO (hClose, openBinaryTempFile)
5356

5457
import qualified Crypto.PubKey.RSA.Types as RSA
5558
import qualified Data.ByteString as BS
@@ -231,9 +234,9 @@ writeCredentials
231234
-> (PrivateKey, SignedCertificate)
232235
-> IO ()
233236
writeCredentials filename (key, cert) = do
234-
BS.writeFile (filename <> ".pem") (BS.concat [keyBytes, "\n", certBytes])
235-
BS.writeFile (filename <> ".key") keyBytes
236-
BS.writeFile (filename <> ".crt") certBytes
237+
writeFileAtomicPrivate (filename <> ".pem") (BS.concat [keyBytes, "\n", certBytes])
238+
writeFileAtomicPrivate (filename <> ".key") keyBytes
239+
writeFileAtomicPrivate (filename <> ".crt") certBytes
237240
where
238241
keyBytes = encodePEM key
239242
certBytes = encodePEM cert
@@ -245,7 +248,7 @@ writeCertificate
245248
-> SignedCertificate
246249
-> IO ()
247250
writeCertificate filename cert =
248-
BS.writeFile (filename <> ".crt") (encodePEM cert)
251+
writeFileAtomicPrivate (filename <> ".crt") (encodePEM cert)
249252

250253

251254
--
@@ -330,3 +333,26 @@ validateCertificateIP ip cert =
330333
[]
331334
else
332335
[NameMismatch $ B8.unpack ip]
336+
337+
338+
-- | Writes a file atomically, and with private file permissions.
339+
--
340+
-- The file is either written successfully or an IO exception is raised and
341+
-- the original file is left unchanged.
342+
--
343+
-- On unix systems the file permissions are 600, i.e. user read and write,
344+
-- but no others.
345+
--
346+
-- On windows it is not possible to delete a file that is open by a process.
347+
-- This case will give an IO exception but the atomic property is not affected.
348+
--
349+
writeFileAtomicPrivate :: FilePath -> ByteString -> IO ()
350+
writeFileAtomicPrivate targetPath content = do
351+
let (targetDir, targetFile) = splitFileName targetPath
352+
bracketOnError
353+
(openBinaryTempFile targetDir $ targetFile <.> "tmp")
354+
(\(tmpPath, handle) -> hClose handle >> removeFile tmpPath)
355+
(\(tmpPath, handle) -> do
356+
BS.hPut handle content
357+
hClose handle
358+
renameFile tmpPath targetPath)

0 commit comments

Comments
 (0)