pcsc-lite  1.8.3
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 6043 2011-10-15 16:44:08Z 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     union
00102     {
00103         struct sockaddr sa;
00104         struct sockaddr_un un;
00105     } sa;
00106 
00107     /*
00108      * Create the common shared connection socket
00109      */
00110     if ((commonSocket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
00111     {
00112         Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
00113             strerror(errno));
00114         return -1;
00115     }
00116 
00117     memset(&sa, 0, sizeof sa);
00118     sa.un.sun_family = AF_UNIX;
00119     strncpy(sa.un.sun_path, PCSCLITE_CSOCK_NAME, sizeof sa.un.sun_path);
00120     (void)remove(PCSCLITE_CSOCK_NAME);
00121 
00122     if (bind(commonSocket, &sa.sa, sizeof sa) < 0)
00123     {
00124         Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
00125             strerror(errno));
00126         return -1;
00127     }
00128 
00129     if (listen(commonSocket, 1) < 0)
00130     {
00131         Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
00132             strerror(errno));
00133         return -1;
00134     }
00135 
00136     /*
00137      * Chmod the public entry channel
00138      */
00139     (void)chmod(PCSCLITE_CSOCK_NAME, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
00140 
00141     return 0;
00142 }
00143 
00156 INTERNAL int32_t ListenExistingSocket(int fd)
00157 {
00158     if (!sd_is_socket(fd, AF_UNIX, SOCK_STREAM, -1))
00159     {
00160         Log1(PCSC_LOG_CRITICAL, "Passed FD is not an UNIX socket");
00161         return -1;
00162     }
00163 
00164     commonSocket = fd;
00165     return 0;
00166 }
00167 
00181 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
00182 #define DO_TIMEOUT
00183 #endif
00184 INTERNAL int32_t ProcessEventsServer(uint32_t *pdwClientID)
00185 {
00186     fd_set read_fd;
00187     int selret;
00188 #ifdef DO_TIMEOUT
00189     struct timeval tv;
00190 
00191     tv.tv_sec = 1;
00192     tv.tv_usec = 0;
00193 #endif
00194 
00195     FD_ZERO(&read_fd);
00196 
00197     /*
00198      * Set up the bit masks for select
00199      */
00200     FD_SET(commonSocket, &read_fd);
00201 
00202     selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
00203         (fd_set *) NULL,
00204 #ifdef DO_TIMEOUT
00205         &tv
00206 #else
00207         NULL
00208 #endif
00209         );
00210 
00211     if (selret < 0)
00212     {
00213         if (EINTR == errno)
00214             return -2;
00215 
00216         Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
00217             strerror(errno));
00218         return -1;
00219     }
00220 
00221     if (selret == 0)
00222         /* timeout. On *BSD only */
00223         return 2;
00224 
00225     /*
00226      * A common pipe packet has arrived - it could be a new application
00227      */
00228     if (FD_ISSET(commonSocket, &read_fd))
00229     {
00230         Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
00231         if (ProcessCommonChannelRequest(pdwClientID) == -1)
00232         {
00233             Log2(PCSC_LOG_ERROR,
00234                 "error in ProcessCommonChannelRequest: %d", *pdwClientID);
00235             return -1;
00236         }
00237     }
00238     else
00239         return -1;
00240 
00241     Log2(PCSC_LOG_DEBUG,
00242         "ProcessCommonChannelRequest detects: %d", *pdwClientID);
00243 
00244     return 0;
00245 }
00246