a14a7e5f59845317e62006ccd9486a7a289dac35
[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     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
204                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
205 }
206
207 /**
208  * Sends Sign In request to cloud
209  *
210  * @param[in] ctx                    context
211  * @param[in] handle                 handle
212  * @param[in] response               response from peer
213  * @return  OCStackApplicationResult application result
214  */
215 static OCStackApplicationResult handleCloudSignInResponse(void *ctx,
216                                                           OCDoHandle handle,
217                                                           OCClientResponse *response)
218 {
219     OC_UNUSED(ctx);
220     OC_UNUSED(handle);
221
222     VERIFY_NON_NULL_RET(response, TAG, "Received NULL response", OC_STACK_DELETE_TRANSACTION);
223
224     if (response->payload)
225     {
226         OIC_LOG(INFO, TAG, "Payload received");
227         OIC_LOG_PAYLOAD(DEBUG, response->payload);
228     }
229
230     if (response->result != LOGIN_OK)
231     {
232         OIC_LOG_V(ERROR, TAG, "Sign In error: result: %d", response->result);
233         return OC_STACK_DELETE_TRANSACTION;
234     }
235
236     sessionObject.expiresin = 0;
237     int64_t tmp = 0;
238     if (!OCRepPayloadGetPropInt((OCRepPayload*)response->payload, OC_RSRVD_EXPIRES_IN, &tmp))
239     {
240         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_EXPIRES_IN);
241     }
242     else
243     {
244         sessionObject.expiresin = tmp;
245     }
246
247     OIC_LOG(INFO, TAG, "Sign In OK");
248
249     return OC_STACK_DELETE_TRANSACTION;
250 }
251
252 static OCStackApplicationResult handleCloudSignOutResponse(void *ctx,
253                                                            OCDoHandle handle,
254                                                            OCClientResponse *response)
255 {
256     OC_UNUSED(ctx);
257     OC_UNUSED(handle);
258
259     VERIFY_NON_NULL_RET(response, TAG, "Received NULL response", OC_STACK_DELETE_TRANSACTION);
260
261     if (response->payload)
262     {
263         OIC_LOG(INFO, TAG, "Payload received");
264         OIC_LOG_PAYLOAD(DEBUG, response->payload);
265     }
266
267     if (response->result != LOGIN_OK)
268     {
269         OIC_LOG(ERROR, TAG, "Sign Out error");
270         return OC_STACK_DELETE_TRANSACTION;
271     }
272
273     OIC_LOG(INFO, TAG, "Sign Out OK");
274
275     return OC_STACK_DELETE_TRANSACTION;
276 }
277
278 /**
279  * Sends Sign In/Out request to cloud
280  *
281  * @param[in] endPoint               peer endPoint
282  * @param[in] signIn                 is it Sign In or Sign Out request
283  * @return  OCStackApplicationResult application result
284  */
285 static OCStackResult CloudSign(const OCDevAddr *endPoint, bool signIn)
286 {
287     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endPoint", OC_STACK_INVALID_PARAM);
288     VERIFY_NON_NULL_RET(sessionObject.uid, TAG,
289                         "UID is missing. Please run Sign Up first", OC_STACK_ERROR);
290     VERIFY_NON_NULL_RET(sessionObject.accesstoken, TAG,
291                         "accesstoken is missing. Please run Sign Up first", OC_STACK_ERROR);
292
293     char *deviceId = getDeviceId();
294     VERIFY_NON_NULL_RET(deviceId, TAG, "Can't get the device id", OC_STACK_ERROR);
295
296     OCRepPayload* payload = OCRepPayloadCreate();
297     VERIFY_NON_NULL_RET(payload, TAG, "Failed to allocate payload", OC_STACK_NO_MEMORY);
298
299     OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID, sessionObject.uid);
300     OCRepPayloadSetPropString(payload, OC_RSRVD_DEVICE_ID, deviceId);
301     OCRepPayloadSetPropString(payload, OC_RSRVD_ACCESS_TOKEN, sessionObject.accesstoken);
302     OCRepPayloadSetPropBool(payload, OC_RSRVD_LOGIN, signIn);
303
304     char uri[MAX_URI_QUERY] = { 0 };
305     snprintf(uri, MAX_URI_QUERY, DEFAULT_QUERY,
306              endPoint->addr, endPoint->port,
307              OC_RSRVD_ACCOUNT_SESSION_URI);
308
309     OCCallbackData cbData;
310     memset(&cbData, 0, sizeof(OCCallbackData));
311     cbData.cb = signIn? handleCloudSignInResponse : handleCloudSignOutResponse;
312     cbData.cd = unlockMenu;
313
314     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
315                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
316 }
317
318 OCStackResult CloudSignIn(const OCDevAddr *endPoint)
319 {
320     return CloudSign(endPoint, true);
321 }
322
323 OCStackResult CloudSignOut(const OCDevAddr *endPoint)
324 {
325     return CloudSign(endPoint, false);
326 }
327