pgp_spec.rb 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  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. end
  369. context 'with no private key present' do
  370. let(:mail) do
  371. pgp_mail = build_mail
  372. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  373. sender_key.destroy!
  374. recipient_key.destroy!
  375. cc_recipient_key.destroy!
  376. SecureMailing.incoming(mail)
  377. mail
  378. end
  379. it 'fails' do
  380. expect(mail[:body]).to include('no visible content')
  381. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be false
  382. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to be_nil
  383. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be false
  384. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to eq('The private PGP key could not be found.')
  385. end
  386. it_behaves_like 'HttpLog writer', 'failed'
  387. end
  388. end
  389. context 'with signature verification and decryption' do
  390. let(:security_preferences) do
  391. {
  392. type: 'PGP',
  393. sign: {
  394. success: true,
  395. },
  396. encryption: {
  397. success: true,
  398. },
  399. }
  400. end
  401. context 'when the mail is signed and encrypted separately' do
  402. before do
  403. create(:pgp_key, :with_private, fixture: sender_email_address)
  404. create(:pgp_key, :with_private, fixture: recipient_email_address)
  405. create(:pgp_key, fixture: cc_recipient_email_address)
  406. end
  407. let(:mail) do
  408. pgp_mail = build_mail
  409. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  410. SecureMailing.incoming(mail)
  411. mail
  412. end
  413. it_behaves_like 'decrypting and verifying signature'
  414. end
  415. context 'when the mail is signed and encrypted (detached signature)' do
  416. let(:sender_key) { create(:pgp_key, :with_private, fixture: sender_email_address) }
  417. let(:recipient_key) { create(:pgp_key, :with_private, fixture: recipient_email_address) }
  418. let(:cc_recipient_key) { create(:pgp_key, :with_private, fixture: cc_recipient_email_address) }
  419. let(:mail) do
  420. # Import a mail that was signed + encrypted with a detached signature.
  421. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-detached.box').read
  422. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  423. SecureMailing.incoming(mail)
  424. mail
  425. end
  426. context 'when all keys are present' do
  427. before do
  428. sender_key
  429. recipient_key
  430. cc_recipient_key
  431. end
  432. it_behaves_like 'decrypting and verifying signature'
  433. end
  434. context 'when only cc recipient key is present for decryption' do
  435. before do
  436. sender_key
  437. cc_recipient_key
  438. end
  439. it_behaves_like 'decrypting and verifying signature'
  440. end
  441. context 'when only decryption key is present' do
  442. before do
  443. recipient_key
  444. cc_recipient_key
  445. end
  446. it 'decrypts, but verifies signature fails' do
  447. expect(mail[:body]).to include(raw_body)
  448. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be false
  449. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to eq('The public PGP key could not be found.')
  450. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be true
  451. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to eq ''
  452. end
  453. end
  454. context 'when all keys are present, but addresses are in upcase' do
  455. let(:mail) do
  456. # Import a mail and change the case of the sender address.
  457. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-detached.box').read
  458. pgp_mail = pgp_mail.sub!('pgp1@example.com', 'PGP1@EXAMPLE.COM')
  459. pgp_mail = pgp_mail.sub!('pgp2@example.com', 'PGP2@EXAMPLE.COM')
  460. pgp_mail = pgp_mail.sub!('pgp3@example.com', 'PGP3@EXAMPLE.COM')
  461. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  462. SecureMailing.incoming(mail)
  463. mail
  464. end
  465. before do
  466. sender_key
  467. recipient_key
  468. cc_recipient_key
  469. end
  470. it_behaves_like 'decrypting and verifying signature'
  471. end
  472. end
  473. context 'when the mail is signed and encrypted (attached signature)' do
  474. let(:sender_key) { create(:pgp_key, :with_private, fixture: sender_email_address) }
  475. let(:recipient_key) { create(:pgp_key, :with_private, fixture: recipient_email_address) }
  476. let(:cc_recipient_key) { create(:pgp_key, :with_private, fixture: cc_recipient_email_address) }
  477. let(:mail) do
  478. # Import a mail that was signed + encrypted with an attached signature.
  479. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-attached.box').read
  480. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  481. SecureMailing.incoming(mail)
  482. mail
  483. end
  484. context 'when all keys are present' do
  485. before do
  486. sender_key
  487. recipient_key
  488. cc_recipient_key
  489. end
  490. it_behaves_like 'decrypting and verifying signature'
  491. end
  492. context 'when only cc recipient key is present for decryption' do
  493. before do
  494. sender_key
  495. cc_recipient_key
  496. end
  497. it_behaves_like 'decrypting and verifying signature'
  498. end
  499. context 'when only decryption key is present' do
  500. before do
  501. recipient_key
  502. cc_recipient_key
  503. end
  504. it 'decrypts, but verifies signature fails' do
  505. expect(mail[:body]).to include(raw_body)
  506. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be false
  507. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to eq('The public PGP key could not be found.')
  508. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be true
  509. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to eq ''
  510. end
  511. end
  512. end
  513. context 'when the mail is signed and encrypted in the same go (combined)' do
  514. let(:sender_key) { create(:pgp_key, :with_private, fixture: sender_email_address) }
  515. let(:recipient_key) { create(:pgp_key, :with_private, fixture: recipient_email_address) }
  516. let(:cc_recipient_key) { create(:pgp_key, :with_private, fixture: cc_recipient_email_address) }
  517. let(:mail) do
  518. # Import a mail that was signed + encrypted with the same command.
  519. pgp_mail = Rails.root.join('spec/fixtures/files/pgp/mail/mail-combined.box').read
  520. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  521. SecureMailing.incoming(mail)
  522. mail
  523. end
  524. context 'when all keys are present' do
  525. before do
  526. sender_key
  527. recipient_key
  528. cc_recipient_key
  529. end
  530. it_behaves_like 'decrypting and verifying signature'
  531. end
  532. context 'when only cc recipient key is present for decryption' do
  533. before do
  534. sender_key
  535. cc_recipient_key
  536. end
  537. it_behaves_like 'decrypting and verifying signature'
  538. end
  539. context 'when only decryption key is present' do
  540. before do
  541. recipient_key
  542. cc_recipient_key
  543. end
  544. it 'decrypts, but verifies signature fails' do
  545. expect(mail[:body]).to include(raw_body)
  546. expect(mail['x-zammad-article-preferences'][:security][:sign][:success]).to be false
  547. expect(mail['x-zammad-article-preferences'][:security][:sign][:comment]).to eq('The public PGP key could not be found.')
  548. expect(mail['x-zammad-article-preferences'][:security][:encryption][:success]).to be true
  549. expect(mail['x-zammad-article-preferences'][:security][:encryption][:comment]).to eq ''
  550. end
  551. end
  552. end
  553. context 'when domain alias support is used' do
  554. before do
  555. Setting.set('pgp_recipient_alias_configuration', true)
  556. create(:pgp_key, :with_private, fixture: 'pgp1@example.com', domain_alias: 'domain1.com')
  557. create(:pgp_key, :with_private, fixture: 'pgp2@example.com', domain_alias: 'domain2.com')
  558. create(:pgp_key, fixture: 'pgp3@example.com', domain_alias: 'domain3.com')
  559. end
  560. let(:system_email_address) { 'pgp1@domain1.com' }
  561. let(:customer_email_address) { 'pgp2@domain2.com' }
  562. let(:cc_customer_email_address) { 'pgp3@domain3.com' }
  563. let(:mail) do
  564. pgp_mail = build_mail
  565. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  566. SecureMailing.incoming(mail)
  567. mail
  568. end
  569. it_behaves_like 'decrypting and verifying signature'
  570. end
  571. end
  572. end
  573. describe '.required_version?' do
  574. context 'with GnuPG being present on the system' do
  575. it 'succeeds' do
  576. expect(described_class.required_version?).to be true
  577. end
  578. end
  579. context 'without GnuPG being present on the system' do
  580. it 'fails' do
  581. allow(SecureMailing::PGP::Tool).to receive(:version).and_raise(Errno::ENOENT)
  582. expect(described_class.required_version?).to be false
  583. end
  584. end
  585. context 'with and outdated version of GnuPG' do
  586. it 'fails' do
  587. allow(SecureMailing::PGP::Tool).to receive(:version).and_return('1.8.0')
  588. expect(described_class.required_version?).to be false
  589. end
  590. end
  591. end
  592. describe '.retry' do
  593. let(:sender_email_address) { customer_email_address }
  594. let(:recipient_email_address) { system_email_address }
  595. let(:cc_recipient_email_address) { nil }
  596. let(:security_preferences) do
  597. {
  598. type: 'PGP',
  599. sign: {
  600. success: false,
  601. },
  602. encryption: {
  603. success: true,
  604. },
  605. }
  606. end
  607. let(:mail) do
  608. sender_pgp_key = create(:pgp_key, :with_private, fixture: sender_email_address)
  609. recipient_pgp_key = create(:pgp_key, :with_private, fixture: system_email_address)
  610. pgp_mail = Channel::EmailBuild.build(
  611. from: sender_email_address,
  612. to: recipient_email_address,
  613. body: raw_body,
  614. content_type: 'text/plain',
  615. security: security_preferences,
  616. attachments: [
  617. {
  618. content_type: 'text/plain',
  619. content: 'blub',
  620. filename: 'test-file1.txt',
  621. },
  622. ],
  623. )
  624. mail = Channel::EmailParser.new.parse(pgp_mail.to_s)
  625. sender_pgp_key.destroy
  626. recipient_pgp_key.destroy
  627. mail
  628. end
  629. let!(:article) do
  630. _ticket, article, _user, _mail = Channel::EmailParser.new.process({}, mail['raw'])
  631. article
  632. end
  633. context 'when private key added' do
  634. before do
  635. create(:pgp_key, :with_private, fixture: recipient_email_address)
  636. end
  637. it 'succeeds' do
  638. SecureMailing.retry(article)
  639. expect(article.preferences[:security][:sign][:success]).to be false
  640. expect(article.preferences[:security][:sign][:comment]).to be_nil
  641. expect(article.preferences[:security][:encryption][:success]).to be true
  642. expect(article.preferences[:security][:encryption][:comment]).to eq ''
  643. expect(article.body).to include(raw_body)
  644. expect(article.attachments.count).to eq(1)
  645. expect(article.attachments.first.filename).to eq('test-file1.txt')
  646. end
  647. context 'when PGP activated' do
  648. before do
  649. Setting.set('pgp_integration', false)
  650. end
  651. it 'succeeds' do
  652. Setting.set('pgp_integration', true)
  653. SecureMailing.retry(article)
  654. expect(article.preferences[:security][:sign][:success]).to be false
  655. expect(article.preferences[:security][:sign][:comment]).to be_nil
  656. expect(article.preferences[:security][:encryption][:success]).to be true
  657. expect(article.preferences[:security][:encryption][:comment]).to eq ''
  658. expect(article.body).to include(raw_body)
  659. expect(article.attachments.count).to eq(1)
  660. expect(article.attachments.first.filename).to eq('test-file1.txt')
  661. end
  662. end
  663. end
  664. end
  665. end