Skip to content

Commit eca1783

Browse files
authored
Update Hue Bridge security (#1912)
1 parent 8b32562 commit eca1783

File tree

20 files changed

+1583
-1439
lines changed

20 files changed

+1583
-1439
lines changed

.github/workflows/windows.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ jobs:
8484
- name: 💾 Download OpenSSL 3.x
8585
uses: ethanjli/[email protected]
8686
with:
87-
url: "https://slproweb.com/download/Win64${{ matrix.os.architecture == 'arm64' && 'ARM' || '' }}OpenSSL-3_5_2.exe"
87+
url: "https://slproweb.com/download/Win64${{ matrix.os.architecture == 'arm64' && 'ARM' || '' }}OpenSSL-3_5_3.exe"
8888
destination: .\installer\openssl.exe
8989
cache-key: OpenSSL
9090

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
### ⚠️ Breaking Changes
1010

11+
- Align Hue Bridge processing to Philips' guidance on security, i.e. no self-signed certificates for orginal bridges
12+
1113
---
1214

1315
### ✨ Added
1416

1517
- HTTPS support for homeassistant LED devices (#1886)
18+
- Hue Bridge - Use https and certificates for all API calls, support Bridge Pro (V3)
19+
- Hue Bridge - Alternate certificate support
1620

1721
---
1822

19-
2023
### 🔧 Changed
2124

25+
- Hue Bridge - Wizard updates to support bridge-ids, overall code refactoring
26+
2227
- **Fixes:**
2328
- UI - Language is not selectable (#1877)
2429
- CEC-Handler is not stopped properly

assets/webconfig/i18n/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@
668668
"edt_dev_spec_PBFiFo_title": "Pi-Blaster FiFo",
669669
"edt_dev_spec_baudrate_title": "Baudrate",
670670
"edt_dev_spec_blackLightsTimeout_title": "Signal detection timeout on black",
671+
"edt_dev_spec_bridgeid_title": "Bridge-ID",
671672
"edt_dev_spec_brightnessFactor_title": "Brightness factor",
672673
"edt_dev_spec_brightnessMax_title": "Brightness maximum",
673674
"edt_dev_spec_brightnessMin_title": "Brightness minimum",
@@ -1179,6 +1180,7 @@
11791180
"wiz_cololight_title": "Cololight Wizard",
11801181
"wiz_guideyou": "The $1 will guide you through the settings. Just press the button!",
11811182
"wiz_hue_blinkblue": "Let it light up",
1183+
"wiz_hue_bridge": "Bridge",
11821184
"wiz_hue_clientkey": "Clientkey",
11831185
"wiz_hue_create_user": "Create new User",
11841186
"wiz_hue_desc1": "1. Hyperion searches automatically for a Hue-Bridge, in case it cannot find one you need to provide the hostname or IP-address and push the reload button. <br> 2. Provide a user ID, if you do not have one create a new one.",

assets/webconfig/js/wizards/LedDevice_philipshue.js

Lines changed: 61 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ const philipshueWizard = (() => {
2929
if (hueIPs[hueIPsinc]) {
3030
const host = hueIPs[hueIPsinc].host;
3131
const port = hueIPs[hueIPsinc].port;
32+
const bridgeid = hueIPs[hueIPsinc].bridgeid ? hueIPs[hueIPsinc].bridgeid.toUpperCase() : undefined;
3233

3334
if (usr != '') {
34-
getProperties(cb, decodeURIComponent(host), port, usr);
35+
getProperties(cb, decodeURIComponent(host), port, bridgeid, usr);
3536
}
3637
else {
3738
cb(false, usr);
@@ -47,8 +48,9 @@ const philipshueWizard = (() => {
4748
if (reply) {
4849
//abort checking, first reachable result is used
4950
$('#wiz_hue_ipstate').html("");
50-
$('#host').val(hueIPs[hueIPsinc].host)
51-
$('#port').val(hueIPs[hueIPsinc].port)
51+
$('#host').val(hueIPs[hueIPsinc].host);
52+
$('#port').val(hueIPs[hueIPsinc].port);
53+
$('#bridgeid').val(hueIPs[hueIPsinc].bridgeid);
5254

5355
$('#usrcont').toggle(true);
5456

@@ -289,22 +291,26 @@ const philipshueWizard = (() => {
289291
if (device) {
290292
let host;
291293
let port;
294+
let bridgeid;
292295
if (discoveryMethod === "ssdp") {
293-
if (device.hostname && device.domain) {
296+
// Use hostname + domain, if available and not an IP address
297+
if (device.hostname && device.domain && !(isValidIPv4(device.hostname) || isValidIPv6(device.hostname))) {
294298
host = device.hostname + "." + device.domain;
295299
port = device.port;
296300
} else {
297301
host = device.ip;
298302
port = device.port;
299303
}
304+
bridgeid = device.other?.["hue-bridgeid"]?.toUpperCase();
300305
} else {
301-
host = device.service;
302-
port = device.port;
306+
host = device.service;
307+
port = device.port;
308+
bridgeid = device.txt?.["bridgeid"]?.toUpperCase();
303309
}
304-
if (host) {
305310

311+
if (host) {
306312
if (!hueIPs.some(item => item.host === host)) {
307-
hueIPs.push({ host: host, port: port });
313+
hueIPs.push({ host, port, bridgeid });
308314
}
309315
}
310316
}
@@ -313,19 +319,20 @@ const philipshueWizard = (() => {
313319
$('#wiz_hue_ipstate').html("");
314320
$('#host').val(hueIPs[hueIPsinc].host)
315321
$('#port').val(hueIPs[hueIPsinc].port)
322+
$('#bridgeid').val(hueIPs[hueIPsinc].bridgeid)
316323

317324
$('#hue_bridge_select').html("");
318325

319326
for (const key in hueIPs) {
320-
$('#hue_bridge_select').append(createSelOpt(key, hueIPs[key].host));
327+
$('#hue_bridge_select').append(createSelOpt(key, hueIPs[key].bridgeid));
321328
}
322329

323330
$('.hue_bridge_sel_watch').on("click", function () {
324331
hueIPsinc = $(this).val();
325332

326-
const name = $("#hue_bridge_select option:selected").text();
327-
$('#host').val(name);
328-
$('#port').val(hueIPs[hueIPsinc].port)
333+
$('#host').val(hueIPs[hueIPsinc].host);
334+
$('#port').val(hueIPs[hueIPsinc].port);
335+
$('#bridgeid').val(hueIPs[hueIPsinc].bridgeid);
329336

330337
const usr = $('#user').val();
331338
if (usr != "") {
@@ -361,8 +368,8 @@ const philipshueWizard = (() => {
361368
keyMap.set(username, ledDeviceProperties);
362369
}
363370

364-
async function getProperties(cb, hostAddress, port, username, resourceFilter) {
365-
let params = { host: hostAddress, username: username, filter: resourceFilter };
371+
async function getProperties(cb, hostAddress, port, bridgeid, username, resourceFilter) {
372+
let params = { host: hostAddress, bridgeid, username, filter: resourceFilter };
366373
if (port !== 'undefined') {
367374
params.port = parseInt(port);
368375
}
@@ -403,12 +410,12 @@ const philipshueWizard = (() => {
403410
}
404411
}
405412

406-
async function identify(hostAddress, port, username, name, id, id_v1) {
413+
async function identify(hostAddress, port, bridgeid, username, name, id, id_v1) {
407414
const disabled = $('#btn_wiz_save').is(':disabled');
408415
// Take care that new record cannot be save during background process
409416
$('#btn_wiz_save').prop('disabled', true);
410417

411-
let params = { host: decodeURIComponent(hostAddress), username: username, lightName: decodeURIComponent(name), lightId: id, lightId_v1: id_v1 };
418+
let params = { host: decodeURIComponent(hostAddress), bridgeid, username, lightName: decodeURIComponent(name), lightId: id, lightId_v1: id_v1 };
412419

413420
if (port !== 'undefined') {
414421
params.port = parseInt(port);
@@ -450,7 +457,11 @@ const philipshueWizard = (() => {
450457
else {
451458
$('#port').val('');
452459
}
453-
hueIPs.push({ host: host, port: port });
460+
461+
const bridgeid = utils.eV("bridgeid");
462+
$('#bridgeid').val(bridgeid);
463+
464+
hueIPs.push({ host, port, bridgeid });
454465

455466
if (usr != "") {
456467
checkHueBridge(checkUserResult, usr);
@@ -460,17 +471,20 @@ const philipshueWizard = (() => {
460471
}
461472

462473
$('#retry_bridge').off().on('click', function () {
474+
463475
const host = $('#host').val();
464476
const port = parseInt($('#port').val());
477+
const bridgeid = $('#bridgeid').val();
465478

466479
if (host != "") {
467-
468-
const idx = hueIPs.findIndex(item => item.host === host && item.port === port);
480+
const idx = hueIPs.findIndex(item => item.host === host);
469481
if (idx === -1) {
470-
hueIPs.push({ host: host, port: port });
482+
hueIPs.push({ host, port, bridgeid });
471483
hueIPsinc = hueIPs.length - 1;
472484
} else {
473485
hueIPsinc = idx;
486+
hueIPs[hueIPsinc].port = port;
487+
hueIPs[hueIPsinc].bridgeid = bridgeid;
474488
}
475489
}
476490
else {
@@ -584,6 +598,7 @@ const philipshueWizard = (() => {
584598
let d = {};
585599
d.host = $('#host').val();
586600
d.port = parseInt($('#port').val());
601+
d.bridgeid = $('#bridgeid').val();
587602
d.username = $('#user').val();
588603
d.type = 'philipshue';
589604
d.colorOrder = 'rgb';
@@ -641,8 +656,9 @@ const philipshueWizard = (() => {
641656
function createHueUser() {
642657
const host = hueIPs[hueIPsinc].host;
643658
const port = hueIPs[hueIPsinc].port;
659+
const bridgeid = hueIPs[hueIPsinc].bridgeid;
644660

645-
let params = { host: host };
661+
let params = { host, bridgeid };
646662
if (port !== 'undefined') {
647663
params.port = parseInt(port);
648664
}
@@ -682,6 +698,7 @@ const philipshueWizard = (() => {
682698
conf_editor.getEditor("root.specificOptions.username").setValue(username);
683699
conf_editor.getEditor("root.specificOptions.host").setValue(host);
684700
conf_editor.getEditor("root.specificOptions.port").setValue(port);
701+
conf_editor.getEditor("root.specificOptions.bridgeid").setValue(bridgeid);
685702
}
686703

687704
if (isEntertainmentReady) {
@@ -745,12 +762,13 @@ const philipshueWizard = (() => {
745762
$('#wizp2_body').on('click', '.btn-identify', function () {
746763
const hostname = $(this).data('hostname');
747764
const port = $(this).data('port');
765+
const bridgeid = $(this).data('bridgeid');
748766
const user = $(this).data('user');
749767
const lightName = $(this).data('light-name');
750768
const lightId = $(this).data('light-id');
751769
const lightId_v1 = $(this).data('light-id-v1');
752770

753-
identify(hostname, port, user, lightName, lightId, lightId_v1);
771+
identify(hostname, port, bridgeid, user, lightName, lightId, lightId_v1);
754772
});
755773
}
756774
function attachGroupButtonEvent() {
@@ -777,6 +795,7 @@ const philipshueWizard = (() => {
777795

778796
function get_hue_lights(username) {
779797
const host = hueIPs[hueIPsinc].host;
798+
const port = hueIPs[hueIPsinc].port;
780799

781800
const ledProperties = getLedDeviceProperty('philipshue', host, username);
782801
if (ledProperties) {
@@ -867,7 +886,7 @@ const philipshueWizard = (() => {
867886
'<select id="hue_' + lightId + '" class="hue_sel_watch form-control">'
868887
+ options
869888
+ '</select>',
870-
'<button class="btn btn-sm btn-primary btn-identify" data-hostname="' + encodeURIComponent($(" #host").val()) + '" data-port="' + $('#port').val() + '" data-user="' + $("#user").val() + '" data-light-name="' + encodeURIComponent(lightName) + '" data-light-id="' + lightId + '" data-light-id-v1="' + lightId_v1 + '">'
889+
'<button class="btn btn-sm btn-primary btn-identify" data-hostname="' + encodeURIComponent(host) + '" data-port="' + port + '" data-bridgeid="' + $('#bridgeid').val() + '" data-user="' + $("#user").val() + '" data-light-name="' + encodeURIComponent(lightName) + '" data-light-id="' + lightId + '" data-light-id-v1="' + lightId_v1 + '">'
871890
+ $.i18n('wiz_hue_blinkblue', id)
872891
+ '</button>']));
873892
}
@@ -916,23 +935,36 @@ const philipshueWizard = (() => {
916935
$('#wizp2_body').html('<div id="wh_topcontainer"></div>');
917936

918937
let topContainer_html = '<p class="text-left" style="font-weight:bold">' + $.i18n(hue_desc1) + '</p>' +
919-
'<div class="row">' +
938+
'<div class="row" style="display: flex; align-items: center; margin-bottom: 10px;">' +
920939
'<div class="col-md-2">' +
921-
' <p class="text-left">' + $.i18n('wiz_hue_ip') + '</p></div>' +
940+
' <p class="text-left" style="margin:0;">' + $.i18n('wiz_hue_bridge') + '</p></div>' +
922941
' <div class="col-md-7"><div class="input-group">' +
923942
' <span class="input-group-addon" id="retry_bridge" style="cursor:pointer"><i class="fa fa-refresh"></i></span>' +
924943
' <select id="hue_bridge_select" class="hue_bridge_sel_watch form-control">' + '</select>' + '</div></div>' +
925-
' <div class="col-md-7"><div class="input-group">' +
926-
' <span class="input-group-addon"><i class="fa fa-arrow-right"></i></span>' +
927-
' <input type="text" class="input-group form-control" id="host" placeholder="' + $.i18n('wiz_hue_ip') + '"></div></div>';
944+
'</div>';
945+
946+
if (storedAccess === 'expert') {
947+
topContainer_html += '<div class="row" style="display: flex; align-items: center; margin-bottom: 10px; margin-top: 30px;">' +
948+
'<div class="col-md-2"><p class="text-left" style="margin:0;">' + $.i18n('edt_dev_spec_bridgeid_title') + '</p></div>' +
949+
'<div class="col-md-7"><div class="input-group">' +
950+
'<span class="input-group-addon"><i class="fa fa-qrcode"></i></span>' +
951+
'<input type="text" class="input-group form-control" id="bridgeid" placeholder="' + $.i18n('edt_dev_spec_bridgeid_title') + '"></div></div></div>';
952+
}
953+
954+
topContainer_html += '<div class="row" style="display: flex; align-items: center; margin-bottom: 10px;">' +
955+
'<div class="col-md-2"><p class="text-left" style="margin:0;">' + $.i18n('edt_dev_spec_targetIpHost_title') + '</p></div>' +
956+
'<div class="col-md-7"><div class="input-group">' +
957+
'<span class="input-group-addon"><i class="fa fa-arrow-right"></i></span>' +
958+
'<input type="text" class="input-group form-control" id="host" placeholder="' + $.i18n('edt_dev_spec_targetIpHost_title') + '"></div></div>';
928959

929960
if (storedAccess === 'expert') {
930961
topContainer_html += '<div class="col-md-3"><div class="input-group">' +
931962
'<span class="input-group-addon">:</span>' +
932963
'<input type="text" class="input-group form-control" id="port" placeholder="' + $.i18n('edt_conf_general_port_title') + '"></div></div>';
933964
}
965+
topContainer_html += '</div><div class="row" style="margin-top: 15px;"><div text-center"><p><span style="font-weight:bold;color:red" id="wiz_hue_ipstate"></span><span style="font-weight:bold;" id="wiz_hue_discovered"></span></p></div></div>';
934966

935-
topContainer_html += '</div><p><span style="font-weight:bold;color:red" id="wiz_hue_ipstate"></span><span style="font-weight:bold;" id="wiz_hue_discovered"></span></p>';
967+
// Hidden fields
936968
topContainer_html += '<div class="form-group" id="usrcont" style="display:none"></div>';
937969

938970
$('#wh_topcontainer').append(topContainer_html);

libsrc/leddevice/LedDevice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace {
2828
const char CONFIG_LATCH_TIME[] = "latchTime";
2929
const char CONFIG_REWRITE_TIME[] = "rewriteTime";
3030

31-
int DEFAULT_LED_COUNT{ 1 };
31+
const int DEFAULT_LED_COUNT{ 1 };
3232
const char DEFAULT_COLOR_ORDER[]{ "RGB" };
3333
const bool DEFAULT_IS_AUTOSTART{ true };
3434

0 commit comments

Comments
 (0)