hardening: Use __secure_getenv if available
[platform/upstream/dbus.git] / dbus / dbus-sysdeps.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-sysdeps.c Wrappers around system/libc features shared between UNIX and Windows (internal to D-Bus implementation)
3  * 
4  * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
5  * Copyright (C) 2003 CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #include <config.h>
26 #include "dbus-internals.h"
27 #include "dbus-sysdeps.h"
28 #include "dbus-threads.h"
29 #include "dbus-protocol.h"
30 #include "dbus-string.h"
31 #include "dbus-list.h"
32
33 /* NOTE: If you include any unix/windows-specific headers here, you are probably doing something
34  * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c.
35  *
36  * These are the standard ANSI C headers...
37  */
38 #if HAVE_LOCALE_H
39 #include <locale.h>
40 #endif
41 #include <stdlib.h>
42 #include <string.h>
43 #include <stdio.h>
44
45 #ifdef HAVE_ERRNO_H
46 #include <errno.h>
47 #endif
48
49 _DBUS_DEFINE_GLOBAL_LOCK (win_fds);
50 _DBUS_DEFINE_GLOBAL_LOCK (sid_atom_cache);
51 _DBUS_DEFINE_GLOBAL_LOCK (system_users);
52
53 #ifdef DBUS_WIN
54   #include <stdlib.h>
55 #elif (defined __APPLE__)
56 # include <crt_externs.h>
57 # define environ (*_NSGetEnviron())
58 #else
59 extern char **environ;
60 #endif
61
62 /**
63  * @defgroup DBusSysdeps Internal system-dependent API
64  * @ingroup DBusInternals
65  * @brief Internal system-dependent API available on UNIX and Windows
66  *
67  * The system-dependent API has a dual purpose. First, it encapsulates
68  * all usage of operating system APIs for ease of auditing and to
69  * avoid cluttering the rest of the code with bizarre OS quirks and
70  * headers. Second, it abstracts different operating system APIs for
71  * portability.
72  * 
73  * @{
74  */
75
76 /**
77  * Aborts the program with SIGABRT (dumping core).
78  */
79 void
80 _dbus_abort (void)
81 {
82   const char *s;
83   
84   _dbus_print_backtrace ();
85   
86   s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT");
87   if (s && *s)
88     {
89       /* don't use _dbus_warn here since it can _dbus_abort() */
90       fprintf (stderr, "  Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
91       _dbus_sleep_milliseconds (1000 * 180);
92     }
93   
94   abort ();
95   _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */
96 }
97
98 /**
99  * Wrapper for setenv(). If the value is #NULL, unsets
100  * the environment variable.
101  *
102  * There is an unfixable memleak in that it is unsafe to
103  * free memory malloced for use with setenv. This is because
104  * we can not rely on internal implementation details of
105  * the underlying libc library.
106  *
107  * @param varname name of environment variable
108  * @param value value of environment variable
109  * @returns #TRUE on success.
110  */
111 dbus_bool_t
112 _dbus_setenv (const char *varname,
113               const char *value)
114 {
115   _dbus_assert (varname != NULL);
116   
117   if (value == NULL)
118     {
119 #ifdef HAVE_UNSETENV
120       unsetenv (varname);
121       return TRUE;
122 #else
123       char *putenv_value;
124       size_t len;
125
126       len = strlen (varname);
127
128       /* Use system malloc to avoid memleaks that dbus_malloc
129        * will get upset about.
130        */
131       
132       putenv_value = malloc (len + 2);
133       if (putenv_value == NULL)
134         return FALSE;
135
136       strcpy (putenv_value, varname);
137 #if defined(DBUS_WIN)
138       strcat (putenv_value, "=");
139 #endif
140       
141       return (putenv (putenv_value) == 0);
142 #endif
143     }
144   else
145     {
146 #ifdef HAVE_SETENV
147       return (setenv (varname, value, TRUE) == 0);
148 #else
149       char *putenv_value;
150       size_t len;
151       size_t varname_len;
152       size_t value_len;
153
154       varname_len = strlen (varname);
155       value_len = strlen (value);
156       
157       len = varname_len + value_len + 1 /* '=' */ ;
158
159       /* Use system malloc to avoid memleaks that dbus_malloc
160        * will get upset about.
161        */
162       
163       putenv_value = malloc (len + 1);
164       if (putenv_value == NULL)
165         return FALSE;
166
167       strcpy (putenv_value, varname);
168       strcpy (putenv_value + varname_len, "=");
169       strcpy (putenv_value + varname_len + 1, value);
170       
171       return (putenv (putenv_value) == 0);
172 #endif
173     }
174 }
175
176 /**
177  * Wrapper for getenv().
178  *
179  * @param varname name of environment variable
180  * @returns value of environment variable or #NULL if unset
181  */
182 const char*
183 _dbus_getenv (const char *varname)
184 {  
185 #if defined(HAVE_SECURE_GETENV)
186   return secure_getenv (varname);
187 #elif defined(HAVE___SECURE_GETENV)
188   return __secure_getenv (varname);
189 #else
190   /* Don't respect any environment variables if the current process is
191    * setuid.  This is the equivalent of glibc's __secure_getenv().
192    */
193   if (_dbus_check_setuid ())
194     return NULL;
195   return getenv (varname);
196 #endif
197 }
198
199 /**
200  * Wrapper for clearenv().
201  *
202  * @returns #TRUE on success.
203  */
204 dbus_bool_t
205 _dbus_clearenv (void)
206 {
207   dbus_bool_t rc = TRUE;
208
209 #ifdef HAVE_CLEARENV
210   if (clearenv () != 0)
211      rc = FALSE;
212 #else
213
214   if (environ != NULL)
215     environ[0] = NULL;
216 #endif
217
218   return rc;
219 }
220
221 /**
222  * Split paths into a list of char strings
223  * 
224  * @param dirs string with pathes 
225  * @param suffix string concated to each path in dirs
226  * @param dir_list contains a list of splitted pathes
227  * return #TRUE is pathes could be splittes,#FALSE in oom case 
228  */
229 dbus_bool_t
230 _dbus_split_paths_and_append (DBusString *dirs, 
231                               const char *suffix, 
232                               DBusList  **dir_list)
233 {
234    int start;
235    int i;
236    int len;
237    char *cpath;
238    DBusString file_suffix;
239
240    start = 0;
241    i = 0;
242
243    _dbus_string_init_const (&file_suffix, suffix);
244
245    len = _dbus_string_get_length (dirs);
246
247    while (_dbus_string_find (dirs, start, _DBUS_PATH_SEPARATOR, &i))
248      {
249        DBusString path;
250
251        if (!_dbus_string_init (&path))
252           goto oom;
253
254        if (!_dbus_string_copy_len (dirs,
255                                    start,
256                                    i - start,
257                                    &path,
258                                    0))
259           {
260             _dbus_string_free (&path);
261             goto oom;
262           }
263
264         _dbus_string_chop_white (&path);
265
266         /* check for an empty path */
267         if (_dbus_string_get_length (&path) == 0)
268           goto next;
269
270         if (!_dbus_concat_dir_and_file (&path,
271                                         &file_suffix))
272           {
273             _dbus_string_free (&path);
274             goto oom;
275           }
276
277         if (!_dbus_string_copy_data(&path, &cpath))
278           {
279             _dbus_string_free (&path);
280             goto oom;
281           }
282
283         if (!_dbus_list_append (dir_list, cpath))
284           {
285             _dbus_string_free (&path);              
286             dbus_free (cpath);
287             goto oom;
288           }
289
290        next:
291         _dbus_string_free (&path);
292         start = i + 1;
293     } 
294       
295   if (start != len)
296     { 
297       DBusString path;
298
299       if (!_dbus_string_init (&path))
300         goto oom;
301
302       if (!_dbus_string_copy_len (dirs,
303                                   start,
304                                   len - start,
305                                   &path,
306                                   0))
307         {
308           _dbus_string_free (&path);
309           goto oom;
310         }
311
312       if (!_dbus_concat_dir_and_file (&path,
313                                       &file_suffix))
314         {
315           _dbus_string_free (&path);
316           goto oom;
317         }
318
319       if (!_dbus_string_copy_data(&path, &cpath))
320         {
321           _dbus_string_free (&path);
322           goto oom;
323         }
324
325       if (!_dbus_list_append (dir_list, cpath))
326         {
327           _dbus_string_free (&path);              
328           dbus_free (cpath);
329           goto oom;
330         }
331
332       _dbus_string_free (&path); 
333     }
334
335   return TRUE;
336
337  oom:
338   _dbus_list_foreach (dir_list, (DBusForeachFunction)dbus_free, NULL); 
339   _dbus_list_clear (dir_list);
340   return FALSE;
341 }
342
343 /** @} */
344
345 /**
346  * @addtogroup DBusString
347  *
348  * @{
349  */
350 /**
351  * Appends an integer to a DBusString.
352  * 
353  * @param str the string
354  * @param value the integer value
355  * @returns #FALSE if not enough memory or other failure.
356  */
357 dbus_bool_t
358 _dbus_string_append_int (DBusString *str,
359                          long        value)
360 {
361   /* this calculation is from comp.lang.c faq */
362 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1)  /* +1 for '-' */
363   int orig_len;
364   int i;
365   char *buf;
366   
367   orig_len = _dbus_string_get_length (str);
368
369   if (!_dbus_string_lengthen (str, MAX_LONG_LEN))
370     return FALSE;
371
372   buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN);
373
374   snprintf (buf, MAX_LONG_LEN, "%ld", value);
375
376   i = 0;
377   while (*buf)
378     {
379       ++buf;
380       ++i;
381     }
382   
383   _dbus_string_shorten (str, MAX_LONG_LEN - i);
384   
385   return TRUE;
386 }
387
388 /**
389  * Appends an unsigned integer to a DBusString.
390  * 
391  * @param str the string
392  * @param value the integer value
393  * @returns #FALSE if not enough memory or other failure.
394  */
395 dbus_bool_t
396 _dbus_string_append_uint (DBusString    *str,
397                           unsigned long  value)
398 {
399   /* this is wrong, but definitely on the high side. */
400 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2)
401   int orig_len;
402   int i;
403   char *buf;
404   
405   orig_len = _dbus_string_get_length (str);
406
407   if (!_dbus_string_lengthen (str, MAX_ULONG_LEN))
408     return FALSE;
409
410   buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN);
411
412   snprintf (buf, MAX_ULONG_LEN, "%lu", value);
413
414   i = 0;
415   while (*buf)
416     {
417       ++buf;
418       ++i;
419     }
420   
421   _dbus_string_shorten (str, MAX_ULONG_LEN - i);
422   
423   return TRUE;
424 }
425
426 /**
427  * Parses an integer contained in a DBusString. Either return parameter
428  * may be #NULL if you aren't interested in it. The integer is parsed
429  * and stored in value_return. Return parameters are not initialized
430  * if the function returns #FALSE.
431  *
432  * @param str the string
433  * @param start the byte index of the start of the integer
434  * @param value_return return location of the integer value or #NULL
435  * @param end_return return location of the end of the integer, or #NULL
436  * @returns #TRUE on success
437  */
438 dbus_bool_t
439 _dbus_string_parse_int (const DBusString *str,
440                         int               start,
441                         long             *value_return,
442                         int              *end_return)
443 {
444   long v;
445   const char *p;
446   char *end;
447
448   p = _dbus_string_get_const_data_len (str, start,
449                                        _dbus_string_get_length (str) - start);
450
451   end = NULL;
452   _dbus_set_errno_to_zero ();
453   v = strtol (p, &end, 0);
454   if (end == NULL || end == p || errno != 0)
455     return FALSE;
456
457   if (value_return)
458     *value_return = v;
459   if (end_return)
460     *end_return = start + (end - p);
461
462   return TRUE;
463 }
464
465 /**
466  * Parses an unsigned integer contained in a DBusString. Either return
467  * parameter may be #NULL if you aren't interested in it. The integer
468  * is parsed and stored in value_return. Return parameters are not
469  * initialized if the function returns #FALSE.
470  *
471  * @param str the string
472  * @param start the byte index of the start of the integer
473  * @param value_return return location of the integer value or #NULL
474  * @param end_return return location of the end of the integer, or #NULL
475  * @returns #TRUE on success
476  */
477 dbus_bool_t
478 _dbus_string_parse_uint (const DBusString *str,
479                          int               start,
480                          unsigned long    *value_return,
481                          int              *end_return)
482 {
483   unsigned long v;
484   const char *p;
485   char *end;
486
487   p = _dbus_string_get_const_data_len (str, start,
488                                        _dbus_string_get_length (str) - start);
489
490   end = NULL;
491   _dbus_set_errno_to_zero ();
492   v = strtoul (p, &end, 0);
493   if (end == NULL || end == p || errno != 0)
494     return FALSE;
495
496   if (value_return)
497     *value_return = v;
498   if (end_return)
499     *end_return = start + (end - p);
500
501   return TRUE;
502 }
503
504 /** @} */ /* DBusString group */
505
506 /**
507  * @addtogroup DBusInternalsUtils
508  * @{
509  */
510
511 void
512 _dbus_generate_pseudorandom_bytes_buffer (char *buffer,
513                                           int   n_bytes)
514 {
515   long tv_usec;
516   int i;
517   
518   /* fall back to pseudorandom */
519   _dbus_verbose ("Falling back to pseudorandom for %d bytes\n",
520                  n_bytes);
521   
522   _dbus_get_real_time (NULL, &tv_usec);
523   srand (tv_usec);
524   
525   i = 0;
526   while (i < n_bytes)
527     {
528       double r;
529       unsigned int b;
530           
531       r = rand ();
532       b = (r / (double) RAND_MAX) * 255.0;
533
534       buffer[i] = b;
535
536       ++i;
537     }
538 }
539
540 /**
541  * Fills n_bytes of the given buffer with random bytes.
542  *
543  * @param buffer an allocated buffer
544  * @param n_bytes the number of bytes in buffer to write to
545  */
546 void
547 _dbus_generate_random_bytes_buffer (char *buffer,
548                                     int   n_bytes)
549 {
550   DBusString str;
551
552   if (!_dbus_string_init (&str))
553     {
554       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
555       return;
556     }
557
558   if (!_dbus_generate_random_bytes (&str, n_bytes))
559     {
560       _dbus_string_free (&str);
561       _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes);
562       return;
563     }
564
565   _dbus_string_copy_to_buffer (&str, buffer, n_bytes);
566
567   _dbus_string_free (&str);
568 }
569
570 /**
571  * Generates the given number of random bytes, where the bytes are
572  * chosen from the alphanumeric ASCII subset.
573  *
574  * @param str the string
575  * @param n_bytes the number of random ASCII bytes to append to string
576  * @returns #TRUE on success, #FALSE if no memory or other failure
577  */
578 dbus_bool_t
579 _dbus_generate_random_ascii (DBusString *str,
580                              int         n_bytes)
581 {
582   static const char letters[] =
583     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
584   int i;
585   int len;
586   
587   if (!_dbus_generate_random_bytes (str, n_bytes))
588     return FALSE;
589   
590   len = _dbus_string_get_length (str);
591   i = len - n_bytes;
592   while (i < len)
593     {
594       _dbus_string_set_byte (str, i,
595                              letters[_dbus_string_get_byte (str, i) %
596                                      (sizeof (letters) - 1)]);
597
598       ++i;
599     }
600
601   _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes,
602                                              n_bytes));
603
604   return TRUE;
605 }
606
607 /**
608  * Converts a UNIX errno, or Windows errno or WinSock error value into
609  * a #DBusError name.
610  *
611  * @todo should cover more errnos, specifically those
612  * from open().
613  * 
614  * @param error_number the errno.
615  * @returns an error name
616  */
617 const char*
618 _dbus_error_from_errno (int error_number)
619 {
620   switch (error_number)
621     {
622     case 0:
623       return DBUS_ERROR_FAILED;
624       
625 #ifdef EPROTONOSUPPORT
626     case EPROTONOSUPPORT:
627       return DBUS_ERROR_NOT_SUPPORTED;
628 #elif defined(WSAEPROTONOSUPPORT)
629     case WSAEPROTONOSUPPORT:
630       return DBUS_ERROR_NOT_SUPPORTED;
631 #endif
632 #ifdef EAFNOSUPPORT
633     case EAFNOSUPPORT:
634       return DBUS_ERROR_NOT_SUPPORTED;
635 #elif defined(WSAEAFNOSUPPORT)
636     case WSAEAFNOSUPPORT:
637       return DBUS_ERROR_NOT_SUPPORTED;
638 #endif
639 #ifdef ENFILE
640     case ENFILE:
641       return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */
642 #endif
643 #ifdef EMFILE
644     case EMFILE:
645       return DBUS_ERROR_LIMITS_EXCEEDED;
646 #endif
647 #ifdef EACCES
648     case EACCES:
649       return DBUS_ERROR_ACCESS_DENIED;
650 #endif
651 #ifdef EPERM
652     case EPERM:
653       return DBUS_ERROR_ACCESS_DENIED;
654 #endif
655 #ifdef ENOBUFS
656     case ENOBUFS:
657       return DBUS_ERROR_NO_MEMORY;
658 #endif
659 #ifdef ENOMEM
660     case ENOMEM:
661       return DBUS_ERROR_NO_MEMORY;
662 #endif
663 #ifdef ECONNREFUSED
664     case ECONNREFUSED:
665       return DBUS_ERROR_NO_SERVER;
666 #elif defined(WSAECONNREFUSED)
667     case WSAECONNREFUSED:
668       return DBUS_ERROR_NO_SERVER;
669 #endif
670 #ifdef ETIMEDOUT
671     case ETIMEDOUT:
672       return DBUS_ERROR_TIMEOUT;
673 #elif defined(WSAETIMEDOUT)
674     case WSAETIMEDOUT:
675       return DBUS_ERROR_TIMEOUT;
676 #endif
677 #ifdef ENETUNREACH
678     case ENETUNREACH:
679       return DBUS_ERROR_NO_NETWORK;
680 #elif defined(WSAENETUNREACH)
681     case WSAENETUNREACH:
682       return DBUS_ERROR_NO_NETWORK;
683 #endif
684 #ifdef EADDRINUSE
685     case EADDRINUSE:
686       return DBUS_ERROR_ADDRESS_IN_USE;
687 #elif defined(WSAEADDRINUSE)
688     case WSAEADDRINUSE:
689       return DBUS_ERROR_ADDRESS_IN_USE;
690 #endif
691 #ifdef EEXIST
692     case EEXIST:
693       return DBUS_ERROR_FILE_EXISTS;
694 #endif
695 #ifdef ENOENT
696     case ENOENT:
697       return DBUS_ERROR_FILE_NOT_FOUND;
698 #endif
699     }
700
701   return DBUS_ERROR_FAILED;
702 }
703
704 /**
705  * Converts the current system errno value into a #DBusError name.
706  *
707  * @returns an error name
708  */
709 const char*
710 _dbus_error_from_system_errno (void)
711 {
712   return _dbus_error_from_errno (errno);
713 }
714
715 /**
716  * Assign 0 to the global errno variable
717  */
718 void
719 _dbus_set_errno_to_zero (void)
720 {
721 #ifdef DBUS_WINCE
722   SetLastError (0);
723 #else
724   errno = 0;
725 #endif
726 }
727
728 /**
729  * See if errno is set
730  * @returns #TRUE if errno is not 0
731  */
732 dbus_bool_t
733 _dbus_get_is_errno_nonzero (void)
734 {
735   return errno != 0;
736 }
737
738 /**
739  * See if errno is ENOMEM
740  * @returns #TRUE if errno == ENOMEM
741  */
742 dbus_bool_t
743 _dbus_get_is_errno_enomem (void)
744 {
745   return errno == ENOMEM;
746 }
747
748 /**
749  * See if errno is EINTR
750  * @returns #TRUE if errno == EINTR
751  */
752 dbus_bool_t
753 _dbus_get_is_errno_eintr (void)
754 {
755   return errno == EINTR;
756 }
757
758 /**
759  * See if errno is EPIPE
760  * @returns #TRUE if errno == EPIPE
761  */
762 dbus_bool_t
763 _dbus_get_is_errno_epipe (void)
764 {
765   return errno == EPIPE;
766 }
767
768 /**
769  * Get error message from errno
770  * @returns _dbus_strerror(errno)
771  */
772 const char*
773 _dbus_strerror_from_errno (void)
774 {
775   return _dbus_strerror (errno);
776 }
777
778 /** @} end of sysdeps */
779
780 /* tests in dbus-sysdeps-util.c */