fix exec from git-shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
diff --git a/git-auth.c b/git-auth.c
index 5495b22..66e980f 100644
--- a/git-auth.c
+++ b/git-auth.c
@@ -38,16 +38,38 @@
s_sympackage g_sympkg;
+void stracat (char *buf, size_t bufsiz, const char **str_array, size_t sasiz)
+{
+ size_t b = 0;
+ size_t a;
+ assert(buf);
+ assert(bufsiz);
+ assert(str_array);
+ assert(sasiz);
+ for (a = 0; a < sasiz && b < bufsiz; a++) {
+ if (a)
+ buf[b++] = ' ';
+ b += strlcpy(buf + b, str_array[a], bufsiz - b);
+ }
+}
+
void log_args (const char *op, int argc, const char **argv)
{
char msg[2048];
+ stracat(msg, sizeof(msg), argv, argc);
+ syslog(LOG_INFO, "%s %s", op, msg);
+}
+
+void log_rule (const char *op, s_symtable *cmd)
+{
+ char msg[2048];
size_t m = 0;
- int a;
- for (a = 0; a < argc && m < sizeof(msg); a++) {
- msg[m++] = ' ';
- m += strlcpy(msg + m, argv[a], sizeof(msg) - m);
- }
- syslog(LOG_INFO, "%s%s", op, msg);
+ assert(cmd);
+ m += strlcpy(msg + m, ENV_AUTH_ID, sizeof(msg) - m);
+ msg[m++] = '=';
+ m += strlcpy(msg + m, cmd->sym[0], sizeof(msg) - m);
+ stracat(msg + m, sizeof(msg) - m, cmd->sym + 1, cmd->count - 1);
+ syslog(LOG_INFO, "%s %s", op, msg);
}
void log_cmd (const char *op, s_symtable *cmd)
@@ -58,10 +80,6 @@ void log_cmd (const char *op, s_symtable *cmd)
assert(cmd);
for (a = 0; a < cmd->count && m < sizeof(msg); a++) {
msg[m++] = ' ';
- if (a == 0) {
- m += strlcpy(msg + m, ENV_AUTH_ID, sizeof(msg) - m);
- msg[m++] = '=';
- }
m += strlcpy(msg + m, cmd->sym[a], sizeof(msg) - m);
}
syslog(LOG_INFO, "%s%s", op, msg);
@@ -97,7 +115,7 @@ void rules_read (s_rules *rr, const char *path)
rule_add(&r, s);
}
if (r.count >= 2) {
- log_cmd("RULE", &r);
+ log_rule("RULE", &r);
rules_add(rr, &r);
}
else if (r.count == 1)
@@ -164,6 +182,29 @@ void cmd_init (s_symtable *cmd, t_sym id, int argc, const char *argv[])
symtable_add(cmd, sympackage_intern(&g_sympkg, *argv++));
}
+void cleanup ()
+{
+ closelog();
+ sympackage_free(&g_sympkg);
+}
+
+void exec_cmd (s_symtable *cmd)
+{
+ assert(cmd);
+ char buf[2048];
+ stracat(buf, sizeof(buf), cmd->sym, cmd->count);
+ assert(cmd);
+ s_symtable xc;
+ symtable_init(&xc);
+ symtable_add(&xc, SHELL);
+ symtable_add(&xc, "-c");
+ symtable_add(&xc, buf);
+ log_cmd("EXEC", &xc);
+ cleanup();
+ execvp(xc.sym[0], (char **)xc.sym);
+ err(2, "exec failed");
+}
+
int main (int argc, char **argv)
{
s_rules rr;
@@ -174,23 +215,20 @@ int main (int argc, char **argv)
if (argc < 2)
usage(argv[0]);
init_package();
- rules_init(&rr);
- rules_read(&rr, "/etc/git-auth.conf");
const char *env_auth_id = getenv(ENV_AUTH_ID);
t_sym id = sympackage_intern(&g_sympkg, env_auth_id ? env_auth_id : "");
s_symtable cmd;
cmd_init(&cmd, id, argc - 1, (const char **) argv + 1);
- if (auth(&rr, &cmd)) {
- log_cmd("ALLOW", &cmd);
- closelog();
- cmd.sym[0] = SHELL;
- rules_free(&rr);
- sympackage_free(&g_sympkg);
- execvp(argv[1], argv + 1);
- err(2, "exec failed");
- return 2;
+ rules_init(&rr);
+ rules_read(&rr, "/etc/git-auth.conf");
+ int auth_ok = auth(&rr, &cmd);
+ rules_free(&rr);
+ log_rule(auth_ok ? "ALLOW" : "DENY", &cmd);
+ if (auth_ok) {
+ exec_cmd(&cmd);
+ // never reached
}
- log_cmd("DENY", &cmd);
- closelog();
+ log_rule("DENY", &cmd);
+ cleanup();
return 1;
}