00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00023 #include "config.h"
00024 #include <fcntl.h>
00025 #include <unistd.h>
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <sys/socket.h>
00029 #include <sys/time.h>
00030 #include <sys/un.h>
00031 #include <sys/ioctl.h>
00032 #include <errno.h>
00033 #include <stdio.h>
00034 #include <time.h>
00035 #include <string.h>
00036 #ifdef HAVE_SYS_FILIO_H
00037 #include <sys/filio.h>
00038 #endif
00039
00040 #include "misc.h"
00041 #include "pcscd.h"
00042 #include "winscard.h"
00043 #include "debuglog.h"
00044 #include "winscard_msg.h"
00045 #include "sys_generic.h"
00046 #include "utils.h"
00047
00061 INTERNAL int ClientSetupSession(uint32_t *pdwClientID)
00062 {
00063 struct sockaddr_un svc_addr;
00064 int one;
00065 int ret;
00066
00067 ret = socket(PF_UNIX, SOCK_STREAM, 0);
00068 if (ret < 0)
00069 {
00070 Log2(PCSC_LOG_CRITICAL, "Error: create on client socket: %s",
00071 strerror(errno));
00072 return -1;
00073 }
00074 *pdwClientID = ret;
00075
00076 svc_addr.sun_family = AF_UNIX;
00077 strncpy(svc_addr.sun_path, PCSCLITE_CSOCK_NAME,
00078 sizeof(svc_addr.sun_path));
00079
00080 if (connect(*pdwClientID, (struct sockaddr *) &svc_addr,
00081 sizeof(svc_addr.sun_family) + strlen(svc_addr.sun_path) + 1) < 0)
00082 {
00083 Log3(PCSC_LOG_CRITICAL, "Error: connect to client socket %s: %s",
00084 PCSCLITE_CSOCK_NAME, strerror(errno));
00085 (void)close(*pdwClientID);
00086 return -1;
00087 }
00088
00089 one = 1;
00090 if (ioctl(*pdwClientID, FIONBIO, &one) < 0)
00091 {
00092 Log3(PCSC_LOG_CRITICAL, "Error: cannot set socket %s nonblocking: %s",
00093 PCSCLITE_CSOCK_NAME, strerror(errno));
00094 (void)close(*pdwClientID);
00095 return -1;
00096 }
00097
00098 return 0;
00099 }
00100
00108 INTERNAL int ClientCloseSession(uint32_t dwClientID)
00109 {
00110 return close(dwClientID);
00111 }
00112
00128 INTERNAL int32_t MessageSend(void *buffer_void, uint64_t buffer_size,
00129 int32_t filedes)
00130 {
00131 char *buffer = buffer_void;
00132
00133
00134 int retval = 0;
00135
00136
00137 size_t remaining = buffer_size;
00138
00139
00140 while (remaining > 0)
00141 {
00142 fd_set write_fd;
00143 int selret;
00144
00145 FD_ZERO(&write_fd);
00146 FD_SET(filedes, &write_fd);
00147
00148 selret = select(filedes + 1, NULL, &write_fd, NULL, NULL);
00149
00150
00151 if (selret > 0)
00152 {
00153 int written;
00154
00155 if (!FD_ISSET(filedes, &write_fd))
00156 {
00157
00158 retval = -1;
00159 break;
00160 }
00161
00162
00163 #ifdef MSG_NOSIGNAL
00164
00165
00166 written = send(filedes, buffer, remaining, MSG_NOSIGNAL);
00167 #else
00168
00169 written = write(filedes, buffer, remaining);
00170 #endif
00171
00172 if (written > 0)
00173 {
00174
00175 buffer += written;
00176 remaining -= written;
00177 } else if (written == 0)
00178 {
00179
00180 retval = -1;
00181 break;
00182 } else
00183 {
00184
00185
00186 if (errno != EINTR && errno != EAGAIN)
00187 {
00188 retval = -1;
00189 break;
00190 }
00191 }
00192 } else if (selret == 0)
00193 {
00194
00195 retval = -1;
00196 break;
00197 } else
00198 {
00199
00200 if (errno != EINTR)
00201 {
00202 Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00203 strerror(errno));
00204 retval = -1;
00205 break;
00206 }
00207 }
00208 }
00209
00210 return retval;
00211 }
00212
00226 INTERNAL int32_t MessageReceive(void *buffer_void, uint64_t buffer_size,
00227 int32_t filedes)
00228 {
00229 char *buffer = buffer_void;
00230
00231
00232 int retval = 0;
00233
00234
00235 size_t remaining = buffer_size;
00236
00237
00238 while (remaining > 0)
00239 {
00240 fd_set read_fd;
00241 int selret;
00242
00243 FD_ZERO(&read_fd);
00244 FD_SET(filedes, &read_fd);
00245
00246 selret = select(filedes + 1, &read_fd, NULL, NULL, NULL);
00247
00248
00249 if (selret > 0)
00250 {
00251 int readed;
00252
00253 if (!FD_ISSET(filedes, &read_fd))
00254 {
00255
00256 retval = -1;
00257 break;
00258 }
00259 readed = read(filedes, buffer, remaining);
00260
00261 if (readed > 0)
00262 {
00263
00264 buffer += readed;
00265 remaining -= readed;
00266 } else if (readed == 0)
00267 {
00268
00269 retval = -1;
00270 break;
00271 } else
00272 {
00273
00274
00275 if (errno != EINTR && errno != EAGAIN)
00276 {
00277 retval = -1;
00278 break;
00279 }
00280 }
00281 }
00282 else
00283 {
00284
00285 if (errno != EINTR)
00286 {
00287 Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00288 strerror(errno));
00289 retval = -1;
00290 break;
00291 }
00292 }
00293 }
00294
00295 return retval;
00296 }
00297
00314 INTERNAL int32_t MessageReceiveTimeout(uint32_t command, void *buffer_void,
00315 uint64_t buffer_size, int32_t filedes, int32_t timeOut)
00316 {
00317 char *buffer = buffer_void;
00318
00319
00320 int retval = 0;
00321
00322
00323 struct timeval start;
00324
00325
00326 size_t remaining = buffer_size;
00327
00328 gettimeofday(&start, NULL);
00329
00330
00331 while (remaining > 0)
00332 {
00333 fd_set read_fd;
00334 struct timeval timeout, now;
00335 int selret;
00336 long delta;
00337
00338 gettimeofday(&now, NULL);
00339 delta = time_sub(&now, &start);
00340
00341 if (delta > timeOut*1000)
00342 {
00343
00344 retval = -2;
00345 break;
00346 }
00347
00348
00349 delta = timeOut*1000 - delta;
00350
00351 FD_ZERO(&read_fd);
00352 FD_SET(filedes, &read_fd);
00353
00354 timeout.tv_sec = delta/1000000;
00355 timeout.tv_usec = delta - timeout.tv_sec*1000000;
00356
00357 selret = select(filedes + 1, &read_fd, NULL, NULL, &timeout);
00358
00359
00360 if (selret > 0)
00361 {
00362 int readed;
00363
00364 if (!FD_ISSET(filedes, &read_fd))
00365 {
00366
00367 retval = -1;
00368 break;
00369 }
00370 readed = read(filedes, buffer, remaining);
00371
00372 if (readed > 0)
00373 {
00374
00375 buffer += readed;
00376 remaining -= readed;
00377 } else if (readed == 0)
00378 {
00379
00380 retval = -1;
00381 break;
00382 } else
00383 {
00384
00385
00386 if (errno != EINTR && errno != EAGAIN)
00387 {
00388 retval = -1;
00389 break;
00390 }
00391 }
00392 } else if (selret == 0)
00393 {
00394 #ifdef PCSCD
00395 (void)command;
00396
00397
00398 retval = -1;
00399 break;
00400 #else
00401
00402 if (SCardCheckDaemonAvailability() != SCARD_S_SUCCESS)
00403 {
00404
00405 retval = -1;
00406 break;
00407 }
00408
00409
00410
00411
00412 Log2(PCSC_LOG_INFO, "Command 0x%X not yet finished", command);
00413 #endif
00414 } else
00415 {
00416
00417 if (errno != EINTR)
00418 {
00419 Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
00420 strerror(errno));
00421 retval = -1;
00422 break;
00423 }
00424 }
00425 }
00426
00427 return retval;
00428 }
00429
00445 INTERNAL int32_t MessageSendWithHeader(uint32_t command, uint32_t dwClientID,
00446 uint64_t size, void *data_void)
00447 {
00448 struct rxHeader header;
00449 int ret;
00450
00451
00452 header.command = command;
00453 header.size = size;
00454 ret = MessageSend(&header, sizeof(header), dwClientID);
00455
00456
00457 ret = MessageSend(data_void, size, dwClientID);
00458
00459 return ret;
00460 }
00461
00471 INTERNAL void CleanupSharedSegment(int sockValue, const char *pcFilePath)
00472 {
00473 (void)close(sockValue);
00474 (void)remove(pcFilePath);
00475 }
00476