pcsc-lite  1.8.23
winscard_msg_srv.c
Go to the documentation of this file.
1 /*
2  * MUSCLE SmartCard Development ( http://pcsclite.alioth.debian.org/pcsclite.html )
3  *
4  * Copyright (C) 2001-2004
5  * David Corcoran <corcoran@musclecard.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 Redistribution and use in source and binary forms, with or without
12 modification, are permitted provided that the following conditions
13 are met:
14 
15 1. Redistributions of source code must retain the above copyright
16  notice, this list of conditions and the following disclaimer.
17 2. Redistributions in binary form must reproduce the above copyright
18  notice, this list of conditions and the following disclaimer in the
19  documentation and/or other materials provided with the distribution.
20 3. The name of the author may not be used to endorse or promote products
21  derived from this software without specific prior written permission.
22 
23 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
44 #include "config.h"
45 #include <fcntl.h>
46 #include <unistd.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <sys/socket.h>
50 #include <sys/time.h>
51 #include <sys/un.h>
52 #include <sys/ioctl.h>
53 #include <errno.h>
54 #include <stdio.h>
55 #include <time.h>
56 #include <string.h>
57 #ifdef HAVE_SYS_FILIO_H
58 #include <sys/filio.h>
59 #endif
60 #ifdef USE_LIBSYSTEMD
61 #include <systemd/sd-daemon.h>
62 #endif
63 
64 #include "misc.h"
65 #include "pcscd.h"
66 #include "winscard.h"
67 #include "debuglog.h"
68 #include "winscard_msg.h"
69 
73 static int commonSocket = 0;
74 extern char AraKiri;
75 
87 static int ProcessCommonChannelRequest(/*@out@*/ uint32_t *pdwClientID)
88 {
89  socklen_t clnt_len;
90  int new_sock;
91  struct sockaddr_un clnt_addr;
92 
93  clnt_len = sizeof(clnt_addr);
94 
95  if ((new_sock = accept(commonSocket, (struct sockaddr *) &clnt_addr,
96  &clnt_len)) < 0)
97  {
98  Log2(PCSC_LOG_CRITICAL, "Accept on common socket: %s",
99  strerror(errno));
100  return -1;
101  }
102 
103  *pdwClientID = new_sock;
104 
105  return 0;
106 }
107 
122 INTERNAL int32_t InitializeSocket(void)
123 {
124  union
125  {
126  struct sockaddr sa;
127  struct sockaddr_un un;
128  } sa;
129 
130  /*
131  * Create the common shared connection socket
132  */
133  if ((commonSocket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
134  {
135  Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
136  strerror(errno));
137  return -1;
138  }
139 
140  memset(&sa, 0, sizeof sa);
141  sa.un.sun_family = AF_UNIX;
142  strncpy(sa.un.sun_path, PCSCLITE_CSOCK_NAME, sizeof sa.un.sun_path);
143  (void)remove(PCSCLITE_CSOCK_NAME);
144 
145  if (bind(commonSocket, &sa.sa, sizeof sa) < 0)
146  {
147  Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
148  strerror(errno));
149  return -1;
150  }
151 
152  if (listen(commonSocket, 1) < 0)
153  {
154  Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
155  strerror(errno));
156  return -1;
157  }
158 
159  /*
160  * Chmod the public entry channel
161  */
162  (void)chmod(PCSCLITE_CSOCK_NAME, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
163 
164  return 0;
165 }
166 
179 #ifdef USE_LIBSYSTEMD
180 INTERNAL int32_t ListenExistingSocket(int fd)
181 {
182  if (!sd_is_socket(fd, AF_UNIX, SOCK_STREAM, -1))
183  {
184  Log1(PCSC_LOG_CRITICAL, "Passed FD is not an UNIX socket");
185  return -1;
186  }
187 
188  commonSocket = fd;
189  return 0;
190 }
191 #endif
192 
206 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
207 #define DO_TIMEOUT
208 #endif
209 INTERNAL int32_t ProcessEventsServer(uint32_t *pdwClientID)
210 {
211  fd_set read_fd;
212  int selret;
213 #ifdef DO_TIMEOUT
214  struct timeval tv;
215 
216  tv.tv_sec = 1;
217  tv.tv_usec = 0;
218 #endif
219 
220  FD_ZERO(&read_fd);
221 
222  /*
223  * Set up the bit masks for select
224  */
225  FD_SET(commonSocket, &read_fd);
226 
227  selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
228  (fd_set *) NULL,
229 #ifdef DO_TIMEOUT
230  &tv
231 #else
232  NULL
233 #endif
234  );
235 
236  if (selret < 0)
237  {
238  if (EINTR == errno)
239  return -2;
240 
241  Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
242  strerror(errno));
243  return -1;
244  }
245 
246  if (selret == 0)
247  /* timeout. On *BSD only */
248  return 2;
249 
250  /*
251  * A common pipe packet has arrived - it could be a new application
252  */
253  if (FD_ISSET(commonSocket, &read_fd))
254  {
255  Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
256  if (ProcessCommonChannelRequest(pdwClientID) == -1)
257  {
258  Log2(PCSC_LOG_ERROR,
259  "error in ProcessCommonChannelRequest: %d", *pdwClientID);
260  return -1;
261  }
262  }
263  else
264  return -1;
265 
266  Log2(PCSC_LOG_DEBUG,
267  "ProcessCommonChannelRequest detects: %d", *pdwClientID);
268 
269  return 0;
270 }
271 
static int ProcessCommonChannelRequest(uint32_t *pdwClientID)
Accepts a Client connection.
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)
Acquires a socket passed in from systemd.
This handles smart card reader communications.
This handles debugging.