1 /*
2 * Copyright (c) 2024 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 "legacy/softbus_adapter_hitrace.h"
17 #include "trans_auth_negotiation.h"
18
19 #include <securec.h>
20
21 #include "softbus_adapter_mem.h"
22 #include "softbus_error_code.h"
23 #include "softbus_utils.h"
24 #include "trans_log.h"
25
26 #include "softbus_proxychannel_manager.h"
27 #include "softbus_proxychannel_transceiver.h"
28
29 #define AUTH_NEGOTIATION_TIMEOUT_MS 10000 // Generate auth key timeout period, unit ms
30 #define AUTH_NEGOTIATION_CHECK_INTERVAL 100 // Auth status check interval, unit ms
31
32 static SoftBusList *g_reqAuthPendingList = NULL;
33
34 typedef struct {
35 ListNode node;
36 uint32_t authRequestId;
37 uint32_t cnt;
38 int32_t errCode;
39 bool isFinished;
40 } TransReqAuthItem;
41
TransReqAuthPendingInit(void)42 int32_t TransReqAuthPendingInit(void)
43 {
44 TRANS_CHECK_AND_RETURN_RET_LOGW(g_reqAuthPendingList == NULL, SOFTBUS_OK, TRANS_SVC, "auth pending already init");
45
46 g_reqAuthPendingList = CreateSoftBusList();
47 TRANS_CHECK_AND_RETURN_RET_LOGE(
48 g_reqAuthPendingList != NULL, SOFTBUS_TRANS_LIST_INIT_FAILED, TRANS_SVC, "auth pending list init failed");
49
50 return SOFTBUS_OK;
51 }
52
TransReqAuthPendingDeinit(void)53 void TransReqAuthPendingDeinit(void)
54 {
55 TRANS_LOGW(TRANS_SVC, "deinit auth request pending list");
56 TRANS_CHECK_AND_RETURN_LOGW(g_reqAuthPendingList != NULL, TRANS_SVC, "auth pending already deinit");
57
58 int32_t ret = SoftBusMutexLock(&g_reqAuthPendingList->lock);
59 TRANS_CHECK_AND_RETURN_LOGE(ret == SOFTBUS_OK, TRANS_SVC, "lock auth pending list failed");
60
61 TransReqAuthItem *item = NULL;
62 TransReqAuthItem *next = NULL;
63 LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_reqAuthPendingList->list, TransReqAuthItem, node) {
64 ListDelete(&item->node);
65 SoftBusFree(item);
66 }
67 (void)SoftBusMutexUnlock(&g_reqAuthPendingList->lock);
68 DestroySoftBusList(g_reqAuthPendingList);
69 g_reqAuthPendingList = NULL;
70 }
71
TransAddAuthReqToPendingList(uint32_t authRequestId)72 static int32_t TransAddAuthReqToPendingList(uint32_t authRequestId)
73 {
74 TRANS_CHECK_AND_RETURN_RET_LOGE(authRequestId != 0, SOFTBUS_INVALID_PARAM, TRANS_SVC, "invalid auth requestId");
75 TRANS_CHECK_AND_RETURN_RET_LOGE(
76 g_reqAuthPendingList != NULL, SOFTBUS_NO_INIT, TRANS_SVC, "auth pending list no init");
77
78 TransReqAuthItem *item = (TransReqAuthItem *)SoftBusCalloc(sizeof(TransReqAuthItem));
79 TRANS_CHECK_AND_RETURN_RET_LOGE(item != NULL, SOFTBUS_MALLOC_ERR, TRANS_SVC, "malloc auth request item failed");
80 item->authRequestId = authRequestId;
81 item->cnt = 0;
82 item->errCode = SOFTBUS_TRANS_AUTH_REQUEST_NOT_FOUND;
83 item->isFinished = false;
84
85 if (SoftBusMutexLock(&g_reqAuthPendingList->lock) != SOFTBUS_OK) {
86 TRANS_LOGE(TRANS_SVC, "lock auth pending list failed");
87 SoftBusFree(item);
88 return SOFTBUS_LOCK_ERR;
89 }
90 ListInit(&item->node);
91 ListAdd(&g_reqAuthPendingList->list, &item->node);
92 g_reqAuthPendingList->cnt++;
93 (void)SoftBusMutexUnlock(&g_reqAuthPendingList->lock);
94 TRANS_LOGI(TRANS_SVC, "add auth request to pending success, authRequestId=%{public}u", authRequestId);
95 return SOFTBUS_OK;
96 }
97
TransDelAuthReqFromPendingList(uint32_t authRequestId)98 static void TransDelAuthReqFromPendingList(uint32_t authRequestId)
99 {
100 TRANS_CHECK_AND_RETURN_LOGE(authRequestId != 0, TRANS_SVC, "invalid auth requestId");
101 TRANS_CHECK_AND_RETURN_LOGE(g_reqAuthPendingList != NULL, TRANS_SVC, "auth pending list no init");
102
103 int32_t ret = SoftBusMutexLock(&g_reqAuthPendingList->lock);
104 TRANS_CHECK_AND_RETURN_LOGE(ret == SOFTBUS_OK, TRANS_SVC, "lock auth pending list failed");
105 TransReqAuthItem *item = NULL;
106 TransReqAuthItem *next = NULL;
107 LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_reqAuthPendingList->list, TransReqAuthItem, node) {
108 if (item->authRequestId == authRequestId) {
109 ListDelete(&item->node);
110 SoftBusFree(item);
111 g_reqAuthPendingList->cnt--;
112 (void)SoftBusMutexUnlock(&g_reqAuthPendingList->lock);
113 TRANS_LOGI(TRANS_SVC, "delete auth request by authRequestId=%{public}u", authRequestId);
114 return;
115 }
116 }
117 (void)SoftBusMutexUnlock(&g_reqAuthPendingList->lock);
118 TRANS_LOGW(TRANS_SVC, "auth request not found by authRequestId=%{public}u", authRequestId);
119 }
120
TransUpdateAuthInfo(uint32_t authRequestId,int32_t errCode)121 static int32_t TransUpdateAuthInfo(uint32_t authRequestId, int32_t errCode)
122 {
123 TRANS_CHECK_AND_RETURN_RET_LOGE(authRequestId != 0, SOFTBUS_INVALID_PARAM, TRANS_SVC, "invalid auth requestId");
124 TRANS_CHECK_AND_RETURN_RET_LOGE(
125 g_reqAuthPendingList != NULL, SOFTBUS_NO_INIT, TRANS_SVC, "auth pending list no init");
126
127 int32_t ret = SoftBusMutexLock(&g_reqAuthPendingList->lock);
128 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, TRANS_SVC, "lock auth pending list failed");
129 TransReqAuthItem *item = NULL;
130 LIST_FOR_EACH_ENTRY(item, &g_reqAuthPendingList->list, TransReqAuthItem, node) {
131 if (item->authRequestId == authRequestId) {
132 item->errCode = errCode;
133 item->isFinished = true;
134 (void)SoftBusMutexUnlock(&g_reqAuthPendingList->lock);
135 return SOFTBUS_OK;
136 }
137 }
138 (void)SoftBusMutexUnlock(&g_reqAuthPendingList->lock);
139 TRANS_LOGE(TRANS_SVC, "auth request not found by authRequestId=%{public}u", authRequestId);
140 return SOFTBUS_TRANS_AUTH_REQUEST_NOT_FOUND;
141 }
142
TransCheckAuthNegoStatusByReqId(uint32_t authRequestId,bool * isFinished,int32_t * errCode,int32_t * cnt)143 static int32_t TransCheckAuthNegoStatusByReqId(uint32_t authRequestId, bool *isFinished, int32_t *errCode, int32_t *cnt)
144 {
145 TRANS_CHECK_AND_RETURN_RET_LOGE(
146 g_reqAuthPendingList != NULL, SOFTBUS_NO_INIT, TRANS_SVC, "auth pending list no init");
147
148 int32_t ret = SoftBusMutexLock(&g_reqAuthPendingList->lock);
149 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, TRANS_SVC, "lock auth pending list failed");
150 TransReqAuthItem *item = NULL;
151 LIST_FOR_EACH_ENTRY(item, &g_reqAuthPendingList->list, TransReqAuthItem, node) {
152 if (item->authRequestId == authRequestId) {
153 *isFinished = item->isFinished;
154 *errCode = item->errCode;
155 *cnt = ++item->cnt;
156 (void)SoftBusMutexUnlock(&g_reqAuthPendingList->lock);
157 return SOFTBUS_OK;
158 }
159 }
160 (void)SoftBusMutexUnlock(&g_reqAuthPendingList->lock);
161 TRANS_LOGE(TRANS_SVC, "auth request not found by authRequestId=%{public}u", authRequestId);
162 return SOFTBUS_TRANS_AUTH_REQUEST_NOT_FOUND;
163 }
164
WaitingForAuthNegoToBeDone(uint32_t authRequestId,int32_t channelId)165 static int32_t WaitingForAuthNegoToBeDone(uint32_t authRequestId, int32_t channelId)
166 {
167 int32_t ret = TransAddAuthReqToPendingList(authRequestId);
168 if (ret != SOFTBUS_OK) {
169 TRANS_LOGE(TRANS_SVC, "channelId=%{public}d add authRequestId=%{public}u to pending fail, ret=%{public}d",
170 channelId, authRequestId, ret);
171 return ret;
172 }
173 TransProxyPostAuthNegoMsgToLooperDelay(authRequestId, channelId, AUTH_NEGOTIATION_CHECK_INTERVAL);
174 return SOFTBUS_OK;
175 }
176
OnAuthSessionKeyGenSucc(uint32_t authRequestId,AuthHandle authHandle)177 static void OnAuthSessionKeyGenSucc(uint32_t authRequestId, AuthHandle authHandle)
178 {
179 (void)authHandle;
180 TRANS_LOGI(TRANS_SVC, "authKey gen success, authRequestId=%{public}u", authRequestId);
181 TransUpdateAuthInfo(authRequestId, SOFTBUS_OK);
182 }
183
OnAuthSessionKeyGenFail(uint32_t authRequestId,int32_t errCode)184 static void OnAuthSessionKeyGenFail(uint32_t authRequestId, int32_t errCode)
185 {
186 TRANS_LOGE(TRANS_SVC, "authKey gen failure, authRequestId=%{public}u errCode=%{public}d", authRequestId, errCode);
187 TransUpdateAuthInfo(authRequestId, errCode);
188 }
189
190 // update session key, no need to notify request
OnUpdateSessionKeySucc(uint32_t authRequestId,AuthHandle authHandle)191 static void OnUpdateSessionKeySucc(uint32_t authRequestId, AuthHandle authHandle)
192 {
193 (void)authRequestId;
194 (void)authHandle;
195 TRANS_LOGI(TRANS_SVC, "update success, authRequestId=%{public}u", authRequestId);
196 }
197
198 // update session key, no need to notify request
OnUpdateSessionKeyFail(uint32_t authRequestId,int32_t errCode)199 static void OnUpdateSessionKeyFail(uint32_t authRequestId, int32_t errCode)
200 {
201 (void)authRequestId;
202 (void)errCode;
203 TRANS_LOGE(TRANS_SVC, "update failure, authRequestId=%{public}u errCode=%{public}d", authRequestId, errCode);
204 }
205
TransNegotiateSessionKey(const AuthConnInfo * authConnInfo,int32_t channelId,const char * peerNetworkId)206 int32_t TransNegotiateSessionKey(const AuthConnInfo *authConnInfo, int32_t channelId, const char *peerNetworkId)
207 {
208 TRANS_CHECK_AND_RETURN_RET_LOGE((authConnInfo != NULL && peerNetworkId != NULL),
209 SOFTBUS_INVALID_PARAM, TRANS_SVC, "invalid param");
210
211 // Meta's peerNetworkId is empty in dSoftBus, and meta no need to negotiate, just skip
212 if (strlen(peerNetworkId) == 0) {
213 TRANS_LOGI(TRANS_SVC, "channelId=%{public}d peerNetworkId is empty, skip negotiate", channelId);
214 TransProxyNegoSessionKeySucc(channelId);
215 return SOFTBUS_OK;
216 }
217
218 int32_t ret = AuthCheckSessionKeyValidByConnInfo(peerNetworkId, authConnInfo);
219 if (ret == SOFTBUS_AUTH_SESSION_KEY_INVALID || ret == SOFTBUS_AUTH_SESSION_KEY_TOO_OLD) {
220 uint32_t authRequestId = AuthGenRequestId();
221 bool isFastAuth = true;
222 if (ret == SOFTBUS_AUTH_SESSION_KEY_TOO_OLD) {
223 TRANS_LOGI(TRANS_SVC, "sessionKey older, update it, authRequestId=%{public}u", authRequestId);
224 TransProxyNegoSessionKeySucc(channelId); // if sessionKey older, use old key to handshake first
225 AuthConnCallback authCallback = {
226 .onConnOpened = OnUpdateSessionKeySucc,
227 .onConnOpenFailed = OnUpdateSessionKeyFail,
228 };
229 AuthStartConnVerify(authConnInfo, authRequestId, &authCallback, AUTH_MODULE_TRANS, isFastAuth);
230 return SOFTBUS_OK;
231 }
232 TRANS_LOGI(TRANS_SVC, "no session key, start generation, authRequestId=%{public}u", authRequestId);
233 AuthConnCallback authCallback = {
234 .onConnOpened = OnAuthSessionKeyGenSucc,
235 .onConnOpenFailed = OnAuthSessionKeyGenFail,
236 };
237 AuthStartConnVerify(authConnInfo, authRequestId, &authCallback, AUTH_MODULE_TRANS, isFastAuth);
238 return WaitingForAuthNegoToBeDone(authRequestId, channelId);
239 }
240 TransProxyNegoSessionKeySucc(channelId);
241 return SOFTBUS_OK;
242 }
243
TransReNegotiateSessionKey(const AuthConnInfo * authConnInfo,int32_t channelId)244 int32_t TransReNegotiateSessionKey(const AuthConnInfo *authConnInfo, int32_t channelId)
245 {
246 TRANS_CHECK_AND_RETURN_RET_LOGE(authConnInfo != NULL, SOFTBUS_INVALID_PARAM, TRANS_SVC, "invalid param");
247
248 uint32_t authRequestId = AuthGenRequestId();
249 bool isFastAuth = true;
250 TRANS_LOGI(TRANS_SVC, "server side no session key, renegotiate, authRequestId=%{public}u", authRequestId);
251 AuthConnCallback authCallback = {
252 .onConnOpened = OnAuthSessionKeyGenSucc,
253 .onConnOpenFailed = OnAuthSessionKeyGenFail,
254 };
255 AuthStartConnVerify(authConnInfo, authRequestId, &authCallback, AUTH_MODULE_TRANS, isFastAuth);
256 return WaitingForAuthNegoToBeDone(authRequestId, channelId);
257 }
258
SetWlanAuthConnInfo(const struct ConnSocketInfo * socketInfo,AuthConnInfo * authConnInfo)259 static int32_t SetWlanAuthConnInfo(const struct ConnSocketInfo *socketInfo, AuthConnInfo *authConnInfo)
260 {
261 if (socketInfo->protocol != LNN_PROTOCOL_IP) {
262 TRANS_LOGE(TRANS_SVC, "tcp protocol=%{public}d not support", socketInfo->protocol);
263 return SOFTBUS_FUNC_NOT_SUPPORT;
264 }
265
266 authConnInfo->type = AUTH_LINK_TYPE_WIFI;
267 if (strcpy_s(authConnInfo->info.ipInfo.ip, IP_LEN, socketInfo->addr) != EOK) {
268 TRANS_LOGE(TRANS_SVC, "strcpy_s ip addr failed");
269 return SOFTBUS_STRCPY_ERR;
270 }
271 authConnInfo->info.ipInfo.port = socketInfo->port;
272 authConnInfo->info.ipInfo.moduleId = (ListenerModule)socketInfo->moduleId;
273
274 return SOFTBUS_OK;
275 }
276
SetBrAuthConnInfo(const struct BrInfo * brInfo,AuthConnInfo * authConnInfo)277 static int32_t SetBrAuthConnInfo(const struct BrInfo *brInfo, AuthConnInfo *authConnInfo)
278 {
279 authConnInfo->type = AUTH_LINK_TYPE_BR;
280 if (strcpy_s(authConnInfo->info.brInfo.brMac, BT_MAC_LEN, brInfo->brMac) != EOK) {
281 TRANS_LOGE(TRANS_SVC, "strcpy_s br mac failed");
282 return SOFTBUS_STRCPY_ERR;
283 }
284
285 return SOFTBUS_OK;
286 }
287
SetBleAuthConnInfo(const struct BleInfo * bleInfo,AuthConnInfo * authConnInfo)288 static int32_t SetBleAuthConnInfo(const struct BleInfo *bleInfo, AuthConnInfo *authConnInfo)
289 {
290 authConnInfo->type = AUTH_LINK_TYPE_BLE;
291 if (strcpy_s(authConnInfo->info.bleInfo.bleMac, BT_MAC_LEN, bleInfo->bleMac) != EOK ||
292 memcpy_s(authConnInfo->info.bleInfo.deviceIdHash,
293 UDID_HASH_LEN,
294 bleInfo->deviceIdHash,
295 UDID_HASH_LEN) != EOK) {
296 TRANS_LOGE(TRANS_SVC, "copy ble mac or deviceId hash failed");
297 return SOFTBUS_MEM_ERR;
298 }
299 authConnInfo->info.bleInfo.protocol = bleInfo->protocol;
300 authConnInfo->info.bleInfo.psm = bleInfo->psm;
301
302 return SOFTBUS_OK;
303 }
304
SetSleAuthConnInfo(const struct SleInfo * sleInfo,AuthConnInfo * authConnInfo)305 static int32_t SetSleAuthConnInfo(const struct SleInfo *sleInfo, AuthConnInfo *authConnInfo)
306 {
307 authConnInfo->type = AUTH_LINK_TYPE_SLE;
308 if (memcpy_s(authConnInfo->info.sleInfo.sleMac, BT_MAC_LEN, sleInfo->address, BT_MAC_LEN) != EOK) {
309 TRANS_LOGE(TRANS_SVC, "memcpy_s sle mac failed.");
310 return SOFTBUS_MEM_ERR;
311 }
312 authConnInfo->info.sleInfo.protocol = sleInfo->protocol;
313 return SOFTBUS_OK;
314 }
315
ConvertConnInfoToAuthConnInfo(const ConnectionInfo * connInfo,AuthConnInfo * authConnInfo)316 static int32_t ConvertConnInfoToAuthConnInfo(const ConnectionInfo *connInfo, AuthConnInfo *authConnInfo)
317 {
318 switch (connInfo->type) {
319 case CONNECT_TCP:
320 return SetWlanAuthConnInfo(&(connInfo->socketInfo), authConnInfo);
321 case CONNECT_BR:
322 return SetBrAuthConnInfo(&(connInfo->brInfo), authConnInfo);
323 case CONNECT_BLE:
324 return SetBleAuthConnInfo(&(connInfo->bleInfo), authConnInfo);
325 case CONNECT_SLE:
326 return SetSleAuthConnInfo(&(connInfo->sleInfo), authConnInfo);
327 default:
328 TRANS_LOGE(TRANS_SVC, "not support connection type=%{public}d", connInfo->type);
329 return SOFTBUS_FUNC_NOT_SUPPORT;
330 }
331 }
332
GetAuthConnInfoByConnId(uint32_t connectionId,AuthConnInfo * authConnInfo)333 int32_t GetAuthConnInfoByConnId(uint32_t connectionId, AuthConnInfo *authConnInfo)
334 {
335 TRANS_CHECK_AND_RETURN_RET_LOGE(authConnInfo != NULL, SOFTBUS_INVALID_PARAM, TRANS_SVC, "invalid param");
336
337 ConnectionInfo connInfo;
338 (void)memset_s(&connInfo, sizeof(ConnectionInfo), 0, sizeof(ConnectionInfo));
339 int32_t ret = ConnGetConnectionInfo(connectionId, &connInfo);
340 if (ret != SOFTBUS_OK) {
341 TRANS_LOGE(TRANS_CTRL, "get ConnectionInfo by connId=%{public}u failed, ret=%{public}d", connectionId, ret);
342 return ret;
343 }
344
345 ret = ConvertConnInfoToAuthConnInfo(&connInfo, authConnInfo);
346 if (ret != SOFTBUS_OK) {
347 TRANS_LOGE(TRANS_CTRL, "convert connInfo to authConnInfo failed, ret=%{public}d", ret);
348 return ret;
349 }
350
351 return SOFTBUS_OK;
352 }
353
TransAuthNegoTaskManager(uint32_t authRequestId,int32_t channelId)354 void TransAuthNegoTaskManager(uint32_t authRequestId, int32_t channelId)
355 {
356 SoftBusHitraceChainBegin("TransAuthNegoTaskManager");
357 if (authRequestId == 0) {
358 TRANS_LOGE(TRANS_SVC, "invalid param");
359 SoftBusHitraceChainEnd();
360 return;
361 }
362 bool isFinished = false;
363 int32_t errCode = SOFTBUS_TRANS_AUTH_NEGO_TASK_NOT_FOUND;
364 int32_t cnt = 0;
365 int32_t ret = TransCheckAuthNegoStatusByReqId(authRequestId, &isFinished, &errCode, &cnt);
366 if (ret != SOFTBUS_OK) {
367 TRANS_LOGE(TRANS_SVC, "check auth status by authRequestId=%{public}u failed", authRequestId);
368 SoftBusHitraceChainEnd();
369 return;
370 }
371
372 if (!isFinished) {
373 int32_t timeoutCnt = AUTH_NEGOTIATION_TIMEOUT_MS / AUTH_NEGOTIATION_CHECK_INTERVAL;
374 if (cnt >= timeoutCnt) {
375 TRANS_LOGE(TRANS_SVC, "authRequestId=%{public}u timeout, cnt=%{public}d", authRequestId, cnt);
376 TransProxyNegoSessionKeyFail(channelId, SOFTBUS_TRANS_AUTH_NEGOTIATE_SK_TIMEOUT);
377 TransDelAuthReqFromPendingList(authRequestId);
378 SoftBusHitraceChainEnd();
379 return;
380 }
381 TRANS_LOGD(TRANS_SVC, "authRequestId=%{public}u not finished, generate new task and waiting", authRequestId);
382 TransProxyPostAuthNegoMsgToLooperDelay(authRequestId, channelId, AUTH_NEGOTIATION_CHECK_INTERVAL);
383 SoftBusHitraceChainEnd();
384 return;
385 }
386
387 if (errCode != SOFTBUS_OK) {
388 TRANS_LOGE(TRANS_SVC, "authRequestId=%{public}u negotiate failed, errCode=%{public}d", authRequestId, errCode);
389 TransProxyNegoSessionKeyFail(channelId, errCode);
390 TransDelAuthReqFromPendingList(authRequestId);
391 SoftBusHitraceChainEnd();
392 return;
393 }
394
395 TransProxyNegoSessionKeySucc(channelId);
396 TransDelAuthReqFromPendingList(authRequestId);
397 SoftBusHitraceChainEnd();
398 }
399