1 /* sysutils.c - system helpers
2 * Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004,
3 * 2007, 2008 Free Software Foundation, Inc.
5 * This file is part of GnuPG.
7 * GnuPG is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * GnuPG is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
34 # include <sys/stat.h>
36 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
37 # include <asm/sysinfo.h>
38 # include <asm/unistd.h>
42 # include <sys/time.h>
43 # include <sys/resource.h>
45 #ifdef HAVE_W32_SYSTEM
46 # define WINVER 0x0500 /* Required for AllowSetForegroundWindow. */
59 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
62 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
63 #warning using trap_unaligned
65 setsysinfo(unsigned long op
, void *buffer
, unsigned long size
,
66 int *start
, void *arg
, unsigned long flag
)
68 return syscall(__NR_osf_setsysinfo
, op
, buffer
, size
, start
, arg
, flag
);
76 buf
[0] = SSIN_UACPROC
;
77 buf
[1] = UAC_SIGBUS
| UAC_NOPRINT
;
78 setsysinfo(SSI_NVPAIRS
, buf
, 1, 0, 0, 0);
89 disable_core_dumps (void)
91 #ifdef HAVE_DOSISH_SYSTEM
94 # ifdef HAVE_SETRLIMIT
97 /* We only set the current limit unless we were not able to
98 retrieve the old value. */
99 if (getrlimit (RLIMIT_CORE
, &limit
))
102 if( !setrlimit (RLIMIT_CORE
, &limit
) )
104 if( errno
!= EINVAL
&& errno
!= ENOSYS
)
105 log_fatal (_("can't disable core dumps: %s\n"), strerror(errno
) );
112 enable_core_dumps (void)
114 #ifdef HAVE_DOSISH_SYSTEM
117 # ifdef HAVE_SETRLIMIT
120 if (getrlimit (RLIMIT_CORE
, &limit
))
122 limit
.rlim_cur
= limit
.rlim_max
;
123 setrlimit (RLIMIT_CORE
, &limit
);
124 return 1; /* We always return true because this function is
125 merely a debugging aid. */
133 /* Return a string which is used as a kind of process ID */
135 get_session_marker( size_t *rlen
)
137 static byte marker
[SIZEOF_UNSIGNED_LONG
*2];
138 static int initialized
;
140 if ( !initialized
) {
141 volatile ulong aa
, bb
; /* we really want the uninitialized value */
145 /* Although this marker is guessable it is not easy to use
146 * for a faked control packet because an attacker does not
147 * have enough control about the time the verification does
148 * take place. Of course, we can add just more random but
149 * than we need the random generator even for verification
150 * tasks - which does not make sense. */
151 a
= aa
^ (ulong
)getpid();
152 b
= bb
^ (ulong
)time(NULL
);
153 memcpy( marker
, &a
, SIZEOF_UNSIGNED_LONG
);
154 memcpy( marker
+SIZEOF_UNSIGNED_LONG
, &b
, SIZEOF_UNSIGNED_LONG
);
156 *rlen
= sizeof(marker
);
161 #if 0 /* not yet needed - Note that this will require inclusion of
162 cmacros.am in Makefile.am */
164 check_permissions(const char *path
,int extension
,int checkonly
)
166 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
175 if(extension
&& path
[0]!=DIRSEP_C
)
177 if(strchr(path
,DIRSEP_C
))
178 tmppath
=make_filename(path
,NULL
);
180 tmppath
=make_filename(GNUPG_LIBDIR
,path
,NULL
);
183 tmppath
=m_strdup(path
);
185 /* It's okay if the file doesn't exist */
186 if(stat(tmppath
,&statbuf
)!=0)
192 isdir
=S_ISDIR(statbuf
.st_mode
);
194 /* Per-user files must be owned by the user. Extensions must be
195 owned by the user or root. */
196 if((!extension
&& statbuf
.st_uid
!= getuid()) ||
197 (extension
&& statbuf
.st_uid
!=0 && statbuf
.st_uid
!=getuid()))
200 log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
201 isdir
?"directory":extension
?"extension":"file",path
);
205 /* This works for both directories and files - basically, we don't
206 care what the owner permissions are, so long as the group and
207 other permissions are 0 for per-user files, and non-writable for
209 if((extension
&& (statbuf
.st_mode
& (S_IWGRP
|S_IWOTH
)) !=0) ||
210 (!extension
&& (statbuf
.st_mode
& (S_IRWXG
|S_IRWXO
)) != 0))
214 /* However, if the directory the directory/file is in is owned
215 by the user and is 700, then this is not a problem.
216 Theoretically, we could walk this test up to the root
217 directory /, but for the sake of sanity, I'm stopping at one
220 dir
= make_dirname (tmppath
);
221 if(stat(dir
,&statbuf
)==0 && statbuf
.st_uid
==getuid() &&
222 S_ISDIR(statbuf
.st_mode
) && (statbuf
.st_mode
& (S_IRWXG
|S_IRWXO
))==0)
232 log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
233 isdir
?"directory":extension
?"extension":"file",path
);
244 #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
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
256 gnupg_sleep (unsigned int seconds
)
259 /* With Pth we force a regular sleep for seconds == 0 so that also
260 the process will give up its timeslot. */
263 # ifdef HAVE_W32_SYSTEM
271 /* Fixme: make sure that a sleep won't wake up to early. */
272 # ifdef HAVE_W32_SYSTEM
273 Sleep (seconds
*1000);
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. */
287 translate_sys2libc_fd (gnupg_fd_t fd
, int for_write
)
289 #ifdef HAVE_W32_SYSTEM
292 if (fd
== GNUPG_INVALID_FD
)
295 /* Note that _open_osfhandle is currently defined to take and return
297 x
= _open_osfhandle ((long)fd
, for_write
? 1 : 0);
299 log_error ("failed to translate osfhandle %p\n", (void *) fd
);
301 #else /*!HAVE_W32_SYSTEM */
306 /* This is the same as translate_sys2libc_fd but takes an integer
307 which is assumed to be such an system handle. */
309 translate_sys2libc_fd_int (int fd
, int for_write
)
311 #ifdef HAVE_W32_SYSTEM
313 return fd
; /* Do not do this for error, stdin, stdout, stderr. */
315 return translate_sys2libc_fd ((void*)fd
, for_write
);
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
330 #ifdef HAVE_W32_SYSTEM
332 char buffer
[MAX_PATH
+7+12+1];
335 int pid
= GetCurrentProcessId ();
338 SECURITY_ATTRIBUTES sec_attr
;
340 memset (&sec_attr
, 0, sizeof sec_attr
);
341 sec_attr
.nLength
= sizeof sec_attr
;
342 sec_attr
.bInheritHandle
= TRUE
;
344 n
= GetTempPath (MAX_PATH
+1, buffer
);
345 if (!n
|| n
> MAX_PATH
|| strlen (buffer
) > MAX_PATH
)
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
355 CreateDirectory (buffer
, NULL
);
358 for (attempts
=0; attempts
< 10; attempts
++)
361 value
= (GetTickCount () ^ ((pid
<<16) & 0xffff0000));
362 for (i
=0; i
< 8; i
++)
364 *p
++ = tohex (((value
>> 28) & 0x0f));
368 file
= CreateFile (buffer
,
369 GENERIC_READ
| GENERIC_WRITE
,
373 FILE_ATTRIBUTE_TEMPORARY
| FILE_FLAG_DELETE_ON_CLOSE
,
375 if (file
!= INVALID_HANDLE_VALUE
)
378 int fd
= _open_osfhandle ((long)file
, 0);
384 fp
= fdopen (fd
, "w+b");
394 Sleep (1); /* One ms as this is the granularity of GetTickCount. */
398 #else /*!HAVE_W32_SYSTEM*/
400 #endif /*!HAVE_W32_SYSTEM*/
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.
412 Must be called before we open any files! */
414 gnupg_reopen_std (const char *pgmname
)
416 #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
423 if (fstat (STDIN_FILENO
, &statbuf
) == -1 && errno
==EBADF
)
425 if (open ("/dev/null",O_RDONLY
) == STDIN_FILENO
)
431 if (fstat (STDOUT_FILENO
, &statbuf
) == -1 && errno
== EBADF
)
433 if (open ("/dev/null",O_WRONLY
) == STDOUT_FILENO
)
439 if (fstat (STDERR_FILENO
, &statbuf
)==-1 && errno
==EBADF
)
441 if (open ("/dev/null", O_WRONLY
) == STDERR_FILENO
)
447 /* It's hard to log this sort of thing since the filehandle we would
448 complain to may be closed... */
451 else if (!did_stdout
)
459 fprintf (complain
, "%s: WARNING: standard input reopened\n", pgmname
);
461 fprintf (complain
, "%s: WARNING: standard output reopened\n", pgmname
);
463 fprintf (complain
, "%s: WARNING: standard error reopened\n", pgmname
);
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
);
470 if (did_stdin
== 2 || did_stdout
== 2 || did_stderr
== 2)
472 #endif /* HAVE_STAT && !HAVE_W32_SYSTEM */
476 /* Hack required for Windows. */
478 gnupg_allow_set_foregound_window (pid_t pid
)
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));