Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] PATCH: run vdr as non-root user



Hi,

Attached patch enables vdr to switch to a different user (and
optionally group) itself, without help of su, sudo etc.

cu
Ludwig

-- 
 (o_   Ludwig Nussel
 //\   SUSE LINUX AG, Development
 V_/_  http://www.suse.de/
only in patch2:
--- vdr-1.2.6pre2/vdr.c.orig	2003-10-21 19:41:44.000000000 +0200
+++ vdr-1.2.6pre2/vdr.c	2003-10-21 19:42:24.000000000 +0200
@@ -31,6 +31,8 @@
 #include <stdlib.h>
 #include <termios.h>
 #include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
 #include "audio.h"
 #include "channels.h"
 #include "config.h"
@@ -77,6 +79,60 @@
   exit(1);
 }
 
+// switch user and group id
+// taken from startproc by Werner Fink
+static int su(const char* username, const char* groupname)
+{
+  gid_t ngid = 0;
+  struct group* grp = NULL;
+  struct passwd *user = NULL;
+
+  if(!username) return 0;
+
+  user = getpwnam(username);
+  endpwent();
+  if(!user)
+  {
+    fprintf(stderr,"invalid user %s: %s\n",username,strerror(errno));
+    return 1;
+  }
+  if(groupname)
+  {
+    grp = getgrnam(groupname);
+    endgrent();
+    if(!grp)
+    {
+      fprintf(stderr,"invalid group %s: %s\n",groupname,strerror(errno));
+      return 1;
+    }
+  }
+
+  ngid = user->pw_gid;
+  if (grp)
+    ngid = grp->gr_gid;
+  else if (setgid(ngid) < 0)
+  {
+    fprintf(stderr,"cannot set group id %u: %s\n", (unsigned int)ngid, strerror(errno));
+    return 1;
+  }
+  if (!getuid())
+  {
+    if (initgroups(user->pw_name, ngid) < 0)
+    {
+      fprintf(stderr,"cannot set supplemental group ids for user %s: %s\n",
+	  user->pw_name, strerror(errno));
+      return 1;
+    }
+  }
+  if (setuid(user->pw_uid) < 0)
+  {
+    fprintf(stderr,"cannot set user id %u: %s\n",
+	(unsigned int)user->pw_uid, strerror(errno));
+    return 1;
+  }
+  return 0;
+}
+
 int main(int argc, char *argv[])
 {
   // Save terminal settings:
@@ -106,6 +162,8 @@
   const char *Terminal = NULL;
   const char *Shutdown = NULL;
   cPluginManager PluginManager(DEFAULTPLUGINDIR);
+  const char* username = NULL;
+  const char* groupname = NULL;
 
   static struct option long_options[] = {
       { "audio",    required_argument, NULL, 'a' },
@@ -125,11 +183,13 @@
       { "version",  no_argument,       NULL, 'V' },
       { "video",    required_argument, NULL, 'v' },
       { "watchdog", required_argument, NULL, 'w' },
+      { "user",     required_argument, NULL, 'u' },
+      { "group",    required_argument, NULL, 'g' },
       { NULL }
     };
 
   int c;
-  while ((c = getopt_long(argc, argv, "a:c:dD:E:hl:L:mp:P:r:s:t:v:Vw:", long_options, NULL)) != -1) {
+  while ((c = getopt_long(argc, argv, "a:c:dD:E:hl:L:mp:P:r:s:t:v:Vw:u:g:", long_options, NULL)) != -1) {
         switch (c) {
           case 'a': AudioCommand = optarg;
                     break;
@@ -219,6 +279,10 @@
                     fprintf(stderr, "vdr: invalid watchdog timeout: %s\n", optarg);
                     return 2;
                     break;
+          case 'u': username = optarg;
+                    break;
+          case 'g': groupname = optarg;
+                    break;
           default:  return 2;
           }
         }
@@ -260,6 +324,8 @@
                "  -V,       --version      print version information and exit\n"
                "  -w SEC,   --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
                "                           seconds (default: %d); '0' disables the watchdog\n"
+	       "  -u USER,  --user=USER    run as user USER instead of root\n"
+	       "  -g GROUP, --group=GROUP  use group GROUP instead of primary group of user\n"
                "\n",
                cSIProcessor::GetEpgDataFileName() ? cSIProcessor::GetEpgDataFileName() : "'-'",
                DEFAULTPLUGINDIR,
@@ -290,6 +356,9 @@
      return 0;
      }
 
+  if (su(username, groupname) != 0)
+    return 2;
+
   // Log file:
 
   if (SysLogLevel > 0)

Home | Main Index | Thread Index