pgp_spec.rb 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe SecureMailing::PGP, :aggregate_failures do
  4. before do
  5. Setting.set('pgp_integration', true)
  6. end
  7. let(:raw_body) { 'Testing some Content' }
  8. let(:attachments) { [] }
  9. let(:system_email_address) { 'pgp1@example.com' }
  10. let(:customer_email_address) { 'pgp2@example.com' }
  11. let(:cc_customer_email_address) { 'pgp3@example.com' }
  12. let(:expired_email_address) { 'expiredpgp1@example.com' }
  13. let(:content_type) { 'text/plain' }
  14. def build_mail
  15. Channel::EmailBuild.build(
  16. from: sender_email_address,
  17. to: recipient_email_address,
  18. cc: cc_recipient_email_address,
  19. body: raw_body,
  20. content_type: content_type,
  21. security: security_preferences,
  22. attachments: attachments
  23. )
  24. end
  25. describe 'outgoing' do
  26. shared_examples 'HttpLog writer' do |status|
  27. it "logs #{status}" do
  28. expect do
  29. build_mail
  30. rescue
  31. # allow failures
  32. end.to change(HttpLog, :count).by(1)
  33. expect(HttpLog.last.attributes).to include('direction' => 'out', 'status' => status)
  34. end
  35. end
  36. let(:sender_email_address) { system_email_address }
  37. let(:recipient_email_address) { customer_email_address }
  38. let(:cc_recipient_email_address) { cc_customer_email_address }
  39. context 'without security' do
  40. let(:security_preferences) do
  41. nil
  42. end
  43. it 'builds mail' do
  44. expect(build_mail.body).not_to match(SecureMailing::PGP::Incoming::SIGNATURE_CONTENT_TYPE)
  45. expect(build_mail.body).to eq(raw_body)
  46. end
  47. end
  48. context 'with signing' do
  49. let(:security_preferences) do
  50. {
  51. type: 'PGP',
  52. sign: {
  53. success: true,
  54. },
  55. encryption: {
  56. success: false,
  57. },
  58. }
  59. end
  60. context 'when private key present' do
  61. before do
  62. create(:pgp_key, :with_private, fixture: system_email_address)
  63. end
  64. it 'builds mail' do
  65. expect(build_mail.body).to match(SecureMailing::PGP::Incoming::SIGNATURE_CONTENT_TYPE)
  66. end
  67. it_behaves_like 'HttpLog writer', 'success'
  68. context 'with expired key' do
  69. let(:system_email_address) { expired_email_address }
  70. it 'raises exception' do
  71. expect { build_mail }.to raise_error ActiveRecord::RecordNotFound
  72. end
  73. it_behaves_like 'HttpLog writer', 'failed'
  74. end
  75. end
  76. context 'when no private key is present' do
  77. it 'raises exception' do
  78. expect { build_mail }.to raise_error ActiveRecord::RecordNotFound
  79. end
  80. it_behaves_like 'HttpLog writer', 'failed'
  81. end
  82. end
  83. context 'with encryption' do
  84. let(:security_preferences) do
  85. {
  86. type: 'PGP',
  87. sign: {
  88. success: false,
  89. },
  90. encryption: {
  91. success: true,
  92. },
  93. }
  94. end
  95. context 'when all needed keys are present' do
  96. before do
  97. create(:pgp_key, :with_private, fixture: system_email_address)
  98. create(:pgp_key, fixture: recipient_email_address)
  99. create(:pgp_key, fixture: cc_recipient_email_address)
  100. end
  101. it 'builds mail' do
  102. mail = build_mail
  103. expect(mail['Content-Type'].value).to include('multipart/encrypted')
  104. expect(mail.body).not_to include(raw_body)
  105. end
  106. it_behaves_like 'HttpLog writer', 'success'
  107. end
  108. context 'when needed keys are not present' do
  109. it 'raises exception' do
  110. expect { build_mail }.to raise_error ActiveRecord::RecordNotFound
  111. end
  112. end
  113. context 'when one key is expired' do
  114. before do
  115. create(:pgp_key, :with_private, fixture: system_email_address)
  116. create(:pgp_key, fixture: recipient_email_address)
  117. create(:pgp_key, fixture: cc_recipient_email_address)
  118. end
  119. let(:customer_email_address) { expired_email_address }
  120. it 'raises exception' do
  121. expect { build_mail }.to raise_error ActiveRecord::RecordNotFound
  122. end
  123. end
  124. context 'when a key with multiple UIDs is present' do
  125. let(:customer_email_address) { 'multipgp2@example.com' }
  126. before do
  127. create(:pgp_key, :with_private, fixture: system_email_address)
  128. create(:pgp_key, fixture: recipient_email_address)
  129. create(:pgp_key, fixture: cc_customer_email_address)
  130. end
  131. it 'builds mail' do
  132. mail = build_mail
  133. expect(mail['Content-Type'].value).to include('multipart/encrypted')
  134. expect(mail.body).not_to include(raw_body)
  135. end
  136. it_behaves_like 'HttpLog writer', 'success'
  137. end
  138. end
  139. context 'with encryption and signing' do
  140. let(:security_preferences) do
  141. {
  142. type: 'PGP',
  143. sign: {
  144. success: true,
  145. },
  146. encryption: {
  147. success: true,
  148. },
  149. }
  150. end
  151. before do
  152. create(:pgp_key, :with_private, fixture: system_email_address)
  153. create(:pgp_key, :with_private, fixture: recipient_email_address)
  154. create(:pgp_key, fixture: cc_customer_email_address)
  155. end
  156. it 'builds mail' do
  157. mail = build_mail
  158. expect(mail['Content-Type'].value).to include('multipart/encrypted')
  159. expect(mail.body).not_to include(raw_body)
  160. end
  161. context 'with inline image' do
  162. let(:article) do
  163. create(:ticket_article,
  164. ticket: create(:ticket),
  165. body: '<div>some message article helper test1</div><div><img src="cid:15.274327094.140939@zammad.example.com"><br></div>')
  166. end
  167. let(:attachments) do
  168. create_list(
  169. :store,
  170. 1,
  171. object: 'Ticket::Article',
  172. o_id: article.id,
  173. data: 'fake',
  174. filename: 'inline_image.jpg',
  175. preferences: {
  176. 'Content-Type' => 'image/jpeg',
  177. 'Mime-Type' => 'image/jpeg',
  178. 'Content-ID' => '<15.274327094.140939>',
  179. 'Content-Disposition' => 'inline',
  180. }
  181. )
  182. end
  183. let(:raw_body) do
  184. <<~MSG_HTML.chomp
  185. <!DOCTYPE html>
  186. <html>
  187. <head>
  188. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  189. </head>
  190. <body style="font-family:Geneva,Helvetica,Arial,sans-serif; font-size: 12px;">
  191. <div>some message article helper test1</div>
  192. <div><img src="cid:15.274327094.140939@zammad.example.com"><br></div>
  193. </body>
  194. </html>
  195. MSG_HTML
  196. end
  197. let(:content_type) { 'text/html' }
  198. it 'builds mail' do
  199. mail = build_mail
  200. expect(mail['Content-Type'].value).to include('multipart/encrypted')
  201. end
  202. end
  203. end
  204. end
  205. describe '.incoming' do
  206. shared_examples 'HttpLog writer' do |status|
  207. it "logs #{status}" do
  208. expect do
  209. mail
  210. rescue
  211. # allow failures
  212. end.to change(HttpLog, :count).by(2)
  213. expect(HttpLog.last.attributes).to include('direction' => 'in', 'status' => status)
  214. end
  215. end
  216. shared_examples 'decrypting message content' do
  217. it 'decrypts message content' do
  218. expect(mail[:body]).to include(raw_body)
  219. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be false
  220. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to be_nil
  221. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be true
  222. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to eq ''
  223. end
  224. end
  225. shared_examples 'decrypting and verifying signature' do
  226. it 'decrypts and verifies signature' do
  227. expect(mail[:body]).to include(raw_body)
  228. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be true
  229. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to eq('Good signature')
  230. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be true
  231. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to eq ''
  232. end
  233. end
  234. let(:sender_email_address) { system_email_address }
  235. let(:recipient_email_address) { customer_email_address }
  236. let(:cc_recipient_email_address) { cc_customer_email_address }
  237. context 'when signature verification' do
  238. context 'when sender public key present' do
  239. before do
  240. create(:pgp_key, :with_private, fixture: sender_email_address)
  241. end
  242. let(:security_preferences) do
  243. {
  244. type: 'PGP',
  245. sign: {
  246. success: true,
  247. },
  248. encryption: {
  249. success: false,
  250. },
  251. }
  252. end
  253. let(:mail) do
  254. pgp_mail = build_mail
  255. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  256. SecureMailing.incoming(mail)
  257. mail
  258. end
  259. it 'verifies' do
  260. expect(mail[:body]).to include(raw_body)
  261. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be true
  262. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to eq 'Good signature'
  263. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be false
  264. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to be_nil
  265. end
  266. it_behaves_like 'HttpLog writer', 'success'
  267. context 'with html mail' do
  268. let(:raw_content) { '<div>&gt; Welcome!</div><div>&gt;</div><div>&gt; Thank you for installing Zammad. äöüß</div><div>&gt;</div>' }
  269. let(:raw_body) do
  270. <<~MSG_HTML.chomp
  271. <!DOCTYPE html>
  272. <html>
  273. <head>
  274. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  275. </head>
  276. <body style="font-family:Geneva,Helvetica,Arial,sans-serif; font-size: 12px;">
  277. #{raw_content}
  278. </body>
  279. </html>
  280. MSG_HTML
  281. end
  282. let(:content_type) { 'text/html' }
  283. it 'verifies' do
  284. expect(mail[:body]).to eq(raw_content)
  285. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be true
  286. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to eq 'Good signature'
  287. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be false
  288. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to be_nil
  289. end
  290. end
  291. context 'when key is expired' do
  292. let(:mail) do
  293. # Import a mail which was created with a now expired key.
  294. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-expired.box').read
  295. mail = Channel::EmailParser.new.parse(pgp_mail)
  296. SecureMailing.incoming(mail)
  297. mail
  298. end
  299. let(:sender_email_address) { expired_email_address }
  300. it 'not verified' do
  301. expect(mail[:body]).to include(raw_body)
  302. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be true
  303. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to eq 'Good signature'
  304. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be false
  305. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to be_nil
  306. end
  307. end
  308. end
  309. end
  310. context 'with decryption' do
  311. let(:security_preferences) do
  312. {
  313. type: 'PGP',
  314. sign: {
  315. success: false,
  316. },
  317. encryption: {
  318. success: true,
  319. },
  320. }
  321. end
  322. let!(:sender_key) { create(:pgp_key, :with_private, fixture: sender_email_address) }
  323. let!(:recipient_key) { create(:pgp_key, :with_private, fixture: recipient_email_address) }
  324. let!(:cc_recipient_key) { create(:pgp_key, :with_private, fixture: cc_recipient_email_address) }
  325. context 'when private key present' do
  326. let(:mail) do
  327. pgp_mail = build_mail
  328. parsed_mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  329. SecureMailing.incoming(parsed_mail)
  330. parsed_mail
  331. end
  332. it_behaves_like 'decrypting message content'
  333. it_behaves_like 'HttpLog writer', 'success'
  334. context 'with existing second key for same uid' do
  335. let(:mail) do
  336. # Import a mail which was created with a now expired key.
  337. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-other-key.box').read
  338. mail = Channel::EmailParser.new.parse(pgp_mail)
  339. SecureMailing.incoming(mail)
  340. mail
  341. end
  342. before do
  343. create(:pgp_key, :with_private, fixture: "#{recipient_email_address}-other")
  344. end
  345. it_behaves_like 'decrypting message content'
  346. end
  347. context 'with OCB key' do
  348. let(:recipient_email_address) { 'ocbpgp1@example.com' }
  349. let(:mail) do
  350. # Import a mail which was created with an OCB key.
  351. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-ocb.box').read
  352. mail = Channel::EmailParser.new.parse(pgp_mail)
  353. SecureMailing.incoming(mail)
  354. mail
  355. end
  356. context 'with GPG version >= 2.2.27', if: SecureMailing::PGP::Tool.version >= '2.2.27' do
  357. it_behaves_like 'decrypting message content'
  358. end
  359. context 'with GPG version < 2.2.27', if: ENV['CI'] && SecureMailing::PGP::Tool.version < '2.2.27' do
  360. it 'provides an error message as an article comment' do
  361. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be false
  362. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to be_nil
  363. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be false
  364. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to eq 'There was an unknown PGP error. This PGP email was encrypted with a potentially unknown encryption algorithm.'
  365. end
  366. end
  367. end
  368. context 'when recipient is bcc only' do
  369. let(:mail) do
  370. create(:pgp_key, :with_private, fixture: 'zammad@localhost')
  371. # Import a mail which was created with bcc recipient only.
  372. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-decrypt-bcc.box').read
  373. mail = Channel::EmailParser.new.parse(pgp_mail)
  374. SecureMailing.incoming(mail)
  375. mail
  376. end
  377. it_behaves_like 'decrypting message content'
  378. end
  379. end
  380. context 'with no private key present' do
  381. let(:mail) do
  382. pgp_mail = build_mail
  383. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  384. sender_key.destroy!
  385. recipient_key.destroy!
  386. cc_recipient_key.destroy!
  387. SecureMailing.incoming(mail)
  388. mail
  389. end
  390. it 'fails' do
  391. expect(mail[:body]).to include('no visible content')
  392. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be false
  393. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to be_nil
  394. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be false
  395. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to eq('The private PGP key could not be found.')
  396. end
  397. it_behaves_like 'HttpLog writer', 'failed'
  398. end
  399. end
  400. context 'with signature verification and decryption' do
  401. let(:security_preferences) do
  402. {
  403. type: 'PGP',
  404. sign: {
  405. success: true,
  406. },
  407. encryption: {
  408. success: true,
  409. },
  410. }
  411. end
  412. context 'when the mail is signed and encrypted separately' do
  413. before do
  414. create(:pgp_key, :with_private, fixture: sender_email_address)
  415. create(:pgp_key, :with_private, fixture: recipient_email_address)
  416. create(:pgp_key, fixture: cc_recipient_email_address)
  417. end
  418. let(:mail) do
  419. pgp_mail = build_mail
  420. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  421. SecureMailing.incoming(mail)
  422. mail
  423. end
  424. it_behaves_like 'decrypting and verifying signature'
  425. end
  426. context 'when the mail is signed and encrypted (detached signature)' do
  427. let(:sender_key) { create(:pgp_key, :with_private, fixture: sender_email_address) }
  428. let(:recipient_key) { create(:pgp_key, :with_private, fixture: recipient_email_address) }
  429. let(:cc_recipient_key) { create(:pgp_key, :with_private, fixture: cc_recipient_email_address) }
  430. let(:mail) do
  431. # Import a mail that was signed + encrypted with a detached signature.
  432. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-detached.box').read
  433. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  434. SecureMailing.incoming(mail)
  435. mail
  436. end
  437. context 'when all keys are present' do
  438. before do
  439. sender_key
  440. recipient_key
  441. cc_recipient_key
  442. end
  443. it_behaves_like 'decrypting and verifying signature'
  444. end
  445. context 'when only cc recipient key is present for decryption' do
  446. before do
  447. sender_key
  448. cc_recipient_key
  449. end
  450. it_behaves_like 'decrypting and verifying signature'
  451. end
  452. context 'when only decryption key is present' do
  453. before do
  454. recipient_key
  455. cc_recipient_key
  456. end
  457. it 'decrypts, but verifies signature fails' do
  458. expect(mail[:body]).to include(raw_body)
  459. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be false
  460. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to eq('The public PGP key could not be found.')
  461. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be true
  462. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to eq ''
  463. end
  464. end
  465. context 'when all keys are present, but addresses are in upcase' do
  466. let(:mail) do
  467. # Import a mail and change the case of the sender address.
  468. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-detached.box').read
  469. pgp_mail = pgp_mail.sub!('pgp1@example.com', 'PGP1@EXAMPLE.COM')
  470. pgp_mail = pgp_mail.sub!('pgp2@example.com', 'PGP2@EXAMPLE.COM')
  471. pgp_mail = pgp_mail.sub!('pgp3@example.com', 'PGP3@EXAMPLE.COM')
  472. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  473. SecureMailing.incoming(mail)
  474. mail
  475. end
  476. before do
  477. sender_key
  478. recipient_key
  479. cc_recipient_key
  480. end
  481. it_behaves_like 'decrypting and verifying signature'
  482. end
  483. end
  484. context 'when the mail is signed and encrypted (attached signature)' do
  485. let(:sender_key) { create(:pgp_key, :with_private, fixture: sender_email_address) }
  486. let(:recipient_key) { create(:pgp_key, :with_private, fixture: recipient_email_address) }
  487. let(:cc_recipient_key) { create(:pgp_key, :with_private, fixture: cc_recipient_email_address) }
  488. let(:mail) do
  489. # Import a mail that was signed + encrypted with an attached signature.
  490. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-attached.box').read
  491. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  492. SecureMailing.incoming(mail)
  493. mail
  494. end
  495. context 'when all keys are present' do
  496. before do
  497. sender_key
  498. recipient_key
  499. cc_recipient_key
  500. end
  501. it_behaves_like 'decrypting and verifying signature'
  502. end
  503. context 'when only cc recipient key is present for decryption' do
  504. before do
  505. sender_key
  506. cc_recipient_key
  507. end
  508. it_behaves_like 'decrypting and verifying signature'
  509. end
  510. context 'when only decryption key is present' do
  511. before do
  512. recipient_key
  513. cc_recipient_key
  514. end
  515. it 'decrypts, but verifies signature fails' do
  516. expect(mail[:body]).to include(raw_body)
  517. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be false
  518. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to eq('The public PGP key could not be found.')
  519. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be true
  520. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to eq ''
  521. end
  522. end
  523. end
  524. context 'when the mail is signed and encrypted in the same go (combined)' do
  525. let(:sender_key) { create(:pgp_key, :with_private, fixture: sender_email_address) }
  526. let(:recipient_key) { create(:pgp_key, :with_private, fixture: recipient_email_address) }
  527. let(:cc_recipient_key) { create(:pgp_key, :with_private, fixture: cc_recipient_email_address) }
  528. let(:mail) do
  529. # Import a mail that was signed + encrypted with the same command.
  530. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-combined.box').read
  531. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  532. SecureMailing.incoming(mail)
  533. mail
  534. end
  535. context 'when all keys are present' do
  536. before do
  537. sender_key
  538. recipient_key
  539. cc_recipient_key
  540. end
  541. it_behaves_like 'decrypting and verifying signature'
  542. end
  543. context 'when only cc recipient key is present for decryption' do
  544. before do
  545. sender_key
  546. cc_recipient_key
  547. end
  548. it_behaves_like 'decrypting and verifying signature'
  549. end
  550. context 'when only decryption key is present' do
  551. before do
  552. recipient_key
  553. cc_recipient_key
  554. end
  555. it 'decrypts, but verifies signature fails' do
  556. expect(mail[:body]).to include(raw_body)
  557. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be false
  558. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to eq('The public PGP key could not be found.')
  559. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be true
  560. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to eq ''
  561. end
  562. end
  563. end
  564. context 'when domain alias support is used' do
  565. before do
  566. Setting.set('pgp_recipient_alias_configuration', true)
  567. create(:pgp_key, :with_private, fixture: 'pgp1@example.com', domain_alias: 'domain1.com')
  568. create(:pgp_key, :with_private, fixture: 'pgp2@example.com', domain_alias: 'domain2.com')
  569. create(:pgp_key, fixture: 'pgp3@example.com', domain_alias: 'domain3.com')
  570. end
  571. let(:system_email_address) { 'pgp1@domain1.com' }
  572. let(:customer_email_address) { 'pgp2@domain2.com' }
  573. let(:cc_customer_email_address) { 'pgp3@domain3.com' }
  574. let(:mail) do
  575. pgp_mail = build_mail
  576. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  577. SecureMailing.incoming(mail)
  578. mail
  579. end
  580. it_behaves_like 'decrypting and verifying signature'
  581. end
  582. end
  583. end
  584. describe '.required_version?' do
  585. context 'with GnuPG being present on the system' do
  586. it 'succeeds' do
  587. expect(described_class.required_version?).to be true
  588. end
  589. end
  590. context 'without GnuPG being present on the system' do
  591. it 'fails' do
  592. allow(SecureMailing::PGP::Tool).to receive(:version).and_raise(Errno::ENOENT)
  593. expect(described_class.required_version?).to be false
  594. end
  595. end
  596. context 'with and outdated version of GnuPG' do
  597. it 'fails' do
  598. allow(SecureMailing::PGP::Tool).to receive(:version).and_return('1.8.0')
  599. expect(described_class.required_version?).to be false
  600. end
  601. end
  602. end
  603. describe '.retry' do
  604. let(:sender_email_address) { customer_email_address }
  605. let(:recipient_email_address) { system_email_address }
  606. let(:cc_recipient_email_address) { nil }
  607. let(:security_preferences) do
  608. {
  609. type: 'PGP',
  610. sign: {
  611. success: false,
  612. },
  613. encryption: {
  614. success: true,
  615. },
  616. }
  617. end
  618. let(:mail) do
  619. sender_pgp_key = create(:pgp_key, :with_private, fixture: sender_email_address)
  620. recipient_pgp_key = create(:pgp_key, :with_private, fixture: system_email_address)
  621. pgp_mail = Channel::EmailBuild.build(
  622. from: sender_email_address,
  623. to: recipient_email_address,
  624. body: raw_body,
  625. content_type: 'text/plain',
  626. security: security_preferences,
  627. attachments: [
  628. {
  629. content_type: 'text/plain',
  630. content: 'blub',
  631. filename: 'test-file1.txt',
  632. },
  633. ],
  634. )
  635. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  636. sender_pgp_key.destroy
  637. recipient_pgp_key.destroy
  638. mail
  639. end
  640. let!(:article) do
  641. _ticket, article, _user, _mail = Channel::EmailParser.new.process({}, mail['raw'])
  642. article
  643. end
  644. context 'when private key added' do
  645. before do
  646. create(:pgp_key, :with_private, fixture: recipient_email_address)
  647. end
  648. it 'succeeds' do
  649. SecureMailing.retry(article)
  650. expect(article.preferences[:security][:sign][:success]).to be false
  651. expect(article.preferences[:security][:sign][:comment]).to be_nil
  652. expect(article.preferences[:security][:encryption][:success]).to be true
  653. expect(article.preferences[:security][:encryption][:comment]).to eq ''
  654. expect(article.body).to include(raw_body)
  655. expect(article.attachments.count).to eq(1)
  656. expect(article.attachments.first.filename).to eq('test-file1.txt')
  657. end
  658. context 'when PGP activated' do
  659. before do
  660. Setting.set('pgp_integration', false)
  661. end
  662. it 'succeeds' do
  663. Setting.set('pgp_integration', true)
  664. SecureMailing.retry(article)
  665. expect(article.preferences[:security][:sign][:success]).to be false
  666. expect(article.preferences[:security][:sign][:comment]).to be_nil
  667. expect(article.preferences[:security][:encryption][:success]).to be true
  668. expect(article.preferences[:security][:encryption][:comment]).to eq ''
  669. expect(article.body).to include(raw_body)
  670. expect(article.attachments.count).to eq(1)
  671. expect(article.attachments.first.filename).to eq('test-file1.txt')
  672. end
  673. end
  674. end
  675. end
  676. end