blob: 0910c1244253f56008caadc9fa5121e537528661 [file] [log] [blame]
/*
*
* Copyright (c) 2013-2017 Nest Labs, Inc.
* All rights reserved.
*
* 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.
*/
/**
* @file
* This file defines data types and objects for a Weave Service
* Provisioning profile unsolicited initiator (client) and
* responder (server).
*
*/
#ifndef SERVICEPROVISIONING_H_
#define SERVICEPROVISIONING_H_
#include <Weave/Support/NLDLLUtil.h>
#include <Weave/Core/WeaveCore.h>
#include <Weave/Core/WeaveServerBase.h>
#include <Weave/Core/WeaveEncoding.h>
#include <Weave/Core/WeaveTLV.h>
#include <Weave/Profiles/security/WeaveCert.h>
/**
* @namespace nl::Weave::Profiles::ServiceProvisioning
*
* @brief
* This namespace includes all interfaces within Weave for the
* Weave Service Provisioning profile, the third of the three
* Weave provisioning profiles.
*/
namespace nl {
namespace Weave {
namespace Profiles {
namespace ServiceProvisioning {
using nl::Inet::IPAddress;
// Service Provisioning Status Codes
//
enum
{
kStatusCode_TooManyServices = 1, // There are too many service's registered on the device.
kStatusCode_ServiceAlreadyRegistered = 2, // The specified service is already registered on the device.
kStatusCode_InvalidServiceConfig = 3, // The specified service configuration is invalid.
kStatusCode_NoSuchService = 4, // The specified id does not match a service registered on the device.
kStatusCode_PairingServerError = 5, // The device could not complete service pairing because it failed to talk to the pairing server.
kStatusCode_InvalidPairingToken = 6, // The device could not complete service pairing because it passed an invalid pairing token.
kStatusCode_PairingTokenOld = 7, // The device could not complete service pairing because the pairing token it passed has expired.
kStatusCode_ServiceCommuncationError = 8, // The device could not complete service pairing because it encountered an error when communicating with the service.
kStatusCode_ServiceConfigTooLarge = 9, // The specified service configuration is too large.
kStatusCode_WrongFabric = 10, // Device paired with a different fabric
kStatusCode_TooManyFabrics = 11 // Too many fabrics in the structure
// !!!!! IMPORTANT !!!!! If you add new Service Provisioning status codes, you must coordinate this with the service team.
// The service runs a separate implementation of the Weave protocol, so it does not automatically pick up undocumented or
// uncommunicated changes to status codes in the devices' Weave stack.
};
// Service Provisioning Message Types
//
enum
{
// Application/Device Messages
kMsgType_RegisterServicePairAccount = 1,
kMsgType_UpdateService = 2,
kMsgType_UnregisterService = 3,
// Device/Service Messages
kMsgType_UnpairDeviceFromAccount = 101,
kMsgType_PairDeviceToAccount = 102
};
// Service Provisioning Data Element Tags
//
enum
{
// ---- Top-level Data Elements ----
kTag_ServiceConfig = 1, // [ structure ] Describes a Weave Service.
kTag_ServiceEndPoint = 2, // [ structure ] Describes a Weave Service EndPoint.
// ---- Context-specific Tags for ServiceConfig Structure ----
kTag_ServiceConfig_CACerts = 1, // [ array, length >= 1 ] List of trusted CA certificates for service.
// Each element is a WeaveCertificate, as defined in the Security Profile.
kTag_ServiceConfig_DirectoryEndPoint = 2, // [ structure ] Contains contact information for the service's primary directory end point.
// Contents are as defined below for ServiceEndPoint structure.
// ---- Context-specific Tags for ServiceEndPoint Structure ----
kTag_ServiceEndPoint_Id = 1, // [ uint, 8-64 bits ] Service end point id (an EUI-64) assigned to the service end point.
kTag_ServiceEndPoint_Addresses = 2, // [ array, length >= 1 ] List of addresses for the service end point.
// Each element is a ServiceEndPointAddress structure, as defined below.
kTag_ServiceEndPoint_NodeId = 3, // [ uint, 8-64 bits ] Weave node id of the node providing the service.
// Mutually exclusive with Addresses list.
// ---- Context-specific Tags for ServiceEndPointAddress Structure ----
kTag_ServiceEndPointAddress_HostName = 1, // [ utf-8 string ] Host name or literal IP address.
kTag_ServiceEndPointAddress_Port = 2 // [ uint, 1-63353 ] IP port number. Optional
};
class NL_DLL_EXPORT RegisterServicePairAccountMessage
{
public:
uint64_t ServiceId;
const char *AccountId;
uint16_t AccountIdLen;
const uint8_t *ServiceConfig;
uint16_t ServiceConfigLen;
const uint8_t *PairingToken;
uint16_t PairingTokenLen;
const uint8_t *PairingInitData;
uint16_t PairingInitDataLen;
WEAVE_ERROR Encode(PacketBuffer *msgBuf);
static WEAVE_ERROR Decode(PacketBuffer *msgBuf, RegisterServicePairAccountMessage& msg);
};
class NL_DLL_EXPORT UpdateServiceMessage
{
public:
uint64_t ServiceId;
const uint8_t *ServiceConfig;
uint16_t ServiceConfigLen;
WEAVE_ERROR Encode(PacketBuffer *msgBuf);
static WEAVE_ERROR Decode(PacketBuffer *msgBuf, UpdateServiceMessage& msg);
};
class NL_DLL_EXPORT PairDeviceToAccountMessage
{
public:
uint64_t ServiceId;
uint64_t FabricId;
const char *AccountId;
uint16_t AccountIdLen;
const uint8_t *PairingToken;
uint16_t PairingTokenLen;
const uint8_t *PairingInitData;
uint16_t PairingInitDataLen;
const uint8_t *DeviceInitData;
uint16_t DeviceInitDataLen;
WEAVE_ERROR Encode(PacketBuffer *msgBuf);
static WEAVE_ERROR Decode(PacketBuffer *msgBuf, PairDeviceToAccountMessage& msg);
};
class ServiceProvisioningDelegate : public WeaveServerDelegateBase
{
public:
virtual WEAVE_ERROR HandleRegisterServicePairAccount(RegisterServicePairAccountMessage& msg) = 0;
virtual WEAVE_ERROR HandleUpdateService(UpdateServiceMessage& msg) = 0;
virtual WEAVE_ERROR HandleUnregisterService(uint64_t serviceId) = 0;
virtual void HandlePairDeviceToAccountResult(WEAVE_ERROR localErr, uint32_t serverStatusProfileId, uint16_t serverStatusCode) = 0;
/**
* Enforce message-level access control for an incoming Service Provisioning request message.
*
* @param[in] ec The ExchangeContext over which the message was received.
* @param[in] msgProfileId The profile id of the received message.
* @param[in] msgType The message type of the received message.
* @param[in] msgInfo A WeaveMessageInfo structure containing information about the received message.
* @param[inout] result An enumerated value describing the result of access control policy evaluation for
* the received message. Upon entry to the method, the value represents the tentative
* result at the current point in the evaluation process. Upon return, the result
* is expected to represent the final assessment of access control policy for the
* message.
*/
virtual void EnforceAccessControl(ExchangeContext *ec, uint32_t msgProfileId, uint8_t msgType,
const WeaveMessageInfo *msgInfo, AccessControlResult& result);
/**
* Called to determine if the device is currently paired to an account.
*/
// TODO: make this pure virtual when product code provides appropriate implementations.
virtual bool IsPairedToAccount() const;
};
// ServiceProvisioningServer -- Simple server class for implementing the Service Provisioning profile.
//
class NL_DLL_EXPORT ServiceProvisioningServer : public WeaveServerBase
{
public:
ServiceProvisioningServer(void);
WEAVE_ERROR Init(WeaveExchangeManager *exchangeMgr);
WEAVE_ERROR Shutdown(void);
void SetDelegate(ServiceProvisioningDelegate *delegate);
ServiceProvisioningDelegate* GetDelegate(void) const;
virtual WEAVE_ERROR SendSuccessResponse(void);
virtual WEAVE_ERROR SendStatusReport(uint32_t statusProfileId, uint16_t statusCode, WEAVE_ERROR sysError = WEAVE_NO_ERROR);
// TODO: [TT] Remove when Bindings support existing Weave Connections or Service Directory.
WEAVE_ERROR SendPairDeviceToAccountRequest(WeaveConnection *serverCon, uint64_t serviceId, uint64_t fabricId,
const char *accountId, uint16_t accountIdLen,
const uint8_t *pairingToken, uint16_t pairingTokenLen,
const uint8_t *pairingInitData, uint16_t pairingInitDataLen,
const uint8_t *deviceInitData, uint16_t deviceInitDataLen);
WEAVE_ERROR SendPairDeviceToAccountRequest(Binding *binding, uint64_t serviceId, uint64_t fabricId,
const char *accountId, uint16_t accountIdLen,
const uint8_t *pairingToken, uint16_t pairingTokenLen,
const uint8_t *pairingInitData, uint16_t pairingInitDataLen,
const uint8_t *deviceInitData, uint16_t deviceInitDataLen);
static bool IsValidServiceConfig(const uint8_t *serviceConfig, uint16_t serviceConfigLen);
protected:
enum
{
kServerOpState_Idle = 0,
kServerOpState_PairDeviceToAccount = 1
};
ServiceProvisioningDelegate *mDelegate;
ExchangeContext *mCurClientOp;
PacketBuffer *mCurClientOpBuf;
union
{
RegisterServicePairAccountMessage RegisterServicePairAccount;
UpdateServiceMessage UpdateService;
} mCurClientOpMsg;
ExchangeContext *mCurServerOp;
uint8_t mServerOpState;
private:
static void HandleClientRequest(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
uint32_t profileId, uint8_t msgType, PacketBuffer *payload);
static void HandleServerResponse(ExchangeContext *ec, const IPPacketInfo *pktInfo, const WeaveMessageInfo *msgInfo,
uint32_t profileId, uint8_t msgType, PacketBuffer *payload);
static void HandleServerResponseTimeout(ExchangeContext *ec);
static void HandleServerConnectionClosed(ExchangeContext *ec, WeaveConnection *con, WEAVE_ERROR conErr);
static void HandleServerKeyError(ExchangeContext *ec, WEAVE_ERROR keyErr);
#if WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
static void HandleServerSendError(ExchangeContext *ec, WEAVE_ERROR err, void *msgCtxt);
#endif // #if WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
void HandlePairDeviceToAccountResult(WEAVE_ERROR localErr, uint32_t serverStatusProfileId, uint16_t serverStatusCode);
ServiceProvisioningServer(const ServiceProvisioningServer&); // not defined
};
extern WEAVE_ERROR EncodeServiceConfig(nl::Weave::Profiles::Security::WeaveCertificateSet& certSet, const char *dirHostName, uint16_t dirPort, uint8_t *outBuf, uint16_t& outLen);
} // namespace ServiceProvisioning
} // namespace Profiles
} // namespace Weave
} // namespace nl
#endif /* SERVICEPROVISIONING_H_ */