From 7699cf116acba18a99df2992b7dd3152491aa961 Mon Sep 17 00:00:00 2001 From: splahoti12 Date: Fri, 21 Nov 2025 16:00:43 +0530 Subject: [PATCH 01/11] Added the SRM into the new AddOn Template --- .gitignore | 2 + build.gradle.kts | 33 +- gradle.properties | 2 +- settings.gradle.kts | 17 + .../srm/zap/srm/ExtensionAlertHttp.java | 104 +++++ .../github/srm/zap/srm/ReportGenerator.java | 365 +++++++++++++++++ .../github/srm/zap/srm/ReportLastScan.java | 326 +++++++++++++++ .../srm/zap/srm/ReportLastScanHttp.java | 32 ++ .../java/com/github/srm/zap/srm/SrmAPI.java | 174 ++++++++ .../com/github/srm/zap/srm/SrmExtension.java | 191 +++++++++ .../com/github/srm/zap/srm/SrmProperties.java | 163 ++++++++ .../srm/zap/srm/UploadActionListener.java | 224 +++++++++++ .../srm/zap/srm/UploadPropertiesDialog.java | 380 ++++++++++++++++++ .../srm/security/CertificateAcceptance.java | 44 ++ .../security/CompositeX509TrustManager.java | 99 +++++ .../zap/srm/security/ExtraCertManager.java | 66 +++ .../HostnameVerifierWithExceptions.java | 45 +++ .../InvalidCertificateDialogStrategy.java | 192 +++++++++ ...InvalidCertificateFingerprintStrategy.java | 51 +++ .../security/InvalidCertificateStrategy.java | 35 ++ .../security/ReloadableX509TrustManager.java | 144 +++++++ .../SSLConnectionSocketFactoryFactory.java | 226 +++++++++++ .../srm/security/SingleExtraCertManager.java | 128 ++++++ .../ExampleFileActiveScanRule.java | 254 ------------ .../ExampleFilePassiveScanRule.java | 164 -------- .../ExampleSimpleActiveScanRule.java | 155 ------- .../ExampleSimplePassiveScanRule.java | 115 ------ .../zap/javaexample/ExtensionJavaExample.java | 185 --------- .../zap/javaexample/RightClickMsgMenu.java | 75 ---- .../zap/javaexample/SimpleExampleAPI.java | 61 --- .../resources/help/contents/images/srm.png | Bin 0 -> 713 bytes .../zap/srm/resources/help/contents/srm.html | 64 +++ .../zap/srm}/resources/help/helpset.hs | 4 +- .../srm/zap/srm/resources/help/index.xml | 9 + .../github/srm/zap/srm/resources/help/map.jhm | 9 + .../github/srm/zap/srm/resources/help/toc.xml | 12 + .../help_ar_SA/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_ar_SA/contents/srm.html | 64 +++ .../srm/resources/help_ar_SA/helpset_ar_SA.hs | 38 ++ .../zap/srm/resources/help_ar_SA/index.xml | 6 + .../zap/srm/resources/help_ar_SA}/map.jhm | 5 +- .../srm/zap/srm/resources/help_ar_SA/toc.xml | 9 + .../help_az_AZ/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_az_AZ/contents/srm.html | 64 +++ .../srm/resources/help_az_AZ/helpset_az_AZ.hs | 38 ++ .../zap/srm/resources/help_az_AZ/index.xml | 6 + .../srm/zap/srm/resources/help_az_AZ/map.jhm | 9 + .../srm/zap/srm/resources/help_az_AZ/toc.xml | 9 + .../help_bs_BA/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_bs_BA/contents/srm.html | 64 +++ .../srm/resources/help_bs_BA/helpset_bs_BA.hs | 38 ++ .../zap/srm/resources/help_bs_BA/index.xml | 6 + .../srm/zap/srm/resources/help_bs_BA/map.jhm | 9 + .../srm/zap/srm/resources/help_bs_BA/toc.xml | 9 + .../help_da_DK/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_da_DK/contents/srm.html | 64 +++ .../srm/resources/help_da_DK/helpset_da_DK.hs | 38 ++ .../zap/srm/resources/help_da_DK/index.xml | 6 + .../srm/zap/srm/resources/help_da_DK/map.jhm | 9 + .../srm/zap/srm/resources/help_da_DK/toc.xml | 9 + .../help_de_DE/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_de_DE/contents/srm.html | 64 +++ .../srm/resources/help_de_DE/helpset_de_DE.hs | 38 ++ .../zap/srm/resources/help_de_DE/index.xml | 6 + .../srm/zap/srm/resources/help_de_DE/map.jhm | 9 + .../srm/zap/srm/resources/help_de_DE/toc.xml | 9 + .../help_el_GR/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_el_GR/contents/srm.html | 64 +++ .../srm/resources/help_el_GR/helpset_el_GR.hs | 38 ++ .../zap/srm/resources/help_el_GR/index.xml | 6 + .../srm/zap/srm/resources/help_el_GR/map.jhm | 9 + .../srm/zap/srm/resources/help_el_GR/toc.xml | 9 + .../help_es_ES/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_es_ES/contents/srm.html | 64 +++ .../srm/resources/help_es_ES/helpset_es_ES.hs | 38 ++ .../zap/srm/resources/help_es_ES/index.xml | 6 + .../srm/zap/srm/resources/help_es_ES/map.jhm | 9 + .../srm/zap/srm/resources/help_es_ES/toc.xml | 9 + .../help_fa_IR/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_fa_IR/contents/srm.html | 64 +++ .../srm/resources/help_fa_IR/helpset_fa_IR.hs | 38 ++ .../zap/srm/resources/help_fa_IR/index.xml | 6 + .../srm/zap/srm/resources/help_fa_IR/map.jhm | 9 + .../srm/zap/srm/resources/help_fa_IR/toc.xml | 9 + .../help_fil_PH/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_fil_PH/contents/srm.html | 64 +++ .../resources/help_fil_PH/helpset_fil_PH.hs | 38 ++ .../zap/srm/resources/help_fil_PH/index.xml | 6 + .../srm/zap/srm/resources/help_fil_PH/map.jhm | 9 + .../srm/zap/srm/resources/help_fil_PH/toc.xml | 9 + .../help_fr_FR/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_fr_FR/contents/srm.html | 64 +++ .../srm/resources/help_fr_FR/helpset_fr_FR.hs | 38 ++ .../zap/srm/resources/help_fr_FR/index.xml | 6 + .../srm/zap/srm/resources/help_fr_FR/map.jhm | 9 + .../srm/zap/srm/resources/help_fr_FR/toc.xml | 9 + .../help_hi_IN/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_hi_IN/contents/srm.html | 64 +++ .../srm/resources/help_hi_IN/helpset_hi_IN.hs | 38 ++ .../zap/srm/resources/help_hi_IN/index.xml | 6 + .../srm/zap/srm/resources/help_hi_IN/map.jhm | 9 + .../srm/zap/srm/resources/help_hi_IN/toc.xml | 9 + .../help_hr_HR/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_hr_HR/contents/srm.html | 64 +++ .../srm/resources/help_hr_HR/helpset_hr_HR.hs | 38 ++ .../zap/srm/resources/help_hr_HR/index.xml | 6 + .../srm/zap/srm/resources/help_hr_HR/map.jhm | 9 + .../srm/zap/srm/resources/help_hr_HR/toc.xml | 9 + .../help_hu_HU/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_hu_HU/contents/srm.html | 64 +++ .../srm/resources/help_hu_HU/helpset_hu_HU.hs | 38 ++ .../zap/srm/resources/help_hu_HU/index.xml | 6 + .../srm/zap/srm/resources/help_hu_HU/map.jhm | 9 + .../srm/zap/srm/resources/help_hu_HU/toc.xml | 9 + .../help_id_ID/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_id_ID/contents/srm.html | 64 +++ .../srm/resources/help_id_ID/helpset_id_ID.hs | 38 ++ .../zap/srm/resources/help_id_ID/index.xml | 6 + .../srm/zap/srm/resources/help_id_ID/map.jhm | 9 + .../srm/zap/srm/resources/help_id_ID/toc.xml | 9 + .../help_it_IT/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_it_IT/contents/srm.html | 64 +++ .../srm/resources/help_it_IT/helpset_it_IT.hs | 38 ++ .../zap/srm/resources/help_it_IT/index.xml | 6 + .../srm/zap/srm/resources/help_it_IT/map.jhm | 9 + .../srm/zap/srm/resources/help_it_IT/toc.xml | 9 + .../help_ja_JP/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_ja_JP/contents/srm.html | 64 +++ .../srm/resources/help_ja_JP/helpset_ja_JP.hs | 38 ++ .../zap/srm/resources/help_ja_JP/index.xml | 6 + .../srm/zap/srm/resources/help_ja_JP/map.jhm | 9 + .../srm/zap/srm/resources/help_ja_JP/toc.xml | 9 + .../help_ko_KR/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_ko_KR/contents/srm.html | 64 +++ .../srm/resources/help_ko_KR/helpset_ko_KR.hs | 38 ++ .../zap/srm/resources/help_ko_KR/index.xml | 6 + .../srm/zap/srm/resources/help_ko_KR/map.jhm | 9 + .../srm/zap/srm/resources/help_ko_KR/toc.xml | 9 + .../help_ms_MY/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_ms_MY/contents/srm.html | 64 +++ .../srm/resources/help_ms_MY/helpset_ms_MY.hs | 38 ++ .../zap/srm/resources/help_ms_MY/index.xml | 6 + .../srm/zap/srm/resources/help_ms_MY/map.jhm | 9 + .../srm/zap/srm/resources/help_ms_MY/toc.xml | 9 + .../help_pl_PL/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_pl_PL/contents/srm.html | 64 +++ .../srm/resources/help_pl_PL/helpset_pl_PL.hs | 38 ++ .../zap/srm/resources/help_pl_PL/index.xml | 6 + .../srm/zap/srm/resources/help_pl_PL/map.jhm | 9 + .../srm/zap/srm/resources/help_pl_PL/toc.xml | 9 + .../help_pt_BR/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_pt_BR/contents/srm.html | 64 +++ .../srm/resources/help_pt_BR/helpset_pt_BR.hs | 38 ++ .../zap/srm/resources/help_pt_BR/index.xml | 6 + .../srm/zap/srm/resources/help_pt_BR/map.jhm | 9 + .../srm/zap/srm/resources/help_pt_BR/toc.xml | 9 + .../help_ro_RO/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_ro_RO/contents/srm.html | 64 +++ .../srm/resources/help_ro_RO/helpset_ro_RO.hs | 38 ++ .../zap/srm/resources/help_ro_RO/index.xml | 6 + .../srm/zap/srm/resources/help_ro_RO/map.jhm | 9 + .../srm/zap/srm/resources/help_ro_RO/toc.xml | 9 + .../help_ru_RU/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_ru_RU/contents/srm.html | 64 +++ .../srm/resources/help_ru_RU/helpset_ru_RU.hs | 38 ++ .../zap/srm/resources/help_ru_RU/index.xml | 6 + .../srm/zap/srm/resources/help_ru_RU/map.jhm | 9 + .../srm/zap/srm/resources/help_ru_RU/toc.xml | 9 + .../help_si_LK/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_si_LK/contents/srm.html | 64 +++ .../srm/resources/help_si_LK/helpset_si_LK.hs | 38 ++ .../zap/srm/resources/help_si_LK/index.xml | 6 + .../srm/zap/srm/resources/help_si_LK/map.jhm | 9 + .../srm/zap/srm/resources/help_si_LK/toc.xml | 9 + .../help_sk_SK/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_sk_SK/contents/srm.html | 64 +++ .../srm/resources/help_sk_SK/helpset_sk_SK.hs | 38 ++ .../zap/srm/resources/help_sk_SK/index.xml | 6 + .../srm/zap/srm/resources/help_sk_SK/map.jhm | 9 + .../srm/zap/srm/resources/help_sk_SK/toc.xml | 9 + .../help_sl_SI/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_sl_SI/contents/srm.html | 64 +++ .../srm/resources/help_sl_SI/helpset_sl_SI.hs | 38 ++ .../zap/srm/resources/help_sl_SI/index.xml | 6 + .../srm/zap/srm/resources/help_sl_SI/map.jhm | 9 + .../srm/zap/srm/resources/help_sl_SI/toc.xml | 9 + .../help_sq_AL/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_sq_AL/contents/srm.html | 64 +++ .../srm/resources/help_sq_AL/helpset_sq_AL.hs | 38 ++ .../zap/srm/resources/help_sq_AL/index.xml | 6 + .../srm/zap/srm/resources/help_sq_AL/map.jhm | 9 + .../srm/zap/srm/resources/help_sq_AL/toc.xml | 9 + .../help_sr_CS/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_sr_CS/contents/srm.html | 64 +++ .../srm/resources/help_sr_CS/helpset_sr_CS.hs | 38 ++ .../zap/srm/resources/help_sr_CS/index.xml | 6 + .../srm/zap/srm/resources/help_sr_CS/map.jhm | 9 + .../srm/zap/srm/resources/help_sr_CS/toc.xml | 9 + .../help_sr_SP/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_sr_SP/contents/srm.html | 64 +++ .../srm/resources/help_sr_SP/helpset_sr_SP.hs | 38 ++ .../zap/srm/resources/help_sr_SP/index.xml | 6 + .../srm/zap/srm/resources/help_sr_SP/map.jhm | 9 + .../srm/zap/srm/resources/help_sr_SP/toc.xml | 9 + .../help_tr_TR/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_tr_TR/contents/srm.html | 64 +++ .../srm/resources/help_tr_TR/helpset_tr_TR.hs | 38 ++ .../zap/srm/resources/help_tr_TR/index.xml | 6 + .../srm/zap/srm/resources/help_tr_TR/map.jhm | 9 + .../srm/zap/srm/resources/help_tr_TR/toc.xml | 9 + .../help_ur_PK/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_ur_PK/contents/srm.html | 64 +++ .../srm/resources/help_ur_PK/helpset_ur_PK.hs | 38 ++ .../zap/srm/resources/help_ur_PK/index.xml | 6 + .../srm/zap/srm/resources/help_ur_PK/map.jhm | 9 + .../srm/zap/srm/resources/help_ur_PK/toc.xml | 9 + .../help_zh_CN/contents/images/srm.png | Bin 0 -> 713 bytes .../resources/help_zh_CN/contents/srm.html | 64 +++ .../srm/resources/help_zh_CN/helpset_zh_CN.hs | 38 ++ .../zap/srm/resources/help_zh_CN/index.xml | 6 + .../srm/zap/srm/resources/help_zh_CN/map.jhm | 9 + .../srm/zap/srm/resources/help_zh_CN/toc.xml | 9 + .../resources/help/contents/about.html | 18 - .../resources/help/contents/images/cake.png | Bin 755 -> 0 bytes .../resources/help/contents/simple.html | 60 --- .../zap/javaexample/resources/help/index.xml | 9 - .../zap/javaexample/resources/help/toc.xml | 14 - .../srm/zap/srm/resources/Messages.properties | 50 +++ .../srm/resources/Messages_ar_SA.properties | 46 +++ .../srm/resources/Messages_az_AZ.properties | 47 +++ .../srm/resources/Messages_bn_BD.properties | 46 +++ .../srm/resources/Messages_bs_BA.properties | 46 +++ .../srm/resources/Messages_ceb_PH.properties | 46 +++ .../srm/resources/Messages_da_DK.properties | 46 +++ .../srm/resources/Messages_de_DE.properties | 46 +++ .../srm/resources/Messages_el_GR.properties | 46 +++ .../srm/resources/Messages_es_ES.properties | 46 +++ .../srm/resources/Messages_fa_IR.properties | 46 +++ .../srm/resources/Messages_fil_PH.properties | 46 +++ .../srm/resources/Messages_fr_FR.properties | 46 +++ .../srm/resources/Messages_ha_HG.properties | 46 +++ .../srm/resources/Messages_he_IL.properties | 46 +++ .../srm/resources/Messages_hi_IN.properties | 46 +++ .../srm/resources/Messages_hr_HR.properties | 46 +++ .../srm/resources/Messages_hu_HU.properties | 46 +++ .../srm/resources/Messages_id_ID.properties | 46 +++ .../srm/resources/Messages_it_IT.properties | 46 +++ .../srm/resources/Messages_ja_JP.properties | 46 +++ .../srm/resources/Messages_ko_KR.properties | 46 +++ .../srm/resources/Messages_mk_MK.properties | 46 +++ .../srm/resources/Messages_ms_MY.properties | 46 +++ .../srm/resources/Messages_nb_NO.properties | 46 +++ .../srm/resources/Messages_nl_NL.properties | 46 +++ .../srm/resources/Messages_pcm_NG.properties | 46 +++ .../srm/resources/Messages_pl_PL.properties | 46 +++ .../srm/resources/Messages_pt_BR.properties | 46 +++ .../srm/resources/Messages_pt_PT.properties | 46 +++ .../srm/resources/Messages_ro_RO.properties | 46 +++ .../srm/resources/Messages_ru_RU.properties | 46 +++ .../srm/resources/Messages_si_LK.properties | 46 +++ .../srm/resources/Messages_sk_SK.properties | 46 +++ .../srm/resources/Messages_sl_SI.properties | 46 +++ .../srm/resources/Messages_sq_AL.properties | 46 +++ .../srm/resources/Messages_sr_CS.properties | 46 +++ .../srm/resources/Messages_sr_SP.properties | 46 +++ .../srm/resources/Messages_tr_TR.properties | 46 +++ .../srm/resources/Messages_uk_UA.properties | 46 +++ .../srm/resources/Messages_ur_PK.properties | 46 +++ .../srm/resources/Messages_vi_VN.properties | 46 +++ .../srm/resources/Messages_yo_NG.properties | 46 +++ .../srm/resources/Messages_zh_CN.properties | 46 +++ .../srm/resources/Messages_zh_TW.properties | 46 +++ .../github/srm/zap/srm/resources/refresh.png | Bin 0 -> 401 bytes .../javaexample/resources/Messages.properties | 20 - .../zap/javaexample/resources/cake.png | Bin 755 -> 0 bytes .../zapHomeFiles/javaexample/ExampleFile.txt | 1 - .../zapHomeFiles/txt/example-ascan-file.txt | 76 ---- 277 files changed, 9100 insertions(+), 1225 deletions(-) create mode 100644 src/main/java/com/github/srm/zap/srm/ExtensionAlertHttp.java create mode 100644 src/main/java/com/github/srm/zap/srm/ReportGenerator.java create mode 100644 src/main/java/com/github/srm/zap/srm/ReportLastScan.java create mode 100644 src/main/java/com/github/srm/zap/srm/ReportLastScanHttp.java create mode 100644 src/main/java/com/github/srm/zap/srm/SrmAPI.java create mode 100644 src/main/java/com/github/srm/zap/srm/SrmExtension.java create mode 100644 src/main/java/com/github/srm/zap/srm/SrmProperties.java create mode 100644 src/main/java/com/github/srm/zap/srm/UploadActionListener.java create mode 100644 src/main/java/com/github/srm/zap/srm/UploadPropertiesDialog.java create mode 100644 src/main/java/com/github/srm/zap/srm/security/CertificateAcceptance.java create mode 100644 src/main/java/com/github/srm/zap/srm/security/CompositeX509TrustManager.java create mode 100644 src/main/java/com/github/srm/zap/srm/security/ExtraCertManager.java create mode 100644 src/main/java/com/github/srm/zap/srm/security/HostnameVerifierWithExceptions.java create mode 100644 src/main/java/com/github/srm/zap/srm/security/InvalidCertificateDialogStrategy.java create mode 100644 src/main/java/com/github/srm/zap/srm/security/InvalidCertificateFingerprintStrategy.java create mode 100644 src/main/java/com/github/srm/zap/srm/security/InvalidCertificateStrategy.java create mode 100644 src/main/java/com/github/srm/zap/srm/security/ReloadableX509TrustManager.java create mode 100644 src/main/java/com/github/srm/zap/srm/security/SSLConnectionSocketFactoryFactory.java create mode 100644 src/main/java/com/github/srm/zap/srm/security/SingleExtraCertManager.java delete mode 100644 src/main/java/com/github/youruser/zap/javaexample/ExampleFileActiveScanRule.java delete mode 100644 src/main/java/com/github/youruser/zap/javaexample/ExampleFilePassiveScanRule.java delete mode 100644 src/main/java/com/github/youruser/zap/javaexample/ExampleSimpleActiveScanRule.java delete mode 100644 src/main/java/com/github/youruser/zap/javaexample/ExampleSimplePassiveScanRule.java delete mode 100644 src/main/java/com/github/youruser/zap/javaexample/ExtensionJavaExample.java delete mode 100644 src/main/java/com/github/youruser/zap/javaexample/RightClickMsgMenu.java delete mode 100644 src/main/java/com/github/youruser/zap/javaexample/SimpleExampleAPI.java create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help/contents/srm.html rename src/main/javahelp/com/github/{youruser/zap/javaexample => srm/zap/srm}/resources/help/helpset.hs (91%) create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/helpset_ar_SA.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/index.xml rename src/main/javahelp/com/github/{youruser/zap/javaexample/resources/help => srm/zap/srm/resources/help_ar_SA}/map.jhm (53%) create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/helpset_az_AZ.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/helpset_bs_BA.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/helpset_da_DK.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/helpset_de_DE.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/helpset_el_GR.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/helpset_es_ES.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/helpset_fa_IR.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/helpset_fil_PH.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/helpset_fr_FR.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/helpset_hi_IN.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/helpset_hr_HR.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/helpset_hu_HU.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/helpset_id_ID.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/helpset_it_IT.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/helpset_ja_JP.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/helpset_ko_KR.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/helpset_ms_MY.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/helpset_pl_PL.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/helpset_pt_BR.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/helpset_ro_RO.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/helpset_ru_RU.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/helpset_si_LK.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/helpset_sk_SK.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/helpset_sl_SI.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/helpset_sq_AL.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/helpset_sr_CS.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/helpset_sr_SP.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/helpset_tr_TR.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/helpset_ur_PK.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/toc.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/contents/images/srm.png create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/contents/srm.html create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/helpset_zh_CN.hs create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/index.xml create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/map.jhm create mode 100644 src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/toc.xml delete mode 100644 src/main/javahelp/com/github/youruser/zap/javaexample/resources/help/contents/about.html delete mode 100644 src/main/javahelp/com/github/youruser/zap/javaexample/resources/help/contents/images/cake.png delete mode 100644 src/main/javahelp/com/github/youruser/zap/javaexample/resources/help/contents/simple.html delete mode 100644 src/main/javahelp/com/github/youruser/zap/javaexample/resources/help/index.xml delete mode 100644 src/main/javahelp/com/github/youruser/zap/javaexample/resources/help/toc.xml create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_ar_SA.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_az_AZ.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_bn_BD.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_bs_BA.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_ceb_PH.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_da_DK.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_de_DE.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_el_GR.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_es_ES.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_fa_IR.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_fil_PH.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_fr_FR.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_ha_HG.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_he_IL.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_hi_IN.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_hr_HR.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_hu_HU.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_id_ID.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_it_IT.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_ja_JP.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_ko_KR.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_mk_MK.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_ms_MY.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_nb_NO.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_nl_NL.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_pcm_NG.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_pl_PL.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_pt_BR.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_pt_PT.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_ro_RO.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_ru_RU.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_si_LK.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_sk_SK.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_sl_SI.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_sq_AL.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_sr_CS.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_sr_SP.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_tr_TR.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_uk_UA.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_ur_PK.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_vi_VN.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_yo_NG.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_zh_CN.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/Messages_zh_TW.properties create mode 100644 src/main/resources/com/github/srm/zap/srm/resources/refresh.png delete mode 100644 src/main/resources/com/github/youruser/zap/javaexample/resources/Messages.properties delete mode 100644 src/main/resources/com/github/youruser/zap/javaexample/resources/cake.png delete mode 100644 src/main/zapHomeFiles/javaexample/ExampleFile.txt delete mode 100644 src/main/zapHomeFiles/txt/example-ascan-file.txt diff --git a/.gitignore b/.gitignore index 128ab20..988e850 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,6 @@ gradle-app.setting *.classpath *.project *.settings +*.idea /bin + diff --git a/build.gradle.kts b/build.gradle.kts index 14d1598..f92a25d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,11 +8,14 @@ plugins { id("org.zaproxy.common") } -description = "A template for a 3rd party ZAP Java add-on." +description = ( + "Includes request and response data in XML reports and provides the ability " + + "to upload reports directly to a Software Risk Manager server" +) zapAddOn { - addOnId.set("addonjava") - addOnName.set("A Template Java Add-on") + addOnId.set("srm") + addOnName.set("Software Risk Manager Extension") zapVersion.set("2.16.0") addOnStatus.set(AddOnStatus.ALPHA) @@ -20,9 +23,9 @@ zapAddOn { unreleasedLink.set("https://github.com/youruser/javaexample/compare/v@CURRENT_VERSION@...HEAD") manifest { - author.set("ZAP Dev Team") - url.set("https://www.zaproxy.org/docs/desktop/addons/addonjava/") - repo.set("https://github.com/zaproxy/addon-java") + author.set("Black Duck, Inc.") + url.set("https://www.zaproxy.org/docs/desktop/addons/software-risk-manager/") + repo.set("https://github.com/codedx/srm-zap-extension/") changesFile.set(tasks.named("generateManifestChanges").flatMap { it.html }) dependencies { @@ -35,6 +38,15 @@ zapAddOn { } } +dependencies { + compileOnly("org.zaproxy.addon:commonlib:1.36.0") + implementation("org.apache.httpcomponents:httpmime:4.5.13") + implementation("com.googlecode.json-simple:json-simple:1.1.1") { + // Not needed. + exclude(group = "junit") + } +} + java { val javaVersion = JavaVersion.VERSION_17 sourceCompatibility = javaVersion @@ -42,11 +54,8 @@ java { } spotless { - kotlinGradle { - ktlint() + java { + // Don't check license nor format/style, 3rd-party add-on. + clearSteps() } } - -dependencies { - compileOnly("org.zaproxy.addon:commonlib:1.36.0") -} diff --git a/gradle.properties b/gradle.properties index 0ea36b1..ed2f91e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ -version=0.1.0 +version=2025.9.0 release=false diff --git a/settings.gradle.kts b/settings.gradle.kts index 74c0109..291563b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,3 +1,20 @@ +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + version("log4j", "2.24.2") + library("log4j-core", "org.apache.logging.log4j", "log4j-core").versionRef("log4j") + library("log4j-slf4j", "org.apache.logging.log4j", "log4j-slf4j-impl").versionRef("log4j") + library("log4j-slf4j2", "org.apache.logging.log4j", "log4j-slf4j2-impl").versionRef("log4j") + } + } +} plugins { id("org.zaproxy.common.settings") version "0.5.0" id("com.diffplug.spotless") version "6.25.0" apply false diff --git a/src/main/java/com/github/srm/zap/srm/ExtensionAlertHttp.java b/src/main/java/com/github/srm/zap/srm/ExtensionAlertHttp.java new file mode 100644 index 0000000..9a51906 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/ExtensionAlertHttp.java @@ -0,0 +1,104 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm; + +import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.core.scanner.Alert; +import org.parosproxy.paros.model.SiteNode; +import org.parosproxy.paros.network.HttpMessage; + +public class ExtensionAlertHttp { + + private static final Logger LOGGER = LogManager.getLogger(ExtensionAlertHttp.class); + + public ExtensionAlertHttp() {} + + public String getXml(SiteNode site) { + StringBuilder xml = new StringBuilder(); + xml.append(""); + List alerts = site.getAlerts(); + for (Alert alert : alerts) { + if (alert.getConfidence() != Alert.CONFIDENCE_FALSE_POSITIVE) { + String urlParamXML = getUrlParamXML(alert); + xml.append(alert.toPluginXML(urlParamXML)); + } + } + xml.append(""); + return xml.toString(); + } + + private String getHTML(Alert alert) { + // gets HttpMessage request and response data from each alert and removes illegal and + // special characters + StringBuilder httpMessage = new StringBuilder(); + + HttpMessage message = alert.getMessage(); + + if (message == null) { + LOGGER.warn(Constant.messages.getString("srm.error.httpMessage", alert.getAlertId())); + return httpMessage.toString(); + } + + String requestHeader = message.getRequestHeader().toString(); + String requestBody = message.getRequestBody().toString(); + String responseHeader = message.getResponseHeader().toString(); + String responseBody = message.getResponseBody().toString(); + + httpMessage.append(""); + httpMessage.append(ReportGenerator.entityEncode(requestHeader)); + httpMessage.append(ReportGenerator.entityEncode(requestBody)); + httpMessage.append("\n\n"); + httpMessage.append(""); + httpMessage.append(ReportGenerator.entityEncode(responseHeader)); + httpMessage.append(ReportGenerator.entityEncode(responseBody)); + httpMessage.append("\n\n"); + + return httpMessage.toString(); + } + + public String getUrlParamXML(Alert alert) { + + String uri = alert.getUri(); + String param = alert.getParam(); + String attack = alert.getAttack(); + String otherInfo = alert.getOtherInfo(); + String evidence = alert.getEvidence(); + + StringBuilder sb = new StringBuilder(200); // ZAP: Changed the type to StringBuilder. + sb.append(getHTML(alert)); + sb.append(" ").append(ReportGenerator.entityEncode(uri)).append("\r\n"); + sb.append(" ").append(ReportGenerator.entityEncode(param)).append("\r\n"); + sb.append(" ") + .append(ReportGenerator.entityEncode(attack)) + .append("\r\n"); + if (evidence != null && evidence.length() > 0) { + sb.append(" ") + .append(ReportGenerator.entityEncode(evidence)) + .append("\r\n"); + } + sb.append(" ") + .append(ReportGenerator.entityEncode(otherInfo)) + .append("\r\n"); + return sb.toString(); + } +} diff --git a/src/main/java/com/github/srm/zap/srm/ReportGenerator.java b/src/main/java/com/github/srm/zap/srm/ReportGenerator.java new file mode 100644 index 0000000..de82583 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/ReportGenerator.java @@ -0,0 +1,365 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2003-2004 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.text.SimpleDateFormat; +import java.util.Date; +import javax.swing.JOptionPane; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; +import net.sf.json.xml.XMLSerializer; +import org.apache.commons.text.StringEscapeUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.view.View; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.zaproxy.zap.utils.XMLStringUtil; +import org.zaproxy.zap.utils.XmlUtils; + +public class ReportGenerator { + + private static final Logger LOGGER = LogManager.getLogger(ReportGenerator.class); + + // private static Pattern patternWindows = Pattern.compile("window", Pattern.CASE_INSENSITIVE); + // private static Pattern patternLinux = Pattern.compile("linux", Pattern.CASE_INSENSITIVE); + + private static final SimpleDateFormat staticDateFormat = + new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss"); + + public static File XMLToHtml(Document xmlDocument, String infilexsl, File outFile) { + File stylesheet = null; + + outFile = new File(outFile.getAbsolutePath()); + try { + stylesheet = new File(infilexsl); + + DOMSource source = new DOMSource(xmlDocument); + + // Use a Transformer for output + TransformerFactory tFactory = TransformerFactory.newInstance(); + StreamSource stylesource = new StreamSource(stylesheet); + Transformer transformer = tFactory.newTransformer(stylesource); + + // Make the transformation and write to the output file + StreamResult result = new StreamResult(outFile.getPath()); + transformer.transform(source, result); + + } catch (TransformerException e) { + LOGGER.error(e.getMessage(), e); + } + + return outFile; + } + + public static File stringToHtml(String inxml, String infilexsl, String outfilename) { + return stringToHtml( + inxml, + infilexsl != null ? new StreamSource(new File(infilexsl)) : null, + outfilename); + } + + public static File stringToHtml(String inxml, StreamSource stylesource, String outfilename) { + if (stylesource != null) { + Document doc = null; + + // factory.setNamespaceAware(true); + // factory.setValidating(true); + File outfile = null; + StringReader inReader = new StringReader(inxml); + String tempOutfilename = outfilename + ".temp"; + + try { + outfile = new File(tempOutfilename); + + DocumentBuilder builder = + XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); + doc = builder.parse(new InputSource(inReader)); + + // Use a Transformer for output + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer = tFactory.newTransformer(stylesource); + transformer.setParameter("datetime", getCurrentDateTimeString()); + + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(outfile.getPath()); + transformer.transform(source, result); + + } catch (TransformerException + | SAXException + | ParserConfigurationException + | IOException e) { + LOGGER.error(e.getMessage(), e); + // Save the xml for diagnosing the problem + BufferedWriter bw = null; + showDialogForGUI(); + try { + bw = + Files.newBufferedWriter( + new File(outfilename + "-orig.xml").toPath(), + StandardCharsets.UTF_8); + bw.write(inxml); + } catch (IOException e2) { + LOGGER.error("Failed to write debug XML file", e); + return new File(outfilename); + } finally { + try { + if (bw != null) { + bw.close(); + } + } catch (IOException ex) { + } + } + return new File(outfilename); + } finally { + + } + // Replace the escaped tags used to make the report look slightly better. + // This is a temp fix to ensure reports always get generated + // we should really adopt something other than XSLT ;) + String line; + + try (BufferedReader br = + Files.newBufferedReader( + new File(tempOutfilename).toPath(), StandardCharsets.UTF_8); + BufferedWriter bw = + Files.newBufferedWriter( + new File(outfilename).toPath(), StandardCharsets.UTF_8)) { + + while ((line = br.readLine()) != null) { + bw.write(line.replace("<p>", "

").replace("</p>", "

")); + bw.newLine(); + } + + } catch (IOException e) { + showDialogForGUI(); + LOGGER.error(e.getMessage(), e); + } + // Remove the temporary file + outfile.delete(); + } else { + // No XSLT file specified, just output the XML straight to the file + BufferedWriter bw = null; + + try { + bw = + Files.newBufferedWriter( + new File(outfilename).toPath(), StandardCharsets.UTF_8); + bw.write(inxml); + } catch (IOException e2) { + showDialogForGUI(); + LOGGER.error(e2.getMessage(), e2); + } finally { + try { + if (bw != null) { + bw.close(); + } + } catch (IOException ex) { + } + } + } + + return new File(outfilename); + } + + public static File stringToJson(String inxml, String outfilename) { + BufferedWriter bw = null; + try { + bw = Files.newBufferedWriter(new File(outfilename).toPath(), StandardCharsets.UTF_8); + bw.write(stringToJson(inxml)); + } catch (IOException e2) { + showDialogForGUI(); + LOGGER.error(e2.getMessage(), e2); + } finally { + try { + if (bw != null) { + bw.close(); + } + } catch (IOException ex) { + } + } + + return new File(outfilename); + } + + public static String stringToHtml(String inxml, String infilexsl) { + return stringToHtml(inxml, new StreamSource(new File(infilexsl))); + } + + public static String stringToHtml(String inxml, StreamSource stylesource) { + Document doc = null; + + StringReader inReader = new StringReader(inxml); + StringWriter writer = new StringWriter(); + + try { + + DocumentBuilder builder = + XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); + doc = builder.parse(new InputSource(inReader)); + + // Use a Transformer for output + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer = tFactory.newTransformer(stylesource); + transformer.setParameter("datetime", getCurrentDateTimeString()); + + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(writer); + transformer.transform(source, result); + + } catch (TransformerException + | SAXException + | ParserConfigurationException + | IOException e) { + showDialogForGUI(); + LOGGER.error(e.getMessage(), e); + } finally { + + } + + // Replace the escaped tags used to make the report look slightly better. + // This is a temp fix to ensure reports always get generated + // we should really adopt something other than XSLT ;) + return writer.toString().replace("<p>", "

").replace("</p>", "

"); + } + + public static File fileToHtml(String infilexml, String infilexsl, String outfilename) { + Document doc = null; + + // factory.setNamespaceAware(true); + // factory.setValidating(true); + File stylesheet = null; + File datafile = null; + File outfile = null; + + try { + stylesheet = new File(infilexsl); + datafile = new File(infilexml); + outfile = new File(outfilename); + + DocumentBuilder builder = + XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); + doc = builder.parse(datafile); + + // Use a Transformer for output + TransformerFactory tFactory = TransformerFactory.newInstance(); + StreamSource stylesource = new StreamSource(stylesheet); + Transformer transformer = tFactory.newTransformer(stylesource); + transformer.setParameter("datetime", getCurrentDateTimeString()); + + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(outfile.getPath()); + transformer.transform(source, result); + + } catch (TransformerException + | SAXException + | ParserConfigurationException + | IOException e) { + showDialogForGUI(); + LOGGER.error(e.getMessage(), e); + } finally { + + } + + return outfile; + } + + public static String stringToJson(String inxml) { + JSONObject report = (JSONObject) new XMLSerializer().read(inxml); + Object site = report.get("site"); + if (!(site instanceof JSONArray)) { + JSONArray siteArray = new JSONArray(); + if (site != null) { + siteArray.add(site); + } + report.put("site", siteArray); + } + return report.toString(); + } + + /** Encode entity for HTML or XML output. */ + public static String entityEncode(String text) { + String result = text; + + if (result == null) { + return result; + } + + // The escapeXml function doesn't cope with some 'special' chrs + + return StringEscapeUtils.escapeXml10(XMLStringUtil.escapeControlChrs(result)); + } + + /** Get today's date string. */ + public static String getCurrentDateTimeString() { + Date dateTime = new Date(System.currentTimeMillis()); + return getDateTimeString(dateTime); + } + + public static String getDateTimeString(Date dateTime) { + // ZAP: fix unsafe call to DateFormats + synchronized (staticDateFormat) { + return staticDateFormat.format(dateTime); + } + } + + public static void addChildTextNode( + Document doc, Element parent, String nodeName, String text) { + Element child = doc.createElement(nodeName); + child.appendChild(doc.createTextNode(text)); + parent.appendChild(child); + } + + public static String getDebugXMLString(Document doc) throws TransformerException { + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + StringWriter writer = new StringWriter(); + transformer.transform(new DOMSource(doc), new StreamResult(writer)); + return writer.getBuffer().toString().replaceAll("\n|\r", ""); + } + + private static void showDialogForGUI() { + if (View.isInitialised()) { + JOptionPane.showMessageDialog( + null, Constant.messages.getString("report.write.dialog.message")); + } + } +} diff --git a/src/main/java/com/github/srm/zap/srm/ReportLastScan.java b/src/main/java/com/github/srm/zap/srm/ReportLastScan.java new file mode 100644 index 0000000..1b42d53 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/ReportLastScan.java @@ -0,0 +1,326 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2003-2004 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Locale; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; +import javax.xml.transform.stream.StreamSource; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.control.Control; +import org.parosproxy.paros.extension.Extension; +import org.parosproxy.paros.extension.ExtensionLoader; +import org.parosproxy.paros.extension.ViewDelegate; +import org.parosproxy.paros.model.Model; +import org.parosproxy.paros.model.SiteMap; +import org.parosproxy.paros.model.SiteNode; +import org.parosproxy.paros.view.View; +import org.zaproxy.zap.extension.XmlReporterExtension; +import org.zaproxy.zap.utils.DesktopUtils; +import org.zaproxy.zap.utils.XMLStringUtil; +import org.zaproxy.zap.view.ScanPanel; +import org.zaproxy.zap.view.widgets.WritableFileChooser; + +public class ReportLastScan { + + private static final Logger LOGGER = LogManager.getLogger(ReportLastScan.class); + + private static final String HTM_FILE_EXTENSION = ".htm"; + private static final String HTML_FILE_EXTENSION = ".html"; + private static final String XML_FILE_EXTENSION = ".xml"; + private static final String MD_FILE_EXTENSION = ".md"; + private static final String JSON_FILE_EXTENSION = ".json"; + + public enum ReportType { + HTML, + XML, + MD, + JSON + } + + public ReportLastScan() {} + + /** + * @deprecated generate has been deprecated in favor of using {@link #generate(String fileName, + * ReportType reportType)} + */ + @Deprecated + public File generate(String fileName, Model model, String xslFile) throws Exception { + StringBuilder sb = new StringBuilder(500); + this.generate(sb); + return ReportGenerator.stringToHtml(sb.toString(), xslFile, fileName); + } + + /** + * @deprecated generate has been deprecated in favor of using {@link #generate(String filename, + * ReportType reportType)} + */ + @Deprecated + public File generate(String fileName, Model model, ReportType reportType) throws Exception { + return generate(fileName, reportType); + } + + public File generate(String fileName, ReportType reportType) throws Exception { + StringBuilder sb = new StringBuilder(500); + this.generate(sb); + if (reportType == ReportType.JSON) { + return ReportGenerator.stringToJson(sb.toString(), fileName); + } + + if (reportType == ReportType.XML) { + return ReportGenerator.stringToHtml(sb.toString(), (String) null, fileName); + } + + String xslFileName = reportType == ReportType.MD ? "report.md.xsl" : "report.html.xsl"; + return generateReportWithXsl(sb.toString(), fileName, xslFileName); + } + + private static File generateReportWithXsl(String report, String reportFile, String xslFileName) + throws IOException { + Path xslFile = Paths.get(Constant.getZapInstall(), "xml", xslFileName); + if (Files.exists(xslFile)) { + return ReportGenerator.stringToHtml(report, xslFile.toString(), reportFile); + } + + String path = "/org/zaproxy/zap/resources/xml/" + xslFileName; + try (InputStream is = ReportLastScan.class.getResourceAsStream(path)) { + if (is == null) { + LOGGER.error("Bundled file not found: {}", path); + return new File(reportFile); + } + return ReportGenerator.stringToHtml(report, new StreamSource(is), reportFile); + } + } + + /** + * @deprecated generate has been deprecated in favor of using {@link #generate(StringBuilder + * report)} + */ + @Deprecated + public void generate(StringBuilder report, Model model) throws Exception { + generate(report); + } + + public void generate(StringBuilder report) throws Exception { + report.append(""); + report.append("\r\n"); + siteXML(report); + report.append(""); + } + + private void siteXML(StringBuilder report) { + SiteMap siteMap = Model.getSingleton().getSession().getSiteTree(); + SiteNode root = siteMap.getRoot(); + int siteNumber = root.getChildCount(); + for (int i = 0; i < siteNumber; i++) { + SiteNode site = (SiteNode) root.getChildAt(i); + String siteName = ScanPanel.cleanSiteName(site, true); + String[] hostAndPort = siteName.split(":"); + boolean isSSL = (site.getNodeName().startsWith("https")); + String siteStart = + ""; + StringBuilder extensionsXML = getExtensionsXML(site); + String siteEnd = ""; + report.append(siteStart); + report.append(extensionsXML); + report.append(siteEnd); + } + } + + public StringBuilder getExtensionsXML(SiteNode site) { + StringBuilder extensionXml = new StringBuilder(); + ExtensionLoader loader = Control.getSingleton().getExtensionLoader(); + int extensionCount = loader.getExtensionCount(); + for (int i = 0; i < extensionCount; i++) { + Extension extension = loader.getExtension(i); + if (extension instanceof XmlReporterExtension) { + extensionXml.append(((XmlReporterExtension) extension).getXml(site)); + } + } + return extensionXml; + } + + /** + * @deprecated generate has been deprecated in favor of using {@link + * #generateReport(ViewDelegate view, ReportType reportType)} + */ + @Deprecated + public void generateReport(ViewDelegate view, Model model, ReportType reportType) { + generateReport(view, reportType); + } + + /** + * Generates a report. Defaults to HTML report if reportType is null. + * + * @param view + * @param reportType + */ + public void generateReport(ViewDelegate view, ReportType reportType) { + // ZAP: Allow scan report file name to be specified + + final ReportType localReportType; + + if (reportType == null) { + localReportType = ReportType.HTML; + } else { + localReportType = reportType; + } + + try { + JFileChooser chooser = + new WritableFileChooser( + Model.getSingleton().getOptionsParam().getUserDirectory()); + + chooser.setFileFilter( + new FileFilter() { + + @Override + public boolean accept(File file) { + if (file.isDirectory()) { + return true; + } else if (file.isFile()) { + String lcFileName = file.getName().toLowerCase(Locale.ROOT); + switch (localReportType) { + case XML: + return lcFileName.endsWith(XML_FILE_EXTENSION); + case MD: + return lcFileName.endsWith(MD_FILE_EXTENSION); + case JSON: + return lcFileName.endsWith(JSON_FILE_EXTENSION); + case HTML: + default: + return (lcFileName.endsWith(HTM_FILE_EXTENSION) + || lcFileName.endsWith(HTML_FILE_EXTENSION)); + } + } + return false; + } + + @Override + public String getDescription() { + switch (localReportType) { + case XML: + return Constant.messages.getString("file.format.xml"); + case MD: + return Constant.messages.getString("file.format.md"); + case JSON: + return Constant.messages.getString("file.format.json"); + case HTML: + default: + return Constant.messages.getString("file.format.html"); + } + } + }); + + String fileExtension = ""; + switch (localReportType) { + case XML: + fileExtension = XML_FILE_EXTENSION; + break; + case JSON: + fileExtension = JSON_FILE_EXTENSION; + break; + case MD: + fileExtension = MD_FILE_EXTENSION; + break; + case HTML: + default: + fileExtension = HTML_FILE_EXTENSION; + break; + } + chooser.setSelectedFile( + new File(fileExtension)); // Default the filename to a reasonable extension; + + int rc = chooser.showSaveDialog(View.getSingleton().getMainFrame()); + File file = null; + if (rc == JFileChooser.APPROVE_OPTION) { + file = chooser.getSelectedFile(); + + File report = generate(file.getAbsolutePath(), localReportType); + if (report == null) { + view.showMessageDialog( + Constant.messages.getString( + "report.unknown.error", file.getAbsolutePath())); + return; + } + + if (Files.notExists(report.toPath())) { + LOGGER.info("Not opening report, does not exist: {}", report); + return; + } + + try { + DesktopUtils.openUrlInBrowser(report.toURI()); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + view.showMessageDialog( + Constant.messages.getString( + "report.complete.warning", report.getAbsolutePath())); + } + } + + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + view.showWarningDialog(Constant.messages.getString("report.unexpected.error")); + } + } + + /** + * @deprecated generateHtml has been deprecated in favor of using {@link + * #generateReport(ViewDelegate, Model, ReportType)} + */ + @Deprecated + public void generateHtml(ViewDelegate view, Model model) { + generateReport(view, model, ReportType.HTML); + } + + /** + * @deprecated generateXml has been deprecated in favor of using {@link + * #generateReport(ViewDelegate, Model, ReportType)} + */ + @Deprecated + public void generateXml(ViewDelegate view, Model model) { + generateReport(view, model, ReportType.XML); + } +} diff --git a/src/main/java/com/github/srm/zap/srm/ReportLastScanHttp.java b/src/main/java/com/github/srm/zap/srm/ReportLastScanHttp.java new file mode 100644 index 0000000..3dad91d --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/ReportLastScanHttp.java @@ -0,0 +1,32 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm; + +import org.parosproxy.paros.model.SiteNode; + +public class ReportLastScanHttp extends ReportLastScan { + + ReportLastScanHttp() {} + + @Override + public StringBuilder getExtensionsXML(SiteNode site) { + return new StringBuilder(new ExtensionAlertHttp().getXml(site)); + } +} diff --git a/src/main/java/com/github/srm/zap/srm/SrmAPI.java b/src/main/java/com/github/srm/zap/srm/SrmAPI.java new file mode 100644 index 0000000..6536f06 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/SrmAPI.java @@ -0,0 +1,174 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm; + +import java.io.File; +import java.io.IOException; +import java.security.GeneralSecurityException; +import net.sf.json.JSONObject; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.zaproxy.zap.extension.api.ApiAction; +import org.zaproxy.zap.extension.api.ApiException; +import org.zaproxy.zap.extension.api.ApiException.Type; +import org.zaproxy.zap.extension.api.ApiImplementor; +import org.zaproxy.zap.extension.api.ApiResponse; +import org.zaproxy.zap.extension.api.ApiResponseElement; +import org.zaproxy.zap.extension.api.ApiView; + +public class SrmAPI extends ApiImplementor { + + private static final Logger LOGGER = LogManager.getLogger(SrmExtension.class); + + private static final String PREFIX = "codedx"; + + private static final String VIEW_GENERATE = "generateReport"; + private static final String ACTION_UPLOAD = "uploadReport"; + private static final String ACTION_GEN_UPLOAD = "generateAndUpload"; + + private static final String ACTION_PARAM_FILE_PATH = "filePath"; + private static final String ACTION_PARAM_SERVER_URL = "serverUrl"; + private static final String ACTION_PARAM_API_KEY = "codeDxApiKey"; + private static final String ACTION_PARAM_PROJECT = "projectId"; + + // Optional + private static final String ACTION_PARAM_FINGERPRINT = "fingerprint"; + private static final String ACTION_PARAM_ACCEPT_PERM = "acceptPermanently"; + + private SrmExtension extension; + + public SrmAPI(SrmExtension extension) { + this.extension = extension; + this.addApiView(new ApiView(VIEW_GENERATE)); + + String[] optionalParams = new String[] {ACTION_PARAM_FINGERPRINT, ACTION_PARAM_ACCEPT_PERM}; + + this.addApiAction( + new ApiAction( + ACTION_UPLOAD, + new String[] { + ACTION_PARAM_FILE_PATH, + ACTION_PARAM_SERVER_URL, + ACTION_PARAM_API_KEY, + ACTION_PARAM_PROJECT + }, + optionalParams)); + this.addApiAction( + new ApiAction( + ACTION_GEN_UPLOAD, + new String[] { + ACTION_PARAM_SERVER_URL, ACTION_PARAM_API_KEY, ACTION_PARAM_PROJECT + }, + optionalParams)); + } + + @Override + public String getPrefix() { + return PREFIX; + } + + @Override + public ApiResponse handleApiAction(String name, JSONObject params) throws ApiException { + if (ACTION_UPLOAD.equals(name)) { + File reportFile = new File(params.getString(ACTION_PARAM_FILE_PATH)); + String serverUrl = params.getString(ACTION_PARAM_SERVER_URL); + String apiKey = params.getString(ACTION_PARAM_API_KEY); + String projectId = params.getString(ACTION_PARAM_PROJECT); + + String fingerprint = this.getParam(params, ACTION_PARAM_FINGERPRINT, ""); + boolean acceptPermanently = this.getParam(params, ACTION_PARAM_ACCEPT_PERM, false); + + uploadFile(reportFile, serverUrl, apiKey, projectId, fingerprint, acceptPermanently); + return ApiResponseElement.OK; + } else if (ACTION_GEN_UPLOAD.equals(name)) { + File reportFile; + String serverUrl = params.getString(ACTION_PARAM_SERVER_URL); + String apiKey = params.getString(ACTION_PARAM_API_KEY); + String projectId = params.getString(ACTION_PARAM_PROJECT); + + String fingerprint = this.getParam(params, ACTION_PARAM_FINGERPRINT, ""); + boolean acceptPermanently = this.getParam(params, ACTION_PARAM_ACCEPT_PERM, false); + + boolean isEmpty = false; + try { + reportFile = UploadActionListener.generateReportFile(extension); + isEmpty = UploadActionListener.reportIsEmpty(reportFile); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + throw new ApiException(Type.INTERNAL_ERROR, e.getMessage()); + } + try { + if (!isEmpty) + uploadFile( + reportFile, + serverUrl, + apiKey, + projectId, + fingerprint, + acceptPermanently); + else return new ApiResponseElement("Result", "empty"); + } finally { + reportFile.delete(); + } + return ApiResponseElement.OK; + } + throw new ApiException(Type.BAD_ACTION); + } + + @Override + public ApiResponse handleApiView(String name, JSONObject params) throws ApiException { + if (VIEW_GENERATE.equals(name)) { + try { + StringBuilder report = new StringBuilder(); + UploadActionListener.generateReportString(extension, report); + return new ApiResponseElement(name, report.toString()); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + throw new ApiException(Type.INTERNAL_ERROR, e.getMessage()); + } + } + throw new ApiException(Type.BAD_VIEW); + } + + private void uploadFile( + File reportFile, + String serverUrl, + String apiKey, + String project, + String fingerprint, + boolean acceptPermanently) + throws ApiException { + if (serverUrl.endsWith("/")) serverUrl = serverUrl.substring(0, serverUrl.length() - 1); + try { + CloseableHttpClient client = + extension.getHttpClient(serverUrl, fingerprint, acceptPermanently); + String err = + UploadActionListener.uploadFile(client, reportFile, serverUrl, apiKey, project); + if (err != null) { + LOGGER.error(err); + throw new ApiException(Type.ILLEGAL_PARAMETER, err); + } + } catch (GeneralSecurityException | IOException e) { + LOGGER.error(e.getMessage(), e); + throw new ApiException(Type.ILLEGAL_PARAMETER, e.getMessage()); + } + } +} diff --git a/src/main/java/com/github/srm/zap/srm/SrmExtension.java b/src/main/java/com/github/srm/zap/srm/SrmExtension.java new file mode 100644 index 0000000..7aa5558 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/SrmExtension.java @@ -0,0 +1,191 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm; + +import com.github.srm.zap.srm.ReportLastScan.ReportType; +import com.github.srm.zap.srm.security.SSLConnectionSocketFactoryFactory; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.security.GeneralSecurityException; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.extension.ExtensionAdaptor; +import org.parosproxy.paros.extension.ExtensionHook; +import org.parosproxy.paros.model.Model; +import org.parosproxy.paros.network.ConnectionParam; +import org.parosproxy.paros.view.View; +import org.zaproxy.zap.extension.api.API; +import org.zaproxy.zap.view.ZapMenuItem; + +/* + * The Software Risk Manager ZAP extension used to include request and response data in alert reports. + * + */ +public class SrmExtension extends ExtensionAdaptor { + + private static final Logger LOGGER = LogManager.getLogger(SrmExtension.class); + + private SrmAPI cdxAPIImpl; + protected static final String PREFIX = "srm"; + + // The name is public so that other extensions can access it + public static final String NAME = "SrmExtension"; + + private ZapMenuItem menuUpload = null; + private ZapMenuItem menuExport = null; + + public SrmExtension() { + super(NAME); + } + + @Override + public boolean canUnload() { + return true; + } + + @Override + public void hook(ExtensionHook extensionHook) { + super.hook(extensionHook); + cdxAPIImpl = new SrmAPI(this); + API.getInstance().registerApiImplementor(cdxAPIImpl); + if (hasView()) { + extensionHook.getHookMenu().addReportMenuItem(getUploadMenu()); + extensionHook.getHookMenu().addReportMenuItem(getExportMenu()); + } + } + + @Override + public void unload() { + API.getInstance().removeApiImplementor(cdxAPIImpl); + } + + public ZapMenuItem getUploadMenu() { + if (menuUpload == null) { + menuUpload = new ZapMenuItem("srm.topmenu.upload.title"); + menuUpload.addActionListener(new UploadActionListener(this)); + } + return menuUpload; + } + + public ZapMenuItem getExportMenu() { + if (menuExport == null) { + menuExport = new ZapMenuItem("srm.topmenu.report.title"); + + menuExport.addActionListener( + e -> { + ReportLastScanHttp saver = new ReportLastScanHttp(); + saver.generateReport(getView(), ReportType.XML); + }); + } + return menuExport; + } + + public CloseableHttpClient getHttpClient() { + try { + return getHttpClient(SrmProperties.getInstance().getServerUrl()); + } catch (MalformedURLException e) { + View.getSingleton() + .showWarningDialog(Constant.messages.getString("srm.error.client.invalid")); + } catch (IOException | GeneralSecurityException e) { + View.getSingleton() + .showWarningDialog(Constant.messages.getString("srm.error.client.failed")); + } + return null; + } + + public CloseableHttpClient getHttpClient(String url) + throws IOException, GeneralSecurityException { + return getHttpClient(url, null, false); + } + + @SuppressWarnings("deprecation") + public CloseableHttpClient getHttpClient( + String url, String fingerprint, boolean acceptPermanently) + throws IOException, GeneralSecurityException { + RequestConfig.Builder configBuilder = + RequestConfig.custom() + .setConnectTimeout(getTimeout()) + .setSocketTimeout(getTimeout()) + .setConnectionRequestTimeout(getTimeout()); + + HttpClientBuilder builder = HttpClientBuilder.create(); + if (fingerprint != null) { + builder.setSSLSocketFactory( + SSLConnectionSocketFactoryFactory.getFactory( + URI.create(url).getHost(), this, fingerprint, acceptPermanently)); + } else { + builder.setSSLSocketFactory( + SSLConnectionSocketFactoryFactory.getFactory(URI.create(url).getHost(), this)); + } + + // --- ZAP Proxy Support --- + ConnectionParam connParam = Model.getSingleton().getOptionsParam().getConnectionParam(); + if (connParam.isUseProxyChain()) { + String proxyHost = connParam.getProxyChainName(); + int proxyPort = connParam.getProxyChainPort(); + HttpHost proxy = new HttpHost(proxyHost, proxyPort); + configBuilder.setProxy(proxy); + + if (connParam.isUseProxyChainAuth()) { + BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials( + new AuthScope(proxyHost, proxyPort), + new UsernamePasswordCredentials( + connParam.getProxyChainUserName(), + connParam.getProxyChainPassword())); + builder.setDefaultCredentialsProvider(credsProvider); + } + } + // --- End ZAP Proxy Support --- + + builder.setDefaultRequestConfig(configBuilder.build()); + return builder.build(); + } + + @Override + public String getDescription() { + return Constant.messages.getString("srm.desc"); + } + + @Override + public URL getURL() { + return null; + } + + private int getTimeout() { + try { + return Integer.parseInt(SrmProperties.getInstance().getTimeout()) * 1000; + } catch (NumberFormatException e) { + // If for some reason the saved timeout value can't be parsed as an int, we will return + // the default value of 120 seconds + return SrmProperties.DEFAULT_TIMEOUT_INT; + } + } +} diff --git a/src/main/java/com/github/srm/zap/srm/SrmProperties.java b/src/main/java/com/github/srm/zap/srm/SrmProperties.java new file mode 100644 index 0000000..f6f0f32 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/SrmProperties.java @@ -0,0 +1,163 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Properties; +import org.apache.commons.configuration.Configuration; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.model.Model; + +public class SrmProperties { + private static class Holder { + static final SrmProperties INSTANCE = new SrmProperties(); + } + + public static SrmProperties getInstance() { + return Holder.INSTANCE; + } + + private SrmProperties() { + loadProperties(); + } + + private static final Logger LOGGER = LogManager.getLogger(SrmProperties.class); + + private static final String PROP_FILE = "srm.properties"; + private static final String FALLBACK_PROP_FILE = "codedx.properties"; + private static final String KEY_SERVER = "serverUrl"; + private static final String KEY_API = "apiKey"; + private static final String KEY_SELECTED = "selectedId"; + private static final String KEY_TIMEOUT = "timeout"; + + // ZAP config keys with prefix + private static final String ZAP_CONFIG_PREFIX = "srm."; + private static final String ZAP_KEY_SERVER = ZAP_CONFIG_PREFIX + KEY_SERVER; + private static final String ZAP_KEY_API = ZAP_CONFIG_PREFIX + KEY_API; + private static final String ZAP_KEY_SELECTED = ZAP_CONFIG_PREFIX + KEY_SELECTED; + private static final String ZAP_KEY_TIMEOUT = ZAP_CONFIG_PREFIX + KEY_TIMEOUT; + + private Properties prop; + private File configFile; + private boolean useZapConfig = false; + + public static final String DEFAULT_TIMEOUT_STRING = "120"; + public static final int DEFAULT_TIMEOUT_INT = 120000; + + public String getServerUrl() { + String text = getProperty(KEY_SERVER); + if (text != null && text.endsWith("/")) { + return text.substring(0, text.length() - 1); + } + return text != null ? text : ""; + } + + public String getApiKey() { + return getProperty(KEY_API); + } + + public String getSelectedId() { + return getProperty(KEY_SELECTED); + } + + public String getTimeout() { + String timeout = getProperty(KEY_TIMEOUT); + if (timeout == null || timeout.isEmpty()) { + timeout = DEFAULT_TIMEOUT_STRING; + } + return timeout; + } + + private String getProperty(String key) { + if (useZapConfig) { + Configuration config = Model.getSingleton().getOptionsParam().getConfig(); + String zapKey = ZAP_CONFIG_PREFIX + key; + return config.getString(zapKey, ""); + } else { + String value = prop.getProperty(key); + return value == null ? "" : value; + } + } + + public void setProperties(String server, String api, String selectedId, String timeout) { + if (useZapConfig) { + Configuration config = Model.getSingleton().getOptionsParam().getConfig(); + config.setProperty(ZAP_KEY_SERVER, server); + config.setProperty(ZAP_KEY_API, api); + config.setProperty(ZAP_KEY_SELECTED, selectedId); + config.setProperty(ZAP_KEY_TIMEOUT, timeout); + } else { + prop.setProperty(KEY_SERVER, server); + prop.setProperty(KEY_API, api); + prop.setProperty(KEY_SELECTED, selectedId); + prop.setProperty(KEY_TIMEOUT, timeout); + saveProperties(); + } + } + + private void loadProperties() { + if (prop == null) prop = new Properties(); + + // Check for srm.properties first + File srmFile = Paths.get(Constant.getZapHome(), PROP_FILE).toFile(); + if (srmFile.exists()) { + configFile = srmFile; + loadFromFile(configFile); + return; + } + + // Check for codedx.properties fallback + File fallbackFile = Paths.get(Constant.getZapHome(), FALLBACK_PROP_FILE).toFile(); + if (fallbackFile.exists()) { + configFile = fallbackFile; + loadFromFile(configFile); + return; + } + + // Neither file exists, use ZAP config + useZapConfig = true; + LOGGER.info("Using ZAP configuration for SRM properties"); + } + + private void loadFromFile(File file) { + try (FileInputStream inp = new FileInputStream(file)) { + prop.load(inp); + LOGGER.info("Loaded SRM properties from: " + file.getName()); + } catch (IOException e) { + LOGGER.error("Error loading properties file: " + file.getName(), e); + } + } + + private void saveProperties() { + if (configFile != null) { + try (FileOutputStream out = new FileOutputStream(configFile)) { + prop.store(out, null); + } catch (IOException e) { + LOGGER.error("Error saving properties file: " + configFile.getName(), e); + } + } + } +} diff --git a/src/main/java/com/github/srm/zap/srm/UploadActionListener.java b/src/main/java/com/github/srm/zap/srm/UploadActionListener.java new file mode 100644 index 0000000..e68afa6 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/UploadActionListener.java @@ -0,0 +1,224 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm; + +import com.github.srm.zap.srm.ReportLastScan.ReportType; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.entity.mime.content.FileBody; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.view.View; + +public class UploadActionListener implements ActionListener { + + private static final Logger LOGGER = LogManager.getLogger(UploadActionListener.class); + + private static final XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); + + static { + xmlInputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false); + xmlInputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); + } + + private SrmExtension extension; + private UploadPropertiesDialog prop; + + public UploadActionListener(SrmExtension extension) { + this.extension = extension; + this.prop = new UploadPropertiesDialog(extension); + } + + @Override + public void actionPerformed(ActionEvent e) { + prop.openProperties(this); + } + + public void generateAndUploadReport() { + String error = null; + try { + final File reportFile = generateReportFile(extension); + if (!reportIsEmpty(reportFile)) { + Thread uploadThread = + new Thread() { + @Override + public void run() { + String err; + try { + err = + uploadFile( + extension.getHttpClient(), + reportFile, + SrmProperties.getInstance().getServerUrl(), + SrmProperties.getInstance().getApiKey(), + prop.getProject().getValue()); + } catch (IOException ex1) { + err = Constant.messages.getString("srm.error.unexpected"); + LOGGER.error("Unexpected error while uploading report: ", ex1); + } + if (err != null) View.getSingleton().showMessageDialog(err); + else + View.getSingleton() + .showMessageDialog( + Constant.messages.getString( + "srm.message.success")); + reportFile.delete(); + } + }; + uploadThread.start(); + } else { + error = Constant.messages.getString("srm.error.empty"); + } + } catch (Exception ex2) { + error = Constant.messages.getString("srm.error.failed"); + LOGGER.error("Unexpected error while generating report: ", ex2); + } + if (error != null) View.getSingleton().showWarningDialog(error); + } + + public static String uploadFile( + CloseableHttpClient client, + File reportFile, + String serverUrl, + String apiKey, + String project) + throws IOException { + String err = null; + HttpResponse response = sendData(client, reportFile, serverUrl, apiKey, project); + StatusLine responseLine = null; + int responseCode = -1; + if (response != null) { + responseLine = response.getStatusLine(); + responseCode = responseLine.getStatusCode(); + } + if (responseCode == 400) { + err = + Constant.messages.getString("srm.error.unexpected") + + "\n" + + Constant.messages.getString("srm.error.http.400"); + } else if (responseCode == 403) { + err = + Constant.messages.getString("srm.error.unsent") + + " " + + Constant.messages.getString("srm.error.http.403"); + } else if (responseCode == 404) { + err = + Constant.messages.getString("srm.error.unsent") + + " " + + Constant.messages.getString("srm.error.http.404"); + } else if (responseCode == 415) { + err = + Constant.messages.getString("srm.error.unexpected") + + "\n" + + Constant.messages.getString("srm.error.http.415"); + } else if (responseCode != 200 && responseCode != 202) { + err = Constant.messages.getString("srm.error.unexpected"); + if (response != null) + err += Constant.messages.getString("srm.error.http.other") + " " + responseLine; + } + return err; + } + + private static HttpResponse sendData( + CloseableHttpClient client, + File reportFile, + String serverUrl, + String apiKey, + String project) + throws IOException { + if (client == null) return null; + try { + HttpPost post = new HttpPost(serverUrl + "/api/projects/" + project + "/analysis"); + post.setHeader("API-Key", apiKey); + + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); + builder.addPart("file", new FileBody(reportFile)); + + HttpEntity entity = builder.build(); + post.setEntity(entity); + + HttpResponse response = client.execute(post); + HttpEntity resEntity = response.getEntity(); + + if (resEntity != null) { + EntityUtils.consume(resEntity); + } + + return response; + } finally { + client.close(); + } + } + + public static void generateReportString(SrmExtension extension, StringBuilder report) + throws Exception { + ReportLastScanHttp saver = new ReportLastScanHttp(); + saver.generate(report); + } + + public static File generateReportFile(SrmExtension extension) throws Exception { + File reportFile = File.createTempFile("srm-zap-report", ".xml"); + reportFile.deleteOnExit(); + + ReportLastScanHttp saver = new ReportLastScanHttp(); + saver.generate(reportFile.getCanonicalPath(), ReportType.XML); + + return reportFile; + } + + public static Boolean reportIsEmpty(File reportFile) throws IOException, XMLStreamException { + BufferedReader br = Files.newBufferedReader(reportFile.toPath()); + try { + XMLEventReader reader = xmlInputFactory.createXMLEventReader(br); + + while (reader.hasNext()) { + XMLEvent event = reader.nextEvent(); + if (event.isStartElement() + && !event.asStartElement() + .getName() + .getLocalPart() + .equals("OWASPZAPReport")) { + return false; + } + } + } finally { + br.close(); + } + return true; + } +} diff --git a/src/main/java/com/github/srm/zap/srm/UploadPropertiesDialog.java b/src/main/java/com/github/srm/zap/srm/UploadPropertiesDialog.java new file mode 100644 index 0000000..157b9ab --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/UploadPropertiesDialog.java @@ -0,0 +1,380 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm; + +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.security.GeneralSecurityException; +import java.util.Arrays; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingConstants; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.parosproxy.paros.Constant; + +public class UploadPropertiesDialog { + + private static final Logger LOGGER = LogManager.getLogger(UploadPropertiesDialog.class); + + private static final String[] DIALOG_BUTTONS = { + Constant.messages.getString("srm.settings.upload"), + Constant.messages.getString("srm.settings.cancel") + }; + + public static final ImageIcon REFRESH_ICON = + new ImageIcon( + UploadPropertiesDialog.class.getResource( + "/com/github/srm/zap/srm/resources/refresh.png")); + + private JTextField serverUrl; + private JTextField apiKey; + private JComboBox projectBox; + private JTextField timeout; + private JDialog dialog; + + private ModifiedNameValuePair[] projectArr = new ModifiedNameValuePair[0]; + + private SrmExtension extension; + + public UploadPropertiesDialog(SrmExtension extension) { + this.extension = extension; + } + + public void openProperties(final UploadActionListener uploader) { + JPanel message = new JPanel(new GridBagLayout()); + + serverUrl = + labelTextField( + Constant.messages.getString("srm.settings.serverurl") + " ", + message, + SrmProperties.getInstance().getServerUrl(), + 30); + apiKey = + labelTextField( + Constant.messages.getString("srm.settings.apikey") + " ", + message, + SrmProperties.getInstance().getApiKey(), + 30); + projectBox = createProjectComboBox(message); + timeout = + labelTextField( + Constant.messages.getString("srm.setting.timeout") + " ", + message, + SrmProperties.getInstance().getTimeout(), + 5); + + final JOptionPane pane = + new JOptionPane( + message, + JOptionPane.PLAIN_MESSAGE, + JOptionPane.OK_CANCEL_OPTION, + null, + DIALOG_BUTTONS, + null); + dialog = pane.createDialog(Constant.messages.getString("srm.settings.title")); + + Thread popupThread = + new Thread() { + @Override + public void run() { + dialog.setVisible(true); + if (DIALOG_BUTTONS[0].equals(pane.getValue())) { + String timeoutValue = timeout.getText(); + if (!isStringNumber(timeoutValue)) { + timeoutValue = SrmProperties.DEFAULT_TIMEOUT_STRING; + error(Constant.messages.getString("srm.error.timeout")); + } + SrmProperties.getInstance() + .setProperties( + serverUrl.getText(), + apiKey.getText(), + getProject().getValue(), + timeoutValue); + uploader.generateAndUploadReport(); + } + } + }; + Thread updateThread = + new Thread() { + @Override + public void run() { + if (!"".equals(serverUrl.getText()) && !"".equals(apiKey.getText())) { + updateProjects(true); + String previousId = SrmProperties.getInstance().getSelectedId(); + for (NameValuePair p : projectArr) { + if (previousId.equals(p.getValue())) projectBox.setSelectedItem(p); + } + } + } + }; + popupThread.start(); + updateThread.start(); + } + + private boolean isStringNumber(String value) { + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (!Character.isDigit(c)) { + return false; + } + } + return true; + } + + private JTextField labelTextField(String label, Container cont, String base, int columns) { + createSettingsLabel(label, cont); + + JTextField textField = new JTextField(base, columns); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 1; + gbc.anchor = GridBagConstraints.WEST; + cont.add(textField, gbc); + + return textField; + } + + private JComboBox createProjectComboBox(Container cont) { + createSettingsLabel("Project: ", cont); + + JComboBox box = new JComboBox<>(); + box.setPreferredSize(new Dimension(300, 27)); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + cont.add(box, gbc); + + JButton refresh = new JButton(REFRESH_ICON); + refresh.setPreferredSize( + new Dimension(REFRESH_ICON.getIconHeight() + 6, REFRESH_ICON.getIconHeight() + 6)); + refresh.addActionListener( + e -> { + if ("".equals(serverUrl.getText()) || "".equals(apiKey.getText())) { + error(Constant.messages.getString("srm.error.required")); + return; + } + dialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + updateProjects(); + dialog.setCursor(Cursor.getDefaultCursor()); + }); + gbc = new GridBagConstraints(); + gbc.gridx = 2; + gbc.gridy = 2; + gbc.anchor = GridBagConstraints.WEST; + cont.add(refresh, gbc); + + return box; + } + + private void createSettingsLabel(String label, Container cont) { + JLabel labelField = new JLabel(label); + labelField.setHorizontalAlignment(SwingConstants.LEFT); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridwidth = 1; + gbc.gridx = 0; + gbc.insets = new Insets(0, 10, 0, 0); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.HORIZONTAL; + cont.add(labelField, gbc); + } + + public void updateProjects() { + updateProjects(false); + } + + public void updateProjects(boolean initialRefresh) { + dialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + CloseableHttpClient client = null; + BufferedReader rd = null; + projectArr = new ModifiedNameValuePair[0]; + try { + client = extension.getHttpClient(getServerUrl()); + if (client != null) { + HttpGet get = new HttpGet(getServerUrl() + "/api/projects"); + get.setHeader("API-Key", getApiKey()); + HttpResponse response = client.execute(get); + rd = + new BufferedReader( + new InputStreamReader(response.getEntity().getContent(), "UTF-8")); + + StringBuilder result = new StringBuilder(); + String line = ""; + while ((line = rd.readLine()) != null) { + result.append(line); + } + + int code = response.getStatusLine().getStatusCode(); + if (code == 200) { + projectArr = parseProjectJson(result.toString(), initialRefresh); + } else if (!initialRefresh) { + String msg = + Constant.messages.getString("srm.refresh.non200") + + ' ' + + response.getStatusLine() + + '.'; + if (code == 403) msg += Constant.messages.getString("srm.refresh.403"); + else if (code == 404) msg += Constant.messages.getString("srm.refresh.404"); + else if (code == 400) msg += Constant.messages.getString("srm.refresh.400"); + error(msg); + } + } + } catch (GeneralSecurityException | ParseException | IOException e) { + if (!initialRefresh) { + if (e instanceof MalformedURLException) + error(Constant.messages.getString("srm.error.client.invalid")); + else error(Constant.messages.getString("srm.refresh.failed")); + } + LOGGER.error("Error refreshing project list: ", e); + } finally { + if (client != null) + try { + client.close(); + } catch (IOException e) { + } + if (rd != null) + try { + rd.close(); + } catch (IOException e) { + } + } + updateProjectComboBox(); + dialog.setCursor(Cursor.getDefaultCursor()); + } + + private ModifiedNameValuePair[] parseProjectJson(String json, boolean initialRefresh) + throws ParseException { + JSONParser parser = new JSONParser(); + JSONObject obj = (JSONObject) parser.parse(json); + JSONArray projects = (JSONArray) obj.get("projects"); + + ModifiedNameValuePair[] projectArr = new ModifiedNameValuePair[projects.size()]; + for (int i = 0; i < projectArr.length; i++) { + JSONObject project = (JSONObject) projects.get(i); + int id = ((Long) project.get("id")).intValue(); + String name = (String) project.get("name"); + projectArr[i] = new ModifiedNameValuePair(name, Integer.toString(id)); + } + if (projectArr.length > 0) { + Arrays.sort(projectArr); + // set the project ids to visible if the names are the same + for (int i = 0; i < projectArr.length - 1; i++) { + if (projectArr[i].getName() != null + && projectArr[i].getName().equals(projectArr[i + 1].getName())) { + projectArr[i].setUseId(true); + projectArr[i + 1].setUseId(true); + } + } + } else if (!initialRefresh) warn(Constant.messages.getString("srm.refresh.noproject")); + return projectArr; + } + + public void updateProjectComboBox() { + if (projectBox != null) { + NameValuePair selected = getProject(); + projectBox.removeAllItems(); + for (NameValuePair p : projectArr) { + projectBox.addItem(p); + if (selected != null && selected.equals(p)) { + projectBox.setSelectedItem(p); + } + } + } + } + + public NameValuePair getProject() { + return (NameValuePair) projectBox.getSelectedItem(); + } + + private void warn(String message) { + JOptionPane.showMessageDialog( + dialog, + message, + Constant.messages.getString("srm.warning"), + JOptionPane.WARNING_MESSAGE); + } + + private void error(String message) { + JOptionPane.showMessageDialog( + dialog, + message, + Constant.messages.getString("srm.error"), + JOptionPane.ERROR_MESSAGE); + } + + private String getServerUrl() { + String text = serverUrl.getText(); + if (text.endsWith("/")) return text.substring(0, text.length() - 1); + return text; + } + + private String getApiKey() { + return apiKey.getText(); + } + + private static class ModifiedNameValuePair extends BasicNameValuePair + implements Comparable { + private static final long serialVersionUID = -6671681121783779976L; + private boolean useId = false; + + public ModifiedNameValuePair(String name, String value) { + super(name, value); + } + + public void setUseId(boolean useId) { + this.useId = useId; + } + + @Override + public String toString() { + if (useId) return getName() + " (id: " + getValue() + ")"; + return getName(); + } + + @Override + public int compareTo(ModifiedNameValuePair o) { + int val = this.getName().compareTo(((NameValuePair) o).getName()); + if (val == 0) return this.getValue().compareTo(((NameValuePair) o).getValue()); + return val; + } + } +} diff --git a/src/main/java/com/github/srm/zap/srm/security/CertificateAcceptance.java b/src/main/java/com/github/srm/zap/srm/security/CertificateAcceptance.java new file mode 100644 index 0000000..bdaeb21 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/security/CertificateAcceptance.java @@ -0,0 +1,44 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm.security; + +/** + * Enumeration to describe the possible outcomes of an {@link InvalidCertificateStrategy} when + * presented with an invalid certificate. + */ +public enum CertificateAcceptance { + + /** The invalid certificate should be rejected. */ + REJECT, + + /** + * The invalid certificate should be accepted on a short-term basis, e.g. for the duration of + * the session, or until the current JVM stops. The actual interpretation is up to the + * corresponding {@link ExtraCertManager}. + */ + ACCEPT_TEMPORARILY, + + /** + * The invalid certificate should be accepted on a long-term basis, e.g. by adding the + * certificate to a custom KeyStore and persisting it to disk. The actual interpretation is up + * to the corresponding {@link ExtraCertManager}. + */ + ACCEPT_PERMANENTLY; +} diff --git a/src/main/java/com/github/srm/zap/srm/security/CompositeX509TrustManager.java b/src/main/java/com/github/srm/zap/srm/security/CompositeX509TrustManager.java new file mode 100644 index 0000000..effec70 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/security/CompositeX509TrustManager.java @@ -0,0 +1,99 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm.security; + +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.LinkedList; +import java.util.List; +import javax.net.ssl.SSLContext; +import javax.net.ssl.X509TrustManager; + +/** + * Represents an ordered list of {@link X509TrustManager}s with additive trust. If any one of the + * composed managers trusts a certificate chain, then it is trusted by the composite manager. + * + *

This is necessary because of the fine-print on {@link SSLContext#init}: Only the first + * instance of a particular key and/or trust manager implementation type in the array is used. (For + * example, only the first javax.net.ssl.X509KeyManager in the array will be used.) + * + *

see + * StackOverflow and the related blog post + * + * @author codyaray + * @since 4/22/2013 + * @see + */ +public class CompositeX509TrustManager implements X509TrustManager { + + private final List trustManagers = new LinkedList<>(); + + /** + * Initializes the composite trust manager, copying all of the non-null entries in the given + * trustManagers list into its own internal list. + * + * @param trustManagers A list of (potentially null) trust managers. + */ + public CompositeX509TrustManager(List trustManagers) { + for (X509TrustManager tm : trustManagers) { + if (tm != null) this.trustManagers.add(tm); + } + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + for (X509TrustManager trustManager : trustManagers) { + try { + trustManager.checkClientTrusted(chain, authType); + return; // someone trusts them. success! + } catch (CertificateException e) { + // maybe someone else will trust them + } + } + throw new CertificateException("None of the TrustManagers trust this certificate chain"); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + for (X509TrustManager trustManager : trustManagers) { + try { + trustManager.checkServerTrusted(chain, authType); + return; // someone trusts them. success! + } catch (CertificateException e) { + // maybe someone else will trust them + } + } + throw new CertificateException("None of the TrustManagers trust this certificate chain"); + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + List certificates = new LinkedList<>(); + for (X509TrustManager trustManager : trustManagers) { + for (X509Certificate cert : trustManager.getAcceptedIssuers()) { + certificates.add(cert); + } + } + return certificates.toArray(new X509Certificate[certificates.size()]); + } +} diff --git a/src/main/java/com/github/srm/zap/srm/security/ExtraCertManager.java b/src/main/java/com/github/srm/zap/srm/security/ExtraCertManager.java new file mode 100644 index 0000000..228c057 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/security/ExtraCertManager.java @@ -0,0 +1,66 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm.security; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.Certificate; + +public interface ExtraCertManager { + + /** + * Add a certificate that will be accepted until some event (as determined by the implementation + * of this interface) occurs, causing it to be "forgotten". + * + * @param cert + */ + void addTemporaryCert(Certificate cert) throws IOException, GeneralSecurityException; + + /** + * Add a certificate that will be accepted until this manager is "purged". Certificates added in + * this way will generally be written to disk, and will be available upon restarting the + * program. + * + * @param cert + * @throws IOException + * @throws GeneralSecurityException + */ + void addPermanentCert(Certificate cert) throws IOException, GeneralSecurityException; + + /** Remove all certificates that have been added via {@link #addTemporaryCert(Certificate)}. */ + void purgeTemporaryCerts() throws IOException, GeneralSecurityException; + + /** Remove all certificates that have been added via {@link #addPermanentCert(Certificate)}. */ + void purgePermanentCerts() throws IOException, GeneralSecurityException; + + /** + * Remove all certificates that have been added either by {@link #addTemporaryCert(Certificate)} + * or {@link #addPermanentCert(Certificate)}. + */ + void purgeAllCerts() throws IOException, GeneralSecurityException; + + /** + * Return a representation of this manager as a KeyStore instance. + * + * @return A new KeyStore that represents the contents of this certificate manager + */ + KeyStore asKeyStore() throws IOException, GeneralSecurityException; +} diff --git a/src/main/java/com/github/srm/zap/srm/security/HostnameVerifierWithExceptions.java b/src/main/java/com/github/srm/zap/srm/security/HostnameVerifierWithExceptions.java new file mode 100644 index 0000000..4bbe4b4 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/security/HostnameVerifierWithExceptions.java @@ -0,0 +1,45 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm.security; + +import java.util.Set; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLSession; + +/** + * HostnameVerifier implementation that delegates to another one, but will allow a particular set of + * hosts through even if the delegate verifier fails. + */ +public class HostnameVerifierWithExceptions implements HostnameVerifier { + + private final HostnameVerifier delegate; + private final Set allowedExceptions; + + public HostnameVerifierWithExceptions( + HostnameVerifier delegate, Set allowedExceptions) { + this.delegate = delegate; + this.allowedExceptions = allowedExceptions; + } + + @Override + public boolean verify(String host, SSLSession session) { + return delegate.verify(host, session) || allowedExceptions.contains(host); + } +} diff --git a/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateDialogStrategy.java b/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateDialogStrategy.java new file mode 100644 index 0000000..9a48122 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateDialogStrategy.java @@ -0,0 +1,192 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm.security; + +import com.github.srm.zap.srm.SrmExtension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Formatter; +import java.util.StringTokenizer; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLException; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.parosproxy.paros.Constant; + +/** + * An InvalidCertificateStrategy implementation that opens a dialog, prompting the user for their + * choice of action. + */ +public class InvalidCertificateDialogStrategy implements InvalidCertificateStrategy { + + private final HostnameVerifier defaultHostVerifier; + private final String host; + private SrmExtension extension; + + private static final String dialogTitle = Constant.messages.getString("srm.ssl.title"); + private static final String[] dialogButtons = { + Constant.messages.getString("srm.ssl.reject"), + Constant.messages.getString("srm.ssl.accepttemp"), + Constant.messages.getString("srm.ssl.acceptperm") + }; + + public InvalidCertificateDialogStrategy( + HostnameVerifier defaultHostVerifier, String host, SrmExtension extension) { + this.defaultHostVerifier = defaultHostVerifier; + this.host = host; + this.extension = extension; + } + + @Override + public CertificateAcceptance checkAcceptance( + Certificate genericCert, CertificateException certError) { + if (genericCert instanceof X509Certificate + && defaultHostVerifier instanceof DefaultHostnameVerifier) { + X509Certificate cert = (X509Certificate) genericCert; + DefaultHostnameVerifier verifier = (DefaultHostnameVerifier) defaultHostVerifier; + + JPanel message = new JPanel(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridwidth = 2; + gbc.insets = new Insets(0, 0, 10, 0); + gbc.anchor = GridBagConstraints.WEST; + message.add(new JLabel(Constant.messages.getString("srm.ssl.description")), gbc); + + gbc = new GridBagConstraints(); + gbc.gridy = 2; + gbc.insets = new Insets(2, 0, 2, 0); + gbc.anchor = GridBagConstraints.WEST; + + JLabel issuer = new JLabel(Constant.messages.getString("srm.ssl.issuer") + " "); + Font defaultFont = issuer.getFont(); + Font bold = new Font(defaultFont.getName(), Font.BOLD, defaultFont.getSize()); + issuer.setFont(bold); + + message.add(issuer, gbc); + gbc.gridx = 1; + message.add(new JLabel(cert.getIssuerX500Principal().getName()), gbc); + + try { + JLabel fingerprint = + new JLabel(Constant.messages.getString("srm.ssl.fingerprint") + " "); + fingerprint.setFont(bold); + gbc.gridx = 0; + gbc.gridy += 1; + message.add(fingerprint, gbc); + + gbc.gridx = 1; + message.add(new JLabel(toHexString(getSHA1(cert.getEncoded()), " ")), gbc); + } catch (CertificateEncodingException e) { + // this shouldn't actually ever happen + } + + try { + verifier.verify(host, cert); + } catch (SSLException e) { + String cn = getCN(cert); + + JLabel mismatch = new JLabel(Constant.messages.getString("srm.ssl.mismatch") + " "); + mismatch.setFont(bold); + gbc.gridx = 0; + gbc.gridy += 1; + message.add(mismatch, gbc); + + String msg; + if (cn != null) { + msg = + String.format( + Constant.messages.getString("srm.ssl.mismatchmsg"), host, cn); + } else { + msg = e.getMessage(); + } + + gbc.gridx = 1; + message.add(new JLabel(msg), gbc); + } + + // Open the dialog, and return its result + int choice = + JOptionPane.showOptionDialog( + extension.getView().getMainFrame(), + message, + dialogTitle, + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.PLAIN_MESSAGE, + null, + dialogButtons, + null); + switch (choice) { + case (0): + return CertificateAcceptance.REJECT; + case (1): + return CertificateAcceptance.ACCEPT_TEMPORARILY; + case (2): + return CertificateAcceptance.ACCEPT_PERMANENTLY; + } + } + return CertificateAcceptance.REJECT; + } + + public static byte[] getSHA1(byte[] input) { + try { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + md.reset(); + return md.digest(input); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + public static String toHexString(byte[] bytes, String sep) { + Formatter f = new Formatter(); + for (int i = 0; i < bytes.length; i++) { + f.format("%02x", bytes[i]); + if (i < bytes.length - 1) { + f.format(sep); + } + } + String result = f.toString(); + f.close(); + return result; + } + + private static String getCN(X509Certificate cert) { + String principal = cert.getSubjectX500Principal().toString(); + StringTokenizer tokenizer = new StringTokenizer(principal, ","); + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + int i = token.indexOf("CN="); + if (i >= 0) { + return token.substring(i + 3); + } + } + return null; + } +} diff --git a/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateFingerprintStrategy.java b/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateFingerprintStrategy.java new file mode 100644 index 0000000..dbe8a91 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateFingerprintStrategy.java @@ -0,0 +1,51 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm.security; + +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; + +public class InvalidCertificateFingerprintStrategy implements InvalidCertificateStrategy { + + private final String fingerprint; + private final boolean acceptPermanently; + + public InvalidCertificateFingerprintStrategy(String fingerprint, boolean acceptPermanently) { + this.fingerprint = fingerprint.replaceAll("\\s", ""); + this.acceptPermanently = acceptPermanently; + } + + @Override + public CertificateAcceptance checkAcceptance(Certificate cert, CertificateException certError) { + try { + byte[] encoded = InvalidCertificateDialogStrategy.getSHA1(cert.getEncoded()); + String obsPrint = InvalidCertificateDialogStrategy.toHexString(encoded, ""); + if (obsPrint.equalsIgnoreCase(fingerprint)) { + if (acceptPermanently) return CertificateAcceptance.ACCEPT_PERMANENTLY; + else return CertificateAcceptance.ACCEPT_TEMPORARILY; + } else { + return CertificateAcceptance.REJECT; + } + } catch (CertificateEncodingException e) { + return CertificateAcceptance.REJECT; + } + } +} diff --git a/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateStrategy.java b/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateStrategy.java new file mode 100644 index 0000000..56fc50d --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateStrategy.java @@ -0,0 +1,35 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm.security; + +import java.security.cert.Certificate; +import java.security.cert.CertificateException; + +public interface InvalidCertificateStrategy { + /** + * Determine what to do with a certificate (reject, accept temporarily, or accept permanently) + * + * @param cert A (probably invalid) certificate + * @param certError An exception (or null) that caused the certificate to be considered invalid + * @return A CertificateAcceptance value that determines whether (and for how long) the + * certificate should be considered valid. + */ + CertificateAcceptance checkAcceptance(Certificate cert, CertificateException certError); +} diff --git a/src/main/java/com/github/srm/zap/srm/security/ReloadableX509TrustManager.java b/src/main/java/com/github/srm/zap/srm/security/ReloadableX509TrustManager.java new file mode 100644 index 0000000..42c88a1 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/security/ReloadableX509TrustManager.java @@ -0,0 +1,144 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm.security; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +/** + * This X509TrustManager implementation allows invalid certificates to possibly be accepted by the + * decision of an {@link InvalidCertificateStrategy} that is passed as a constructor argument. + * Certificates added in this way will be added via a {@link ExtraCertManager}, causing the + * underlying trust manager to be reloaded. + * + *

Adapted from the implementation at "Managing a + * Dynamic Java Trust Store" (blog post) + */ +public class ReloadableX509TrustManager implements X509TrustManager { + + /* package-private */ final ExtraCertManager certManager; + private final InvalidCertificateStrategy invalidCertStrat; + private X509TrustManager tmDelegate; + + public ReloadableX509TrustManager( + ExtraCertManager certManager, InvalidCertificateStrategy invalidCertStrat) + throws IOException, GeneralSecurityException { + this.certManager = certManager; + this.invalidCertStrat = invalidCertStrat; + reloadTrustManager(); + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + tmDelegate.checkClientTrusted(chain, authType); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + try { + tmDelegate.checkServerTrusted(chain, authType); + } catch (CertificateException cx) { + + /* + * At this point, we have come across an apparently-invalid + * certificate. We use the `InvalidCertificateStrategy` to decide + * what to do about it; either reject it (rethrow the exception), or + * accept it. If accepting, the certificate can be added + * "temporarily" or "permanently", which is done via the + * `ExtraCertManager`. + */ + Certificate cert = chain[0]; + CertificateAcceptance certAcceptance = invalidCertStrat.checkAcceptance(cert, cx); + + switch (certAcceptance) { + case REJECT: + throw cx; + + case ACCEPT_TEMPORARILY: + try { + certManager.addTemporaryCert(cert); + reloadTrustManager(); + } catch (IOException | GeneralSecurityException e) { + // wrap errors from the cert manipulation + throw new CertificateException( + "Error handling temporary acceptance of the certificate", e); + } + // now retry the trust check + tmDelegate.checkServerTrusted(chain, authType); + break; + + case ACCEPT_PERMANENTLY: + try { + certManager.addPermanentCert(cert); + reloadTrustManager(); + } catch (IOException | GeneralSecurityException e) { + // wrap errors from the cert manipulation + throw new CertificateException( + "Error handling permanent acceptance of the certificate", e); + } + // now retry the trust check + tmDelegate.checkServerTrusted(chain, authType); + break; + + default: + throw cx; + } + } + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return tmDelegate.getAcceptedIssuers(); + } + + /* package-private */ + final void reloadTrustManager() throws IOException, GeneralSecurityException { + KeyStore ks = certManager.asKeyStore(); + + // initialize a new TMF with the KeyStore we just created + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + + // acquire an X509 trust manager from the TMF + // and update the `tmDelegate` to that value + TrustManager[] tms = tmf.getTrustManagers(); + for (TrustManager tm : tms) { + if (tm instanceof X509TrustManager) { + tmDelegate = (X509TrustManager) tm; + return; + } + } + + // should have returned in the `for` loop above + throw new NoSuchAlgorithmException("No X509TrustManager in TrustManagerFactory"); + } +} diff --git a/src/main/java/com/github/srm/zap/srm/security/SSLConnectionSocketFactoryFactory.java b/src/main/java/com/github/srm/zap/srm/security/SSLConnectionSocketFactoryFactory.java new file mode 100644 index 0000000..ed7d233 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/security/SSLConnectionSocketFactoryFactory.java @@ -0,0 +1,226 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm.security; + +import com.github.srm.zap.srm.SrmExtension; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; + +public class SSLConnectionSocketFactoryFactory { + + private static Map dialogFactoriesByHost = new HashMap<>(); + private static Map fingerprintFactoriesByHost = + new HashMap<>(); + + /** + * Returns a SSLConnectionSocketFactory for the given host. When a SSL connection is created + * with the returned socket factory, if the server's certificate appears to be invalid, the user + * will be prompted to either reject temporarily accept, or permanently accept the certificate. + * Permanently accepted certificates will be stored in a .truststore file so the + * user won't need to prompted again for the same host. + * + * @param host The host (URL component) that the socket factory will be used to connect to + * @param extension + * @return A socket factory for the given host + * @throws IOException + * @throws GeneralSecurityException + */ + public static SSLConnectionSocketFactory getFactory(String host, SrmExtension extension) + throws IOException, GeneralSecurityException { + + SSLConnectionSocketFactory instance = dialogFactoriesByHost.get(host); + if (instance == null) { + initializeFactory(host, extension, null, false); + return dialogFactoriesByHost.get(host); + } else { + return instance; + } + } + + /** + * Returns a SSLConnectionSocketFactory for the given host. When a SSL connection is created + * with the returned socket factory, if the server's certificate appears to be invalid, the user + * will be prompted to either reject temporarily accept, or permanently accept the certificate. + * Permanently accepted certificates will be stored in a .truststore file so the + * user won't need to prompted again for the same host. + * + * @param host The host (URL component) that the socket factory will be used to connect to + * @param extension + * @param fingerprint Expected SHA1 fingerprint of an invalid certificate + * @param acceptPermanently + * @return A socket factory for the given host + * @throws IOException + * @throws GeneralSecurityException + */ + public static SSLConnectionSocketFactory getFactory( + String host, SrmExtension extension, String fingerprint, boolean acceptPermanently) + throws IOException, GeneralSecurityException { + SSLConnectionSocketFactory instance = fingerprintFactoriesByHost.get(host); + if (instance == null) { + initializeFactory(host, extension, fingerprint, acceptPermanently); + return fingerprintFactoriesByHost.get(host); + } else { + return instance; + } + } + + /** + * Determines the location for the truststore file for the given host. Each {@link + * SSLConnectionSocketFactory} returned by {@link #initializeFactory(String, SrmExtension, + * String, boolean)} needs to have a file to store user-accepted invalid certificates; these + * files will be stored in the user's OS-appropriate "appdata" directory. + * + * @param host A URL hostname, e.g. "www.google.com" + * @return The file where the trust store for the given host should be stored + */ + private static File getTrustStoreForHost(String host) { + String OS = System.getProperty("os.name").toUpperCase(); + Path env; + if (OS.contains("WIN")) { + env = Paths.get(System.getenv("APPDATA"), "Software Risk Manager", "ZAP"); + } else if (OS.contains("MAC")) { + env = + Paths.get( + System.getProperty("user.home"), + "Library", + "Application Support", + "Software Risk Manager", + "ZAP"); + } else if (OS.contains("NUX")) { + env = Paths.get(System.getProperty("user.home"), ".srm", "zap"); + } else { + env = Paths.get(System.getProperty("user.dir"), "srm", "zap"); + } + + File keystoreDir = new File(env.toFile(), ".usertrust"); + keystoreDir.mkdirs(); + + // Host may only contain alphanumerics, dash, and dot. + // Replace anything else with an underscore. + String safeHost = host.replaceAll("[^a-zA-Z0-9\\-\\.]", "_"); + + // /.usertrust/.truststore + return new File(keystoreDir, safeHost + ".truststore"); + } + + /** + * Creates a new SSLConnectionSocketFactory with the behavior described in + * {@link #getFactory(String, SrmExtension)}. Instead of returning, this + * method registers the factory instance to the factoriesByHost + * map, as well as registering its ExtraCertManager to the + * certManagersByHost map. The cert manager registration is + * important in order to detect and purge trusted certificates on a per-host + * basis. + * + * @param host + * @param extension + * @throws IOException + * @throws GeneralSecurityException + */ + private static void initializeFactory( + String host, SrmExtension extension, String fingerprint, boolean acceptPermanently) + throws IOException, GeneralSecurityException { + // set up the certificate management + File managedKeyStoreFile = getTrustStoreForHost(host); + ExtraCertManager certManager = + new SingleExtraCertManager(managedKeyStoreFile, "u9lwIfUpaN"); + + // get the default hostname verifier that gets used by the modified one + // and the invalid cert dialog + HostnameVerifier defaultHostnameVerifier = new DefaultHostnameVerifier(); + + InvalidCertificateStrategy invalidCertStrat; + if (fingerprint == null) { + invalidCertStrat = + new InvalidCertificateDialogStrategy(defaultHostnameVerifier, host, extension); + } else { + invalidCertStrat = + new InvalidCertificateFingerprintStrategy(fingerprint, acceptPermanently); + } + + /* + * Set up a composite trust manager that uses the default trust manager + * before delegating to the "reloadable" trust manager that allows users + * to accept invalid certificates. + */ + List trustManagersForComposite = new LinkedList<>(); + X509TrustManager systemTrustManager = getDefaultTrustManager(); + ReloadableX509TrustManager customTrustManager = + new ReloadableX509TrustManager(certManager, invalidCertStrat); + trustManagersForComposite.add(systemTrustManager); + trustManagersForComposite.add(customTrustManager); + X509TrustManager trustManager = new CompositeX509TrustManager(trustManagersForComposite); + + // setup the SSLContext using the custom trust manager + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, new TrustManager[] {trustManager}, null); + // the actual hostname verifier that will be used with the socket + // factory + Set allowedHosts = new HashSet<>(); + allowedHosts.add(host); + HostnameVerifier modifiedHostnameVerifier = + new HostnameVerifierWithExceptions(defaultHostnameVerifier, allowedHosts); + + SSLConnectionSocketFactory factory = + new SSLConnectionSocketFactory(sslContext, modifiedHostnameVerifier); + // Register the `factory` and the `customTrustManager` under the given + // `host` + if (fingerprint == null) { + dialogFactoriesByHost.put(host, factory); + } else { + fingerprintFactoriesByHost.put(host, factory); + } + } + + private static X509TrustManager getDefaultTrustManager() + throws NoSuchAlgorithmException, KeyStoreException { + TrustManagerFactory defaultFactory = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + defaultFactory.init((KeyStore) null); + + TrustManager[] managers = defaultFactory.getTrustManagers(); + for (TrustManager mgr : managers) { + if (mgr instanceof X509TrustManager) { + return (X509TrustManager) mgr; + } + } + + return null; + } +} diff --git a/src/main/java/com/github/srm/zap/srm/security/SingleExtraCertManager.java b/src/main/java/com/github/srm/zap/srm/security/SingleExtraCertManager.java new file mode 100644 index 0000000..153f0c3 --- /dev/null +++ b/src/main/java/com/github/srm/zap/srm/security/SingleExtraCertManager.java @@ -0,0 +1,128 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.srm.zap.srm.security; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.Certificate; + +/** + * ExtraCertManager implementation that only allows a single accepted certificate at once. Any time + * a certificate is added (be it temporarily or permanently), any previous certificates will be + * forgotten. At any given time, the {@link #asKeyStore()} method should return a KeyStore with 0 or + * 1 certificates registered. + */ +public class SingleExtraCertManager implements ExtraCertManager { + + private final File keystoreFile; + private final char[] password; + private boolean isUsingFile; + private Certificate tempCert = null; + + public SingleExtraCertManager(File keystoreFile, String password) { + this.keystoreFile = keystoreFile; + this.password = password.toCharArray(); + isUsingFile = true; + } + + @Override + public void addTemporaryCert(Certificate cert) { + if (isUsingFile) { + keystoreFile.delete(); + } + isUsingFile = false; + tempCert = cert; + } + + @Override + public void addPermanentCert(Certificate cert) throws IOException, GeneralSecurityException { + tempCert = null; + isUsingFile = true; + + // create a keystore and put the cert in it + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(null, password); + ks.setCertificateEntry("default", cert); + + // store the new keystore to the keystoreFile + FileOutputStream out = new FileOutputStream(keystoreFile); + try { + ks.store(out, password); + } finally { + out.close(); + } + } + + @Override + public void purgeTemporaryCerts() { + isUsingFile = true; + tempCert = null; + } + + @Override + public void purgePermanentCerts() { + if (isUsingFile) { + // keep the flag, but delete the file + keystoreFile.delete(); + } + } + + @Override + public void purgeAllCerts() { + isUsingFile = true; + tempCert = null; + keystoreFile.delete(); + } + + @Override + public KeyStore asKeyStore() throws IOException, GeneralSecurityException { + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + + if (isUsingFile) { + // load from the file, as long as it exists + if (keystoreFile.canRead()) { + FileInputStream in = new FileInputStream(keystoreFile); + try { + ks.load(in, password); + } finally { + in.close(); + } + } else { + ks.load(null, password); + } + } else { + ks.load(null, password); + // insert the tempCert to the keystore + if (tempCert != null) { + ks.setCertificateEntry("default", tempCert); + } + } + + if (ks.aliases().hasMoreElements()) { + return ks; + } else { + return null; + } + } +} diff --git a/src/main/java/com/github/youruser/zap/javaexample/ExampleFileActiveScanRule.java b/src/main/java/com/github/youruser/zap/javaexample/ExampleFileActiveScanRule.java deleted file mode 100644 index 9c28b14..0000000 --- a/src/main/java/com/github/youruser/zap/javaexample/ExampleFileActiveScanRule.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2014 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.youruser.zap.javaexample; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.parosproxy.paros.Constant; -import org.parosproxy.paros.core.scanner.AbstractAppParamPlugin; -import org.parosproxy.paros.core.scanner.Alert; -import org.parosproxy.paros.core.scanner.Category; -import org.parosproxy.paros.core.scanner.Plugin; -import org.parosproxy.paros.network.HttpBody; -import org.parosproxy.paros.network.HttpMessage; -import org.zaproxy.zap.model.Tech; -import org.zaproxy.zap.model.TechSet; - -/** - * An example active scan rule, for more details see - * https://www.zaproxy.org/blog/2014-04-30-hacking-zap-4-active-scan-rules/ - * - * @author psiinon - */ -public class ExampleFileActiveScanRule extends AbstractAppParamPlugin { - - /** Prefix for internationalized messages used by this rule */ - private static final String MESSAGE_PREFIX = "javaexample.active.examplefile."; - - private static final String exampleAscanFile = "txt/example-ascan-file.txt"; - private List strings = null; - private static final Logger LOGGER = LogManager.getLogger(ExampleFileActiveScanRule.class); - - @Override - public int getId() { - /* - * This should be unique across all active and passive rules. - * The master list is https://github.com/zaproxy/zaproxy/blob/main/docs/scanners.md - */ - return 60101; - } - - @Override - public String getName() { - return Constant.messages.getString(MESSAGE_PREFIX + "name"); - } - - @Override - public boolean targets( - TechSet technologies) { // This method allows the programmer or user to restrict when a - // scanner is run based on the technologies selected. For example, to restrict the scanner - // to run just when - // C language is selected - return technologies.includes(Tech.C); - } - - @Override - public String getDescription() { - return Constant.messages.getString(MESSAGE_PREFIX + "desc"); - } - - private static String getOtherInfo() { - return Constant.messages.getString(MESSAGE_PREFIX + "other"); - } - - @Override - public String getSolution() { - return Constant.messages.getString(MESSAGE_PREFIX + "soln"); - } - - @Override - public String getReference() { - return Constant.messages.getString(MESSAGE_PREFIX + "refs"); - } - - @Override - public int getCategory() { - return Category.MISC; - } - - /* - * This method is called by the active scanner for each GET and POST parameter for every page - * @see org.parosproxy.paros.core.scanner.AbstractAppParamPlugin#scan(org.parosproxy.paros.network.HttpMessage, java.lang.String, java.lang.String) - */ - @Override - public void scan(HttpMessage msg, String param, String value) { - try { - if (!Constant.isDevBuild()) { - // Only run this example scan rule in dev mode - // Uncomment locally if you want to see these alerts in non dev mode ;) - return; - } - - if (this.strings == null) { - this.strings = loadFile(exampleAscanFile); - } - // This is where you change the 'good' request to attack the application - // You can make multiple requests if needed - int numAttacks = 0; - - switch (this.getAttackStrength()) { - case LOW: - numAttacks = 6; - break; - case MEDIUM: - numAttacks = 12; - break; - case HIGH: - numAttacks = 24; - break; - case INSANE: - numAttacks = 96; - break; - default: - break; - } - - for (int i = 0; i < numAttacks; i++) { - if (this.isStop()) { - // User has stopped the scan - break; - } - if (i >= this.strings.size()) { - // run out of attack strings - break; - } - String attack = this.strings.get(i); - // Always use getNewMsg() for each new request - HttpMessage testMsg = getNewMsg(); - setParameter(testMsg, param, attack); - sendAndReceive(testMsg); - - // This is where you detect potential vulnerabilities in the response - String evidence; - if ((evidence = doesResponseContainString(msg.getResponseBody(), attack)) != null) { - // Raise an alert - createAlert(param, attack, evidence).setMessage(testMsg).raise(); - return; - } - } - - } catch (IOException e) { - LOGGER.error(e.getMessage(), e); - } - } - - private String doesResponseContainString(HttpBody body, String str) { - String sBody; - if (Plugin.AlertThreshold.HIGH.equals(this.getAlertThreshold())) { - // For a high threshold perform a case exact check - sBody = body.toString(); - } else { - // For all other thresholds perform a case ignore check - sBody = body.toString().toLowerCase(); - } - - if (!Plugin.AlertThreshold.HIGH.equals(this.getAlertThreshold())) { - // Use case ignore unless a high threshold has been specified - str = str.toLowerCase(); - } - int start = sBody.indexOf(str); - if (start >= 0) { - // Return the original (case exact) string so we can match it in the response - return body.toString().substring(start, start + str.length()); - } - return null; - } - - private AlertBuilder createAlert(String param, String attack, String evidence) { - return newAlert() - .setConfidence(Alert.CONFIDENCE_MEDIUM) - .setParam(param) - .setAttack(attack) - .setOtherInfo(getOtherInfo()) - .setEvidence(evidence); - } - - private static List loadFile(String file) { - /* - * ZAP will have already extracted the file from the add-on and put it underneath the 'ZAP home' directory - */ - List strings = new ArrayList<>(); - BufferedReader reader = null; - File f = new File(Constant.getZapHome() + File.separator + file); - if (!f.exists()) { - LOGGER.error("No such file: {}", f.getAbsolutePath()); - return strings; - } - try { - String line; - reader = new BufferedReader(new FileReader(f)); - while ((line = reader.readLine()) != null) { - if (!line.startsWith("#") && line.length() > 0) { - strings.add(line); - } - } - } catch (IOException e) { - LOGGER.error( - "Error on opening/reading example error file. Error: {}", e.getMessage(), e); - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - LOGGER.debug("Error on closing the file reader. Error: {}", e.getMessage(), e); - } - } - } - return strings; - } - - @Override - public int getRisk() { - return Alert.RISK_HIGH; - } - - @Override - public int getCweId() { - // The CWE id - return 0; - } - - @Override - public int getWascId() { - // The WASC ID - return 0; - } - - @Override - public List getExampleAlerts() { - return List.of(createAlert("foo", " -'';!--"=&{()} - - - - - - - -SRC= - - - - - - - - -'"--> - - +ADw-SCRIPT+AD4-alert('XSS');+ADw-/SCRIPT+AD4- - - - - -PT SRC="http://ha.ckers.org/xss.js"> From 5a1843eb0f5b0f4cf8fcbb37bf8de3ec3b47d29c Mon Sep 17 00:00:00 2001 From: splahoti12 Date: Mon, 24 Nov 2025 14:53:45 +0530 Subject: [PATCH 02/11] Wrap the this refernce into a method --- src/main/java/com/github/srm/zap/srm/SrmAPI.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/github/srm/zap/srm/SrmAPI.java b/src/main/java/com/github/srm/zap/srm/SrmAPI.java index 6536f06..1a65c6a 100644 --- a/src/main/java/com/github/srm/zap/srm/SrmAPI.java +++ b/src/main/java/com/github/srm/zap/srm/SrmAPI.java @@ -57,6 +57,10 @@ public class SrmAPI extends ApiImplementor { public SrmAPI(SrmExtension extension) { this.extension = extension; + initApiViewsAndActions(); + } + + private static void initApiViewsAndActions() { this.addApiView(new ApiView(VIEW_GENERATE)); String[] optionalParams = new String[] {ACTION_PARAM_FINGERPRINT, ACTION_PARAM_ACCEPT_PERM}; From c74444e616a82f52052400a5cb1f2c7365286f7a Mon Sep 17 00:00:00 2001 From: splahoti12 Date: Mon, 24 Nov 2025 14:57:07 +0530 Subject: [PATCH 03/11] fix the this reference issue --- src/main/java/com/github/srm/zap/srm/SrmAPI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/srm/zap/srm/SrmAPI.java b/src/main/java/com/github/srm/zap/srm/SrmAPI.java index 1a65c6a..8c52117 100644 --- a/src/main/java/com/github/srm/zap/srm/SrmAPI.java +++ b/src/main/java/com/github/srm/zap/srm/SrmAPI.java @@ -60,7 +60,7 @@ public SrmAPI(SrmExtension extension) { initApiViewsAndActions(); } - private static void initApiViewsAndActions() { + private void initApiViewsAndActions() { this.addApiView(new ApiView(VIEW_GENERATE)); String[] optionalParams = new String[] {ACTION_PARAM_FINGERPRINT, ACTION_PARAM_ACCEPT_PERM}; From 11e4cdac42674c3448cc03cb61eb22eb701db57f Mon Sep 17 00:00:00 2001 From: splahoti12 Date: Tue, 25 Nov 2025 22:34:37 +0530 Subject: [PATCH 04/11] Refactor the directory and Updated the Readme file also --- README.md | 25 +- settings.gradle.kts | 12 +- .../blackduck/zap/srm/ExtensionAlertHttp.java | 106 +++++ .../blackduck/zap/srm/ReportGenerator.java | 359 +++++++++++++++++ .../com/blackduck/zap/srm/ReportLastScan.java | 328 +++++++++++++++ .../zap/srm/ReportLastScanHttp.java | 13 +- .../java/com/blackduck/zap/srm/SrmAPI.java | 172 ++++++++ .../com/blackduck/zap/srm/SrmExtension.java | 190 +++++++++ .../com/blackduck/zap/srm/SrmProperties.java | 162 ++++++++ .../zap/srm/UploadActionListener.java | 225 +++++++++++ .../zap/srm/UploadPropertiesDialog.java | 369 +++++++++++++++++ .../srm/security/CertificateAcceptance.java | 32 +- .../security/CompositeX509TrustManager.java | 98 +++++ .../zap/srm/security/ExtraCertManager.java | 70 ++++ .../HostnameVerifierWithExceptions.java | 26 +- .../InvalidCertificateDialogStrategy.java | 186 +++++++++ ...InvalidCertificateFingerprintStrategy.java | 51 +++ .../security/InvalidCertificateStrategy.java | 20 +- .../security/ReloadableX509TrustManager.java | 144 +++++++ .../SSLConnectionSocketFactoryFactory.java | 218 ++++++++++ .../srm/security/SingleExtraCertManager.java | 128 ++++++ .../srm/zap/srm/ExtensionAlertHttp.java | 104 ----- .../github/srm/zap/srm/ReportGenerator.java | 365 ----------------- .../github/srm/zap/srm/ReportLastScan.java | 326 --------------- .../java/com/github/srm/zap/srm/SrmAPI.java | 178 -------- .../com/github/srm/zap/srm/SrmExtension.java | 191 --------- .../com/github/srm/zap/srm/SrmProperties.java | 163 -------- .../srm/zap/srm/UploadActionListener.java | 224 ----------- .../srm/zap/srm/UploadPropertiesDialog.java | 380 ------------------ .../security/CompositeX509TrustManager.java | 99 ----- .../zap/srm/security/ExtraCertManager.java | 66 --- .../InvalidCertificateDialogStrategy.java | 192 --------- ...InvalidCertificateFingerprintStrategy.java | 51 --- .../security/ReloadableX509TrustManager.java | 144 ------- .../SSLConnectionSocketFactoryFactory.java | 226 ----------- .../srm/security/SingleExtraCertManager.java | 128 ------ .../resources/help/contents/images/srm.png | Bin .../zap/srm/resources/help/contents/srm.html | 0 .../zap/srm/resources/help/helpset.hs | 0 .../zap/srm/resources/help/index.xml | 0 .../zap/srm/resources/help/map.jhm | 0 .../zap/srm/resources/help/toc.xml | 0 .../help_ar_SA/contents/images/srm.png | Bin .../resources/help_ar_SA/contents/srm.html | 0 .../srm/resources/help_ar_SA/helpset_ar_SA.hs | 0 .../zap/srm/resources/help_ar_SA/index.xml | 0 .../zap/srm/resources/help_ar_SA/map.jhm | 0 .../zap/srm/resources/help_ar_SA/toc.xml | 0 .../help_az_AZ/contents/images/srm.png | Bin .../resources/help_az_AZ/contents/srm.html | 0 .../srm/resources/help_az_AZ/helpset_az_AZ.hs | 0 .../zap/srm/resources/help_az_AZ/index.xml | 0 .../zap/srm/resources/help_az_AZ/map.jhm | 0 .../zap/srm/resources/help_az_AZ/toc.xml | 0 .../help_bs_BA/contents/images/srm.png | Bin .../resources/help_bs_BA/contents/srm.html | 0 .../srm/resources/help_bs_BA/helpset_bs_BA.hs | 0 .../zap/srm/resources/help_bs_BA/index.xml | 0 .../zap/srm/resources/help_bs_BA/map.jhm | 0 .../zap/srm/resources/help_bs_BA/toc.xml | 0 .../help_da_DK/contents/images/srm.png | Bin .../resources/help_da_DK/contents/srm.html | 0 .../srm/resources/help_da_DK/helpset_da_DK.hs | 0 .../zap/srm/resources/help_da_DK/index.xml | 0 .../zap/srm/resources/help_da_DK/map.jhm | 0 .../zap/srm/resources/help_da_DK/toc.xml | 0 .../help_de_DE/contents/images/srm.png | Bin .../resources/help_de_DE/contents/srm.html | 0 .../srm/resources/help_de_DE/helpset_de_DE.hs | 0 .../zap/srm/resources/help_de_DE/index.xml | 0 .../zap/srm/resources/help_de_DE/map.jhm | 0 .../zap/srm/resources/help_de_DE/toc.xml | 0 .../help_el_GR/contents/images/srm.png | Bin .../resources/help_el_GR/contents/srm.html | 0 .../srm/resources/help_el_GR/helpset_el_GR.hs | 0 .../zap/srm/resources/help_el_GR/index.xml | 0 .../zap/srm/resources/help_el_GR/map.jhm | 0 .../zap/srm/resources/help_el_GR/toc.xml | 0 .../help_es_ES/contents/images/srm.png | Bin .../resources/help_es_ES/contents/srm.html | 0 .../srm/resources/help_es_ES/helpset_es_ES.hs | 0 .../zap/srm/resources/help_es_ES/index.xml | 0 .../zap/srm/resources/help_es_ES/map.jhm | 0 .../zap/srm/resources/help_es_ES/toc.xml | 0 .../help_fa_IR/contents/images/srm.png | Bin .../resources/help_fa_IR/contents/srm.html | 0 .../srm/resources/help_fa_IR/helpset_fa_IR.hs | 0 .../zap/srm/resources/help_fa_IR/index.xml | 0 .../zap/srm/resources/help_fa_IR/map.jhm | 0 .../zap/srm/resources/help_fa_IR/toc.xml | 0 .../help_fil_PH/contents/images/srm.png | Bin .../resources/help_fil_PH/contents/srm.html | 0 .../resources/help_fil_PH/helpset_fil_PH.hs | 0 .../zap/srm/resources/help_fil_PH/index.xml | 0 .../zap/srm/resources/help_fil_PH/map.jhm | 0 .../zap/srm/resources/help_fil_PH/toc.xml | 0 .../help_fr_FR/contents/images/srm.png | Bin .../resources/help_fr_FR/contents/srm.html | 0 .../srm/resources/help_fr_FR/helpset_fr_FR.hs | 0 .../zap/srm/resources/help_fr_FR/index.xml | 0 .../zap/srm/resources/help_fr_FR/map.jhm | 0 .../zap/srm/resources/help_fr_FR/toc.xml | 0 .../help_hi_IN/contents/images/srm.png | Bin .../resources/help_hi_IN/contents/srm.html | 0 .../srm/resources/help_hi_IN/helpset_hi_IN.hs | 0 .../zap/srm/resources/help_hi_IN/index.xml | 0 .../zap/srm/resources/help_hi_IN/map.jhm | 0 .../zap/srm/resources/help_hi_IN/toc.xml | 0 .../help_hr_HR/contents/images/srm.png | Bin .../resources/help_hr_HR/contents/srm.html | 0 .../srm/resources/help_hr_HR/helpset_hr_HR.hs | 0 .../zap/srm/resources/help_hr_HR/index.xml | 0 .../zap/srm/resources/help_hr_HR/map.jhm | 0 .../zap/srm/resources/help_hr_HR/toc.xml | 0 .../help_hu_HU/contents/images/srm.png | Bin .../resources/help_hu_HU/contents/srm.html | 0 .../srm/resources/help_hu_HU/helpset_hu_HU.hs | 0 .../zap/srm/resources/help_hu_HU/index.xml | 0 .../zap/srm/resources/help_hu_HU/map.jhm | 0 .../zap/srm/resources/help_hu_HU/toc.xml | 0 .../help_id_ID/contents/images/srm.png | Bin .../resources/help_id_ID/contents/srm.html | 0 .../srm/resources/help_id_ID/helpset_id_ID.hs | 0 .../zap/srm/resources/help_id_ID/index.xml | 0 .../zap/srm/resources/help_id_ID/map.jhm | 0 .../zap/srm/resources/help_id_ID/toc.xml | 0 .../help_it_IT/contents/images/srm.png | Bin .../resources/help_it_IT/contents/srm.html | 0 .../srm/resources/help_it_IT/helpset_it_IT.hs | 0 .../zap/srm/resources/help_it_IT/index.xml | 0 .../zap/srm/resources/help_it_IT/map.jhm | 0 .../zap/srm/resources/help_it_IT/toc.xml | 0 .../help_ja_JP/contents/images/srm.png | Bin .../resources/help_ja_JP/contents/srm.html | 0 .../srm/resources/help_ja_JP/helpset_ja_JP.hs | 0 .../zap/srm/resources/help_ja_JP/index.xml | 0 .../zap/srm/resources/help_ja_JP/map.jhm | 0 .../zap/srm/resources/help_ja_JP/toc.xml | 0 .../help_ko_KR/contents/images/srm.png | Bin .../resources/help_ko_KR/contents/srm.html | 0 .../srm/resources/help_ko_KR/helpset_ko_KR.hs | 0 .../zap/srm/resources/help_ko_KR/index.xml | 0 .../zap/srm/resources/help_ko_KR/map.jhm | 0 .../zap/srm/resources/help_ko_KR/toc.xml | 0 .../help_ms_MY/contents/images/srm.png | Bin .../resources/help_ms_MY/contents/srm.html | 0 .../srm/resources/help_ms_MY/helpset_ms_MY.hs | 0 .../zap/srm/resources/help_ms_MY/index.xml | 0 .../zap/srm/resources/help_ms_MY/map.jhm | 0 .../zap/srm/resources/help_ms_MY/toc.xml | 0 .../help_pl_PL/contents/images/srm.png | Bin .../resources/help_pl_PL/contents/srm.html | 0 .../srm/resources/help_pl_PL/helpset_pl_PL.hs | 0 .../zap/srm/resources/help_pl_PL/index.xml | 0 .../zap/srm/resources/help_pl_PL/map.jhm | 0 .../zap/srm/resources/help_pl_PL/toc.xml | 0 .../help_pt_BR/contents/images/srm.png | Bin .../resources/help_pt_BR/contents/srm.html | 0 .../srm/resources/help_pt_BR/helpset_pt_BR.hs | 0 .../zap/srm/resources/help_pt_BR/index.xml | 0 .../zap/srm/resources/help_pt_BR/map.jhm | 0 .../zap/srm/resources/help_pt_BR/toc.xml | 0 .../help_ro_RO/contents/images/srm.png | Bin .../resources/help_ro_RO/contents/srm.html | 0 .../srm/resources/help_ro_RO/helpset_ro_RO.hs | 0 .../zap/srm/resources/help_ro_RO/index.xml | 0 .../zap/srm/resources/help_ro_RO/map.jhm | 0 .../zap/srm/resources/help_ro_RO/toc.xml | 0 .../help_ru_RU/contents/images/srm.png | Bin .../resources/help_ru_RU/contents/srm.html | 0 .../srm/resources/help_ru_RU/helpset_ru_RU.hs | 0 .../zap/srm/resources/help_ru_RU/index.xml | 0 .../zap/srm/resources/help_ru_RU/map.jhm | 0 .../zap/srm/resources/help_ru_RU/toc.xml | 0 .../help_si_LK/contents/images/srm.png | Bin .../resources/help_si_LK/contents/srm.html | 0 .../srm/resources/help_si_LK/helpset_si_LK.hs | 0 .../zap/srm/resources/help_si_LK/index.xml | 0 .../zap/srm/resources/help_si_LK/map.jhm | 0 .../zap/srm/resources/help_si_LK/toc.xml | 0 .../help_sk_SK/contents/images/srm.png | Bin .../resources/help_sk_SK/contents/srm.html | 0 .../srm/resources/help_sk_SK/helpset_sk_SK.hs | 0 .../zap/srm/resources/help_sk_SK/index.xml | 0 .../zap/srm/resources/help_sk_SK/map.jhm | 0 .../zap/srm/resources/help_sk_SK/toc.xml | 0 .../help_sl_SI/contents/images/srm.png | Bin .../resources/help_sl_SI/contents/srm.html | 0 .../srm/resources/help_sl_SI/helpset_sl_SI.hs | 0 .../zap/srm/resources/help_sl_SI/index.xml | 0 .../zap/srm/resources/help_sl_SI/map.jhm | 0 .../zap/srm/resources/help_sl_SI/toc.xml | 0 .../help_sq_AL/contents/images/srm.png | Bin .../resources/help_sq_AL/contents/srm.html | 0 .../srm/resources/help_sq_AL/helpset_sq_AL.hs | 0 .../zap/srm/resources/help_sq_AL/index.xml | 0 .../zap/srm/resources/help_sq_AL/map.jhm | 0 .../zap/srm/resources/help_sq_AL/toc.xml | 0 .../help_sr_CS/contents/images/srm.png | Bin .../resources/help_sr_CS/contents/srm.html | 0 .../srm/resources/help_sr_CS/helpset_sr_CS.hs | 0 .../zap/srm/resources/help_sr_CS/index.xml | 0 .../zap/srm/resources/help_sr_CS/map.jhm | 0 .../zap/srm/resources/help_sr_CS/toc.xml | 0 .../help_sr_SP/contents/images/srm.png | Bin .../resources/help_sr_SP/contents/srm.html | 0 .../srm/resources/help_sr_SP/helpset_sr_SP.hs | 0 .../zap/srm/resources/help_sr_SP/index.xml | 0 .../zap/srm/resources/help_sr_SP/map.jhm | 0 .../zap/srm/resources/help_sr_SP/toc.xml | 0 .../help_tr_TR/contents/images/srm.png | Bin .../resources/help_tr_TR/contents/srm.html | 0 .../srm/resources/help_tr_TR/helpset_tr_TR.hs | 0 .../zap/srm/resources/help_tr_TR/index.xml | 0 .../zap/srm/resources/help_tr_TR/map.jhm | 0 .../zap/srm/resources/help_tr_TR/toc.xml | 0 .../help_ur_PK/contents/images/srm.png | Bin .../resources/help_ur_PK/contents/srm.html | 0 .../srm/resources/help_ur_PK/helpset_ur_PK.hs | 0 .../zap/srm/resources/help_ur_PK/index.xml | 0 .../zap/srm/resources/help_ur_PK/map.jhm | 0 .../zap/srm/resources/help_ur_PK/toc.xml | 0 .../help_zh_CN/contents/images/srm.png | Bin .../resources/help_zh_CN/contents/srm.html | 0 .../srm/resources/help_zh_CN/helpset_zh_CN.hs | 0 .../zap/srm/resources/help_zh_CN/index.xml | 0 .../zap/srm/resources/help_zh_CN/map.jhm | 0 .../zap/srm/resources/help_zh_CN/toc.xml | 0 .../zap/srm/resources/Messages.properties | 0 .../srm/resources/Messages_ar_SA.properties | 0 .../srm/resources/Messages_az_AZ.properties | 0 .../srm/resources/Messages_bn_BD.properties | 0 .../srm/resources/Messages_bs_BA.properties | 0 .../srm/resources/Messages_ceb_PH.properties | 0 .../srm/resources/Messages_da_DK.properties | 0 .../srm/resources/Messages_de_DE.properties | 0 .../srm/resources/Messages_el_GR.properties | 0 .../srm/resources/Messages_es_ES.properties | 0 .../srm/resources/Messages_fa_IR.properties | 0 .../srm/resources/Messages_fil_PH.properties | 0 .../srm/resources/Messages_fr_FR.properties | 0 .../srm/resources/Messages_ha_HG.properties | 0 .../srm/resources/Messages_he_IL.properties | 0 .../srm/resources/Messages_hi_IN.properties | 0 .../srm/resources/Messages_hr_HR.properties | 0 .../srm/resources/Messages_hu_HU.properties | 0 .../srm/resources/Messages_id_ID.properties | 0 .../srm/resources/Messages_it_IT.properties | 0 .../srm/resources/Messages_ja_JP.properties | 0 .../srm/resources/Messages_ko_KR.properties | 0 .../srm/resources/Messages_mk_MK.properties | 0 .../srm/resources/Messages_ms_MY.properties | 0 .../srm/resources/Messages_nb_NO.properties | 0 .../srm/resources/Messages_nl_NL.properties | 0 .../srm/resources/Messages_pcm_NG.properties | 0 .../srm/resources/Messages_pl_PL.properties | 0 .../srm/resources/Messages_pt_BR.properties | 0 .../srm/resources/Messages_pt_PT.properties | 0 .../srm/resources/Messages_ro_RO.properties | 0 .../srm/resources/Messages_ru_RU.properties | 0 .../srm/resources/Messages_si_LK.properties | 0 .../srm/resources/Messages_sk_SK.properties | 0 .../srm/resources/Messages_sl_SI.properties | 0 .../srm/resources/Messages_sq_AL.properties | 0 .../srm/resources/Messages_sr_CS.properties | 0 .../srm/resources/Messages_sr_SP.properties | 0 .../srm/resources/Messages_tr_TR.properties | 0 .../srm/resources/Messages_uk_UA.properties | 0 .../srm/resources/Messages_ur_PK.properties | 0 .../srm/resources/Messages_vi_VN.properties | 0 .../srm/resources/Messages_yo_NG.properties | 0 .../srm/resources/Messages_zh_CN.properties | 0 .../srm/resources/Messages_zh_TW.properties | 0 .../zap/srm/resources/refresh.png | Bin 274 files changed, 2870 insertions(+), 2901 deletions(-) create mode 100644 src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java create mode 100644 src/main/java/com/blackduck/zap/srm/ReportGenerator.java create mode 100644 src/main/java/com/blackduck/zap/srm/ReportLastScan.java rename src/main/java/com/{github/srm => blackduck}/zap/srm/ReportLastScanHttp.java (79%) create mode 100644 src/main/java/com/blackduck/zap/srm/SrmAPI.java create mode 100644 src/main/java/com/blackduck/zap/srm/SrmExtension.java create mode 100644 src/main/java/com/blackduck/zap/srm/SrmProperties.java create mode 100644 src/main/java/com/blackduck/zap/srm/UploadActionListener.java create mode 100644 src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java rename src/main/java/com/{github/srm => blackduck}/zap/srm/security/CertificateAcceptance.java (58%) create mode 100644 src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java create mode 100644 src/main/java/com/blackduck/zap/srm/security/ExtraCertManager.java rename src/main/java/com/{github/srm => blackduck}/zap/srm/security/HostnameVerifierWithExceptions.java (68%) create mode 100644 src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java create mode 100644 src/main/java/com/blackduck/zap/srm/security/InvalidCertificateFingerprintStrategy.java rename src/main/java/com/{github/srm => blackduck}/zap/srm/security/InvalidCertificateStrategy.java (61%) create mode 100644 src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java create mode 100644 src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java create mode 100644 src/main/java/com/blackduck/zap/srm/security/SingleExtraCertManager.java delete mode 100644 src/main/java/com/github/srm/zap/srm/ExtensionAlertHttp.java delete mode 100644 src/main/java/com/github/srm/zap/srm/ReportGenerator.java delete mode 100644 src/main/java/com/github/srm/zap/srm/ReportLastScan.java delete mode 100644 src/main/java/com/github/srm/zap/srm/SrmAPI.java delete mode 100644 src/main/java/com/github/srm/zap/srm/SrmExtension.java delete mode 100644 src/main/java/com/github/srm/zap/srm/SrmProperties.java delete mode 100644 src/main/java/com/github/srm/zap/srm/UploadActionListener.java delete mode 100644 src/main/java/com/github/srm/zap/srm/UploadPropertiesDialog.java delete mode 100644 src/main/java/com/github/srm/zap/srm/security/CompositeX509TrustManager.java delete mode 100644 src/main/java/com/github/srm/zap/srm/security/ExtraCertManager.java delete mode 100644 src/main/java/com/github/srm/zap/srm/security/InvalidCertificateDialogStrategy.java delete mode 100644 src/main/java/com/github/srm/zap/srm/security/InvalidCertificateFingerprintStrategy.java delete mode 100644 src/main/java/com/github/srm/zap/srm/security/ReloadableX509TrustManager.java delete mode 100644 src/main/java/com/github/srm/zap/srm/security/SSLConnectionSocketFactoryFactory.java delete mode 100644 src/main/java/com/github/srm/zap/srm/security/SingleExtraCertManager.java rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help/helpset.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ar_SA/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ar_SA/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ar_SA/helpset_ar_SA.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ar_SA/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ar_SA/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ar_SA/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_az_AZ/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_az_AZ/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_az_AZ/helpset_az_AZ.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_az_AZ/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_az_AZ/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_az_AZ/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_bs_BA/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_bs_BA/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_bs_BA/helpset_bs_BA.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_bs_BA/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_bs_BA/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_bs_BA/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_da_DK/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_da_DK/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_da_DK/helpset_da_DK.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_da_DK/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_da_DK/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_da_DK/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_de_DE/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_de_DE/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_de_DE/helpset_de_DE.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_de_DE/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_de_DE/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_de_DE/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_el_GR/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_el_GR/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_el_GR/helpset_el_GR.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_el_GR/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_el_GR/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_el_GR/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_es_ES/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_es_ES/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_es_ES/helpset_es_ES.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_es_ES/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_es_ES/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_es_ES/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fa_IR/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fa_IR/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fa_IR/helpset_fa_IR.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fa_IR/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fa_IR/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fa_IR/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fil_PH/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fil_PH/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fil_PH/helpset_fil_PH.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fil_PH/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fil_PH/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fil_PH/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fr_FR/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fr_FR/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fr_FR/helpset_fr_FR.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fr_FR/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fr_FR/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_fr_FR/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hi_IN/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hi_IN/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hi_IN/helpset_hi_IN.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hi_IN/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hi_IN/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hi_IN/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hr_HR/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hr_HR/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hr_HR/helpset_hr_HR.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hr_HR/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hr_HR/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hr_HR/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hu_HU/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hu_HU/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hu_HU/helpset_hu_HU.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hu_HU/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hu_HU/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_hu_HU/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_id_ID/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_id_ID/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_id_ID/helpset_id_ID.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_id_ID/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_id_ID/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_id_ID/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_it_IT/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_it_IT/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_it_IT/helpset_it_IT.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_it_IT/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_it_IT/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_it_IT/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ja_JP/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ja_JP/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ja_JP/helpset_ja_JP.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ja_JP/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ja_JP/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ja_JP/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ko_KR/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ko_KR/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ko_KR/helpset_ko_KR.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ko_KR/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ko_KR/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ko_KR/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ms_MY/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ms_MY/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ms_MY/helpset_ms_MY.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ms_MY/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ms_MY/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ms_MY/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pl_PL/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pl_PL/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pl_PL/helpset_pl_PL.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pl_PL/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pl_PL/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pl_PL/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pt_BR/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pt_BR/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pt_BR/helpset_pt_BR.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pt_BR/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pt_BR/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_pt_BR/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ro_RO/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ro_RO/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ro_RO/helpset_ro_RO.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ro_RO/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ro_RO/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ro_RO/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ru_RU/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ru_RU/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ru_RU/helpset_ru_RU.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ru_RU/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ru_RU/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ru_RU/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_si_LK/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_si_LK/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_si_LK/helpset_si_LK.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_si_LK/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_si_LK/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_si_LK/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sk_SK/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sk_SK/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sk_SK/helpset_sk_SK.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sk_SK/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sk_SK/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sk_SK/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sl_SI/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sl_SI/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sl_SI/helpset_sl_SI.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sl_SI/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sl_SI/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sl_SI/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sq_AL/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sq_AL/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sq_AL/helpset_sq_AL.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sq_AL/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sq_AL/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sq_AL/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_CS/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_CS/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_CS/helpset_sr_CS.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_CS/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_CS/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_CS/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_SP/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_SP/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_SP/helpset_sr_SP.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_SP/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_SP/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_sr_SP/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_tr_TR/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_tr_TR/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_tr_TR/helpset_tr_TR.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_tr_TR/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_tr_TR/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_tr_TR/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ur_PK/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ur_PK/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ur_PK/helpset_ur_PK.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ur_PK/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ur_PK/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_ur_PK/toc.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_zh_CN/contents/images/srm.png (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_zh_CN/contents/srm.html (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_zh_CN/helpset_zh_CN.hs (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_zh_CN/index.xml (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_zh_CN/map.jhm (100%) rename src/main/javahelp/com/{github/srm => blackduck}/zap/srm/resources/help_zh_CN/toc.xml (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_ar_SA.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_az_AZ.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_bn_BD.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_bs_BA.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_ceb_PH.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_da_DK.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_de_DE.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_el_GR.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_es_ES.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_fa_IR.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_fil_PH.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_fr_FR.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_ha_HG.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_he_IL.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_hi_IN.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_hr_HR.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_hu_HU.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_id_ID.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_it_IT.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_ja_JP.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_ko_KR.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_mk_MK.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_ms_MY.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_nb_NO.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_nl_NL.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_pcm_NG.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_pl_PL.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_pt_BR.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_pt_PT.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_ro_RO.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_ru_RU.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_si_LK.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_sk_SK.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_sl_SI.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_sq_AL.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_sr_CS.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_sr_SP.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_tr_TR.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_uk_UA.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_ur_PK.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_vi_VN.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_yo_NG.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_zh_CN.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/Messages_zh_TW.properties (100%) rename src/main/resources/com/{github/srm => blackduck}/zap/srm/resources/refresh.png (100%) diff --git a/README.md b/README.md index 3093bbb..6c0fd43 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,24 @@ -# ZAP Template Java Add-on +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![CodeQL](https://github.com/zaproxy/zap-extensions/actions/workflows/codeql.yml/badge.svg)](https://github.com/zaproxy/zap-extensions/actions/workflows/codeql.yml) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=zaproxy_zap-extensions&metric=alert_status)](https://sonarcloud.io/dashboard?id=zaproxy_zap-extensions) -A template repo for a 3rd party [ZAP](https://www.zaproxy.org) Java add-on. +This project contains add-ons for the [Zed Attack Proxy](https://github.com/zaproxy/zaproxy) (ZAP). -If you'd like to create your own ZAP add-on which could be published to the [ZAP Marketplace](https://www.zaproxy.org/addons/) then copy this repo and make the following changes: +If you are using the latest version of ZAP, you can browse and download "Software Risk Manager Extension" directly from within ZAP by clicking the Marketplace button in the toolbar. +This specific add-on is Software Risk Manager (SRM), and you can find it in the Marketplace under the name “Software Risk Manager Extension”. -1. Rename the `youruser` directories to be your github name (or choose another package hierarchy which works better for you). +![Image](https://github.com/zaproxy/zap-extensions/wiki/images/zap-screenshot-browse-addons.png) -1. Change the add-on ID `addonjava` to be a new ID which is not already on the [ZAP Marketplace](https://www.zaproxy.org/addons/). +You can also import add-ons you have downloaded manually from https://github.com/zaproxy/zap-extensions/releases via the "File / Load Add-on File..." menu option. -1. Change the code and help files to do whatever you want :smiley: +Please see the [wiki](https://github.com/zaproxy/zap-extensions/wiki) for more details. -1. Deploy and test your app locally, e.g. using `./gradlew copyZapAddon` +## Building -1. Optional: Raise an [Issue](https://github.com/zaproxy/zaproxy/issues/new?assignees=&labels=marketplace&template=third-party-addon.yml) to get your add-on published on the [ZAP Marketplace](https://www.zaproxy.org/addons/). +The add-ons are built with [Gradle], each add-on has its own project which is located under the `addOns` project/directory. -For more info on developing ZAP add-ons see https://www.zaproxy.org/docs/developer/ \ No newline at end of file +To build zap-extensions follow the instructions on: + +https://www.zaproxy.org/docs/developer/quick-start-build/ + +[Gradle]: https://gradle.org/ diff --git a/settings.gradle.kts b/settings.gradle.kts index 291563b..3b30197 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,19 +5,9 @@ pluginManagement { } } -dependencyResolutionManagement { - versionCatalogs { - create("libs") { - version("log4j", "2.24.2") - library("log4j-core", "org.apache.logging.log4j", "log4j-core").versionRef("log4j") - library("log4j-slf4j", "org.apache.logging.log4j", "log4j-slf4j-impl").versionRef("log4j") - library("log4j-slf4j2", "org.apache.logging.log4j", "log4j-slf4j2-impl").versionRef("log4j") - } - } -} plugins { id("org.zaproxy.common.settings") version "0.5.0" id("com.diffplug.spotless") version "6.25.0" apply false } -rootProject.name = "addon-java" +rootProject.name = "zap-srm-addon" diff --git a/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java b/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java new file mode 100644 index 0000000..20302e7 --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java @@ -0,0 +1,106 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.core.scanner.Alert; +import org.parosproxy.paros.model.SiteNode; +import org.parosproxy.paros.network.HttpMessage; + +import java.util.List; + +public class ExtensionAlertHttp { + + private static final Logger LOGGER = LogManager.getLogger(ExtensionAlertHttp.class); + + public ExtensionAlertHttp() { + } + + public String getXml(SiteNode site) { + StringBuilder xml = new StringBuilder(); + xml.append(""); + List alerts = site.getAlerts(); + for (Alert alert : alerts) { + if (alert.getConfidence() != Alert.CONFIDENCE_FALSE_POSITIVE) { + String urlParamXML = getUrlParamXML(alert); + xml.append(alert.toPluginXML(urlParamXML)); + } + } + xml.append(""); + return xml.toString(); + } + + private String getHTML(Alert alert) { + // gets HttpMessage request and response data from each alert and removes illegal and + // special characters + StringBuilder httpMessage = new StringBuilder(); + + HttpMessage message = alert.getMessage(); + + if (message == null) { + LOGGER.warn(Constant.messages.getString("srm.error.httpMessage", alert.getAlertId())); + return httpMessage.toString(); + } + + String requestHeader = message.getRequestHeader().toString(); + String requestBody = message.getRequestBody().toString(); + String responseHeader = message.getResponseHeader().toString(); + String responseBody = message.getResponseBody().toString(); + + httpMessage.append(""); + httpMessage.append(ReportGenerator.entityEncode(requestHeader)); + httpMessage.append(ReportGenerator.entityEncode(requestBody)); + httpMessage.append("\n\n"); + httpMessage.append(""); + httpMessage.append(ReportGenerator.entityEncode(responseHeader)); + httpMessage.append(ReportGenerator.entityEncode(responseBody)); + httpMessage.append("\n\n"); + + return httpMessage.toString(); + } + + public String getUrlParamXML(Alert alert) { + + String uri = alert.getUri(); + String param = alert.getParam(); + String attack = alert.getAttack(); + String otherInfo = alert.getOtherInfo(); + String evidence = alert.getEvidence(); + + StringBuilder sb = new StringBuilder(200); // ZAP: Changed the type to StringBuilder. + sb.append(getHTML(alert)); + sb.append(" ").append(ReportGenerator.entityEncode(uri)).append("\r\n"); + sb.append(" ").append(ReportGenerator.entityEncode(param)).append("\r\n"); + sb.append(" ") + .append(ReportGenerator.entityEncode(attack)) + .append("\r\n"); + if (evidence != null && evidence.length() > 0) { + sb.append(" ") + .append(ReportGenerator.entityEncode(evidence)) + .append("\r\n"); + } + sb.append(" ") + .append(ReportGenerator.entityEncode(otherInfo)) + .append("\r\n"); + return sb.toString(); + } +} diff --git a/src/main/java/com/blackduck/zap/srm/ReportGenerator.java b/src/main/java/com/blackduck/zap/srm/ReportGenerator.java new file mode 100644 index 0000000..6171b5e --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/ReportGenerator.java @@ -0,0 +1,359 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2003-2004 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm; + +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; +import net.sf.json.xml.XMLSerializer; +import org.apache.commons.text.StringEscapeUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.view.View; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.zaproxy.zap.utils.XMLStringUtil; +import org.zaproxy.zap.utils.XmlUtils; + +import javax.swing.*; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class ReportGenerator { + + private static final Logger LOGGER = LogManager.getLogger(ReportGenerator.class); + + // private static Pattern patternWindows = Pattern.compile("window", Pattern.CASE_INSENSITIVE); + // private static Pattern patternLinux = Pattern.compile("linux", Pattern.CASE_INSENSITIVE); + + private static final SimpleDateFormat staticDateFormat = + new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss"); + + public static File XMLToHtml(Document xmlDocument, String infilexsl, File outFile) { + File stylesheet = null; + + outFile = new File(outFile.getAbsolutePath()); + try { + stylesheet = new File(infilexsl); + + DOMSource source = new DOMSource(xmlDocument); + + // Use a Transformer for output + TransformerFactory tFactory = TransformerFactory.newInstance(); + StreamSource stylesource = new StreamSource(stylesheet); + Transformer transformer = tFactory.newTransformer(stylesource); + + // Make the transformation and write to the output file + StreamResult result = new StreamResult(outFile.getPath()); + transformer.transform(source, result); + + } catch (TransformerException e) { + LOGGER.error(e.getMessage(), e); + } + + return outFile; + } + + public static File stringToHtml(String inxml, String infilexsl, String outfilename) { + return stringToHtml( + inxml, + infilexsl != null ? new StreamSource(new File(infilexsl)) : null, + outfilename); + } + + public static File stringToHtml(String inxml, StreamSource stylesource, String outfilename) { + if (stylesource != null) { + Document doc = null; + + // factory.setNamespaceAware(true); + // factory.setValidating(true); + File outfile = null; + StringReader inReader = new StringReader(inxml); + String tempOutfilename = outfilename + ".temp"; + + try { + outfile = new File(tempOutfilename); + + DocumentBuilder builder = + XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); + doc = builder.parse(new InputSource(inReader)); + + // Use a Transformer for output + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer = tFactory.newTransformer(stylesource); + transformer.setParameter("datetime", getCurrentDateTimeString()); + + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(outfile.getPath()); + transformer.transform(source, result); + + } catch (TransformerException + | SAXException + | ParserConfigurationException + | IOException e) { + LOGGER.error(e.getMessage(), e); + // Save the xml for diagnosing the problem + BufferedWriter bw = null; + showDialogForGUI(); + try { + bw = + Files.newBufferedWriter( + new File(outfilename + "-orig.xml").toPath(), + StandardCharsets.UTF_8); + bw.write(inxml); + } catch (IOException e2) { + LOGGER.error("Failed to write debug XML file", e); + return new File(outfilename); + } finally { + try { + if (bw != null) { + bw.close(); + } + } catch (IOException ex) { + } + } + return new File(outfilename); + } + // Replace the escaped tags used to make the report look slightly better. + // This is a temp fix to ensure reports always get generated + // we should really adopt something other than XSLT ;) + String line; + + try (BufferedReader br = + Files.newBufferedReader( + new File(tempOutfilename).toPath(), StandardCharsets.UTF_8); + BufferedWriter bw = + Files.newBufferedWriter( + new File(outfilename).toPath(), StandardCharsets.UTF_8)) { + + while ((line = br.readLine()) != null) { + bw.write(line.replace("<p>", "

").replace("</p>", "

")); + bw.newLine(); + } + + } catch (IOException e) { + showDialogForGUI(); + LOGGER.error(e.getMessage(), e); + } + // Remove the temporary file + outfile.delete(); + } else { + // No XSLT file specified, just output the XML straight to the file + BufferedWriter bw = null; + + try { + bw = + Files.newBufferedWriter( + new File(outfilename).toPath(), StandardCharsets.UTF_8); + bw.write(inxml); + } catch (IOException e2) { + showDialogForGUI(); + LOGGER.error(e2.getMessage(), e2); + } finally { + try { + if (bw != null) { + bw.close(); + } + } catch (IOException ex) { + } + } + } + + return new File(outfilename); + } + + public static File stringToJson(String inxml, String outfilename) { + BufferedWriter bw = null; + try { + bw = Files.newBufferedWriter(new File(outfilename).toPath(), StandardCharsets.UTF_8); + bw.write(stringToJson(inxml)); + } catch (IOException e2) { + showDialogForGUI(); + LOGGER.error(e2.getMessage(), e2); + } finally { + try { + if (bw != null) { + bw.close(); + } + } catch (IOException ex) { + } + } + + return new File(outfilename); + } + + public static String stringToHtml(String inxml, String infilexsl) { + return stringToHtml(inxml, new StreamSource(new File(infilexsl))); + } + + public static String stringToHtml(String inxml, StreamSource stylesource) { + Document doc = null; + + StringReader inReader = new StringReader(inxml); + StringWriter writer = new StringWriter(); + + try { + + DocumentBuilder builder = + XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); + doc = builder.parse(new InputSource(inReader)); + + // Use a Transformer for output + TransformerFactory tFactory = TransformerFactory.newInstance(); + Transformer transformer = tFactory.newTransformer(stylesource); + transformer.setParameter("datetime", getCurrentDateTimeString()); + + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(writer); + transformer.transform(source, result); + + } catch (TransformerException + | SAXException + | ParserConfigurationException + | IOException e) { + showDialogForGUI(); + LOGGER.error(e.getMessage(), e); + } + + // Replace the escaped tags used to make the report look slightly better. + // This is a temp fix to ensure reports always get generated + // we should really adopt something other than XSLT ;) + return writer.toString().replace("<p>", "

").replace("</p>", "

"); + } + + public static File fileToHtml(String infilexml, String infilexsl, String outfilename) { + Document doc = null; + + // factory.setNamespaceAware(true); + // factory.setValidating(true); + File stylesheet = null; + File datafile = null; + File outfile = null; + + try { + stylesheet = new File(infilexsl); + datafile = new File(infilexml); + outfile = new File(outfilename); + + DocumentBuilder builder = + XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); + doc = builder.parse(datafile); + + // Use a Transformer for output + TransformerFactory tFactory = TransformerFactory.newInstance(); + StreamSource stylesource = new StreamSource(stylesheet); + Transformer transformer = tFactory.newTransformer(stylesource); + transformer.setParameter("datetime", getCurrentDateTimeString()); + + DOMSource source = new DOMSource(doc); + StreamResult result = new StreamResult(outfile.getPath()); + transformer.transform(source, result); + + } catch (TransformerException + | SAXException + | ParserConfigurationException + | IOException e) { + showDialogForGUI(); + LOGGER.error(e.getMessage(), e); + } + + return outfile; + } + + public static String stringToJson(String inxml) { + JSONObject report = (JSONObject) new XMLSerializer().read(inxml); + Object site = report.get("site"); + if (!(site instanceof JSONArray)) { + JSONArray siteArray = new JSONArray(); + if (site != null) { + siteArray.add(site); + } + report.put("site", siteArray); + } + return report.toString(); + } + + /** + * Encode entity for HTML or XML output. + */ + public static String entityEncode(String text) { + String result = text; + + if (result == null) { + return result; + } + + // The escapeXml function doesn't cope with some 'special' chrs + + return StringEscapeUtils.escapeXml10(XMLStringUtil.escapeControlChrs(result)); + } + + /** + * Get today's date string. + */ + public static String getCurrentDateTimeString() { + Date dateTime = new Date(System.currentTimeMillis()); + return getDateTimeString(dateTime); + } + + public static String getDateTimeString(Date dateTime) { + // ZAP: fix unsafe call to DateFormats + synchronized (staticDateFormat) { + return staticDateFormat.format(dateTime); + } + } + + public static void addChildTextNode( + Document doc, Element parent, String nodeName, String text) { + Element child = doc.createElement(nodeName); + child.appendChild(doc.createTextNode(text)); + parent.appendChild(child); + } + + public static String getDebugXMLString(Document doc) throws TransformerException { + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + StringWriter writer = new StringWriter(); + transformer.transform(new DOMSource(doc), new StreamResult(writer)); + return writer.getBuffer().toString().replaceAll("\n|\r", ""); + } + + private static void showDialogForGUI() { + if (View.isInitialised()) { + JOptionPane.showMessageDialog( + null, Constant.messages.getString("report.write.dialog.message")); + } + } +} diff --git a/src/main/java/com/blackduck/zap/srm/ReportLastScan.java b/src/main/java/com/blackduck/zap/srm/ReportLastScan.java new file mode 100644 index 0000000..81e990f --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/ReportLastScan.java @@ -0,0 +1,328 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2003-2004 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.control.Control; +import org.parosproxy.paros.extension.Extension; +import org.parosproxy.paros.extension.ExtensionLoader; +import org.parosproxy.paros.extension.ViewDelegate; +import org.parosproxy.paros.model.Model; +import org.parosproxy.paros.model.SiteMap; +import org.parosproxy.paros.model.SiteNode; +import org.parosproxy.paros.view.View; +import org.zaproxy.zap.extension.XmlReporterExtension; +import org.zaproxy.zap.utils.DesktopUtils; +import org.zaproxy.zap.utils.XMLStringUtil; +import org.zaproxy.zap.view.ScanPanel; +import org.zaproxy.zap.view.widgets.WritableFileChooser; + +import javax.swing.*; +import javax.swing.filechooser.FileFilter; +import javax.xml.transform.stream.StreamSource; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Locale; + +public class ReportLastScan { + + private static final Logger LOGGER = LogManager.getLogger(ReportLastScan.class); + + private static final String HTM_FILE_EXTENSION = ".htm"; + private static final String HTML_FILE_EXTENSION = ".html"; + private static final String XML_FILE_EXTENSION = ".xml"; + private static final String MD_FILE_EXTENSION = ".md"; + private static final String JSON_FILE_EXTENSION = ".json"; + + public enum ReportType { + HTML, + XML, + MD, + JSON + } + + public ReportLastScan() { + } + + /** + * @deprecated generate has been deprecated in favor of using {@link #generate(String fileName, + * ReportType reportType)} + */ + @Deprecated + public File generate(String fileName, Model model, String xslFile) throws Exception { + StringBuilder sb = new StringBuilder(500); + this.generate(sb); + return ReportGenerator.stringToHtml(sb.toString(), xslFile, fileName); + } + + /** + * @deprecated generate has been deprecated in favor of using {@link #generate(String filename, + * ReportType reportType)} + */ + @Deprecated + public File generate(String fileName, Model model, ReportType reportType) throws Exception { + return generate(fileName, reportType); + } + + public File generate(String fileName, ReportType reportType) throws Exception { + StringBuilder sb = new StringBuilder(500); + this.generate(sb); + if (reportType == ReportType.JSON) { + return ReportGenerator.stringToJson(sb.toString(), fileName); + } + + if (reportType == ReportType.XML) { + return ReportGenerator.stringToHtml(sb.toString(), (String) null, fileName); + } + + String xslFileName = reportType == ReportType.MD ? "report.md.xsl" : "report.html.xsl"; + return generateReportWithXsl(sb.toString(), fileName, xslFileName); + } + + private static File generateReportWithXsl(String report, String reportFile, String xslFileName) + throws IOException { + Path xslFile = Paths.get(Constant.getZapInstall(), "xml", xslFileName); + if (Files.exists(xslFile)) { + return ReportGenerator.stringToHtml(report, xslFile.toString(), reportFile); + } + + String path = "/org/zaproxy/zap/resources/xml/" + xslFileName; + try (InputStream is = ReportLastScan.class.getResourceAsStream(path)) { + if (is == null) { + LOGGER.error("Bundled file not found: {}", path); + return new File(reportFile); + } + return ReportGenerator.stringToHtml(report, new StreamSource(is), reportFile); + } + } + + /** + * @deprecated generate has been deprecated in favor of using {@link #generate(StringBuilder + * report)} + */ + @Deprecated + public void generate(StringBuilder report, Model model) throws Exception { + generate(report); + } + + public void generate(StringBuilder report) throws Exception { + report.append(""); + report.append("\r\n"); + siteXML(report); + report.append(""); + } + + private void siteXML(StringBuilder report) { + SiteMap siteMap = Model.getSingleton().getSession().getSiteTree(); + SiteNode root = siteMap.getRoot(); + int siteNumber = root.getChildCount(); + for (int i = 0; i < siteNumber; i++) { + SiteNode site = (SiteNode) root.getChildAt(i); + String siteName = ScanPanel.cleanSiteName(site, true); + String[] hostAndPort = siteName.split(":"); + boolean isSSL = (site.getNodeName().startsWith("https")); + String siteStart = + ""; + StringBuilder extensionsXML = getExtensionsXML(site); + String siteEnd = ""; + report.append(siteStart); + report.append(extensionsXML); + report.append(siteEnd); + } + } + + public StringBuilder getExtensionsXML(SiteNode site) { + StringBuilder extensionXml = new StringBuilder(); + ExtensionLoader loader = Control.getSingleton().getExtensionLoader(); + int extensionCount = loader.getExtensionCount(); + for (int i = 0; i < extensionCount; i++) { + Extension extension = loader.getExtension(i); + if (extension instanceof XmlReporterExtension) { + extensionXml.append(((XmlReporterExtension) extension).getXml(site)); + } + } + return extensionXml; + } + + /** + * @deprecated generate has been deprecated in favor of using {@link + * #generateReport(ViewDelegate view, ReportType reportType)} + */ + @Deprecated + public void generateReport(ViewDelegate view, Model model, ReportType reportType) { + generateReport(view, reportType); + } + + /** + * Generates a report. Defaults to HTML report if reportType is null. + * + * @param view + * @param reportType + */ + public void generateReport(ViewDelegate view, ReportType reportType) { + // ZAP: Allow scan report file name to be specified + + final ReportType localReportType; + + if (reportType == null) { + localReportType = ReportType.HTML; + } else { + localReportType = reportType; + } + + try { + JFileChooser chooser = + new WritableFileChooser( + Model.getSingleton().getOptionsParam().getUserDirectory()); + + chooser.setFileFilter( + new FileFilter() { + + @Override + public boolean accept(File file) { + if (file.isDirectory()) { + return true; + } else if (file.isFile()) { + String lcFileName = file.getName().toLowerCase(Locale.ROOT); + switch (localReportType) { + case XML: + return lcFileName.endsWith(XML_FILE_EXTENSION); + case MD: + return lcFileName.endsWith(MD_FILE_EXTENSION); + case JSON: + return lcFileName.endsWith(JSON_FILE_EXTENSION); + case HTML: + default: + return (lcFileName.endsWith(HTM_FILE_EXTENSION) + || lcFileName.endsWith(HTML_FILE_EXTENSION)); + } + } + return false; + } + + @Override + public String getDescription() { + switch (localReportType) { + case XML: + return Constant.messages.getString("file.format.xml"); + case MD: + return Constant.messages.getString("file.format.md"); + case JSON: + return Constant.messages.getString("file.format.json"); + case HTML: + default: + return Constant.messages.getString("file.format.html"); + } + } + }); + + String fileExtension = ""; + switch (localReportType) { + case XML: + fileExtension = XML_FILE_EXTENSION; + break; + case JSON: + fileExtension = JSON_FILE_EXTENSION; + break; + case MD: + fileExtension = MD_FILE_EXTENSION; + break; + case HTML: + default: + fileExtension = HTML_FILE_EXTENSION; + break; + } + chooser.setSelectedFile( + new File(fileExtension)); // Default the filename to a reasonable extension; + + int rc = chooser.showSaveDialog(View.getSingleton().getMainFrame()); + File file = null; + if (rc == JFileChooser.APPROVE_OPTION) { + file = chooser.getSelectedFile(); + + File report = generate(file.getAbsolutePath(), localReportType); + if (report == null) { + view.showMessageDialog( + Constant.messages.getString( + "report.unknown.error", file.getAbsolutePath())); + return; + } + + if (Files.notExists(report.toPath())) { + LOGGER.info("Not opening report, does not exist: {}", report); + return; + } + + try { + DesktopUtils.openUrlInBrowser(report.toURI()); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + view.showMessageDialog( + Constant.messages.getString( + "report.complete.warning", report.getAbsolutePath())); + } + } + + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + view.showWarningDialog(Constant.messages.getString("report.unexpected.error")); + } + } + + /** + * @deprecated generateHtml has been deprecated in favor of using {@link + * #generateReport(ViewDelegate, Model, ReportType)} + */ + @Deprecated + public void generateHtml(ViewDelegate view, Model model) { + generateReport(view, model, ReportType.HTML); + } + + /** + * @deprecated generateXml has been deprecated in favor of using {@link + * #generateReport(ViewDelegate, Model, ReportType)} + */ + @Deprecated + public void generateXml(ViewDelegate view, Model model) { + generateReport(view, model, ReportType.XML); + } +} diff --git a/src/main/java/com/github/srm/zap/srm/ReportLastScanHttp.java b/src/main/java/com/blackduck/zap/srm/ReportLastScanHttp.java similarity index 79% rename from src/main/java/com/github/srm/zap/srm/ReportLastScanHttp.java rename to src/main/java/com/blackduck/zap/srm/ReportLastScanHttp.java index 3dad91d..a332b2e 100644 --- a/src/main/java/com/github/srm/zap/srm/ReportLastScanHttp.java +++ b/src/main/java/com/blackduck/zap/srm/ReportLastScanHttp.java @@ -17,16 +17,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.github.srm.zap.srm; +package com.blackduck.zap.srm; import org.parosproxy.paros.model.SiteNode; public class ReportLastScanHttp extends ReportLastScan { - ReportLastScanHttp() {} + ReportLastScanHttp() { + } - @Override - public StringBuilder getExtensionsXML(SiteNode site) { - return new StringBuilder(new ExtensionAlertHttp().getXml(site)); - } + @Override + public StringBuilder getExtensionsXML(SiteNode site) { + return new StringBuilder(new ExtensionAlertHttp().getXml(site)); + } } diff --git a/src/main/java/com/blackduck/zap/srm/SrmAPI.java b/src/main/java/com/blackduck/zap/srm/SrmAPI.java new file mode 100644 index 0000000..35bfd6b --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/SrmAPI.java @@ -0,0 +1,172 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm; + +import net.sf.json.JSONObject; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.zaproxy.zap.extension.api.*; +import org.zaproxy.zap.extension.api.ApiException.Type; + +import java.io.File; +import java.io.IOException; +import java.security.GeneralSecurityException; + +public class SrmAPI extends ApiImplementor { + + private static final Logger LOGGER = LogManager.getLogger(SrmExtension.class); + private static final String PREFIX = "codedx"; + + private static final String VIEW_GENERATE = "generateReport"; + private static final String ACTION_UPLOAD = "uploadReport"; + private static final String ACTION_GEN_UPLOAD = "generateAndUpload"; + + private static final String ACTION_PARAM_FILE_PATH = "filePath"; + private static final String ACTION_PARAM_SERVER_URL = "serverUrl"; + private static final String ACTION_PARAM_API_KEY = "codeDxApiKey"; + private static final String ACTION_PARAM_PROJECT = "projectId"; + + // Optional + private static final String ACTION_PARAM_FINGERPRINT = "fingerprint"; + private static final String ACTION_PARAM_ACCEPT_PERM = "acceptPermanently"; + + private final SrmExtension extension; + + public SrmAPI(SrmExtension extension) { + this.extension = extension; + } + + public void initApiViewsAndActions() { + this.addApiView(new ApiView(VIEW_GENERATE)); + + String[] optionalParams = new String[]{ACTION_PARAM_FINGERPRINT, ACTION_PARAM_ACCEPT_PERM}; + + this.addApiAction( + new ApiAction( + ACTION_UPLOAD, + new String[]{ + ACTION_PARAM_FILE_PATH, + ACTION_PARAM_SERVER_URL, + ACTION_PARAM_API_KEY, + ACTION_PARAM_PROJECT + }, + optionalParams)); + this.addApiAction( + new ApiAction( + ACTION_GEN_UPLOAD, + new String[]{ + ACTION_PARAM_SERVER_URL, ACTION_PARAM_API_KEY, ACTION_PARAM_PROJECT + }, + optionalParams)); + } + + @Override + public String getPrefix() { + return PREFIX; + } + + @Override + public ApiResponse handleApiAction(String name, JSONObject params) throws ApiException { + if (ACTION_UPLOAD.equals(name)) { + File reportFile = new File(params.getString(ACTION_PARAM_FILE_PATH)); + String serverUrl = params.getString(ACTION_PARAM_SERVER_URL); + String apiKey = params.getString(ACTION_PARAM_API_KEY); + String projectId = params.getString(ACTION_PARAM_PROJECT); + + String fingerprint = this.getParam(params, ACTION_PARAM_FINGERPRINT, ""); + boolean acceptPermanently = this.getParam(params, ACTION_PARAM_ACCEPT_PERM, false); + + uploadFile(reportFile, serverUrl, apiKey, projectId, fingerprint, acceptPermanently); + return ApiResponseElement.OK; + } else if (ACTION_GEN_UPLOAD.equals(name)) { + File reportFile; + String serverUrl = params.getString(ACTION_PARAM_SERVER_URL); + String apiKey = params.getString(ACTION_PARAM_API_KEY); + String projectId = params.getString(ACTION_PARAM_PROJECT); + + String fingerprint = this.getParam(params, ACTION_PARAM_FINGERPRINT, ""); + boolean acceptPermanently = this.getParam(params, ACTION_PARAM_ACCEPT_PERM, false); + + boolean isEmpty = false; + try { + reportFile = UploadActionListener.generateReportFile(extension); + isEmpty = UploadActionListener.reportIsEmpty(reportFile); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + throw new ApiException(Type.INTERNAL_ERROR, e.getMessage()); + } + try { + if (!isEmpty) + uploadFile( + reportFile, + serverUrl, + apiKey, + projectId, + fingerprint, + acceptPermanently); + else return new ApiResponseElement("Result", "empty"); + } finally { + reportFile.delete(); + } + return ApiResponseElement.OK; + } + throw new ApiException(Type.BAD_ACTION); + } + + @Override + public ApiResponse handleApiView(String name, JSONObject params) throws ApiException { + if (VIEW_GENERATE.equals(name)) { + try { + StringBuilder report = new StringBuilder(); + UploadActionListener.generateReportString(extension, report); + return new ApiResponseElement(name, report.toString()); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + throw new ApiException(Type.INTERNAL_ERROR, e.getMessage()); + } + } + throw new ApiException(Type.BAD_VIEW); + } + + private void uploadFile( + File reportFile, + String serverUrl, + String apiKey, + String project, + String fingerprint, + boolean acceptPermanently) + throws ApiException { + if (serverUrl.endsWith("/")) serverUrl = serverUrl.substring(0, serverUrl.length() - 1); + try { + CloseableHttpClient client = + extension.getHttpClient(serverUrl, fingerprint, acceptPermanently); + String err = + UploadActionListener.uploadFile(client, reportFile, serverUrl, apiKey, project); + if (err != null) { + LOGGER.error(err); + throw new ApiException(Type.ILLEGAL_PARAMETER, err); + } + } catch (GeneralSecurityException | IOException e) { + LOGGER.error(e.getMessage(), e); + throw new ApiException(Type.ILLEGAL_PARAMETER, e.getMessage()); + } + } +} diff --git a/src/main/java/com/blackduck/zap/srm/SrmExtension.java b/src/main/java/com/blackduck/zap/srm/SrmExtension.java new file mode 100644 index 0000000..b7eb8b2 --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/SrmExtension.java @@ -0,0 +1,190 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm; + +import com.blackduck.zap.srm.ReportLastScan.ReportType; +import com.blackduck.zap.srm.security.SSLConnectionSocketFactoryFactory; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.extension.ExtensionAdaptor; +import org.parosproxy.paros.extension.ExtensionHook; +import org.parosproxy.paros.model.Model; +import org.parosproxy.paros.network.ConnectionParam; +import org.parosproxy.paros.view.View; +import org.zaproxy.zap.extension.api.API; +import org.zaproxy.zap.view.ZapMenuItem; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.security.GeneralSecurityException; + +/* + * The Software Risk Manager ZAP extension used to include request and response data in alert reports. + * + */ +public class SrmExtension extends ExtensionAdaptor { + + private static final Logger LOGGER = LogManager.getLogger(SrmExtension.class); + + private SrmAPI cdxAPIImpl; + protected static final String PREFIX = "srm"; + + // The name is public so that other extensions can access it + public static final String NAME = "SrmExtension"; + + private ZapMenuItem menuUpload = null; + private ZapMenuItem menuExport = null; + + public SrmExtension() { + super(NAME); + } + + @Override + public boolean canUnload() { + return true; + } + + @Override + public void hook(ExtensionHook extensionHook) { + super.hook(extensionHook); + cdxAPIImpl = new SrmAPI(this); + cdxAPIImpl.initApiViewsAndActions(); + API.getInstance().registerApiImplementor(cdxAPIImpl); + if (hasView()) { + extensionHook.getHookMenu().addReportMenuItem(getUploadMenu()); + extensionHook.getHookMenu().addReportMenuItem(getExportMenu()); + } + } + + @Override + public void unload() { + API.getInstance().removeApiImplementor(cdxAPIImpl); + } + + public ZapMenuItem getUploadMenu() { + if (menuUpload == null) { + menuUpload = new ZapMenuItem("srm.topmenu.upload.title"); + menuUpload.addActionListener(new UploadActionListener(this)); + } + return menuUpload; + } + + public ZapMenuItem getExportMenu() { + if (menuExport == null) { + menuExport = new ZapMenuItem("srm.topmenu.report.title"); + + menuExport.addActionListener( + e -> { + ReportLastScanHttp saver = new ReportLastScanHttp(); + saver.generateReport(getView(), ReportType.XML); + }); + } + return menuExport; + } + + public CloseableHttpClient getHttpClient() { + try { + return getHttpClient(SrmProperties.getInstance().getServerUrl()); + } catch (MalformedURLException e) { + View.getSingleton() + .showWarningDialog(Constant.messages.getString("srm.error.client.invalid")); + } catch (IOException | GeneralSecurityException e) { + View.getSingleton() + .showWarningDialog(Constant.messages.getString("srm.error.client.failed")); + } + return null; + } + + public CloseableHttpClient getHttpClient(String url) + throws IOException, GeneralSecurityException { + return getHttpClient(url, null, false); + } + + @SuppressWarnings("deprecation") + public CloseableHttpClient getHttpClient( + String url, String fingerprint, boolean acceptPermanently) + throws IOException, GeneralSecurityException { + RequestConfig.Builder configBuilder = + RequestConfig.custom() + .setConnectTimeout(getTimeout()) + .setSocketTimeout(getTimeout()) + .setConnectionRequestTimeout(getTimeout()); + + HttpClientBuilder builder = HttpClientBuilder.create(); + if (fingerprint != null) { + builder.setSSLSocketFactory( + SSLConnectionSocketFactoryFactory.getFactory( + URI.create(url).getHost(), this, fingerprint, acceptPermanently)); + } else { + builder.setSSLSocketFactory( + SSLConnectionSocketFactoryFactory.getFactory(URI.create(url).getHost(), this)); + } + + ConnectionParam connParam = Model.getSingleton().getOptionsParam().getConnectionParam(); + if (connParam.isUseProxyChain()) { + String proxyHost = connParam.getProxyChainName(); + int proxyPort = connParam.getProxyChainPort(); + HttpHost proxy = new HttpHost(proxyHost, proxyPort); + configBuilder.setProxy(proxy); + + if (connParam.isUseProxyChainAuth()) { + BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials( + new AuthScope(proxyHost, proxyPort), + new UsernamePasswordCredentials( + connParam.getProxyChainUserName(), + connParam.getProxyChainPassword())); + builder.setDefaultCredentialsProvider(credsProvider); + } + } + builder.setDefaultRequestConfig(configBuilder.build()); + return builder.build(); + } + + @Override + public String getDescription() { + return Constant.messages.getString("srm.desc"); + } + + @Override + public URL getURL() { + return null; + } + + private int getTimeout() { + try { + return Integer.parseInt(SrmProperties.getInstance().getTimeout()) * 1000; + } catch (NumberFormatException e) { + // If for some reason the saved timeout value can't be parsed as an int, we will return + // the default value of 120 seconds + return SrmProperties.DEFAULT_TIMEOUT_INT; + } + } +} diff --git a/src/main/java/com/blackduck/zap/srm/SrmProperties.java b/src/main/java/com/blackduck/zap/srm/SrmProperties.java new file mode 100644 index 0000000..3f4edbf --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/SrmProperties.java @@ -0,0 +1,162 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm; + +import org.apache.commons.configuration.Configuration; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.model.Model; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Properties; + +public class SrmProperties { + private static class Holder { + static final SrmProperties INSTANCE = new SrmProperties(); + } + + public static SrmProperties getInstance() { + return Holder.INSTANCE; + } + + private SrmProperties() { + loadProperties(); + } + + private static final Logger LOGGER = LogManager.getLogger(SrmProperties.class); + + private static final String PROP_FILE = "srm.properties"; + private static final String FALLBACK_PROP_FILE = "codedx.properties"; + private static final String KEY_SERVER = "serverUrl"; + private static final String KEY_API = "apiKey"; + private static final String KEY_SELECTED = "selectedId"; + private static final String KEY_TIMEOUT = "timeout"; + + // ZAP config keys with prefix + private static final String ZAP_CONFIG_PREFIX = "srm."; + private static final String ZAP_KEY_SERVER = ZAP_CONFIG_PREFIX + KEY_SERVER; + private static final String ZAP_KEY_API = ZAP_CONFIG_PREFIX + KEY_API; + private static final String ZAP_KEY_SELECTED = ZAP_CONFIG_PREFIX + KEY_SELECTED; + private static final String ZAP_KEY_TIMEOUT = ZAP_CONFIG_PREFIX + KEY_TIMEOUT; + + private Properties prop; + private File configFile; + + public static final String DEFAULT_TIMEOUT_STRING = "120"; + public static final int DEFAULT_TIMEOUT_INT = 120000; + + public String getServerUrl() { + String text = getProperty(KEY_SERVER); + if (text != null && text.endsWith("/")) { + return text.substring(0, text.length() - 1); + } + return text != null ? text : ""; + } + + public String getApiKey() { + return getProperty(KEY_API); + } + + public String getSelectedId() { + return getProperty(KEY_SELECTED); + } + + public String getTimeout() { + String timeout = getProperty(KEY_TIMEOUT); + if (timeout == null || timeout.isEmpty()) { + timeout = DEFAULT_TIMEOUT_STRING; + } + return timeout; + } + + private String getProperty(String key) { + if (configFile == null) { + Configuration config = Model.getSingleton().getOptionsParam().getConfig(); + String zapKey = ZAP_CONFIG_PREFIX + key; + return config.getString(zapKey, ""); + } else { + String value = prop.getProperty(key); + return value == null ? "" : value; + } + } + + + public void setProperties(String server, String api, String selectedId, String timeout) { + if (configFile == null) { + Configuration config = Model.getSingleton().getOptionsParam().getConfig(); + config.setProperty(ZAP_KEY_SERVER, server); + config.setProperty(ZAP_KEY_API, api); + config.setProperty(ZAP_KEY_SELECTED, selectedId); + config.setProperty(ZAP_KEY_TIMEOUT, timeout); + } else { + prop.setProperty(KEY_SERVER, server); + prop.setProperty(KEY_API, api); + prop.setProperty(KEY_SELECTED, selectedId); + prop.setProperty(KEY_TIMEOUT, timeout); + saveProperties(); + } + } + + private void loadProperties() { + if (prop == null) prop = new Properties(); + + File srmFile = Paths.get(Constant.getZapHome(), PROP_FILE).toFile(); + if (srmFile.exists()) { + configFile = srmFile; + loadFromFile(configFile); + return; + } + + File fallbackFile = Paths.get(Constant.getZapHome(), FALLBACK_PROP_FILE).toFile(); + if (fallbackFile.exists()) { + configFile = fallbackFile; + loadFromFile(configFile); + return; + } + + // Neither file exists, use ZAP config + configFile = null; + LOGGER.info("Using ZAP configuration for SRM properties"); + } + + private void loadFromFile(File file) { + try (FileInputStream inp = new FileInputStream(file)) { + prop.load(inp); + LOGGER.info("Loaded SRM properties from: " + file.getName()); + } catch (IOException e) { + LOGGER.error("Error loading properties file: " + file.getName(), e); + } + } + + private void saveProperties() { + if (configFile != null) { + try (FileOutputStream out = new FileOutputStream(configFile)) { + prop.store(out, null); + } catch (IOException e) { + LOGGER.error("Error saving properties file: " + configFile.getName(), e); + } + } + } +} diff --git a/src/main/java/com/blackduck/zap/srm/UploadActionListener.java b/src/main/java/com/blackduck/zap/srm/UploadActionListener.java new file mode 100644 index 0000000..55a4f07 --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/UploadActionListener.java @@ -0,0 +1,225 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm; + +import com.blackduck.zap.srm.ReportLastScan.ReportType; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.entity.mime.content.FileBody; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.view.View; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.XMLEvent; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +public class UploadActionListener implements ActionListener { + + private static final Logger LOGGER = LogManager.getLogger(UploadActionListener.class); + + private static final XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); + + static { + xmlInputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false); + xmlInputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); + } + + private final SrmExtension extension; + private final UploadPropertiesDialog prop; + + public UploadActionListener(SrmExtension extension) { + this.extension = extension; + this.prop = new UploadPropertiesDialog(extension); + } + + @Override + public void actionPerformed(ActionEvent e) { + prop.openProperties(this); + } + + public void generateAndUploadReport() { + String error = null; + try { + final File reportFile = generateReportFile(extension); + if (!reportIsEmpty(reportFile)) { + Thread uploadThread = + new Thread() { + @Override + public void run() { + String err; + try { + err = + uploadFile( + extension.getHttpClient(), + reportFile, + SrmProperties.getInstance().getServerUrl(), + SrmProperties.getInstance().getApiKey(), + prop.getProject().getValue()); + } catch (IOException ex1) { + err = Constant.messages.getString("srm.error.unexpected"); + LOGGER.error("Unexpected error while uploading report: ", ex1); + } + if (err != null) View.getSingleton().showMessageDialog(err); + else + View.getSingleton() + .showMessageDialog( + Constant.messages.getString( + "srm.message.success")); + reportFile.delete(); + } + }; + uploadThread.start(); + } else { + error = Constant.messages.getString("srm.error.empty"); + } + } catch (Exception ex2) { + error = Constant.messages.getString("srm.error.failed"); + LOGGER.error("Unexpected error while generating report: ", ex2); + } + if (error != null) View.getSingleton().showWarningDialog(error); + } + + public static String uploadFile( + CloseableHttpClient client, + File reportFile, + String serverUrl, + String apiKey, + String project) + throws IOException { + String err = null; + HttpResponse response = sendData(client, reportFile, serverUrl, apiKey, project); + StatusLine responseLine = null; + int responseCode = -1; + if (response != null) { + responseLine = response.getStatusLine(); + responseCode = responseLine.getStatusCode(); + } + if (responseCode == 400) { + err = + Constant.messages.getString("srm.error.unexpected") + + "\n" + + Constant.messages.getString("srm.error.http.400"); + } else if (responseCode == 403) { + err = + Constant.messages.getString("srm.error.unsent") + + " " + + Constant.messages.getString("srm.error.http.403"); + } else if (responseCode == 404) { + err = + Constant.messages.getString("srm.error.unsent") + + " " + + Constant.messages.getString("srm.error.http.404"); + } else if (responseCode == 415) { + err = + Constant.messages.getString("srm.error.unexpected") + + "\n" + + Constant.messages.getString("srm.error.http.415"); + } else if (responseCode != 200 && responseCode != 202) { + err = Constant.messages.getString("srm.error.unexpected"); + if (response != null) + err += Constant.messages.getString("srm.error.http.other") + " " + responseLine; + } + return err; + } + + private static HttpResponse sendData( + CloseableHttpClient client, + File reportFile, + String serverUrl, + String apiKey, + String project) + throws IOException { + if (client == null) return null; + try { + HttpPost post = new HttpPost(serverUrl + "/api/projects/" + project + "/analysis"); + post.setHeader("API-Key", apiKey); + + MultipartEntityBuilder builder = MultipartEntityBuilder.create(); + builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); + builder.addPart("file", new FileBody(reportFile)); + + HttpEntity entity = builder.build(); + post.setEntity(entity); + + HttpResponse response = client.execute(post); + HttpEntity resEntity = response.getEntity(); + + if (resEntity != null) { + EntityUtils.consume(resEntity); + } + + return response; + } finally { + client.close(); + } + } + + public static void generateReportString(SrmExtension extension, StringBuilder report) + throws Exception { + ReportLastScanHttp saver = new ReportLastScanHttp(); + saver.generate(report); + } + + public static File generateReportFile(SrmExtension extension) throws Exception { + File reportFile = File.createTempFile("srm-zap-report", ".xml"); + reportFile.deleteOnExit(); + + ReportLastScanHttp saver = new ReportLastScanHttp(); + saver.generate(reportFile.getCanonicalPath(), ReportType.XML); + + return reportFile; + } + + public static Boolean reportIsEmpty(File reportFile) throws IOException, XMLStreamException { + BufferedReader br = Files.newBufferedReader(reportFile.toPath()); + try { + XMLEventReader reader = xmlInputFactory.createXMLEventReader(br); + + while (reader.hasNext()) { + XMLEvent event = reader.nextEvent(); + if (event.isStartElement() + && !event.asStartElement() + .getName() + .getLocalPart() + .equals("OWASPZAPReport")) { + return false; + } + } + } finally { + br.close(); + } + return true; + } +} diff --git a/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java b/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java new file mode 100644 index 0000000..9120a2c --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java @@ -0,0 +1,369 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm; + +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.parosproxy.paros.Constant; + +import javax.swing.*; +import java.awt.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; +import java.util.Arrays; + +public class UploadPropertiesDialog { + + private static final Logger LOGGER = LogManager.getLogger(UploadPropertiesDialog.class); + + private static final String[] DIALOG_BUTTONS = { + Constant.messages.getString("srm.settings.upload"), + Constant.messages.getString("srm.settings.cancel") + }; + + public static final ImageIcon REFRESH_ICON = + new ImageIcon( + UploadPropertiesDialog.class.getResource( + "/com/blackduck/zap/srm/resources/refresh.png")); + + private JTextField serverUrl; + private JTextField apiKey; + private JComboBox projectBox; + private JTextField timeout; + private JDialog dialog; + + private ModifiedNameValuePair[] projectArr = new ModifiedNameValuePair[0]; + + private final SrmExtension extension; + + public UploadPropertiesDialog(SrmExtension extension) { + this.extension = extension; + } + + public void openProperties(final UploadActionListener uploader) { + JPanel message = new JPanel(new GridBagLayout()); + + serverUrl = + labelTextField( + Constant.messages.getString("srm.settings.serverurl") + " ", + message, + SrmProperties.getInstance().getServerUrl(), + 30); + apiKey = + labelTextField( + Constant.messages.getString("srm.settings.apikey") + " ", + message, + SrmProperties.getInstance().getApiKey(), + 30); + projectBox = createProjectComboBox(message); + timeout = + labelTextField( + Constant.messages.getString("srm.setting.timeout") + " ", + message, + SrmProperties.getInstance().getTimeout(), + 5); + + final JOptionPane pane = + new JOptionPane( + message, + JOptionPane.PLAIN_MESSAGE, + JOptionPane.OK_CANCEL_OPTION, + null, + DIALOG_BUTTONS, + null); + dialog = pane.createDialog(Constant.messages.getString("srm.settings.title")); + + Thread popupThread = + new Thread() { + @Override + public void run() { + dialog.setVisible(true); + if (DIALOG_BUTTONS[0].equals(pane.getValue())) { + String timeoutValue = timeout.getText(); + if (!isStringNumber(timeoutValue)) { + timeoutValue = SrmProperties.DEFAULT_TIMEOUT_STRING; + error(Constant.messages.getString("srm.error.timeout")); + } + SrmProperties.getInstance() + .setProperties( + serverUrl.getText(), + apiKey.getText(), + getProject().getValue(), + timeoutValue); + uploader.generateAndUploadReport(); + } + } + }; + Thread updateThread = + new Thread() { + @Override + public void run() { + if (!"".equals(serverUrl.getText()) && !"".equals(apiKey.getText())) { + updateProjects(true); + String previousId = SrmProperties.getInstance().getSelectedId(); + for (NameValuePair p : projectArr) { + if (previousId.equals(p.getValue())) projectBox.setSelectedItem(p); + } + } + } + }; + popupThread.start(); + updateThread.start(); + } + + private boolean isStringNumber(String value) { + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (!Character.isDigit(c)) { + return false; + } + } + return true; + } + + private JTextField labelTextField(String label, Container cont, String base, int columns) { + createSettingsLabel(label, cont); + + JTextField textField = new JTextField(base, columns); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 1; + gbc.anchor = GridBagConstraints.WEST; + cont.add(textField, gbc); + + return textField; + } + + private JComboBox createProjectComboBox(Container cont) { + createSettingsLabel("Project: ", cont); + + JComboBox box = new JComboBox<>(); + box.setPreferredSize(new Dimension(300, 27)); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + cont.add(box, gbc); + + JButton refresh = new JButton(REFRESH_ICON); + refresh.setPreferredSize( + new Dimension(REFRESH_ICON.getIconHeight() + 6, REFRESH_ICON.getIconHeight() + 6)); + refresh.addActionListener( + e -> { + if ("".equals(serverUrl.getText()) || "".equals(apiKey.getText())) { + error(Constant.messages.getString("srm.error.required")); + return; + } + dialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + updateProjects(); + dialog.setCursor(Cursor.getDefaultCursor()); + }); + gbc = new GridBagConstraints(); + gbc.gridx = 2; + gbc.gridy = 2; + gbc.anchor = GridBagConstraints.WEST; + cont.add(refresh, gbc); + + return box; + } + + private void createSettingsLabel(String label, Container cont) { + JLabel labelField = new JLabel(label); + labelField.setHorizontalAlignment(SwingConstants.LEFT); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridwidth = 1; + gbc.gridx = 0; + gbc.insets = new Insets(0, 10, 0, 0); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.HORIZONTAL; + cont.add(labelField, gbc); + } + + public void updateProjects() { + updateProjects(false); + } + + public void updateProjects(boolean initialRefresh) { + dialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + CloseableHttpClient client = null; + BufferedReader rd = null; + projectArr = new ModifiedNameValuePair[0]; + try { + client = extension.getHttpClient(getServerUrl()); + if (client != null) { + HttpGet get = new HttpGet(getServerUrl() + "/api/projects"); + get.setHeader("API-Key", getApiKey()); + HttpResponse response = client.execute(get); + rd = + new BufferedReader( + new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); + + StringBuilder result = new StringBuilder(); + String line = ""; + while ((line = rd.readLine()) != null) { + result.append(line); + } + + int code = response.getStatusLine().getStatusCode(); + if (code == 200) { + projectArr = parseProjectJson(result.toString(), initialRefresh); + } else if (!initialRefresh) { + String msg = + Constant.messages.getString("srm.refresh.non200") + + ' ' + + response.getStatusLine() + + '.'; + if (code == 403) msg += Constant.messages.getString("srm.refresh.403"); + else if (code == 404) msg += Constant.messages.getString("srm.refresh.404"); + else if (code == 400) msg += Constant.messages.getString("srm.refresh.400"); + error(msg); + } + } + } catch (GeneralSecurityException | ParseException | IOException e) { + if (!initialRefresh) { + if (e instanceof MalformedURLException) + error(Constant.messages.getString("srm.error.client.invalid")); + else error(Constant.messages.getString("srm.refresh.failed")); + } + LOGGER.error("Error refreshing project list: ", e); + } finally { + if (client != null) + try { + client.close(); + } catch (IOException e) { + } + if (rd != null) + try { + rd.close(); + } catch (IOException e) { + } + } + updateProjectComboBox(); + dialog.setCursor(Cursor.getDefaultCursor()); + } + + private ModifiedNameValuePair[] parseProjectJson(String json, boolean initialRefresh) + throws ParseException { + JSONParser parser = new JSONParser(); + JSONObject obj = (JSONObject) parser.parse(json); + JSONArray projects = (JSONArray) obj.get("projects"); + + ModifiedNameValuePair[] projectArr = new ModifiedNameValuePair[projects.size()]; + for (int i = 0; i < projectArr.length; i++) { + JSONObject project = (JSONObject) projects.get(i); + int id = ((Long) project.get("id")).intValue(); + String name = (String) project.get("name"); + projectArr[i] = new ModifiedNameValuePair(name, Integer.toString(id)); + } + if (projectArr.length > 0) { + Arrays.sort(projectArr); + // set the project ids to visible if the names are the same + for (int i = 0; i < projectArr.length - 1; i++) { + if (projectArr[i].getName() != null + && projectArr[i].getName().equals(projectArr[i + 1].getName())) { + projectArr[i].setUseId(true); + projectArr[i + 1].setUseId(true); + } + } + } else if (!initialRefresh) warn(Constant.messages.getString("srm.refresh.noproject")); + return projectArr; + } + + public void updateProjectComboBox() { + if (projectBox != null) { + NameValuePair selected = getProject(); + projectBox.removeAllItems(); + for (NameValuePair p : projectArr) { + projectBox.addItem(p); + if (selected != null && selected.equals(p)) { + projectBox.setSelectedItem(p); + } + } + } + } + + public NameValuePair getProject() { + return (NameValuePair) projectBox.getSelectedItem(); + } + + private void warn(String message) { + JOptionPane.showMessageDialog( + dialog, + message, + Constant.messages.getString("srm.warning"), + JOptionPane.WARNING_MESSAGE); + } + + private void error(String message) { + JOptionPane.showMessageDialog( + dialog, + message, + Constant.messages.getString("srm.error"), + JOptionPane.ERROR_MESSAGE); + } + + private String getServerUrl() { + String text = serverUrl.getText(); + if (text.endsWith("/")) return text.substring(0, text.length() - 1); + return text; + } + + private String getApiKey() { + return apiKey.getText(); + } + + private static class ModifiedNameValuePair extends BasicNameValuePair + implements Comparable { + private static final long serialVersionUID = -6671681121783779976L; + private boolean useId = false; + + public ModifiedNameValuePair(String name, String value) { + super(name, value); + } + + public void setUseId(boolean useId) { + this.useId = useId; + } + + @Override + public String toString() { + if (useId) return getName() + " (id: " + getValue() + ")"; + return getName(); + } + + @Override + public int compareTo(ModifiedNameValuePair o) { + int val = this.getName().compareTo(o.getName()); + if (val == 0) return this.getValue().compareTo(o.getValue()); + return val; + } + } +} diff --git a/src/main/java/com/github/srm/zap/srm/security/CertificateAcceptance.java b/src/main/java/com/blackduck/zap/srm/security/CertificateAcceptance.java similarity index 58% rename from src/main/java/com/github/srm/zap/srm/security/CertificateAcceptance.java rename to src/main/java/com/blackduck/zap/srm/security/CertificateAcceptance.java index bdaeb21..ef9bf75 100644 --- a/src/main/java/com/github/srm/zap/srm/security/CertificateAcceptance.java +++ b/src/main/java/com/blackduck/zap/srm/security/CertificateAcceptance.java @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.github.srm.zap.srm.security; +package com.blackduck.zap.srm.security; /** * Enumeration to describe the possible outcomes of an {@link InvalidCertificateStrategy} when @@ -25,20 +25,22 @@ */ public enum CertificateAcceptance { - /** The invalid certificate should be rejected. */ - REJECT, + /** + * The invalid certificate should be rejected. + */ + REJECT, - /** - * The invalid certificate should be accepted on a short-term basis, e.g. for the duration of - * the session, or until the current JVM stops. The actual interpretation is up to the - * corresponding {@link ExtraCertManager}. - */ - ACCEPT_TEMPORARILY, + /** + * The invalid certificate should be accepted on a short-term basis, e.g. for the duration of + * the session, or until the current JVM stops. The actual interpretation is up to the + * corresponding {@link ExtraCertManager}. + */ + ACCEPT_TEMPORARILY, - /** - * The invalid certificate should be accepted on a long-term basis, e.g. by adding the - * certificate to a custom KeyStore and persisting it to disk. The actual interpretation is up - * to the corresponding {@link ExtraCertManager}. - */ - ACCEPT_PERMANENTLY; + /** + * The invalid certificate should be accepted on a long-term basis, e.g. by adding the + * certificate to a custom KeyStore and persisting it to disk. The actual interpretation is up + * to the corresponding {@link ExtraCertManager}. + */ + ACCEPT_PERMANENTLY } diff --git a/src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java b/src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java new file mode 100644 index 0000000..6b58984 --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java @@ -0,0 +1,98 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm.security; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.X509TrustManager; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * Represents an ordered list of {@link X509TrustManager}s with additive trust. If any one of the + * composed managers trusts a certificate chain, then it is trusted by the composite manager. + * + *

This is necessary because of the fine-print on {@link SSLContext#init}: Only the first + * instance of a particular key and/or trust manager implementation type in the array is used. (For + * example, only the first javax.net.ssl.X509KeyManager in the array will be used.) + * + *

see + * StackOverflow and the related blog post + * + * @author codyaray + * @see + * @since 4/22/2013 + */ +public class CompositeX509TrustManager implements X509TrustManager { + + private final List trustManagers = new LinkedList<>(); + + /** + * Initializes the composite trust manager, copying all of the non-null entries in the given + * trustManagers list into its own internal list. + * + * @param trustManagers A list of (potentially null) trust managers. + */ + public CompositeX509TrustManager(List trustManagers) { + for (X509TrustManager tm : trustManagers) { + if (tm != null) this.trustManagers.add(tm); + } + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + for (X509TrustManager trustManager : trustManagers) { + try { + trustManager.checkClientTrusted(chain, authType); + return; // someone trusts them. success! + } catch (CertificateException e) { + // maybe someone else will trust them + } + } + throw new CertificateException("None of the TrustManagers trust this certificate chain"); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + for (X509TrustManager trustManager : trustManagers) { + try { + trustManager.checkServerTrusted(chain, authType); + return; // someone trusts them. success! + } catch (CertificateException e) { + // maybe someone else will trust them + } + } + throw new CertificateException("None of the TrustManagers trust this certificate chain"); + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + List certificates = new LinkedList<>(); + for (X509TrustManager trustManager : trustManagers) { + Collections.addAll(certificates, trustManager.getAcceptedIssuers()); + } + return certificates.toArray(new X509Certificate[certificates.size()]); + } +} diff --git a/src/main/java/com/blackduck/zap/srm/security/ExtraCertManager.java b/src/main/java/com/blackduck/zap/srm/security/ExtraCertManager.java new file mode 100644 index 0000000..9bcf367 --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/security/ExtraCertManager.java @@ -0,0 +1,70 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm.security; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.Certificate; + +public interface ExtraCertManager { + + /** + * Add a certificate that will be accepted until some event (as determined by the implementation + * of this interface) occurs, causing it to be "forgotten". + * + * @param cert + */ + void addTemporaryCert(Certificate cert) throws IOException, GeneralSecurityException; + + /** + * Add a certificate that will be accepted until this manager is "purged". Certificates added in + * this way will generally be written to disk, and will be available upon restarting the + * program. + * + * @param cert + * @throws IOException + * @throws GeneralSecurityException + */ + void addPermanentCert(Certificate cert) throws IOException, GeneralSecurityException; + + /** + * Remove all certificates that have been added via {@link #addTemporaryCert(Certificate)}. + */ + void purgeTemporaryCerts() throws IOException, GeneralSecurityException; + + /** + * Remove all certificates that have been added via {@link #addPermanentCert(Certificate)}. + */ + void purgePermanentCerts() throws IOException, GeneralSecurityException; + + /** + * Remove all certificates that have been added either by {@link #addTemporaryCert(Certificate)} + * or {@link #addPermanentCert(Certificate)}. + */ + void purgeAllCerts() throws IOException, GeneralSecurityException; + + /** + * Return a representation of this manager as a KeyStore instance. + * + * @return A new KeyStore that represents the contents of this certificate manager + */ + KeyStore asKeyStore() throws IOException, GeneralSecurityException; +} diff --git a/src/main/java/com/github/srm/zap/srm/security/HostnameVerifierWithExceptions.java b/src/main/java/com/blackduck/zap/srm/security/HostnameVerifierWithExceptions.java similarity index 68% rename from src/main/java/com/github/srm/zap/srm/security/HostnameVerifierWithExceptions.java rename to src/main/java/com/blackduck/zap/srm/security/HostnameVerifierWithExceptions.java index 4bbe4b4..eaeeb05 100644 --- a/src/main/java/com/github/srm/zap/srm/security/HostnameVerifierWithExceptions.java +++ b/src/main/java/com/blackduck/zap/srm/security/HostnameVerifierWithExceptions.java @@ -17,11 +17,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.github.srm.zap.srm.security; +package com.blackduck.zap.srm.security; -import java.util.Set; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLSession; +import java.util.Set; /** * HostnameVerifier implementation that delegates to another one, but will allow a particular set of @@ -29,17 +29,17 @@ */ public class HostnameVerifierWithExceptions implements HostnameVerifier { - private final HostnameVerifier delegate; - private final Set allowedExceptions; + private final HostnameVerifier delegate; + private final Set allowedExceptions; - public HostnameVerifierWithExceptions( - HostnameVerifier delegate, Set allowedExceptions) { - this.delegate = delegate; - this.allowedExceptions = allowedExceptions; - } + public HostnameVerifierWithExceptions( + HostnameVerifier delegate, Set allowedExceptions) { + this.delegate = delegate; + this.allowedExceptions = allowedExceptions; + } - @Override - public boolean verify(String host, SSLSession session) { - return delegate.verify(host, session) || allowedExceptions.contains(host); - } + @Override + public boolean verify(String host, SSLSession session) { + return delegate.verify(host, session) || allowedExceptions.contains(host); + } } diff --git a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java new file mode 100644 index 0000000..d0bb385 --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java @@ -0,0 +1,186 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm.security; + +import com.blackduck.zap.srm.SrmExtension; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.parosproxy.paros.Constant; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLException; +import javax.swing.*; +import java.awt.*; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Formatter; +import java.util.StringTokenizer; + +/** + * An InvalidCertificateStrategy implementation that opens a dialog, prompting the user for their + * choice of action. + */ +public class InvalidCertificateDialogStrategy implements InvalidCertificateStrategy { + + private final HostnameVerifier defaultHostVerifier; + private final String host; + private final SrmExtension extension; + + private static final String dialogTitle = Constant.messages.getString("srm.ssl.title"); + private static final String[] dialogButtons = { + Constant.messages.getString("srm.ssl.reject"), + Constant.messages.getString("srm.ssl.accepttemp"), + Constant.messages.getString("srm.ssl.acceptperm") + }; + + public InvalidCertificateDialogStrategy( + HostnameVerifier defaultHostVerifier, String host, SrmExtension extension) { + this.defaultHostVerifier = defaultHostVerifier; + this.host = host; + this.extension = extension; + } + + @Override + public CertificateAcceptance checkAcceptance( + Certificate genericCert, CertificateException certError) { + if (genericCert instanceof X509Certificate cert + && defaultHostVerifier instanceof DefaultHostnameVerifier verifier) { + + JPanel message = new JPanel(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.gridwidth = 2; + gbc.insets = new Insets(0, 0, 10, 0); + gbc.anchor = GridBagConstraints.WEST; + message.add(new JLabel(Constant.messages.getString("srm.ssl.description")), gbc); + + gbc = new GridBagConstraints(); + gbc.gridy = 2; + gbc.insets = new Insets(2, 0, 2, 0); + gbc.anchor = GridBagConstraints.WEST; + + JLabel issuer = new JLabel(Constant.messages.getString("srm.ssl.issuer") + " "); + Font defaultFont = issuer.getFont(); + Font bold = new Font(defaultFont.getName(), Font.BOLD, defaultFont.getSize()); + issuer.setFont(bold); + + message.add(issuer, gbc); + gbc.gridx = 1; + message.add(new JLabel(cert.getIssuerX500Principal().getName()), gbc); + + try { + JLabel fingerprint = + new JLabel(Constant.messages.getString("srm.ssl.fingerprint") + " "); + fingerprint.setFont(bold); + gbc.gridx = 0; + gbc.gridy += 1; + message.add(fingerprint, gbc); + + gbc.gridx = 1; + message.add(new JLabel(toHexString(getSHA1(cert.getEncoded()), " ")), gbc); + } catch (CertificateEncodingException e) { + // this shouldn't actually ever happen + } + + try { + verifier.verify(host, cert); + } catch (SSLException e) { + String cn = getCN(cert); + + JLabel mismatch = new JLabel(Constant.messages.getString("srm.ssl.mismatch") + " "); + mismatch.setFont(bold); + gbc.gridx = 0; + gbc.gridy += 1; + message.add(mismatch, gbc); + + String msg; + if (cn != null) { + msg = + String.format( + Constant.messages.getString("srm.ssl.mismatchmsg"), host, cn); + } else { + msg = e.getMessage(); + } + + gbc.gridx = 1; + message.add(new JLabel(msg), gbc); + } + + // Open the dialog, and return its result + int choice = + JOptionPane.showOptionDialog( + extension.getView().getMainFrame(), + message, + dialogTitle, + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.PLAIN_MESSAGE, + null, + dialogButtons, + null); + switch (choice) { + case (0): + return CertificateAcceptance.REJECT; + case (1): + return CertificateAcceptance.ACCEPT_TEMPORARILY; + case (2): + return CertificateAcceptance.ACCEPT_PERMANENTLY; + } + } + return CertificateAcceptance.REJECT; + } + + public static byte[] getSHA1(byte[] input) { + try { + MessageDigest md = MessageDigest.getInstance("SHA-1"); + md.reset(); + return md.digest(input); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + public static String toHexString(byte[] bytes, String sep) { + Formatter f = new Formatter(); + for (int i = 0; i < bytes.length; i++) { + f.format("%02x", bytes[i]); + if (i < bytes.length - 1) { + f.format(sep); + } + } + String result = f.toString(); + f.close(); + return result; + } + + private static String getCN(X509Certificate cert) { + String principal = cert.getSubjectX500Principal().toString(); + StringTokenizer tokenizer = new StringTokenizer(principal, ","); + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + int i = token.indexOf("CN="); + if (i >= 0) { + return token.substring(i + 3); + } + } + return null; + } +} diff --git a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateFingerprintStrategy.java b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateFingerprintStrategy.java new file mode 100644 index 0000000..e5fdc9c --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateFingerprintStrategy.java @@ -0,0 +1,51 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm.security; + +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; + +public class InvalidCertificateFingerprintStrategy implements InvalidCertificateStrategy { + + private final String fingerprint; + private final boolean acceptPermanently; + + public InvalidCertificateFingerprintStrategy(String fingerprint, boolean acceptPermanently) { + this.fingerprint = fingerprint.replaceAll("\\s", ""); + this.acceptPermanently = acceptPermanently; + } + + @Override + public CertificateAcceptance checkAcceptance(Certificate cert, CertificateException certError) { + try { + byte[] encoded = InvalidCertificateDialogStrategy.getSHA1(cert.getEncoded()); + String obsPrint = InvalidCertificateDialogStrategy.toHexString(encoded, ""); + if (obsPrint.equalsIgnoreCase(fingerprint)) { + if (acceptPermanently) return CertificateAcceptance.ACCEPT_PERMANENTLY; + else return CertificateAcceptance.ACCEPT_TEMPORARILY; + } else { + return CertificateAcceptance.REJECT; + } + } catch (CertificateEncodingException e) { + return CertificateAcceptance.REJECT; + } + } +} diff --git a/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateStrategy.java b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateStrategy.java similarity index 61% rename from src/main/java/com/github/srm/zap/srm/security/InvalidCertificateStrategy.java rename to src/main/java/com/blackduck/zap/srm/security/InvalidCertificateStrategy.java index 56fc50d..48f5643 100644 --- a/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateStrategy.java +++ b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateStrategy.java @@ -17,19 +17,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.github.srm.zap.srm.security; +package com.blackduck.zap.srm.security; import java.security.cert.Certificate; import java.security.cert.CertificateException; public interface InvalidCertificateStrategy { - /** - * Determine what to do with a certificate (reject, accept temporarily, or accept permanently) - * - * @param cert A (probably invalid) certificate - * @param certError An exception (or null) that caused the certificate to be considered invalid - * @return A CertificateAcceptance value that determines whether (and for how long) the - * certificate should be considered valid. - */ - CertificateAcceptance checkAcceptance(Certificate cert, CertificateException certError); + /** + * Determine what to do with a certificate (reject, accept temporarily, or accept permanently) + * + * @param cert A (probably invalid) certificate + * @param certError An exception (or null) that caused the certificate to be considered invalid + * @return A CertificateAcceptance value that determines whether (and for how long) the + * certificate should be considered valid. + */ + CertificateAcceptance checkAcceptance(Certificate cert, CertificateException certError); } diff --git a/src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java b/src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java new file mode 100644 index 0000000..c5974d7 --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java @@ -0,0 +1,144 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm.security; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +/** + * This X509TrustManager implementation allows invalid certificates to possibly be accepted by the + * decision of an {@link InvalidCertificateStrategy} that is passed as a constructor argument. + * Certificates added in this way will be added via a {@link ExtraCertManager}, causing the + * underlying trust manager to be reloaded. + * + *

Adapted from the implementation at "Managing a + * Dynamic Java Trust Store" (blog post) + */ +public class ReloadableX509TrustManager implements X509TrustManager { + + /* package-private */ final ExtraCertManager certManager; + private final InvalidCertificateStrategy invalidCertStrat; + private X509TrustManager tmDelegate; + + public ReloadableX509TrustManager( + ExtraCertManager certManager, InvalidCertificateStrategy invalidCertStrat) + throws IOException, GeneralSecurityException { + this.certManager = certManager; + this.invalidCertStrat = invalidCertStrat; + reloadTrustManager(); + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + tmDelegate.checkClientTrusted(chain, authType); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + throws CertificateException { + try { + tmDelegate.checkServerTrusted(chain, authType); + } catch (CertificateException cx) { + + /* + * At this point, we have come across an apparently-invalid + * certificate. We use the `InvalidCertificateStrategy` to decide + * what to do about it; either reject it (rethrow the exception), or + * accept it. If accepting, the certificate can be added + * "temporarily" or "permanently", which is done via the + * `ExtraCertManager`. + */ + Certificate cert = chain[0]; + CertificateAcceptance certAcceptance = invalidCertStrat.checkAcceptance(cert, cx); + + switch (certAcceptance) { + case REJECT: + throw cx; + + case ACCEPT_TEMPORARILY: + try { + certManager.addTemporaryCert(cert); + reloadTrustManager(); + } catch (IOException | GeneralSecurityException e) { + // wrap errors from the cert manipulation + throw new CertificateException( + "Error handling temporary acceptance of the certificate", e); + } + // now retry the trust check + tmDelegate.checkServerTrusted(chain, authType); + break; + + case ACCEPT_PERMANENTLY: + try { + certManager.addPermanentCert(cert); + reloadTrustManager(); + } catch (IOException | GeneralSecurityException e) { + // wrap errors from the cert manipulation + throw new CertificateException( + "Error handling permanent acceptance of the certificate", e); + } + // now retry the trust check + tmDelegate.checkServerTrusted(chain, authType); + break; + + default: + throw cx; + } + } + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return tmDelegate.getAcceptedIssuers(); + } + + /* package-private */ + final void reloadTrustManager() throws IOException, GeneralSecurityException { + KeyStore ks = certManager.asKeyStore(); + + // initialize a new TMF with the KeyStore we just created + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + + // acquire an X509 trust manager from the TMF + // and update the `tmDelegate` to that value + TrustManager[] tms = tmf.getTrustManagers(); + for (TrustManager tm : tms) { + if (tm instanceof X509TrustManager) { + tmDelegate = (X509TrustManager) tm; + return; + } + } + + // should have returned in the `for` loop above + throw new NoSuchAlgorithmException("No X509TrustManager in TrustManagerFactory"); + } +} diff --git a/src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java b/src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java new file mode 100644 index 0000000..295b750 --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java @@ -0,0 +1,218 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm.security; + +import com.blackduck.zap.srm.SrmExtension; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; + +import javax.net.ssl.*; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.util.*; + +public class SSLConnectionSocketFactoryFactory { + + private static final Map dialogFactoriesByHost = new HashMap<>(); + private static final Map fingerprintFactoriesByHost = + new HashMap<>(); + + /** + * Returns a SSLConnectionSocketFactory for the given host. When a SSL connection is created + * with the returned socket factory, if the server's certificate appears to be invalid, the user + * will be prompted to either reject temporarily accept, or permanently accept the certificate. + * Permanently accepted certificates will be stored in a .truststore file so the + * user won't need to prompted again for the same host. + * + * @param host The host (URL component) that the socket factory will be used to connect to + * @param extension + * @return A socket factory for the given host + * @throws IOException + * @throws GeneralSecurityException + */ + public static SSLConnectionSocketFactory getFactory(String host, SrmExtension extension) + throws IOException, GeneralSecurityException { + + SSLConnectionSocketFactory instance = dialogFactoriesByHost.get(host); + if (instance == null) { + initializeFactory(host, extension, null, false); + return dialogFactoriesByHost.get(host); + } else { + return instance; + } + } + + /** + * Returns a SSLConnectionSocketFactory for the given host. When a SSL connection is created + * with the returned socket factory, if the server's certificate appears to be invalid, the user + * will be prompted to either reject temporarily accept, or permanently accept the certificate. + * Permanently accepted certificates will be stored in a .truststore file so the + * user won't need to prompted again for the same host. + * + * @param host The host (URL component) that the socket factory will be used to connect to + * @param extension + * @param fingerprint Expected SHA1 fingerprint of an invalid certificate + * @param acceptPermanently + * @return A socket factory for the given host + * @throws IOException + * @throws GeneralSecurityException + */ + public static SSLConnectionSocketFactory getFactory( + String host, SrmExtension extension, String fingerprint, boolean acceptPermanently) + throws IOException, GeneralSecurityException { + SSLConnectionSocketFactory instance = fingerprintFactoriesByHost.get(host); + if (instance == null) { + initializeFactory(host, extension, fingerprint, acceptPermanently); + return fingerprintFactoriesByHost.get(host); + } else { + return instance; + } + } + + /** + * Determines the location for the truststore file for the given host. Each {@link + * SSLConnectionSocketFactory} returned by {@link #initializeFactory(String, SrmExtension, + * String, boolean)} needs to have a file to store user-accepted invalid certificates; these + * files will be stored in the user's OS-appropriate "appdata" directory. + * + * @param host A URL hostname, e.g. "www.google.com" + * @return The file where the trust store for the given host should be stored + */ + private static File getTrustStoreForHost(String host) { + String OS = System.getProperty("os.name").toUpperCase(); + Path env; + if (OS.contains("WIN")) { + env = Paths.get(System.getenv("APPDATA"), "Software Risk Manager", "ZAP"); + } else if (OS.contains("MAC")) { + env = + Paths.get( + System.getProperty("user.home"), + "Library", + "Application Support", + "Software Risk Manager", + "ZAP"); + } else if (OS.contains("NUX")) { + env = Paths.get(System.getProperty("user.home"), ".srm", "zap"); + } else { + env = Paths.get(System.getProperty("user.dir"), "srm", "zap"); + } + + File keystoreDir = new File(env.toFile(), ".usertrust"); + keystoreDir.mkdirs(); + + // Host may only contain alphanumerics, dash, and dot. + // Replace anything else with an underscore. + String safeHost = host.replaceAll("[^a-zA-Z0-9\\-\\.]", "_"); + + // /.usertrust/.truststore + return new File(keystoreDir, safeHost + ".truststore"); + } + + /** + * Creates a new SSLConnectionSocketFactory with the behavior described in + * {@link #getFactory(String, SrmExtension)}. Instead of returning, this + * method registers the factory instance to the factoriesByHost + * map, as well as registering its ExtraCertManager to the + * certManagersByHost map. The cert manager registration is + * important in order to detect and purge trusted certificates on a per-host + * basis. + * + * @param host + * @param extension + * @throws IOException + * @throws GeneralSecurityException + */ + private static void initializeFactory( + String host, SrmExtension extension, String fingerprint, boolean acceptPermanently) + throws IOException, GeneralSecurityException { + // set up the certificate management + File managedKeyStoreFile = getTrustStoreForHost(host); + ExtraCertManager certManager = + new SingleExtraCertManager(managedKeyStoreFile, "u9lwIfUpaN"); + + // get the default hostname verifier that gets used by the modified one + // and the invalid cert dialog + HostnameVerifier defaultHostnameVerifier = new DefaultHostnameVerifier(); + + InvalidCertificateStrategy invalidCertStrat; + if (fingerprint == null) { + invalidCertStrat = + new InvalidCertificateDialogStrategy(defaultHostnameVerifier, host, extension); + } else { + invalidCertStrat = + new InvalidCertificateFingerprintStrategy(fingerprint, acceptPermanently); + } + + /* + * Set up a composite trust manager that uses the default trust manager + * before delegating to the "reloadable" trust manager that allows users + * to accept invalid certificates. + */ + List trustManagersForComposite = new LinkedList<>(); + X509TrustManager systemTrustManager = getDefaultTrustManager(); + ReloadableX509TrustManager customTrustManager = + new ReloadableX509TrustManager(certManager, invalidCertStrat); + trustManagersForComposite.add(systemTrustManager); + trustManagersForComposite.add(customTrustManager); + X509TrustManager trustManager = new CompositeX509TrustManager(trustManagersForComposite); + + // setup the SSLContext using the custom trust manager + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, new TrustManager[]{trustManager}, null); + // the actual hostname verifier that will be used with the socket + // factory + Set allowedHosts = new HashSet<>(); + allowedHosts.add(host); + HostnameVerifier modifiedHostnameVerifier = + new HostnameVerifierWithExceptions(defaultHostnameVerifier, allowedHosts); + + SSLConnectionSocketFactory factory = + new SSLConnectionSocketFactory(sslContext, modifiedHostnameVerifier); + // Register the `factory` and the `customTrustManager` under the given + // `host` + if (fingerprint == null) { + dialogFactoriesByHost.put(host, factory); + } else { + fingerprintFactoriesByHost.put(host, factory); + } + } + + private static X509TrustManager getDefaultTrustManager() + throws NoSuchAlgorithmException, KeyStoreException { + TrustManagerFactory defaultFactory = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + defaultFactory.init((KeyStore) null); + + TrustManager[] managers = defaultFactory.getTrustManagers(); + for (TrustManager mgr : managers) { + if (mgr instanceof X509TrustManager) { + return (X509TrustManager) mgr; + } + } + + return null; + } +} diff --git a/src/main/java/com/blackduck/zap/srm/security/SingleExtraCertManager.java b/src/main/java/com/blackduck/zap/srm/security/SingleExtraCertManager.java new file mode 100644 index 0000000..9b91770 --- /dev/null +++ b/src/main/java/com/blackduck/zap/srm/security/SingleExtraCertManager.java @@ -0,0 +1,128 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2025 The ZAP Development Team + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.blackduck.zap.srm.security; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.Certificate; + +/** + * ExtraCertManager implementation that only allows a single accepted certificate at once. Any time + * a certificate is added (be it temporarily or permanently), any previous certificates will be + * forgotten. At any given time, the {@link #asKeyStore()} method should return a KeyStore with 0 or + * 1 certificates registered. + */ +public class SingleExtraCertManager implements ExtraCertManager { + + private final File keystoreFile; + private final char[] password; + private boolean isUsingFile; + private Certificate tempCert = null; + + public SingleExtraCertManager(File keystoreFile, String password) { + this.keystoreFile = keystoreFile; + this.password = password.toCharArray(); + isUsingFile = true; + } + + @Override + public void addTemporaryCert(Certificate cert) { + if (isUsingFile) { + keystoreFile.delete(); + } + isUsingFile = false; + tempCert = cert; + } + + @Override + public void addPermanentCert(Certificate cert) throws IOException, GeneralSecurityException { + tempCert = null; + isUsingFile = true; + + // create a keystore and put the cert in it + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(null, password); + ks.setCertificateEntry("default", cert); + + // store the new keystore to the keystoreFile + FileOutputStream out = new FileOutputStream(keystoreFile); + try { + ks.store(out, password); + } finally { + out.close(); + } + } + + @Override + public void purgeTemporaryCerts() { + isUsingFile = true; + tempCert = null; + } + + @Override + public void purgePermanentCerts() { + if (isUsingFile) { + // keep the flag, but delete the file + keystoreFile.delete(); + } + } + + @Override + public void purgeAllCerts() { + isUsingFile = true; + tempCert = null; + keystoreFile.delete(); + } + + @Override + public KeyStore asKeyStore() throws IOException, GeneralSecurityException { + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + + if (isUsingFile) { + // load from the file, as long as it exists + if (keystoreFile.canRead()) { + FileInputStream in = new FileInputStream(keystoreFile); + try { + ks.load(in, password); + } finally { + in.close(); + } + } else { + ks.load(null, password); + } + } else { + ks.load(null, password); + // insert the tempCert to the keystore + if (tempCert != null) { + ks.setCertificateEntry("default", tempCert); + } + } + + if (ks.aliases().hasMoreElements()) { + return ks; + } else { + return null; + } + } +} diff --git a/src/main/java/com/github/srm/zap/srm/ExtensionAlertHttp.java b/src/main/java/com/github/srm/zap/srm/ExtensionAlertHttp.java deleted file mode 100644 index 9a51906..0000000 --- a/src/main/java/com/github/srm/zap/srm/ExtensionAlertHttp.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm; - -import java.util.List; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.parosproxy.paros.Constant; -import org.parosproxy.paros.core.scanner.Alert; -import org.parosproxy.paros.model.SiteNode; -import org.parosproxy.paros.network.HttpMessage; - -public class ExtensionAlertHttp { - - private static final Logger LOGGER = LogManager.getLogger(ExtensionAlertHttp.class); - - public ExtensionAlertHttp() {} - - public String getXml(SiteNode site) { - StringBuilder xml = new StringBuilder(); - xml.append(""); - List alerts = site.getAlerts(); - for (Alert alert : alerts) { - if (alert.getConfidence() != Alert.CONFIDENCE_FALSE_POSITIVE) { - String urlParamXML = getUrlParamXML(alert); - xml.append(alert.toPluginXML(urlParamXML)); - } - } - xml.append(""); - return xml.toString(); - } - - private String getHTML(Alert alert) { - // gets HttpMessage request and response data from each alert and removes illegal and - // special characters - StringBuilder httpMessage = new StringBuilder(); - - HttpMessage message = alert.getMessage(); - - if (message == null) { - LOGGER.warn(Constant.messages.getString("srm.error.httpMessage", alert.getAlertId())); - return httpMessage.toString(); - } - - String requestHeader = message.getRequestHeader().toString(); - String requestBody = message.getRequestBody().toString(); - String responseHeader = message.getResponseHeader().toString(); - String responseBody = message.getResponseBody().toString(); - - httpMessage.append(""); - httpMessage.append(ReportGenerator.entityEncode(requestHeader)); - httpMessage.append(ReportGenerator.entityEncode(requestBody)); - httpMessage.append("\n\n"); - httpMessage.append(""); - httpMessage.append(ReportGenerator.entityEncode(responseHeader)); - httpMessage.append(ReportGenerator.entityEncode(responseBody)); - httpMessage.append("\n\n"); - - return httpMessage.toString(); - } - - public String getUrlParamXML(Alert alert) { - - String uri = alert.getUri(); - String param = alert.getParam(); - String attack = alert.getAttack(); - String otherInfo = alert.getOtherInfo(); - String evidence = alert.getEvidence(); - - StringBuilder sb = new StringBuilder(200); // ZAP: Changed the type to StringBuilder. - sb.append(getHTML(alert)); - sb.append(" ").append(ReportGenerator.entityEncode(uri)).append("\r\n"); - sb.append(" ").append(ReportGenerator.entityEncode(param)).append("\r\n"); - sb.append(" ") - .append(ReportGenerator.entityEncode(attack)) - .append("\r\n"); - if (evidence != null && evidence.length() > 0) { - sb.append(" ") - .append(ReportGenerator.entityEncode(evidence)) - .append("\r\n"); - } - sb.append(" ") - .append(ReportGenerator.entityEncode(otherInfo)) - .append("\r\n"); - return sb.toString(); - } -} diff --git a/src/main/java/com/github/srm/zap/srm/ReportGenerator.java b/src/main/java/com/github/srm/zap/srm/ReportGenerator.java deleted file mode 100644 index de82583..0000000 --- a/src/main/java/com/github/srm/zap/srm/ReportGenerator.java +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2003-2004 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.text.SimpleDateFormat; -import java.util.Date; -import javax.swing.JOptionPane; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import javax.xml.transform.stream.StreamSource; -import net.sf.json.JSONArray; -import net.sf.json.JSONObject; -import net.sf.json.xml.XMLSerializer; -import org.apache.commons.text.StringEscapeUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.parosproxy.paros.Constant; -import org.parosproxy.paros.view.View; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.zaproxy.zap.utils.XMLStringUtil; -import org.zaproxy.zap.utils.XmlUtils; - -public class ReportGenerator { - - private static final Logger LOGGER = LogManager.getLogger(ReportGenerator.class); - - // private static Pattern patternWindows = Pattern.compile("window", Pattern.CASE_INSENSITIVE); - // private static Pattern patternLinux = Pattern.compile("linux", Pattern.CASE_INSENSITIVE); - - private static final SimpleDateFormat staticDateFormat = - new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss"); - - public static File XMLToHtml(Document xmlDocument, String infilexsl, File outFile) { - File stylesheet = null; - - outFile = new File(outFile.getAbsolutePath()); - try { - stylesheet = new File(infilexsl); - - DOMSource source = new DOMSource(xmlDocument); - - // Use a Transformer for output - TransformerFactory tFactory = TransformerFactory.newInstance(); - StreamSource stylesource = new StreamSource(stylesheet); - Transformer transformer = tFactory.newTransformer(stylesource); - - // Make the transformation and write to the output file - StreamResult result = new StreamResult(outFile.getPath()); - transformer.transform(source, result); - - } catch (TransformerException e) { - LOGGER.error(e.getMessage(), e); - } - - return outFile; - } - - public static File stringToHtml(String inxml, String infilexsl, String outfilename) { - return stringToHtml( - inxml, - infilexsl != null ? new StreamSource(new File(infilexsl)) : null, - outfilename); - } - - public static File stringToHtml(String inxml, StreamSource stylesource, String outfilename) { - if (stylesource != null) { - Document doc = null; - - // factory.setNamespaceAware(true); - // factory.setValidating(true); - File outfile = null; - StringReader inReader = new StringReader(inxml); - String tempOutfilename = outfilename + ".temp"; - - try { - outfile = new File(tempOutfilename); - - DocumentBuilder builder = - XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); - doc = builder.parse(new InputSource(inReader)); - - // Use a Transformer for output - TransformerFactory tFactory = TransformerFactory.newInstance(); - Transformer transformer = tFactory.newTransformer(stylesource); - transformer.setParameter("datetime", getCurrentDateTimeString()); - - DOMSource source = new DOMSource(doc); - StreamResult result = new StreamResult(outfile.getPath()); - transformer.transform(source, result); - - } catch (TransformerException - | SAXException - | ParserConfigurationException - | IOException e) { - LOGGER.error(e.getMessage(), e); - // Save the xml for diagnosing the problem - BufferedWriter bw = null; - showDialogForGUI(); - try { - bw = - Files.newBufferedWriter( - new File(outfilename + "-orig.xml").toPath(), - StandardCharsets.UTF_8); - bw.write(inxml); - } catch (IOException e2) { - LOGGER.error("Failed to write debug XML file", e); - return new File(outfilename); - } finally { - try { - if (bw != null) { - bw.close(); - } - } catch (IOException ex) { - } - } - return new File(outfilename); - } finally { - - } - // Replace the escaped tags used to make the report look slightly better. - // This is a temp fix to ensure reports always get generated - // we should really adopt something other than XSLT ;) - String line; - - try (BufferedReader br = - Files.newBufferedReader( - new File(tempOutfilename).toPath(), StandardCharsets.UTF_8); - BufferedWriter bw = - Files.newBufferedWriter( - new File(outfilename).toPath(), StandardCharsets.UTF_8)) { - - while ((line = br.readLine()) != null) { - bw.write(line.replace("<p>", "

").replace("</p>", "

")); - bw.newLine(); - } - - } catch (IOException e) { - showDialogForGUI(); - LOGGER.error(e.getMessage(), e); - } - // Remove the temporary file - outfile.delete(); - } else { - // No XSLT file specified, just output the XML straight to the file - BufferedWriter bw = null; - - try { - bw = - Files.newBufferedWriter( - new File(outfilename).toPath(), StandardCharsets.UTF_8); - bw.write(inxml); - } catch (IOException e2) { - showDialogForGUI(); - LOGGER.error(e2.getMessage(), e2); - } finally { - try { - if (bw != null) { - bw.close(); - } - } catch (IOException ex) { - } - } - } - - return new File(outfilename); - } - - public static File stringToJson(String inxml, String outfilename) { - BufferedWriter bw = null; - try { - bw = Files.newBufferedWriter(new File(outfilename).toPath(), StandardCharsets.UTF_8); - bw.write(stringToJson(inxml)); - } catch (IOException e2) { - showDialogForGUI(); - LOGGER.error(e2.getMessage(), e2); - } finally { - try { - if (bw != null) { - bw.close(); - } - } catch (IOException ex) { - } - } - - return new File(outfilename); - } - - public static String stringToHtml(String inxml, String infilexsl) { - return stringToHtml(inxml, new StreamSource(new File(infilexsl))); - } - - public static String stringToHtml(String inxml, StreamSource stylesource) { - Document doc = null; - - StringReader inReader = new StringReader(inxml); - StringWriter writer = new StringWriter(); - - try { - - DocumentBuilder builder = - XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); - doc = builder.parse(new InputSource(inReader)); - - // Use a Transformer for output - TransformerFactory tFactory = TransformerFactory.newInstance(); - Transformer transformer = tFactory.newTransformer(stylesource); - transformer.setParameter("datetime", getCurrentDateTimeString()); - - DOMSource source = new DOMSource(doc); - StreamResult result = new StreamResult(writer); - transformer.transform(source, result); - - } catch (TransformerException - | SAXException - | ParserConfigurationException - | IOException e) { - showDialogForGUI(); - LOGGER.error(e.getMessage(), e); - } finally { - - } - - // Replace the escaped tags used to make the report look slightly better. - // This is a temp fix to ensure reports always get generated - // we should really adopt something other than XSLT ;) - return writer.toString().replace("<p>", "

").replace("</p>", "

"); - } - - public static File fileToHtml(String infilexml, String infilexsl, String outfilename) { - Document doc = null; - - // factory.setNamespaceAware(true); - // factory.setValidating(true); - File stylesheet = null; - File datafile = null; - File outfile = null; - - try { - stylesheet = new File(infilexsl); - datafile = new File(infilexml); - outfile = new File(outfilename); - - DocumentBuilder builder = - XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); - doc = builder.parse(datafile); - - // Use a Transformer for output - TransformerFactory tFactory = TransformerFactory.newInstance(); - StreamSource stylesource = new StreamSource(stylesheet); - Transformer transformer = tFactory.newTransformer(stylesource); - transformer.setParameter("datetime", getCurrentDateTimeString()); - - DOMSource source = new DOMSource(doc); - StreamResult result = new StreamResult(outfile.getPath()); - transformer.transform(source, result); - - } catch (TransformerException - | SAXException - | ParserConfigurationException - | IOException e) { - showDialogForGUI(); - LOGGER.error(e.getMessage(), e); - } finally { - - } - - return outfile; - } - - public static String stringToJson(String inxml) { - JSONObject report = (JSONObject) new XMLSerializer().read(inxml); - Object site = report.get("site"); - if (!(site instanceof JSONArray)) { - JSONArray siteArray = new JSONArray(); - if (site != null) { - siteArray.add(site); - } - report.put("site", siteArray); - } - return report.toString(); - } - - /** Encode entity for HTML or XML output. */ - public static String entityEncode(String text) { - String result = text; - - if (result == null) { - return result; - } - - // The escapeXml function doesn't cope with some 'special' chrs - - return StringEscapeUtils.escapeXml10(XMLStringUtil.escapeControlChrs(result)); - } - - /** Get today's date string. */ - public static String getCurrentDateTimeString() { - Date dateTime = new Date(System.currentTimeMillis()); - return getDateTimeString(dateTime); - } - - public static String getDateTimeString(Date dateTime) { - // ZAP: fix unsafe call to DateFormats - synchronized (staticDateFormat) { - return staticDateFormat.format(dateTime); - } - } - - public static void addChildTextNode( - Document doc, Element parent, String nodeName, String text) { - Element child = doc.createElement(nodeName); - child.appendChild(doc.createTextNode(text)); - parent.appendChild(child); - } - - public static String getDebugXMLString(Document doc) throws TransformerException { - TransformerFactory tf = TransformerFactory.newInstance(); - Transformer transformer = tf.newTransformer(); - transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); - StringWriter writer = new StringWriter(); - transformer.transform(new DOMSource(doc), new StreamResult(writer)); - return writer.getBuffer().toString().replaceAll("\n|\r", ""); - } - - private static void showDialogForGUI() { - if (View.isInitialised()) { - JOptionPane.showMessageDialog( - null, Constant.messages.getString("report.write.dialog.message")); - } - } -} diff --git a/src/main/java/com/github/srm/zap/srm/ReportLastScan.java b/src/main/java/com/github/srm/zap/srm/ReportLastScan.java deleted file mode 100644 index 1b42d53..0000000 --- a/src/main/java/com/github/srm/zap/srm/ReportLastScan.java +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2003-2004 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Locale; -import javax.swing.JFileChooser; -import javax.swing.filechooser.FileFilter; -import javax.xml.transform.stream.StreamSource; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.parosproxy.paros.Constant; -import org.parosproxy.paros.control.Control; -import org.parosproxy.paros.extension.Extension; -import org.parosproxy.paros.extension.ExtensionLoader; -import org.parosproxy.paros.extension.ViewDelegate; -import org.parosproxy.paros.model.Model; -import org.parosproxy.paros.model.SiteMap; -import org.parosproxy.paros.model.SiteNode; -import org.parosproxy.paros.view.View; -import org.zaproxy.zap.extension.XmlReporterExtension; -import org.zaproxy.zap.utils.DesktopUtils; -import org.zaproxy.zap.utils.XMLStringUtil; -import org.zaproxy.zap.view.ScanPanel; -import org.zaproxy.zap.view.widgets.WritableFileChooser; - -public class ReportLastScan { - - private static final Logger LOGGER = LogManager.getLogger(ReportLastScan.class); - - private static final String HTM_FILE_EXTENSION = ".htm"; - private static final String HTML_FILE_EXTENSION = ".html"; - private static final String XML_FILE_EXTENSION = ".xml"; - private static final String MD_FILE_EXTENSION = ".md"; - private static final String JSON_FILE_EXTENSION = ".json"; - - public enum ReportType { - HTML, - XML, - MD, - JSON - } - - public ReportLastScan() {} - - /** - * @deprecated generate has been deprecated in favor of using {@link #generate(String fileName, - * ReportType reportType)} - */ - @Deprecated - public File generate(String fileName, Model model, String xslFile) throws Exception { - StringBuilder sb = new StringBuilder(500); - this.generate(sb); - return ReportGenerator.stringToHtml(sb.toString(), xslFile, fileName); - } - - /** - * @deprecated generate has been deprecated in favor of using {@link #generate(String filename, - * ReportType reportType)} - */ - @Deprecated - public File generate(String fileName, Model model, ReportType reportType) throws Exception { - return generate(fileName, reportType); - } - - public File generate(String fileName, ReportType reportType) throws Exception { - StringBuilder sb = new StringBuilder(500); - this.generate(sb); - if (reportType == ReportType.JSON) { - return ReportGenerator.stringToJson(sb.toString(), fileName); - } - - if (reportType == ReportType.XML) { - return ReportGenerator.stringToHtml(sb.toString(), (String) null, fileName); - } - - String xslFileName = reportType == ReportType.MD ? "report.md.xsl" : "report.html.xsl"; - return generateReportWithXsl(sb.toString(), fileName, xslFileName); - } - - private static File generateReportWithXsl(String report, String reportFile, String xslFileName) - throws IOException { - Path xslFile = Paths.get(Constant.getZapInstall(), "xml", xslFileName); - if (Files.exists(xslFile)) { - return ReportGenerator.stringToHtml(report, xslFile.toString(), reportFile); - } - - String path = "/org/zaproxy/zap/resources/xml/" + xslFileName; - try (InputStream is = ReportLastScan.class.getResourceAsStream(path)) { - if (is == null) { - LOGGER.error("Bundled file not found: {}", path); - return new File(reportFile); - } - return ReportGenerator.stringToHtml(report, new StreamSource(is), reportFile); - } - } - - /** - * @deprecated generate has been deprecated in favor of using {@link #generate(StringBuilder - * report)} - */ - @Deprecated - public void generate(StringBuilder report, Model model) throws Exception { - generate(report); - } - - public void generate(StringBuilder report) throws Exception { - report.append(""); - report.append("\r\n"); - siteXML(report); - report.append(""); - } - - private void siteXML(StringBuilder report) { - SiteMap siteMap = Model.getSingleton().getSession().getSiteTree(); - SiteNode root = siteMap.getRoot(); - int siteNumber = root.getChildCount(); - for (int i = 0; i < siteNumber; i++) { - SiteNode site = (SiteNode) root.getChildAt(i); - String siteName = ScanPanel.cleanSiteName(site, true); - String[] hostAndPort = siteName.split(":"); - boolean isSSL = (site.getNodeName().startsWith("https")); - String siteStart = - ""; - StringBuilder extensionsXML = getExtensionsXML(site); - String siteEnd = ""; - report.append(siteStart); - report.append(extensionsXML); - report.append(siteEnd); - } - } - - public StringBuilder getExtensionsXML(SiteNode site) { - StringBuilder extensionXml = new StringBuilder(); - ExtensionLoader loader = Control.getSingleton().getExtensionLoader(); - int extensionCount = loader.getExtensionCount(); - for (int i = 0; i < extensionCount; i++) { - Extension extension = loader.getExtension(i); - if (extension instanceof XmlReporterExtension) { - extensionXml.append(((XmlReporterExtension) extension).getXml(site)); - } - } - return extensionXml; - } - - /** - * @deprecated generate has been deprecated in favor of using {@link - * #generateReport(ViewDelegate view, ReportType reportType)} - */ - @Deprecated - public void generateReport(ViewDelegate view, Model model, ReportType reportType) { - generateReport(view, reportType); - } - - /** - * Generates a report. Defaults to HTML report if reportType is null. - * - * @param view - * @param reportType - */ - public void generateReport(ViewDelegate view, ReportType reportType) { - // ZAP: Allow scan report file name to be specified - - final ReportType localReportType; - - if (reportType == null) { - localReportType = ReportType.HTML; - } else { - localReportType = reportType; - } - - try { - JFileChooser chooser = - new WritableFileChooser( - Model.getSingleton().getOptionsParam().getUserDirectory()); - - chooser.setFileFilter( - new FileFilter() { - - @Override - public boolean accept(File file) { - if (file.isDirectory()) { - return true; - } else if (file.isFile()) { - String lcFileName = file.getName().toLowerCase(Locale.ROOT); - switch (localReportType) { - case XML: - return lcFileName.endsWith(XML_FILE_EXTENSION); - case MD: - return lcFileName.endsWith(MD_FILE_EXTENSION); - case JSON: - return lcFileName.endsWith(JSON_FILE_EXTENSION); - case HTML: - default: - return (lcFileName.endsWith(HTM_FILE_EXTENSION) - || lcFileName.endsWith(HTML_FILE_EXTENSION)); - } - } - return false; - } - - @Override - public String getDescription() { - switch (localReportType) { - case XML: - return Constant.messages.getString("file.format.xml"); - case MD: - return Constant.messages.getString("file.format.md"); - case JSON: - return Constant.messages.getString("file.format.json"); - case HTML: - default: - return Constant.messages.getString("file.format.html"); - } - } - }); - - String fileExtension = ""; - switch (localReportType) { - case XML: - fileExtension = XML_FILE_EXTENSION; - break; - case JSON: - fileExtension = JSON_FILE_EXTENSION; - break; - case MD: - fileExtension = MD_FILE_EXTENSION; - break; - case HTML: - default: - fileExtension = HTML_FILE_EXTENSION; - break; - } - chooser.setSelectedFile( - new File(fileExtension)); // Default the filename to a reasonable extension; - - int rc = chooser.showSaveDialog(View.getSingleton().getMainFrame()); - File file = null; - if (rc == JFileChooser.APPROVE_OPTION) { - file = chooser.getSelectedFile(); - - File report = generate(file.getAbsolutePath(), localReportType); - if (report == null) { - view.showMessageDialog( - Constant.messages.getString( - "report.unknown.error", file.getAbsolutePath())); - return; - } - - if (Files.notExists(report.toPath())) { - LOGGER.info("Not opening report, does not exist: {}", report); - return; - } - - try { - DesktopUtils.openUrlInBrowser(report.toURI()); - } catch (Exception e) { - LOGGER.error(e.getMessage(), e); - view.showMessageDialog( - Constant.messages.getString( - "report.complete.warning", report.getAbsolutePath())); - } - } - - } catch (Exception e) { - LOGGER.error(e.getMessage(), e); - view.showWarningDialog(Constant.messages.getString("report.unexpected.error")); - } - } - - /** - * @deprecated generateHtml has been deprecated in favor of using {@link - * #generateReport(ViewDelegate, Model, ReportType)} - */ - @Deprecated - public void generateHtml(ViewDelegate view, Model model) { - generateReport(view, model, ReportType.HTML); - } - - /** - * @deprecated generateXml has been deprecated in favor of using {@link - * #generateReport(ViewDelegate, Model, ReportType)} - */ - @Deprecated - public void generateXml(ViewDelegate view, Model model) { - generateReport(view, model, ReportType.XML); - } -} diff --git a/src/main/java/com/github/srm/zap/srm/SrmAPI.java b/src/main/java/com/github/srm/zap/srm/SrmAPI.java deleted file mode 100644 index 8c52117..0000000 --- a/src/main/java/com/github/srm/zap/srm/SrmAPI.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm; - -import java.io.File; -import java.io.IOException; -import java.security.GeneralSecurityException; -import net.sf.json.JSONObject; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.zaproxy.zap.extension.api.ApiAction; -import org.zaproxy.zap.extension.api.ApiException; -import org.zaproxy.zap.extension.api.ApiException.Type; -import org.zaproxy.zap.extension.api.ApiImplementor; -import org.zaproxy.zap.extension.api.ApiResponse; -import org.zaproxy.zap.extension.api.ApiResponseElement; -import org.zaproxy.zap.extension.api.ApiView; - -public class SrmAPI extends ApiImplementor { - - private static final Logger LOGGER = LogManager.getLogger(SrmExtension.class); - - private static final String PREFIX = "codedx"; - - private static final String VIEW_GENERATE = "generateReport"; - private static final String ACTION_UPLOAD = "uploadReport"; - private static final String ACTION_GEN_UPLOAD = "generateAndUpload"; - - private static final String ACTION_PARAM_FILE_PATH = "filePath"; - private static final String ACTION_PARAM_SERVER_URL = "serverUrl"; - private static final String ACTION_PARAM_API_KEY = "codeDxApiKey"; - private static final String ACTION_PARAM_PROJECT = "projectId"; - - // Optional - private static final String ACTION_PARAM_FINGERPRINT = "fingerprint"; - private static final String ACTION_PARAM_ACCEPT_PERM = "acceptPermanently"; - - private SrmExtension extension; - - public SrmAPI(SrmExtension extension) { - this.extension = extension; - initApiViewsAndActions(); - } - - private void initApiViewsAndActions() { - this.addApiView(new ApiView(VIEW_GENERATE)); - - String[] optionalParams = new String[] {ACTION_PARAM_FINGERPRINT, ACTION_PARAM_ACCEPT_PERM}; - - this.addApiAction( - new ApiAction( - ACTION_UPLOAD, - new String[] { - ACTION_PARAM_FILE_PATH, - ACTION_PARAM_SERVER_URL, - ACTION_PARAM_API_KEY, - ACTION_PARAM_PROJECT - }, - optionalParams)); - this.addApiAction( - new ApiAction( - ACTION_GEN_UPLOAD, - new String[] { - ACTION_PARAM_SERVER_URL, ACTION_PARAM_API_KEY, ACTION_PARAM_PROJECT - }, - optionalParams)); - } - - @Override - public String getPrefix() { - return PREFIX; - } - - @Override - public ApiResponse handleApiAction(String name, JSONObject params) throws ApiException { - if (ACTION_UPLOAD.equals(name)) { - File reportFile = new File(params.getString(ACTION_PARAM_FILE_PATH)); - String serverUrl = params.getString(ACTION_PARAM_SERVER_URL); - String apiKey = params.getString(ACTION_PARAM_API_KEY); - String projectId = params.getString(ACTION_PARAM_PROJECT); - - String fingerprint = this.getParam(params, ACTION_PARAM_FINGERPRINT, ""); - boolean acceptPermanently = this.getParam(params, ACTION_PARAM_ACCEPT_PERM, false); - - uploadFile(reportFile, serverUrl, apiKey, projectId, fingerprint, acceptPermanently); - return ApiResponseElement.OK; - } else if (ACTION_GEN_UPLOAD.equals(name)) { - File reportFile; - String serverUrl = params.getString(ACTION_PARAM_SERVER_URL); - String apiKey = params.getString(ACTION_PARAM_API_KEY); - String projectId = params.getString(ACTION_PARAM_PROJECT); - - String fingerprint = this.getParam(params, ACTION_PARAM_FINGERPRINT, ""); - boolean acceptPermanently = this.getParam(params, ACTION_PARAM_ACCEPT_PERM, false); - - boolean isEmpty = false; - try { - reportFile = UploadActionListener.generateReportFile(extension); - isEmpty = UploadActionListener.reportIsEmpty(reportFile); - } catch (Exception e) { - LOGGER.error(e.getMessage(), e); - throw new ApiException(Type.INTERNAL_ERROR, e.getMessage()); - } - try { - if (!isEmpty) - uploadFile( - reportFile, - serverUrl, - apiKey, - projectId, - fingerprint, - acceptPermanently); - else return new ApiResponseElement("Result", "empty"); - } finally { - reportFile.delete(); - } - return ApiResponseElement.OK; - } - throw new ApiException(Type.BAD_ACTION); - } - - @Override - public ApiResponse handleApiView(String name, JSONObject params) throws ApiException { - if (VIEW_GENERATE.equals(name)) { - try { - StringBuilder report = new StringBuilder(); - UploadActionListener.generateReportString(extension, report); - return new ApiResponseElement(name, report.toString()); - } catch (Exception e) { - LOGGER.error(e.getMessage(), e); - throw new ApiException(Type.INTERNAL_ERROR, e.getMessage()); - } - } - throw new ApiException(Type.BAD_VIEW); - } - - private void uploadFile( - File reportFile, - String serverUrl, - String apiKey, - String project, - String fingerprint, - boolean acceptPermanently) - throws ApiException { - if (serverUrl.endsWith("/")) serverUrl = serverUrl.substring(0, serverUrl.length() - 1); - try { - CloseableHttpClient client = - extension.getHttpClient(serverUrl, fingerprint, acceptPermanently); - String err = - UploadActionListener.uploadFile(client, reportFile, serverUrl, apiKey, project); - if (err != null) { - LOGGER.error(err); - throw new ApiException(Type.ILLEGAL_PARAMETER, err); - } - } catch (GeneralSecurityException | IOException e) { - LOGGER.error(e.getMessage(), e); - throw new ApiException(Type.ILLEGAL_PARAMETER, e.getMessage()); - } - } -} diff --git a/src/main/java/com/github/srm/zap/srm/SrmExtension.java b/src/main/java/com/github/srm/zap/srm/SrmExtension.java deleted file mode 100644 index 7aa5558..0000000 --- a/src/main/java/com/github/srm/zap/srm/SrmExtension.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm; - -import com.github.srm.zap.srm.ReportLastScan.ReportType; -import com.github.srm.zap.srm.security.SSLConnectionSocketFactoryFactory; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.security.GeneralSecurityException; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.parosproxy.paros.Constant; -import org.parosproxy.paros.extension.ExtensionAdaptor; -import org.parosproxy.paros.extension.ExtensionHook; -import org.parosproxy.paros.model.Model; -import org.parosproxy.paros.network.ConnectionParam; -import org.parosproxy.paros.view.View; -import org.zaproxy.zap.extension.api.API; -import org.zaproxy.zap.view.ZapMenuItem; - -/* - * The Software Risk Manager ZAP extension used to include request and response data in alert reports. - * - */ -public class SrmExtension extends ExtensionAdaptor { - - private static final Logger LOGGER = LogManager.getLogger(SrmExtension.class); - - private SrmAPI cdxAPIImpl; - protected static final String PREFIX = "srm"; - - // The name is public so that other extensions can access it - public static final String NAME = "SrmExtension"; - - private ZapMenuItem menuUpload = null; - private ZapMenuItem menuExport = null; - - public SrmExtension() { - super(NAME); - } - - @Override - public boolean canUnload() { - return true; - } - - @Override - public void hook(ExtensionHook extensionHook) { - super.hook(extensionHook); - cdxAPIImpl = new SrmAPI(this); - API.getInstance().registerApiImplementor(cdxAPIImpl); - if (hasView()) { - extensionHook.getHookMenu().addReportMenuItem(getUploadMenu()); - extensionHook.getHookMenu().addReportMenuItem(getExportMenu()); - } - } - - @Override - public void unload() { - API.getInstance().removeApiImplementor(cdxAPIImpl); - } - - public ZapMenuItem getUploadMenu() { - if (menuUpload == null) { - menuUpload = new ZapMenuItem("srm.topmenu.upload.title"); - menuUpload.addActionListener(new UploadActionListener(this)); - } - return menuUpload; - } - - public ZapMenuItem getExportMenu() { - if (menuExport == null) { - menuExport = new ZapMenuItem("srm.topmenu.report.title"); - - menuExport.addActionListener( - e -> { - ReportLastScanHttp saver = new ReportLastScanHttp(); - saver.generateReport(getView(), ReportType.XML); - }); - } - return menuExport; - } - - public CloseableHttpClient getHttpClient() { - try { - return getHttpClient(SrmProperties.getInstance().getServerUrl()); - } catch (MalformedURLException e) { - View.getSingleton() - .showWarningDialog(Constant.messages.getString("srm.error.client.invalid")); - } catch (IOException | GeneralSecurityException e) { - View.getSingleton() - .showWarningDialog(Constant.messages.getString("srm.error.client.failed")); - } - return null; - } - - public CloseableHttpClient getHttpClient(String url) - throws IOException, GeneralSecurityException { - return getHttpClient(url, null, false); - } - - @SuppressWarnings("deprecation") - public CloseableHttpClient getHttpClient( - String url, String fingerprint, boolean acceptPermanently) - throws IOException, GeneralSecurityException { - RequestConfig.Builder configBuilder = - RequestConfig.custom() - .setConnectTimeout(getTimeout()) - .setSocketTimeout(getTimeout()) - .setConnectionRequestTimeout(getTimeout()); - - HttpClientBuilder builder = HttpClientBuilder.create(); - if (fingerprint != null) { - builder.setSSLSocketFactory( - SSLConnectionSocketFactoryFactory.getFactory( - URI.create(url).getHost(), this, fingerprint, acceptPermanently)); - } else { - builder.setSSLSocketFactory( - SSLConnectionSocketFactoryFactory.getFactory(URI.create(url).getHost(), this)); - } - - // --- ZAP Proxy Support --- - ConnectionParam connParam = Model.getSingleton().getOptionsParam().getConnectionParam(); - if (connParam.isUseProxyChain()) { - String proxyHost = connParam.getProxyChainName(); - int proxyPort = connParam.getProxyChainPort(); - HttpHost proxy = new HttpHost(proxyHost, proxyPort); - configBuilder.setProxy(proxy); - - if (connParam.isUseProxyChainAuth()) { - BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials( - new AuthScope(proxyHost, proxyPort), - new UsernamePasswordCredentials( - connParam.getProxyChainUserName(), - connParam.getProxyChainPassword())); - builder.setDefaultCredentialsProvider(credsProvider); - } - } - // --- End ZAP Proxy Support --- - - builder.setDefaultRequestConfig(configBuilder.build()); - return builder.build(); - } - - @Override - public String getDescription() { - return Constant.messages.getString("srm.desc"); - } - - @Override - public URL getURL() { - return null; - } - - private int getTimeout() { - try { - return Integer.parseInt(SrmProperties.getInstance().getTimeout()) * 1000; - } catch (NumberFormatException e) { - // If for some reason the saved timeout value can't be parsed as an int, we will return - // the default value of 120 seconds - return SrmProperties.DEFAULT_TIMEOUT_INT; - } - } -} diff --git a/src/main/java/com/github/srm/zap/srm/SrmProperties.java b/src/main/java/com/github/srm/zap/srm/SrmProperties.java deleted file mode 100644 index f6f0f32..0000000 --- a/src/main/java/com/github/srm/zap/srm/SrmProperties.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.file.Paths; -import java.util.Properties; -import org.apache.commons.configuration.Configuration; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.parosproxy.paros.Constant; -import org.parosproxy.paros.model.Model; - -public class SrmProperties { - private static class Holder { - static final SrmProperties INSTANCE = new SrmProperties(); - } - - public static SrmProperties getInstance() { - return Holder.INSTANCE; - } - - private SrmProperties() { - loadProperties(); - } - - private static final Logger LOGGER = LogManager.getLogger(SrmProperties.class); - - private static final String PROP_FILE = "srm.properties"; - private static final String FALLBACK_PROP_FILE = "codedx.properties"; - private static final String KEY_SERVER = "serverUrl"; - private static final String KEY_API = "apiKey"; - private static final String KEY_SELECTED = "selectedId"; - private static final String KEY_TIMEOUT = "timeout"; - - // ZAP config keys with prefix - private static final String ZAP_CONFIG_PREFIX = "srm."; - private static final String ZAP_KEY_SERVER = ZAP_CONFIG_PREFIX + KEY_SERVER; - private static final String ZAP_KEY_API = ZAP_CONFIG_PREFIX + KEY_API; - private static final String ZAP_KEY_SELECTED = ZAP_CONFIG_PREFIX + KEY_SELECTED; - private static final String ZAP_KEY_TIMEOUT = ZAP_CONFIG_PREFIX + KEY_TIMEOUT; - - private Properties prop; - private File configFile; - private boolean useZapConfig = false; - - public static final String DEFAULT_TIMEOUT_STRING = "120"; - public static final int DEFAULT_TIMEOUT_INT = 120000; - - public String getServerUrl() { - String text = getProperty(KEY_SERVER); - if (text != null && text.endsWith("/")) { - return text.substring(0, text.length() - 1); - } - return text != null ? text : ""; - } - - public String getApiKey() { - return getProperty(KEY_API); - } - - public String getSelectedId() { - return getProperty(KEY_SELECTED); - } - - public String getTimeout() { - String timeout = getProperty(KEY_TIMEOUT); - if (timeout == null || timeout.isEmpty()) { - timeout = DEFAULT_TIMEOUT_STRING; - } - return timeout; - } - - private String getProperty(String key) { - if (useZapConfig) { - Configuration config = Model.getSingleton().getOptionsParam().getConfig(); - String zapKey = ZAP_CONFIG_PREFIX + key; - return config.getString(zapKey, ""); - } else { - String value = prop.getProperty(key); - return value == null ? "" : value; - } - } - - public void setProperties(String server, String api, String selectedId, String timeout) { - if (useZapConfig) { - Configuration config = Model.getSingleton().getOptionsParam().getConfig(); - config.setProperty(ZAP_KEY_SERVER, server); - config.setProperty(ZAP_KEY_API, api); - config.setProperty(ZAP_KEY_SELECTED, selectedId); - config.setProperty(ZAP_KEY_TIMEOUT, timeout); - } else { - prop.setProperty(KEY_SERVER, server); - prop.setProperty(KEY_API, api); - prop.setProperty(KEY_SELECTED, selectedId); - prop.setProperty(KEY_TIMEOUT, timeout); - saveProperties(); - } - } - - private void loadProperties() { - if (prop == null) prop = new Properties(); - - // Check for srm.properties first - File srmFile = Paths.get(Constant.getZapHome(), PROP_FILE).toFile(); - if (srmFile.exists()) { - configFile = srmFile; - loadFromFile(configFile); - return; - } - - // Check for codedx.properties fallback - File fallbackFile = Paths.get(Constant.getZapHome(), FALLBACK_PROP_FILE).toFile(); - if (fallbackFile.exists()) { - configFile = fallbackFile; - loadFromFile(configFile); - return; - } - - // Neither file exists, use ZAP config - useZapConfig = true; - LOGGER.info("Using ZAP configuration for SRM properties"); - } - - private void loadFromFile(File file) { - try (FileInputStream inp = new FileInputStream(file)) { - prop.load(inp); - LOGGER.info("Loaded SRM properties from: " + file.getName()); - } catch (IOException e) { - LOGGER.error("Error loading properties file: " + file.getName(), e); - } - } - - private void saveProperties() { - if (configFile != null) { - try (FileOutputStream out = new FileOutputStream(configFile)) { - prop.store(out, null); - } catch (IOException e) { - LOGGER.error("Error saving properties file: " + configFile.getName(), e); - } - } - } -} diff --git a/src/main/java/com/github/srm/zap/srm/UploadActionListener.java b/src/main/java/com/github/srm/zap/srm/UploadActionListener.java deleted file mode 100644 index e68afa6..0000000 --- a/src/main/java/com/github/srm/zap/srm/UploadActionListener.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm; - -import com.github.srm.zap.srm.ReportLastScan.ReportType; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.XMLEvent; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.mime.HttpMultipartMode; -import org.apache.http.entity.mime.MultipartEntityBuilder; -import org.apache.http.entity.mime.content.FileBody; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.util.EntityUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.parosproxy.paros.Constant; -import org.parosproxy.paros.view.View; - -public class UploadActionListener implements ActionListener { - - private static final Logger LOGGER = LogManager.getLogger(UploadActionListener.class); - - private static final XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance(); - - static { - xmlInputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false); - xmlInputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); - } - - private SrmExtension extension; - private UploadPropertiesDialog prop; - - public UploadActionListener(SrmExtension extension) { - this.extension = extension; - this.prop = new UploadPropertiesDialog(extension); - } - - @Override - public void actionPerformed(ActionEvent e) { - prop.openProperties(this); - } - - public void generateAndUploadReport() { - String error = null; - try { - final File reportFile = generateReportFile(extension); - if (!reportIsEmpty(reportFile)) { - Thread uploadThread = - new Thread() { - @Override - public void run() { - String err; - try { - err = - uploadFile( - extension.getHttpClient(), - reportFile, - SrmProperties.getInstance().getServerUrl(), - SrmProperties.getInstance().getApiKey(), - prop.getProject().getValue()); - } catch (IOException ex1) { - err = Constant.messages.getString("srm.error.unexpected"); - LOGGER.error("Unexpected error while uploading report: ", ex1); - } - if (err != null) View.getSingleton().showMessageDialog(err); - else - View.getSingleton() - .showMessageDialog( - Constant.messages.getString( - "srm.message.success")); - reportFile.delete(); - } - }; - uploadThread.start(); - } else { - error = Constant.messages.getString("srm.error.empty"); - } - } catch (Exception ex2) { - error = Constant.messages.getString("srm.error.failed"); - LOGGER.error("Unexpected error while generating report: ", ex2); - } - if (error != null) View.getSingleton().showWarningDialog(error); - } - - public static String uploadFile( - CloseableHttpClient client, - File reportFile, - String serverUrl, - String apiKey, - String project) - throws IOException { - String err = null; - HttpResponse response = sendData(client, reportFile, serverUrl, apiKey, project); - StatusLine responseLine = null; - int responseCode = -1; - if (response != null) { - responseLine = response.getStatusLine(); - responseCode = responseLine.getStatusCode(); - } - if (responseCode == 400) { - err = - Constant.messages.getString("srm.error.unexpected") - + "\n" - + Constant.messages.getString("srm.error.http.400"); - } else if (responseCode == 403) { - err = - Constant.messages.getString("srm.error.unsent") - + " " - + Constant.messages.getString("srm.error.http.403"); - } else if (responseCode == 404) { - err = - Constant.messages.getString("srm.error.unsent") - + " " - + Constant.messages.getString("srm.error.http.404"); - } else if (responseCode == 415) { - err = - Constant.messages.getString("srm.error.unexpected") - + "\n" - + Constant.messages.getString("srm.error.http.415"); - } else if (responseCode != 200 && responseCode != 202) { - err = Constant.messages.getString("srm.error.unexpected"); - if (response != null) - err += Constant.messages.getString("srm.error.http.other") + " " + responseLine; - } - return err; - } - - private static HttpResponse sendData( - CloseableHttpClient client, - File reportFile, - String serverUrl, - String apiKey, - String project) - throws IOException { - if (client == null) return null; - try { - HttpPost post = new HttpPost(serverUrl + "/api/projects/" + project + "/analysis"); - post.setHeader("API-Key", apiKey); - - MultipartEntityBuilder builder = MultipartEntityBuilder.create(); - builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); - builder.addPart("file", new FileBody(reportFile)); - - HttpEntity entity = builder.build(); - post.setEntity(entity); - - HttpResponse response = client.execute(post); - HttpEntity resEntity = response.getEntity(); - - if (resEntity != null) { - EntityUtils.consume(resEntity); - } - - return response; - } finally { - client.close(); - } - } - - public static void generateReportString(SrmExtension extension, StringBuilder report) - throws Exception { - ReportLastScanHttp saver = new ReportLastScanHttp(); - saver.generate(report); - } - - public static File generateReportFile(SrmExtension extension) throws Exception { - File reportFile = File.createTempFile("srm-zap-report", ".xml"); - reportFile.deleteOnExit(); - - ReportLastScanHttp saver = new ReportLastScanHttp(); - saver.generate(reportFile.getCanonicalPath(), ReportType.XML); - - return reportFile; - } - - public static Boolean reportIsEmpty(File reportFile) throws IOException, XMLStreamException { - BufferedReader br = Files.newBufferedReader(reportFile.toPath()); - try { - XMLEventReader reader = xmlInputFactory.createXMLEventReader(br); - - while (reader.hasNext()) { - XMLEvent event = reader.nextEvent(); - if (event.isStartElement() - && !event.asStartElement() - .getName() - .getLocalPart() - .equals("OWASPZAPReport")) { - return false; - } - } - } finally { - br.close(); - } - return true; - } -} diff --git a/src/main/java/com/github/srm/zap/srm/UploadPropertiesDialog.java b/src/main/java/com/github/srm/zap/srm/UploadPropertiesDialog.java deleted file mode 100644 index 157b9ab..0000000 --- a/src/main/java/com/github/srm/zap/srm/UploadPropertiesDialog.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm; - -import java.awt.Container; -import java.awt.Cursor; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.security.GeneralSecurityException; -import java.util.Arrays; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SwingConstants; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.parosproxy.paros.Constant; - -public class UploadPropertiesDialog { - - private static final Logger LOGGER = LogManager.getLogger(UploadPropertiesDialog.class); - - private static final String[] DIALOG_BUTTONS = { - Constant.messages.getString("srm.settings.upload"), - Constant.messages.getString("srm.settings.cancel") - }; - - public static final ImageIcon REFRESH_ICON = - new ImageIcon( - UploadPropertiesDialog.class.getResource( - "/com/github/srm/zap/srm/resources/refresh.png")); - - private JTextField serverUrl; - private JTextField apiKey; - private JComboBox projectBox; - private JTextField timeout; - private JDialog dialog; - - private ModifiedNameValuePair[] projectArr = new ModifiedNameValuePair[0]; - - private SrmExtension extension; - - public UploadPropertiesDialog(SrmExtension extension) { - this.extension = extension; - } - - public void openProperties(final UploadActionListener uploader) { - JPanel message = new JPanel(new GridBagLayout()); - - serverUrl = - labelTextField( - Constant.messages.getString("srm.settings.serverurl") + " ", - message, - SrmProperties.getInstance().getServerUrl(), - 30); - apiKey = - labelTextField( - Constant.messages.getString("srm.settings.apikey") + " ", - message, - SrmProperties.getInstance().getApiKey(), - 30); - projectBox = createProjectComboBox(message); - timeout = - labelTextField( - Constant.messages.getString("srm.setting.timeout") + " ", - message, - SrmProperties.getInstance().getTimeout(), - 5); - - final JOptionPane pane = - new JOptionPane( - message, - JOptionPane.PLAIN_MESSAGE, - JOptionPane.OK_CANCEL_OPTION, - null, - DIALOG_BUTTONS, - null); - dialog = pane.createDialog(Constant.messages.getString("srm.settings.title")); - - Thread popupThread = - new Thread() { - @Override - public void run() { - dialog.setVisible(true); - if (DIALOG_BUTTONS[0].equals(pane.getValue())) { - String timeoutValue = timeout.getText(); - if (!isStringNumber(timeoutValue)) { - timeoutValue = SrmProperties.DEFAULT_TIMEOUT_STRING; - error(Constant.messages.getString("srm.error.timeout")); - } - SrmProperties.getInstance() - .setProperties( - serverUrl.getText(), - apiKey.getText(), - getProject().getValue(), - timeoutValue); - uploader.generateAndUploadReport(); - } - } - }; - Thread updateThread = - new Thread() { - @Override - public void run() { - if (!"".equals(serverUrl.getText()) && !"".equals(apiKey.getText())) { - updateProjects(true); - String previousId = SrmProperties.getInstance().getSelectedId(); - for (NameValuePair p : projectArr) { - if (previousId.equals(p.getValue())) projectBox.setSelectedItem(p); - } - } - } - }; - popupThread.start(); - updateThread.start(); - } - - private boolean isStringNumber(String value) { - for (int i = 0; i < value.length(); i++) { - char c = value.charAt(i); - if (!Character.isDigit(c)) { - return false; - } - } - return true; - } - - private JTextField labelTextField(String label, Container cont, String base, int columns) { - createSettingsLabel(label, cont); - - JTextField textField = new JTextField(base, columns); - GridBagConstraints gbc = new GridBagConstraints(); - gbc.gridx = 1; - gbc.anchor = GridBagConstraints.WEST; - cont.add(textField, gbc); - - return textField; - } - - private JComboBox createProjectComboBox(Container cont) { - createSettingsLabel("Project: ", cont); - - JComboBox box = new JComboBox<>(); - box.setPreferredSize(new Dimension(300, 27)); - GridBagConstraints gbc = new GridBagConstraints(); - gbc.gridx = 1; - gbc.fill = GridBagConstraints.HORIZONTAL; - cont.add(box, gbc); - - JButton refresh = new JButton(REFRESH_ICON); - refresh.setPreferredSize( - new Dimension(REFRESH_ICON.getIconHeight() + 6, REFRESH_ICON.getIconHeight() + 6)); - refresh.addActionListener( - e -> { - if ("".equals(serverUrl.getText()) || "".equals(apiKey.getText())) { - error(Constant.messages.getString("srm.error.required")); - return; - } - dialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); - updateProjects(); - dialog.setCursor(Cursor.getDefaultCursor()); - }); - gbc = new GridBagConstraints(); - gbc.gridx = 2; - gbc.gridy = 2; - gbc.anchor = GridBagConstraints.WEST; - cont.add(refresh, gbc); - - return box; - } - - private void createSettingsLabel(String label, Container cont) { - JLabel labelField = new JLabel(label); - labelField.setHorizontalAlignment(SwingConstants.LEFT); - GridBagConstraints gbc = new GridBagConstraints(); - gbc.gridwidth = 1; - gbc.gridx = 0; - gbc.insets = new Insets(0, 10, 0, 0); - gbc.anchor = GridBagConstraints.WEST; - gbc.fill = GridBagConstraints.HORIZONTAL; - cont.add(labelField, gbc); - } - - public void updateProjects() { - updateProjects(false); - } - - public void updateProjects(boolean initialRefresh) { - dialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); - CloseableHttpClient client = null; - BufferedReader rd = null; - projectArr = new ModifiedNameValuePair[0]; - try { - client = extension.getHttpClient(getServerUrl()); - if (client != null) { - HttpGet get = new HttpGet(getServerUrl() + "/api/projects"); - get.setHeader("API-Key", getApiKey()); - HttpResponse response = client.execute(get); - rd = - new BufferedReader( - new InputStreamReader(response.getEntity().getContent(), "UTF-8")); - - StringBuilder result = new StringBuilder(); - String line = ""; - while ((line = rd.readLine()) != null) { - result.append(line); - } - - int code = response.getStatusLine().getStatusCode(); - if (code == 200) { - projectArr = parseProjectJson(result.toString(), initialRefresh); - } else if (!initialRefresh) { - String msg = - Constant.messages.getString("srm.refresh.non200") - + ' ' - + response.getStatusLine() - + '.'; - if (code == 403) msg += Constant.messages.getString("srm.refresh.403"); - else if (code == 404) msg += Constant.messages.getString("srm.refresh.404"); - else if (code == 400) msg += Constant.messages.getString("srm.refresh.400"); - error(msg); - } - } - } catch (GeneralSecurityException | ParseException | IOException e) { - if (!initialRefresh) { - if (e instanceof MalformedURLException) - error(Constant.messages.getString("srm.error.client.invalid")); - else error(Constant.messages.getString("srm.refresh.failed")); - } - LOGGER.error("Error refreshing project list: ", e); - } finally { - if (client != null) - try { - client.close(); - } catch (IOException e) { - } - if (rd != null) - try { - rd.close(); - } catch (IOException e) { - } - } - updateProjectComboBox(); - dialog.setCursor(Cursor.getDefaultCursor()); - } - - private ModifiedNameValuePair[] parseProjectJson(String json, boolean initialRefresh) - throws ParseException { - JSONParser parser = new JSONParser(); - JSONObject obj = (JSONObject) parser.parse(json); - JSONArray projects = (JSONArray) obj.get("projects"); - - ModifiedNameValuePair[] projectArr = new ModifiedNameValuePair[projects.size()]; - for (int i = 0; i < projectArr.length; i++) { - JSONObject project = (JSONObject) projects.get(i); - int id = ((Long) project.get("id")).intValue(); - String name = (String) project.get("name"); - projectArr[i] = new ModifiedNameValuePair(name, Integer.toString(id)); - } - if (projectArr.length > 0) { - Arrays.sort(projectArr); - // set the project ids to visible if the names are the same - for (int i = 0; i < projectArr.length - 1; i++) { - if (projectArr[i].getName() != null - && projectArr[i].getName().equals(projectArr[i + 1].getName())) { - projectArr[i].setUseId(true); - projectArr[i + 1].setUseId(true); - } - } - } else if (!initialRefresh) warn(Constant.messages.getString("srm.refresh.noproject")); - return projectArr; - } - - public void updateProjectComboBox() { - if (projectBox != null) { - NameValuePair selected = getProject(); - projectBox.removeAllItems(); - for (NameValuePair p : projectArr) { - projectBox.addItem(p); - if (selected != null && selected.equals(p)) { - projectBox.setSelectedItem(p); - } - } - } - } - - public NameValuePair getProject() { - return (NameValuePair) projectBox.getSelectedItem(); - } - - private void warn(String message) { - JOptionPane.showMessageDialog( - dialog, - message, - Constant.messages.getString("srm.warning"), - JOptionPane.WARNING_MESSAGE); - } - - private void error(String message) { - JOptionPane.showMessageDialog( - dialog, - message, - Constant.messages.getString("srm.error"), - JOptionPane.ERROR_MESSAGE); - } - - private String getServerUrl() { - String text = serverUrl.getText(); - if (text.endsWith("/")) return text.substring(0, text.length() - 1); - return text; - } - - private String getApiKey() { - return apiKey.getText(); - } - - private static class ModifiedNameValuePair extends BasicNameValuePair - implements Comparable { - private static final long serialVersionUID = -6671681121783779976L; - private boolean useId = false; - - public ModifiedNameValuePair(String name, String value) { - super(name, value); - } - - public void setUseId(boolean useId) { - this.useId = useId; - } - - @Override - public String toString() { - if (useId) return getName() + " (id: " + getValue() + ")"; - return getName(); - } - - @Override - public int compareTo(ModifiedNameValuePair o) { - int val = this.getName().compareTo(((NameValuePair) o).getName()); - if (val == 0) return this.getValue().compareTo(((NameValuePair) o).getValue()); - return val; - } - } -} diff --git a/src/main/java/com/github/srm/zap/srm/security/CompositeX509TrustManager.java b/src/main/java/com/github/srm/zap/srm/security/CompositeX509TrustManager.java deleted file mode 100644 index effec70..0000000 --- a/src/main/java/com/github/srm/zap/srm/security/CompositeX509TrustManager.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm.security; - -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.LinkedList; -import java.util.List; -import javax.net.ssl.SSLContext; -import javax.net.ssl.X509TrustManager; - -/** - * Represents an ordered list of {@link X509TrustManager}s with additive trust. If any one of the - * composed managers trusts a certificate chain, then it is trusted by the composite manager. - * - *

This is necessary because of the fine-print on {@link SSLContext#init}: Only the first - * instance of a particular key and/or trust manager implementation type in the array is used. (For - * example, only the first javax.net.ssl.X509KeyManager in the array will be used.) - * - *

see - * StackOverflow and the related blog post - * - * @author codyaray - * @since 4/22/2013 - * @see - */ -public class CompositeX509TrustManager implements X509TrustManager { - - private final List trustManagers = new LinkedList<>(); - - /** - * Initializes the composite trust manager, copying all of the non-null entries in the given - * trustManagers list into its own internal list. - * - * @param trustManagers A list of (potentially null) trust managers. - */ - public CompositeX509TrustManager(List trustManagers) { - for (X509TrustManager tm : trustManagers) { - if (tm != null) this.trustManagers.add(tm); - } - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - for (X509TrustManager trustManager : trustManagers) { - try { - trustManager.checkClientTrusted(chain, authType); - return; // someone trusts them. success! - } catch (CertificateException e) { - // maybe someone else will trust them - } - } - throw new CertificateException("None of the TrustManagers trust this certificate chain"); - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - for (X509TrustManager trustManager : trustManagers) { - try { - trustManager.checkServerTrusted(chain, authType); - return; // someone trusts them. success! - } catch (CertificateException e) { - // maybe someone else will trust them - } - } - throw new CertificateException("None of the TrustManagers trust this certificate chain"); - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - List certificates = new LinkedList<>(); - for (X509TrustManager trustManager : trustManagers) { - for (X509Certificate cert : trustManager.getAcceptedIssuers()) { - certificates.add(cert); - } - } - return certificates.toArray(new X509Certificate[certificates.size()]); - } -} diff --git a/src/main/java/com/github/srm/zap/srm/security/ExtraCertManager.java b/src/main/java/com/github/srm/zap/srm/security/ExtraCertManager.java deleted file mode 100644 index 228c057..0000000 --- a/src/main/java/com/github/srm/zap/srm/security/ExtraCertManager.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm.security; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.cert.Certificate; - -public interface ExtraCertManager { - - /** - * Add a certificate that will be accepted until some event (as determined by the implementation - * of this interface) occurs, causing it to be "forgotten". - * - * @param cert - */ - void addTemporaryCert(Certificate cert) throws IOException, GeneralSecurityException; - - /** - * Add a certificate that will be accepted until this manager is "purged". Certificates added in - * this way will generally be written to disk, and will be available upon restarting the - * program. - * - * @param cert - * @throws IOException - * @throws GeneralSecurityException - */ - void addPermanentCert(Certificate cert) throws IOException, GeneralSecurityException; - - /** Remove all certificates that have been added via {@link #addTemporaryCert(Certificate)}. */ - void purgeTemporaryCerts() throws IOException, GeneralSecurityException; - - /** Remove all certificates that have been added via {@link #addPermanentCert(Certificate)}. */ - void purgePermanentCerts() throws IOException, GeneralSecurityException; - - /** - * Remove all certificates that have been added either by {@link #addTemporaryCert(Certificate)} - * or {@link #addPermanentCert(Certificate)}. - */ - void purgeAllCerts() throws IOException, GeneralSecurityException; - - /** - * Return a representation of this manager as a KeyStore instance. - * - * @return A new KeyStore that represents the contents of this certificate manager - */ - KeyStore asKeyStore() throws IOException, GeneralSecurityException; -} diff --git a/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateDialogStrategy.java b/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateDialogStrategy.java deleted file mode 100644 index 9a48122..0000000 --- a/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateDialogStrategy.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm.security; - -import com.github.srm.zap.srm.SrmExtension; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Formatter; -import java.util.StringTokenizer; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLException; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import org.apache.http.conn.ssl.DefaultHostnameVerifier; -import org.parosproxy.paros.Constant; - -/** - * An InvalidCertificateStrategy implementation that opens a dialog, prompting the user for their - * choice of action. - */ -public class InvalidCertificateDialogStrategy implements InvalidCertificateStrategy { - - private final HostnameVerifier defaultHostVerifier; - private final String host; - private SrmExtension extension; - - private static final String dialogTitle = Constant.messages.getString("srm.ssl.title"); - private static final String[] dialogButtons = { - Constant.messages.getString("srm.ssl.reject"), - Constant.messages.getString("srm.ssl.accepttemp"), - Constant.messages.getString("srm.ssl.acceptperm") - }; - - public InvalidCertificateDialogStrategy( - HostnameVerifier defaultHostVerifier, String host, SrmExtension extension) { - this.defaultHostVerifier = defaultHostVerifier; - this.host = host; - this.extension = extension; - } - - @Override - public CertificateAcceptance checkAcceptance( - Certificate genericCert, CertificateException certError) { - if (genericCert instanceof X509Certificate - && defaultHostVerifier instanceof DefaultHostnameVerifier) { - X509Certificate cert = (X509Certificate) genericCert; - DefaultHostnameVerifier verifier = (DefaultHostnameVerifier) defaultHostVerifier; - - JPanel message = new JPanel(new GridBagLayout()); - GridBagConstraints gbc = new GridBagConstraints(); - gbc.gridwidth = 2; - gbc.insets = new Insets(0, 0, 10, 0); - gbc.anchor = GridBagConstraints.WEST; - message.add(new JLabel(Constant.messages.getString("srm.ssl.description")), gbc); - - gbc = new GridBagConstraints(); - gbc.gridy = 2; - gbc.insets = new Insets(2, 0, 2, 0); - gbc.anchor = GridBagConstraints.WEST; - - JLabel issuer = new JLabel(Constant.messages.getString("srm.ssl.issuer") + " "); - Font defaultFont = issuer.getFont(); - Font bold = new Font(defaultFont.getName(), Font.BOLD, defaultFont.getSize()); - issuer.setFont(bold); - - message.add(issuer, gbc); - gbc.gridx = 1; - message.add(new JLabel(cert.getIssuerX500Principal().getName()), gbc); - - try { - JLabel fingerprint = - new JLabel(Constant.messages.getString("srm.ssl.fingerprint") + " "); - fingerprint.setFont(bold); - gbc.gridx = 0; - gbc.gridy += 1; - message.add(fingerprint, gbc); - - gbc.gridx = 1; - message.add(new JLabel(toHexString(getSHA1(cert.getEncoded()), " ")), gbc); - } catch (CertificateEncodingException e) { - // this shouldn't actually ever happen - } - - try { - verifier.verify(host, cert); - } catch (SSLException e) { - String cn = getCN(cert); - - JLabel mismatch = new JLabel(Constant.messages.getString("srm.ssl.mismatch") + " "); - mismatch.setFont(bold); - gbc.gridx = 0; - gbc.gridy += 1; - message.add(mismatch, gbc); - - String msg; - if (cn != null) { - msg = - String.format( - Constant.messages.getString("srm.ssl.mismatchmsg"), host, cn); - } else { - msg = e.getMessage(); - } - - gbc.gridx = 1; - message.add(new JLabel(msg), gbc); - } - - // Open the dialog, and return its result - int choice = - JOptionPane.showOptionDialog( - extension.getView().getMainFrame(), - message, - dialogTitle, - JOptionPane.YES_NO_CANCEL_OPTION, - JOptionPane.PLAIN_MESSAGE, - null, - dialogButtons, - null); - switch (choice) { - case (0): - return CertificateAcceptance.REJECT; - case (1): - return CertificateAcceptance.ACCEPT_TEMPORARILY; - case (2): - return CertificateAcceptance.ACCEPT_PERMANENTLY; - } - } - return CertificateAcceptance.REJECT; - } - - public static byte[] getSHA1(byte[] input) { - try { - MessageDigest md = MessageDigest.getInstance("SHA-1"); - md.reset(); - return md.digest(input); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - } - - public static String toHexString(byte[] bytes, String sep) { - Formatter f = new Formatter(); - for (int i = 0; i < bytes.length; i++) { - f.format("%02x", bytes[i]); - if (i < bytes.length - 1) { - f.format(sep); - } - } - String result = f.toString(); - f.close(); - return result; - } - - private static String getCN(X509Certificate cert) { - String principal = cert.getSubjectX500Principal().toString(); - StringTokenizer tokenizer = new StringTokenizer(principal, ","); - while (tokenizer.hasMoreTokens()) { - String token = tokenizer.nextToken(); - int i = token.indexOf("CN="); - if (i >= 0) { - return token.substring(i + 3); - } - } - return null; - } -} diff --git a/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateFingerprintStrategy.java b/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateFingerprintStrategy.java deleted file mode 100644 index dbe8a91..0000000 --- a/src/main/java/com/github/srm/zap/srm/security/InvalidCertificateFingerprintStrategy.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm.security; - -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; - -public class InvalidCertificateFingerprintStrategy implements InvalidCertificateStrategy { - - private final String fingerprint; - private final boolean acceptPermanently; - - public InvalidCertificateFingerprintStrategy(String fingerprint, boolean acceptPermanently) { - this.fingerprint = fingerprint.replaceAll("\\s", ""); - this.acceptPermanently = acceptPermanently; - } - - @Override - public CertificateAcceptance checkAcceptance(Certificate cert, CertificateException certError) { - try { - byte[] encoded = InvalidCertificateDialogStrategy.getSHA1(cert.getEncoded()); - String obsPrint = InvalidCertificateDialogStrategy.toHexString(encoded, ""); - if (obsPrint.equalsIgnoreCase(fingerprint)) { - if (acceptPermanently) return CertificateAcceptance.ACCEPT_PERMANENTLY; - else return CertificateAcceptance.ACCEPT_TEMPORARILY; - } else { - return CertificateAcceptance.REJECT; - } - } catch (CertificateEncodingException e) { - return CertificateAcceptance.REJECT; - } - } -} diff --git a/src/main/java/com/github/srm/zap/srm/security/ReloadableX509TrustManager.java b/src/main/java/com/github/srm/zap/srm/security/ReloadableX509TrustManager.java deleted file mode 100644 index 42c88a1..0000000 --- a/src/main/java/com/github/srm/zap/srm/security/ReloadableX509TrustManager.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm.security; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.NoSuchAlgorithmException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -/** - * This X509TrustManager implementation allows invalid certificates to possibly be accepted by the - * decision of an {@link InvalidCertificateStrategy} that is passed as a constructor argument. - * Certificates added in this way will be added via a {@link ExtraCertManager}, causing the - * underlying trust manager to be reloaded. - * - *

Adapted from the implementation at "Managing a - * Dynamic Java Trust Store" (blog post) - */ -public class ReloadableX509TrustManager implements X509TrustManager { - - /* package-private */ final ExtraCertManager certManager; - private final InvalidCertificateStrategy invalidCertStrat; - private X509TrustManager tmDelegate; - - public ReloadableX509TrustManager( - ExtraCertManager certManager, InvalidCertificateStrategy invalidCertStrat) - throws IOException, GeneralSecurityException { - this.certManager = certManager; - this.invalidCertStrat = invalidCertStrat; - reloadTrustManager(); - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - tmDelegate.checkClientTrusted(chain, authType); - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - try { - tmDelegate.checkServerTrusted(chain, authType); - } catch (CertificateException cx) { - - /* - * At this point, we have come across an apparently-invalid - * certificate. We use the `InvalidCertificateStrategy` to decide - * what to do about it; either reject it (rethrow the exception), or - * accept it. If accepting, the certificate can be added - * "temporarily" or "permanently", which is done via the - * `ExtraCertManager`. - */ - Certificate cert = chain[0]; - CertificateAcceptance certAcceptance = invalidCertStrat.checkAcceptance(cert, cx); - - switch (certAcceptance) { - case REJECT: - throw cx; - - case ACCEPT_TEMPORARILY: - try { - certManager.addTemporaryCert(cert); - reloadTrustManager(); - } catch (IOException | GeneralSecurityException e) { - // wrap errors from the cert manipulation - throw new CertificateException( - "Error handling temporary acceptance of the certificate", e); - } - // now retry the trust check - tmDelegate.checkServerTrusted(chain, authType); - break; - - case ACCEPT_PERMANENTLY: - try { - certManager.addPermanentCert(cert); - reloadTrustManager(); - } catch (IOException | GeneralSecurityException e) { - // wrap errors from the cert manipulation - throw new CertificateException( - "Error handling permanent acceptance of the certificate", e); - } - // now retry the trust check - tmDelegate.checkServerTrusted(chain, authType); - break; - - default: - throw cx; - } - } - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return tmDelegate.getAcceptedIssuers(); - } - - /* package-private */ - final void reloadTrustManager() throws IOException, GeneralSecurityException { - KeyStore ks = certManager.asKeyStore(); - - // initialize a new TMF with the KeyStore we just created - TrustManagerFactory tmf = - TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - tmf.init(ks); - - // acquire an X509 trust manager from the TMF - // and update the `tmDelegate` to that value - TrustManager[] tms = tmf.getTrustManagers(); - for (TrustManager tm : tms) { - if (tm instanceof X509TrustManager) { - tmDelegate = (X509TrustManager) tm; - return; - } - } - - // should have returned in the `for` loop above - throw new NoSuchAlgorithmException("No X509TrustManager in TrustManagerFactory"); - } -} diff --git a/src/main/java/com/github/srm/zap/srm/security/SSLConnectionSocketFactoryFactory.java b/src/main/java/com/github/srm/zap/srm/security/SSLConnectionSocketFactoryFactory.java deleted file mode 100644 index ed7d233..0000000 --- a/src/main/java/com/github/srm/zap/srm/security/SSLConnectionSocketFactoryFactory.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm.security; - -import com.github.srm.zap.srm.SrmExtension; -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; -import org.apache.http.conn.ssl.DefaultHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; - -public class SSLConnectionSocketFactoryFactory { - - private static Map dialogFactoriesByHost = new HashMap<>(); - private static Map fingerprintFactoriesByHost = - new HashMap<>(); - - /** - * Returns a SSLConnectionSocketFactory for the given host. When a SSL connection is created - * with the returned socket factory, if the server's certificate appears to be invalid, the user - * will be prompted to either reject temporarily accept, or permanently accept the certificate. - * Permanently accepted certificates will be stored in a .truststore file so the - * user won't need to prompted again for the same host. - * - * @param host The host (URL component) that the socket factory will be used to connect to - * @param extension - * @return A socket factory for the given host - * @throws IOException - * @throws GeneralSecurityException - */ - public static SSLConnectionSocketFactory getFactory(String host, SrmExtension extension) - throws IOException, GeneralSecurityException { - - SSLConnectionSocketFactory instance = dialogFactoriesByHost.get(host); - if (instance == null) { - initializeFactory(host, extension, null, false); - return dialogFactoriesByHost.get(host); - } else { - return instance; - } - } - - /** - * Returns a SSLConnectionSocketFactory for the given host. When a SSL connection is created - * with the returned socket factory, if the server's certificate appears to be invalid, the user - * will be prompted to either reject temporarily accept, or permanently accept the certificate. - * Permanently accepted certificates will be stored in a .truststore file so the - * user won't need to prompted again for the same host. - * - * @param host The host (URL component) that the socket factory will be used to connect to - * @param extension - * @param fingerprint Expected SHA1 fingerprint of an invalid certificate - * @param acceptPermanently - * @return A socket factory for the given host - * @throws IOException - * @throws GeneralSecurityException - */ - public static SSLConnectionSocketFactory getFactory( - String host, SrmExtension extension, String fingerprint, boolean acceptPermanently) - throws IOException, GeneralSecurityException { - SSLConnectionSocketFactory instance = fingerprintFactoriesByHost.get(host); - if (instance == null) { - initializeFactory(host, extension, fingerprint, acceptPermanently); - return fingerprintFactoriesByHost.get(host); - } else { - return instance; - } - } - - /** - * Determines the location for the truststore file for the given host. Each {@link - * SSLConnectionSocketFactory} returned by {@link #initializeFactory(String, SrmExtension, - * String, boolean)} needs to have a file to store user-accepted invalid certificates; these - * files will be stored in the user's OS-appropriate "appdata" directory. - * - * @param host A URL hostname, e.g. "www.google.com" - * @return The file where the trust store for the given host should be stored - */ - private static File getTrustStoreForHost(String host) { - String OS = System.getProperty("os.name").toUpperCase(); - Path env; - if (OS.contains("WIN")) { - env = Paths.get(System.getenv("APPDATA"), "Software Risk Manager", "ZAP"); - } else if (OS.contains("MAC")) { - env = - Paths.get( - System.getProperty("user.home"), - "Library", - "Application Support", - "Software Risk Manager", - "ZAP"); - } else if (OS.contains("NUX")) { - env = Paths.get(System.getProperty("user.home"), ".srm", "zap"); - } else { - env = Paths.get(System.getProperty("user.dir"), "srm", "zap"); - } - - File keystoreDir = new File(env.toFile(), ".usertrust"); - keystoreDir.mkdirs(); - - // Host may only contain alphanumerics, dash, and dot. - // Replace anything else with an underscore. - String safeHost = host.replaceAll("[^a-zA-Z0-9\\-\\.]", "_"); - - // /.usertrust/.truststore - return new File(keystoreDir, safeHost + ".truststore"); - } - - /** - * Creates a new SSLConnectionSocketFactory with the behavior described in - * {@link #getFactory(String, SrmExtension)}. Instead of returning, this - * method registers the factory instance to the factoriesByHost - * map, as well as registering its ExtraCertManager to the - * certManagersByHost map. The cert manager registration is - * important in order to detect and purge trusted certificates on a per-host - * basis. - * - * @param host - * @param extension - * @throws IOException - * @throws GeneralSecurityException - */ - private static void initializeFactory( - String host, SrmExtension extension, String fingerprint, boolean acceptPermanently) - throws IOException, GeneralSecurityException { - // set up the certificate management - File managedKeyStoreFile = getTrustStoreForHost(host); - ExtraCertManager certManager = - new SingleExtraCertManager(managedKeyStoreFile, "u9lwIfUpaN"); - - // get the default hostname verifier that gets used by the modified one - // and the invalid cert dialog - HostnameVerifier defaultHostnameVerifier = new DefaultHostnameVerifier(); - - InvalidCertificateStrategy invalidCertStrat; - if (fingerprint == null) { - invalidCertStrat = - new InvalidCertificateDialogStrategy(defaultHostnameVerifier, host, extension); - } else { - invalidCertStrat = - new InvalidCertificateFingerprintStrategy(fingerprint, acceptPermanently); - } - - /* - * Set up a composite trust manager that uses the default trust manager - * before delegating to the "reloadable" trust manager that allows users - * to accept invalid certificates. - */ - List trustManagersForComposite = new LinkedList<>(); - X509TrustManager systemTrustManager = getDefaultTrustManager(); - ReloadableX509TrustManager customTrustManager = - new ReloadableX509TrustManager(certManager, invalidCertStrat); - trustManagersForComposite.add(systemTrustManager); - trustManagersForComposite.add(customTrustManager); - X509TrustManager trustManager = new CompositeX509TrustManager(trustManagersForComposite); - - // setup the SSLContext using the custom trust manager - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(null, new TrustManager[] {trustManager}, null); - // the actual hostname verifier that will be used with the socket - // factory - Set allowedHosts = new HashSet<>(); - allowedHosts.add(host); - HostnameVerifier modifiedHostnameVerifier = - new HostnameVerifierWithExceptions(defaultHostnameVerifier, allowedHosts); - - SSLConnectionSocketFactory factory = - new SSLConnectionSocketFactory(sslContext, modifiedHostnameVerifier); - // Register the `factory` and the `customTrustManager` under the given - // `host` - if (fingerprint == null) { - dialogFactoriesByHost.put(host, factory); - } else { - fingerprintFactoriesByHost.put(host, factory); - } - } - - private static X509TrustManager getDefaultTrustManager() - throws NoSuchAlgorithmException, KeyStoreException { - TrustManagerFactory defaultFactory = - TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - defaultFactory.init((KeyStore) null); - - TrustManager[] managers = defaultFactory.getTrustManagers(); - for (TrustManager mgr : managers) { - if (mgr instanceof X509TrustManager) { - return (X509TrustManager) mgr; - } - } - - return null; - } -} diff --git a/src/main/java/com/github/srm/zap/srm/security/SingleExtraCertManager.java b/src/main/java/com/github/srm/zap/srm/security/SingleExtraCertManager.java deleted file mode 100644 index 153f0c3..0000000 --- a/src/main/java/com/github/srm/zap/srm/security/SingleExtraCertManager.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2025 The ZAP Development Team - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.srm.zap.srm.security; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.cert.Certificate; - -/** - * ExtraCertManager implementation that only allows a single accepted certificate at once. Any time - * a certificate is added (be it temporarily or permanently), any previous certificates will be - * forgotten. At any given time, the {@link #asKeyStore()} method should return a KeyStore with 0 or - * 1 certificates registered. - */ -public class SingleExtraCertManager implements ExtraCertManager { - - private final File keystoreFile; - private final char[] password; - private boolean isUsingFile; - private Certificate tempCert = null; - - public SingleExtraCertManager(File keystoreFile, String password) { - this.keystoreFile = keystoreFile; - this.password = password.toCharArray(); - isUsingFile = true; - } - - @Override - public void addTemporaryCert(Certificate cert) { - if (isUsingFile) { - keystoreFile.delete(); - } - isUsingFile = false; - tempCert = cert; - } - - @Override - public void addPermanentCert(Certificate cert) throws IOException, GeneralSecurityException { - tempCert = null; - isUsingFile = true; - - // create a keystore and put the cert in it - KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - ks.load(null, password); - ks.setCertificateEntry("default", cert); - - // store the new keystore to the keystoreFile - FileOutputStream out = new FileOutputStream(keystoreFile); - try { - ks.store(out, password); - } finally { - out.close(); - } - } - - @Override - public void purgeTemporaryCerts() { - isUsingFile = true; - tempCert = null; - } - - @Override - public void purgePermanentCerts() { - if (isUsingFile) { - // keep the flag, but delete the file - keystoreFile.delete(); - } - } - - @Override - public void purgeAllCerts() { - isUsingFile = true; - tempCert = null; - keystoreFile.delete(); - } - - @Override - public KeyStore asKeyStore() throws IOException, GeneralSecurityException { - KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - - if (isUsingFile) { - // load from the file, as long as it exists - if (keystoreFile.canRead()) { - FileInputStream in = new FileInputStream(keystoreFile); - try { - ks.load(in, password); - } finally { - in.close(); - } - } else { - ks.load(null, password); - } - } else { - ks.load(null, password); - // insert the tempCert to the keystore - if (tempCert != null) { - ks.setCertificateEntry("default", tempCert); - } - } - - if (ks.aliases().hasMoreElements()) { - return ks; - } else { - return null; - } - } -} diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help/helpset.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help/helpset.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help/helpset.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help/helpset.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/helpset_ar_SA.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/helpset_ar_SA.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/helpset_ar_SA.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/helpset_ar_SA.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ar_SA/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ar_SA/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/helpset_az_AZ.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/helpset_az_AZ.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/helpset_az_AZ.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/helpset_az_AZ.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_az_AZ/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_az_AZ/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/helpset_bs_BA.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/helpset_bs_BA.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/helpset_bs_BA.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/helpset_bs_BA.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_bs_BA/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_bs_BA/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/helpset_da_DK.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/helpset_da_DK.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/helpset_da_DK.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/helpset_da_DK.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_da_DK/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_da_DK/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/helpset_de_DE.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/helpset_de_DE.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/helpset_de_DE.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/helpset_de_DE.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_de_DE/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_de_DE/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/helpset_el_GR.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/helpset_el_GR.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/helpset_el_GR.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/helpset_el_GR.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_el_GR/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_el_GR/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/helpset_es_ES.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/helpset_es_ES.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/helpset_es_ES.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/helpset_es_ES.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_es_ES/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_es_ES/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/helpset_fa_IR.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/helpset_fa_IR.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/helpset_fa_IR.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/helpset_fa_IR.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fa_IR/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fa_IR/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/helpset_fil_PH.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/helpset_fil_PH.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/helpset_fil_PH.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/helpset_fil_PH.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fil_PH/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fil_PH/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/helpset_fr_FR.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/helpset_fr_FR.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/helpset_fr_FR.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/helpset_fr_FR.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_fr_FR/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_fr_FR/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/helpset_hi_IN.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/helpset_hi_IN.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/helpset_hi_IN.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/helpset_hi_IN.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hi_IN/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hi_IN/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/helpset_hr_HR.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/helpset_hr_HR.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/helpset_hr_HR.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/helpset_hr_HR.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hr_HR/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hr_HR/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/helpset_hu_HU.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/helpset_hu_HU.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/helpset_hu_HU.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/helpset_hu_HU.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_hu_HU/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_hu_HU/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/helpset_id_ID.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/helpset_id_ID.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/helpset_id_ID.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/helpset_id_ID.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_id_ID/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_id_ID/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/helpset_it_IT.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/helpset_it_IT.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/helpset_it_IT.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/helpset_it_IT.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_it_IT/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_it_IT/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/helpset_ja_JP.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/helpset_ja_JP.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/helpset_ja_JP.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/helpset_ja_JP.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ja_JP/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ja_JP/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/helpset_ko_KR.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/helpset_ko_KR.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/helpset_ko_KR.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/helpset_ko_KR.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ko_KR/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ko_KR/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/helpset_ms_MY.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/helpset_ms_MY.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/helpset_ms_MY.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/helpset_ms_MY.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ms_MY/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ms_MY/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/helpset_pl_PL.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/helpset_pl_PL.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/helpset_pl_PL.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/helpset_pl_PL.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pl_PL/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pl_PL/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/helpset_pt_BR.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/helpset_pt_BR.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/helpset_pt_BR.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/helpset_pt_BR.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_pt_BR/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_pt_BR/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/helpset_ro_RO.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/helpset_ro_RO.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/helpset_ro_RO.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/helpset_ro_RO.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ro_RO/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ro_RO/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/helpset_ru_RU.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/helpset_ru_RU.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/helpset_ru_RU.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/helpset_ru_RU.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ru_RU/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ru_RU/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/helpset_si_LK.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/helpset_si_LK.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/helpset_si_LK.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/helpset_si_LK.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_si_LK/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_si_LK/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/helpset_sk_SK.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/helpset_sk_SK.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/helpset_sk_SK.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/helpset_sk_SK.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sk_SK/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sk_SK/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/helpset_sl_SI.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/helpset_sl_SI.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/helpset_sl_SI.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/helpset_sl_SI.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sl_SI/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sl_SI/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/helpset_sq_AL.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/helpset_sq_AL.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/helpset_sq_AL.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/helpset_sq_AL.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sq_AL/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sq_AL/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/helpset_sr_CS.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/helpset_sr_CS.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/helpset_sr_CS.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/helpset_sr_CS.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_CS/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_CS/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/helpset_sr_SP.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/helpset_sr_SP.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/helpset_sr_SP.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/helpset_sr_SP.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_sr_SP/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_sr_SP/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/helpset_tr_TR.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/helpset_tr_TR.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/helpset_tr_TR.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/helpset_tr_TR.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_tr_TR/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_tr_TR/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/helpset_ur_PK.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/helpset_ur_PK.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/helpset_ur_PK.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/helpset_ur_PK.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_ur_PK/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_ur_PK/toc.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/contents/images/srm.png b/src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/contents/images/srm.png similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/contents/images/srm.png rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/contents/images/srm.png diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/contents/srm.html b/src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/contents/srm.html similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/contents/srm.html rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/contents/srm.html diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/helpset_zh_CN.hs b/src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/helpset_zh_CN.hs similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/helpset_zh_CN.hs rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/helpset_zh_CN.hs diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/index.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/index.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/index.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/index.xml diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/map.jhm b/src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/map.jhm similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/map.jhm rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/map.jhm diff --git a/src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/toc.xml b/src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/toc.xml similarity index 100% rename from src/main/javahelp/com/github/srm/zap/srm/resources/help_zh_CN/toc.xml rename to src/main/javahelp/com/blackduck/zap/srm/resources/help_zh_CN/toc.xml diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_ar_SA.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_ar_SA.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_ar_SA.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_ar_SA.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_az_AZ.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_az_AZ.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_az_AZ.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_az_AZ.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_bn_BD.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_bn_BD.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_bn_BD.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_bn_BD.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_bs_BA.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_bs_BA.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_bs_BA.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_bs_BA.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_ceb_PH.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_ceb_PH.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_ceb_PH.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_ceb_PH.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_da_DK.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_da_DK.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_da_DK.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_da_DK.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_de_DE.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_de_DE.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_de_DE.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_de_DE.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_el_GR.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_el_GR.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_el_GR.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_el_GR.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_es_ES.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_es_ES.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_es_ES.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_es_ES.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_fa_IR.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_fa_IR.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_fa_IR.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_fa_IR.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_fil_PH.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_fil_PH.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_fil_PH.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_fil_PH.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_fr_FR.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_fr_FR.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_fr_FR.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_fr_FR.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_ha_HG.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_ha_HG.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_ha_HG.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_ha_HG.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_he_IL.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_he_IL.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_he_IL.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_he_IL.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_hi_IN.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_hi_IN.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_hi_IN.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_hi_IN.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_hr_HR.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_hr_HR.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_hr_HR.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_hr_HR.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_hu_HU.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_hu_HU.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_hu_HU.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_hu_HU.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_id_ID.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_id_ID.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_id_ID.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_id_ID.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_it_IT.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_it_IT.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_it_IT.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_it_IT.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_ja_JP.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_ja_JP.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_ja_JP.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_ja_JP.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_ko_KR.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_ko_KR.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_ko_KR.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_ko_KR.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_mk_MK.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_mk_MK.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_mk_MK.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_mk_MK.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_ms_MY.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_ms_MY.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_ms_MY.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_ms_MY.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_nb_NO.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_nb_NO.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_nb_NO.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_nb_NO.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_nl_NL.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_nl_NL.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_nl_NL.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_nl_NL.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_pcm_NG.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_pcm_NG.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_pcm_NG.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_pcm_NG.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_pl_PL.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_pl_PL.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_pl_PL.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_pl_PL.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_pt_BR.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_pt_BR.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_pt_BR.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_pt_BR.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_pt_PT.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_pt_PT.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_pt_PT.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_pt_PT.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_ro_RO.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_ro_RO.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_ro_RO.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_ro_RO.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_ru_RU.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_ru_RU.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_ru_RU.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_ru_RU.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_si_LK.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_si_LK.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_si_LK.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_si_LK.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_sk_SK.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_sk_SK.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_sk_SK.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_sk_SK.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_sl_SI.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_sl_SI.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_sl_SI.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_sl_SI.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_sq_AL.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_sq_AL.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_sq_AL.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_sq_AL.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_sr_CS.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_sr_CS.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_sr_CS.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_sr_CS.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_sr_SP.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_sr_SP.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_sr_SP.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_sr_SP.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_tr_TR.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_tr_TR.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_tr_TR.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_tr_TR.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_uk_UA.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_uk_UA.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_uk_UA.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_uk_UA.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_ur_PK.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_ur_PK.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_ur_PK.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_ur_PK.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_vi_VN.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_vi_VN.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_vi_VN.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_vi_VN.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_yo_NG.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_yo_NG.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_yo_NG.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_yo_NG.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_zh_CN.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_zh_CN.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_zh_CN.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_zh_CN.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/Messages_zh_TW.properties b/src/main/resources/com/blackduck/zap/srm/resources/Messages_zh_TW.properties similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/Messages_zh_TW.properties rename to src/main/resources/com/blackduck/zap/srm/resources/Messages_zh_TW.properties diff --git a/src/main/resources/com/github/srm/zap/srm/resources/refresh.png b/src/main/resources/com/blackduck/zap/srm/resources/refresh.png similarity index 100% rename from src/main/resources/com/github/srm/zap/srm/resources/refresh.png rename to src/main/resources/com/blackduck/zap/srm/resources/refresh.png From 62e504d49e6a305310eec68e476a2c1ca2cf1bfc Mon Sep 17 00:00:00 2001 From: splahoti12 Date: Tue, 25 Nov 2025 22:51:53 +0530 Subject: [PATCH 05/11] Suppress the this escape warning --- src/main/java/com/blackduck/zap/srm/SrmAPI.java | 4 +--- src/main/java/com/blackduck/zap/srm/SrmExtension.java | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/blackduck/zap/srm/SrmAPI.java b/src/main/java/com/blackduck/zap/srm/SrmAPI.java index 35bfd6b..a983890 100644 --- a/src/main/java/com/blackduck/zap/srm/SrmAPI.java +++ b/src/main/java/com/blackduck/zap/srm/SrmAPI.java @@ -50,11 +50,9 @@ public class SrmAPI extends ApiImplementor { private final SrmExtension extension; + @SuppressWarnings("this-escape") public SrmAPI(SrmExtension extension) { this.extension = extension; - } - - public void initApiViewsAndActions() { this.addApiView(new ApiView(VIEW_GENERATE)); String[] optionalParams = new String[]{ACTION_PARAM_FINGERPRINT, ACTION_PARAM_ACCEPT_PERM}; diff --git a/src/main/java/com/blackduck/zap/srm/SrmExtension.java b/src/main/java/com/blackduck/zap/srm/SrmExtension.java index b7eb8b2..2013ff1 100644 --- a/src/main/java/com/blackduck/zap/srm/SrmExtension.java +++ b/src/main/java/com/blackduck/zap/srm/SrmExtension.java @@ -75,7 +75,6 @@ public boolean canUnload() { public void hook(ExtensionHook extensionHook) { super.hook(extensionHook); cdxAPIImpl = new SrmAPI(this); - cdxAPIImpl.initApiViewsAndActions(); API.getInstance().registerApiImplementor(cdxAPIImpl); if (hasView()) { extensionHook.getHookMenu().addReportMenuItem(getUploadMenu()); From a98e93cfb5e994557d8ad30b448f74448a355ba9 Mon Sep 17 00:00:00 2001 From: splahoti12 Date: Wed, 26 Nov 2025 00:35:39 +0530 Subject: [PATCH 06/11] Removed the CopyRight Comments In each of the Files --- .../com/blackduck/zap/srm/ExtensionAlertHttp.java | 3 +-- .../com/blackduck/zap/srm/ReportGenerator.java | 10 ++-------- .../java/com/blackduck/zap/srm/ReportLastScan.java | 6 +----- .../com/blackduck/zap/srm/ReportLastScanHttp.java | 2 -- src/main/java/com/blackduck/zap/srm/SrmAPI.java | 2 -- .../java/com/blackduck/zap/srm/SrmExtension.java | 2 -- .../java/com/blackduck/zap/srm/SrmProperties.java | 2 -- .../blackduck/zap/srm/UploadActionListener.java | 14 ++++++-------- .../blackduck/zap/srm/UploadPropertiesDialog.java | 6 ++---- .../zap/srm/security/CertificateAcceptance.java | 2 -- .../srm/security/CompositeX509TrustManager.java | 2 -- .../zap/srm/security/ExtraCertManager.java | 2 -- .../security/HostnameVerifierWithExceptions.java | 2 -- .../security/InvalidCertificateDialogStrategy.java | 2 -- .../InvalidCertificateFingerprintStrategy.java | 2 -- .../srm/security/InvalidCertificateStrategy.java | 2 -- .../srm/security/ReloadableX509TrustManager.java | 2 -- .../SSLConnectionSocketFactoryFactory.java | 2 -- .../zap/srm/security/SingleExtraCertManager.java | 2 -- 19 files changed, 12 insertions(+), 55 deletions(-) diff --git a/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java b/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java index 20302e7..5a27999 100644 --- a/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java +++ b/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java @@ -3,8 +3,7 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * + * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/ReportGenerator.java b/src/main/java/com/blackduck/zap/srm/ReportGenerator.java index 6171b5e..8e30ac9 100644 --- a/src/main/java/com/blackduck/zap/srm/ReportGenerator.java +++ b/src/main/java/com/blackduck/zap/srm/ReportGenerator.java @@ -3,7 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2003-2004 The ZAP Development Team * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -127,10 +126,7 @@ public static File stringToHtml(String inxml, StreamSource stylesource, String o BufferedWriter bw = null; showDialogForGUI(); try { - bw = - Files.newBufferedWriter( - new File(outfilename + "-orig.xml").toPath(), - StandardCharsets.UTF_8); + bw = Files.newBufferedWriter(new File(outfilename + "-orig.xml").toPath(), StandardCharsets.UTF_8); bw.write(inxml); } catch (IOException e2) { LOGGER.error("Failed to write debug XML file", e); @@ -173,9 +169,7 @@ public static File stringToHtml(String inxml, StreamSource stylesource, String o BufferedWriter bw = null; try { - bw = - Files.newBufferedWriter( - new File(outfilename).toPath(), StandardCharsets.UTF_8); + bw = Files.newBufferedWriter(new File(outfilename).toPath(), StandardCharsets.UTF_8); bw.write(inxml); } catch (IOException e2) { showDialogForGUI(); diff --git a/src/main/java/com/blackduck/zap/srm/ReportLastScan.java b/src/main/java/com/blackduck/zap/srm/ReportLastScan.java index 81e990f..5dce335 100644 --- a/src/main/java/com/blackduck/zap/srm/ReportLastScan.java +++ b/src/main/java/com/blackduck/zap/srm/ReportLastScan.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2003-2004 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -210,9 +208,7 @@ public void generateReport(ViewDelegate view, ReportType reportType) { } try { - JFileChooser chooser = - new WritableFileChooser( - Model.getSingleton().getOptionsParam().getUserDirectory()); + JFileChooser chooser = new WritableFileChooser(Model.getSingleton().getOptionsParam().getUserDirectory()); chooser.setFileFilter( new FileFilter() { diff --git a/src/main/java/com/blackduck/zap/srm/ReportLastScanHttp.java b/src/main/java/com/blackduck/zap/srm/ReportLastScanHttp.java index a332b2e..2eec8f0 100644 --- a/src/main/java/com/blackduck/zap/srm/ReportLastScanHttp.java +++ b/src/main/java/com/blackduck/zap/srm/ReportLastScanHttp.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/SrmAPI.java b/src/main/java/com/blackduck/zap/srm/SrmAPI.java index a983890..8b9f0a9 100644 --- a/src/main/java/com/blackduck/zap/srm/SrmAPI.java +++ b/src/main/java/com/blackduck/zap/srm/SrmAPI.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/SrmExtension.java b/src/main/java/com/blackduck/zap/srm/SrmExtension.java index 2013ff1..614d64f 100644 --- a/src/main/java/com/blackduck/zap/srm/SrmExtension.java +++ b/src/main/java/com/blackduck/zap/srm/SrmExtension.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/SrmProperties.java b/src/main/java/com/blackduck/zap/srm/SrmProperties.java index 3f4edbf..0788419 100644 --- a/src/main/java/com/blackduck/zap/srm/SrmProperties.java +++ b/src/main/java/com/blackduck/zap/srm/SrmProperties.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/UploadActionListener.java b/src/main/java/com/blackduck/zap/srm/UploadActionListener.java index 55a4f07..14fa13b 100644 --- a/src/main/java/com/blackduck/zap/srm/UploadActionListener.java +++ b/src/main/java/com/blackduck/zap/srm/UploadActionListener.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -81,12 +79,12 @@ public void run() { String err; try { err = - uploadFile( - extension.getHttpClient(), - reportFile, - SrmProperties.getInstance().getServerUrl(), - SrmProperties.getInstance().getApiKey(), - prop.getProject().getValue()); + uploadFile( + extension.getHttpClient(), + reportFile, + SrmProperties.getInstance().getServerUrl(), + SrmProperties.getInstance().getApiKey(), + prop.getProject().getValue()); } catch (IOException ex1) { err = Constant.messages.getString("srm.error.unexpected"); LOGGER.error("Unexpected error while uploading report: ", ex1); diff --git a/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java b/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java index 9120a2c..3136e68 100644 --- a/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java +++ b/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -223,8 +221,8 @@ public void updateProjects(boolean initialRefresh) { get.setHeader("API-Key", getApiKey()); HttpResponse response = client.execute(get); rd = - new BufferedReader( - new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); + new BufferedReader( + new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); StringBuilder result = new StringBuilder(); String line = ""; diff --git a/src/main/java/com/blackduck/zap/srm/security/CertificateAcceptance.java b/src/main/java/com/blackduck/zap/srm/security/CertificateAcceptance.java index ef9bf75..9c2302a 100644 --- a/src/main/java/com/blackduck/zap/srm/security/CertificateAcceptance.java +++ b/src/main/java/com/blackduck/zap/srm/security/CertificateAcceptance.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java b/src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java index 6b58984..a156278 100644 --- a/src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java +++ b/src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/security/ExtraCertManager.java b/src/main/java/com/blackduck/zap/srm/security/ExtraCertManager.java index 9bcf367..3c3d5b2 100644 --- a/src/main/java/com/blackduck/zap/srm/security/ExtraCertManager.java +++ b/src/main/java/com/blackduck/zap/srm/security/ExtraCertManager.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/security/HostnameVerifierWithExceptions.java b/src/main/java/com/blackduck/zap/srm/security/HostnameVerifierWithExceptions.java index eaeeb05..52757f8 100644 --- a/src/main/java/com/blackduck/zap/srm/security/HostnameVerifierWithExceptions.java +++ b/src/main/java/com/blackduck/zap/srm/security/HostnameVerifierWithExceptions.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java index d0bb385..2c15026 100644 --- a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java +++ b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateFingerprintStrategy.java b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateFingerprintStrategy.java index e5fdc9c..5c0020d 100644 --- a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateFingerprintStrategy.java +++ b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateFingerprintStrategy.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateStrategy.java b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateStrategy.java index 48f5643..2284cbb 100644 --- a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateStrategy.java +++ b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateStrategy.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java b/src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java index c5974d7..c26efd2 100644 --- a/src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java +++ b/src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java b/src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java index 295b750..ae7a1b4 100644 --- a/src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java +++ b/src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/security/SingleExtraCertManager.java b/src/main/java/com/blackduck/zap/srm/security/SingleExtraCertManager.java index 9b91770..3624383 100644 --- a/src/main/java/com/blackduck/zap/srm/security/SingleExtraCertManager.java +++ b/src/main/java/com/blackduck/zap/srm/security/SingleExtraCertManager.java @@ -3,8 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Copyright 2025 The ZAP Development Team - * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at From b4829589ace9e6f7298b250e31fc630f907b5a00 Mon Sep 17 00:00:00 2001 From: splahoti12 Date: Wed, 26 Nov 2025 00:38:39 +0530 Subject: [PATCH 07/11] Replace the codedx with srm in the prefix --- src/main/java/com/blackduck/zap/srm/SrmAPI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/blackduck/zap/srm/SrmAPI.java b/src/main/java/com/blackduck/zap/srm/SrmAPI.java index 8b9f0a9..9e5d203 100644 --- a/src/main/java/com/blackduck/zap/srm/SrmAPI.java +++ b/src/main/java/com/blackduck/zap/srm/SrmAPI.java @@ -31,7 +31,7 @@ public class SrmAPI extends ApiImplementor { private static final Logger LOGGER = LogManager.getLogger(SrmExtension.class); - private static final String PREFIX = "codedx"; + private static final String PREFIX = "srm"; private static final String VIEW_GENERATE = "generateReport"; private static final String ACTION_UPLOAD = "uploadReport"; From 522c350a7026b144385f4926ab61828023dcd3d3 Mon Sep 17 00:00:00 2001 From: splahoti12 Date: Wed, 26 Nov 2025 00:42:06 +0530 Subject: [PATCH 08/11] Remove the Plugin management from Settings --- settings.gradle.kts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 3b30197..be781eb 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,10 +1,3 @@ -pluginManagement { - repositories { - mavenCentral() - gradlePluginPortal() - } -} - plugins { id("org.zaproxy.common.settings") version "0.5.0" id("com.diffplug.spotless") version "6.25.0" apply false From 80c81194720d151adb0df538f6eb7c5ad0d3fb0b Mon Sep 17 00:00:00 2001 From: splahoti12 Date: Wed, 26 Nov 2025 01:36:13 +0530 Subject: [PATCH 09/11] Refactor the code and updated the Readme --- README.md | 23 +-- .../blackduck/zap/srm/ExtensionAlertHttp.java | 12 +- .../blackduck/zap/srm/ReportGenerator.java | 45 ++--- .../com/blackduck/zap/srm/ReportLastScan.java | 114 +++++------- .../java/com/blackduck/zap/srm/SrmAPI.java | 43 +---- .../com/blackduck/zap/srm/SrmExtension.java | 41 ++--- .../zap/srm/UploadActionListener.java | 89 +++------ .../zap/srm/UploadPropertiesDialog.java | 173 ++++++------------ .../security/CompositeX509TrustManager.java | 6 +- .../HostnameVerifierWithExceptions.java | 3 +- .../InvalidCertificateDialogStrategy.java | 35 +--- .../security/ReloadableX509TrustManager.java | 19 +- .../SSLConnectionSocketFactoryFactory.java | 46 ++--- 13 files changed, 194 insertions(+), 455 deletions(-) diff --git a/README.md b/README.md index 6c0fd43..da4c85f 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,15 @@ -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) -[![CodeQL](https://github.com/zaproxy/zap-extensions/actions/workflows/codeql.yml/badge.svg)](https://github.com/zaproxy/zap-extensions/actions/workflows/codeql.yml) -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=zaproxy_zap-extensions&metric=alert_status)](https://sonarcloud.io/dashboard?id=zaproxy_zap-extensions) - -This project contains add-ons for the [Zed Attack Proxy](https://github.com/zaproxy/zaproxy) (ZAP). +This project contains the Software Risk Manager add-on for the [Zed Attack Proxy](https://github.com/zaproxy/zaproxy) (ZAP). If you are using the latest version of ZAP, you can browse and download "Software Risk Manager Extension" directly from within ZAP by clicking the Marketplace button in the toolbar. -This specific add-on is Software Risk Manager (SRM), and you can find it in the Marketplace under the name “Software Risk Manager Extension”. ![Image](https://github.com/zaproxy/zap-extensions/wiki/images/zap-screenshot-browse-addons.png) -You can also import add-ons you have downloaded manually from https://github.com/zaproxy/zap-extensions/releases via the "File / Load Add-on File..." menu option. - -Please see the [wiki](https://github.com/zaproxy/zap-extensions/wiki) for more details. - -## Building - -The add-ons are built with [Gradle], each add-on has its own project which is located under the `addOns` project/directory. - -To build zap-extensions follow the instructions on: +## Build and Import Steps +The add-ons are built with [Gradle], -https://www.zaproxy.org/docs/developer/quick-start-build/ +1\. Run `./gradlew assemble` to build the add-on. +2\. Locate the output file at `/build/zapAddOn/bin/srm-alpha-*.zap`. +3\. In ZAP, go to the menu option `File / Load Add-on File...`. +4\. Select the generated `.zap` file to import the add-on. [Gradle]: https://gradle.org/ diff --git a/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java b/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java index 5a27999..05fd7d8 100644 --- a/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java +++ b/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java @@ -89,17 +89,11 @@ public String getUrlParamXML(Alert alert) { sb.append(getHTML(alert)); sb.append(" ").append(ReportGenerator.entityEncode(uri)).append("\r\n"); sb.append(" ").append(ReportGenerator.entityEncode(param)).append("\r\n"); - sb.append(" ") - .append(ReportGenerator.entityEncode(attack)) - .append("\r\n"); + sb.append(" ").append(ReportGenerator.entityEncode(attack)).append("\r\n"); if (evidence != null && evidence.length() > 0) { - sb.append(" ") - .append(ReportGenerator.entityEncode(evidence)) - .append("\r\n"); + sb.append(" ").append(ReportGenerator.entityEncode(evidence)).append("\r\n"); } - sb.append(" ") - .append(ReportGenerator.entityEncode(otherInfo)) - .append("\r\n"); + sb.append(" ").append(ReportGenerator.entityEncode(otherInfo)).append("\r\n"); return sb.toString(); } } diff --git a/src/main/java/com/blackduck/zap/srm/ReportGenerator.java b/src/main/java/com/blackduck/zap/srm/ReportGenerator.java index 8e30ac9..cc5e7a6 100644 --- a/src/main/java/com/blackduck/zap/srm/ReportGenerator.java +++ b/src/main/java/com/blackduck/zap/srm/ReportGenerator.java @@ -56,8 +56,7 @@ public class ReportGenerator { // private static Pattern patternWindows = Pattern.compile("window", Pattern.CASE_INSENSITIVE); // private static Pattern patternLinux = Pattern.compile("linux", Pattern.CASE_INSENSITIVE); - private static final SimpleDateFormat staticDateFormat = - new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss"); + private static final SimpleDateFormat staticDateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss"); public static File XMLToHtml(Document xmlDocument, String infilexsl, File outFile) { File stylesheet = null; @@ -85,10 +84,7 @@ public static File XMLToHtml(Document xmlDocument, String infilexsl, File outFil } public static File stringToHtml(String inxml, String infilexsl, String outfilename) { - return stringToHtml( - inxml, - infilexsl != null ? new StreamSource(new File(infilexsl)) : null, - outfilename); + return stringToHtml(inxml, infilexsl != null ? new StreamSource(new File(infilexsl)) : null, outfilename); } public static File stringToHtml(String inxml, StreamSource stylesource, String outfilename) { @@ -104,8 +100,7 @@ public static File stringToHtml(String inxml, StreamSource stylesource, String o try { outfile = new File(tempOutfilename); - DocumentBuilder builder = - XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); + DocumentBuilder builder = XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); doc = builder.parse(new InputSource(inReader)); // Use a Transformer for output @@ -117,10 +112,7 @@ public static File stringToHtml(String inxml, StreamSource stylesource, String o StreamResult result = new StreamResult(outfile.getPath()); transformer.transform(source, result); - } catch (TransformerException - | SAXException - | ParserConfigurationException - | IOException e) { + } catch (TransformerException | SAXException | ParserConfigurationException | IOException e) { LOGGER.error(e.getMessage(), e); // Save the xml for diagnosing the problem BufferedWriter bw = null; @@ -146,12 +138,7 @@ public static File stringToHtml(String inxml, StreamSource stylesource, String o // we should really adopt something other than XSLT ;) String line; - try (BufferedReader br = - Files.newBufferedReader( - new File(tempOutfilename).toPath(), StandardCharsets.UTF_8); - BufferedWriter bw = - Files.newBufferedWriter( - new File(outfilename).toPath(), StandardCharsets.UTF_8)) { + try (BufferedReader br = Files.newBufferedReader(new File(tempOutfilename).toPath(), StandardCharsets.UTF_8); BufferedWriter bw = Files.newBufferedWriter(new File(outfilename).toPath(), StandardCharsets.UTF_8)) { while ((line = br.readLine()) != null) { bw.write(line.replace("<p>", "

").replace("</p>", "

")); @@ -219,8 +206,7 @@ public static String stringToHtml(String inxml, StreamSource stylesource) { try { - DocumentBuilder builder = - XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); + DocumentBuilder builder = XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); doc = builder.parse(new InputSource(inReader)); // Use a Transformer for output @@ -232,10 +218,7 @@ public static String stringToHtml(String inxml, StreamSource stylesource) { StreamResult result = new StreamResult(writer); transformer.transform(source, result); - } catch (TransformerException - | SAXException - | ParserConfigurationException - | IOException e) { + } catch (TransformerException | SAXException | ParserConfigurationException | IOException e) { showDialogForGUI(); LOGGER.error(e.getMessage(), e); } @@ -260,8 +243,7 @@ public static File fileToHtml(String infilexml, String infilexsl, String outfile datafile = new File(infilexml); outfile = new File(outfilename); - DocumentBuilder builder = - XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); + DocumentBuilder builder = XmlUtils.newXxeDisabledDocumentBuilderFactory().newDocumentBuilder(); doc = builder.parse(datafile); // Use a Transformer for output @@ -274,10 +256,7 @@ public static File fileToHtml(String infilexml, String infilexsl, String outfile StreamResult result = new StreamResult(outfile.getPath()); transformer.transform(source, result); - } catch (TransformerException - | SAXException - | ParserConfigurationException - | IOException e) { + } catch (TransformerException | SAXException | ParserConfigurationException | IOException e) { showDialogForGUI(); LOGGER.error(e.getMessage(), e); } @@ -328,8 +307,7 @@ public static String getDateTimeString(Date dateTime) { } } - public static void addChildTextNode( - Document doc, Element parent, String nodeName, String text) { + public static void addChildTextNode(Document doc, Element parent, String nodeName, String text) { Element child = doc.createElement(nodeName); child.appendChild(doc.createTextNode(text)); parent.appendChild(child); @@ -346,8 +324,7 @@ public static String getDebugXMLString(Document doc) throws TransformerException private static void showDialogForGUI() { if (View.isInitialised()) { - JOptionPane.showMessageDialog( - null, Constant.messages.getString("report.write.dialog.message")); + JOptionPane.showMessageDialog(null, Constant.messages.getString("report.write.dialog.message")); } } } diff --git a/src/main/java/com/blackduck/zap/srm/ReportLastScan.java b/src/main/java/com/blackduck/zap/srm/ReportLastScan.java index 5dce335..314d771 100644 --- a/src/main/java/com/blackduck/zap/srm/ReportLastScan.java +++ b/src/main/java/com/blackduck/zap/srm/ReportLastScan.java @@ -56,10 +56,7 @@ public class ReportLastScan { private static final String JSON_FILE_EXTENSION = ".json"; public enum ReportType { - HTML, - XML, - MD, - JSON + HTML, XML, MD, JSON } public ReportLastScan() { @@ -100,8 +97,7 @@ public File generate(String fileName, ReportType reportType) throws Exception { return generateReportWithXsl(sb.toString(), fileName, xslFileName); } - private static File generateReportWithXsl(String report, String reportFile, String xslFileName) - throws IOException { + private static File generateReportWithXsl(String report, String reportFile, String xslFileName) throws IOException { Path xslFile = Paths.get(Constant.getZapInstall(), "xml", xslFileName); if (Files.exists(xslFile)) { return ReportGenerator.stringToHtml(report, xslFile.toString(), reportFile); @@ -128,11 +124,7 @@ public void generate(StringBuilder report, Model model) throws Exception { public void generate(StringBuilder report) throws Exception { report.append(""); - report.append("\r\n"); + report.append("\r\n"); siteXML(report); report.append(""); } @@ -146,20 +138,7 @@ private void siteXML(StringBuilder report) { String siteName = ScanPanel.cleanSiteName(site, true); String[] hostAndPort = siteName.split(":"); boolean isSSL = (site.getNodeName().startsWith("https")); - String siteStart = - ""; + String siteStart = ""; StringBuilder extensionsXML = getExtensionsXML(site); String siteEnd = ""; report.append(siteStart); @@ -210,46 +189,44 @@ public void generateReport(ViewDelegate view, ReportType reportType) { try { JFileChooser chooser = new WritableFileChooser(Model.getSingleton().getOptionsParam().getUserDirectory()); - chooser.setFileFilter( - new FileFilter() { - - @Override - public boolean accept(File file) { - if (file.isDirectory()) { - return true; - } else if (file.isFile()) { - String lcFileName = file.getName().toLowerCase(Locale.ROOT); - switch (localReportType) { - case XML: - return lcFileName.endsWith(XML_FILE_EXTENSION); - case MD: - return lcFileName.endsWith(MD_FILE_EXTENSION); - case JSON: - return lcFileName.endsWith(JSON_FILE_EXTENSION); - case HTML: - default: - return (lcFileName.endsWith(HTM_FILE_EXTENSION) - || lcFileName.endsWith(HTML_FILE_EXTENSION)); - } - } - return false; + chooser.setFileFilter(new FileFilter() { + + @Override + public boolean accept(File file) { + if (file.isDirectory()) { + return true; + } else if (file.isFile()) { + String lcFileName = file.getName().toLowerCase(Locale.ROOT); + switch (localReportType) { + case XML: + return lcFileName.endsWith(XML_FILE_EXTENSION); + case MD: + return lcFileName.endsWith(MD_FILE_EXTENSION); + case JSON: + return lcFileName.endsWith(JSON_FILE_EXTENSION); + case HTML: + default: + return (lcFileName.endsWith(HTM_FILE_EXTENSION) || lcFileName.endsWith(HTML_FILE_EXTENSION)); } + } + return false; + } - @Override - public String getDescription() { - switch (localReportType) { - case XML: - return Constant.messages.getString("file.format.xml"); - case MD: - return Constant.messages.getString("file.format.md"); - case JSON: - return Constant.messages.getString("file.format.json"); - case HTML: - default: - return Constant.messages.getString("file.format.html"); - } - } - }); + @Override + public String getDescription() { + switch (localReportType) { + case XML: + return Constant.messages.getString("file.format.xml"); + case MD: + return Constant.messages.getString("file.format.md"); + case JSON: + return Constant.messages.getString("file.format.json"); + case HTML: + default: + return Constant.messages.getString("file.format.html"); + } + } + }); String fileExtension = ""; switch (localReportType) { @@ -267,8 +244,7 @@ public String getDescription() { fileExtension = HTML_FILE_EXTENSION; break; } - chooser.setSelectedFile( - new File(fileExtension)); // Default the filename to a reasonable extension; + chooser.setSelectedFile(new File(fileExtension)); // Default the filename to a reasonable extension; int rc = chooser.showSaveDialog(View.getSingleton().getMainFrame()); File file = null; @@ -277,9 +253,7 @@ public String getDescription() { File report = generate(file.getAbsolutePath(), localReportType); if (report == null) { - view.showMessageDialog( - Constant.messages.getString( - "report.unknown.error", file.getAbsolutePath())); + view.showMessageDialog(Constant.messages.getString("report.unknown.error", file.getAbsolutePath())); return; } @@ -292,9 +266,7 @@ public String getDescription() { DesktopUtils.openUrlInBrowser(report.toURI()); } catch (Exception e) { LOGGER.error(e.getMessage(), e); - view.showMessageDialog( - Constant.messages.getString( - "report.complete.warning", report.getAbsolutePath())); + view.showMessageDialog(Constant.messages.getString("report.complete.warning", report.getAbsolutePath())); } } diff --git a/src/main/java/com/blackduck/zap/srm/SrmAPI.java b/src/main/java/com/blackduck/zap/srm/SrmAPI.java index 9e5d203..0fa4a54 100644 --- a/src/main/java/com/blackduck/zap/srm/SrmAPI.java +++ b/src/main/java/com/blackduck/zap/srm/SrmAPI.java @@ -55,23 +55,8 @@ public SrmAPI(SrmExtension extension) { String[] optionalParams = new String[]{ACTION_PARAM_FINGERPRINT, ACTION_PARAM_ACCEPT_PERM}; - this.addApiAction( - new ApiAction( - ACTION_UPLOAD, - new String[]{ - ACTION_PARAM_FILE_PATH, - ACTION_PARAM_SERVER_URL, - ACTION_PARAM_API_KEY, - ACTION_PARAM_PROJECT - }, - optionalParams)); - this.addApiAction( - new ApiAction( - ACTION_GEN_UPLOAD, - new String[]{ - ACTION_PARAM_SERVER_URL, ACTION_PARAM_API_KEY, ACTION_PARAM_PROJECT - }, - optionalParams)); + this.addApiAction(new ApiAction(ACTION_UPLOAD, new String[]{ACTION_PARAM_FILE_PATH, ACTION_PARAM_SERVER_URL, ACTION_PARAM_API_KEY, ACTION_PARAM_PROJECT}, optionalParams)); + this.addApiAction(new ApiAction(ACTION_GEN_UPLOAD, new String[]{ACTION_PARAM_SERVER_URL, ACTION_PARAM_API_KEY, ACTION_PARAM_PROJECT}, optionalParams)); } @Override @@ -110,14 +95,7 @@ public ApiResponse handleApiAction(String name, JSONObject params) throws ApiExc throw new ApiException(Type.INTERNAL_ERROR, e.getMessage()); } try { - if (!isEmpty) - uploadFile( - reportFile, - serverUrl, - apiKey, - projectId, - fingerprint, - acceptPermanently); + if (!isEmpty) uploadFile(reportFile, serverUrl, apiKey, projectId, fingerprint, acceptPermanently); else return new ApiResponseElement("Result", "empty"); } finally { reportFile.delete(); @@ -142,20 +120,11 @@ public ApiResponse handleApiView(String name, JSONObject params) throws ApiExcep throw new ApiException(Type.BAD_VIEW); } - private void uploadFile( - File reportFile, - String serverUrl, - String apiKey, - String project, - String fingerprint, - boolean acceptPermanently) - throws ApiException { + private void uploadFile(File reportFile, String serverUrl, String apiKey, String project, String fingerprint, boolean acceptPermanently) throws ApiException { if (serverUrl.endsWith("/")) serverUrl = serverUrl.substring(0, serverUrl.length() - 1); try { - CloseableHttpClient client = - extension.getHttpClient(serverUrl, fingerprint, acceptPermanently); - String err = - UploadActionListener.uploadFile(client, reportFile, serverUrl, apiKey, project); + CloseableHttpClient client = extension.getHttpClient(serverUrl, fingerprint, acceptPermanently); + String err = UploadActionListener.uploadFile(client, reportFile, serverUrl, apiKey, project); if (err != null) { LOGGER.error(err); throw new ApiException(Type.ILLEGAL_PARAMETER, err); diff --git a/src/main/java/com/blackduck/zap/srm/SrmExtension.java b/src/main/java/com/blackduck/zap/srm/SrmExtension.java index 614d64f..8ae8f6a 100644 --- a/src/main/java/com/blackduck/zap/srm/SrmExtension.java +++ b/src/main/java/com/blackduck/zap/srm/SrmExtension.java @@ -97,11 +97,10 @@ public ZapMenuItem getExportMenu() { if (menuExport == null) { menuExport = new ZapMenuItem("srm.topmenu.report.title"); - menuExport.addActionListener( - e -> { - ReportLastScanHttp saver = new ReportLastScanHttp(); - saver.generateReport(getView(), ReportType.XML); - }); + menuExport.addActionListener(e -> { + ReportLastScanHttp saver = new ReportLastScanHttp(); + saver.generateReport(getView(), ReportType.XML); + }); } return menuExport; } @@ -110,38 +109,26 @@ public CloseableHttpClient getHttpClient() { try { return getHttpClient(SrmProperties.getInstance().getServerUrl()); } catch (MalformedURLException e) { - View.getSingleton() - .showWarningDialog(Constant.messages.getString("srm.error.client.invalid")); + View.getSingleton().showWarningDialog(Constant.messages.getString("srm.error.client.invalid")); } catch (IOException | GeneralSecurityException e) { - View.getSingleton() - .showWarningDialog(Constant.messages.getString("srm.error.client.failed")); + View.getSingleton().showWarningDialog(Constant.messages.getString("srm.error.client.failed")); } return null; } - public CloseableHttpClient getHttpClient(String url) - throws IOException, GeneralSecurityException { + public CloseableHttpClient getHttpClient(String url) throws IOException, GeneralSecurityException { return getHttpClient(url, null, false); } @SuppressWarnings("deprecation") - public CloseableHttpClient getHttpClient( - String url, String fingerprint, boolean acceptPermanently) - throws IOException, GeneralSecurityException { - RequestConfig.Builder configBuilder = - RequestConfig.custom() - .setConnectTimeout(getTimeout()) - .setSocketTimeout(getTimeout()) - .setConnectionRequestTimeout(getTimeout()); + public CloseableHttpClient getHttpClient(String url, String fingerprint, boolean acceptPermanently) throws IOException, GeneralSecurityException { + RequestConfig.Builder configBuilder = RequestConfig.custom().setConnectTimeout(getTimeout()).setSocketTimeout(getTimeout()).setConnectionRequestTimeout(getTimeout()); HttpClientBuilder builder = HttpClientBuilder.create(); if (fingerprint != null) { - builder.setSSLSocketFactory( - SSLConnectionSocketFactoryFactory.getFactory( - URI.create(url).getHost(), this, fingerprint, acceptPermanently)); + builder.setSSLSocketFactory(SSLConnectionSocketFactoryFactory.getFactory(URI.create(url).getHost(), this, fingerprint, acceptPermanently)); } else { - builder.setSSLSocketFactory( - SSLConnectionSocketFactoryFactory.getFactory(URI.create(url).getHost(), this)); + builder.setSSLSocketFactory(SSLConnectionSocketFactoryFactory.getFactory(URI.create(url).getHost(), this)); } ConnectionParam connParam = Model.getSingleton().getOptionsParam().getConnectionParam(); @@ -153,11 +140,7 @@ public CloseableHttpClient getHttpClient( if (connParam.isUseProxyChainAuth()) { BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials( - new AuthScope(proxyHost, proxyPort), - new UsernamePasswordCredentials( - connParam.getProxyChainUserName(), - connParam.getProxyChainPassword())); + credsProvider.setCredentials(new AuthScope(proxyHost, proxyPort), new UsernamePasswordCredentials(connParam.getProxyChainUserName(), connParam.getProxyChainPassword())); builder.setDefaultCredentialsProvider(credsProvider); } } diff --git a/src/main/java/com/blackduck/zap/srm/UploadActionListener.java b/src/main/java/com/blackduck/zap/srm/UploadActionListener.java index 14fa13b..be95a1e 100644 --- a/src/main/java/com/blackduck/zap/srm/UploadActionListener.java +++ b/src/main/java/com/blackduck/zap/srm/UploadActionListener.java @@ -72,32 +72,21 @@ public void generateAndUploadReport() { try { final File reportFile = generateReportFile(extension); if (!reportIsEmpty(reportFile)) { - Thread uploadThread = - new Thread() { - @Override - public void run() { - String err; - try { - err = - uploadFile( - extension.getHttpClient(), - reportFile, - SrmProperties.getInstance().getServerUrl(), - SrmProperties.getInstance().getApiKey(), - prop.getProject().getValue()); - } catch (IOException ex1) { - err = Constant.messages.getString("srm.error.unexpected"); - LOGGER.error("Unexpected error while uploading report: ", ex1); - } - if (err != null) View.getSingleton().showMessageDialog(err); - else - View.getSingleton() - .showMessageDialog( - Constant.messages.getString( - "srm.message.success")); - reportFile.delete(); - } - }; + Thread uploadThread = new Thread() { + @Override + public void run() { + String err; + try { + err = uploadFile(extension.getHttpClient(), reportFile, SrmProperties.getInstance().getServerUrl(), SrmProperties.getInstance().getApiKey(), prop.getProject().getValue()); + } catch (IOException ex1) { + err = Constant.messages.getString("srm.error.unexpected"); + LOGGER.error("Unexpected error while uploading report: ", ex1); + } + if (err != null) View.getSingleton().showMessageDialog(err); + else View.getSingleton().showMessageDialog(Constant.messages.getString("srm.message.success")); + reportFile.delete(); + } + }; uploadThread.start(); } else { error = Constant.messages.getString("srm.error.empty"); @@ -109,13 +98,7 @@ public void run() { if (error != null) View.getSingleton().showWarningDialog(error); } - public static String uploadFile( - CloseableHttpClient client, - File reportFile, - String serverUrl, - String apiKey, - String project) - throws IOException { + public static String uploadFile(CloseableHttpClient client, File reportFile, String serverUrl, String apiKey, String project) throws IOException { String err = null; HttpResponse response = sendData(client, reportFile, serverUrl, apiKey, project); StatusLine responseLine = null; @@ -125,40 +108,21 @@ public static String uploadFile( responseCode = responseLine.getStatusCode(); } if (responseCode == 400) { - err = - Constant.messages.getString("srm.error.unexpected") - + "\n" - + Constant.messages.getString("srm.error.http.400"); + err = Constant.messages.getString("srm.error.unexpected") + "\n" + Constant.messages.getString("srm.error.http.400"); } else if (responseCode == 403) { - err = - Constant.messages.getString("srm.error.unsent") - + " " - + Constant.messages.getString("srm.error.http.403"); + err = Constant.messages.getString("srm.error.unsent") + " " + Constant.messages.getString("srm.error.http.403"); } else if (responseCode == 404) { - err = - Constant.messages.getString("srm.error.unsent") - + " " - + Constant.messages.getString("srm.error.http.404"); + err = Constant.messages.getString("srm.error.unsent") + " " + Constant.messages.getString("srm.error.http.404"); } else if (responseCode == 415) { - err = - Constant.messages.getString("srm.error.unexpected") - + "\n" - + Constant.messages.getString("srm.error.http.415"); + err = Constant.messages.getString("srm.error.unexpected") + "\n" + Constant.messages.getString("srm.error.http.415"); } else if (responseCode != 200 && responseCode != 202) { err = Constant.messages.getString("srm.error.unexpected"); - if (response != null) - err += Constant.messages.getString("srm.error.http.other") + " " + responseLine; + if (response != null) err += Constant.messages.getString("srm.error.http.other") + " " + responseLine; } return err; } - private static HttpResponse sendData( - CloseableHttpClient client, - File reportFile, - String serverUrl, - String apiKey, - String project) - throws IOException { + private static HttpResponse sendData(CloseableHttpClient client, File reportFile, String serverUrl, String apiKey, String project) throws IOException { if (client == null) return null; try { HttpPost post = new HttpPost(serverUrl + "/api/projects/" + project + "/analysis"); @@ -184,8 +148,7 @@ private static HttpResponse sendData( } } - public static void generateReportString(SrmExtension extension, StringBuilder report) - throws Exception { + public static void generateReportString(SrmExtension extension, StringBuilder report) throws Exception { ReportLastScanHttp saver = new ReportLastScanHttp(); saver.generate(report); } @@ -207,11 +170,7 @@ public static Boolean reportIsEmpty(File reportFile) throws IOException, XMLStre while (reader.hasNext()) { XMLEvent event = reader.nextEvent(); - if (event.isStartElement() - && !event.asStartElement() - .getName() - .getLocalPart() - .equals("OWASPZAPReport")) { + if (event.isStartElement() && !event.asStartElement().getName().getLocalPart().equals("OWASPZAPReport")) { return false; } } diff --git a/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java b/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java index 3136e68..8b3da94 100644 --- a/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java +++ b/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java @@ -44,15 +44,9 @@ public class UploadPropertiesDialog { private static final Logger LOGGER = LogManager.getLogger(UploadPropertiesDialog.class); - private static final String[] DIALOG_BUTTONS = { - Constant.messages.getString("srm.settings.upload"), - Constant.messages.getString("srm.settings.cancel") - }; + private static final String[] DIALOG_BUTTONS = {Constant.messages.getString("srm.settings.upload"), Constant.messages.getString("srm.settings.cancel")}; - public static final ImageIcon REFRESH_ICON = - new ImageIcon( - UploadPropertiesDialog.class.getResource( - "/com/blackduck/zap/srm/resources/refresh.png")); + public static final ImageIcon REFRESH_ICON = new ImageIcon(UploadPropertiesDialog.class.getResource("/com/blackduck/zap/srm/resources/refresh.png")); private JTextField serverUrl; private JTextField apiKey; @@ -71,70 +65,41 @@ public UploadPropertiesDialog(SrmExtension extension) { public void openProperties(final UploadActionListener uploader) { JPanel message = new JPanel(new GridBagLayout()); - serverUrl = - labelTextField( - Constant.messages.getString("srm.settings.serverurl") + " ", - message, - SrmProperties.getInstance().getServerUrl(), - 30); - apiKey = - labelTextField( - Constant.messages.getString("srm.settings.apikey") + " ", - message, - SrmProperties.getInstance().getApiKey(), - 30); + serverUrl = labelTextField(Constant.messages.getString("srm.settings.serverurl") + " ", message, SrmProperties.getInstance().getServerUrl(), 30); + apiKey = labelTextField(Constant.messages.getString("srm.settings.apikey") + " ", message, SrmProperties.getInstance().getApiKey(), 30); projectBox = createProjectComboBox(message); - timeout = - labelTextField( - Constant.messages.getString("srm.setting.timeout") + " ", - message, - SrmProperties.getInstance().getTimeout(), - 5); - - final JOptionPane pane = - new JOptionPane( - message, - JOptionPane.PLAIN_MESSAGE, - JOptionPane.OK_CANCEL_OPTION, - null, - DIALOG_BUTTONS, - null); + timeout = labelTextField(Constant.messages.getString("srm.setting.timeout") + " ", message, SrmProperties.getInstance().getTimeout(), 5); + + final JOptionPane pane = new JOptionPane(message, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null, DIALOG_BUTTONS, null); dialog = pane.createDialog(Constant.messages.getString("srm.settings.title")); - Thread popupThread = - new Thread() { - @Override - public void run() { - dialog.setVisible(true); - if (DIALOG_BUTTONS[0].equals(pane.getValue())) { - String timeoutValue = timeout.getText(); - if (!isStringNumber(timeoutValue)) { - timeoutValue = SrmProperties.DEFAULT_TIMEOUT_STRING; - error(Constant.messages.getString("srm.error.timeout")); - } - SrmProperties.getInstance() - .setProperties( - serverUrl.getText(), - apiKey.getText(), - getProject().getValue(), - timeoutValue); - uploader.generateAndUploadReport(); - } + Thread popupThread = new Thread() { + @Override + public void run() { + dialog.setVisible(true); + if (DIALOG_BUTTONS[0].equals(pane.getValue())) { + String timeoutValue = timeout.getText(); + if (!isStringNumber(timeoutValue)) { + timeoutValue = SrmProperties.DEFAULT_TIMEOUT_STRING; + error(Constant.messages.getString("srm.error.timeout")); } - }; - Thread updateThread = - new Thread() { - @Override - public void run() { - if (!"".equals(serverUrl.getText()) && !"".equals(apiKey.getText())) { - updateProjects(true); - String previousId = SrmProperties.getInstance().getSelectedId(); - for (NameValuePair p : projectArr) { - if (previousId.equals(p.getValue())) projectBox.setSelectedItem(p); - } - } + SrmProperties.getInstance().setProperties(serverUrl.getText(), apiKey.getText(), getProject().getValue(), timeoutValue); + uploader.generateAndUploadReport(); + } + } + }; + Thread updateThread = new Thread() { + @Override + public void run() { + if (!"".equals(serverUrl.getText()) && !"".equals(apiKey.getText())) { + updateProjects(true); + String previousId = SrmProperties.getInstance().getSelectedId(); + for (NameValuePair p : projectArr) { + if (previousId.equals(p.getValue())) projectBox.setSelectedItem(p); } - }; + } + } + }; popupThread.start(); updateThread.start(); } @@ -172,18 +137,16 @@ private JComboBox createProjectComboBox(Container cont) { cont.add(box, gbc); JButton refresh = new JButton(REFRESH_ICON); - refresh.setPreferredSize( - new Dimension(REFRESH_ICON.getIconHeight() + 6, REFRESH_ICON.getIconHeight() + 6)); - refresh.addActionListener( - e -> { - if ("".equals(serverUrl.getText()) || "".equals(apiKey.getText())) { - error(Constant.messages.getString("srm.error.required")); - return; - } - dialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); - updateProjects(); - dialog.setCursor(Cursor.getDefaultCursor()); - }); + refresh.setPreferredSize(new Dimension(REFRESH_ICON.getIconHeight() + 6, REFRESH_ICON.getIconHeight() + 6)); + refresh.addActionListener(e -> { + if ("".equals(serverUrl.getText()) || "".equals(apiKey.getText())) { + error(Constant.messages.getString("srm.error.required")); + return; + } + dialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); + updateProjects(); + dialog.setCursor(Cursor.getDefaultCursor()); + }); gbc = new GridBagConstraints(); gbc.gridx = 2; gbc.gridy = 2; @@ -220,9 +183,7 @@ public void updateProjects(boolean initialRefresh) { HttpGet get = new HttpGet(getServerUrl() + "/api/projects"); get.setHeader("API-Key", getApiKey()); HttpResponse response = client.execute(get); - rd = - new BufferedReader( - new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); + rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); StringBuilder result = new StringBuilder(); String line = ""; @@ -234,11 +195,7 @@ public void updateProjects(boolean initialRefresh) { if (code == 200) { projectArr = parseProjectJson(result.toString(), initialRefresh); } else if (!initialRefresh) { - String msg = - Constant.messages.getString("srm.refresh.non200") - + ' ' - + response.getStatusLine() - + '.'; + String msg = Constant.messages.getString("srm.refresh.non200") + ' ' + response.getStatusLine() + '.'; if (code == 403) msg += Constant.messages.getString("srm.refresh.403"); else if (code == 404) msg += Constant.messages.getString("srm.refresh.404"); else if (code == 400) msg += Constant.messages.getString("srm.refresh.400"); @@ -247,29 +204,25 @@ public void updateProjects(boolean initialRefresh) { } } catch (GeneralSecurityException | ParseException | IOException e) { if (!initialRefresh) { - if (e instanceof MalformedURLException) - error(Constant.messages.getString("srm.error.client.invalid")); + if (e instanceof MalformedURLException) error(Constant.messages.getString("srm.error.client.invalid")); else error(Constant.messages.getString("srm.refresh.failed")); } LOGGER.error("Error refreshing project list: ", e); } finally { - if (client != null) - try { - client.close(); - } catch (IOException e) { - } - if (rd != null) - try { - rd.close(); - } catch (IOException e) { - } + if (client != null) try { + client.close(); + } catch (IOException e) { + } + if (rd != null) try { + rd.close(); + } catch (IOException e) { + } } updateProjectComboBox(); dialog.setCursor(Cursor.getDefaultCursor()); } - private ModifiedNameValuePair[] parseProjectJson(String json, boolean initialRefresh) - throws ParseException { + private ModifiedNameValuePair[] parseProjectJson(String json, boolean initialRefresh) throws ParseException { JSONParser parser = new JSONParser(); JSONObject obj = (JSONObject) parser.parse(json); JSONArray projects = (JSONArray) obj.get("projects"); @@ -285,8 +238,7 @@ private ModifiedNameValuePair[] parseProjectJson(String json, boolean initialRef Arrays.sort(projectArr); // set the project ids to visible if the names are the same for (int i = 0; i < projectArr.length - 1; i++) { - if (projectArr[i].getName() != null - && projectArr[i].getName().equals(projectArr[i + 1].getName())) { + if (projectArr[i].getName() != null && projectArr[i].getName().equals(projectArr[i + 1].getName())) { projectArr[i].setUseId(true); projectArr[i + 1].setUseId(true); } @@ -313,19 +265,11 @@ public NameValuePair getProject() { } private void warn(String message) { - JOptionPane.showMessageDialog( - dialog, - message, - Constant.messages.getString("srm.warning"), - JOptionPane.WARNING_MESSAGE); + JOptionPane.showMessageDialog(dialog, message, Constant.messages.getString("srm.warning"), JOptionPane.WARNING_MESSAGE); } private void error(String message) { - JOptionPane.showMessageDialog( - dialog, - message, - Constant.messages.getString("srm.error"), - JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(dialog, message, Constant.messages.getString("srm.error"), JOptionPane.ERROR_MESSAGE); } private String getServerUrl() { @@ -338,8 +282,7 @@ private String getApiKey() { return apiKey.getText(); } - private static class ModifiedNameValuePair extends BasicNameValuePair - implements Comparable { + private static class ModifiedNameValuePair extends BasicNameValuePair implements Comparable { private static final long serialVersionUID = -6671681121783779976L; private boolean useId = false; diff --git a/src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java b/src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java index a156278..2f97725 100644 --- a/src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java +++ b/src/main/java/com/blackduck/zap/srm/security/CompositeX509TrustManager.java @@ -58,8 +58,7 @@ public CompositeX509TrustManager(List trustManagers) { } @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { for (X509TrustManager trustManager : trustManagers) { try { trustManager.checkClientTrusted(chain, authType); @@ -72,8 +71,7 @@ public void checkClientTrusted(X509Certificate[] chain, String authType) } @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { for (X509TrustManager trustManager : trustManagers) { try { trustManager.checkServerTrusted(chain, authType); diff --git a/src/main/java/com/blackduck/zap/srm/security/HostnameVerifierWithExceptions.java b/src/main/java/com/blackduck/zap/srm/security/HostnameVerifierWithExceptions.java index 52757f8..1634295 100644 --- a/src/main/java/com/blackduck/zap/srm/security/HostnameVerifierWithExceptions.java +++ b/src/main/java/com/blackduck/zap/srm/security/HostnameVerifierWithExceptions.java @@ -30,8 +30,7 @@ public class HostnameVerifierWithExceptions implements HostnameVerifier { private final HostnameVerifier delegate; private final Set allowedExceptions; - public HostnameVerifierWithExceptions( - HostnameVerifier delegate, Set allowedExceptions) { + public HostnameVerifierWithExceptions(HostnameVerifier delegate, Set allowedExceptions) { this.delegate = delegate; this.allowedExceptions = allowedExceptions; } diff --git a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java index 2c15026..5368903 100644 --- a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java +++ b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java @@ -45,24 +45,17 @@ public class InvalidCertificateDialogStrategy implements InvalidCertificateStrat private final SrmExtension extension; private static final String dialogTitle = Constant.messages.getString("srm.ssl.title"); - private static final String[] dialogButtons = { - Constant.messages.getString("srm.ssl.reject"), - Constant.messages.getString("srm.ssl.accepttemp"), - Constant.messages.getString("srm.ssl.acceptperm") - }; - - public InvalidCertificateDialogStrategy( - HostnameVerifier defaultHostVerifier, String host, SrmExtension extension) { + private static final String[] dialogButtons = {Constant.messages.getString("srm.ssl.reject"), Constant.messages.getString("srm.ssl.accepttemp"), Constant.messages.getString("srm.ssl.acceptperm")}; + + public InvalidCertificateDialogStrategy(HostnameVerifier defaultHostVerifier, String host, SrmExtension extension) { this.defaultHostVerifier = defaultHostVerifier; this.host = host; this.extension = extension; } @Override - public CertificateAcceptance checkAcceptance( - Certificate genericCert, CertificateException certError) { - if (genericCert instanceof X509Certificate cert - && defaultHostVerifier instanceof DefaultHostnameVerifier verifier) { + public CertificateAcceptance checkAcceptance(Certificate genericCert, CertificateException certError) { + if (genericCert instanceof X509Certificate cert && defaultHostVerifier instanceof DefaultHostnameVerifier verifier) { JPanel message = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); @@ -86,8 +79,7 @@ public CertificateAcceptance checkAcceptance( message.add(new JLabel(cert.getIssuerX500Principal().getName()), gbc); try { - JLabel fingerprint = - new JLabel(Constant.messages.getString("srm.ssl.fingerprint") + " "); + JLabel fingerprint = new JLabel(Constant.messages.getString("srm.ssl.fingerprint") + " "); fingerprint.setFont(bold); gbc.gridx = 0; gbc.gridy += 1; @@ -112,9 +104,7 @@ public CertificateAcceptance checkAcceptance( String msg; if (cn != null) { - msg = - String.format( - Constant.messages.getString("srm.ssl.mismatchmsg"), host, cn); + msg = String.format(Constant.messages.getString("srm.ssl.mismatchmsg"), host, cn); } else { msg = e.getMessage(); } @@ -124,16 +114,7 @@ public CertificateAcceptance checkAcceptance( } // Open the dialog, and return its result - int choice = - JOptionPane.showOptionDialog( - extension.getView().getMainFrame(), - message, - dialogTitle, - JOptionPane.YES_NO_CANCEL_OPTION, - JOptionPane.PLAIN_MESSAGE, - null, - dialogButtons, - null); + int choice = JOptionPane.showOptionDialog(extension.getView().getMainFrame(), message, dialogTitle, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, dialogButtons, null); switch (choice) { case (0): return CertificateAcceptance.REJECT; diff --git a/src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java b/src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java index c26efd2..a865ac8 100644 --- a/src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java +++ b/src/main/java/com/blackduck/zap/srm/security/ReloadableX509TrustManager.java @@ -44,23 +44,19 @@ public class ReloadableX509TrustManager implements X509TrustManager { private final InvalidCertificateStrategy invalidCertStrat; private X509TrustManager tmDelegate; - public ReloadableX509TrustManager( - ExtraCertManager certManager, InvalidCertificateStrategy invalidCertStrat) - throws IOException, GeneralSecurityException { + public ReloadableX509TrustManager(ExtraCertManager certManager, InvalidCertificateStrategy invalidCertStrat) throws IOException, GeneralSecurityException { this.certManager = certManager; this.invalidCertStrat = invalidCertStrat; reloadTrustManager(); } @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { tmDelegate.checkClientTrusted(chain, authType); } @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { try { tmDelegate.checkServerTrusted(chain, authType); } catch (CertificateException cx) { @@ -86,8 +82,7 @@ public void checkServerTrusted(X509Certificate[] chain, String authType) reloadTrustManager(); } catch (IOException | GeneralSecurityException e) { // wrap errors from the cert manipulation - throw new CertificateException( - "Error handling temporary acceptance of the certificate", e); + throw new CertificateException("Error handling temporary acceptance of the certificate", e); } // now retry the trust check tmDelegate.checkServerTrusted(chain, authType); @@ -99,8 +94,7 @@ public void checkServerTrusted(X509Certificate[] chain, String authType) reloadTrustManager(); } catch (IOException | GeneralSecurityException e) { // wrap errors from the cert manipulation - throw new CertificateException( - "Error handling permanent acceptance of the certificate", e); + throw new CertificateException("Error handling permanent acceptance of the certificate", e); } // now retry the trust check tmDelegate.checkServerTrusted(chain, authType); @@ -122,8 +116,7 @@ final void reloadTrustManager() throws IOException, GeneralSecurityException { KeyStore ks = certManager.asKeyStore(); // initialize a new TMF with the KeyStore we just created - TrustManagerFactory tmf = - TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); // acquire an X509 trust manager from the TMF diff --git a/src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java b/src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java index ae7a1b4..597587b 100644 --- a/src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java +++ b/src/main/java/com/blackduck/zap/srm/security/SSLConnectionSocketFactoryFactory.java @@ -35,8 +35,7 @@ public class SSLConnectionSocketFactoryFactory { private static final Map dialogFactoriesByHost = new HashMap<>(); - private static final Map fingerprintFactoriesByHost = - new HashMap<>(); + private static final Map fingerprintFactoriesByHost = new HashMap<>(); /** * Returns a SSLConnectionSocketFactory for the given host. When a SSL connection is created @@ -51,8 +50,7 @@ public class SSLConnectionSocketFactoryFactory { * @throws IOException * @throws GeneralSecurityException */ - public static SSLConnectionSocketFactory getFactory(String host, SrmExtension extension) - throws IOException, GeneralSecurityException { + public static SSLConnectionSocketFactory getFactory(String host, SrmExtension extension) throws IOException, GeneralSecurityException { SSLConnectionSocketFactory instance = dialogFactoriesByHost.get(host); if (instance == null) { @@ -78,9 +76,7 @@ public static SSLConnectionSocketFactory getFactory(String host, SrmExtension ex * @throws IOException * @throws GeneralSecurityException */ - public static SSLConnectionSocketFactory getFactory( - String host, SrmExtension extension, String fingerprint, boolean acceptPermanently) - throws IOException, GeneralSecurityException { + public static SSLConnectionSocketFactory getFactory(String host, SrmExtension extension, String fingerprint, boolean acceptPermanently) throws IOException, GeneralSecurityException { SSLConnectionSocketFactory instance = fingerprintFactoriesByHost.get(host); if (instance == null) { initializeFactory(host, extension, fingerprint, acceptPermanently); @@ -105,13 +101,7 @@ private static File getTrustStoreForHost(String host) { if (OS.contains("WIN")) { env = Paths.get(System.getenv("APPDATA"), "Software Risk Manager", "ZAP"); } else if (OS.contains("MAC")) { - env = - Paths.get( - System.getProperty("user.home"), - "Library", - "Application Support", - "Software Risk Manager", - "ZAP"); + env = Paths.get(System.getProperty("user.home"), "Library", "Application Support", "Software Risk Manager", "ZAP"); } else if (OS.contains("NUX")) { env = Paths.get(System.getProperty("user.home"), ".srm", "zap"); } else { @@ -143,13 +133,10 @@ private static File getTrustStoreForHost(String host) { * @throws IOException * @throws GeneralSecurityException */ - private static void initializeFactory( - String host, SrmExtension extension, String fingerprint, boolean acceptPermanently) - throws IOException, GeneralSecurityException { + private static void initializeFactory(String host, SrmExtension extension, String fingerprint, boolean acceptPermanently) throws IOException, GeneralSecurityException { // set up the certificate management File managedKeyStoreFile = getTrustStoreForHost(host); - ExtraCertManager certManager = - new SingleExtraCertManager(managedKeyStoreFile, "u9lwIfUpaN"); + ExtraCertManager certManager = new SingleExtraCertManager(managedKeyStoreFile, "u9lwIfUpaN"); // get the default hostname verifier that gets used by the modified one // and the invalid cert dialog @@ -157,11 +144,9 @@ private static void initializeFactory( InvalidCertificateStrategy invalidCertStrat; if (fingerprint == null) { - invalidCertStrat = - new InvalidCertificateDialogStrategy(defaultHostnameVerifier, host, extension); + invalidCertStrat = new InvalidCertificateDialogStrategy(defaultHostnameVerifier, host, extension); } else { - invalidCertStrat = - new InvalidCertificateFingerprintStrategy(fingerprint, acceptPermanently); + invalidCertStrat = new InvalidCertificateFingerprintStrategy(fingerprint, acceptPermanently); } /* @@ -171,8 +156,7 @@ private static void initializeFactory( */ List trustManagersForComposite = new LinkedList<>(); X509TrustManager systemTrustManager = getDefaultTrustManager(); - ReloadableX509TrustManager customTrustManager = - new ReloadableX509TrustManager(certManager, invalidCertStrat); + ReloadableX509TrustManager customTrustManager = new ReloadableX509TrustManager(certManager, invalidCertStrat); trustManagersForComposite.add(systemTrustManager); trustManagersForComposite.add(customTrustManager); X509TrustManager trustManager = new CompositeX509TrustManager(trustManagersForComposite); @@ -184,11 +168,9 @@ private static void initializeFactory( // factory Set allowedHosts = new HashSet<>(); allowedHosts.add(host); - HostnameVerifier modifiedHostnameVerifier = - new HostnameVerifierWithExceptions(defaultHostnameVerifier, allowedHosts); + HostnameVerifier modifiedHostnameVerifier = new HostnameVerifierWithExceptions(defaultHostnameVerifier, allowedHosts); - SSLConnectionSocketFactory factory = - new SSLConnectionSocketFactory(sslContext, modifiedHostnameVerifier); + SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslContext, modifiedHostnameVerifier); // Register the `factory` and the `customTrustManager` under the given // `host` if (fingerprint == null) { @@ -198,10 +180,8 @@ private static void initializeFactory( } } - private static X509TrustManager getDefaultTrustManager() - throws NoSuchAlgorithmException, KeyStoreException { - TrustManagerFactory defaultFactory = - TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + private static X509TrustManager getDefaultTrustManager() throws NoSuchAlgorithmException, KeyStoreException { + TrustManagerFactory defaultFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); defaultFactory.init((KeyStore) null); TrustManager[] managers = defaultFactory.getTrustManagers(); From c6c06b1e567dfe85dd2fed5c37246e4b704fa94d Mon Sep 17 00:00:00 2001 From: splahoti12 Date: Wed, 26 Nov 2025 15:11:30 +0530 Subject: [PATCH 10/11] Formatted the code --- .../blackduck/zap/srm/ExtensionAlertHttp.java | 1 - .../blackduck/zap/srm/ReportGenerator.java | 7 +++--- .../com/blackduck/zap/srm/ReportLastScan.java | 12 ++++++++-- .../java/com/blackduck/zap/srm/SrmAPI.java | 23 +++++++++++++++++-- .../com/blackduck/zap/srm/SrmExtension.java | 10 ++++++-- .../zap/srm/UploadActionListener.java | 8 ++++++- .../zap/srm/UploadPropertiesDialog.java | 17 +++++++------- .../InvalidCertificateDialogStrategy.java | 15 ++++++++++-- 8 files changed, 71 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java b/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java index 05fd7d8..559c8a9 100644 --- a/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java +++ b/src/main/java/com/blackduck/zap/srm/ExtensionAlertHttp.java @@ -3,7 +3,6 @@ * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * - * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/src/main/java/com/blackduck/zap/srm/ReportGenerator.java b/src/main/java/com/blackduck/zap/srm/ReportGenerator.java index cc5e7a6..a06cf79 100644 --- a/src/main/java/com/blackduck/zap/srm/ReportGenerator.java +++ b/src/main/java/com/blackduck/zap/srm/ReportGenerator.java @@ -138,13 +138,14 @@ public static File stringToHtml(String inxml, StreamSource stylesource, String o // we should really adopt something other than XSLT ;) String line; - try (BufferedReader br = Files.newBufferedReader(new File(tempOutfilename).toPath(), StandardCharsets.UTF_8); BufferedWriter bw = Files.newBufferedWriter(new File(outfilename).toPath(), StandardCharsets.UTF_8)) { - + try ( + BufferedReader br = Files.newBufferedReader(new File(tempOutfilename).toPath(), StandardCharsets.UTF_8); + BufferedWriter bw = Files.newBufferedWriter(new File(outfilename).toPath(), StandardCharsets.UTF_8) + ) { while ((line = br.readLine()) != null) { bw.write(line.replace("<p>", "

").replace("</p>", "

")); bw.newLine(); } - } catch (IOException e) { showDialogForGUI(); LOGGER.error(e.getMessage(), e); diff --git a/src/main/java/com/blackduck/zap/srm/ReportLastScan.java b/src/main/java/com/blackduck/zap/srm/ReportLastScan.java index 314d771..622db2c 100644 --- a/src/main/java/com/blackduck/zap/srm/ReportLastScan.java +++ b/src/main/java/com/blackduck/zap/srm/ReportLastScan.java @@ -124,7 +124,11 @@ public void generate(StringBuilder report, Model model) throws Exception { public void generate(StringBuilder report) throws Exception { report.append(""); - report.append("\r\n"); + report.append("\r\n"); siteXML(report); report.append(""); } @@ -138,7 +142,11 @@ private void siteXML(StringBuilder report) { String siteName = ScanPanel.cleanSiteName(site, true); String[] hostAndPort = siteName.split(":"); boolean isSSL = (site.getNodeName().startsWith("https")); - String siteStart = ""; + String siteStart = ""; StringBuilder extensionsXML = getExtensionsXML(site); String siteEnd = ""; report.append(siteStart); diff --git a/src/main/java/com/blackduck/zap/srm/SrmAPI.java b/src/main/java/com/blackduck/zap/srm/SrmAPI.java index 0fa4a54..6ad08ee 100644 --- a/src/main/java/com/blackduck/zap/srm/SrmAPI.java +++ b/src/main/java/com/blackduck/zap/srm/SrmAPI.java @@ -55,8 +55,27 @@ public SrmAPI(SrmExtension extension) { String[] optionalParams = new String[]{ACTION_PARAM_FINGERPRINT, ACTION_PARAM_ACCEPT_PERM}; - this.addApiAction(new ApiAction(ACTION_UPLOAD, new String[]{ACTION_PARAM_FILE_PATH, ACTION_PARAM_SERVER_URL, ACTION_PARAM_API_KEY, ACTION_PARAM_PROJECT}, optionalParams)); - this.addApiAction(new ApiAction(ACTION_GEN_UPLOAD, new String[]{ACTION_PARAM_SERVER_URL, ACTION_PARAM_API_KEY, ACTION_PARAM_PROJECT}, optionalParams)); + this.addApiAction( + new ApiAction( + ACTION_UPLOAD, + new String[]{ + ACTION_PARAM_FILE_PATH, + ACTION_PARAM_SERVER_URL, + ACTION_PARAM_API_KEY, + ACTION_PARAM_PROJECT + }, + optionalParams + )); + this.addApiAction( + new ApiAction( + ACTION_GEN_UPLOAD, + new String[]{ + ACTION_PARAM_SERVER_URL, + ACTION_PARAM_API_KEY, + ACTION_PARAM_PROJECT + }, + optionalParams + )); } @Override diff --git a/src/main/java/com/blackduck/zap/srm/SrmExtension.java b/src/main/java/com/blackduck/zap/srm/SrmExtension.java index 8ae8f6a..cd60917 100644 --- a/src/main/java/com/blackduck/zap/srm/SrmExtension.java +++ b/src/main/java/com/blackduck/zap/srm/SrmExtension.java @@ -122,7 +122,10 @@ public CloseableHttpClient getHttpClient(String url) throws IOException, General @SuppressWarnings("deprecation") public CloseableHttpClient getHttpClient(String url, String fingerprint, boolean acceptPermanently) throws IOException, GeneralSecurityException { - RequestConfig.Builder configBuilder = RequestConfig.custom().setConnectTimeout(getTimeout()).setSocketTimeout(getTimeout()).setConnectionRequestTimeout(getTimeout()); + RequestConfig.Builder configBuilder = RequestConfig.custom() + .setConnectTimeout(getTimeout()) + .setSocketTimeout(getTimeout()) + .setConnectionRequestTimeout(getTimeout()); HttpClientBuilder builder = HttpClientBuilder.create(); if (fingerprint != null) { @@ -140,7 +143,10 @@ public CloseableHttpClient getHttpClient(String url, String fingerprint, boolean if (connParam.isUseProxyChainAuth()) { BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials(new AuthScope(proxyHost, proxyPort), new UsernamePasswordCredentials(connParam.getProxyChainUserName(), connParam.getProxyChainPassword())); + credsProvider.setCredentials( + new AuthScope(proxyHost, proxyPort), + new UsernamePasswordCredentials(connParam.getProxyChainUserName(), connParam.getProxyChainPassword()) + ); builder.setDefaultCredentialsProvider(credsProvider); } } diff --git a/src/main/java/com/blackduck/zap/srm/UploadActionListener.java b/src/main/java/com/blackduck/zap/srm/UploadActionListener.java index be95a1e..7e5867a 100644 --- a/src/main/java/com/blackduck/zap/srm/UploadActionListener.java +++ b/src/main/java/com/blackduck/zap/srm/UploadActionListener.java @@ -77,7 +77,13 @@ public void generateAndUploadReport() { public void run() { String err; try { - err = uploadFile(extension.getHttpClient(), reportFile, SrmProperties.getInstance().getServerUrl(), SrmProperties.getInstance().getApiKey(), prop.getProject().getValue()); + err = uploadFile( + extension.getHttpClient(), + reportFile, + SrmProperties.getInstance().getServerUrl(), + SrmProperties.getInstance().getApiKey(), + prop.getProject().getValue() + ); } catch (IOException ex1) { err = Constant.messages.getString("srm.error.unexpected"); LOGGER.error("Unexpected error while uploading report: ", ex1); diff --git a/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java b/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java index 8b3da94..2bb822f 100644 --- a/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java +++ b/src/main/java/com/blackduck/zap/srm/UploadPropertiesDialog.java @@ -44,7 +44,10 @@ public class UploadPropertiesDialog { private static final Logger LOGGER = LogManager.getLogger(UploadPropertiesDialog.class); - private static final String[] DIALOG_BUTTONS = {Constant.messages.getString("srm.settings.upload"), Constant.messages.getString("srm.settings.cancel")}; + private static final String[] DIALOG_BUTTONS = { + Constant.messages.getString("srm.settings.upload"), + Constant.messages.getString("srm.settings.cancel") + }; public static final ImageIcon REFRESH_ICON = new ImageIcon(UploadPropertiesDialog.class.getResource("/com/blackduck/zap/srm/resources/refresh.png")); @@ -209,14 +212,10 @@ public void updateProjects(boolean initialRefresh) { } LOGGER.error("Error refreshing project list: ", e); } finally { - if (client != null) try { - client.close(); - } catch (IOException e) { - } - if (rd != null) try { - rd.close(); - } catch (IOException e) { - } + if (client != null) + try { client.close(); } catch (IOException e) {} + if (rd != null) + try { rd.close(); } catch (IOException e) {} } updateProjectComboBox(); dialog.setCursor(Cursor.getDefaultCursor()); diff --git a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java index 5368903..04ec86a 100644 --- a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java +++ b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java @@ -45,7 +45,11 @@ public class InvalidCertificateDialogStrategy implements InvalidCertificateStrat private final SrmExtension extension; private static final String dialogTitle = Constant.messages.getString("srm.ssl.title"); - private static final String[] dialogButtons = {Constant.messages.getString("srm.ssl.reject"), Constant.messages.getString("srm.ssl.accepttemp"), Constant.messages.getString("srm.ssl.acceptperm")}; + private static final String[] dialogButtons = { + Constant.messages.getString("srm.ssl.reject"), + Constant.messages.getString("srm.ssl.accepttemp"), + Constant.messages.getString("srm.ssl.acceptperm") + }; public InvalidCertificateDialogStrategy(HostnameVerifier defaultHostVerifier, String host, SrmExtension extension) { this.defaultHostVerifier = defaultHostVerifier; @@ -114,7 +118,14 @@ public CertificateAcceptance checkAcceptance(Certificate genericCert, Certificat } // Open the dialog, and return its result - int choice = JOptionPane.showOptionDialog(extension.getView().getMainFrame(), message, dialogTitle, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, dialogButtons, null); + int choice = JOptionPane.showOptionDialog( + extension.getView().getMainFrame(), + message, + dialogTitle, + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.PLAIN_MESSAGE, null, + dialogButtons, null + ); switch (choice) { case (0): return CertificateAcceptance.REJECT; From da8ec61e3467800d5f37688d2723cbcb9c3bfe37 Mon Sep 17 00:00:00 2001 From: splahoti12 Date: Wed, 26 Nov 2025 21:08:09 +0530 Subject: [PATCH 11/11] Formatted the code --- .../zap/srm/security/InvalidCertificateDialogStrategy.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java index 04ec86a..4cb7d95 100644 --- a/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java +++ b/src/main/java/com/blackduck/zap/srm/security/InvalidCertificateDialogStrategy.java @@ -123,8 +123,10 @@ public CertificateAcceptance checkAcceptance(Certificate genericCert, Certificat message, dialogTitle, JOptionPane.YES_NO_CANCEL_OPTION, - JOptionPane.PLAIN_MESSAGE, null, - dialogButtons, null + JOptionPane.PLAIN_MESSAGE, + null, + dialogButtons, + null ); switch (choice) { case (0):