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