File ppolicy-20200806-upgrade.sh of Package openldap2.24984
#!/bin/bash
# Script to update ppolicy.ldif in the OpenLDAP Online Configuration (OLC) to
# include the pwdMaxRecordedFailure attribute.
# Check if an update is necessary.
conf_dir='/etc/openldap/slapd.d'
if [ ! -d "${conf_dir}" ] || [ ! -f "${conf_dir}/cn=config.ldif" ]; then
exit 0
fi
ppolicy_ldif=( "${conf_dir}"/cn=config/cn=schema/cn={*}ppolicy.ldif )
if [ ! -f "${ppolicy_ldif}" ]; then
exit 0
fi
if /usr/bin/grep -q pwdMaxRecordedFailure "${ppolicy_ldif}"; then
exit 0
fi
# Check that .rpmnew can be used as a temporary file by the script. The file
# should never be present.
if [ -f "${ppolicy_ldif}.rpmnew" ]; then
exit 0
fi
echo "Updating ppolicy schema ${ppolicy_ldif} ..."
# Make sure slapd.service is not running.
slapd_running=1
# Don't check if no systemd, we could be in a container.
if [ -f "/usr/bin/systemctl" ]; then
/usr/bin/systemctl is-active --quiet slapd.service
slapd_running=$?
fi
if [ $slapd_running -eq 0 ]; then
/usr/bin/systemctl stop slapd.service
fi
# Backup the original file.
if [ ! -f "${ppolicy_ldif}.rpmsave" ]; then
/bin/cp -p "${ppolicy_ldif}" "${ppolicy_ldif}.rpmsave"
fi
# Update the ppolicy.ldif file with pwdMaxRecordedFailure.
/bin/cp -p "${ppolicy_ldif}" "${ppolicy_ldif}.rpmnew"
/usr/bin/awk '
BEGIN {
# CRC-32 ZIP polynomial in reversed bit order.
POLY = 0xedb88320
# 8-bit character -> ordinal table.
for (i = 0; i < 256; i++)
ORD[sprintf("%c", i)] = i
# Input location of the last olcAttributeTypes entry.
last_attr_type_index = -1
last_attr_type_length = -1
in_attr_type = 0
# Input location of the olcObjectClasses pwdPolicy entry.
pwd_policy_index = -1
pwd_policy_length = -1
in_pwd_policy = 0
}
{
# Remember each input line.
input[NR] = $0
# Verify the file header.
if (NR == 1 && $0 != "# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify.")
exit 1
if (NR == 2 && $0 !~ /# CRC32 ......../)
exit 1
# Reset any continuation if a new entry is encountered.
if ($0 !~ /^ /) {
in_attr_type = 0
in_pwd_policy = 0
}
# Find the last olcAttributeTypes and the olcObjectClasses pwdPolicy
# entries in the input.
if ($0 ~ /^olcAttributeTypes: /) {
last_attr_type_index = NR
last_attr_type_length = 1
in_attr_type = 1
}
else if ($0 ~ /^olcObjectClasses: .* NAME '\''pwdPolicy'\''/) {
pwd_policy_index = NR
pwd_policy_length = 1
in_pwd_policy = 1
}
else if ($0 ~ /^ /) {
if (in_attr_type)
last_attr_type_length++
if (in_pwd_policy)
pwd_policy_length++
}
}
# Unwrap a series of lines from the global `input` array and return the
# resulting entry string.
function input_unwrap(input_index, entry_length, res, i) {
res = input[input_index]
for (i = 1; i < entry_length; i++)
res = res substr(input[input_index + i], 2)
return res
}
# Wrap an entry string and record it in the global `output` array.
function output_wrap(output_index, entry) {
output[output_index] = substr(entry, 1, 76)
entry = substr(entry, 77)
output_index++
while (length(entry) > 0) {
output[output_index++] = " " substr(entry, 1, 75)
entry = substr(entry, 76)
}
return output_index
}
# Calculate CRC-32.
function crc32(crc, string, i, j, c) {
crc = and(compl(crc), 0xffffffff)
for (i = 1; i <= length(string); i++) {
c = substr(string, i, 1)
crc = xor(crc, ORD[c])
for (j = 0; j < 8; j++)
crc = and(crc, 1) ? xor(rshift(crc, 1), POLY) : rshift(crc, 1)
}
crc = and(compl(crc), 0xffffffff)
return crc
}
END {
# Check that the input data looks sensible.
if (last_attr_type_index == -1 || pwd_policy_index == -1 ||
last_attr_type_index > pwd_policy_index)
exit 1
# Get index of the last olcAttributeTypes entry.
line = input[last_attr_type_index]
m = match(line, /{[^}]+}/)
if (!m)
exit 1
next_type_entry = strtonum(substr(line, RSTART + 1, RLENGTH - 2))
if (!next_type_entry)
exit 1
next_type_entry++
# Prepare the new pwdMaxRecordedFailure entry.
new_type_entry = "olcAttributeTypes: {" next_type_entry "}( 1.3.6.1.4.1.42.2.27.8.1.30 NAME '\''pwdMaxRecordedFailure'\'' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )"
# Update the pwdPolicy entry to include pwdMaxRecordedFailure.
pwd_policy_entry = input_unwrap(pwd_policy_index, pwd_policy_length)
r = gsub(/\$ pwdSafeModify/, "$ pwdSafeModify $ pwdMaxRecordedFailure", pwd_policy_entry)
if (r != 1)
exit 1
# Prepare the output.
output_index = 1
last_attr_type_end = last_attr_type_index + last_attr_type_length
for (i = 1; i < last_attr_type_end; i++)
output[output_index++] = input[i]
output_index = output_wrap(output_index, new_type_entry)
for (i = last_attr_type_end; i < pwd_policy_index; i++)
output[output_index++] = input[i]
output_index = output_wrap(output_index, pwd_policy_entry)
for (i = pwd_policy_index + pwd_policy_length; i <= length(input); i++)
output[output_index++] = input[i]
# Calculate CRC-32 of the file and update it in the header.
crc = 0
for (i = 3; i <= length(output); i++)
crc = crc32(crc, output[i] "\n")
output[2] = "# CRC32 " sprintf("%08x", crc)
# Print the output.
for (i = 1; i <= length(output); i++)
print output[i]
}' "${ppolicy_ldif}" > "${ppolicy_ldif}.rpmnew"
rc=$?
if [ $rc -eq 0 ]; then
/bin/mv "${ppolicy_ldif}.rpmnew" "${ppolicy_ldif}"
else
/bin/rm "${ppolicy_ldif}.rpmnew"
fi
# Restore slapd.service to the previous state.
if [ $slapd_running -eq 0 ]; then
/usr/bin/systemctl start slapd.service
fi
exit 0