1 /* 2 * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) 3 * All rights reserved. 4 * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted 5 * their moral rights under the UK Copyright Design and Patents Act 1988 to 6 * be recorded as the authors of this copyright work. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 9 * use this file except in compliance with the License. 10 * 11 * You may obtain a copy of the License at 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 #include "config.h" 22 23 #include <sys/types.h> 24 #include <sys/stat.h> 25 26 #ifdef HAVE_SYS_MMAN_H 27 #include <sys/mman.h> 28 #endif 29 30 #ifdef HAVE_SYS_PARAM_H 31 #include <sys/param.h> 32 #endif 33 34 #include <fcntl.h> 35 36 #ifdef HAVE_UNISTD_H 37 #include <unistd.h> 38 #endif 39 40 #ifdef HAVE_DIRECT_H 41 #include <direct.h> 42 #endif 43 44 #ifdef HAVE_ASSERT_H 45 #include <assert.h> 46 #endif 47 48 #ifdef HAVE_INTTYPES_H 49 #include <inttypes.h> 50 #endif 51 52 #ifdef HAVE_OPENSSL_IDEA_H 53 #include <openssl/cast.h> 54 #endif 55 56 #ifdef HAVE_OPENSSL_IDEA_H 57 #include <openssl/idea.h> 58 #endif 59 60 #ifdef HAVE_OPENSSL_AES_H 61 #include <openssl/aes.h> 62 #endif 63 64 #ifdef HAVE_OPENSSL_DES_H 65 #include <openssl/des.h> 66 #endif 67 68 #include <string.h> 69 #include <stdarg.h> 70 #include <stdlib.h> 71 #include <stdio.h> 72 73 #ifdef HAVE_TERMIOS_H 74 #include <termios.h> 75 #endif 76 77 #ifdef HAVE_ERRNO_H 78 #include <errno.h> 79 #endif 80 81 #ifdef HAVE_UNISTD_H 82 #include <unistd.h> 83 #endif 84 85 #ifdef HAVE_LIMITS_H 86 #include <limits.h> 87 #endif 88 89 #include "errors.h" 90 #include "crypto.h" 91 #include "create.h" 92 #include "signature.h" 93 #include "packet.h" 94 #include "packet-parse.h" 95 #include "packet-show.h" 96 #include "packet.h" 97 #include "keyring.h" 98 99 #include "readerwriter.h" 100 #include "netpgpdefs.h" 101 #include "version.h" 102 #include "parse_local.h" 103 104 105 /** 106 * \ingroup Internal_Readers_Generic 107 * \brief Starts reader stack 108 * \param pinfo Parse settings 109 * \param reader Reader to use 110 * \param destroyer Destroyer to use 111 * \param vp Reader-specific arg 112 */ 113 void 114 __ops_reader_set(__ops_parse_info_t * pinfo, __ops_reader_t * reader, __ops_reader_destroyer_t * destroyer, void *vp) 115 { 116 pinfo->rinfo.reader = reader; 117 pinfo->rinfo.destroyer = destroyer; 118 pinfo->rinfo.arg = vp; 119 } 120 121 /** 122 * \ingroup Internal_Readers_Generic 123 * \brief Adds to reader stack 124 * \param pinfo Parse settings 125 * \param reader Reader to use 126 * \param destroyer Reader's destroyer 127 * \param vp Reader-specific arg 128 */ 129 void 130 __ops_reader_push(__ops_parse_info_t * pinfo, __ops_reader_t * reader, __ops_reader_destroyer_t * destroyer, void *vp) 131 { 132 __ops_reader_info_t *rinfo = calloc(1, sizeof(*rinfo)); 133 134 *rinfo = pinfo->rinfo; 135 (void) memset(&pinfo->rinfo, 0x0, sizeof(pinfo->rinfo)); 136 pinfo->rinfo.next = rinfo; 137 pinfo->rinfo.pinfo = pinfo; 138 139 /* should copy accumulate flags from other reader? RW */ 140 pinfo->rinfo.accumulate = rinfo->accumulate; 141 142 __ops_reader_set(pinfo, reader, destroyer, vp); 143 } 144 145 /** 146 * \ingroup Internal_Readers_Generic 147 * \brief Removes from reader stack 148 * \param pinfo Parse settings 149 */ 150 void 151 __ops_reader_pop(__ops_parse_info_t * pinfo) 152 { 153 __ops_reader_info_t *next = pinfo->rinfo.next; 154 155 pinfo->rinfo = *next; 156 free(next); 157 } 158 159 /** 160 * \ingroup Internal_Readers_Generic 161 * \brief Gets arg from reader 162 * \param rinfo Reader info 163 * \return Pointer to reader info's arg 164 */ 165 void * 166 __ops_reader_get_arg(__ops_reader_info_t * rinfo) 167 { 168 return rinfo->arg; 169 } 170 171 /**************************************************************************/ 172 173 #define CRC24_POLY 0x1864cfbL 174 175 /** 176 * \struct dearmour_t 177 */ 178 typedef struct { 179 enum { 180 OUTSIDE_BLOCK = 0, 181 BASE64, 182 AT_TRAILER_NAME, 183 } state; 184 185 enum { 186 NONE = 0, 187 BEGIN_PGP_MESSAGE, 188 BEGIN_PGP_PUBLIC_KEY_BLOCK, 189 BEGIN_PGP_PRIVATE_KEY_BLOCK, 190 BEGIN_PGP_MULTI, 191 BEGIN_PGP_SIGNATURE, 192 193 END_PGP_MESSAGE, 194 END_PGP_PUBLIC_KEY_BLOCK, 195 END_PGP_PRIVATE_KEY_BLOCK, 196 END_PGP_MULTI, 197 END_PGP_SIGNATURE, 198 199 BEGIN_PGP_SIGNED_MESSAGE 200 } lastseen; 201 202 __ops_parse_info_t *parse_info; 203 unsigned seen_nl:1; 204 unsigned prev_nl:1; 205 unsigned allow_headers_without_gap:1; /* !< allow headers in 206 * armoured data that 207 * are not separated 208 * from the data by a 209 * blank line */ 210 unsigned allow_no_gap:1; /* !< allow no blank line at the 211 * start of armoured data */ 212 unsigned allow_trailing_whitespace:1; /* !< allow armoured 213 * stuff to have 214 * trailing whitespace 215 * where we wouldn't 216 * strictly expect it */ 217 218 /* it is an error to get a cleartext message without a sig */ 219 unsigned expect_sig:1; 220 unsigned got_sig:1; 221 222 /* base64 stuff */ 223 unsigned buffered; 224 unsigned char buffer[3]; 225 bool eof64; 226 unsigned long checksum; 227 unsigned long read_checksum; 228 /* unarmoured text blocks */ 229 unsigned char unarmoured[NETPGP_BUFSIZ]; 230 size_t num_unarmoured; 231 /* pushed back data (stored backwards) */ 232 unsigned char *pushed_back; 233 unsigned npushed_back; 234 /* armoured block headers */ 235 __ops_headers_t headers; 236 } dearmour_t; 237 238 static void 239 push_back(dearmour_t * dearmour, const unsigned char *buf, 240 unsigned length) 241 { 242 unsigned n; 243 244 assert(!dearmour->pushed_back); 245 dearmour->pushed_back = calloc(1, length); 246 for (n = 0; n < length; ++n) { 247 dearmour->pushed_back[n] = buf[length - n - 1]; 248 } 249 dearmour->npushed_back = length; 250 } 251 252 static int 253 set_lastseen_headerline(dearmour_t * dearmour, char *buf, __ops_error_t ** errors) 254 { 255 const char *begin_msg = "BEGIN PGP MESSAGE"; 256 const char *begin_public = "BEGIN PGP PUBLIC KEY BLOCK"; 257 const char *begin_private = "BEGIN PGP PRIVATE KEY BLOCK"; 258 const char *begin_multi = "BEGIN PGP MESSAGE, PART "; 259 const char *begin_sig = "BEGIN PGP SIGNATURE"; 260 261 const char *end_msg = "END PGP MESSAGE"; 262 const char *end_public = "END PGP PUBLIC KEY BLOCK"; 263 const char *end_private = "END PGP PRIVATE KEY BLOCK"; 264 const char *end_multi = "END PGP MESSAGE, PART "; 265 const char *end_sig = "END PGP SIGNATURE"; 266 267 const char *begin_signed_msg = "BEGIN PGP SIGNED MESSAGE"; 268 269 int prev = dearmour->lastseen; 270 271 if (!strncmp(buf, begin_msg, strlen(begin_msg))) 272 dearmour->lastseen = BEGIN_PGP_MESSAGE; 273 else if (!strncmp(buf, begin_public, strlen(begin_public))) 274 dearmour->lastseen = BEGIN_PGP_PUBLIC_KEY_BLOCK; 275 else if (!strncmp(buf, begin_private, strlen(begin_private))) 276 dearmour->lastseen = BEGIN_PGP_PRIVATE_KEY_BLOCK; 277 else if (!strncmp(buf, begin_multi, strlen(begin_multi))) 278 dearmour->lastseen = BEGIN_PGP_MULTI; 279 else if (!strncmp(buf, begin_sig, strlen(begin_sig))) 280 dearmour->lastseen = BEGIN_PGP_SIGNATURE; 281 282 else if (!strncmp(buf, end_msg, strlen(end_msg))) 283 dearmour->lastseen = END_PGP_MESSAGE; 284 else if (!strncmp(buf, end_public, strlen(end_public))) 285 dearmour->lastseen = END_PGP_PUBLIC_KEY_BLOCK; 286 else if (!strncmp(buf, end_private, strlen(end_private))) 287 dearmour->lastseen = END_PGP_PRIVATE_KEY_BLOCK; 288 else if (!strncmp(buf, end_multi, strlen(end_multi))) 289 dearmour->lastseen = END_PGP_MULTI; 290 else if (!strncmp(buf, end_sig, strlen(end_sig))) 291 dearmour->lastseen = END_PGP_SIGNATURE; 292 293 else if (!strncmp(buf, begin_signed_msg, strlen(begin_signed_msg))) 294 dearmour->lastseen = BEGIN_PGP_SIGNED_MESSAGE; 295 296 else { 297 OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, "Unrecognised Header Line %s", buf); 298 return 0; 299 } 300 301 if (__ops_get_debug_level(__FILE__)) 302 printf("set header: buf=%s, dearmour->lastseen=%d, prev=%d\n", buf, dearmour->lastseen, prev); 303 304 switch (dearmour->lastseen) { 305 case NONE: 306 OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, "Unrecognised last seen Header Line %s", buf); 307 break; 308 309 case END_PGP_MESSAGE: 310 if (prev != BEGIN_PGP_MESSAGE) 311 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Got END PGP MESSAGE, but not after BEGIN"); 312 break; 313 314 case END_PGP_PUBLIC_KEY_BLOCK: 315 if (prev != BEGIN_PGP_PUBLIC_KEY_BLOCK) 316 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Got END PGP PUBLIC KEY BLOCK, but not after BEGIN"); 317 break; 318 319 case END_PGP_PRIVATE_KEY_BLOCK: 320 if (prev != BEGIN_PGP_PRIVATE_KEY_BLOCK) 321 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Got END PGP PRIVATE KEY BLOCK, but not after BEGIN"); 322 break; 323 324 case BEGIN_PGP_MULTI: 325 case END_PGP_MULTI: 326 OPS_ERROR(errors, OPS_E_R_UNSUPPORTED, "Multi-part messages are not yet supported"); 327 break; 328 329 case END_PGP_SIGNATURE: 330 if (prev != BEGIN_PGP_SIGNATURE) 331 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Got END PGP SIGNATURE, but not after BEGIN"); 332 break; 333 334 case BEGIN_PGP_MESSAGE: 335 case BEGIN_PGP_PUBLIC_KEY_BLOCK: 336 case BEGIN_PGP_PRIVATE_KEY_BLOCK: 337 case BEGIN_PGP_SIGNATURE: 338 case BEGIN_PGP_SIGNED_MESSAGE: 339 break; 340 } 341 342 return 1; 343 } 344 345 static int 346 read_char(dearmour_t * dearmour, __ops_error_t ** errors, 347 __ops_reader_info_t * rinfo, 348 __ops_parse_cb_info_t * cbinfo, 349 bool skip) 350 { 351 unsigned char c[1]; 352 353 do { 354 if (dearmour->npushed_back) { 355 c[0] = dearmour->pushed_back[--dearmour->npushed_back]; 356 if (!dearmour->npushed_back) { 357 free(dearmour->pushed_back); 358 dearmour->pushed_back = NULL; 359 } 360 } 361 /* 362 * XXX: should __ops_stacked_read exist? Shouldn't this be a 363 * limited_read? 364 */ 365 else if (__ops_stacked_read(c, 1, errors, rinfo, cbinfo) != 1) 366 return -1; 367 } 368 while (skip && c[0] == '\r'); 369 370 dearmour->prev_nl = dearmour->seen_nl; 371 dearmour->seen_nl = c[0] == '\n'; 372 373 return c[0]; 374 } 375 376 static int 377 eat_whitespace(int first, 378 dearmour_t * dearmour, __ops_error_t ** errors, 379 __ops_reader_info_t * rinfo, 380 __ops_parse_cb_info_t * cbinfo, 381 bool skip) 382 { 383 int c = first; 384 385 while (c == ' ' || c == '\t') 386 c = read_char(dearmour, errors, rinfo, cbinfo, skip); 387 388 return c; 389 } 390 391 static int 392 read_and_eat_whitespace(dearmour_t * dearmour, 393 __ops_error_t ** errors, 394 __ops_reader_info_t * rinfo, 395 __ops_parse_cb_info_t * cbinfo, 396 bool skip) 397 { 398 int c; 399 400 do { 401 c = read_char(dearmour, errors, rinfo, cbinfo, skip); 402 } while (c == ' ' || c == '\t'); 403 404 return c; 405 } 406 407 static void 408 flush(dearmour_t * dearmour, __ops_parse_cb_info_t * cbinfo) 409 { 410 __ops_parser_content_t content; 411 412 if (dearmour->num_unarmoured == 0) 413 return; 414 415 content.u.unarmoured_text.data = dearmour->unarmoured; 416 content.u.unarmoured_text.length = dearmour->num_unarmoured; 417 CALLBACK(cbinfo, OPS_PTAG_CT_UNARMOURED_TEXT, &content); 418 dearmour->num_unarmoured = 0; 419 } 420 421 static int 422 unarmoured_read_char(dearmour_t * dearmour, __ops_error_t ** errors, 423 __ops_reader_info_t * rinfo, 424 __ops_parse_cb_info_t * cbinfo, 425 bool skip) 426 { 427 int c; 428 429 do { 430 c = read_char(dearmour, errors, rinfo, cbinfo, false); 431 if (c < 0) { 432 return c; 433 } 434 dearmour->unarmoured[dearmour->num_unarmoured++] = c; 435 if (dearmour->num_unarmoured == sizeof(dearmour->unarmoured)) { 436 flush(dearmour, cbinfo); 437 } 438 } while (skip && c == '\r'); 439 440 return c; 441 } 442 443 /** 444 * \param headers 445 * \param key 446 * 447 * \return header value if found, otherwise NULL 448 */ 449 static const char * 450 __ops_find_header(__ops_headers_t * headers, const char *key) 451 { 452 unsigned n; 453 454 for (n = 0; n < headers->nheaders; ++n) { 455 if (strcmp(headers->headers[n].key, key) == 0) { 456 return headers->headers[n].value; 457 } 458 } 459 return NULL; 460 } 461 462 /** 463 * \param dest 464 * \param src 465 */ 466 static void 467 __ops_dup_headers(__ops_headers_t * dest, const __ops_headers_t * src) 468 { 469 unsigned n; 470 471 dest->headers = calloc(src->nheaders, sizeof(*dest->headers)); 472 dest->nheaders = src->nheaders; 473 474 for (n = 0; n < src->nheaders; ++n) { 475 dest->headers[n].key = strdup(src->headers[n].key); 476 dest->headers[n].value = strdup(src->headers[n].value); 477 } 478 } 479 480 /* 481 * Note that this skips CRs so implementations always see just straight LFs 482 * as line terminators 483 */ 484 static int 485 process_dash_escaped(dearmour_t * dearmour, __ops_error_t ** errors, 486 __ops_reader_info_t * rinfo, 487 __ops_parse_cb_info_t * cbinfo) 488 { 489 __ops_parser_content_t content; 490 __ops_parser_content_t content2; 491 __ops_signed_cleartext_body_t *body = &content.u.signed_cleartext_body; 492 __ops_signed_cleartext_trailer_t *trailer 493 = &content2.u.signed_cleartext_trailer; 494 const char *hashstr; 495 __ops_hash_t *hash; 496 int total; 497 498 hash = calloc(1, sizeof(*hash)); 499 hashstr = __ops_find_header(&dearmour->headers, "Hash"); 500 if (hashstr) { 501 __ops_hash_algorithm_t alg; 502 503 alg = __ops_hash_algorithm_from_text(hashstr); 504 505 if (!__ops_is_hash_alg_supported(&alg)) { 506 free(hash); 507 OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, "Unsupported hash algorithm '%s'", hashstr); 508 return -1; 509 } 510 if (alg == OPS_HASH_UNKNOWN) { 511 free(hash); 512 OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, "Unknown hash algorithm '%s'", hashstr); 513 return -1; 514 } 515 __ops_hash_any(hash, alg); 516 } else 517 __ops_hash_md5(hash); 518 519 hash->init(hash); 520 521 body->length = 0; 522 total = 0; 523 for (;;) { 524 int c; 525 unsigned count; 526 527 if ((c = read_char(dearmour, errors, rinfo, cbinfo, true)) < 0) 528 return -1; 529 if (dearmour->prev_nl && c == '-') { 530 if ((c = read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) 531 return -1; 532 if (c != ' ') { 533 /* then this had better be a trailer! */ 534 if (c != '-') 535 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad dash-escaping"); 536 for (count = 2; count < 5; ++count) { 537 if ((c = read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) { 538 return -1; 539 } 540 if (c != '-') { 541 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad dash-escaping (2)"); 542 } 543 } 544 dearmour->state = AT_TRAILER_NAME; 545 break; 546 } 547 /* otherwise we read the next character */ 548 if ((c = read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) { 549 return -1; 550 } 551 } 552 if (c == '\n' && body->length) { 553 assert(memchr(body->data + 1, '\n', body->length - 1) == NULL); 554 if (body->data[0] == '\n') { 555 hash->add(hash, (const unsigned char *) "\r", 1); 556 } 557 hash->add(hash, body->data, body->length); 558 if (__ops_get_debug_level(__FILE__)) { 559 fprintf(stderr, "Got body:\n%s\n", body->data); 560 } 561 CALLBACK(cbinfo, OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, &content); 562 body->length = 0; 563 } 564 body->data[body->length++] = c; 565 ++total; 566 if (body->length == sizeof(body->data)) { 567 if (__ops_get_debug_level(__FILE__)) { 568 fprintf(stderr, "Got body (2):\n%s\n", body->data); 569 } 570 CALLBACK(cbinfo, OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, &content); 571 body->length = 0; 572 } 573 } 574 575 assert(body->data[0] == '\n'); 576 assert(body->length == 1); 577 /* don't send that one character, because its part of the trailer. */ 578 579 trailer->hash = hash; 580 CALLBACK(cbinfo, OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, &content2); 581 582 return total; 583 } 584 585 static int 586 add_header(dearmour_t * dearmour, const char *key, const char 587 *value) 588 { 589 /* 590 * Check that the header is valid 591 */ 592 if (strcmp(key, "Version") == 0 || strcmp(key, "Comment") == 0 || 593 strcmp(key, "MessageID") == 0 || strcmp(key, "Hash") == 0 || 594 strcmp(key, "Charset") == 0) { 595 dearmour->headers.headers = realloc(dearmour->headers.headers, 596 (dearmour->headers.nheaders + 1) 597 * sizeof(*dearmour->headers.headers)); 598 dearmour->headers.headers[dearmour->headers.nheaders].key = strdup(key); 599 dearmour->headers.headers[dearmour->headers.nheaders].value = strdup(value); 600 ++dearmour->headers.nheaders; 601 return 1; 602 } else { 603 return 0; 604 } 605 } 606 607 /* \todo what does a return value of 0 indicate? 1 is good, -1 is bad */ 608 static int 609 parse_headers(dearmour_t * dearmour, __ops_error_t ** errors, 610 __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo) 611 { 612 unsigned nbuf; 613 unsigned size; 614 char *buf; 615 bool first = true; 616 int rtn = 1; 617 618 buf = NULL; 619 nbuf = size = 0; 620 621 for (;;) { 622 int c; 623 624 if ((c = read_char(dearmour, errors, rinfo, cbinfo, true)) < 0) { 625 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Unexpected EOF"); 626 rtn = -1; 627 break; 628 } 629 if (c == '\n') { 630 char *s; 631 632 if (nbuf == 0) { 633 break; 634 } 635 636 assert(nbuf < size); 637 buf[nbuf] = '\0'; 638 639 s = strchr(buf, ':'); 640 if (!s) 641 if (!first && !dearmour->allow_headers_without_gap) { 642 /* 643 * then we have seriously malformed 644 * armour 645 */ 646 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No colon in armour header"); 647 rtn = -1; 648 break; 649 } else { 650 if (first && 651 !(dearmour->allow_headers_without_gap || dearmour->allow_no_gap)) { 652 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No colon in armour header (2)"); 653 /* 654 * then we have a nasty 655 * armoured block with no 656 */ 657 /* 658 * headers, not even a blank 659 * line. 660 */ 661 buf[nbuf] = '\n'; 662 push_back(dearmour, (unsigned char *) buf, nbuf + 1); 663 rtn = -1; 664 break; 665 } 666 } 667 else { 668 *s = '\0'; 669 if (s[1] != ' ') { 670 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No space in armour header"); 671 rtn = -1; 672 goto end; 673 } 674 if (!add_header(dearmour, buf, s + 2)) { 675 OPS_ERROR_1(errors, OPS_E_R_BAD_FORMAT, "Invalid header %s", buf); 676 rtn = -1; 677 goto end; 678 } 679 nbuf = 0; 680 } 681 first = false; 682 } else { 683 if (size <= nbuf + 1) { 684 size += size + 80; 685 buf = realloc(buf, size); 686 } 687 buf[nbuf++] = c; 688 } 689 } 690 691 end: 692 free(buf); 693 694 return rtn; 695 } 696 697 static int 698 read4(dearmour_t * dearmour, __ops_error_t ** errors, 699 __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo, 700 int *pc, unsigned *pn, unsigned long *pl) 701 { 702 int n, c; 703 unsigned long l = 0; 704 705 for (n = 0; n < 4; ++n) { 706 c = read_char(dearmour, errors, rinfo, cbinfo, true); 707 if (c < 0) { 708 dearmour->eof64 = true; 709 return -1; 710 } 711 if (c == '-' || c == '=') { 712 break; 713 } 714 l <<= 6; 715 if (c >= 'A' && c <= 'Z') 716 l += c - 'A'; 717 else if (c >= 'a' && c <= 'z') 718 l += c - 'a' + 26; 719 else if (c >= '0' && c <= '9') 720 l += c - '0' + 52; 721 else if (c == '+') 722 l += 62; 723 else if (c == '/') 724 l += 63; 725 else { 726 --n; 727 l >>= 6; 728 } 729 } 730 731 *pc = c; 732 *pn = n; 733 *pl = l; 734 735 return 4; 736 } 737 738 unsigned 739 __ops_crc24(unsigned checksum, unsigned char c) 740 { 741 unsigned i; 742 743 checksum ^= c << 16; 744 for (i = 0; i < 8; i++) { 745 checksum <<= 1; 746 if (checksum & 0x1000000) 747 checksum ^= CRC24_POLY; 748 } 749 return checksum & 0xffffffL; 750 } 751 752 static int 753 decode64(dearmour_t * dearmour, __ops_error_t ** errors, 754 __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo) 755 { 756 unsigned n; 757 int n2; 758 unsigned long l; 759 int c; 760 int ret; 761 762 assert(dearmour->buffered == 0); 763 764 ret = read4(dearmour, errors, rinfo, cbinfo, &c, &n, &l); 765 if (ret < 0) { 766 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly formed base64"); 767 return 0; 768 } 769 if (n == 3) { 770 if (c != '=') { 771 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly terminated base64 (2)"); 772 return 0; 773 } 774 dearmour->buffered = 2; 775 dearmour->eof64 = true; 776 l >>= 2; 777 } else if (n == 2) { 778 if (c != '=') { 779 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly terminated base64 (3)"); 780 return 0; 781 } 782 dearmour->buffered = 1; 783 dearmour->eof64 = true; 784 l >>= 4; 785 c = read_char(dearmour, errors, rinfo, cbinfo, false); 786 if (c != '=') { 787 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly terminated base64"); 788 return 0; 789 } 790 } else if (n == 0) { 791 if (!dearmour->prev_nl || c != '=') { 792 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly terminated base64 (4)"); 793 return 0; 794 } 795 dearmour->buffered = 0; 796 } else { 797 assert(n == 4); 798 dearmour->buffered = 3; 799 assert(c != '-' && c != '='); 800 } 801 802 if (dearmour->buffered < 3 && dearmour->buffered > 0) { 803 /* then we saw padding */ 804 assert(c == '='); 805 c = read_and_eat_whitespace(dearmour, errors, rinfo, cbinfo, true); 806 if (c != '\n') { 807 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No newline at base64 end"); 808 return 0; 809 } 810 c = read_char(dearmour, errors, rinfo, cbinfo, false); 811 if (c != '=') { 812 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "No checksum at base64 end"); 813 return 0; 814 } 815 } 816 if (c == '=') { 817 /* now we are at the checksum */ 818 ret = read4(dearmour, errors, rinfo, cbinfo, &c, &n, &dearmour->read_checksum); 819 if (ret < 0 || n != 4) { 820 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Error in checksum"); 821 return 0; 822 } 823 c = read_char(dearmour, errors, rinfo, cbinfo, true); 824 if (dearmour->allow_trailing_whitespace) 825 c = eat_whitespace(c, dearmour, errors, rinfo, cbinfo, true); 826 if (c != '\n') { 827 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Badly terminated checksum"); 828 return 0; 829 } 830 c = read_char(dearmour, errors, rinfo, cbinfo, false); 831 if (c != '-') { 832 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad base64 trailer (2)"); 833 return 0; 834 } 835 } 836 if (c == '-') { 837 for (n = 0; n < 4; ++n) 838 if (read_char(dearmour, errors, rinfo, cbinfo, false) != '-') { 839 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad base64 trailer"); 840 return 0; 841 } 842 dearmour->eof64 = true; 843 } else 844 assert(dearmour->buffered); 845 846 for (n = 0; n < dearmour->buffered; ++n) { 847 dearmour->buffer[n] = l; 848 l >>= 8; 849 } 850 851 for (n2 = dearmour->buffered - 1; n2 >= 0; --n2) 852 dearmour->checksum = __ops_crc24(dearmour->checksum, dearmour->buffer[n2]); 853 854 if (dearmour->eof64 && dearmour->read_checksum != dearmour->checksum) { 855 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Checksum mismatch"); 856 return 0; 857 } 858 return 1; 859 } 860 861 static void 862 base64(dearmour_t * dearmour) 863 { 864 dearmour->state = BASE64; 865 dearmour->checksum = CRC24_INIT; 866 dearmour->eof64 = false; 867 dearmour->buffered = 0; 868 } 869 870 /* This reader is rather strange in that it can generate callbacks for */ 871 /* content - this is because plaintext is not encapsulated in PGP */ 872 /* packets... it also calls back for the text between the blocks. */ 873 874 static int 875 armoured_data_reader(void *dest_, size_t length, __ops_error_t ** errors, 876 __ops_reader_info_t * rinfo, 877 __ops_parse_cb_info_t * cbinfo) 878 { 879 dearmour_t *dearmour = __ops_reader_get_arg(rinfo); 880 __ops_parser_content_t content; 881 int ret; 882 bool first; 883 unsigned char *dest = dest_; 884 int saved = length; 885 886 if (dearmour->eof64 && !dearmour->buffered) 887 assert(dearmour->state == OUTSIDE_BLOCK || dearmour->state == AT_TRAILER_NAME); 888 889 while (length > 0) { 890 unsigned count; 891 unsigned n; 892 char buf[1024]; 893 int c; 894 895 flush(dearmour, cbinfo); 896 switch (dearmour->state) { 897 case OUTSIDE_BLOCK: 898 /* 899 * This code returns EOF rather than EARLY_EOF 900 * because if we don't see a header line at all, then 901 * it is just an EOF (and not a BLOCK_END) 902 */ 903 while (!dearmour->seen_nl) { 904 if ((c = unarmoured_read_char(dearmour, errors, rinfo, cbinfo, true)) < 0) { 905 return 0; 906 } 907 } 908 909 /* 910 * flush at this point so we definitely have room for 911 * the header, and so we can easily erase it from the 912 * buffer 913 */ 914 flush(dearmour, cbinfo); 915 /* Find and consume the 5 leading '-' */ 916 for (count = 0; count < 5; ++count) { 917 if ((c = unarmoured_read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) { 918 return 0; 919 } 920 if (c != '-') { 921 goto reloop; 922 } 923 } 924 925 /* Now find the block type */ 926 for (n = 0; n < sizeof(buf) - 1;) { 927 if ((c = unarmoured_read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) { 928 return 0; 929 } 930 if (c == '-') { 931 goto got_minus; 932 } 933 buf[n++] = c; 934 } 935 /* then I guess this wasn't a proper header */ 936 break; 937 938 got_minus: 939 buf[n] = '\0'; 940 941 /* Consume trailing '-' */ 942 for (count = 1; count < 5; ++count) { 943 if ((c = unarmoured_read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) { 944 return 0; 945 } 946 if (c != '-') { 947 /* wasn't a header after all */ 948 goto reloop; 949 } 950 } 951 952 /* Consume final NL */ 953 if ((c = unarmoured_read_char(dearmour, errors, rinfo, cbinfo, true)) < 0) { 954 return 0; 955 } 956 if (dearmour->allow_trailing_whitespace) { 957 if ((c = eat_whitespace(c, dearmour, errors, rinfo, cbinfo, 958 true)) < 0) { 959 return 0; 960 } 961 } 962 if (c != '\n') { 963 /* wasn't a header line after all */ 964 break; 965 } 966 967 /* 968 * Now we've seen the header, scrub it from the 969 * buffer 970 */ 971 dearmour->num_unarmoured = 0; 972 973 /* 974 * But now we've seen a header line, then errors are 975 * EARLY_EOF 976 */ 977 if ((ret = parse_headers(dearmour, errors, rinfo, cbinfo)) <= 0) { 978 return -1; 979 } 980 981 if (!set_lastseen_headerline(dearmour, buf, errors)) { 982 return -1; 983 } 984 985 if (!strcmp(buf, "BEGIN PGP SIGNED MESSAGE")) { 986 __ops_dup_headers(&content.u.signed_cleartext_header.headers, &dearmour->headers); 987 CALLBACK(cbinfo, OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER, &content); 988 ret = process_dash_escaped(dearmour, errors, rinfo, cbinfo); 989 if (ret <= 0) { 990 return ret; 991 } 992 } else { 993 content.u.armour_header.type = buf; 994 content.u.armour_header.headers = dearmour->headers; 995 (void) memset(&dearmour->headers, 0x0, sizeof(dearmour->headers)); 996 CALLBACK(cbinfo, OPS_PTAG_CT_ARMOUR_HEADER, &content); 997 base64(dearmour); 998 } 999 break; 1000 1001 case BASE64: 1002 first = true; 1003 while (length > 0) { 1004 if (!dearmour->buffered) { 1005 if (!dearmour->eof64) { 1006 ret = decode64(dearmour, errors, rinfo, cbinfo); 1007 if (ret <= 0) { 1008 return ret; 1009 } 1010 } 1011 if (!dearmour->buffered) { 1012 assert(dearmour->eof64); 1013 if (first) { 1014 dearmour->state = AT_TRAILER_NAME; 1015 goto reloop; 1016 } 1017 return -1; 1018 } 1019 } 1020 assert(dearmour->buffered); 1021 *dest = dearmour->buffer[--dearmour->buffered]; 1022 ++dest; 1023 --length; 1024 first = false; 1025 } 1026 if (dearmour->eof64 && !dearmour->buffered) { 1027 dearmour->state = AT_TRAILER_NAME; 1028 } 1029 break; 1030 1031 case AT_TRAILER_NAME: 1032 for (n = 0; n < sizeof(buf) - 1;) { 1033 if ((c = read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) { 1034 return -1; 1035 } 1036 if (c == '-') { 1037 goto got_minus2; 1038 } 1039 buf[n++] = c; 1040 } 1041 /* then I guess this wasn't a proper trailer */ 1042 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad ASCII armour trailer"); 1043 break; 1044 1045 got_minus2: 1046 buf[n] = '\0'; 1047 1048 if (!set_lastseen_headerline(dearmour, buf, errors)) { 1049 return -1; 1050 } 1051 1052 /* Consume trailing '-' */ 1053 for (count = 1; count < 5; ++count) { 1054 if ((c = read_char(dearmour, errors, rinfo, cbinfo, false)) < 0) { 1055 return -1; 1056 } 1057 if (c != '-') { 1058 /* wasn't a trailer after all */ 1059 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad ASCII armour trailer (2)"); 1060 } 1061 } 1062 1063 /* Consume final NL */ 1064 if ((c = read_char(dearmour, errors, rinfo, cbinfo, true)) < 0) { 1065 return -1; 1066 } 1067 if (dearmour->allow_trailing_whitespace) { 1068 if ((c = eat_whitespace(c, dearmour, errors, rinfo, cbinfo, 1069 true)) < 0) { 1070 return 0; 1071 } 1072 } 1073 if (c != '\n') { 1074 /* wasn't a trailer line after all */ 1075 OPS_ERROR(errors, OPS_E_R_BAD_FORMAT, "Bad ASCII armour trailer (3)"); 1076 } 1077 1078 if (strncmp(buf, "BEGIN ", 6) == 0) { 1079 if (!set_lastseen_headerline(dearmour, buf, errors)) { 1080 return -1; 1081 } 1082 if ((ret = parse_headers(dearmour, errors, rinfo, cbinfo)) <= 0) { 1083 return ret; 1084 } 1085 content.u.armour_header.type = buf; 1086 content.u.armour_header.headers = dearmour->headers; 1087 (void) memset(&dearmour->headers, 0x0, sizeof(dearmour->headers)); 1088 CALLBACK(cbinfo, OPS_PTAG_CT_ARMOUR_HEADER, &content); 1089 base64(dearmour); 1090 } else { 1091 content.u.armour_trailer.type = buf; 1092 CALLBACK(cbinfo, OPS_PTAG_CT_ARMOUR_TRAILER, &content); 1093 dearmour->state = OUTSIDE_BLOCK; 1094 } 1095 break; 1096 } 1097 reloop: 1098 continue; 1099 } 1100 1101 return saved; 1102 } 1103 1104 static void 1105 armoured_data_destroyer(__ops_reader_info_t * rinfo) 1106 { 1107 free(__ops_reader_get_arg(rinfo)); 1108 } 1109 1110 /** 1111 * \ingroup Core_Readers_Armour 1112 * \brief Pushes dearmouring reader onto stack 1113 * \param parse_info Usual structure containing information about to how to do the parse 1114 * \sa __ops_reader_pop_dearmour() 1115 */ 1116 void 1117 __ops_reader_push_dearmour(__ops_parse_info_t * parse_info) 1118 /* 1119 * This function originally had these parameters to cater for packets which 1120 * didn't strictly match the RFC. The initial 0.5 release is only going to 1121 * support strict checking. If it becomes desirable to support loose checking 1122 * of armoured packets and these params are reinstated, parse_headers() must 1123 * be fixed so that these flags work correctly. 1124 * 1125 * // Allow headers in armoured data that are not separated from the data by a 1126 * blank line bool without_gap, 1127 * 1128 * // Allow no blank line at the start of armoured data bool no_gap, 1129 * 1130 * //Allow armoured data to have trailing whitespace where we strictly would not 1131 * expect it bool trailing_whitespace 1132 */ 1133 { 1134 dearmour_t *dearmour; 1135 1136 dearmour = calloc(1, sizeof(*dearmour)); 1137 dearmour->seen_nl = true; 1138 /* 1139 dearmour->allow_headers_without_gap=without_gap; 1140 dearmour->allow_no_gap=no_gap; 1141 dearmour->allow_trailing_whitespace=trailing_whitespace; 1142 */ 1143 dearmour->expect_sig = false; 1144 dearmour->got_sig = false; 1145 1146 __ops_reader_push(parse_info, armoured_data_reader, armoured_data_destroyer, dearmour); 1147 } 1148 1149 /** 1150 * \ingroup Core_Readers_Armour 1151 * \brief Pops dearmour reader from stock 1152 * \param pinfo 1153 * \sa __ops_reader_push_dearmour() 1154 */ 1155 void 1156 __ops_reader_pop_dearmour(__ops_parse_info_t * pinfo) 1157 { 1158 dearmour_t *dearmour = __ops_reader_get_arg(__ops_parse_get_rinfo(pinfo)); 1159 free(dearmour); 1160 __ops_reader_pop(pinfo); 1161 } 1162 1163 /**************************************************************************/ 1164 1165 /* this is used for *decrypting* */ 1166 typedef struct { 1167 unsigned char decrypted[1024]; 1168 size_t decrypted_count; 1169 size_t decrypted_offset; 1170 __ops_crypt_t *decrypt; 1171 __ops_region_t *region; 1172 unsigned prev_read_was_plain:1; 1173 } encrypted_t; 1174 1175 static int 1176 encrypted_data_reader(void *dest, size_t length, __ops_error_t ** errors, 1177 __ops_reader_info_t * rinfo, 1178 __ops_parse_cb_info_t * cbinfo) 1179 { 1180 encrypted_t *encrypted = __ops_reader_get_arg(rinfo); 1181 int saved = length; 1182 char *cdest; 1183 1184 /* 1185 * V3 MPIs have the count plain and the cipher is reset after each 1186 * count 1187 */ 1188 if (encrypted->prev_read_was_plain && !rinfo->pinfo->reading_mpi_length) { 1189 assert(rinfo->pinfo->reading_v3_secret); 1190 encrypted->decrypt->decrypt_resync(encrypted->decrypt); 1191 encrypted->prev_read_was_plain = false; 1192 } else if (rinfo->pinfo->reading_v3_secret && 1193 rinfo->pinfo->reading_mpi_length) { 1194 encrypted->prev_read_was_plain = true; 1195 } 1196 while (length > 0) { 1197 if (encrypted->decrypted_count) { 1198 unsigned n; 1199 1200 /* 1201 * if we are reading v3 we should never read more 1202 * than 1203 */ 1204 /* we're asked for */ 1205 assert(length >= encrypted->decrypted_count 1206 || (!rinfo->pinfo->reading_v3_secret 1207 && !rinfo->pinfo->exact_read)); 1208 1209 n = MIN(length, encrypted->decrypted_count); 1210 1211 (void) memcpy(dest, encrypted->decrypted + encrypted->decrypted_offset, n); 1212 encrypted->decrypted_count -= n; 1213 encrypted->decrypted_offset += n; 1214 length -= n; 1215 cdest = dest; 1216 cdest += n; 1217 dest = cdest; 1218 } else { 1219 unsigned n = encrypted->region->length; 1220 unsigned char buffer[1024]; 1221 1222 if (!n) { 1223 return -1; 1224 } 1225 if (!encrypted->region->indeterminate) { 1226 n -= encrypted->region->length_read; 1227 if (n == 0) 1228 return saved - length; 1229 if (n > sizeof(buffer)) 1230 n = sizeof(buffer); 1231 } else { 1232 n = sizeof(buffer); 1233 } 1234 1235 /* 1236 * we can only read as much as we're asked for in v3 1237 * keys 1238 */ 1239 /* because they're partially unencrypted! */ 1240 if ((rinfo->pinfo->reading_v3_secret || rinfo->pinfo->exact_read) 1241 && n > length) 1242 n = length; 1243 1244 if (!__ops_stacked_limited_read(buffer, n, encrypted->region, errors, rinfo, 1245 cbinfo)) { 1246 return -1; 1247 } 1248 if (!rinfo->pinfo->reading_v3_secret || 1249 !rinfo->pinfo->reading_mpi_length) { 1250 encrypted->decrypted_count = __ops_decrypt_se_ip(encrypted->decrypt, 1251 encrypted->decrypted, 1252 buffer, n); 1253 1254 if (__ops_get_debug_level(__FILE__)) { 1255 int i; 1256 1257 (void) fprintf(stderr, "READING:\nencrypted: "); 1258 for (i = 0; i < 16; i++) { 1259 (void) fprintf(stderr, "%2x ", buffer[i]); 1260 } 1261 (void) fprintf(stderr, "\ndecrypted: "); 1262 for (i = 0; i < 16; i++) { 1263 (void) fprintf(stderr, "%2x ", encrypted->decrypted[i]); 1264 } 1265 (void) fprintf(stderr, "\n"); 1266 } 1267 } else { 1268 (void) memcpy(&encrypted->decrypted[encrypted->decrypted_offset], buffer, n); 1269 encrypted->decrypted_count = n; 1270 } 1271 1272 assert(encrypted->decrypted_count > 0); 1273 1274 encrypted->decrypted_offset = 0; 1275 } 1276 } 1277 1278 return saved; 1279 } 1280 1281 static void 1282 encrypted_data_destroyer(__ops_reader_info_t * rinfo) 1283 { 1284 free(__ops_reader_get_arg(rinfo)); 1285 } 1286 1287 /** 1288 * \ingroup Core_Readers_SE 1289 * \brief Pushes decryption reader onto stack 1290 * \sa __ops_reader_pop_decrypt() 1291 */ 1292 void 1293 __ops_reader_push_decrypt(__ops_parse_info_t * pinfo, __ops_crypt_t * decrypt, 1294 __ops_region_t * region) 1295 { 1296 encrypted_t *encrypted = calloc(1, sizeof(*encrypted)); 1297 1298 encrypted->decrypt = decrypt; 1299 encrypted->region = region; 1300 1301 __ops_decrypt_init(encrypted->decrypt); 1302 1303 __ops_reader_push(pinfo, encrypted_data_reader, encrypted_data_destroyer, encrypted); 1304 } 1305 1306 /** 1307 * \ingroup Core_Readers_Encrypted 1308 * \brief Pops decryption reader from stack 1309 * \sa __ops_reader_push_decrypt() 1310 */ 1311 void 1312 __ops_reader_pop_decrypt(__ops_parse_info_t * pinfo) 1313 { 1314 encrypted_t *encrypted = __ops_reader_get_arg(__ops_parse_get_rinfo(pinfo)); 1315 1316 encrypted->decrypt->decrypt_finish(encrypted->decrypt); 1317 free(encrypted); 1318 1319 __ops_reader_pop(pinfo); 1320 } 1321 1322 /**************************************************************************/ 1323 1324 typedef struct { 1325 /* boolean: false once we've done the preamble/MDC checks */ 1326 /* and are reading from the plaintext */ 1327 int passed_checks; 1328 unsigned char *plaintext; 1329 size_t plaintext_available; 1330 size_t plaintext_offset; 1331 __ops_region_t *region; 1332 __ops_crypt_t *decrypt; 1333 } decrypt_se_ip_t; 1334 1335 static int 1336 se_ip_data_reader(void *dest_, size_t len, __ops_error_t ** errors, 1337 __ops_reader_info_t * rinfo, 1338 __ops_parse_cb_info_t * cbinfo) 1339 { 1340 1341 /* 1342 Gets entire SE_IP data packet. 1343 Verifies leading preamble 1344 Verifies trailing MDC packet 1345 Then passes up plaintext as requested 1346 */ 1347 1348 unsigned int n = 0; 1349 1350 __ops_region_t decrypted_region; 1351 1352 decrypt_se_ip_t *se_ip = __ops_reader_get_arg(rinfo); 1353 1354 if (!se_ip->passed_checks) { 1355 unsigned char *buf = NULL; 1356 1357 __ops_hash_t hash; 1358 unsigned char hashed[SHA_DIGEST_LENGTH]; 1359 1360 size_t b; 1361 size_t sz_preamble; 1362 size_t sz_mdc_hash; 1363 size_t sz_mdc; 1364 size_t sz_plaintext; 1365 1366 unsigned char *preamble; 1367 unsigned char *plaintext; 1368 unsigned char *mdc; 1369 unsigned char *mdc_hash; 1370 1371 __ops_hash_any(&hash, OPS_HASH_SHA1); 1372 hash.init(&hash); 1373 1374 __ops_init_subregion(&decrypted_region, NULL); 1375 decrypted_region.length = se_ip->region->length - se_ip->region->length_read; 1376 buf = calloc(1, decrypted_region.length); 1377 1378 /* read entire SE IP packet */ 1379 1380 if (!__ops_stacked_limited_read(buf, decrypted_region.length, &decrypted_region, errors, rinfo, cbinfo)) { 1381 free(buf); 1382 return -1; 1383 } 1384 if (__ops_get_debug_level(__FILE__)) { 1385 unsigned int i = 0; 1386 fprintf(stderr, "\n\nentire SE IP packet (len=%d):\n", decrypted_region.length); 1387 for (i = 0; i < decrypted_region.length; i++) { 1388 fprintf(stderr, "0x%02x ", buf[i]); 1389 if (!((i + 1) % 8)) 1390 fprintf(stderr, "\n"); 1391 } 1392 fprintf(stderr, "\n"); 1393 fprintf(stderr, "\n"); 1394 } 1395 /* verify leading preamble */ 1396 1397 if (__ops_get_debug_level(__FILE__)) { 1398 unsigned int i = 0; 1399 fprintf(stderr, "\npreamble: "); 1400 for (i = 0; i < se_ip->decrypt->blocksize + 2; i++) 1401 fprintf(stderr, " 0x%02x", buf[i]); 1402 fprintf(stderr, "\n"); 1403 } 1404 b = se_ip->decrypt->blocksize; 1405 if (buf[b - 2] != buf[b] || buf[b - 1] != buf[b + 1]) { 1406 fprintf(stderr, "Bad symmetric decrypt (%02x%02x vs %02x%02x)\n", 1407 buf[b - 2], buf[b - 1], buf[b], buf[b + 1]); 1408 OPS_ERROR(errors, OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT, "Bad symmetric decrypt when parsing SE IP packet"); 1409 free(buf); 1410 return -1; 1411 } 1412 /* Verify trailing MDC hash */ 1413 1414 sz_preamble = se_ip->decrypt->blocksize + 2; 1415 sz_mdc_hash = OPS_SHA1_HASH_SIZE; 1416 sz_mdc = 1 + 1 + sz_mdc_hash; 1417 sz_plaintext = decrypted_region.length - sz_preamble - sz_mdc; 1418 1419 preamble = buf; 1420 plaintext = buf + sz_preamble; 1421 mdc = plaintext + sz_plaintext; 1422 mdc_hash = mdc + 2; 1423 1424 #ifdef DEBUG 1425 if (__ops_get_debug_level(__FILE__)) { 1426 unsigned int i = 0; 1427 1428 fprintf(stderr, "\nplaintext (len=%" PRIsize "u): ", sz_plaintext); 1429 for (i = 0; i < sz_plaintext; i++) 1430 fprintf(stderr, " 0x%02x", plaintext[i]); 1431 fprintf(stderr, "\n"); 1432 1433 fprintf(stderr, "\nmdc (len=%" PRIsize "u): ", sz_mdc); 1434 for (i = 0; i < sz_mdc; i++) 1435 fprintf(stderr, " 0x%02x", mdc[i]); 1436 fprintf(stderr, "\n"); 1437 } 1438 #endif /* DEBUG */ 1439 1440 __ops_calc_mdc_hash(preamble, sz_preamble, plaintext, sz_plaintext, &hashed[0]); 1441 1442 if (memcmp(mdc_hash, hashed, OPS_SHA1_HASH_SIZE)) { 1443 OPS_ERROR(errors, OPS_E_V_BAD_HASH, "Bad hash in MDC packet"); 1444 free(buf); 1445 return 0; 1446 } 1447 /* all done with the checks */ 1448 /* now can start reading from the plaintext */ 1449 assert(!se_ip->plaintext); 1450 se_ip->plaintext = calloc(1, sz_plaintext); 1451 memcpy(se_ip->plaintext, plaintext, sz_plaintext); 1452 se_ip->plaintext_available = sz_plaintext; 1453 1454 se_ip->passed_checks = 1; 1455 1456 free(buf); 1457 } 1458 n = len; 1459 if (n > se_ip->plaintext_available) { 1460 n = se_ip->plaintext_available; 1461 } 1462 1463 memcpy(dest_, se_ip->plaintext + se_ip->plaintext_offset, n); 1464 se_ip->plaintext_available -= n; 1465 se_ip->plaintext_offset += n; 1466 len -= n; 1467 1468 return n; 1469 } 1470 1471 static void 1472 se_ip_data_destroyer(__ops_reader_info_t * rinfo) 1473 { 1474 decrypt_se_ip_t *se_ip = __ops_reader_get_arg(rinfo); 1475 free(se_ip->plaintext); 1476 free(se_ip); 1477 /* free(__ops_reader_get_arg(rinfo)); */ 1478 } 1479 1480 /** 1481 \ingroup Internal_Readers_SEIP 1482 */ 1483 void 1484 __ops_reader_push_se_ip_data(__ops_parse_info_t * pinfo, __ops_crypt_t * decrypt, 1485 __ops_region_t * region) 1486 { 1487 decrypt_se_ip_t *se_ip = calloc(1, sizeof(*se_ip)); 1488 se_ip->region = region; 1489 se_ip->decrypt = decrypt; 1490 1491 __ops_reader_push(pinfo, se_ip_data_reader, se_ip_data_destroyer, se_ip); 1492 } 1493 1494 /** 1495 \ingroup Internal_Readers_SEIP 1496 */ 1497 void 1498 __ops_reader_pop_se_ip_data(__ops_parse_info_t * pinfo) 1499 { 1500 /* 1501 * decrypt_se_ip_t 1502 * *se_ip=__ops_reader_get_arg(__ops_parse_get_rinfo(pinfo)); 1503 */ 1504 /* free(se_ip); */ 1505 __ops_reader_pop(pinfo); 1506 } 1507 1508 /**************************************************************************/ 1509 1510 /** Arguments for reader_fd 1511 */ 1512 typedef struct mmap_reader_t { 1513 void *mem; /* memory mapped file */ 1514 uint64_t size; /* size of file */ 1515 uint64_t offset; /* current offset in file */ 1516 int fd; /* file descriptor */ 1517 } mmap_reader_t; 1518 1519 1520 /** 1521 * \ingroup Core_Readers 1522 * 1523 * __ops_reader_fd() attempts to read up to "plength" bytes from the file 1524 * descriptor in "parse_info" into the buffer starting at "dest" using the 1525 * rules contained in "flags" 1526 * 1527 * \param dest Pointer to previously allocated buffer 1528 * \param plength Number of bytes to try to read 1529 * \param flags Rules about reading to use 1530 * \param rinfo Reader info 1531 * \param cbinfo Callback info 1532 * 1533 * \return n Number of bytes read 1534 * 1535 * OPS_R_EARLY_EOF and OPS_R_ERROR push errors on the stack 1536 */ 1537 static int 1538 fd_reader(void *dest, size_t length, __ops_error_t ** errors, 1539 __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo) 1540 { 1541 mmap_reader_t *reader = __ops_reader_get_arg(rinfo); 1542 int n = read(reader->fd, dest, length); 1543 1544 OPS_USED(cbinfo); 1545 1546 if (n == 0) 1547 return 0; 1548 1549 if (n < 0) { 1550 OPS_SYSTEM_ERROR_1(errors, OPS_E_R_READ_FAILED, "read", 1551 "file descriptor %d", reader->fd); 1552 return -1; 1553 } 1554 return n; 1555 } 1556 1557 static void 1558 reader_fd_destroyer(__ops_reader_info_t * rinfo) 1559 { 1560 free(__ops_reader_get_arg(rinfo)); 1561 } 1562 1563 /** 1564 \ingroup Core_Readers_First 1565 \brief Starts stack with file reader 1566 */ 1567 1568 void 1569 __ops_reader_set_fd(__ops_parse_info_t * pinfo, int fd) 1570 { 1571 mmap_reader_t *reader = calloc(1, sizeof(*reader)); 1572 1573 reader->fd = fd; 1574 __ops_reader_set(pinfo, fd_reader, reader_fd_destroyer, reader); 1575 } 1576 1577 /**************************************************************************/ 1578 1579 typedef struct { 1580 const unsigned char *buffer; 1581 size_t length; 1582 size_t offset; 1583 } reader_mem_t; 1584 1585 static int 1586 mem_reader(void *dest, size_t length, __ops_error_t ** errors, 1587 __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo) 1588 { 1589 reader_mem_t *reader = __ops_reader_get_arg(rinfo); 1590 unsigned n; 1591 1592 OPS_USED(cbinfo); 1593 OPS_USED(errors); 1594 1595 if (reader->offset + length > reader->length) 1596 n = reader->length - reader->offset; 1597 else 1598 n = length; 1599 1600 if (n == 0) 1601 return 0; 1602 1603 memcpy(dest, reader->buffer + reader->offset, n); 1604 reader->offset += n; 1605 1606 return n; 1607 } 1608 1609 static void 1610 mem_destroyer(__ops_reader_info_t * rinfo) 1611 { 1612 free(__ops_reader_get_arg(rinfo)); 1613 } 1614 1615 /** 1616 \ingroup Core_Readers_First 1617 \brief Starts stack with memory reader 1618 */ 1619 1620 void 1621 __ops_reader_set_memory(__ops_parse_info_t * pinfo, const void *buffer, 1622 size_t length) 1623 { 1624 reader_mem_t *mem = calloc(1, sizeof(*mem)); 1625 1626 mem->buffer = buffer; 1627 mem->length = length; 1628 mem->offset = 0; 1629 __ops_reader_set(pinfo, mem_reader, mem_destroyer, mem); 1630 } 1631 1632 /**************************************************************************/ 1633 1634 /** 1635 \ingroup Core_Writers 1636 \brief Create and initialise cinfo and mem; Set for writing to mem 1637 \param cinfo Address where new cinfo pointer will be set 1638 \param mem Address when new mem pointer will be set 1639 \param bufsz Initial buffer size (will automatically be increased when necessary) 1640 \note It is the caller's responsiblity to free cinfo and mem. 1641 \sa __ops_teardown_memory_write() 1642 */ 1643 void 1644 __ops_setup_memory_write(__ops_create_info_t ** cinfo, __ops_memory_t ** mem, size_t bufsz) 1645 { 1646 /* 1647 * initialise needed structures for writing to memory 1648 */ 1649 1650 *cinfo = __ops_create_info_new(); 1651 *mem = __ops_memory_new(); 1652 1653 __ops_memory_init(*mem, bufsz); 1654 1655 __ops_writer_set_memory(*cinfo, *mem); 1656 } 1657 1658 /** 1659 \ingroup Core_Writers 1660 \brief Closes writer and frees cinfo and mem 1661 \param cinfo 1662 \param mem 1663 \sa __ops_setup_memory_write() 1664 */ 1665 void 1666 __ops_teardown_memory_write(__ops_create_info_t * cinfo, __ops_memory_t * mem) 1667 { 1668 __ops_writer_close(cinfo);/* new */ 1669 __ops_create_info_delete(cinfo); 1670 __ops_memory_free(mem); 1671 } 1672 1673 /** 1674 \ingroup Core_Readers 1675 \brief Create parse_info and sets to read from memory 1676 \param pinfo Address where new parse_info will be set 1677 \param mem Memory to read from 1678 \param arg Reader-specific arg 1679 \param callback Callback to use with reader 1680 \param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification) 1681 \note It is the caller's responsiblity to free parse_info 1682 \sa __ops_teardown_memory_read() 1683 */ 1684 void 1685 __ops_setup_memory_read(__ops_parse_info_t ** pinfo, __ops_memory_t * mem, 1686 void *vp, 1687 __ops_parse_cb_return_t callback(const __ops_parser_content_t *, __ops_parse_cb_info_t *), 1688 bool accumulate) 1689 { 1690 /* 1691 * initialise needed structures for reading 1692 */ 1693 1694 *pinfo = __ops_parse_info_new(); 1695 __ops_parse_cb_set(*pinfo, callback, vp); 1696 __ops_reader_set_memory(*pinfo, 1697 __ops_memory_get_data(mem), 1698 __ops_memory_get_length(mem)); 1699 1700 if (accumulate) 1701 (*pinfo)->rinfo.accumulate = true; 1702 } 1703 1704 /** 1705 \ingroup Core_Readers 1706 \brief Frees pinfo and mem 1707 \param pinfo 1708 \param mem 1709 \sa __ops_setup_memory_read() 1710 */ 1711 void 1712 __ops_teardown_memory_read(__ops_parse_info_t * pinfo, __ops_memory_t * mem) 1713 { 1714 __ops_parse_info_delete(pinfo); 1715 __ops_memory_free(mem); 1716 } 1717 1718 /** 1719 \ingroup Core_Writers 1720 \brief Create and initialise cinfo and mem; Set for writing to file 1721 \param cinfo Address where new cinfo pointer will be set 1722 \param filename File to write to 1723 \param allow_overwrite Allows file to be overwritten, if set. 1724 \return Newly-opened file descriptor 1725 \note It is the caller's responsiblity to free cinfo and to close fd. 1726 \sa __ops_teardown_file_write() 1727 */ 1728 int 1729 __ops_setup_file_write(__ops_create_info_t ** cinfo, const char *filename, bool allow_overwrite) 1730 { 1731 int fd = 0; 1732 int flags = 0; 1733 1734 /* 1735 * initialise needed structures for writing to file 1736 */ 1737 1738 flags = O_WRONLY | O_CREAT; 1739 if (allow_overwrite == true) 1740 flags |= O_TRUNC; 1741 else 1742 flags |= O_EXCL; 1743 1744 #ifdef O_BINARY 1745 flags |= O_BINARY; 1746 #endif 1747 1748 fd = open(filename, flags, 0600); 1749 if (fd < 0) { 1750 perror(filename); 1751 return fd; 1752 } 1753 *cinfo = __ops_create_info_new(); 1754 1755 __ops_writer_set_fd(*cinfo, fd); 1756 1757 return fd; 1758 } 1759 1760 /** 1761 \ingroup Core_Writers 1762 \brief Closes writer, frees info, closes fd 1763 \param cinfo 1764 \param fd 1765 */ 1766 void 1767 __ops_teardown_file_write(__ops_create_info_t * cinfo, int fd) 1768 { 1769 __ops_writer_close(cinfo); 1770 close(fd); 1771 __ops_create_info_delete(cinfo); 1772 } 1773 1774 /** 1775 \ingroup Core_Writers 1776 \brief As __ops_setup_file_write, but appends to file 1777 */ 1778 int 1779 __ops_setup_file_append(__ops_create_info_t ** cinfo, const char *filename) 1780 { 1781 int fd; 1782 /* 1783 * initialise needed structures for writing to file 1784 */ 1785 1786 #ifdef O_BINARY 1787 fd = open(filename, O_WRONLY | O_APPEND | O_BINARY, 0600); 1788 #else 1789 fd = open(filename, O_WRONLY | O_APPEND, 0600); 1790 #endif 1791 if (fd < 0) { 1792 perror(filename); 1793 return fd; 1794 } 1795 *cinfo = __ops_create_info_new(); 1796 1797 __ops_writer_set_fd(*cinfo, fd); 1798 1799 return fd; 1800 } 1801 1802 /** 1803 \ingroup Core_Writers 1804 \brief As __ops_teardown_file_write() 1805 */ 1806 void 1807 __ops_teardown_file_append(__ops_create_info_t * cinfo, int fd) 1808 { 1809 __ops_teardown_file_write(cinfo, fd); 1810 } 1811 1812 /** 1813 \ingroup Core_Readers 1814 \brief Creates parse_info, opens file, and sets to read from file 1815 \param pinfo Address where new parse_info will be set 1816 \param filename Name of file to read 1817 \param vp Reader-specific arg 1818 \param callback Callback to use when reading 1819 \param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification) 1820 \note It is the caller's responsiblity to free parse_info and to close fd 1821 \sa __ops_teardown_file_read() 1822 */ 1823 1824 int 1825 __ops_setup_file_read(__ops_parse_info_t ** pinfo, const char *filename, 1826 void *vp, 1827 __ops_parse_cb_return_t callback(const __ops_parser_content_t *, __ops_parse_cb_info_t *), 1828 bool accumulate) 1829 { 1830 int fd = 0; 1831 /* 1832 * initialise needed structures for reading 1833 */ 1834 1835 #ifdef O_BINARY 1836 fd = open(filename, O_RDONLY | O_BINARY); 1837 #else 1838 fd = open(filename, O_RDONLY); 1839 #endif 1840 if (fd < 0) { 1841 perror(filename); 1842 return fd; 1843 } 1844 *pinfo = __ops_parse_info_new(); 1845 __ops_parse_cb_set(*pinfo, callback, vp); 1846 #ifdef USE_MMAP_FOR_FILES 1847 __ops_reader_set_mmap(*pinfo, fd); 1848 #else 1849 __ops_reader_set_fd(*pinfo, fd); 1850 #endif 1851 1852 if (accumulate) { 1853 (*pinfo)->rinfo.accumulate = true; 1854 } 1855 1856 if (__ops_get_debug_level(__FILE__)) { 1857 printf("__ops_setup_file_read: accumulate %d\n", accumulate); 1858 } 1859 return fd; 1860 } 1861 1862 /** 1863 \ingroup Core_Readers 1864 \brief Frees pinfo and closes fd 1865 \param pinfo 1866 \param fd 1867 \sa __ops_setup_file_read() 1868 */ 1869 void 1870 __ops_teardown_file_read(__ops_parse_info_t * pinfo, int fd) 1871 { 1872 close(fd); 1873 __ops_parse_info_delete(pinfo); 1874 } 1875 1876 __ops_parse_cb_return_t 1877 literal_data_cb(const __ops_parser_content_t *contents, __ops_parse_cb_info_t *cbinfo) 1878 { 1879 const __ops_parser_content_union_t *content = &contents->u; 1880 1881 OPS_USED(cbinfo); 1882 1883 if (__ops_get_debug_level(__FILE__)) { 1884 printf("literal_data_cb: "); 1885 __ops_print_packet(contents); 1886 } 1887 /* Read data from packet into static buffer */ 1888 switch (contents->tag) { 1889 case OPS_PTAG_CT_LITERAL_DATA_BODY: 1890 /* if writer enabled, use it */ 1891 if (cbinfo->cinfo) { 1892 if (__ops_get_debug_level(__FILE__)) { 1893 printf("literal_data_cb: length is %d\n", 1894 content->literal_data_body.length); 1895 } 1896 __ops_write(content->literal_data_body.data, 1897 content->literal_data_body.length, 1898 cbinfo->cinfo); 1899 } 1900 break; 1901 1902 case OPS_PTAG_CT_LITERAL_DATA_HEADER: 1903 /* ignore */ 1904 break; 1905 1906 default: 1907 break; 1908 } 1909 1910 return OPS_RELEASE_MEMORY; 1911 } 1912 1913 __ops_parse_cb_return_t 1914 pk_session_key_cb(const __ops_parser_content_t * contents, __ops_parse_cb_info_t * cbinfo) 1915 { 1916 const __ops_parser_content_union_t *content = &contents->u; 1917 1918 OPS_USED(cbinfo); 1919 1920 if (__ops_get_debug_level(__FILE__)) { 1921 __ops_print_packet(contents); 1922 } 1923 /* Read data from packet into static buffer */ 1924 switch (contents->tag) { 1925 case OPS_PTAG_CT_PK_SESSION_KEY: 1926 if (__ops_get_debug_level(__FILE__)) { 1927 printf("OPS_PTAG_CT_PK_SESSION_KEY\n"); 1928 } 1929 assert(cbinfo->cryptinfo.keyring); 1930 cbinfo->cryptinfo.keydata = __ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring, 1931 content->pk_session_key.key_id); 1932 if (!cbinfo->cryptinfo.keydata) 1933 break; 1934 break; 1935 1936 default: 1937 /* return callback_general(contents,cbinfo); */ 1938 break; 1939 } 1940 1941 return OPS_RELEASE_MEMORY; 1942 } 1943 1944 /** 1945 \ingroup Core_Callbacks 1946 1947 \brief Callback to get secret key, decrypting if necessary. 1948 1949 @verbatim 1950 This callback does the following: 1951 * finds the session key in the keyring 1952 * gets a passphrase if required 1953 * decrypts the secret key, if necessary 1954 * sets the secret_key in the content struct 1955 @endverbatim 1956 */ 1957 1958 __ops_parse_cb_return_t 1959 get_secret_key_cb(const __ops_parser_content_t * contents, __ops_parse_cb_info_t * cbinfo) 1960 { 1961 const __ops_parser_content_union_t *content = &contents->u; 1962 const __ops_secret_key_t *secret; 1963 __ops_parser_content_t seckey; 1964 1965 OPS_USED(cbinfo); 1966 1967 if (__ops_get_debug_level(__FILE__)) { 1968 __ops_print_packet(contents); 1969 } 1970 switch (contents->tag) { 1971 case OPS_PARSER_CMD_GET_SECRET_KEY: 1972 cbinfo->cryptinfo.keydata = __ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring, content->get_secret_key.pk_session_key->key_id); 1973 if (!cbinfo->cryptinfo.keydata || !__ops_is_key_secret(cbinfo->cryptinfo.keydata)) 1974 return 0; 1975 1976 /* now get the key from the data */ 1977 secret = __ops_get_secret_key_from_data(cbinfo->cryptinfo.keydata); 1978 while (!secret) { 1979 if (!cbinfo->cryptinfo.passphrase) { 1980 (void) memset(&seckey, 0x0, sizeof(seckey)); 1981 seckey.u.secret_key_passphrase.passphrase = &cbinfo->cryptinfo.passphrase; 1982 CALLBACK(cbinfo, OPS_PARSER_CMD_GET_SK_PASSPHRASE, &seckey); 1983 if (!cbinfo->cryptinfo.passphrase) { 1984 fprintf(stderr, "can't get passphrase\n"); 1985 assert(0); 1986 } 1987 } 1988 /* then it must be encrypted */ 1989 secret = __ops_decrypt_secret_key_from_data(cbinfo->cryptinfo.keydata, cbinfo->cryptinfo.passphrase); 1990 } 1991 1992 *content->get_secret_key.secret_key = secret; 1993 break; 1994 1995 default: 1996 /* return callback_general(contents,cbinfo); */ 1997 break; 1998 } 1999 2000 return OPS_RELEASE_MEMORY; 2001 } 2002 2003 char * 2004 __ops_malloc_passphrase(char *pp) 2005 { 2006 size_t n; 2007 char *passphrase; 2008 2009 n = strlen(pp); 2010 if ((passphrase = calloc(1, n + 1)) != NULL) { 2011 (void) memcpy(passphrase, pp, n); 2012 passphrase[n] = 0x0; 2013 } 2014 return passphrase; 2015 } 2016 2017 /** 2018 \ingroup HighLevel_Callbacks 2019 \brief Callback to use when you need to prompt user for passphrase 2020 \param contents 2021 \param cbinfo 2022 */ 2023 __ops_parse_cb_return_t 2024 get_passphrase_cb(const __ops_parser_content_t *contents, __ops_parse_cb_info_t *cbinfo) 2025 { 2026 const __ops_parser_content_union_t *content = &contents->u; 2027 2028 OPS_USED(cbinfo); 2029 if (__ops_get_debug_level(__FILE__)) { 2030 __ops_print_packet(contents); 2031 } 2032 switch (contents->tag) { 2033 case OPS_PARSER_CMD_GET_SK_PASSPHRASE: 2034 *(content->secret_key_passphrase.passphrase) = 2035 __ops_malloc_passphrase(getpass("netpgp passphrase: ")); 2036 return OPS_KEEP_MEMORY; 2037 2038 default: 2039 /* return callback_general(contents,cbinfo); */ 2040 break; 2041 } 2042 2043 return OPS_RELEASE_MEMORY; 2044 } 2045 2046 bool 2047 __ops_reader_set_accumulate(__ops_parse_info_t * pinfo, bool state) 2048 { 2049 pinfo->rinfo.accumulate = state; 2050 return state; 2051 } 2052 2053 /**************************************************************************/ 2054 2055 static int 2056 hash_reader(void *dest, size_t length, __ops_error_t ** errors, 2057 __ops_reader_info_t * rinfo, __ops_parse_cb_info_t * cbinfo) 2058 { 2059 __ops_hash_t *hash = __ops_reader_get_arg(rinfo); 2060 int r = __ops_stacked_read(dest, length, errors, rinfo, cbinfo); 2061 2062 if (r <= 0) 2063 return r; 2064 2065 hash->add(hash, dest, r); 2066 2067 return r; 2068 } 2069 2070 /** 2071 \ingroup Internal_Readers_Hash 2072 \brief Push hashed data reader on stack 2073 */ 2074 void 2075 __ops_reader_push_hash(__ops_parse_info_t * pinfo, __ops_hash_t * hash) 2076 { 2077 hash->init(hash); 2078 __ops_reader_push(pinfo, hash_reader, NULL, hash); 2079 } 2080 2081 /** 2082 \ingroup Internal_Readers_Hash 2083 \brief Pop hashed data reader from stack 2084 */ 2085 void 2086 __ops_reader_pop_hash(__ops_parse_info_t * pinfo) 2087 { 2088 __ops_reader_pop(pinfo); 2089 } 2090 2091 /* read memory from the previously mmap-ed file */ 2092 static int 2093 mmap_reader(void *dest, size_t length, __ops_error_t **errors, 2094 __ops_reader_info_t *rinfo, __ops_parse_cb_info_t *cbinfo) 2095 { 2096 mmap_reader_t *mem = __ops_reader_get_arg(rinfo); 2097 char *cmem = mem->mem; 2098 int n = MIN(length, mem->size - mem->offset); 2099 2100 OPS_USED(cbinfo); 2101 if (n > 0) { 2102 (void) memcpy(dest, &cmem[mem->offset], n); 2103 mem->offset += n; 2104 } 2105 return n; 2106 } 2107 2108 /* tear down the mmap, close the fd */ 2109 static void 2110 mmap_destroyer(__ops_reader_info_t * rinfo) 2111 { 2112 mmap_reader_t *mem = __ops_reader_get_arg(rinfo); 2113 2114 (void) munmap(mem->mem, mem->size); 2115 (void) close(mem->fd); 2116 free(__ops_reader_get_arg(rinfo)); 2117 } 2118 2119 /* set up the file to use mmap-ed memory if available, file IO otherwise */ 2120 void 2121 __ops_reader_set_mmap(__ops_parse_info_t * pinfo, int fd) 2122 { 2123 mmap_reader_t *mem = calloc(1, sizeof(*mem)); 2124 struct stat st; 2125 2126 if (fstat(fd, &st) == 0) { 2127 mem->size = st.st_size; 2128 mem->offset = 0; 2129 mem->fd = fd; 2130 mem->mem = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0); 2131 if (mem->mem == MAP_FAILED) { 2132 __ops_reader_set(pinfo, fd_reader, reader_fd_destroyer, mem); 2133 } else { 2134 __ops_reader_set(pinfo, mmap_reader, mmap_destroyer, mem); 2135 } 2136 } 2137 } 2138