winscard_msg_srv.c

Go to the documentation of this file.
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 

Generated on Mon Aug 17 01:00:12 2009 for pcsc-lite by  doxygen 1.5.9