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 "pcsclite.h"
00040 #include "winscard.h"
00041 #include "debug.h"
00042 #include "winscard_msg.h"
00043 #include "sys_generic.h"
00044
00056 INTERNAL int SHMClientRead(psharedSegmentMsg msgStruct, DWORD dwClientID, int blockamount)
00057 {
00058 return SHMMessageReceive(msgStruct, sizeof(*msgStruct), dwClientID, blockamount);
00059 }
00060
00074 INTERNAL int SHMClientSetupSession(PDWORD pdwClientID)
00075 {
00076 struct sockaddr_un svc_addr;
00077 int one;
00078 int ret;
00079
00080 ret = socket(AF_UNIX, SOCK_STREAM, 0);
00081 if (ret < 0)
00082 {
00083 Log2(PCSC_LOG_CRITICAL, "Error: create on client socket: %s",
00084 strerror(errno));
00085 return -1;
00086 }
00087 *pdwClientID = ret;
00088
00089 svc_addr.sun_family = AF_UNIX;
00090 strncpy(svc_addr.sun_path, PCSCLITE_CSOCK_NAME,
00091 sizeof(svc_addr.sun_path));
00092
00093 if (connect(*pdwClientID, (struct sockaddr *) &svc_addr,
00094 sizeof(svc_addr.sun_family) + strlen(svc_addr.sun_path) + 1) < 0)
00095 {
00096 Log2(PCSC_LOG_CRITICAL, "Error: connect to client socket: %s",
00097 strerror(errno));
00098 SYS_CloseFile(*pdwClientID);
00099 return -1;
00100 }
00101
00102 one = 1;
00103 if (ioctl(*pdwClientID, FIONBIO, &one) < 0)
00104 {
00105 Log2(PCSC_LOG_CRITICAL, "Error: cannot set socket nonblocking: %s",
00106 strerror(errno));
00107 SYS_CloseFile(*pdwClientID);
00108 return -1;
00109 }
00110
00111 return 0;
00112 }
00113
00121 INTERNAL int SHMClientCloseSession(DWORD dwClientID)
00122 {
00123 SYS_CloseFile(dwClientID);
00124 return 0;
00125 }
00126
00142 INTERNAL int SHMMessageSend(void *buffer_void, size_t buffer_size,
00143 int filedes, int blockAmount)
00144 {
00145 char *buffer = buffer_void;
00146
00147
00148
00149
00150 int retval = 0;
00151
00152
00153
00154 time_t start = time(0);
00155
00156
00157
00158 size_t remaining = buffer_size;
00159
00160
00161
00162
00163 while (remaining > 0)
00164 {
00165 fd_set write_fd;
00166 struct timeval timeout;
00167 int selret;
00168
00169 FD_ZERO(&write_fd);
00170 FD_SET(filedes, &write_fd);
00171
00172 timeout.tv_usec = 0;
00173 if ((timeout.tv_sec = start + blockAmount - time(0)) < 0)
00174 {
00175
00176
00177
00178 retval = -1;
00179 break;
00180 }
00181
00182 selret = select(filedes + 1, NULL, &write_fd, NULL, &timeout);
00183
00184
00185
00186
00187 if (selret > 0)
00188 {
00189 int written;
00190
00191 if (!FD_ISSET(filedes, &write_fd))
00192 {
00193
00194
00195
00196 retval = -1;
00197 break;
00198 }
00199 written = write(filedes, buffer, remaining);
00200
00201 if (written > 0)
00202 {
00203
00204
00205
00206 buffer += written;
00207 remaining -= written;
00208 } else if (written == 0)
00209 {
00210
00211
00212
00213 retval = -1;
00214 break;
00215 } else
00216 {
00217
00218
00219
00220
00221 if (errno != EINTR && errno != EAGAIN)
00222 {
00223 retval = -1;
00224 break;
00225 }
00226 }
00227 } else if (selret == 0)
00228 {
00229
00230
00231
00232 retval = -1;
00233 break;
00234 } else
00235 {
00236
00237
00238
00239 if (errno != EINTR)
00240 {
00241 Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00242 strerror(errno));
00243 retval = -1;
00244 break;
00245 }
00246 }
00247 }
00248
00249 return retval;
00250 }
00251
00267 INTERNAL int SHMMessageReceive(void *buffer_void, size_t buffer_size,
00268 int filedes, int blockAmount)
00269 {
00270 char *buffer = buffer_void;
00271
00272
00273
00274
00275 int retval = 0;
00276
00277
00278
00279 time_t start = time(0);
00280
00281
00282
00283 size_t remaining = buffer_size;
00284
00285
00286
00287
00288 while (remaining > 0)
00289 {
00290 fd_set read_fd;
00291 struct timeval timeout;
00292 int selret;
00293
00294 FD_ZERO(&read_fd);
00295 FD_SET(filedes, &read_fd);
00296
00297 timeout.tv_usec = 0;
00298 if ((timeout.tv_sec = start + blockAmount - time(0)) < 0)
00299 {
00300
00301
00302
00303 retval = -1;
00304 break;
00305 }
00306
00307 selret = select(filedes + 1, &read_fd, NULL, NULL, &timeout);
00308
00309
00310
00311
00312 if (selret > 0)
00313 {
00314 int readed;
00315
00316 if (!FD_ISSET(filedes, &read_fd))
00317 {
00318
00319
00320
00321 retval = -1;
00322 break;
00323 }
00324 readed = read(filedes, buffer, remaining);
00325
00326 if (readed > 0)
00327 {
00328
00329
00330
00331 buffer += readed;
00332 remaining -= readed;
00333 } else if (readed == 0)
00334 {
00335
00336
00337
00338 retval = -1;
00339 break;
00340 } else
00341 {
00342
00343
00344
00345
00346 if (errno != EINTR && errno != EAGAIN)
00347 {
00348 retval = -1;
00349 break;
00350 }
00351 }
00352 } else if (selret == 0)
00353 {
00354
00355
00356
00357 retval = -1;
00358 break;
00359 } else
00360 {
00361
00362
00363
00364 if (errno != EINTR)
00365 {
00366 Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00367 strerror(errno));
00368 retval = -1;
00369 break;
00370 }
00371 }
00372 }
00373
00374 return retval;
00375 }
00376
00392 INTERNAL int WrapSHMWrite(unsigned int command, DWORD dwClientID,
00393 unsigned int size, unsigned int blockAmount, void *data_void)
00394 {
00395 char *data = data_void;
00396
00397 sharedSegmentMsg msgStruct;
00398 int ret;
00399
00400
00401
00402
00403
00404 memset(&msgStruct, 0, sizeof(msgStruct));
00405 msgStruct.mtype = CMD_FUNCTION;
00406 msgStruct.user_id = SYS_GetUID();
00407 msgStruct.group_id = SYS_GetGID();
00408 msgStruct.command = command;
00409 msgStruct.date = time(NULL);
00410 if ((SCARD_TRANSMIT_EXTENDED == command)
00411 || (SCARD_CONTROL_EXTENDED == command))
00412 {
00413
00414 memcpy(msgStruct.data, data, PCSCLITE_MAX_MESSAGE_SIZE);
00415 ret = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
00416 blockAmount);
00417 if (ret)
00418 return ret;
00419
00420
00421 if (size > PCSCLITE_MAX_MESSAGE_SIZE)
00422 {
00423
00424 ret = SHMMessageSend(data+PCSCLITE_MAX_MESSAGE_SIZE,
00425 size-PCSCLITE_MAX_MESSAGE_SIZE, dwClientID, blockAmount);
00426 if (ret)
00427 return ret;
00428 }
00429 }
00430 else
00431 {
00432 memcpy(msgStruct.data, data, size);
00433
00434 ret = SHMMessageSend(&msgStruct, sizeof(msgStruct), dwClientID,
00435 blockAmount);
00436 }
00437 return ret;
00438 }
00439
00449 INTERNAL void SHMCleanupSharedSegment(int sockValue, const char *pcFilePath)
00450 {
00451 SYS_CloseFile(sockValue);
00452 SYS_Unlink(pcFilePath);
00453 }
00454