replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / provisioning / examples / cloudClient.cpp
1 //******************************************************************
2 //
3 // Copyright 2016 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "ocstack.h"
25 #include "logger.h"
26 #include "octhread.h"
27 #include "cathreadpool.h"
28 #include "ocpayload.h"
29 #include "payload_logging.h"
30 #include "ocprovisioningmanager.h"
31
32 #include "utils.h"
33 #include "cloudAuth.h"
34 #include "cloudWrapper.h"
35 #include "OCApi.h"
36 #include "OCCloudProvisioning.hpp"
37
38 #ifdef __unix__
39 #include <unistd.h> //for unlink
40 #endif
41
42 #define TAG "cloudClient"
43 using namespace OC;
44
45 #define DEFAULT_HOST            "127.0.0.1"
46 #define DEFAULT_PORT            OC_MULTICAST_PORT
47 #define DEFAULT_DEVICEID        "6A757374-776F-726B-4465-765575696430"
48 #define DEFAULT_USERID          "6A757374-776F-726B-4465-765575696430"
49 #define DEFAULT_AUTH_PROVIDER   "github"
50 #define DEFAULT_DB_FILE         "./cloud.dat"
51 #define DEFAULT_RESPONSE_WAIT_TIME (10 * 1000000) //10s
52
53 #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"
54
55 static bool fExit = false;
56
57 static OCDevAddr endPoint;
58 static char token[1024];
59 static char authProvider[1024];
60 static const char *fname = DEFAULT_DB_FILE;
61 static uint64_t timeout;
62 static uint16_t g_credId = 0;
63
64 oc_cond cond;
65 oc_mutex mutex;
66 std::string ip(DEFAULT_HOST);
67 OCCloudProvisioning g_cloudProv(ip, (uint16_t)DEFAULT_PORT);
68
69 typedef enum {
70     SIGN_UP       = 1,
71     SIGN_IN       = 2,
72     SIGN_OUT      = 3,
73
74     HOST          = 4,
75     PORT          = 5,
76     DB_FILE       = 6,
77     AUTH_PROVIDER = 7,
78     USE_RSA = 8,
79     SAVE_TRUST_CERT = 9,
80     USE_SECURE_CONN = 10,
81
82     CSR_SIGN      = 19,
83
84     CRL_GET       = 20,
85     CRL_POST      = 21,
86
87     ACL_ID_CREATE = 30,
88     ACL_ID_GET_BY_DEVICE = 31,
89     ACL_ID_DELETE = 32,
90
91     ACL_INDIVIDUAL_GET_INFO = 40,
92     ACL_INDIVIDUAL_UPDATE_ACE = 41,
93     ACL_INDIVIDUAL_DELETE = 42,
94
95     ACL_GROUP_CREATE = 50,
96     ACL_GROUP_FIND   = 51,
97     ACL_GROUP_JOIN   = 52,
98     ACL_GROUP_OBSERVE= 53,
99     ACL_GROUP_DELETE = 54,
100
101     ACL_GROUP_SHARE_DEVICE  = 60,
102     ACL_GROUP_DELETE_DEVICE  = 61,
103     ACL_GROUP_GET_INFO  = 62,
104
105     ACL_POLICY_CHECK_REQUEST = 70,
106
107     ACL_GROUP_INVITE_USER = 80,
108     ACL_GROUP_GET_INVITE  = 81,
109     ACL_GROUP_DELETE_INVITE  = 82,
110     ACL_GROUP_CANCEL_INVITE  = 83,
111
112     EXIT          = 99
113 }CloudRequest;
114
115 void printMenu()
116 {
117     printf("************************************************************\n");
118     printf("****************** Cloud Client Requests *******************\n");
119     printf("************************************************************\n");
120     printf("** AUTHORIZATION\n");
121     printf("** %d - Sign Up request\n", SIGN_UP);
122     printf("** %d - Sign In request\n", SIGN_IN);
123     printf("** %d - Sign Out request\n", SIGN_OUT);
124
125     printf("** SETTINGS \n");
126     printf("** %d - Change default host\n", HOST);
127     printf("** %d - Change default port\n", PORT);
128     printf("** %d - Change default database filename\n", DB_FILE);
129     printf("** %d - Change default auth provider\n", AUTH_PROVIDER);
130     printf("** %d - Change TLS cipher suite to RSA\n", USE_RSA);
131     printf("** %d - Save Trust Cert. Chain into Cred of SVR\n", SAVE_TRUST_CERT);
132     printf("** %d - Change Protocol type (CoAP/CoAPs)\n", USE_SECURE_CONN);
133
134     printf("** CERTIFICATE REQUEST\n");
135     printf("** %d - Certificate Request\n", CSR_SIGN);
136
137     printf("** CRL\n");
138     printf("** %d - CRL GET Request\n", CRL_GET);
139     printf("** %d - CRL POST Request\n", CRL_POST);
140
141     printf("** ACL MANAGER\n");
142     printf("** %d - ACL id create Request\n", ACL_ID_CREATE);
143     printf("** %d - ACL id retrieve by device Request\n", ACL_ID_GET_BY_DEVICE);
144     printf("** %d - ACL id delete Request\n", ACL_ID_DELETE);
145
146     printf("** ACL INDIVIDUAL\n");
147     printf("** %d - ACL individual get info Request\n", ACL_INDIVIDUAL_GET_INFO);
148     printf("** %d - ACL individual update ACE Request\n", ACL_INDIVIDUAL_UPDATE_ACE);
149     printf("** %d - ACL individual delete Request\n", ACL_INDIVIDUAL_DELETE);
150
151     printf("** ACL GROUP MANAGER\n");
152     printf("** %d - ACL Create Group Request\n", ACL_GROUP_CREATE);
153     printf("** %d - ACL Find Group Request\n", ACL_GROUP_FIND);
154     printf("** %d - ACL Join to invited Group Request\n", ACL_GROUP_JOIN);
155     printf("** %d - ACL Observe Group Request\n", ACL_GROUP_OBSERVE);
156     printf("** %d - ACL Delete Group Request\n", ACL_GROUP_DELETE);
157
158     printf("** ACL INDIVIDUAL GROUP\n");
159     printf("** %d - ACL Share device into Group Request\n", ACL_GROUP_SHARE_DEVICE);
160     printf("** %d - ACL Delete device from Group Request\n", ACL_GROUP_DELETE_DEVICE);
161     printf("** %d - ACL Get Group Info Request\n", ACL_GROUP_GET_INFO);
162
163     printf("** ACL POLICY ENFORCEMENT\n");
164     printf("** %d - ACL Check Permissions Request\n", ACL_POLICY_CHECK_REQUEST);
165
166     printf("** ACL MEMBER INVITATION\n");
167     printf("** %d - ACL Invite user to group Request\n", ACL_GROUP_INVITE_USER);
168     printf("** %d - ACL Retrieve invitation Request\n", ACL_GROUP_GET_INVITE);
169     printf("** %d - ACL Delete invitation Request\n", ACL_GROUP_DELETE_INVITE);
170     printf("** %d - ACL Cancel invitation Request\n", ACL_GROUP_CANCEL_INVITE);
171
172     printf("** EXIT\n");
173     printf("** %d - Exit cloud client\n\n", EXIT);
174     printf("************************************************************\n");
175
176     printf(">> Enter Menu number:\n");
177 }
178
179 /**
180  * This is default callback to all requests
181  * Used to sync with main menu
182  *
183  * @param[in] ctx          context
184  * @param[in] result       result
185  * @param[in] data         data
186  */
187 void handleCB(void* ctx, OCStackResult result, void* data)
188 {
189     OC_UNUSED(ctx);
190     OC_UNUSED(data);
191
192     printf("Cloud request Result is == %d", result);
193     oc_mutex_lock(mutex);
194     oc_cond_signal(cond);
195     oc_mutex_unlock(mutex);
196 }
197
198 void handleCB1(OCStackResult result, void *data)
199 {
200     OC_UNUSED(data);
201
202     printf("Cloud request Result is == %d", result);
203     oc_mutex_lock(mutex);
204     oc_cond_signal(cond);
205     oc_mutex_unlock(mutex);
206 }
207
208 void handleCB2(OCStackResult result, std::string data)
209 {
210     printf("Cloud request Result is == %d", result);
211     printf("ACL ID for the device is == %s", data.c_str());
212
213     oc_mutex_lock(mutex);
214     oc_cond_signal(cond);
215     oc_mutex_unlock(mutex);
216 }
217
218 static int saveTrustCert(void)
219 {
220     OCStackResult res = OC_STACK_ERROR;
221     OIC_LOG(INFO, TAG, "Save Trust Cert. Chain into Cred of SVR");
222
223     ByteArray trustCertChainArray = {0, 0};
224
225     FILE *fp = fopen("rootca.crt", "rb+");
226
227     if (fp)
228     {
229         size_t fsize;
230         if (fseeko(fp, 0, SEEK_END) == 0 && (fsize = ftello(fp)) > 0)
231         {
232             trustCertChainArray.data = (uint8_t*)OICCalloc(1, fsize);
233             trustCertChainArray.len = fsize;
234             if (NULL == trustCertChainArray.data)
235             {
236                 OIC_LOG(ERROR,TAG,"Failed to allocate memory");
237                 fclose(fp);
238                 return res;
239             }
240             rewind(fp);
241             if (fsize != fread(trustCertChainArray.data, 1, fsize, fp))
242             {
243                 OIC_LOG(ERROR, TAG, "Certiface not read completely");
244             }
245         }
246         fclose(fp);
247     }
248     OIC_LOG_BUFFER(DEBUG, TAG, trustCertChainArray.data, trustCertChainArray.len);
249
250     res = OCSaveTrustCertChain(trustCertChainArray.data, trustCertChainArray.len, OIC_ENCODING_PEM,&g_credId);
251
252     if(OC_STACK_OK != res)
253     {
254         OIC_LOG(ERROR, TAG, "OCSaveTrustCertChainBin API error");
255         return res;
256     }
257     OIC_LOG_V(INFO, TAG, "CredId of Saved Trust Cert. Chain into Cred of SVR : %d.\n", g_credId);
258
259     return res;
260 }
261
262 static void userRequests(void *data)
263 {
264     (void) data;
265     //defaults
266     memset(token, 0, sizeof(token));
267     memset(authProvider, 0, sizeof(authProvider));
268     strncpy(authProvider, DEFAULT_AUTH_PROVIDER, sizeof(authProvider));
269     memset(&endPoint, 0, sizeof(endPoint));
270     strncpy(endPoint.addr, DEFAULT_HOST, sizeof(endPoint.addr));
271     endPoint.port = DEFAULT_PORT;
272
273     mutex = oc_mutex_new();
274     cond = oc_cond_new();
275
276     while (false == fExit)
277     {
278         OCStackResult res = OC_STACK_ERROR;
279         timeout = DEFAULT_RESPONSE_WAIT_TIME;
280         //startup report
281         printf("-----------------------------------------------------------\n");
282         printf("Connecting to: %s:%d\n", endPoint.addr, endPoint.port);
283         printf("via auth provider: %s\n", authProvider);
284         printf("srv file: %s\n", fname);
285         printf("CoAP prefix: %s\n", DEFAULT_PREFIX);
286         printf("-----------------------------------------------------------\n");
287
288         printMenu();
289
290         int request = 0;
291
292         for (int ret = 0; 1 != ret; )
293         {
294             ret = scanf("%d", &request);
295             for( ; 0x20 <= getchar(); );
296         }
297
298         switch (request)
299         {
300         case SIGN_UP:
301             if (0 == strncmp(authProvider, DEFAULT_AUTH_PROVIDER, sizeof(authProvider)))
302             {
303                 printf("Paste to browser %s and get auth code\n", GITHUB_AUTH_LINK);
304             }
305             readString(token, sizeof(token), "auth token", "check link above");
306             res = CloudSignUp(&endPoint, authProvider, token, handleCloudSignUpResponse);
307             break;
308         case SIGN_IN:
309             res = CloudSignIn(&endPoint, handleCloudSignInResponse);
310             break;
311         case SIGN_OUT:
312             res = CloudSignOut(&endPoint, handleCloudSignOutResponse);
313             break;
314         case HOST:
315             {
316                 readString(endPoint.addr, sizeof(endPoint.addr), "host ip address", DEFAULT_HOST);
317                 std::string str(endPoint.addr);
318                 g_cloudProv.setIpAddr(str);
319                 break;
320             }
321         case PORT:
322         {
323             char example[8];
324             snprintf(example, sizeof(example), "%d", DEFAULT_PORT);
325             int tmp = 0;
326             readInteger(&tmp, "port number", example);
327             endPoint.port = tmp;
328             g_cloudProv.setPort((uint16_t)tmp);
329         }
330         break;
331         case CRL_GET:
332             res = OCWrapperGetCRL( g_cloudProv, handleCB1);
333             break;
334         case CRL_POST:
335             res = OCWrapperPostCRL( g_cloudProv, handleCB1);
336             break;
337         case ACL_GROUP_CREATE:
338             res = OCWrapperAclCreateGroup(&endPoint, handleCB);
339             break;
340         case ACL_GROUP_FIND:
341             res = OCWrapperAclFindMyGroup(&endPoint, handleCB);
342             break;
343         case ACL_GROUP_DELETE:
344             res = OCWrapperAclDeleteGroup(&endPoint, handleCB);
345             break;
346         case ACL_GROUP_JOIN:
347             res = OCWrapperAclJoinToInvitedGroup(&endPoint, handleCB);
348             break;
349         case ACL_GROUP_OBSERVE:
350             res = OCWrapperAclObserveGroup(&endPoint, handleCB);
351             break;
352         case ACL_GROUP_SHARE_DEVICE:
353             res = OCWrapperAclShareDeviceIntoGroup(&endPoint, handleCB);
354             break;
355         case ACL_GROUP_DELETE_DEVICE:
356             res = OCWrapperAclDeleteDeviceFromGroup(&endPoint, handleCB);
357             break;
358         case ACL_GROUP_GET_INFO:
359             res = OCWrapperAclGroupGetInfo(&endPoint, handleCB);
360             break;
361         case ACL_GROUP_INVITE_USER:
362             res = OCWrapperAclInviteUser(&endPoint, handleCB);
363             break;
364         case ACL_GROUP_GET_INVITE:
365             res = OCWrapperAclGetInvitation(&endPoint, handleCB);
366             break;
367         case ACL_GROUP_DELETE_INVITE:
368             res = OCWrapperAclDeleteInvitation(&endPoint, handleCB);
369             break;
370         case ACL_GROUP_CANCEL_INVITE:
371             res = OCWrapperAclCancelInvitation(&endPoint, handleCB);
372             break;
373         case ACL_POLICY_CHECK_REQUEST:
374             res = OCWrapperAclPolicyCheck(&endPoint, handleCB);
375             break;
376         case ACL_ID_GET_BY_DEVICE:
377             res = OCWrapperAclIdGetByDevice( g_cloudProv, handleCB2);
378             break;
379         case ACL_ID_CREATE:
380             res = OCWrapperAclIdCreate(&endPoint, handleCB);
381             break;
382         case ACL_ID_DELETE:
383             res = OCWrapperAclIdDelete(&endPoint, handleCB);
384             break;
385         case ACL_INDIVIDUAL_GET_INFO:
386             res = OCWrapperAclIndividualGetInfo( g_cloudProv, handleCB1);
387             break;
388         case ACL_INDIVIDUAL_UPDATE_ACE:
389             res = OCWrapperAclIndividualUpdateAce(&endPoint, handleCB);
390             break;
391         case ACL_INDIVIDUAL_DELETE:
392             res = OCWrapperAclIndividualDelete(&endPoint, handleCB);
393             break;
394         case CSR_SIGN:
395             res = OCWrapperCertificateIssueRequest( g_cloudProv, handleCB1);
396             break;
397         case USE_RSA:
398             res = CAManager::setCipherSuite(0x35, OC_ADAPTER_TCP);
399             break;
400         case SAVE_TRUST_CERT:
401             saveTrustCert();
402             break;
403         case USE_SECURE_CONN:
404         {
405             int tmp = 0;
406             readInteger(&tmp, "CoAP protocol type", "0 - non-secure, 1 - secure");
407             setCoapPrefix(0 == tmp ? false : true);
408         }
409             break;
410         case EXIT:
411             oc_mutex_free(mutex);
412             oc_cond_free(cond);
413             fExit = true;
414             break;
415         default:
416             printf(">> Entered Wrong Menu Number. Please Enter Again\n\n");
417             break;
418         }
419
420         //if requests were sent then wait response
421         if (res == OC_STACK_OK)
422         {
423             oc_mutex_lock(mutex);
424             oc_cond_wait_for(cond, mutex, timeout);
425             oc_mutex_unlock(mutex);
426         }
427     }
428
429
430 }
431
432 FILE* server_fopen(const char *path, const char *mode)
433 {
434     OC_UNUSED(path);
435     return fopen(fname, mode);
436 }
437
438 /**
439  * Check file accessibility
440  *
441  * @param[in] name        file path
442  * @return true           if check was successful
443  */
444 static bool checkConfig(const char *name)
445 {
446     FILE* file = fopen(name, "rb");
447
448     if (file)
449     {
450         fclose(file);
451         return true;
452     }
453     return false;
454 }
455
456 static void printUsage(char *name)
457 {
458     printf("Wrong arguments count!\n");
459     printf("Usage : %s <database_filename>\n", name);
460     printf("Examples : 1) %s 2) %s cloud.dat\n", name, name);
461 }
462
463 //==============================================================
464 int main(int argc, char *argv[])
465 {
466     OC_UNUSED(argc);
467     OC_UNUSED(argv);
468
469     if (2 == argc)
470     {
471         fname = argv[1];
472
473         if (!checkConfig(fname))
474         {
475             OIC_LOG_V(ERROR, TAG, "Can't open database file %s, exit!", fname);
476             return -1;
477         }
478     }
479     else if (argc > 2)
480     {
481         printUsage(argv[0]);
482     }
483
484     //Initialize Persistent Storage for SVR database
485     OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink, NULL, NULL};
486
487     OCRegisterPersistentStorageHandler(&ps);
488
489     OCMode stackMode = OC_CLIENT_SERVER;
490     if (OCInit(NULL, 0, stackMode) != OC_STACK_OK)
491     {
492         OIC_LOG(ERROR, TAG, "OCStack init error, exit\n");
493         return 1;
494     }
495
496     ca_thread_pool_t g_threadPoolHandle = NULL;
497     CAResult_t res = ca_thread_pool_init(1, &g_threadPoolHandle);
498     if (CA_STATUS_OK != res)
499     {
500         OIC_LOG(ERROR, TAG, "thread pool initialize error.");
501         return res;
502     }
503
504     res = ca_thread_pool_add_task(g_threadPoolHandle, userRequests, NULL, NULL);
505     if (CA_STATUS_OK != res)
506     {
507         OIC_LOG(ERROR, TAG, "thread pool add task error.");
508         goto error;
509     }
510
511     while(false == fExit)
512     {
513         if (OCProcess() != OC_STACK_OK)
514         {
515             OIC_LOG(ERROR, TAG,"OCProcess process error, exit\n");
516             return 2;
517         }
518     }
519
520     if (OCStop() != OC_STACK_OK)
521     {
522         OIC_LOG(ERROR, TAG, "OCStop process error\n");
523     }
524
525     error:
526     if (g_threadPoolHandle)
527     {
528         ca_thread_pool_free(g_threadPoolHandle);
529     }
530
531     return 0;
532 }