1 /*- 2 * Copyright (c) 2012 Alistair Crooks <agc@NetBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 #include <sys/types.h> 26 27 #include <err.h> 28 #include <inttypes.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <time.h> 33 #include <unistd.h> 34 35 #include "verify.h" 36 37 #include "array.h" 38 39 /* print the time nicely */ 40 static void 41 ptime(int64_t secs) 42 { 43 time_t t; 44 45 t = (time_t)secs; 46 printf("%s", ctime(&t)); 47 } 48 49 /* print entry n */ 50 static void 51 pentry(pgpv_t *pgp, int n) 52 { 53 char *s; 54 55 pgpv_get_entry(pgp, (unsigned)n, &s); 56 printf("%s", s); 57 free(s); 58 } 59 60 #define MB(x) ((x) * 1024 * 1024) 61 62 /* get stdin into memory so we can verify it */ 63 static char * 64 getstdin(ssize_t *cc, size_t *size) 65 { 66 size_t newsize; 67 char *newin; 68 char *in; 69 int rc; 70 71 *cc = 0; 72 *size = 0; 73 in = NULL; 74 do { 75 newsize = *size + MB(1); 76 if ((newin = realloc(in, newsize)) == NULL) { 77 break; 78 } 79 in = newin; 80 *size = newsize; 81 if ((rc = read(STDIN_FILENO, &in[*cc], newsize - *cc)) > 0) { 82 *cc += rc; 83 } 84 } while (rc > 0); 85 return in; 86 } 87 88 /* verify memory or file */ 89 static int 90 verify_data(pgpv_t *pgp, const char *cmd, const char *inname, char *in, ssize_t cc) 91 { 92 pgpv_cursor_t cursor; 93 size_t size; 94 size_t cookie; 95 char *data; 96 97 memset(&cursor, 0x0, sizeof(cursor)); 98 if (strcasecmp(cmd, "cat") == 0) { 99 if ((cookie = pgpv_verify(&cursor, pgp, in, cc)) != 0) { 100 if ((size = pgpv_get_verified(&cursor, cookie, &data)) > 0) { 101 printf("%.*s", (int)size, data); 102 } 103 return 1; 104 } 105 } else if (strcasecmp(cmd, "verify") == 0) { 106 if (pgpv_verify(&cursor, pgp, in, cc)) { 107 printf("Good signature for %s made ", inname); 108 ptime(cursor.sigtime); 109 pentry(pgp, ARRAY_ELEMENT(cursor.found, 0)); 110 return 1; 111 } 112 warnx("Signature did not match contents -- %s", cursor.why); 113 } else { 114 warnx("unrecognised command \"%s\"", cmd); 115 } 116 return 0; 117 } 118 119 int 120 main(int argc, char **argv) 121 { 122 const char *keyring; 123 const char *cmd; 124 ssize_t cc; 125 size_t size; 126 pgpv_t pgp; 127 char *in; 128 int ok; 129 int i; 130 131 memset(&pgp, 0x0, sizeof(pgp)); 132 cmd = NULL; 133 keyring = NULL; 134 ok = 1; 135 while ((i = getopt(argc, argv, "c:k:")) != -1) { 136 switch(i) { 137 case 'c': 138 cmd = optarg; 139 break; 140 case 'k': 141 keyring = optarg; 142 break; 143 default: 144 break; 145 } 146 } 147 if (cmd == NULL) { 148 cmd = "verify"; 149 } 150 if (!pgpv_read_pubring(&pgp, keyring, -1)) { 151 errx(EXIT_FAILURE, "can't read keyring"); 152 } 153 if (optind == argc) { 154 in = getstdin(&cc, &size); 155 ok = verify_data(&pgp, cmd, "[stdin]", in, cc); 156 } else { 157 for (ok = 1, i = optind ; i < argc ; i++) { 158 if (!verify_data(&pgp, cmd, argv[i], argv[i], -1)) { 159 ok = 0; 160 } 161 } 162 } 163 pgpv_close(&pgp); 164 exit((ok) ? EXIT_SUCCESS : EXIT_FAILURE); 165 } 166