Browse code

Add support to forward console query to systemd

Systemd requires console query to be forwarded using its own
tool.

Signed-off-by: Frederic Crozat <fcrozat@suse.com>
Acked-by: David Sommerseth <davids@redhat.com>
URL: http://thread.gmane.org/gmane.network.openvpn.devel/5073/focus=5277
Signed-off-by: David Sommerseth <davids@redhat.com>

Frederic Crozat authored on 2011/10/31 23:51:53
Showing 2 changed files
... ...
@@ -223,6 +223,12 @@ AC_ARG_ENABLE(selinux,
223 223
    [SELINUX="yes"]
224 224
 )
225 225
 
226
+AC_ARG_ENABLE(systemd,
227
+   [  --enable-systemd        Enable systemd suppport],
228
+   [SYSTEMD="$enableval"],
229
+   [SYSTEMD="no"]
230
+)
231
+
226 232
 AC_ARG_WITH(ssl-headers,
227 233
    [  --with-ssl-headers=DIR  Crypto/SSL Include files location],
228 234
    [CS_HDR_DIR="$withval"]
... ...
@@ -930,6 +936,11 @@ if test "$PASSWORD_SAVE" = "yes"; then
930 930
    AC_DEFINE(ENABLE_PASSWORD_SAVE, 1, [Allow --askpass and --auth-user-pass passwords to be read from a file])
931 931
 fi
932 932
 
933
+dnl enable systemd support
934
+if test "$SYSTEMD" = "yes"; then
935
+   AC_DEFINE(ENABLE_SYSTEMD, 1, [Enable systemd support])
936
+fi
937
+
933 938
 dnl
934 939
 dnl check for SELinux library and headers
935 940
 dnl
... ...
@@ -36,6 +36,7 @@
36 36
 #include "crypto.h"
37 37
 #include "route.h"
38 38
 #include "win32.h"
39
+#include <unistd.h>
39 40
 
40 41
 #include "memdbg.h"
41 42
 
... ...
@@ -610,6 +611,73 @@ openvpn_system (const char *command, const struct env_set *es, unsigned int flag
610 610
 }
611 611
 
612 612
 /*
613
+ * Run execve() inside a fork(), duping stdout.  Designed to replicate the semantics of popen() but
614
+ * in a safer way that doesn't require the invocation of a shell or the risks
615
+ * assocated with formatting and parsing a command line.
616
+ */
617
+int
618
+openvpn_popen (const struct argv *a,  const struct env_set *es)
619
+{
620
+  struct gc_arena gc = gc_new ();
621
+  int ret = -1;
622
+  static bool warn_shown = false;
623
+
624
+  if (a && a->argv[0])
625
+    {
626
+#if defined(ENABLE_EXECVE)
627
+      if (script_security >= SSEC_BUILT_IN)
628
+	{
629
+	      const char *cmd = a->argv[0];
630
+	      char *const *argv = a->argv;
631
+	      char *const *envp = (char *const *)make_env_array (es, true, &gc);
632
+	      pid_t pid;
633
+	      int pipe_stdout[2];
634
+
635
+              if (pipe (pipe_stdout) == 0) {
636
+		      pid = fork ();
637
+		      if (pid == (pid_t)0) /* child side */
638
+			{
639
+			  close (pipe_stdout[0]);
640
+			  dup2 (pipe_stdout[1],1);
641
+			  execve (cmd, argv, envp);
642
+			  exit (127);
643
+			}
644
+		      else if (pid < (pid_t)0) /* fork failed */
645
+			{
646
+			  msg (M_ERR, "openvpn_popen: unable to fork");
647
+			}
648
+		      else /* parent side */
649
+			{
650
+                            ret=pipe_stdout[0];
651
+			    close (pipe_stdout[1]);
652
+			}
653
+	      }
654
+	      else {
655
+		      msg (M_WARN, "openvpn_popen: unable to create stdout pipe");
656
+		      ret = -1;
657
+	      }
658
+	}
659
+      else if (!warn_shown && (script_security < SSEC_SCRIPTS))
660
+	{
661
+	  msg (M_WARN, SCRIPT_SECURITY_WARNING);
662
+          warn_shown = true;
663
+	}
664
+#else
665
+      msg (M_WARN, "openvpn_popen: execve function not available");
666
+#endif
667
+    }
668
+  else
669
+    {
670
+      msg (M_FATAL, "openvpn_popen: called with empty argv");
671
+    }
672
+
673
+  gc_free (&gc);
674
+  return ret;
675
+}
676
+
677
+
678
+
679
+/*
613 680
  * Initialize random number seed.  random() is only used
614 681
  * when "weak" random numbers are acceptable.
615 682
  * OpenSSL routines are always used when cryptographically
... ...
@@ -1328,6 +1396,56 @@ close_tty (FILE *fp)
1328 1328
 #endif
1329 1329
 
1330 1330
 /*
1331
+ * is systemd running
1332
+ */
1333
+
1334
+#if defined(TARGET_LINUX) && defined(ENABLE_SYSTEMD)
1335
+bool
1336
+check_systemd_running ()
1337
+{
1338
+  struct stat a, b;
1339
+
1340
+  /* We simply test whether the systemd cgroup hierarchy is
1341
+   * mounted */
1342
+
1343
+  return (lstat("/sys/fs/cgroup", &a) == 0)
1344
+	  && (lstat("/sys/fs/cgroup/systemd", &b) == 0)
1345
+	  && (a.st_dev != b.st_dev);
1346
+
1347
+}
1348
+
1349
+bool
1350
+get_console_input_systemd (const char *prompt, const bool echo, char *input, const int capacity)
1351
+{
1352
+  int std_out;
1353
+  char cmd[256];
1354
+  bool ret = false;
1355
+  struct argv argv;
1356
+
1357
+  argv_init (&argv);
1358
+  argv_printf (&argv, "/bin/systemd-ask-password");
1359
+  argv_printf_cat (&argv, "%s", prompt);
1360
+
1361
+  if ((std_out = openvpn_popen (&argv, NULL)) < 0) {
1362
+	  return false;
1363
+  }
1364
+  CLEAR (*input);
1365
+  if (read (std_out, input, capacity) != 0)
1366
+    {
1367
+       chomp (input);
1368
+       ret = true;
1369
+    }
1370
+  close (std_out);
1371
+
1372
+  argv_reset (&argv);
1373
+
1374
+  return ret;
1375
+}
1376
+
1377
+
1378
+#endif
1379
+
1380
+/*
1331 1381
  * Get input from console
1332 1382
  */
1333 1383
 bool
... ...
@@ -1339,6 +1457,11 @@ get_console_input (const char *prompt, const bool echo, char *input, const int c
1339 1339
   ASSERT (capacity > 0);
1340 1340
   input[0] = '\0';
1341 1341
 
1342
+#if defined(TARGET_LINUX) && defined(ENABLE_SYSTEMD)
1343
+  if (check_systemd_running ())
1344
+    return get_console_input_systemd (prompt, echo, input, capacity);
1345
+#endif
1346
+
1342 1347
 #if defined(WIN32)
1343 1348
   return get_console_input_win32 (prompt, echo, input, capacity);
1344 1349
 #elif defined(HAVE_GETPASS)