~ubuntu-branches/ubuntu/karmic/gnupg2/karmic-security

« back to all changes in this revision

Viewing changes to common/sysutils.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-10-04 10:25:53 UTC
  • mfrom: (5.1.15 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081004102553-fv62pp8dsitxli47
Tags: 2.0.9-3.1
* Non-maintainer upload.
* agent/gpg-agent.c: Deinit the threading library before exec'ing
  the command to run in --daemon mode. And because that still doesn't
  restore the sigprocmask, do that manually. Closes: #499569

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* sysutils.c -  system helpers
2
 
 * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004,
 
3
 *               2007, 2008  Free Software Foundation, Inc.
3
4
 *
4
5
 * This file is part of GnuPG.
5
6
 *
6
7
 * GnuPG is free software; you can redistribute it and/or modify
7
8
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * the Free Software Foundation; either version 3 of the License, or
9
10
 * (at your option) any later version.
10
11
 *
11
12
 * GnuPG is distributed in the hope that it will be useful,
14
15
 * GNU General Public License for more details.
15
16
 *
16
17
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
18
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19
19
 */
20
20
 
21
21
#include <config.h>
 
22
 
 
23
#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth.  */
 
24
# undef HAVE_PTH
 
25
# undef USE_GNU_PTH
 
26
#endif
 
27
 
22
28
#include <stdio.h>
23
29
#include <stdlib.h>
24
30
#include <string.h>
25
31
#include <unistd.h>
26
32
#include <errno.h>
27
33
#ifdef HAVE_STAT
28
 
#include <sys/stat.h>
 
34
# include <sys/stat.h>
29
35
#endif
30
36
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
31
 
  #include <asm/sysinfo.h>
32
 
  #include <asm/unistd.h>
 
37
# include <asm/sysinfo.h>
 
38
# include <asm/unistd.h>
33
39
#endif
34
40
#ifdef HAVE_SETRLIMIT
35
 
  #include <time.h>
36
 
  #include <sys/time.h>
37
 
  #include <sys/resource.h>
38
 
#endif
 
41
# include <time.h>
 
42
# include <sys/time.h>
 
43
# include <sys/resource.h>
 
44
#endif
 
45
#ifdef HAVE_W32_SYSTEM
 
46
# define WINVER 0x0500  /* Required for AllowSetForegroundWindow.  */
 
47
# include <windows.h>
 
48
#endif
 
49
#ifdef HAVE_PTH      
 
50
# include <pth.h>
 
51
#endif
 
52
#include <fcntl.h>
 
53
 
39
54
#include "util.h"
40
55
#include "i18n.h"
41
56
 
42
57
#include "sysutils.h"
43
58
 
 
59
#define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
 
60
 
 
61
 
44
62
#if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
45
63
#warning using trap_unaligned
46
64
static int
103
121
      return 1;
104
122
    limit.rlim_cur = limit.rlim_max;
105
123
    setrlimit (RLIMIT_CORE, &limit);
106
 
    return 1; /* We always return true because trhis function is
 
124
    return 1; /* We always return true because this function is
107
125
                 merely a debugging aid. */
108
126
# endif
109
127
    return 1;
124
142
        ulong a, b;
125
143
 
126
144
        initialized = 1;
127
 
        /* also this marker is guessable it is not easy to use this 
 
145
        /* Although this marker is guessable it is not easy to use
128
146
         * for a faked control packet because an attacker does not
129
147
         * have enough control about the time the verification does 
130
148
         * take place.  Of course, we can add just more random but 
228
246
  return 0;
229
247
}
230
248
#endif
 
249
 
 
250
 
 
251
/* Wrapper around the usual sleep fucntion.  This one won't wake up
 
252
   before the sleep time has really elapsed.  When build with Pth it
 
253
   merely calls pth_sleep and thus suspends only the current
 
254
   thread. */
 
255
void
 
256
gnupg_sleep (unsigned int seconds)
 
257
{
 
258
#ifdef HAVE_PTH
 
259
  /* With Pth we force a regular sleep for seconds == 0 so that also
 
260
     the process will give up its timeslot.  */
 
261
  if (!seconds)
 
262
    {
 
263
# ifdef HAVE_W32_SYSTEM    
 
264
      Sleep (0);
 
265
# else
 
266
      sleep (0);
 
267
# endif
 
268
    }
 
269
  pth_sleep (seconds);
 
270
#else
 
271
  /* Fixme:  make sure that a sleep won't wake up to early.  */
 
272
# ifdef HAVE_W32_SYSTEM    
 
273
  Sleep (seconds*1000);
 
274
# else
 
275
  sleep (seconds);
 
276
# endif
 
277
#endif
 
278
}
 
279
 
 
280
 
 
281
/* This function is a NOP for POSIX systems but required under Windows
 
282
   as the file handles as returned by OS calls (like CreateFile) are
 
283
   different from the libc file descriptors (like open). This function
 
284
   translates system file handles to libc file handles.  FOR_WRITE
 
285
   gives the direction of the handle.  */
 
286
int
 
287
translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
 
288
{
 
289
#ifdef HAVE_W32_SYSTEM
 
290
  int x;
 
291
 
 
292
  if (fd == GNUPG_INVALID_FD)
 
293
    return -1;
 
294
  
 
295
  /* Note that _open_osfhandle is currently defined to take and return
 
296
     a long.  */
 
297
  x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
 
298
  if (x == -1)
 
299
    log_error ("failed to translate osfhandle %p\n", (void *) fd);
 
300
  return x;
 
301
#else /*!HAVE_W32_SYSTEM */
 
302
  return fd;
 
303
#endif
 
304
}
 
305
 
 
306
/* This is the same as translate_sys2libc_fd but takes an integer
 
307
   which is assumed to be such an system handle.  */
 
308
int
 
309
translate_sys2libc_fd_int (int fd, int for_write)
 
310
{
 
311
#ifdef HAVE_W32_SYSTEM
 
312
  if (fd <= 2)
 
313
    return fd;  /* Do not do this for error, stdin, stdout, stderr. */
 
314
 
 
315
  return translate_sys2libc_fd ((void*)fd, for_write);
 
316
#else
 
317
  return fd;
 
318
#endif
 
319
}
 
320
 
 
321
 
 
322
 
 
323
/* Replacement for tmpfile().  This is required because the tmpfile
 
324
   function of Windows' runtime library is broken, insecure, ignores
 
325
   TMPDIR and so on.  In addition we create a file with an inheritable
 
326
   handle.  */
 
327
FILE *
 
328
gnupg_tmpfile (void)
 
329
{
 
330
#ifdef HAVE_W32_SYSTEM
 
331
  int attempts, n;
 
332
  char buffer[MAX_PATH+7+12+1];
 
333
  char *name, *p;
 
334
  HANDLE file;
 
335
  int pid = GetCurrentProcessId ();
 
336
  unsigned int value;
 
337
  int i;
 
338
  SECURITY_ATTRIBUTES sec_attr;
 
339
 
 
340
  memset (&sec_attr, 0, sizeof sec_attr );
 
341
  sec_attr.nLength = sizeof sec_attr;
 
342
  sec_attr.bInheritHandle = TRUE;
 
343
 
 
344
  n = GetTempPath (MAX_PATH+1, buffer);
 
345
  if (!n || n > MAX_PATH || strlen (buffer) > MAX_PATH)
 
346
    {
 
347
      errno = ENOENT;
 
348
      return NULL;
 
349
    }
 
350
  p = buffer + strlen (buffer);
 
351
  p = stpcpy (p, "_gnupg");
 
352
  /* We try to create the directory but don't care about an error as
 
353
     it may already exist and the CreateFile would throw an error
 
354
     anyway.  */
 
355
  CreateDirectory (buffer, NULL);
 
356
  *p++ = '\\';
 
357
  name = p;
 
358
  for (attempts=0; attempts < 10; attempts++)
 
359
    {
 
360
      p = name;
 
361
      value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
 
362
      for (i=0; i < 8; i++)
 
363
        {
 
364
          *p++ = tohex (((value >> 28) & 0x0f));
 
365
          value <<= 4;
 
366
        }
 
367
      strcpy (p, ".tmp");
 
368
      file = CreateFile (buffer,
 
369
                         GENERIC_READ | GENERIC_WRITE,
 
370
                         0,
 
371
                         &sec_attr,
 
372
                         CREATE_NEW,
 
373
                         FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
 
374
                         NULL);
 
375
      if (file != INVALID_HANDLE_VALUE)
 
376
        {
 
377
          FILE *fp;
 
378
          int fd = _open_osfhandle ((long)file, 0);
 
379
          if (fd == -1)
 
380
            {
 
381
              CloseHandle (file);
 
382
              return NULL;
 
383
            }
 
384
          fp = fdopen (fd, "w+b");
 
385
          if (!fp)
 
386
            {
 
387
              int save = errno;
 
388
              close (fd);
 
389
              errno = save;
 
390
              return NULL;
 
391
            }
 
392
          return fp;
 
393
        }
 
394
      Sleep (1); /* One ms as this is the granularity of GetTickCount.  */
 
395
    }
 
396
  errno = ENOENT;
 
397
  return NULL;
 
398
#else /*!HAVE_W32_SYSTEM*/
 
399
  return tmpfile ();
 
400
#endif /*!HAVE_W32_SYSTEM*/
 
401
}
 
402
 
 
403
 
 
404
/* Make sure that the standard file descriptors are opened. Obviously
 
405
   some folks close them before an exec and the next file we open will
 
406
   get one of them assigned and thus any output (i.e. diagnostics) end
 
407
   up in that file (e.g. the trustdb).  Not actually a gpg problem as
 
408
   this will hapen with almost all utilities when called in a wrong
 
409
   way.  However we try to minimize the damage here and raise
 
410
   awareness of the problem.
 
411
 
 
412
   Must be called before we open any files! */
 
413
void
 
414
gnupg_reopen_std (const char *pgmname)
 
415
{  
 
416
#if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
 
417
  struct stat statbuf;
 
418
  int did_stdin = 0;
 
419
  int did_stdout = 0;
 
420
  int did_stderr = 0;
 
421
  FILE *complain;
 
422
 
 
423
  if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
 
424
    {
 
425
      if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
 
426
        did_stdin = 1;
 
427
      else
 
428
        did_stdin = 2;
 
429
    }
 
430
  
 
431
  if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
 
432
    {
 
433
      if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
 
434
        did_stdout = 1;
 
435
      else
 
436
        did_stdout = 2;
 
437
    }
 
438
 
 
439
  if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
 
440
    {
 
441
      if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
 
442
        did_stderr = 1;
 
443
      else
 
444
        did_stderr = 2;
 
445
    }
 
446
 
 
447
  /* It's hard to log this sort of thing since the filehandle we would
 
448
     complain to may be closed... */
 
449
  if (!did_stderr)
 
450
    complain = stderr;
 
451
  else if (!did_stdout)
 
452
    complain = stdout;
 
453
  else
 
454
    complain = NULL;
 
455
 
 
456
  if (complain)
 
457
    {
 
458
      if (did_stdin == 1)
 
459
        fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
 
460
      if (did_stdout == 1)
 
461
        fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
 
462
      if (did_stderr == 1)
 
463
        fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
 
464
 
 
465
      if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
 
466
        fprintf(complain,"%s: fatal: unable to reopen standard input,"
 
467
                " output, or error\n", pgmname);
 
468
    }
 
469
 
 
470
  if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
 
471
    exit (3);
 
472
#endif /* HAVE_STAT && !HAVE_W32_SYSTEM */
 
473
}
 
474
 
 
475
 
 
476
/* Hack required for Windows.  */
 
477
void 
 
478
gnupg_allow_set_foregound_window (pid_t pid)
 
479
{
 
480
  if (!pid || pid == (pid_t)(-1))
 
481
    log_info ("%s called with invalid pid %lu\n",
 
482
              "gnupg_allow_set_foregound_window", (unsigned long)pid);
 
483
#ifdef HAVE_W32_SYSTEM  
 
484
  else if (!AllowSetForegroundWindow (pid))
 
485
    log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
 
486
               (unsigned long)pid, w32_strerror (-1));
 
487
#endif
 
488
}