security: protect local data at rest (issue #146)
All checks were successful
CI Code / Check spelling (pull_request) Successful in 15s
CI Code / Check coding style (pull_request) Successful in 26s
CI Code / Linux (debian) (pull_request) Successful in 5m3s
CI Code / Linux (arch) (pull_request) Successful in 6m25s
CI Code / Linux (ubuntu) (pull_request) Successful in 8m1s
CI Code / Code Coverage (pull_request) Successful in 9m27s
All checks were successful
CI Code / Check spelling (pull_request) Successful in 15s
CI Code / Check coding style (pull_request) Successful in 26s
CI Code / Linux (debian) (pull_request) Successful in 5m3s
CI Code / Linux (arch) (pull_request) Successful in 6m25s
CI Code / Linux (ubuntu) (pull_request) Successful in 8m1s
CI Code / Code Coverage (pull_request) Successful in 9m27s
T03 — keep secrets out of profanity.log: - new redact_secrets() helper (common.c) masks the content of SASL auth/response/challenge/success and <password> elements; applied in the libstrophe logger (_xmpp_file_logger) and the stderr-to-log bridge (REQ-DAR-03, REQ-LOG-06) - _add_to_db() no longer logs decrypted message bodies or the full INSERT statement (REQ-DAR-03) T07 — owner-only permissions on key material and history (REQ-AUTH-01): - chmod 0600 on chatlog.db after open (journal/WAL files inherit) - chmod 0600 on OTR keys.txt and fingerprints.txt after every write - parent dirs are already 0700 (create_dir); this is defense in depth T08 — integrity before trust: - PRAGMA quick_check(1) gates every chatlog.db open; on failure the DB stays closed, the user is warned once in the console and the session continues without history (REQ-RES-02) - OMEMO aesgcm downloads decrypt into a 0600 tempfile next to the target and rename it into place only after the GCM tag verifies; the open-command hook no longer runs on failed decryption (REQ-CRY-06) Tests: redact_secrets unit tests; AES-256-GCM roundtrip and tampered-tag/ciphertext unit tests (crypto.c now linked into unittests under BUILD_OMEMO); functional test planting a corrupt chatlog.db and asserting graceful degradation. Closes #146
This commit is contained in:
@@ -1384,3 +1384,55 @@ str_xml_sanitize__strips_illegal_characters(void** state)
|
||||
assert_string_equal("UTF-8: üñîçøðé and more", res5);
|
||||
g_free(res5);
|
||||
}
|
||||
|
||||
void
|
||||
redact_secrets__masks_credentials(void** state)
|
||||
{
|
||||
// NULL input
|
||||
assert_null(redact_secrets(NULL));
|
||||
|
||||
// Plain text and non-secret XML pass through unchanged
|
||||
gchar* res1 = redact_secrets("hello world");
|
||||
assert_string_equal("hello world", res1);
|
||||
g_free(res1);
|
||||
|
||||
gchar* res2 = redact_secrets("<message><body>secret-looking text</body></message>");
|
||||
assert_string_equal("<message><body>secret-looking text</body></message>", res2);
|
||||
g_free(res2);
|
||||
|
||||
// SASL auth payload is redacted, envelope kept
|
||||
gchar* res3 = redact_secrets("SENT: <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>AGFsaWNlAHBhc3N3b3Jk</auth>");
|
||||
assert_string_equal("SENT: <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>[REDACTED]</auth>", res3);
|
||||
g_free(res3);
|
||||
|
||||
// SASL challenge/response round-trip
|
||||
gchar* res4 = redact_secrets("<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cj1abc</challenge>");
|
||||
assert_string_equal("<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>[REDACTED]</challenge>", res4);
|
||||
g_free(res4);
|
||||
|
||||
gchar* res5 = redact_secrets("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>Yz1iaXdz</response>");
|
||||
assert_string_equal("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>[REDACTED]</response>", res5);
|
||||
g_free(res5);
|
||||
|
||||
// Empty SASL response element has no content to redact
|
||||
gchar* res6 = redact_secrets("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>");
|
||||
assert_string_equal("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>", res6);
|
||||
g_free(res6);
|
||||
|
||||
// XEP-0077 registration: password redacted, username kept
|
||||
gchar* res7 = redact_secrets("<query xmlns='jabber:iq:register'><username>alice</username><password>hunter2</password></query>");
|
||||
assert_string_equal("<query xmlns='jabber:iq:register'><username>alice</username><password>[REDACTED]</password></query>", res7);
|
||||
g_free(res7);
|
||||
|
||||
// XEP-0078 legacy auth: password-derived digest redacted
|
||||
gchar* res8 = redact_secrets("<query xmlns='jabber:iq:auth'><username>alice</username><digest>48fc78be9ec8f86d8ce1c39ebd7a5b4c9d0e2f13</digest><resource>tui</resource></query>");
|
||||
assert_string_equal("<query xmlns='jabber:iq:auth'><username>alice</username><digest>[REDACTED]</digest><resource>tui</resource></query>", res8);
|
||||
g_free(res8);
|
||||
|
||||
// invalid UTF-8 must not make redaction fail open
|
||||
gchar* res9 = redact_secrets("\xFF garbage <password>hunter2</password>");
|
||||
assert_non_null(res9);
|
||||
assert_null(strstr(res9, "hunter2"));
|
||||
assert_non_null(strstr(res9, "[REDACTED]"));
|
||||
g_free(res9);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user