mirror of
https://github.com/libgit2/libgit2.git
synced 2026-01-25 02:56:17 +00:00
ssh_exec: don't use sh for ssh execution
Construct the arguments for the ssh exec as an explicit array, instead of trying to create a command-line for sh. The latter may use user input (the remote path) so this may be vulnerable to command injection.
This commit is contained in:
@@ -120,7 +120,7 @@ GIT_INLINE(int) ensure_transport_state(
|
||||
}
|
||||
|
||||
static int get_ssh_cmdline(
|
||||
git_str *out,
|
||||
git_vector *args,
|
||||
ssh_exec_subtransport *transport,
|
||||
git_net_url *url,
|
||||
const char *command)
|
||||
@@ -128,7 +128,8 @@ static int get_ssh_cmdline(
|
||||
git_remote *remote = ((transport_smart *)transport->owner)->owner;
|
||||
git_repository *repo = remote->repo;
|
||||
git_config *cfg;
|
||||
git_str ssh_cmd = GIT_STR_INIT;
|
||||
git_str ssh_cmd = GIT_STR_INIT, url_and_host = GIT_STR_INIT,
|
||||
remote_cmd = GIT_STR_INIT;
|
||||
const char *default_ssh_cmd = "ssh";
|
||||
int error;
|
||||
|
||||
@@ -158,18 +159,46 @@ static int get_ssh_cmdline(
|
||||
else if ((error = git_config__get_string_buf(&ssh_cmd, cfg, "core.sshcommand")) < 0 && error != GIT_ENOTFOUND)
|
||||
goto done;
|
||||
|
||||
error = git_str_printf(out, "%s %s %s \"%s%s%s\" \"%s\" \"%s\"",
|
||||
ssh_cmd.size > 0 ? ssh_cmd.ptr : default_ssh_cmd,
|
||||
url->port_specified ? "-p" : "",
|
||||
url->port_specified ? url->port : "",
|
||||
url->username ? url->username : "",
|
||||
url->username ? "@" : "",
|
||||
url->host,
|
||||
command,
|
||||
url->path);
|
||||
git_error_clear();
|
||||
|
||||
if (!ssh_cmd.size &&
|
||||
git_str_puts(&ssh_cmd, default_ssh_cmd) < 0)
|
||||
goto done;
|
||||
|
||||
if ((error = git_vector_insert(args, git_str_detach(&ssh_cmd))) < 0)
|
||||
goto done;
|
||||
|
||||
if (url->port_specified) {
|
||||
char *p = git__strdup("-p");
|
||||
char *port = git__strdup(url->port);
|
||||
|
||||
if (!p || !port ||
|
||||
(error = git_vector_insert(args, p)) < 0 ||
|
||||
(error = git_vector_insert(args, port)) < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (url->username) {
|
||||
if ((error = git_str_puts(&url_and_host, url->username)) < 0 ||
|
||||
(error = git_str_putc(&url_and_host, '@')) < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((error = git_str_puts(&url_and_host, url->host)) < 0 ||
|
||||
(error = git_vector_insert(args, git_str_detach(&url_and_host))) < 0)
|
||||
goto done;
|
||||
|
||||
if ((error = git_str_puts(&remote_cmd, command)) < 0 ||
|
||||
(error = git_str_puts(&remote_cmd, " '")) < 0 ||
|
||||
(error = git_str_puts(&remote_cmd, url->path)) < 0 ||
|
||||
(error = git_str_puts(&remote_cmd, "'")) < 0 ||
|
||||
(error = git_vector_insert(args, git_str_detach(&remote_cmd))) < 0)
|
||||
goto done;
|
||||
|
||||
done:
|
||||
git_str_dispose(&ssh_cmd);
|
||||
git_str_dispose(&url_and_host);
|
||||
git_str_dispose(&remote_cmd);
|
||||
git_config_free(cfg);
|
||||
return error;
|
||||
}
|
||||
@@ -183,7 +212,7 @@ static int start_ssh(
|
||||
|
||||
git_process_options process_opts = GIT_PROCESS_OPTIONS_INIT;
|
||||
git_net_url url = GIT_NET_URL_INIT;
|
||||
git_str ssh_cmdline = GIT_STR_INIT;
|
||||
git_vector args = GIT_VECTOR_INIT;
|
||||
const char *command;
|
||||
int error;
|
||||
|
||||
@@ -214,11 +243,12 @@ static int start_ssh(
|
||||
if (error < 0)
|
||||
goto done;
|
||||
|
||||
if ((error = get_ssh_cmdline(&ssh_cmdline, transport, &url, command)) < 0)
|
||||
if ((error = get_ssh_cmdline(&args, transport, &url, command)) < 0)
|
||||
goto done;
|
||||
|
||||
if ((error = git_process_new_from_cmdline(&transport->process,
|
||||
ssh_cmdline.ptr, env, ARRAY_SIZE(env), &process_opts)) < 0 ||
|
||||
if ((error = git_process_new(&transport->process,
|
||||
(const char **)args.contents, args.length,
|
||||
env, ARRAY_SIZE(env), &process_opts)) < 0 ||
|
||||
(error = git_process_start(transport->process)) < 0) {
|
||||
git_process_free(transport->process);
|
||||
transport->process = NULL;
|
||||
@@ -226,7 +256,7 @@ static int start_ssh(
|
||||
}
|
||||
|
||||
done:
|
||||
git_str_dispose(&ssh_cmdline);
|
||||
git_vector_dispose_deep(&args);
|
||||
git_net_url_dispose(&url);
|
||||
return error;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user