2 * Copyright (c) 2009 The NetBSD Foundation, Inc.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Alistair Crooks (agc@NetBSD.org)
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
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.
36 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
37 * use this file except in compliance with the License.
39 * You may obtain a copy of the License at
40 * http://www.apache.org/licenses/LICENSE-2.0
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.
46 * See the License for the specific language governing permissions and
47 * limitations under the License.
51 #ifdef HAVE_SYS_CDEFS_H
52 #include <sys/cdefs.h>
55 #if defined(__NetBSD__)
56 __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
57 __RCSID("$NetBSD: reader.c,v 1.26 2009/12/05 07:08:19 agc Exp $");
60 #include <sys/types.h>
63 #ifdef HAVE_SYS_MMAN_H
67 #ifdef HAVE_SYS_PARAM_H
68 #include <sys/param.h>
83 #ifdef HAVE_INTTYPES_H
87 #ifdef HAVE_OPENSSL_IDEA_H
88 #include <openssl/cast.h>
91 #ifdef HAVE_OPENSSL_IDEA_H
92 #include <openssl/idea.h>
95 #ifdef HAVE_OPENSSL_AES_H
96 #include <openssl/aes.h>
99 #ifdef HAVE_OPENSSL_DES_H
100 #include <openssl/des.h>
107 #ifdef HAVE_TERMIOS_H
126 #include "signature.h"
128 #include "packet-parse.h"
129 #include "packet-show.h"
132 #include "readerwriter.h"
133 #include "netpgpdefs.h"
134 #include "netpgpdigest.h"
137 /* get a pass phrase from the user */
139 __ops_getpassphrase(void *in
, char *phrase
, size_t size
)
144 while ((p
= getpass("netpgp passphrase: ")) == NULL
) {
146 (void) snprintf(phrase
, size
, "%s", p
);
148 if (fgets(phrase
, (int)size
, in
) == NULL
) {
151 phrase
[strlen(phrase
) - 1] = 0x0;
157 * \ingroup Internal_Readers_Generic
158 * \brief Starts reader stack
159 * \param stream Parse settings
160 * \param reader Reader to use
161 * \param destroyer Destroyer to use
162 * \param vp Reader-specific arg
165 __ops_reader_set(__ops_stream_t
*stream
,
166 __ops_reader_func_t
*reader
,
167 __ops_reader_destroyer_t
*destroyer
,
170 stream
->readinfo
.reader
= reader
;
171 stream
->readinfo
.destroyer
= destroyer
;
172 stream
->readinfo
.arg
= vp
;
176 * \ingroup Internal_Readers_Generic
177 * \brief Adds to reader stack
178 * \param stream Parse settings
179 * \param reader Reader to use
180 * \param destroyer Reader's destroyer
181 * \param vp Reader-specific arg
184 __ops_reader_push(__ops_stream_t
*stream
,
185 __ops_reader_func_t
*reader
,
186 __ops_reader_destroyer_t
*destroyer
,
189 __ops_reader_t
*readinfo
;
191 if ((readinfo
= calloc(1, sizeof(*readinfo
))) == NULL
) {
192 (void) fprintf(stderr
, "__ops_reader_push: bad alloc\n");
194 *readinfo
= stream
->readinfo
;
195 (void) memset(&stream
->readinfo
, 0x0, sizeof(stream
->readinfo
));
196 stream
->readinfo
.next
= readinfo
;
197 stream
->readinfo
.parent
= stream
;
199 /* should copy accumulate flags from other reader? RW */
200 stream
->readinfo
.accumulate
= readinfo
->accumulate
;
202 __ops_reader_set(stream
, reader
, destroyer
, vp
);
207 * \ingroup Internal_Readers_Generic
208 * \brief Removes from reader stack
209 * \param stream Parse settings
212 __ops_reader_pop(__ops_stream_t
*stream
)
214 __ops_reader_t
*next
= stream
->readinfo
.next
;
216 stream
->readinfo
= *next
;
221 * \ingroup Internal_Readers_Generic
222 * \brief Gets arg from reader
223 * \param readinfo Reader info
224 * \return Pointer to reader info's arg
227 __ops_reader_get_arg(__ops_reader_t
*readinfo
)
229 return readinfo
->arg
;
232 /**************************************************************************/
234 #define CRC24_POLY 0x1864cfbL
239 BEGIN_PGP_PUBLIC_KEY_BLOCK
,
240 BEGIN_PGP_PRIVATE_KEY_BLOCK
,
245 END_PGP_PUBLIC_KEY_BLOCK
,
246 END_PGP_PRIVATE_KEY_BLOCK
,
250 BEGIN_PGP_SIGNED_MESSAGE
263 __ops_stream_t
*parse_info
;
266 unsigned allow_headers_without_gap
:1;
267 /* !< allow headers in armoured data that are
268 * not separated from the data by a blank line
270 unsigned allow_no_gap
:1;
271 /* !< allow no blank line at the start of
273 unsigned allow_trailing_whitespace
:1;
274 /* !< allow armoured stuff to have trailing
275 * whitespace where we wouldn't strictly expect
277 /* it is an error to get a cleartext message without a sig */
278 unsigned expect_sig
:1;
282 unsigned char buffer
[3];
284 unsigned long checksum
;
285 unsigned long read_checksum
;
286 /* unarmoured text blocks */
287 unsigned char unarmoured
[NETPGP_BUFSIZ
];
289 /* pushed back data (stored backwards) */
290 unsigned char *pushback
;
292 /* armoured block headers */
293 __ops_headers_t headers
;
297 push_back(dearmour_t
*dearmour
, const unsigned char *buf
,
302 if (dearmour
->pushback
) {
303 (void) fprintf(stderr
, "push_back: already pushed back\n");
304 } else if ((dearmour
->pushback
= calloc(1, length
)) == NULL
) {
305 (void) fprintf(stderr
, "push_back: bad alloc\n");
307 for (n
= 0; n
< length
; ++n
) {
308 dearmour
->pushback
[n
] = buf
[(length
- n
) - 1];
310 dearmour
->pushbackc
= length
;
314 /* this struct holds a textual header line */
315 typedef struct headerline_t
{
316 const char *s
; /* the header line */
317 size_t len
; /* its length */
318 int type
; /* the defined type */
321 static headerline_t headerlines
[] = {
322 { "BEGIN PGP MESSAGE", 17, BEGIN_PGP_MESSAGE
},
323 { "BEGIN PGP PUBLIC KEY BLOCK", 26, BEGIN_PGP_PUBLIC_KEY_BLOCK
},
324 { "BEGIN PGP PRIVATE KEY BLOCK",27, BEGIN_PGP_PRIVATE_KEY_BLOCK
},
325 { "BEGIN PGP MESSAGE, PART ", 25, BEGIN_PGP_MULTI
},
326 { "BEGIN PGP SIGNATURE", 19, BEGIN_PGP_SIGNATURE
},
328 { "END PGP MESSAGE", 15, END_PGP_MESSAGE
},
329 { "END PGP PUBLIC KEY BLOCK", 24, END_PGP_PUBLIC_KEY_BLOCK
},
330 { "END PGP PRIVATE KEY BLOCK", 25, END_PGP_PRIVATE_KEY_BLOCK
},
331 { "END PGP MESSAGE, PART ", 22, END_PGP_MULTI
},
332 { "END PGP SIGNATURE", 17, END_PGP_SIGNATURE
},
334 { "BEGIN PGP SIGNED MESSAGE", 24, BEGIN_PGP_SIGNED_MESSAGE
},
339 /* search through the table of header lines */
341 findheaderline(char *headerline
)
345 for (hp
= headerlines
; hp
->s
; hp
++) {
346 if (strncmp(headerline
, hp
->s
, hp
->len
) == 0) {
354 set_lastseen_headerline(dearmour_t
*dearmour
, char *hdr
, __ops_error_t
**errors
)
359 prev
= dearmour
->lastseen
;
360 if ((lastseen
= findheaderline(hdr
)) == -1) {
361 OPS_ERROR_1(errors
, OPS_E_R_BAD_FORMAT
,
362 "Unrecognised Header Line %s", hdr
);
365 dearmour
->lastseen
= lastseen
;
366 if (__ops_get_debug_level(__FILE__
)) {
367 printf("set header: hdr=%s, dearmour->lastseen=%d, prev=%d\n",
368 hdr
, dearmour
->lastseen
, prev
);
370 switch (dearmour
->lastseen
) {
372 OPS_ERROR_1(errors
, OPS_E_R_BAD_FORMAT
,
373 "Unrecognised last seen Header Line %s", hdr
);
376 case END_PGP_MESSAGE
:
377 if (prev
!= BEGIN_PGP_MESSAGE
) {
378 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
379 "Got END PGP MESSAGE, but not after BEGIN");
383 case END_PGP_PUBLIC_KEY_BLOCK
:
384 if (prev
!= BEGIN_PGP_PUBLIC_KEY_BLOCK
) {
385 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
386 "Got END PGP PUBLIC KEY BLOCK, but not after BEGIN");
390 case END_PGP_PRIVATE_KEY_BLOCK
:
391 if (prev
!= BEGIN_PGP_PRIVATE_KEY_BLOCK
) {
392 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
393 "Got END PGP PRIVATE KEY BLOCK, but not after BEGIN");
397 case BEGIN_PGP_MULTI
:
399 OPS_ERROR(errors
, OPS_E_R_UNSUPPORTED
,
400 "Multi-part messages are not yet supported");
403 case END_PGP_SIGNATURE
:
404 if (prev
!= BEGIN_PGP_SIGNATURE
) {
405 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
406 "Got END PGP SIGNATURE, but not after BEGIN");
410 case BEGIN_PGP_MESSAGE
:
411 case BEGIN_PGP_PUBLIC_KEY_BLOCK
:
412 case BEGIN_PGP_PRIVATE_KEY_BLOCK
:
413 case BEGIN_PGP_SIGNATURE
:
414 case BEGIN_PGP_SIGNED_MESSAGE
:
421 read_char(dearmour_t
*dearmour
,
422 __ops_error_t
**errors
,
423 __ops_reader_t
*readinfo
,
424 __ops_cbdata_t
*cbinfo
,
430 if (dearmour
->pushbackc
) {
431 c
= dearmour
->pushback
[--dearmour
->pushbackc
];
432 if (dearmour
->pushbackc
== 0) {
433 free(dearmour
->pushback
);
434 dearmour
->pushback
= NULL
;
436 } else if (__ops_stacked_read(&c
, 1, errors
, readinfo
,
440 } while (skip
&& c
== '\r');
441 dearmour
->prev_nl
= dearmour
->seen_nl
;
442 dearmour
->seen_nl
= c
== '\n';
447 eat_whitespace(int first
,
448 dearmour_t
*dearmour
,
449 __ops_error_t
**errors
,
450 __ops_reader_t
*readinfo
,
451 __ops_cbdata_t
*cbinfo
,
456 while (c
== ' ' || c
== '\t') {
457 c
= read_char(dearmour
, errors
, readinfo
, cbinfo
, skip
);
463 read_and_eat_whitespace(dearmour_t
*dearmour
,
464 __ops_error_t
**errors
,
465 __ops_reader_t
*readinfo
,
466 __ops_cbdata_t
*cbinfo
,
472 c
= read_char(dearmour
, errors
, readinfo
, cbinfo
, skip
);
473 } while (c
== ' ' || c
== '\t');
478 flush(dearmour_t
*dearmour
, __ops_cbdata_t
*cbinfo
)
480 __ops_packet_t content
;
482 if (dearmour
->unarmoredc
> 0) {
483 content
.u
.unarmoured_text
.data
= dearmour
->unarmoured
;
484 content
.u
.unarmoured_text
.length
= dearmour
->unarmoredc
;
485 CALLBACK(OPS_PTAG_CT_UNARMOURED_TEXT
, cbinfo
, &content
);
486 dearmour
->unarmoredc
= 0;
491 unarmoured_read_char(dearmour_t
*dearmour
,
492 __ops_error_t
**errors
,
493 __ops_reader_t
*readinfo
,
494 __ops_cbdata_t
*cbinfo
,
500 c
= read_char(dearmour
, errors
, readinfo
, cbinfo
, 0);
504 dearmour
->unarmoured
[dearmour
->unarmoredc
++] = c
;
505 if (dearmour
->unarmoredc
== sizeof(dearmour
->unarmoured
)) {
506 flush(dearmour
, cbinfo
);
508 } while (skip
&& c
== '\r');
516 * \return header value if found, otherwise NULL
519 __ops_find_header(__ops_headers_t
*headers
, const char *key
)
523 for (n
= 0; n
< headers
->headerc
; ++n
) {
524 if (strcmp(headers
->headers
[n
].key
, key
) == 0) {
525 return headers
->headers
[n
].value
;
536 __ops_dup_headers(__ops_headers_t
*dest
, const __ops_headers_t
*src
)
540 if ((dest
->headers
= calloc(src
->headerc
, sizeof(*dest
->headers
))) == NULL
) {
541 (void) fprintf(stderr
, "__ops_dup_headers: bad alloc\n");
543 dest
->headerc
= src
->headerc
;
544 for (n
= 0; n
< src
->headerc
; ++n
) {
545 dest
->headers
[n
].key
= strdup(src
->headers
[n
].key
);
546 dest
->headers
[n
].value
= strdup(src
->headers
[n
].value
);
552 * Note that this skips CRs so implementations always see just straight LFs
553 * as line terminators
556 process_dash_escaped(dearmour_t
*dearmour
,
557 __ops_error_t
**errors
,
558 __ops_reader_t
*readinfo
,
559 __ops_cbdata_t
*cbinfo
)
561 __ops_packet_t content
;
562 __ops_packet_t content2
;
563 __ops_cleartext_body_t
*body
= &content
.u
.cleartext_body
;
564 __ops_cleartext_trailer_t
*trailer
= &content2
.u
.cleartext_trailer
;
569 if ((hash
= calloc(1, sizeof(*hash
))) == NULL
) {
570 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
571 "process_dash_escaped: bad alloc");
574 hashstr
= __ops_find_header(&dearmour
->headers
, "Hash");
576 __ops_hash_alg_t alg
;
578 alg
= __ops_str_to_hash_alg(hashstr
);
579 if (!__ops_is_hash_alg_supported(&alg
)) {
581 OPS_ERROR_1(errors
, OPS_E_R_BAD_FORMAT
,
582 "Unsupported hash algorithm '%s'", hashstr
);
585 if (alg
== OPS_HASH_UNKNOWN
) {
587 OPS_ERROR_1(errors
, OPS_E_R_BAD_FORMAT
,
588 "Unknown hash algorithm '%s'", hashstr
);
591 __ops_hash_any(hash
, alg
);
593 __ops_hash_md5(hash
);
596 if (!hash
->init(hash
)) {
597 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
598 "can't initialise hash");
608 c
= read_char(dearmour
, errors
, readinfo
, cbinfo
, 1);
612 if (dearmour
->prev_nl
&& c
== '-') {
613 if ((c
= read_char(dearmour
, errors
, readinfo
, cbinfo
,
618 /* then this had better be a trailer! */
620 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
621 "Bad dash-escaping");
623 for (count
= 2; count
< 5; ++count
) {
624 if ((c
= read_char(dearmour
, errors
,
625 readinfo
, cbinfo
, 0)) < 0) {
631 "Bad dash-escaping (2)");
634 dearmour
->state
= AT_TRAILER_NAME
;
637 /* otherwise we read the next character */
638 if ((c
= read_char(dearmour
, errors
, readinfo
, cbinfo
,
643 if (c
== '\n' && body
->length
) {
644 if (memchr(body
->data
+ 1, '\n', body
->length
- 1)
646 (void) fprintf(stderr
,
647 "process_dash_escaped: newline found\n");
650 if (body
->data
[0] == '\n') {
651 hash
->add(hash
, (const unsigned char *)"\r", 1);
653 hash
->add(hash
, body
->data
, body
->length
);
654 if (__ops_get_debug_level(__FILE__
)) {
655 fprintf(stderr
, "Got body:\n%s\n", body
->data
);
657 CALLBACK(OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY
, cbinfo
,
661 body
->data
[body
->length
++] = c
;
663 if (body
->length
== sizeof(body
->data
)) {
664 if (__ops_get_debug_level(__FILE__
)) {
665 (void) fprintf(stderr
, "Got body (2):\n%s\n",
668 CALLBACK(OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY
, cbinfo
,
673 if (body
->data
[0] != '\n') {
674 (void) fprintf(stderr
,
675 "process_dash_escaped: no newline in body data\n");
678 if (body
->length
!= 1) {
679 (void) fprintf(stderr
,
680 "process_dash_escaped: bad body length\n");
684 /* don't send that one character, because it's part of the trailer */
685 trailer
->hash
= hash
;
686 CALLBACK(OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER
, cbinfo
, &content2
);
691 add_header(dearmour_t
*dearmour
, const char *key
, const char *value
)
696 * Check that the header is valid
698 if (strcmp(key
, "Version") == 0 ||
699 strcmp(key
, "Comment") == 0 ||
700 strcmp(key
, "MessageID") == 0 ||
701 strcmp(key
, "Hash") == 0 ||
702 strcmp(key
, "Charset") == 0) {
703 n
= dearmour
->headers
.headerc
;
704 dearmour
->headers
.headers
= realloc(dearmour
->headers
.headers
,
705 (n
+ 1) * sizeof(*dearmour
->headers
.headers
));
706 if (dearmour
->headers
.headers
== NULL
) {
707 (void) fprintf(stderr
, "add_header: bad alloc\n");
710 dearmour
->headers
.headers
[n
].key
= strdup(key
);
711 dearmour
->headers
.headers
[n
].value
= strdup(value
);
712 dearmour
->headers
.headerc
= n
+ 1;
718 /* \todo what does a return value of 0 indicate? 1 is good, -1 is bad */
720 parse_headers(dearmour_t
*dearmour
, __ops_error_t
**errors
,
721 __ops_reader_t
* readinfo
, __ops_cbdata_t
* cbinfo
)
731 if ((buf
= calloc(1, size
)) == NULL
) {
732 (void) fprintf(stderr
, "parse_headers: bad calloc\n");
738 if ((c
= read_char(dearmour
, errors
, readinfo
, cbinfo
, 1)) < 0) {
739 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
, "Unexpected EOF");
751 (void) fprintf(stderr
,
752 "parse_headers: bad size\n");
757 if ((s
= strchr(buf
, ':')) == NULL
) {
758 if (!first
&& !dearmour
->allow_headers_without_gap
) {
760 * then we have seriously malformed
763 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
, "No colon in armour header");
768 !(dearmour
->allow_headers_without_gap
|| dearmour
->allow_no_gap
)) {
769 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
, "No colon in armour header (2)");
771 * then we have a nasty
772 * armoured block with no
773 * headers, not even a blank
777 push_back(dearmour
, (unsigned char *) buf
, nbuf
+ 1);
785 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
, "No space in armour header");
789 if (!add_header(dearmour
, buf
, s
+ 2)) {
790 OPS_ERROR_1(errors
, OPS_E_R_BAD_FORMAT
, "Invalid header %s", buf
);
798 if (size
<= nbuf
+ 1) {
800 buf
= realloc(buf
, size
);
802 (void) fprintf(stderr
, "bad alloc\n");
818 read4(dearmour_t
*dearmour
, __ops_error_t
**errors
,
819 __ops_reader_t
*readinfo
, __ops_cbdata_t
*cbinfo
,
820 int *pc
, unsigned *pn
, unsigned long *pl
)
825 for (n
= 0; n
< 4; ++n
) {
826 c
= read_char(dearmour
, errors
, readinfo
, cbinfo
, 1);
831 if (c
== '-' || c
== '=') {
835 if (c
>= 'A' && c
<= 'Z') {
836 l
+= (unsigned long)(c
- 'A');
837 } else if (c
>= 'a' && c
<= 'z') {
838 l
+= (unsigned long)(c
- 'a') + 26;
839 } else if (c
>= '0' && c
<= '9') {
840 l
+= (unsigned long)(c
- '0') + 52;
841 } else if (c
== '+') {
843 } else if (c
== '/') {
859 __ops_crc24(unsigned checksum
, unsigned char c
)
864 for (i
= 0; i
< 8; i
++) {
866 if (checksum
& 0x1000000)
867 checksum
^= CRC24_POLY
;
869 return checksum
& 0xffffffL
;
873 decode64(dearmour_t
*dearmour
, __ops_error_t
**errors
,
874 __ops_reader_t
*readinfo
, __ops_cbdata_t
*cbinfo
)
882 if (dearmour
->buffered
) {
883 (void) fprintf(stderr
, "decode64: bad dearmour->buffered\n");
887 ret
= read4(dearmour
, errors
, readinfo
, cbinfo
, &c
, &n
, &l
);
889 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
, "Badly formed base64");
894 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
895 "Badly terminated base64 (2)");
898 dearmour
->buffered
= 2;
903 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
904 "Badly terminated base64 (3)");
907 dearmour
->buffered
= 1;
910 c
= read_char(dearmour
, errors
, readinfo
, cbinfo
, 0);
912 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
913 "Badly terminated base64");
917 if (!dearmour
->prev_nl
|| c
!= '=') {
918 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
919 "Badly terminated base64 (4)");
922 dearmour
->buffered
= 0;
925 (void) fprintf(stderr
,
926 "decode64: bad n (!= 4)\n");
929 dearmour
->buffered
= 3;
930 if (c
== '-' || c
== '=') {
931 (void) fprintf(stderr
, "decode64: bad c\n");
936 if (dearmour
->buffered
< 3 && dearmour
->buffered
> 0) {
937 /* then we saw padding */
939 (void) fprintf(stderr
, "decode64: bad c (=)\n");
942 c
= read_and_eat_whitespace(dearmour
, errors
, readinfo
, cbinfo
,
945 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
946 "No newline at base64 end");
949 c
= read_char(dearmour
, errors
, readinfo
, cbinfo
, 0);
951 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
952 "No checksum at base64 end");
957 /* now we are at the checksum */
958 ret
= read4(dearmour
, errors
, readinfo
, cbinfo
, &c
, &n
,
959 &dearmour
->read_checksum
);
960 if (ret
< 0 || n
!= 4) {
961 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
962 "Error in checksum");
965 c
= read_char(dearmour
, errors
, readinfo
, cbinfo
, 1);
966 if (dearmour
->allow_trailing_whitespace
)
967 c
= eat_whitespace(c
, dearmour
, errors
, readinfo
, cbinfo
,
970 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
971 "Badly terminated checksum");
974 c
= read_char(dearmour
, errors
, readinfo
, cbinfo
, 0);
976 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
977 "Bad base64 trailer (2)");
982 for (n
= 0; n
< 4; ++n
)
983 if (read_char(dearmour
, errors
, readinfo
, cbinfo
,
985 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
986 "Bad base64 trailer");
991 if (!dearmour
->buffered
) {
992 (void) fprintf(stderr
, "decode64: not buffered\n");
997 for (n
= 0; n
< dearmour
->buffered
; ++n
) {
998 dearmour
->buffer
[n
] = (unsigned char)l
;
1002 for (n2
= dearmour
->buffered
- 1; n2
>= 0; --n2
)
1003 dearmour
->checksum
= __ops_crc24((unsigned)dearmour
->checksum
,
1004 dearmour
->buffer
[n2
]);
1006 if (dearmour
->eof64
&& dearmour
->read_checksum
!= dearmour
->checksum
) {
1007 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
, "Checksum mismatch");
1014 base64(dearmour_t
*dearmour
)
1016 dearmour
->state
= BASE64
;
1017 dearmour
->checksum
= CRC24_INIT
;
1018 dearmour
->eof64
= 0;
1019 dearmour
->buffered
= 0;
1022 /* This reader is rather strange in that it can generate callbacks for */
1023 /* content - this is because plaintext is not encapsulated in PGP */
1024 /* packets... it also calls back for the text between the blocks. */
1027 armoured_data_reader(void *dest_
, size_t length
, __ops_error_t
**errors
,
1028 __ops_reader_t
*readinfo
,
1029 __ops_cbdata_t
*cbinfo
)
1031 __ops_packet_t content
;
1032 unsigned char *dest
= dest_
;
1033 dearmour_t
*dearmour
;
1038 dearmour
= __ops_reader_get_arg(readinfo
);
1040 if (dearmour
->eof64
&& !dearmour
->buffered
) {
1041 if (dearmour
->state
!= OUTSIDE_BLOCK
&&
1042 dearmour
->state
!= AT_TRAILER_NAME
) {
1043 (void) fprintf(stderr
,
1044 "armoured_data_reader: bad dearmour state\n");
1049 while (length
> 0) {
1055 flush(dearmour
, cbinfo
);
1056 switch (dearmour
->state
) {
1059 * This code returns EOF rather than EARLY_EOF
1060 * because if we don't see a header line at all, then
1061 * it is just an EOF (and not a BLOCK_END)
1063 while (!dearmour
->seen_nl
) {
1064 if ((c
= unarmoured_read_char(dearmour
, errors
,
1065 readinfo
, cbinfo
, 1)) < 0) {
1071 * flush at this point so we definitely have room for
1072 * the header, and so we can easily erase it from the
1075 flush(dearmour
, cbinfo
);
1076 /* Find and consume the 5 leading '-' */
1077 for (count
= 0; count
< 5; ++count
) {
1078 if ((c
= unarmoured_read_char(dearmour
, errors
,
1079 readinfo
, cbinfo
, 0)) < 0) {
1087 /* Now find the block type */
1088 for (n
= 0; n
< sizeof(buf
) - 1;) {
1089 if ((c
= unarmoured_read_char(dearmour
, errors
,
1090 readinfo
, cbinfo
, 0)) < 0) {
1098 /* then I guess this wasn't a proper header */
1104 /* Consume trailing '-' */
1105 for (count
= 1; count
< 5; ++count
) {
1106 if ((c
= unarmoured_read_char(dearmour
, errors
,
1107 readinfo
, cbinfo
, 0)) < 0) {
1111 /* wasn't a header after all */
1116 /* Consume final NL */
1117 if ((c
= unarmoured_read_char(dearmour
, errors
, readinfo
,
1121 if (dearmour
->allow_trailing_whitespace
) {
1122 if ((c
= eat_whitespace(c
, dearmour
, errors
,
1123 readinfo
, cbinfo
, 1)) < 0) {
1128 /* wasn't a header line after all */
1133 * Now we've seen the header, scrub it from the
1136 dearmour
->unarmoredc
= 0;
1139 * But now we've seen a header line, then errors are
1142 if ((ret
= parse_headers(dearmour
, errors
, readinfo
,
1147 if (!set_lastseen_headerline(dearmour
, buf
, errors
)) {
1151 if (strcmp(buf
, "BEGIN PGP SIGNED MESSAGE") == 0) {
1153 &content
.u
.cleartext_head
.headers
,
1154 &dearmour
->headers
);
1155 CALLBACK(OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER
,
1158 ret
= process_dash_escaped(dearmour
, errors
,
1164 /* XXX Flexelint - Assigning address of auto variable 'buf' to outer
1165 scope symbol 'content'*/
1166 content
.u
.armour_header
.type
= buf
;
1167 content
.u
.armour_header
.headers
=
1169 (void) memset(&dearmour
->headers
, 0x0,
1170 sizeof(dearmour
->headers
));
1171 CALLBACK(OPS_PTAG_CT_ARMOUR_HEADER
, cbinfo
,
1179 while (length
> 0) {
1180 if (!dearmour
->buffered
) {
1181 if (!dearmour
->eof64
) {
1182 ret
= decode64(dearmour
,
1183 errors
, readinfo
, cbinfo
);
1188 if (!dearmour
->buffered
) {
1189 if (!dearmour
->eof64
) {
1190 (void) fprintf(stderr
,
1191 "armoured_data_reader: bad dearmour eof64\n");
1202 if (!dearmour
->buffered
) {
1203 (void) fprintf(stderr
,
1204 "armoured_data_reader: bad dearmour buffered\n");
1207 *dest
= dearmour
->buffer
[--dearmour
->buffered
];
1212 if (dearmour
->eof64
&& !dearmour
->buffered
) {
1213 dearmour
->state
= AT_TRAILER_NAME
;
1217 case AT_TRAILER_NAME
:
1218 for (n
= 0; n
< sizeof(buf
) - 1;) {
1219 if ((c
= read_char(dearmour
, errors
, readinfo
,
1228 /* then I guess this wasn't a proper trailer */
1229 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
1230 "Bad ASCII armour trailer");
1236 if (!set_lastseen_headerline(dearmour
, buf
, errors
)) {
1240 /* Consume trailing '-' */
1241 for (count
= 1; count
< 5; ++count
) {
1242 if ((c
= read_char(dearmour
, errors
, readinfo
,
1247 /* wasn't a trailer after all */
1248 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
1249 "Bad ASCII armour trailer (2)");
1253 /* Consume final NL */
1254 if ((c
= read_char(dearmour
, errors
, readinfo
, cbinfo
,
1258 if (dearmour
->allow_trailing_whitespace
) {
1259 if ((c
= eat_whitespace(c
, dearmour
, errors
,
1260 readinfo
, cbinfo
, 1)) < 0) {
1265 /* wasn't a trailer line after all */
1266 OPS_ERROR(errors
, OPS_E_R_BAD_FORMAT
,
1267 "Bad ASCII armour trailer (3)");
1270 if (strncmp(buf
, "BEGIN ", 6) == 0) {
1271 if (!set_lastseen_headerline(dearmour
, buf
,
1275 if ((ret
= parse_headers(dearmour
, errors
,
1276 readinfo
, cbinfo
)) <= 0) {
1279 content
.u
.armour_header
.type
= buf
;
1280 content
.u
.armour_header
.headers
=
1282 (void) memset(&dearmour
->headers
, 0x0,
1283 sizeof(dearmour
->headers
));
1284 CALLBACK(OPS_PTAG_CT_ARMOUR_HEADER
, cbinfo
,
1288 content
.u
.armour_trailer
.type
= buf
;
1289 CALLBACK(OPS_PTAG_CT_ARMOUR_TRAILER
, cbinfo
,
1291 dearmour
->state
= OUTSIDE_BLOCK
;
1303 armoured_data_destroyer(__ops_reader_t
*readinfo
)
1305 free(__ops_reader_get_arg(readinfo
));
1309 * \ingroup Core_Readers_Armour
1310 * \brief Pushes dearmouring reader onto stack
1311 * \param parse_info Usual structure containing information about to how to do the parse
1312 * \sa __ops_reader_pop_dearmour()
1315 __ops_reader_push_dearmour(__ops_stream_t
*parse_info
)
1317 * This function originally had these params to cater for packets which
1318 * didn't strictly match the RFC. The initial 0.5 release is only going to
1319 * support strict checking. If it becomes desirable to support loose checking
1320 * of armoured packets and these params are reinstated, parse_headers() must
1321 * be fixed so that these flags work correctly.
1323 * // Allow headers in armoured data that are not separated from the data by a
1324 * blank line unsigned without_gap,
1326 * // Allow no blank line at the start of armoured data unsigned no_gap,
1328 * //Allow armoured data to have trailing whitespace where we strictly would not
1329 * expect it unsigned trailing_whitespace
1332 dearmour_t
*dearmour
;
1334 if ((dearmour
= calloc(1, sizeof(*dearmour
))) == NULL
) {
1335 (void) fprintf(stderr
, "__ops_reader_push_dearmour: bad alloc\n");
1337 dearmour
->seen_nl
= 1;
1339 dearmour->allow_headers_without_gap=without_gap;
1340 dearmour->allow_no_gap=no_gap;
1341 dearmour->allow_trailing_whitespace=trailing_whitespace;
1343 dearmour
->expect_sig
= 0;
1344 dearmour
->got_sig
= 0;
1346 __ops_reader_push(parse_info
, armoured_data_reader
,
1347 armoured_data_destroyer
, dearmour
);
1352 * \ingroup Core_Readers_Armour
1353 * \brief Pops dearmour reader from stock
1355 * \sa __ops_reader_push_dearmour()
1358 __ops_reader_pop_dearmour(__ops_stream_t
*stream
)
1360 dearmour_t
*dearmour
;
1362 dearmour
= __ops_reader_get_arg(__ops_readinfo(stream
));
1364 __ops_reader_pop(stream
);
1367 /**************************************************************************/
1369 /* this is actually used for *decrypting* */
1371 unsigned char decrypted
[1024 * 15];
1374 __ops_crypt_t
*decrypt
;
1375 __ops_region_t
*region
;
1376 unsigned prevplain
:1;
1380 encrypted_data_reader(void *dest
,
1382 __ops_error_t
**errors
,
1383 __ops_reader_t
*readinfo
,
1384 __ops_cbdata_t
*cbinfo
)
1386 encrypted_t
*encrypted
;
1390 encrypted
= __ops_reader_get_arg(readinfo
);
1393 * V3 MPIs have the count plain and the cipher is reset after each
1396 if (encrypted
->prevplain
&& !readinfo
->parent
->reading_mpi_len
) {
1397 if (!readinfo
->parent
->reading_v3_secret
) {
1398 (void) fprintf(stderr
,
1399 "encrypted_data_reader: bad v3 secret\n");
1402 encrypted
->decrypt
->decrypt_resync(encrypted
->decrypt
);
1403 encrypted
->prevplain
= 0;
1404 } else if (readinfo
->parent
->reading_v3_secret
&&
1405 readinfo
->parent
->reading_mpi_len
) {
1406 encrypted
->prevplain
= 1;
1408 while (length
> 0) {
1413 * if we are reading v3 we should never read
1414 * more than we're asked for */
1415 if (length
< encrypted
->c
&&
1416 (readinfo
->parent
->reading_v3_secret
||
1417 readinfo
->parent
->exact_read
)) {
1418 (void) fprintf(stderr
,
1419 "encrypted_data_reader: bad v3 read\n");
1422 n
= MIN(length
, encrypted
->c
);
1424 encrypted
->decrypted
+ encrypted
->off
, n
);
1426 encrypted
->off
+= n
;
1432 unsigned n
= encrypted
->region
->length
;
1433 unsigned char buffer
[1024];
1438 if (!encrypted
->region
->indeterminate
) {
1439 n
-= encrypted
->region
->readc
;
1441 return saved
- length
;
1443 if (n
> sizeof(buffer
)) {
1451 * we can only read as much as we're asked for
1452 * in v3 keys because they're partially
1454 if ((readinfo
->parent
->reading_v3_secret
||
1455 readinfo
->parent
->exact_read
) && n
> length
) {
1459 if (!__ops_stacked_limited_read(buffer
, n
,
1460 encrypted
->region
, errors
, readinfo
, cbinfo
)) {
1463 if (!readinfo
->parent
->reading_v3_secret
||
1464 !readinfo
->parent
->reading_mpi_len
) {
1466 __ops_decrypt_se_ip(encrypted
->decrypt
,
1467 encrypted
->decrypted
, buffer
, n
);
1469 if (__ops_get_debug_level(__FILE__
)) {
1472 (void) fprintf(stderr
,
1473 "READING:\nencrypted: ");
1474 for (i
= 0; i
< 16; i
++) {
1475 (void) fprintf(stderr
,
1478 (void) fprintf(stderr
, "\ndecrypted: ");
1479 for (i
= 0; i
< 16; i
++) {
1480 (void) fprintf(stderr
, "%2x ",
1481 encrypted
->decrypted
[i
]);
1483 (void) fprintf(stderr
, "\n");
1487 &encrypted
->decrypted
[encrypted
->off
], buffer
, n
);
1491 if (encrypted
->c
== 0) {
1492 (void) fprintf(stderr
,
1493 "encrypted_data_reader: 0 decrypted count\n");
1505 encrypted_data_destroyer(__ops_reader_t
*readinfo
)
1507 free(__ops_reader_get_arg(readinfo
));
1511 * \ingroup Core_Readers_SE
1512 * \brief Pushes decryption reader onto stack
1513 * \sa __ops_reader_pop_decrypt()
1516 __ops_reader_push_decrypt(__ops_stream_t
*stream
, __ops_crypt_t
*decrypt
,
1517 __ops_region_t
*region
)
1519 encrypted_t
*encrypted
;
1521 if ((encrypted
= calloc(1, sizeof(*encrypted
))) == NULL
) {
1522 (void) fprintf(stderr
, "__ops_reader_push_decrypted: bad alloc\n");
1524 encrypted
->decrypt
= decrypt
;
1525 encrypted
->region
= region
;
1526 __ops_decrypt_init(encrypted
->decrypt
);
1527 __ops_reader_push(stream
, encrypted_data_reader
,
1528 encrypted_data_destroyer
, encrypted
);
1533 * \ingroup Core_Readers_Encrypted
1534 * \brief Pops decryption reader from stack
1535 * \sa __ops_reader_push_decrypt()
1538 __ops_reader_pop_decrypt(__ops_stream_t
*stream
)
1540 encrypted_t
*encrypted
;
1542 encrypted
= __ops_reader_get_arg(__ops_readinfo(stream
));
1543 encrypted
->decrypt
->decrypt_finish(encrypted
->decrypt
);
1545 __ops_reader_pop(stream
);
1548 /**************************************************************************/
1551 /* boolean: 0 once we've done the preamble/MDC checks */
1552 /* and are reading from the plaintext */
1554 unsigned char *plaintext
;
1555 size_t plaintext_available
;
1556 size_t plaintext_offset
;
1557 __ops_region_t
*region
;
1558 __ops_crypt_t
*decrypt
;
1562 Gets entire SE_IP data packet.
1563 Verifies leading preamble
1564 Verifies trailing MDC packet
1565 Then passes up plaintext as requested
1568 se_ip_data_reader(void *dest_
,
1570 __ops_error_t
**errors
,
1571 __ops_reader_t
*readinfo
,
1572 __ops_cbdata_t
*cbinfo
)
1574 decrypt_se_ip_t
*se_ip
;
1575 __ops_region_t decrypted_region
;
1578 se_ip
= __ops_reader_get_arg(readinfo
);
1579 if (!se_ip
->passed_checks
) {
1580 unsigned char *buf
= NULL
;
1581 unsigned char hashed
[OPS_SHA1_HASH_SIZE
];
1582 unsigned char *preamble
;
1583 unsigned char *plaintext
;
1585 unsigned char *mdc_hash
;
1591 size_t sz_plaintext
;
1593 __ops_hash_any(&hash
, OPS_HASH_SHA1
);
1594 if (!hash
.init(&hash
)) {
1595 (void) fprintf(stderr
,
1596 "se_ip_data_reader: can't init hash\n");
1600 __ops_init_subregion(&decrypted_region
, NULL
);
1601 decrypted_region
.length
=
1602 se_ip
->region
->length
- se_ip
->region
->readc
;
1603 if ((buf
= calloc(1, decrypted_region
.length
)) == NULL
) {
1604 (void) fprintf(stderr
, "se_ip_data_reader: bad alloc\n");
1608 /* read entire SE IP packet */
1609 if (!__ops_stacked_limited_read(buf
, decrypted_region
.length
,
1610 &decrypted_region
, errors
, readinfo
, cbinfo
)) {
1614 if (__ops_get_debug_level(__FILE__
)) {
1617 fprintf(stderr
, "\n\nentire SE IP packet (len=%d):\n",
1618 decrypted_region
.length
);
1619 for (i
= 0; i
< decrypted_region
.length
; i
++) {
1620 fprintf(stderr
, "0x%02x ", buf
[i
]);
1622 fprintf(stderr
, "\n");
1624 fprintf(stderr
, "\n\n");
1626 /* verify leading preamble */
1628 if (__ops_get_debug_level(__FILE__
)) {
1631 fprintf(stderr
, "\npreamble: ");
1632 for (i
= 0; i
< se_ip
->decrypt
->blocksize
+ 2; i
++)
1633 fprintf(stderr
, " 0x%02x", buf
[i
]);
1634 fprintf(stderr
, "\n");
1636 b
= se_ip
->decrypt
->blocksize
;
1637 if (buf
[b
- 2] != buf
[b
] || buf
[b
- 1] != buf
[b
+ 1]) {
1639 "Bad symmetric decrypt (%02x%02x vs %02x%02x)\n",
1640 buf
[b
- 2], buf
[b
- 1], buf
[b
], buf
[b
+ 1]);
1641 OPS_ERROR(errors
, OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT
,
1642 "Bad symmetric decrypt when parsing SE IP packet");
1646 /* Verify trailing MDC hash */
1648 sz_preamble
= se_ip
->decrypt
->blocksize
+ 2;
1649 sz_mdc_hash
= OPS_SHA1_HASH_SIZE
;
1650 sz_mdc
= 1 + 1 + sz_mdc_hash
;
1651 sz_plaintext
= (decrypted_region
.length
- sz_preamble
) - sz_mdc
;
1654 plaintext
= buf
+ sz_preamble
;
1655 mdc
= plaintext
+ sz_plaintext
;
1658 if (__ops_get_debug_level(__FILE__
)) {
1661 fprintf(stderr
, "\nplaintext (len=%" PRIsize
"u): ",
1663 for (i
= 0; i
< sz_plaintext
; i
++)
1664 fprintf(stderr
, " 0x%02x", plaintext
[i
]);
1665 fprintf(stderr
, "\n");
1667 fprintf(stderr
, "\nmdc (len=%" PRIsize
"u): ", sz_mdc
);
1668 for (i
= 0; i
< sz_mdc
; i
++)
1669 fprintf(stderr
, " 0x%02x", mdc
[i
]);
1670 fprintf(stderr
, "\n");
1672 __ops_calc_mdc_hash(preamble
, sz_preamble
, plaintext
,
1673 sz_plaintext
, hashed
);
1675 if (memcmp(mdc_hash
, hashed
, OPS_SHA1_HASH_SIZE
) != 0) {
1676 OPS_ERROR(errors
, OPS_E_V_BAD_HASH
,
1677 "Bad hash in MDC packet");
1681 /* all done with the checks */
1682 /* now can start reading from the plaintext */
1683 if (se_ip
->plaintext
) {
1684 (void) fprintf(stderr
,
1685 "se_ip_data_reader: bad plaintext\n");
1688 if ((se_ip
->plaintext
= calloc(1, sz_plaintext
)) == NULL
) {
1689 (void) fprintf(stderr
,
1690 "se_ip_data_reader: bad alloc\n");
1693 memcpy(se_ip
->plaintext
, plaintext
, sz_plaintext
);
1694 se_ip
->plaintext_available
= sz_plaintext
;
1696 se_ip
->passed_checks
= 1;
1701 if (n
> se_ip
->plaintext_available
) {
1702 n
= se_ip
->plaintext_available
;
1705 memcpy(dest_
, se_ip
->plaintext
+ se_ip
->plaintext_offset
, n
);
1706 se_ip
->plaintext_available
-= n
;
1707 se_ip
->plaintext_offset
+= n
;
1708 /* len -= n; - not used at all, for info only */
1714 se_ip_data_destroyer(__ops_reader_t
*readinfo
)
1716 decrypt_se_ip_t
*se_ip
;
1718 se_ip
= __ops_reader_get_arg(readinfo
);
1719 free(se_ip
->plaintext
);
1724 \ingroup Internal_Readers_SEIP
1727 __ops_reader_push_se_ip_data(__ops_stream_t
*stream
, __ops_crypt_t
*decrypt
,
1728 __ops_region_t
* region
)
1730 decrypt_se_ip_t
*se_ip
;
1732 if ((se_ip
= calloc(1, sizeof(*se_ip
))) == NULL
) {
1733 (void) fprintf(stderr
, "__ops_reader_push_se_ip_data: bad alloc\n");
1735 se_ip
->region
= region
;
1736 se_ip
->decrypt
= decrypt
;
1737 __ops_reader_push(stream
, se_ip_data_reader
, se_ip_data_destroyer
,
1743 \ingroup Internal_Readers_SEIP
1746 __ops_reader_pop_se_ip_data(__ops_stream_t
*stream
)
1750 * *se_ip=__ops_reader_get_arg(__ops_readinfo(stream));
1753 __ops_reader_pop(stream
);
1756 /**************************************************************************/
1758 /** Arguments for reader_fd
1760 typedef struct mmap_reader_t
{
1761 void *mem
; /* memory mapped file */
1762 uint64_t size
; /* size of file */
1763 uint64_t offset
; /* current offset in file */
1764 int fd
; /* file descriptor */
1769 * \ingroup Core_Readers
1771 * __ops_reader_fd() attempts to read up to "plength" bytes from the file
1772 * descriptor in "parse_info" into the buffer starting at "dest" using the
1773 * rules contained in "flags"
1775 * \param dest Pointer to previously allocated buffer
1776 * \param plength Number of bytes to try to read
1777 * \param flags Rules about reading to use
1778 * \param readinfo Reader info
1779 * \param cbinfo Callback info
1781 * \return n Number of bytes read
1783 * OPS_R_EARLY_EOF and OPS_R_ERROR push errors on the stack
1786 fd_reader(void *dest
, size_t length
, __ops_error_t
**errors
,
1787 __ops_reader_t
*readinfo
, __ops_cbdata_t
*cbinfo
)
1789 mmap_reader_t
*reader
= __ops_reader_get_arg(readinfo
);
1790 int n
= read(reader
->fd
, dest
, length
);
1796 OPS_SYSTEM_ERROR_1(errors
, OPS_E_R_READ_FAILED
, "read",
1797 "file descriptor %d", reader
->fd
);
1804 reader_fd_destroyer(__ops_reader_t
*readinfo
)
1806 free(__ops_reader_get_arg(readinfo
));
1810 \ingroup Core_Readers_First
1811 \brief Starts stack with file reader
1815 __ops_reader_set_fd(__ops_stream_t
*stream
, int fd
)
1817 mmap_reader_t
*reader
;
1819 if ((reader
= calloc(1, sizeof(*reader
))) == NULL
) {
1820 (void) fprintf(stderr
, "__ops_reader_set_fd: bad alloc\n");
1823 __ops_reader_set(stream
, fd_reader
, reader_fd_destroyer
, reader
);
1827 /**************************************************************************/
1830 const unsigned char *buffer
;
1836 mem_reader(void *dest
, size_t length
, __ops_error_t
**errors
,
1837 __ops_reader_t
*readinfo
, __ops_cbdata_t
*cbinfo
)
1839 reader_mem_t
*reader
= __ops_reader_get_arg(readinfo
);
1845 if (reader
->offset
+ length
> reader
->length
)
1846 n
= reader
->length
- reader
->offset
;
1853 memcpy(dest
, reader
->buffer
+ reader
->offset
, n
);
1854 reader
->offset
+= n
;
1860 mem_destroyer(__ops_reader_t
*readinfo
)
1862 free(__ops_reader_get_arg(readinfo
));
1866 \ingroup Core_Readers_First
1867 \brief Starts stack with memory reader
1871 __ops_reader_set_memory(__ops_stream_t
*stream
, const void *buffer
,
1876 if ((mem
= calloc(1, sizeof(*mem
))) == NULL
) {
1877 (void) fprintf(stderr
, "__ops_reader_set_memory: bad alloc\n");
1879 mem
->buffer
= buffer
;
1880 mem
->length
= length
;
1882 __ops_reader_set(stream
, mem_reader
, mem_destroyer
, mem
);
1886 /**************************************************************************/
1889 \ingroup Core_Writers
1890 \brief Create and initialise output and mem; Set for writing to mem
1891 \param output Address where new output pointer will be set
1892 \param mem Address when new mem pointer will be set
1893 \param bufsz Initial buffer size (will automatically be increased when necessary)
1894 \note It is the caller's responsiblity to free output and mem.
1895 \sa __ops_teardown_memory_write()
1898 __ops_setup_memory_write(__ops_output_t
**output
, __ops_memory_t
**mem
, size_t bufsz
)
1901 * initialise needed structures for writing to memory
1904 *output
= __ops_output_new();
1905 *mem
= __ops_memory_new();
1907 __ops_memory_init(*mem
, bufsz
);
1909 __ops_writer_set_memory(*output
, *mem
);
1913 \ingroup Core_Writers
1914 \brief Closes writer and frees output and mem
1917 \sa __ops_setup_memory_write()
1920 __ops_teardown_memory_write(__ops_output_t
*output
, __ops_memory_t
*mem
)
1922 __ops_writer_close(output
);/* new */
1923 __ops_output_delete(output
);
1924 __ops_memory_free(mem
);
1928 \ingroup Core_Readers
1929 \brief Create parse_info and sets to read from memory
1930 \param stream Address where new parse_info will be set
1931 \param mem Memory to read from
1932 \param arg Reader-specific arg
1933 \param callback Callback to use with reader
1934 \param accumulate Set if we need to accumulate as we read. (Usually 0 unless doing signature verification)
1935 \note It is the caller's responsiblity to free parse_info
1936 \sa __ops_teardown_memory_read()
1939 __ops_setup_memory_read(__ops_io_t
*io
,
1940 __ops_stream_t
**stream
,
1941 __ops_memory_t
*mem
,
1943 __ops_cb_ret_t
callback(const __ops_packet_t
*,
1945 unsigned accumulate
)
1947 *stream
= __ops_new(sizeof(**stream
));
1948 (*stream
)->io
= (*stream
)->cbinfo
.io
= io
;
1949 __ops_set_callback(*stream
, callback
, vp
);
1950 __ops_reader_set_memory(*stream
,
1951 __ops_mem_data(mem
),
1952 __ops_mem_len(mem
));
1954 (*stream
)->readinfo
.accumulate
= 1;
1959 \ingroup Core_Readers
1960 \brief Frees stream and mem
1963 \sa __ops_setup_memory_read()
1966 __ops_teardown_memory_read(__ops_stream_t
*stream
, __ops_memory_t
*mem
)
1968 __ops_stream_delete(stream
);
1969 __ops_memory_free(mem
);
1973 \ingroup Core_Writers
1974 \brief Create and initialise output and mem; Set for writing to file
1975 \param output Address where new output pointer will be set
1976 \param filename File to write to
1977 \param allow_overwrite Allows file to be overwritten, if set.
1978 \return Newly-opened file descriptor
1979 \note It is the caller's responsiblity to free output and to close fd.
1980 \sa __ops_teardown_file_write()
1983 __ops_setup_file_write(__ops_output_t
**output
, const char *filename
,
1984 unsigned allow_overwrite
)
1990 * initialise needed structures for writing to file
1992 if (filename
== NULL
) {
1993 /* write to stdout */
1996 flags
= O_WRONLY
| O_CREAT
;
1997 if (allow_overwrite
)
2004 fd
= open(filename
, flags
, 0600);
2010 *output
= __ops_output_new();
2011 __ops_writer_set_fd(*output
, fd
);
2016 \ingroup Core_Writers
2017 \brief Closes writer, frees info, closes fd
2022 __ops_teardown_file_write(__ops_output_t
*output
, int fd
)
2024 __ops_writer_close(output
);
2026 __ops_output_delete(output
);
2030 \ingroup Core_Writers
2031 \brief As __ops_setup_file_write, but appends to file
2034 __ops_setup_file_append(__ops_output_t
**output
, const char *filename
)
2038 * initialise needed structures for writing to file
2042 fd
= open(filename
, O_WRONLY
| O_APPEND
| O_BINARY
, 0600);
2044 fd
= open(filename
, O_WRONLY
| O_APPEND
, 0600);
2050 *output
= __ops_output_new();
2052 __ops_writer_set_fd(*output
, fd
);
2058 \ingroup Core_Writers
2059 \brief As __ops_teardown_file_write()
2062 __ops_teardown_file_append(__ops_output_t
*output
, int fd
)
2064 __ops_teardown_file_write(output
, fd
);
2068 \ingroup Core_Readers
2069 \brief Creates parse_info, opens file, and sets to read from file
2070 \param stream Address where new parse_info will be set
2071 \param filename Name of file to read
2072 \param vp Reader-specific arg
2073 \param callback Callback to use when reading
2074 \param accumulate Set if we need to accumulate as we read. (Usually 0 unless doing signature verification)
2075 \note It is the caller's responsiblity to free parse_info and to close fd
2076 \sa __ops_teardown_file_read()
2079 __ops_setup_file_read(__ops_io_t
*io
,
2080 __ops_stream_t
**stream
,
2081 const char *filename
,
2083 __ops_cb_ret_t
callback(const __ops_packet_t
*,
2085 unsigned accumulate
)
2090 fd
= open(filename
, O_RDONLY
| O_BINARY
);
2092 fd
= open(filename
, O_RDONLY
);
2095 (void) fprintf(io
->errs
, "can't open \"%s\"\n", filename
);
2098 *stream
= __ops_new(sizeof(**stream
));
2099 (*stream
)->io
= (*stream
)->cbinfo
.io
= io
;
2100 __ops_set_callback(*stream
, callback
, vp
);
2101 #ifdef USE_MMAP_FOR_FILES
2102 __ops_reader_set_mmap(*stream
, fd
);
2104 __ops_reader_set_fd(*stream
, fd
);
2107 (*stream
)->readinfo
.accumulate
= 1;
2113 \ingroup Core_Readers
2114 \brief Frees stream and closes fd
2117 \sa __ops_setup_file_read()
2120 __ops_teardown_file_read(__ops_stream_t
*stream
, int fd
)
2123 __ops_stream_delete(stream
);
2127 litdata_cb(const __ops_packet_t
*pkt
, __ops_cbdata_t
*cbinfo
)
2129 const __ops_contents_t
*content
= &pkt
->u
;
2131 if (__ops_get_debug_level(__FILE__
)) {
2132 printf("litdata_cb: ");
2133 __ops_print_packet(pkt
);
2135 /* Read data from packet into static buffer */
2137 case OPS_PTAG_CT_LITDATA_BODY
:
2138 /* if writer enabled, use it */
2139 if (cbinfo
->output
) {
2140 if (__ops_get_debug_level(__FILE__
)) {
2141 printf("litdata_cb: length is %u\n",
2142 content
->litdata_body
.length
);
2144 __ops_write(cbinfo
->output
,
2145 content
->litdata_body
.data
,
2146 content
->litdata_body
.length
);
2150 case OPS_PTAG_CT_LITDATA_HEADER
:
2158 return OPS_RELEASE_MEMORY
;
2162 pk_sesskey_cb(const __ops_packet_t
*pkt
, __ops_cbdata_t
*cbinfo
)
2164 const __ops_contents_t
*content
= &pkt
->u
;
2169 if (__ops_get_debug_level(__FILE__
)) {
2170 __ops_print_packet(pkt
);
2172 /* Read data from packet into static buffer */
2174 case OPS_PTAG_CT_PK_SESSION_KEY
:
2175 if (__ops_get_debug_level(__FILE__
)) {
2176 printf("OPS_PTAG_CT_PK_SESSION_KEY\n");
2178 if (!cbinfo
->cryptinfo
.keyring
) {
2179 (void) fprintf(io
->errs
,
2180 "pk_sesskey_cb: bad keyring\n");
2181 return (__ops_cb_ret_t
)0;
2184 cbinfo
->cryptinfo
.keydata
=
2185 __ops_getkeybyid(io
, cbinfo
->cryptinfo
.keyring
,
2186 content
->pk_sesskey
.key_id
, &from
);
2187 if (!cbinfo
->cryptinfo
.keydata
) {
2196 return OPS_RELEASE_MEMORY
;
2200 \ingroup Core_Callbacks
2202 \brief Callback to get secret key, decrypting if necessary.
2205 This callback does the following:
2206 * finds the session key in the keyring
2207 * gets a passphrase if required
2208 * decrypts the secret key, if necessary
2209 * sets the seckey in the content struct
2214 get_seckey_cb(const __ops_packet_t
*pkt
, __ops_cbdata_t
*cbinfo
)
2216 const __ops_contents_t
*content
= &pkt
->u
;
2217 const __ops_seckey_t
*secret
;
2218 const __ops_key_t
*keypair
;
2223 if (__ops_get_debug_level(__FILE__
)) {
2224 __ops_print_packet(pkt
);
2227 case OPS_GET_SECKEY
:
2229 cbinfo
->cryptinfo
.keydata
=
2230 __ops_getkeybyid(io
, cbinfo
->cryptinfo
.keyring
,
2231 content
->get_seckey
.pk_sesskey
->key_id
,
2233 if (!cbinfo
->cryptinfo
.keydata
||
2234 !__ops_is_key_secret(cbinfo
->cryptinfo
.keydata
)) {
2235 return (__ops_cb_ret_t
)0;
2238 keypair
= cbinfo
->cryptinfo
.keydata
;
2240 /* print out the user id */
2241 __ops_print_keydata(io
, keypair
, "pub", &keypair
->key
.pubkey
);
2242 /* now decrypt key */
2243 secret
= __ops_decrypt_seckey(keypair
);
2244 if (secret
== NULL
) {
2245 (void) fprintf(io
->errs
, "Bad passphrase\n");
2247 } while (secret
== NULL
);
2248 *content
->get_seckey
.seckey
= secret
;
2255 return OPS_RELEASE_MEMORY
;
2259 \ingroup HighLevel_Callbacks
2260 \brief Callback to use when you need to prompt user for passphrase
2265 get_passphrase_cb(const __ops_packet_t
*pkt
, __ops_cbdata_t
*cbinfo
)
2267 const __ops_contents_t
*content
= &pkt
->u
;
2271 if (__ops_get_debug_level(__FILE__
)) {
2272 __ops_print_packet(pkt
);
2274 if (cbinfo
->cryptinfo
.keydata
== NULL
) {
2275 (void) fprintf(io
->errs
, "get_passphrase_cb: NULL keydata\n");
2277 __ops_print_keydata(io
, cbinfo
->cryptinfo
.keydata
, "pub",
2278 &cbinfo
->cryptinfo
.keydata
->key
.pubkey
);
2281 case OPS_GET_PASSPHRASE
:
2282 *(content
->skey_passphrase
.passphrase
) =
2283 strdup(getpass("netpgp passphrase: "));
2284 return OPS_KEEP_MEMORY
;
2288 return OPS_RELEASE_MEMORY
;
2292 __ops_reader_set_accumulate(__ops_stream_t
*stream
, unsigned state
)
2294 return stream
->readinfo
.accumulate
= state
;
2297 /**************************************************************************/
2300 hash_reader(void *dest
,
2302 __ops_error_t
**errors
,
2303 __ops_reader_t
*readinfo
,
2304 __ops_cbdata_t
*cbinfo
)
2306 __ops_hash_t
*hash
= __ops_reader_get_arg(readinfo
);
2309 r
= __ops_stacked_read(dest
, length
, errors
, readinfo
, cbinfo
);
2313 hash
->add(hash
, dest
, (unsigned)r
);
2318 \ingroup Internal_Readers_Hash
2319 \brief Push hashed data reader on stack
2322 __ops_reader_push_hash(__ops_stream_t
*stream
, __ops_hash_t
*hash
)
2324 if (!hash
->init(hash
)) {
2325 (void) fprintf(stderr
, "__ops_reader_push_hash: can't init hash\n");
2326 /* just continue and die */
2327 /* XXX - agc - no way to return failure */
2329 __ops_reader_push(stream
, hash_reader
, NULL
, hash
);
2333 \ingroup Internal_Readers_Hash
2334 \brief Pop hashed data reader from stack
2337 __ops_reader_pop_hash(__ops_stream_t
*stream
)
2339 __ops_reader_pop(stream
);
2342 /* read memory from the previously mmap-ed file */
2344 mmap_reader(void *dest
, size_t length
, __ops_error_t
**errors
,
2345 __ops_reader_t
*readinfo
, __ops_cbdata_t
*cbinfo
)
2347 mmap_reader_t
*mem
= __ops_reader_get_arg(readinfo
);
2349 char *cmem
= mem
->mem
;
2353 n
= MIN(length
, (unsigned)(mem
->size
- mem
->offset
));
2355 (void) memcpy(dest
, &cmem
[(int)mem
->offset
], (unsigned)n
);
2361 /* tear down the mmap, close the fd */
2363 mmap_destroyer(__ops_reader_t
*readinfo
)
2365 mmap_reader_t
*mem
= __ops_reader_get_arg(readinfo
);
2367 (void) munmap(mem
->mem
, (unsigned)mem
->size
);
2368 (void) close(mem
->fd
);
2369 free(__ops_reader_get_arg(readinfo
));
2372 /* set up the file to use mmap-ed memory if available, file IO otherwise */
2374 __ops_reader_set_mmap(__ops_stream_t
*stream
, int fd
)
2379 if (fstat(fd
, &st
) != 0) {
2380 (void) fprintf(stderr
, "__ops_reader_set_mmap: can't fstat\n");
2381 } else if ((mem
= calloc(1, sizeof(*mem
))) == NULL
) {
2382 (void) fprintf(stderr
, "__ops_reader_set_mmap: bad alloc\n");
2384 mem
->size
= (uint64_t)st
.st_size
;
2387 mem
->mem
= mmap(NULL
, (size_t)st
.st_size
, PROT_READ
,
2388 MAP_PRIVATE
| MAP_FILE
, fd
, 0);
2389 if (mem
->mem
== MAP_FAILED
) {
2390 __ops_reader_set(stream
, fd_reader
, reader_fd_destroyer
,
2393 __ops_reader_set(stream
, mmap_reader
, mmap_destroyer
,