# # # patch "keys.cc" # from [8841bda1e0f18e79de1b45e2c5aece68b22dc765] # to [a3bbb2452143e5ac9579f6b9dc96ad37702f7d3f] # # patch "monotone.texi" # from [a746cac00da9abdd8770c89c2b92461d60d848d4] # to [83eb9aad5ee3e0deb6be40ff81c1cfdd3cb748d0] # ============================================================ --- keys.cc 8841bda1e0f18e79de1b45e2c5aece68b22dc765 +++ keys.cc a3bbb2452143e5ac9579f6b9dc96ad37702f7d3f @@ -365,16 +365,25 @@ make_signature(app_state & app, string const & tosign, base64 & signature) { - E(!app.opts.ssh_sign.empty(), F("--ssh-sign requires a value ['yes', 'no', or 'check']")); - E(app.opts.ssh_sign == "yes" || app.opts.ssh_sign == "no" || app.opts.ssh_sign == "check", - F("--ssh-sign must be set to 'yes', 'no', or 'check'")); + E(!app.opts.ssh_sign.empty(), + F("--ssh-sign requires a value ['yes', 'no', 'only', or 'check']")); + E(app.opts.ssh_sign == "yes" + || app.opts.ssh_sign == "no" + || app.opts.ssh_sign == "check" + || app.opts.ssh_sign == "only", + F("--ssh-sign must be set to 'yes', 'no', 'only', or 'check'")); keypair key; app.keys.get_key_pair(id, key); string sig_string; //sign with ssh-agent (if connected) - if (app.opts.ssh_sign == "yes" || app.opts.ssh_sign == "check") + N(app.agent.connected() || app.opts.ssh_sign != "only", + F("You have chosen to sign only with ssh-agent but ssh-agent" + " does not seem to be running.")); + if (app.opts.ssh_sign == "yes" + || app.opts.ssh_sign == "check" + || app.opts.ssh_sign == "only") { vector ssh_keys = app.agent.get_keys(); if (ssh_keys.size() <= 0) @@ -385,7 +394,8 @@ make_signature(app_state & app, rsa_pub_key pub; decode_base64(key.pub, pub); SecureVector pub_block; - pub_block.set(reinterpret_cast(pub().data()), pub().size()); + pub_block.set(reinterpret_cast(pub().data()), + pub().size()); L(FL("make_signature: building %d-byte pub key") % pub_block.size()); shared_ptr x509_key = shared_ptr(Botan::X509::load_key(pub_block)); @@ -399,49 +409,59 @@ make_signature(app_state & app, si = ssh_keys.begin(); si != ssh_keys.end(); ++si) { if ((*pub_key).get_e() == (*si).get_e() && (*pub_key).get_n() == (*si).get_n()) { - L(FL("make_signature: ssh key matches monotone key, signing with ssh-agent")); + L(FL("make_signature: ssh key matches monotone key, signing with" + " ssh-agent")); app.agent.sign_data(*si, tosign, sig_string); break; } } } if (sig_string.length() <= 0) - L(FL("make_signature: monotone and ssh-agent keys do not match, will use monotone signing")); + L(FL("make_signature: monotone and ssh-agent keys do not match, will" + " use monotone signing")); } string ssh_sig = sig_string; - if (ssh_sig.length() <= 0 || app.opts.ssh_sign == "check") { // || app.opts.ssh_sign == "no" - SecureVector sig; - // we permit the user to relax security here, by caching a decrypted key - // (if they permit it) through the life of a program run. this helps when - // you're making a half-dozen certs during a commit or merge or - // something. + N(ssh_sig.length() > 0 || app.opts.ssh_sign != "only", + F("You don't seem to have your monotone key imported ")); - bool persist_phrase = (!app.signers.empty()) || app.lua.hook_persist_phrase_ok(); + if (ssh_sig.length() <= 0 + || app.opts.ssh_sign == "check" + || app.opts.ssh_sign == "no") + { + SecureVector sig; - shared_ptr signer; - shared_ptr priv_key; - if (persist_phrase && app.signers.find(id) != app.signers.end()) - signer = app.signers[id].first; + // we permit the user to relax security here, by caching a decrypted key + // (if they permit it) through the life of a program run. this helps when + // you're making a half-dozen certs during a commit or merge or + // something. - else - { - priv_key = get_private_key(app.lua, id, priv); - signer = shared_ptr(get_pk_signer(*priv_key, "EMSA3(SHA-1)")); + bool persist_phrase = (!app.signers.empty()) + || app.lua.hook_persist_phrase_ok(); - /* XXX This is ugly. We need to keep the key around as long - * as the signer is around, but the shared_ptr for the key will go - * away after we leave this scope. Hence we store a pair of - * so they both exist. */ - if (persist_phrase) - app.signers.insert(make_pair(id,make_pair(signer,priv_key))); - } + shared_ptr signer; + shared_ptr priv_key; + if (persist_phrase && app.signers.find(id) != app.signers.end()) + signer = app.signers[id].first; - sig = signer->sign_message(reinterpret_cast(tosign.data()), tosign.size()); - sig_string = string(reinterpret_cast(sig.begin()), sig.size()); - } + else + { + priv_key = get_private_key(app.lua, id, priv); + signer = shared_ptr(get_pk_signer(*priv_key, "EMSA3(SHA-1)")); + /* XXX This is ugly. We need to keep the key around as long + * as the signer is around, but the shared_ptr for the key will go + * away after we leave this scope. Hence we store a pair of + * so they both exist. */ + if (persist_phrase) + app.signers.insert(make_pair(id,make_pair(signer,priv_key))); + } + + sig = signer->sign_message(reinterpret_cast(tosign.data()), tosign.size()); + sig_string = string(reinterpret_cast(sig.begin()), sig.size()); + } + if (app.opts.ssh_sign == "check" && ssh_sig.length() > 0) { E(ssh_sig == sig_string, @@ -452,13 +472,15 @@ make_signature(app_state & app, % sig_string.length() % encode_hexenc(ssh_sig) % encode_hexenc(sig_string)); - L(FL("make_signature: signatures from ssh-agent and monotone are the same")); + L(FL("make_signature: signatures from ssh-agent and monotone" + " are the same")); } L(FL("make_signature: produced %d-byte signature") % sig_string.size()); encode_base64(rsa_sha1_signature(sig_string), signature); - E(check_signature(app, id, key.pub, tosign, signature), F("make_signature: signature is not valid")); + E(check_signature(app, id, key.pub, tosign, signature), + F("make_signature: signature is not valid")); } bool ============================================================ --- monotone.texi a746cac00da9abdd8770c89c2b92461d60d848d4 +++ monotone.texi 83eb9aad5ee3e0deb6be40ff81c1cfdd3cb748d0 @@ -1264,7 +1264,12 @@ @section Generating Keys @code{jim@@juicebot.co.jp}, so it indicates that Jim's key-pair has been successfully generated and stored. On subsequent commands, Jim will need to re-enter his passphrase in order to perform security-sensitive -tasks. Jim isn't very worried about security (and, more importantly, it +tasks. + +TODO: add ssh-agent explanation + +DEPRECATED!! +Jim isn't very worried about security (and, more importantly, it simplifies the tutorial text to skip the passphrase prompts) so he decides to store his passphrase in his @file{monotonerc} file. He does this by writing a @emph{hook function} which returns the passphrase: @@ -5012,12 +5017,13 @@ @section Key and Cert Trust You can also use the @option{--ssh-sign} option to control whether ssh-agent will be used for signing. If set to @emph{yes}, ssh-agent will be used to sign. If your key has not been added to ssh-agent monotone will fall back to its internal signing -code and ask you for your password. If set to @emph{no}, monotone will always use -its internal signing code even if ssh-agent is running and has your monotone key -loaded. If set to @emph{check}, monotone will sign with both ssh-agent (if your key -is loaded into it) and monotone's internal signing code, then compare the results. address@hidden will be removed at some future time as it is meant only for testing -and will not work with all signing algorithms. +code and ask you for your password. If set to @emph{only}, monotone will sign only +with ssh-agent. If set to @emph{no}, monotone will always use its internal signing +code even if ssh-agent is running and has your monotone key loaded. If set to address@hidden, monotone will sign with both ssh-agent (if your key is loaded into +it) and monotone's internal signing code, then compare the results. @emph{check} +will be removed at some future time as it is meant only for testing and will not +work with all signing algorithms. @end ftable