commit 214d733a8e368034e6afa52b6c9ac25e071fd0c7 from: Omar Polo via: Thomas Adam date: Mon Jan 23 18:21:06 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 - f5f71a04830c68cddf72cca7f77c8dec97451abb commit + 214d733a8e368034e6afa52b6c9ac25e071fd0c7 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 - 5f8f44b1493cc8a296d4d7b4ddd0e31317e213c3 blob + a3bb6f2f4edf03609cd6c5a364d94d6dd8d7a756 --- 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; }