summaryrefslogtreecommitdiffstats
path: root/framework/src/domain/mimetreeparser/otp/applicationpkcs7mime.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/domain/mimetreeparser/otp/applicationpkcs7mime.cpp')
-rw-r--r--framework/src/domain/mimetreeparser/otp/applicationpkcs7mime.cpp178
1 files changed, 178 insertions, 0 deletions
diff --git a/framework/src/domain/mimetreeparser/otp/applicationpkcs7mime.cpp b/framework/src/domain/mimetreeparser/otp/applicationpkcs7mime.cpp
new file mode 100644
index 00000000..bcfc0616
--- /dev/null
+++ b/framework/src/domain/mimetreeparser/otp/applicationpkcs7mime.cpp
@@ -0,0 +1,178 @@
1/*
2 Copyright (c) 2016 Sandro Knauß <sknauss@kde.org>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#include "applicationpkcs7mime.h"
21
22#include "utils.h"
23
24#include "attachmentstrategy.h"
25#include "objecttreeparser.h"
26#include "messagepart.h"
27
28#include <QGpgME/Protocol>
29
30#include <KMime/Content>
31
32#include <QTextCodec>
33
34#include "mimetreeparser_debug.h"
35
36using namespace MimeTreeParser;
37
38const ApplicationPkcs7MimeBodyPartFormatter *ApplicationPkcs7MimeBodyPartFormatter::self;
39
40const Interface::BodyPartFormatter *ApplicationPkcs7MimeBodyPartFormatter::create()
41{
42 if (!self) {
43 self = new ApplicationPkcs7MimeBodyPartFormatter();
44 }
45 return self;
46}
47Interface::BodyPartFormatter::Result ApplicationPkcs7MimeBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const
48{
49 Q_UNUSED(writer)
50 const auto p = process(*part);
51 const auto mp = static_cast<MessagePart *>(p.data());
52 if (mp) {
53 mp->html(false);
54 return Ok;
55 }
56 return Failed;
57}
58
59Interface::MessagePart::Ptr ApplicationPkcs7MimeBodyPartFormatter::process(Interface::BodyPart &part) const
60{
61 KMime::Content *node = part.content();
62
63 if (node->head().isEmpty()) {
64 return MessagePart::Ptr();
65 }
66
67 const auto smimeCrypto = QGpgME::smime();
68 if (!smimeCrypto) {
69 return MessagePart::Ptr();
70 }
71
72 const QString smimeType = node->contentType()->parameter(QStringLiteral("smime-type")).toLower();
73
74 if (smimeType == QLatin1String("certs-only")) {
75 part.processResult()->setNeverDisplayInline(true);
76
77 CertMessagePart::Ptr mp(new CertMessagePart(part.objectTreeParser(), node, smimeCrypto, part.source()->autoImportKeys()));
78 return mp;
79 }
80
81 bool isSigned = (smimeType == QLatin1String("signed-data"));
82 bool isEncrypted = (smimeType == QLatin1String("enveloped-data"));
83
84 // Analyze "signTestNode" node to find/verify a signature.
85 // If zero part.objectTreeParser() verification was successfully done after
86 // decrypting via recursion by insertAndParseNewChildNode().
87 KMime::Content *signTestNode = isEncrypted ? nullptr : node;
88
89 // We try decrypting the content
90 // if we either *know* that it is an encrypted message part
91 // or there is neither signed nor encrypted parameter.
92 MessagePart::Ptr mp;
93 if (!isSigned) {
94 if (isEncrypted) {
95 qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime == S/MIME TYPE: enveloped (encrypted) data";
96 } else {
97 qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - type unknown - enveloped (encrypted) data ?";
98 }
99
100 auto _mp = EncryptedMessagePart::Ptr(new EncryptedMessagePart(part.objectTreeParser(),
101 node->decodedText(), smimeCrypto,
102 part.nodeHelper()->fromAsString(node), node));
103 mp = _mp;
104 _mp->setIsEncrypted(true);
105 _mp->setDecryptMessage(part.source()->decryptMessage());
106 PartMetaData *messagePart(_mp->partMetaData());
107 if (!part.source()->decryptMessage()) {
108 isEncrypted = true;
109 signTestNode = nullptr; // PENDING(marc) to be abs. sure, we'd need to have to look at the content
110 } else {
111 _mp->startDecryption();
112 if (messagePart->isDecryptable) {
113 qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - encryption found - enveloped (encrypted) data !";
114 isEncrypted = true;
115 part.nodeHelper()->setEncryptionState(node, KMMsgFullyEncrypted);
116 signTestNode = nullptr;
117
118 } else {
119 // decryption failed, which could be because the part was encrypted but
120 // decryption failed, or because we didn't know if it was encrypted, tried,
121 // and failed. If the message was not actually encrypted, we continue
122 // assuming it's signed
123 if (_mp->passphraseError() || (smimeType.isEmpty() && messagePart->isEncrypted)) {
124 isEncrypted = true;
125 signTestNode = nullptr;
126 }
127
128 if (isEncrypted) {
129 qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - ERROR: COULD NOT DECRYPT enveloped data !";
130 } else {
131 qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - NO encryption found";
132 }
133 }
134 }
135
136 if (isEncrypted) {
137 part.nodeHelper()->setEncryptionState(node, KMMsgFullyEncrypted);
138 }
139 }
140
141 // We now try signature verification if necessarry.
142 if (signTestNode) {
143 if (isSigned) {
144 qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime == S/MIME TYPE: opaque signed data";
145 } else {
146 qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - type unknown - opaque signed data ?";
147 }
148
149 const QTextCodec *aCodec(part.objectTreeParser()->codecFor(signTestNode));
150 const QByteArray signaturetext = signTestNode->decodedContent();
151 auto _mp = SignedMessagePart::Ptr(new SignedMessagePart(part.objectTreeParser(),
152 aCodec->toUnicode(signaturetext), smimeCrypto,
153 part.nodeHelper()->fromAsString(node), signTestNode));
154 mp = _mp;
155 //mp->setDecryptMessage(part.source()->decryptMessage());
156 PartMetaData *messagePart(mp->partMetaData());
157 if (smimeCrypto) {
158 _mp->startVerificationDetached(signaturetext, nullptr, QByteArray());
159 } else {
160 messagePart->auditLogError = GpgME::Error(GPG_ERR_NOT_IMPLEMENTED);
161 }
162
163 if (_mp->isSigned()) {
164 if (!isSigned) {
165 qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - signature found - opaque signed data !";
166 isSigned = true;
167 }
168
169 if (signTestNode != node) {
170 part.nodeHelper()->setSignatureState(node, KMMsgFullySigned);
171 }
172 } else {
173 qCDebug(MIMETREEPARSER_LOG) << "pkcs7 mime - NO signature found :-(";
174 }
175 }
176
177 return mp;
178}