point to more example scripts
[shellsnippets/shellsnippets.git] / mksh / assoldap.ksh
1 #-
2 # Copyright © 2013
3 #       Thorsten Glaser <t.glaser@tarent.de>
4 #
5 # Provided that these terms and disclaimer and all copyright notices
6 # are retained or reproduced in an accompanying document, permission
7 # is granted to deal in this work without restriction, including un‐
8 # limited rights to use, publicly perform, distribute, sell, modify,
9 # merge, give away, or sublicence.
10 #
11 # This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
12 # the utmost extent permitted by applicable law, neither express nor
13 # implied; without malicious intent or gross negligence. In no event
14 # may a licensor, author or contributor be held liable for indirect,
15 # direct, other damage, loss, or other issues arising in any way out
16 # of dealing in the work, even if advised of the possibility of such
17 # damage or existence of a defect, except proven that it results out
18 # of said person’s immediate fault when using the work as intended.
19 #-
20 # Generic LDAP (LDIF) parser into associative arrays.
21
22 # include assockit and pure-mksh base64 decoder, unless already done
23 mydir=$(realpath "$(dirname "$0")")
24 [[ -n $ASSO_VAL ]] || PATH="$mydir:$mydir/..:$PATH" . assockit.ksh
25 typeset -f Lb64decode >/dev/null || PATH="$mydir:$mydir/..:$PATH" . base64
26
27 # Syntax: asso_setldap arrayname index ... -- ldapsearch-options
28 function asso_setldap {
29         # parse options
30         local arrpath ldapopts x i=0 T dn line value
31         set -A arrpath
32         while (( $# )); do
33                 [[ $1 = -- ]] && break
34                 arrpath[i++]=$1
35                 shift
36         done
37         if [[ $1 != -- ]]; then
38                 print -u2 'assoldap.ksh: syntax: asso_setldap arraypath -- ldappath'
39                 return 255
40         fi
41         shift
42         set -A ldapopts -- "$@"
43
44         # just in case, unset the target array and create it as associative
45         asso__lookup 1 "${arrpath[@]}"
46         asso__r_free
47         asso__r_setf $ASSO_AASS
48
49         # call ldapsearch with decent output format
50         if ! T=$(mktemp -d /tmp/assoldap.XXXXXXXXXX); then
51                 print -u2 'assoldap.ksh: could not create temporary directory'
52                 return 255
53         fi
54         (ldapsearch -xLLL "${ldapopts[@]}"; echo $? >"$T/err") | \
55             tr '\n' $'\a' | sed -e $'s/\a //g' >"$T/out"
56         i=$(<"$T/err")
57         if (( i )); then
58                 print -u2 'assoldap.ksh: ldapsearch returned error'
59                 rm -rf "$T"
60                 return $i
61         fi
62         if [[ ! -s $T/out ]]; then
63                 # empty output
64                 rm -rf "$T"
65                 return 0
66         fi
67
68         # parse LDIF (without linewraps)
69         while IFS= read -d $'\a' -r line; do
70                 if [[ -z $line ]]; then
71                         dn=
72                         continue
73                 fi
74                 value=${line##+([!:]):?(:)*( )}
75                 if [[ $value = "$line" ]]; then
76                         print -ru2 "assoldap.ksh: malformed line: $line"
77                         rm -rf "$T"
78                         return 255
79                 fi
80                 x=${line%%*( )"$value"}
81                 if [[ $x = "$line" ]]; then
82                         print -ru2 "assoldap.ksh: malformed line: $line"
83                         rm -rf "$T"
84                         return 255
85                 fi
86                 [[ $x = *:: ]] && value=$(Lb64decode "$value")
87                 x=${x%%+(:)}
88                 if [[ -z $dn ]]; then
89                         if [[ $x = dn ]]; then
90                                 dn=$value
91                         else
92                                 print -ru2 "assoldap.ksh: not dn: $line"
93                                 rm -rf "$T"
94                                 return 255
95                         fi
96                 elif [[ $x = dn ]]; then
97                         print -ru2 "assoldap.ksh: unexpected dn ($dn): $line"
98                         rm -rf "$T"
99                         return 255
100                 fi
101                 asso_sets "$value" "${arrpath[@]}" "$dn" "$x"
102         done <"$T/out"
103         rm -rf "$T"
104         if [[ -n $dn ]]; then
105                 print -u2 'assoldap.ksh: missing empty line at EOT'
106                 return 255
107         fi
108         return 0
109 }
110
111 :||\
112 {
113         # for testing
114         LDAPTLS_CACERT=/etc/ssl/certs/dc.lan.tarent.de.cer \
115             asso_setldap users -- \
116             -H ldaps://dc.lan.tarent.de -b cn=users,dc=tarent,dc=de -s one \
117             isJabberAccount=1 cn uid
118         if (( $? )); then
119                 print -u2 An error occurred: $?
120                 exit 1
121         fi
122         print "uid (dn) = cn"
123         asso_loadk users
124         for user_dn in "${asso_y[@]}"; do
125                 print -r -- "$(asso_getv users "$user_dn" uid)" \
126                     "($user_dn) = $(asso_getv users "$user_dn" cn)"
127         done | sort
128 }