blob: 3e18a41841485e8138d7ccaf36e24cc99e5d81cd [file] [log] [blame]
Daniel Barkalow2636f612005-04-28 07:46:33 -07001#include "cache.h"
Junio C Hamano8f1d2e62006-01-07 01:33:54 -08002#include "tag.h"
Stefan Bellercbd53a22018-05-15 16:42:15 -07003#include "object-store.h"
Nicolas Pitre0ab17952007-02-26 14:56:00 -05004#include "commit.h"
5#include "tree.h"
6#include "blob.h"
Stefan Beller14ba97f2018-05-15 14:48:42 -07007#include "alloc.h"
Lukas Puehringer94240b92017-01-17 18:37:18 -05008#include "gpg-interface.h"
Jonathan Tan8c4cc322018-07-12 17:03:07 -07009#include "packfile.h"
Daniel Barkalow2636f612005-04-28 07:46:33 -070010
11const char *tag_type = "tag";
12
Santiago Torres45a227e2016-04-22 10:52:04 -040013static int run_gpg_verify(const char *buf, unsigned long size, unsigned flags)
14{
15 struct signature_check sigc;
brian m. carlson482c1192021-02-11 02:08:03 +000016 struct strbuf payload = STRBUF_INIT;
17 struct strbuf signature = STRBUF_INIT;
Santiago Torres45a227e2016-04-22 10:52:04 -040018 int ret;
19
20 memset(&sigc, 0, sizeof(sigc));
21
brian m. carlson482c1192021-02-11 02:08:03 +000022 if (!parse_signature(buf, size, &payload, &signature)) {
Santiago Torres45a227e2016-04-22 10:52:04 -040023 if (flags & GPG_VERIFY_VERBOSE)
brian m. carlson482c1192021-02-11 02:08:03 +000024 write_in_full(1, buf, size);
Santiago Torres45a227e2016-04-22 10:52:04 -040025 return error("no signature found");
26 }
27
brian m. carlson482c1192021-02-11 02:08:03 +000028 ret = check_signature(payload.buf, payload.len, signature.buf,
29 signature.len, &sigc);
Lukas Puehringer94240b92017-01-17 18:37:18 -050030
31 if (!(flags & GPG_VERIFY_OMIT_STATUS))
32 print_signature_buffer(&sigc, flags);
Santiago Torres45a227e2016-04-22 10:52:04 -040033
34 signature_check_clear(&sigc);
brian m. carlson482c1192021-02-11 02:08:03 +000035 strbuf_release(&payload);
36 strbuf_release(&signature);
Santiago Torres45a227e2016-04-22 10:52:04 -040037 return ret;
38}
39
Stefan Beller84571762017-07-12 17:44:15 -070040int gpg_verify_tag(const struct object_id *oid, const char *name_to_report,
Santiago Torres45a227e2016-04-22 10:52:04 -040041 unsigned flags)
42{
43 enum object_type type;
44 char *buf;
45 unsigned long size;
46 int ret;
47
Stefan Beller0df8e962018-04-25 11:20:59 -070048 type = oid_object_info(the_repository, oid, NULL);
Santiago Torres45a227e2016-04-22 10:52:04 -040049 if (type != OBJ_TAG)
50 return error("%s: cannot verify a non-tag object of type %s.",
51 name_to_report ?
52 name_to_report :
brian m. carlsonaab95832018-03-12 02:27:30 +000053 find_unique_abbrev(oid, DEFAULT_ABBREV),
Brandon Williamsdebca9d2018-02-14 10:59:24 -080054 type_name(type));
Santiago Torres45a227e2016-04-22 10:52:04 -040055
brian m. carlsonb4f5aca2018-03-12 02:27:53 +000056 buf = read_object_file(oid, &type, &size);
Santiago Torres45a227e2016-04-22 10:52:04 -040057 if (!buf)
58 return error("%s: unable to read file.",
59 name_to_report ?
60 name_to_report :
brian m. carlsonaab95832018-03-12 02:27:30 +000061 find_unique_abbrev(oid, DEFAULT_ABBREV));
Santiago Torres45a227e2016-04-22 10:52:04 -040062
63 ret = run_gpg_verify(buf, size, flags);
64
65 free(buf);
66 return ret;
67}
68
Stefan Beller286d2582018-06-28 18:22:20 -070069struct object *deref_tag(struct repository *r, struct object *o, const char *warn, int warnlen)
Junio C Hamano37fde872005-08-05 00:47:56 -070070{
Jonathan Tan8c4cc322018-07-12 17:03:07 -070071 struct object_id *last_oid = NULL;
Linus Torvalds19746322006-07-11 20:45:31 -070072 while (o && o->type == OBJ_TAG)
Jonathan Tan8c4cc322018-07-12 17:03:07 -070073 if (((struct tag *)o)->tagged) {
74 last_oid = &((struct tag *)o)->tagged->oid;
Junio C Hamano09ca6132018-08-02 15:30:46 -070075 o = parse_object(r, last_oid);
Jonathan Tan8c4cc322018-07-12 17:03:07 -070076 } else {
77 last_oid = NULL;
Martin Koegler24e8a3c2008-02-18 08:31:55 +010078 o = NULL;
Jonathan Tan8c4cc322018-07-12 17:03:07 -070079 }
Junio C Hamano9534f402005-11-02 15:19:13 -080080 if (!o && warn) {
Jonathan Tan8c4cc322018-07-12 17:03:07 -070081 if (last_oid && is_promisor_object(last_oid))
82 return NULL;
Junio C Hamano9534f402005-11-02 15:19:13 -080083 if (!warnlen)
84 warnlen = strlen(warn);
85 error("missing object referenced by '%.*s'", warnlen, warn);
86 }
Junio C Hamano37fde872005-08-05 00:47:56 -070087 return o;
88}
89
Jeff King90108a22012-01-06 14:18:01 -050090struct object *deref_tag_noverify(struct object *o)
91{
92 while (o && o->type == OBJ_TAG) {
Stefan Beller109cd762018-06-28 18:21:51 -070093 o = parse_object(the_repository, &o->oid);
Jeff King90108a22012-01-06 14:18:01 -050094 if (o && o->type == OBJ_TAG && ((struct tag *)o)->tagged)
95 o = ((struct tag *)o)->tagged;
96 else
97 o = NULL;
98 }
99 return o;
100}
101
Stefan Beller8bde69b2018-06-28 18:22:11 -0700102struct tag *lookup_tag(struct repository *r, const struct object_id *oid)
Daniel Barkalow2636f612005-04-28 07:46:33 -0700103{
Jeff Kingd0229ab2019-06-20 03:41:14 -0400104 struct object *obj = lookup_object(r, oid);
Linus Torvalds100c5f32007-04-16 22:11:43 -0700105 if (!obj)
Jeff Kinga3785092019-06-20 03:41:21 -0400106 return create_object(r, oid, alloc_tag_node(r));
Abhishek Kumar6da43d92020-06-17 14:44:08 +0530107 return object_as_type(obj, OBJ_TAG, 0);
Daniel Barkalow2636f612005-04-28 07:46:33 -0700108}
109
Johannes Schindelindddbad72017-04-26 21:29:31 +0200110static timestamp_t parse_tag_date(const char *buf, const char *tail)
Shawn O. Pearcee451d062010-04-12 16:25:28 -0700111{
112 const char *dateptr;
113
114 while (buf < tail && *buf++ != '>')
115 /* nada */;
116 if (buf >= tail)
117 return 0;
118 dateptr = buf;
119 while (buf < tail && *buf++ != '\n')
120 /* nada */;
121 if (buf >= tail)
122 return 0;
Johannes Schindelin1aeb7e72017-04-21 12:45:44 +0200123 /* dateptr < buf && buf[-1] == '\n', so parsing will stop at buf-1 */
124 return parse_timestamp(dateptr, NULL, 10);
Shawn O. Pearcee451d062010-04-12 16:25:28 -0700125}
126
Stefan Beller14ba97f2018-05-15 14:48:42 -0700127void release_tag_memory(struct tag *t)
128{
129 free(t->tag);
130 t->tagged = NULL;
131 t->object.parsed = 0;
132 t->date = 0;
133}
134
Stefan Beller84f80cd2018-06-28 18:22:12 -0700135int parse_tag_buffer(struct repository *r, struct tag *item, const void *data, unsigned long size)
Daniel Barkalow2636f612005-04-28 07:46:33 -0700136{
brian m. carlson1e4085a2017-05-06 22:10:02 +0000137 struct object_id oid;
Daniel Barkalow89e42022005-06-21 20:35:10 -0400138 char type[20];
Shawn O. Pearce28de5b62010-04-12 16:25:27 -0700139 const char *bufptr = data;
140 const char *tail = bufptr + size;
141 const char *nl;
Edgar Toernigae200ee2005-04-30 09:51:03 -0700142
Shawn O. Pearce2e0052a2010-04-12 16:25:25 -0700143 if (item->object.parsed)
144 return 0;
Jeff King228c78f2019-10-25 17:20:20 -0400145
146 if (item->tag) {
147 /*
148 * Presumably left over from a previous failed parse;
149 * clear it out in preparation for re-parsing (we'll probably
150 * hit the same error, which lets us tell our current caller
151 * about the problem).
152 */
153 FREE_AND_NULL(item->tag);
154 }
Daniel Barkalow2636f612005-04-28 07:46:33 -0700155
brian m. carlsond8a3a692018-10-15 00:01:58 +0000156 if (size < the_hash_algo->hexsz + 24)
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400157 return -1;
brian m. carlson1e4085a2017-05-06 22:10:02 +0000158 if (memcmp("object ", bufptr, 7) || parse_oid_hex(bufptr + 7, &oid, &bufptr) || *bufptr++ != '\n')
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400159 return -1;
Daniel Barkalow2636f612005-04-28 07:46:33 -0700160
Christian Couder59556542013-11-30 21:55:40 +0100161 if (!starts_with(bufptr, "type "))
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400162 return -1;
Shawn O. Pearce28de5b62010-04-12 16:25:27 -0700163 bufptr += 5;
164 nl = memchr(bufptr, '\n', tail - bufptr);
165 if (!nl || sizeof(type) <= (nl - bufptr))
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400166 return -1;
Jeff Kingeddda372015-09-24 17:08:26 -0400167 memcpy(type, bufptr, nl - bufptr);
Shawn O. Pearce28de5b62010-04-12 16:25:27 -0700168 type[nl - bufptr] = '\0';
169 bufptr = nl + 1;
Daniel Barkalow2636f612005-04-28 07:46:33 -0700170
Nicolas Pitre0ab17952007-02-26 14:56:00 -0500171 if (!strcmp(type, blob_type)) {
Stefan Beller84f80cd2018-06-28 18:22:12 -0700172 item->tagged = (struct object *)lookup_blob(r, &oid);
Nicolas Pitre0ab17952007-02-26 14:56:00 -0500173 } else if (!strcmp(type, tree_type)) {
Stefan Beller84f80cd2018-06-28 18:22:12 -0700174 item->tagged = (struct object *)lookup_tree(r, &oid);
Nicolas Pitre0ab17952007-02-26 14:56:00 -0500175 } else if (!strcmp(type, commit_type)) {
Stefan Beller84f80cd2018-06-28 18:22:12 -0700176 item->tagged = (struct object *)lookup_commit(r, &oid);
Nicolas Pitre0ab17952007-02-26 14:56:00 -0500177 } else if (!strcmp(type, tag_type)) {
Stefan Beller84f80cd2018-06-28 18:22:12 -0700178 item->tagged = (struct object *)lookup_tag(r, &oid);
Nicolas Pitre0ab17952007-02-26 14:56:00 -0500179 } else {
Jeff King78d50142019-10-18 00:45:35 -0400180 return error("unknown tag type '%s' in %s",
181 type, oid_to_hex(&item->object.oid));
Nicolas Pitre0ab17952007-02-26 14:56:00 -0500182 }
183
Jeff King78d50142019-10-18 00:45:35 -0400184 if (!item->tagged)
185 return error("bad tag pointer to %s in %s",
186 oid_to_hex(&oid),
187 oid_to_hex(&item->object.oid));
188
Christian Couder59556542013-11-30 21:55:40 +0100189 if (bufptr + 4 < tail && starts_with(bufptr, "tag "))
Nguyễn Thái Ngọc Duy85594252011-02-14 20:02:51 +0700190 ; /* good */
191 else
Shawn O. Pearce28de5b62010-04-12 16:25:27 -0700192 return -1;
193 bufptr += 4;
194 nl = memchr(bufptr, '\n', tail - bufptr);
195 if (!nl)
196 return -1;
197 item->tag = xmemdupz(bufptr, nl - bufptr);
198 bufptr = nl + 1;
199
Christian Couder59556542013-11-30 21:55:40 +0100200 if (bufptr + 7 < tail && starts_with(bufptr, "tagger "))
Shawn O. Pearcee451d062010-04-12 16:25:28 -0700201 item->date = parse_tag_date(bufptr, tail);
202 else
203 item->date = 0;
204
Jeff King228c78f2019-10-25 17:20:20 -0400205 item->object.parsed = 1;
Daniel Barkalow2636f612005-04-28 07:46:33 -0700206 return 0;
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400207}
Sergey Vlasov13019d42005-05-04 21:44:15 +0400208
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400209int parse_tag(struct tag *item)
210{
Nicolas Pitre21666f12007-02-26 14:55:59 -0500211 enum object_type type;
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400212 void *data;
213 unsigned long size;
214 int ret;
215
216 if (item->object.parsed)
217 return 0;
brian m. carlsonb4f5aca2018-03-12 02:27:53 +0000218 data = read_object_file(&item->object.oid, &type, &size);
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400219 if (!data)
220 return error("Could not read %s",
brian m. carlsonf2fd0762015-11-10 02:22:28 +0000221 oid_to_hex(&item->object.oid));
Nicolas Pitre21666f12007-02-26 14:55:59 -0500222 if (type != OBJ_TAG) {
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400223 free(data);
224 return error("Object %s not a tag",
brian m. carlsonf2fd0762015-11-10 02:22:28 +0000225 oid_to_hex(&item->object.oid));
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400226 }
Stefan Beller0e740fe2018-06-28 18:22:04 -0700227 ret = parse_tag_buffer(the_repository, item, data, size);
Sergey Vlasov13019d42005-05-04 21:44:15 +0400228 free(data);
Nicolas Pitrebd2c39f2005-05-06 13:48:34 -0400229 return ret;
Daniel Barkalow2636f612005-04-28 07:46:33 -0700230}
René Scharfedad3f062019-09-05 21:55:55 +0200231
232struct object_id *get_tagged_oid(struct tag *tag)
233{
234 if (!tag->tagged)
235 die("bad tag");
236 return &tag->tagged->oid;
237}