blob: e7a72ae38405e3ecce88f2fce10d3bac7d7ab214 [file] [log] [blame]
/*
* OpenVPN -- An application to securely tunnel IP networks
* over a single UDP port, with support for SSL/TLS-based
* session authentication and key exchange,
* packet encryption, packet authentication, and
* packet compression.
*
* Copyright (C) 2014-2015 David Sommerseth <davids@redhat.com>
* Copyright (C) 2016 David Sommerseth <dazo@privateinternetaccess.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/**
* @file Alternative method to query for user input, using systemd
*
*/
#include "config.h"
#ifdef ENABLE_SYSTEMD
#include "syshead.h"
#include "console.h"
#include "misc.h"
#include <systemd/sd-daemon.h>
/*
* is systemd running
*/
static bool
check_systemd_running(void)
{
struct stat c;
/* We simply test whether the systemd cgroup hierarchy is
* mounted, as well as the systemd-ask-password executable
* being available */
return (sd_booted() > 0)
&& (stat(SYSTEMD_ASK_PASSWORD_PATH, &c) == 0);
}
static bool
get_console_input_systemd(const char *prompt, const bool echo, char *input, const int capacity)
{
int std_out;
bool ret = false;
struct argv argv = argv_new();
argv_printf(&argv, SYSTEMD_ASK_PASSWORD_PATH);
#ifdef SYSTEMD_NEWER_THAN_216
/* the --echo support arrived in upstream systemd 217 */
if (echo)
{
argv_printf_cat(&argv, "--echo");
}
#endif
argv_printf_cat(&argv, "--icon network-vpn");
argv_printf_cat(&argv, "%s", prompt);
if ((std_out = openvpn_popen(&argv, NULL)) < 0)
{
return false;
}
memset(input, 0, capacity);
if (read(std_out, input, capacity-1) != 0)
{
chomp(input);
ret = true;
}
close(std_out);
argv_reset(&argv);
return ret;
}
/**
* Systemd aware implementation of query_user_exec(). If systemd is not running
* it will fall back to use query_user_exec_builtin() instead.
*
*/
bool
query_user_exec(void)
{
bool ret = true; /* Presume everything goes okay */
int i;
/* If systemd is not available, use the default built-in mechanism */
if (!check_systemd_running())
{
return query_user_exec_builtin();
}
/* Loop through the complete query setup and when needed, collect the information */
for (i = 0; i < QUERY_USER_NUMSLOTS && query_user[i].response != NULL; i++)
{
if (!get_console_input_systemd(query_user[i].prompt, query_user[i].echo,
query_user[i].response, query_user[i].response_len) )
{
/* Force the final result state to failed on failure */
ret = false;
}
}
return ret;
}
#endif /* ENABLE_SYSTEMD */