diff --git a/include/rnp/rnp.h b/include/rnp/rnp.h index 55b06d0743..75311e6a5b 100644 --- a/include/rnp/rnp.h +++ b/include/rnp/rnp.h @@ -2707,6 +2707,17 @@ RNP_API rnp_result_t rnp_op_verify_get_file_info(rnp_op_verify_t op, char ** filename, uint32_t * mtime); +/** + * @brief Get format of the data stored in the message, if available. + * + * @param op opaque verification context. Must be initialized and have execute() called on it. + * @param format character describing format would be stored here, see RFC 4880 section 5.9 and + * further standard extensions for possible values. If information is not + * available then '\0' value will be stored here. Cannot be NULL. + * @return RNP_SUCCESS if call succeeded. + */ +RNP_API rnp_result_t rnp_op_verify_get_format(rnp_op_verify_t op, char *format); + /** * @brief Get data protection (encryption) mode, used in processed message. * diff --git a/src/lib/ffi-priv-types.h b/src/lib/ffi-priv-types.h index 8164580c8b..97f012748f 100644 --- a/src/lib/ffi-priv-types.h +++ b/src/lib/ffi-priv-types.h @@ -187,8 +187,7 @@ struct rnp_op_verify_st { rnp_ctx_t rnpctx{}; /* these fields are filled after operation execution */ std::vector signatures_; - std::string filename; - uint32_t file_mtime{}; + pgp_literal_hdr_t lithdr{}; /* encryption information */ bool encrypted{}; bool mdc{}; diff --git a/src/lib/rnp.cpp b/src/lib/rnp.cpp index 7e1a1965d6..ac18368811 100644 --- a/src/lib/rnp.cpp +++ b/src/lib/rnp.cpp @@ -3110,11 +3110,10 @@ rnp_verify_src_provider(pgp_parse_handler_t *handler, pgp_source_t *src) }; static bool -rnp_verify_dest_provider(pgp_parse_handler_t *handler, - pgp_dest_t ** dst, - bool * closedst, - const char * filename, - uint32_t mtime) +rnp_verify_dest_provider(pgp_parse_handler_t * handler, + pgp_dest_t ** dst, + bool * closedst, + const pgp_literal_hdr_t *lithdr) { rnp_op_verify_t op = (rnp_op_verify_t) handler->param; if (!op->output) { @@ -3122,8 +3121,7 @@ rnp_verify_dest_provider(pgp_parse_handler_t *handler, } *dst = &(op->output->dst); *closedst = false; - op->filename = filename ? std::string(filename) : ""; - op->file_mtime = mtime; + op->lithdr = lithdr ? *lithdr : pgp_literal_hdr_t(); return true; } @@ -3396,9 +3394,24 @@ try { return RNP_ERROR_NULL_POINTER; } if (mtime) { - *mtime = op->file_mtime; + *mtime = op->lithdr.timestamp; } - return filename ? ret_str_value(op->filename.c_str(), filename) : RNP_SUCCESS; + if (!filename) { + return RNP_SUCCESS; + } + const std::string fname(op->lithdr.fname, op->lithdr.fname_len); + return ret_str_value(fname.c_str(), filename); +} +FFI_GUARD + +rnp_result_t +rnp_op_verify_get_format(rnp_op_verify_t op, char *format) +try { + if (!op || !format) { + return RNP_ERROR_NULL_POINTER; + } + *format = (char) op->lithdr.format; + return RNP_SUCCESS; } FFI_GUARD diff --git a/src/lib/types.h b/src/lib/types.h index f14459ea91..706463b922 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -365,10 +365,10 @@ typedef enum { } pgp_key_server_prefs_t; typedef struct pgp_literal_hdr_t { - uint8_t format; - char fname[256]; - uint8_t fname_len; - uint32_t timestamp; + uint8_t format{}; + char fname[256]{}; + uint8_t fname_len{}; + uint32_t timestamp{}; } pgp_literal_hdr_t; typedef struct pgp_aead_hdr_t { diff --git a/src/librepgp/stream-parse.cpp b/src/librepgp/stream-parse.cpp index 60e6b528ff..fd2c3bd5ee 100644 --- a/src/librepgp/stream-parse.cpp +++ b/src/librepgp/stream-parse.cpp @@ -1968,11 +1968,11 @@ init_literal_src(pgp_source_t *src, pgp_source_t *readsrc) case 'u': case 'l': case '1': + case 'm': break; default: - RNP_LOG("unknown data format %" PRIu8, format); - ret = RNP_ERROR_BAD_FORMAT; - goto finish; + RNP_LOG("Warning: unknown data format %" PRIu8 ", ignoring.", format); + break; } param->hdr.format = format; /* file name */ @@ -2913,20 +2913,17 @@ process_pgp_source(pgp_parse_handler_t *handler, pgp_source_t &src) } /* file processing case */ decsrc = &ctx.sources.back(); - const char *filename = NULL; - uint32_t mtime = 0; + const pgp_literal_hdr_t *lithdr = nullptr; if (ctx.literal_src) { - auto &hdr = get_literal_src_hdr(*ctx.literal_src); - filename = hdr.fname; - mtime = hdr.timestamp; + lithdr = &get_literal_src_hdr(*ctx.literal_src); if (ctx.signed_src) { - signed_src_set_literal_hdr(*ctx.signed_src, hdr); + signed_src_set_literal_hdr(*ctx.signed_src, *lithdr); } } if (!handler->dest_provider || - !handler->dest_provider(handler, &outdest, &closeout, filename, mtime)) { + !handler->dest_provider(handler, &outdest, &closeout, lithdr)) { res = RNP_ERROR_WRITE; goto finish; } diff --git a/src/librepgp/stream-parse.h b/src/librepgp/stream-parse.h index 9b905e2ed6..2af2fbc36a 100644 --- a/src/librepgp/stream-parse.h +++ b/src/librepgp/stream-parse.h @@ -37,11 +37,10 @@ typedef struct pgp_parse_handler_t pgp_parse_handler_t; typedef struct pgp_signature_info_t pgp_signature_info_t; -typedef bool pgp_destination_func_t(pgp_parse_handler_t *handler, - pgp_dest_t ** dst, - bool * closedst, - const char * filename, - uint32_t mtime); +typedef bool pgp_destination_func_t(pgp_parse_handler_t * handler, + pgp_dest_t ** dst, + bool * closedst, + const pgp_literal_hdr_t *lithdr); typedef bool pgp_source_func_t(pgp_parse_handler_t *handler, pgp_source_t *src); typedef void pgp_signatures_func_t(const std::vector &sigs, void *param); diff --git a/src/tests/data/test_messages/message.txt.signed-mimemode b/src/tests/data/test_messages/message.txt.signed-mimemode new file mode 100644 index 0000000000..27f75798f1 Binary files /dev/null and b/src/tests/data/test_messages/message.txt.signed-mimemode differ diff --git a/src/tests/ffi-enc.cpp b/src/tests/ffi-enc.cpp index 9512344bb4..7874a6fc4f 100644 --- a/src/tests/ffi-enc.cpp +++ b/src/tests/ffi-enc.cpp @@ -1519,3 +1519,32 @@ TEST_F(rnp_tests, test_ffi_v5_signatures) rnp_ffi_destroy(ffi); } + +TEST_F(rnp_tests, test_ffi_mimemode_signature) +{ + rnp_ffi_t ffi = NULL; + assert_rnp_success(rnp_ffi_create(&ffi, "GPG", "GPG")); + assert_true(import_pub_keys(ffi, "data/test_stream_key_load/ecc-25519-pub.asc")); + + rnp_input_t input = NULL; + assert_rnp_success( + rnp_input_from_path(&input, "data/test_messages/message.txt.signed-mimemode")); + rnp_output_t output = NULL; + assert_rnp_success(rnp_output_to_null(&output)); + rnp_op_verify_t verify = NULL; + assert_rnp_success(rnp_op_verify_create(&verify, ffi, input, output)); + assert_rnp_success(rnp_op_verify_execute(verify)); + size_t sigcount = 255; + assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); + assert_int_equal(sigcount, 1); + rnp_op_verify_signature_t sig = NULL; + assert_rnp_success(rnp_op_verify_get_signature_at(verify, 0, &sig)); + assert_rnp_success(rnp_op_verify_signature_get_status(sig)); + char format = 0; + assert_rnp_success(rnp_op_verify_get_format(verify, &format)); + assert_int_equal(format, 'm'); + rnp_op_verify_destroy(verify); + rnp_input_destroy(input); + rnp_output_destroy(output); + rnp_ffi_destroy(ffi); +} diff --git a/src/tests/ffi.cpp b/src/tests/ffi.cpp index feab1099c9..ad7155cce3 100644 --- a/src/tests/ffi.cpp +++ b/src/tests/ffi.cpp @@ -3833,6 +3833,11 @@ TEST_F(rnp_tests, test_ffi_op_verify_sig_count) assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); assert_int_equal(sigcount, 1); assert_true(check_signature(verify, 0, RNP_SUCCESS)); + char format = 'b'; + assert_rnp_failure(rnp_op_verify_get_format(NULL, &format)); + assert_rnp_failure(rnp_op_verify_get_format(verify, NULL)); + assert_rnp_success(rnp_op_verify_get_format(verify, &format)); + assert_int_equal(format, '\0'); rnp_op_verify_destroy(verify); rnp_input_destroy(source); rnp_input_destroy(input); @@ -3879,6 +3884,11 @@ TEST_F(rnp_tests, test_ffi_op_verify_sig_count) assert_rnp_success(rnp_op_verify_get_signature_count(verify, &sigcount)); assert_int_equal(sigcount, 1); assert_true(check_signature(verify, 0, RNP_SUCCESS)); + format = '\0'; + assert_rnp_failure(rnp_op_verify_get_format(NULL, &format)); + assert_rnp_failure(rnp_op_verify_get_format(verify, NULL)); + assert_rnp_success(rnp_op_verify_get_format(verify, &format)); + assert_int_equal(format, 't'); rnp_op_verify_destroy(verify); rnp_input_destroy(input); rnp_output_destroy(output);