Commit 84a94244b1
Verified · cmc
Layout: unified · split
Sources/keycask/AtomicFile.swift +2 −1
| @@ -49,7 +49,8 @@ enum AtomicFile { | |||
| 49 | } | 49 | } |
| 50 | #else | 50 | #else |
| 51 | private static func writePrivate(_ data: Data, to url: URL) throws { | 51 | private static func writePrivate(_ data: Data, to url: URL) throws { |
| 52 | let fd = open(url.path, O_WRONLY | O_CREAT | O_TRUNC, 0o600) | 52 | _ = unlink(url.path) |
| 53 | let fd = open(url.path, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0o600) | ||
| 53 | guard fd >= 0 else { | 54 | guard fd >= 0 else { |
| 54 | throw KeycaskError.io("open \(url.path): \(String(cString: strerror(errno)))") | 55 | throw KeycaskError.io("open \(url.path): \(String(cString: strerror(errno)))") |
| 55 | } | 56 | } |
Tests/KeycaskCLITests/InitTests.swift +30
| @@ -65,6 +65,36 @@ import Testing | |||
| 65 | let mode = (attrs[.posixPermissions] as! NSNumber).intValue & 0o777 | 65 | let mode = (attrs[.posixPermissions] as! NSNumber).intValue & 0o777 |
| 66 | #expect(mode == 0o600) | 66 | #expect(mode == 0o600) |
| 67 | } | 67 | } |
| 68 | |||
| 69 | @Test func preExistingTempFileDoesNotWeakenPermissions() throws { | ||
| 70 | let cli = try CLI() | ||
| 71 | let temp = cli.dir.appendingPathComponent("vault.kc.tmp") | ||
| 72 | FileManager.default.createFile( | ||
| 73 | atPath: temp.path, contents: Data(), attributes: [.posixPermissions: 0o644]) | ||
| 74 | |||
| 75 | let r = try cli.run(["init"]) | ||
| 76 | #expect(r.status == 0) | ||
| 77 | let attrs = try FileManager.default.attributesOfItem(atPath: cli.vault.path) | ||
| 78 | let mode = (attrs[.posixPermissions] as! NSNumber).intValue & 0o777 | ||
| 79 | #expect(mode == 0o600) | ||
| 80 | #expect(!FileManager.default.fileExists(atPath: temp.path)) | ||
| 81 | } | ||
| 82 | |||
| 83 | @Test func symlinkedTempFileIsNotFollowed() throws { | ||
| 84 | let cli = try CLI() | ||
| 85 | let victim = cli.dir.appendingPathComponent("victim.txt") | ||
| 86 | FileManager.default.createFile(atPath: victim.path, contents: Data()) | ||
| 87 | let temp = cli.dir.appendingPathComponent("vault.kc.tmp") | ||
| 88 | try FileManager.default.createSymbolicLink(at: temp, withDestinationURL: victim) | ||
| 89 | |||
| 90 | let r = try cli.run(["init"]) | ||
| 91 | #expect(r.status == 0) | ||
| 92 | let victimAttrs = try FileManager.default.attributesOfItem(atPath: victim.path) | ||
| 93 | #expect((victimAttrs[.size] as! NSNumber).intValue == 0) | ||
| 94 | let attrs = try FileManager.default.attributesOfItem(atPath: cli.vault.path) | ||
| 95 | #expect(attrs[.type] as? FileAttributeType == .typeRegular) | ||
| 96 | #expect((attrs[.posixPermissions] as! NSNumber).intValue & 0o777 == 0o600) | ||
| 97 | } | ||
| 68 | #endif | 98 | #endif |
| 69 | 99 | ||
| 70 | @Test func noTempFileLeftBehind() throws { | 100 | @Test func noTempFileLeftBehind() throws { |