# # # patch "cmd_netsync.cc" # from [1c9f724505164da0026f77e4e81010fddc81faad] # to [424c270866fc33f5067b2399f5f77920b9bce99c] # # patch "key_store.cc" # from [510eb02eab491fd9e79c49fcfcf5e6efa145872f] # to [5c423e17442795e5cd6ca41ddc2c041e5ac5e553] # # patch "key_store.hh" # from [a2cba22c7534941db07838f8f7b9e3abede66cce] # to [86b0cfb3002761e38f91aa1b2b696d604a6bc674] # # patch "options_list.hh" # from [78fbe7c5728513ee672b75d6dcefbc2f508ba915] # to [5ea48e4362ae53c3cf69b6422f98eb5a33e92086] # ============================================================ --- cmd_netsync.cc 1c9f724505164da0026f77e4e81010fddc81faad +++ cmd_netsync.cc 424c270866fc33f5067b2399f5f77920b9bce99c @@ -262,18 +262,43 @@ CMD_AUTOMATE(pull, N_("[ADDRESS[:PORTNUM CMD_AUTOMATE(pull, N_("[ADDRESS[:PORTNUMBER] [PATTERN ...]]"), N_("Pulls branches from a netsync server"), "", - options::opts::set_default | options::opts::exclude) + options::opts::set_default | options::opts::exclude | + options::opts::do_not_enforce_ssh_agent +) { database db(app); key_store keys(app); project_t project(db); + if (!app.opts.do_not_enforce_ssh_agent) + { + // enforce that any command which needs to encrypt a private key later on + // uses the ssh_agent to do the task, because we cannot handle password + // prompts over stdio. basically this is the same as giving --ssh-sign=only + // as option to stdio, but it is more explicit. however, this also leaves + // the opportunity of giving a possible passphrase via the get_passphrase + // lua hook, because the ssh agent is _always_ used, but its a reasonable + // trade-off + keys.enforce_ssh_agent(); + } + netsync_connection_info info; extract_client_connection_info(app.opts, app.lua, db, keys, args, info, false); if (app.opts.signing_key() == "") - P(F("doing anonymous pull; use -kKEYNAME if you need authentication")); + { + P(F("doing anonymous pull; use -kKEYNAME if you need authentication")); + } + else + { + if (!app.opts.do_not_enforce_ssh_agent) + { + N(keys.agent_knows_key(app.opts.signing_key), + F("key '%s' is unknown to the running ssh-agent instance") + % app.opts.signing_key); + } + } run_netsync_protocol(app.opts, app.lua, project, keys, client_voice, sink_role, info); ============================================================ --- key_store.cc 510eb02eab491fd9e79c49fcfcf5e6efa145872f +++ key_store.cc 5c423e17442795e5cd6ca41ddc2c041e5ac5e553 @@ -710,7 +710,31 @@ key_store::export_key_for_agent(rsa_keyp p.end_msg(); } +void +key_store::enforce_ssh_agent() +{ + ssh_agent & agent = s->get_agent(); + N(agent.connected(), + F("this command enforces the only usage of ssh_agent, " + "but no ssh-agent is available.")); + if (s->ssh_sign_mode != "only") + { + W(F("enforcing the only usage of ssh_agent")); + const_cast(s->ssh_sign_mode) = "only"; + } +} +bool +key_store::agent_knows_key(rsa_keypair_id const & ident) +{ + keypair keyp; + N(maybe_get_key_pair(ident, keyp), + F("no keypair for '%s' in keyring") % ident); + + ssh_agent & agent = s->get_agent(); + return agent.has_key(keyp); +} + // // Migration from old databases // ============================================================ --- key_store.hh a2cba22c7534941db07838f8f7b9e3abede66cce +++ key_store.hh 86b0cfb3002761e38f91aa1b2b696d604a6bc674 @@ -82,6 +82,8 @@ public: void add_key_to_agent(rsa_keypair_id const & id); void export_key_for_agent(rsa_keypair_id const & id, std::ostream & os); + void enforce_ssh_agent(); + bool agent_knows_key(rsa_keypair_id const & ident); // Migration from old databases ============================================================ --- options_list.hh 78fbe7c5728513ee672b75d6dcefbc2f508ba915 +++ options_list.hh 5ea48e4362ae53c3cf69b6422f98eb5a33e92086 @@ -80,6 +80,17 @@ OPT(automate_stdio_size, "automate-stdio } #endif +OPT(do_not_enforce_ssh_agent, "do-not-enforce-ssh-agent", bool, false, + gettext_noop("do not enforce the usage of ssh-agent. enabling this is " + "highly discouraged if you run this command over stdio " + "as it may prompt for a key password which cannot be " + "handled.")) +#ifdef option_bodies +{ + do_not_enforce_ssh_agent = true; +} +#endif + OPTSET(bind_opts) OPTVAR(bind_opts, std::list, bind_uris, ) OPTVAR(bind_opts, bool, bind_stdio, false)