1/*- 2 * Copyright (c) 2009 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Alistair Crooks (agc@NetBSD.org) 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29/* 30 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) 31 * All rights reserved. 32 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted 33 * their moral rights under the UK Copyright Design and Patents Act 1988 to 34 * be recorded as the authors of this copyright work. 35 * 36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 37 * use this file except in compliance with the License. 38 * 39 * You may obtain a copy of the License at 40 * http://www.apache.org/licenses/LICENSE-2.0 41 * 42 * Unless required by applicable law or agreed to in writing, software 43 * distributed under the License is distributed on an "AS IS" BASIS, 44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 45 * 46 * See the License for the specific language governing permissions and 47 * limitations under the License. 48 */ 49#include "config.h" 50 51#ifdef HAVE_SYS_CDEFS_H 52#include <sys/cdefs.h> 53#endif 54 55#if defined(__NetBSD__) 56__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); 57__RCSID("$NetBSD: validate.c,v 1.42 2010/11/07 08:39:59 agc Exp $"); 58#endif 59 60#include <sys/types.h> 61#include <sys/param.h> 62#include <sys/stat.h> 63 64#include <string.h> 65#include <stdio.h> 66 67#ifdef HAVE_UNISTD_H 68#include <unistd.h> 69#endif 70 71#ifdef HAVE_FCNTL_H 72#include <fcntl.h> 73#endif 74 75#include "packet-parse.h" 76#include "packet-show.h" 77#include "keyring.h" 78#include "signature.h" 79#include "netpgpsdk.h" 80#include "readerwriter.h" 81#include "netpgpdefs.h" 82#include "memory.h" 83#include "packet.h" 84#include "crypto.h" 85#include "validate.h" 86 87#ifdef HAVE_FCNTL_H 88#include <fcntl.h> 89#endif 90 91 92static int 93keydata_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors, 94 pgp_reader_t *readinfo, 95 pgp_cbdata_t *cbinfo) 96{ 97 validate_reader_t *reader = pgp_reader_get_arg(readinfo); 98 99 __PGP_USED(stream); 100 __PGP_USED(errors); 101 __PGP_USED(cbinfo); 102 if (reader->offset == reader->key->packets[reader->packet].length) { 103 reader->packet += 1; 104 reader->offset = 0; 105 } 106 if (reader->packet == reader->key->packetc) { 107 return 0; 108 } 109 110 /* 111 * we should never be asked to cross a packet boundary in a single 112 * read 113 */ 114 if (reader->key->packets[reader->packet].length < 115 reader->offset + length) { 116 (void) fprintf(stderr, "keydata_reader: weird length\n"); 117 return 0; 118 } 119 120 (void) memcpy(dest, 121 &reader->key->packets[reader->packet].raw[reader->offset], 122 length); 123 reader->offset += (unsigned)length; 124 125 return (int)length; 126} 127 128static void 129free_sig_info(pgp_sig_info_t *sig) 130{ 131 free(sig->v4_hashed); 132 free(sig); 133} 134 135static void 136copy_sig_info(pgp_sig_info_t *dst, const pgp_sig_info_t *src) 137{ 138 (void) memcpy(dst, src, sizeof(*src)); 139 if ((dst->v4_hashed = calloc(1, src->v4_hashlen)) == NULL) { 140 (void) fprintf(stderr, "copy_sig_info: bad alloc\n"); 141 } else { 142 (void) memcpy(dst->v4_hashed, src->v4_hashed, src->v4_hashlen); 143 } 144} 145 146static int 147add_sig_to_list(const pgp_sig_info_t *sig, pgp_sig_info_t **sigs, 148 unsigned *count) 149{ 150 pgp_sig_info_t *newsigs; 151 152 if (*count == 0) { 153 newsigs = calloc(*count + 1, sizeof(pgp_sig_info_t)); 154 } else { 155 newsigs = realloc(*sigs, 156 (*count + 1) * sizeof(pgp_sig_info_t)); 157 } 158 if (newsigs == NULL) { 159 (void) fprintf(stderr, "add_sig_to_list: alloc failure\n"); 160 return 0; 161 } 162 *sigs = newsigs; 163 copy_sig_info(&(*sigs)[*count], sig); 164 *count += 1; 165 return 1; 166} 167 168/* 169The hash value is calculated by the following method: 170+ hash the data using the given digest algorithm 171+ hash the hash value onto the end 172+ hash the trailer - 6 bytes 173 [PGP_V4][0xff][len >> 24][len >> 16][len >> 8][len & 0xff] 174to give the final hash value that is checked against the one in the signature 175*/ 176 177/* Does the signed hash match the given hash? */ 178unsigned 179check_binary_sig(const uint8_t *data, 180 const unsigned len, 181 const pgp_sig_t *sig, 182 const pgp_pubkey_t *signer) 183{ 184 unsigned hashedlen; 185 pgp_hash_t hash; 186 unsigned n; 187 uint8_t hashout[PGP_MAX_HASH_SIZE]; 188 uint8_t trailer[6]; 189 190 pgp_hash_any(&hash, sig->info.hash_alg); 191 if (!hash.init(&hash)) { 192 (void) fprintf(stderr, "check_binary_sig: bad hash init\n"); 193 return 0; 194 } 195 hash.add(&hash, data, len); 196 switch (sig->info.version) { 197 case PGP_V3: 198 trailer[0] = sig->info.type; 199 trailer[1] = (unsigned)(sig->info.birthtime) >> 24; 200 trailer[2] = (unsigned)(sig->info.birthtime) >> 16; 201 trailer[3] = (unsigned)(sig->info.birthtime) >> 8; 202 trailer[4] = (uint8_t)(sig->info.birthtime); 203 hash.add(&hash, trailer, 5); 204 break; 205 206 case PGP_V4: 207 if (pgp_get_debug_level(__FILE__)) { 208 hexdump(stderr, "v4 hash", sig->info.v4_hashed, 209 sig->info.v4_hashlen); 210 } 211 hash.add(&hash, sig->info.v4_hashed, (unsigned)sig->info.v4_hashlen); 212 trailer[0] = 0x04; /* version */ 213 trailer[1] = 0xFF; 214 hashedlen = (unsigned)sig->info.v4_hashlen; 215 trailer[2] = (uint8_t)(hashedlen >> 24); 216 trailer[3] = (uint8_t)(hashedlen >> 16); 217 trailer[4] = (uint8_t)(hashedlen >> 8); 218 trailer[5] = (uint8_t)(hashedlen); 219 hash.add(&hash, trailer, 6); 220 break; 221 222 default: 223 (void) fprintf(stderr, "Invalid signature version %d\n", 224 sig->info.version); 225 return 0; 226 } 227 228 n = hash.finish(&hash, hashout); 229 if (pgp_get_debug_level(__FILE__)) { 230 hexdump(stdout, "hash out", hashout, n); 231 } 232 return pgp_check_sig(hashout, n, sig, signer); 233} 234 235pgp_cb_ret_t 236pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) 237{ 238 const pgp_contents_t *content = &pkt->u; 239 const pgp_key_t *signer; 240 validate_key_cb_t *key; 241 pgp_pubkey_t *sigkey; 242 pgp_error_t **errors; 243 pgp_io_t *io; 244 unsigned from; 245 unsigned valid = 0; 246 247 io = cbinfo->io; 248 if (pgp_get_debug_level(__FILE__)) { 249 (void) fprintf(io->errs, "%s\n", 250 pgp_show_packet_tag(pkt->tag)); 251 } 252 key = pgp_callback_arg(cbinfo); 253 errors = pgp_callback_errors(cbinfo); 254 switch (pkt->tag) { 255 case PGP_PTAG_CT_PUBLIC_KEY: 256 if (key->pubkey.version != 0) { 257 (void) fprintf(io->errs, 258 "pgp_validate_key_cb: version bad\n"); 259 return PGP_FINISHED; 260 } 261 key->pubkey = content->pubkey; 262 return PGP_KEEP_MEMORY; 263 264 case PGP_PTAG_CT_PUBLIC_SUBKEY: 265 if (key->subkey.version) { 266 pgp_pubkey_free(&key->subkey); 267 } 268 key->subkey = content->pubkey; 269 return PGP_KEEP_MEMORY; 270 271 case PGP_PTAG_CT_SECRET_KEY: 272 key->seckey = content->seckey; 273 key->pubkey = key->seckey.pubkey; 274 return PGP_KEEP_MEMORY; 275 276 case PGP_PTAG_CT_USER_ID: 277 if (key->userid) { 278 pgp_userid_free(&key->userid); 279 } 280 key->userid = content->userid; 281 key->last_seen = ID; 282 return PGP_KEEP_MEMORY; 283 284 case PGP_PTAG_CT_USER_ATTR: 285 if (content->userattr.len == 0) { 286 (void) fprintf(io->errs, 287 "pgp_validate_key_cb: user attribute length 0"); 288 return PGP_FINISHED; 289 } 290 (void) fprintf(io->outs, "user attribute, length=%d\n", 291 (int) content->userattr.len); 292 if (key->userattr.len) { 293 pgp_data_free(&key->userattr); 294 } 295 key->userattr = content->userattr; 296 key->last_seen = ATTRIBUTE; 297 return PGP_KEEP_MEMORY; 298 299 case PGP_PTAG_CT_SIGNATURE: /* V3 sigs */ 300 case PGP_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */ 301 from = 0; 302 signer = pgp_getkeybyid(io, key->keyring, 303 content->sig.info.signer_id, 304 &from, &sigkey); 305 if (!signer) { 306 if (!add_sig_to_list(&content->sig.info, 307 &key->result->unknown_sigs, 308 &key->result->unknownc)) { 309 (void) fprintf(io->errs, 310 "pgp_validate_key_cb: user attribute length 0"); 311 return PGP_FINISHED; 312 } 313 break; 314 } 315 if (sigkey == &signer->enckey) { 316 (void) fprintf(io->errs, 317 "WARNING: signature made with encryption key\n"); 318 } 319 switch (content->sig.info.type) { 320 case PGP_CERT_GENERIC: 321 case PGP_CERT_PERSONA: 322 case PGP_CERT_CASUAL: 323 case PGP_CERT_POSITIVE: 324 case PGP_SIG_REV_CERT: 325 valid = (key->last_seen == ID) ? 326 pgp_check_useridcert_sig(&key->pubkey, 327 key->userid, 328 &content->sig, 329 pgp_get_pubkey(signer), 330 key->reader->key->packets[ 331 key->reader->packet].raw) : 332 pgp_check_userattrcert_sig(&key->pubkey, 333 &key->userattr, 334 &content->sig, 335 pgp_get_pubkey(signer), 336 key->reader->key->packets[ 337 key->reader->packet].raw); 338 break; 339 340 case PGP_SIG_SUBKEY: 341 /* 342 * XXX: we should also check that the signer is the 343 * key we are validating, I think. 344 */ 345 valid = pgp_check_subkey_sig(&key->pubkey, 346 &key->subkey, 347 &content->sig, 348 pgp_get_pubkey(signer), 349 key->reader->key->packets[ 350 key->reader->packet].raw); 351 break; 352 353 case PGP_SIG_DIRECT: 354 valid = pgp_check_direct_sig(&key->pubkey, 355 &content->sig, 356 pgp_get_pubkey(signer), 357 key->reader->key->packets[ 358 key->reader->packet].raw); 359 break; 360 361 case PGP_SIG_STANDALONE: 362 case PGP_SIG_PRIMARY: 363 case PGP_SIG_REV_KEY: 364 case PGP_SIG_REV_SUBKEY: 365 case PGP_SIG_TIMESTAMP: 366 case PGP_SIG_3RD_PARTY: 367 PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, 368 "Sig Verification type 0x%02x not done yet\n", 369 content->sig.info.type); 370 break; 371 372 default: 373 PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, 374 "Unexpected signature type 0x%02x\n", 375 content->sig.info.type); 376 } 377 378 if (valid) { 379 if (!add_sig_to_list(&content->sig.info, 380 &key->result->valid_sigs, 381 &key->result->validc)) { 382 PGP_ERROR(errors, PGP_E_UNIMPLEMENTED, 383 "Can't add good sig to list\n"); 384 } 385 } else { 386 PGP_ERROR(errors, PGP_E_V_BAD_SIGNATURE, "Bad Sig"); 387 if (!add_sig_to_list(&content->sig.info, 388 &key->result->invalid_sigs, 389 &key->result->invalidc)) { 390 PGP_ERROR(errors, PGP_E_UNIMPLEMENTED, 391 "Can't add good sig to list\n"); 392 } 393 } 394 break; 395 396 /* ignore these */ 397 case PGP_PARSER_PTAG: 398 case PGP_PTAG_CT_SIGNATURE_HEADER: 399 case PGP_PARSER_PACKET_END: 400 break; 401 402 case PGP_GET_PASSPHRASE: 403 if (key->getpassphrase) { 404 return key->getpassphrase(pkt, cbinfo); 405 } 406 break; 407 408 case PGP_PTAG_CT_TRUST: 409 /* 1 byte for level (depth), 1 byte for trust amount */ 410 printf("trust dump\n"); 411 printf("Got trust\n"); 412 //hexdump(stdout, (const uint8_t *)content->trust.data, 10, " "); 413 //hexdump(stdout, (const uint8_t *)&content->ss_trust, 2, " "); 414 //printf("Trust level %d, amount %d\n", key->trust.level, key->trust.amount); 415 break; 416 417 default: 418 (void) fprintf(stderr, "unexpected tag=0x%x\n", pkt->tag); 419 return PGP_FINISHED; 420 } 421 return PGP_RELEASE_MEMORY; 422} 423 424pgp_cb_ret_t 425validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) 426{ 427 const pgp_contents_t *content = &pkt->u; 428 const pgp_key_t *signer; 429 validate_data_cb_t *data; 430 pgp_pubkey_t *sigkey; 431 pgp_error_t **errors; 432 pgp_io_t *io; 433 unsigned from; 434 unsigned valid = 0; 435 436 io = cbinfo->io; 437 if (pgp_get_debug_level(__FILE__)) { 438 (void) fprintf(io->errs, "validate_data_cb: %s\n", 439 pgp_show_packet_tag(pkt->tag)); 440 } 441 data = pgp_callback_arg(cbinfo); 442 errors = pgp_callback_errors(cbinfo); 443 switch (pkt->tag) { 444 case PGP_PTAG_CT_SIGNED_CLEARTEXT_HEADER: 445 /* 446 * ignore - this gives us the "Armor Header" line "Hash: 447 * SHA1" or similar 448 */ 449 break; 450 451 case PGP_PTAG_CT_LITDATA_HEADER: 452 /* ignore */ 453 break; 454 455 case PGP_PTAG_CT_LITDATA_BODY: 456 data->data.litdata_body = content->litdata_body; 457 data->type = LITDATA; 458 pgp_memory_add(data->mem, data->data.litdata_body.data, 459 data->data.litdata_body.length); 460 return PGP_KEEP_MEMORY; 461 462 case PGP_PTAG_CT_SIGNED_CLEARTEXT_BODY: 463 data->data.cleartext_body = content->cleartext_body; 464 data->type = SIGNED_CLEARTEXT; 465 pgp_memory_add(data->mem, data->data.cleartext_body.data, 466 data->data.cleartext_body.length); 467 return PGP_KEEP_MEMORY; 468 469 case PGP_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: 470 /* this gives us an pgp_hash_t struct */ 471 break; 472 473 case PGP_PTAG_CT_SIGNATURE: /* V3 sigs */ 474 case PGP_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */ 475 if (pgp_get_debug_level(__FILE__)) { 476 hexdump(io->outs, "hashed data", content->sig.info.v4_hashed, 477 content->sig.info.v4_hashlen); 478 hexdump(io->outs, "signer id", content->sig.info.signer_id, 479 sizeof(content->sig.info.signer_id)); 480 } 481 from = 0; 482 signer = pgp_getkeybyid(io, data->keyring, 483 content->sig.info.signer_id, &from, &sigkey); 484 if (!signer) { 485 PGP_ERROR(errors, PGP_E_V_UNKNOWN_SIGNER, 486 "Unknown Signer"); 487 if (!add_sig_to_list(&content->sig.info, 488 &data->result->unknown_sigs, 489 &data->result->unknownc)) { 490 PGP_ERROR(errors, PGP_E_V_UNKNOWN_SIGNER, 491 "Can't add unknown sig to list"); 492 } 493 break; 494 } 495 if (sigkey == &signer->enckey) { 496 (void) fprintf(io->errs, 497 "WARNING: signature made with encryption key\n"); 498 } 499 if (content->sig.info.birthtime_set) { 500 data->result->birthtime = content->sig.info.birthtime; 501 } 502 if (content->sig.info.duration_set) { 503 data->result->duration = content->sig.info.duration; 504 } 505 switch (content->sig.info.type) { 506 case PGP_SIG_BINARY: 507 case PGP_SIG_TEXT: 508 if (pgp_mem_len(data->mem) == 0 && 509 data->detachname) { 510 /* check we have seen some data */ 511 /* if not, need to read from detached name */ 512 (void) fprintf(io->errs, 513 "netpgp: assuming signed data in \"%s\"\n", 514 data->detachname); 515 data->mem = pgp_memory_new(); 516 pgp_mem_readfile(data->mem, data->detachname); 517 } 518 if (pgp_get_debug_level(__FILE__)) { 519 hexdump(stderr, "sig dump", (const uint8_t *)(const void *)&content->sig, 520 sizeof(content->sig)); 521 } 522 valid = check_binary_sig(pgp_mem_data(data->mem), 523 (const unsigned)pgp_mem_len(data->mem), 524 &content->sig, 525 pgp_get_pubkey(signer)); 526 break; 527 528 default: 529 PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, 530 "No Sig Verification type 0x%02x yet\n", 531 content->sig.info.type); 532 break; 533 534 } 535 536 if (valid) { 537 if (!add_sig_to_list(&content->sig.info, 538 &data->result->valid_sigs, 539 &data->result->validc)) { 540 PGP_ERROR(errors, PGP_E_V_BAD_SIGNATURE, 541 "Can't add good sig to list"); 542 } 543 } else { 544 PGP_ERROR(errors, PGP_E_V_BAD_SIGNATURE, 545 "Bad Signature"); 546 if (!add_sig_to_list(&content->sig.info, 547 &data->result->invalid_sigs, 548 &data->result->invalidc)) { 549 PGP_ERROR(errors, PGP_E_V_BAD_SIGNATURE, 550 "Can't add good sig to list"); 551 } 552 } 553 break; 554 555 /* ignore these */ 556 case PGP_PARSER_PTAG: 557 case PGP_PTAG_CT_SIGNATURE_HEADER: 558 case PGP_PTAG_CT_ARMOUR_HEADER: 559 case PGP_PTAG_CT_ARMOUR_TRAILER: 560 case PGP_PTAG_CT_1_PASS_SIG: 561 break; 562 563 case PGP_PARSER_PACKET_END: 564 break; 565 566 default: 567 PGP_ERROR(errors, PGP_E_V_NO_SIGNATURE, "No signature"); 568 break; 569 } 570 return PGP_RELEASE_MEMORY; 571} 572 573static void 574keydata_destroyer(pgp_reader_t *readinfo) 575{ 576 free(pgp_reader_get_arg(readinfo)); 577} 578 579void 580pgp_keydata_reader_set(pgp_stream_t *stream, const pgp_key_t *key) 581{ 582 validate_reader_t *data; 583 584 if ((data = calloc(1, sizeof(*data))) == NULL) { 585 (void) fprintf(stderr, "pgp_keydata_reader_set: bad alloc\n"); 586 } else { 587 data->key = key; 588 data->packet = 0; 589 data->offset = 0; 590 pgp_reader_set(stream, keydata_reader, keydata_destroyer, data); 591 } 592} 593 594static char * 595fmtsecs(int64_t n, char *buf, size_t size) 596{ 597 if (n > 365 * 24 * 60 * 60) { 598 n /= (365 * 24 * 60 * 60); 599 (void) snprintf(buf, size, "%" PRId64 " year%s", n, (n == 1) ? "" : "s"); 600 return buf; 601 } 602 if (n > 30 * 24 * 60 * 60) { 603 n /= (30 * 24 * 60 * 60); 604 (void) snprintf(buf, size, "%" PRId64 " month%s", n, (n == 1) ? "" : "s"); 605 return buf; 606 } 607 if (n > 24 * 60 * 60) { 608 n /= (24 * 60 * 60); 609 (void) snprintf(buf, size, "%" PRId64 " day%s", n, (n == 1) ? "" : "s"); 610 return buf; 611 } 612 if (n > 60 * 60) { 613 n /= (60 * 60); 614 (void) snprintf(buf, size, "%" PRId64 " hour%s", n, (n == 1) ? "" : "s"); 615 return buf; 616 } 617 if (n > 60) { 618 n /= 60; 619 (void) snprintf(buf, size, "%" PRId64 " minute%s", n, (n == 1) ? "" : "s"); 620 return buf; 621 } 622 (void) snprintf(buf, size, "%" PRId64 " second%s", n, (n == 1) ? "" : "s"); 623 return buf; 624} 625 626/** 627 * \ingroup HighLevel_Verify 628 * \brief Indicicates whether any errors were found 629 * \param result Validation result to check 630 * \return 0 if any invalid signatures or unknown signers 631 or no valid signatures; else 1 632 */ 633static unsigned 634validate_result_status(FILE *errs, const char *f, pgp_validation_t *val) 635{ 636 time_t now; 637 time_t t; 638 char buf[128]; 639 640 now = time(NULL); 641 if (now < val->birthtime) { 642 /* signature is not valid yet! */ 643 if (f) { 644 (void) fprintf(errs, "\"%s\": ", f); 645 } else { 646 (void) fprintf(errs, "memory "); 647 } 648 (void) fprintf(errs, 649 "signature not valid until %.24s (%s)\n", 650 ctime(&val->birthtime), 651 fmtsecs((int64_t)(val->birthtime - now), buf, sizeof(buf))); 652 return 0; 653 } 654 if (val->duration != 0 && now > val->birthtime + val->duration) { 655 /* signature has expired */ 656 t = val->duration + val->birthtime; 657 if (f) { 658 (void) fprintf(errs, "\"%s\": ", f); 659 } else { 660 (void) fprintf(errs, "memory "); 661 } 662 (void) fprintf(errs, 663 "signature not valid after %.24s (%s ago)\n", 664 ctime(&t), 665 fmtsecs((int64_t)(now - t), buf, sizeof(buf))); 666 return 0; 667 } 668 return val->validc && !val->invalidc && !val->unknownc; 669} 670 671/** 672 * \ingroup HighLevel_Verify 673 * \brief Validate all signatures on a single key against the given keyring 674 * \param result Where to put the result 675 * \param key Key to validate 676 * \param keyring Keyring to use for validation 677 * \param cb_get_passphrase Callback to use to get passphrase 678 * \return 1 if all signatures OK; else 0 679 * \note It is the caller's responsiblity to free result after use. 680 * \sa pgp_validate_result_free() 681 */ 682unsigned 683pgp_validate_key_sigs(pgp_validation_t *result, 684 const pgp_key_t *key, 685 const pgp_keyring_t *keyring, 686 pgp_cb_ret_t cb_get_passphrase(const pgp_packet_t *, 687 pgp_cbdata_t *)) 688{ 689 pgp_stream_t *stream; 690 validate_key_cb_t keysigs; 691 const int printerrors = 1; 692 693 (void) memset(&keysigs, 0x0, sizeof(keysigs)); 694 keysigs.result = result; 695 keysigs.getpassphrase = cb_get_passphrase; 696 697 stream = pgp_new(sizeof(*stream)); 698 /* pgp_parse_options(&opt,PGP_PTAG_CT_SIGNATURE,PGP_PARSE_PARSED); */ 699 700 keysigs.keyring = keyring; 701 702 pgp_set_callback(stream, pgp_validate_key_cb, &keysigs); 703 stream->readinfo.accumulate = 1; 704 pgp_keydata_reader_set(stream, key); 705 706 /* Note: Coverity incorrectly reports an error that keysigs.reader */ 707 /* is never used. */ 708 keysigs.reader = stream->readinfo.arg; 709 710 pgp_parse(stream, !printerrors); 711 712 pgp_pubkey_free(&keysigs.pubkey); 713 if (keysigs.subkey.version) { 714 pgp_pubkey_free(&keysigs.subkey); 715 } 716 pgp_userid_free(&keysigs.userid); 717 pgp_data_free(&keysigs.userattr); 718 719 pgp_stream_delete(stream); 720 721 return (!result->invalidc && !result->unknownc && result->validc); 722} 723 724/** 725 \ingroup HighLevel_Verify 726 \param result Where to put the result 727 \param ring Keyring to use 728 \param cb_get_passphrase Callback to use to get passphrase 729 \note It is the caller's responsibility to free result after use. 730 \sa pgp_validate_result_free() 731*/ 732unsigned 733pgp_validate_all_sigs(pgp_validation_t *result, 734 const pgp_keyring_t *ring, 735 pgp_cb_ret_t cb_get_passphrase(const pgp_packet_t *, 736 pgp_cbdata_t *)) 737{ 738 unsigned n; 739 740 (void) memset(result, 0x0, sizeof(*result)); 741 for (n = 0; n < ring->keyc; ++n) { 742 pgp_validate_key_sigs(result, &ring->keys[n], ring, 743 cb_get_passphrase); 744 } 745 return validate_result_status(stderr, "keyring", result); 746} 747 748/** 749 \ingroup HighLevel_Verify 750 \brief Frees validation result and associated memory 751 \param result Struct to be freed 752 \note Must be called after validation functions 753*/ 754void 755pgp_validate_result_free(pgp_validation_t *result) 756{ 757 if (result != NULL) { 758 if (result->valid_sigs) { 759 free_sig_info(result->valid_sigs); 760 } 761 if (result->invalid_sigs) { 762 free_sig_info(result->invalid_sigs); 763 } 764 if (result->unknown_sigs) { 765 free_sig_info(result->unknown_sigs); 766 } 767 free(result); 768 /* result = NULL; - XXX unnecessary */ 769 } 770} 771 772/** 773 \ingroup HighLevel_Verify 774 \brief Verifies the signatures in a signed file 775 \param result Where to put the result 776 \param filename Name of file to be validated 777 \param armoured Treat file as armoured, if set 778 \param keyring Keyring to use 779 \return 1 if signatures validate successfully; 780 0 if signatures fail or there are no signatures 781 \note After verification, result holds the details of all keys which 782 have passed, failed and not been recognised. 783 \note It is the caller's responsiblity to call 784 pgp_validate_result_free(result) after use. 785*/ 786unsigned 787pgp_validate_file(pgp_io_t *io, 788 pgp_validation_t *result, 789 const char *infile, 790 const char *outfile, 791 const int user_says_armoured, 792 const pgp_keyring_t *keyring) 793{ 794 validate_data_cb_t validation; 795 pgp_stream_t *parse = NULL; 796 struct stat st; 797 const char *signame; 798 const int printerrors = 1; 799 unsigned ret; 800 char f[MAXPATHLEN]; 801 char *dataname; 802 int realarmour; 803 int outfd = 0; 804 int infd; 805 int cc; 806 807 if (stat(infile, &st) < 0) { 808 (void) fprintf(io->errs, 809 "pgp_validate_file: can't open '%s'\n", infile); 810 return 0; 811 } 812 realarmour = user_says_armoured; 813 dataname = NULL; 814 signame = NULL; 815 cc = snprintf(f, sizeof(f), "%s", infile); 816 if (strcmp(&f[cc - 4], ".sig") == 0) { 817 /* we've been given a sigfile as infile */ 818 f[cc - 4] = 0x0; 819 /* set dataname to name of file which was signed */ 820 dataname = f; 821 signame = infile; 822 } else if (strcmp(&f[cc - 4], ".asc") == 0) { 823 /* we've been given an armored sigfile as infile */ 824 f[cc - 4] = 0x0; 825 /* set dataname to name of file which was signed */ 826 dataname = f; 827 signame = infile; 828 realarmour = 1; 829 } else { 830 signame = infile; 831 } 832 (void) memset(&validation, 0x0, sizeof(validation)); 833 infd = pgp_setup_file_read(io, &parse, signame, &validation, 834 validate_data_cb, 1); 835 if (infd < 0) { 836 return 0; 837 } 838 839 if (dataname) { 840 validation.detachname = netpgp_strdup(dataname); 841 } 842 843 /* Set verification reader and handling options */ 844 validation.result = result; 845 validation.keyring = keyring; 846 validation.mem = pgp_memory_new(); 847 pgp_memory_init(validation.mem, 128); 848 /* Note: Coverity incorrectly reports an error that validation.reader */ 849 /* is never used. */ 850 validation.reader = parse->readinfo.arg; 851 852 if (realarmour) { 853 pgp_reader_push_dearmour(parse); 854 } 855 856 /* Do the verification */ 857 pgp_parse(parse, !printerrors); 858 859 /* Tidy up */ 860 if (realarmour) { 861 pgp_reader_pop_dearmour(parse); 862 } 863 pgp_teardown_file_read(parse, infd); 864 865 ret = validate_result_status(io->errs, infile, result); 866 867 /* this is triggered only for --cat output */ 868 if (outfile) { 869 /* need to send validated output somewhere */ 870 if (strcmp(outfile, "-") == 0) { 871 outfd = STDOUT_FILENO; 872 } else { 873 outfd = open(outfile, O_WRONLY | O_CREAT, 0666); 874 } 875 if (outfd < 0) { 876 /* even if the signature was good, we can't 877 * write the file, so send back a bad return 878 * code */ 879 ret = 0; 880 } else if (validate_result_status(io->errs, infile, result)) { 881 unsigned len; 882 char *cp; 883 int i; 884 885 len = (unsigned)pgp_mem_len(validation.mem); 886 cp = pgp_mem_data(validation.mem); 887 for (i = 0 ; i < (int)len ; i += cc) { 888 cc = (int)write(outfd, &cp[i], (unsigned)(len - i)); 889 if (cc < 0) { 890 (void) fprintf(io->errs, 891 "netpgp: short write\n"); 892 ret = 0; 893 break; 894 } 895 } 896 if (strcmp(outfile, "-") != 0) { 897 (void) close(outfd); 898 } 899 } 900 } 901 pgp_memory_free(validation.mem); 902 return ret; 903} 904 905/** 906 \ingroup HighLevel_Verify 907 \brief Verifies the signatures in a pgp_memory_t struct 908 \param result Where to put the result 909 \param mem Memory to be validated 910 \param user_says_armoured Treat data as armoured, if set 911 \param keyring Keyring to use 912 \return 1 if signature validates successfully; 0 if not 913 \note After verification, result holds the details of all keys which 914 have passed, failed and not been recognised. 915 \note It is the caller's responsiblity to call 916 pgp_validate_result_free(result) after use. 917*/ 918 919unsigned 920pgp_validate_mem(pgp_io_t *io, 921 pgp_validation_t *result, 922 pgp_memory_t *mem, 923 pgp_memory_t **cat, 924 const int user_says_armoured, 925 const pgp_keyring_t *keyring) 926{ 927 validate_data_cb_t validation; 928 pgp_stream_t *stream = NULL; 929 const int printerrors = 1; 930 int realarmour; 931 932 pgp_setup_memory_read(io, &stream, mem, &validation, validate_data_cb, 1); 933 /* Set verification reader and handling options */ 934 (void) memset(&validation, 0x0, sizeof(validation)); 935 validation.result = result; 936 validation.keyring = keyring; 937 validation.mem = pgp_memory_new(); 938 pgp_memory_init(validation.mem, 128); 939 /* Note: Coverity incorrectly reports an error that validation.reader */ 940 /* is never used. */ 941 validation.reader = stream->readinfo.arg; 942 943 if ((realarmour = user_says_armoured) != 0 || 944 strncmp(pgp_mem_data(mem), 945 "-----BEGIN PGP MESSAGE-----", 27) == 0) { 946 realarmour = 1; 947 } 948 if (realarmour) { 949 pgp_reader_push_dearmour(stream); 950 } 951 952 /* Do the verification */ 953 pgp_parse(stream, !printerrors); 954 955 /* Tidy up */ 956 if (realarmour) { 957 pgp_reader_pop_dearmour(stream); 958 } 959 pgp_teardown_memory_read(stream, mem); 960 961 /* this is triggered only for --cat output */ 962 if (cat) { 963 /* need to send validated output somewhere */ 964 *cat = validation.mem; 965 } else { 966 pgp_memory_free(validation.mem); 967 } 968 969 return validate_result_status(io->errs, NULL, result); 970} 971