2007-07-05 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / common / sysutils.c
blob47031a152cfe531891b1882f17ba2956bef6e0bd
1 /* sysutils.c - system helpers
2 * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
22 #ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
23 # undef HAVE_PTH
24 # undef USE_GNU_PTH
25 #endif
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #ifdef HAVE_STAT
33 # include <sys/stat.h>
34 #endif
35 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
36 # include <asm/sysinfo.h>
37 # include <asm/unistd.h>
38 #endif
39 #ifdef HAVE_SETRLIMIT
40 # include <time.h>
41 # include <sys/time.h>
42 # include <sys/resource.h>
43 #endif
44 #ifdef HAVE_W32_SYSTEM
45 # include <windows.h>
46 #endif
47 #ifdef HAVE_PTH
48 # include <pth.h>
49 #endif
51 #include "util.h"
52 #include "i18n.h"
54 #include "sysutils.h"
56 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
57 #warning using trap_unaligned
58 static int
59 setsysinfo(unsigned long op, void *buffer, unsigned long size,
60 int *start, void *arg, unsigned long flag)
62 return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
65 void
66 trap_unaligned(void)
68 unsigned int buf[2];
70 buf[0] = SSIN_UACPROC;
71 buf[1] = UAC_SIGBUS | UAC_NOPRINT;
72 setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
74 #else
75 void
76 trap_unaligned(void)
77 { /* dummy */
79 #endif
82 int
83 disable_core_dumps (void)
85 #ifdef HAVE_DOSISH_SYSTEM
86 return 0;
87 #else
88 # ifdef HAVE_SETRLIMIT
89 struct rlimit limit;
91 /* We only set the current limit unless we were not able to
92 retrieve the old value. */
93 if (getrlimit (RLIMIT_CORE, &limit))
94 limit.rlim_max = 0;
95 limit.rlim_cur = 0;
96 if( !setrlimit (RLIMIT_CORE, &limit) )
97 return 0;
98 if( errno != EINVAL && errno != ENOSYS )
99 log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
100 #endif
101 return 1;
102 #endif
106 enable_core_dumps (void)
108 #ifdef HAVE_DOSISH_SYSTEM
109 return 0;
110 #else
111 # ifdef HAVE_SETRLIMIT
112 struct rlimit limit;
114 if (getrlimit (RLIMIT_CORE, &limit))
115 return 1;
116 limit.rlim_cur = limit.rlim_max;
117 setrlimit (RLIMIT_CORE, &limit);
118 return 1; /* We always return true because trhis function is
119 merely a debugging aid. */
120 # endif
121 return 1;
122 #endif
127 /* Return a string which is used as a kind of process ID */
128 const byte *
129 get_session_marker( size_t *rlen )
131 static byte marker[SIZEOF_UNSIGNED_LONG*2];
132 static int initialized;
134 if ( !initialized ) {
135 volatile ulong aa, bb; /* we really want the uninitialized value */
136 ulong a, b;
138 initialized = 1;
139 /* Although this marker is guessable it is not easy to use
140 * for a faked control packet because an attacker does not
141 * have enough control about the time the verification does
142 * take place. Of course, we can add just more random but
143 * than we need the random generator even for verification
144 * tasks - which does not make sense. */
145 a = aa ^ (ulong)getpid();
146 b = bb ^ (ulong)time(NULL);
147 memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
148 memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
150 *rlen = sizeof(marker);
151 return marker;
155 #if 0 /* not yet needed - Note that this will require inclusion of
156 cmacros.am in Makefile.am */
158 check_permissions(const char *path,int extension,int checkonly)
160 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
161 char *tmppath;
162 struct stat statbuf;
163 int ret=1;
164 int isdir=0;
166 if(opt.no_perm_warn)
167 return 0;
169 if(extension && path[0]!=DIRSEP_C)
171 if(strchr(path,DIRSEP_C))
172 tmppath=make_filename(path,NULL);
173 else
174 tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
176 else
177 tmppath=m_strdup(path);
179 /* It's okay if the file doesn't exist */
180 if(stat(tmppath,&statbuf)!=0)
182 ret=0;
183 goto end;
186 isdir=S_ISDIR(statbuf.st_mode);
188 /* Per-user files must be owned by the user. Extensions must be
189 owned by the user or root. */
190 if((!extension && statbuf.st_uid != getuid()) ||
191 (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
193 if(!checkonly)
194 log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
195 isdir?"directory":extension?"extension":"file",path);
196 goto end;
199 /* This works for both directories and files - basically, we don't
200 care what the owner permissions are, so long as the group and
201 other permissions are 0 for per-user files, and non-writable for
202 extensions. */
203 if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
204 (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
206 char *dir;
208 /* However, if the directory the directory/file is in is owned
209 by the user and is 700, then this is not a problem.
210 Theoretically, we could walk this test up to the root
211 directory /, but for the sake of sanity, I'm stopping at one
212 level down. */
214 dir= make_dirname (tmppath);
215 if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
216 S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
218 xfree (dir);
219 ret=0;
220 goto end;
223 m_free(dir);
225 if(!checkonly)
226 log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
227 isdir?"directory":extension?"extension":"file",path);
228 goto end;
231 ret=0;
233 end:
234 m_free(tmppath);
236 return ret;
238 #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
240 return 0;
242 #endif
245 /* Wrapper around the usual sleep fucntion. This one won't wake up
246 before the sleep time has really elapsed. When build with Pth it
247 merely calls pth_sleep and thus suspends only the current
248 thread. */
249 void
250 gnupg_sleep (unsigned int seconds)
252 #ifdef HAVE_PTH
253 /* With Pth we force a regular sleep for seconds == 0 so that also
254 the process will give up its timeslot. */
255 if (!seconds)
257 # ifdef HAVE_W32_SYSTEM
258 Sleep (0);
259 # else
260 sleep (0);
261 # endif
263 pth_sleep (seconds);
264 #else
265 /* Fixme: make sure that a sleep won't wake up to early. */
266 # ifdef HAVE_W32_SYSTEM
267 Sleep (seconds*1000);
268 # else
269 sleep (seconds);
270 # endif
271 #endif
275 /* This function is a NOP for POSIX systems but required under Windows
276 as the file handles as returned by OS calls (like CreateFile) are
277 different from the libc file descriptors (like open). This function
278 translates system file handles to libc file handles. FOR_WRITE
279 gives the direction of the handle. */
281 translate_sys2libc_fd (int fd, int for_write)
283 #ifdef HAVE_W32_SYSTEM
284 int x;
286 if (fd <= 2)
287 return fd; /* Do not do this for error, stdin, stdout, stderr.
288 (This also ignores an fd of -1.) */
290 x = _open_osfhandle (fd, for_write ? 1 : 0);
291 if (x == -1)
292 log_error ("failed to translate osfhandle %p\n", (void *) fd);
293 else
295 /* log_info ("_open_osfhandle %p yields %d%s\n", */
296 /* (void*)fd, x, for_write? " for writing":"" ); */
297 fd = x;
299 #endif /* HAVE_W32_SYSTEM */
300 return fd;