15
|
1 package name.blackcap.passman
|
|
2
|
|
3 import java.nio.file.Files
|
|
4 import java.nio.file.Path
|
|
5 import java.nio.file.StandardCopyOption
|
|
6 import kotlin.system.exitProcess
|
|
7
|
|
8 class PasswordSubcommand : Subcommand() {
|
|
9 override fun run(args: Array<String>) {
|
|
10 // Parse arguments
|
|
11 if (args.size > 0 && (args[0] == "-h" || args[0].startsWith("--h"))) {
|
|
12 println("usage: passman password")
|
|
13 exitProcess(0)
|
|
14 }
|
|
15 if (!args.isEmpty()) {
|
|
16 die("unexpected arguments", 2)
|
|
17 }
|
|
18
|
|
19 // Open databases
|
|
20 println("Changing database encryption key...")
|
|
21 val oldPath = Path.of(DB_FILE)
|
|
22 val oldDb = Database.open(fileName = DB_FILE, passwordPrompt = "Old database key: ")
|
|
23 val newPath = Path.of(NEW_DB_FILE)
|
|
24 if (Files.exists(newPath)) {
|
|
25 println("WARNING: deleting ${see(NEW_DB_FILE)}")
|
|
26 Files.delete(newPath)
|
|
27 }
|
|
28 val newDb = Database.open(fileName = NEW_DB_FILE, passwordPrompt = "New database key: ", create = true)
|
|
29
|
|
30 // Copy old to new
|
|
31 println("WARNING: do not interrupt this process or data may be lost!")
|
|
32 copyRecords(oldDb, newDb)
|
|
33
|
|
34 // Wrap up
|
|
35 oldDb.connection.close()
|
|
36 newDb.connection.close()
|
|
37 Files.move(newPath, oldPath, StandardCopyOption.REPLACE_EXISTING)
|
|
38 println("Database key changed.")
|
|
39 }
|
|
40
|
|
41 private fun copyRecords(oldDb: Database, newDb: Database) {
|
|
42 oldDb.connection.prepareStatement("select name, username, password, notes, created, modified, accessed from passwords").use { old ->
|
|
43 val results = old.executeQuery()
|
|
44 while (results.next()) {
|
|
45 newDb.connection.prepareStatement("insert into passwords (id, name, username, password, notes, created, modified, accessed) values (?, ?, ?, ?, ?, ?, ?, ?)").use { new ->
|
|
46 // id and name
|
|
47 val name = results.getDecryptedString(1, oldDb.encryption)!!
|
|
48 new.setLong(1, newDb.makeKey(name))
|
|
49 new.setEncryptedString(2, name, newDb.encryption)
|
|
50 // username
|
|
51 new.setEncryptedString(3,
|
|
52 results.getDecryptedString(2, oldDb.encryption)!!, newDb.encryption)
|
|
53 // password
|
|
54 val password = results.getDecrypted(3, oldDb.encryption)!!
|
|
55 new.setEncrypted(4, password, newDb.encryption)
|
|
56 password.clear()
|
|
57 // notes
|
|
58 new.setEncryptedString(5,
|
|
59 results.getDecryptedString(4, oldDb.encryption), newDb.encryption)
|
|
60 // created, modified, accessed
|
|
61 new.setDateOrNull(6, results.getLong(5))
|
|
62 new.setDateOrNull(7, results.getLong(6))
|
|
63 new.setDateOrNull(8, results.getLong(7))
|
|
64 new.executeUpdate()
|
|
65 }
|
|
66 }
|
|
67 }
|
|
68 }
|
|
69 } |