Skip to content

Commit 5e10345

Browse files
darwin-framework-tool: Add options to disable HTTPS or certificate validation (#37783)
* darwin-framework-tool: Add options to disable HTTPS or certificate validation Note that while the Darwin and generic implementation of HTTPSRequest share the same header, only the Darwin implementation currently supports the two new non-default security modes. * Restyled by clang-format --------- Co-authored-by: Restyled.io <commits@restyled.io>
1 parent 392909e commit 5e10345

File tree

7 files changed

+96
-28
lines changed

7 files changed

+96
-28
lines changed

examples/chip-tool/commands/dcl/DCLClient.cpp

+8-10
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ CHIP_ERROR ValidateTermsAndConditionsSchema(const Json::Value & tc, unsigned int
131131
return ValidateTCCountryEntries(tc["countryEntries"]);
132132
}
133133

134-
CHIP_ERROR RequestTermsAndConditions(const Json::Value & json, Json::Value & tc)
134+
CHIP_ERROR RequestTermsAndConditions(const Json::Value & json, Json::Value & tc, tool::https::HttpsSecurityMode httpsSecurityMode)
135135
{
136136
auto & model = json["model"];
137137
if ((model["enhancedSetupFlowOptions"].asUInt() & 0x01) == 0)
@@ -151,19 +151,17 @@ CHIP_ERROR RequestTermsAndConditions(const Json::Value & json, Json::Value & tc)
151151
auto * tcUrl = enhancedSetupFlowTCUrl.asCString();
152152
const auto optionalFileSize = MakeOptional(static_cast<uint32_t>(enhancedSetupFlowTCFileSize.asUInt()));
153153
const auto optionalDigest = MakeOptional(enhancedSetupFlowTCDigest.asCString());
154-
ReturnErrorOnFailure(https::Request(tcUrl, tc, optionalFileSize, optionalDigest));
154+
ReturnErrorOnFailure(https::Request(tcUrl, tc, optionalFileSize, optionalDigest, httpsSecurityMode));
155155
ReturnErrorOnFailure(ValidateTermsAndConditionsSchema(tc, enhancedSetupFlowTCRevision.asUInt()));
156156

157157
return CHIP_NO_ERROR;
158158
}
159159

160160
} // namespace
161161

162-
DCLClient::DCLClient(Optional<const char *> hostname, Optional<uint16_t> port)
163-
{
164-
mHostName = hostname.ValueOr(kDefaultDCLHostName);
165-
mPort = port.ValueOr(0);
166-
}
162+
DCLClient::DCLClient(Optional<const char *> hostname, Optional<uint16_t> port, https::HttpsSecurityMode httpsSecurityMode) :
163+
mHostName(hostname.ValueOr(kDefaultDCLHostName)), mPort(port.ValueOr(0)), mHttpsSecurityMode(httpsSecurityMode)
164+
{}
167165

168166
CHIP_ERROR DCLClient::Model(const char * onboardingPayload, Json::Value & outModel)
169167
{
@@ -209,7 +207,7 @@ CHIP_ERROR DCLClient::Model(const chip::VendorId vendorId, const uint16_t produc
209207
char path[kRequestPathBufferSize];
210208
VerifyOrReturnError(snprintf(path, sizeof(path), kRequestModelVendorProductPath, to_underlying(vendorId), productId) >= 0,
211209
CHIP_ERROR_INVALID_ARGUMENT);
212-
ReturnErrorOnFailure(https::Request(mHostName, mPort, path, outModel));
210+
ReturnErrorOnFailure(https::Request(mHostName, mPort, path, outModel, NullOptional, NullOptional, mHttpsSecurityMode));
213211

214212
CHIP_ERROR error = ValidateModelSchema(outModel);
215213
VerifyOrReturnError(CHIP_NO_ERROR == error, error,
@@ -223,7 +221,7 @@ CHIP_ERROR DCLClient::TermsAndConditions(const char * onboardingPayload, Json::V
223221
Json::Value json;
224222
ReturnErrorOnFailure(Model(onboardingPayload, json));
225223
VerifyOrReturnError(Json::nullValue != json.type(), CHIP_NO_ERROR, outTc = Json::nullValue);
226-
ReturnErrorOnFailure(RequestTermsAndConditions(json, outTc));
224+
ReturnErrorOnFailure(RequestTermsAndConditions(json, outTc, mHttpsSecurityMode));
227225
return CHIP_NO_ERROR;
228226
}
229227

@@ -232,7 +230,7 @@ CHIP_ERROR DCLClient::TermsAndConditions(const chip::VendorId vendorId, const ui
232230
Json::Value json;
233231
ReturnErrorOnFailure(Model(vendorId, productId, json));
234232
VerifyOrReturnError(Json::nullValue != json.type(), CHIP_NO_ERROR, outTc = Json::nullValue);
235-
ReturnErrorOnFailure(RequestTermsAndConditions(json, outTc));
233+
ReturnErrorOnFailure(RequestTermsAndConditions(json, outTc, mHttpsSecurityMode));
236234
return CHIP_NO_ERROR;
237235
}
238236

examples/chip-tool/commands/dcl/DCLClient.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
*
1717
*/
1818

19+
#pragma once
20+
21+
#include "HTTPSRequest.h"
22+
1923
#include <lib/core/CHIPError.h>
2024
#include <lib/core/CHIPVendorIdentifiers.hpp>
2125
#include <lib/core/Optional.h>
@@ -29,7 +33,8 @@ namespace dcl {
2933
class DCLClient
3034
{
3135
public:
32-
DCLClient(Optional<const char *> hostname, Optional<uint16_t> port);
36+
DCLClient(Optional<const char *> hostname, Optional<uint16_t> port,
37+
https::HttpsSecurityMode httpsSecurityMode = https::HttpsSecurityMode::kDefault);
3338

3439
/**
3540
* @brief Retrieves the model information from the DCL based on the onboarding payload.
@@ -94,6 +99,7 @@ class DCLClient
9499
private:
95100
std::string mHostName;
96101
uint16_t mPort;
102+
https::HttpsSecurityMode mHttpsSecurityMode;
97103
};
98104
} // namespace dcl
99105
} // namespace tool

examples/chip-tool/commands/dcl/HTTPSRequest.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ namespace {
6464
class HTTPSSessionHolder
6565
{
6666
public:
67-
CHIP_ERROR Init(std::string & hostname, uint16_t port) { return LogNotImplementedError(); }
67+
CHIP_ERROR Init(std::string & hostname, uint16_t port, HttpsSecurityMode securityMode) { return LogNotImplementedError(); }
6868

6969
CHIP_ERROR SendRequest(std::string & request) { return LogNotImplementedError(); }
7070

@@ -152,9 +152,10 @@ class HTTPSSessionHolder
152152
#endif
153153
}
154154

155-
CHIP_ERROR Init(std::string & hostname, uint16_t port)
155+
CHIP_ERROR Init(std::string & hostname, uint16_t port, HttpsSecurityMode securityMode)
156156
{
157157
int sock;
158+
VerifyOrReturnError(securityMode == HttpsSecurityMode::kDefault, CHIP_ERROR_NOT_IMPLEMENTED);
158159
ReturnErrorOnFailure(InitSocket(hostname, port, sock));
159160
ReturnErrorOnFailure(InitSSL(sock));
160161
return CHIP_NO_ERROR;
@@ -363,17 +364,18 @@ CHIP_ERROR ExtractHostNamePortPath(std::string url, std::string & outHostName, u
363364
} // namespace
364365

365366
CHIP_ERROR Request(std::string url, Json::Value & jsonResponse, const Optional<uint32_t> & optionalExpectedSize,
366-
const Optional<const char *> & optionalExpectedDigest)
367+
const Optional<const char *> & optionalExpectedDigest, HttpsSecurityMode securityMode)
367368
{
368369
std::string hostname;
369370
uint16_t port;
370371
std::string path;
371372
ReturnErrorOnFailure(ExtractHostNamePortPath(url, hostname, port, path));
372-
return Request(hostname, port, path, jsonResponse, optionalExpectedSize, optionalExpectedDigest);
373+
return Request(hostname, port, path, jsonResponse, optionalExpectedSize, optionalExpectedDigest, securityMode);
373374
}
374375

375376
CHIP_ERROR Request(std::string hostname, uint16_t port, std::string path, Json::Value & jsonResponse,
376-
const Optional<uint32_t> & optionalExpectedSize, const Optional<const char *> & optionalExpectedDigest)
377+
const Optional<uint32_t> & optionalExpectedSize, const Optional<const char *> & optionalExpectedDigest,
378+
HttpsSecurityMode securityMode)
377379
{
378380
VerifyOrDo(port != 0, port = kHttpsPort);
379381

@@ -383,7 +385,7 @@ CHIP_ERROR Request(std::string hostname, uint16_t port, std::string path, Json::
383385
std::string response;
384386

385387
HTTPSSessionHolder session;
386-
ReturnErrorOnFailure(session.Init(hostname, port));
388+
ReturnErrorOnFailure(session.Init(hostname, port, securityMode));
387389
ReturnErrorOnFailure(session.SendRequest(request));
388390
ReturnErrorOnFailure(session.ReceiveResponse(response));
389391
ReturnErrorOnFailure(RemoveHeader(response));

examples/chip-tool/commands/dcl/HTTPSRequest.h

+13-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
*
1717
*/
1818

19+
#pragma once
20+
1921
#include <lib/core/CHIPError.h>
2022
#include <lib/core/Optional.h>
2123

@@ -26,13 +28,22 @@ namespace chip {
2628
namespace tool {
2729
namespace https {
2830

31+
enum class HttpsSecurityMode
32+
{
33+
kDefault = 0,
34+
kDisableValidation = 1, // Use HTTPS, but disable all validations (cert, server name, ...)
35+
kDisableHttps = 2, // Disable HTTPS, i.e. use plain HTTP
36+
};
37+
2938
CHIP_ERROR Request(std::string url, Json::Value & jsonResponse,
3039
const chip::Optional<uint32_t> & optionalExpectedSize = chip::NullOptional,
31-
const chip::Optional<const char *> & optionalExpectedDigest = chip::NullOptional);
40+
const chip::Optional<const char *> & optionalExpectedDigest = chip::NullOptional,
41+
HttpsSecurityMode securityMode = HttpsSecurityMode::kDefault);
3242

3343
CHIP_ERROR Request(std::string hostname, uint16_t port, std::string path, Json::Value & jsonResponse,
3444
const chip::Optional<uint32_t> & optionalExpectedSize = chip::NullOptional,
35-
const chip::Optional<const char *> & optionalExpectedDigest = chip::NullOptional);
45+
const chip::Optional<const char *> & optionalExpectedDigest = chip::NullOptional,
46+
HttpsSecurityMode securityMode = HttpsSecurityMode::kDefault);
3647

3748
} // namespace https
3849
} // namespace tool

examples/darwin-framework-tool/commands/dcl/HTTPSRequest.mm

+50-8
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@
5959
constexpr const char * kErrorConnectionTimeout = "Timeout connecting to: ";
6060
constexpr const char * kErrorConnectionUnknowState = "Unknown connection state";
6161
constexpr const char * kErrorDigestMismatch = "The response digest does not match the expected digest";
62+
63+
constexpr sec_protocol_verify_t NULL_VERIFIER = ^(sec_protocol_metadata_t metadata,
64+
sec_trust_t trust_ref,
65+
sec_protocol_verify_complete_t complete) {
66+
complete(true);
67+
};
68+
6269
class HTTPSSessionHolder {
6370
public:
6471
HTTPSSessionHolder() {};
@@ -70,13 +77,35 @@
7077
mConnection = nullptr;
7178
}
7279

73-
CHIP_ERROR Init(std::string & hostname, uint16_t port)
80+
CHIP_ERROR Init(std::string & hostname, uint16_t port, HttpsSecurityMode securityMode)
7481
{
7582
__auto_type semaphore = dispatch_semaphore_create(0);
7683
__block CHIP_ERROR result = CHIP_NO_ERROR;
84+
__auto_type queue = dispatch_queue_create(kDispatchQueueName, DISPATCH_QUEUE_SERIAL);
7785

7886
__auto_type endpoint = nw_endpoint_create_host(hostname.c_str(), std::to_string(port).c_str());
79-
nw_parameters_t parameters = nw_parameters_create_secure_tcp(NW_PARAMETERS_DEFAULT_CONFIGURATION, NW_PARAMETERS_DEFAULT_CONFIGURATION);
87+
88+
nw_parameters_configure_protocol_block_t tls_options;
89+
switch (securityMode) {
90+
case HttpsSecurityMode::kDefault: {
91+
tls_options = NW_PARAMETERS_DEFAULT_CONFIGURATION;
92+
break;
93+
}
94+
case HttpsSecurityMode::kDisableValidation: {
95+
tls_options = ^(nw_protocol_options_t tls_options) {
96+
sec_protocol_options_t sec_options = nw_tls_copy_sec_protocol_options(tls_options);
97+
sec_protocol_options_set_verify_block(sec_options, NULL_VERIFIER, queue);
98+
};
99+
break;
100+
}
101+
case HttpsSecurityMode::kDisableHttps: {
102+
tls_options = NW_PARAMETERS_DISABLE_PROTOCOL;
103+
break;
104+
}
105+
}
106+
107+
// NW_PARAMETERS_DISABLE_PROTOCOL
108+
nw_parameters_t parameters = nw_parameters_create_secure_tcp(tls_options, NW_PARAMETERS_DEFAULT_CONFIGURATION);
80109

81110
mConnection = nw_connection_create(endpoint, parameters);
82111
VerifyOrReturnError(nullptr != mConnection, CHIP_ERROR_INTERNAL);
@@ -101,7 +130,6 @@ CHIP_ERROR Init(std::string & hostname, uint16_t port)
101130
}
102131
});
103132

104-
__auto_type queue = dispatch_queue_create(kDispatchQueueName, DISPATCH_QUEUE_SERIAL);
105133
nw_connection_set_queue(mConnection, queue);
106134
nw_connection_start(mConnection);
107135

@@ -185,6 +213,7 @@ CHIP_ERROR ReceiveResponse(std::string & response)
185213

186214
CHIP_ERROR RemoveHeader(std::string & response)
187215
{
216+
// TODO: Parse the response status. Why are we doing HTTP by hand?
188217
size_t headerEnd = response.find("\r\n\r\n");
189218
VerifyOrReturnError(std::string::npos != headerEnd, CHIP_ERROR_INVALID_ARGUMENT);
190219

@@ -290,27 +319,40 @@ CHIP_ERROR ExtractHostNamePortPath(std::string url, std::string & outHostName, u
290319
} // namespace
291320

292321
CHIP_ERROR Request(std::string url, Json::Value & jsonResponse, const Optional<uint32_t> & optionalExpectedSize,
293-
const Optional<const char *> & optionalExpectedDigest)
322+
const Optional<const char *> & optionalExpectedDigest, HttpsSecurityMode securityMode)
294323
{
295324
std::string hostname;
296325
uint16_t port;
297326
std::string path;
298327
ReturnErrorOnFailure(ExtractHostNamePortPath(url, hostname, port, path));
299-
return Request(hostname, port, path, jsonResponse, optionalExpectedSize, optionalExpectedDigest);
328+
return Request(hostname, port, path, jsonResponse, optionalExpectedSize, optionalExpectedDigest, securityMode);
300329
}
301330

302331
CHIP_ERROR Request(std::string hostname, uint16_t port, std::string path, Json::Value & jsonResponse,
303-
const Optional<uint32_t> & optionalExpectedSize, const Optional<const char *> & optionalExpectedDigest)
332+
const Optional<uint32_t> & optionalExpectedSize, const Optional<const char *> & optionalExpectedDigest,
333+
HttpsSecurityMode securityMode)
304334
{
305335
VerifyOrDo(port != 0, port = kHttpsPort);
306336

307-
ChipLogDetail(chipTool, "HTTPS request to %s:%u%s", hostname.c_str(), port, path.c_str());
337+
char const * protocol;
338+
switch (securityMode) {
339+
case HttpsSecurityMode::kDefault:
340+
protocol = "HTTPS";
341+
break;
342+
case HttpsSecurityMode::kDisableValidation:
343+
protocol = "HTTPS (no validation)";
344+
break;
345+
case HttpsSecurityMode::kDisableHttps:
346+
protocol = "HTTP";
347+
break;
348+
}
349+
ChipLogDetail(chipTool, "%s request to %s:%u%s", protocol, hostname.c_str(), port, path.c_str());
308350

309351
std::string request = BuildRequest(hostname, path);
310352
std::string response;
311353

312354
HTTPSSessionHolder session;
313-
ReturnErrorOnFailure(session.Init(hostname, port));
355+
ReturnErrorOnFailure(session.Init(hostname, port, securityMode));
314356
ReturnErrorOnFailure(session.SendRequest(request));
315357
ReturnErrorOnFailure(session.ReceiveResponse(response));
316358
ReturnErrorOnFailure(RemoveHeader(response));

examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.h

+7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
*/
1818

1919
#pragma once
20+
2021
#include "../common/CHIPCommandBridge.h"
22+
#include <commands/dcl/HTTPSRequest.h>
23+
2124
#import <Matter/Matter.h>
2225

2326
enum class PairingMode
@@ -66,6 +69,8 @@ class PairingCommandBridge : public CHIPCommandBridge
6669
AddArgument("dcl-hostname", &mDCLHostName,
6770
"Hostname of the DCL server to fetch information from. Defaults to 'on.dcl.csa-iot.org'.");
6871
AddArgument("dcl-port", 0, UINT16_MAX, &mDCLPort, "Port number for connecting to the DCL server. Defaults to '443'.");
72+
AddArgument("dcl-disable-https", 0, 1, &mDCLDisableHttps, "Disable HTTPS (use plain HTTP)");
73+
AddArgument("dcl-disable-https-validation", 0, 1, &mDCLDisableHttpsValidation, "Disable HTTPS validation");
6974
AddArgument("use-dcl", 0, 1, &mUseDCL, "Use DCL to fetch onboarding information");
7075
break;
7176
case PairingMode::Ble:
@@ -121,5 +126,7 @@ class PairingCommandBridge : public CHIPCommandBridge
121126
chip::Optional<char *> mCountryCode;
122127
chip::Optional<char *> mDCLHostName;
123128
chip::Optional<uint16_t> mDCLPort;
129+
chip::Optional<bool> mDCLDisableHttps;
130+
chip::Optional<bool> mDCLDisableHttpsValidation;
124131
chip::Optional<bool> mUseDCL;
125132
};

examples/darwin-framework-tool/commands/pairing/PairingCommandBridge.mm

+3-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ - (void)deviceAttestationCompletedForController:(MTRDeviceController *)controlle
103103
VerifyOrReturn(mUseDCL.ValueOr(false));
104104

105105
Json::Value tc;
106-
auto client = tool::dcl::DCLClient(mDCLHostName, mDCLPort);
106+
auto securityMode = mDCLDisableHttps.ValueOr(false) ? tool::https::HttpsSecurityMode::kDisableHttps : mDCLDisableHttpsValidation.ValueOr(false) ? tool::https::HttpsSecurityMode::kDisableValidation
107+
: tool::https::HttpsSecurityMode::kDefault;
108+
auto client = tool::dcl::DCLClient(mDCLHostName, mDCLPort, securityMode);
107109
CHIP_ERROR err = client.TermsAndConditions(mOnboardingPayload, tc);
108110

109111
if (CHIP_NO_ERROR != err) {

0 commit comments

Comments
 (0)