configure.ac | 31 +++--
ldap/admin/src/scripts/DSCreate.pm.in | 136 ++++++++++++++----------
ldap/admin/src/scripts/ds_selinux_enabled.in | 23 ++++
ldap/admin/src/scripts/ds_selinux_port_query.in | 69 ++++++++++++
5 files changed, 201 insertions(+), 63 deletions(-)
New commits:
commit 8269288d987e8372c4ce03e97d41dcac2ce3da4d
Author: William Brown <firstyear@redhat.com>
Date: Wed May 18 09:41:23 2016 +1000
Ticket 48336 - setup-ds should detect if port is already defined
Bug Description: Previously setup-ds.pl could not detect if a port was defined
in selinux policy or not.
Fix Description: This adds a set of selinux helpers that can query selinux port
in policy. Using these, setup-ds.pl can now make better decisions about whether
to label ports, or if they should be removed from policy during removal.
https://fedorahosted.org/389/ticket/48336
Author: wibrown
Review by: vashirov and nhosoi (Thank you!)
diff --git a/Makefile.am b/Makefile.am
index e715fba..824b745 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -154,6 +154,7 @@ CLEANFILES = dberrstrs.h ns-slapd.properties \
ldap/admin/src/scripts/ns-inactivate.pl ldap/admin/src/scripts/ns-newpwpolicy.pl \
ldap/admin/src/scripts/schema-reload.pl ldap/admin/src/scripts/syntax-validate.pl \
ldap/admin/src/scripts/usn-tombstone-cleanup.pl ldap/admin/src/scripts/verify-db.pl \
+ ldap/admin/src/scripts/ds_selinux_port_query ldap/admin/src/scripts/ds_selinux_enabled \
ldap/admin/src/scripts/dbverify \
$(NULL)
@@ -617,6 +618,8 @@ sbin_SCRIPTS = ldap/admin/src/scripts/setup-ds.pl \
ldap/admin/src/scripts/dbverify \
ldap/admin/src/scripts/upgradedb \
ldap/admin/src/scripts/dbmon.sh \
+ ldap/admin/src/scripts/ds_selinux_enabled \
+ ldap/admin/src/scripts/ds_selinux_port_query \
wrappers/ldap-agent
bin_SCRIPTS = ldap/servers/slapd/tools/rsearch/scripts/dbgen.pl \
@@ -1822,6 +1825,7 @@ fixupcmd = sed \
-e 's,@with_selinux\@,@with_selinux@,g' \
-e 's,@with_tmpfiles_d\@,@with_tmpfiles_d@,g' \
-e 's,@perlexec\@,@perlexec@,g' \
+ -e 's,@pythonexec\@,@pythonexec@,g' \
-e 's,@sttyexec\@,@sttyexec@,g' \
-e 's,@initconfigdir\@,$(initconfigdir),g'\
-e 's,@updatedir\@,$(updatedir),g' \
@@ -1890,6 +1894,7 @@ fixupcmd = sed \
-e 's,@with_selinux\@,@with_selinux@,g' \
-e 's,@with_tmpfiles_d\@,@with_tmpfiles_d@,g' \
-e 's,@perlexec\@,@perlexec@,g' \
+ -e 's,@pythonexec\@,@pythonexec@,g' \
-e 's,@sttyexec\@,@sttyexec@,g' \
-e 's,@initconfigdir\@,$(initconfigdir),g' \
-e 's,@updatedir\@,$(updatedir),g' \
diff --git a/configure.ac b/configure.ac
index 85e99f0..a7f0bbf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -396,21 +396,21 @@ else
with_perldir=
fi
-AC_MSG_CHECKING(for --with-pythondir)
-AC_ARG_WITH([pythondir],
- AS_HELP_STRING([--with-pythondir=PATH],
- [Directory for python)])
+AC_MSG_CHECKING(for --with-pythonexec)
+AC_ARG_WITH([pythonexec],
+ AS_HELP_STRING([--with-pythonexec=PATH],
+ [Path to executable for python)])
)
-if test -n "$with_pythondir"; then
- if test "$with_pythondir" = yes ; then
- AC_MSG_ERROR([You must specify --with-pythondir=/full/path/to/python])
- elif test "$with_pythondir" = no ; then
- with_pythondir=
+if test -n "$with_pythonexec"; then
+ if test "$with_pythonexec" = yes ; then
+ AC_MSG_ERROR([You must specify --with-pythonexec=/full/path/to/python])
+ elif test "$with_pythonexec" = no ; then
+ with_pythonexec=/usr/bin/python2
else
- AC_MSG_RESULT([$with_pythondir])
+ AC_MSG_RESULT([$with_pythonexec])
fi
else
- with_pythondir=
+ with_pythonexec=/usr/bin/python2
fi
AC_SUBST(configdir)
@@ -483,6 +483,14 @@ if test -n "$with_perldir"; then
else
perlexec='/usr/bin/env perl'
fi
+
+# This will let us change over the python version easier in the future.
+if test -n "$with_pythonexec"; then
+ pythonexec="$with_pythonexec"
+else
+ pythonexec='/usr/bin/env python2'
+fi
+
# we use stty in perl scripts to disable password echo
# this doesn't work unless the full absolute path of the
# stty command is used e.g. system("stty -echo") does not
@@ -622,6 +630,7 @@ fi
# sysv init scripts not used when systemd is used
AC_SUBST(initdir)
AC_SUBST(perlexec)
+AC_SUBST(pythonexec)
AC_SUBST(sttyexec)
# set default initconfigdir if not already set
diff --git a/ldap/admin/src/scripts/DSCreate.pm.in b/ldap/admin/src/scripts/DSCreate.pm.in
index cdbad35..bf5fc5c 100644
--- a/ldap/admin/src/scripts/DSCreate.pm.in
+++ b/ldap/admin/src/scripts/DSCreate.pm.in
@@ -1009,8 +1009,10 @@ sub updateSelinuxPolicy {
my $mydevnull = (-c "/dev/null" ? " /dev/null " : " NUL ");
# if selinux is not available, do nothing
- if ((getLogin() eq 'root') and "@with_selinux@" and
- -f "@sbindir@/sestatus" and !system ("@sbindir@/sestatus | egrep -i \"selinux status:\\s*enabled\" > $mydevnull 2>&1")) {
+ # In perl, exit(1) is 256 from system. ds_selinux_enable returns 1 on true, 0 on false.
+ if ((getLogin() eq 'root') and "@with_selinux@" and system("$inf->{slapd}->{sbindir}/ds_selinux_enabled") == 256 ) {
+ debug(1, "Selinux is enabled or permissive, fixing contexts\n");
+ # -f "@sbindir@/sestatus" and !system ("@sbindir@/sestatus | egrep -i \"selinux status:\\s*enabled\" > $mydevnull 2>&1")) {
my $localstatedir = $inf->{slapd}->{localstatedir};
# run restorecon on all of the parent directories we
@@ -1036,36 +1038,35 @@ sub updateSelinuxPolicy {
}
# label the selected port as ldap_port_t
+ # We should be doing this for secure port too .....
if ($inf->{slapd}->{ServerPort} != 0) {
- my $need_label = 1;
-
- # check if the port is already labeled properly
- my $portline = `semanage port -l | grep ldap_port_t | grep tcp`;
- chomp($portline);
- $portline =~ s/ldap_port_t\s+tcp\s+//g;
- my @labeledports = split(/,\s+/, $portline);
- foreach my $labeledport (@labeledports) {
- if (index($labeledport, "-") == -1) {
- # this is not a range of ports
- if ($inf->{slapd}->{ServerPort} == $labeledport) {
- $need_label = 0;
- last;
- }
- } else {
- # this is a range of ports like '<portMin>-<portMax>'
- my @range = split(/-/, $labeledport);
- if ((@range[0] <= $inf->{slapd}->{ServerPort}) && ($inf->{slapd}->{ServerPort} <= @range[1])) {
- $need_label = 0;
- last;
- }
- }
+ my $port_query_cmd = ("$inf->{slapd}->{sbindir}/ds_selinux_port_query $inf->{slapd}->{ServerPort} ldap_port_t 2> $mydevnull");
+ my $need_label = 0;
+ my $result = system($port_query_cmd);
+
+ # 0 is false, 1 is true. True means 'already in policy'.
+ if ($result == 0) {
+ debug(1, "Port $inf->{slapd}->{ServerPort} must be labeled as ldap_port_t \n");
+ $need_label = 1;
+ }
+ if ($result == 512) {
+ $need_label = 0;
+ debug(0, "Port $inf->{slapd}->{ServerPort} already belongs to another selinux type.\n");
+ debug(0, " The command below will show you the current type that owns the port.\n");
+ debug(0, "sudo $inf->{slapd}->{sbindir}/ds_selinux_port_query $inf->{slapd}->{ServerPort} ldap_port_t\n");
+ debug(0, " It is highly likely your server will fail to start ... \n");
+ }
+ if ($result == 131072) {
+ $need_label = 0;
+ debug(0, "An error occured running ds_selinux_port_query. This is probably a bug\n");
+ debug(0, "$port_query_cmd \n");
}
if ($need_label == 1) {
my $semanage_err;
my $rc;
# 60 is a bit excessive, we should fail faster.
- my $retry = 5;
+ my $retry = 2;
$ENV{LANG} = "C";
while (($retry > 0) && ($semanage_err = `semanage port -a -t ldap_port_t -p tcp $inf->{slapd}->{ServerPort} 2>&1`) && ($rc = $?)) {
debug(1, "Adding port $inf->{slapd}->{ServerPort} to selinux policy failed - $semanage_err (return code: $rc, $retry attempts remain).\n");
@@ -1461,52 +1462,83 @@ sub removeDSInstance {
# remove the selinux label from the ports if needed
my $mydevnull = (-c "/dev/null" ? " /dev/null " : " NUL ");
- if ((getLogin() eq 'root') and "@with_selinux@" and
- -f "@sbindir@/sestatus" and !system ("@sbindir@/sestatus | egrep -i \"selinux status:\\s*enabled\" > $mydevnull 2>&1")) {
+ if ((getLogin() eq 'root') and "@with_selinux@" and system("@sbindir@/ds_selinux_enabled") == 256 ) {
foreach my $port (@{$entry->{"nsslapd-port"}})
{
+
+ my $need_remove_label = 0;
+ my $port_query_cmd = ("@sbindir@/ds_selinux_port_query $port ldap_port_t 2> $mydevnull");
+ my $result = system($port_query_cmd);
+
+ if ($result == 256) {
+ debug(1, "Port $port may be removed as ldap_port_t \n");
+ $need_remove_label = 1;
+ }
+ if ($result == 131072) {
+ $need_remove_label = 0;
+ debug(0, "An error occured running ds_selinux_port_query. This is probably a bug\n");
+ debug(0, "$port_query_cmd \n");
+ }
+
my $semanage_err;
my $rc;
my $retry = 5;
$ENV{LANG} = "C";
- while (($retry > 0) && ($semanage_err = `semanage port -d -t ldap_port_t -p tcp $port 2>&1`) && ($rc = $?)) {
- if (($semanage_err =~ /defined in policy, cannot be deleted/) || ($semanage_err =~ /is not defined/)) {
- $retry = -1;
- } else {
- debug(1, "Warning: Port $port not removed from selinux policy correctly, $retry attempts remain. Error: $semanage_err\n");
- debug(1, "Retrying in 5 seconds\n");
- sleep(5);
- $retry--;
+ if ($need_remove_label) {
+ while (($retry > 0) && ($semanage_err = `semanage port -d -t ldap_port_t -p tcp $port 2>&1`) && ($rc = $?)) {
+ if (($semanage_err =~ /defined in policy, cannot be deleted/) || ($semanage_err =~ /is not defined/)) {
+ $retry = -1;
+ } else {
+ debug(1, "Warning: Port $port not removed from selinux policy correctly, $retry attempts remain. Error: $semanage_err\n");
+ debug(1, "Retrying in 5 seconds\n");
+ sleep(5);
+ $retry--;
+ }
+ }
+ if (0 == $retry) {
+ push @errs, [ 'error_removing_port_label', $port, $semanage_err];
+ debug(1, "Warning: Port $port not removed from selinux policy correctly. Error: $semanage_err\n");
+ debug(1, "Reached time limit.\n");
}
- }
- if (0 == $retry) {
- push @errs, [ 'error_removing_port_label', $port, $semanage_err];
- debug(1, "Warning: Port $port not removed from selinux policy correctly. Error: $semanage_err\n");
- debug(1, "Reached time limit.\n");
}
}
foreach my $secureport (@{$entry->{"nsslapd-secureport"}})
{
+ my $need_remove_label = 0;
+ my $port_query_cmd = ("@sbindir@/ds_selinux_port_query $secureport ldap_port_t 2> $mydevnull");
+ my $result = system($port_query_cmd);
+
+ if ($result == 256) {
+ debug(1, "Port $secureport may be removed as ldap_port_t \n");
+ $need_remove_label = 1;
+ }
+ if ($result == 131072) {
+ $need_remove_label = 0;
+ debug(0, "An error occured running ds_selinux_port_query. This is probably a bug\n");
+ debug(0, "$port_query_cmd \n");
+ }
my $semanage_err;
my $rc;
my $retry = 60;
$ENV{LANG} = "C";
- while (($retry > 0) && ($semanage_err = `semanage port -d -t ldap_port_t -p tcp $secureport 2>&1`) && ($rc = $?)) {
- if (($semanage_err =~ /defined in policy, cannot be deleted/) || ($semanage_err =~ /is not defined/)) {
- $retry = -1;
- } else {
+ if ($need_remove_label) {
+ while (($retry > 0) && ($semanage_err = `semanage port -d -t ldap_port_t -p tcp $secureport 2>&1`) && ($rc = $?)) {
+ if (($semanage_err =~ /defined in policy, cannot be deleted/) || ($semanage_err =~ /is not defined/)) {
+ $retry = -1;
+ } else {
+ debug(1, "Warning: Port $secureport not removed from selinux policy correctly. Error: $semanage_err\n");
+ debug(1, "Retrying in 5 seconds\n");
+ sleep(5);
+ $retry--;
+ }
+ }
+ if (0 == $retry) {
+ push @errs, [ 'error_removing_port_label', $secureport, $semanage_err];
debug(1, "Warning: Port $secureport not removed from selinux policy correctly. Error: $semanage_err\n");
- debug(1, "Retrying in 5 seconds\n");
- sleep(5);
- $retry--;
+ debug(1, "Reached time limit.\n");
}
}
- if (0 == $retry) {
- push @errs, [ 'error_removing_port_label', $secureport, $semanage_err];
- debug(1, "Warning: Port $secureport not removed from selinux policy correctly. Error: $semanage_err\n");
- debug(1, "Reached time limit.\n");
- }
}
}
diff --git a/ldap/admin/src/scripts/ds_selinux_enabled.in b/ldap/admin/src/scripts/ds_selinux_enabled.in
new file mode 100755
index 0000000..54a79b0
--- /dev/null
+++ b/ldap/admin/src/scripts/ds_selinux_enabled.in
@@ -0,0 +1,23 @@
+#!@pythonexec@
+
+# BEGIN COPYRIGHT BLOCK
+# Copyright (C) 2016 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# END COPYRIGHT BLOCK
+#
+
+# These are python 3 capable, but el7 doesn't have libsemanage-python3
+
+
+import sys
+import selinux
+import semanage
+
+# Returns 1 for true, 0 for false.
+
+sys.exit(selinux.is_selinux_enabled())
+
+
diff --git a/ldap/admin/src/scripts/ds_selinux_port_query.in b/ldap/admin/src/scripts/ds_selinux_port_query.in
new file mode 100644
index 0000000..006f978
--- /dev/null
+++ b/ldap/admin/src/scripts/ds_selinux_port_query.in
@@ -0,0 +1,69 @@
+#!@pythonexec@
+
+# BEGIN COPYRIGHT BLOCK
+# Copyright (C) 2016 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# END COPYRIGHT BLOCK
+#
+
+import sys
+import selinux
+import semanage
+
+# These are python 3 capable, but el7 doesn't have libsemanage-python3
+
+# Given a port number as the first argument, determine if it's already part of the policy.
+# The second (optional) argument is a label type to check.
+
+# 0 for does not exist in policy. 1 mean exists (with no label)
+# or if a lable is given, exists AND inside of label type.
+# 2 means port exists but belongs to a different type.
+
+if len(sys.argv) <= 1:
+ sys.stderr.write("Must provide port to query\n")
+ sys.exit(512)
+
+port = int(sys.argv[1])
+label = None
+try:
+ label = sys.argv[2]
+except:
+ pass
+
+# Get the arguments
+
+# Fail if they are not set correctly.
+
+# Check the port in policy
+h = semanage.semanage_handle_create()
+semanage.semanage_connect(h)
+# This could check high / low values, but eh.
+(r, k) = semanage.semanage_port_key_create(h, port, port, semanage.SEMANAGE_PROTO_TCP)
+
+# Do I need to check _local too?
+(t, e) = semanage.semanage_port_exists(h, k)
+
+if label is None:
+ sys.exit(e)
+
+# See if it has a specifc label
+
+if (e == 0):
+ # No point checking the label, it doesn't exist
+ sys.exit(e)
+
+(t, sp) = semanage.semanage_port_query(h, k)
+
+# do we need to check if this is none? We already know that the port exists, so it must have a context ...
+r = semanage.semanage_port_get_con(sp)
+
+if label == semanage.semanage_context_get_type(r):
+ sys.exit(1)
+
+else:
+ sys.stderr.write('Port belongs to %s\n' % semanage.semanage_context_get_type(r))
+ sys.exit(2)
+
_______________________________________________
389-commits mailing list -- 389-commits@lists.fedoraproject.org
To unsubscribe send an email to 389-commits-leave@lists.fedoraproject.org
No comments:
Post a Comment