{"thread":{"id":"53292","subject":"[PATCH] ssh: add 'ssh.keyfile' option","startedAt":"2020-04-23T06:47:16Z","lastAt":"2020-04-25T09:43:42Z","messageCount":9,"participants":["Raymond E. Pasco","Johannes Sixt","Matthias Aßhauer","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"395981","messageId":"20200423064110.77258-1-ray@ameretat.dev","threadId":"53292","inReplyTo":null,"subject":"[PATCH] ssh: add 'ssh.keyfile' option","fromName":"Raymond E. Pasco","fromEmail":"ray@ameretat.dev","sentAt":"2020-04-23T06:41:10Z","receivedAt":"2020-04-23T06:47:16Z","isPatch":true,"sender":{"key":"ray@ameretat.dev","avatar":"https://avatars.githubusercontent.com/u/115765?v=4"},"body":"When a specific private key needs to be used with a repository, manually\nspecifying it via 'core.sshCommand' is not ideal. This option allows a\nkeyfile to be specified in the local configuration. If a keyfile is\nspecified, SSH agents are disabled for the command.\n\nSigned-off-by: Raymond E. Pasco <ray@ameretat.dev>\n---\nI've encountered the need to specify a specific SSH key to be used with\na repository, and overriding the whole ssh command isn't great. I have\nonly tested this with OpenSSH.\n\n connect.c | 32 ++++++++++++++++++++++++++++----\n 1 file changed, 28 insertions(+), 4 deletions(-)\n\ndiff --git a/connect.c b/connect.c\nindex 23013c6344..dc7c75ead3 100644\n--- a/connect.c\n+++ b/connect.c\n@@ -1104,8 +1104,9 @@ static struct child_process *git_connect_git(int fd[2], char *hostandport,\n  * `args` for running ssh in Git's SSH-tunneled transport.\n  */\n static void push_ssh_options(struct argv_array *args, struct argv_array *env,\n-\t\t\t     enum ssh_variant variant, const char *port,\n-\t\t\t     enum protocol_version version, int flags)\n+\t\t\t     enum ssh_variant variant, const char *keyfile,\n+\t\t\t     const char *port, enum protocol_version version,\n+\t\t\t     int flags)\n {\n \tif (variant == VARIANT_SSH &&\n \t    version > 0) {\n@@ -1144,6 +1145,26 @@ static void push_ssh_options(struct argv_array *args, struct argv_array *env,\n \tif (variant == VARIANT_TORTOISEPLINK)\n \t\targv_array_push(args, \"-batch\");\n \n+\tif (keyfile) {\n+\t\tswitch (variant) {\n+\t\tcase VARIANT_AUTO:\n+\t\t\tBUG(\"VARIANT_AUTO passed to push_ssh_options\");\n+\t\tcase VARIANT_SIMPLE:\n+\t\t\tdie(_(\"ssh variant 'simple' does not support setting keyfiles\"));\n+\t\tcase VARIANT_SSH:\n+\t\t\targv_array_push(args, \"-a\");\n+\t\t\targv_array_push(args, \"-i\");\n+\t\t\targv_array_push(args, keyfile);\n+\t\t\tbreak;\n+\t\tcase VARIANT_PLINK:\n+\t\tcase VARIANT_PUTTY:\n+\t\tcase VARIANT_TORTOISEPLINK:\n+\t\t\targv_array_push(args, \"-noagent\");\n+\t\t\targv_array_push(args, \"-i\");\n+\t\t\targv_array_push(args, keyfile);\n+\t\t}\n+\t}\n+\n \tif (port) {\n \t\tswitch (variant) {\n \t\tcase VARIANT_AUTO:\n@@ -1169,6 +1190,7 @@ static void fill_ssh_args(struct child_process *conn, const char *ssh_host,\n \t\t\t  int flags)\n {\n \tconst char *ssh;\n+\tconst char *keyfile;\n \tenum ssh_variant variant;\n \n \tif (looks_like_command_line_option(ssh_host))\n@@ -1200,14 +1222,16 @@ static void fill_ssh_args(struct child_process *conn, const char *ssh_host,\n \t\targv_array_push(&detect.args, ssh);\n \t\targv_array_push(&detect.args, \"-G\");\n \t\tpush_ssh_options(&detect.args, &detect.env_array,\n-\t\t\t\t VARIANT_SSH, port, version, flags);\n+\t\t\t\t VARIANT_SSH, keyfile, port, version, flags);\n \t\targv_array_push(&detect.args, ssh_host);\n \n \t\tvariant = run_command(&detect) ? VARIANT_SIMPLE : VARIANT_SSH;\n \t}\n \n+\tgit_config_get_string_const(\"ssh.keyfile\", &keyfile);\n+\n \targv_array_push(&conn->args, ssh);\n-\tpush_ssh_options(&conn->args, &conn->env_array, variant, port, version, flags);\n+\tpush_ssh_options(&conn->args, &conn->env_array, variant, keyfile, port, version, flags);\n \targv_array_push(&conn->args, ssh_host);\n }\n \n-- \n2.26.1\n\n"},{"id":"395998","messageId":"20200423112110.45405-1-ray@ameretat.dev","threadId":"53292","inReplyTo":"20200423064110.77258-1-ray@ameretat.dev","subject":"[PATCH v2] ssh: add 'ssh.keyfile' option","fromName":"Raymond E. Pasco","fromEmail":"ray@ameretat.dev","sentAt":"2020-04-23T11:21:10Z","receivedAt":"2020-04-23T11:28:07Z","isPatch":true,"sender":{"key":"ray@ameretat.dev","avatar":"https://avatars.githubusercontent.com/u/115765?v=4"},"body":"When a specific private key needs to be used with a repository, manually\nspecifying it via 'core.sshCommand' is not ideal. This option allows a\nkeyfile to be specified in the local configuration. If a keyfile is\nspecified, SSH agents are disabled for the command.\n\nSigned-off-by: Raymond E. Pasco <ray@ameretat.dev>\n---\nRetract the previous submission - these are the correct options to pass\nto bypass the ssh agent. It had worked for me before, but I had killed\nthe agent earlier and forgotten about it...\n\n connect.c | 33 +++++++++++++++++++++++++++++----\n 1 file changed, 29 insertions(+), 4 deletions(-)\n\ndiff --git a/connect.c b/connect.c\nindex 23013c6344..7759248194 100644\n--- a/connect.c\n+++ b/connect.c\n@@ -1104,8 +1104,9 @@ static struct child_process *git_connect_git(int fd[2], char *hostandport,\n  * `args` for running ssh in Git's SSH-tunneled transport.\n  */\n static void push_ssh_options(struct argv_array *args, struct argv_array *env,\n-\t\t\t     enum ssh_variant variant, const char *port,\n-\t\t\t     enum protocol_version version, int flags)\n+\t\t\t     enum ssh_variant variant, const char *keyfile,\n+\t\t\t     const char *port, enum protocol_version version,\n+\t\t\t     int flags)\n {\n \tif (variant == VARIANT_SSH &&\n \t    version > 0) {\n@@ -1144,6 +1145,27 @@ static void push_ssh_options(struct argv_array *args, struct argv_array *env,\n \tif (variant == VARIANT_TORTOISEPLINK)\n \t\targv_array_push(args, \"-batch\");\n \n+\tif (keyfile) {\n+\t\tswitch (variant) {\n+\t\tcase VARIANT_AUTO:\n+\t\t\tBUG(\"VARIANT_AUTO passed to push_ssh_options\");\n+\t\tcase VARIANT_SIMPLE:\n+\t\t\tdie(_(\"ssh variant 'simple' does not support setting keyfiles\"));\n+\t\tcase VARIANT_SSH:\n+\t\t\targv_array_push(args, \"-o\");\n+\t\t\targv_array_push(args, \"IdentitiesOnly=yes\");\n+\t\t\targv_array_push(args, \"-i\");\n+\t\t\targv_array_push(args, keyfile);\n+\t\t\tbreak;\n+\t\tcase VARIANT_PLINK:\n+\t\tcase VARIANT_PUTTY:\n+\t\tcase VARIANT_TORTOISEPLINK:\n+\t\t\targv_array_push(args, \"-noagent\");\n+\t\t\targv_array_push(args, \"-i\");\n+\t\t\targv_array_push(args, keyfile);\n+\t\t}\n+\t}\n+\n \tif (port) {\n \t\tswitch (variant) {\n \t\tcase VARIANT_AUTO:\n@@ -1169,6 +1191,7 @@ static void fill_ssh_args(struct child_process *conn, const char *ssh_host,\n \t\t\t  int flags)\n {\n \tconst char *ssh;\n+\tconst char *keyfile;\n \tenum ssh_variant variant;\n \n \tif (looks_like_command_line_option(ssh_host))\n@@ -1200,14 +1223,16 @@ static void fill_ssh_args(struct child_process *conn, const char *ssh_host,\n \t\targv_array_push(&detect.args, ssh);\n \t\targv_array_push(&detect.args, \"-G\");\n \t\tpush_ssh_options(&detect.args, &detect.env_array,\n-\t\t\t\t VARIANT_SSH, port, version, flags);\n+\t\t\t\t VARIANT_SSH, keyfile, port, version, flags);\n \t\targv_array_push(&detect.args, ssh_host);\n \n \t\tvariant = run_command(&detect) ? VARIANT_SIMPLE : VARIANT_SSH;\n \t}\n \n+\tgit_config_get_string_const(\"ssh.keyfile\", &keyfile);\n+\n \targv_array_push(&conn->args, ssh);\n-\tpush_ssh_options(&conn->args, &conn->env_array, variant, port, version, flags);\n+\tpush_ssh_options(&conn->args, &conn->env_array, variant, keyfile, port, version, flags);\n \targv_array_push(&conn->args, ssh_host);\n }\n \n-- \n2.26.1\n\n"},{"id":"396017","messageId":"d26f8556-ed9b-5145-735b-d348449bb31d@kdbg.org","threadId":"53292","inReplyTo":"20200423112110.45405-1-ray@ameretat.dev","subject":"Re: [PATCH v2] ssh: add 'ssh.keyfile' option","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2020-04-23T17:24:09Z","receivedAt":"2020-04-23T17:24:14Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 23.04.20 um 13:21 schrieb Raymond E. Pasco:\n> When a specific private key needs to be used with a repository, manually\n> specifying it via 'core.sshCommand' is not ideal. This option allows a\n> keyfile to be specified in the local configuration. If a keyfile is\n> specified, SSH agents are disabled for the command.\n\nYou can do this without modifying Git. Say, your key file is\n~/.ssh/id_other_ed25519, then do this:\n\nRename your remote to use an invented host name:\n\n  git remote set-url origin git@other.github.com:other/repo\n\nThen attach the invented name to the real host name and the identity in\nyour ~/.ssh/config:\n\n  Host other.github.com\n    Hostname github.com\n    Identity ~/.ssh/id_other_ed25519\n\n-- Hannes\n"},{"id":"396018","messageId":"AM0PR04MB47715A57B110E14D6631EACDA5D30@AM0PR04MB4771.eurprd04.prod.outlook.com","threadId":"53292","inReplyTo":"20200423112110.45405-1-ray@ameretat.dev","subject":"Re: [PATCH v2] ssh: add 'ssh.keyfile' option","fromName":"Matthias Aßhauer","fromEmail":"mha1993@live.de","sentAt":"2020-04-23T18:03:26Z","receivedAt":"2020-04-23T18:03:32Z","isPatch":true,"sender":{"key":"mha1993@live.de","avatar":"https://avatars.githubusercontent.com/u/6178234?v=4"},"body":">+\t\tswitch (variant) {\n>+\t\tcase VARIANT_AUTO:\n>+\t\t\tBUG(\"VARIANT_AUTO passed to push_ssh_options\");\n\nWhy do we keep replicating this all over push_ssh_options? The wording\nvery much sounds like it's a bug whenever VARIANT_AUTO gets passed to\npush_ssh_options, no exceptions. In that case we should probably just\ncheck for it once at the beginning of push_ssh_options instead of after\nalmost every single if. If there are valid cases where VARIANT_AUTO gets\npassed to push_ssh_options we should probably clarify the wording as to\nwhat parameter combinations are and aren't valid with VARIANT_AUTO.\n\nI've included the Sign-Offs and Acks of the commits that introduced the\nprevious copies of this.[1][2] The previous discussion[3] on the mailing\nlist does not seem to mention the duplication.\n\n[1] a3f5b66f: \"ssh: 'simple' variant does not support -4/-6\" 2017-11-20\n[2] 3fa5e0d0: \"ssh: 'simple' variant does not support --port\" 2017-11-20\n[3] https://lore.kernel.org/git/20170913215448.84674-1-bmwill@google.com/T/#u\n\nBest regards\n\nMatthias Aßhauer\n\n"},{"id":"396025","messageId":"xmqqimhqgfrd.fsf@gitster.c.googlers.com","threadId":"53292","inReplyTo":"d26f8556-ed9b-5145-735b-d348449bb31d@kdbg.org","subject":"Re: [PATCH v2] ssh: add 'ssh.keyfile' option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-04-23T19:32:06Z","receivedAt":"2020-04-23T19:32:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Sixt <j6t@kdbg.org> writes:\n\n> Am 23.04.20 um 13:21 schrieb Raymond E. Pasco:\n>> When a specific private key needs to be used with a repository, manually\n>> specifying it via 'core.sshCommand' is not ideal. This option allows a\n>> keyfile to be specified in the local configuration. If a keyfile is\n>> specified, SSH agents are disabled for the command.\n>\n> You can do this without modifying Git. Say, your key file is\n> ~/.ssh/id_other_ed25519, then do this:\n>\n> Rename your remote to use an invented host name:\n>\n>   git remote set-url origin git@other.github.com:other/repo\n>\n> Then attach the invented name to the real host name and the identity in\n> your ~/.ssh/config:\n>\n>   Host other.github.com\n>     Hostname github.com\n>     Identity ~/.ssh/id_other_ed25519\n\nNice.  I wonder if this answer (and answers to other \"how would I\nuse .ssh/config to adjust Git to suite my use?\" questions people may\noften ask) can be put in some of our documentation.\n"},{"id":"396026","messageId":"xmqqeesegfgy.fsf@gitster.c.googlers.com","threadId":"53292","inReplyTo":"AM0PR04MB47715A57B110E14D6631EACDA5D30@AM0PR04MB4771.eurprd04.prod.outlook.com","subject":"Re: [PATCH v2] ssh: add 'ssh.keyfile' option","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-04-23T19:38:21Z","receivedAt":"2020-04-23T19:38:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matthias Aßhauer <mha1993@live.de> writes:\n\n>>+\t\tswitch (variant) {\n>>+\t\tcase VARIANT_AUTO:\n>>+\t\t\tBUG(\"VARIANT_AUTO passed to push_ssh_options\");\n>\n> Why do we keep replicating this all over push_ssh_options? The wording\n> very much sounds like it's a bug whenever VARIANT_AUTO gets passed to\n> push_ssh_options, no exceptions. In that case ...\n\nMy reading of the code tells me that it is *not* the case.  When the\ncaller asks to connect only over IPv4 with CONNECT_IPV4 bit set in\nthe flags, we cannot translate that to an option to underlying SSH\nimplementation without knowing the variant.  As long as the caller\ndoes not specify IPV4/IPV6 or custom port, I think it is OK for the\ncaller to leave the variant AUTO.\n\nSo you probably want a patch along the lines of...\n\n connect.c | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/connect.c b/connect.c\nindex b6451ab5e8..b02cf74c9a 100644\n--- a/connect.c\n+++ b/connect.c\n@@ -1118,7 +1118,7 @@ static void push_ssh_options(struct argv_array *args, struct argv_array *env,\n \tif (flags & CONNECT_IPV4) {\n \t\tswitch (variant) {\n \t\tcase VARIANT_AUTO:\n-\t\t\tBUG(\"VARIANT_AUTO passed to push_ssh_options\");\n+\t\t\tBUG(\"VARIANT_AUTO and CONNECT_IPV4 used together\");\n \t\tcase VARIANT_SIMPLE:\n \t\t\tdie(_(\"ssh variant 'simple' does not support -4\"));\n \t\tcase VARIANT_SSH:\n"},{"id":"396092","messageId":"C2947F3O0OB7.2XJGV8LYVERWN@nietzsche.my.domain","threadId":"53292","inReplyTo":"d26f8556-ed9b-5145-735b-d348449bb31d@kdbg.org","subject":"Re: [PATCH v2] ssh: add 'ssh.keyfile' option","fromName":"Raymond E. Pasco","fromEmail":"ray@ameretat.dev","sentAt":"2020-04-24T03:24:28Z","receivedAt":"2020-04-24T03:24:34Z","isPatch":true,"sender":{"key":"ray@ameretat.dev","avatar":"https://avatars.githubusercontent.com/u/115765?v=4"},"body":"On Thu Apr 23, 2020 at 7:24 PM, Johannes Sixt wrote:\n> Then attach the invented name to the real host name and the identity in\n> your ~/.ssh/config:\n>\n> \n> Host other.github.com\n> Hostname github.com\n> Identity ~/.ssh/id_other_ed25519\n\nThis works for my purposes. The exact block I needed:\n\nHost fake.host\n  Hostname real.host\n  IdentityFile ~/.ssh/alt_ed25519\n  IdentitiesOnly yes\n"},{"id":"396104","messageId":"AM0PR04MB4771FB8BCD1EEB7E60EF54C7A5D00@AM0PR04MB4771.eurprd04.prod.outlook.com","threadId":"53292","inReplyTo":"xmqqeesegfgy.fsf@gitster.c.googlers.com","subject":"Re: [PATCH v2] ssh: add 'ssh.keyfile' option","fromName":"Matthias Aßhauer","fromEmail":"mha1993@live.de","sentAt":"2020-04-24T04:33:10Z","receivedAt":"2020-04-24T04:33:15Z","isPatch":true,"sender":{"key":"mha1993@live.de","avatar":"https://avatars.githubusercontent.com/u/6178234?v=4"},"body":"Am 23.04.2020 um 21:38 schrieb Junio C Hamano:\n\n> My reading of the code tells me that it is *not* the case.  When the\n> caller asks to connect only over IPv4 with CONNECT_IPV4 bit set in\n> the flags, we cannot translate that to an option to underlying SSH\n> implementation without knowing the variant.  As long as the caller\n> does not specify IPV4/IPV6 or custom port, I think it is OK for the\n> caller to leave the variant AUTO.\n>\n> So you probably want a patch along the lines of...\n>\n>   connect.c | 2 +-\n>   1 file changed, 1 insertion(+), 1 deletion(-)\n>\n> diff --git a/connect.c b/connect.c\n> index b6451ab5e8..b02cf74c9a 100644\n> --- a/connect.c\n> +++ b/connect.c\n> @@ -1118,7 +1118,7 @@ static void push_ssh_options(struct argv_array *args, struct argv_array *env,\n>   \tif (flags & CONNECT_IPV4) {\n>   \t\tswitch (variant) {\n>   \t\tcase VARIANT_AUTO:\n> -\t\t\tBUG(\"VARIANT_AUTO passed to push_ssh_options\");\n> +\t\t\tBUG(\"VARIANT_AUTO and CONNECT_IPV4 used together\");\n>   \t\tcase VARIANT_SIMPLE:\n>   \t\t\tdie(_(\"ssh variant 'simple' does not support -4\"));\n>   \t\tcase VARIANT_SSH:\n\nYes, that looks about right. I'll extend the patch to also cover CONNECT_IPV6 and a custom port,\ngive it a run through the test suite and send it back with a commit message. Thanks for taking a look\nat the legitimate cases where VARIANT_AUTO gets passed to push_ssh_options.\n\n"},{"id":"396239","messageId":"AM0PR04MB4771946E0134D9D875AB1A8AA5D10@AM0PR04MB4771.eurprd04.prod.outlook.com","threadId":"53292","inReplyTo":"AM0PR04MB4771FB8BCD1EEB7E60EF54C7A5D00@AM0PR04MB4771.eurprd04.prod.outlook.com","subject":"[PATCH] connect.c: clarify BUG() messages in push_ssh_options","fromName":"Matthias Aßhauer","fromEmail":"mha1993@live.de","sentAt":"2020-04-25T09:43:29Z","receivedAt":"2020-04-25T09:43:42Z","isPatch":true,"sender":{"key":"mha1993@live.de","avatar":"https://avatars.githubusercontent.com/u/6178234?v=4"},"body":"The current BUG() messages in push_ssh_options imply that calling push_ssh_options and passing VARIANT_AUTO is always a bug\nand we should check for it once at the top of push_ssh_options instead of multiple times in various if statements. That is\nnot actually the case. When the caller passes CONNECT_IPV4, CONNECT_IPV6 or a custom port alongside VARIANT_AUTO we cannot\ntranslate that to an option to the underlying SSH implementation without knowing the variant. As long as the caller does\nnot specify IPV4/IPV6 or a custom port, it is ok for the caller to leave the variant AUTO. Let's explicitly state that the\nbug is in the combination of parameters.\n\nSigned-off-by: Matthias Aßhauer <mha1993@live.de>\n---\n  connect.c | 6 +++---\n  1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/connect.c b/connect.c\nindex 23013c6344..c15e60b13a 100644\n--- a/connect.c\n+++ b/connect.c\n@@ -1118,7 +1118,7 @@ static void push_ssh_options(struct argv_array *args, struct argv_array *env,\n  \tif (flags & CONNECT_IPV4) {\n  \t\tswitch (variant) {\n  \t\tcase VARIANT_AUTO:\n-\t\t\tBUG(\"VARIANT_AUTO passed to push_ssh_options\");\n+\t\t\tBUG(\"VARIANT_AUTO and CONNECT_IPV4 passed to push_ssh_options\");\n  \t\tcase VARIANT_SIMPLE:\n  \t\t\tdie(_(\"ssh variant 'simple' does not support -4\"));\n  \t\tcase VARIANT_SSH:\n@@ -1130,7 +1130,7 @@ static void push_ssh_options(struct argv_array *args, struct argv_array *env,\n  \t} else if (flags & CONNECT_IPV6) {\n  \t\tswitch (variant) {\n  \t\tcase VARIANT_AUTO:\n-\t\t\tBUG(\"VARIANT_AUTO passed to push_ssh_options\");\n+\t\t\tBUG(\"VARIANT_AUTO and CONNECT_IPV6 passed to push_ssh_options\");\n  \t\tcase VARIANT_SIMPLE:\n  \t\t\tdie(_(\"ssh variant 'simple' does not support -6\"));\n  \t\tcase VARIANT_SSH:\n@@ -1147,7 +1147,7 @@ static void push_ssh_options(struct argv_array *args, struct argv_array *env,\n  \tif (port) {\n  \t\tswitch (variant) {\n  \t\tcase VARIANT_AUTO:\n-\t\t\tBUG(\"VARIANT_AUTO passed to push_ssh_options\");\n+\t\t\tBUG(\"VARIANT_AUTO and a custom port passed to push_ssh_options\");\n  \t\tcase VARIANT_SIMPLE:\n  \t\t\tdie(_(\"ssh variant 'simple' does not support setting port\"));\n  \t\tcase VARIANT_SSH:\n-- \n2.17.1\n\n\n"}]}