Test that hsmd handles wrong passphrase gracefully without crashing. This test reproduces a bug where hsmd would crash with "HSM sent unknown message type" when a wrong passphrase was provided. The issue was that hsmd_send_init_reply_failure was using write_all() instead of wire_sync_wr
(node_factory)
| 2600 | |
| 2601 | @unittest.skipIf(VALGRIND, "It does not play well with prompt and key derivation.") |
| 2602 | def test_hsm_wrong_passphrase_crash(node_factory): |
| 2603 | """Test that hsmd handles wrong passphrase gracefully without crashing. |
| 2604 | |
| 2605 | This test reproduces a bug where hsmd would crash with "HSM sent unknown message type" |
| 2606 | when a wrong passphrase was provided. The issue was that hsmd_send_init_reply_failure |
| 2607 | was using write_all() instead of wire_sync_write(), missing the length prefix. |
| 2608 | """ |
| 2609 | l1 = node_factory.get_node(start=False, expect_fail=True) |
| 2610 | hsm_path = os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, "hsm_secret") |
| 2611 | os.remove(hsm_path) |
| 2612 | |
| 2613 | # Create hsm_secret with a passphrase |
| 2614 | passphrase = "correct_passphrase" |
| 2615 | mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" |
| 2616 | |
| 2617 | hsmtool = HsmTool(node_factory.directory, "generatehsm", hsm_path) |
| 2618 | master_fd, slave_fd = os.openpty() |
| 2619 | hsmtool.start(stdin=slave_fd) |
| 2620 | hsmtool.wait_for_log(r"Introduce your BIP39 word list") |
| 2621 | write_all(master_fd, f"{mnemonic}\n".encode("utf-8")) |
| 2622 | hsmtool.wait_for_log(r"Enter your passphrase:") |
| 2623 | write_all(master_fd, f"{passphrase}\n".encode("utf-8")) |
| 2624 | assert hsmtool.proc.wait(WAIT_TIMEOUT) == 0 |
| 2625 | os.close(master_fd) |
| 2626 | os.close(slave_fd) |
| 2627 | |
| 2628 | # Try to start with wrong passphrase |
| 2629 | l1.daemon.opts["hsm-passphrase"] = None |
| 2630 | master_fd2, slave_fd2 = os.openpty() |
| 2631 | l1.daemon.start(stdin=slave_fd2, wait_for_initialized=False, stderr_redir=True) |
| 2632 | l1.daemon.wait_for_log("Enter hsm_secret passphrase:") |
| 2633 | write_all(master_fd2, "wrong_passphrase\n".encode("utf-8")) |
| 2634 | |
| 2635 | # Should fail gracefully with proper error message, not "unknown message type" |
| 2636 | l1.daemon.wait() |
| 2637 | assert l1.daemon.is_in_stderr("Failed to load hsm_secret: Wrong passphrase") |
| 2638 | assert not l1.daemon.is_in_stderr("HSM sent unknown message type") |
| 2639 | assert not l1.daemon.is_in_stderr("send_backtrace") # No backtrace for user error |
| 2640 | |
| 2641 | os.close(master_fd2) |
| 2642 | os.close(slave_fd2) |
| 2643 | |
| 2644 | |
| 2645 | def test_unspend_during_reorg(node_factory, bitcoind): |
nothing calls this directly
no test coverage detected