Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
ConnectorClient.cpp
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2017 ARM Ltd. 00003 // 00004 // SPDX-License-Identifier: Apache-2.0 00005 // 00006 // Licensed under the Apache License, Version 2.0 (the "License"); 00007 // you may not use this file except in compliance with the License. 00008 // You may obtain a copy of the License at 00009 // 00010 // http://www.apache.org/licenses/LICENSE-2.0 00011 // 00012 // Unless required by applicable law or agreed to in writing, software 00013 // distributed under the License is distributed on an "AS IS" BASIS, 00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 // See the License for the specific language governing permissions and 00016 // limitations under the License. 00017 // ---------------------------------------------------------------------------- 00018 00019 #include <string> 00020 #include <assert.h> 00021 #include <stdio.h> 00022 #include "include/ConnectorClient.h" 00023 #include "include/CloudClientStorage.h" 00024 #include "include/CertificateParser.h" 00025 #include "MbedCloudClient.h" 00026 #include "mbed-client/m2minterfacefactory.h" 00027 #include "mbed-client/m2mdevice.h" 00028 #include "mbed-trace/mbed_trace.h" 00029 #include "factory_configurator_client.h" 00030 00031 #define TRACE_GROUP "mClt" 00032 00033 #define INTERNAL_ENDPOINT_PARAM "&iep=" 00034 #define DEFAULT_ENDPOINT "endpoint" 00035 #define INTERFACE_ERROR "Client interface is not created. Restart" 00036 #define CREDENTIAL_ERROR "Failed to read credentials from storage" 00037 #define DEVICE_NOT_PROVISIONED "Device not provisioned" 00038 #define ERROR_NO_MEMORY "Not enough memory to stroe LWM2M credentials" 00039 00040 // XXX: nothing here yet 00041 class EventData { 00042 00043 }; 00044 00045 ConnectorClient::ConnectorClient(ConnectorClientCallback* callback) 00046 : _callback(callback), 00047 _current_state(State_Bootstrap_Start), 00048 _event_generated(false), _state_engine_running(false), 00049 _interface(NULL), _security(NULL), 00050 _endpoint_info(M2MSecurity::Certificate), _client_objs(NULL), 00051 _rebootstrap_timer(*this), _bootstrap_security_instance(1), _lwm2m_security_instance(0) 00052 { 00053 assert(_callback != NULL); 00054 00055 // Create the lwm2m server security object we need always 00056 _security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer); 00057 _interface = M2MInterfaceFactory::create_interface(*this, 00058 DEFAULT_ENDPOINT, // endpoint name string 00059 MBED_CLOUD_CLIENT_ENDPOINT_TYPE, // endpoint type string 00060 MBED_CLOUD_CLIENT_LIFETIME, // lifetime 00061 MBED_CLOUD_CLIENT_LISTEN_PORT, // listen port 00062 _endpoint_info.account_id, // domain string 00063 transport_mode(), // binding mode 00064 M2MInterface::LwIP_IPv4); // network stack 00065 00066 initialize_storage(); 00067 } 00068 00069 00070 ConnectorClient::~ConnectorClient() 00071 { 00072 M2MDevice::delete_instance(); 00073 M2MSecurity::delete_instance(); 00074 delete _interface; 00075 } 00076 00077 void ConnectorClient::start_bootstrap() 00078 { 00079 tr_debug("ConnectorClient::start_bootstrap()"); 00080 assert(_callback != NULL); 00081 // Stop rebootstrap timer if it was running 00082 _rebootstrap_timer.stop_timer(); 00083 if (create_bootstrap_object()) { 00084 _interface->update_endpoint(_endpoint_info.endpoint_name); 00085 _interface->update_domain(_endpoint_info.account_id); 00086 internal_event(State_Bootstrap_Start); 00087 } else { 00088 tr_error("ConnectorClient::start_bootstrap() - bootstrap object fail"); 00089 } 00090 state_engine(); 00091 } 00092 00093 void ConnectorClient::start_registration(M2MObjectList* client_objs) 00094 { 00095 tr_debug("ConnectorClient::start_registration()"); 00096 assert(_callback != NULL); 00097 _client_objs = client_objs; 00098 00099 // XXX: actually this call should be external_event() to match the pattern used in other m2m classes 00100 create_register_object(); 00101 if(_security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) { 00102 if(use_bootstrap()) { 00103 // Bootstrap registration always uses iep 00104 _interface->update_endpoint(_endpoint_info.internal_endpoint_name); 00105 } else { 00106 // Registration without bootstrap always uses external id 00107 _interface->update_endpoint(_endpoint_info.endpoint_name); 00108 } 00109 _interface->update_domain(_endpoint_info.account_id); 00110 internal_event(State_Registration_Start); 00111 } else { 00112 tr_error("ConnectorClient::state_init(): failed to create objs"); 00113 _callback->connector_error(M2MInterface::InvalidParameters, INTERFACE_ERROR); 00114 } 00115 state_engine(); 00116 } 00117 00118 M2MInterface * ConnectorClient::m2m_interface() 00119 { 00120 return _interface; 00121 } 00122 00123 void ConnectorClient::update_registration() 00124 { 00125 if(_interface && _security && _security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) { 00126 if (_client_objs != NULL) { 00127 _interface->update_registration(_security, *_client_objs); 00128 } 00129 else { 00130 _interface->update_registration(_security); 00131 } 00132 } 00133 } 00134 00135 // generates an internal event. called from within a state 00136 // function to transition to a new state 00137 void ConnectorClient::internal_event(StartupSubStateRegistration new_state) 00138 { 00139 tr_debug("ConnectorClient::internal_event: state: %d -> %d", _current_state, new_state); 00140 _event_generated = true; 00141 _current_state = new_state; 00142 00143 // Avoid recursive chain which eats too much of stack 00144 if (!_state_engine_running) { 00145 state_engine(); 00146 } 00147 } 00148 00149 // the state engine executes the state machine states 00150 void ConnectorClient::state_engine(void) 00151 { 00152 tr_debug("ConnectorClient::state_engine"); 00153 00154 // this simple flagging gets rid of recursive calls to this method 00155 _state_engine_running = true; 00156 00157 // while events are being generated keep executing states 00158 while (_event_generated) { 00159 _event_generated = false; // event used up, reset flag 00160 00161 state_function(_current_state); 00162 } 00163 00164 _state_engine_running = false; 00165 } 00166 00167 void ConnectorClient::state_function(StartupSubStateRegistration current_state) 00168 { 00169 switch (current_state) { 00170 case State_Bootstrap_Start: 00171 state_bootstrap_start(); 00172 break; 00173 case State_Bootstrap_Started: 00174 state_bootstrap_started(); 00175 break; 00176 case State_Bootstrap_Success: 00177 state_bootstrap_success(); 00178 break; 00179 case State_Bootstrap_Failure: 00180 state_bootstrap_failure(); 00181 break; 00182 case State_Registration_Start: 00183 state_registration_start(); 00184 break; 00185 case State_Registration_Started: 00186 state_registration_started(); 00187 break; 00188 case State_Registration_Success: 00189 state_registration_success(); 00190 break; 00191 case State_Registration_Failure: 00192 state_registration_failure(); 00193 break; 00194 case State_Unregistered: 00195 state_unregistered(); 00196 break; 00197 default: 00198 break; 00199 } 00200 } 00201 00202 /* 00203 * Creates register server object with mbed device server address and other parameters 00204 * required for client to connect to mbed device server. 00205 */ 00206 void ConnectorClient::create_register_object() 00207 { 00208 tr_debug("ConnectorClient::create_register_object()"); 00209 if(_security && _security->get_security_instance_id(M2MSecurity::M2MServer) == -1) { 00210 _security->create_object_instance(M2MSecurity::M2MServer); 00211 int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer); 00212 _security->set_resource_value(M2MSecurity::BootstrapServer, M2MSecurity::M2MServer, m2m_id); 00213 // Add ResourceID's and values to the security ObjectID/ObjectInstance 00214 _security->set_resource_value(M2MSecurity::SecurityMode, _endpoint_info.mode, m2m_id); 00215 00216 // Allocate scratch buffer, this will be used to copy parameters from storage to security object 00217 const int max_size = 2048; 00218 uint8_t *buffer = (uint8_t*)malloc(max_size); 00219 size_t real_size = 0; 00220 bool success = false; 00221 if (buffer != NULL) { 00222 success = true; 00223 } 00224 00225 // Connector CA 00226 if (success) { 00227 success = false; 00228 if (get_config_certificate(g_fcc_lwm2m_server_ca_certificate_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00229 tr_info("ConnectorClient::create_register_object - ServerPublicKey %d", (int)real_size); 00230 success = true; 00231 _security->set_resource_value(M2MSecurity::ServerPublicKey, 00232 buffer, 00233 (uint32_t)real_size, 00234 m2m_id); 00235 } 00236 else { 00237 tr_error("KEY_CONNECTOR_CA cert failed."); 00238 } 00239 } 00240 00241 // Connector device public key 00242 if (success) { 00243 success = false; 00244 if (get_config_certificate(g_fcc_lwm2m_device_certificate_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00245 tr_info("ConnectorClient::create_register_object - PublicKey %d", (int)real_size); 00246 success = true; 00247 _security->set_resource_value(M2MSecurity::PublicKey, buffer, (uint32_t)real_size, m2m_id); 00248 } 00249 else { 00250 tr_error("KEY_CONNECTOR__DEVICE_CERT failed."); 00251 } 00252 } 00253 00254 // Connector device private key 00255 if (success) { 00256 success = false; 00257 if (get_config_private_key(g_fcc_lwm2m_device_private_key_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00258 tr_info("ConnectorClient::create_register_object - SecretKey %d", (int)real_size); 00259 success = true; 00260 _security->set_resource_value(M2MSecurity::Secretkey, buffer, (uint32_t)real_size, m2m_id); 00261 } 00262 else 00263 tr_error("KEY_CONNECTOR_DEVICE_PRIV failed."); 00264 } 00265 00266 // Connector URL 00267 if (success) { 00268 success = false; 00269 if (get_config_parameter(g_fcc_lwm2m_server_uri_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00270 tr_info("ConnectorClient::create_register_object - M2MServerUri %.*s", (int)real_size, buffer); 00271 success = true; 00272 _security->set_resource_value(M2MSecurity::M2MServerUri, buffer, (uint32_t)real_size, m2m_id); 00273 } 00274 else 00275 tr_error("KEY_CONNECTOR_URL failed."); 00276 } 00277 00278 // Endpoint 00279 if (success) { 00280 success = false; 00281 if (get_config_parameter(g_fcc_endpoint_parameter_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00282 tr_info("ConnectorClient::create_register_object - endpoint name %.*s", (int)real_size, buffer); 00283 success = true; 00284 _endpoint_info.endpoint_name = String((const char*)buffer, real_size); 00285 } 00286 else 00287 tr_error("KEY_ENDPOINT_NAME failed."); 00288 } 00289 00290 // Try to get internal endpoint name 00291 if (success) { 00292 if (get_config_parameter(KEY_INTERNAL_ENDPOINT, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00293 _endpoint_info.internal_endpoint_name = String((const char*)buffer, real_size); 00294 tr_info("Using internal endpoint name instead: %s", _endpoint_info.internal_endpoint_name.c_str()); 00295 } 00296 else { 00297 tr_debug("KEY_INTERNAL_ENDPOINT failed."); 00298 } 00299 } 00300 00301 // Account ID, not mandatory 00302 if (success) { 00303 if (get_config_parameter(KEY_ACCOUNT_ID, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00304 tr_info("ConnectorClient::create_register_object - AccountId %.*s", (int)real_size, buffer); 00305 _endpoint_info.account_id = String((const char*)buffer, real_size); 00306 } 00307 else 00308 tr_debug("KEY_ACCOUNT_ID failed."); 00309 } 00310 00311 free(buffer); 00312 if (!success) { 00313 tr_error("ConnectorClient::create_register_object - Failed to read credentials"); 00314 _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials,CREDENTIAL_ERROR); 00315 // TODO: what to do with the m2mserver security instance 00316 } 00317 } else { 00318 tr_info("ConnectorClient::create_register_object() - Credentials already exists"); 00319 } 00320 } 00321 00322 /* 00323 * Creates bootstrap server object with bootstrap server address and other parameters 00324 * required for connecting to mbed Cloud bootstrap server. 00325 */ 00326 bool ConnectorClient::create_bootstrap_object() 00327 { 00328 tr_debug("ConnectorClient::create_bootstrap_object"); 00329 bool success = false; 00330 00331 // Check if bootstrap credentials are already stored in KCM 00332 if (bootstrap_credentials_stored_in_kcm() && _security) { 00333 if (_security->get_security_instance_id(M2MSecurity::Bootstrap) == -1) { 00334 _security->create_object_instance(M2MSecurity::Bootstrap); 00335 int32_t bs_id = _security->get_security_instance_id(M2MSecurity::Bootstrap); 00336 _security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate, bs_id); 00337 tr_info("ConnectorClient::create_bootstrap_object - bs_id = %d", bs_id); 00338 tr_info("ConnectorClient::create_bootstrap_object - use credentials from storage"); 00339 00340 // Allocate scratch buffer, this will be used to copy parameters from storage to security object 00341 size_t real_size = 0; 00342 const int max_size = 2048; 00343 uint8_t *buffer = (uint8_t*)malloc(max_size); 00344 if (buffer != NULL) { 00345 success = true; 00346 } 00347 00348 // Read internal endpoint name if it exists, we need to append 00349 // it to bootstrap uri if device already bootstrapped 00350 uint8_t *iep = NULL; 00351 if (success && get_config_parameter_string(KEY_INTERNAL_ENDPOINT, buffer, max_size) == CCS_STATUS_SUCCESS) { 00352 iep = (uint8_t*)malloc(strlen((const char*)buffer) + strlen(INTERNAL_ENDPOINT_PARAM) + 1); 00353 if (iep != NULL) { 00354 strcpy((char*)iep, INTERNAL_ENDPOINT_PARAM); 00355 strcat((char*)iep, (const char*)buffer); 00356 tr_info("ConnectorClient::create_bootstrap_object - iep: %s", buffer); 00357 } 00358 //TODO: Should handle error if iep exists but allocation fails? 00359 } 00360 00361 // Bootstrap URI 00362 if (success) { 00363 success = false; 00364 if (get_config_parameter_string(g_fcc_bootstrap_server_uri_name, buffer, max_size) == CCS_STATUS_SUCCESS) { 00365 success = true; 00366 00367 real_size = strlen((const char*)buffer); 00368 // Append iep if we 1. have it 2. it doesn't already exist in uri 3. it fits 00369 if (iep && 00370 strstr((const char*)buffer, (const char*)iep) == NULL && 00371 (real_size + strlen((const char*)iep) + 1) <= max_size) { 00372 strcat((char*)buffer, (const char*)iep); 00373 real_size += strlen((const char*)iep) + 1; 00374 } 00375 00376 tr_info("ConnectorClient::create_bootstrap_object - M2MServerUri %.*s", (int)real_size, buffer); 00377 _security->set_resource_value(M2MSecurity::M2MServerUri, buffer, real_size, bs_id); 00378 } 00379 } 00380 00381 free(iep); 00382 00383 // Bootstrap server public key (certificate) 00384 if (success) { 00385 success = false; 00386 if (get_config_certificate(g_fcc_bootstrap_server_ca_certificate_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00387 success = true; 00388 tr_info("ConnectorClient::create_bootstrap_object - ServerPublicKey %d", (int)real_size); 00389 _security->set_resource_value(M2MSecurity::ServerPublicKey, buffer, real_size, bs_id); 00390 } 00391 } 00392 00393 // Bootstrap client public key (certificate) 00394 if (success) { 00395 success = false; 00396 if (get_config_certificate(g_fcc_bootstrap_device_certificate_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00397 success = true; 00398 tr_info("ConnectorClient::create_bootstrap_object - PublicKey %d", (int)real_size); 00399 _security->set_resource_value(M2MSecurity::PublicKey, buffer, real_size, bs_id); 00400 } 00401 } 00402 00403 // Bootstrap client private key 00404 if (success) { 00405 success = false; 00406 if (get_config_private_key(g_fcc_bootstrap_device_private_key_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00407 success = true; 00408 tr_info("ConnectorClient::create_bootstrap_object - Secretkey %d", (int)real_size); 00409 _security->set_resource_value(M2MSecurity::Secretkey, buffer, real_size, bs_id); 00410 } 00411 } 00412 00413 // Endpoint 00414 if (success) { 00415 success = false; 00416 if (get_config_parameter(g_fcc_endpoint_parameter_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00417 success = true; 00418 _endpoint_info.endpoint_name = String((const char*)buffer, real_size); 00419 tr_info("ConnectorClient::create_bootstrap_object - Endpoint %s", _endpoint_info.endpoint_name.c_str()); 00420 } 00421 } 00422 00423 // Account ID, not mandatory 00424 if (success) { 00425 if (get_config_parameter(KEY_ACCOUNT_ID, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00426 _endpoint_info.account_id = String((const char*)buffer, real_size); 00427 tr_info("ConnectorClient::create_bootstrap_object - AccountId %s", _endpoint_info.account_id.c_str()); 00428 } 00429 } 00430 free(buffer); 00431 00432 if (!success) { 00433 tr_error("ConnectorClient::create_bootstrap_object - Failed to read credentials"); 00434 _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials,CREDENTIAL_ERROR); 00435 _security->remove_object_instance(bs_id); 00436 } 00437 } else { 00438 success = true; 00439 tr_info("ConnectorClient::create_bootstrap_object - bootstrap object already done"); 00440 } 00441 // Device not provisioned 00442 } else { 00443 _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorInvalidCredentials, DEVICE_NOT_PROVISIONED); 00444 tr_error("ConnectorClient::create_bootstrap_object - device not provisioned!"); 00445 } 00446 return success; 00447 } 00448 00449 void ConnectorClient::state_bootstrap_start() 00450 { 00451 tr_info("ConnectorClient::state_bootstrap_start()"); 00452 assert(_interface != NULL); 00453 assert(_security != NULL); 00454 00455 _interface->bootstrap(_security); 00456 00457 internal_event(State_Bootstrap_Started); 00458 } 00459 00460 void ConnectorClient::state_bootstrap_started() 00461 { 00462 // this state may be useful only for verifying the callbacks? 00463 } 00464 00465 void ConnectorClient::state_bootstrap_success() 00466 { 00467 assert(_callback != NULL); 00468 // Parse internal endpoint name from mDS cert 00469 _callback->registration_process_result(State_Bootstrap_Success); 00470 } 00471 00472 void ConnectorClient::state_bootstrap_failure() 00473 { 00474 assert(_callback != NULL); 00475 // maybe some additional canceling and/or leanup is needed here? 00476 _callback->registration_process_result(State_Bootstrap_Failure); 00477 } 00478 00479 void ConnectorClient::state_registration_start() 00480 { 00481 tr_info("ConnectorClient::state_registration_start()"); 00482 assert(_interface != NULL); 00483 assert(_security != NULL); 00484 _interface->register_object(_security, *_client_objs); 00485 internal_event(State_Registration_Started); 00486 } 00487 00488 void ConnectorClient::state_registration_started() 00489 { 00490 // this state may be useful only for verifying the callbacks? 00491 } 00492 00493 void ConnectorClient::state_registration_success() 00494 { 00495 assert(_callback != NULL); 00496 _endpoint_info.internal_endpoint_name = _interface->internal_endpoint_name(); 00497 00498 //The endpoint is maximum 32 character long, we put bigger buffer for future extensions 00499 const int max_size = 64; 00500 uint8_t buffer[max_size]; 00501 00502 bool no_param_update = true; 00503 00504 if(get_config_parameter_string(KEY_INTERNAL_ENDPOINT, buffer, max_size) == CCS_STATUS_SUCCESS) { 00505 if (strcmp((const char*)buffer, _endpoint_info.internal_endpoint_name.c_str()) != 0) { 00506 // Update is required as the stored KCM entry is different than _endpoint_info.internal_endpoint_name. 00507 no_param_update = false; 00508 } 00509 } 00510 00511 // Update INTERNAL_ENDPOINT setting only if there is no such entry or the value is not matching the 00512 // _endpoint_info.internal_endpoint_name. 00513 if(!no_param_update) { 00514 delete_config_parameter(KEY_INTERNAL_ENDPOINT); 00515 set_config_parameter(KEY_INTERNAL_ENDPOINT, (const uint8_t*)_endpoint_info.internal_endpoint_name.c_str(), 00516 (size_t)_endpoint_info.internal_endpoint_name.size()); 00517 } 00518 00519 _callback->registration_process_result(State_Registration_Success); 00520 } 00521 00522 void ConnectorClient::state_registration_failure() 00523 { 00524 assert(_callback != NULL); 00525 // maybe some additional canceling and/or leanup is needed here? 00526 _callback->registration_process_result(State_Registration_Failure); 00527 } 00528 00529 void ConnectorClient::state_unregistered() 00530 { 00531 assert(_callback != NULL); 00532 _callback->registration_process_result(State_Unregistered); 00533 } 00534 00535 void ConnectorClient::bootstrap_done(M2MSecurity *security_object) 00536 { 00537 tr_info("ConnectorClient::bootstrap_done"); 00538 ccs_status_e status = CCS_STATUS_ERROR; 00539 StartupSubStateRegistration state = State_Bootstrap_Success; 00540 if(security_object) { 00541 // Update bootstrap credentials (we could skip this if we knew whether they were updated) 00542 // This will also update the address in case of first to claim 00543 status = set_bootstrap_credentials(security_object); 00544 if (status != CCS_STATUS_SUCCESS) { 00545 // TODO: what now? 00546 tr_error("ConnectorClient::bootstrap_done - couldn't store bootstrap credentials"); 00547 } 00548 00549 // Clear the first to claim flag if it's active 00550 if (is_first_to_claim()) { 00551 status = clear_first_to_claim(); 00552 if (status != CCS_STATUS_SUCCESS) { 00553 // TODO: what now? 00554 tr_error("ConnectorClient::bootstrap_done - couldn't clear first to claim flag!"); 00555 } 00556 } 00557 00558 // Bootstrap might delete m2mserver security object instance completely to force bootstrap 00559 // with new credentials, in that case delete the stored lwm2m credentials as well and re-bootstrap 00560 if (security_object->get_security_instance_id(M2MSecurity::M2MServer) == -1) { 00561 tr_info("ConnectorClient::bootstrap_done() - Clearing lwm2m credentials"); 00562 // delete the old connector credentials when BS sends re-direction. 00563 delete_config_parameter(g_fcc_lwm2m_server_uri_name); 00564 delete_config_certificate(g_fcc_lwm2m_server_ca_certificate_name); 00565 delete_config_certificate(g_fcc_lwm2m_device_certificate_name); 00566 delete_config_private_key(g_fcc_lwm2m_device_private_key_name); 00567 // Start re-bootstrap timer 00568 tr_info("ConnectorClient::bootstrap_done() - Re-directing bootstrap in 100 milliseconds"); 00569 _rebootstrap_timer.start_timer(100, M2MTimerObserver::BootstrapFlowTimer, true); 00570 return; 00571 } 00572 // Bootstrap wrote M2MServer credentials, store them and also update first to claim status if it's configured 00573 else { 00574 tr_info("ConnectorClient::bootstrap_done() - Storing lwm2m credentials"); 00575 status = set_connector_credentials(security_object); 00576 } 00577 } 00578 if (status != CCS_STATUS_SUCCESS) { 00579 internal_event(State_Bootstrap_Failure); 00580 //Failed to store credentials, bootstrap failed 00581 _callback->connector_error(M2MInterface::MemoryFail, ERROR_NO_MEMORY); // Translated to error code ConnectMemoryConnectFail 00582 return; 00583 } else { 00584 tr_error("ConnectorClient::bootstrap_done - set_credentials status %d", status); 00585 } 00586 internal_event(state); 00587 } 00588 00589 void ConnectorClient::object_registered(M2MSecurity *security_object, const M2MServer &server_object) 00590 { 00591 internal_event(State_Registration_Success); 00592 } 00593 00594 void ConnectorClient::object_unregistered(M2MSecurity *server_object) 00595 { 00596 internal_event(State_Unregistered); 00597 } 00598 00599 void ConnectorClient::registration_updated(M2MSecurity *security_object, const M2MServer & server_object) 00600 { 00601 _callback->registration_process_result(State_Registration_Updated); 00602 } 00603 00604 void ConnectorClient::error(M2MInterface::Error error) 00605 { 00606 tr_error("ConnectorClient::error() - error: %d", error); 00607 assert(_callback != NULL); 00608 if (_current_state >= State_Registration_Start && 00609 use_bootstrap() && 00610 (error == M2MInterface::SecureConnectionFailed || 00611 error == M2MInterface::InvalidParameters)) { 00612 tr_info("ConnectorClient::error() - Error during lwm2m registration"); 00613 tr_info("ConnectorClient::error() - Clearing lwm2m credentials"); 00614 // delete the old connector credentials when DTLS handshake fails or 00615 // server rejects the registration. 00616 delete_config_parameter(g_fcc_lwm2m_server_uri_name); 00617 delete_config_certificate(g_fcc_lwm2m_server_ca_certificate_name); 00618 delete_config_certificate(g_fcc_lwm2m_device_certificate_name); 00619 delete_config_private_key(g_fcc_lwm2m_device_private_key_name); 00620 // Delete the lwm2m security instance 00621 int32_t id = _security->get_security_instance_id(M2MSecurity::M2MServer); 00622 if (id >= 0) { 00623 _security->remove_object_instance(id); 00624 } 00625 // Delete bootstrap security instance 00626 id = _security->get_security_instance_id(M2MSecurity::Bootstrap); 00627 if (id >= 0) { 00628 _security->remove_object_instance(id); 00629 } 00630 // Start re-bootstrap timer 00631 tr_info("ConnectorClient::error() - Re-bootstrapping in 100 milliseconds"); 00632 _rebootstrap_timer.start_timer(100, M2MTimerObserver::BootstrapFlowTimer, true); 00633 } 00634 else { 00635 _callback->connector_error(error, _interface->error_description()); 00636 } 00637 } 00638 00639 void ConnectorClient::value_updated(M2MBase *base, M2MBase::BaseType type) 00640 { 00641 assert(_callback != NULL); 00642 _callback->value_updated(base, type); 00643 } 00644 00645 bool ConnectorClient::connector_credentials_available() 00646 { 00647 tr_debug("ConnectorClient::connector_credentials_available"); 00648 const int max_size = 2048; 00649 uint8_t *buffer = (uint8_t*)malloc(max_size); 00650 size_t real_size = 0; 00651 get_config_private_key(g_fcc_lwm2m_device_private_key_name, buffer, max_size, &real_size); 00652 free(buffer); 00653 if (real_size > 0) { 00654 return true; 00655 } 00656 return false; 00657 } 00658 00659 bool ConnectorClient::use_bootstrap() 00660 { 00661 tr_debug("ConnectorClient::use_bootstrap"); 00662 const int max_size = 32; 00663 uint8_t *buffer = (uint8_t*)malloc(max_size); 00664 bool ret = false; 00665 if (buffer != NULL) { 00666 memset(buffer, 0, max_size); 00667 size_t real_size = 0; 00668 ccs_status_e status = get_config_parameter(g_fcc_use_bootstrap_parameter_name, buffer, max_size, &real_size); 00669 if (status == CCS_STATUS_SUCCESS && real_size > 0 && buffer[0] > 0) { 00670 ret = true; 00671 } 00672 free(buffer); 00673 } 00674 return ret; 00675 } 00676 00677 00678 bool ConnectorClient::get_key(const char *key, const char *endpoint, char *&key_name) 00679 { 00680 if(key_name) { 00681 free(key_name); 00682 key_name = NULL; 00683 } 00684 00685 key_name = (char*)malloc(strlen(key)+strlen(endpoint)+1); 00686 if(key_name) { 00687 strcpy(key_name, key); 00688 strcat(key_name, endpoint); 00689 tr_debug("key %s", key_name); 00690 return true; 00691 } 00692 return false; 00693 } 00694 00695 ccs_status_e ConnectorClient::set_connector_credentials(M2MSecurity *security) 00696 { 00697 tr_debug("ConnectorClient::set_connector_credentials"); 00698 ccs_status_e status = CCS_STATUS_ERROR; 00699 00700 const uint8_t *srv_public_key = NULL; 00701 const uint8_t *public_key = NULL; 00702 const uint8_t *sec_key = NULL; 00703 00704 int32_t m2m_id = security->get_security_instance_id(M2MSecurity::M2MServer); 00705 if (m2m_id == -1) { 00706 return status; 00707 } 00708 00709 uint32_t srv_public_key_size = security->resource_value_buffer(M2MSecurity::ServerPublicKey, srv_public_key, m2m_id); 00710 uint32_t public_key_size = security->resource_value_buffer(M2MSecurity::PublicKey, public_key, m2m_id); 00711 uint32_t sec_key_size = security->resource_value_buffer(M2MSecurity::Secretkey, sec_key, m2m_id); 00712 00713 if(srv_public_key && public_key && sec_key) { 00714 // Parse common name 00715 char common_name[64]; 00716 memset(common_name, 0, 64); 00717 if (extract_cn_from_certificate(public_key, public_key_size, common_name)){ 00718 tr_info("ConnectorClient::set_connector_credentials - CN: %s", common_name); 00719 _endpoint_info.internal_endpoint_name = String(common_name); 00720 delete_config_parameter(KEY_INTERNAL_ENDPOINT); 00721 status = set_config_parameter(KEY_INTERNAL_ENDPOINT,(uint8_t*)common_name, strlen(common_name)); 00722 } 00723 00724 if(status == CCS_STATUS_SUCCESS) { 00725 delete_config_certificate(g_fcc_lwm2m_server_ca_certificate_name); 00726 status = set_config_certificate(g_fcc_lwm2m_server_ca_certificate_name, 00727 srv_public_key, 00728 (size_t)srv_public_key_size); 00729 } 00730 if(status == CCS_STATUS_SUCCESS) { 00731 status = set_config_certificate(g_fcc_lwm2m_device_certificate_name, 00732 public_key, 00733 (size_t)public_key_size); 00734 } 00735 if(status == CCS_STATUS_SUCCESS) { 00736 status = set_config_private_key(g_fcc_lwm2m_device_private_key_name, 00737 sec_key, 00738 (size_t)sec_key_size); 00739 } 00740 00741 if(status == CCS_STATUS_SUCCESS) { 00742 delete_config_parameter(KEY_ACCOUNT_ID); 00743 // AccountID optional so don't fail if unable to store 00744 set_config_parameter(KEY_ACCOUNT_ID, 00745 (const uint8_t*)_endpoint_info.account_id.c_str(), 00746 (size_t)_endpoint_info.account_id.size()); 00747 } 00748 if(status == CCS_STATUS_SUCCESS) { 00749 status = set_config_parameter(g_fcc_lwm2m_server_uri_name, 00750 (const uint8_t*)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).c_str(), 00751 (size_t)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).size()); 00752 } 00753 M2MDevice *device = M2MInterfaceFactory::create_device(); 00754 if (device) { 00755 String temp = ""; 00756 uint32_t currenttime = (uint32_t)device->resource_value_int(M2MDevice::CurrentTime, 0); 00757 uint8_t data[4]; 00758 memcpy(data, ¤ttime, 4); 00759 delete_config_parameter(g_fcc_current_time_parameter_name); 00760 set_config_parameter(g_fcc_current_time_parameter_name, data, 4); 00761 00762 temp = device->resource_value_string(M2MDevice::Timezone, 0); 00763 delete_config_parameter(g_fcc_device_time_zone_parameter_name); 00764 set_config_parameter(g_fcc_device_time_zone_parameter_name, (const uint8_t*)temp.c_str(), temp.size()); 00765 00766 temp = device->resource_value_string(M2MDevice::UTCOffset, 0); 00767 delete_config_parameter(g_fcc_offset_from_utc_parameter_name); 00768 set_config_parameter(g_fcc_offset_from_utc_parameter_name, (const uint8_t*)temp.c_str(), temp.size()); 00769 00770 status = CCS_STATUS_SUCCESS; 00771 } 00772 else { 00773 tr_debug("No device object to store!"); 00774 } 00775 } 00776 00777 return status; 00778 } 00779 00780 ccs_status_e ConnectorClient::set_bootstrap_credentials(M2MSecurity *security) 00781 { 00782 tr_debug("ConnectorClient::set_bootstrap_credentials"); 00783 ccs_status_e status = CCS_STATUS_ERROR; 00784 00785 const uint8_t *srv_public_key = NULL; 00786 const uint8_t *public_key = NULL; 00787 const uint8_t *sec_key = NULL; 00788 00789 int32_t bs_id = security->get_security_instance_id(M2MSecurity::Bootstrap); 00790 if (bs_id == -1) { 00791 return status; 00792 } 00793 00794 uint32_t srv_public_key_size = security->resource_value_buffer(M2MSecurity::ServerPublicKey, srv_public_key, bs_id); 00795 uint32_t public_key_size = security->resource_value_buffer(M2MSecurity::PublicKey, public_key, bs_id); 00796 uint32_t sec_key_size = security->resource_value_buffer(M2MSecurity::Secretkey, sec_key, bs_id); 00797 00798 if(srv_public_key && public_key && sec_key) { 00799 delete_config_certificate(g_fcc_bootstrap_server_ca_certificate_name); 00800 status = set_config_certificate(g_fcc_bootstrap_server_ca_certificate_name, 00801 srv_public_key, 00802 (size_t)srv_public_key_size); 00803 if(status == CCS_STATUS_SUCCESS) { 00804 delete_config_certificate(g_fcc_bootstrap_device_certificate_name); 00805 status = set_config_certificate(g_fcc_bootstrap_device_certificate_name, 00806 public_key, 00807 (size_t)public_key_size); 00808 } 00809 if(status == CCS_STATUS_SUCCESS) { 00810 delete_config_private_key(g_fcc_bootstrap_device_private_key_name); 00811 status = set_config_private_key(g_fcc_bootstrap_device_private_key_name, 00812 sec_key, 00813 (size_t)sec_key_size); 00814 } 00815 if(status == CCS_STATUS_SUCCESS) { 00816 delete_config_parameter(g_fcc_bootstrap_server_uri_name); 00817 status = set_config_parameter(g_fcc_bootstrap_server_uri_name, 00818 (const uint8_t*)security->resource_value_string(M2MSecurity::M2MServerUri, bs_id).c_str(), 00819 (size_t)security->resource_value_string(M2MSecurity::M2MServerUri, bs_id).size()); 00820 } 00821 } 00822 00823 return status; 00824 } 00825 00826 ccs_status_e ConnectorClient::store_bootstrap_address(M2MSecurity *security) 00827 { 00828 tr_debug("ConnectorClient::store_bootstrap_address"); 00829 ccs_status_e status = CCS_STATUS_ERROR; 00830 00831 const uint8_t *srv_address = NULL; 00832 int32_t bs_id = security->get_security_instance_id(M2MSecurity::Bootstrap); 00833 if (bs_id == -1) { 00834 return status; 00835 } 00836 00837 uint32_t srv_address_size = security->resource_value_buffer(M2MSecurity::M2MServerUri, srv_address, bs_id); 00838 00839 if(srv_address) { 00840 delete_config_parameter(g_fcc_bootstrap_server_uri_name); 00841 status = set_config_parameter(g_fcc_bootstrap_server_uri_name, 00842 srv_address, 00843 (size_t)srv_address_size); 00844 } 00845 00846 return status; 00847 } 00848 00849 ccs_status_e ConnectorClient::clear_first_to_claim() 00850 { 00851 tr_debug("ConnectorClient::clear_first_to_claim"); 00852 return delete_config_parameter(KEY_FIRST_TO_CLAIM); 00853 } 00854 00855 00856 const ConnectorClientEndpointInfo *ConnectorClient::endpoint_info() const 00857 { 00858 return &_endpoint_info; 00859 } 00860 00861 bool ConnectorClient::bootstrap_credentials_stored_in_kcm() 00862 { 00863 size_t real_size = 0; 00864 ccs_status_e success = size_config_parameter(g_fcc_bootstrap_server_uri_name, &real_size); 00865 // Return true if bootstrap uri exists in KCM 00866 if ((success == CCS_STATUS_SUCCESS) && real_size > 0) { 00867 return true; 00868 } else { 00869 return false; 00870 } 00871 } 00872 00873 bool ConnectorClient::is_first_to_claim() 00874 { 00875 size_t real_size = 0; 00876 uint8_t data[4] = {0}; 00877 uint32_t value = 0; 00878 ccs_status_e status = get_config_parameter(KEY_FIRST_TO_CLAIM, data, 4, &real_size); 00879 if (status == CCS_STATUS_SUCCESS) { 00880 memcpy(&value, data, 4); 00881 // Return true if bootstrap uri exists in KCM 00882 if (value == 1) { 00883 return true; 00884 } 00885 } 00886 return false; 00887 } 00888 00889 void ConnectorClient::timer_expired(M2MTimerObserver::Type type) 00890 { 00891 if (type == M2MTimerObserver::BootstrapFlowTimer) { 00892 start_bootstrap(); 00893 } 00894 } 00895 00896 M2MInterface::BindingMode ConnectorClient::transport_mode() 00897 { 00898 #ifdef MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP 00899 return M2MInterface::UDP; 00900 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP 00901 return M2MInterface::TCP; 00902 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE 00903 return M2MInterface::UDP_QUEUE; 00904 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE 00905 return M2MInterface::TCP_QUEUE; 00906 #else 00907 return M2MInterface::UDP; 00908 #endif 00909 }
Generated on Tue Jul 12 2022 19:01:34 by 1.7.2