[xiph-cvs] cvs commit: icecast/src config.c config.h main.c

Michael Smith msmith at xiph.org
Tue May 14 04:06:55 PDT 2002



msmith      02/05/14 04:06:55

  Modified:    .        configure.in
               conf     icecast.xml
               src      config.c config.h main.c
  Log:
  Ian Kumlien's security (chroot() and setuid() patch), with some modifications.

Revision  Changes    Path
1.13      +2 -0      icecast/configure.in

Index: configure.in
===================================================================
RCS file: /usr/local/cvsroot/icecast/configure.in,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- configure.in	2001/10/29 15:53:28	1.12
+++ configure.in	2002/05/14 11:06:53	1.13
@@ -72,6 +72,8 @@
 AC_HEADER_STDC
 
 AC_CHECK_HEADER(stdint.h, AC_DEFINE(HAVE_STDINT_H, 1),,)
+AC_CHECK_HEADER(pwd.h, AC_DEFINE(CHUID, 1),,)
+AC_CHECK_HEADER(unistd.h, AC_DEFINE(CHROOT, 1),,)
 
 dnl Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST

<p><p>1.3       +8 -0      icecast/conf/icecast.xml

Index: icecast.xml
===================================================================
RCS file: /usr/local/cvsroot/icecast/conf/icecast.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- icecast.xml	2002/01/21 04:28:30	1.2
+++ icecast.xml	2002/05/14 11:06:54	1.3
@@ -34,4 +34,12 @@
                 <accesslog>access.log</accesslog>
                 <errorlog>error.log</errorlog>
         </logging>
+
+    <security>
+        <chroot>0</chroot>
+    <!--<changeowner>
+            <user>nobody</user>
+            <group>nogroup</group>
+        </changeowner> -->
+    </security>
 </icecast>

<p><p>1.6       +46 -0     icecast/src/config.c

Index: config.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/config.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- config.c	2002/05/03 15:04:55	1.5
+++ config.c	2002/05/14 11:06:54	1.6
@@ -19,6 +19,10 @@
 #define CONFIG_DEFAULT_PORT 8888
 #define CONFIG_DEFAULT_ACCESS_LOG "access.log"
 #define CONFIG_DEFAULT_ERROR_LOG "error.log"
+#define CONFIG_DEFAULT_CHROOT 0
+#define CONFIG_DEFAULT_CHUID 0
+#define CONFIG_DEFAULT_USER NULL
+#define CONFIG_DEFAULT_GROUP NULL
 
 #ifndef _WIN32
 #define CONFIG_DEFAULT_BASE_DIR "/usr/local/icecast"
@@ -37,6 +41,7 @@
 static void _parse_directory(xmlDocPtr doc, xmlNodePtr node);
 static void _parse_paths(xmlDocPtr doc, xmlNodePtr node);
 static void _parse_logging(xmlDocPtr doc, xmlNodePtr node);
+static void _parse_security(xmlDocPtr doc, xmlNodePtr node);
 static void _add_server(xmlDocPtr doc, xmlNodePtr node);
 
 void config_initialize(void)
@@ -60,6 +65,8 @@
         if (_configuration.access_log) free(_configuration.access_log);
         if (_configuration.error_log) free(_configuration.error_log);
     if (_configuration.bind_address) free(_configuration.bind_address);
+    if (_configuration.user) free(_configuration.user);
+    if (_configuration.group) free(_configuration.group);
     dirnode = _configuration.dir_list;
     while(dirnode) {
         nextdirnode = dirnode->next;
@@ -138,6 +145,10 @@
         _configuration.log_dir = (char *)strdup(CONFIG_DEFAULT_LOG_DIR);
         _configuration.access_log = (char *)strdup(CONFIG_DEFAULT_ACCESS_LOG);
         _configuration.error_log = (char *)strdup(CONFIG_DEFAULT_ERROR_LOG);
+    _configuration.chroot = CONFIG_DEFAULT_CHROOT;
+    _configuration.chuid = CONFIG_DEFAULT_CHUID;
+    _configuration.user = CONFIG_DEFAULT_USER;
+    _configuration.group = CONFIG_DEFAULT_GROUP;
 }
 
 static void _parse_root(xmlDocPtr doc, xmlNodePtr node)
@@ -175,6 +186,8 @@
                         _parse_paths(doc, node->xmlChildrenNode);
                 } else if (strcmp(node->name, "logging") == 0) {
                         _parse_logging(doc, node->xmlChildrenNode);
+        } else if (strcmp(node->name, "security") == 0) {
+            _parse_security(doc, node->xmlChildrenNode);
                 }
         } while ((node = node->next));
 }
@@ -263,6 +276,39 @@
                         _configuration.error_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
                 }
         } while ((node = node->next));
+}
+
+static void _parse_security(xmlDocPtr doc, xmlNodePtr node)
+{
+   char *tmp;
+   xmlNodePtr oldnode;
+
+   do {
+       if (node == NULL) break;
+       if (xmlIsBlankNode(node)) continue;
+
+       if (strcmp(node->name, "chroot") == 0) {
+           tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+           _configuration.chroot = atoi(tmp);
+           if (tmp) free(tmp);
+       } else if (strcmp(node->name, "changeowner") == 0) {
+           _configuration.chuid = 1;
+           oldnode = node;
+           node = node->xmlChildrenNode;
+           do {
+               if(node == NULL) break;
+               if(xmlIsBlankNode(node)) continue;
+               if(strcmp(node->name, "user") == 0) {
+                   if(_configuration.user) free(_configuration.user);
+                   _configuration.user = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+               } else if(strcmp(node->name, "group") == 0) {
+                   if(_configuration.group) free(_configuration.group);
+                   _configuration.group = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
+               }
+           } while((node = node->next));
+           node = oldnode;
+       }
+   } while ((node = node->next));
 }
 
 static void _add_server(xmlDocPtr doc, xmlNodePtr node)

<p><p>1.3       +5 -0      icecast/src/config.h

Index: config.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/config.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- config.h	2002/01/21 04:28:30	1.2
+++ config.h	2002/05/14 11:06:54	1.3
@@ -38,6 +38,11 @@
 
         char *access_log;
         char *error_log;
+
+    int chroot;
+    int chuid;
+    char *user;
+    char *group;
 } ice_config_t;
 
 void config_initialize(void);

<p><p>1.5       +99 -6     icecast/src/main.c

Index: main.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/main.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- main.c	2002/02/08 03:59:17	1.4
+++ main.c	2002/05/14 11:06:54	1.5
@@ -8,6 +8,12 @@
 #include "resolver.h"
 #include "httpp.h"
 
+#ifdef CHUID
+#include <sys/types.h>
+#include <grp.h>
+#include <pwd.h>
+#include <errno.h>
+#endif
 
 #include "config.h"
 #include "sighandler.h"
@@ -43,7 +49,6 @@
         config_initialize();
         connection_initialize();
         global_initialize();
-	stats_initialize();
         refbuf_initialize();
 }
 
@@ -135,8 +140,8 @@
         return 1;
 }
 
-/* this is the heart of the beast */
-static void _server_proc(void)
+/* bind the socket and start listening */
+static void _server_proc_init(void)
 {
         if (!_setup_socket()) {
                 ERROR1("Could not create listener socket on port %d", config_get_config()->port);
@@ -147,12 +152,76 @@
                 ERROR0("Failed trying to listen on server socket");
                 return;
         }
+}
 
+/* this is the heart of the beast */
+static void _server_proc(void)
+{
         connection_accept_loop();
 
         sock_close(global.serversock);
 }
 
+#ifdef CHROOT
+/* chroot the process. Watch out - we need to do this before starting other
+ * threads */
+
+static void _chroot_setup(void)
+{
+   ice_config_t *conf = config_get_config();
+
+   if (conf->chroot)
+   {
+       if(getuid()) /* root check */
+       {
+           fprintf(stderr, "WARNING: Cannot change server root unless running as root.\n");
+           return;
+       }
+       if(chroot(conf->base_dir))
+       {
+           fprintf(stderr,"WARNING: Couldn't change server root: %s\n", strerror(errno));
+           return;
+       }
+       else
+           fprintf(stdout, "Changed root successfully to \"%s\".\n", conf->base_dir);
+
+   }   
+}
+#endif
+
+#ifdef CHUID
+/* change uid and gid */
+static void _chuid_setup(void)
+{
+   ice_config_t *conf = config_get_config();
+   struct passwd *user;
+   struct group *group;
+   
+   if(conf->chuid)
+   {
+       if(getuid()) /* root check */
+       {
+           fprintf(stderr, "WARNING: Can't change user id unless you are root.\n");
+           return;
+       }
+
+       user = getpwnam(conf->user);
+       group = getgrnam(conf->group);
+       
+       if(!setgid(group->gr_gid))
+           fprintf(stdout, "Changed groupid to %i.\n", group->gr_gid);
+       else
+           fprintf(stdout, "Error changing groupid: %s.\n", strerror(errno));
+
+       if(!setuid(user->pw_uid))
+           fprintf(stdout, "Changed userid to %i.\n", user->pw_uid);
+       else
+           fprintf(stdout, "Error changing userid: %s.\n", strerror(errno));
+
+   }
+}
+#endif
+
 int main(int argc, char **argv)
 {
         int res, ret;
@@ -161,9 +230,6 @@
         /* startup all the modules */
         _initialize_subsystems();
 
-	/* setup the default signal handlers */
-	sighandler_initialize();
-
         /* parse the '-c icecast.xml' option
         ** only, so that we can read a configfile
         */
@@ -196,6 +262,33 @@
         
         /* override config file options with commandline options */
         config_parse_cmdline(argc, argv);
+
+#ifdef CHROOT
+    _chroot_setup(); /* Perform chroot, if requested */
+#endif
+
+    _server_proc_init(); /* Bind socket, before we change userid */
+
+#ifdef CHUID
+    _chuid_setup(); /* change user id */
+#endif
+
+    stats_initialize(); /* We have to do this later on because of threading */
+
+#ifdef CHUID 
+    /* We'll only have getuid() if we also have setuid(), it's reasonable to
+     * assume */
+    if(!getuid()) /* Running as root! Don't allow this */
+    {
+        fprintf(stderr, "WARNING: You should not run icecast2 as root\n");
+        fprintf(stderr, "Use the changeowner directive in the config file\n");
+        _shutdown_subsystems();
+        return 1;
+    }
+#endif
+
+    /* setup default signal handlers */
+    sighandler_initialize();
 
         if (!_start_logging()) {
                 fprintf(stderr, "FATAL: Could not start logging\n");

<p><p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list