1#include "cache.h" 2 3/* 4 * A signature file has a very simple fixed format: three lines 5 * of "object <sha1>" + "type <typename>" + "tag <tagname>", 6 * followed by some free-form signature that git itself doesn't 7 * care about, but that can be verified with gpg or similar. 8 * 9 * The first three lines are guaranteed to be at least 63 bytes: 10 * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the 11 * shortest possible type-line, and "tag .\n" at 6 bytes is the 12 * shortest single-character-tag line. 13 * 14 * We also artificially limit the size of the full object to 8kB. 15 * Just because I'm a lazy bastard, and if you can't fit a signature 16 * in that size, you're doing something wrong. 17 */ 18 19// Some random size 20#define MAXSIZE (8192) 21 22/* 23 * We refuse to tag something we can't verify. Just because. 24 */ 25static int verify_object(unsigned char *sha1, const char *expected_type) 26{ 27 int ret = -1; 28 char type[100]; 29 unsigned long size; 30 void *buffer = read_sha1_file(sha1, type, &size); 31 32 if (buffer) { 33 if (!strcmp(type, expected_type)) 34 ret = check_sha1_signature(sha1, buffer, size, type); 35 free(buffer); 36 } 37 return ret; 38} 39 40static int verify_tag(char *buffer, unsigned long size) 41{ 42 int typelen; 43 char type[20]; 44 unsigned char sha1[20]; 45 const char *object, *type_line, *tag_line; 46 47 if (size < 64 || size > MAXSIZE-1) 48 return -1; 49 buffer[size] = 0; 50 51 /* Verify object line */ 52 object = buffer; 53 if (memcmp(object, "object ", 7)) 54 return -1; 55 if (get_sha1_hex(object + 7, sha1)) 56 return -1; 57 58 /* Verify type line */ 59 type_line = object + 48; 60 if (memcmp(type_line - 1, "\ntype ", 6)) 61 return -1; 62 63 /* Verify tag-line */ 64 tag_line = strchr(type_line, '\n'); 65 if (!tag_line) 66 return -1; 67 tag_line++; 68 if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n') 69 return -1; 70 71 /* Get the actual type */ 72 typelen = tag_line - type_line - strlen("type \n"); 73 if (typelen >= sizeof(type)) 74 return -1; 75 memcpy(type, type_line+5, typelen); 76 type[typelen] = 0; 77 78 /* Verify that the object matches */ 79 if (get_sha1_hex(object + 7, sha1)) 80 return -1; 81 if (verify_object(sha1, type)) 82 return -1; 83 84 /* Verify the tag-name: we don't allow control characters or spaces in it */ 85 tag_line += 4; 86 for (;;) { 87 unsigned char c = *tag_line++; 88 if (c == '\n') 89 break; 90 if (c > ' ') 91 continue; 92 return -1; 93 } 94 95 /* The actual stuff afterwards we don't care about.. */ 96 return 0; 97} 98 99int main(int argc, char **argv) 100{ 101 unsigned long size; 102 char buffer[MAXSIZE]; 103 unsigned char result_sha1[20]; 104 105 if (argc != 1) 106 usage("cat <signaturefile> | git-mktag"); 107 108 // Read the signature 109 size = read(0, buffer, MAXSIZE); 110 111 // Verify it for some basic sanity: it needs to start with "object <sha1>\ntype " 112 if (verify_tag(buffer, size) < 0) 113 die("invalid tag signature file"); 114 115 if (write_sha1_file(buffer, size, "tag", result_sha1) < 0) 116 die("unable to write tag file"); 117 printf("%s\n", sha1_to_hex(result_sha1)); 118 return 0; 119}