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 }