1 /*
2  * Copyright (c) 2021-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_tcp_direct_listener.h"
17 
18 #include <arpa/inet.h>
19 #include <securec.h>
20 #include "auth_interface.h"
21 #include "bus_center_manager.h"
22 #include "lnn_distributed_net_ledger.h"
23 #include "softbus_adapter_crypto.h"
24 #include "softbus_adapter_hitrace.h"
25 #include "softbus_adapter_mem.h"
26 #include "softbus_base_listener.h"
27 #include "softbus_def.h"
28 #include "softbus_errcode.h"
29 #include "softbus_message_open_channel.h"
30 #include "softbus_socket.h"
31 #include "trans_channel_common.h"
32 #include "trans_channel_manager.h"
33 #include "trans_event.h"
34 #include "trans_log.h"
35 #include "trans_tcp_direct_message.h"
36 #include "trans_tcp_direct_sessionconn.h"
37 
38 #define ID_OFFSET (1)
39 #define OHOS_TYPE_UNKNOWN (-1)
40 #define OH_OS_TYPE 10
41 #define HO_OS_TYPE 11
42 
SwitchAuthLinkTypeToFlagType(AuthLinkType type)43 uint32_t SwitchAuthLinkTypeToFlagType(AuthLinkType type)
44 {
45     switch (type) {
46         case AUTH_LINK_TYPE_BR:
47             return FLAG_BR;
48         case AUTH_LINK_TYPE_BLE:
49             return FLAG_BLE;
50         case AUTH_LINK_TYPE_P2P:
51             return FLAG_P2P;
52         case AUTH_LINK_TYPE_ENHANCED_P2P:
53             return FLAG_ENHANCE_P2P;
54         default:
55             return FLAG_WIFI;
56     }
57 }
58 
GetCipherFlagByAuthId(AuthHandle authHandle,uint32_t * flag,bool * isAuthServer,bool isLegacyOs)59 int32_t GetCipherFlagByAuthId(AuthHandle authHandle, uint32_t *flag, bool *isAuthServer, bool isLegacyOs)
60 {
61     if (flag == NULL || isAuthServer == NULL) {
62         TRANS_LOGE(TRANS_CTRL, "param invalid");
63         return SOFTBUS_INVALID_PARAM;
64     }
65     AuthConnInfo info;
66     int32_t ret = AuthGetServerSide(authHandle.authId, isAuthServer);
67     if (ret != SOFTBUS_OK) {
68         TRANS_LOGE(TRANS_CTRL, "get auth server side fail authId=%{public}" PRId64, authHandle.authId);
69         return ret;
70     }
71     ret = AuthGetConnInfo(authHandle, &info);
72     if (ret != SOFTBUS_OK) {
73         TRANS_LOGE(TRANS_CTRL, "get authinfo fail authId=%{public}" PRId64, authHandle.authId);
74         return ret;
75     }
76     // In order to be compatible with legacyOs versions that only has AUTH_P2P
77     if (isLegacyOs && info.type == AUTH_LINK_TYPE_ENHANCED_P2P) {
78         *flag = FLAG_P2P;
79         TRANS_LOGW(TRANS_CTRL,
80             "peer device is legacyOs, change flag form P2P_ENHANCE to P2P flag=0x%{public}x", *flag);
81         return SOFTBUS_OK;
82     }
83     *flag = SwitchAuthLinkTypeToFlagType(info.type);
84     TRANS_LOGI(TRANS_CTRL, "get auth link type=%{public}d, flag=0x%{public}x", info.type, *flag);
85     return SOFTBUS_OK;
86 }
87 
StartVerifySession(SessionConn * conn)88 static int32_t StartVerifySession(SessionConn *conn)
89 {
90     TRANS_LOGI(TRANS_CTRL, "verify enter. channelId=%{public}d, fd=%{public}d", conn->channelId, conn->appInfo.fd);
91     if (SoftBusGenerateSessionKey(conn->appInfo.sessionKey, SESSION_KEY_LENGTH) != SOFTBUS_OK) {
92         TRANS_LOGE(TRANS_CTRL,
93             "Generate SessionKey failed channelId=%{public}d, fd=%{public}d",
94             conn->channelId, conn->appInfo.fd);
95         return SOFTBUS_TRANS_TCP_GENERATE_SESSIONKEY_FAILED;
96     }
97     SetSessionKeyByChanId(conn->channelId, conn->appInfo.sessionKey, sizeof(conn->appInfo.sessionKey));
98 
99     bool isAuthServer = false;
100     uint32_t cipherFlag = FLAG_WIFI;
101     bool isLegacyOs = IsPeerDeviceLegacyOs(conn->appInfo.osType);
102     if (GetCipherFlagByAuthId(conn->authHandle, &cipherFlag, &isAuthServer, isLegacyOs)) {
103         TRANS_LOGE(TRANS_CTRL,
104             "get cipher flag failed channelId=%{public}d, fd=%{public}d",
105             conn->channelId, conn->appInfo.fd);
106         return SOFTBUS_TRANS_GET_CIPHER_FAILED;
107     }
108     uint64_t seq = TransTdcGetNewSeqId();
109     if (isAuthServer) {
110         seq |= AUTH_CONN_SERVER_SIDE;
111     }
112 
113     char *bytes = PackRequest(&conn->appInfo);
114     if (bytes == NULL) {
115         TRANS_LOGE(TRANS_CTRL,
116             "Pack Request failed channelId=%{public}d, fd=%{public}d",
117             conn->channelId, conn->appInfo.fd);
118         return SOFTBUS_TRANS_PACK_REQUEST_FAILED;
119     }
120     TdcPacketHead packetHead = {
121         .magicNumber = MAGIC_NUMBER,
122         .module = MODULE_SESSION,
123         .seq = seq,
124         .flags = (FLAG_REQUEST | cipherFlag),
125         .dataLen = strlen(bytes), /* reset after encrypt */
126     };
127     if (conn->isMeta) {
128         packetHead.flags |= FLAG_AUTH_META;
129     }
130     int32_t ret = TransTdcPostBytes(conn->channelId, &packetHead, bytes);
131     cJSON_free(bytes);
132     if (ret != SOFTBUS_OK) {
133         TRANS_LOGE(TRANS_CTRL,
134             "TransTdc post bytes failed channelId=%{public}d, fd=%{public}d, ret=%{public}d",
135             conn->channelId, conn->appInfo.fd, ret);
136         return ret;
137     }
138     TRANS_LOGI(TRANS_CTRL, "verify ok. channelId=%{public}d, fd=%{public}d", conn->channelId, conn->appInfo.fd);
139 
140     return SOFTBUS_OK;
141 }
142 
TransSetTcpDirectConnectType(int32_t * connectType,ListenerModule module)143 static void TransSetTcpDirectConnectType(int32_t *connectType, ListenerModule module)
144 {
145     if (module >= DIRECT_CHANNEL_SERVER_HML_START && module <= DIRECT_CHANNEL_SERVER_HML_END) {
146         *connectType = CONNECT_HML;
147     } else if (module == DIRECT_CHANNEL_SERVER_P2P) {
148         *connectType = CONNECT_P2P;
149     } else if (module == DIRECT_CHANNEL_SERVER_WIFI) {
150         *connectType = CONNECT_TCP;
151     }
152 }
153 
CreateSessionConnNode(ListenerModule module,int fd,int32_t chanId,const ConnectOption * clientAddr)154 static int32_t CreateSessionConnNode(ListenerModule module, int fd, int32_t chanId, const ConnectOption *clientAddr)
155 {
156     SessionConn *conn = (SessionConn *)SoftBusCalloc(sizeof(SessionConn));
157     if (conn == NULL) {
158         TRANS_LOGE(TRANS_CTRL, "malloc fail in create session conn node.");
159         return SOFTBUS_MALLOC_ERR;
160     }
161     conn->appInfo.myData.apiVersion = API_V2;
162     conn->appInfo.fd = fd;
163     conn->serverSide = true;
164     conn->channelId = chanId;
165     conn->status = TCP_DIRECT_CHANNEL_STATUS_CONNECTING;
166     conn->timeout = 0;
167     conn->listenMod = module;
168     conn->authHandle.authId = AUTH_INVALID_ID;
169     conn->appInfo.routeType = (module == DIRECT_CHANNEL_SERVER_P2P) ? WIFI_P2P : WIFI_STA;
170     conn->appInfo.peerData.port = clientAddr->socketOption.port;
171     TransSetTcpDirectConnectType(&conn->appInfo.connectType, module);
172     int32_t ret =
173         LnnGetLocalStrInfo(STRING_KEY_UUID, conn->appInfo.myData.deviceId, sizeof(conn->appInfo.myData.deviceId));
174     if (ret != SOFTBUS_OK) {
175         TRANS_LOGE(TRANS_CTRL, "get local deviceId failed.");
176         SoftBusFree(conn);
177         return ret;
178     }
179 
180     if (strcpy_s(conn->appInfo.peerData.addr, sizeof(conn->appInfo.peerData.addr), clientAddr->socketOption.addr) !=
181         EOK) {
182         TRANS_LOGE(TRANS_CTRL, "copy ip to app info failed.");
183         SoftBusFree(conn);
184         return SOFTBUS_STRCPY_ERR;
185     }
186     conn->appInfo.protocol = clientAddr->socketOption.protocol;
187 
188     const char *authState = "";
189     if (strcpy_s(conn->appInfo.myData.authState, sizeof(conn->appInfo.myData.authState), authState) != EOK) {
190         TRANS_LOGE(TRANS_CTRL, "copy auth state to app info failed.");
191         SoftBusFree(conn);
192         return SOFTBUS_STRCPY_ERR;
193     }
194     ret = TransTdcAddSessionConn(conn);
195     if (ret != SOFTBUS_OK) {
196         TRANS_LOGE(TRANS_CTRL, "add session conn node failed.");
197         SoftBusFree(conn);
198         return ret;
199     }
200     ret = AddTrigger(module, fd, READ_TRIGGER);
201     if (ret != SOFTBUS_OK) {
202         TRANS_LOGE(TRANS_CTRL, "add trigger failed, delete session conn.");
203         TransDelSessionConnById(chanId);
204         return ret;
205     }
206 
207     return SOFTBUS_OK;
208 }
209 
TdcOnConnectEvent(ListenerModule module,int cfd,const ConnectOption * clientAddr)210 static int32_t TdcOnConnectEvent(ListenerModule module, int cfd, const ConnectOption *clientAddr)
211 {
212     if (cfd < 0 || clientAddr == NULL) {
213         TRANS_LOGW(TRANS_CTRL, "invalid param, cfd=%{public}d", cfd);
214         return SOFTBUS_INVALID_PARAM;
215     }
216     int32_t ret;
217     int32_t channelId = GenerateChannelId(true);
218     TransEventExtra extra = {
219         .socketName = NULL,
220         .peerNetworkId = NULL,
221         .calleePkg = NULL,
222         .callerPkg = NULL,
223         .socketFd = cfd,
224         .channelId = channelId
225     };
226     if (channelId <= INVALID_CHANNEL_ID) {
227         ret = SOFTBUS_TRANS_INVALID_CHANNEL_ID;
228         extra.result = EVENT_STAGE_RESULT_FAILED;
229         extra.errcode = ret;
230         TRANS_EVENT(EVENT_SCENE_OPEN_CHANNEL_SERVER, EVENT_STAGE_START_CONNECT, extra);
231         TRANS_LOGE(TRANS_CTRL, "channelId is invalid");
232         ConnShutdownSocket(cfd);
233         return ret;
234     }
235     ret = TransSrvAddDataBufNode(channelId, cfd); // fd != channelId
236     if (ret != SOFTBUS_OK) {
237         extra.result = EVENT_STAGE_RESULT_FAILED;
238         extra.errcode = ret;
239         TRANS_EVENT(EVENT_SCENE_OPEN_CHANNEL_SERVER, EVENT_STAGE_START_CONNECT, extra);
240         TRANS_LOGE(TRANS_CTRL, "create srv data buf node failed.");
241         ConnShutdownSocket(cfd);
242         return ret;
243     }
244 
245     ret = CreateSessionConnNode(module, cfd, channelId, clientAddr);
246     if (ret != SOFTBUS_OK) {
247         extra.result = EVENT_STAGE_RESULT_FAILED;
248         extra.errcode = ret;
249         TRANS_EVENT(EVENT_SCENE_OPEN_CHANNEL_SERVER, EVENT_STAGE_START_CONNECT, extra);
250         TRANS_LOGE(TRANS_CTRL, "create session conn node fail, delete data buf node.");
251         TransSrvDelDataBufNode(channelId);
252         ConnShutdownSocket(cfd);
253         return ret;
254     }
255     extra.result = EVENT_STAGE_RESULT_OK;
256     TRANS_EVENT(EVENT_SCENE_OPEN_CHANNEL_SERVER, EVENT_STAGE_START_CONNECT, extra);
257     TRANS_LOGI(TRANS_CTRL, "tdc conn event cfd=%{public}d, channelId=%{public}d, module=%{public}d",
258         cfd, channelId, module);
259     return SOFTBUS_OK;
260 }
261 
CloseTcpDirectFd(int fd)262 static void CloseTcpDirectFd(int fd)
263 {
264 #ifndef __LITEOS_M__
265     ConnCloseSocket(fd);
266 #else
267     (void)fd;
268 #endif
269 }
270 
TransProcDataRes(ListenerModule module,int32_t ret,int32_t channelId,int32_t fd)271 static void TransProcDataRes(ListenerModule module, int32_t ret, int32_t channelId, int32_t fd)
272 {
273     if (ret != SOFTBUS_OK) {
274         TransEventExtra extra = {
275             .socketName = NULL,
276             .peerNetworkId = NULL,
277             .calleePkg = NULL,
278             .callerPkg = NULL,
279             .channelId = channelId,
280             .socketFd = fd,
281             .errcode = ret,
282             .result = EVENT_STAGE_RESULT_FAILED
283         };
284         SessionConn conn;
285         if (GetSessionConnById(channelId, &conn) != SOFTBUS_OK || !conn.serverSide) {
286             TRANS_EVENT(EVENT_SCENE_OPEN_CHANNEL, EVENT_STAGE_HANDSHAKE_REPLY, extra);
287         } else {
288             TRANS_EVENT(EVENT_SCENE_OPEN_CHANNEL_SERVER, EVENT_STAGE_HANDSHAKE_REPLY, extra);
289         }
290         (void)memset_s(conn.appInfo.sessionKey, sizeof(conn.appInfo.sessionKey), 0, sizeof(conn.appInfo.sessionKey));
291         DelTrigger(module, fd, READ_TRIGGER);
292         ConnShutdownSocket(fd);
293         (void)NotifyChannelOpenFailed(channelId, ret);
294     } else {
295         CloseTcpDirectFd(fd);
296     }
297     TransDelSessionConnById(channelId);
298     TransSrvDelDataBufNode(channelId);
299 }
300 
ProcessSocketInEvent(SessionConn * conn,int fd)301 static int32_t ProcessSocketInEvent(SessionConn *conn, int fd)
302 {
303     int32_t ret = TransTdcSrvRecvData(conn->listenMod, conn->channelId, conn->authHandle.type);
304     if (ret == SOFTBUS_DATA_NOT_ENOUGH) {
305         return SOFTBUS_OK;
306     }
307     if (ret != SOFTBUS_OK) {
308         TRANS_LOGE(TRANS_CTRL, "Trans Srv Recv Data, ret=%{public}d.", ret);
309     }
310     TransProcDataRes(conn->listenMod, ret, conn->channelId, fd);
311     return ret;
312 }
313 
ProcessSocketOutEvent(SessionConn * conn,int fd)314 static int32_t ProcessSocketOutEvent(SessionConn *conn, int fd)
315 {
316     int32_t ret = SOFTBUS_TCP_SOCKET_ERR;
317     if (conn->serverSide) {
318         return ret;
319     }
320     DelTrigger(conn->listenMod, fd, WRITE_TRIGGER);
321     if (AddTrigger(conn->listenMod, fd, READ_TRIGGER) != SOFTBUS_OK) {
322         TRANS_LOGE(TRANS_CTRL, "add trigger fail, module=%{public}d, fd=%{public}d", conn->listenMod, fd);
323         return SOFTBUS_TRANS_ADD_TRIGGER_FAILED;
324     }
325     ret = StartVerifySession(conn);
326     TransEventExtra extra = {
327         .socketName = NULL,
328         .peerNetworkId = NULL,
329         .calleePkg = NULL,
330         .callerPkg = NULL,
331         .socketFd = fd,
332         .channelId = conn->channelId,
333         .authId = conn->authHandle.authId,
334         .errcode = ret,
335         .result = (ret == SOFTBUS_OK) ? EVENT_STAGE_RESULT_OK : EVENT_STAGE_RESULT_FAILED
336     };
337     TRANS_EVENT(EVENT_SCENE_OPEN_CHANNEL, EVENT_STAGE_HANDSHAKE_START, extra);
338     if (ret != SOFTBUS_OK) {
339         TRANS_LOGE(TRANS_CTRL, "start verify session failed, ret = %{public}d", ret);
340         DelTrigger(conn->listenMod, fd, READ_TRIGGER);
341         ConnShutdownSocket(fd);
342         (void)NotifyChannelOpenFailed(conn->channelId, ret);
343         TransDelSessionConnById(conn->channelId);
344         TransSrvDelDataBufNode(conn->channelId);
345     }
346     return ret;
347 }
348 
ProcessSocketExceptionEvent(SessionConn * conn,int fd)349 static void ProcessSocketExceptionEvent(SessionConn *conn, int fd)
350 {
351     TRANS_LOGE(TRANS_CTRL, "exception occurred.");
352     DelTrigger(conn->listenMod, fd, EXCEPT_TRIGGER);
353     ConnShutdownSocket(fd);
354     TransDelSessionConnById(conn->channelId);
355     TransSrvDelDataBufNode(conn->channelId);
356 }
357 
TdcOnDataEvent(ListenerModule module,int events,int fd)358 static int32_t TdcOnDataEvent(ListenerModule module, int events, int fd)
359 {
360     (void)module;
361     SessionConn *conn = (SessionConn *)SoftBusCalloc(sizeof(SessionConn));
362     if (conn == NULL) {
363         TRANS_LOGE(TRANS_CTRL, "OnDataEvent malloc fail.");
364         return SOFTBUS_MALLOC_ERR;
365     }
366     if (GetSessionConnByFd(fd, conn) != SOFTBUS_OK || conn->appInfo.fd != fd) {
367         TRANS_LOGE(TRANS_CTRL, "fd is not exist tdc info. fd=%{public}d, appfd=%{public}d", fd, conn->appInfo.fd);
368         for (uint32_t i = DIRECT_CHANNEL_SERVER_P2P; i <= DIRECT_CHANNEL_SERVER_HML_END; i++) {
369             DelTrigger((ListenerModule)i, fd, READ_TRIGGER);
370             DelTrigger((ListenerModule)i, fd, WRITE_TRIGGER);
371             DelTrigger((ListenerModule)i, fd, EXCEPT_TRIGGER);
372         }
373         SoftBusFree(conn);
374         ConnShutdownSocket(fd);
375         return SOFTBUS_INVALID_FD;
376     }
377     SoftbusHitraceStart(SOFTBUS_HITRACE_ID_VALID, (uint64_t)(conn->channelId + ID_OFFSET));
378     int32_t ret = SOFTBUS_TRANS_TDC_ON_DATA_EVENT_FAILED;
379     if (events == SOFTBUS_SOCKET_IN) {
380         ret = ProcessSocketInEvent(conn, fd);
381     } else if (events == SOFTBUS_SOCKET_OUT) {
382         ret = ProcessSocketOutEvent(conn, fd);
383     } else if (events == SOFTBUS_SOCKET_EXCEPTION) {
384         ProcessSocketExceptionEvent(conn, fd);
385     }
386     (void)memset_s(conn->appInfo.sessionKey, sizeof(conn->appInfo.sessionKey), 0, sizeof(conn->appInfo.sessionKey));
387     SoftBusFree(conn);
388     return ret;
389 }
390 
TransTdcStartSessionListener(ListenerModule module,const LocalListenerInfo * info)391 int32_t TransTdcStartSessionListener(ListenerModule module, const LocalListenerInfo *info)
392 {
393     if (info == NULL || (info->type != CONNECT_TCP && info->type != CONNECT_P2P && info->type != CONNECT_HML) ||
394         info->socketOption.port < 0) {
395         TRANS_LOGE(TRANS_CTRL, "Invalid para.");
396         return SOFTBUS_INVALID_PARAM;
397     }
398 
399     static SoftbusBaseListener sessionListener = {
400         .onConnectEvent = TdcOnConnectEvent,
401         .onDataEvent = TdcOnDataEvent
402     };
403 
404     TRANS_LOGI(TRANS_CTRL, "set listener for module=%{public}d.", module);
405     int serverPort = StartBaseListener(info, &sessionListener);
406     return serverPort;
407 }
408 
TransTdcStopSessionListener(ListenerModule module)409 int32_t TransTdcStopSessionListener(ListenerModule module)
410 {
411     TransTdcStopSessionProc(module);
412     return StopBaseListener(module);
413 }