コード例 #1
0
ファイル: mainconfig.c プロジェクト: Gejove/freeradius-server
/*
 *  Do chroot, if requested.
 *
 *  Switch UID and GID to what is specified in the config file
 */
static int switch_users(CONF_SECTION *cs)
{
#ifdef HAVE_SYS_RESOURCE_H
	/*
	 *	Get the current maximum for core files.  Do this
	 *	before anything else so as to ensure it's properly
	 *	initialized.
	 */
	if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
		radlog(L_ERR, "Failed to get current core limit:  %s", strerror(errno));
		return 0;
	}
#endif

	/*
	 *	Don't do chroot/setuid/setgid if we're in debugging
	 *	as non-root.
	 */
	if (debug_flag && (getuid() != 0)) return 1;

	if (cf_section_parse(cs, NULL, bootstrap_config) < 0) {
		fprintf(stderr, "radiusd: Error: Failed to parse user/group information.\n");
		return 0;
	}


#ifdef HAVE_GRP_H
	/*  Set GID.  */
	if (gid_name) {
		struct group *gr;

		gr = getgrnam(gid_name);
		if (gr == NULL) {
			fprintf(stderr, "%s: Cannot get ID for group %s: %s\n",
				progname, gid_name, strerror(errno));
			return 0;
		}
		server_gid = gr->gr_gid;
	} else {
		server_gid = getgid();
	}
#endif

#ifdef HAVE_PWD_H
	/*  Set UID.  */
	if (uid_name) {
		struct passwd *pw;
		
		pw = getpwnam(uid_name);
		if (pw == NULL) {
			fprintf(stderr, "%s: Cannot get passwd entry for user %s: %s\n",
				progname, uid_name, strerror(errno));
			return 0;
		}

		if (getuid() == pw->pw_uid) {
			uid_name = NULL;
		} else {

			server_uid = pw->pw_uid;
#ifdef HAVE_INITGROUPS
			if (initgroups(uid_name, server_gid) < 0) {
				fprintf(stderr, "%s: Cannot initialize supplementary group list for user %s: %s\n",
					progname, uid_name, strerror(errno));
				return 0;
			}
#endif
		}
	} else {
		server_uid = getuid();
	}
#endif

	if (chroot_dir) {
		if (chroot(chroot_dir) < 0) {
			fprintf(stderr, "%s: Failed to perform chroot %s: %s",
				progname, chroot_dir, strerror(errno));
			return 0;
		}

		/*
		 *	Note that we leave chdir alone.  It may be
		 *	OUTSIDE of the root.  This allows us to read
		 *	the configuration from "-d ./etc/raddb", with
		 *	the chroot as "./chroot/" for example.  After
		 *	the server has been loaded, it does a "cd
		 *	${logdir}" below, so that core files (if any)
		 *	go to a logging directory.
		 *
		 *	This also allows the configuration of the
		 *	server to be outside of the chroot.  If the
		 *	server is statically linked, then the only
		 *	things needed inside of the chroot are the
		 *	logging directories.
		 */
	}

#ifdef HAVE_GRP_H
	/*  Set GID.  */
	if (gid_name && (setgid(server_gid) < 0)) {
		fprintf(stderr, "%s: Failed setting group to %s: %s",
			progname, gid_name, strerror(errno));
		return 0;
	}
#endif

#ifdef HAVE_SETUID
	/*
	 *	Just before losing root permissions, ensure that the
	 *	log files have the correct owner && group.
	 *
	 *	We have to do this because the log file MAY have been
	 *	specified on the command-line.
	 */
	if (uid_name || gid_name) {
		if ((mainconfig.radlog_dest == RADLOG_FILES) &&
		    (mainconfig.radlog_fd < 0)) {
			mainconfig.radlog_fd = open(mainconfig.log_file,
						    O_WRONLY | O_APPEND | O_CREAT, 0640);
			if (mainconfig.radlog_fd < 0) {
				fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, strerror(errno));
				return 0;
			}
		
			if (chown(mainconfig.log_file, server_uid, server_gid) < 0) {
				fprintf(stderr, "%s: Cannot change ownership of log file %s: %s\n", 
					progname, mainconfig.log_file, strerror(errno));
				return 0;
			}
		}
	}		

	if (uid_name) {
		doing_setuid = TRUE;

		fr_suid_down();
	}
#endif

	/*
	 *	This also clears the dumpable flag if core dumps
	 *	aren't allowed.
	 */
	fr_set_dumpable();

	if (allow_core_dumps) {
		radlog(L_INFO, "Core dumps are enabled.");
	}

	return 1;
}
コード例 #2
0
ファイル: mainconfig.c プロジェクト: Antti/freeradius-server
/*
 *  Do chroot, if requested.
 *
 *  Switch UID and GID to what is specified in the config file
 */
static int switch_users(CONF_SECTION *cs)
{
	CONF_PAIR *cp;

#ifdef HAVE_SYS_RESOURCE_H
	struct rlimit core_limits;
#endif

	/*
	 *	Don't do chroot/setuid/setgid if we're in debugging
	 *	as non-root.
	 */
	if (debug_flag && (getuid() != 0)) return 1;

#ifdef HAVE_GRP_H
	/*  Set GID.  */
	cp = cf_pair_find(cs, "group");
	if (cp) gid_name = cf_pair_value(cp);
	if (gid_name) {
		struct group *gr;

		DEBUG2("group = %s", gid_name);
		gr = getgrnam(gid_name);
		if (gr == NULL) {
			fprintf(stderr, "%s: Cannot get ID for group %s: %s\n",
				progname, gid_name, strerror(errno));
			return 0;
		}
		server_gid = gr->gr_gid;
	} else {
		server_gid = getgid();
	}
#endif

#ifdef HAVE_PWD_H
	/*  Set UID.  */
	cp = cf_pair_find(cs, "user");
	if (cp) uid_name = cf_pair_value(cp);
	if (uid_name) {
		struct passwd *pw;
		
		DEBUG2("user = %s", uid_name);
		pw = getpwnam(uid_name);
		if (pw == NULL) {
			fprintf(stderr, "%s: Cannot get passwd entry for user %s: %s\n",
				progname, uid_name, strerror(errno));
			return 0;
		}
		server_uid = pw->pw_uid;
#ifdef HAVE_INITGROUPS
		if (initgroups(uid_name, server_gid) < 0) {
			fprintf(stderr, "%s: Cannot initialize supplementary group list for user %s: %s\n",
				progname, uid_name, strerror(errno));
			return 0;
		}
#endif
	} else {
		server_uid = getuid();
	}
#endif

	cp = cf_pair_find(cs, "chroot");
	if (cp) chroot_dir = cf_pair_value(cp);
	if (chroot_dir) {
		DEBUG2("chroot = %s", chroot_dir);
		if (chroot(chroot_dir) < 0) {
			fprintf(stderr, "%s: Failed to perform chroot %s: %s",
				progname, chroot_dir, strerror(errno));
			return 0;
		}

		/*
		 *	Note that we leave chdir alone.  It may be
		 *	OUTSIDE of the root.  This allows us to read
		 *	the configuration from "-d ./etc/raddb", with
		 *	the chroot as "./chroot/" for example.  After
		 *	the server has been loaded, it does a "cd
		 *	${logdir}" below, so that core files (if any)
		 *	go to a logging directory.
		 *
		 *	This also allows the configuration of the
		 *	server to be outside of the chroot.  If the
		 *	server is statically linked, then the only
		 *	things needed inside of the chroot are the
		 *	logging directories.
		 */
		radlog(L_INFO, "performing chroot to %s\n", chroot_dir);
	}

#ifdef HAVE_GRP_H
	/*  Set GID.  */
	if (gid_name && (setgid(server_gid) < 0)) {
		fprintf(stderr, "%s: Failed setting group to %s: %s",
			progname, gid_name, strerror(errno));
		return 0;
	}
#endif

#ifdef HAVE_PWD_H
	if (uid_name) {
		fr_suid_down();

		/*
		 *	Now core dumps are disabled on most secure systems.
		 */
		
		did_setuid = TRUE;
	}
#endif

	/*
	 *	Double check that we can write to the log directory.
	 *
	 *	If we can't, don't start, as we can't log any errors!
	 */
	if ((mainconfig.radlog_dest == RADLOG_FILES) &&
	    (mainconfig.log_file != NULL)) {
		int fd = open(mainconfig.log_file,
			      O_WRONLY | O_APPEND | O_CREAT, 0640);
		if (fd < 0) {
			fprintf(stderr, "%s: Cannot write to log file %s: %s\n",
				progname, mainconfig.log_file, strerror(errno));
			return 0;
		}
		close(fd);

		/*
		 *	After this it's safe to call radlog(), as it's going
		 *	to the right place.
		 */
	}

#ifdef HAVE_SYS_RESOURCE_H
	/*  Get the current maximum for core files.  */
	if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
		radlog(L_ERR, "Failed to get current core limit:  %s", strerror(errno));
		return 0;
	}
#endif

	/*
	 *	Core dumps are allowed if we're in debug mode, OR
	 *	we've allowed them, OR we did a setuid (which turns
	 *	core dumps off).
	 *
	 *	Otherwise, disable core dumps for security.
	 *	
	 */
	if (!(debug_flag || allow_core_dumps || did_setuid)) {
#ifdef HAVE_SYS_RESOURCE_H
		struct rlimit no_core;

		no_core.rlim_cur = 0;
		no_core.rlim_max = 0;

		if (setrlimit(RLIMIT_CORE, &no_core) < 0) {
			radlog(L_ERR, "Failed disabling core dumps: %s",
			       strerror(errno));
			return 0;
		}
#endif

		/*
		 *	Otherwise, re-enable core dumps if we're
		 *	running as a daemon, AND core dumps are
		 *	allowed, AND we changed UID's.
		 */
	} else if ((debug_flag == 0) && allow_core_dumps && did_setuid) {
		/*
		 *	Set the dumpable flag.
		 */
#ifdef HAVE_SYS_PRCTL_H
#ifdef PR_SET_DUMPABLE
		if (prctl(PR_SET_DUMPABLE, 1) < 0) {
			radlog(L_ERR,"Cannot enable core dumps: prctl(PR_SET_DUMPABLE) failed: '%s'",
			       strerror(errno));
		}
#endif
#endif

		/*
		 *	Reset the core dump limits again, just to
		 *	double check that they haven't changed.
		 */
#ifdef HAVE_SYS_RESOURCE_H
		if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
			radlog(L_ERR, "Cannot update core dump limit: %s",
					strerror(errno));
			return 0;
		}
#endif

		radlog(L_INFO, "Core dumps are enabled.");
	}
	/*
	 *	Else we're debugging (so core dumps are enabled)
	 *	OR we're not debugging, AND "allow_core_dumps == FALSE",
	 *	OR we're not debugging, AND core dumps are allowed,
	 *	   BUT we didn't call setuid, so we haven't changed the
	 *	   core dump capabilities inherited from the parent shell.
	 */

	return 1;
}