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 "ipc/daemon_stub.h"
17 
18 #include "dfs_error.h"
19 #include "dfsu_access_token_helper.h"
20 #include "dm_device_info.h"
21 #include "ipc/distributed_file_daemon_ipc_interface_code.h"
22 #include "ipc_skeleton.h"
23 #include "utils_log.h"
24 
25 namespace OHOS {
26 namespace Storage {
27 namespace DistributedFile {
28 using namespace OHOS::FileManagement;
29 const int32_t UID = 1009;
30 const int32_t DATA_UID = 3012;
DaemonStub()31 DaemonStub::DaemonStub()
32 {
33     opToInterfaceMap_[static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_OPEN_P2P_CONNECTION)] =
34         &DaemonStub::HandleOpenP2PConnection;
35     opToInterfaceMap_[static_cast<uint32_t>(
36         DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_CLOSE_P2P_CONNECTION)] =
37         &DaemonStub::HandleCloseP2PConnection;
38     opToInterfaceMap_[static_cast<uint32_t>(
39         DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_OPEN_P2P_CONNECTION_EX)] =
40         &DaemonStub::HandleOpenP2PConnectionEx;
41     opToInterfaceMap_[static_cast<uint32_t>(
42         DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_CLOSE_P2P_CONNECTION_EX)] =
43         &DaemonStub::HandleCloseP2PConnectionEx;
44     opToInterfaceMap_[static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_PREPARE_SESSION)] =
45         &DaemonStub::HandlePrepareSession;
46     opToInterfaceMap_[static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_CANCEL_COPY_TASK)] =
47             &DaemonStub::HandleCancelCopyTask;
48     opToInterfaceMap_[static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_REQUEST_SEND_FILE)] =
49         &DaemonStub::HandleRequestSendFile;
50     opToInterfaceMap_[static_cast<uint32_t>(
51         DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_GET_REMOTE_COPY_INFO)] =
52         &DaemonStub::HandleGetRemoteCopyInfo;
53     opToInterfaceMap_[static_cast<uint32_t>(
54         DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_REGISTER_ASSET_CALLBACK)] =
55         &DaemonStub::HandleRegisterRecvCallback;
56     opToInterfaceMap_[static_cast<uint32_t>(
57         DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_UN_REGISTER_ASSET_CALLBACK)] =
58         &DaemonStub::HandleUnRegisterRecvCallback;
59     opToInterfaceMap_[static_cast<uint32_t>(
60         DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_PUSH_ASSET)] =
61         &DaemonStub::HandlePushAsset;
62 }
63 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)64 int32_t DaemonStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
65 {
66     if (data.ReadInterfaceToken() != GetDescriptor()) {
67         return DFS_DAEMON_DESCRIPTOR_IS_EMPTY;
68     }
69     switch (code) {
70         case static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_OPEN_P2P_CONNECTION):
71             return HandleOpenP2PConnection(data, reply);
72         case static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_CLOSE_P2P_CONNECTION):
73             return HandleCloseP2PConnection(data, reply);
74         case static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_OPEN_P2P_CONNECTION_EX):
75             return HandleOpenP2PConnectionEx(data, reply);
76         case static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_CLOSE_P2P_CONNECTION_EX):
77             return HandleCloseP2PConnectionEx(data, reply);
78         case static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_PREPARE_SESSION):
79             return HandlePrepareSession(data, reply);
80         case static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_CANCEL_COPY_TASK):
81             return HandleCancelCopyTask(data, reply);
82         case static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_REQUEST_SEND_FILE):
83             return HandleRequestSendFile(data, reply);
84         case static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_GET_REMOTE_COPY_INFO):
85             return HandleGetRemoteCopyInfo(data, reply);
86         case static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_REGISTER_ASSET_CALLBACK):
87             return HandleRegisterRecvCallback(data, reply);
88         case static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_UN_REGISTER_ASSET_CALLBACK):
89             return HandleUnRegisterRecvCallback(data, reply);
90         case static_cast<uint32_t>(DistributedFileDaemonInterfaceCode::DISTRIBUTED_FILE_PUSH_ASSET):
91             return HandlePushAsset(data, reply);
92         default:
93             LOGE("Cannot response request %d: unknown tranction", code);
94             return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
95     }
96 }
97 
HandleOpenP2PConnection(MessageParcel & data,MessageParcel & reply)98 int32_t DaemonStub::HandleOpenP2PConnection(MessageParcel &data, MessageParcel &reply)
99 {
100     LOGI("Begin OpenP2PConnection");
101     if (!DfsuAccessTokenHelper::CheckCallerPermission(PERM_DISTRIBUTED_DATASYNC)) {
102         LOGE("[HandleOpenP2PConnection] DATASYNC permission denied");
103         return E_PERMISSION_DENIED;
104     }
105     DistributedHardware::DmDeviceInfo deviceInfo;
106     auto ret = strcpy_s(deviceInfo.deviceId, DM_MAX_DEVICE_ID_LEN, data.ReadCString());
107     if (ret != 0) {
108         LOGE("strcpy for source device id failed, ret is %{public}d", ret);
109         return -1;
110     }
111     ret = strcpy_s(deviceInfo.deviceName, DM_MAX_DEVICE_NAME_LEN, data.ReadCString());
112     if (ret != 0) {
113         LOGE("strcpy for source device name failed, ret is %{public}d", ret);
114         return -1;
115     }
116     ret = strcpy_s(deviceInfo.networkId, DM_MAX_DEVICE_ID_LEN, data.ReadCString());
117     if (ret != 0) {
118         LOGE("strcpy for source network id failed, ret is %{public}d", ret);
119         return -1;
120     }
121     deviceInfo.deviceTypeId = data.ReadUint16();
122     deviceInfo.range = static_cast<int32_t>(data.ReadUint32());
123     deviceInfo.authForm = static_cast<DistributedHardware::DmAuthForm>(data.ReadInt32());
124 
125     int32_t res = OpenP2PConnection(deviceInfo);
126     reply.WriteInt32(res);
127     LOGI("End OpenP2PConnection, res = %{public}d", res);
128     return res;
129 }
130 
HandleCloseP2PConnection(MessageParcel & data,MessageParcel & reply)131 int32_t DaemonStub::HandleCloseP2PConnection(MessageParcel &data, MessageParcel &reply)
132 {
133     LOGI("Begin CloseP2PConnection");
134     if (!DfsuAccessTokenHelper::CheckCallerPermission(PERM_DISTRIBUTED_DATASYNC)) {
135         LOGE("[HandleCloseP2PConnection] DATASYNC permission denied");
136         return E_PERMISSION_DENIED;
137     }
138     DistributedHardware::DmDeviceInfo deviceInfo;
139     auto ret = strcpy_s(deviceInfo.deviceId, DM_MAX_DEVICE_ID_LEN, data.ReadCString());
140     if (ret != 0) {
141         LOGE("strcpy for source device id failed, ret is %{public}d", ret);
142         return -1;
143     }
144     ret = strcpy_s(deviceInfo.deviceName, DM_MAX_DEVICE_NAME_LEN, data.ReadCString());
145     if (ret != 0) {
146         LOGE("strcpy for source device name failed, ret is %{public}d", ret);
147         return -1;
148     }
149     ret = strcpy_s(deviceInfo.networkId, DM_MAX_DEVICE_ID_LEN, data.ReadCString());
150     if (ret != 0) {
151         LOGE("strcpy for source network id failed, ret is %{public}d", ret);
152         return -1;
153     }
154     deviceInfo.deviceTypeId = data.ReadUint16();
155     deviceInfo.range = static_cast<int32_t>(data.ReadUint32());
156     deviceInfo.authForm = static_cast<DistributedHardware::DmAuthForm>(data.ReadInt32());
157 
158     int32_t res = CloseP2PConnection(deviceInfo);
159     reply.WriteInt32(res);
160     LOGI("End CloseP2PConnection");
161     return res;
162 }
163 
HandleOpenP2PConnectionEx(MessageParcel & data,MessageParcel & reply)164 int32_t DaemonStub::HandleOpenP2PConnectionEx(MessageParcel &data, MessageParcel &reply)
165 {
166     LOGI("DaemonStub::Begin OpenP2PConnectionEx");
167     std::string networkId;
168     if (!data.ReadString(networkId)) {
169         LOGE("read networkId failed");
170         return E_IPC_READ_FAILED;
171     }
172     auto remote = data.ReadRemoteObject();
173     if (remote == nullptr) {
174         LOGE("read remoteObject failed");
175         return E_IPC_READ_FAILED;
176     }
177     auto remoteReverseObj = iface_cast<IFileDfsListener>(remote);
178     if (remoteReverseObj == nullptr) {
179         LOGE("remoteReverseObj is null");
180         return E_INVAL_ARG;
181     }
182     int32_t res = OpenP2PConnectionEx(networkId, remoteReverseObj);
183     reply.WriteInt32(res);
184     LOGI("DaemonStub::End OpenP2PConnection, res = %{public}d.", res);
185     return res;
186 }
187 
HandleCloseP2PConnectionEx(MessageParcel & data,MessageParcel & reply)188 int32_t DaemonStub::HandleCloseP2PConnectionEx(MessageParcel &data, MessageParcel &reply)
189 {
190     LOGI("DaemonStub::Begin CloseP2PConnection.");
191     std::string networkId;
192     if (!data.ReadString(networkId)) {
193         LOGE("read networkId failed");
194         return E_IPC_READ_FAILED;
195     }
196 
197     int32_t res = CloseP2PConnectionEx(networkId);
198     reply.WriteInt32(res);
199     LOGI("DaemonStub::End CloseP2PConnection");
200     return res;
201 }
202 
HandlePrepareSession(MessageParcel & data,MessageParcel & reply)203 int32_t DaemonStub::HandlePrepareSession(MessageParcel &data, MessageParcel &reply)
204 {
205     std::string srcUri;
206     if (!data.ReadString(srcUri)) {
207         LOGE("read srcUri failed");
208         return E_IPC_READ_FAILED;
209     }
210     if (!DfsuAccessTokenHelper::CheckUriPermission(srcUri)) {
211         LOGE("permission verify failed");
212         return E_PERMISSION_DENIED;
213     }
214     std::string dstUri;
215     if (!data.ReadString(dstUri)) {
216         LOGE("read dstUri failed");
217         return E_IPC_READ_FAILED;
218     }
219     std::string srcDeviceId;
220     if (!data.ReadString(srcDeviceId)) {
221         LOGE("read srcDeviceId failed");
222         return E_IPC_READ_FAILED;
223     }
224     auto listener = data.ReadRemoteObject();
225     if (listener == nullptr) {
226         LOGE("read listener failed");
227         return E_IPC_READ_FAILED;
228     }
229     HmdfsInfo info{};
230     if (!data.ReadString(info.copyPath)) {
231         LOGE("read info.copyPath failed");
232         return E_IPC_READ_FAILED;
233     }
234     if (!data.ReadBool(info.dirExistFlag)) {
235         LOGE("read info.dirExistFlag failed");
236         return E_IPC_READ_FAILED;
237     }
238     int32_t res = PrepareSession(srcUri, dstUri, srcDeviceId, listener, info);
239     if (!reply.WriteString(info.sessionName)) {
240         LOGE("Write sessionName failed");
241         return E_IPC_WRITE_FAILED;
242     }
243     reply.WriteInt32(res);
244     LOGD("End PrepareSession, ret = %{public}d.", res);
245     return res;
246 }
247 
HandleRequestSendFile(MessageParcel & data,MessageParcel & reply)248 int32_t DaemonStub::HandleRequestSendFile(MessageParcel &data, MessageParcel &reply)
249 {
250     auto uid = IPCSkeleton::GetCallingUid();
251     if (uid != UID) {
252         LOGE("Permission denied, caller is not dfs!");
253         return E_PERMISSION_DENIED;
254     }
255     std::string srcUri;
256     if (!data.ReadString(srcUri)) {
257         LOGE("read srcUri failed");
258         return E_IPC_READ_FAILED;
259     }
260     std::string dstPath;
261     if (!data.ReadString(dstPath)) {
262         LOGE("read dstPath failed");
263         return E_IPC_READ_FAILED;
264     }
265     std::string dstDeviceId;
266     if (!data.ReadString(dstDeviceId)) {
267         LOGE("read remoteDeviceId failed");
268         return E_IPC_READ_FAILED;
269     }
270     std::string sessionName;
271     if (!data.ReadString(sessionName)) {
272         LOGE("read sessionName failed");
273         return E_IPC_READ_FAILED;
274     }
275     auto res = RequestSendFile(srcUri, dstPath, dstDeviceId, sessionName);
276     reply.WriteInt32(res);
277     LOGD("End RequestSendFile, ret = %{public}d.", res);
278     return res;
279 }
280 
HandleGetRemoteCopyInfo(MessageParcel & data,MessageParcel & reply)281 int32_t DaemonStub::HandleGetRemoteCopyInfo(MessageParcel &data, MessageParcel &reply)
282 {
283     auto uid = IPCSkeleton::GetCallingUid();
284     if (uid != UID) {
285         LOGE("Permission denied, caller is not dfs!");
286         return E_PERMISSION_DENIED;
287     }
288     std::string srcUri;
289     if (!data.ReadString(srcUri)) {
290         LOGE("read srcUri failed");
291         return E_IPC_READ_FAILED;
292     }
293     bool isFile = false;
294     bool isDir = false;
295     auto res = GetRemoteCopyInfo(srcUri, isFile, isDir);
296     if (res != E_OK) {
297         LOGE("GetRemoteCopyInfo failed");
298         return E_IPC_READ_FAILED;
299     }
300     if (!reply.WriteBool(isFile)) {
301         LOGE("Write isFile failed");
302         return E_IPC_READ_FAILED;
303     }
304     if (!reply.WriteBool(isDir)) {
305         LOGE("Write isDir failed");
306         return E_IPC_READ_FAILED;
307     }
308     if (!reply.WriteInt32(res)) {
309         LOGE("Write res failed");
310         return E_IPC_READ_FAILED;
311     }
312     LOGD("End GetRemoteCopyInfo, ret = %{public}d.", res);
313     return res;
314 }
315 
HandleCancelCopyTask(MessageParcel & data,MessageParcel & reply)316 int32_t DaemonStub::HandleCancelCopyTask(MessageParcel &data, MessageParcel &reply)
317 {
318     std::string sessionName;
319     if (!data.ReadString(sessionName)) {
320         LOGE("read sessionName failed");
321         return E_IPC_READ_FAILED;
322     }
323     return CancelCopyTask(sessionName);
324 }
325 
HandleRegisterRecvCallback(MessageParcel & data,MessageParcel & reply)326 int32_t DaemonStub::HandleRegisterRecvCallback(MessageParcel &data, MessageParcel &reply)
327 {
328     LOGI("Begin RegisterRecvCallback");
329     auto uid = IPCSkeleton::GetCallingUid();
330     if (uid != DATA_UID) {
331         LOGE("Permission denied, caller is not data!");
332         return E_PERMISSION_DENIED;
333     }
334     if (!DfsuAccessTokenHelper::CheckCallerPermission(PERM_DISTRIBUTED_DATASYNC)) {
335         LOGE("[RegisterRecvCallback] DATASYNC permission denied");
336         return E_PERMISSION_DENIED;
337     }
338     auto object = data.ReadRemoteObject();
339     if (object == nullptr) {
340         LOGE("RegisterRecvCallback failed, object is nullptr.");
341         return E_IPC_READ_FAILED;
342     }
343     auto recvCallback = iface_cast<IAssetRecvCallback>(object);
344     if (recvCallback == nullptr) {
345         LOGE("RegisterRecvCallback failed, Callback is nullptr");
346         return E_INVAL_ARG;
347     }
348     int32_t res = RegisterAssetCallback(recvCallback);
349     if (!reply.WriteInt32(res)) {
350         LOGE("RegisterRecvCallback write res failed, res is %{public}d", res);
351         return E_IPC_READ_FAILED;
352     }
353     return res;
354 }
355 
HandleUnRegisterRecvCallback(MessageParcel & data,MessageParcel & reply)356 int32_t DaemonStub::HandleUnRegisterRecvCallback(MessageParcel &data, MessageParcel &reply)
357 {
358     LOGI("Begin UnRegisterRecvCallback");
359     auto uid = IPCSkeleton::GetCallingUid();
360     if (uid != DATA_UID) {
361         LOGE("Permission denied, caller is not data!");
362         return E_PERMISSION_DENIED;
363     }
364     if (!DfsuAccessTokenHelper::CheckCallerPermission(PERM_DISTRIBUTED_DATASYNC)) {
365         LOGE("[UnRegisterRecvCallback] DATASYNC permission denied");
366         return E_PERMISSION_DENIED;
367     }
368     auto object = data.ReadRemoteObject();
369     if (object == nullptr) {
370         LOGE("UnRegisterRecvCallback failed, object is nullptr.");
371         return E_IPC_READ_FAILED;
372     }
373     auto recvCallback = iface_cast<IAssetRecvCallback>(object);
374     if (recvCallback == nullptr) {
375         LOGE("UnRegisterRecvCallback failed, Callback is nullptr");
376         return E_INVAL_ARG;
377     }
378     int32_t res = UnRegisterAssetCallback(recvCallback);
379     if (!reply.WriteInt32(res)) {
380         LOGE("UnRegisterRecvCallback write res failed, res is %{public}d", res);
381         return E_IPC_READ_FAILED;
382     }
383     return res;
384 }
385 
HandlePushAsset(MessageParcel & data,MessageParcel & reply)386 int32_t DaemonStub::HandlePushAsset(MessageParcel &data, MessageParcel &reply)
387 {
388     LOGI("Begin PushAsset");
389     auto uid = IPCSkeleton::GetCallingUid();
390     if (uid != DATA_UID) {
391         LOGE("Permission denied, caller is not data!");
392         return E_PERMISSION_DENIED;
393     }
394     if (!DfsuAccessTokenHelper::CheckCallerPermission(PERM_DISTRIBUTED_DATASYNC)) {
395         LOGE("[PushAsset] DATASYNC permission denied");
396         return E_PERMISSION_DENIED;
397     }
398     int32_t userId;
399     if (!data.ReadInt32(userId)) {
400         LOGE("read userId failed");
401         return E_INVAL_ARG;
402     }
403 
404     sptr<AssetObj> assetObj = data.ReadParcelable<AssetObj>();
405     if (!assetObj) {
406         LOGE("object of AssetObj is nullptr");
407         return E_INVAL_ARG;
408     }
409 
410     auto object = data.ReadRemoteObject();
411     if (object == nullptr) {
412         LOGE("PushAsset failed, object is nullptr.");
413         return E_IPC_READ_FAILED;
414     }
415     auto sendCallback = iface_cast<IAssetSendCallback>(object);
416     if (sendCallback == nullptr) {
417         LOGE("PushAsset failed, Callback is nullptr");
418         return E_INVAL_ARG;
419     }
420 
421     int32_t res = PushAsset(userId, assetObj, sendCallback);
422     if (!reply.WriteInt32(res)) {
423         LOGE("PushAsset write res failed, res is %{public}d", res);
424         return E_IPC_READ_FAILED;
425     }
426     return res;
427 }
428 } // namespace DistributedFile
429 } // namespace Storage
430 } // namespace OHOS