/** * mail_importer_add_line: * importer: A MailImporter structure. * str: Next line of the mbox. * finished: TRUE if @str is the last line of the message. * * Adds lines to the message until it is finished, and then adds * the complete message to the folder. */ void mail_importer_add_line (MailImporter *importer, const char *str, gboolean finished) { CamelMimeMessage *msg; CamelMessageInfo *info; CamelException *ex; if (importer->mstream == NULL) importer->mstream = CAMEL_STREAM_MEM (camel_stream_mem_new ()); camel_stream_write (CAMEL_STREAM (importer->mstream), str, strlen (str)); if (finished == FALSE) return; camel_stream_reset (CAMEL_STREAM (importer->mstream)); info = camel_message_info_new(NULL); camel_message_info_set_flags(info, CAMEL_MESSAGE_SEEN, ~0); msg = camel_mime_message_new (); camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), CAMEL_STREAM (importer->mstream)); camel_object_unref (importer->mstream); importer->mstream = NULL; ex = camel_exception_new (); camel_folder_append_message (importer->folder, msg, info, NULL, ex); camel_object_unref (msg); camel_exception_free (ex); camel_message_info_free(info); }
static CamelStream * insert_finish (CamelImapMessageCache *cache, const char *uid, char *path, char *key, CamelStream *stream) { camel_stream_flush (stream); camel_stream_reset (stream); cache_put (cache, uid, key, stream); g_free (path); return stream; }
/** * camel_imap_message_cache_get: * @cache: the cache * @uid: the UID of the data to get * @part_spec: the part_spec of the data to get * @ex: exception * * Return value: a CamelStream containing the cached data (which the * caller must unref), or %NULL if that data is not cached. **/ CamelStream * camel_imap_message_cache_get (CamelImapMessageCache *cache, const char *uid, const char *part_spec, CamelException *ex) { CamelStream *stream; char *path, *key; if (uid[0] == 0) return NULL; #ifdef G_OS_WIN32 /* See comment in insert_setup() */ if (!*part_spec) part_spec = "~"; #endif path = g_strdup_printf ("%s/%s.%s", cache->path, uid, part_spec); key = strrchr (path, '/') + 1; stream = g_hash_table_lookup (cache->parts, key); if (stream) { camel_stream_reset (CAMEL_STREAM (stream)); camel_object_ref (CAMEL_OBJECT (stream)); g_free (path); return stream; } stream = camel_stream_fs_new_with_name (path, O_RDONLY, 0); if (stream) { cache_put (cache, uid, key, stream); } else { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to cache %s: %s"), part_spec, g_strerror (errno)); } g_free (path); return stream; }
static gssize data_wrapper_write_to_stream_sync (CamelDataWrapper *data_wrapper, CamelStream *stream, GCancellable *cancellable, GError **error) { gssize ret; if (data_wrapper->stream == NULL) { g_set_error ( error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("No stream available")); return -1; } camel_data_wrapper_lock (data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK); /* Check for cancellation after locking. */ if (g_cancellable_set_error_if_cancelled (cancellable, error)) { camel_data_wrapper_unlock ( data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK); return -1; } if (camel_stream_reset (data_wrapper->stream, error) == -1) { camel_data_wrapper_unlock ( data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK); return -1; } ret = camel_stream_write_to_stream ( data_wrapper->stream, stream, cancellable, error); camel_data_wrapper_unlock (data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK); return ret; }
static CamelStream * nntp_folder_download_message (CamelNNTPFolder *nntp_folder, const char *id, const char *msgid, CamelException *ex) { CamelNNTPStore *nntp_store = (CamelNNTPStore *) ((CamelFolder *) nntp_folder)->parent_store; CamelStream *stream = NULL; int ret; char *line; ret = camel_nntp_command (nntp_store, ex, nntp_folder, &line, "article %s", id); if (ret == 220) { stream = camel_data_cache_add (nntp_store->cache, "cache", msgid, NULL); if (stream) { if (camel_stream_write_to_stream ((CamelStream *) nntp_store->stream, stream) == -1) goto fail; if (camel_stream_reset (stream) == -1) goto fail; } else { stream = (CamelStream *) nntp_store->stream; camel_object_ref (stream); } } else if (ret == 423 || ret == 430) { camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID, _("Cannot get message %s: %s"), msgid, line); } else if (ret != -1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), msgid, line); } return stream; fail: if (errno == EINTR) camel_exception_setv (ex, CAMEL_EXCEPTION_USER_CANCEL, _("User canceled")); else camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot get message %s: %s"), msgid, g_strerror (errno)); return NULL; }
static CamelCipherValidity * sm_decrypt(CamelCipherContext *context, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex) { NSSCMSDecoderContext *dec; NSSCMSMessage *cmsg; CamelStreamMem *istream; CamelStream *ostream; CamelCipherValidity *valid = NULL; /* FIXME: This assumes the content is only encrypted. Perhaps its ok for this api to do this ... */ ostream = camel_stream_mem_new(); camel_stream_mem_set_secure((CamelStreamMem *)ostream); /* FIXME: stream this to the decoder incrementally */ istream = (CamelStreamMem *)camel_stream_mem_new(); camel_data_wrapper_decode_to_stream(camel_medium_get_content_object((CamelMedium *)ipart), (CamelStream *)istream); camel_stream_reset((CamelStream *)istream); dec = NSS_CMSDecoder_Start(NULL, sm_write_stream, ostream, /* content callback */ NULL, NULL, NULL, NULL); /* decrypt key callback */ if (NSS_CMSDecoder_Update(dec, (char *) istream->buffer->data, istream->buffer->len) != SECSuccess) { printf("decoder update failed\n"); } camel_object_unref(istream); cmsg = NSS_CMSDecoder_Finish(dec); if (cmsg == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Decoder failed, error %d"), PORT_GetError()); goto fail; } #if 0 /* not sure if we really care about this? */ if (!NSS_CMSMessage_IsEncrypted(cmsg)) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("S/MIME Decrypt: No encrypted content found")); NSS_CMSMessage_Destroy(cmsg); goto fail; } #endif camel_stream_reset(ostream); camel_data_wrapper_construct_from_stream((CamelDataWrapper *)opart, ostream); if (NSS_CMSMessage_IsSigned(cmsg)) { valid = sm_verify_cmsg(context, cmsg, NULL, ex); } else { valid = camel_cipher_validity_new(); valid->encrypt.description = g_strdup(_("Encrypted content")); valid->encrypt.status = CAMEL_CIPHER_VALIDITY_ENCRYPT_ENCRYPTED; } NSS_CMSMessage_Destroy(cmsg); fail: camel_object_unref(ostream); return valid; }
static int sm_sign(CamelCipherContext *context, const char *userid, CamelCipherHash hash, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex) { int res = -1; NSSCMSMessage *cmsg; CamelStream *ostream, *istream; SECOidTag sechash; NSSCMSEncoderContext *enc; CamelDataWrapper *dw; CamelContentType *ct; switch (hash) { case CAMEL_CIPHER_HASH_SHA1: case CAMEL_CIPHER_HASH_DEFAULT: default: sechash = SEC_OID_SHA1; break; case CAMEL_CIPHER_HASH_MD5: sechash = SEC_OID_MD5; break; } cmsg = sm_signing_cmsmessage((CamelSMIMEContext *)context, userid, sechash, ((CamelSMIMEContext *)context)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN, ex); if (cmsg == NULL) return -1; ostream = camel_stream_mem_new(); /* FIXME: stream this, we stream output at least */ istream = camel_stream_mem_new(); if (camel_cipher_canonical_to_stream(ipart, CAMEL_MIME_FILTER_CANON_STRIP |CAMEL_MIME_FILTER_CANON_CRLF |CAMEL_MIME_FILTER_CANON_FROM, istream) == -1) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Could not generate signing data: %s"), g_strerror(errno)); goto fail; } enc = NSS_CMSEncoder_Start(cmsg, sm_write_stream, ostream, /* DER output callback */ NULL, NULL, /* destination storage */ NULL, NULL, /* password callback */ NULL, NULL, /* decrypt key callback */ NULL, NULL ); /* detached digests */ if (!enc) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create encoder context")); goto fail; } if (NSS_CMSEncoder_Update(enc, (char *) ((CamelStreamMem *)istream)->buffer->data, ((CamelStreamMem *)istream)->buffer->len) != SECSuccess) { NSS_CMSEncoder_Cancel(enc); camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to add data to CMS encoder")); goto fail; } if (NSS_CMSEncoder_Finish(enc) != SECSuccess) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to encode data")); goto fail; } res = 0; dw = camel_data_wrapper_new(); camel_stream_reset(ostream); camel_data_wrapper_construct_from_stream(dw, ostream); dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY; if (((CamelSMIMEContext *)context)->priv->sign_mode == CAMEL_SMIME_SIGN_CLEARSIGN) { CamelMultipartSigned *mps; CamelMimePart *sigpart; sigpart = camel_mime_part_new(); ct = camel_content_type_new("application", "x-pkcs7-signature"); camel_content_type_set_param(ct, "name", "smime.p7s"); camel_data_wrapper_set_mime_type_field(dw, ct); camel_content_type_unref(ct); camel_medium_set_content_object((CamelMedium *)sigpart, dw); camel_mime_part_set_filename(sigpart, "smime.p7s"); camel_mime_part_set_disposition(sigpart, "attachment"); camel_mime_part_set_encoding(sigpart, CAMEL_TRANSFER_ENCODING_BASE64); mps = camel_multipart_signed_new(); ct = camel_content_type_new("multipart", "signed"); camel_content_type_set_param(ct, "micalg", camel_cipher_hash_to_id(context, hash)); camel_content_type_set_param(ct, "protocol", context->sign_protocol); camel_data_wrapper_set_mime_type_field((CamelDataWrapper *)mps, ct); camel_content_type_unref(ct); camel_multipart_set_boundary((CamelMultipart *)mps, NULL); mps->signature = sigpart; mps->contentraw = istream; camel_stream_reset(istream); camel_object_ref(istream); camel_medium_set_content_object((CamelMedium *)opart, (CamelDataWrapper *)mps); } else { ct = camel_content_type_new("application", "x-pkcs7-mime"); camel_content_type_set_param(ct, "name", "smime.p7m"); camel_content_type_set_param(ct, "smime-type", "signed-data"); camel_data_wrapper_set_mime_type_field(dw, ct); camel_content_type_unref(ct); camel_medium_set_content_object((CamelMedium *)opart, dw); camel_mime_part_set_filename(opart, "smime.p7m"); camel_mime_part_set_description(opart, "S/MIME Signed Message"); camel_mime_part_set_disposition(opart, "attachment"); camel_mime_part_set_encoding(opart, CAMEL_TRANSFER_ENCODING_BASE64); } camel_object_unref(dw); fail: camel_object_unref(ostream); camel_object_unref(istream); return res; }
/* TODO: This is suboptimal, but the only other solution is to pass around NSSCMSMessages */ guint32 camel_smime_context_describe_part(CamelSMIMEContext *context, CamelMimePart *part) { guint32 flags = 0; CamelContentType *ct; const char *tmp; if (!part) return flags; ct = camel_mime_part_get_content_type(part); if (camel_content_type_is(ct, "multipart", "signed")) { tmp = camel_content_type_param(ct, "protocol"); if (tmp && (g_ascii_strcasecmp(tmp, ((CamelCipherContext *)context)->sign_protocol) == 0 || g_ascii_strcasecmp(tmp, "application/pkcs7-signature") == 0)) flags = CAMEL_SMIME_SIGNED; } else if (camel_content_type_is(ct, "application", "x-pkcs7-mime")) { CamelStreamMem *istream; NSSCMSMessage *cmsg; NSSCMSDecoderContext *dec; /* FIXME: stream this to the decoder incrementally */ istream = (CamelStreamMem *)camel_stream_mem_new(); camel_data_wrapper_decode_to_stream(camel_medium_get_content_object((CamelMedium *)part), (CamelStream *)istream); camel_stream_reset((CamelStream *)istream); dec = NSS_CMSDecoder_Start(NULL, NULL, NULL, NULL, NULL, /* password callback */ NULL, NULL); /* decrypt key callback */ NSS_CMSDecoder_Update(dec, (char *) istream->buffer->data, istream->buffer->len); camel_object_unref(istream); cmsg = NSS_CMSDecoder_Finish(dec); if (cmsg) { if (NSS_CMSMessage_IsSigned(cmsg)) { printf("message is signed\n"); flags |= CAMEL_SMIME_SIGNED; } if (NSS_CMSMessage_IsEncrypted(cmsg)) { printf("message is encrypted\n"); flags |= CAMEL_SMIME_ENCRYPTED; } #if 0 if (NSS_CMSMessage_ContainsCertsOrCrls(cmsg)) { printf("message contains certs or crls\n"); flags |= CAMEL_SMIME_CERTS; } #endif NSS_CMSMessage_Destroy(cmsg); } else { printf("Message could not be parsed\n"); } } return flags; }
static void test_filter(CamelMimeFilter *f, const char *inname, const char *outname) { CamelStreamMem *in, *out; CamelStream *indisk, *outdisk, *filter; int id; camel_test_push("Data file `%s'", inname); camel_test_push("setup"); indisk = camel_stream_fs_new_with_name(inname, O_RDONLY, 0); check(indisk); outdisk = camel_stream_fs_new_with_name(outname, O_RDONLY, 0); check(outdisk); out = (CamelStreamMem *)camel_stream_mem_new(); check(camel_stream_write_to_stream(outdisk, (CamelStream *)out) > 0); camel_test_pull(); camel_test_push("reading through filter stream"); in = (CamelStreamMem *)camel_stream_mem_new(); filter = (CamelStream *)camel_stream_filter_new_with_stream(indisk); check_count(indisk, 2); id = camel_stream_filter_add((CamelStreamFilter *)filter, f); check_count(f, 2); check(camel_stream_write_to_stream(filter, (CamelStream *)in) > 0); check_msg(in->buffer->len == out->buffer->len && memcmp(in->buffer->data, out->buffer->data, in->buffer->len) == 0, "Buffer content mismatch, %d != %d, in = '%.*s' != out = '%.*s'", in->buffer->len, out->buffer->len, in->buffer->len, in->buffer->data, out->buffer->len, out->buffer->data); camel_test_pull(); camel_stream_filter_remove((CamelStreamFilter *)filter, id); check_count(f, 1); camel_mime_filter_reset(f); check_unref(filter, 1); check_count(indisk, 1); check_count(f, 1); check_unref(in, 1); check(camel_stream_reset(indisk) == 0); camel_test_push("writing through filter stream"); in = (CamelStreamMem *)camel_stream_mem_new(); filter = (CamelStream *)camel_stream_filter_new_with_stream((CamelStream *)in); check_count(in, 2); id = camel_stream_filter_add((CamelStreamFilter *)filter, f); check_count(f, 2); check(camel_stream_write_to_stream(indisk, filter) > 0); check(camel_stream_flush(filter) == 0); check_msg(in->buffer->len == out->buffer->len && memcmp(in->buffer->data, out->buffer->data, in->buffer->len) == 0, "Buffer content mismatch, %d != %d, in = '%.*s' != out = '%.*s'", in->buffer->len, out->buffer->len, in->buffer->len, in->buffer->data, out->buffer->len, out->buffer->data); camel_stream_filter_remove((CamelStreamFilter *)filter, id); check_unref(filter, 1); check_unref(in, 1); check_unref(indisk, 1); check_unref(outdisk, 1); check_unref(out, 1); camel_test_pull(); camel_test_pull(); }
int main (int argc, char **argv) { CamelSession *session; CamelCipherContext *ctx; CamelException *ex; CamelCipherValidity *valid; CamelStream *stream1, *stream2; struct _CamelMimePart *sigpart, *conpart, *encpart, *outpart; CamelDataWrapper *dw; GPtrArray *recipients; GByteArray *buf; char *before, *after; int ret; if (getenv("CAMEL_TEST_GPG") == NULL) return 77; camel_test_init (argc, argv); /* clear out any camel-test data */ system ("/bin/rm -rf /tmp/camel-test"); system ("/bin/mkdir /tmp/camel-test"); setenv ("GNUPGHOME", "/tmp/camel-test/.gnupg", 1); /* import the gpg keys */ if ((ret = system ("gpg < /dev/null > /dev/null 2>&1")) == -1) return 77; else if (WEXITSTATUS (ret) == 127) return 77; g_message ("gpg --import " TEST_DATA_DIR "/camel-test.gpg.pub > /dev/null 2>&1"); system ("gpg --import " TEST_DATA_DIR "/camel-test.gpg.pub > /dev/null 2>&1"); g_message ("gpg --import " TEST_DATA_DIR "/camel-test.gpg.sec > /dev/null 2>&1"); system ("gpg --import " TEST_DATA_DIR "/camel-test.gpg.sec > /dev/null 2>&1"); session = camel_pgp_session_new ("/tmp/camel-test"); ex = camel_exception_new (); ctx = camel_gpg_context_new (session); camel_gpg_context_set_always_trust (CAMEL_GPG_CONTEXT (ctx), TRUE); camel_test_start ("Test of PGP functions"); stream1 = camel_stream_mem_new (); camel_stream_write (stream1, "Hello, I am a test stream.\n", 27); camel_stream_reset (stream1); conpart = camel_mime_part_new(); dw = camel_data_wrapper_new(); camel_data_wrapper_construct_from_stream(dw, stream1); camel_medium_set_content_object((CamelMedium *)conpart, dw); camel_object_unref(stream1); camel_object_unref(dw); sigpart = camel_mime_part_new(); camel_test_push ("PGP signing"); camel_cipher_sign (ctx, "*****@*****.**", CAMEL_CIPHER_HASH_SHA1, conpart, sigpart, ex); if (camel_exception_is_set(ex)) { printf("PGP signing failed assuming non-functional environment\n%s", camel_exception_get_description (ex)); camel_test_pull(); return 77; } camel_test_pull (); camel_exception_clear (ex); camel_test_push ("PGP verify"); valid = camel_cipher_verify (ctx, sigpart, ex); check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); check_msg (camel_cipher_validity_get_valid (valid), "%s", camel_cipher_validity_get_description (valid)); camel_cipher_validity_free (valid); camel_test_pull (); camel_object_unref(conpart); camel_object_unref(sigpart); stream1 = camel_stream_mem_new (); camel_stream_write (stream1, "Hello, I am a test of encryption/decryption.", 44); camel_stream_reset (stream1); conpart = camel_mime_part_new(); dw = camel_data_wrapper_new(); camel_stream_reset(stream1); camel_data_wrapper_construct_from_stream(dw, stream1); camel_medium_set_content_object((CamelMedium *)conpart, dw); camel_object_unref(stream1); camel_object_unref(dw); encpart = camel_mime_part_new(); camel_exception_clear (ex); camel_test_push ("PGP encrypt"); recipients = g_ptr_array_new (); g_ptr_array_add (recipients, "*****@*****.**"); camel_cipher_encrypt (ctx, "*****@*****.**", recipients, conpart, encpart, ex); check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); g_ptr_array_free (recipients, TRUE); camel_test_pull (); camel_exception_clear (ex); camel_test_push ("PGP decrypt"); outpart = camel_mime_part_new(); valid = camel_cipher_decrypt (ctx, encpart, outpart, ex); check_msg (!camel_exception_is_set (ex), "%s", camel_exception_get_description (ex)); check_msg (valid->encrypt.status == CAMEL_CIPHER_VALIDITY_ENCRYPT_ENCRYPTED, "%s", valid->encrypt.description); stream1 = camel_stream_mem_new(); stream2 = camel_stream_mem_new(); camel_data_wrapper_write_to_stream((CamelDataWrapper *)conpart, stream1); camel_data_wrapper_write_to_stream((CamelDataWrapper *)outpart, stream2); buf = CAMEL_STREAM_MEM (stream1)->buffer; before = g_strndup (buf->data, buf->len); buf = CAMEL_STREAM_MEM (stream2)->buffer; after = g_strndup (buf->data, buf->len); check_msg (string_equal (before, after), "before = '%s', after = '%s'", before, after); g_free (before); g_free (after); camel_object_unref(stream1); camel_object_unref(stream2); camel_object_unref(conpart); camel_object_unref(encpart); camel_object_unref(outpart); camel_test_pull (); camel_object_unref (CAMEL_OBJECT (ctx)); camel_object_unref (CAMEL_OBJECT (session)); camel_test_end (); return 0; }