commit 91d845ad5d8f8897e51d3f9233a9ea3e89fee80d from: Josh Rickmar date: Sun Jul 03 21:44:01 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 - 41e8d27de3dea9d283199eb2e1a7f6a98ee9286f commit + 91d845ad5d8f8897e51d3f9233a9ea3e89fee80d blob - 78d21329448a5ced385a2691f8f4294e0935e230 blob + ce9c1f6a767e1ce46cdb4ed24321c4f9a5901747 --- got/got.c +++ got/got.c @@ -7214,7 +7214,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; @@ -7280,7 +7280,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 - 4bfaed588e2d81e1b0578a939dd96553de6bc11b blob + 9dcd5b85b181ee63d76a75bf16c9ae0dc46aaa26 --- include/got_error.h +++ include/got_error.h @@ -171,6 +171,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 - 3c092e61bab70845c184eb10f359eb6df3ee01ce blob + bde78fabea00a9c132a5ec2ea937fc0665428986 --- lib/error.c +++ lib/error.c @@ -219,6 +219,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 - 8f33d6ba0309e1d8f43ef3b0c35b661bd6045211 blob + 2e773fde3898b103364cc053c27f666b78abea2d --- lib/object_create.c +++ lib/object_create.c @@ -612,7 +612,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; @@ -687,7 +687,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; @@ -721,7 +721,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; @@ -738,6 +738,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) { @@ -840,7 +844,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 - b39af2be74c1e13b37e5bb89219e62eed8046e23 blob + 07c00cbd2fc48f250fa1aeb4ffca75211219ae7d --- regress/cmdline/tag.sh +++ regress/cmdline/tag.sh @@ -416,8 +416,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