LCOV - code coverage report
Current view: top level - daemon - gkd-util.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 74.2 % 97 72
Test Date: 2024-04-08 13:24:42 Functions: 81.8 % 11 9

            Line data    Source code
       1              : /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
       2              : /* gkr-daemon-util.c - Helper utilities for the daemon
       3              : 
       4              :    Copyright (C) 2007, Stefan Walter
       5              : 
       6              :    The Gnome Keyring Library is free software; you can redistribute it and/or
       7              :    modify it under the terms of the GNU Library General Public License as
       8              :    published by the Free Software Foundation; either version 2 of the
       9              :    License, or (at your option) any later version.
      10              : 
      11              :    The Gnome Keyring Library 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 GNU
      14              :    Library General Public License for more details.
      15              : 
      16              :    You should have received a copy of the GNU Library General Public
      17              :    License along with the Gnome Library; see the file COPYING.LIB.  If not,
      18              :    <http://www.gnu.org/licenses/>.
      19              : 
      20              :    Author: Stef Walter <stef@memberwebs.com>
      21              : */
      22              : 
      23              : #include "config.h"
      24              : 
      25              : #include "gkd-util.h"
      26              : 
      27              : #include "egg/egg-cleanup.h"
      28              : #include "egg/egg-unix-credentials.h"
      29              : 
      30              : #include <glib.h>
      31              : 
      32              : #include <sys/stat.h>
      33              : 
      34              : #include <errno.h>
      35              : #include <stdlib.h>
      36              : #include <string.h>
      37              : #include <unistd.h>
      38              : 
      39              : /*
      40              :  * A list of all the environment variables the daemon can
      41              :  * possibly send out when it starts.
      42              :  */
      43              : const gchar *GKD_UTIL_OUT_ENVIRONMENT[] = {
      44              :         "SSH_AUTH_SOCK",
      45              :         "GNOME_KEYRING_CONTROL",
      46              :         "SSH_AGENT_PID",
      47              :         NULL
      48              : };
      49              : 
      50              : /*
      51              :  * A list of all the environment variables the daemon
      52              :  * is interested in from clients if it was started
      53              :  * early before these environment variables were set.
      54              :  */
      55              : const gchar *GKD_UTIL_IN_ENVIRONMENT[] = {
      56              :         "DBUS_SESSION_BUS_ADDRESS",
      57              :         "DESKTOP_AUTOSTART_ID",
      58              :         "LANG",
      59              :         "XDG_RUNTIME_DIR",
      60              :         "LOGNAME",
      61              :         "USERNAME",
      62              :         NULL
      63              : };
      64              : 
      65              : static gchar* master_directory = NULL;
      66              : static GArray* published_environ = NULL;
      67              : 
      68              : static GFunc watch_environ = NULL;
      69              : static gpointer watch_user_data = NULL;
      70              : static GDestroyNotify watch_destroy_notify = NULL;
      71              : 
      72              : static void
      73           27 : uninit_master_directory (gpointer data)
      74              : {
      75           27 :         g_assert (master_directory);
      76           27 :         rmdir (master_directory);
      77           27 :         g_free (master_directory);
      78           27 :         master_directory = NULL;
      79           27 : }
      80              : 
      81              : static gboolean
      82           29 : validate_master_directory (const gchar *directory,
      83              :                            gboolean *exists)
      84              : {
      85              :         struct stat st;
      86              : 
      87           29 :         if (lstat (directory, &st) < 0) {
      88           22 :                 if (errno == ENOTDIR || errno == ENOENT) {
      89           21 :                         *exists = FALSE;
      90           21 :                         return TRUE;
      91              :                 }
      92            1 :                 g_message ("The gnome-keyring control directory cannot be accessed: %s: %s",
      93              :                            directory, g_strerror (errno));
      94            1 :                 return FALSE;
      95            7 :         } else if (st.st_uid != geteuid ()) {
      96            0 :                 g_message ("The gnome-keyring control directory is not owned with the same "
      97              :                            "credentials as the user login: %s", directory);
      98            0 :                 return FALSE;
      99            7 :         } else if ((st.st_mode & 0777) != 0700) {
     100            1 :                 g_message ("The gnome-keyring control directory has invalid permissions. It "
     101              :                            "must be only be accessible by its owner (ie: 0700): %s", directory);
     102            1 :                 return FALSE;
     103              :         } else {
     104            6 :                 *exists = TRUE;
     105            6 :                 return TRUE;
     106              :         }
     107              : }
     108              : 
     109              : void
     110           27 : gkd_util_init_master_directory (const gchar *replace)
     111              : {
     112           27 :         gboolean exists = FALSE;
     113           27 :         gboolean is_default = FALSE;
     114              : 
     115           27 :         g_free (master_directory);
     116           27 :         master_directory = NULL;
     117              : 
     118           27 :         if (replace && validate_master_directory (replace, &exists)) {
     119           22 :                 master_directory = g_strdup (replace);
     120              : 
     121              :         /* Only use default directory if it has an predictable explicit path */
     122            5 :         } else if (g_getenv ("XDG_RUNTIME_DIR")) {
     123            5 :                 master_directory = g_build_filename (g_get_user_runtime_dir (), "keyring", NULL);
     124            5 :                 if (validate_master_directory (master_directory, &exists)) {
     125            5 :                         is_default = TRUE;
     126              :                 } else {
     127            0 :                         g_free (master_directory);
     128            0 :                         master_directory = NULL;
     129              :                 }
     130              :         }
     131              : 
     132              :         /* No directory yet, make one up */
     133           27 :         if (!master_directory) {
     134            0 :                 master_directory = g_build_filename (g_get_user_runtime_dir (), "keyring-XXXXXX", NULL);
     135            0 :                 if (g_mkdtemp (master_directory) == NULL) {
     136            0 :                         g_warning ("couldn't create socket directory: %s: %s",
     137              :                                    master_directory, g_strerror (errno));
     138              :                 }
     139            0 :                 exists = TRUE;
     140              :         }
     141              : 
     142              :         /* A directory was supplied, but doesn't exist yet */
     143           27 :         if (!exists) {
     144           21 :                 if (g_mkdir_with_parents (master_directory, 0700) < 0) {
     145            0 :                         g_warning ("couldn't create socket directory: %s: %s",
     146              :                                    master_directory, g_strerror (errno));
     147              :                 }
     148              :         }
     149              : 
     150           27 :         if (!is_default)
     151           22 :                 gkd_util_push_environment (GKD_UTIL_ENV_CONTROL, master_directory);
     152           27 :         egg_cleanup_register (uninit_master_directory, NULL);
     153           27 : }
     154              : 
     155              : const gchar*
     156           38 : gkd_util_get_master_directory (void)
     157              : {
     158           38 :         g_return_val_if_fail (master_directory, NULL);
     159           38 :         return master_directory;
     160              : }
     161              : 
     162              : static void
     163           27 : uninit_environment (gpointer data)
     164              : {
     165              :         guint i;
     166              : 
     167           27 :         if (published_environ) {
     168           49 :                 for (i = 0; i < published_environ->len; ++i)
     169           22 :                         g_free (g_array_index (published_environ, gchar*, i));
     170           27 :                 g_array_free (published_environ, TRUE);
     171              :         }
     172              : 
     173           27 :         published_environ = NULL;
     174              : 
     175           27 :         if (watch_destroy_notify && watch_user_data)
     176           27 :                 (watch_destroy_notify) (watch_user_data);
     177           27 :         watch_user_data = NULL;
     178           27 :         watch_destroy_notify = NULL;
     179           27 :         watch_environ = NULL;
     180           27 : }
     181              : 
     182              : static void
     183           76 : init_environment ()
     184              : {
     185           76 :         if (published_environ)
     186           49 :                 return;
     187           27 :         published_environ = g_array_new (TRUE, TRUE, sizeof (gchar*));
     188           27 :         egg_cleanup_register (uninit_environment, NULL);
     189              : }
     190              : 
     191              : void
     192           22 : gkd_util_push_environment (const gchar *name, const gchar *value)
     193              : {
     194              :         gchar *env;
     195              : 
     196           22 :         init_environment ();
     197              : 
     198           22 :         env = g_strdup_printf ("%s=%s", name, value);
     199           22 :         g_array_append_val (published_environ, env);
     200              : 
     201           22 :         if (watch_environ)
     202            0 :                 (watch_environ) (env, watch_user_data);
     203           22 : }
     204              : 
     205              : void
     206            0 : gkd_util_push_environment_full (const gchar *var)
     207              : {
     208              :         gchar *env;
     209              : 
     210            0 :         g_return_if_fail (strchr (var, '=') != NULL);
     211            0 :         init_environment ();
     212              : 
     213            0 :         env = g_strdup (var);
     214            0 :         g_array_append_val (published_environ, env);
     215              : 
     216            0 :         if (watch_environ)
     217            0 :                 (watch_environ) (env, watch_user_data);
     218              : }
     219              : 
     220              : const gchar**
     221           54 : gkd_util_get_environment (void)
     222              : {
     223           54 :         init_environment ();
     224           54 :         return (const gchar**)published_environ->data;
     225              : }
     226              : 
     227              : void
     228           27 : gkd_util_watch_environment (GFunc func, gpointer user_data,
     229              :                             GDestroyNotify destroy_notify)
     230              : {
     231           27 :         g_return_if_fail (func);
     232           27 :         g_return_if_fail (!watch_environ);
     233              : 
     234           27 :         watch_environ = func;
     235           27 :         watch_user_data = user_data;
     236           27 :         watch_destroy_notify = destroy_notify;
     237              : }
     238              : 
     239              : gchar**
     240            0 : gkd_util_build_environment (const gchar **names)
     241              : {
     242            0 :         GArray *array = g_array_sized_new (TRUE, TRUE, sizeof (gchar*), 8);
     243              :         const gchar *value;
     244              :         const gchar **name;
     245              :         gchar *env;
     246              : 
     247              :         /* Transform them into NAME=VALUE pairs */
     248            0 :         for (name = names; *name; ++name) {
     249            0 :                 value = g_getenv (*name);
     250            0 :                 if (value) {
     251            0 :                         env = g_strdup_printf ("%s=%s", *name, value);
     252            0 :                         g_array_append_val (array, env);
     253              :                 }
     254              :         }
     255              : 
     256            0 :         return (gchar**)g_array_free (array, FALSE);
     257              : }
        

Generated by: LCOV version 2.0-1