1 /*
2 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12
13 #include "tee_ca_daemon.h"
14 #include <unistd.h>
15 #include <errno.h> /* for errno */
16 #include <fcntl.h>
17 #include <sys/ioctl.h> /* for ioctl */
18 #include <sys/mman.h> /* for mmap */
19 #include <sys/socket.h>
20 #include <sys/un.h>
21 #include <pthread.h>
22 #include "securec.h"
23 #include "tc_ns_client.h"
24 #include "tee_client_type.h"
25 #include "tee_client_socket.h"
26 #include "tee_agent.h"
27 #include "tee_log.h"
28 #include "tee_auth_common.h"
29 #include "tee_ca_auth.h"
30 #include "fs_work_agent.h"
31
32 /* debug switch */
33 #ifdef LOG_NDEBUG
34 #undef LOG_NDEBUG
35 #endif
36 #ifdef LOG_TAG
37 #undef LOG_TAG
38 #endif
39 #define LOG_TAG "teecd"
40
41 #define IOV_LEN 1
42
43 static unsigned int g_version = 0;
44
InitMsg(struct msghdr * hmsg,struct iovec * iov,size_t iovLen,char * ctrlBuf,size_t ctrlBufLen)45 static int InitMsg(struct msghdr *hmsg, struct iovec *iov, size_t iovLen,
46 char *ctrlBuf, size_t ctrlBufLen)
47 {
48 if (hmsg == NULL || iov == NULL || ctrlBuf == NULL) {
49 return EINVAL;
50 }
51 hmsg->msg_name = NULL;
52 hmsg->msg_namelen = 0;
53 hmsg->msg_iov = iov;
54 hmsg->msg_iovlen = iovLen;
55 hmsg->msg_control = ctrlBuf;
56 hmsg->msg_controllen = ctrlBufLen;
57 return EOK;
58 }
59
SendFileDescriptor(int cmd,int socket,int fd)60 static int SendFileDescriptor(int cmd, int socket, int fd)
61 {
62 struct msghdr hmsg;
63 struct iovec iov[IOV_LEN];
64 char ctrlBuf[CMSG_SPACE(sizeof(int))];
65 char base[IOV_LEN];
66 int *cmdata = NULL;
67
68 errno_t ret = memset_s(&hmsg, sizeof(hmsg), 0, sizeof(hmsg));
69 if (ret != EOK) {
70 tloge("memset failed!\n");
71 return ret;
72 }
73
74 ret = memset_s(ctrlBuf, CMSG_SPACE(sizeof(int)), 0, CMSG_SPACE(sizeof(int)));
75 if (ret != EOK) {
76 tloge("memset failed!\n");
77 return ret;
78 }
79 /* Pass at least one byte data, recvmsg() will not return 0 */
80 base[0] = ' ';
81 iov[0].iov_base = base;
82 iov[0].iov_len = sizeof(base);
83
84 ret = InitMsg(&hmsg, iov, IOV_LEN, ctrlBuf, CMSG_SPACE(sizeof(int)));
85 if (ret != EOK) {
86 tloge("init msg failed!\n");
87 return ret;
88 }
89
90 struct cmsghdr *controlMsg = CMSG_FIRSTHDR(&hmsg);
91 if (controlMsg != NULL) {
92 controlMsg->cmsg_level = SOL_SOCKET;
93 controlMsg->cmsg_type = SCM_RIGHTS;
94 controlMsg->cmsg_len = CMSG_LEN(sizeof(int));
95 cmdata = (int *)(uintptr_t)CMSG_DATA(controlMsg);
96 *cmdata = fd;
97 }
98
99 if (cmd == GET_TEEVERSION) {
100 iov[0].iov_base = &fd;
101 iov[0].iov_len = sizeof(int);
102 hmsg.msg_control = NULL;
103 hmsg.msg_controllen = 0;
104 }
105
106 ret = (int)sendmsg(socket, &hmsg, 0);
107 if (ret <= 0) {
108 tloge("sendmsg failed ret=0x%x:%d.\n", ret, errno);
109 return -1;
110 }
111 return 0;
112 }
113
ProcessCaMsg(const struct ucred * cr,const CaRevMsg * caInfo,int socket)114 static int ProcessCaMsg(const struct ucred *cr, const CaRevMsg *caInfo, int socket)
115 {
116 int ret;
117
118 if (caInfo->cmd == GET_TEEVERSION) {
119 ret = SendFileDescriptor(caInfo->cmd, socket, (int)g_version);
120 if (ret != 0) {
121 tloge("Failed to send version back. ret = %d\n", ret);
122 return -1;
123 }
124 return 0;
125 }
126
127 int fd = open(TC_NS_CLIENT_DEV_NAME, O_RDWR);
128 if (fd == -1) {
129 tloge("Failed to open %s: %d\n", TC_NS_CLIENT_DEV_NAME, errno);
130 return -1;
131 }
132
133 ret = SendLoginInfo(cr, caInfo, fd);
134 if (ret != EOK) {
135 tloge("Failed to send login info. ret=%d\n", ret);
136 close(fd);
137 return -1;
138 }
139
140 ret = SendFileDescriptor(caInfo->cmd, socket, fd);
141 if (ret != EOK) {
142 tloge("Failed to send fd. ret=%d\n", ret);
143 close(fd);
144 return -1;
145 }
146 close(fd);
147 return 0;
148 }
149
ProcessAccept(int s,CaRevMsg * caInfo)150 static void ProcessAccept(int s, CaRevMsg *caInfo)
151 {
152 struct ucred cr;
153 struct sockaddr_un remote;
154 int ret;
155
156 while (1) {
157 /* int done, n; */
158 tlogd("Waiting for a connection...target daemon\n");
159 size_t t = sizeof(remote);
160 int s2 = accept(s, (struct sockaddr *)&remote, (socklen_t *)&t);
161 if (s2 == -1) {
162 tloge("accept() to server socket failed, errno=%d", errno);
163 continue;
164 }
165
166 socklen_t len = sizeof(struct ucred);
167 if (getsockopt(s2, SOL_SOCKET, SO_PEERCRED, &cr, &len) < 0) {
168 tloge("peercred failed: %d", errno);
169 close(s2);
170 continue;
171 }
172
173 tlogd("uid %d pid %d\n", cr.uid, cr.pid);
174
175 ret = RecvCaMsg(s2, caInfo);
176 if (ret != 0) {
177 tloge("tee ca daemon recvmsg failed\n");
178 goto CLOSE_SOCKET;
179 }
180
181 TrySyncSysTimeToSecure();
182
183 ret = ProcessCaMsg(&cr, caInfo, s2);
184 if (ret != 0) {
185 tloge("Failed to process ca msg. ret=%d\n", ret);
186 goto CLOSE_SOCKET;
187 }
188
189 CLOSE_SOCKET:
190 tlogd("close_socket and curret ret=%u\n", ret);
191 close(s2);
192 errno_t rc = memset_s(caInfo, sizeof(CaRevMsg), 0, sizeof(CaRevMsg));
193 if (rc != EOK) {
194 tloge("ca_info memset_s failed\n");
195 }
196 }
197 }
198
FormatSockAddr(struct sockaddr_un * local,socklen_t * len)199 static int FormatSockAddr(struct sockaddr_un *local, socklen_t *len)
200 {
201 int ret = strncpy_s(local->sun_path, sizeof(local->sun_path), TC_NS_SOCKET_NAME, sizeof(TC_NS_SOCKET_NAME));
202 if (ret != EOK) {
203 tloge("strncpy_s failed\n");
204 return ret;
205 }
206
207 local->sun_family = AF_UNIX;
208 *len = (socklen_t)(strlen(local->sun_path) + sizeof(local->sun_family));
209 /* Make the socket in the Abstract Domain(no path but everyone can connect) */
210 local->sun_path[0] = 0;
211
212 return 0;
213 }
214
CreateSocket(void)215 static int32_t CreateSocket(void)
216 {
217 int32_t ret;
218
219 /* Open a socket (a UNIX domain stream socket) */
220 int32_t s = socket(AF_UNIX, SOCK_STREAM, 0);
221 if (s < 0) {
222 tloge("can't open stream socket, errno=%d\n", errno);
223 return -1;
224 }
225
226 /* Fill in address structure and bind to socket */
227 struct sockaddr_un local;
228 socklen_t len;
229 ret = memset_s(&local, sizeof(local), 0, sizeof(local));
230 if (ret != EOK) {
231 tloge("memset_s sockaddr_un local failed!\n");
232 close(s);
233 return -1;
234 }
235
236 ret = FormatSockAddr(&local, &len);
237 if (ret != EOK) {
238 tloge("format sock addr failed\n");
239 close(s);
240 return -1;
241 }
242
243 if (bind(s, (struct sockaddr *)&local, len) < 0) {
244 tloge("bind() to server socket failed, errno=%d\n", errno);
245 close(s);
246 return -1;
247 }
248
249 return s;
250 }
251
CaServerWorkThread(void * dummy)252 void *CaServerWorkThread(void *dummy)
253 {
254 (void)dummy;
255 CaRevMsg *caInfo = NULL;
256
257 int32_t s = CreateSocket();
258 if (s < 0) {
259 return NULL;
260 }
261
262 /* Start listening on the socket */
263 if (listen(s, BACKLOG_LEN) < 0) {
264 tloge("listen() failed, errno=%d\n", errno);
265 goto CLOSE_EXIT;
266 }
267
268 tlogv("\n********* deamon successfully initialized!***\n");
269
270 caInfo = (CaRevMsg *)malloc(sizeof(CaRevMsg));
271 if (caInfo == NULL) {
272 tloge("ca server: Failed to malloc caInfo\n");
273 goto CLOSE_EXIT;
274 }
275
276 if (memset_s(caInfo, sizeof(CaRevMsg), 0, sizeof(CaRevMsg)) != EOK) {
277 tloge("ca_info memset_s failed\n");
278 free(caInfo);
279 goto CLOSE_EXIT;
280 }
281
282 ProcessAccept(s, caInfo);
283 free(caInfo);
284
285 tlogv("\n********* deamon process_accept over!***\n");
286
287 CLOSE_EXIT:
288 close(s);
289 return NULL;
290 }
291