IOT-1583: Removing /W3 warning from resource/csdk/security.
[iotivity.git] / resource / provisioning / examples / cloudAuth.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
21 #include "octypes.h"
22 #include "logger.h"
23 #include "payload_logging.h"
24 #include "ocstack.h"
25 #include "ocpayload.h"
26 //#include "psinterface.h"
27 #include "securevirtualresourcetypes.h"
28 #include "doxmresource.h"
29 #include "oic_malloc.h"
30 #include "oic_string.h"
31 #include "srmutility.h"
32 #include "pmutility.h"
33 #include "credresource.h"
34 #include "payload_logging.h"
35
36 #include "utils.h"
37 #include "cloudAuth.h"
38
39 #define TAG "cloudAuth"
40
41 #define LOGIN_OK 4
42
43 #define MAX_URI_QUERY MAX_URI_LENGTH + MAX_QUERY_LENGTH
44
45 typedef struct
46 {
47     char *accesstoken;
48     char *refreshtoken;
49     char *tokentype;
50     int64_t expiresin;
51     char *uid;
52     char *redirecturi;
53     char *certificate;
54     char *sid;
55 } sessionObject_t;
56
57 static sessionObject_t sessionObject = {0,0,0,0,0,0,0,0};
58
59 extern void handleCB(void* ctx, OCStackResult result, void* data);
60
61 /**
62  * Session free function
63  *
64  * @return  OCStackResult application result
65  */
66 void SessionFree()
67 {
68     if (sessionObject.accesstoken)  OICFree(sessionObject.accesstoken);
69     if (sessionObject.refreshtoken) OICFree(sessionObject.refreshtoken);
70     if (sessionObject.tokentype)    OICFree(sessionObject.tokentype);
71     if (sessionObject.uid)          OICFree(sessionObject.uid);
72     if (sessionObject.redirecturi)  OICFree(sessionObject.redirecturi);
73     if (sessionObject.certificate)  OICFree(sessionObject.certificate);
74     if (sessionObject.sid)          OICFree(sessionObject.sid);
75
76     memset(&sessionObject, 0, sizeof(sessionObject_t));
77 }
78
79 /**
80  * Session init function
81  *
82  * @param[in] sessionObject session data
83  * @return  OCStackResult application result
84  */
85 OCStackResult SessionInit()
86 {
87     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
88
89     SessionFree();
90
91     OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
92
93     return OC_STACK_OK;
94 }
95
96 /**
97  * Session parse payload
98  *
99  * @param[in] payload
100  * @param[in] sessionObject session data
101  * @return  OCStackResult application result
102  */
103 OCStackResult SessionParsePayload(OCRepPayload *payload)
104 {
105     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
106
107     VERIFY_NOT_NULL(TAG, payload, ERROR);
108
109     SessionInit();
110
111     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
112                                    &sessionObject.accesstoken))
113     {
114         OIC_LOG(ERROR, TAG, "Can't get: accesstoken");
115     }
116     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REFRESH_TOKEN,
117                                    &sessionObject.refreshtoken))
118     {
119         OIC_LOG(ERROR, TAG, "Can't get: refreshtoken");
120     }
121     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_TOKEN_TYPE,
122                                    &sessionObject.tokentype))
123     {
124         OIC_LOG(ERROR, TAG, "Can't get: tokentype");
125     }
126     if (!OCRepPayloadGetPropInt(payload, OC_RSRVD_EXPIRES_IN,
127                                 &(sessionObject.expiresin)))
128     {
129         OIC_LOG(ERROR, TAG, "Can't get: expiresin");
130     }
131     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_USER_UUID,
132                                    &sessionObject.uid))
133     {
134         OIC_LOG(ERROR, TAG, "Can't get: uid");
135     }
136     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REDIRECT_URI,
137                                    &sessionObject.redirecturi))
138     {
139         OIC_LOG(ERROR, TAG, "Can't get: redirecturi");
140     }
141     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_CERTIFICATE,
142                                    &sessionObject.certificate))
143     {
144         OIC_LOG(ERROR, TAG, "Can't get: certificate");
145     }
146     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_SUBJECT_ID,
147                                    &sessionObject.sid))
148     {
149         OIC_LOG(ERROR, TAG, "Can't get: sid");
150     }
151
152     OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
153 exit:
154     return OC_STACK_OK;
155 }
156
157 /**
158  * Cloud login handler
159  *
160  * @param[in] response  login response
161  */
162 OCStackApplicationResult handleCloudSignUpResponse(void *ctx,
163                                                           OCDoHandle handle,
164                                                           OCClientResponse *response)
165 {
166     OC_UNUSED(ctx);
167     OC_UNUSED(handle);
168
169     if (!response)
170     {
171         OIC_LOG(ERROR, TAG, "Received NULL response!");
172         goto exit;
173     }
174
175     if (response->payload)
176     {
177         OIC_LOG(ERROR, TAG, "Payload received");
178         OIC_LOG_PAYLOAD(DEBUG, response->payload);
179     }
180
181     if (response->result != LOGIN_OK)
182     {
183         OIC_LOG_V(ERROR, TAG, "Login error: %d",response->result);
184     }
185     else
186     {
187         OIC_LOG(DEBUG, TAG, "Login successful");
188         SessionParsePayload((OCRepPayload*)response->payload);
189     }
190 exit:
191     handleCB(NULL, OC_STACK_OK, NULL);
192     return OC_STACK_DELETE_TRANSACTION;
193 }
194
195 /**
196  * Cloud authentication
197  *
198  * @param[in] endPoint          cloud host and port
199  * @param[in] authProvider      auth provider
200  * @param[in] authToken         token
201  * @return  OCStackResult application result
202  */
203 OCStackResult
204 CloudSignUp(OCDevAddr *endPoint,
205            const char *authProvider,
206            const char *authToken,
207            OCClientResponseHandler response)
208 {
209     char uri[MAX_URI_LENGTH] = { 0 };
210
211     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
212
213     if (!endPoint || !authProvider || !authToken)
214     {
215         OIC_LOG(ERROR, TAG, "Some of the input params are NULL");
216         return OC_STACK_INVALID_PARAM;
217     }
218
219     char *deviceId = getDeviceId();
220     if (!deviceId)
221     {
222         OIC_LOG(ERROR, TAG, "Can't get the device id");
223         return OC_STACK_ERROR;
224     }
225
226     snprintf(uri, MAX_URI_LENGTH, DEFAULT_QUERY,
227              endPoint->addr, endPoint->port, OC_RSRVD_ACCOUNT_URI);
228
229     OIC_LOG_V(DEBUG, TAG, "Query created: %s", uri);
230
231     OCCallbackData cbData;
232     memset(&cbData, 0, sizeof(OCCallbackData));
233     cbData.cb = response;
234     cbData.context = (void*)handleCloudSignUpResponse;
235
236     OCRepPayload *payload = OCRepPayloadCreate();
237     if (!payload)
238     {
239         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
240         return OC_STACK_NO_MEMORY;
241     }
242
243     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
244     OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHPROVIDER, OICStrdup(authProvider));
245     OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHCODE, OICStrdup(authToken));
246
247     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
248                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
249 }
250
251 /**
252  * Cloud Sign In handler
253  *
254  * @param[in] OCClientResponse  cloud response
255  * @return  OCStackApplicationResult application result
256  */
257 OCStackApplicationResult handleCloudSignInResponse(void *ctx,
258                                                           OCDoHandle handle,
259                                                           OCClientResponse *response)
260 {
261     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
262
263     OC_UNUSED(ctx);
264     OC_UNUSED(handle);
265
266     if (!response)
267     {
268         OIC_LOG(ERROR, TAG, "Received NULL response!");
269         goto exit;
270     }
271
272     if (response->payload)
273     {
274         OIC_LOG(ERROR, TAG, "Payload received");
275         OIC_LOG_PAYLOAD(DEBUG, response->payload);
276     }
277
278     if (response->result < 4 && response->payload)
279     {
280         OIC_LOG_V(ERROR, TAG, "Sign In error: result: %d, payload exist: %s",
281                   response->result, response->payload ? "yes" : "no");
282         goto exit;
283     }
284
285     if (!OCRepPayloadGetPropString((OCRepPayload*)response->payload, OC_RSRVD_USER_UUID,
286                                    &(sessionObject.uid)))
287     {
288         OIC_LOG(ERROR, TAG, "Can't get: uid");
289     }
290
291     if (!OCRepPayloadGetPropInt((OCRepPayload*)response->payload, OC_RSRVD_EXPIRES_IN,
292                                 &(sessionObject.expiresin)))
293     {
294         OIC_LOG(ERROR, TAG, "Cann't get: expiresin");
295     }
296
297     OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
298
299 exit:
300     handleCB(NULL, OC_STACK_OK, NULL);
301     return OC_STACK_DELETE_TRANSACTION;
302 }
303
304 /**
305  * Sign In request function
306  *
307  * @param[in] endPoint          cloud host and port
308  * @return  OCStackResult application result
309  */
310 OCStackResult CloudSignIn(OCDevAddr  *endPoint, OCClientResponseHandler response)
311 {
312     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
313
314     if (!endPoint)
315     {
316         OIC_LOG_V(ERROR, TAG, "%s: endPoint is NULL",__func__);
317         return OC_STACK_INVALID_PARAM;
318     }
319
320     if (!sessionObject.uid)
321     {
322         OIC_LOG_V(ERROR, TAG, "%s: UID is missing. Please run Sign Up first",__func__);
323         return OC_STACK_ERROR;
324     }
325
326     if (!sessionObject.accesstoken)
327     {
328         OIC_LOG_V(ERROR, TAG, "%s: accesstoken is missing. Please run Sign Up first",__func__);
329         return OC_STACK_ERROR;
330     }
331
332     char *deviceId = getDeviceId();
333     if (!deviceId)
334     {
335         OIC_LOG(ERROR, TAG, "Can't get the device id");
336         return OC_STACK_ERROR;
337     }
338
339     OCRepPayload* payload = OCRepPayloadCreate();
340     if (NULL == payload)
341     {
342         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
343         return OC_STACK_NO_MEMORY;
344     }
345
346     OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID, sessionObject.uid);
347     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
348     OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
349                               sessionObject.accesstoken);
350     OCRepPayloadSetPropBool(payload, OC_RSRVD_LOGIN, true);
351
352     char uri[MAX_URI_QUERY] = { 0, };
353     snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
354              endPoint->addr, endPoint->port,
355              OC_RSRVD_ACCOUNT_SESSION_URI);
356
357     OCCallbackData cbData;
358     memset(&cbData, 0, sizeof(OCCallbackData));
359     cbData.cb = response;
360     cbData.context = (void*)handleCloudSignInResponse;
361
362     return OCDoResource(NULL, OC_REST_POST, uri, NULL,
363                        (OCPayload *)payload,
364                        CT_ADAPTER_TCP,
365                        OC_LOW_QOS, &cbData, NULL, 0);
366 }
367 /**
368  * Cloud Sign Out handler
369  *
370  * @param[in] OCClientResponse  cloud response
371  * @return  OCStackApplicationResult application result
372  */
373 OCStackApplicationResult handleCloudSignOutResponse(void *ctx,
374                                                           OCDoHandle handle,
375                                                           OCClientResponse *response)
376 {
377     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
378
379     OC_UNUSED(ctx);
380     OC_UNUSED(handle);
381
382     if (!response)
383     {
384         OIC_LOG(ERROR, TAG, "Received NULL response!");
385         goto exit;
386     }
387
388     if (response->payload)
389     {
390         OIC_LOG(ERROR, TAG, "Payload received");
391         OIC_LOG_PAYLOAD(DEBUG, response->payload);
392     }
393
394     if (response->result < 4 && response->payload)
395     {
396         OIC_LOG_V(ERROR, TAG, "Sign Out error");
397         return OC_STACK_DELETE_TRANSACTION;
398     }
399     else
400     {
401         OIC_LOG_V(ERROR, TAG, "Sign Out OK");
402     }
403
404     OIC_LOG_V(DEBUG, TAG, "OUT: %s", __func__);
405
406 exit:
407     handleCB(NULL, OC_STACK_OK, NULL);
408     return OC_STACK_DELETE_TRANSACTION;
409 }
410 /**
411  * Sign In request function
412  *
413  * @param[in] endPoint          cloud host and port
414  * @return  OCStackResult application result
415  */
416 OCStackResult CloudSignOut(OCDevAddr  *endPoint, OCClientResponseHandler response)
417 {
418     OIC_LOG_V(DEBUG, TAG, "IN: %s", __func__);
419
420     if (!endPoint)
421     {
422         OIC_LOG_V(ERROR, TAG, "%s: endPoint is NULL",__func__);
423         return OC_STACK_INVALID_PARAM;
424     }
425
426     char *deviceId = getDeviceId();
427     if (!deviceId)
428     {
429         OIC_LOG(ERROR, TAG, "Cann't get the device id");
430         return OC_STACK_ERROR;
431     }
432
433     OCRepPayload* payload = OCRepPayloadCreate();
434     if (!payload)
435     {
436         OIC_LOG(ERROR, TAG, "Failed to memory allocation");
437         return OC_STACK_NO_MEMORY;
438     }
439
440     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
441     OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
442                               sessionObject.accesstoken);
443     OCRepPayloadSetPropBool(payload, OC_RSRVD_LOGIN, false);
444
445     char uri[MAX_URI_QUERY] = { 0, };
446     snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
447              endPoint->addr, endPoint->port,
448              OC_RSRVD_ACCOUNT_SESSION_URI);
449
450     OCCallbackData cbData;
451     memset(&cbData, 0, sizeof(OCCallbackData));
452     cbData.cb = response;
453     cbData.context = (void*)handleCloudSignOutResponse;
454
455     return OCDoResource(NULL, OC_REST_POST, uri, NULL,
456                        (OCPayload *)payload,
457                        CT_ADAPTER_TCP,
458                        OC_LOW_QOS, &cbData, NULL, 0);
459 }
460