diff --git a/src/config.c b/src/config.c index abe5ba6a..b8f0c4f2 100644 --- a/src/config.c +++ b/src/config.c @@ -1200,7 +1200,7 @@ dobackup(const char *oldver) } snprintf(outfile, sizeof(outfile), "%s/backup", root); - if (makedirs(outfile, 0700)) + if (makedirs(outfile, 0700, -1, -1)) goto fatal; if (chdir(root)) { tvherror("config", "unable to find directory '%s'", root); @@ -1363,7 +1363,7 @@ config_check ( void ) static int config_newcfg = 0; void -config_boot ( const char *path ) +config_boot ( const char *path, gid_t gid, uid_t uid ) { struct stat st; char buf[1024]; @@ -1378,7 +1378,7 @@ config_boot ( const char *path ) /* Ensure directory exists */ if (stat(path, &st)) { config_newcfg = 1; - if (makedirs(path, 0700)) { + if (makedirs(path, 0700, gid, uid)) { tvhwarn("START", "failed to create settings directory %s," " settings will not be saved", path); return; @@ -1402,6 +1402,8 @@ config_boot ( const char *path ) if ((config_lock_fd = file_lock(config_lock, 3)) < 0) exit(78); /* config error */ + chown(config_lock, uid, gid); + /* Load global settings */ config = hts_settings_load("config"); if (!config) { @@ -1413,6 +1415,16 @@ config_boot ( const char *path ) void config_init ( int backup ) { + const char *path = hts_settings_get_root(); + + if (access(path, R_OK | W_OK)) { + tvhwarn("START", "configuration path %s is not r/w" + " for UID:%d GID:%d [e=%s]," + " settings will not be saved", + path, getuid(), getgid(), strerror(errno)); + return; + } + /* Store version number */ if (config_newcfg) { htsmsg_set_u32(config, "version", ARRAY_SIZE(config_migrate_table)); diff --git a/src/config.h b/src/config.h index 659ae777..edf940a2 100644 --- a/src/config.h +++ b/src/config.h @@ -23,7 +23,7 @@ #include "htsmsg.h" -void config_boot ( const char *path ); +void config_boot ( const char *path, gid_t gid, uid_t uid ); void config_init ( int backup ); void config_done ( void ); void config_save ( void ); diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c index 741a2e8a..a8377f08 100644 --- a/src/dvr/dvr_rec.c +++ b/src/dvr/dvr_rec.c @@ -257,7 +257,7 @@ pvr_generate_filename(dvr_entry_t *de, const streaming_start_t *ss) } } - if (makedirs(path, cfg->dvr_muxcnf.m_directory_permissions) != 0) + if (makedirs(path, cfg->dvr_muxcnf.m_directory_permissions, -1, -1) != 0) return -1; /* Construct final name */ diff --git a/src/main.c b/src/main.c index 1fc808b9..02140965 100644 --- a/src/main.c +++ b/src/main.c @@ -442,6 +442,8 @@ main(int argc, char **argv) int log_level = LOG_INFO; int log_options = TVHLOG_OPT_MILLIS | TVHLOG_OPT_STDERR | TVHLOG_OPT_SYSLOG; const char *log_debug = NULL, *log_trace = NULL; + gid_t gid = -1; + uid_t uid = -1; char buf[512]; FILE *pidfile = NULL; extern int dvb_bouquets_parse; @@ -708,21 +710,9 @@ main(int argc, char **argv) signal(SIGPIPE, handle_sigpipe); // will be redundant later signal(SIGILL, handle_sigill); // see handler.. - uuid_init(); - config_boot(opt_config); - tcp_server_preinit(opt_ipv6); - http_server_init(opt_bindaddr); // bind to ports only - htsp_init(opt_bindaddr); // bind to ports only - satip_server_init(opt_satip_rtsp); // bind to ports only - - if (opt_fork) - pidfile = tvh_fopen(opt_pidpath, "w+"); - /* Set priviledges */ if(opt_fork || opt_group || opt_user) { const char *homedir; - gid_t gid; - uid_t uid; struct group *grp = getgrnam(opt_group ?: "video"); struct passwd *pw = opt_user ? getpwnam(opt_user) : NULL; @@ -754,16 +744,27 @@ main(int argc, char **argv) } else { uid = 1; } - if ((getgid() != gid) && setgid(gid)) { - tvhlog(LOG_ALERT, "START", - "setgid(%d) failed, do you have permission?", gid); - return 1; - } - if ((getuid() != uid) && setuid(uid)) { - tvhlog(LOG_ALERT, "START", - "setuid(%d) failed, do you have permission?", uid); - return 1; - } + } + + uuid_init(); + config_boot(opt_config, gid, uid); + tcp_server_preinit(opt_ipv6); + http_server_init(opt_bindaddr); // bind to ports only + htsp_init(opt_bindaddr); // bind to ports only + satip_server_init(opt_satip_rtsp); // bind to ports only + + if (opt_fork) + pidfile = tvh_fopen(opt_pidpath, "w+"); + + if (gid >= 0 && (getgid() != gid) && setgid(gid)) { + tvhlog(LOG_ALERT, "START", + "setgid(%d) failed, do you have permission?", gid); + return 1; + } + if (uid >= 0 && (getuid() != uid) && setuid(uid)) { + tvhlog(LOG_ALERT, "START", + "setuid(%d) failed, do you have permission?", uid); + return 1; } /* Daemonise */ diff --git a/src/settings.c b/src/settings.c index 294376c7..1fa9483f 100644 --- a/src/settings.c +++ b/src/settings.c @@ -82,7 +82,7 @@ hts_settings_makedirs ( const char *inpath ) } x--; } - return makedirs(path, 0700); + return makedirs(path, 0700, -1, -1); } /** diff --git a/src/timeshift/timeshift_filemgr.c b/src/timeshift/timeshift_filemgr.c index 46d83d5c..04c6ea0a 100644 --- a/src/timeshift/timeshift_filemgr.c +++ b/src/timeshift/timeshift_filemgr.c @@ -143,7 +143,7 @@ int timeshift_filemgr_makedirs ( int index, char *buf, size_t len ) if (timeshift_filemgr_get_root(buf, len)) return 1; snprintf(buf+strlen(buf), len-strlen(buf), "/%d", index); - return makedirs(buf, 0700); + return makedirs(buf, 0700, -1, -1); } /* diff --git a/src/tvheadend.h b/src/tvheadend.h index 2a281fd9..1fb91e67 100644 --- a/src/tvheadend.h +++ b/src/tvheadend.h @@ -706,7 +706,7 @@ static inline uint8_t *sbuf_peek(sbuf_t *sb, int off) { return sb->sb_data + off char *md5sum ( const char *str ); -int makedirs ( const char *path, int mode ); +int makedirs ( const char *path, int mode, gid_t gid, uid_t uid ); int rmtree ( const char *path ); diff --git a/src/utils.c b/src/utils.c index 845bfa4d..6e62f02c 100644 --- a/src/utils.c +++ b/src/utils.c @@ -472,7 +472,7 @@ md5sum ( const char *str ) } int -makedirs ( const char *inpath, int mode ) +makedirs ( const char *inpath, int mode, gid_t gid, uid_t uid ) { int err, ok; size_t x; @@ -491,15 +491,18 @@ makedirs ( const char *inpath, int mode ) path[x] = 0; if (stat(path, &st)) { err = mkdir(path, mode); - tvhtrace("settings", "Creating directory \"%s\" with octal permissions \"%o\"", path, mode); + if (!err && gid >= 0 && uid >= 0) + err = chown(path, uid, gid); + tvhtrace("settings", "Creating directory \"%s\" with octal permissions " + "\"%o\" gid %d uid %d", path, mode, gid, uid); } else { err = S_ISDIR(st.st_mode) ? 0 : 1; errno = ENOTDIR; } if (err) { - tvhlog(LOG_ALERT, "settings", "Unable to create dir \"%s\": %s", - path, strerror(errno)); - return -1; + tvhlog(LOG_ALERT, "settings", "Unable to create dir \"%s\": %s", + path, strerror(errno)); + return -1; } path[x] = '/'; }