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