>From 48853ed48fa47146c83638bbe04381e04fd79721 Mon Sep 17 00:00:00 2001 From: Nathan Kinder <nkinder@xxxxxxxxxx> Date: Wed, 16 Sep 2009 09:28:56 -0700 Subject: [PATCH] Add SELinux policy for ldap-agent. This adds SELinux policy to confine the SNMP subagent (ldap-agent). There were some changes required around the aubagent to make it work in a more standard fashion. I moved the ldap-agent binary and wrapper to sbindir. It was previously in bindir, yet it is not a user command. The location really should be sbindir per FHS. I added init scripts for the subagent, so it can now be managed using "service dirsrv-snmp [start|stop|restart|condrestart|status]". While doing this, I found that the parent process was exiting with 1 on success instead of 0, so I fixed that. I added a default config file for the subagent as well. When using the init script, the config file is hardcoded into this standard location. Having this config template should also hopefully cut down on configuration errors since it's self documenting. The pid file location was also changed to go into /var/run per FHS. Previously, it was written to the same directory as the log file. There are a few notes in the policy .te file about some bugs that we are working around for now. These bugs are mainly minor issues in the snmp policy that is a part of the selinux-policy pacakge. Once those bugs are fixed, we can clean our policy .te file up. --- Makefile.am | 21 ++- ldap/servers/snmp/ldap-agent.conf.in | 30 +++++ ldap/servers/snmp/ldap-agent.h | 2 +- ldap/servers/snmp/main.c | 37 +++--- selinux/dirsrv.fc.in | 4 + selinux/dirsrv.te | 85 +++++++++++++- wrappers/ldap-agent-initscript.in | 221 ++++++++++++++++++++++++++++++++++ wrappers/ldap-agent.in | 2 +- 8 files changed, 373 insertions(+), 29 deletions(-) create mode 100644 ldap/servers/snmp/ldap-agent.conf.in create mode 100644 wrappers/ldap-agent-initscript.in diff --git a/Makefile.am b/Makefile.am index 665b1f4..7f35c6a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -135,10 +135,10 @@ defaultgroup=@defaultgroup@ #------------------------ # Build Products #------------------------ -sbin_PROGRAMS = ns-slapd +sbin_PROGRAMS = ns-slapd ldap-agent-bin -bin_PROGRAMS = dbscan-bin dsktune-bin infadd-bin ldap-agent-bin \ - ldclt-bin ldif-bin migratecred-bin mmldif-bin pwdhash-bin rsearch-bin +bin_PROGRAMS = dbscan-bin dsktune-bin infadd-bin ldclt-bin \ + ldif-bin migratecred-bin mmldif-bin pwdhash-bin rsearch-bin server_LTLIBRARIES = libslapd.la libns-dshttpd.la @@ -193,7 +193,8 @@ policy_DATA = $(POLICY_MODULE) config_DATA = $(srcdir)/lib/ldaputil/certmap.conf \ $(srcdir)/ldap/schema/slapd-collations.conf \ - ldap/admin/src/template-initconfig + ldap/admin/src/template-initconfig \ + ldap/servers/snmp/ldap-agent.conf # the schema files in this list are either not # standard schema, not tested, or not compatible @@ -274,13 +275,13 @@ sbin_SCRIPTS = ldap/admin/src/scripts/setup-ds.pl \ ldap/admin/src/scripts/remove-ds.pl \ ldap/admin/src/scripts/start-dirsrv \ ldap/admin/src/scripts/stop-dirsrv \ - ldap/admin/src/scripts/restart-dirsrv + ldap/admin/src/scripts/restart-dirsrv \ + wrappers/ldap-agent bin_SCRIPTS = ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl \ wrappers/dbscan \ wrappers/dsktune \ wrappers/infadd \ - wrappers/ldap-agent \ wrappers/ldclt \ wrappers/ldif \ $(srcdir)/ldap/admin/src/logconv.pl \ @@ -343,7 +344,8 @@ task_SCRIPTS = ldap/admin/src/scripts/template-bak2db \ ldap/admin/src/scripts/template-verify-db.pl \ ldap/admin/src/scripts/template-dbverify -init_SCRIPTS = wrappers/$(PACKAGE_NAME) +init_SCRIPTS = wrappers/$(PACKAGE_NAME) \ + wrappers/$(PACKAGE_NAME)-snmp initconfig_DATA = ldap/admin/src/$(PACKAGE_NAME) @@ -1315,3 +1317,8 @@ endif %/$(PACKAGE_NAME): %/initconfig.in if [ ! -d $(dir $@) ] ; then mkdir -p $(dir $@) ; fi $(fixupcmd) $^ > $@ + +%/$(PACKAGE_NAME)-snmp: %/ldap-agent-initscript.in + if [ ! -d $(dir $@) ] ; then mkdir -p $(dir $@) ; fi + $(fixupcmd) $^ > $@ + diff --git a/ldap/servers/snmp/ldap-agent.conf.in b/ldap/servers/snmp/ldap-agent.conf.in new file mode 100644 index 0000000..6593685 --- /dev/null +++ b/ldap/servers/snmp/ldap-agent.conf.in @@ -0,0 +1,30 @@ +# The agentx-master setting defines how to communicate +# with the SNMP master agent using the AgentX protocol. +# The default is to use a UNIX domain socket. If your +# master agent is listening on a tcp port for AgentX +# subagents, use a line like the following: +# +# agentx-master localhost:705 +agentx-master /var/agentx/master + +# The agent-logdir settings defines where the subagent +# will write it's logfile. +agent-logdir @localstatedir@/log/@package_name@ + +# The server setting specifies a Directory Server +# instance that you want to monitor. You must use one +# server setting for each Directory Server instance. The +# subagent requires at least one server setting to be +# specified. The server setting +# should be set to the name of the Directory Server +# instance you would like to monitor. For example: +# +# server slapd-phonebook +# +# To monitor multiple Directory Server instances, add +# an additional server parameter for each instance: +# +# server slapd-phonebook +# server slapd-example +# server slapd-directory + diff --git a/ldap/servers/snmp/ldap-agent.h b/ldap/servers/snmp/ldap-agent.h index 30253d1..664d7e2 100644 --- a/ldap/servers/snmp/ldap-agent.h +++ b/ldap/servers/snmp/ldap-agent.h @@ -90,7 +90,7 @@ extern "C" { #define CACHE_REFRESH_INTERVAL 15 #define UPDATE_THRESHOLD 20 #define SNMP_NUM_SEM_WAITS 10 -#define LDAP_AGENT_PIDFILE ".ldap-agent.pid" +#define LDAP_AGENT_PIDFILE "ldap-agent.pid" #define LDAP_AGENT_LOGFILE "ldap-agent.log" /************************************************************* diff --git a/ldap/servers/snmp/main.c b/ldap/servers/snmp/main.c index 5b2ad68..04c4ee3 100644 --- a/ldap/servers/snmp/main.c +++ b/ldap/servers/snmp/main.c @@ -191,7 +191,7 @@ main (int argc, char *argv[]) { fscanf(pid_fp, "%d", &child_pid); fclose(pid_fp); printf("ldap-agent: Started as pid %d\n", child_pid); - exit(1); + exit(0); } /* initialize the agent */ @@ -205,7 +205,7 @@ main (int argc, char *argv[]) { signal(SIGTERM, stop_server); signal(SIGINT, stop_server); - /* create pidfile in config file dir */ + /* create pidfile */ child_pid = getpid(); if ((pid_fp = fopen(pidfile, "w")) == NULL) { snmp_log(LOG_ERR, "Error creating pid file: %s\n", pidfile); @@ -272,25 +272,24 @@ load_config(char *conf_path) } /* set pidfile path */ + if ((pidfile = malloc(strlen(LOCALSTATEDIR) + strlen("/run/") + + strlen(LDAP_AGENT_PIDFILE) + 1)) != NULL) { + strncpy(pidfile, LOCALSTATEDIR, strlen(LOCALSTATEDIR)); + /* The above will likely not be NULL terminated, but we need to + * be sure that we're properly NULL terminated for the below + * strcat() to work properly. */ + pidfile[strlen(LOCALSTATEDIR)] = (char)0; + strcat(pidfile, "/run/"); + strcat(pidfile, LDAP_AGENT_PIDFILE); + } else { + printf("ldap-agent: malloc error processing config file\n"); + error = 1; + goto close_and_exit; + } + + /* set default logdir to location of config file */ for (p = (conf_path + strlen(conf_path) - 1); p >= conf_path; p--) { if (*p == '/') { - /* set pidfile path */ - if ((pidfile = malloc((p - conf_path) + - strlen(LDAP_AGENT_PIDFILE) + 2)) != NULL) { - strncpy(pidfile, conf_path, (p - conf_path + 1)); - /* The above will likely not be NULL terminated, but we need to - * be sure that we're properly NULL terminated for the below - * strcat() to work properly. */ - pidfile[(p - conf_path + 2)] = (char)0; - strcat(pidfile, LDAP_AGENT_PIDFILE); - pidfile[((p - conf_path) + strlen(LDAP_AGENT_PIDFILE) + 1)] = (char)0; - } else { - printf("ldap-agent: malloc error processing config file\n"); - error = 1; - goto close_and_exit; - } - - /* set default logdir to location of config file */ if ((agent_logdir = malloc((p - conf_path) + 1)) != NULL) { strncpy(agent_logdir, conf_path, (p - conf_path)); agent_logdir[(p - conf_path)] = (char)0; diff --git a/selinux/dirsrv.fc.in b/selinux/dirsrv.fc.in index ae768b1..f61a871 100644 --- a/selinux/dirsrv.fc.in +++ b/selinux/dirsrv.fc.in @@ -4,14 +4,18 @@ # MCS categories: <none> @sbindir@/ns-slapd -- gen_context(system_u:object_r:dirsrv_exec_t,s0) +@sbindir@/ldap-agent -- gen_context(system_u:object_r:initrc_exec_t,s0) +@sbindir@/ldap-agent-bin -- gen_context(system_u:object_r:dirsrv_snmp_exec_t,s0) @sbindir@/start-dirsrv -- gen_context(system_u:object_r:initrc_exec_t,s0) @sbindir@/restart-dirsrv -- gen_context(system_u:object_r:initrc_exec_t,s0) @serverdir@ gen_context(system_u:object_r:dirsrv_lib_t,s0) @serverdir@(/.*) gen_context(system_u:object_r:dirsrv_lib_t,s0) @localstatedir@/run/@package_name@ gen_context(system_u:object_r:dirsrv_var_run_t,s0) @localstatedir@/run/@package_name@(/.*) gen_context(system_u:object_r:dirsrv_var_run_t,s0) +@localstatedir@/run/ldap-agent.pid gen_context(system_u:object_r:dirsrv_snmp_var_run_t,s0) @localstatedir@/log/@package_name@ gen_context(system_u:object_r:dirsrv_var_log_t,s0) @localstatedir@/log/@package_name@(/.*) gen_context(system_u:object_r:dirsrv_var_log_t,s0) +@localstatedir@/log/@package_name@/ldap-agent.log gen_context(system_u:object_r:dirsrv_snmp_var_log_t,s0) @localstatedir@/lock/@package_name@ gen_context(system_u:object_r:dirsrv_var_lock_t,s0) @localstatedir@/lock/@package_name@(/.*) gen_context(system_u:object_r:dirsrv_var_lock_t,s0) @localstatedir@/lib/@package_name@ gen_context(system_u:object_r:dirsrv_var_lib_t,s0) diff --git a/selinux/dirsrv.te b/selinux/dirsrv.te index 872e42f..b505c89 100644 --- a/selinux/dirsrv.te +++ b/selinux/dirsrv.te @@ -5,12 +5,26 @@ policy_module(dirsrv,1.0.0) # Declarations # +# NGK - this can go away when bz 478629, bz 523548, +# and bz 523771 are addressed. See the notes below +# where we work around those issues. +require { + type snmpd_var_lib_t; + type snmpd_t; +} + # main daemon type dirsrv_t; type dirsrv_exec_t; domain_type(dirsrv_t) init_daemon_domain(dirsrv_t, dirsrv_exec_t) +# snmp subagent daemon +type dirsrv_snmp_t; +type dirsrv_snmp_exec_t; +domain_type(dirsrv_snmp_t) +init_daemon_domain(dirsrv_snmp_t, dirsrv_snmp_exec_t) + # dynamic libraries type dirsrv_lib_t; files_type(dirsrv_lib_t) @@ -23,10 +37,18 @@ files_type(dirsrv_var_lib_t) type dirsrv_var_log_t; logging_log_file(dirsrv_var_log_t) +# snmp log file +type dirsrv_snmp_var_log_t; +logging_log_file(dirsrv_snmp_var_log_t) + # pid files type dirsrv_var_run_t; files_pid_file(dirsrv_var_run_t) +# snmp pid file +type dirsrv_snmp_var_run_t; +files_pid_file(dirsrv_snmp_var_run_t) + # lock files type dirsrv_var_lock_t; files_lock_file(dirsrv_var_lock_t) @@ -93,7 +115,7 @@ files_pid_filetrans(dirsrv_t, dirsrv_var_run_t, { file sock_file }) # ldapi socket manage_sock_files_pattern(dirsrv_t, dirsrv_var_run_t, dirsrv_var_run_t) -#lock files +# lock files manage_files_pattern(dirsrv_t, dirsrv_var_lock_t, dirsrv_var_lock_t) manage_dirs_pattern(dirsrv_t, dirsrv_var_lock_t, dirsrv_var_lock_t) files_lock_filetrans(dirsrv_t, dirsrv_var_lock_t, { file }) @@ -128,3 +150,64 @@ allow dirsrv_t self:tcp_socket { create_stream_socket_perms }; init_use_fds(dirsrv_t) init_use_script_ptys(dirsrv_t) domain_use_interactive_fds(dirsrv_t) + + +######################################## +# +# dirsrv-snmp local policy +# + +# Some common macros +files_read_etc_files(dirsrv_snmp_t) +miscfiles_read_localization(dirsrv_snmp_t) +libs_use_ld_so(dirsrv_snmp_t) +libs_use_shared_libs(dirsrv_snmp_t) +dev_read_rand(dirsrv_snmp_t) +dev_read_urand(dirsrv_snmp_t) +files_read_usr_files(dirsrv_snmp_t) +fs_getattr_tmpfs(dirsrv_snmp_t) +fs_search_tmpfs(dirsrv_snmp_t) +allow dirsrv_snmp_t self:fifo_file { read write }; +sysnet_read_config(dirsrv_snmp_t) +sysnet_dns_name_resolve(dirsrv_snmp_t) + +# Net-SNMP /var/lib files (includes agentx unix domain socket) +snmp_dontaudit_read_snmp_var_lib_files(dirsrv_snmp_t) +snmp_dontaudit_write_snmp_var_lib_files(dirsrv_snmp_t) +# NGK - there really should be a macro for this. (see bz 523771) +allow dirsrv_snmp_t snmpd_var_lib_t:file append; +# NGK - use snmp_stream_connect(dirsrv_snmp_t) when it is made +# available on all platforms we build on (see bz 478629 and bz 523548) +stream_connect_pattern(dirsrv_snmp_t, snmpd_var_lib_t, snmpd_var_lib_t, snmpd_t) + +# Net-SNMP agentx tcp socket +corenet_tcp_connect_agentx_port(dirsrv_snmp_t) + +# Net-SNMP persistent data file +files_manage_var_files(dirsrv_snmp_t) + +# stats file semaphore +rw_files_pattern(dirsrv_snmp_t, dirsrv_tmpfs_t, dirsrv_tmpfs_t) + +# stats file +read_files_pattern(dirsrv_snmp_t, dirsrv_var_run_t, dirsrv_var_run_t) + +# process stuff +allow dirsrv_snmp_t self:capability { dac_override dac_read_search }; + +# config file +read_files_pattern(dirsrv_snmp_t, dirsrv_config_t, dirsrv_config_t) + +# pid file +admin_pattern(dirsrv_snmp_t, dirsrv_snmp_var_run_t) +files_pid_filetrans(dirsrv_snmp_t, dirsrv_snmp_var_run_t, { file sock_file }) +search_dirs_pattern(dirsrv_snmp_t, dirsrv_var_run_t, dirsrv_var_run_t) + +# log file +manage_files_pattern(dirsrv_snmp_t, dirsrv_var_log_t, dirsrv_snmp_var_log_t); +filetrans_pattern(dirsrv_snmp_t, dirsrv_var_log_t, dirsrv_snmp_var_log_t, file) + +# Init script handling +init_use_fds(dirsrv_snmp_t) +init_use_script_ptys(dirsrv_snmp_t) +domain_use_interactive_fds(dirsrv_snmp_t) diff --git a/wrappers/ldap-agent-initscript.in b/wrappers/ldap-agent-initscript.in new file mode 100644 index 0000000..d4e791f --- /dev/null +++ b/wrappers/ldap-agent-initscript.in @@ -0,0 +1,221 @@ +#!/bin/sh +# +# @package_name@-snmp This starts and stops @package_name@-snmp +# +# chkconfig: - 22 78 +# description: @capbrand@ Directory Server SNMP Subagent +# processname: ldap-agent-bin +# config: @sysconfdir@/@package_name@/config/ldap-agent.conf +# pidfile: @localstatedir@/run/ldap-agent.pid +# + +# Source function library. +if [ -f /etc/rc.d/init.d/functions ] ; then +. /etc/rc.d/init.d/functions +fi +# Source networking configuration. +if [ -f /etc/sysconfig/network ] ; then +. /etc/sysconfig/network +fi + +# Check that networking is up. +if [ "${NETWORKING}" = "no" ] +then + echo "Networking is down" + exit 0 +fi + +# figure out which echo we're using +ECHO_N=`echo -n` + +# some shells echo cannot use -n - linux echo by default cannot use \c +echo_n() +{ + if [ "$ECHO_N" = '-n' ] ; then + echo "$*\c" + else + echo -n "$*" + fi +} + +# failure and success are not defined on some platforms +type failure > /dev/null 2>&1 || { +failure() +{ + echo_n " FAILED" +} +} + +type success > /dev/null 2>&1 || { +success() +{ + echo_n " SUCCESS" +} +} + +baseexec="ldap-agent" +exec="@sbindir@/$baseexec" +processname="ldap-agent-bin" +prog="@package_name@-snmp" +pidfile="@localstatedir@/run/ldap-agent.pid" +configfile="@sysconfdir@/@package_name@/config/ldap-agent.conf" + + + +[ -f $exec ] || exit 0 + + +umask 077 + +start() { + echo_n "Starting $prog: " + ret=0 + subagent_running=0 + subagent_started=0 + + # the subagent creates a pidfile and writes + # the pid to it when it is fully started. + if [ -f $pidfile ]; then + pid=`cat $pidfile` + name=`ps -p $pid | tail -1 | awk '{ print $4 }'` + if kill -0 $pid && [ $name = "$processname" ]; then + echo_n " already running" + success; echo + subagent_running=1 + else + echo " not running, but pid file exists" + echo_n " ... attempting to start anyway" + fi + fi + + if [ $subagent_running -eq 0 ] ; then + rm -f $pidfile + $exec $configfile > /dev/null 2>&1 + if [ $? -eq 0 ]; then + subagent_started=1 # well, perhaps not running, but started ok + else + failure; echo + ret=1 + fi + fi + # ok, if we started the subagent successfully, let's see + # if it is really running and ready to serve requests. + if [ $subagent_started -eq 1 ] ; then + loop_counter=1 + # wait for 10 seconds + max_count=10 + while test $loop_counter -le $max_count ; do + loop_counter=`expr $loop_counter + 1` + if test ! -f $pidfile ; then + if kill -0 $pid > /dev/null 2>&1 ; then + sleep 1 + else + break + fi + else + pid=`cat $pidfile` + break + fi + done + if kill -0 $pid > /dev/null 2>&1 && test -f $pidfile ; then + success; echo + else + failure; echo + ret=1 + fi + fi + + exit $ret +} + +stop() { + echo_n "Shutting down $prog: " + if [ -f $pidfile ]; then + pid=`cat $pidfile` + subagent_stopped=0 + if kill -0 $pid > /dev/null 2>&1 ; then + kill $pid + if [ $? -eq 0 ]; then + subagent_stopped=1 + else + failure; echo + fi + else + echo_n " subagent not running" + failure; echo + fi + if [ $subagent_stopped -eq 1 ] ; then + loop_counter=1 + # wait for 10 seconds + max_count=10 + while test $loop_counter -le $max_count; do + loop_counter=`expr $loop_counter + 1` + if kill -0 $pid > /dev/null 2>&1 ; then + sleep 1 + else + if test -f $pidfile ; then + rm -f $pidfile + fi + break + fi + done + if test -f $pidfile ; then + failure; echo + else + success; echo + rm -f $pidfile + fi + fi + else + echo_n " subagent already stopped" + failure; echo + fi +} + +reload() { + stop + start +} + +restart() { + stop + start +} + +condrestart() { + if [ -f $pidfile ]; then + pid=`cat $pidfile` + name=`ps -p $pid | tail -1 | awk '{ print $4 }'` + if kill -0 $pid && [ $name = "$processname" ]; then + restart + fi + fi +} + +status() { + ret=0 + if [ -f $pidfile ]; then + pid=`cat $pidfile` + if kill -0 $pid > /dev/null 2>&1 ; then + echo "$prog (pid $pid) is running..." + else + echo "$prog dead but pid file exists" + ret=1 + fi + else + echo "$prog is stopped" + ret=3 + fi + exit $ret +} + + +case "$1" in + start|stop|restart|reload|condrestart|status) + $1 + ;; + *) + echo Unknown command $1 + echo "Usage: $0 {start|stop|restart|reload|condrestart|status}" + exit 2 +esac diff --git a/wrappers/ldap-agent.in b/wrappers/ldap-agent.in index 0b19d8e..266507a 100755 --- a/wrappers/ldap-agent.in +++ b/wrappers/ldap-agent.in @@ -5,7 +5,7 @@ ############################################################################### LIB_DIR=@nss_libdir@:@nspr_libdir@:@ldapsdk_libdir@:@netsnmp_libdir@ -BIN_DIR=@bindir@ +BIN_DIR=@sbindir@ COMMAND=ldap-agent-bin # We don't need to load any mibs, so set MIBS to nothing. -- 1.6.2.5
-- 389-devel mailing list 389-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/fedora-directory-devel