00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00021 #include "config.h"
00022 #include <fcntl.h>
00023 #include <unistd.h>
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <sys/socket.h>
00027 #include <sys/time.h>
00028 #include <sys/un.h>
00029 #include <sys/ioctl.h>
00030 #include <errno.h>
00031 #include <stdio.h>
00032 #include <time.h>
00033 #include <string.h>
00034 #ifdef HAVE_SYS_FILIO_H
00035 #include <sys/filio.h>
00036 #endif
00037
00038 #include "misc.h"
00039 #include "pcscd.h"
00040 #include "winscard.h"
00041 #include "debuglog.h"
00042 #include "winscard_msg.h"
00043 #include "sys_generic.h"
00044
00048 static int commonSocket = 0;
00049 extern char AraKiri;
00050 extern char ReCheckSerialReaders;
00051
00064 static int SHMProcessCommonChannelRequest(PDWORD pdwClientID)
00065 {
00066 socklen_t clnt_len;
00067 int new_sock;
00068 struct sockaddr_un clnt_addr;
00069 int one;
00070
00071 clnt_len = sizeof(clnt_addr);
00072
00073 if ((new_sock = accept(commonSocket, (struct sockaddr *) &clnt_addr,
00074 &clnt_len)) < 0)
00075 {
00076 Log2(PCSC_LOG_CRITICAL, "Accept on common socket: %s",
00077 strerror(errno));
00078 return -1;
00079 }
00080
00081 *pdwClientID = new_sock;
00082
00083 one = 1;
00084 if (ioctl(*pdwClientID, FIONBIO, &one) < 0)
00085 {
00086 Log2(PCSC_LOG_CRITICAL, "Error: cannot set socket nonblocking: %s",
00087 strerror(errno));
00088 SYS_CloseFile(*pdwClientID);
00089 *pdwClientID = -1;
00090 return -1;
00091 }
00092
00093 return 0;
00094 }
00095
00110 INTERNAL int SHMInitializeCommonSegment(void)
00111 {
00112 static struct sockaddr_un serv_adr;
00113
00114
00115
00116
00117 if ((commonSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
00118 {
00119 Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
00120 strerror(errno));
00121 return -1;
00122 }
00123
00124 serv_adr.sun_family = AF_UNIX;
00125 strncpy(serv_adr.sun_path, PCSCLITE_CSOCK_NAME,
00126 sizeof(serv_adr.sun_path));
00127 SYS_Unlink(PCSCLITE_CSOCK_NAME);
00128
00129 if (bind(commonSocket, (struct sockaddr *) &serv_adr,
00130 sizeof(serv_adr.sun_family) + strlen(serv_adr.sun_path) + 1) < 0)
00131 {
00132 Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
00133 strerror(errno));
00134 SHMCleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
00135 return -1;
00136 }
00137
00138 if (listen(commonSocket, 1) < 0)
00139 {
00140 Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
00141 strerror(errno));
00142 SHMCleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
00143 return -1;
00144 }
00145
00146
00147
00148
00149 SYS_Chmod(PCSCLITE_CSOCK_NAME, S_IRWXO | S_IRWXG | S_IRWXU);
00150
00151 return 0;
00152 }
00153
00168 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
00169 #define DO_TIMEOUT
00170 #endif
00171 INTERNAL int SHMProcessEventsServer(PDWORD pdwClientID, int blocktime)
00172 {
00173 fd_set read_fd;
00174 int selret;
00175 #ifdef DO_TIMEOUT
00176 struct timeval tv;
00177
00178 tv.tv_sec = 1;
00179 tv.tv_usec = 0;
00180 #endif
00181
00182 FD_ZERO(&read_fd);
00183
00184
00185
00186
00187 FD_SET(commonSocket, &read_fd);
00188
00189 selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
00190 (fd_set *) NULL,
00191 #ifdef DO_TIMEOUT
00192 &tv
00193 #else
00194 NULL
00195 #endif
00196 );
00197
00198 if (selret < 0)
00199 {
00200 if (EINTR == errno)
00201 return -2;
00202
00203 Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
00204 strerror(errno));
00205 return -1;
00206 }
00207
00208 if (selret == 0)
00209
00210 return 2;
00211
00212
00213
00214
00215 if (FD_ISSET(commonSocket, &read_fd))
00216 {
00217 Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
00218 if (SHMProcessCommonChannelRequest(pdwClientID) == -1)
00219 {
00220 Log2(PCSC_LOG_ERROR,
00221 "error in SHMProcessCommonChannelRequest: %d", *pdwClientID);
00222 return -1;
00223 } else
00224 {
00225 Log2(PCSC_LOG_DEBUG,
00226 "SHMProcessCommonChannelRequest detects: %d", *pdwClientID);
00227 return 0;
00228 }
00229 }
00230
00231 return -1;
00232 }
00233
00239 INTERNAL int SHMProcessEventsContext(PDWORD pdwClientID, psharedSegmentMsg msgStruct, int blocktime)
00240 {
00241 fd_set read_fd;
00242 int selret, rv;
00243 struct timeval tv;
00244
00245 tv.tv_sec = 1;
00246 tv.tv_usec = 0;
00247
00248 FD_ZERO(&read_fd);
00249 FD_SET(*pdwClientID, &read_fd);
00250
00251 selret = select(*pdwClientID + 1, &read_fd, (fd_set *) NULL,
00252 (fd_set *) NULL, &tv);
00253
00254 if (selret < 0)
00255 {
00256 Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00257 strerror(errno));
00258 return -1;
00259 }
00260
00261 if (selret == 0)
00262
00263 return 2;
00264
00265 if (FD_ISSET(*pdwClientID, &read_fd))
00266 {
00267
00268
00269
00270 rv = SHMMessageReceive(msgStruct, sizeof(*msgStruct), *pdwClientID,
00271 PCSCLITE_SERVER_ATTEMPTS);
00272
00273 if (rv == -1)
00274 {
00275 Log2(PCSC_LOG_DEBUG, "Client has disappeared: %d",
00276 *pdwClientID);
00277 msgStruct->mtype = CMD_CLIENT_DIED;
00278 msgStruct->command = 0;
00279 SYS_CloseFile(*pdwClientID);
00280
00281 return 0;
00282 }
00283
00284
00285
00286
00287 Log2(PCSC_LOG_DEBUG, "correctly processed client: %d",
00288 *pdwClientID);
00289 return 1;
00290 }
00291
00292 return -1;
00293 }
00294