• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "idm_session.h"
17 
18 #include <inttypes.h>
19 #include "securec.h"
20 
21 #include "adaptor_algorithm.h"
22 #include "adaptor_log.h"
23 #include "adaptor_memory.h"
24 #include "adaptor_time.h"
25 #include "coauth.h"
26 #include "linked_list.h"
27 
28 #define SESSION_VALIDITY_PERIOD (10 * 60 * 1000)
29 #define MAX_CHALLENGE_GENERATION_TIMES 5
30 
31 #ifdef IAM_TEST_ENABLE
32 #define IAM_STATIC
33 #else
34 #define IAM_STATIC static
35 #endif
36 
37 // User IDM session information.
38 struct SessionInfo {
39     int32_t userId;
40     uint32_t authType;
41     uint64_t time;
42     uint64_t validAuthTokenTime;
43     uint8_t challenge[CHALLENGE_LEN];
44     uint64_t scheduleId;
45     bool isUpdate;
46     bool isScheduleValid;
47 } *g_session;
48 
IsSessionExist(void)49 IAM_STATIC bool IsSessionExist(void)
50 {
51     if (g_session == NULL) {
52         LOG_INFO("the session does not exist");
53         return false;
54     }
55     return true;
56 }
57 
GenerateChallenge(uint8_t * challenge,uint32_t challengeLen)58 IAM_STATIC ResultCode GenerateChallenge(uint8_t *challenge, uint32_t challengeLen)
59 {
60     for (uint32_t i = 0; i < MAX_CHALLENGE_GENERATION_TIMES; ++i) {
61         if (SecureRandom(challenge, challengeLen) != RESULT_SUCCESS) {
62             LOG_ERROR("get challenge failed");
63             return RESULT_GENERAL_ERROR;
64         }
65         for (uint32_t j = 0; j < challengeLen; j++) {
66             if (challenge[j] != 0) {
67                 return RESULT_SUCCESS;
68             }
69         }
70         LOG_INFO("challenge is invalid, get again.");
71     }
72     LOG_ERROR("a rare failture");
73     return RESULT_GENERAL_ERROR;
74 }
75 
OpenEditSession(int32_t userId,uint8_t * challenge,uint32_t challengeLen)76 ResultCode OpenEditSession(int32_t userId, uint8_t *challenge, uint32_t challengeLen)
77 {
78     if (challenge == NULL || challengeLen != CHALLENGE_LEN) {
79         LOG_ERROR("challenge is null");
80         return RESULT_BAD_PARAM;
81     }
82     (void)memset_s(challenge, CHALLENGE_LEN, 0, CHALLENGE_LEN);
83     if (IsSessionExist()) {
84         (void)CloseEditSession();
85     }
86     g_session = Malloc(sizeof(struct SessionInfo));
87     if (g_session == NULL) {
88         LOG_ERROR("g_session malloc failed");
89         return RESULT_NO_MEMORY;
90     }
91     if (memset_s(g_session, sizeof(struct SessionInfo), 0, sizeof(struct SessionInfo)) != EOK) {
92         LOG_ERROR("g_session set failed");
93         Free(g_session);
94         g_session = NULL;
95         return RESULT_GENERAL_ERROR;
96     }
97     g_session->userId = userId;
98     ResultCode ret = GenerateChallenge(g_session->challenge, CHALLENGE_LEN);
99     if (ret != RESULT_SUCCESS) {
100         LOG_ERROR("failed to generate challenge");
101         Free(g_session);
102         g_session = NULL;
103         return ret;
104     }
105     g_session->time = GetSystemTime();
106     g_session->validAuthTokenTime = g_session->time;
107 
108     if (memcpy_s(challenge, CHALLENGE_LEN, g_session->challenge, CHALLENGE_LEN) != EOK) {
109         LOG_ERROR("failed to copy challenge");
110         Free(g_session);
111         g_session = NULL;
112         return RESULT_BAD_COPY;
113     }
114     g_session->isScheduleValid = false;
115     return RESULT_SUCCESS;
116 }
117 
RefreshValidTokenTime(void)118 void RefreshValidTokenTime(void)
119 {
120     if (!IsSessionExist()) {
121         LOG_ERROR("session is invalid");
122         return;
123     }
124     g_session->validAuthTokenTime = GetSystemTime();
125 }
126 
IsValidTokenTime(uint64_t tokenTime)127 bool IsValidTokenTime(uint64_t tokenTime)
128 {
129     if (!IsSessionExist()) {
130         LOG_ERROR("session is invalid");
131         return false;
132     }
133     return tokenTime >= g_session->validAuthTokenTime;
134 }
135 
CloseEditSession(void)136 ResultCode CloseEditSession(void)
137 {
138     if (!IsSessionExist()) {
139         return RESULT_GENERAL_ERROR;
140     }
141     Free(g_session);
142     g_session = NULL;
143     return RESULT_SUCCESS;
144 }
145 
GetUserId(int32_t * userId)146 ResultCode GetUserId(int32_t *userId)
147 {
148     if (userId == NULL || !IsSessionExist()) {
149         LOG_ERROR("param is invalid");
150         return RESULT_BAD_PARAM;
151     }
152     *userId = g_session->userId;
153     return RESULT_SUCCESS;
154 }
155 
CheckChallenge(uint8_t * challenge,uint32_t challengeLen)156 ResultCode CheckChallenge(uint8_t *challenge, uint32_t challengeLen)
157 {
158     if (challenge == NULL || challengeLen != CHALLENGE_LEN) {
159         LOG_ERROR("param is invalid");
160         return RESULT_BAD_PARAM;
161     }
162     if (!IsSessionExist()) {
163         LOG_ERROR("param is invalid");
164         return RESULT_NEED_INIT;
165     }
166     if (memcmp(challenge, g_session->challenge, CHALLENGE_LEN) != EOK) {
167         LOG_ERROR("failed to compare challenge");
168         return RESULT_BAD_MATCH;
169     }
170     return RESULT_SUCCESS;
171 }
172 
AssociateCoauthSchedule(uint64_t scheduleId,uint32_t authType,bool isUpdate)173 ResultCode AssociateCoauthSchedule(uint64_t scheduleId, uint32_t authType, bool isUpdate)
174 {
175     if (!IsSessionExist()) {
176         return RESULT_NEED_INIT;
177     }
178     g_session->scheduleId = scheduleId;
179     g_session->authType = authType;
180     g_session->isUpdate = isUpdate;
181     g_session->isScheduleValid = true;
182     return RESULT_SUCCESS;
183 }
184 
BreakOffCoauthSchedule(void)185 void BreakOffCoauthSchedule(void)
186 {
187     if (!IsSessionExist()) {
188         return;
189     }
190     if (g_session->isScheduleValid) {
191         RemoveCoAuthSchedule(g_session->scheduleId);
192     }
193     g_session->isScheduleValid = false;
194 }
195 
GetEnrollScheduleInfo(uint64_t * scheduleId,uint32_t * authType)196 ResultCode GetEnrollScheduleInfo(uint64_t *scheduleId, uint32_t *authType)
197 {
198     if (scheduleId == NULL || authType == NULL) {
199         LOG_ERROR("param is null");
200         return RESULT_BAD_PARAM;
201     }
202     if (!IsSessionExist() || g_session->isScheduleValid == false) {
203         return RESULT_NEED_INIT;
204     }
205     *scheduleId = g_session->scheduleId;
206     *authType = g_session->authType;
207     return RESULT_SUCCESS;
208 }
209 
IsSessionTimeout(void)210 bool IsSessionTimeout(void)
211 {
212     if (!IsSessionExist()) {
213         return true;
214     }
215     uint64_t currentTime = GetSystemTime();
216     if (currentTime < g_session->time || currentTime - g_session->time > SESSION_VALIDITY_PERIOD) {
217         LOG_ERROR("timeout, currentTime: %{public}" PRIu64 ", sessionTime: %{public}" PRIu64,
218             currentTime, g_session->time);
219         return true;
220     }
221     return false;
222 }
223 
GetIsUpdate(bool * isUpdate)224 ResultCode GetIsUpdate(bool *isUpdate)
225 {
226     if (isUpdate == NULL) {
227         LOG_ERROR("param is invalid");
228         return RESULT_BAD_PARAM;
229     }
230     if (!IsSessionExist() || g_session->isScheduleValid == false) {
231         LOG_ERROR("session need init");
232         return RESULT_NEED_INIT;
233     }
234     *isUpdate = g_session->isUpdate;
235     return RESULT_SUCCESS;
236 }
237 
IsSessionValid(int32_t userId)238 bool IsSessionValid(int32_t userId)
239 {
240     if (!IsSessionExist() || IsSessionTimeout()) {
241         return false;
242     }
243     if (g_session->userId == userId) {
244         return true;
245     }
246     return false;
247 }