replace : iotivity -> iotivity-sec
[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 "pmutility.h"
32 #include "credresource.h"
33 #include "payload_logging.h"
34 #include "cacommonutil.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 = {NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL};
59
60 /**
61  * Session free function
62  *
63  * @return  OCStackResult application result
64  */
65 static void SessionFree()
66 {
67     OICFree(sessionObject.accesstoken);
68     OICFree(sessionObject.refreshtoken);
69     OICFree(sessionObject.tokentype);
70     OICFree(sessionObject.uid);
71     OICFree(sessionObject.redirecturi);
72     OICFree(sessionObject.certificate);
73     OICFree(sessionObject.sid);
74
75     memset(&sessionObject, 0, sizeof(sessionObject_t));
76 }
77
78 /**
79  * Session parse payload
80  *
81  * @param[in] payload
82  * @param[in] sessionObject session data
83  * @return  OCStackResult application result
84  */
85 static OCStackResult SessionParsePayload(OCRepPayload *payload)
86 {
87     VERIFY_NON_NULL_RET(payload, TAG, "NULL payload", OC_STACK_ERROR);
88
89     SessionFree();
90
91     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_ACCESS_TOKEN,
92                                    &sessionObject.accesstoken))
93     {
94         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_ACCESS_TOKEN);
95     }
96     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REFRESH_TOKEN,
97                                    &sessionObject.refreshtoken))
98     {
99         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_REFRESH_TOKEN);
100     }
101     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_TOKEN_TYPE,
102                                    &sessionObject.tokentype))
103     {
104         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_TOKEN_TYPE);
105     }
106     int64_t tmp = 0;
107     if (!OCRepPayloadGetPropInt(payload, OC_RSRVD_EXPIRES_IN, &tmp))
108     {
109         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_EXPIRES_IN);
110     }
111     else
112     {
113         sessionObject.expiresin = tmp;
114     }
115     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_USER_UUID,
116                                    &sessionObject.uid))
117     {
118         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_USER_UUID);
119     }
120     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REDIRECT_URI,
121                                    &sessionObject.redirecturi))
122     {
123         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_REDIRECT_URI);
124     }
125     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_CERTIFICATE,
126                                    &sessionObject.certificate))
127     {
128         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_CERTIFICATE);
129     }
130     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_SUBJECT_ID,
131                                    &sessionObject.sid))
132     {
133         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_SUBJECT_ID);
134     }
135
136     return OC_STACK_OK;
137 }
138
139 /**
140  * Sends Sign Up request to cloud
141  *
142  * @param[in] ctx                    context
143  * @param[in] handle                 handle
144  * @param[in] response               response from peer
145  * @return  OCStackApplicationResult application result
146  */
147 static OCStackApplicationResult handleCloudSignUpResponse(void *ctx,
148                                                           OCDoHandle handle,
149                                                           OCClientResponse *response)
150 {
151     OC_UNUSED(ctx);
152     OC_UNUSED(handle);
153
154     VERIFY_NON_NULL_RET(response, TAG, "Received NULL response", OC_STACK_DELETE_TRANSACTION);
155
156     if (response->payload)
157     {
158         OIC_LOG(INFO, TAG, "Payload received");
159         OIC_LOG_PAYLOAD(DEBUG, response->payload);
160     }
161
162     if (response->result != LOGIN_OK)
163     {
164         OIC_LOG_V(ERROR, TAG, "Login error: %d",response->result);
165     }
166     else
167     {
168         SessionParsePayload((OCRepPayload*)response->payload);
169         OIC_LOG(INFO, TAG, "Sign Up OK");
170     }
171
172     return OC_STACK_DELETE_TRANSACTION;
173 }
174
175 OCStackResult CloudSignUp(const OCDevAddr *endPoint,
176                           const char *authProvider,
177                           const char *authToken)
178 {
179     char uri[MAX_URI_LENGTH] = { 0 };
180
181     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
182     VERIFY_NON_NULL_RET(authProvider, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
183     VERIFY_NON_NULL_RET(authToken, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
184
185     char *deviceId = getDeviceId();
186     VERIFY_NON_NULL_RET(deviceId, TAG, "Can't get the device id", OC_STACK_ERROR);
187
188     snprintf(uri, MAX_URI_LENGTH, DEFAULT_QUERY,
189              endPoint->addr, endPoint->port, OC_RSRVD_ACCOUNT_URI);
190
191     OCCallbackData cbData;
192     memset(&cbData, 0, sizeof(OCCallbackData));
193     cbData.cb = handleCloudSignUpResponse;
194     cbData.cd = unlockMenu;
195
196     OCRepPayload *payload = OCRepPayloadCreate();
197     VERIFY_NON_NULL_RET(payload, TAG, "Failed to allocate payload", OC_STACK_NO_MEMORY);
198
199     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
200     OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHPROVIDER, authProvider);
201     OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHCODE, authToken);
202
203     OICFree(deviceId);
204
205     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
206                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
207 }
208
209 /**
210  * Sends Sign In request to cloud
211  *
212  * @param[in] ctx                    context
213  * @param[in] handle                 handle
214  * @param[in] response               response from peer
215  * @return  OCStackApplicationResult application result
216  */
217 static OCStackApplicationResult handleCloudSignInResponse(void *ctx,
218                                                           OCDoHandle handle,
219                                                           OCClientResponse *response)
220 {
221     OC_UNUSED(ctx);
222     OC_UNUSED(handle);
223
224     VERIFY_NON_NULL_RET(response, TAG, "Received NULL response", OC_STACK_DELETE_TRANSACTION);
225
226     if (response->payload)
227     {
228         OIC_LOG(INFO, TAG, "Payload received");
229         OIC_LOG_PAYLOAD(DEBUG, response->payload);
230     }
231
232     if (response->result != LOGIN_OK)
233     {
234         OIC_LOG_V(ERROR, TAG, "Sign In error: result: %d", response->result);
235         return OC_STACK_DELETE_TRANSACTION;
236     }
237
238     sessionObject.expiresin = 0;
239     int64_t tmp = 0;
240     if (!OCRepPayloadGetPropInt((OCRepPayload*)response->payload, OC_RSRVD_EXPIRES_IN, &tmp))
241     {
242         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_EXPIRES_IN);
243     }
244     else
245     {
246         sessionObject.expiresin = tmp;
247     }
248
249     OIC_LOG(INFO, TAG, "Sign In OK");
250
251     return OC_STACK_DELETE_TRANSACTION;
252 }
253
254 static OCStackApplicationResult handleCloudSignOutResponse(void *ctx,
255                                                            OCDoHandle handle,
256                                                            OCClientResponse *response)
257 {
258     OC_UNUSED(ctx);
259     OC_UNUSED(handle);
260
261     VERIFY_NON_NULL_RET(response, TAG, "Received NULL response", OC_STACK_DELETE_TRANSACTION);
262
263     if (response->payload)
264     {
265         OIC_LOG(INFO, TAG, "Payload received");
266         OIC_LOG_PAYLOAD(DEBUG, response->payload);
267     }
268
269     if (response->result != LOGIN_OK)
270     {
271         OIC_LOG(ERROR, TAG, "Sign Out error");
272         return OC_STACK_DELETE_TRANSACTION;
273     }
274
275     OIC_LOG(INFO, TAG, "Sign Out OK");
276
277     return OC_STACK_DELETE_TRANSACTION;
278 }
279
280 /**
281  * Sends Sign In/Out request to cloud
282  *
283  * @param[in] endPoint               peer endPoint
284  * @param[in] signIn                 is it Sign In or Sign Out request
285  * @return  OCStackApplicationResult application result
286  */
287 static OCStackResult CloudSign(const OCDevAddr *endPoint, bool signIn)
288 {
289     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
290     VERIFY_NON_NULL_RET(sessionObject.uid, TAG,
291                         "UID is missing. Please run Sign Up first", OC_STACK_ERROR);
292     VERIFY_NON_NULL_RET(sessionObject.accesstoken, TAG,
293                         "accesstoken is missing. Please run Sign Up first", OC_STACK_ERROR);
294
295     char *deviceId = getDeviceId();
296     VERIFY_NON_NULL_RET(deviceId, TAG, "Can't get the device id", OC_STACK_ERROR);
297
298     OCRepPayload* payload = OCRepPayloadCreate();
299     VERIFY_NON_NULL_RET(payload, TAG, "Failed to allocate payload", OC_STACK_NO_MEMORY);
300
301     OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID, sessionObject.uid);
302     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
303     OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN, sessionObject.accesstoken);
304     OCRepPayloadSetPropBool(payload, OC_RSRVD_LOGIN, signIn);
305
306     OICFree(deviceId);
307
308     char uri[MAX_URI_QUERY] = { 0 };
309     snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
310              endPoint->addr, endPoint->port,
311              OC_RSRVD_ACCOUNT_SESSION_URI);
312
313     OCCallbackData cbData;
314     memset(&cbData, 0, sizeof(OCCallbackData));
315     cbData.cb = signIn? handleCloudSignInResponse : handleCloudSignOutResponse;
316     cbData.cd = unlockMenu;
317
318     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
319                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
320 }
321
322 OCStackResult CloudSignIn(const OCDevAddr *endPoint)
323 {
324     return CloudSign(endPoint, true);
325 }
326
327 OCStackResult CloudSignOut(const OCDevAddr *endPoint)
328 {
329     return CloudSign(endPoint, false);
330 }
331