pcsc-lite
1.7.4
|
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