changeset 11614:b3e5d914be7d

Tests for module 'idpriv-drop'.
author Bruno Haible <bruno@clisp.org>
date Tue, 09 Jun 2009 00:56:36 +0200
parents 1d540dc13d74
children 89b7d2d527e8
files ChangeLog modules/idpriv-drop-tests tests/test-idpriv-drop.c tests/test-idpriv-drop.sh tests/test-idpriv-drop.su.sh
diffstat 5 files changed, 273 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2009-06-08  Bruno Haible  <bruno@clisp.org>
 
+	Tests for module 'idpriv-drop'.
+	* modules/idpriv-drop-tests: New file.
+	* tests/test-idpriv-drop.sh: New file.
+	* tests/test-idpriv-drop.su.sh: New file.
+	* tests/test-idpriv-drop.c: New file.
+
 	New module 'idpriv-drop'.
 	* lib/idpriv.h: New file.
 	* lib-idpriv-drop.c: New file.
new file mode 100644
--- /dev/null
+++ b/modules/idpriv-drop-tests
@@ -0,0 +1,19 @@
+Notice:
+The 'idpriv-drop-tests' module asks the user for the root password.  It is
+therefore not suitable for all environments. To disable it, pass option
+'--avoid=idpriv-drop-tests' to gnulib-tool.
+
+Files:
+tests/test-idpriv-drop.sh
+tests/test-idpriv-drop.su.sh
+tests/test-idpriv-drop.c
+
+Depends-on:
+stdbool
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-idpriv-drop.sh
+TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' srcdir='$(srcdir)'
+check_PROGRAMS += test-idpriv-drop
new file mode 100644
--- /dev/null
+++ b/tests/test-idpriv-drop.c
@@ -0,0 +1,163 @@
+/* Test of dropping uid/gid privileges of the current process permanently.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   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, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include "idpriv.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define ASSERT(expr) \
+  do									     \
+    {									     \
+      if (!(expr))							     \
+        {								     \
+          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+          fflush (stderr);						     \
+          abort ();							     \
+        }								     \
+    }									     \
+  while (0)
+
+static void
+show_uids ()
+{
+#if HAVE_GETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  uid_t real;
+  uid_t effective;
+  uid_t saved;
+  ASSERT (getresuid (&real, &effective, &saved) >= 0);
+  printf ("uids: real=%d effective=%d saved=%d",
+	  (int) real, (int) effective, (int) saved);
+#elif HAVE_GETEUID
+  printf ("uids: real=%d effective=%d",
+	  (int) getuid (), (int) geteuid());
+#elif HAVE_GETUID
+  printf ("uids: real=%d",
+	  (int) getuid ());
+#endif
+}
+
+static void
+show_gids ()
+{
+#if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  gid_t real;
+  gid_t effective;
+  gid_t saved;
+  ASSERT (getresgid (&real, &effective, &saved) >= 0);
+  printf ("gids: real=%d effective=%d saved=%d",
+	  (int) real, (int) effective, (int) saved);
+#elif HAVE_GETEGID
+  printf ("gids: real=%d effective=%d",
+	  (int) getgid (), (int) getegid());
+#elif HAVE_GETGID
+  printf ("gids: real=%d",
+	  (int) getgid ());
+#endif
+}
+
+static void
+show (const char *prefix)
+{
+  printf ("%s  ", prefix);
+  show_uids ();
+  printf ("  ");
+  show_gids ();
+  printf ("\n");
+}
+
+int
+main (int argc, char *argv[])
+{
+  bool verbose = false;
+  int i;
+
+#if HAVE_GETUID
+  int uid = getuid ();
+#endif
+#if HAVE_GETGID
+  int gid = getgid ();
+#endif
+
+  /* Parse arguments.
+     -v  enables verbose output.
+   */
+  for (i = 1; i < argc; i++)
+    {
+      const char *arg = argv[i];
+      if (strcmp (arg, "-v") == 0)
+	verbose = true;
+    }
+
+  if (verbose)
+    show ("before drop:");
+
+  ASSERT (idpriv_drop () == 0);
+
+  if (verbose)
+    show ("after drop: ");
+
+  /* Verify that the privileges have really been dropped.  */
+#if HAVE_GETRESUID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  {
+    uid_t real;
+    uid_t effective;
+    uid_t saved;
+    if (getresuid (&real, &effective, &saved) < 0
+	|| real != uid
+	|| effective != uid
+	|| saved != uid)
+      abort ();
+  }
+#else
+# if HAVE_GETEUID
+  if (geteuid () != uid)
+    abort ();
+# endif
+# if HAVE_GETUID
+  if (getuid () != uid)
+    abort ();
+# endif
+#endif
+#if HAVE_GETRESGID /* glibc, FreeBSD, OpenBSD, HP-UX */
+  {
+    gid_t real;
+    gid_t effective;
+    gid_t saved;
+    if (getresgid (&real, &effective, &saved) < 0
+	|| real != gid
+	|| effective != gid
+	|| saved != gid)
+      abort ();
+  }
+#else
+# if HAVE_GETEGID
+  if (getegid () != gid)
+    abort ();
+# endif
+# if HAVE_GETGID
+  if (getgid () != gid)
+    abort ();
+# endif
+#endif
+
+  return 0;
+}
new file mode 100755
--- /dev/null
+++ b/tests/test-idpriv-drop.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# A POSIX compliant 'id' program.
+if test -f /usr/xpg4/bin/id; then
+  ID=/usr/xpg4/bin/id
+else
+  ID=id
+fi
+
+# The user's original uid and gid.
+uid=`$ID -u`
+gid=`$ID -g`
+
+if test `$ID -u` = 0; then
+  # No need to ask for a password.
+  "${srcdir}/test-idpriv-drop.su.sh" "$uid" "$gid"
+else
+  echo "Need root privileges for the 'test-idpriv-drop' test. Deny if you don't trust." > /dev/tty
+  if (type sudo) > /dev/null 2>&1; then
+    # Use the 'sudo' program.
+    sudo "${srcdir}/test-idpriv-drop.su.sh" "$uid" "$gid"
+  else
+    # Use the 'su' program.
+    su root -c "${srcdir}/test-idpriv-drop.su.sh \"$uid\" \"$gid\""
+  fi
+  result=$?
+  case $result in
+    0)  exit 0;;
+    77) exit 77;;
+    13) exit 1;;
+    *)  echo "Skipping test: root privileges not granted"; exit 77;;
+  esac
+fi
new file mode 100755
--- /dev/null
+++ b/tests/test-idpriv-drop.su.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+# This script must be run as superuser.
+
+origuid=$1
+origgid=$2
+
+# A POSIX compliant 'id' program.
+if test -f /usr/xpg4/bin/id; then
+  ID=/usr/xpg4/bin/id
+else
+  ID=id
+fi
+
+if test `$ID -u` != 0; then
+  echo "Skipping test: not superuser"
+  exit 77
+fi
+
+./test-idpriv-drop${EXEEXT} || exit 13          # normal
+
+chown root:root test-idpriv-drop${EXEEXT} 2>/dev/null || \
+chown root:wheel test-idpriv-drop${EXEEXT} 2>/dev/null || \
+  { echo "Skipping test: root privilege not sufficient on this file system"
+    exit 77
+  }
+chmod 4755 test-idpriv-drop${EXEEXT}
+./test-idpriv-drop${EXEEXT} || exit 13          # setuid root
+chmod 2755 test-idpriv-drop${EXEEXT}
+./test-idpriv-drop${EXEEXT} || exit 13          # setgid root
+chmod 6755 test-idpriv-drop${EXEEXT}
+./test-idpriv-drop${EXEEXT} || exit 13          # setuid and setgid root
+
+if chown nobody test-idpriv-drop${EXEEXT} 2>/dev/null; then
+  chmod 4755 test-idpriv-droptemp${EXEEXT}
+  ./test-idpriv-droptemp${EXEEXT} || exit 13    # setuid nobody
+  chmod 2755 test-idpriv-droptemp${EXEEXT}
+  ./test-idpriv-droptemp${EXEEXT} || exit 13    # setgid root
+  chmod 6755 test-idpriv-droptemp${EXEEXT}
+  ./test-idpriv-droptemp${EXEEXT} || exit 13    # setuid nobody and setgid root
+fi
+
+if chown root:nobody test-idpriv-drop${EXEEXT} 2>/dev/null; then
+  chmod 4755 test-idpriv-drop${EXEEXT}
+  ./test-idpriv-drop${EXEEXT} || exit 13        # setuid root
+  chmod 2755 test-idpriv-drop${EXEEXT}
+  ./test-idpriv-drop${EXEEXT} || exit 13        # setgid nobody
+  chmod 6755 test-idpriv-drop${EXEEXT}
+  ./test-idpriv-drop${EXEEXT} || exit 13        # setuid root and setgid nobody
+fi
+
+chown "$origuid:$origgid" test-idpriv-drop${EXEEXT}
+chmod 755 test-idpriv-drop${EXEEXT}