~noskcaj/ubuntu/trusty/gpgme1.0/1.4.3

« back to all changes in this revision

Viewing changes to assuan/assuan-socket.c

  • Committer: Bazaar Package Importer
  • Author(s): Jose Carlos Garcia Sogo
  • Date: 2009-09-08 14:30:11 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20090908143011-dv8rzfraejhex6t5
Tags: 1.2.0-1
* New Upstream Version (Closes: #545671)
* As there are new symbols introduced in this version, bump shlibs info. 
* Bump Standards-Version to 3.8.3, no changes. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
 * Lesser General Public License for more details.
15
15
 *
16
16
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19
 
 * USA. 
 
17
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20
18
 */
21
19
 
22
20
#include <config.h>
23
21
#include <stdio.h>
 
22
#include <stdlib.h>
24
23
#ifdef HAVE_W32_SYSTEM
 
24
#define WIN32_LEAN_AND_MEAN
25
25
#include <windows.h>
 
26
#include <wincrypt.h>
26
27
#include <io.h>
27
28
#else
28
29
#include <sys/types.h>
29
30
#include <sys/socket.h>
30
31
#endif
 
32
#include <errno.h>
 
33
#include <sys/stat.h>
 
34
#include <fcntl.h>
 
35
#include <assert.h>
 
36
 
31
37
#include "assuan-defs.h"
32
38
 
33
39
/* Hacks for Slowaris.  */
42
48
# define AF_LOCAL AF_UNIX
43
49
#endif
44
50
 
45
 
int
46
 
_assuan_close (int fd)
47
 
{
48
 
#if defined (HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN)
49
 
  int rc = closesocket (fd);
 
51
#ifdef HAVE_W32_SYSTEM
 
52
#ifndef S_IRGRP
 
53
# define S_IRGRP 0
 
54
# define S_IWGRP 0
 
55
#endif
 
56
#endif
 
57
 
 
58
 
 
59
#ifdef HAVE_W32_SYSTEM
 
60
int
 
61
_assuan_sock_wsa2errno (int err)
 
62
{
 
63
  switch (err)
 
64
    {
 
65
    case WSAENOTSOCK:
 
66
      return EINVAL;
 
67
    case WSAEWOULDBLOCK:
 
68
      return EAGAIN;
 
69
    case ERROR_BROKEN_PIPE:
 
70
      return EPIPE;
 
71
    case WSANOTINITIALISED:
 
72
      return ENOSYS;
 
73
    default:
 
74
      return EIO;
 
75
    }
 
76
}
 
77
 
 
78
 
 
79
/* W32: Fill BUFFER with LENGTH bytes of random.  Returns -1 on
 
80
   failure, 0 on success.  Sets errno on failure.  */
 
81
static int
 
82
get_nonce (char *buffer, size_t nbytes) 
 
83
{
 
84
  HCRYPTPROV prov;
 
85
  int ret = -1;
 
86
 
 
87
  if (!CryptAcquireContext (&prov, NULL, NULL, PROV_RSA_FULL, 
 
88
                            (CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) )
 
89
    errno = ENODEV;
 
90
  else 
 
91
    {
 
92
      if (!CryptGenRandom (prov, nbytes, buffer))
 
93
        errno = ENODEV;
 
94
      else
 
95
        ret = 0;
 
96
      CryptReleaseContext (prov, 0);
 
97
    }
 
98
  return ret;
 
99
}
 
100
 
 
101
 
 
102
/* W32: The buffer for NONCE needs to be at least 16 bytes.  Returns 0 on
 
103
   success and sets errno on failure. */
 
104
static int
 
105
read_port_and_nonce (const char *fname, unsigned short *port, char *nonce)
 
106
{
 
107
  FILE *fp;
 
108
  char buffer[50], *p;
 
109
  size_t nread;
 
110
  int aval;
 
111
 
 
112
  fp = fopen (fname, "rb");
 
113
  if (!fp)
 
114
    return -1;
 
115
  nread = fread (buffer, 1, sizeof buffer - 1, fp);
 
116
  fclose (fp);
 
117
  if (!nread)
 
118
    {
 
119
      errno = ENOFILE;
 
120
      return -1;
 
121
    }
 
122
  buffer[nread] = 0;
 
123
  aval = atoi (buffer);
 
124
  if (aval < 1 || aval > 65535)
 
125
    {
 
126
      errno = EINVAL;
 
127
      return -1;
 
128
    }
 
129
  *port = (unsigned int)aval;
 
130
  for (p=buffer; nread && *p != '\n'; p++, nread--)
 
131
    ;
 
132
  if (*p != '\n' || nread != 17)
 
133
    {
 
134
      errno = EINVAL;
 
135
      return -1;
 
136
    }
 
137
  p++; nread--;
 
138
  memcpy (nonce, p, 16);
 
139
  return 0;
 
140
}
 
141
#endif /*HAVE_W32_SYSTEM*/
 
142
 
 
143
 
 
144
 
 
145
int
 
146
_assuan_close (assuan_fd_t fd)
 
147
{
 
148
#ifdef _ASSUAN_CUSTOM_IO
 
149
  return _assuan_custom_close (fd);
 
150
#else
 
151
#ifdef (HAVE_W32_SYSTEM)
 
152
  int rc = closesocket (HANDLE2SOCKET(fd));
 
153
  if (rc)
 
154
    errno = _assuan_sock_wsa2errno (WSAGetLastError ());
50
155
  if (rc && WSAGetLastError () == WSAENOTSOCK)
51
 
    rc = CloseHandle (fd);
 
156
    {
 
157
      rc = CloseHandle (fd);
 
158
      if (rc)
 
159
        /* FIXME. */
 
160
        errno = EIO;
 
161
    }
52
162
  return rc;
53
163
#else
54
164
  return close (fd);
55
165
#endif
 
166
#endif
56
167
}
57
168
 
58
169
 
59
 
int
 
170
/* Return a new socket.  Note that under W32 we consider a socket the
 
171
   same as an System Handle; all functions using such a handle know
 
172
   about this dual use and act accordingly. */ 
 
173
assuan_fd_t
60
174
_assuan_sock_new (int domain, int type, int proto)
61
175
{
62
 
#ifndef HAVE_W32_SYSTEM
63
 
  return socket (domain, type, proto);
64
 
#else
 
176
#ifdef HAVE_W32_SYSTEM
 
177
  assuan_fd_t res;
65
178
  if (domain == AF_UNIX || domain == AF_LOCAL)
66
179
    domain = AF_INET;
 
180
 
 
181
#ifdef _ASSUAN_CUSTOM_IO
 
182
  return _assuan_custom_socket (domain, type, proto);
 
183
#else
 
184
  res = SOCKET2HANDLE(socket (domain, type, proto));
 
185
  if (res == ASSUAN_INVALID_FD)
 
186
    errno = _assuan_sock_wsa2errno (WSAGetLastError ());
 
187
  return res;
 
188
#endif
 
189
 
 
190
#else
 
191
 
 
192
#ifdef _ASSUAN_CUSTOM_IO
 
193
  return _gpgme_io_socket (domain, type, proto);
 
194
#else
67
195
  return socket (domain, type, proto);
68
196
#endif
 
197
 
 
198
#endif
69
199
}
70
200
 
71
201
 
72
202
int
73
 
_assuan_sock_connect (int sockfd, struct sockaddr * addr, int addrlen)
 
203
_assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
74
204
{
75
 
#ifndef HAVE_W32_SYSTEM
 
205
#ifdef HAVE_W32_SYSTEM
 
206
  if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
 
207
    {
 
208
      struct sockaddr_in myaddr;
 
209
      struct sockaddr_un *unaddr;
 
210
      unsigned short port;
 
211
      char nonce[16];
 
212
      int ret;
 
213
      
 
214
      unaddr = (struct sockaddr_un *)addr;
 
215
      if (read_port_and_nonce (unaddr->sun_path, &port, nonce))
 
216
        return -1;
 
217
      
 
218
      myaddr.sin_family = AF_INET;
 
219
      myaddr.sin_port = htons (port); 
 
220
      myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
 
221
  
 
222
      /* Set return values.  */
 
223
      unaddr->sun_family = myaddr.sin_family;
 
224
      unaddr->sun_port = myaddr.sin_port;
 
225
      unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
 
226
  
 
227
#ifdef _ASSUAN_CUSTOM_IO
 
228
      ret = _assuan_custom_connect (sockfd,
 
229
                                    (struct sockaddr *)&myaddr, sizeof myaddr);
 
230
#else
 
231
      ret = connect (HANDLE2SOCKET(sockfd), 
 
232
                     (struct sockaddr *)&myaddr, sizeof myaddr);
 
233
#endif
 
234
 
 
235
      if (!ret)
 
236
        {
 
237
          /* Send the nonce. */
 
238
 
 
239
          ret = _assuan_io_write (sockfd, nonce, 16);
 
240
          if (ret >= 0 && ret != 16)
 
241
            {
 
242
              errno = EIO;
 
243
              ret = -1;
 
244
            }
 
245
        }
 
246
      else
 
247
        errno = _assuan_sock_wsa2errno (WSAGetLastError ());
 
248
      return ret;
 
249
    }
 
250
  else
 
251
    {
 
252
      int res;
 
253
      res = connect (HANDLE2SOCKET (sockfd), addr, addrlen);
 
254
      if (res < 0)
 
255
        errno = _assuan_sock_wsa2errno (WSAGetLastError ());
 
256
      return res;
 
257
    }      
 
258
#else
 
259
 
 
260
#ifdef _ASSUAN_CUSTOM_IO
 
261
  return _assuan_custom_connect (sockfd, addr, addrlen);
 
262
#else
76
263
  return connect (sockfd, addr, addrlen);
77
 
#else
78
 
  struct sockaddr_in myaddr;
79
 
  struct sockaddr_un * unaddr;
80
 
  FILE * fp;
81
 
  int port = 0;
82
 
  
83
 
  unaddr = (struct sockaddr_un *)addr;
84
 
  fp = fopen (unaddr->sun_path, "rb");
85
 
  if (!fp)
86
 
      return -1;
87
 
  fscanf (fp, "%d", &port);
88
 
  fclose (fp);
89
 
  /* XXX: set errno in this case */
90
 
  if (port < 0 || port > 65535)
91
 
      return -1;
92
 
  
93
 
  myaddr.sin_family = AF_INET;
94
 
  myaddr.sin_port = port; 
95
 
  myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
 
264
#endif
96
265
 
97
 
  /* we need this later. */
98
 
  unaddr->sun_family = myaddr.sin_family;
99
 
  unaddr->sun_port = myaddr.sin_port;
100
 
  unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
101
 
  
102
 
  return connect (sockfd, (struct sockaddr *)&myaddr, sizeof myaddr);
103
266
#endif
104
267
}
105
268
 
106
269
 
107
270
int
108
 
_assuan_sock_bind (int sockfd, struct sockaddr * addr, int addrlen)
 
271
_assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
109
272
{
110
 
#ifndef HAVE_W32_SYSTEM
111
 
  return bind (sockfd, addr, addrlen);
112
 
#else
 
273
#ifdef HAVE_W32_SYSTEM
113
274
  if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
114
275
    {
115
276
      struct sockaddr_in myaddr;
116
 
      struct sockaddr_un * unaddr;
117
 
      FILE * fp;
 
277
      struct sockaddr_un *unaddr;
 
278
      int filefd;
 
279
      FILE *fp;
118
280
      int len = sizeof myaddr;
119
281
      int rc;
 
282
      char nonce[16];
 
283
 
 
284
      if (get_nonce (nonce, 16))
 
285
        return -1;
 
286
 
 
287
      unaddr = (struct sockaddr_un *)addr;
120
288
 
121
289
      myaddr.sin_port = 0;
122
290
      myaddr.sin_family = AF_INET;
123
291
      myaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
124
292
 
125
 
      rc = bind (sockfd, (struct sockaddr *)&myaddr, len);
126
 
      if (rc)
127
 
        return rc;
128
 
      rc = getsockname (sockfd, (struct sockaddr *)&myaddr, &len);
129
 
      if (rc)
130
 
        return rc;
131
 
      unaddr = (struct sockaddr_un *)addr;
132
 
      fp = fopen (unaddr->sun_path, "wb");
 
293
      filefd = open (unaddr->sun_path, 
 
294
                     (O_WRONLY|O_CREAT|O_EXCL|O_BINARY), 
 
295
                     (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP));
 
296
      if (filefd == -1)
 
297
        {
 
298
          if (errno == EEXIST)
 
299
            errno = WSAEADDRINUSE;
 
300
          return -1;
 
301
        }
 
302
      fp = fdopen (filefd, "wb");
133
303
      if (!fp)
134
 
        return -1;
135
 
      fprintf (fp, "%d", myaddr.sin_port);
 
304
        { 
 
305
          int save_e = errno;
 
306
          close (filefd);
 
307
          errno = save_e;
 
308
          return -1;
 
309
        }
 
310
 
 
311
      rc = bind (HANDLE2SOCKET (sockfd), (struct sockaddr *)&myaddr, len);
 
312
      if (!rc)
 
313
        rc = getsockname (HANDLE2SOCKET (sockfd), 
 
314
                          (struct sockaddr *)&myaddr, &len);
 
315
      if (rc)
 
316
        {
 
317
          int save_e = errno;
 
318
          fclose (fp);
 
319
          remove (unaddr->sun_path);
 
320
          errno = save_e;
 
321
          return rc;
 
322
        }
 
323
      fprintf (fp, "%d\n", ntohs (myaddr.sin_port));
 
324
      fwrite (nonce, 16, 1, fp);
136
325
      fclose (fp);
137
326
 
138
 
      /* we need this later. */
139
 
      unaddr->sun_family = myaddr.sin_family;
140
 
      unaddr->sun_port = myaddr.sin_port;
141
 
      unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
142
 
      
143
327
      return 0;
144
328
    }
 
329
  else
 
330
    {
 
331
      int res = bind (HANDLE2SOCKET(sockfd), addr, addrlen);
 
332
      if (res < 0)
 
333
        errno = _assuan_sock_wsa2errno (WSAGetLastError ());
 
334
      return res;
 
335
    }
 
336
#else
145
337
  return bind (sockfd, addr, addrlen);
146
338
#endif
147
339
}
148
340
 
 
341
 
 
342
int
 
343
_assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, 
 
344
                        assuan_sock_nonce_t *nonce)
 
345
{
 
346
#ifdef HAVE_W32_SYSTEM
 
347
  if (addr->sa_family == AF_LOCAL || addr->sa_family == AF_UNIX)
 
348
    {
 
349
      struct sockaddr_un *unaddr;
 
350
      unsigned short port;
 
351
 
 
352
      if (sizeof nonce->nonce != 16)
 
353
        {
 
354
          errno = EINVAL;
 
355
          return -1;
 
356
        }
 
357
      nonce->length = 16;
 
358
      unaddr = (struct sockaddr_un *)addr;
 
359
      if (read_port_and_nonce (unaddr->sun_path, &port, nonce->nonce))
 
360
        return -1;
 
361
    }
 
362
  else
 
363
    {
 
364
      nonce->length = 42; /* Arbitrary valuie to detect unitialized nonce. */
 
365
      nonce->nonce[0] = 42;
 
366
    }
 
367
#else
 
368
  (void)addr;
 
369
  (void)addrlen;
 
370
  nonce->length = 0;
 
371
#endif
 
372
  return 0;
 
373
}
 
374
 
 
375
 
 
376
int
 
377
_assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
 
378
{
 
379
#ifdef HAVE_W32_SYSTEM
 
380
  char buffer[16], *p;
 
381
  size_t nleft;
 
382
  int n;
 
383
 
 
384
  if (sizeof nonce->nonce != 16)
 
385
    {
 
386
      errno = EINVAL;
 
387
      return -1;
 
388
    }
 
389
 
 
390
  if (nonce->length == 42 && nonce->nonce[0] == 42)
 
391
    return 0; /* Not a Unix domain socket.  */
 
392
 
 
393
  if (nonce->length != 16)
 
394
    {
 
395
      errno = EINVAL;
 
396
      return -1;
 
397
    }
 
398
      
 
399
  p = buffer;
 
400
  nleft = 16;
 
401
  while (nleft)
 
402
    {
 
403
      n = _assuan_io_read (SOCKET2HANDLE(fd), p, nleft);
 
404
      if (n < 0 && errno == EINTR)
 
405
        ;
 
406
      else if (n < 0 && errno == EAGAIN)
 
407
        Sleep (100);
 
408
      else if (n < 0)
 
409
        return -1;
 
410
      else if (!n)
 
411
        {
 
412
          errno = EIO;
 
413
          return -1;
 
414
        }
 
415
      else
 
416
        {
 
417
          p += n;
 
418
          nleft -= n;
 
419
        }
 
420
    }
 
421
  if (memcmp (buffer, nonce->nonce, 16))
 
422
    {
 
423
      errno = EACCES;
 
424
      return -1;
 
425
    }
 
426
#else
 
427
  (void)fd;
 
428
  (void)nonce;
 
429
#endif
 
430
  return 0;
 
431
}
 
432
 
 
433
 
 
434
/* Public API.  */
 
435
int
 
436
assuan_sock_close (assuan_fd_t fd)
 
437
{
 
438
  return _assuan_close (fd);
 
439
}
 
440
 
 
441
assuan_fd_t 
 
442
assuan_sock_new (int domain, int type, int proto)
 
443
{
 
444
  return _assuan_sock_new (domain, type, proto);
 
445
}
 
446
 
 
447
int
 
448
assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
 
449
{
 
450
  return _assuan_sock_connect (sockfd, addr, addrlen);
 
451
}
 
452
 
 
453
int
 
454
assuan_sock_bind (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)
 
455
{
 
456
  return _assuan_sock_bind (sockfd, addr, addrlen);
 
457
}
 
458
 
 
459
int
 
460
assuan_sock_get_nonce (struct sockaddr *addr, int addrlen, 
 
461
                       assuan_sock_nonce_t *nonce)
 
462
{     
 
463
  return _assuan_sock_get_nonce (addr, addrlen, nonce);
 
464
}
 
465
 
 
466
int
 
467
assuan_sock_check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce)
 
468
{
 
469
  return _assuan_sock_check_nonce (fd, nonce);
 
470
}