1 /*
2  * Remote device access - debugging utility that allows to
3  * test smart card readers on remote hosts.
4  *
5  * Copyright (C) 2003, Olaf Kirch <okir@suse.de>
6  */
7 
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/poll.h>
14 #include <sys/socket.h>
15 #include <arpa/inet.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include <errno.h>
22 
23 #include <openct/socket.h>
24 #include <openct/server.h>
25 #include <openct/logging.h>
26 #include <openct/ifd.h>
27 #include "internal.h"
28 #include "ria.h"
29 
30 typedef struct ria_peer {
31 	struct ria_peer *next;
32 	struct ria_peer *prev;
33 	ct_socket_t *sock;
34 	struct ria_peer *peer;
35 	ria_device_t device;
36 } ria_peer_t;
37 
38 static unsigned int dev_handle = 1;
39 
40 static ria_peer_t clients = { &clients, &clients };
41 
42 static int ria_svc_accept(ct_socket_t *);
43 static int ria_svc_app_handler(ct_socket_t *, header_t *,
44 			       ct_buf_t *, ct_buf_t *);
45 static int ria_svc_dev_handler(ct_socket_t *, header_t *,
46 			       ct_buf_t *, ct_buf_t *);
47 static void ria_svc_app_close(ct_socket_t *);
48 static void ria_svc_dev_close(ct_socket_t *);
49 static ria_peer_t *ria_peer_new(ct_socket_t *);
50 static void ria_peer_free(ria_peer_t *, int);
51 static ria_peer_t *ria_find_device(const char *, size_t);
52 static void ria_svc_link(ria_peer_t *);
53 static void ria_svc_unlink(ria_peer_t *);
54 
ria_svc_listen(const char * address,int trusted)55 int ria_svc_listen(const char *address, int trusted)
56 {
57 	ct_socket_t *sock;
58 	int rc;
59 
60 	sock = ct_socket_new(1024);
61 	if ((rc = ct_socket_listen(sock, address, 0666)) < 0) {
62 		ct_error("Cannot bind to network address \"%s\"\n", address);
63 		ct_socket_free(sock);
64 		return rc;
65 	}
66 
67 	sock->recv = ria_svc_accept;
68 	sock->send = NULL;
69 	if (trusted) {
70 		sock->process = ria_svc_app_handler;
71 		sock->close = ria_svc_app_close;
72 	} else {
73 		sock->process = ria_svc_dev_handler;
74 		sock->close = ria_svc_dev_close;
75 	}
76 
77 	ct_mainloop_add_socket(sock);
78 	return 0;
79 }
80 
ria_svc_accept(ct_socket_t * listener)81 static int ria_svc_accept(ct_socket_t * listener)
82 {
83 	ria_peer_t *clnt;
84 	ct_socket_t *sock;
85 	int rc;
86 
87 	if (!(sock = ct_socket_accept(listener)))
88 		return 0;
89 
90 	clnt = ria_peer_new(sock);
91 	rc = ct_socket_getpeername(sock,
92 				   clnt->device.address,
93 				   sizeof(clnt->device.address));
94 	if (rc < 0) {
95 		ria_peer_free(clnt, 0);
96 		return rc;
97 	}
98 
99 	ifd_debug(1, "New connection from %s", clnt->device.address);
100 	sock->user_data = clnt;
101 	sock->process = listener->process;
102 	sock->close = listener->close;
103 	return 0;
104 }
105 
ria_svc_app_close(ct_socket_t * sock)106 static void ria_svc_app_close(ct_socket_t * sock)
107 {
108 	ria_peer_t *clnt = (ria_peer_t *) sock->user_data;
109 
110 	ifd_debug(1, "Application on %s closed connection",
111 		  clnt->device.address);
112 	ria_peer_free((ria_peer_t *) sock->user_data, 0);
113 }
114 
ria_svc_dev_close(ct_socket_t * sock)115 static void ria_svc_dev_close(ct_socket_t * sock)
116 {
117 	ria_peer_t *clnt = (ria_peer_t *) sock->user_data;
118 
119 	ifd_debug(1, "Device on %s closed connection", clnt->device.address);
120 	ria_peer_free((ria_peer_t *) sock->user_data, 1);
121 }
122 
123 /*
124  * Process commands from local clients (i.e. those allowed
125  * to claim a device).
126  */
ria_svc_app_handler(ct_socket_t * sock,header_t * hdr,ct_buf_t * args,ct_buf_t * resp)127 static int ria_svc_app_handler(ct_socket_t * sock, header_t * hdr,
128 			       ct_buf_t * args, ct_buf_t * resp)
129 {
130 	unsigned char cmd;
131 	ria_peer_t *clnt, *peer;
132 	int rc;
133 
134 	clnt = (ria_peer_t *) sock->user_data;
135 	ria_print_packet(sock, 2, "app >>", hdr, args);
136 
137 	if (ct_buf_get(args, &cmd, 1) < 0)
138 		return IFD_ERROR_INVALID_MSG;
139 
140 	switch (cmd) {
141 	case RIA_MGR_LIST:
142 		peer = &clients;
143 		ifd_debug(1, "%s requests a device listing",
144 			  clnt->device.address);
145 		while ((peer = peer->next) != &clients) {
146 			if (peer->device.name[0] != '\0')
147 				ct_buf_put(resp, &peer->device,
148 					   sizeof(peer->device));
149 		}
150 		return 0;
151 
152 	case RIA_MGR_INFO:
153 		peer =
154 		    ria_find_device((const char *)ct_buf_head(args),
155 				    ct_buf_avail(args));
156 		if (peer == NULL)
157 			return IFD_ERROR_UNKNOWN_DEVICE;
158 		ct_buf_put(resp, &peer->device, sizeof(peer->device));
159 		return 0;
160 
161 	case RIA_MGR_CLAIM:
162 		peer =
163 		    ria_find_device((const char *)ct_buf_head(args),
164 				    ct_buf_avail(args));
165 		if (peer == NULL)
166 			return IFD_ERROR_UNKNOWN_DEVICE;
167 		if (peer->peer)
168 			return IFD_ERROR_DEVICE_BUSY;
169 		ifd_debug(1, "%s claimed %s device %s/%s",
170 			  clnt->device.address,
171 			  peer->device.type,
172 			  peer->device.address, peer->device.name);
173 		ct_buf_put(resp, &peer->device, sizeof(peer->device));
174 		clnt->peer = peer;
175 		peer->peer = clnt;
176 		return 0;
177 	}
178 
179 	if (cmd < __RIA_PEER_CMD_BASE)
180 		return IFD_ERROR_INVALID_CMD;
181 
182 	/* All subsequent commands require a device */
183 	if ((peer = clnt->peer) == NULL)
184 		return IFD_ERROR_NOT_CONNECTED;
185 
186 	/* Push back the command byte */
187 	ct_buf_push(args, &cmd, 1);
188 	rc = ct_socket_put_packet(peer->sock, hdr, args);
189 
190 	/* Tell the caller not to send a response */
191 	hdr->xid = 0;
192 	return rc;
193 }
194 
195 /*
196  * Process commands from remote clients (i.e. those offering a device).
197  */
ria_svc_dev_handler(ct_socket_t * sock,header_t * hdr,ct_buf_t * args,ct_buf_t * resp)198 static int ria_svc_dev_handler(ct_socket_t * sock, header_t * hdr,
199 			       ct_buf_t * args, ct_buf_t * resp)
200 {
201 	unsigned char cmd;
202 	ria_peer_t *clnt, *peer;
203 	ria_device_t devinfo;
204 	int rc;
205 
206 	clnt = (ria_peer_t *) sock->user_data;
207 	ria_print_packet(sock, 2, "dev <<", hdr, args);
208 
209 	/* bounce response to peer right away */
210 	if (hdr->dest)
211 		goto bounce_to_peer;
212 
213 	if (ct_buf_get(args, &cmd, 1) < 0)
214 		return IFD_ERROR_INVALID_MSG;
215 
216 	switch (cmd) {
217 	case RIA_MGR_REGISTER:
218 		if (clnt->device.name[0])
219 			return IFD_ERROR_INVALID_ARG;
220 		if ((rc = ct_buf_get(args, &devinfo, sizeof(devinfo))) < 0)
221 			return IFD_ERROR_INVALID_ARG;
222 		if (devinfo.type[0] == '\0')
223 			return IFD_ERROR_INVALID_ARG;
224 		/* For security reasons, don't allow the handle counter
225 		 * to wrap around. */
226 		if (dev_handle == 0)
227 			return IFD_ERROR_GENERIC;
228 
229 		memcpy(&devinfo.address, clnt->device.address, RIA_NAME_MAX);
230 		clnt->device = devinfo;
231 		snprintf(clnt->device.handle, RIA_NAME_MAX,
232 			 "%s%u", clnt->device.type, dev_handle++);
233 		ifd_debug(1,
234 			  "%s registered new %s device , handle '%s', name `%s'",
235 			  clnt->device.address, clnt->device.type,
236 			  clnt->device.handle, clnt->device.name);
237 		return 0;
238 	}
239 
240 	if (cmd < __RIA_PEER_CMD_BASE)
241 		return IFD_ERROR_INVALID_CMD;
242 
243 	/* Push back the command byte */
244 	ct_buf_push(args, &cmd, 1);
245 
246       bounce_to_peer:
247 	if ((peer = clnt->peer) == NULL)
248 		return IFD_ERROR_NOT_CONNECTED;
249 
250 	rc = ct_socket_put_packet(peer->sock, hdr, args);
251 
252 	/* Tell the caller not to send a response */
253 	hdr->xid = 0;
254 	return rc;
255 }
256 
ria_peer_new(ct_socket_t * sock)257 static ria_peer_t *ria_peer_new(ct_socket_t * sock)
258 {
259 	ria_peer_t *clnt;
260 
261 	clnt = (ria_peer_t *) calloc(1, sizeof(ria_peer_t));
262 	if (!clnt) {
263 		ct_error("out of memory");
264 		return NULL;
265 	}
266 	clnt->sock = sock;
267 	ria_svc_link(clnt);
268 
269 	return clnt;
270 }
271 
ria_peer_free(ria_peer_t * clnt,int detach_peer)272 static void ria_peer_free(ria_peer_t * clnt, int detach_peer)
273 {
274 	ria_peer_t *peer;
275 
276 	if ((peer = clnt->peer) != NULL) {
277 		if (detach_peer)
278 			shutdown(peer->sock->fd, SHUT_RD);
279 		peer->peer = NULL;
280 	}
281 	if (clnt->device.name[0])
282 		ifd_debug(1, "Removing device `%s' on %s",
283 			  clnt->device.name, clnt->device.address);
284 	ria_svc_unlink(clnt);
285 	memset(clnt, 0, sizeof(*clnt));
286 	free(clnt);
287 }
288 
ria_svc_link(ria_peer_t * clnt)289 static void ria_svc_link(ria_peer_t * clnt)
290 {
291 	ria_peer_t *prev;
292 
293 	prev = clients.prev;
294 	clnt->next = &clients;
295 	clnt->prev = prev;
296 	prev->next = clnt;
297 	clients.prev = clnt;
298 }
299 
ria_find_device(const char * handle,size_t len)300 static ria_peer_t *ria_find_device(const char *handle, size_t len)
301 {
302 	ria_peer_t *peer;
303 
304 	ifd_debug(2, "handle=%*.*s", (int)len, (int)len, handle);
305 
306 	if (len == 0 || len > RIA_NAME_MAX - 1)
307 		return NULL;
308 
309 	peer = &clients;
310 	while ((peer = peer->next) != &clients) {
311 		if (!memcmp(peer->device.handle, handle, len)
312 		    && peer->device.handle[len] == '\0')
313 			return peer;
314 		if (!memcmp(peer->device.name, handle, len)
315 		    && peer->device.name[len] == '\0')
316 			return peer;
317 	}
318 
319 	return NULL;
320 }
321 
ria_svc_unlink(ria_peer_t * clnt)322 static void ria_svc_unlink(ria_peer_t * clnt)
323 {
324 	ria_peer_t *prev, *next;
325 
326 	prev = clnt->prev;
327 	next = clnt->next;
328 	prev->next = next;
329 	next->prev = prev;
330 	clnt->prev = clnt->next = clnt;
331 }
332