diff --git a/contrib/mt-daapd.conf b/contrib/mt-daapd.conf index ba4b4b26..34ccbf9c 100644 --- a/contrib/mt-daapd.conf +++ b/contrib/mt-daapd.conf @@ -9,7 +9,7 @@ # Location of the admin web pages. This should be correct # -web_root /usr/share/mt-daapd/admin-root +web_root /home/ron/working/mt-daapd/admin-root # # port (required) @@ -46,6 +46,18 @@ mp3_dir /mnt/mp3 servername mt-daapd +# +# runas (required) +# +# This is the user to drop privs to if running as +# root. If mt-daapd is not started as root, this +# configuration option is ignored. Notice that this +# must be specified whether the server is running +# as root or not. +# + +runas nobody + # # playlist (optional) # @@ -59,7 +71,7 @@ servername mt-daapd # specified # -playlist /etc/mt-daapd.playlist +playlist /home/ron/mt-daapd.playlist # # password (optional) @@ -68,4 +80,7 @@ playlist /etc/mt-daapd.playlist # i.e. the password that iTunes prompts for # -#password mp3 \ No newline at end of file +#password mp3 + + + diff --git a/src/configfile.c b/src/configfile.c index 27d51ad2..2c479754 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -72,6 +72,7 @@ typedef struct tag_configelement { } CONFIGELEMENT; CONFIGELEMENT config_elements[] = { + { 1,1,0,CONFIG_TYPE_STRING,"runas",(void*)&config.runas,config_emit_string }, { 1,1,0,CONFIG_TYPE_STRING,"web_root",(void*)&config.web_root,config_emit_string }, { 1,1,0,CONFIG_TYPE_INT,"port",(void*)&config.port,config_emit_int }, { 1,1,0,CONFIG_TYPE_STRING,"admin_pw",(void*)&config.adminpassword,config_emit_string }, @@ -141,6 +142,7 @@ int config_read(char *file) { config.readpassword=NULL; config.mp3dir=NULL; config.playlist=NULL; + config.runas=NULL; config.servername="mt-daapd " VERSION; while(fgets(buffer,MAX_LINE,fin)) { diff --git a/src/daapd.h b/src/daapd.h index 10eddedb..76e98b41 100644 --- a/src/daapd.h +++ b/src/daapd.h @@ -41,6 +41,7 @@ typedef struct tag_config { char *mp3dir; char *servername; char *playlist; + char *runas; SONGENTRY songlist; } CONFIG; diff --git a/src/main.c b/src/main.c index a6a3ff3a..2b3c129b 100644 --- a/src/main.c +++ b/src/main.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -379,6 +380,7 @@ int main(int argc, char *argv[]) { int parseonly=0; int foreground=0; config.use_mdns=0; + struct passwd *pw=NULL; #ifdef DEBUG char *optval="d:c:mpf"; @@ -420,6 +422,13 @@ int main(int argc, char *argv[]) { } } +#ifdef DEBUG + if(!foreground) { + fprintf(stderr,"WARNING: Debug mode: not detaching\n"); + foreground=1; + } +#endif + /* read the configfile, if specified, otherwise * try defaults */ @@ -430,7 +439,24 @@ int main(int argc, char *argv[]) { if((config.use_mdns) && (!parseonly)) { fprintf(stderr,"Starting rendezvous daemon\n"); - rend_init(&config.rend_pid,config.servername, config.port); + rend_init(&config.rend_pid,config.servername, config.port, config.runas); + } + + /* drop privs */ + if(getuid() == (uid_t)0) { + pw=getpwnam(config.runas); + if(pw) { + if(initgroups(config.runas,pw->pw_gid) != 0 || + setgid(pw->pw_gid) != 0 || + setuid(pw->pw_uid) != 0) { + fprintf(stderr,"Couldn't change to %s, gid=%d, uid=%d\n", + config.runas,pw->pw_gid, pw->pw_uid); + exit(EXIT_FAILURE); + } + } else { + fprintf(stderr,"Couldn't lookup user %s\n",config.runas); + exit(EXIT_FAILURE); + } } DPRINTF(ERR_DEBUG,"Initializing database\n"); @@ -488,17 +514,17 @@ int main(int argc, char *argv[]) { sleep(10); if(config.use_mdns) { - fprintf(stderr,"Killing rendezvous daemon\n"); + if(foreground) fprintf(stderr,"Killing rendezvous daemon\n"); kill(config.rend_pid,SIGINT); wait(&status); } - fprintf(stderr,"Stopping webserver\n"); + if(foreground) fprintf(stderr,"Stopping webserver\n"); ws_stop(server); config_close(); - fprintf(stderr,"Closing database\n"); + if(foreground) fprintf(stderr,"Closing database\n"); db_deinit(); #ifdef DEBUG @@ -506,7 +532,9 @@ int main(int argc, char *argv[]) { err_leakcheck(); #endif - fprintf(stderr,"\nDone\n"); + if(foreground) fprintf(stderr,"\nDone\n"); + + log_err(0,"Exiting"); return EXIT_SUCCESS; } diff --git a/src/rend-howl.c b/src/rend-howl.c index 8b495c68..41ff1222 100644 --- a/src/rend-howl.c +++ b/src/rend-howl.c @@ -21,9 +21,13 @@ #include #include +#include +#include +#include #include #include + #include "err.h" /* @@ -51,11 +55,30 @@ static sw_result rend_howl_reply(sw_rendezvous_publish_handler handler, /* * public interface */ -int rend_init(pid_t *pid, char *name, int port) { +int rend_init(pid_t *pid, char *name, int port, char *user) { sw_rendezvous rendezvous; sw_result result; sw_rendezvous_publish_id daap_id; sw_rendezvous_publish_id http_id; + struct passwd *pw=NULL; + + /* drop privs */ + if(getuid() == (uid_t)0) { + pw=getpwnam(user); + if(pw) { + if(initgroups(user,pw->pw_gid) != 0 || + setgid(pw->pw_gid) != 0 || + setuid(pw->pw_uid) != 0) { + fprintf(stderr,"Couldn't change to %s, gid=%d, uid=%d\n", + user,pw->pw_gid, pw->pw_uid); + exit(EXIT_FAILURE); + } + } else { + fprintf(stderr,"Couldn't lookup user %s\n",user); + exit(EXIT_FAILURE); + } + } + if(sw_rendezvous_init(&rendezvous) != SW_OKAY) { DPRINTF(ERR_WARN,"Error initializing rendezvous\n"); diff --git a/src/rend-osx.c b/src/rend-osx.c index 923ef12f..4cb765dd 100644 --- a/src/rend-osx.c +++ b/src/rend-osx.c @@ -19,6 +19,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include +#include +#include + #include #include #include @@ -79,16 +83,36 @@ static void rend_reply(DNSServiceRegistrationReplyErrorType errorCode, void *con /* * public interface */ -int rend_init(pid_t *pid, char *name, int port) { +int rend_init(pid_t *pid, char *name, int port, char *user) { dns_service_discovery_ref daap_ref=NULL; dns_service_discovery_ref http_ref=NULL; unsigned short usPort=port; + struct passwd *pw=NULL; *pid=fork(); if(*pid) { return 0; } + + /* drop privs */ + if(getuid() == (uid_t)0) { + pw=getpwnam(user); + if(pw) { + if(initgroups(user,pw->pw_gid) != 0 || + setgid(pw->pw_gid) != 0 || + setuid(pw->pw_uid) != 0) { + fprintf(stderr,"Couldn't change to %s, gid=%d, uid=%d\n", + user,pw->pw_gid, pw->pw_uid); + exit(EXIT_FAILURE); + } + } else { + fprintf(stderr,"Couldn't lookup user %s\n",user); + exit(EXIT_FAILURE); + } + } + + signal(SIGINT, rend_sigint); // SIGINT is what you get for a Ctrl-C diff --git a/src/rend-posix.c b/src/rend-posix.c index f5440bfa..bea6ec22 100644 --- a/src/rend-posix.c +++ b/src/rend-posix.c @@ -89,6 +89,9 @@ Change History (most recent first): $Log$ + Revision 1.8 2003/12/29 23:39:18 ron + add priv dropping + Revision 1.7 2003/12/29 20:41:08 ron Make sure all files have GPL notice @@ -132,6 +135,8 @@ #include // For errno, EINTR #include #include +#include +#include #define __IN_ERR__ #include "err.h" @@ -543,9 +548,10 @@ static void DeregisterOurServices(void) #pragma mark **** Main -int rend_init(pid_t *pid,char *name, int port) { +int rend_init(pid_t *pid,char *name, int port, char user) { mStatus status; mDNSBool result; + struct passwd *pw=NULL; status = mDNS_Init(&mDNSStorage, &PlatformStorage, mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize, @@ -562,6 +568,24 @@ int rend_init(pid_t *pid,char *name, int port) { return 0; } + /* drop privs */ + if(getuid() == (uid_t)0) { + pw=getpwnam(user); + if(pw) { + if(initgroups(user,pw->pw_gid) != 0 || + setgid(pw->pw_gid) != 0 || + setuid(pw->pw_uid) != 0) { + fprintf(stderr,"Couldn't change to %s, gid=%d, uid=%d\n", + user,pw->pw_gid, pw->pw_uid); + exit(EXIT_FAILURE); + } + } else { + fprintf(stderr,"Couldn't lookup user %s\n",user); + exit(EXIT_FAILURE); + } + } + + DPRINTF(ERR_DEBUG,"Registering tcp service\n"); RegisterOneService(name,"_http._tcp",NULL,0,port); RegisterOneService(name,"_daap._tcp",NULL,0,port); diff --git a/src/rend.h b/src/rend.h index 3655835d..1b141cbf 100644 --- a/src/rend.h +++ b/src/rend.h @@ -22,6 +22,6 @@ #ifndef _REND_H_ #define _REND_H_ -int rend_init(pid_t *pid, char *name, int port); +int rend_init(pid_t *pid, char *name, int port, char *user); #endif /* _REND_H_ */