IOT-1583: Removing /W3 warning from resource/csdk/security.
[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     int64_t  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     if (!OCRepPayloadGetPropInt(payload, OC_RSRVD_EXPIRES_IN, &(sessionObject.expiresin)))
107     {
108         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_EXPIRES_IN);
109     }
110     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_USER_UUID,
111                                    &sessionObject.uid))
112     {
113         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_USER_UUID);
114     }
115     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_REDIRECT_URI,
116                                    &sessionObject.redirecturi))
117     {
118         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_REDIRECT_URI);
119     }
120     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_CERTIFICATE,
121                                    &sessionObject.certificate))
122     {
123         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_CERTIFICATE);
124     }
125     if (!OCRepPayloadGetPropString(payload, OC_RSRVD_SUBJECT_ID,
126                                    &sessionObject.sid))
127     {
128         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_SUBJECT_ID);
129     }
130
131     return OC_STACK_OK;
132 }
133
134 /**
135  * Sends Sign Up request to cloud
136  *
137  * @param[in] ctx                    context
138  * @param[in] handle                 handle
139  * @param[in] response               response from peer
140  * @return  OCStackApplicationResult application result
141  */
142 static OCStackApplicationResult handleCloudSignUpResponse(void *ctx,
143                                                           OCDoHandle handle,
144                                                           OCClientResponse *response)
145 {
146     OC_UNUSED(ctx);
147     OC_UNUSED(handle);
148
149     VERIFY_NON_NULL_RET(response, TAG, "Received NULL response", OC_STACK_DELETE_TRANSACTION);
150
151     if (response->payload)
152     {
153         OIC_LOG(INFO, TAG, "Payload received");
154         OIC_LOG_PAYLOAD(DEBUG, response->payload);
155     }
156
157     if (response->result != LOGIN_OK)
158     {
159         OIC_LOG_V(ERROR, TAG, "Login error: %d",response->result);
160     }
161     else
162     {
163         SessionParsePayload((OCRepPayload*)response->payload);
164         OIC_LOG(INFO, TAG, "Sign Up OK");
165     }
166
167     return OC_STACK_DELETE_TRANSACTION;
168 }
169
170 OCStackResult CloudSignUp(const OCDevAddr *endPoint,
171                           const char *authProvider,
172                           const char *authToken)
173 {
174     char uri[MAX_URI_LENGTH] = { 0 };
175
176     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
177     VERIFY_NON_NULL_RET(authProvider, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
178     VERIFY_NON_NULL_RET(authToken, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
179
180     char *deviceId = getDeviceId();
181     VERIFY_NON_NULL_RET(deviceId, TAG, "Can't get the device id", OC_STACK_ERROR);
182
183     snprintf(uri, MAX_URI_LENGTH, DEFAULT_QUERY,
184              endPoint->addr, endPoint->port, OC_RSRVD_ACCOUNT_URI);
185
186     OCCallbackData cbData;
187     memset(&cbData, 0, sizeof(OCCallbackData));
188     cbData.cb = handleCloudSignUpResponse;
189     cbData.cd = unlockMenu;
190
191     OCRepPayload *payload = OCRepPayloadCreate();
192     VERIFY_NON_NULL_RET(payload, TAG, "Failed to allocate payload", OC_STACK_NO_MEMORY);
193
194     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
195     OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHPROVIDER, authProvider);
196     OCRepPayloadSetPropString(payload, OC_RSRVD_AUTHCODE, authToken);
197
198     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
199                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
200 }
201
202 /**
203  * Sends Sign In request to cloud
204  *
205  * @param[in] ctx                    context
206  * @param[in] handle                 handle
207  * @param[in] response               response from peer
208  * @return  OCStackApplicationResult application result
209  */
210 static OCStackApplicationResult handleCloudSignInResponse(void *ctx,
211                                                           OCDoHandle handle,
212                                                           OCClientResponse *response)
213 {
214     OC_UNUSED(ctx);
215     OC_UNUSED(handle);
216
217     VERIFY_NON_NULL_RET(response, TAG, "Received NULL response", OC_STACK_DELETE_TRANSACTION);
218
219     if (response->payload)
220     {
221         OIC_LOG(INFO, TAG, "Payload received");
222         OIC_LOG_PAYLOAD(DEBUG, response->payload);
223     }
224
225     if (response->result != LOGIN_OK)
226     {
227         OIC_LOG_V(ERROR, TAG, "Sign In error: result: %d", response->result);
228         return OC_STACK_DELETE_TRANSACTION;
229     }
230
231     sessionObject.expiresin = 0;
232     if (!OCRepPayloadGetPropInt((OCRepPayload*)response->payload, OC_RSRVD_EXPIRES_IN, &(sessionObject.expiresin)))
233     {
234         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_EXPIRES_IN);
235     }
236
237     OIC_LOG(INFO, TAG, "Sign In OK");
238
239     return OC_STACK_DELETE_TRANSACTION;
240 }
241
242 static OCStackApplicationResult handleCloudSignOutResponse(void *ctx,
243                                                            OCDoHandle handle,
244                                                            OCClientResponse *response)
245 {
246     OC_UNUSED(ctx);
247     OC_UNUSED(handle);
248
249     VERIFY_NON_NULL_RET(response, TAG, "Received NULL response", OC_STACK_DELETE_TRANSACTION);
250
251     if (response->payload)
252     {
253         OIC_LOG(INFO, TAG, "Payload received");
254         OIC_LOG_PAYLOAD(DEBUG, response->payload);
255     }
256
257     if (response->result != LOGIN_OK)
258     {
259         OIC_LOG(ERROR, TAG, "Sign Out error");
260         return OC_STACK_DELETE_TRANSACTION;
261     }
262
263     OIC_LOG(INFO, TAG, "Sign Out OK");
264
265     return OC_STACK_DELETE_TRANSACTION;
266 }
267
268 /**
269  * Sends Sign In/Out request to cloud
270  *
271  * @param[in] endPoint               peer endPoint
272  * @param[in] signIn                 is it Sign In or Sign Out request
273  * @return  OCStackApplicationResult application result
274  */
275 static OCStackResult CloudSign(const OCDevAddr *endPoint, bool signIn)
276 {
277     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
278     VERIFY_NON_NULL_RET(sessionObject.uid, TAG,
279                         "UID is missing. Please run Sign Up first", OC_STACK_ERROR);
280     VERIFY_NON_NULL_RET(sessionObject.accesstoken, TAG,
281                         "accesstoken is missing. Please run Sign Up first", OC_STACK_ERROR);
282
283     char *deviceId = getDeviceId();
284     VERIFY_NON_NULL_RET(deviceId, TAG, "Can't get the device id", OC_STACK_ERROR);
285
286     OCRepPayload* payload = OCRepPayloadCreate();
287     VERIFY_NON_NULL_RET(payload, TAG, "Failed to allocate payload", OC_STACK_NO_MEMORY);
288
289     OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID, sessionObject.uid);
290     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
291     OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN, sessionObject.accesstoken);
292     OCRepPayloadSetPropBool(payload, OC_RSRVD_LOGIN, signIn);
293
294     char uri[MAX_URI_QUERY] = { 0 };
295     snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
296              endPoint->addr, endPoint->port,
297              OC_RSRVD_ACCOUNT_SESSION_URI);
298
299     OCCallbackData cbData;
300     memset(&cbData, 0, sizeof(OCCallbackData));
301     cbData.cb = signIn? handleCloudSignInResponse : handleCloudSignOutResponse;
302     cbData.cd = unlockMenu;
303
304     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
305                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
306 }
307
308 OCStackResult CloudSignIn(const OCDevAddr *endPoint)
309 {
310     return CloudSign(endPoint, true);
311 }
312
313 OCStackResult CloudSignOut(const OCDevAddr *endPoint)
314 {
315     return CloudSign(endPoint, false);
316 }
317