103552
#!/bin/bash
103552
# This script serves one purpose, to add a possibly missing attribute
103552
# to a ppolicy schema in a dynamic configuration of OpenLDAP. This
103552
# attribute was introduced in openldap-2.4.43 and slapd will not 
103552
# start without it later on.
103552
#
103552
# The script tries to update in a directory given as first parameter,
103552
# or in /etc/openldap/slapd.d implicitly.
103552
#
103552
# Author: Matus Honek <mhonek@redhat.com>
103552
# Bugzilla: #1487857
103552
103552
function log {
103552
    echo "Update dynamic configuration: " $@
103552
    true
103552
}
103552
103552
function iferr {
103552
    if [ $? -ne 0 ]; then
103552
	log "ERROR: " $@
103552
	true
103552
    else
103552
	false
103552
    fi
103552
}
103552
103552
function update {
103552
    set -u
103552
    shopt -s extglob
103552
103552
    ORIGINAL="${1:-/etc/openldap/slapd.d}"
103552
    ORIGINAL="${ORIGINAL%*(/)}"
103552
103552
    ### check if necessary
103552
    grep -r "pwdMaxRecordedFail" "${ORIGINAL}/cn=config/cn=schema" >/dev/null
103552
    [ $? -eq 0 ] && log "Schemas look up to date. Ok. Quitting." && return 0
103552
103552
    ### prep
103552
    log "Prepare environment."
103552
    
103552
    TEMPDIR=$(mktemp -d)
103552
    iferr "Could not create a temporary directory. Quitting." && return 1
103552
    DBDIR="${TEMPDIR}/db"
103552
    SUBDBDIR="${DBDIR}/cn=temporary"
103552
103552
    mkdir "${DBDIR}"
103552
    iferr "Could not create temporary configuration directory. Quitting." && return 1
103552
    cp -r --no-target-directory "${ORIGINAL}" "${SUBDBDIR}"
103552
    iferr "Could not copy configuration. Quitting." && return 1
103552
    
103552
    pushd "$TEMPDIR" >/dev/null
103552
103552
    cat > temp.conf <
103552
database ldif
103552
suffix cn=temporary
103552
directory db
103552
access to * by * manage
103552
EOF
103552
    
103552
    SOCKET="$(pwd)/socket"
103552
    LISTENER="ldapi://${SOCKET//\//%2F}"
103552
    CONN_PARAMS=("-Y" "EXTERNAL" "-H" "${LISTENER}")
103552
    
103552
    slapd -f temp.conf -h "$LISTENER" -d 0 >/dev/null 2>&1 &
103552
    SLAPDPID="$!"
103552
    sleep 2
103552
103552
    ldapadd ${CONN_PARAMS[@]} -d 0 >/dev/null 2>&1 <
103552
dn: cn=temporary
103552
objectClass: olcGlobal
103552
cn: temporary
103552
EOF
103552
    iferr "Could not populate the temporary database. Quitting." && return 1
103552
    
103552
    ### update
103552
    log "Update with new pwdMaxRecordedFailure attribute."
103552
    FILTER="(&"
103552
    FILTER+="(olcObjectClasses=*'pwdPolicy'*)"
103552
    FILTER+="(!(olcObjectClasses=*'pwdPolicy'*'pwdMaxRecordedFailure'*))"
103552
    FILTER+="(!(olcAttributeTypes=*'pwdMaxRecordedFailure'*))"
103552
    FILTER+=")"
103552
    RES=$(ldapsearch ${CONN_PARAMS[@]} \
103552
		     -b cn=schema,cn=config,cn=temporary \
103552
		     -LLL \
103552
		     -o ldif-wrap=no \
103552
		     "$FILTER" \
103552
		     dn olcObjectClasses \
103552
		     2>/dev/null \
103552
	      | sed '/^$/d')
103552
    DN=$(printf "$RES" | grep '^dn:')
103552
    OC=$(printf "$RES" | grep "^olcObjectClasses:.*'pwdPolicy'")
103552
    NEWOC="${OC//$ pwdSafeModify /$ pwdSafeModify $ pwdMaxRecordedFailure }"
103552
103552
    test $(echo "$DN" | wc -l) = 1
103552
    iferr "Received more than one DN. Cannot continue. Quitting." && return 1
103552
    test "$NEWOC" != "$OC"
103552
    iferr "Updating pwdPolicy objectClass definition failed. Quitting." && return 1
103552
103552
    ldapmodify ${CONN_PARAMS[@]} -d 0 >/dev/null 2>&1 <
103552
$DN
103552
changetype: modify
103552
add: olcAttributeTypes
103552
olcAttributeTypes: ( 1.3.6.1.4.1.42.2.27.8.1.30 NAME 'pwdMaxRecordedFailur
103552
 e' EQUALITY integerMatch ORDERING integerOrderingMatch  SYNTAX 1.3.6.1.4.1.
103552
 1466.115.121.1.27 SINGLE-VALUE )
103552
-
103552
delete: olcObjectClasses
103552
$OC
103552
-
103552
add: olcObjectClasses
103552
$NEWOC
103552
EOF
103552
    iferr "Updating with new attribute failed. Quitting." && return 1
103552
103552
    popd >/dev/null
103552
103552
    ### apply
103552
    log "Apply changes."
103552
    cp -r --no-target-directory "$ORIGINAL" "$ORIGINAL~backup"
103552
    iferr "Backing up old configuration failed. Quitting." && return 1
103552
    cp -r --no-target-directory "$SUBDBDIR" "$ORIGINAL"
103552
    iferr "Applying new configuration failed. Quitting." && return 1
103552
    
103552
    ### clean up
103552
    log "Clean up."
103552
    kill "$SLAPDPID"
103552
    SLAPDPID=
103552
    rm -rf "$TEMPDIR"
103552
    TEMPDIR=
103552
}
103552
103552
SLAPDPID=
103552
TEMPDIR=
103552
update "$1"
103552
if [ $? -ne 0 ]; then
103552
    log "Clean up."
103552
    echo "$SLAPDPID"
103552
    echo "$TEMPDIR"
103552
    kill "$SLAPDPID"
103552
    rm -rf "$TEMPDIR"
103552
fi
103552
log "Finished."