Translate all file descriptors received from assuan.
[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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21
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
26
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
50
51 #include "util.h"
52 #include "i18n.h"
53
54 #include "sysutils.h"
55
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)
61 {
62     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
63 }
64
65 void
66 trap_unaligned(void)
67 {
68     unsigned int buf[2];
69
70     buf[0] = SSIN_UACPROC;
71     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
72     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
73 }
74 #else
75 void
76 trap_unaligned(void)
77 {  /* dummy */
78 }
79 #endif
80
81
82 int
83 disable_core_dumps (void)
84 {
85 #ifdef HAVE_DOSISH_SYSTEM
86     return 0;
87 #else
88 # ifdef HAVE_SETRLIMIT
89     struct rlimit limit;
90
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
103 }
104
105 int
106 enable_core_dumps (void)
107 {
108 #ifdef HAVE_DOSISH_SYSTEM
109     return 0;
110 #else
111 # ifdef HAVE_SETRLIMIT
112     struct rlimit limit;
113
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
123 }
124
125
126
127 /* Return a string which is used as a kind of process ID */
128 const byte *
129 get_session_marker( size_t *rlen )
130 {
131     static byte marker[SIZEOF_UNSIGNED_LONG*2];
132     static int initialized;
133
134     if ( !initialized ) {
135         volatile ulong aa, bb; /* we really want the uninitialized value */
136         ulong a, b;
137
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 );
149     }
150     *rlen = sizeof(marker);
151     return marker;
152 }
153
154
155 #if 0 /* not yet needed - Note that this will require inclusion of
156          cmacros.am in Makefile.am */
157 int
158 check_permissions(const char *path,int extension,int checkonly)
159 {
160 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
161   char *tmppath;
162   struct stat statbuf;
163   int ret=1;
164   int isdir=0;
165
166   if(opt.no_perm_warn)
167     return 0;
168
169   if(extension && path[0]!=DIRSEP_C)
170     {
171       if(strchr(path,DIRSEP_C))
172         tmppath=make_filename(path,NULL);
173       else
174         tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
175     }
176   else
177     tmppath=m_strdup(path);
178
179   /* It's okay if the file doesn't exist */
180   if(stat(tmppath,&statbuf)!=0)
181     {
182       ret=0;
183       goto end;
184     }
185
186   isdir=S_ISDIR(statbuf.st_mode);
187
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()))
192     {
193       if(!checkonly)
194         log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
195                  isdir?"directory":extension?"extension":"file",path);
196       goto end;
197     }
198
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))
205     {
206       char *dir;
207
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. */
213
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)
217         {
218           xfree (dir);
219           ret=0;
220           goto end;
221         }
222
223       m_free(dir);
224
225       if(!checkonly)
226         log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
227                  isdir?"directory":extension?"extension":"file",path);
228       goto end;
229     }
230
231   ret=0;
232
233  end:
234   m_free(tmppath);
235
236   return ret;
237
238 #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
239
240   return 0;
241 }
242 #endif
243
244
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)
251 {
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)
256     {
257 # ifdef HAVE_W32_SYSTEM    
258       Sleep (0);
259 # else
260       sleep (0);
261 # endif
262     }
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
272 }
273
274
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.  */
280 int
281 translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
282 {
283 #ifdef HAVE_W32_SYSTEM
284   int x;
285
286   if (fd == GNUPG_INVALID_FD)
287     return -1;
288   
289   /* Note that _open_osfhandle is currently defined to take and return
290      a long.  */
291   x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
292   if (x == -1)
293     log_error ("failed to translate osfhandle %p\n", (void *) fd);
294   return x;
295 #else /*!HAVE_W32_SYSTEM */
296   return fd;
297 #endif
298 }
299
300 /* This is the same as translate_sys2libc_fd but takes an integer
301    which is assumet to be such an system handle.  */
302 int
303 translate_sys2libc_fd_int (int fd, int for_write)
304 {
305 #ifdef HAVE_W32_SYSTEM
306   if (fd <= 2)
307     return fd;  /* Do not do this for error, stdin, stdout, stderr. */
308
309   return translate_sys2libc_fd ((void*)fd, for_write);
310 #else
311   return fd;
312 #endif
313 }