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