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