mirror of
https://github.com/git/git.git
synced 2024-11-18 17:03:56 +01:00
b10d0ec732
This tries to be more lenient to the users and stricter to the attackers by quoting the input properly for shell safety, instead of forbidding certain characters from the input. Things to note: - We do not quote "prog" parameter (which comes from --exec). The user should know what he is doing. --exec='echo foo' will supply the first two parameters to the resulting command, while --exec="'echo foo'" will give the first parameter, a single string with a space inside. - We do not care too much about leaking the sq_quote() output just before running exec(). Signed-off-by: Junio C Hamano <junkio@cox.net> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
102 lines
1.9 KiB
C
102 lines
1.9 KiB
C
#include "cache.h"
|
|
#include "pkt-line.h"
|
|
#include "quote.h"
|
|
#include <sys/wait.h>
|
|
|
|
int get_ack(int fd, unsigned char *result_sha1)
|
|
{
|
|
static char line[1000];
|
|
int len = packet_read_line(fd, line, sizeof(line));
|
|
|
|
if (!len)
|
|
die("git-fetch-pack: expected ACK/NAK, got EOF");
|
|
if (line[len-1] == '\n')
|
|
line[--len] = 0;
|
|
if (!strcmp(line, "NAK"))
|
|
return 0;
|
|
if (!strncmp(line, "ACK ", 3)) {
|
|
if (!get_sha1_hex(line+4, result_sha1))
|
|
return 1;
|
|
}
|
|
die("git-fetch_pack: expected ACK/NAK, got '%s'", line);
|
|
}
|
|
|
|
int path_match(const char *path, int nr, char **match)
|
|
{
|
|
int i;
|
|
int pathlen = strlen(path);
|
|
|
|
for (i = 0; i < nr; i++) {
|
|
char *s = match[i];
|
|
int len = strlen(s);
|
|
|
|
if (!len || len > pathlen)
|
|
continue;
|
|
if (memcmp(path + pathlen - len, s, len))
|
|
continue;
|
|
if (pathlen > len && path[pathlen - len - 1] != '/')
|
|
continue;
|
|
*s = 0;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Yeah, yeah, fixme. Need to pass in the heads etc.
|
|
*/
|
|
int git_connect(int fd[2], char *url, const char *prog)
|
|
{
|
|
char command[1024];
|
|
const char *host, *path;
|
|
char *colon;
|
|
int pipefd[2][2];
|
|
pid_t pid;
|
|
|
|
host = NULL;
|
|
path = url;
|
|
colon = strchr(url, ':');
|
|
if (colon) {
|
|
*colon = 0;
|
|
host = url;
|
|
path = colon+1;
|
|
}
|
|
if (pipe(pipefd[0]) < 0 || pipe(pipefd[1]) < 0)
|
|
die("unable to create pipe pair for communication");
|
|
pid = fork();
|
|
if (!pid) {
|
|
snprintf(command, sizeof(command), "%s %s", prog,
|
|
sq_quote(path));
|
|
dup2(pipefd[1][0], 0);
|
|
dup2(pipefd[0][1], 1);
|
|
close(pipefd[0][0]);
|
|
close(pipefd[0][1]);
|
|
close(pipefd[1][0]);
|
|
close(pipefd[1][1]);
|
|
if (host)
|
|
execlp("ssh", "ssh", host, command, NULL);
|
|
else
|
|
execlp("sh", "sh", "-c", command, NULL);
|
|
die("exec failed");
|
|
}
|
|
fd[0] = pipefd[0][0];
|
|
fd[1] = pipefd[1][1];
|
|
close(pipefd[0][1]);
|
|
close(pipefd[1][0]);
|
|
return pid;
|
|
}
|
|
|
|
int finish_connect(pid_t pid)
|
|
{
|
|
int ret;
|
|
|
|
for (;;) {
|
|
ret = waitpid(pid, NULL, 0);
|
|
if (!ret)
|
|
break;
|
|
if (errno != EINTR)
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|