Enable the server to originate CoA-Request && Disconnect-Request
[freeradius.git] / src / main / mainconfig.c
index e5939c8..970e773 100644 (file)
@@ -67,10 +67,12 @@ char *debug_condition = NULL;
  *     Temporary local variables for parsing the configuration
  *     file.
  */
-static uid_t server_uid;
+#ifndef __MINGW32__
+uid_t server_uid;
 static gid_t server_gid;
 static const char *uid_name = NULL;
 static const char *gid_name = NULL;
+#endif
 static const char *chroot_dir = NULL;
 static int allow_core_dumps = 0;
 static const char *radlog_dest = NULL;
@@ -401,6 +403,98 @@ static int r_mkdir(const char *part)
 }
 
 
+#ifndef __MINGW32__
+int did_setuid = FALSE;
+
+#if defined(HAVE_SETRESUID) && defined (HAVE_GETRESUID)
+void fr_suid_up(void)
+{
+       uid_t ruid, euid, suid;
+       
+       if (getresuid(&ruid, &euid, &suid) < 0) {
+               radlog(L_ERR, "Failed getting saved UID's");
+               _exit(1);
+       }
+
+       if (setresuid(-1, suid, -1) < 0) {
+               radlog(L_ERR, "Failed switching to privileged user");
+               _exit(1);
+       }
+
+       if (geteuid() != suid) {
+               radlog(L_ERR, "Switched to unknown UID");
+               _exit(1);
+       }
+}
+
+void fr_suid_down(void)
+{
+       if (!did_setuid) return;
+
+       if (setresuid(-1, server_uid, geteuid()) < 0) {
+               fprintf(stderr, "%s: Failed switching to uid %s: %s\n",
+                       progname, uid_name, strerror(errno));
+               _exit(1);
+       }
+               
+       if (geteuid() != server_uid) {
+               fprintf(stderr, "%s: Failed switching uid: UID is incorrect\n",
+                       progname);
+               _exit(1);
+       }
+}
+
+void fr_suid_down_permanent(void)
+{
+       uid_t ruid, euid, suid;
+
+       if (!did_setuid) return;
+
+       if (getresuid(&ruid, &euid, &suid) < 0) {
+               radlog(L_ERR, "Failed getting saved uid's");
+               _exit(1);
+       }
+
+       if (setresuid(server_uid, server_uid, server_uid) < 0) {
+               radlog(L_ERR, "Failed in permanent switch to uid %s: %s",
+                      uid_name, strerror(errno));
+               _exit(1);
+       }
+
+       if (geteuid() != server_uid) {
+               radlog(L_ERR, "Switched to unknown uid");
+               _exit(1);
+       }
+
+
+       if (getresuid(&ruid, &euid, &suid) < 0) {
+               radlog(L_ERR, "Failed getting saved uid's: %s",
+                      strerror(errno));
+               _exit(1);
+       }
+}
+#else
+/*
+ *     Much less secure...
+ */
+void fr_suid_up(void)
+{
+}
+void fr_suid_down(void)
+{
+       if (!uid_name) return;
+
+       if (setuid(server_uid) < 0) {
+               fprintf(stderr, "%s: Failed switching to uid %s: %s\n",
+                       progname, uid_name, strerror(errno));
+               _exit(1);
+       }
+}
+void fr_suid_down_permanent(void)
+{
+}
+#endif
+
 /*
  *  Do chroot, if requested.
  *
@@ -408,7 +502,6 @@ static int r_mkdir(const char *part)
  */
 static int switch_users(CONF_SECTION *cs)
 {
-       int did_setuid = FALSE;
        CONF_PAIR *cp;
 
 #ifdef HAVE_SYS_RESOURCE_H
@@ -506,16 +599,15 @@ static int switch_users(CONF_SECTION *cs)
 #endif
 
 #ifdef HAVE_PWD_H
-       if (uid_name && (setuid(server_uid) < 0)) {
-               fprintf(stderr, "%s: Failed setting user to %s: %s",
-                       progname, uid_name, strerror(errno));
-               return 0;
-       }
+       if (uid_name) {
+               fr_suid_down();
 
-       /*
-        *      Now core dumps are disabled on most secure systems.
-        */
-       did_setuid = TRUE;
+               /*
+                *      Now core dumps are disabled on most secure systems.
+                */
+               
+               did_setuid = TRUE;
+       }
 #endif
 
        /*
@@ -612,6 +704,7 @@ static int switch_users(CONF_SECTION *cs)
 
        return 1;
 }
+#endif
 
 
 static const FR_NAME_NUMBER str2dest[] = {
@@ -720,10 +813,12 @@ int read_mainconfig(int reload)
                }
        }
 
+#ifndef __MINGW32__
        /*
         *      We should really switch users earlier in the process.
         */
        if (!switch_users(cs)) exit(1);
+#endif
 
        /* Initialize the dictionary */
        cp = cf_pair_find(cs, "dictionary");
@@ -752,13 +847,13 @@ int read_mainconfig(int reload)
        cf_section_free(&mainconfig.config);
        mainconfig.config = cs;
 
-       if (!clients_parse_section(cs)) {
+       DEBUG2("%s: #### Loading Realms and Home Servers ####", mainconfig.name);
+       if (!realms_init(cs)) {
                return -1;
        }
 
-       DEBUG2("%s: #### Loading Realms and Home Servers ####", mainconfig.name);
-
-       if (!realms_init(cs)) {
+       DEBUG2("%s: #### Loading Clients ####", mainconfig.name);
+       if (!clients_parse_section(cs)) {
                return -1;
        }