3 # Configure LDAP for GForge
4 # Christian Bayle, Roland Mas
5 # Initially written for debian-sf (Sourceforge for Debian)
6 # Adapted as time went by for Gforge
10 # This is purely for compatibility, and will be removed sometime
11 if [ "$DEBSFDEBUG" = 1 ] ; then
15 if [ "$GFORGEDEBUG" != 1 ] ; then
16 DEVNULL12="> /dev/null 2>&1"
17 DEVNULL2="2> /dev/null"
22 if [ $(id -u) != 0 -a "x$1" != "xlist" ] ; then
23 echo "You must be root to run this, please enter passwd"
30 ldap_host=$(grep ^ldap_host= /etc/fusionforge/fusionforge.conf | cut -d= -f2-)
32 gforge_base_dn=$(grep ^ldap_base_dn= /etc/fusionforge/fusionforge.conf | cut -d= -f2-)
33 gforge_admin_dn="cn=admin,$gforge_base_dn"
34 slapd_base_dn=$(grep ^suffix /etc/ldap/slapd.conf | cut -d\" -f2)
35 slapd_admin_dn="cn=admin,$slapd_base_dn"
36 robot_dn="cn=SF_robot,$gforge_base_dn"
38 robot_passwd=$(grep ^ldap_web_add_password= /etc/fusionforge/fusionforge.conf | cut -d= -f2-)
39 robot_cryptedpasswd=`slappasswd -s "$robot_passwd" -h {CRYPT}`
40 # TODO: ask the user for the main (slapd) password
41 # Probably only do that when needed (when inserting the robot account)
42 [ -f /etc/ldap.secret ] && slapd_admin_passwd=$(cat /etc/ldap.secret) || slapd_admin_passwd=$robot_passwd
44 cryptedpasswd=`slappasswd -s "$slapd_admin_passwd" -h {CRYPT}`
46 tmpfile_pattern=/tmp/$(basename $0).XXXXXX
50 echo "slapd_base_dn = '$slapd_base_dn'"
51 echo "gforge_base_dn = '$gforge_base_dn'"
52 echo "slapd_admin_dn = '$slapd_admin_dn'"
53 echo "slapd_admin_passwd = '$slapd_admin_passwd'"
54 echo "cryptedpasswd = '$cryptedpasswd'"
55 echo "tmpfile_pattern = '$tmpfile_pattern'"
59 server_base_dn=$(eval "ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts $DEVNULL2" | grep "namingContexts:" | cut -d" " -f2)
60 echo "gforge_base_dn = $gforge_base_dn"
61 echo "server_base_dn = $server_base_dn"
62 if echo $gforge_base_dn | grep -q "$server_base_dn\$" ; then
63 echo Gforge base DN is under the existing server base DN -- OK
65 echo Gforge base DN is *not* under the existing server base DN -- fail
69 addon=$(echo $gforge_base_dn | sed "s/$server_base_dn\$//")
71 if [ -z "$addon" ] ; then
72 echo Gforge base DN is equal to server base DN -- OK
74 elif [ -z "$(echo $addon | cut -d, -f2-)" ] ; then
75 echo Gforge base DN is just a level under the server base DN -- OK
78 echo Gforge base DN is at least two levels under the server base DN -- continuing investigations
81 needednc=$(echo $gforge_base_dn | cut -d, -f2-)
82 if slapcat | grep -q "dn: $needednc" ; then
83 echo Found existing object in which to create our directory -- OK
85 echo No existing object in which to create our directory -- fail
93 nr=$(ldapsearch -LLL -x -b "$my_dn" -s base '' dn 2> /dev/null | grep ^dn: | wc -l)
94 echo "$nr:${PIPESTATUS[0]}"
97 nr=$(echo $r | cut -d: -f1)
98 p=$(echo $r | cut -d: -f2)
99 if [ $p == 32 ] || [ $nr = 0 ] ; then
108 answer=$(eval "ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts $DEVNULL2" | grep "namingContexts:" | cut -d" " -f2)
109 if [ "x$answer" == "x" ] ; then
110 eval "invoke-rc.d slapd restart $DEVNULL12" && sleep 5
111 answer=$(eval "ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts $DEVNULL2" \
112 | grep "namingContexts:" \
115 if [ "x$answer" == "x" ] ; then
116 echo "LDAP Server dead"
119 # echo "LDAP Server OK: suffix=$answer"
123 # Check admin password
125 tmpcheckpwd=$(mktemp $tmpfile_pattern)
126 if ldapsearch -D $slapd_admin_dn -x -w$slapd_admin_passwd -n $slapd_admin_dn > $tmpcheckpwd 2>&1 ; then
127 echo "Password checked OK." > /dev/null
129 if grep -q "ldap_bind: Invalid credentials" $tmpcheckpwd ; then
131 exit 5 # Wrong password
134 exit 99 # Unknown error
139 # Should I do something for /etc/pam_ldap.conf ?
142 # echo "Nothing to do"
145 # Check/Modify /etc/libnss-ldap.conf
146 configure_libnss_ldap(){
147 cp -a /etc/libnss-ldap.conf /etc/libnss-ldap.conf.gforge-new
148 # Check if DN is correct
149 if ! grep -q "^base[ ]*$sf_ldap_dn" /etc/libnss-ldap.conf.gforge-new ; then
150 echo "WARNING: Probably incorrect base line in /etc/libnss-ldap.conf"
151 grep "^base" /etc/libnss-ldap.conf
152 echo "Should be: base $gforge_base_dn"
155 # Should contain the secret
156 # All users can see ldap stored gid/uid
157 chmod 644 /etc/libnss-ldap.conf.gforge-new
158 # It doesn't seem to be necessary, only rootbinddn is necessary
159 # if ! grep -q "^bindpw" /etc/libnss-ldap.conf ; then
160 # echo "# Next line added by GForge install" >>/etc/libnss-ldap.conf
161 # echo "bindpw secret" >>/etc/libnss-ldap.conf
164 # This seems to be necessary to display uid/gid
165 # Should be cn=admin,dc=...
166 if ! grep -q "^rootbinddn" /etc/libnss-ldap.conf.gforge-new ; then
167 echo "# Next line added by GForge install" >>/etc/libnss-ldap.conf.gforge-new
168 echo "rootbinddn $gforge_admin_dn" >>/etc/libnss-ldap.conf.gforge-new
172 # Purge /etc/libnss-ldap.conf
174 cp -a /etc/libnss-ldap.conf /etc/libnss-ldap.conf.gforge-new
175 perl -pi -e "s/^# Next line added by GForge install\n/#SF#/g" /etc/libnss-ldap.conf.gforge-new
176 perl -pi -e "s/^#SF#.*\n//g" /etc/libnss-ldap.conf.gforge-new
179 # Modify /etc/ldap/slapd.conf
181 if [ ! -e /etc/ldap/slapd.conf ] ; then
182 echo "ERROR: You don't have a /etc/ldap/slapd.conf file."
183 echo "Please make sure your slapd package is correctly configured."
186 cp -a /etc/ldap/slapd.conf /etc/ldap/slapd.conf.gforge-new
189 # Maybe should comment referral line too
190 echo "WARNING: Please check referal line in /etc/ldap/slapd.conf"
192 # Debian config by default only include core schema
193 if ! grep -q "GForge" /etc/ldap/slapd.conf.gforge-new ; then
194 tmpfile=$(mktemp $tmpfile_pattern)
195 for schema in /etc/ldap/schema/core.schema \
196 /etc/ldap/schema/cosine.schema \
197 /etc/ldap/schema/inetorgperson.schema \
198 /etc/ldap/schema/nis.schema \
199 /etc/gforge/gforge.schema
201 if ! grep -q "^include[ ]*$schema" /etc/ldap/slapd.conf.gforge-new ; then
202 echo "include $schema #Added by GForge install" >> $tmpfile
203 # echo "Adding $schema"
205 # echo "Commenting $schema"
206 perl -pi -e "s(^include[ ]*$schema)(#Comment by GForge install#include $schema)g" /etc/ldap/slapd.conf.gforge-new
207 echo "include $schema #Added by GForge install" >> $tmpfile
208 # echo "Adding $schema"
212 cat /etc/ldap/slapd.conf.gforge-new >> $tmpfile
213 cat $tmpfile > /etc/ldap/slapd.conf.gforge-new
216 # Then write access for SF_robot
217 perl -pi -e "s/access to attribute=userPassword/# Next second line added by GForge install
218 access to attribute=userPassword
219 by dn=\"$robot_dn\" write/" /etc/ldap/slapd.conf.gforge-new
221 # odd looking regex makes sure it doesnt match the comment 'access to *'
222 perl -pi -e "s/(?<!')access to \*(?!')/# Next lines added by GForge install
223 access to dn.subtree=\"ou=People,$gforge_base_dn\"
224 by dn=\"$gforge_admin_dn\" write
225 by dn=\"$robot_dn\" write
226 by dn=\"$slapd_admin_dn\" write
228 access to dn.subtree=\"ou=Group,$gforge_base_dn\"
229 by dn=\"$gforge_admin_dn\" write
230 by dn=\"$robot_dn\" write
231 by dn=\"$slapd_admin_dn\" write
233 access to dn.subtree=\"ou=mailingList,$gforge_base_dn\"
234 by dn=\"$gforge_admin_dn\" write
235 by dn=\"$robot_dn\" write
236 by dn=\"$slapd_admin_dn\" write
238 access to dn.subtree=\"ou=cvsGroup,$gforge_base_dn\"
239 by dn=\"$gforge_admin_dn\" write
240 by dn=\"$robot_dn\" write
241 by dn=\"$slapd_admin_dn\" write
244 access to */" /etc/ldap/slapd.conf.gforge-new
246 # invoke-rc.d slapd restart
250 # Purge /etc/ldap/slapd.conf
252 if [ ! -e /etc/ldap/slapd.conf ] ; then
253 echo "ERROR: You don't have a /etc/ldap/slapd.conf file."
254 echo "Please make sure your slapd package is correctly configured."
257 cp -a /etc/ldap/slapd.conf /etc/ldap/slapd.conf.gforge-new
262 perl -pi -e "s/^.*#Added by GForge install\n//" /etc/ldap/slapd.conf.gforge-new
263 perl -pi -e "s/#Comment by GForge install#//" /etc/ldap/slapd.conf.gforge-new
264 if grep -q "# Next second line added by GForge install" /etc/ldap/slapd.conf.gforge-new ; then
265 vi -e /etc/ldap/slapd.conf.gforge-new <<-FIN
266 /# Next second line added by GForge install
274 if grep -q "Next lines added by GForge install" /etc/ldap/slapd.conf.gforge-new ; then
275 vi -e /etc/ldap/slapd.conf.gforge-new <<-FIN
276 /# Next lines added by GForge install
287 # Modify /etc/nsswitch.conf
290 cp -a /etc/nsswitch.conf /etc/nsswitch.conf.gforge-new
291 # This is sensitive file
292 # By security i let priority to files
293 # Should maybe enhance this to take in account nis
294 # Maybe ask the order db/files/nis/ldap
295 if ! grep -q '^passwd:.*ldap' /etc/nsswitch.conf.gforge-new ; then
296 perl -pi -e "s/^(passwd:[^#\n]*)([^\n]*)/\1 ldap \2#Added by GForge install\n#Comment by GForge install#\1\2/gs" /etc/nsswitch.conf.gforge-new
298 if ! grep -q '^group:.*ldap' /etc/nsswitch.conf.gforge-new ; then
299 perl -pi -e "s/^(group:[^#\n]*)([^\n]*)/\1 ldap \2#Added by GForge install\n#Comment by GForge install#\1\2/gs" /etc/nsswitch.conf.gforge-new
301 if ! grep -q '^shadow:.*ldap' /etc/nsswitch.conf.gforge-new ; then
302 perl -pi -e "s/^(shadow:[^#\n]*)([^\n]*)/\1 ldap \2#Added by GForge install\n#Comment by GForge install#\1\2/gs" /etc/nsswitch.conf.gforge-new
306 # Purge /etc/nsswitch.conf
309 cp -a /etc/nsswitch.conf /etc/nsswitch.conf.gforge-new
310 perl -pi -e "s/^[^\n]*#Added by GForge install\n//" /etc/nsswitch.conf.gforge-new
311 perl -pi -e "s/#Comment by GForge install#//" /etc/nsswitch.conf.gforge-new
314 # Load ldap database from gforge database
316 # First, let's make sure our base DN exists
317 if ! exists_dn $gforge_base_dn ; then
318 tmpldif=$(mktemp $tmpfile_pattern)
319 tmpldifadd=$(mktemp $tmpfile_pattern)
320 tmpldifmod=$(mktemp $tmpfile_pattern)
321 dc=$(echo $gforge_base_dn | cut -d, -f1 | cut -d= -f2)
323 cat >> $tmpldif <<EOF
324 dn: $sys_ldap_base_dn
327 objectClass: domainRelatedObject
328 associatedDomain: $sys_default_domain
330 # echo "Filling LDAP with database"
331 if ! eval "ldapadd -r -c -D '$robot_dn' -x -w'$robot_passwd' -f $tmpldif > $tmpldifadd 2>&1" ; then
332 # Some entries could not be added (already there?)
333 # Therefore, we try to modify them
334 if ! eval "ldapmodify -r -c -D '$robot_dn' -x -w'$robot_passwd' -f $tmpldif > $tmpldifmod 2>&1" ; then
335 echo "WARNING WARNING WARNING Something wrong happened in ldapmodify"
336 echo "please check and report following error"
337 echo ========================================================================================
338 cat $tmpldifmod | perl -pi -e 's/^\n//' | perl -pi -e 's/modifying.*\"\n//'
339 echo ========================================================================================
340 echo SEE ALSO result of ldapadd in:
342 echo AND result of ldapmodify in:
344 echo AND ldif file in:
346 echo ========================================================================================
350 rm -f $tmpldif $tmpldifadd $tmpldifmod
353 # CLEANUP: should be done with the robot
354 # This loads the ldap database
355 # echo "Our base DN is $gforge_base_dn"
356 # echo "Creating ldif file from database"
357 tmpldif=$(mktemp $tmpfile_pattern)
358 tmpldifadd=$(mktemp $tmpfile_pattern)
359 tmpldifmod=$(mktemp $tmpfile_pattern)
360 dc=$(echo $gforge_base_dn | cut -d, -f1 | cut -d= -f2)
361 su -s /bin/sh gforge -c /usr/share/gforge/bin/sql2ldif.pl >> $tmpldif
362 # echo "Filling LDAP with database"
363 if ! eval "ldapadd -r -c -D '$robot_dn' -x -w'$robot_passwd' -f $tmpldif > $tmpldifadd 2>&1" ; then
364 # Some entries could not be added (already there)
365 # Therefore, we have to modify them
366 if ! eval "ldapmodify -r -c -D '$robot_dn' -x -w'$robot_passwd' -f $tmpldif > $tmpldifmod 2>&1" ; then
367 echo "WARNING WARNING WARNING Something wrong happened in ldapmodify"
368 echo "please check and report following error"
369 echo ========================================================================================
370 cat $tmpldifmod | perl -pi -e 's/^\n//' | perl -pi -e 's/modifying.*\"\n//'
371 echo ========================================================================================
372 echo SEE ALSO result of ldapadd in:
374 echo AND result of ldapmodify in:
376 echo AND ldif file in:
378 echo ========================================================================================
382 rm -f $tmpldif $tmpldifadd $tmpldifmod
385 print_ldif_default(){
386 dc=`echo $slapd_base_dn | sed 's/dc=\(.[^,]*\),.*/\1/'`
390 objectClass: dcObject
393 dn: cn=admin,$slapd_base_dn
394 objectClass: organizationalRole
395 objectClass: simpleSecurityObject
397 userPassword: $cryptedpasswd
398 description: LDAP administrator
400 dn: ou=People,$slapd_base_dn
401 objectClass: organizationalUnit
404 dn: ou=Roaming,$slapd_base_dn
405 objectCLass: organizationalUnit
414 # The first account is only used in a multiserver SF
416 if ! exists_dn "$robot_dn" || ! exists_dn "ou=People,$gforge_base_dn" ; then
418 echo "Adding robot accounts and sub-trees"
419 dc=$(echo $gforge_base_dn | cut -d, -f1 | cut -d= -f2)
420 tmpldif=$(mktemp $tmpfile_pattern)
421 tmpldifadd=$(mktemp $tmpfile_pattern)
422 tmpldifmod=$(mktemp $tmpfile_pattern)
424 cat > $tmpldif <<-FIN
426 objectClass: organization
428 dn: ou=People,$gforge_base_dn
430 objectClass: organizationalUnit
432 dn: ou=Aliases,$gforge_base_dn
434 objectClass: organizationalUnit
436 dn: ou=Group,$gforge_base_dn
438 objectClass: organizationalUnit
440 dn: ou=cvsGroup,$gforge_base_dn
442 objectClass: organizationalUnit
444 dn: ou=mailingList,$gforge_base_dn
446 objectClass: organizationalUnit
448 dn: cn=Replicator,$gforge_base_dn
449 description: Replicator the Robot
450 objectClass: organizationalRole
451 objectClass: simpleSecurityObject
452 userPassword: {CRYPT}xxxxx
456 description: SF the Robot
457 objectClass: organizationalRole
458 objectClass: simpleSecurityObject
459 userPassword: $robot_cryptedpasswd
462 dn: uid=dummy,ou=People,$gforge_base_dn
466 objectClass: posixAccount
468 objectClass: shadowAccount
469 objectClass: debGforgeAccount
470 userPassword: {crypt}x
471 shadowLastChange: 10879
474 loginShell: /bin/false
475 debGforgeCvsShell: /bin/false
483 if ! eval "ldapadd -r -c -D '$slapd_admin_dn' -x -w'$slapd_admin_passwd' -f $tmpldif > $tmpldifadd 2>&1" ; then
484 if ! eval "ldapmodify -r -c -D '$slapd_admin_dn' -x -w'$slapd_admin_passwd' -f $tmpldif > $tmpldifadd 2>&1" ; then
485 echo "WARNING WARNING WARNING Something wrong happened when setting up the robot"
486 echo "please check and report following error"
487 echo ========================================================================================
488 cat $tmpldifmod | perl -pi -e 's/^\n//' | perl -pi -e 's/modifying.*\"\n//'
489 echo ========================================================================================
490 echo SEE ALSO result of ldapadd in:
492 echo AND result of ldapmodify in:
494 echo AND ldif file in:
496 echo ========================================================================================
501 echo "Robot accounts already present, not adding"
505 # echo "Testing LDAP"
506 if ! exists_dn uid=dummy,ou=People,$gforge_base_dn ; then
507 # echo "Adding dummy user"
508 eval "ldapadd -v -c -D '$robot_dn' -x -w'$robot_passwd' $DEVNULL12" <<-FIN
509 dn: uid=dummy,ou=People,$gforge_base_dn
510 objectClass: posixAccount
511 objectClass: debGforgeAccount
513 cn: Dummy User (untested)
518 loginShell: /bin/false
521 # echo "Changing dummy cn using SF_robot account"
522 eval "ldapmodify -v -c -D '$robot_dn' -x -w'$robot_passwd' $DEVNULL12" <<-FIN
523 dn: uid=dummy,ou=People,$gforge_base_dn
526 cn: Dummy User (tested)
534 # echo "Modifying /etc/ldap/slapd.conf"
536 # echo "Modifying /etc/libnss-ldap.conf"
537 configure_libnss_ldap
538 # echo "Modifying /etc/nsswitch.conf"
542 # Don't try to use ldap if config file is not changed
543 if grep -q "GForge" /etc/ldap/slapd.conf ; then
546 invoke-rc.d slapd restart
547 sleep 5 # Sometimes it takes a bit of time to get out of bed
550 # echo "Setup SF_robot account"
555 echo "Not configuring until slapd is configured"
559 # Don't try to use ldap if config file is not changed
560 if grep -q "GForge" /etc/ldap/slapd.conf ; then
565 echo "Not updating until slapd is configured"
570 # echo "Purging /etc/ldap/slapd.conf"
572 # echo "Purging /etc/nsswitch.conf"
574 # echo "Purging /etc/libnss-ldap.conf"
583 # Display what is now in the database
584 ldapsearch -x -b "$slapd_base_dn" '(objectclass=*)'
589 admin_regexp=$(echo $gforge_base_dn | sed 's/, */, /g')
590 admin_regexp="^cn=admin, *$admin_regexp"
592 { # List candidates...
593 /usr/share/gforge/bin/sql2ldif.pl \
598 | grep -v "$admin_regexp"
599 /usr/share/gforge/bin/sql2ldif.pl \
603 | grep -v "^ou=People," \
604 | grep -v "^ou=Roaming," \
605 | grep -v "$admin_regexp"
606 echo cn=Replicator,$gforge_base_dn
608 } | sort -u # ...then uniquify that list
611 get_our_entries | eval "ldapdelete -D '$slapd_admin_dn' -x -w'$slapd_admin_passwd' -c $DEVNULL12" || true
615 invoke-rc.d slapd stop
616 rm -f /var/lib/ldap/*.dbb
617 invoke-rc.d slapd start
618 tmpldif=$(mktemp $tmpfile_pattern)
619 print_ldif_default $gforge_base_dn $cryptedpasswd > $tmpldif
631 cp /etc/ldap/slapd.conf /etc/ldap/slapd.conf.gforge-old
632 cp /etc/libnss-ldap.conf /etc/libnss-ldap.conf.gforge-old
633 cp /etc/nsswitch.conf.gforge /etc/nsswitch.conf.gforge-old
634 mv /etc/ldap/slapd.conf.gforge-new /etc/ldap/slapd.conf
635 mv /etc/libnss-ldap.conf.gforge-new /etc/libnss-ldap.conf
636 mv /etc/nsswitch.conf.gforge-new /etc/nsswitch.conf
641 cp /etc/ldap/slapd.conf /etc/ldap/slapd.conf.gforge-old
642 cp /etc/libnss-ldap.conf /etc/libnss-ldap.conf.gforge-old
643 cp /etc/nsswitch.conf.gforge /etc/nsswitch.conf.gforge-old
644 mv /etc/ldap/slapd.conf.gforge-new /etc/ldap/slapd.conf
645 mv /etc/libnss-ldap.conf.gforge-new /etc/libnss-ldap.conf
646 mv /etc/nsswitch.conf.gforge-new /etc/nsswitch.conf
649 echo "Usage: $0 {configure|configure-files|update|purge|purge-files|list|empty|reset|test|setup|cleanup}"