pcsc-lite  1.8.8
winscard_msg_srv.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://www.linuxnet.com )
3  *
4  * Copyright (C) 2001-2004
5  * David Corcoran <corcoran@linuxnet.com>
6  * Copyright (C) 2003-2004
7  * Damien Sauveron <damien.sauveron@labri.fr>
8  * Copyright (C) 2002-2010
9  * Ludovic Rousseau <ludovic.rousseau@free.fr>
10  *
11  * $Id: winscard_msg_srv.c 6043 2011-10-15 16:44:08Z rousseau $
12  */
13 
23 #include "config.h"
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/socket.h>
29 #include <sys/time.h>
30 #include <sys/un.h>
31 #include <sys/ioctl.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <time.h>
35 #include <string.h>
36 #ifdef HAVE_SYS_FILIO_H
37 #include <sys/filio.h>
38 #endif
39 
40 #include "misc.h"
41 #include "pcscd.h"
42 #include "sd-daemon.h"
43 #include "winscard.h"
44 #include "debuglog.h"
45 #include "winscard_msg.h"
46 
50 static int commonSocket = 0;
51 extern char AraKiri;
52 
64 static int ProcessCommonChannelRequest(/*@out@*/ uint32_t *pdwClientID)
65 {
66  socklen_t clnt_len;
67  int new_sock;
68  struct sockaddr_un clnt_addr;
69 
70  clnt_len = sizeof(clnt_addr);
71 
72  if ((new_sock = accept(commonSocket, (struct sockaddr *) &clnt_addr,
73  &clnt_len)) < 0)
74  {
75  Log2(PCSC_LOG_CRITICAL, "Accept on common socket: %s",
76  strerror(errno));
77  return -1;
78  }
79 
80  *pdwClientID = new_sock;
81 
82  return 0;
83 }
84 
99 INTERNAL int32_t InitializeSocket(void)
100 {
101  union
102  {
103  struct sockaddr sa;
104  struct sockaddr_un un;
105  } sa;
106 
107  /*
108  * Create the common shared connection socket
109  */
110  if ((commonSocket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
111  {
112  Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
113  strerror(errno));
114  return -1;
115  }
116 
117  memset(&sa, 0, sizeof sa);
118  sa.un.sun_family = AF_UNIX;
119  strncpy(sa.un.sun_path, PCSCLITE_CSOCK_NAME, sizeof sa.un.sun_path);
120  (void)remove(PCSCLITE_CSOCK_NAME);
121 
122  if (bind(commonSocket, &sa.sa, sizeof sa) < 0)
123  {
124  Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
125  strerror(errno));
126  return -1;
127  }
128 
129  if (listen(commonSocket, 1) < 0)
130  {
131  Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
132  strerror(errno));
133  return -1;
134  }
135 
136  /*
137  * Chmod the public entry channel
138  */
139  (void)chmod(PCSCLITE_CSOCK_NAME, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
140 
141  return 0;
142 }
143 
156 INTERNAL int32_t ListenExistingSocket(int fd)
157 {
158  if (!sd_is_socket(fd, AF_UNIX, SOCK_STREAM, -1))
159  {
160  Log1(PCSC_LOG_CRITICAL, "Passed FD is not an UNIX socket");
161  return -1;
162  }
163 
164  commonSocket = fd;
165  return 0;
166 }
167 
181 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
182 #define DO_TIMEOUT
183 #endif
184 INTERNAL int32_t ProcessEventsServer(uint32_t *pdwClientID)
185 {
186  fd_set read_fd;
187  int selret;
188 #ifdef DO_TIMEOUT
189  struct timeval tv;
190 
191  tv.tv_sec = 1;
192  tv.tv_usec = 0;
193 #endif
194 
195  FD_ZERO(&read_fd);
196 
197  /*
198  * Set up the bit masks for select
199  */
200  FD_SET(commonSocket, &read_fd);
201 
202  selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
203  (fd_set *) NULL,
204 #ifdef DO_TIMEOUT
205  &tv
206 #else
207  NULL
208 #endif
209  );
210 
211  if (selret < 0)
212  {
213  if (EINTR == errno)
214  return -2;
215 
216  Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
217  strerror(errno));
218  return -1;
219  }
220 
221  if (selret == 0)
222  /* timeout. On *BSD only */
223  return 2;
224 
225  /*
226  * A common pipe packet has arrived - it could be a new application
227  */
228  if (FD_ISSET(commonSocket, &read_fd))
229  {
230  Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
231  if (ProcessCommonChannelRequest(pdwClientID) == -1)
232  {
233  Log2(PCSC_LOG_ERROR,
234  "error in ProcessCommonChannelRequest: %d", *pdwClientID);
235  return -1;
236  }
237  }
238  else
239  return -1;
240 
241  Log2(PCSC_LOG_DEBUG,
242  "ProcessCommonChannelRequest detects: %d", *pdwClientID);
243 
244  return 0;
245 }
246 
static int ProcessCommonChannelRequest(uint32_t *pdwClientID)
Accepts a Client connection.
INTERNAL int32_t ListenExistingSocket(int fd)
Acquires a socket passed in from systemd.
This defines some structures and #defines to be used over the transport layer.
INTERNAL int32_t InitializeSocket(void)
Prepares the communication channel used by the server to talk to the clients.
static int commonSocket
Socket to a file, used for clients-server comminication.
This keeps a list of defines for pcsc-lite.
INTERNAL int32_t ProcessEventsServer(uint32_t *pdwClientID)
Looks for messages sent by clients.
This handles smart card reader communications.
This handles debugging.