vdr/vdr/debian/patches 05_set_system_time_as_user.dpatch 00list

Thomas Schmidt pkg-vdr-dvb-changes@lists.alioth.debian.org
Thu, 30 Dec 2004 23:03:23 +0000


Update of /cvsroot/pkg-vdr-dvb/vdr/vdr/debian/patches
In directory haydn:/tmp/cvs-serv3027/vdr/vdr/debian/patches

Modified Files:
	00list 
Added Files:
	05_set_system_time_as_user.dpatch 
Log Message:


Index: 00list
===================================================================
RCS file: /cvsroot/pkg-vdr-dvb/vdr/vdr/debian/patches/00list,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- 00list	31 Oct 2004 10:08:28 -0000	1.10
+++ 00list	30 Dec 2004 23:03:20 -0000	1.11
@@ -3,6 +3,7 @@
 02_Makefile-CFGDIR
 03_cmdsubmenu
 04_newplugin
+05_set_system_time_as_user
 
 # The Elchi AIO 4d patch for a nicer OSD, inlcuding the frames and black
 # square fix.

--- NEW FILE: 05_set_system_time_as_user.dpatch ---
#! /bin/sh /usr/share/dpatch/dpatch-run
## 05_set_system_time_as_user.dpatch by Thomas Schmidt <thomas.schmidt@in.stud.tu-ilmenau.de>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Allow vdr to be run as a normal user, but keep the capability 
## DP: to set the system-time by vdr (Patch from Ludwig Nussel 
## DP: <ludwig.nussel@gmx.de>

@DPATCH@
diff -urNad vdr-1.2.6/Makefile /tmp/dpep.NAw891/vdr-1.2.6/Makefile
--- vdr-1.2.6/Makefile	2004-04-22 12:48:23.000000000 +0200
+++ /tmp/dpep.NAw891/vdr-1.2.6/Makefile	2004-12-30 22:32:22.000000000 +0100
@@ -55,7 +55,7 @@
 
 ifdef DEBUG_OSD
 DEFINES += -DDEBUG_OSD
-NCURSESLIB = -lncurses
+LIBS += -lncurses
 endif
 
 ifdef VFAT
@@ -63,6 +63,11 @@
 DEFINES += -DVFAT
 endif
 
+ifdef WITH_CAPABILITIES
+DEFINES += -DWITH_CAPABILITIES
+LIBS += -lcap
+endif
+
 all: vdr
 font: genfontfile fontfix.c fontosd.c
 	@echo "font files created."
@@ -84,7 +89,7 @@
 # The main program:
 
 vdr: $(OBJS) $(DTVLIB)
-	$(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(NCURSESLIB) -ljpeg -lpthread -ldl $(LIBDIRS) $(DTVLIB) -o vdr
+	$(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(LIBS) -ljpeg -lpthread -ldl $(LIBDIRS) $(DTVLIB) -o vdr
 
 # The font files:
 
diff -urNad vdr-1.2.6/vdr.c /tmp/dpep.NAw891/vdr-1.2.6/vdr.c
--- vdr-1.2.6/vdr.c	2004-04-22 12:48:59.000000000 +0200
+++ /tmp/dpep.NAw891/vdr-1.2.6/vdr.c	2004-12-30 22:32:22.000000000 +0100
@@ -31,6 +31,12 @@
 #include <stdlib.h>
 #include <termios.h>
 #include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#ifdef WITH_CAPABILITIES
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#endif
 #include "audio.h"
 #include "channels.h"
 #include "config.h"
@@ -77,6 +83,104 @@
   exit(1);
 }
 
+// switch user and group uid
+// 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;
+
+  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;
+}
+
+#ifdef WITH_CAPABILITIES
+// drop all capabilities except cap_sys_time
+static int set_cap_sys_time(void)
+{
+  cap_t caps;
+
+  caps = cap_from_text("= cap_sys_time=ep");
+  if(!caps)
+  {
+    perror("cap_from_text");
+    return -1;
+  }
+
+  if( cap_set_proc(caps) == -1 )
+  {
+    perror("cap_set_proc");
+    cap_free(caps);
+    return -1;
+  }
+
+  cap_free(caps);
+
+  return 0;
+}
+
+// keep capabilities during setuid()
+static inline int set_keepcaps(void)
+{
+  return prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+}
+
+static inline int set_nokeepcaps(void)
+{
+  return prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
+}
+#else
+static inline int return0() { return 0; }
+#define printcap() return0()
+#define set_cap_sys_time() return0()
+#define set_keepcaps() return0()
+#define set_nokeepcaps() return0()
+#endif
+
 int main(int argc, char *argv[])
 {
   // Save terminal settings:
@@ -106,6 +210,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 +231,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 +327,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 +372,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 +404,17 @@
      return 0;
      }
 
+  if(username && set_keepcaps() != 0)
+    return 2;
+
+  if (su(username, groupname) != 0)
+    return 2;
+
+  if(username && set_nokeepcaps() != 0)
+    return 2;
+
+  set_cap_sys_time();
+
   // Log file:
 
   if (SysLogLevel > 0)