Fixed a problem in estream-printf.c.
[gnupg.git] / common / sysutils.c
1 /* sysutils.c -  system helpers
2  * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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 2 of the License, or
9  * (at your option) any later version.
10  *
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.
15  *
16  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23
24 #ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth.  */
25 # undef HAVE_PTH
26 # undef USE_GNU_PTH
27 #endif
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #ifdef HAVE_STAT
35 # include <sys/stat.h>
36 #endif
37 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
38 # include <asm/sysinfo.h>
39 # include <asm/unistd.h>
40 #endif
41 #ifdef HAVE_SETRLIMIT
42 # include <time.h>
43 # include <sys/time.h>
44 # include <sys/resource.h>
45 #endif
46 #ifdef HAVE_W32_SYSTEM
47 # include <windows.h>
48 #endif
49 #ifdef HAVE_PTH      
50 # include <pth.h>
51 #endif
52
53 #include "util.h"
54 #include "i18n.h"
55
56 #include "sysutils.h"
57
58 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
59 #warning using trap_unaligned
60 static int
61 setsysinfo(unsigned long op, void *buffer, unsigned long size,
62                      int *start, void *arg, unsigned long flag)
63 {
64     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
65 }
66
67 void
68 trap_unaligned(void)
69 {
70     unsigned int buf[2];
71
72     buf[0] = SSIN_UACPROC;
73     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
74     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
75 }
76 #else
77 void
78 trap_unaligned(void)
79 {  /* dummy */
80 }
81 #endif
82
83
84 int
85 disable_core_dumps (void)
86 {
87 #ifdef HAVE_DOSISH_SYSTEM
88     return 0;
89 #else
90 # ifdef HAVE_SETRLIMIT
91     struct rlimit limit;
92
93     /* We only set the current limit unless we were not able to
94        retrieve the old value. */
95     if (getrlimit (RLIMIT_CORE, &limit))
96       limit.rlim_max = 0;
97     limit.rlim_cur = 0;
98     if( !setrlimit (RLIMIT_CORE, &limit) )
99         return 0;
100     if( errno != EINVAL && errno != ENOSYS )
101         log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
102 #endif
103     return 1;
104 #endif
105 }
106
107 int
108 enable_core_dumps (void)
109 {
110 #ifdef HAVE_DOSISH_SYSTEM
111     return 0;
112 #else
113 # ifdef HAVE_SETRLIMIT
114     struct rlimit limit;
115
116     if (getrlimit (RLIMIT_CORE, &limit))
117       return 1;
118     limit.rlim_cur = limit.rlim_max;
119     setrlimit (RLIMIT_CORE, &limit);
120     return 1; /* We always return true because trhis function is
121                  merely a debugging aid. */
122 # endif
123     return 1;
124 #endif
125 }
126
127
128
129 /* Return a string which is used as a kind of process ID */
130 const byte *
131 get_session_marker( size_t *rlen )
132 {
133     static byte marker[SIZEOF_UNSIGNED_LONG*2];
134     static int initialized;
135
136     if ( !initialized ) {
137         volatile ulong aa, bb; /* we really want the uninitialized value */
138         ulong a, b;
139
140         initialized = 1;
141         /* Although this marker is guessable it is not easy to use
142          * for a faked control packet because an attacker does not
143          * have enough control about the time the verification does 
144          * take place.  Of course, we can add just more random but 
145          * than we need the random generator even for verification
146          * tasks - which does not make sense. */
147         a = aa ^ (ulong)getpid();
148         b = bb ^ (ulong)time(NULL);
149         memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
150         memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
151     }
152     *rlen = sizeof(marker);
153     return marker;
154 }
155
156
157 #if 0 /* not yet needed - Note that this will require inclusion of
158          cmacros.am in Makefile.am */
159 int
160 check_permissions(const char *path,int extension,int checkonly)
161 {
162 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
163   char *tmppath;
164   struct stat statbuf;
165   int ret=1;
166   int isdir=0;
167
168   if(opt.no_perm_warn)
169     return 0;
170
171   if(extension && path[0]!=DIRSEP_C)
172     {
173       if(strchr(path,DIRSEP_C))
174         tmppath=make_filename(path,NULL);
175       else
176         tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
177     }
178   else
179     tmppath=m_strdup(path);
180
181   /* It's okay if the file doesn't exist */
182   if(stat(tmppath,&statbuf)!=0)
183     {
184       ret=0;
185       goto end;
186     }
187
188   isdir=S_ISDIR(statbuf.st_mode);
189
190   /* Per-user files must be owned by the user.  Extensions must be
191      owned by the user or root. */
192   if((!extension && statbuf.st_uid != getuid()) ||
193      (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
194     {
195       if(!checkonly)
196         log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
197                  isdir?"directory":extension?"extension":"file",path);
198       goto end;
199     }
200
201   /* This works for both directories and files - basically, we don't
202      care what the owner permissions are, so long as the group and
203      other permissions are 0 for per-user files, and non-writable for
204      extensions. */
205   if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
206      (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
207     {
208       char *dir;
209
210       /* However, if the directory the directory/file is in is owned
211          by the user and is 700, then this is not a problem.
212          Theoretically, we could walk this test up to the root
213          directory /, but for the sake of sanity, I'm stopping at one
214          level down. */
215
216       dir= make_dirname (tmppath);
217       if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
218          S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
219         {
220           xfree (dir);
221           ret=0;
222           goto end;
223         }
224
225       m_free(dir);
226
227       if(!checkonly)
228         log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
229                  isdir?"directory":extension?"extension":"file",path);
230       goto end;
231     }
232
233   ret=0;
234
235  end:
236   m_free(tmppath);
237
238   return ret;
239
240 #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
241
242   return 0;
243 }
244 #endif
245
246
247 /* Wrapper around the usual sleep fucntion.  This one won't wake up
248    before the sleep time has really elapsed.  When build with Pth it
249    merely calls pth_sleep and thus suspends only the current
250    thread. */
251 void
252 gnupg_sleep (unsigned int seconds)
253 {
254 #ifdef HAVE_PTH
255   /* With Pth we force a regular sleep for seconds == 0 so that also
256      the process will give up its timeslot.  */
257   if (!seconds)
258     {
259 # ifdef HAVE_W32_SYSTEM    
260       Sleep (0);
261 # else
262       sleep (0);
263 # endif
264     }
265   pth_sleep (seconds);
266 #else
267   /* Fixme:  make sure that a sleep won't wake up to early.  */
268 # ifdef HAVE_W32_SYSTEM    
269   Sleep (seconds*1000);
270 # else
271   sleep (seconds);
272 # endif
273 #endif
274 }
275
276
277 /* This function is a NOP for POSIX systems but required under Windows
278    as the file handles as returned by OS calls (like CreateFile) are
279    different from the libc file descriptors (like open). This function
280    translates system file handles to libc file handles.  FOR_WRITE
281    gives the direction of the handle.  */
282 int
283 translate_sys2libc_fd (int fd, int for_write)
284 {
285 #ifdef HAVE_W32_SYSTEM
286   int x;
287   
288   if (fd <= 2)
289     return fd;  /* Do not do this for error, stdin, stdout, stderr.
290                    (This also ignores an fd of -1.) */
291
292   x = _open_osfhandle (fd, for_write ? 1 : 0);
293   if (x == -1)
294     log_error ("failed to translate osfhandle %p\n", (void *) fd);
295   else
296     {
297 /*       log_info ("_open_osfhandle %p yields %d%s\n", */
298 /*                 (void*)fd, x, for_write? " for writing":"" ); */
299       fd = x;
300     }
301 #endif /* HAVE_W32_SYSTEM */
302   return fd;
303 }