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)