pcsc-lite  1.7.4
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  * Copyright (C) 2003-2004
00007  *  Damien Sauveron <damien.sauveron@labri.fr>
00008  * Copyright (C) 2002-2010
00009  *  Ludovic Rousseau <ludovic.rousseau@free.fr>
00010  *
00011  * $Id: winscard_msg_srv.c 5391 2010-11-08 14:53:02Z rousseau $
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 "sd-daemon.h"
00043 #include "winscard.h"
00044 #include "debuglog.h"
00045 #include "winscard_msg.h"
00046 
00050 static int commonSocket = 0;
00051 extern char AraKiri;
00052 
00064 static int ProcessCommonChannelRequest(/*@out@*/ uint32_t *pdwClientID)
00065 {
00066     socklen_t clnt_len;
00067     int new_sock;
00068     struct sockaddr_un clnt_addr;
00069 
00070     clnt_len = sizeof(clnt_addr);
00071 
00072     if ((new_sock = accept(commonSocket, (struct sockaddr *) &clnt_addr,
00073                 &clnt_len)) < 0)
00074     {
00075         Log2(PCSC_LOG_CRITICAL, "Accept on common socket: %s",
00076             strerror(errno));
00077         return -1;
00078     }
00079 
00080     *pdwClientID = new_sock;
00081 
00082     return 0;
00083 }
00084 
00099 INTERNAL int32_t InitializeSocket(void)
00100 {
00101     struct sockaddr_un serv_adr;
00102 
00103     /*
00104      * Create the common shared connection socket
00105      */
00106     if ((commonSocket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
00107     {
00108         Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
00109             strerror(errno));
00110         return -1;
00111     }
00112 
00113     serv_adr.sun_family = AF_UNIX;
00114     strncpy(serv_adr.sun_path, PCSCLITE_CSOCK_NAME,
00115         sizeof(serv_adr.sun_path));
00116     (void)remove(PCSCLITE_CSOCK_NAME);
00117 
00118     if (bind(commonSocket, (struct sockaddr *) &serv_adr,
00119             sizeof(serv_adr.sun_family) + strlen(serv_adr.sun_path) + 1) < 0)
00120     {
00121         Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
00122             strerror(errno));
00123         return -1;
00124     }
00125 
00126     if (listen(commonSocket, 1) < 0)
00127     {
00128         Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
00129             strerror(errno));
00130         return -1;
00131     }
00132 
00133     /*
00134      * Chmod the public entry channel
00135      */
00136     (void)chmod(PCSCLITE_CSOCK_NAME, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
00137 
00138     return 0;
00139 }
00140 
00153 INTERNAL int32_t ListenExistingSocket(int fd)
00154 {
00155     if (!sd_is_socket(fd, AF_UNIX, SOCK_STREAM, -1))
00156     {
00157         Log1(PCSC_LOG_CRITICAL, "Passed FD is not an UNIX socket");
00158         return -1;
00159     }
00160 
00161     commonSocket = fd;
00162     return 0;
00163 }
00164 
00178 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
00179 #define DO_TIMEOUT
00180 #endif
00181 INTERNAL int32_t ProcessEventsServer(uint32_t *pdwClientID)
00182 {
00183     fd_set read_fd;
00184     int selret;
00185 #ifdef DO_TIMEOUT
00186     struct timeval tv;
00187 
00188     tv.tv_sec = 1;
00189     tv.tv_usec = 0;
00190 #endif
00191 
00192     FD_ZERO(&read_fd);
00193 
00194     /*
00195      * Set up the bit masks for select
00196      */
00197     FD_SET(commonSocket, &read_fd);
00198 
00199     selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
00200         (fd_set *) NULL,
00201 #ifdef DO_TIMEOUT
00202         &tv
00203 #else
00204         NULL
00205 #endif
00206         );
00207 
00208     if (selret < 0)
00209     {
00210         if (EINTR == errno)
00211             return -2;
00212 
00213         Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
00214             strerror(errno));
00215         return -1;
00216     }
00217 
00218     if (selret == 0)
00219         /* timeout. On *BSD only */
00220         return 2;
00221 
00222     /*
00223      * A common pipe packet has arrived - it could be a new application
00224      */
00225     if (FD_ISSET(commonSocket, &read_fd))
00226     {
00227         Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
00228         if (ProcessCommonChannelRequest(pdwClientID) == -1)
00229         {
00230             Log2(PCSC_LOG_ERROR,
00231                 "error in ProcessCommonChannelRequest: %d", *pdwClientID);
00232             return -1;
00233         }
00234     }
00235     else
00236         return -1;
00237 
00238     Log2(PCSC_LOG_DEBUG,
00239         "ProcessCommonChannelRequest detects: %d", *pdwClientID);
00240 
00241     return 0;
00242 }
00243