~ubuntu-branches/ubuntu/jaunty/pcsc-lite/jaunty-security

« back to all changes in this revision

Viewing changes to src/winscard_msg_srv.c

  • Committer: Bazaar Package Importer
  • Author(s): Ludovic Rousseau
  • Date: 2005-11-27 18:04:59 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051127180459-qrex2gzpq9d8jexd
Tags: 1.2.9-beta9-1
* New upstream version
* debian/compat: change from 3 to 4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * MUSCLE SmartCard Development ( http://www.linuxnet.com )
 
3
 *
 
4
 * Copyright (C) 2001-2004
 
5
 *  David Corcoran <corcoran@linuxnet.com>
 
6
 *  Damien Sauveron <damien.sauveron@labri.fr>
 
7
 *  Ludoic Rousseau <ludovic.rousseau@free.fr>
 
8
 *
 
9
 * $Id: winscard_msg_srv.c,v 1.2 2005-11-27 17:08:31 rousseau Exp $
 
10
 */
 
11
 
 
12
/**
 
13
 * @file
 
14
 * @brief client/server communication (on the server side only)
 
15
 *
 
16
 * A file based socket (\c commonSocket) is used to send/receive only messages 
 
17
 * among clients and server.\n
 
18
 * The messages' data are passed throw a memory mapped file: \c sharedSegmentMsg.
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
#include <fcntl.h>
 
23
#include <unistd.h>
 
24
#include <sys/types.h>
 
25
#include <sys/stat.h>
 
26
#include <sys/socket.h>
 
27
#include <sys/time.h>
 
28
#include <sys/un.h>
 
29
#include <sys/ioctl.h>
 
30
#include <errno.h>
 
31
#include <stdio.h>
 
32
#include <time.h>
 
33
#include <string.h>
 
34
#ifdef HAVE_SYS_FILIO_H
 
35
#include <sys/filio.h>
 
36
#endif
 
37
 
 
38
#include "pcsclite.h"
 
39
#include "winscard.h"
 
40
#include "debuglog.h"
 
41
#include "winscard_msg.h"
 
42
#include "sys_generic.h"
 
43
#include "misc.h"
 
44
 
 
45
/**
 
46
 * Socket to a file, used for clients-server comminication.
 
47
 */
 
48
static int commonSocket = 0;
 
49
extern char AraKiri;
 
50
extern char ReCheckSerialReaders;
 
51
 
 
52
/**
 
53
 * @brief Accepts a Client connection.
 
54
 *
 
55
 * Called by \c SHMProcessEventsServer().
 
56
 *
 
57
 * @param[out] pdwClientID Connection ID used to reference the Client.
 
58
 *
 
59
 * @return Error code.
 
60
 * @retval 0 Success.
 
61
 * @retval -1 Can not establish the connection.
 
62
 * @retval -1 Can not set the connection to non-blocking mode.
 
63
 */
 
64
static int SHMProcessCommonChannelRequest(PDWORD pdwClientID)
 
65
{
 
66
        socklen_t clnt_len;
 
67
        int new_sock;
 
68
        struct sockaddr_un clnt_addr;
 
69
        int one;
 
70
 
 
71
        clnt_len = sizeof(clnt_addr);
 
72
 
 
73
        if ((new_sock = accept(commonSocket, (struct sockaddr *) &clnt_addr,
 
74
                                &clnt_len)) < 0)
 
75
        {
 
76
                Log2(PCSC_LOG_CRITICAL, "Accept on common socket: %s",
 
77
                        strerror(errno));
 
78
                return -1;
 
79
        }
 
80
 
 
81
        *pdwClientID = new_sock;
 
82
 
 
83
        one = 1;
 
84
        if (ioctl(*pdwClientID, FIONBIO, &one) < 0)
 
85
        {
 
86
                Log2(PCSC_LOG_CRITICAL, "Error: cannot set socket nonblocking: %s",
 
87
                        strerror(errno));
 
88
                SYS_CloseFile(*pdwClientID);
 
89
                *pdwClientID = -1;
 
90
                return -1;
 
91
        }
 
92
 
 
93
        return 0;
 
94
}
 
95
 
 
96
/**
 
97
 * @brief Prepares the communication channel used by the server to talk to the
 
98
 * clients.
 
99
 *
 
100
 * This is called by the server to create a socket for local IPC with the
 
101
 * clients. The socket is associated to the file \c PCSCLITE_CSOCK_NAME.
 
102
 * Each client will open a connection to this socket.
 
103
 * 
 
104
 * @return Error code.
 
105
 * @retval 0 Success
 
106
 * @retval -1 Can not create the socket.
 
107
 * @retval -1 Can not bind the socket to the file \c PCSCLITE_CSOCK_NAME.
 
108
 * @retval -1 Can not put the socket in listen mode.
 
109
 */
 
110
INTERNAL int SHMInitializeCommonSegment(void)
 
111
{
 
112
        static struct sockaddr_un serv_adr;
 
113
 
 
114
        /*
 
115
         * Create the common shared connection socket 
 
116
         */
 
117
        if ((commonSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
 
118
        {
 
119
                Log2(PCSC_LOG_CRITICAL, "Unable to create common socket: %s",
 
120
                        strerror(errno));
 
121
                return -1;
 
122
        }
 
123
 
 
124
        serv_adr.sun_family = AF_UNIX;
 
125
        strncpy(serv_adr.sun_path, PCSCLITE_CSOCK_NAME,
 
126
                sizeof(serv_adr.sun_path));
 
127
        SYS_Unlink(PCSCLITE_CSOCK_NAME);
 
128
 
 
129
        if (bind(commonSocket, (struct sockaddr *) &serv_adr,
 
130
                        sizeof(serv_adr.sun_family) + strlen(serv_adr.sun_path) + 1) < 0)
 
131
        {
 
132
                Log2(PCSC_LOG_CRITICAL, "Unable to bind common socket: %s",
 
133
                        strerror(errno));
 
134
                SHMCleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
 
135
                return -1;
 
136
        }
 
137
 
 
138
        if (listen(commonSocket, 1) < 0)
 
139
        {
 
140
                Log2(PCSC_LOG_CRITICAL, "Unable to listen common socket: %s",
 
141
                        strerror(errno));
 
142
                SHMCleanupSharedSegment(commonSocket, PCSCLITE_CSOCK_NAME);
 
143
                return -1;
 
144
        }
 
145
 
 
146
        /*
 
147
         * Chmod the public entry channel 
 
148
         */
 
149
        SYS_Chmod(PCSCLITE_CSOCK_NAME, S_IRWXO | S_IRWXG | S_IRWXU);
 
150
 
 
151
        return 0;
 
152
}
 
153
 
 
154
/**
 
155
 * @brief Looks for messages sent by clients.
 
156
 *
 
157
 * This is called by the Server's function \c SVCServiceRunLoop().
 
158
 *
 
159
 * @param[out] pdwClientID Connection ID used to reference the Client.
 
160
 * @param[in] blocktime Timeout (not used).
 
161
 *
 
162
 * @return Error code.
 
163
 * @retval 0 Success.
 
164
 * @retval -1 Error accessing the communication channel.
 
165
 * @retval -1 Can not set the connection to non-blocking mode.
 
166
 * @retval 2 Timeout.
 
167
 */
 
168
INTERNAL int SHMProcessEventsServer(PDWORD pdwClientID, int blocktime)
 
169
{
 
170
        fd_set read_fd;
 
171
        int selret;
 
172
        struct timeval tv;
 
173
        
 
174
        tv.tv_sec = 1;
 
175
        tv.tv_usec = 0;
 
176
 
 
177
        FD_ZERO(&read_fd);
 
178
 
 
179
        /*
 
180
         * Set up the bit masks for select 
 
181
         */
 
182
        FD_SET(commonSocket, &read_fd);
 
183
 
 
184
        selret = select(commonSocket + 1, &read_fd, (fd_set *) NULL,
 
185
                (fd_set *) NULL, &tv);
 
186
 
 
187
        if (selret < 0)
 
188
        {
 
189
                if ((!AraKiri) && (!ReCheckSerialReaders))
 
190
                        Log2(PCSC_LOG_CRITICAL, "Select returns with failure: %s",
 
191
                                strerror(errno));
 
192
                return -1;
 
193
        }
 
194
 
 
195
        if (selret == 0)
 
196
                /* timeout */
 
197
                return 2;
 
198
        /*
 
199
         * A common pipe packet has arrived - it could be a new application  
 
200
         */
 
201
        if (FD_ISSET(commonSocket, &read_fd))
 
202
        {
 
203
                Log1(PCSC_LOG_DEBUG, "Common channel packet arrival");
 
204
                if (SHMProcessCommonChannelRequest(pdwClientID) == -1)
 
205
                {
 
206
                        Log2(PCSC_LOG_ERROR,
 
207
                                "error in SHMProcessCommonChannelRequest: %d", *pdwClientID);
 
208
                        return -1;
 
209
                } else
 
210
                {
 
211
                        Log2(PCSC_LOG_DEBUG,
 
212
                                "SHMProcessCommonChannelRequest detects: %d", *pdwClientID);
 
213
                        return 0;
 
214
                }
 
215
        }
 
216
        
 
217
        return -1;
 
218
}
 
219
 
 
220
/**
 
221
 * @brief 
 
222
 *
 
223
 * Called by \c ContextThread().
 
224
 */
 
225
INTERNAL int SHMProcessEventsContext(PDWORD pdwClientID, psharedSegmentMsg msgStruct, int blocktime)
 
226
{
 
227
        fd_set read_fd;
 
228
        int selret, rv;
 
229
        struct timeval tv;
 
230
 
 
231
        tv.tv_sec = 1;
 
232
        tv.tv_usec = 0;
 
233
 
 
234
        FD_ZERO(&read_fd);
 
235
        FD_SET(*pdwClientID, &read_fd);
 
236
 
 
237
        selret = select(*pdwClientID + 1, &read_fd, (fd_set *) NULL,
 
238
                (fd_set *) NULL, &tv);
 
239
 
 
240
        if (selret < 0)
 
241
        {
 
242
                Log2(PCSC_LOG_ERROR, "select returns with failure: %s",
 
243
                        strerror(errno));
 
244
                return -1;
 
245
        }
 
246
 
 
247
        if (selret == 0)
 
248
                /* timeout */
 
249
                return 2;
 
250
 
 
251
        if (FD_ISSET(*pdwClientID, &read_fd))
 
252
        {
 
253
                /*
 
254
                 * Return the current handle 
 
255
                 */
 
256
                rv = SHMMessageReceive(msgStruct, *pdwClientID,
 
257
                                       PCSCLITE_SERVER_ATTEMPTS);
 
258
                
 
259
                if (rv == -1)
 
260
                {       /* The client has died */
 
261
                        Log2(PCSC_LOG_DEBUG, "Client has disappeared: %d",
 
262
                                *pdwClientID);
 
263
                        msgStruct->mtype = CMD_CLIENT_DIED;
 
264
                        msgStruct->command = 0;
 
265
                        SYS_CloseFile(*pdwClientID);
 
266
 
 
267
                        return 0;
 
268
                }
 
269
                
 
270
                /*
 
271
                 * Set the identifier handle 
 
272
                 */
 
273
                Log2(PCSC_LOG_DEBUG, "correctly processed client: %d",
 
274
                        *pdwClientID);
 
275
                return 1;
 
276
        }
 
277
        
 
278
        return -1;
 
279
 
 
280
}
 
281
 
 
282