From 65ef139428351eef40d3e36438faeabc6f8f0d32 Mon Sep 17 00:00:00 2001 From: Felix Kaechele Date: Thu, 4 Jan 2024 16:23:22 +0100 Subject: [PATCH] feat: support for custom CA certificates (#422) - Adds custom CA certificate for Philips Hue OTA updates - Adds support to use these certificates to `scripts/add.js` - Adds concatenation of CA certs to `scripts/updateall.js` Part of the fixes for https://github.com/Koenkk/zigbee-OTA/issues/420 Signed-off-by: Felix Kaechele --- cacerts.pem | 12 ++++++++++++ cacerts/otau.meethue.com.pem | 12 ++++++++++++ scripts/add.js | 8 +++++++- scripts/updateall.js | 14 ++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 cacerts.pem create mode 100644 cacerts/otau.meethue.com.pem diff --git a/cacerts.pem b/cacerts.pem new file mode 100644 index 00000000..5ac613bc --- /dev/null +++ b/cacerts.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBwDCCAWagAwIBAgIJAJtrMkoTxs+WMAoGCCqGSM49BAMCMDIxCzAJBgNVBAYT +Ak5MMRQwEgYDVQQKDAtQaGlsaXBzIEh1ZTENMAsGA1UEAwwEcm9vdDAgFw0xNjA4 +MjUwNzU5NDNaGA8yMDY4MDEwNTA3NTk0M1owMjELMAkGA1UEBhMCTkwxFDASBgNV +BAoMC1BoaWxpcHMgSHVlMQ0wCwYDVQQDDARyb290MFkwEwYHKoZIzj0CAQYIKoZI +zj0DAQcDQgAEENC1JOl6BxJrwCb+YK655zlM57VKFSi5OHDsmlCaF/EfTGGgU08/ +JUtkCyMlHUUoYBZyzCBKXqRKkrT512evEKNjMGEwHQYDVR0OBBYEFAlkFYACVzir +qTr++cWia8AKH/fOMB8GA1UdIwQYMBaAFAlkFYACVzirqTr++cWia8AKH/fOMA8G +A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA0gAMEUC +IQDcGfyXaUl5hjr5YE8m2piXhMcDzHTNbO1RvGgz4r9IswIgFTTw/R85KyfIiW+E +clwJRVSsq8EApeFREenCkRM0EIk= +-----END CERTIFICATE----- diff --git a/cacerts/otau.meethue.com.pem b/cacerts/otau.meethue.com.pem new file mode 100644 index 00000000..52f4f431 --- /dev/null +++ b/cacerts/otau.meethue.com.pem @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBwDCCAWagAwIBAgIJAJtrMkoTxs+WMAoGCCqGSM49BAMCMDIxCzAJBgNVBAYT +Ak5MMRQwEgYDVQQKDAtQaGlsaXBzIEh1ZTENMAsGA1UEAwwEcm9vdDAgFw0xNjA4 +MjUwNzU5NDNaGA8yMDY4MDEwNTA3NTk0M1owMjELMAkGA1UEBhMCTkwxFDASBgNV +BAoMC1BoaWxpcHMgSHVlMQ0wCwYDVQQDDARyb290MFkwEwYHKoZIzj0CAQYIKoZI +zj0DAQcDQgAEENC1JOl6BxJrwCb+YK655zlM57VKFSi5OHDsmlCaF/EfTGGgU08/ +JUtkCyMlHUUoYBZyzCBKXqRKkrT512evEKNjMGEwHQYDVR0OBBYEFAlkFYACVzir +qTr++cWia8AKH/fOMB8GA1UdIwQYMBaAFAlkFYACVzirqTr++cWia8AKH/fOMA8G +A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA0gAMEUC +IQDcGfyXaUl5hjr5YE8m2piXhMcDzHTNbO1RvGgz4r9IswIgFTTw/R85KyfIiW+E +clwJRVSsq8EApeFREenCkRM0EIk= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/scripts/add.js b/scripts/add.js index b75a1057..ec1a7ada 100644 --- a/scripts/add.js +++ b/scripts/add.js @@ -1,10 +1,12 @@ const path = require('path'); const fs = require('fs'); const crypto = require('crypto'); +const tls = require('tls'); const ota = require('../lib/ota'); const filenameOrURL = process.argv[2]; const modelId = process.argv[3]; const baseURL = 'https://github.com/Koenkk/zigbee-OTA/raw/master'; +const caCerts = './cacerts.pem'; const manufacturerNameLookup = { 123: 'UHome', @@ -53,7 +55,11 @@ const main = async () => { const file = fs.createWriteStream(path); return new Promise((resolve, reject) => { - const request = lib.get(url, function(response) { + const ca = [...tls.rootCertificates]; + if(fs.existsSync(caCerts)) { + ca.push(fs.readFileSync(caCerts)); + } + const request = lib.get(url, { ca }, function(response) { if (response.statusCode >= 200 && response.statusCode < 300) { response.pipe(file); file.on('finish', function() { diff --git a/scripts/updateall.js b/scripts/updateall.js index c9d60f33..76718206 100644 --- a/scripts/updateall.js +++ b/scripts/updateall.js @@ -2,7 +2,21 @@ const child_process = require('child_process'); const fs = require('fs'); const path = require('path'); +const concatCaCerts = (folder = 'cacerts', outputFilename = 'cacerts.pem') => { + const files = fs.readdirSync(folder); + + const caCertFiles = files.filter((file) => path.extname(file) === '.pem'); + const outputFile = fs.openSync(outputFilename, 'w'); + + caCertFiles.forEach((caCert) => { + const filePath = path.join(folder, caCert); + const fileContent = fs.readFileSync(filePath, 'utf8'); + fs.appendFileSync(outputFile, fileContent + '\n'); + }); +}; + const main = async () => { + concatCaCerts(); const indexJSON = JSON.parse(fs.readFileSync('index.json')); indexJSON.forEach(entry => { const result = child_process.execSync(`node ./scripts/add.js "${entry.path || entry.url}" "${entry.modelId || ''}"`, {