commit 9aeaf23a7e94501bdcb20d18427620cf70b87995 from: Omar Polo date: Sun Jan 22 14:09:47 2023 UTC gotsh: validate with parse_command before connecting Export parse_command (now got_serve_parse_command) from lib/serve.c and use it to validate the command line in gotsh instead of just checking that the -c argument starts with 'git-receive-pack' or 'git-upload-pack'. Invalid usage now always fails before opening the socket, while before it wasn't always the case. This also means that invalid usage doesn't count towards the limits. ok jamsek, stsp commit - b5225f29d85b32692bdfed88b3e93babf8269494 commit + 9aeaf23a7e94501bdcb20d18427620cf70b87995 blob - acc4545ba9aeab1061576f340ba1ba16ed227d59 blob + fb5f331b5c32503b2fe1e1c4de73a8af9959be9d --- gotsh/gotsh.c +++ gotsh/gotsh.c @@ -67,7 +67,7 @@ main(int argc, char *argv[]) char *unix_socket_path_env = getenv("GOTD_UNIX_SOCKET"); int gotd_sock = -1; struct sockaddr_un sun; - char *gitcmd = NULL; + char *gitcmd = NULL, *command = NULL, *repo_path = NULL; #ifndef PROFILE if (pledge("stdio recvfd unix unveil", NULL) == -1) @@ -79,17 +79,16 @@ main(int argc, char *argv[]) usage(); if (asprintf(&gitcmd, "%s %s", argv[0], argv[1]) == -1) err(1, "asprintf"); + error = got_serve_parse_command(&command, &repo_path, gitcmd); } else { - if (argc != 3 || strcmp(argv[1], "-c") != 0 || - (strncmp(argv[2], GOT_SERVE_CMD_SEND, - strlen(GOT_SERVE_CMD_SEND)) != 0 && - (strncmp(argv[2], GOT_SERVE_CMD_FETCH, - strlen(GOT_SERVE_CMD_FETCH)) != 0))) + if (argc != 3 || strcmp(argv[1], "-c") != 0) usage(); - gitcmd = strdup(argv[2]); - if (gitcmd == NULL) - err(1, "strdup"); + error = got_serve_parse_command(&command, &repo_path, argv[2]); } + if (error && error->code == GOT_ERR_BAD_PACKET) + usage(); + if (error) + goto done; if (unix_socket_path_env) { if (strlcpy(unix_socket_path, unix_socket_path_env, @@ -123,10 +122,12 @@ main(int argc, char *argv[]) if (pledge("stdio recvfd", NULL) == -1) err(1, "pledge"); #endif - error = got_serve(STDIN_FILENO, STDOUT_FILENO, gitcmd, gotd_sock, - chattygot); + error = got_serve(STDIN_FILENO, STDOUT_FILENO, command, repo_path, + gotd_sock, chattygot); done: free(gitcmd); + free(command); + free(repo_path); if (gotd_sock != -1) close(gotd_sock); if (error) { blob - 180c362c726680bac4fbe3b5fd47dca9a5e166ae blob + 437fff67924784d199bc37269ac367e71f2dc063 --- include/got_serve.h +++ include/got_serve.h @@ -17,5 +17,6 @@ #define GOT_SERVE_CMD_SEND "git-receive-pack" #define GOT_SERVE_CMD_FETCH "git-upload-pack" -const struct got_error *got_serve(int infd, int outfd, const char *gitcmd, - int gotd_sock, int chattygot); +const struct got_error *got_serve_parse_command(char **, char **, const char *); +const struct got_error *got_serve(int infd, int outfd, const char *command, + const char *repo_path, int gotd_sock, int chattygot); blob - 8b6e7dae0d002c424ec5925b1f143e4f367f9b96 blob + 6664a0be413a6c6e1b9a90d98cea4891ccaf46c9 --- lib/serve.c +++ lib/serve.c @@ -64,8 +64,8 @@ static const struct got_capability write_capabilities[ #endif }; -static const struct got_error * -parse_command(char **command, char **repo_path, const char *gitcmd) +const struct got_error * +got_serve_parse_command(char **command, char **repo_path, const char *gitcmd) { const struct got_error *err = NULL; size_t len, cmdlen, pathlen; @@ -1482,15 +1482,11 @@ done: } const struct got_error * -got_serve(int infd, int outfd, const char *gitcmd, int gotd_sock, int chattygot) +got_serve(int infd, int outfd, const char *command, const char *repo_path, + int gotd_sock, int chattygot) { const struct got_error *err = NULL; - char *command = NULL, *repo_path = NULL; - err = parse_command(&command, &repo_path, gitcmd); - if (err) - return err; - if (strcmp(command, GOT_SERVE_CMD_FETCH) == 0) err = serve_read(infd, outfd, gotd_sock, repo_path, chattygot); else if (strcmp(command, GOT_SERVE_CMD_SEND) == 0) @@ -1499,7 +1495,5 @@ got_serve(int infd, int outfd, const char *gitcmd, int else err = got_error(GOT_ERR_BAD_PACKET); - free(command); - free(repo_path); return err; }