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 "securec.h"
19 #include "adaptor_algorithm.h"
20 #include "adaptor_log.h"
21 #include "adaptor_memory.h"
22 #include "adaptor_time.h"
23 #include "coauth.h"
24 #include "linked_list.h"
25
26 #define SESSION_VALIDITY_PERIOD (10 * 60 * 1000)
27 #define MAX_CHALLENGE_GENERATION_TIMES 5
28
29 // User IDM session information.
30 struct SessionInfo {
31 int32_t userId;
32 uint32_t authType;
33 uint64_t time;
34 uint64_t validAuthTokenTime;
35 uint8_t challenge[CHALLENGE_LEN];
36 uint64_t scheduleId;
37 bool isUpdate;
38 bool isScheduleValid;
39 } *g_session;
40
IsSessionExist()41 static bool IsSessionExist()
42 {
43 if (g_session == NULL) {
44 LOG_INFO("the session does not exist");
45 return false;
46 }
47 return true;
48 }
49
GenerateChallenge(uint8_t * challenge,uint32_t challengeLen)50 static ResultCode GenerateChallenge(uint8_t *challenge, uint32_t challengeLen)
51 {
52 for (uint32_t i = 0; i < MAX_CHALLENGE_GENERATION_TIMES; ++i) {
53 if (SecureRandom(challenge, challengeLen) != RESULT_SUCCESS) {
54 LOG_ERROR("get challenge failed");
55 return RESULT_GENERAL_ERROR;
56 }
57 for (uint32_t j = 0; j < challengeLen; j++) {
58 if (challenge[j] != 0) {
59 return RESULT_SUCCESS;
60 }
61 }
62 LOG_INFO("challenge is invalid, get again.");
63 }
64 LOG_ERROR("a rare failture");
65 return RESULT_GENERAL_ERROR;
66 }
67
OpenEditSession(int32_t userId,uint8_t * challenge,uint32_t challengeLen)68 ResultCode OpenEditSession(int32_t userId, uint8_t *challenge, uint32_t challengeLen)
69 {
70 if (challenge == NULL || challengeLen != CHALLENGE_LEN) {
71 LOG_ERROR("challenge is null");
72 return RESULT_BAD_PARAM;
73 }
74 (void)memset_s(challenge, CHALLENGE_LEN, 0, CHALLENGE_LEN);
75 if (IsSessionExist()) {
76 (void)CloseEditSession();
77 }
78 g_session = Malloc(sizeof(struct SessionInfo));
79 if (g_session == NULL) {
80 LOG_ERROR("g_session malloc failed");
81 return RESULT_NO_MEMORY;
82 }
83 if (memset_s(g_session, sizeof(struct SessionInfo), 0, sizeof(struct SessionInfo)) != EOK) {
84 LOG_ERROR("g_session set failed");
85 Free(g_session);
86 g_session = NULL;
87 return RESULT_GENERAL_ERROR;
88 }
89 g_session->userId = userId;
90 ResultCode ret = GenerateChallenge(g_session->challenge, CHALLENGE_LEN);
91 if (ret != RESULT_SUCCESS) {
92 LOG_ERROR("failed to generate challenge");
93 Free(g_session);
94 g_session = NULL;
95 return ret;
96 }
97 g_session->time = GetSystemTime();
98 g_session->validAuthTokenTime = g_session->time;
99
100 if (memcpy_s(challenge, CHALLENGE_LEN, g_session->challenge, CHALLENGE_LEN) != EOK) {
101 LOG_ERROR("failed to copy challenge");
102 Free(g_session);
103 g_session = NULL;
104 return ret;
105 }
106 g_session->isScheduleValid = false;
107 return RESULT_SUCCESS;
108 }
109
RefreshValidTokenTime(void)110 void RefreshValidTokenTime(void)
111 {
112 if (!IsSessionExist()) {
113 LOG_ERROR("session is invalid");
114 return;
115 }
116 g_session->validAuthTokenTime = GetSystemTime();
117 }
118
IsValidTokenTime(uint64_t tokenTime)119 bool IsValidTokenTime(uint64_t tokenTime)
120 {
121 if (!IsSessionExist()) {
122 LOG_ERROR("session is invalid");
123 return false;
124 }
125 return tokenTime >= g_session->validAuthTokenTime;
126 }
127
CloseEditSession()128 ResultCode CloseEditSession()
129 {
130 if (!IsSessionExist()) {
131 return RESULT_GENERAL_ERROR;
132 }
133 Free(g_session);
134 g_session = NULL;
135 return RESULT_SUCCESS;
136 }
137
GetUserId(int32_t * userId)138 ResultCode GetUserId(int32_t *userId)
139 {
140 if (userId == NULL || !IsSessionExist()) {
141 LOG_ERROR("param is invalid");
142 return RESULT_BAD_PARAM;
143 }
144 *userId = g_session->userId;
145 return RESULT_SUCCESS;
146 }
147
CheckChallenge(uint8_t * challenge,uint32_t challengeLen)148 ResultCode CheckChallenge(uint8_t *challenge, uint32_t challengeLen)
149 {
150 if (challenge == NULL || challengeLen != CHALLENGE_LEN) {
151 LOG_ERROR("param is invalid");
152 return RESULT_BAD_PARAM;
153 }
154 if (!IsSessionExist()) {
155 LOG_ERROR("param is invalid");
156 return RESULT_NEED_INIT;
157 }
158 if (memcmp(challenge, g_session->challenge, CHALLENGE_LEN) != EOK) {
159 LOG_ERROR("failed to compare challenge");
160 return RESULT_BAD_MATCH;
161 }
162 return RESULT_SUCCESS;
163 }
164
AssociateCoauthSchedule(uint64_t scheduleId,uint32_t authType,bool isUpdate)165 ResultCode AssociateCoauthSchedule(uint64_t scheduleId, uint32_t authType, bool isUpdate)
166 {
167 if (!IsSessionExist()) {
168 return RESULT_NEED_INIT;
169 }
170 g_session->scheduleId = scheduleId;
171 g_session->authType = authType;
172 g_session->isUpdate = isUpdate;
173 g_session->isScheduleValid = true;
174 return RESULT_SUCCESS;
175 }
176
BreakOffCoauthSchedule(void)177 void BreakOffCoauthSchedule(void)
178 {
179 if (!IsSessionExist()) {
180 return;
181 }
182 if (g_session->isScheduleValid) {
183 RemoveCoAuthSchedule(g_session->scheduleId);
184 }
185 g_session->isScheduleValid = false;
186 }
187
GetEnrollScheduleInfo(uint64_t * scheduleId,uint32_t * authType)188 ResultCode GetEnrollScheduleInfo(uint64_t *scheduleId, uint32_t *authType)
189 {
190 if (scheduleId == NULL || authType == NULL) {
191 LOG_ERROR("param is null");
192 return RESULT_BAD_PARAM;
193 }
194 if (!IsSessionExist() || g_session->isScheduleValid == false) {
195 return RESULT_NEED_INIT;
196 }
197 *scheduleId = g_session->scheduleId;
198 *authType = g_session->authType;
199 return RESULT_SUCCESS;
200 }
201
IsSessionTimeout(void)202 bool IsSessionTimeout(void)
203 {
204 if (!IsSessionExist()) {
205 return true;
206 }
207 uint64_t currentTime = GetSystemTime();
208 if (currentTime < g_session->time || currentTime - g_session->time > SESSION_VALIDITY_PERIOD) {
209 LOG_ERROR("timeout, %{public}llu, %{public}llu",
210 (unsigned long long)currentTime, (unsigned long long)g_session->time);
211 return true;
212 }
213 return false;
214 }
215
GetIsUpdate(bool * isUpdate)216 ResultCode GetIsUpdate(bool *isUpdate)
217 {
218 if (isUpdate == NULL) {
219 LOG_ERROR("param is invalid");
220 return RESULT_BAD_PARAM;
221 }
222 if (!IsSessionExist() || g_session->isScheduleValid == false) {
223 LOG_ERROR("session need init");
224 return RESULT_NEED_INIT;
225 }
226 *isUpdate = g_session->isUpdate;
227 return RESULT_SUCCESS;
228 }
229
IsSessionValid(int32_t userId)230 bool IsSessionValid(int32_t userId)
231 {
232 if (!IsSessionExist() || IsSessionTimeout()) {
233 return false;
234 }
235 if (g_session->userId == userId) {
236 return true;
237 }
238 return false;
239 }