pcsc-lite 1.5.5
|
00001 /* 00002 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 00003 * 00004 * Copyright (C) 2001-2004 00005 * David Corcoran <corcoran@linuxnet.com> 00006 * Damien Sauveron <damien.sauveron@labri.fr> 00007 * Ludoic Rousseau <ludovic.rousseau@free.fr> 00008 * 00009 * $Id: winscard_msg_srv.c 3260 2009-01-02 15:19:59Z rousseau $ 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", /* mtype = 0xF8 and command = 0x00 */ 00054 "ESTABLISH_CONTEXT", /* mtype = 0xF1 */ 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(/*@out@*/ 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 * Create the common shared connection socket 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 * Chmod the public entry channel 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 * Set up the bit masks for select 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 /* timeout. On *BSD only */ 00232 return 2; 00233 00234 /* 00235 * A common pipe packet has arrived - it could be a new application 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 /* timeout */ 00294 return 2; 00295 00296 if (FD_ISSET(dwClientID, &read_fd)) 00297 { 00298 /* 00299 * Return the current handle 00300 */ 00301 rv = SHMMessageReceive(msgStruct, sizeof(*msgStruct), dwClientID, 00302 PCSCLITE_SERVER_ATTEMPTS); 00303 00304 if (rv == -1) 00305 { /* The client has died */ 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 * Set the identifier handle 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