commit 64313a9ca0c0dcc6618c399f11960a44cda569b4 from: Josh Rickmar via: Thomas Adam date: Sun Jul 03 22:08:19 2022 UTC fix tag signing when the key file does not exist This should fail without creating any tag. Before, ssh-keygen(1) would print an error to stderr, but got would create an unsigned tag. ok op@ commit - d40a767d29b8dedc179d18a0df070f47ab334747 commit + 64313a9ca0c0dcc6618c399f11960a44cda569b4 blob - 06178d049f6e1c1b3ca9e8e1ff2b0fd4b578c310 blob + 033e452284cf91d48b02e0a4e100d62a059b93ac --- got/got.c +++ got/got.c @@ -7213,7 +7213,7 @@ done: static const struct got_error * add_tag(struct got_repository *repo, const char *tagger, const char *tag_name, const char *commit_arg, const char *tagmsg_arg, - const char *key_file, int verbosity) + const char *signer_id, int verbosity) { const struct got_error *err = NULL; struct got_object_id *commit_id = NULL, *tag_id = NULL; @@ -7279,7 +7279,7 @@ add_tag(struct got_repository *repo, const char *tagge } err = got_object_tag_create(&tag_id, tag_name, commit_id, - tagger, time(NULL), tagmsg ? tagmsg : tagmsg_arg, key_file, repo, + tagger, time(NULL), tagmsg ? tagmsg : tagmsg_arg, signer_id, repo, verbosity); if (err) { if (tagmsg_path) blob - 81018778e6b22147a6c7dabec33ba165789d46cc blob + 7f782dfab8e87a8c8c568f8f7e3c6459d964829d --- include/got_error.h +++ include/got_error.h @@ -173,6 +173,7 @@ #define GOT_ERR_PIN_PACK 153 #define GOT_ERR_BAD_TAG_SIGNATURE 154 #define GOT_ERR_VERIFY_TAG_SIGNATURE 155 +#define GOT_ERR_SIGNING_TAG 156 struct got_error { int code; blob - 35d22ec31b15f0e724ecfef6bbc4ecfa8c92b242 blob + 7be87fb981fd9501f03be122b01840603bf5b379 --- lib/error.c +++ lib/error.c @@ -226,6 +226,7 @@ static const struct got_error got_errors[] = { { GOT_ERR_PIN_PACK, "could not pin pack file" }, { GOT_ERR_BAD_TAG_SIGNATURE, "invalid tag signature" }, { GOT_ERR_VERIFY_TAG_SIGNATURE, "cannot verify signature" }, + { GOT_ERR_SIGNING_TAG, "unable to sign tag" }, }; static struct got_custom_error { blob - 2cb607608f8d00326409231209fe90a0502a0fba blob + c412cff628ac62c7308c1d21aafbe88fa6f63595 --- lib/object_create.c +++ lib/object_create.c @@ -613,7 +613,7 @@ done: const struct got_error * got_object_tag_create(struct got_object_id **id, const char *tag_name, struct got_object_id *object_id, const char *tagger, - time_t tagger_time, const char *tagmsg, const char *key_file, + time_t tagger_time, const char *tagmsg, const char *signer_id, struct got_repository *repo, int verbosity) { const struct got_error *err = NULL; @@ -688,7 +688,7 @@ got_object_tag_create(struct got_object_id **id, while (isspace((unsigned char)msg[0])) msg++; - if (key_file) { + if (signer_id) { FILE *out; pid_t pid; size_t len; @@ -722,7 +722,7 @@ got_object_tag_create(struct got_object_id **id, if (err) goto done; - err = got_sigs_sign_tag_ssh(&pid, &in_fd, &out_fd, key_file, + err = got_sigs_sign_tag_ssh(&pid, &in_fd, &out_fd, signer_id, verbosity); if (err) goto done; @@ -739,6 +739,10 @@ got_object_tag_create(struct got_object_id **id, err = got_error_from_errno("waitpid"); goto done; } + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + err = got_error(GOT_ERR_SIGNING_TAG); + goto done; + } out = fdopen(out_fd, "r"); if (out == NULL) { @@ -841,7 +845,7 @@ got_object_tag_create(struct got_object_id **id, } tagsize += n; - if (key_file && buf_len(buf) > 0) { + if (signer_id && buf_len(buf) > 0) { len = buf_len(buf); SHA1Update(&sha1_ctx, buf_get(buf), len); n = fwrite(buf_get(buf), 1, len, tagfile); blob - 65d7577f240b78881da8bf24d352cd05849fa247 blob + 8e562c11ebed91d1a5a206f6674cb8aa76e6c438 --- regress/cmdline/tag.sh +++ regress/cmdline/tag.sh @@ -431,8 +431,45 @@ test_tag_create_ssh_signed() { fi test_done "$testroot" "$ret" } + +test_tag_create_ssh_signed_missing_key() { + local testroot=`test_init tag_create` + local commit_id=`git_show_head $testroot/repo` + local tag=1.0.0 + + # Fail to create a signed tag due to a missing SSH key + got tag -s $testroot/bogus -m 'test' -r $testroot/repo \ + -c HEAD $tag > $testroot/stdout 2> $testroot/stderr + ret=$? + if [ $ret -eq 0 ]; then + echo "got tag command succeeded unexpectedly" + test_done "$testroot" 1 + return 1 + fi + got ref -r $testroot/repo -l > $testroot/stdout + echo "HEAD: refs/heads/master" > $testroot/stdout.expected + echo "refs/heads/master: $commit_id" >> $testroot/stdout.expected + cmp -s $testroot/stdout $testroot/stdout.expected + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + printf "Couldn't load public key $testroot/bogus: " \ + echo "got: unable to sign tag" >> $testroot/stderr.expected + printf "No such file or directory\r\n" >> $testroot/stderr.expected + cmp -s $testroot/stderr $testroot/stderr.expected + ret=$? + if [ $ret -ne 0 ]; then + diff -u $testroot/stderr.expected $testroot/stderr + fi + test_done "$testroot" "$ret" +} + test_parseargs "$@" +test_parseargs "$@" run_test test_tag_create run_test test_tag_list run_test test_tag_list_lightweight