Line data Source code
1 : /* sysutils.c - system helpers
2 : * Copyright (C) 1991-2001, 2003-2004,
3 : * 2006-2008 Free Software Foundation, Inc.
4 : * Copyright (C) 2013-2014 Werner Koch
5 : *
6 : * This file is part of GnuPG.
7 : *
8 : * This file is free software; you can redistribute it and/or modify
9 : * it under the terms of either
10 : *
11 : * - the GNU Lesser General Public License as published by the Free
12 : * Software Foundation; either version 3 of the License, or (at
13 : * your option) any later version.
14 : *
15 : * or
16 : *
17 : * - the GNU General Public License as published by the Free
18 : * Software Foundation; either version 2 of the License, or (at
19 : * your option) any later version.
20 : *
21 : * or both in parallel, as here.
22 : *
23 : * This file is distributed in the hope that it will be useful,
24 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 : * GNU General Public License for more details.
27 : *
28 : * You should have received a copy of the GNU General Public License
29 : * along with this program; if not, see <https://www.gnu.org/licenses/>.
30 : */
31 :
32 : #include <config.h>
33 :
34 : #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */
35 : # undef HAVE_NPTH
36 : # undef USE_NPTH
37 : #endif
38 :
39 : #include <stdio.h>
40 : #include <stdlib.h>
41 : #include <stdint.h>
42 : #include <string.h>
43 : #include <unistd.h>
44 : #include <errno.h>
45 : #ifdef HAVE_STAT
46 : # include <sys/stat.h>
47 : #endif
48 : #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
49 : # include <asm/sysinfo.h>
50 : # include <asm/unistd.h>
51 : #endif
52 : #include <time.h>
53 : #ifdef HAVE_SETRLIMIT
54 : # include <sys/time.h>
55 : # include <sys/resource.h>
56 : #endif
57 : #ifdef HAVE_W32_SYSTEM
58 : # if WINVER < 0x0500
59 : # define WINVER 0x0500 /* Required for AllowSetForegroundWindow. */
60 : # endif
61 : # ifdef HAVE_WINSOCK2_H
62 : # include <winsock2.h>
63 : # endif
64 : # include <windows.h>
65 : #else /*!HAVE_W32_SYSTEM*/
66 : # include <sys/socket.h>
67 : # include <sys/un.h>
68 : #endif
69 : #ifdef HAVE_INOTIFY_INIT
70 : # include <sys/inotify.h>
71 : #endif /*HAVE_INOTIFY_INIT*/
72 : #ifdef HAVE_NPTH
73 : # include <npth.h>
74 : #endif
75 : #include <fcntl.h>
76 :
77 : #include <assuan.h>
78 :
79 : #include "util.h"
80 : #include "i18n.h"
81 :
82 : #include "sysutils.h"
83 :
84 : #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
85 :
86 :
87 : static GPGRT_INLINE gpg_error_t
88 0 : my_error_from_syserror (void)
89 : {
90 0 : return gpg_err_make (default_errsource, gpg_err_code_from_syserror ());
91 : }
92 :
93 : static GPGRT_INLINE gpg_error_t
94 0 : my_error (int e)
95 : {
96 0 : return gpg_err_make (default_errsource, (e));
97 : }
98 :
99 :
100 :
101 : #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
102 : #warning using trap_unaligned
103 : static int
104 : setsysinfo(unsigned long op, void *buffer, unsigned long size,
105 : int *start, void *arg, unsigned long flag)
106 : {
107 : return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
108 : }
109 :
110 : void
111 : trap_unaligned(void)
112 : {
113 : unsigned int buf[2];
114 :
115 : buf[0] = SSIN_UACPROC;
116 : buf[1] = UAC_SIGBUS | UAC_NOPRINT;
117 : setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
118 : }
119 : #else
120 : void
121 1227 : trap_unaligned(void)
122 : { /* dummy */
123 1227 : }
124 : #endif
125 :
126 :
127 : int
128 1280 : disable_core_dumps (void)
129 : {
130 : #ifdef HAVE_DOSISH_SYSTEM
131 : return 0;
132 : #else
133 : # ifdef HAVE_SETRLIMIT
134 : struct rlimit limit;
135 :
136 : /* We only set the current limit unless we were not able to
137 : retrieve the old value. */
138 1280 : if (getrlimit (RLIMIT_CORE, &limit))
139 0 : limit.rlim_max = 0;
140 1280 : limit.rlim_cur = 0;
141 1280 : if( !setrlimit (RLIMIT_CORE, &limit) )
142 1280 : return 0;
143 0 : if( errno != EINVAL && errno != ENOSYS )
144 0 : log_fatal (_("can't disable core dumps: %s\n"), strerror(errno) );
145 : #endif
146 0 : return 1;
147 : #endif
148 : }
149 :
150 : int
151 0 : enable_core_dumps (void)
152 : {
153 : #ifdef HAVE_DOSISH_SYSTEM
154 : return 0;
155 : #else
156 : # ifdef HAVE_SETRLIMIT
157 : struct rlimit limit;
158 :
159 0 : if (getrlimit (RLIMIT_CORE, &limit))
160 0 : return 1;
161 0 : limit.rlim_cur = limit.rlim_max;
162 0 : setrlimit (RLIMIT_CORE, &limit);
163 0 : return 1; /* We always return true because this function is
164 : merely a debugging aid. */
165 : # endif
166 : return 1;
167 : #endif
168 : }
169 :
170 :
171 :
172 : /* Return a string which is used as a kind of process ID. */
173 : const byte *
174 34 : get_session_marker (size_t *rlen)
175 : {
176 : static byte marker[SIZEOF_UNSIGNED_LONG*2];
177 : static int initialized;
178 :
179 34 : if (!initialized)
180 : {
181 16 : gcry_create_nonce (marker, sizeof marker);
182 16 : initialized = 1;
183 : }
184 34 : *rlen = sizeof (marker);
185 34 : return marker;
186 : }
187 :
188 : /* Return a random number in an unsigned int. */
189 : unsigned int
190 0 : get_uint_nonce (void)
191 : {
192 : unsigned int value;
193 :
194 0 : gcry_create_nonce (&value, sizeof value);
195 0 : return value;
196 : }
197 :
198 :
199 :
200 : #if 0 /* not yet needed - Note that this will require inclusion of
201 : cmacros.am in Makefile.am */
202 : int
203 : check_permissions(const char *path,int extension,int checkonly)
204 : {
205 : #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
206 : char *tmppath;
207 : struct stat statbuf;
208 : int ret=1;
209 : int isdir=0;
210 :
211 : if(opt.no_perm_warn)
212 : return 0;
213 :
214 : if(extension && path[0]!=DIRSEP_C)
215 : {
216 : if(strchr(path,DIRSEP_C))
217 : tmppath=make_filename(path,NULL);
218 : else
219 : tmppath=make_filename(GNUPG_LIBDIR,path,NULL);
220 : }
221 : else
222 : tmppath=m_strdup(path);
223 :
224 : /* It's okay if the file doesn't exist */
225 : if(stat(tmppath,&statbuf)!=0)
226 : {
227 : ret=0;
228 : goto end;
229 : }
230 :
231 : isdir=S_ISDIR(statbuf.st_mode);
232 :
233 : /* Per-user files must be owned by the user. Extensions must be
234 : owned by the user or root. */
235 : if((!extension && statbuf.st_uid != getuid()) ||
236 : (extension && statbuf.st_uid!=0 && statbuf.st_uid!=getuid()))
237 : {
238 : if(!checkonly)
239 : log_info(_("Warning: unsafe ownership on %s \"%s\"\n"),
240 : isdir?"directory":extension?"extension":"file",path);
241 : goto end;
242 : }
243 :
244 : /* This works for both directories and files - basically, we don't
245 : care what the owner permissions are, so long as the group and
246 : other permissions are 0 for per-user files, and non-writable for
247 : extensions. */
248 : if((extension && (statbuf.st_mode & (S_IWGRP|S_IWOTH)) !=0) ||
249 : (!extension && (statbuf.st_mode & (S_IRWXG|S_IRWXO)) != 0))
250 : {
251 : char *dir;
252 :
253 : /* However, if the directory the directory/file is in is owned
254 : by the user and is 700, then this is not a problem.
255 : Theoretically, we could walk this test up to the root
256 : directory /, but for the sake of sanity, I'm stopping at one
257 : level down. */
258 :
259 : dir= make_dirname (tmppath);
260 : if(stat(dir,&statbuf)==0 && statbuf.st_uid==getuid() &&
261 : S_ISDIR(statbuf.st_mode) && (statbuf.st_mode & (S_IRWXG|S_IRWXO))==0)
262 : {
263 : xfree (dir);
264 : ret=0;
265 : goto end;
266 : }
267 :
268 : m_free(dir);
269 :
270 : if(!checkonly)
271 : log_info(_("Warning: unsafe permissions on %s \"%s\"\n"),
272 : isdir?"directory":extension?"extension":"file",path);
273 : goto end;
274 : }
275 :
276 : ret=0;
277 :
278 : end:
279 : m_free(tmppath);
280 :
281 : return ret;
282 :
283 : #endif /* HAVE_STAT && !HAVE_DOSISH_SYSTEM */
284 :
285 : return 0;
286 : }
287 : #endif
288 :
289 :
290 : /* Wrapper around the usual sleep function. This one won't wake up
291 : before the sleep time has really elapsed. When build with Pth it
292 : merely calls pth_sleep and thus suspends only the current
293 : thread. */
294 : void
295 50 : gnupg_sleep (unsigned int seconds)
296 : {
297 : #ifdef USE_NPTH
298 0 : npth_sleep (seconds);
299 : #else
300 : /* Fixme: make sure that a sleep won't wake up to early. */
301 : # ifdef HAVE_W32_SYSTEM
302 : Sleep (seconds*1000);
303 : # else
304 50 : sleep (seconds);
305 : # endif
306 : #endif
307 50 : }
308 :
309 :
310 : /* Wrapper around the platforms usleep function. This one won't wake
311 : * up before the sleep time has really elapsed. When build with nPth
312 : * it merely calls npth_usleep and thus suspends only the current
313 : * thread. */
314 : void
315 0 : gnupg_usleep (unsigned int usecs)
316 : {
317 : #if defined(USE_NPTH)
318 :
319 0 : npth_usleep (usecs);
320 :
321 : #elif defined(HAVE_W32_SYSTEM)
322 :
323 : Sleep ((usecs + 999) / 1000);
324 :
325 : #elif defined(HAVE_NANOSLEEP)
326 :
327 0 : if (usecs)
328 : {
329 : struct timespec req;
330 : struct timespec rem;
331 :
332 0 : req.tv_sec = 0;
333 0 : req.tv_nsec = usecs * 1000;
334 :
335 0 : while (nanosleep (&req, &rem) < 0 && errno == EINTR)
336 0 : req = rem;
337 : }
338 :
339 : #else /*Standard Unix*/
340 :
341 : if (usecs)
342 : {
343 : struct timeval tv;
344 :
345 : tv.tv_sec = usecs / 1000000;
346 : tv.tv_usec = usecs % 1000000;
347 : select (0, NULL, NULL, NULL, &tv);
348 : }
349 :
350 : #endif
351 0 : }
352 :
353 :
354 : /* This function is a NOP for POSIX systems but required under Windows
355 : as the file handles as returned by OS calls (like CreateFile) are
356 : different from the libc file descriptors (like open). This function
357 : translates system file handles to libc file handles. FOR_WRITE
358 : gives the direction of the handle. */
359 : int
360 0 : translate_sys2libc_fd (gnupg_fd_t fd, int for_write)
361 : {
362 : #if defined(HAVE_W32CE_SYSTEM)
363 : (void)for_write;
364 : return (int) fd;
365 : #elif defined(HAVE_W32_SYSTEM)
366 : int x;
367 :
368 : if (fd == GNUPG_INVALID_FD)
369 : return -1;
370 :
371 : /* Note that _open_osfhandle is currently defined to take and return
372 : a long. */
373 : x = _open_osfhandle ((long)fd, for_write ? 1 : 0);
374 : if (x == -1)
375 : log_error ("failed to translate osfhandle %p\n", (void *) fd);
376 : return x;
377 : #else /*!HAVE_W32_SYSTEM */
378 : (void)for_write;
379 0 : return fd;
380 : #endif
381 : }
382 :
383 : /* This is the same as translate_sys2libc_fd but takes an integer
384 : which is assumed to be such an system handle. On WindowsCE the
385 : passed FD is a rendezvous ID and the function finishes the pipe
386 : creation. */
387 : int
388 193 : translate_sys2libc_fd_int (int fd, int for_write)
389 : {
390 : #if HAVE_W32CE_SYSTEM
391 : fd = (int) _assuan_w32ce_finish_pipe (fd, for_write);
392 : return translate_sys2libc_fd ((void*)fd, for_write);
393 : #elif HAVE_W32_SYSTEM
394 : if (fd <= 2)
395 : return fd; /* Do not do this for error, stdin, stdout, stderr. */
396 :
397 : return translate_sys2libc_fd ((void*)fd, for_write);
398 : #else
399 : (void)for_write;
400 193 : return fd;
401 : #endif
402 : }
403 :
404 :
405 :
406 : /* Replacement for tmpfile(). This is required because the tmpfile
407 : function of Windows' runtime library is broken, insecure, ignores
408 : TMPDIR and so on. In addition we create a file with an inheritable
409 : handle. */
410 : FILE *
411 10 : gnupg_tmpfile (void)
412 : {
413 : #ifdef HAVE_W32_SYSTEM
414 : int attempts, n;
415 : #ifdef HAVE_W32CE_SYSTEM
416 : wchar_t buffer[MAX_PATH+7+12+1];
417 : # define mystrlen(a) wcslen (a)
418 : wchar_t *name, *p;
419 : #else
420 : char buffer[MAX_PATH+7+12+1];
421 : # define mystrlen(a) strlen (a)
422 : char *name, *p;
423 : #endif
424 : HANDLE file;
425 : int pid = GetCurrentProcessId ();
426 : unsigned int value;
427 : int i;
428 : SECURITY_ATTRIBUTES sec_attr;
429 :
430 : memset (&sec_attr, 0, sizeof sec_attr );
431 : sec_attr.nLength = sizeof sec_attr;
432 : sec_attr.bInheritHandle = TRUE;
433 :
434 : n = GetTempPath (MAX_PATH+1, buffer);
435 : if (!n || n > MAX_PATH || mystrlen (buffer) > MAX_PATH)
436 : {
437 : gpg_err_set_errno (ENOENT);
438 : return NULL;
439 : }
440 : p = buffer + mystrlen (buffer);
441 : #ifdef HAVE_W32CE_SYSTEM
442 : wcscpy (p, L"_gnupg");
443 : p += 7;
444 : #else
445 : p = stpcpy (p, "_gnupg");
446 : #endif
447 : /* We try to create the directory but don't care about an error as
448 : it may already exist and the CreateFile would throw an error
449 : anyway. */
450 : CreateDirectory (buffer, NULL);
451 : *p++ = '\\';
452 : name = p;
453 : for (attempts=0; attempts < 10; attempts++)
454 : {
455 : p = name;
456 : value = (GetTickCount () ^ ((pid<<16) & 0xffff0000));
457 : for (i=0; i < 8; i++)
458 : {
459 : *p++ = tohex (((value >> 28) & 0x0f));
460 : value <<= 4;
461 : }
462 : #ifdef HAVE_W32CE_SYSTEM
463 : wcscpy (p, L".tmp");
464 : #else
465 : strcpy (p, ".tmp");
466 : #endif
467 : file = CreateFile (buffer,
468 : GENERIC_READ | GENERIC_WRITE,
469 : 0,
470 : &sec_attr,
471 : CREATE_NEW,
472 : FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
473 : NULL);
474 : if (file != INVALID_HANDLE_VALUE)
475 : {
476 : FILE *fp;
477 : #ifdef HAVE_W32CE_SYSTEM
478 : int fd = (int)file;
479 : fp = _wfdopen (fd, L"w+b");
480 : #else
481 : int fd = _open_osfhandle ((long)file, 0);
482 : if (fd == -1)
483 : {
484 : CloseHandle (file);
485 : return NULL;
486 : }
487 : fp = fdopen (fd, "w+b");
488 : #endif
489 : if (!fp)
490 : {
491 : int save = errno;
492 : close (fd);
493 : gpg_err_set_errno (save);
494 : return NULL;
495 : }
496 : return fp;
497 : }
498 : Sleep (1); /* One ms as this is the granularity of GetTickCount. */
499 : }
500 : gpg_err_set_errno (ENOENT);
501 : return NULL;
502 : #undef mystrlen
503 : #else /*!HAVE_W32_SYSTEM*/
504 10 : return tmpfile ();
505 : #endif /*!HAVE_W32_SYSTEM*/
506 : }
507 :
508 :
509 : /* Make sure that the standard file descriptors are opened. Obviously
510 : some folks close them before an exec and the next file we open will
511 : get one of them assigned and thus any output (i.e. diagnostics) end
512 : up in that file (e.g. the trustdb). Not actually a gpg problem as
513 : this will happen with almost all utilities when called in a wrong
514 : way. However we try to minimize the damage here and raise
515 : awareness of the problem.
516 :
517 : Must be called before we open any files! */
518 : void
519 1388 : gnupg_reopen_std (const char *pgmname)
520 : {
521 : #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
522 : struct stat statbuf;
523 1388 : int did_stdin = 0;
524 1388 : int did_stdout = 0;
525 1388 : int did_stderr = 0;
526 : FILE *complain;
527 :
528 1388 : if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
529 : {
530 0 : if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
531 0 : did_stdin = 1;
532 : else
533 0 : did_stdin = 2;
534 : }
535 :
536 1388 : if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
537 : {
538 0 : if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
539 0 : did_stdout = 1;
540 : else
541 0 : did_stdout = 2;
542 : }
543 :
544 1388 : if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
545 : {
546 0 : if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
547 0 : did_stderr = 1;
548 : else
549 0 : did_stderr = 2;
550 : }
551 :
552 : /* It's hard to log this sort of thing since the filehandle we would
553 : complain to may be closed... */
554 1388 : if (!did_stderr)
555 1388 : complain = stderr;
556 0 : else if (!did_stdout)
557 0 : complain = stdout;
558 : else
559 0 : complain = NULL;
560 :
561 1388 : if (complain)
562 : {
563 1388 : if (did_stdin == 1)
564 0 : fprintf (complain, "%s: WARNING: standard input reopened\n", pgmname);
565 1388 : if (did_stdout == 1)
566 0 : fprintf (complain, "%s: WARNING: standard output reopened\n", pgmname);
567 1388 : if (did_stderr == 1)
568 0 : fprintf (complain, "%s: WARNING: standard error reopened\n", pgmname);
569 :
570 1388 : if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
571 0 : fprintf(complain,"%s: fatal: unable to reopen standard input,"
572 : " output, or error\n", pgmname);
573 : }
574 :
575 1388 : if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
576 0 : exit (3);
577 : #else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
578 : (void)pgmname;
579 : #endif
580 1388 : }
581 :
582 :
583 : /* Hack required for Windows. */
584 : void
585 5 : gnupg_allow_set_foregound_window (pid_t pid)
586 : {
587 5 : if (!pid)
588 1 : log_info ("%s called with invalid pid %lu\n",
589 : "gnupg_allow_set_foregound_window", (unsigned long)pid);
590 : #if defined(HAVE_W32_SYSTEM) && !defined(HAVE_W32CE_SYSTEM)
591 : else if (!AllowSetForegroundWindow ((pid_t)pid == (pid_t)(-1)?ASFW_ANY:pid))
592 : log_info ("AllowSetForegroundWindow(%lu) failed: %s\n",
593 : (unsigned long)pid, w32_strerror (-1));
594 : #endif
595 5 : }
596 :
597 : int
598 200 : gnupg_remove (const char *fname)
599 : {
600 : #ifdef HAVE_W32CE_SYSTEM
601 : int rc;
602 : wchar_t *wfname;
603 :
604 : wfname = utf8_to_wchar (fname);
605 : if (!wfname)
606 : rc = 0;
607 : else
608 : {
609 : rc = DeleteFile (wfname);
610 : xfree (wfname);
611 : }
612 : if (!rc)
613 : return -1; /* ERRNO is automagically provided by gpg-error.h. */
614 : return 0;
615 : #else
616 200 : return remove (fname);
617 : #endif
618 : }
619 :
620 :
621 : /* Wrapper for rename(2) to handle Windows peculiarities. If
622 : * BLOCK_SIGNALS is not NULL and points to a variable set to true, all
623 : * signals will be blocked by calling gnupg_block_all_signals; the
624 : * caller needs to call gnupg_unblock_all_signals if that variable is
625 : * still set to true on return. */
626 : gpg_error_t
627 334 : gnupg_rename_file (const char *oldname, const char *newname, int *block_signals)
628 : {
629 334 : gpg_error_t err = 0;
630 :
631 334 : if (block_signals && *block_signals)
632 167 : gnupg_block_all_signals ();
633 :
634 : #ifdef HAVE_DOSISH_SYSTEM
635 : {
636 : int wtime = 0;
637 :
638 : gnupg_remove (newname);
639 : again:
640 : if (rename (oldname, newname))
641 : {
642 : if (GetLastError () == ERROR_SHARING_VIOLATION)
643 : {
644 : /* Another process has the file open. We do not use a
645 : * lock for read but instead we wait until the other
646 : * process has closed the file. This may take long but
647 : * that would also be the case with a dotlock approach for
648 : * read and write. Note that we don't need this on Unix
649 : * due to the inode concept.
650 : *
651 : * So let's wait until the rename has worked. The retry
652 : * intervals are 50, 100, 200, 400, 800, 50ms, ... */
653 : if (!wtime || wtime >= 800)
654 : wtime = 50;
655 : else
656 : wtime *= 2;
657 :
658 : if (wtime >= 800)
659 : log_info (_("waiting for file '%s' to become accessible ...\n"),
660 : oldname);
661 :
662 : Sleep (wtime);
663 : goto again;
664 : }
665 : err = my_error_from_syserror ();
666 : }
667 : }
668 : #else /* Unix */
669 : {
670 : #ifdef __riscos__
671 : gnupg_remove (newname);
672 : #endif
673 334 : if (rename (oldname, newname) )
674 0 : err = my_error_from_syserror ();
675 : }
676 : #endif /* Unix */
677 :
678 334 : if (block_signals && *block_signals && err)
679 : {
680 0 : gnupg_unblock_all_signals ();
681 0 : *block_signals = 0;
682 : }
683 :
684 334 : if (err)
685 0 : log_error (_("renaming '%s' to '%s' failed: %s\n"),
686 : oldname, newname, gpg_strerror (err));
687 334 : return err;
688 : }
689 :
690 :
691 : #ifndef HAVE_W32_SYSTEM
692 : static mode_t
693 1242 : modestr_to_mode (const char *modestr)
694 : {
695 1242 : mode_t mode = 0;
696 :
697 1242 : if (modestr && *modestr)
698 : {
699 1241 : modestr++;
700 1241 : if (*modestr && *modestr++ == 'r')
701 1241 : mode |= S_IRUSR;
702 1241 : if (*modestr && *modestr++ == 'w')
703 1241 : mode |= S_IWUSR;
704 1241 : if (*modestr && *modestr++ == 'x')
705 1241 : mode |= S_IXUSR;
706 1241 : if (*modestr && *modestr++ == 'r')
707 0 : mode |= S_IRGRP;
708 1241 : if (*modestr && *modestr++ == 'w')
709 0 : mode |= S_IWGRP;
710 1241 : if (*modestr && *modestr++ == 'x')
711 0 : mode |= S_IXGRP;
712 1241 : if (*modestr && *modestr++ == 'r')
713 0 : mode |= S_IROTH;
714 1241 : if (*modestr && *modestr++ == 'w')
715 0 : mode |= S_IWOTH;
716 1241 : if (*modestr && *modestr++ == 'x')
717 0 : mode |= S_IXOTH;
718 : }
719 :
720 1242 : return mode;
721 : }
722 : #endif
723 :
724 :
725 : /* A wrapper around mkdir which takes a string for the mode argument.
726 : This makes it easier to handle the mode argument which is not
727 : defined on all systems. The format of the modestring is
728 :
729 : "-rwxrwxrwx"
730 :
731 : '-' is a don't care or not set. 'r', 'w', 'x' are read allowed,
732 : write allowed, execution allowed with the first group for the user,
733 : the second for the group and the third for all others. If the
734 : string is shorter than above the missing mode characters are meant
735 : to be not set. */
736 : int
737 992 : gnupg_mkdir (const char *name, const char *modestr)
738 : {
739 : #ifdef HAVE_W32CE_SYSTEM
740 : wchar_t *wname;
741 : (void)modestr;
742 :
743 : wname = utf8_to_wchar (name);
744 : if (!wname)
745 : return -1;
746 : if (!CreateDirectoryW (wname, NULL))
747 : {
748 : xfree (wname);
749 : return -1; /* ERRNO is automagically provided by gpg-error.h. */
750 : }
751 : xfree (wname);
752 : return 0;
753 : #elif MKDIR_TAKES_ONE_ARG
754 : (void)modestr;
755 : /* Note: In the case of W32 we better use CreateDirectory and try to
756 : set appropriate permissions. However using mkdir is easier
757 : because this sets ERRNO. */
758 : return mkdir (name);
759 : #else
760 992 : return mkdir (name, modestr_to_mode (modestr));
761 : #endif
762 : }
763 :
764 :
765 : /* A wrapper around chmod which takes a string for the mode argument.
766 : This makes it easier to handle the mode argument which is not
767 : defined on all systems. The format of the modestring is the same
768 : as for gnupg_mkdir. */
769 : int
770 250 : gnupg_chmod (const char *name, const char *modestr)
771 : {
772 : #ifdef HAVE_W32_SYSTEM
773 : (void)name;
774 : (void)modestr;
775 : return 0;
776 : #else
777 250 : return chmod (name, modestr_to_mode (modestr));
778 : #endif
779 : }
780 :
781 :
782 : /* Our version of mkdtemp. The API is identical to POSIX.1-2008
783 : version. We do not use a system provided mkdtemp because we have a
784 : good RNG instantly available and this way we don't have diverging
785 : versions. */
786 : char *
787 863 : gnupg_mkdtemp (char *tmpl)
788 : {
789 : /* A lower bound on the number of temporary files to attempt to
790 : generate. The maximum total number of temporary file names that
791 : can exist for a given template is 62**6 (5*36**3 for Windows).
792 : It should never be necessary to try all these combinations.
793 : Instead if a reasonable number of names is tried (we define
794 : reasonable as 62**3 or 5*36**3) fail to give the system
795 : administrator the chance to remove the problems. */
796 : #ifdef HAVE_W32_SYSTEM
797 : static const char letters[] =
798 : "abcdefghijklmnopqrstuvwxyz0123456789";
799 : # define NUMBER_OF_LETTERS 36
800 : # define ATTEMPTS_MIN (5 * 36 * 36 * 36)
801 : #else
802 : static const char letters[] =
803 : "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
804 : # define NUMBER_OF_LETTERS 62
805 : # define ATTEMPTS_MIN (62 * 62 * 62)
806 : #endif
807 : int len;
808 : char *XXXXXX;
809 : uint64_t value;
810 : unsigned int count;
811 863 : int save_errno = errno;
812 : /* The number of times to attempt to generate a temporary file. To
813 : conform to POSIX, this must be no smaller than TMP_MAX. */
814 : #if ATTEMPTS_MIN < TMP_MAX
815 : unsigned int attempts = TMP_MAX;
816 : #else
817 863 : unsigned int attempts = ATTEMPTS_MIN;
818 : #endif
819 :
820 863 : len = strlen (tmpl);
821 863 : if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
822 : {
823 0 : gpg_err_set_errno (EINVAL);
824 0 : return NULL;
825 : }
826 :
827 : /* This is where the Xs start. */
828 863 : XXXXXX = &tmpl[len - 6];
829 :
830 : /* Get a random start value. */
831 863 : gcry_create_nonce (&value, sizeof value);
832 :
833 : /* Loop until a directory was created. */
834 863 : for (count = 0; count < attempts; value += 7777, ++count)
835 : {
836 863 : uint64_t v = value;
837 :
838 : /* Fill in the random bits. */
839 863 : XXXXXX[0] = letters[v % NUMBER_OF_LETTERS];
840 863 : v /= NUMBER_OF_LETTERS;
841 863 : XXXXXX[1] = letters[v % NUMBER_OF_LETTERS];
842 863 : v /= NUMBER_OF_LETTERS;
843 863 : XXXXXX[2] = letters[v % NUMBER_OF_LETTERS];
844 863 : v /= NUMBER_OF_LETTERS;
845 863 : XXXXXX[3] = letters[v % NUMBER_OF_LETTERS];
846 863 : v /= NUMBER_OF_LETTERS;
847 863 : XXXXXX[4] = letters[v % NUMBER_OF_LETTERS];
848 863 : v /= NUMBER_OF_LETTERS;
849 863 : XXXXXX[5] = letters[v % NUMBER_OF_LETTERS];
850 :
851 863 : if (!gnupg_mkdir (tmpl, "-rwx"))
852 : {
853 863 : gpg_err_set_errno (save_errno);
854 863 : return tmpl;
855 : }
856 0 : if (errno != EEXIST)
857 0 : return NULL;
858 : }
859 :
860 : /* We got out of the loop because we ran out of combinations to try. */
861 0 : gpg_err_set_errno (EEXIST);
862 0 : return NULL;
863 : }
864 :
865 :
866 : int
867 106 : gnupg_setenv (const char *name, const char *value, int overwrite)
868 : {
869 : #ifdef HAVE_W32CE_SYSTEM
870 : (void)name;
871 : (void)value;
872 : (void)overwrite;
873 : return 0;
874 : #else /*!W32CE*/
875 : # ifdef HAVE_W32_SYSTEM
876 : /* Windows maintains (at least) two sets of environment variables.
877 : One set can be accessed by GetEnvironmentVariable and
878 : SetEnvironmentVariable. This set is inherited by the children.
879 : The other set is maintained in the C runtime, and is accessed
880 : using getenv and putenv. We try to keep them in sync by
881 : modifying both sets. */
882 : {
883 : int exists;
884 : char tmpbuf[10];
885 : exists = GetEnvironmentVariable (name, tmpbuf, sizeof tmpbuf);
886 :
887 : if ((! exists || overwrite) && !SetEnvironmentVariable (name, value))
888 : {
889 : gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
890 : return -1;
891 : }
892 : }
893 : # endif /*W32*/
894 :
895 : # ifdef HAVE_SETENV
896 106 : return setenv (name, value, overwrite);
897 : # else /*!HAVE_SETENV*/
898 : if (! getenv (name) || overwrite)
899 : {
900 : char *buf;
901 :
902 : (void)overwrite;
903 : if (!name || !value)
904 : {
905 : gpg_err_set_errno (EINVAL);
906 : return -1;
907 : }
908 : buf = strconcat (name, "=", value, NULL);
909 : if (!buf)
910 : return -1;
911 : # if __GNUC__
912 : # warning no setenv - using putenv but leaking memory.
913 : # endif
914 : return putenv (buf);
915 : }
916 : return 0;
917 : # endif /*!HAVE_SETENV*/
918 : #endif /*!W32CE*/
919 : }
920 :
921 :
922 : int
923 100 : gnupg_unsetenv (const char *name)
924 : {
925 : #ifdef HAVE_W32CE_SYSTEM
926 : (void)name;
927 : return 0;
928 : #else /*!W32CE*/
929 : # ifdef HAVE_W32_SYSTEM
930 : /* Windows maintains (at least) two sets of environment variables.
931 : One set can be accessed by GetEnvironmentVariable and
932 : SetEnvironmentVariable. This set is inherited by the children.
933 : The other set is maintained in the C runtime, and is accessed
934 : using getenv and putenv. We try to keep them in sync by
935 : modifying both sets. */
936 : if (!SetEnvironmentVariable (name, NULL))
937 : {
938 : gpg_err_set_errno (EINVAL); /* (Might also be ENOMEM.) */
939 : return -1;
940 : }
941 : # endif /*W32*/
942 :
943 : # ifdef HAVE_UNSETENV
944 100 : return unsetenv (name);
945 : # else /*!HAVE_UNSETENV*/
946 : {
947 : char *buf;
948 :
949 : if (!name)
950 : {
951 : gpg_err_set_errno (EINVAL);
952 : return -1;
953 : }
954 : buf = xtrystrdup (name);
955 : if (!buf)
956 : return -1;
957 : # if __GNUC__
958 : # warning no unsetenv - trying putenv but leaking memory.
959 : # endif
960 : return putenv (buf);
961 : }
962 : # endif /*!HAVE_UNSETENV*/
963 : #endif /*!W32CE*/
964 : }
965 :
966 :
967 : /* Return the current working directory as a malloced string. Return
968 : NULL and sets ERRNo on error. */
969 : char *
970 133 : gnupg_getcwd (void)
971 : {
972 : char *buffer;
973 133 : size_t size = 100;
974 :
975 : for (;;)
976 : {
977 133 : buffer = xtrymalloc (size+1);
978 133 : if (!buffer)
979 0 : return NULL;
980 : #ifdef HAVE_W32CE_SYSTEM
981 : strcpy (buffer, "/"); /* Always "/". */
982 : return buffer;
983 : #else
984 133 : if (getcwd (buffer, size) == buffer)
985 133 : return buffer;
986 0 : xfree (buffer);
987 0 : if (errno != ERANGE)
988 0 : return NULL;
989 0 : size *= 2;
990 : #endif
991 0 : }
992 : }
993 :
994 :
995 :
996 : #ifdef HAVE_W32CE_SYSTEM
997 : /* There is a isatty function declaration in cegcc but it does not
998 : make sense, thus we redefine it. */
999 : int
1000 : _gnupg_isatty (int fd)
1001 : {
1002 : (void)fd;
1003 : return 0;
1004 : }
1005 : #endif
1006 :
1007 :
1008 : #ifdef HAVE_W32CE_SYSTEM
1009 : /* Replacement for getenv which takes care of the our use of getenv.
1010 : The code is not thread safe but we expect it to work in all cases
1011 : because it is called for the first time early enough. */
1012 : char *
1013 : _gnupg_getenv (const char *name)
1014 : {
1015 : static int initialized;
1016 : static char *assuan_debug;
1017 :
1018 : if (!initialized)
1019 : {
1020 : assuan_debug = read_w32_registry_string (NULL,
1021 : "\\Software\\GNU\\libassuan",
1022 : "debug");
1023 : initialized = 1;
1024 : }
1025 :
1026 : if (!strcmp (name, "ASSUAN_DEBUG"))
1027 : return assuan_debug;
1028 : else
1029 : return NULL;
1030 : }
1031 :
1032 : #endif /*HAVE_W32CE_SYSTEM*/
1033 :
1034 :
1035 : #ifdef HAVE_W32_SYSTEM
1036 : /* Return the user's security identifier from the current process. */
1037 : PSID
1038 : w32_get_user_sid (void)
1039 : {
1040 : int okay = 0;
1041 : HANDLE proc = NULL;
1042 : HANDLE token = NULL;
1043 : TOKEN_USER *user = NULL;
1044 : PSID sid = NULL;
1045 : DWORD tokenlen, sidlen;
1046 :
1047 : proc = OpenProcess (PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
1048 : if (!proc)
1049 : goto leave;
1050 :
1051 : if (!OpenProcessToken (proc, TOKEN_QUERY, &token))
1052 : goto leave;
1053 :
1054 : if (!GetTokenInformation (token, TokenUser, NULL, 0, &tokenlen)
1055 : && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1056 : goto leave;
1057 :
1058 : user = xtrymalloc (tokenlen);
1059 : if (!user)
1060 : goto leave;
1061 :
1062 : if (!GetTokenInformation (token, TokenUser, user, tokenlen, &tokenlen))
1063 : goto leave;
1064 : if (!IsValidSid (user->User.Sid))
1065 : goto leave;
1066 : sidlen = GetLengthSid (user->User.Sid);
1067 : sid = xtrymalloc (sidlen);
1068 : if (!sid)
1069 : goto leave;
1070 : if (!CopySid (sidlen, sid, user->User.Sid))
1071 : goto leave;
1072 : okay = 1;
1073 :
1074 : leave:
1075 : xfree (user);
1076 : if (token)
1077 : CloseHandle (token);
1078 : if (proc)
1079 : CloseHandle (proc);
1080 :
1081 : if (!okay)
1082 : {
1083 : xfree (sid);
1084 : sid = NULL;
1085 : }
1086 : return sid;
1087 : }
1088 : #endif /*HAVE_W32_SYSTEM*/
1089 :
1090 :
1091 :
1092 : /* Support for inotify under Linux. */
1093 :
1094 : /* Store a new inotify file handle for SOCKET_NAME at R_FD or return
1095 : * an error code. */
1096 : gpg_error_t
1097 50 : gnupg_inotify_watch_socket (int *r_fd, const char *socket_name)
1098 : {
1099 : #if HAVE_INOTIFY_INIT
1100 : gpg_error_t err;
1101 : char *fname;
1102 : int fd;
1103 : char *p;
1104 :
1105 50 : *r_fd = -1;
1106 :
1107 50 : if (!socket_name)
1108 0 : return my_error (GPG_ERR_INV_VALUE);
1109 :
1110 50 : fname = xtrystrdup (socket_name);
1111 50 : if (!fname)
1112 0 : return my_error_from_syserror ();
1113 :
1114 50 : fd = inotify_init ();
1115 50 : if (fd == -1)
1116 : {
1117 0 : err = my_error_from_syserror ();
1118 0 : xfree (fname);
1119 0 : return err;
1120 : }
1121 :
1122 : /* We need to watch the directory for the file because there won't
1123 : * be an IN_DELETE_SELF for a socket file. To handle a removal of
1124 : * the directory we also watch the directory itself. */
1125 50 : p = strrchr (fname, '/');
1126 50 : if (p)
1127 50 : *p = 0;
1128 50 : if (inotify_add_watch (fd, fname,
1129 : (IN_DELETE|IN_DELETE_SELF|IN_EXCL_UNLINK)) == -1)
1130 : {
1131 0 : err = my_error_from_syserror ();
1132 0 : close (fd);
1133 0 : xfree (fname);
1134 0 : return err;
1135 : }
1136 :
1137 50 : xfree (fname);
1138 :
1139 50 : *r_fd = fd;
1140 50 : return 0;
1141 : #else /*!HAVE_INOTIFY_INIT*/
1142 :
1143 : (void)socket_name;
1144 : *r_fd = -1;
1145 : return my_error (GPG_ERR_NOT_SUPPORTED);
1146 :
1147 : #endif /*!HAVE_INOTIFY_INIT*/
1148 : }
1149 :
1150 :
1151 : /* Read an inotify event and return true if it matches NAME or if it
1152 : * sees an IN_DELETE_SELF event for the directory of NAME. */
1153 : int
1154 78 : gnupg_inotify_has_name (int fd, const char *name)
1155 : {
1156 : #if USE_NPTH && HAVE_INOTIFY_INIT
1157 : #define BUFSIZE_FOR_INOTIFY (sizeof (struct inotify_event) + 255 + 1)
1158 : union {
1159 : struct inotify_event ev;
1160 : char _buf[sizeof (struct inotify_event) + 255 + 1];
1161 : } buf;
1162 : struct inotify_event *evp;
1163 : int n;
1164 :
1165 78 : n = npth_read (fd, &buf, sizeof buf);
1166 : /* log_debug ("notify read: n=%d\n", n); */
1167 78 : evp = &buf.ev;
1168 244 : while (n >= sizeof (struct inotify_event))
1169 : {
1170 : /* log_debug (" mask=%x len=%u name=(%s)\n", */
1171 : /* evp->mask, (unsigned int)evp->len, evp->len? evp->name:""); */
1172 92 : if ((evp->mask & IN_UNMOUNT))
1173 : {
1174 : /* log_debug (" found (dir unmounted)\n"); */
1175 0 : return 3; /* Directory was unmounted. */
1176 : }
1177 92 : if ((evp->mask & IN_DELETE_SELF))
1178 : {
1179 : /* log_debug (" found (dir removed)\n"); */
1180 0 : return 2; /* Directory was removed. */
1181 : }
1182 92 : if ((evp->mask & IN_DELETE))
1183 : {
1184 92 : if (evp->len >= strlen (name) && !strcmp (evp->name, name))
1185 : {
1186 : /* log_debug (" found (file removed)\n"); */
1187 4 : return 1; /* File was removed. */
1188 : }
1189 : }
1190 88 : n -= sizeof (*evp) + evp->len;
1191 88 : evp = (struct inotify_event *)(void *)
1192 88 : ((char *)evp + sizeof (*evp) + evp->len);
1193 : }
1194 :
1195 : #else /*!(USE_NPTH && HAVE_INOTIFY_INIT)*/
1196 :
1197 : (void)fd;
1198 : (void)name;
1199 :
1200 : #endif /*!(USE_NPTH && HAVE_INOTIFY_INIT)*/
1201 :
1202 74 : return 0; /* Not found. */
1203 : }
1204 :
1205 :
1206 : /* Return a malloc'ed string that is the path to the passed
1207 : * unix-domain socket (or return NULL if this is not a valid
1208 : * unix-domain socket). We use a plain int here because it is only
1209 : * used on Linux.
1210 : *
1211 : * FIXME: This function needs to be moved to libassuan. */
1212 : #ifndef HAVE_W32_SYSTEM
1213 : char *
1214 0 : gnupg_get_socket_name (int fd)
1215 : {
1216 : struct sockaddr_un un;
1217 0 : socklen_t len = sizeof(un);
1218 0 : char *name = NULL;
1219 :
1220 0 : if (getsockname (fd, (struct sockaddr*)&un, &len) != 0)
1221 0 : log_error ("could not getsockname(%d): %s\n", fd,
1222 : gpg_strerror (my_error_from_syserror ()));
1223 0 : else if (un.sun_family != AF_UNIX)
1224 0 : log_error ("file descriptor %d is not a unix-domain socket\n", fd);
1225 0 : else if (len <= offsetof (struct sockaddr_un, sun_path))
1226 0 : log_error ("socket name not present for file descriptor %d\n", fd);
1227 0 : else if (len > sizeof(un))
1228 0 : log_error ("socket name for file descriptor %d was truncated "
1229 : "(passed %zu bytes, wanted %u)\n", fd, sizeof(un), len);
1230 : else
1231 : {
1232 0 : size_t namelen = len - offsetof (struct sockaddr_un, sun_path);
1233 :
1234 : /* log_debug ("file descriptor %d has path %s (%zu octets)\n", fd, */
1235 : /* un.sun_path, namelen); */
1236 0 : name = xtrymalloc (namelen + 1);
1237 0 : if (!name)
1238 0 : log_error ("failed to allocate memory for name of fd %d: %s\n",
1239 : fd, gpg_strerror (my_error_from_syserror ()));
1240 : else
1241 : {
1242 0 : memcpy (name, un.sun_path, namelen);
1243 0 : name[namelen] = 0;
1244 : }
1245 : }
1246 :
1247 0 : return name;
1248 : }
1249 : #endif /*!HAVE_W32_SYSTEM*/
|