Fixes loading of private key on Windows (#299)

Unix permissions don't work on Windows; 
adds check for correct ACL settings in Windows.
This commit is contained in:
markspanbroek 2022-11-07 09:54:24 -05:00 committed by GitHub
parent c893b1f0cb
commit be32b9619b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 2 deletions

View File

@ -49,6 +49,12 @@ proc secureWriteFile*[T: byte|char](path: string,
else: else:
writeFile(path, data, 0o600) writeFile(path, data, 0o600)
proc checkSecureFile*(path: string): IOResult[bool] =
when defined(windows):
checkCurrentUserOnlyACL(path)
else:
ok (? getPermissionsSet(path) == {UserRead, UserWrite})
proc checkAndCreateDataDir*(dataDir: string): bool = proc checkAndCreateDataDir*(dataDir: string): bool =
when defined(posix): when defined(posix):
let requiredPerms = 0o700 let requiredPerms = 0o700

View File

@ -36,11 +36,11 @@ proc setupKey*(path: string): ?!PrivateKey =
res = ? PrivateKey.random(Rng.instance()[]).mapFailure(CodexKeyError) res = ? PrivateKey.random(Rng.instance()[]).mapFailure(CodexKeyError)
bytes = ? res.getBytes().mapFailure(CodexKeyError) bytes = ? res.getBytes().mapFailure(CodexKeyError)
? path.writeFile(bytes, SafePermissions.toInt()).mapFailure(CodexKeyError) ? path.secureWriteFile(bytes).mapFailure(CodexKeyError)
return PrivateKey.init(bytes).mapFailure(CodexKeyError) return PrivateKey.init(bytes).mapFailure(CodexKeyError)
info "Found a network private key" info "Found a network private key"
if path.getPermissionsSet().get() != SafePermissions: if not ? checkSecureFile(path).mapFailure(CodexKeyError):
warn "The network private key file is not safe, aborting" warn "The network private key file is not safe, aborting"
return failure newException( return failure newException(
CodexKeyUnsafeError, "The network private key file is not safe") CodexKeyUnsafeError, "The network private key file is not safe")

View File

@ -1,4 +1,5 @@
import ./utils/teststatemachine import ./utils/teststatemachine
import ./utils/testoptionalcast import ./utils/testoptionalcast
import ./utils/testkeyutils
{.warning[UnusedImport]: off.} {.warning[UnusedImport]: off.}

View File

@ -0,0 +1,34 @@
import std/unittest
import std/os
import pkg/libp2p
import pkg/questionable/results
import codex/utils/keyutils
when defined(windows):
import stew/windows/acl
suite "keyutils":
let path = getTempDir() / "CodexTest"
setup:
os.createDir(path)
teardown:
os.removeDir(path)
test "creates a key file when it does not exist yet":
check setupKey(path / "keyfile").isSuccess
check fileExists(path / "keyfile")
test "stores key in a file that's only readable by the user":
discard !setupKey(path / "keyfile")
when defined(posix):
check getFilePermissions(path / "keyfile") == {fpUserRead, fpUserWrite}
when defined(windows):
check checkCurrentUserOnlyACL(path / "keyfile").get()
test "reads key file when it does exist":
let key = !setupKey(path / "keyfile")
check !setupKey(path / "keyfile") == key