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