pcsc-lite  1.8.13
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  * $Id: winscard_msg_srv.c 7004 2014-10-02 09:26:36Z rousseau $
35  */
36 
46 #include "config.h"
47 #include <fcntl.h>
48 #include <unistd.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <sys/socket.h>
52 #include <sys/time.h>
53 #include <sys/un.h>
54 #include <sys/ioctl.h>
55 #include <errno.h>
56 #include <stdio.h>
57 #include <time.h>
58 #include <string.h>
59 #ifdef HAVE_SYS_FILIO_H
60 #include <sys/filio.h>
61 #endif
62 
63 #include "misc.h"
64 #include "pcscd.h"
65 #include "sd-daemon.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 INTERNAL int32_t ListenExistingSocket(int fd)
180 {
181  if (!sd_is_socket(fd, AF_UNIX, SOCK_STREAM, -1))
182  {
183  Log1(PCSC_LOG_CRITICAL, "Passed FD is not an UNIX socket");
184  return -1;
185  }
186 
187  commonSocket = fd;
188  return 0;
189 }
190 
204 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
205 #define DO_TIMEOUT
206 #endif
207 INTERNAL int32_t ProcessEventsServer(uint32_t *pdwClientID)
208 {
209  fd_set read_fd;
210  int selret;
211 #ifdef DO_TIMEOUT
212  struct timeval tv;
213 
214  tv.tv_sec = 1;
215  tv.tv_usec = 0;
216 #endif
217 
218  FD_ZERO(&read_fd);
219 
220  /*
221  * Set up the bit masks for select
222  */
223  FD_SET(commonSocket, &read_fd);
224 
225  selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
226  (fd_set *) NULL,
227 #ifdef DO_TIMEOUT
228  &tv
229 #else
230  NULL
231 #endif
232  );
233 
234  if (selret < 0)
235  {
236  if (EINTR == errno)
237  return -2;
238 
239  Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
240  strerror(errno));
241  return -1;
242  }
243 
244  if (selret == 0)
245  /* timeout. On *BSD only */
246  return 2;
247 
248  /*
249  * A common pipe packet has arrived - it could be a new application
250  */
251  if (FD_ISSET(commonSocket, &read_fd))
252  {
253  Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
254  if (ProcessCommonChannelRequest(pdwClientID) == -1)
255  {
256  Log2(PCSC_LOG_ERROR,
257  "error in ProcessCommonChannelRequest: %d", *pdwClientID);
258  return -1;
259  }
260  }
261  else
262  return -1;
263 
264  Log2(PCSC_LOG_DEBUG,
265  "ProcessCommonChannelRequest detects: %d", *pdwClientID);
266 
267  return 0;
268 }
269 
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.