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
00052 static const char *CommandsText[] = {
00053 "CMD_VERSION",
00054 "ESTABLISH_CONTEXT",
00055 "RELEASE_CONTEXT",
00056 "LIST_READERS",
00057 "CONNECT",
00058 "RECONNECT",
00059 "DISCONNECT",
00060 "BEGIN_TRANSACTION",
00061 "END_TRANSACTION",
00062 "TRANSMIT",
00063 "CONTROL",
00064 "STATUS",
00065 "GET_STATUS_CHANGE",
00066 "CANCEL",
00067 "CANCEL_TRANSACTION",
00068 "GET_ATTRIB",
00069 "SET_ATTRIB",
00070 "TRANSMIT_EXTENDED",
00071 "CONTROL_EXTENDED",
00072 "NULL"
00073 };
00074
00087 static int SHMProcessCommonChannelRequest( uint32_t *pdwClientID)
00088 {
00089 socklen_t clnt_len;
00090 int new_sock;
00091 struct sockaddr_un clnt_addr;
00092 int one;
00093
00094 clnt_len = sizeof(clnt_addr);
00095
00096 if ((new_sock = accept(commonSocket, (struct sockaddr *) &clnt_addr,
00097 &clnt_len)) < 0)
00098 {
00099 Log2(PCSC_LOG_CRITICAL, "Accept on common socket: %s",
00100 strerror(errno));
00101 return -1;
00102 }
00103
00104 *pdwClientID = new_sock;
00105
00106 one = 1;
00107 if (ioctl(*pdwClientID, FIONBIO, &one) < 0)
00108 {
00109 Log2(PCSC_LOG_CRITICAL, "Error: cannot set socket nonblocking: %s",
00110 strerror(errno));
00111 (void)SYS_CloseFile(*pdwClientID);
00112 *pdwClientID = -1;
00113 return -1;
00114 }
00115
00116 return 0;
00117 }
00118
00133 INTERNAL int32_t SHMInitializeCommonSegment(void)
00134 {
00135 static struct sockaddr_un serv_adr;
00136
00137
00138
00139
00140 if ((commonSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
00141 {
00142 Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
00143 strerror(errno));
00144 return -1;
00145 }
00146
00147 serv_adr.sun_family = AF_UNIX;
00148 strncpy(serv_adr.sun_path, PCSCLITE_CSOCK_NAME,
00149 sizeof(serv_adr.sun_path));
00150 (void)SYS_RemoveFile(PCSCLITE_CSOCK_NAME);
00151
00152 if (bind(commonSocket, (struct sockaddr *) &serv_adr,
00153 sizeof(serv_adr.sun_family) + strlen(serv_adr.sun_path) + 1) < 0)
00154 {
00155 Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
00156 strerror(errno));
00157 SHMCleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
00158 return -1;
00159 }
00160
00161 if (listen(commonSocket, 1) < 0)
00162 {
00163 Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
00164 strerror(errno));
00165 SHMCleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
00166 return -1;
00167 }
00168
00169
00170
00171
00172 (void)SYS_Chmod(PCSCLITE_CSOCK_NAME, S_IRWXO | S_IRWXG | S_IRWXU);
00173
00174 return 0;
00175 }
00176
00190 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
00191 #define DO_TIMEOUT
00192 #endif
00193 INTERNAL int32_t SHMProcessEventsServer(uint32_t *pdwClientID)
00194 {
00195 fd_set read_fd;
00196 int selret;
00197 #ifdef DO_TIMEOUT
00198 struct timeval tv;
00199
00200 tv.tv_sec = 1;
00201 tv.tv_usec = 0;
00202 #endif
00203
00204 FD_ZERO(&read_fd);
00205
00206
00207
00208
00209 FD_SET(commonSocket, &read_fd);
00210
00211 selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
00212 (fd_set *) NULL,
00213 #ifdef DO_TIMEOUT
00214 &tv
00215 #else
00216 NULL
00217 #endif
00218 );
00219
00220 if (selret < 0)
00221 {
00222 if (EINTR == errno)
00223 return -2;
00224
00225 Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
00226 strerror(errno));
00227 return -1;
00228 }
00229
00230 if (selret == 0)
00231
00232 return 2;
00233
00234
00235
00236
00237 if (FD_ISSET(commonSocket, &read_fd))
00238 {
00239 Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
00240 if (SHMProcessCommonChannelRequest(pdwClientID) == -1)
00241 {
00242 Log2(PCSC_LOG_ERROR,
00243 "error in SHMProcessCommonChannelRequest: %d", *pdwClientID);
00244 return -1;
00245 } else
00246 {
00247 Log2(PCSC_LOG_DEBUG,
00248 "SHMProcessCommonChannelRequest detects: %d", *pdwClientID);
00249 return 0;
00250 }
00251 }
00252
00253 return -1;
00254 }
00255
00261 INTERNAL int32_t SHMProcessEventsContext(uint32_t dwClientID,
00262 psharedSegmentMsg msgStruct)
00263 {
00264 fd_set read_fd;
00265 int selret, rv;
00266 #ifdef DO_TIMEOUT
00267 struct timeval tv;
00268
00269 tv.tv_sec = 1;
00270 tv.tv_usec = 0;
00271 #endif
00272
00273 FD_ZERO(&read_fd);
00274 FD_SET(dwClientID, &read_fd);
00275
00276 selret = select(dwClientID + 1, &read_fd, (fd_set *) NULL,
00277 (fd_set *) NULL,
00278 #ifdef DO_TIMEOUT
00279 &tv
00280 #else
00281 NULL
00282 #endif
00283 );
00284
00285 if (selret < 0)
00286 {
00287 Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00288 strerror(errno));
00289 return -1;
00290 }
00291
00292 if (selret == 0)
00293
00294 return 2;
00295
00296 if (FD_ISSET(dwClientID, &read_fd))
00297 {
00298
00299
00300
00301 rv = SHMMessageReceive(msgStruct, sizeof(*msgStruct), dwClientID,
00302 PCSCLITE_SERVER_ATTEMPTS);
00303
00304 if (rv == -1)
00305 {
00306 Log2(PCSC_LOG_DEBUG, "Client has disappeared: %d", dwClientID);
00307 msgStruct->mtype = CMD_CLIENT_DIED;
00308 msgStruct->command = 0;
00309 (void)SYS_CloseFile(dwClientID);
00310
00311 return 0;
00312 }
00313
00314
00315
00316
00317 Log3(PCSC_LOG_DEBUG, "command %s received by client %d", CommandsText[msgStruct->command], dwClientID);
00318 return 1;
00319 }
00320
00321 return -1;
00322 }
00323