1 //******************************************************************
3 // Copyright 2016 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
28 #include "cathreadpool.h"
29 #include "ocpayload.h"
30 #include "securevirtualresourcetypes.h"
31 #include "payload_logging.h"
32 #include "aclresource.h"
33 #include "crlresource.h"
34 #include "ocprovisioningmanager.h"
35 #include "casecurityinterface.h"
36 #include "mbedtls/ssl_ciphersuites.h"
37 #include "pkix_interface.h"
38 #include "../hw_emul/hw_interface.h"
41 #include "cloudAuth.h"
42 #include "cloudCommon.h"
43 #include "cloudWrapper.h"
44 #include "cloudDiscovery.h"
47 #include <unistd.h> //for unlink
50 #define TAG "cloudCommon"
52 #define DEFAULT_HOST "10.113.68.85"//"127.0.0.1"
53 #define DEFAULT_PORT OC_MULTICAST_PORT
54 #define DEFAULT_AUTH_PROVIDER "github"
55 #define DEFAULT_DB_FILE "./cloud.dat"
56 #define DEFAULT_RESPONSE_WAIT_TIME (10 * 1000000) //10s
58 #define GITHUB_AUTH_LINK "https://github.com/login?return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3Dea9c18f540323b0213d0%26redirect_uri%3Dhttp%253A%252F%252Fwww.example.com%252Foauth_callback%252F"
60 #define CLIENT_ONLY(mode) if (OC_SERVER == (mode)) { wrongRequest(); sendDataToServer = false; break; }
62 static bool fExit = false;
64 static ca_thread_pool_t g_threadPoolHandle = NULL;
65 static OCDevAddr endPoint;
66 static char token[1024] = "";
67 static char authProvider[1024] = DEFAULT_AUTH_PROVIDER;
68 static char *fname = DEFAULT_DB_FILE;
69 static uint64_t timeout;
70 static uint16_t g_credId = 0;
73 static oc_mutex mutex;
87 CONFIG_SELF_OWNERSHIP = 11,
88 SECURE_STORAGE_HW_EMULATION = 12,
101 ACL_ID_GET_BY_DEVICE = 31,
104 ACL_INDIVIDUAL_GET_INFO = 40,
105 ACL_INDIVIDUAL_UPDATE_ACE = 41,
106 ACL_INDIVIDUAL_UPDATE = 42,
107 ACL_INDIVIDUAL_DELETE = 43,
108 ACL_INDIVIDUAL_DELETE_ACE = 44,
110 ACL_GROUP_CREATE = 50,
113 ACL_GROUP_OBSERVE= 53,
114 ACL_GROUP_DELETE = 54,
116 ACL_GROUP_SHARE_DEVICE = 60,
117 ACL_GROUP_DELETE_DEVICE = 61,
118 ACL_GROUP_GET_INFO = 62,
120 ACL_POLICY_CHECK_REQUEST = 70,
122 ACL_GROUP_INVITE_USER = 80,
123 ACL_GROUP_GET_INVITE = 81,
124 ACL_GROUP_DELETE_INVITE = 82,
125 ACL_GROUP_CANCEL_INVITE = 83,
130 static void printMenu(OCMode mode)
132 char *title = "Client";
133 if (OC_SERVER == mode)
137 printf("************************************************************\n");
138 printf("****************** Cloud %s Requests *******************\n", title);
139 printf("************************************************************\n");
140 printf("** AUTHORIZATION\n");
141 printf("** %d - Sign Up request\n", SIGN_UP);
142 printf("** %d - Sign In request\n", SIGN_IN);
143 printf("** %d - Sign Out request\n", SIGN_OUT);
145 printf("** SETTINGS \n");
146 printf("** %d - Change default host\n", HOST);
147 printf("** %d - Change default port\n", PORT);
148 printf("** %d - Change default database filename\n", DB_FILE);
149 printf("** %d - Change default auth provider\n", AUTH_PROVIDER);
150 printf("** %d - Change TLS cipher suite (ECDSA/RSA)\n", USE_RSA);
151 printf("** %d - Save Trust Cert. Chain into Cred of SVR\n", SAVE_TRUST_CERT);
152 printf("** %d - Change Protocol type (CoAP/CoAPs)\n", USE_SECURE_CONN);
153 printf("** %d - Configure SVRdb as Self-OwnerShip\n", CONFIG_SELF_OWNERSHIP);
154 printf("** %d - Configure Secure Storage HW Emulation\n", SECURE_STORAGE_HW_EMULATION);
156 if (OC_CLIENT == mode)
158 printf("** DISCOVERY\n");
159 printf("** %d - Start Discovery\n", DISCOVERY);
160 printf("** %d - Get Request\n", GET);
161 printf("** %d - Put Request\n", PUT);
162 printf("** %d - Post Request\n", POST);
165 printf("** CERTIFICATE REQUEST\n");
166 printf("** %d - Certificate Request\n", CSR_SIGN);
169 printf("** %d - CRL GET Request\n", CRL_GET);
170 printf("** %d - CRL POST Request\n", CRL_POST);
172 printf("** ACL MANAGER\n");
173 printf("** %d - ACL id create Request\n", ACL_ID_CREATE);
174 printf("** %d - ACL id retrieve by device Request\n", ACL_ID_GET_BY_DEVICE);
175 printf("** %d - ACL id delete Request\n", ACL_ID_DELETE);
177 printf("** ACL INDIVIDUAL\n");
178 printf("** %d - ACL individual get info Request\n", ACL_INDIVIDUAL_GET_INFO);
179 printf("** %d - ACL individual update ACE Request\n", ACL_INDIVIDUAL_UPDATE_ACE);
180 printf("** %d - ACL individual update Request\n", ACL_INDIVIDUAL_UPDATE);
181 printf("** %d - ACL individual delete Request\n", ACL_INDIVIDUAL_DELETE);
182 printf("** %d - ACL individual delete ACE Request\n", ACL_INDIVIDUAL_DELETE_ACE);
184 printf("** ACL GROUP MANAGER\n");
185 printf("** %d - ACL Create Group Request\n", ACL_GROUP_CREATE);
186 printf("** %d - ACL Find Group Request\n", ACL_GROUP_FIND);
187 printf("** %d - ACL Join to invited Group Request\n", ACL_GROUP_JOIN);
188 printf("** %d - ACL Observe Group Request\n", ACL_GROUP_OBSERVE);
189 printf("** %d - ACL Delete Group Request\n", ACL_GROUP_DELETE);
191 printf("** ACL INDIVIDUAL GROUP\n");
192 printf("** %d - ACL Share device into Group Request\n", ACL_GROUP_SHARE_DEVICE);
193 printf("** %d - ACL Delete device from Group Request\n", ACL_GROUP_DELETE_DEVICE);
194 printf("** %d - ACL Get Group Info Request\n", ACL_GROUP_GET_INFO);
196 printf("** ACL POLICY ENFORCEMENT\n");
197 printf("** %d - ACL Check Permissions Request\n", ACL_POLICY_CHECK_REQUEST);
199 printf("** ACL MEMBER INVITATION\n");
200 printf("** %d - ACL Invite user to group Request\n", ACL_GROUP_INVITE_USER);
201 printf("** %d - ACL Retrieve invitation Request\n", ACL_GROUP_GET_INVITE);
202 printf("** %d - ACL Delete invitation Request\n", ACL_GROUP_DELETE_INVITE);
203 printf("** %d - ACL Cancel invitation Request\n", ACL_GROUP_CANCEL_INVITE);
206 printf("** %d - Exit cloud %s\n", EXIT, title);
207 printf("************************************************************\n");
210 void unlockMenu(void *data)
216 oc_mutex_lock(mutex);
217 oc_cond_signal(cond);
218 oc_mutex_unlock(mutex);
223 * This is default callback to all requests
224 * Used to sync with main menu
226 * @param[in] ctx context
227 * @param[in] result result
228 * @param[in] data data
230 static void handleCB(void* ctx, OCStackResult result, void* data)
235 OIC_LOG_V(INFO, TAG, "%s: Received result = %d", __func__, result);
241 * This function prints Acl id and calls default callback function handleCB()
243 * @param[in] ctx context
244 * @param[in] result result
245 * @param[in] aclId acl id
247 static void handleAclIdCB(void* ctx, OCStackResult result, void* aclId)
249 OIC_LOG_V(INFO, TAG, "Received Acl id = %s", (char *)aclId);
250 handleCB(ctx, result, aclId);
255 * This function prints group id and calls default callback function handleCB()
257 * @param[in] ctx context
258 * @param[in] result result
259 * @param[in] groupId group id
261 static void handleAclCreateGroupCB(void* ctx, OCStackResult result, void* groupId)
263 OIC_LOG_V(INFO, TAG, "Received gid = %s", (char *)groupId);
264 handleCB(ctx, result, groupId);
269 * This function prints group policy and calls default callback function handleCB()
271 * @param[in] ctx context
272 * @param[in] result result
273 * @param[in] gp group policy
275 static void handleAclPolicyCheckCB(void* ctx, OCStackResult result, void* gp)
277 OIC_LOG_V(INFO, TAG, "Received gp = %s", (char *)gp);
278 handleCB(ctx, result, gp);
283 * This function prints received acl and calls default callback function handleCB()
285 * @param[in] ctx context
286 * @param[in] result result
289 static void handleAclIndividualGetInfoCB(void* ctx, OCStackResult result, void* acl)
291 printACL((OicSecAcl_t* )acl);
292 handleCB(ctx, result, acl);
293 //can't delete acl here because its ACE's were added to gAcl
294 //TODO: changes in aclresources.c required to fix that
298 * This function prints received group id list and calls default callback function handleCB()
300 * @param[in] ctx context
301 * @param[in] result result
302 * @param[in] gidList group id list
304 static void handleAclFindMyGroupCB(void* ctx, OCStackResult result, void* gidList)
306 printStringArray((stringArray_t *)gidList);
307 handleCB(ctx, result, gidList);
308 clearStringArray((stringArray_t *)gidList);
312 * This function prints received acl and calls default callback function handleCB()
314 * @param[in] ctx context
315 * @param[in] result result
318 static void handleGetCrlCB(void* ctx, OCStackResult result, void* crl)
320 printCrl((OicSecCrl_t *)crl);
321 handleCB(ctx, result, crl);
322 DeleteCrl((OicSecCrl_t *)crl);
326 * This function prints received invitation response and calls default callback function handleCB()
328 * @param[in] ctx context
329 * @param[in] result result
330 * @param[in] invite invitation response (it has inviteResponse_t* type)
332 static void handleAclGetInvitationCB(void* ctx, OCStackResult result, void* invite)
334 printInviteResponse((inviteResponse_t *)invite);
335 handleCB(ctx, result, invite);
336 clearInviteResponse((inviteResponse_t *)invite);
340 static OCStackResult saveTrustCert(void)
342 OCStackResult res = OC_STACK_ERROR;
343 OIC_LOG(INFO, TAG, "Save Trust Cert. Chain into Cred of SVR");
345 OCByteString trustCertChainArray = {0, 0};
346 const char *filename = "rootca.crt";
348 if (!readFile(filename, &trustCertChainArray))
350 OIC_LOG_V(ERROR, TAG, "Can't read %s file", filename);
351 OICFree(trustCertChainArray.bytes);
352 return OC_STACK_ERROR;
354 OIC_LOG_BUFFER(DEBUG, TAG, trustCertChainArray.bytes, trustCertChainArray.len);
356 res = OCSaveTrustCertChain(trustCertChainArray.bytes, trustCertChainArray.len, OIC_ENCODING_PEM,&g_credId);
358 if (OC_STACK_OK != res)
360 OIC_LOG(ERROR, TAG, "OCSaveTrustCertChain API error");
364 OIC_LOG_V(INFO, TAG, "CredId of Saved Trust Cert. Chain into Cred of SVR : %d.\n", g_credId);
366 OICFree(trustCertChainArray.bytes);
371 static OCStackResult configSelfOwnership(void)
373 OCStackResult res = OC_STACK_ERROR;
374 OIC_LOG(INFO, TAG, "Configures SVR DB as self-ownership.");
376 res = OCConfigSelfOwnership();
378 if (OC_STACK_OK != res)
380 OIC_LOG(ERROR, TAG, "OCConfigSelfOwnership API error. Please check SVR DB");
384 OIC_LOG(INFO, TAG, "Success to configures SVR DB as self-ownership");
390 static void configSecureStorageHwEmulation()
392 OIC_LOG(INFO, TAG, "Enable Secure Storage HW Emulation");
394 printf(" Enter Own Certificate File Path[~4095]: ");
395 char cert_filepath[4096] = {0,};
396 for(int ret=0; 1!=ret; )
398 ret = scanf("%255s", cert_filepath);
399 for( ; 0x20<=getchar(); ); // for removing overflow garbages
400 // '0x20<=code' is character region
403 printf(" Enter Private Key File Path[~4095]: ");
404 char key_filepath[4096] = {0,};
405 for(int ret=0; 1!=ret; )
407 ret = scanf("%255s", key_filepath);
408 for( ; 0x20<=getchar(); ); // for removing overflow garbages
409 // '0x20<=code' is character region
412 printf(" Enter Password for Key Password[~31][Press (Enter) to not set]: ");
414 for(int i=0; i < 31; i++)
416 pwd[i] = (char)getchar();
429 if (0 != SSemulSetCertkeyFilepath(cert_filepath, key_filepath, pwd))
431 OIC_LOG(ERROR, TAG, " Fail to set cert/key file path");
435 if (0 != SetHwPkixCallbacks(HWGetKeyContext,
437 HWGetOwnCertificateChain,
440 OIC_LOG(ERROR, TAG, " Fail to regist HW Pkix Callbacks");
443 OIC_LOG(INFO, TAG, " Success to regist HW Pkix Callbacks");
446 static void wrongRequest()
448 printf(">> Entered Wrong Menu Number. Please Enter Again\n\n");
451 static void userRequests(void *data)
455 OIC_LOG(ERROR, TAG, "Received NULL data");
459 OCMode mode = *(OCMode*)data;
461 memset(&endPoint, 0, sizeof(endPoint));
462 strncpy(endPoint.addr, DEFAULT_HOST, sizeof(endPoint.addr));
463 endPoint.port = DEFAULT_PORT;
465 mutex = oc_mutex_new();
466 cond = oc_cond_new();
468 while (false == fExit)
470 OCStackResult res = OC_STACK_ERROR;
471 bool sendDataToServer = true;
472 timeout = DEFAULT_RESPONSE_WAIT_TIME;
474 printf("-----------------------------------------------------------\n");
475 printf("Connecting to: %s:%d\n", endPoint.addr, endPoint.port);
476 printf("via auth provider: %s\n", authProvider);
477 printf("srv file: %s\n", fname);
478 printf("CoAP prefix: %s\n", DEFAULT_PREFIX);
479 printf("-----------------------------------------------------------\n");
484 readInteger(&request, "Menu number", "see above");
489 if (0 == strncmp(authProvider, DEFAULT_AUTH_PROVIDER, sizeof(authProvider)))
491 printf("Paste to browser %s and get auth code\n", GITHUB_AUTH_LINK);
493 readString(token, sizeof(token), "auth token", "check link above");
494 res = CloudSignUp(&endPoint, authProvider, token);
497 res = CloudSignIn(&endPoint);
500 res = CloudSignOut(&endPoint);
503 readString(endPoint.addr, sizeof(endPoint.addr), "host ip address", DEFAULT_HOST);
504 sendDataToServer = false;
509 snprintf(example, sizeof(example), "%d", DEFAULT_PORT);
511 readInteger(&tmp, "port number", example);
513 sendDataToServer = false;
517 res = OCWrapperGetCRL(&endPoint, handleGetCrlCB);
520 res = OCWrapperPostCRL(&endPoint, handleCB);
522 case ACL_GROUP_CREATE:
523 res = OCWrapperAclCreateGroup(&endPoint, handleAclCreateGroupCB);
526 res = OCWrapperAclFindMyGroup(&endPoint, handleAclFindMyGroupCB);
528 case ACL_GROUP_DELETE:
529 res = OCWrapperAclDeleteGroup(&endPoint, handleCB);
532 res = OCWrapperAclJoinToInvitedGroup(&endPoint, handleCB);
534 case ACL_GROUP_OBSERVE:
535 res = OCWrapperAclObserveGroup(&endPoint, handleCB);
537 case ACL_GROUP_SHARE_DEVICE:
538 res = OCWrapperAclShareDeviceIntoGroup(&endPoint, handleCB);
540 case ACL_GROUP_DELETE_DEVICE:
541 res = OCWrapperAclDeleteDeviceFromGroup(&endPoint, handleCB);
543 case ACL_GROUP_GET_INFO:
544 res = OCWrapperAclGroupGetInfo(&endPoint, handleCB);
546 case ACL_GROUP_INVITE_USER:
547 res = OCWrapperAclInviteUser(&endPoint, handleCB);
549 case ACL_GROUP_GET_INVITE:
550 res = OCWrapperAclGetInvitation(&endPoint, handleAclGetInvitationCB);
552 case ACL_GROUP_DELETE_INVITE:
553 res = OCWrapperAclDeleteInvitation(&endPoint, handleCB);
555 case ACL_GROUP_CANCEL_INVITE:
556 res = OCWrapperAclCancelInvitation(&endPoint, handleCB);
558 case ACL_POLICY_CHECK_REQUEST:
559 res = OCWrapperAclPolicyCheck(&endPoint, handleAclPolicyCheckCB);
561 case ACL_ID_GET_BY_DEVICE:
562 res = OCWrapperAclIdGetByDevice(&endPoint, handleAclIdCB);
565 res = OCWrapperAclIdCreate(&endPoint, handleAclIdCB);
568 res = OCWrapperAclIdDelete(&endPoint, handleCB);
570 case ACL_INDIVIDUAL_GET_INFO:
571 res = OCWrapperAclIndividualGetInfo(&endPoint, handleAclIndividualGetInfoCB);
573 case ACL_INDIVIDUAL_UPDATE_ACE:
574 res = OCWrapperAclIndividualUpdateAce(&endPoint, handleCB);
576 case ACL_INDIVIDUAL_UPDATE:
577 res = OCWrapperAclIndividualUpdate(&endPoint, handleCB);
579 case ACL_INDIVIDUAL_DELETE:
580 res = OCWrapperAclIndividualDelete(&endPoint, handleCB);
582 case ACL_INDIVIDUAL_DELETE_ACE:
583 res = OCWrapperAclIndividualDeleteAce(&endPoint, handleCB);
586 res = OCWrapperCertificateIssueRequest(&endPoint, handleCB);
590 res = InitDiscovery();
594 res = InitRequest(OC_REST_GET);
598 res= InitRequest(OC_REST_PUT);
602 res= InitRequest(OC_REST_POST);
607 readInteger(&tmp, "Select Cipher Suite", "0 - ECDSA, other - RSA");
608 uint16_t cipher = tmp? MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256:
609 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
610 if (CA_STATUS_OK != CASelectCipherSuite(cipher, CA_ADAPTER_TCP))
612 OIC_LOG(ERROR, TAG, "CASelectCipherSuite returned an error");
614 sendDataToServer = false;
617 case SAVE_TRUST_CERT:
619 sendDataToServer = false;
621 case USE_SECURE_CONN:
624 readInteger(&tmp, "CoAP protocol type", "0 - non-secure, 1 - secure");
625 setCoapPrefix(0 == tmp ? false : true);
626 sendDataToServer = false;
629 case CONFIG_SELF_OWNERSHIP:
630 configSelfOwnership();
631 sendDataToServer = false;
633 case SECURE_STORAGE_HW_EMULATION:
634 configSecureStorageHwEmulation();
635 sendDataToServer = false;
638 oc_mutex_free(mutex);
641 sendDataToServer = false;
645 sendDataToServer = false;
649 //if requests were sent then wait response
650 if (sendDataToServer)
652 if (OC_STACK_OK == res)
654 oc_mutex_lock(mutex);
655 oc_cond_wait_for(cond, mutex, timeout);
656 oc_mutex_unlock(mutex);
660 OIC_LOG_V(ERROR, TAG, "Request returned an error %d", res);
666 FILE* server_fopen(const char *path, const char *mode)
669 return fopen(fname, mode);
673 * Check file accessibility
675 * @param[in] name file path
676 * @return true if check was successful
678 static bool checkConfig(const char *name)
680 FILE* file = fopen(name, "rb");
690 static void printUsage(char *name)
692 printf("Wrong arguments count!\n");
693 printf("Usage : %s <database_filename>\n", name);
694 printf("Examples : 1) %s 2) %s cloud.dat\n", name, name);
697 bool parseCommandLineArguments(int argc, char *argv[])
704 if (!checkConfig(fname))
706 OIC_LOG_V(ERROR, TAG, "Can't open database file %s, exit!", fname);
718 OCStackResult initPersistentStorage()
720 //Initialize Persistent Storage for SVR database
721 static OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink, NULL, NULL};
723 return OCRegisterPersistentStorageHandler(&ps);
726 OCStackResult startRequestsThread(OCMode *mode)
728 CAResult_t res = ca_thread_pool_init(1, &g_threadPoolHandle);
729 if (CA_STATUS_OK != res)
731 OIC_LOG(ERROR, TAG, "thread pool initialize error.");
735 res = ca_thread_pool_add_task(g_threadPoolHandle, userRequests, mode, NULL);
736 if (CA_STATUS_OK != res)
738 OIC_LOG(ERROR, TAG, "thread pool add task error.");
739 ca_thread_pool_free(g_threadPoolHandle);
744 OCStackResult initProcess(OCMode mode)
746 return OCInit(NULL, 0, mode);
751 struct timespec timeout;
753 timeout.tv_nsec = 100000000L;
755 while(false == fExit)
757 if (OCProcess() != OC_STACK_OK)
759 OIC_LOG(ERROR, TAG,"OCProcess process error, exit\n");
762 nanosleep(&timeout, NULL);
765 if (OCStop() != OC_STACK_OK)
767 OIC_LOG(ERROR, TAG, "OCStop process error\n");
771 void freeThreadResources()
773 if (g_threadPoolHandle)
775 ca_thread_pool_free(g_threadPoolHandle);