diff options
Diffstat (limited to '')
| -rw-r--r-- | src/client/database.rs | 41 |
1 files changed, 0 insertions, 41 deletions
diff --git a/src/client/database.rs b/src/client/database.rs index 04a271a..c4601b5 100644 --- a/src/client/database.rs +++ b/src/client/database.rs | |||
| @@ -20,14 +20,9 @@ pub fn init_db(conn: &Connection) { | |||
| 20 | [], | 20 | [], |
| 21 | ) | 21 | ) |
| 22 | .unwrap(); | 22 | .unwrap(); |
| 23 | // Migration for databases created before TOFU trust. | ||
| 24 | let _ = conn.execute("ALTER TABLE hosts ADD COLUMN fingerprint TEXT", []); | ||
| 25 | 23 | ||
| 26 | // Credentials belong to a server identity (the certificate key), not to a | 24 | // Credentials belong to a server identity (the certificate key), not to a |
| 27 | // single address, so every address that presents the same key shares them. | 25 | // single address, so every address that presents the same key shares them. |
| 28 | if has_column(conn, "credentials", "host") { | ||
| 29 | migrate_credentials_to_fingerprints(conn); | ||
| 30 | } | ||
| 31 | conn.execute( | 26 | conn.execute( |
| 32 | "CREATE TABLE IF NOT EXISTS credentials ( | 27 | "CREATE TABLE IF NOT EXISTS credentials ( |
| 33 | fingerprint TEXT PRIMARY KEY, | 28 | fingerprint TEXT PRIMARY KEY, |
| @@ -39,42 +34,6 @@ pub fn init_db(conn: &Connection) { | |||
| 39 | .unwrap(); | 34 | .unwrap(); |
| 40 | } | 35 | } |
| 41 | 36 | ||
| 42 | fn has_column(conn: &Connection, table: &str, column: &str) -> bool { | ||
| 43 | let Ok(mut statement) = conn.prepare(&format!("PRAGMA table_info({table})")) else { | ||
| 44 | return false; | ||
| 45 | }; | ||
| 46 | let Ok(rows) = statement.query_map([], |row| row.get::<_, String>(1)) else { | ||
| 47 | return false; | ||
| 48 | }; | ||
| 49 | rows.flatten().any(|name| name == column) | ||
| 50 | } | ||
| 51 | |||
| 52 | /// Re-key host-bound credentials by the fingerprint of their host. | ||
| 53 | /// | ||
| 54 | /// Rows whose host was already forgotten have no identity to attach to and are | ||
| 55 | /// dropped; those addresses have to re-authenticate once. | ||
| 56 | fn migrate_credentials_to_fingerprints(conn: &Connection) { | ||
| 57 | let tx = conn.unchecked_transaction().unwrap(); | ||
| 58 | tx.execute_batch( | ||
| 59 | "DROP TABLE IF EXISTS credentials_by_identity; | ||
| 60 | CREATE TABLE credentials_by_identity ( | ||
| 61 | fingerprint TEXT PRIMARY KEY, | ||
| 62 | username TEXT NOT NULL, | ||
| 63 | password TEXT NOT NULL | ||
| 64 | ); | ||
| 65 | INSERT OR REPLACE INTO credentials_by_identity (fingerprint, username, password) | ||
| 66 | SELECT h.fingerprint, c.username, c.password | ||
| 67 | FROM credentials c | ||
| 68 | JOIN hosts h ON h.host = c.host | ||
| 69 | WHERE h.fingerprint IS NOT NULL | ||
| 70 | ORDER BY h.last_used ASC, h.host ASC; | ||
| 71 | DROP TABLE credentials; | ||
| 72 | ALTER TABLE credentials_by_identity RENAME TO credentials;", | ||
| 73 | ) | ||
| 74 | .unwrap(); | ||
| 75 | tx.commit().unwrap(); | ||
| 76 | } | ||
| 77 | |||
| 78 | pub fn get_last_host(conn: &Connection) -> Option<String> { | 37 | pub fn get_last_host(conn: &Connection) -> Option<String> { |
| 79 | let mut stmt = conn | 38 | let mut stmt = conn |
| 80 | .prepare("SELECT host FROM hosts ORDER BY last_used DESC LIMIT 1") | 39 | .prepare("SELECT host FROM hosts ORDER BY last_used DESC LIMIT 1") |
