1#!/bin/sh
2#
3# ident	"%Z%%M%	%I%	%E% SMI"
4#
5# CDDL HEADER START
6#
7# The contents of this file are subject to the terms of the
8# Common Development and Distribution License (the "License").
9# You may not use this file except in compliance with the License.
10#
11# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
12# or http://www.opensolaris.org/os/licensing.
13# See the License for the specific language governing permissions
14# and limitations under the License.
15#
16# When distributing Covered Code, include this CDDL HEADER in each
17# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
18# If applicable, add the following below this CDDL HEADER, with the
19# fields enclosed by brackets "[]" replaced with your own identifying
20# information: Portions Copyright [yyyy] [name of copyright owner]
21#
22# CDDL HEADER END
23#
24#
25# idsconfig -- script to setup iDS 5.x for Native LDAP II.
26#
27# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
28# Use is subject to license terms.
29#
30
31#
32# display_msg(): Displays message corresponding to the tag passed in.
33#
34display_msg()
35{
36    case "$1" in
37    usage) cat <<EOF
38 $PROG: [ -v ] [ -i input file ] [ -o output file ]
39   i <input file>     Get setup info from input file.
40   o <output file>    Generate a server configuration output file.
41   v                  Verbose mode
42EOF
43    ;;
44    backup_server) cat <<EOF
45It is strongly recommended that you BACKUP the directory server
46before running $PROG.
47
48Hit Ctrl-C at any time before the final confirmation to exit.
49
50EOF
51    ;;
52    setup_complete) cat <<EOF
53
54$PROG: Setup of iDS server ${IDS_SERVER} is complete.
55
56EOF
57    ;;
58    display_vlv_list) cat <<EOF
59
60Note: idsconfig has created entries for VLV indexes.  Use the 
61      directoryserver(1m) script on ${IDS_SERVER} to stop
62      the server and then enter the following vlvindex
63      sub-commands to create the actual VLV indexes:
64
65EOF
66    ;;
67    cred_level_menu) cat <<EOF
68The following are the supported credential levels:
69  1  anonymous
70  2  proxy
71  3  proxy anonymous
72EOF
73    ;;
74    auth_method_menu) cat <<EOF
75The following are the supported Authentication Methods:
76  1  none
77  2  simple
78  3  sasl/DIGEST-MD5
79  4  tls:simple
80  5  tls:sasl/DIGEST-MD5
81EOF
82    ;;
83    srvauth_method_menu) cat <<EOF
84The following are the supported Authentication Methods:
85  1  simple
86  2  sasl/DIGEST-MD5
87  3  tls:simple
88  4  tls:sasl/DIGEST-MD5
89EOF
90    ;;
91    prompt_ssd_menu) cat <<EOF
92  A  Add a Service Search Descriptor
93  D  Delete a SSD
94  M  Modify a SSD
95  P  Display all SSD's
96  H  Help
97  X  Clear all SSD's
98
99  Q  Exit menu
100EOF
101    ;;
102    summary_menu)
103
104	SUFFIX_INFO=
105	DB_INFO=
106
107	[ -n "${NEED_CREATE_SUFFIX}" ] &&
108	{
109		SUFFIX_INFO=`cat <<EOF
110
111         Suffix to create          : $LDAP_SUFFIX
112EOF
113`
114		[ -n "${NEED_CREATE_BACKEND}" ] &&
115			DB_INFO=`cat <<EOF
116
117         Database to create        : $IDS_DATABASE
118EOF
119`
120	}
121
122	cat <<EOF
123              Summary of Configuration
124
125  1  Domain to serve               : $LDAP_DOMAIN
126  2  Base DN to setup              : $LDAP_BASEDN$SUFFIX_INFO$DB_INFO
127  3  Profile name to create        : $LDAP_PROFILE_NAME
128  4  Default Server List           : $LDAP_SERVER_LIST
129  5  Preferred Server List         : $LDAP_PREF_SRVLIST
130  6  Default Search Scope          : $LDAP_SEARCH_SCOPE
131  7  Credential Level              : $LDAP_CRED_LEVEL
132  8  Authentication Method         : $LDAP_AUTHMETHOD
133  9  Enable Follow Referrals       : $LDAP_FOLLOWREF
134 10  iDS Time Limit                : $IDS_TIMELIMIT
135 11  iDS Size Limit                : $IDS_SIZELIMIT
136 12  Enable crypt password storage : $NEED_CRYPT
137 13  Service Auth Method pam_ldap  : $LDAP_SRV_AUTHMETHOD_PAM
138 14  Service Auth Method keyserv   : $LDAP_SRV_AUTHMETHOD_KEY
139 15  Service Auth Method passwd-cmd: $LDAP_SRV_AUTHMETHOD_CMD
140 16  Search Time Limit             : $LDAP_SEARCH_TIME_LIMIT
141 17  Profile Time to Live          : $LDAP_PROFILE_TTL
142 18  Bind Limit                    : $LDAP_BIND_LIMIT
143 19  Service Search Descriptors Menu
144
145EOF
146    ;;
147    sfx_not_suitable) cat <<EOF
148
149Sorry, suffix ${LDAP_SUFFIX} is not suitable for Base DN ${LDAP_BASEDN}
150
151EOF
152    ;;
153    obj_not_found) cat <<EOF
154
155Sorry, ${PROG} can't find an objectclass for "$_ATT" attribute
156
157EOF
158    ;;
159    sfx_config_incons) cat <<EOF
160
161Sorry, there is no suffix mapping for ${LDAP_SUFFIX},
162while ldbm database exists, server configuration needs to be fixed manually,
163look at cn=mapping tree,cn=config and cn=ldbm database,cn=plugins,cn=config
164
165EOF
166    ;;
167    ldbm_db_exist) cat <<EOF
168
169Database "${IDS_DATABASE}" already exists,
170however "${IDS_DATABASE_AVAIL}" name is available
171
172EOF
173    ;;
174    unable_find_db_name) cat <<EOF
175    
176Unable to find any available database name close to "${IDS_DATABASE}"
177
178EOF
179    ;;
180    create_ldbm_db_error) cat <<EOF
181
182ERROR: unable to create suffix ${LDAP_SUFFIX}
183       due to server error that occurred during creation of ldbm database
184
185EOF
186    ;;
187    create_suffix_entry_error) cat <<EOF
188
189ERROR: unable to create entry ${LDAP_SUFFIX} of ${LDAP_SUFFIX_OBJ} class
190
191EOF
192    ;;
193    ldap_suffix_list) cat <<EOF
194
195No valid suffixes (naming contexts) were found for LDAP base DN:
196${LDAP_BASEDN}
197
198Available suffixes are:
199${LDAP_SUFFIX_LIST}
200
201EOF
202    ;;
203    sorry) cat <<EOF
204
205HELP - No help is available for this topic.
206
207EOF
208    ;;
209    create_suffix_help) cat <<EOF
210
211HELP - Our Base DN is ${LDAP_BASEDN}
212       and we need to create a Directory Suffix,
213       which can be equal to Base DN itself or be any of Base DN parents.
214       All intermediate entries up to suffix will be created on demand.
215
216EOF
217    ;;
218    enter_ldbm_db_help) cat <<EOF
219
220HELP - ldbm database is an internal database for storage of our suffix data.
221       Database name must be alphanumeric due to Directory Server restriction.
222
223EOF
224    ;;
225    backup_help) cat <<EOF
226
227HELP - Since idsconfig modifies the directory server configuration,
228       it is strongly recommended that you backup the server prior
229       to running this utility.  This is especially true if the server
230       being configured is a production server.
231
232EOF
233    ;;
234    port_help) cat <<EOF
235
236HELP - Enter the port number the directory server is configured to
237       use for LDAP.
238
239EOF
240    ;;
241    domain_help) cat <<EOF
242
243HELP - This is the DNS domain name this server will be serving.  You
244       must provide this name even if the server is not going to be populated
245       with hostnames.  Any unqualified hostname stored in the directory
246       will be fully qualified using this DNS domain name.
247
248EOF
249    ;;
250    basedn_help) cat <<EOF
251
252HELP - This parameter defines the default location in the directory tree for
253       the naming services entries.  You can override this default by using 
254       serviceSearchDescriptors (SSD). You will be given the option to set up 
255       an SSD later on in the setup.
256
257EOF
258    ;;
259    profile_help) cat <<EOF
260
261HELP - Name of the configuration profile with which the clients will be
262       configured. A directory server can store various profiles for multiple 
263       groups of clients.  The initialization tool, (ldapclient(1M)), assumes 
264       "default" unless another is specified.
265
266EOF
267    ;;
268    def_srvlist_help) cat <<EOF
269
270HELP - Provide a list of directory servers to serve clients using this profile.
271       All these servers should contain consistent data and provide similar 
272       functionality.  This list is not ordered, and clients might change the 
273       order given in this list. Note that this is a space separated list of 
274       *IP addresses* (not host names).  Providing port numbers is optional.
275
276EOF
277    ;;
278    pref_srvlist_help) cat <<EOF
279
280HELP - Provide a list of directory servers to serve this client profile. 
281       Unlike the default server list, which is not ordered, the preferred 
282       servers must be entered IN THE ORDER you wish to have them contacted. 
283       If you do specify a preferred server list, clients will always contact 
284       them before attempting to contact any of the servers on the default 
285       server list. Note that you must enter the preferred server list as a 
286       space-separated list of *IP addresses* (not host names).  Providing port 
287       numbers is optional.
288
289EOF
290    ;;
291    srch_scope_help) cat <<EOF
292
293HELP - Default search scope to be used for all searches unless they are
294       overwritten using serviceSearchDescriptors.  The valid options
295       are "one", which would specify the search will only be performed 
296       at the base DN for the given service, or "sub", which would specify 
297       the search will be performed through *all* levels below the base DN 
298       for the given service.
299
300EOF
301    ;;
302    cred_lvl_help) cat <<EOF
303
304HELP - This parameter defines what credentials the clients use to
305       authenticate to the directory server.  This list might contain
306       multiple credential levels and is ordered.  If a proxy level
307       is configured, you will also be prompted to enter a bind DN
308       for the proxy agent along with a password.  This proxy agent
309       will be created if it does not exist.
310
311EOF
312    ;;
313    auth_help) cat <<EOF
314
315HELP - The default authentication method(s) to be used by all services
316       in the client using this profile.  This is a ordered list of
317       authentication methods separated by a ';'.  The supported methods
318       are provided in a menu.  Note that sasl/DIGEST-MD5 binds require
319       passwords to be stored un-encrypted on the server.
320
321EOF
322    ;;
323    srvauth_help) cat <<EOF
324
325HELP - The authentication methods to be used by a given service.  Currently
326       3 services support this feature: pam_ldap, keyserv, and passwd-cmd.
327       The authentication method specified in this attribute overrides
328       the default authentication method defined in the profile.  This
329       feature can be used to select stronger authentication methods for
330       services which require increased security.
331
332EOF
333    ;;
334    pam_ldap_help) cat <<EOF
335
336HELP - The authentication method(s) to be used by pam_ldap when contacting
337       the directory server.  This is a ordered list, and, if provided, will
338       override the default authentication method parameter.
339
340EOF
341    ;;
342    keyserv_help) cat <<EOF
343
344HELP - The authentication method(s) to be used by newkey(1M) and chkey(1)
345       when contacting the directory server.  This is a ordered list and
346       if provided will override the default authentication method
347       parameter.
348
349EOF
350    ;;
351    passwd-cmd_help) cat <<EOF
352
353HELP - The authentication method(s) to be used by passwd(1) command when
354       contacting the directory server.  This is a ordered list and if
355       provided will override the default authentication method parameter.
356
357EOF
358    ;;
359    referrals_help) cat <<EOF
360
361HELP - This parameter indicates whether the client should follow
362       ldap referrals if it encounters one during naming lookups.
363
364EOF
365    ;;
366    tlim_help) cat <<EOF
367
368HELP - The server time limit value indicates the maximum amount of time the
369       server would spend on a query from the client before abandoning it.
370       A value of '-1' indicates no limit.
371
372EOF
373    ;;
374    slim_help) cat <<EOF
375
376HELP - The server sizelimit value indicates the maximum number of entries
377       the server would return in respond to a query from the client.  A
378       value of '-1' indicates no limit.
379
380EOF
381    ;;
382    crypt_help) cat <<EOF
383
384HELP - By default iDS does not store userPassword attribute values using
385       unix "crypt" format.  If you need to keep your passwords in the crypt
386       format for NIS/NIS+ and pam_unix compatibility, choose 'yes'.  If
387       passwords are stored using any other format than crypt, pam_ldap
388       MUST be used by clients to authenticate users to the system. Note 
389       that if you wish to use sasl/DIGEST-MD5 in conjunction with pam_ldap,
390       user passwords must be stored in the clear format.
391
392EOF
393    ;;
394    srchtime_help) cat <<EOF
395
396HELP - The search time limit the client will enforce for directory
397       lookups.
398
399EOF
400    ;;
401    profttl_help) cat <<EOF
402
403HELP - The time to live value for profile.  The client will refresh its
404       cached version of the configuration profile at this TTL interval.
405
406EOF
407    ;;
408    bindlim_help) cat <<EOF
409
410HELP - The time limit for the bind operation to the directory.  This
411       value controls the responsiveness of the client in case a server
412       becomes unavailable.  The smallest timeout value for a given
413       network architecture/conditions would work best.  This is very
414       similar to setting TCP timeout, but only for LDAP bind operation.
415
416EOF
417    ;;
418    ssd_help) cat <<EOF
419
420HELP - Using Service Search Descriptors (SSD), you can override the
421       default configuration for a given service.  The SSD can be
422       used to override the default search base DN, the default search
423       scope, and the default search filter to be used for directory
424       lookups.  SSD are supported for all services (databases)
425       defined in nsswitch.conf(4).  The default base DN is defined
426       in ldap(1).
427
428       Note: SSD are powerful tools in defining configuration profiles
429             and provide a great deal of flexibility.  However, care
430             must be taken in creating them.  If you decide to make use
431             of SSDs, consult the documentation first.
432
433EOF
434    ;;
435    ssd_menu_help) cat <<EOF
436
437HELP - Using this menu SSD can be added, updated, or deleted from
438       the profile.
439
440       A - This option creates a new SSD by prompting for the
441           service name, base DN, and scope.  Service name is
442           any valid service as defined in ldap(1).  base is
443           either the distinguished name to the container where
444           this service will use, or a relative DN followed
445           by a ','.
446       D - Delete a previously created SSD.
447       M - Modify a previously created SSD.
448       P - Display a list of all the previously created SSD.
449       X - Delete all of the previously created SSD.
450
451       Q - Exit the menu and continue with the server configuration.
452
453EOF
454    ;;
455    ldap_suffix_list_help) cat <<EOF
456
457HELP - No valid suffixes (naming contexts) are available on server 
458       ${IDS_SERVER}:${IDS_PORT}.
459       You must set an LDAP Base DN that can be contained in 
460       an existing suffix.
461
462EOF
463    ;;
464    esac
465}
466
467
468#
469# get_ans(): gets an answer from the user.
470#		$1  instruction/comment/description/question
471#		$2  default value
472#
473get_ans()
474{
475    if [ -z "$2" ]
476    then
477	${ECHO} "$1 \c"
478    else
479	${ECHO} "$1 [$2] \c"
480    fi
481
482    read ANS
483    if [ -z "$ANS" ]
484    then
485	ANS=$2
486    fi
487}
488
489
490#
491# get_ans_req(): gets an answer (required) from the user, NULL value not allowed.
492#		$@  instruction/comment/description/question
493#
494get_ans_req()
495{
496    ANS=""                  # Set ANS to NULL.
497    while [ "$ANS" = "" ]
498    do
499	get_ans "$@"
500	[ "$ANS" = "" ] && ${ECHO} "NULL value not allowed!"
501    done
502}
503
504
505#
506# get_number(): Querys and verifies that number entered is numeric.
507#               Function will repeat prompt user for number value.
508#               $1  Message text.
509#		$2  default value.
510#               $3  Help argument.
511#
512get_number()
513{
514    ANS=""                  # Set ANS to NULL.
515    NUM=""
516
517    get_ans "$1" "$2"
518
519    # Verify that value is numeric.
520    while not_numeric $ANS
521    do
522	case "$ANS" in
523	    [Hh] | help | Help | \?) display_msg ${3:-sorry} ;;
524	    * ) ${ECHO} "Invalid value: \"${ANS}\". \c"
525	     ;;
526	esac
527	# Get a new value.
528	get_ans "Enter a numeric value:" "$2"
529    done
530    NUM=$ANS
531}
532
533
534#
535# get_negone_num(): Only allows a -1 or positive integer.
536#                   Used for values where -1 has special meaning.
537#
538#                   $1 - Prompt message.
539#                   $2 - Default value (require).
540#                   $3 - Optional help argument.
541get_negone_num()
542{
543    while :
544    do
545	get_number "$1" "$2" "$3"
546	if is_negative $ANS
547	then
548	    if [ "$ANS" = "-1" ]; then
549		break  # -1 is OK, so break.
550	    else       # Need to re-enter number.
551		${ECHO} "Invalid number: please enter -1 or positive number."
552	    fi
553	else
554	    break      # Positive number
555	fi
556    done
557}
558
559
560#
561# get_passwd(): Reads a password from the user and verify with second.
562#		$@  instruction/comment/description/question
563#
564get_passwd()
565{
566    [ $DEBUG -eq 1 ] && ${ECHO} "In get_passwd()"
567
568    # Temporary PASSWD variables
569    _PASS1=""
570    _PASS2=""
571
572    /usr/bin/stty -echo     # Turn echo OFF
573
574    # Endless loop that continues until passwd and re-entered passwd
575    # match.
576    while :
577    do
578	ANS=""                  # Set ANS to NULL.
579
580	# Don't allow NULL for first try.
581	while [ "$ANS" = "" ]
582	do
583	    get_ans "$@"
584	    [ "$ANS" = "" ] && ${ECHO} "" && ${ECHO} "NULL passwd not allowed!"
585	done
586	_PASS1=$ANS         # Store first try.
587
588	# Get second try.
589	${ECHO} ""
590	get_ans "Re-enter passwd:"
591	_PASS2=$ANS
592
593	# Test if passwords are identical.
594	if [ "$_PASS1" = "$_PASS2" ]; then
595	    break
596	fi
597
598	# Move cursor down to next line and print ERROR message.
599	${ECHO} ""
600	${ECHO} "ERROR: passwords don't match; try again."
601    done
602
603    /usr/bin/stty echo      # Turn echo ON
604
605    ${ECHO} ""
606}
607
608
609#
610# get_passwd_nochk(): Reads a password from the user w/o check.
611#		$@  instruction/comment/description/question
612#
613get_passwd_nochk()
614{
615    [ $DEBUG -eq 1 ] && ${ECHO} "In get_passwd_nochk()"
616
617    /usr/bin/stty -echo     # Turn echo OFF
618
619    get_ans "$@"
620
621    /usr/bin/stty echo      # Turn echo ON
622
623    ${ECHO} ""
624}
625
626
627#
628# get_menu_choice(): Get a menu choice from user.  Continue prompting
629#                    till the choice is in required range.
630#   $1 .. Message text.
631#   $2 .. min value
632#   $3 .. max value
633#   $4 .. OPTIONAL: default value
634#
635#   Return value:
636#     MN_CH will contain the value selected.
637#
638get_menu_choice()
639{
640    # Check for req parameter.
641    if [ $# -lt 3 ]; then
642	${ECHO} "get_menu_choice(): Did not get required parameters."
643	return 1
644    fi
645
646    while :
647    do
648	get_ans "$1" "$4"
649	MN_CH=$ANS
650	is_negative $MN_CH
651	if [ $? -eq 1 ]; then
652	    if [ $MN_CH -ge $2 ]; then
653		if [ $MN_CH -le $3 ]; then
654		    return
655		fi
656	    fi
657	fi
658	${ECHO} "Invalid choice: $MN_CH"
659    done
660}
661
662
663#
664# get_confirm(): Get confirmation from the user. (Y/Yes or N/No)
665#                $1 - Message
666#                $2 - default value.
667#
668get_confirm()
669{
670    _ANSWER=
671
672    while :
673    do
674	# Display Internal ERROR if $2 not set.
675	if [ -z "$2" ]
676	then
677	    ${ECHO} "INTERNAL ERROR: get_confirm requires 2 args, 3rd is optional."
678	    exit 2
679	fi
680
681	# Display prompt.
682	${ECHO} "$1 [$2] \c"
683
684	# Get the ANSWER.
685	read _ANSWER
686	if [ "$_ANSWER" = "" ] && [ -n "$2" ] ; then
687	    _ANSWER=$2
688	fi
689	case "$_ANSWER" in
690	    [Yy] | yes | Yes | YES) return 1 ;;
691	    [Nn] | no  | No  | NO)  return 0 ;;
692	    [Hh] | help | Help | \?) display_msg ${3:-sorry};;
693	    * ) ${ECHO} "Please enter y or n."  ;;
694	esac
695    done
696}
697
698
699#
700# get_confirm_nodef(): Get confirmation from the user. (Y/Yes or N/No)
701#                      No default value supported.
702#
703get_confirm_nodef()
704{
705    _ANSWER=
706
707    while :
708    do
709	${ECHO} "$@ \c"
710	read _ANSWER
711	case "$_ANSWER" in
712	    [Yy] | yes | Yes | YES) return 1 ;;
713	    [Nn] | no  | No  | NO)  return 0 ;;
714	    * ) ${ECHO} "Please enter y or n."  ;;
715	esac
716    done
717}
718
719
720#
721# is_numeric(): Tells is a string is numeric.
722#    0 = Numeric
723#    1 = NOT Numeric
724#
725is_numeric()
726{
727    # Check for parameter.
728    if [ $# -ne 1 ]; then
729	return 1
730    fi
731
732    # Determine if numeric.
733    expr "$1" + 1 > /dev/null 2>&1
734    if [ $? -ge 2 ]; then
735	return 1
736    fi
737
738    # Made it here, it's Numeric.
739    return 0
740}
741
742
743#
744# not_numeric(): Reverses the return values of is_numeric.  Useful
745#                 for if and while statements that want to test for
746#                 non-numeric data.
747#    0 = NOT Numeric
748#    1 = Numeric
749#
750not_numeric()
751{
752    is_numeric $1
753    if [ $? -eq 0 ]; then
754       return 1
755    else
756       return 0
757    fi
758}
759
760
761#
762# is_negative(): Tells is a Numeric value is less than zero.
763#    0 = Negative Numeric
764#    1 = Positive Numeric
765#    2 = NOT Numeric
766#
767is_negative()
768{
769    # Check for parameter.
770    if [ $# -ne 1 ]; then
771	return 1
772    fi
773
774    # Determine if numeric.  Can't use expr because -0 is
775    # considered positive??
776    if is_numeric $1; then
777	case "$1" in
778	    -*)  return 0 ;;   # Negative Numeric
779	    *)   return 1 ;;   # Positive Numeric
780	esac
781    else
782	return 2
783    fi
784}
785
786
787#
788# check_domainname(): check validity of a domain name.  Currently we check
789#                     that it has at least two components.
790#		$1  the domain name to be checked
791#
792check_domainname()
793{
794    if [ ! -z "$1" ]
795    then
796	t=`expr "$1" : '[^.]\{1,\}[.][^.]\{1,\}'`
797	if [ "$t" = 0 ]
798	then
799	    return 1
800	fi
801    fi
802    return 0
803}
804
805
806#
807# check_baseDN(): check validity of the baseDN name.
808#		$1  the baseDN name to be checked
809#
810#     NOTE: The check_baseDN function does not catch all invalid DN's.
811#           Its purpose is to reduce the number of invalid DN's to
812#           get past the input routine.  The invalid DN's will be
813#           caught by the LDAP server when they are attempted to be
814#           created.
815#
816check_baseDN()
817{
818    ck_DN=$1
819    ${ECHO} "  Checking LDAP Base DN ..."
820    if [ ! -z "$ck_DN" ]; then
821        [ $DEBUG -eq 1 ] && ${ECHO} "Checking baseDN: $ck_DN"
822        # Check for = (assignment operator)
823        ${ECHO} "$ck_DN" | ${GREP} "=" > /dev/null 2>&1
824        if [ $? -ne 0 ]; then
825            [ $DEBUG -eq 1 ] && ${ECHO} "check_baseDN: No '=' in baseDN."
826            return 1
827        fi
828
829        # Check all keys.
830        while :
831        do
832            # Get first key.
833            dkey=`${ECHO} $ck_DN | cut -d'=' -f1`
834
835            # Check that the key string is valid
836	    check_attrName $dkey
837	    if [ $? -ne 0 ]; then
838                [ $DEBUG -eq 1 ] && ${ECHO} "check_baseDN: invalid key=${dkey}"
839                return 1
840            fi
841
842            [ $DEBUG -eq 1 ] && ${ECHO} "check_baseDN: valid key=${dkey}"
843
844            # Remove first key from DN
845            ck_DN=`${ECHO} $ck_DN | cut -s -d',' -f2-`
846
847            # Break loop if nothing left.
848            if [ "$ck_DN" = "" ]; then
849                break
850            fi
851        done
852    fi
853    return 0
854}
855
856
857#
858# domain_2_dc(): Convert a domain name into dc string.
859#    $1  .. Domain name.
860#
861domain_2_dc()
862{
863    _DOM=$1           # Domain parameter.
864    _DOM_2_DC=""      # Return value from function.
865    _FIRST=1          # Flag for first time.
866
867    export _DOM_2_DC  # Make visible for others.
868
869    # Convert "."'s to spaces for "for" loop.
870    domtmp="`${ECHO} ${_DOM} | tr '.' ' '`"
871    for i in $domtmp; do
872	if [ $_FIRST -eq 1 ]; then
873	    _DOM_2_DC="dc=${i}"
874	    _FIRST=0
875	else
876	    _DOM_2_DC="${_DOM_2_DC},dc=${i}"
877	fi
878    done
879}
880
881
882#
883# is_root_user(): Check to see if logged in as root user.
884#
885is_root_user()
886{
887    case `id` in
888	uid=0\(root\)*) return 0 ;;
889	* )             return 1 ;;
890    esac
891}
892
893
894#
895# parse_arg(): Parses the command line arguments and sets the
896#              appropriate variables.
897#
898parse_arg()
899{
900    while getopts "dvhi:o:" ARG
901    do
902	case $ARG in
903	    d)      DEBUG=1;;
904	    v)      VERB="";;
905	    i)      INPUT_FILE=$OPTARG;;
906	    o)      OUTPUT_FILE=$OPTARG;;
907	    \?)	display_msg usage
908		    exit 1;;
909	    *)	${ECHO} "**ERROR: Supported option missing handler!"
910		    display_msg usage
911		    exit 1;;
912	esac
913    done
914    return `expr $OPTIND - 1`
915}
916
917
918#
919# init(): initializes variables and options
920#
921init()
922{
923    # General variables.
924    PROG=`basename $0`	# Program name
925    PID=$$              # Program ID
926    VERB='> /dev/null 2>&1'	# NULL or "> /dev/null"
927    ECHO="/bin/echo"	# print message on screen
928    EVAL="eval"		# eval or echo
929    EGREP="/usr/bin/egrep"
930    GREP="/usr/bin/grep"
931    DEBUG=0             # Set Debug OFF
932    BACKUP=no_ldap	# backup suffix
933    HOST=""		# NULL or <hostname>
934
935    DOM=""              # Set to NULL
936    # If DNS domain (resolv.conf) exists use that, otherwise use domainname.
937    if [ -f /etc/resolv.conf ]; then
938        DOM=`/usr/xpg4/bin/grep -i -E '^domain|^search' /etc/resolv.conf \
939	    | awk '{ print $2 }' | tail -1`
940    fi
941
942    # If for any reason the DOM did not get set (error'd resolv.conf) set
943    # DOM to the domainname command's output.
944    if [ "$DOM" = "" ]; then
945        DOM=`domainname`	# domain from domainname command.
946    fi
947
948    STEP=1
949    INTERACTIVE=1       # 0 = on, 1 = off (For input file mode)
950    DEL_OLD_PROFILE=0   # 0 (default), 1 = delete old profile.
951
952    # idsconfig specific variables.
953    INPUT_FILE=""
954    OUTPUT_FILE=""
955    NEED_PROXY=0        # 0 = No Proxy, 1 = Create Proxy.
956    LDAP_PROXYAGENT=""
957    LDAP_SUFFIX=""
958    LDAP_DOMAIN=$DOM	# domainname on Server (default value)
959    GEN_CMD=""
960
961    # LDAP COMMANDS
962    LDAPSEARCH="/bin/ldapsearch -r"
963    LDAPMODIFY=/bin/ldapmodify
964    LDAPADD=/bin/ldapadd
965    LDAPDELETE=/bin/ldapdelete
966    LDAP_GEN_PROFILE=/usr/sbin/ldap_gen_profile
967
968    # iDS specific information
969    IDS_SERVER=""
970    IDS_PORT=389
971    NEED_TIME=0
972    NEED_SIZE=0
973    NEED_SRVAUTH_PAM=0
974    NEED_SRVAUTH_KEY=0
975    NEED_SRVAUTH_CMD=0
976    IDS_TIMELIMIT=""
977    IDS_SIZELIMIT=""
978
979    # LDAP PROFILE related defaults
980    LDAP_ROOTDN="cn=Directory Manager"   # Provide common default.
981    LDAP_ROOTPWD=""                      # NULL passwd as default (i.e. invalid)
982    LDAP_PROFILE_NAME="default"
983    LDAP_BASEDN=""
984    LDAP_SERVER_LIST=""
985    LDAP_AUTHMETHOD=""
986    LDAP_FOLLOWREF="FALSE"
987    NEED_CRYPT=""
988    LDAP_SEARCH_SCOPE="one"
989    LDAP_SRV_AUTHMETHOD_PAM=""
990    LDAP_SRV_AUTHMETHOD_KEY=""
991    LDAP_SRV_AUTHMETHOD_CMD=""
992    LDAP_SEARCH_TIME_LIMIT=30
993    LDAP_PREF_SRVLIST=""
994    LDAP_PROFILE_TTL=43200
995    LDAP_CRED_LEVEL="proxy"
996    LDAP_BIND_LIMIT=10
997
998    # Prevent new files from being read by group or others.
999    umask 077
1000
1001    # Service Search Descriptors
1002    LDAP_SERV_SRCH_DES=""
1003
1004    # Set and create TMPDIR.
1005    TMPDIR="/tmp/idsconfig.${PID}"
1006    if mkdir -m 700 ${TMPDIR}
1007    then
1008	# Cleanup on exit.
1009	trap 'rm -rf ${TMPDIR}; /usr/bin/stty echo; exit' 1 2 3 6 15
1010    else
1011	echo "ERROR: unable to create a safe temporary directory."
1012	exit 1
1013    fi
1014    LDAP_ROOTPWF=${TMPDIR}/rootPWD
1015
1016    # Set the SSD file name after setting TMPDIR.
1017    SSD_FILE=${TMPDIR}/ssd_list
1018
1019    export DEBUG VERB ECHO EVAL EGREP GREP STEP TMPDIR
1020    export IDS_SERVER IDS_PORT LDAP_ROOTDN LDAP_ROOTPWD LDAP_SERVER_LIST
1021    export LDAP_BASEDN LDAP_ROOTPWF
1022    export LDAP_DOMAIN LDAP_SUFFIX LDAP_PROXYAGENT LDAP_PROXYAGENT_CRED
1023    export NEED_PROXY
1024    export LDAP_PROFILE_NAME LDAP_BASEDN LDAP_SERVER_LIST
1025    export LDAP_AUTHMETHOD LDAP_FOLLOWREF LDAP_SEARCH_SCOPE LDAP_SEARCH_TIME_LIMIT
1026    export LDAP_PREF_SRVLIST LDAP_PROFILE_TTL LDAP_CRED_LEVEL LDAP_BIND_LIMIT
1027    export NEED_SRVAUTH_PAM NEED_SRVAUTH_KEY NEED_SRVAUTH_CMD
1028    export LDAP_SRV_AUTHMETHOD_PAM LDAP_SRV_AUTHMETHOD_KEY LDAP_SRV_AUTHMETHOD_CMD
1029    export LDAP_SERV_SRCH_DES SSD_FILE
1030    export GEN_CMD
1031}
1032
1033
1034#
1035# disp_full_debug(): List of all debug variables usually interested in.
1036#                    Grouped to avoid MASSIVE code duplication.
1037#
1038disp_full_debug()
1039{
1040    [ $DEBUG -eq 1 ] && ${ECHO} "  IDS_SERVER = $IDS_SERVER"
1041    [ $DEBUG -eq 1 ] && ${ECHO} "  IDS_PORT = $IDS_PORT"
1042    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_ROOTDN = $LDAP_ROOTDN"
1043    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_ROOTPWD = $LDAP_ROOTPWD"
1044    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_DOMAIN = $LDAP_DOMAIN"
1045    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_SUFFIX = $LDAP_SUFFIX"
1046    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_BASEDN = $LDAP_BASEDN"
1047    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_PROFILE_NAME = $LDAP_PROFILE_NAME"
1048    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_SERVER_LIST = $LDAP_SERVER_LIST"
1049    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_PREF_SRVLIST = $LDAP_PREF_SRVLIST"
1050    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_SEARCH_SCOPE = $LDAP_SEARCH_SCOPE"
1051    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_CRED_LEVEL = $LDAP_CRED_LEVEL"
1052    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_AUTHMETHOD = $LDAP_AUTHMETHOD"
1053    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_FOLLOWREF = $LDAP_FOLLOWREF"
1054    [ $DEBUG -eq 1 ] && ${ECHO} "  IDS_TIMELIMIT = $IDS_TIMELIMIT"
1055    [ $DEBUG -eq 1 ] && ${ECHO} "  IDS_SIZELIMIT = $IDS_SIZELIMIT"
1056    [ $DEBUG -eq 1 ] && ${ECHO} "  NEED_CRYPT = $NEED_CRYPT"
1057    [ $DEBUG -eq 1 ] && ${ECHO} "  NEED_SRVAUTH_PAM = $NEED_SRVAUTH_PAM"
1058    [ $DEBUG -eq 1 ] && ${ECHO} "  NEED_SRVAUTH_KEY = $NEED_SRVAUTH_KEY"
1059    [ $DEBUG -eq 1 ] && ${ECHO} "  NEED_SRVAUTH_CMD = $NEED_SRVAUTH_CMD"
1060    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_SRV_AUTHMETHOD_PAM = $LDAP_SRV_AUTHMETHOD_PAM"
1061    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_SRV_AUTHMETHOD_KEY = $LDAP_SRV_AUTHMETHOD_KEY"
1062    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_SRV_AUTHMETHOD_CMD = $LDAP_SRV_AUTHMETHOD_CMD"
1063    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_SEARCH_TIME_LIMIT = $LDAP_SEARCH_TIME_LIMIT"
1064    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_PROFILE_TTL = $LDAP_PROFILE_TTL"
1065    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_BIND_LIMIT = $LDAP_BIND_LIMIT"
1066
1067    # Only display proxy stuff if needed.
1068    if [ $NEED_PROXY -eq  1 ]; then
1069	[ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_PROXYAGENT = $LDAP_PROXYAGENT"
1070	[ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_PROXYAGENT_CRED = $LDAP_PROXYAGENT_CRED"
1071	[ $DEBUG -eq 1 ] && ${ECHO} "  NEED_PROXY = $NEED_PROXY"
1072    fi
1073
1074    # Service Search Descriptors are a special case.
1075    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_SERV_SRCH_DES = $LDAP_SERV_SRCH_DES"
1076}
1077
1078
1079#
1080# load_config_file(): Loads the config file.
1081#
1082load_config_file()
1083{
1084    [ $DEBUG -eq 1 ] && ${ECHO} "In load_config_file()"
1085
1086    # Remove SSD lines from input file before sourcing.
1087    # The SSD lines must be removed because some forms of the
1088    # data could cause SHELL errors.
1089    ${GREP} -v "LDAP_SERV_SRCH_DES=" ${INPUT_FILE} > ${TMPDIR}/inputfile.noSSD
1090
1091    # Source the input file.
1092    . ${TMPDIR}/inputfile.noSSD
1093
1094    # If LDAP_SUFFIX is no set, try to utilize LDAP_TREETOP since older
1095    # config files use LDAP_TREETOP
1096    LDAP_SUFFIX="${LDAP_SUFFIX:-$LDAP_TREETOP}"
1097
1098    # Save password to temporary file.
1099    save_password
1100
1101    # Create the SSD file.
1102    create_ssd_file
1103
1104    # Display FULL debugging info.
1105    disp_full_debug
1106}
1107
1108#
1109# save_password(): Save password to temporary file.
1110#
1111save_password()
1112{
1113    cat > ${LDAP_ROOTPWF} <<EOF
1114${LDAP_ROOTPWD}
1115EOF
1116}
1117
1118######################################################################
1119# FUNCTIONS  FOR prompt_config_info() START HERE.
1120######################################################################
1121
1122#
1123# get_ids_server(): Prompt for iDS server name.
1124#
1125get_ids_server()
1126{
1127    while :
1128    do
1129	# Prompt for server name.
1130	get_ans "Enter the iPlanet Directory Server's (iDS) hostname to setup:" "$IDS_SERVER"
1131	IDS_SERVER=$ANS
1132
1133	# Ping server to see if live.  If valid break out of loop.
1134	ping $IDS_SERVER > /dev/null 2>&1
1135	if [ $? -eq 0 ]; then
1136	    break
1137	fi
1138
1139	# Invalid server, enter a new name.
1140	${ECHO} "ERROR: Server '${IDS_SERVER}' is invalid or unreachable."
1141	IDS_SERVER=""
1142    done
1143
1144    # Set SERVER_ARGS and LDAP_ARGS since values might of changed.
1145    SERVER_ARGS="-h ${IDS_SERVER} -p ${IDS_PORT}"
1146    LDAP_ARGS="${SERVER_ARGS} ${AUTH_ARGS}"
1147    export SERVER_ARGS
1148
1149}
1150
1151#
1152# get_ids_port(): Prompt for iDS port number.
1153#
1154get_ids_port()
1155{
1156    # Get a valid iDS port number.
1157    while :
1158    do
1159	# Enter port number.
1160	get_number "Enter the port number for iDS (h=help):" "$IDS_PORT" "port_help"
1161	IDS_PORT=$ANS
1162
1163	# Do a simple search to check hostname and port number.
1164	# If search returns SUCCESS, break out, host and port must
1165	# be valid.
1166	${LDAPSEARCH} -h ${IDS_SERVER} -p ${IDS_PORT} -b "" -s base "objectclass=*" > /dev/null 2>&1
1167	if [ $? -eq 0 ]; then
1168	    break
1169	fi
1170
1171	# Invalid host/port pair, Re-enter.
1172	${ECHO} "ERROR: Invalid host or port: ${IDS_SERVER}:${IDS_PORT}, Please re-enter!"
1173	get_ids_server
1174    done
1175
1176    # Set SERVER_ARGS and LDAP_ARGS since values might of changed.
1177    SERVER_ARGS="-h ${IDS_SERVER} -p ${IDS_PORT}"
1178    LDAP_ARGS="${SERVER_ARGS} ${AUTH_ARGS}"
1179    export SERVER_ARGS
1180}
1181
1182
1183#
1184# chk_ids_version(): Read the slapd config file and set variables
1185#
1186chk_ids_version()
1187{
1188    [ $DEBUG -eq 1 ] && ${ECHO} "In chk_ids_version()"
1189
1190    # check iDS version number.
1191    eval "${LDAPSEARCH} ${SERVER_ARGS} -b cn=monitor -s base \"objectclass=*\" version | ${GREP} \"^version=\" | cut -f2 -d'/' | cut -f1 -d' ' > ${TMPDIR}/checkDSver 2>&1"
1192    if [ $? -ne 0 ]; then
1193	${ECHO} "ERROR: Can not determine the version number of iDS!"
1194	exit 1
1195    fi
1196    IDS_VER=`cat ${TMPDIR}/checkDSver`
1197    IDS_MAJVER=`${ECHO} ${IDS_VER} | cut -f1 -d.`
1198    IDS_MINVER=`${ECHO} ${IDS_VER} | cut -f2 -d.`
1199    if [ "${IDS_MAJVER}" != "5" ]; then
1200	${ECHO} "ERROR: $PROG only works with iDS version 5.x, not ${IDS_VER}."
1201    	exit 1
1202    fi
1203    if [ $DEBUG -eq 1 ]; then
1204	${ECHO} "  IDS_MAJVER = $IDS_MAJVER"
1205	${ECHO} "  IDS_MINVER = $IDS_MINVER"
1206    fi
1207}
1208
1209
1210#
1211# get_dirmgr_dn(): Get the directory manger DN.
1212#
1213get_dirmgr_dn()
1214{
1215    get_ans "Enter the directory manager DN:" "$LDAP_ROOTDN"
1216    LDAP_ROOTDN=$ANS
1217
1218    # Update ENV variables using DN.
1219    AUTH_ARGS="-D \"${LDAP_ROOTDN}\" -j ${LDAP_ROOTPWF}"
1220    LDAP_ARGS="${SERVER_ARGS} ${AUTH_ARGS}"
1221    export AUTH_ARGS LDAP_ARGS
1222}
1223
1224
1225#
1226# get_dirmgr_pw(): Get the Root DN passwd. (Root DN found in slapd.conf)
1227#
1228get_dirmgr_pw()
1229{
1230    while :
1231    do
1232	# Get passwd.
1233	get_passwd_nochk "Enter passwd for ${LDAP_ROOTDN} :"
1234	LDAP_ROOTPWD=$ANS
1235
1236	# Store password in file.
1237	save_password
1238
1239	# Update ENV variables using DN's PW.
1240	AUTH_ARGS="-D \"${LDAP_ROOTDN}\" -j ${LDAP_ROOTPWF}"
1241	LDAP_ARGS="${SERVER_ARGS} ${AUTH_ARGS}"
1242	export AUTH_ARGS LDAP_ARGS
1243
1244	# Verify that ROOTDN and ROOTPWD are valid.
1245	eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"\" -s base \"objectclass=*\" > ${TMPDIR}/checkDN 2>&1"
1246	if [ $? -ne 0 ]; then
1247	    eval "${GREP} credential ${TMPDIR}/checkDN ${VERB}"
1248	    if [ $? -eq 0 ]; then
1249		${ECHO} "ERROR: Root DN passwd is invalid."
1250	    else
1251		${ECHO} "ERROR: Invalid Root DN <${LDAP_ROOTDN}>."
1252		get_dirmgr_dn
1253	    fi
1254	else
1255	    break         # Both are valid.
1256	fi
1257    done
1258
1259
1260}
1261
1262
1263#
1264# get_domain(): Get the Domain that will be served by the LDAP server.
1265#               $1 - Help argument.
1266#
1267get_domain()
1268{
1269    # Use LDAP_DOMAIN as default.
1270    get_ans "Enter the domainname to be served (h=help):" $LDAP_DOMAIN
1271
1272    # Check domainname, and have user re-enter if not valid.
1273    check_domainname $ANS
1274    while [ $? -ne 0 ]
1275    do
1276	case "$ANS" in
1277	    [Hh] | help | Help | \?) display_msg ${1:-sorry} ;;
1278	    * ) ${ECHO} "Invalid domainname: \"${ANS}\"."
1279	     ;;
1280	esac
1281	get_ans "Enter domainname to be served (h=help):" $DOM
1282
1283	check_domainname $ANS
1284    done
1285
1286    # Set the domainname to valid name.
1287    LDAP_DOMAIN=$ANS
1288}
1289
1290
1291#
1292# get_basedn(): Query for the Base DN.
1293#
1294get_basedn()
1295{
1296    # Set the $_DOM_2_DC and assign to LDAP_BASEDN as default.
1297    # Then call get_basedn().  This method remakes the default
1298    # each time just in case the domain changed.
1299    domain_2_dc $LDAP_DOMAIN
1300    LDAP_BASEDN=$_DOM_2_DC
1301
1302    # Get Base DN.
1303    while :
1304    do
1305	get_ans_req "Enter LDAP Base DN (h=help):" "${_DOM_2_DC}"
1306	check_baseDN "$ANS"
1307	while [ $? -ne 0 ]
1308	do
1309	    case "$ANS" in
1310		[Hh] | help | Help | \?) display_msg basedn_help ;;
1311		* ) ${ECHO} "Invalid base DN: \"${ANS}\"."
1312		;;
1313	    esac
1314
1315	    # Re-Enter the BaseDN
1316	    get_ans_req "Enter LDAP Base DN (h=help):" "${_DOM_2_DC}"
1317	    check_baseDN "$ANS"
1318	done
1319
1320	# Set base DN and check its suffix
1321	LDAP_BASEDN=${ANS}
1322	check_basedn_suffix ||
1323	{
1324		cleanup
1325		exit 1
1326	}
1327
1328	# suffix may need to be created, in that case get suffix from user
1329	[ -n "${NEED_CREATE_SUFFIX}" ] &&
1330	{
1331		get_suffix || continue
1332	}
1333
1334	# suffix is ok, break out of the base dn inquire loop
1335	break
1336    done
1337}
1338
1339#
1340# get_profile_name(): Enter the profile name.
1341#
1342get_profile_name()
1343{
1344    # Reset Delete Old Profile since getting new profile name.
1345    DEL_OLD_PROFILE=0
1346
1347    # Loop until valid profile name, or replace.
1348    while :
1349    do
1350	# Prompt for profile name.
1351	get_ans "Enter the profile name (h=help):" "$LDAP_PROFILE_NAME"
1352
1353	# Check for Help.
1354	case "$ANS" in
1355	    [Hh] | help | Help | \?) display_msg profile_help
1356				     continue ;;
1357	    * )  ;;
1358	esac
1359
1360	# Search to see if profile name already exists.
1361	eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=${ANS},ou=profile,${LDAP_BASEDN}\" -s base \"objectclass=*\" ${VERB}"
1362	if [ $? -eq 0 ]; then
1363	    get_confirm_nodef "Are you sure you want to overwire profile cn=${ANS}?"
1364	    if [ $? -eq 1 ]; then
1365		DEL_OLD_PROFILE=1
1366		return 0  # Replace old profile name.
1367	    else
1368		${ECHO} "Please re-enter a new profile name."
1369	    fi
1370	else
1371	    break  # Unique profile name.
1372	fi
1373    done
1374
1375    # Set Profile Name.
1376    LDAP_PROFILE_NAME=$ANS
1377}
1378
1379
1380#
1381# get_srv_list(): Get the default server list.
1382#
1383get_srv_list()
1384{
1385    # If LDAP_SERVER_LIST is NULL, then set, otherwise leave alone.
1386    if [ -z "${LDAP_SERVER_LIST}" ]; then
1387	LDAP_SERVER_LIST=`getent hosts ${IDS_SERVER} | awk '{print $1}'`
1388        if [ ${IDS_PORT} -ne 389 ]; then
1389	    LDAP_SERVER_LIST="${LDAP_SERVER_LIST}:${IDS_PORT}"
1390	fi
1391    fi
1392
1393    # Prompt for new LDAP_SERVER_LIST.
1394    while :
1395    do
1396	get_ans "Default server list (h=help):" $LDAP_SERVER_LIST
1397
1398	# If help continue, otherwise break.
1399	case "$ANS" in
1400	    [Hh] | help | Help | \?) display_msg def_srvlist_help ;;
1401	    * ) break ;;
1402	esac
1403    done
1404    LDAP_SERVER_LIST=$ANS
1405}
1406
1407
1408#
1409# get_pref_srv(): The preferred server list (Overrides the server list)
1410#
1411get_pref_srv()
1412{
1413    while :
1414    do
1415	get_ans "Preferred server list (h=help):" $LDAP_PREF_SRVLIST
1416
1417	# If help continue, otherwise break.
1418	case "$ANS" in
1419	    [Hh] | help | Help | \?) display_msg pref_srvlist_help ;;
1420	    * ) break ;;
1421	esac
1422    done
1423    LDAP_PREF_SRVLIST=$ANS
1424}
1425
1426
1427#
1428# get_search_scope(): Get the search scope from the user.
1429#
1430get_search_scope()
1431{
1432    [ $DEBUG -eq 1 ] && ${ECHO} "In get_search_scope()"
1433
1434    _MENU_CHOICE=0
1435    while :
1436    do
1437	get_ans "Choose desired search scope (one, sub, h=help): " "one"
1438	_MENU_CHOICE=$ANS
1439	case "$_MENU_CHOICE" in
1440	    one) LDAP_SEARCH_SCOPE="one"
1441	       return 1 ;;
1442	    sub) LDAP_SEARCH_SCOPE="sub"
1443	       return 2 ;;
1444	    h) display_msg srch_scope_help ;;
1445	    *) ${ECHO} "Please enter \"one\", \"sub\", or \"h\"." ;;
1446	esac
1447    done
1448
1449}
1450
1451
1452#
1453# get_cred_level(): Function to display menu to user and get the
1454#                  credential level.
1455#
1456get_cred_level()
1457{
1458    [ $DEBUG -eq 1 ] && ${ECHO} "In get_cred_level()"
1459
1460    _MENU_CHOICE=0
1461    display_msg cred_level_menu
1462    while :
1463    do
1464	get_ans "Choose Credential level [h=help]:" "1"
1465	_MENU_CHOICE=$ANS
1466	case "$_MENU_CHOICE" in
1467	    1) LDAP_CRED_LEVEL="anonymous"
1468	       return 1 ;;
1469	    2) LDAP_CRED_LEVEL="proxy"
1470	       return 2 ;;
1471	    3) LDAP_CRED_LEVEL="proxy anonymous"
1472	       return 3 ;;
1473	    h) display_msg cred_lvl_help ;;
1474	    *) ${ECHO} "Please enter 1, 2 or 3." ;;
1475	esac
1476    done
1477}
1478
1479
1480#
1481# srvauth_menu_handler(): Enter the Service Authentication method.
1482#
1483srvauth_menu_handler()
1484{
1485    # Display Auth menu
1486    display_msg srvauth_method_menu
1487
1488    # Get a Valid choice.
1489    while :
1490    do
1491	# Display appropriate prompt and get answer.
1492	if [ $_FIRST -eq 1 ]; then
1493	    get_ans "Choose Service Authentication Method:" "1"
1494	else
1495	    get_ans "Choose Service Authentication Method (0=reset):"
1496	fi
1497
1498	# Determine choice.
1499	_MENU_CHOICE=$ANS
1500	case "$_MENU_CHOICE" in
1501	    1) _AUTHMETHOD="simple"
1502		break ;;
1503	    2) _AUTHMETHOD="sasl/DIGEST-MD5"
1504		break ;;
1505	    3) _AUTHMETHOD="tls:simple"
1506		break ;;
1507	    4) _AUTHMETHOD="tls:sasl/DIGEST-MD5"
1508		break ;;
1509	    0) _AUTHMETHOD=""
1510		_FIRST=1
1511		break ;;
1512	    *) ${ECHO} "Please enter 1-4 or 0 to reset." ;;
1513	esac
1514    done
1515}
1516
1517
1518#
1519# auth_menu_handler(): Enter the Authentication method.
1520#
1521auth_menu_handler()
1522{
1523    # Display Auth menu
1524    display_msg auth_method_menu
1525
1526    # Get a Valid choice.
1527    while :
1528    do
1529	# Display appropriate prompt and get answer.
1530	if [ $_FIRST -eq 1 ]; then
1531	    get_ans "Choose Authentication Method (h=help):" "1"
1532	else
1533	    get_ans "Choose Authentication Method (0=reset, h=help):"
1534	fi
1535
1536	# Determine choice.
1537	_MENU_CHOICE=$ANS
1538	case "$_MENU_CHOICE" in
1539	    1) _AUTHMETHOD="none"
1540		break ;;
1541	    2) _AUTHMETHOD="simple"
1542		break ;;
1543	    3) _AUTHMETHOD="sasl/DIGEST-MD5"
1544		break ;;
1545	    4) _AUTHMETHOD="tls:simple"
1546		break ;;
1547	    5) _AUTHMETHOD="tls:sasl/DIGEST-MD5"
1548		break ;;
1549	    0) _AUTHMETHOD=""
1550		_FIRST=1
1551		break ;;
1552	    h) display_msg auth_help ;;
1553	    *) ${ECHO} "Please enter 1-5, 0=reset, or h=help." ;;
1554	esac
1555    done
1556}
1557
1558
1559#
1560# get_auth(): Enter the Authentication method.
1561#
1562get_auth()
1563{
1564    [ $DEBUG -eq 1 ] && ${ECHO} "In get_auth()"
1565
1566    _FIRST=1          # Flag for first time.
1567    _MENU_CHOICE=0
1568    _AUTHMETHOD=""    # Tmp method.
1569
1570    while :
1571    do
1572	# Call Menu handler
1573	auth_menu_handler
1574
1575	# Add Auth Method to list.
1576        if [ $_FIRST -eq 1 ]; then
1577	    LDAP_AUTHMETHOD="${_AUTHMETHOD}"
1578	    _FIRST=0
1579	else
1580	    LDAP_AUTHMETHOD="${LDAP_AUTHMETHOD};${_AUTHMETHOD}"
1581	fi
1582
1583	# Display current Authentication Method.
1584	${ECHO} ""
1585	${ECHO} "Current authenticationMethod: ${LDAP_AUTHMETHOD}"
1586	${ECHO} ""
1587
1588	# Prompt for another Auth Method, or break out.
1589	get_confirm_nodef "Do you want to add another Authentication Method?"
1590	if [ $? -eq 0 ]; then
1591	    break;
1592	fi
1593    done
1594}
1595
1596
1597#
1598# get_followref(): Whether or not to follow referrals.
1599#
1600get_followref()
1601{
1602    get_confirm "Do you want the clients to follow referrals (y/n/h)?" "n" "referrals_help"
1603    if [ $? -eq 1 ]; then
1604	LDAP_FOLLOWREF="TRUE"
1605    else
1606	LDAP_FOLLOWREF="FALSE"
1607    fi
1608}
1609
1610
1611#
1612# get_timelimit(): Set the time limit. -1 is max time.
1613#
1614get_timelimit()
1615{
1616    # Get current timeout value from cn=config.
1617    eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=config\" -s base \"objectclass=*\" nsslapd-timelimit > ${TMPDIR}/chk_timeout 2>&1"
1618    if [ $? -ne 0 ]; then
1619	${ECHO} "  ERROR: Could not reach LDAP server to check current timeout!"
1620	cleanup
1621	exit 1
1622    fi
1623    CURR_TIMELIMIT=`${GREP} timelimit ${TMPDIR}/chk_timeout | cut -f2 -d=`
1624
1625    get_negone_num "Enter the time limit for iDS (current=${CURR_TIMELIMIT}):" "-1"
1626    IDS_TIMELIMIT=$NUM
1627}
1628
1629
1630#
1631# get_sizelimit(): Set the size limit. -1 is max size.
1632#
1633get_sizelimit()
1634{
1635    # Get current sizelimit value from cn=config.
1636    eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=config\" -s base \"objectclass=*\" nsslapd-sizelimit > ${TMPDIR}/chk_sizelimit 2>&1"
1637    if [ $? -ne 0 ]; then
1638	${ECHO} "  ERROR: Could not reach LDAP server to check current sizelimit!"
1639	cleanup
1640	exit 1
1641    fi
1642    CURR_SIZELIMIT=`${GREP} sizelimit ${TMPDIR}/chk_sizelimit | cut -f2 -d=`
1643
1644    get_negone_num "Enter the size limit for iDS (current=${CURR_SIZELIMIT}):" "-1"
1645    IDS_SIZELIMIT=$NUM
1646}
1647
1648
1649#
1650# get_want_crypt(): Ask user if want to store passwords in crypt?
1651#
1652get_want_crypt()
1653{
1654    get_confirm "Do you want to store passwords in \"crypt\" format (y/n/h)?" "n" "crypt_help"
1655    if [ $? -eq 1 ]; then
1656	NEED_CRYPT="TRUE"
1657    else
1658	NEED_CRYPT="FALSE"
1659    fi
1660}
1661
1662
1663#
1664# get_srv_authMethod_pam(): Get the Service Auth Method for pam_ldap from user.
1665#
1666#  NOTE: This function is base on get_auth().
1667#
1668get_srv_authMethod_pam()
1669{
1670    [ $DEBUG -eq 1 ] && ${ECHO} "In get_srv_authMethod_pam()"
1671
1672    _FIRST=1          # Flag for first time.
1673    _MENU_CHOICE=0
1674    _AUTHMETHOD=""    # Tmp method.
1675
1676    while :
1677    do
1678	# Call Menu handler
1679	srvauth_menu_handler
1680
1681	# Add Auth Method to list.
1682        if [ $_FIRST -eq 1 ]; then
1683	    if [ "$_AUTHMETHOD" = "" ]; then
1684		LDAP_SRV_AUTHMETHOD_PAM=""
1685	    else
1686		LDAP_SRV_AUTHMETHOD_PAM="pam_ldap:${_AUTHMETHOD}"
1687	    fi
1688	    _FIRST=0
1689	else
1690	    LDAP_SRV_AUTHMETHOD_PAM="${LDAP_SRV_AUTHMETHOD_PAM};${_AUTHMETHOD}"
1691	fi
1692
1693	# Display current Authentication Method.
1694	${ECHO} ""
1695	${ECHO} "Current authenticationMethod: ${LDAP_SRV_AUTHMETHOD_PAM}"
1696	${ECHO} ""
1697
1698	# Prompt for another Auth Method, or break out.
1699	get_confirm_nodef "Do you want to add another Authentication Method?"
1700	if [ $? -eq 0 ]; then
1701	    break;
1702	fi
1703    done
1704
1705    # Check in case user reset string and exited loop.
1706    if [ "$LDAP_SRV_AUTHMETHOD_PAM" = "" ]; then
1707	NEED_SRVAUTH_PAM=0
1708    fi
1709}
1710
1711
1712#
1713# get_srv_authMethod_key(): Get the Service Auth Method for keyserv from user.
1714#
1715#  NOTE: This function is base on get_auth().
1716#
1717get_srv_authMethod_key()
1718{
1719    [ $DEBUG -eq 1 ] && ${ECHO} "In get_srv_authMethod_key()"
1720
1721    _FIRST=1          # Flag for first time.
1722    _MENU_CHOICE=0
1723    _AUTHMETHOD=""    # Tmp method.
1724
1725    while :
1726    do
1727	# Call Menu handler
1728	srvauth_menu_handler
1729
1730	# Add Auth Method to list.
1731        if [ $_FIRST -eq 1 ]; then
1732	    if [ "$_AUTHMETHOD" = "" ]; then
1733		LDAP_SRV_AUTHMETHOD_KEY=""
1734	    else
1735		LDAP_SRV_AUTHMETHOD_KEY="keyserv:${_AUTHMETHOD}"
1736	    fi
1737	    _FIRST=0
1738	else
1739	    LDAP_SRV_AUTHMETHOD_KEY="${LDAP_SRV_AUTHMETHOD_KEY};${_AUTHMETHOD}"
1740	fi
1741
1742	# Display current Authentication Method.
1743	${ECHO} ""
1744	${ECHO} "Current authenticationMethod: ${LDAP_SRV_AUTHMETHOD_KEY}"
1745	${ECHO} ""
1746
1747	# Prompt for another Auth Method, or break out.
1748	get_confirm_nodef "Do you want to add another Authentication Method?"
1749	if [ $? -eq 0 ]; then
1750	    break;
1751	fi
1752    done
1753
1754    # Check in case user reset string and exited loop.
1755    if [ "$LDAP_SRV_AUTHMETHOD_KEY" = "" ]; then
1756	NEED_SRVAUTH_KEY=0
1757    fi
1758}
1759
1760
1761#
1762# get_srv_authMethod_cmd(): Get the Service Auth Method for passwd-cmd from user.
1763#
1764#  NOTE: This function is base on get_auth().
1765#
1766get_srv_authMethod_cmd()
1767{
1768    [ $DEBUG -eq 1 ] && ${ECHO} "In get_srv_authMethod_cmd()"
1769
1770    _FIRST=1          # Flag for first time.
1771    _MENU_CHOICE=0
1772    _AUTHMETHOD=""    # Tmp method.
1773
1774    while :
1775    do
1776	# Call Menu handler
1777	srvauth_menu_handler
1778
1779	# Add Auth Method to list.
1780        if [ $_FIRST -eq 1 ]; then
1781	    if [ "$_AUTHMETHOD" = "" ]; then
1782		LDAP_SRV_AUTHMETHOD_CMD=""
1783	    else
1784		LDAP_SRV_AUTHMETHOD_CMD="passwd-cmd:${_AUTHMETHOD}"
1785	    fi
1786	    _FIRST=0
1787	else
1788	    LDAP_SRV_AUTHMETHOD_CMD="${LDAP_SRV_AUTHMETHOD_CMD};${_AUTHMETHOD}"
1789	fi
1790
1791	# Display current Authentication Method.
1792	${ECHO} ""
1793	${ECHO} "Current authenticationMethod: ${LDAP_SRV_AUTHMETHOD_CMD}"
1794	${ECHO} ""
1795
1796	# Prompt for another Auth Method, or break out.
1797	get_confirm_nodef "Do you want to add another Authentication Method?"
1798	if [ $? -eq 0 ]; then
1799	    break;
1800	fi
1801    done
1802
1803    # Check in case user reset string and exited loop.
1804    if [ "$LDAP_SRV_AUTHMETHOD_CMD" = "" ]; then
1805	NEED_SRVAUTH_CMD=0
1806    fi
1807}
1808
1809
1810#
1811# get_srch_time(): Amount of time to search.
1812#
1813get_srch_time()
1814{
1815    get_negone_num "Client search time limit in seconds (h=help):" "$LDAP_SEARCH_TIME_LIMIT" "srchtime_help"
1816    LDAP_SEARCH_TIME_LIMIT=$NUM
1817}
1818
1819
1820#
1821# get_prof_ttl(): The profile time to live (TTL)
1822#
1823get_prof_ttl()
1824{
1825    get_negone_num "Profile Time To Live in seconds (h=help):" "$LDAP_PROFILE_TTL" "profttl_help"
1826    LDAP_PROFILE_TTL=$NUM
1827}
1828
1829
1830#
1831# get_bind_limit(): Bind time limit
1832#
1833get_bind_limit()
1834{
1835    get_negone_num "Bind time limit in seconds (h=help):" "$LDAP_BIND_LIMIT" "bindlim_help"
1836    LDAP_BIND_LIMIT=$NUM
1837}
1838
1839
1840######################################################################
1841# FUNCTIONS  FOR Service Search Descriptor's START HERE.
1842######################################################################
1843
1844
1845#
1846# add_ssd(): Get SSD's from user and add to file.
1847#
1848add_ssd()
1849{
1850    [ $DEBUG -eq 1 ] && ${ECHO} "In add_ssd()"
1851
1852    # Enter the service id.  Loop til unique.
1853    while :
1854    do
1855	get_ans "Enter the service id:"
1856	_SERV_ID=$ANS
1857
1858	# Grep for name existing.
1859	${GREP} -i "^$ANS:" ${SSD_FILE} > /dev/null 2>&1
1860	if [ $? -eq 1 ]; then
1861	    break
1862	fi
1863
1864	# Name exists, print message, let user decide.
1865	${ECHO} "ERROR: Service id ${ANS} already exists."
1866    done
1867
1868    get_ans "Enter the base:"
1869    _BASE=$ANS
1870
1871    # Get the scope and verify that its one or sub.
1872    while :
1873    do
1874	get_ans "Enter the scope:"
1875	_SCOPE=$ANS
1876	case `${ECHO} ${_SCOPE} | tr '[A-Z]' '[a-z]'` in
1877	    one) break ;;
1878	    sub) break ;;
1879	    *)   ${ECHO} "${_SCOPE} is Not valid - Enter 'one' or 'sub'" ;;
1880	esac
1881    done
1882
1883    # Build SSD to add to file.
1884    _SSD="${_SERV_ID}:${_BASE}?${_SCOPE}"
1885
1886    # Add the SSD to the file.
1887    ${ECHO} "${_SSD}" >> ${SSD_FILE}
1888}
1889
1890
1891#
1892# delete_ssd(): Delete a SSD from the list.
1893#
1894delete_ssd()
1895{
1896    [ $DEBUG -eq 1 ] && ${ECHO} "In delete_ssd()"
1897
1898    # Get service id name from user for SSD to delete.
1899    get_ans_req "Enter service id to delete:"
1900
1901    # Make sure service id exists.
1902    ${GREP} "$ANS" ${SSD_FILE} > /dev/null 2>&1
1903    if [ $? -eq 1 ]; then
1904	${ECHO} "Invalid service id: $ANS not present in list."
1905	return
1906    fi
1907
1908    # Create temporary back SSD file.
1909    cp ${SSD_FILE} ${SSD_FILE}.bak
1910    if [ $? -eq 1 ]; then
1911	${ECHO} "ERROR: could not create file: ${SSD_FILE}.bak"
1912	exit 1
1913    fi
1914
1915    # Use ${GREP} to remove the SSD.  Read from temp file
1916    # and write to the orig file.
1917    ${GREP} -v "$ANS" ${SSD_FILE}.bak > ${SSD_FILE}
1918}
1919
1920
1921#
1922# modify_ssd(): Allow user to modify a SSD.
1923#
1924modify_ssd()
1925{
1926    [ $DEBUG -eq 1 ] && ${ECHO} "In modify_ssd()"
1927
1928    # Prompt user for service id.
1929    get_ans_req "Enter service id to modify:"
1930
1931    # Put into temp _LINE.
1932    _LINE=`${GREP} "^$ANS:" ${SSD_FILE}`
1933    if [ "$_LINE" = "" ]; then
1934	${ECHO} "Invalid service id: $ANS"
1935	return
1936    fi
1937
1938    # Display current filter for user to see.
1939    ${ECHO} ""
1940    ${ECHO} "Current SSD: $_LINE"
1941    ${ECHO} ""
1942
1943    # Get the defaults.
1944    _CURR_BASE=`${ECHO} $_LINE | cut -d: -f2 | cut -d'?' -f 1`
1945    _CURR_SCOPE=`${ECHO} $_LINE | cut -d: -f2 | cut -d'?' -f 2`
1946
1947    # Create temporary back SSD file.
1948    cp ${SSD_FILE} ${SSD_FILE}.bak
1949    if [ $? -eq 1 ]; then
1950	${ECHO} "ERROR: could not create file: ${SSD_FILE}.bak"
1951	cleanup
1952	exit 1
1953    fi
1954
1955    # Removed the old line.
1956    ${GREP} -v "^$ANS:" ${SSD_FILE}.bak > ${SSD_FILE} 2>&1
1957
1958    # New Entry
1959    _SERV_ID=$ANS
1960    get_ans_req "Enter the base:" "$_CURR_BASE"
1961    _BASE=$ANS
1962    get_ans_req "Enter the scope:" "$_CURR_SCOPE"
1963    _SCOPE=$ANS
1964
1965    # Build the new SSD.
1966    _SSD="${_SERV_ID}:${_BASE}?${_SCOPE}"
1967
1968    # Add the SSD to the file.
1969    ${ECHO} "${_SSD}" >> ${SSD_FILE}
1970}
1971
1972
1973#
1974# display_ssd(): Display the current SSD list.
1975#
1976display_ssd()
1977{
1978    [ $DEBUG -eq 1 ] && ${ECHO} "In display_ssd()"
1979
1980    ${ECHO} ""
1981    ${ECHO} "Current Service Search Descriptors:"
1982    ${ECHO} "=================================="
1983    cat ${SSD_FILE}
1984    ${ECHO} ""
1985    ${ECHO} "Hit return to continue."
1986    read __A
1987}
1988
1989
1990#
1991# prompt_ssd(): Get SSD's from user.
1992#
1993prompt_ssd()
1994{
1995    [ $DEBUG -eq 1 ] && ${ECHO} "In prompt_ssd()"
1996    # See if user wants SSD's?
1997    get_confirm "Do you wish to setup Service Search Descriptors (y/n/h)?" "n" "ssd_help"
1998    [ "$?" -eq 0 ] && return
1999
2000    # Display menu for SSD choices.
2001    while :
2002    do
2003	display_msg prompt_ssd_menu
2004	get_ans "Enter menu choice:" "Quit"
2005	case "$ANS" in
2006	    [Aa] | add) add_ssd ;;
2007	    [Dd] | delete) delete_ssd ;;
2008	    [Mm] | modify) modify_ssd ;;
2009	    [Pp] | print | display) display_ssd ;;
2010	    [Xx] | reset | clear) reset_ssd_file ;;
2011	    [Hh] | Help | help)	display_msg ssd_menu_help
2012				${ECHO} " Press return to continue."
2013				read __A ;;
2014	    [Qq] | Quit | quit)	return ;;
2015	    *)    ${ECHO} "Invalid choice: $ANS please re-enter from menu." ;;
2016	esac
2017    done
2018}
2019
2020
2021#
2022# reset_ssd_file(): Blank out current SSD file.
2023#
2024reset_ssd_file()
2025{
2026    [ $DEBUG -eq 1 ] && ${ECHO} "In reset_ssd_file()"
2027
2028    rm -f ${SSD_FILE}
2029    touch ${SSD_FILE}
2030}
2031
2032
2033#
2034# create_ssd_file(): Create a temporary file for SSD's.
2035#
2036create_ssd_file()
2037{
2038    [ $DEBUG -eq 1 ] && ${ECHO} "In create_ssd_file()"
2039
2040    # Build a list of SSD's and store in temp file.
2041    ${GREP} "LDAP_SERV_SRCH_DES=" ${INPUT_FILE} | \
2042	sed 's/LDAP_SERV_SRCH_DES=//' \
2043	> ${SSD_FILE}
2044}
2045
2046
2047#
2048# ssd_2_config(): Append the SSD file to the output file.
2049#
2050ssd_2_config()
2051{
2052    [ $DEBUG -eq 1 ] && ${ECHO} "In ssd_2_config()"
2053
2054    # Convert to config file format using sed.
2055    sed -e "s/^/LDAP_SERV_SRCH_DES=/" ${SSD_FILE} >> ${OUTPUT_FILE}
2056}
2057
2058
2059#
2060# ssd_2_profile(): Add SSD's to the GEN_CMD string.
2061#
2062ssd_2_profile()
2063{
2064    [ $DEBUG -eq 1 ] && ${ECHO} "In ssd_2_profile()"
2065
2066    GEN_TMPFILE=${TMPDIR}/ssd_tmpfile
2067    touch ${GEN_TMPFILE}
2068
2069    # Add and convert each SSD to string.
2070    while read SSD_LINE
2071    do
2072	${ECHO} " -a \"serviceSearchDescriptor=${SSD_LINE}\"\c" >> ${GEN_TMPFILE}
2073    done <${SSD_FILE}
2074
2075    # Add SSD's to GEN_CMD.
2076    GEN_CMD="${GEN_CMD} `cat ${GEN_TMPFILE}`"
2077}
2078
2079
2080#
2081# prompt_config_info(): This function prompts the user for the config
2082# info that is not specified in the input file.
2083#
2084prompt_config_info()
2085{
2086    [ $DEBUG -eq 1 ] && ${ECHO} "In prompt_config_info()"
2087
2088    # Prompt for iDS server name.
2089    get_ids_server
2090
2091    # Prompt for iDS port number.
2092    get_ids_port
2093
2094    # Check iDS version for compatibility.
2095    chk_ids_version
2096
2097    # Check if the server supports the VLV.
2098    chk_vlv_indexes
2099
2100    # Get the Directory manager DN and passwd.
2101    get_dirmgr_dn
2102    get_dirmgr_pw
2103
2104    #
2105    # LDAP CLIENT PROFILE SPECIFIC INFORMATION.
2106    #   (i.e. The fields that show up in the profile.)
2107    #
2108    get_domain "domain_help"
2109
2110    get_basedn
2111
2112    get_profile_name
2113    get_srv_list
2114    get_pref_srv
2115    get_search_scope
2116
2117    # If cred is "anonymous", make auth == "none"
2118    get_cred_level
2119    if [ "$LDAP_CRED_LEVEL" != "anonymous" ]; then
2120	get_auth
2121    fi
2122
2123    get_followref
2124
2125    # Query user about timelimt.
2126    get_confirm "Do you want to modify the server timelimit value (y/n/h)?" "n" "tlim_help"
2127    NEED_TIME=$?
2128    [ $NEED_TIME -eq 1 ] && get_timelimit
2129
2130    # Query user about sizelimit.
2131    get_confirm "Do you want to modify the server sizelimit value (y/n/h)?" "n" "slim_help"
2132    NEED_SIZE=$?
2133    [ $NEED_SIZE -eq 1 ] && get_sizelimit
2134
2135    # Does the user want to store passwords in crypt format?
2136    get_want_crypt
2137
2138    # Prompt for any Service Authentication Methods?
2139    get_confirm "Do you want to setup a Service Authentication Methods (y/n/h)?" "n" "srvauth_help"
2140    if [ $? -eq 1 ]; then
2141	# Does the user want to set Service Authentication Method for pam_ldap?
2142	get_confirm "Do you want to setup a Service Auth. Method for \"pam_ldap\" (y/n/h)?" "n" "pam_ldap_help"
2143	NEED_SRVAUTH_PAM=$?
2144	[ $NEED_SRVAUTH_PAM -eq 1 ] && get_srv_authMethod_pam
2145
2146	# Does the user want to set Service Authentication Method for keyserv?
2147	get_confirm "Do you want to setup a Service Auth. Method for \"keyserv\" (y/n/h)?" "n" "keyserv_help"
2148	NEED_SRVAUTH_KEY=$?
2149	[ $NEED_SRVAUTH_KEY -eq 1 ] && get_srv_authMethod_key
2150
2151	# Does the user want to set Service Authentication Method for passwd-cmd?
2152	get_confirm "Do you want to setup a Service Auth. Method for \"passwd-cmd\" (y/n/h)?" "n" "passwd-cmd_help"
2153	NEED_SRVAUTH_CMD=$?
2154	[ $NEED_SRVAUTH_CMD -eq 1 ] && get_srv_authMethod_cmd
2155    fi
2156
2157    # Get Timeouts
2158    get_srch_time
2159    get_prof_ttl
2160    get_bind_limit
2161
2162    # Reset the sdd_file and prompt user for SSD.  Will use menus
2163    # to build an SSD File.
2164    reset_ssd_file
2165    prompt_ssd
2166
2167    # Display FULL debugging info.
2168    disp_full_debug
2169
2170    # Extra blank line to separate prompt lines from steps.
2171    ${ECHO} " "
2172}
2173
2174
2175######################################################################
2176# FUNCTIONS  FOR display_summary() START HERE.
2177######################################################################
2178
2179
2180#
2181# get_proxyagent(): Get the proxyagent DN.
2182#
2183get_proxyagent()
2184{
2185    LDAP_PROXYAGENT="cn=proxyagent,ou=profile,${LDAP_BASEDN}"  # default
2186    get_ans "Enter DN for proxy agent:" "$LDAP_PROXYAGENT"
2187    LDAP_PROXYAGENT=$ANS
2188}
2189
2190
2191#
2192# get_proxy_pw(): Get the proxyagent passwd.
2193#
2194get_proxy_pw()
2195{
2196    get_passwd "Enter passwd for proxyagent:"
2197    LDAP_PROXYAGENT_CRED=$ANS
2198}
2199
2200
2201#
2202# display_summary(): Display a summary of values entered and let the
2203#                    user modify values at will.
2204#
2205display_summary()
2206{
2207    [ $DEBUG -eq 1 ] && ${ECHO} "In display_summary()"
2208
2209    # Create lookup table for function names.  First entry is dummy for
2210    # shift.
2211    TBL1="dummy"
2212    TBL2="get_domain get_basedn get_profile_name"
2213    TBL3="get_srv_list get_pref_srv get_search_scope get_cred_level"
2214    TBL4="get_auth get_followref"
2215    TBL5="get_timelimit get_sizelimit get_want_crypt"
2216    TBL6="get_srv_authMethod_pam get_srv_authMethod_key get_srv_authMethod_cmd"
2217    TBL7="get_srch_time get_prof_ttl get_bind_limit"
2218    TBL8="prompt_ssd"
2219    FUNC_TBL="$TBL1 $TBL2 $TBL3 $TBL4 $TBL5 $TBL6 $TBL7 $TBL8"
2220
2221    # Since menu prompt string is long, set here.
2222    _MENU_PROMPT="Enter config value to change: (1-19 0=commit changes)"
2223
2224    # Infinite loop.  Test for 0, and break in loop.
2225    while :
2226    do
2227	# Display menu and get value in range.
2228	display_msg summary_menu
2229	get_menu_choice "${_MENU_PROMPT}" "0" "19" "0"
2230	_CH=$MN_CH
2231
2232	# Make sure where not exiting.
2233	if [ $_CH -eq 0 ]; then
2234	    break       # Break out of loop if 0 selected.
2235	fi
2236
2237	# Call appropriate function from function table.
2238	set $FUNC_TBL
2239	shift $_CH
2240	$1          # Call the appropriate function.
2241    done
2242
2243    # If cred level is still see if user wants a change?
2244    if ${ECHO} "$LDAP_CRED_LEVEL" | ${GREP} "proxy" > /dev/null 2>&1
2245    then
2246	if [ "$LDAP_AUTHMETHOD" != "none" ]; then
2247	    NEED_PROXY=1    # I assume integer test is faster?
2248	    get_proxyagent
2249	    get_proxy_pw
2250	else
2251	    ${ECHO} "WARNING: Since Authentication method is 'none'."
2252	    ${ECHO} "         Credential level will be set to 'anonymous'."
2253	    LDAP_CRED_LEVEL="anonymous"
2254	fi
2255    fi
2256
2257    # Display FULL debugging info.
2258    disp_full_debug
2259
2260    # Final confirmation message. (ARE YOU SURE!)
2261    ${ECHO} " "
2262    get_confirm_nodef "WARNING: About to start committing changes. (y=continue, n=EXIT)"
2263    if [ $? -eq 0 ]; then
2264	${ECHO} "Terminating setup without making changes at users request."
2265	cleanup
2266	exit 1
2267    fi
2268
2269    # Print newline
2270    ${ECHO} " "
2271}
2272
2273
2274#
2275# create_config_file(): Write config data to config file specified.
2276#
2277create_config_file()
2278{
2279    [ $DEBUG -eq 1 ] && ${ECHO} "In create_config_file()"
2280
2281    # If output file exists, delete it.
2282    [ -f $OUTPUT_FILE ] && rm $OUTPUT_FILE
2283
2284    # Create output file.
2285    cat > $OUTPUT_FILE <<EOF
2286#!/bin/sh
2287# $OUTPUT_FILE - This file contains configuration information for
2288#                Native LDAP.  Use the idsconfig tool to load it.
2289#
2290# WARNING: This file was generated by idsconfig, and is intended to
2291#          be loaded by idsconfig as is.  DO NOT EDIT THIS FILE!
2292#
2293IDS_SERVER="$IDS_SERVER"
2294IDS_PORT=$IDS_PORT
2295IDS_TIMELIMIT=$IDS_TIMELIMIT
2296IDS_SIZELIMIT=$IDS_SIZELIMIT
2297LDAP_ROOTDN="$LDAP_ROOTDN"
2298LDAP_ROOTPWD=$LDAP_ROOTPWD
2299LDAP_DOMAIN="$LDAP_DOMAIN"
2300LDAP_SUFFIX="$LDAP_SUFFIX"
2301
2302# Internal program variables that need to be set.
2303NEED_PROXY=$NEED_PROXY
2304NEED_TIME=$NEED_TIME
2305NEED_SIZE=$NEED_SIZE
2306NEED_CRYPT=$NEED_CRYPT
2307
2308# LDAP PROFILE related defaults
2309LDAP_PROFILE_NAME="$LDAP_PROFILE_NAME"
2310DEL_OLD_PROFILE=1
2311LDAP_BASEDN="$LDAP_BASEDN"
2312LDAP_SERVER_LIST="$LDAP_SERVER_LIST"
2313LDAP_AUTHMETHOD="$LDAP_AUTHMETHOD"
2314LDAP_FOLLOWREF=$LDAP_FOLLOWREF
2315LDAP_SEARCH_SCOPE="$LDAP_SEARCH_SCOPE"
2316NEED_SRVAUTH_PAM=$NEED_SRVAUTH_PAM
2317NEED_SRVAUTH_KEY=$NEED_SRVAUTH_KEY
2318NEED_SRVAUTH_CMD=$NEED_SRVAUTH_CMD
2319LDAP_SRV_AUTHMETHOD_PAM="$LDAP_SRV_AUTHMETHOD_PAM"
2320LDAP_SRV_AUTHMETHOD_KEY="$LDAP_SRV_AUTHMETHOD_KEY"
2321LDAP_SRV_AUTHMETHOD_CMD="$LDAP_SRV_AUTHMETHOD_CMD"
2322LDAP_SEARCH_TIME_LIMIT=$LDAP_SEARCH_TIME_LIMIT
2323LDAP_PREF_SRVLIST="$LDAP_PREF_SRVLIST"
2324LDAP_PROFILE_TTL=$LDAP_PROFILE_TTL
2325LDAP_CRED_LEVEL="$LDAP_CRED_LEVEL"
2326LDAP_BIND_LIMIT=$LDAP_BIND_LIMIT
2327
2328# Proxy Agent
2329LDAP_PROXYAGENT="$LDAP_PROXYAGENT"
2330LDAP_PROXYAGENT_CRED=$LDAP_PROXYAGENT_CRED
2331
2332# Export all the variables (just in case)
2333export IDS_HOME IDS_PORT LDAP_ROOTDN LDAP_ROOTPWD LDAP_SERVER_LIST LDAP_BASEDN
2334export LDAP_DOMAIN LDAP_SUFFIX LDAP_PROXYAGENT LDAP_PROXYAGENT_CRED
2335export NEED_PROXY
2336export LDAP_PROFILE_NAME LDAP_BASEDN LDAP_SERVER_LIST 
2337export LDAP_AUTHMETHOD LDAP_FOLLOWREF LDAP_SEARCH_SCOPE LDAP_SEARCH_TIME_LIMIT
2338export LDAP_PREF_SRVLIST LDAP_PROFILE_TTL LDAP_CRED_LEVEL LDAP_BIND_LIMIT
2339export NEED_SRVAUTH_PAM NEED_SRVAUTH_KEY NEED_SRVAUTH_CMD
2340export LDAP_SRV_AUTHMETHOD_PAM LDAP_SRV_AUTHMETHOD_KEY LDAP_SRV_AUTHMETHOD_CMD
2341export LDAP_SERV_SRCH_DES SSD_FILE
2342
2343# Service Search Descriptors start here if present:
2344EOF
2345    # Add service search descriptors.
2346    ssd_2_config "${OUTPUT_FILE}"
2347
2348    # Add LDAP suffix preferences
2349    print_suffix_config >> "${OUTPUT_FILE}"
2350
2351    # Add the end of FILE tag.
2352    ${ECHO} "" >> ${OUTPUT_FILE}
2353    ${ECHO} "# End of $OUTPUT_FILE" >> ${OUTPUT_FILE}
2354}
2355
2356
2357#
2358# chk_vlv_indexes(): Do ldapsearch to see if server supports VLV.
2359#
2360chk_vlv_indexes()
2361{
2362    # Do ldapsearch to see if server supports VLV.
2363    ${LDAPSEARCH} ${SERVER_ARGS} -b "" -s base "objectclass=*" > ${TMPDIR}/checkVLV 2>&1
2364    eval "${GREP} 2.16.840.1.113730.3.4.9 ${TMPDIR}/checkVLV ${VERB}"
2365    if [ $? -ne 0 ]; then
2366	${ECHO} "ERROR: VLV is not supported on LDAP server!"
2367	cleanup
2368	exit 1
2369    fi
2370    [ $DEBUG -eq 1 ] && ${ECHO} "  VLV controls found on LDAP server."
2371}
2372
2373#
2374# get_backend(): this function gets the relevant backend
2375#                (database) for LDAP_BASED.
2376#                Description: set IDS_DATABASE; exit on failure.
2377#                Prerequisite: LDAP_BASEDN and LDAP_SUFFIX are
2378#                valid.
2379#
2380#                backend is retrieved from suffixes and subsuffixes
2381#                defined under "cn=mapping tree,cn=config". The
2382#                nsslapd-state attribute of these suffixes entries
2383#                is filled with either Backend, Disabled or referrals
2384#                related values. We only want those that have a true
2385#                backend database to select the relevant backend.
2386#
2387get_backend()
2388{
2389    [ $DEBUG -eq 1 ] && ${ECHO} "In get_backend()"
2390
2391    cur_suffix=${LDAP_BASEDN}
2392    prev_suffix=
2393    IDS_DATABASE=
2394    while [ "${cur_suffix}" != "${prev_suffix}" ]
2395    do
2396	[ $DEBUG -eq 1 ] && ${ECHO} "testing LDAP suffix: ${cur_suffix}"
2397	eval "${LDAPSEARCH} ${LDAP_ARGS} " \
2398		"-b \"cn=\\\"${cur_suffix}\\\",cn=mapping tree,cn=config\" " \
2399		"-s base nsslapd-state=Backend nsslapd-backend 2>&1 " \
2400		"| ${GREP} 'nsslapd-backend=' " \
2401		"> ${TMPDIR}/ids_database_name 2>&1"
2402	NUM_DBS=`wc -l ${TMPDIR}/ids_database_name | awk '{print $1}'`
2403	case ${NUM_DBS} in
2404	0) # not a suffix, or suffix not activated; try next
2405	    prev_suffix=${cur_suffix}
2406	    cur_suffix=`${ECHO} ${cur_suffix} | cut -f2- -d','`
2407	    ;;
2408	1) # suffix found; get database name
2409	    IDS_DATABASE=`cat ${TMPDIR}/ids_database_name | cut -d= -f2`
2410	    ;;
2411	*) # can not handle more than one database per suffix
2412	    ${ECHO} "ERROR: More than one database is configured "
2413	    ${ECHO} "       for $LDAP_SUFFIX!"
2414	    ${ECHO} "       $PROG can not configure suffixes where "
2415	    ${ECHO} "       more than one database is used for one suffix."
2416	    cleanup
2417	    exit 1
2418	    ;;
2419	esac
2420	if [ -n "${IDS_DATABASE}" ]; then
2421	    break
2422	fi
2423    done
2424
2425    if [ -z "${IDS_DATABASE}" ]; then
2426	# should not happen, since LDAP_BASEDN is supposed to be valid
2427	${ECHO} "Could not find a valid backend for ${LDAP_BASEDN}."
2428	${ECHO} "Exiting."
2429	cleanup
2430	exit 1
2431    fi
2432
2433    [ $DEBUG -eq 1 ] && ${ECHO} "IDS_DATABASE: ${IDS_DATABASE}"
2434}
2435
2436#
2437# validate_suffix(): This function validates ${LDAP_SUFFIX}
2438#                  THIS FUNCTION IS FOR THE LOAD CONFIG FILE OPTION.
2439#
2440validate_suffix()
2441{
2442    [ $DEBUG -eq 1 ] && ${ECHO} "In validate_suffix()"
2443
2444    # Check LDAP_SUFFIX is not null
2445    if [ -z "${LDAP_SUFFIX}" ]; then
2446	${ECHO} "Invalid suffix (null suffix)"
2447	cleanup
2448	exit 1
2449    fi
2450
2451    # Check LDAP_SUFFIX and LDAP_BASEDN are consistent
2452    # Convert to lower case for basename.
2453    format_string "${LDAP_BASEDN}"
2454    LOWER_BASEDN="${FMT_STR}"
2455    format_string "${LDAP_SUFFIX}"
2456    LOWER_SUFFIX="${FMT_STR}"
2457
2458    [ $DEBUG -eq 1 ] && ${ECHO} "LOWER_BASEDN: ${LOWER_BASEDN}"
2459    [ $DEBUG -eq 1 ] && ${ECHO} "LOWER_SUFFIX: ${LOWER_SUFFIX}"
2460
2461    if [ "${LOWER_BASEDN}" != "${LOWER_SUFFIX}" ]; then
2462    	sub_basedn=`basename "${LOWER_BASEDN}" "${LOWER_SUFFIX}"`
2463    	if [ "$sub_basedn" = "${LOWER_BASEDN}" ]; then
2464	    ${ECHO} "Invalid suffix ${LOWER_SUFFIX}"
2465	    ${ECHO} "for Base DN ${LOWER_BASEDN}"
2466	    cleanup
2467	    exit 1
2468	fi
2469    fi
2470
2471    # Check LDAP_SUFFIX does exist
2472    ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_SUFFIX}\" -s base \"objectclass=*\" > ${TMPDIR}/checkSuffix 2>&1" && return 0
2473
2474    # Well, suffix does not exist, try to prepare create it ...
2475    NEED_CREATE_SUFFIX=1
2476    prep_create_sfx_entry ||
2477    {
2478	cleanup
2479	exit 1
2480    }
2481    [ -n "${NEED_CREATE_BACKEND}" ] &&
2482    {
2483	# try to use id attr value of the suffix as a database name
2484	IDS_DATABASE=${_VAL}
2485	prep_create_sfx_backend
2486	case $? in
2487	1)	# cann't use the name we want, so we can either exit or use
2488		# some another available name - doing the last ...
2489		IDS_DATABASE=${IDS_DATABASE_AVAIL}
2490		;;
2491	2)	# unable to determine database name
2492		cleanup
2493		exit 1
2494		;;
2495	esac
2496    }
2497
2498    [ $DEBUG -eq 1 ] && ${ECHO} "Suffix $LDAP_SUFFIX, Database $IDS_DATABASE"
2499}
2500
2501#
2502# validate_info(): This function validates the basic info collected
2503#                  So that some problems are caught right away.
2504#                  THIS FUNCTION IS FOR THE LOAD CONFIG FILE OPTION.
2505#
2506validate_info()
2507{
2508    [ $DEBUG -eq 1 ] && ${ECHO} "In validate_info()"
2509
2510    # Set SERVER_ARGS, AUTH_ARGS, and LDAP_ARGS for the config file.
2511    SERVER_ARGS="-h ${IDS_SERVER} -p ${IDS_PORT}"
2512    AUTH_ARGS="-D \"${LDAP_ROOTDN}\" -j ${LDAP_ROOTPWF}"
2513    LDAP_ARGS="${SERVER_ARGS} ${AUTH_ARGS}"
2514    export SERVER_ARGS
2515
2516    # Check the Root DN and Root DN passwd.
2517    # Use eval instead of $EVAL because not part of setup. (validate)
2518    eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"\" -s base \"objectclass=*\" > ${TMPDIR}/checkDN 2>&1"
2519    if [ $? -ne 0 ]; then
2520	eval "${GREP} credential ${TMPDIR}/checkDN ${VERB}"
2521	if [ $? -eq 0 ]; then
2522	    ${ECHO} "ERROR: Root DN passwd is invalid."
2523	else
2524	    ${ECHO} "ERROR2: Invalid Root DN <${LDAP_ROOTDN}>."
2525	fi
2526	cleanup
2527	exit 1
2528    fi
2529    [ $DEBUG -eq 1 ] && ${ECHO} "  RootDN ... OK"
2530    [ $DEBUG -eq 1 ] && ${ECHO} "  RootDN passwd ... OK"
2531
2532    # Check if the server supports the VLV.
2533    chk_vlv_indexes
2534    [ $DEBUG -eq 1 ] && ${ECHO} "  VLV indexes ... OK"
2535
2536    # Check LDAP suffix
2537    validate_suffix
2538    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP suffix ... OK"
2539}
2540
2541#
2542# format_string(): take a string as argument and set FMT_STR
2543# to be the same string formatted as follow:
2544# - only lower case characters
2545# - no unnecessary spaces around , and =
2546#
2547format_string()
2548{
2549    FMT_STR=`${ECHO} "$1" | tr '[A-Z]' '[a-z]' |
2550	sed -e 's/[ ]*,[ ]*/,/g' -e 's/[ ]*=[ ]*/=/g'`
2551}
2552
2553#
2554# prepare for the suffix entry creation
2555#
2556# input  : LDAP_BASEDN, LDAP_SUFFIX - base dn and suffix;
2557# in/out : LDAP_SUFFIX_OBJ, LDAP_SUFFIX_ACI - initially may come from config.
2558# output : NEED_CREATE_BACKEND - backend for this suffix needs to be created;
2559#          _RDN, _ATT, _VAL - suffix's RDN, id attribute name and its value.
2560# return : 0 - success, otherwise error.
2561#
2562prep_create_sfx_entry()
2563{
2564    [ $DEBUG -eq 1 ] && ${ECHO} "In prep_create_sfx_entry()"
2565
2566    # check whether suffix corresponds to base dn
2567    format_string "${LDAP_BASEDN}"
2568    ${ECHO} ",${FMT_STR}" | ${GREP} ",${LDAP_SUFFIX}$" >/dev/null 2>&1 ||
2569    {
2570	display_msg sfx_not_suitable
2571	return 1
2572    }
2573
2574    # parse LDAP_SUFFIX
2575    _RDN=`${ECHO} "${LDAP_SUFFIX}" | cut -d, -f1`
2576    _ATT=`${ECHO} "${_RDN}" | cut -d= -f1`
2577    _VAL=`${ECHO} "${_RDN}" | cut -d= -f2-`
2578
2579    # find out an objectclass for suffix entry if it is not defined yet
2580    [ -z "${LDAP_SUFFIX_OBJ}" ] &&
2581    {
2582	get_objectclass ${_ATT}
2583	[ -z "${_ATTR_NAME}" ] &&
2584	{
2585		display_msg obj_not_found
2586		return 1
2587	}
2588	LDAP_SUFFIX_OBJ=${_ATTR_NAME}
2589    }
2590    [ $DEBUG -eq 1 ] && ${ECHO} "Suffix entry object is ${LDAP_SUFFIX_OBJ}"
2591
2592    # find out an aci for suffix entry if it is not defined yet
2593    [ -z "${LDAP_SUFFIX_ACI}" ] &&
2594    {
2595	# set Directory Server default aci
2596	LDAP_SUFFIX_ACI=`cat <<EOF
2597aci: (targetattr != "userPassword || passwordHistory || passwordExpirationTime
2598 || passwordExpWarned || passwordRetryCount || retryCountResetTime ||
2599 accountUnlockTime || passwordAllowChangeTime")
2600 (
2601   version 3.0;
2602   acl "Anonymous access";
2603   allow (read, search, compare) userdn = "ldap:///anyone";
2604 )
2605aci: (targetattr != "nsroledn || aci || nsLookThroughLimit || nsSizeLimit ||
2606 nsTimeLimit || nsIdleTimeout || passwordPolicySubentry ||
2607 passwordExpirationTime || passwordExpWarned || passwordRetryCount ||
2608 retryCountResetTime || accountUnlockTime || passwordHistory ||
2609 passwordAllowChangeTime")
2610 (
2611   version 3.0;
2612   acl "Allow self entry modification except for some attributes";
2613   allow (write) userdn = "ldap:///self";
2614 )
2615aci: (targetattr = "*")
2616 (
2617   version 3.0;
2618   acl "Configuration Administrator";
2619   allow (all) userdn = "ldap:///uid=admin,ou=Administrators,
2620                         ou=TopologyManagement,o=NetscapeRoot";
2621 )
2622aci: (targetattr ="*")
2623 (
2624   version 3.0;
2625   acl "Configuration Administrators Group";
2626   allow (all) groupdn = "ldap:///cn=Configuration Administrators,
2627                          ou=Groups,ou=TopologyManagement,o=NetscapeRoot";
2628 )
2629EOF
2630`
2631    }
2632    [ $DEBUG -eq 1 ] && cat <<EOF
2633DEBUG: ACI for ${LDAP_SUFFIX} is
2634${LDAP_SUFFIX_ACI}
2635EOF
2636
2637    NEED_CREATE_BACKEND=
2638
2639    # check the suffix mapping tree ...
2640    # if mapping exists, suffix should work, otherwise DS inconsistent
2641    # NOTE: -b 'cn=mapping tree,cn=config' -s one 'cn=\"$1\"' won't work
2642    #       in case of 'cn' value in LDAP is not quoted by '"',
2643    #       -b 'cn=\"$1\",cn=mapping tree,cn=config' works in all cases
2644    ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} \
2645	-b 'cn=\"${LDAP_SUFFIX}\",cn=mapping tree,cn=config' \
2646	-s base 'objectclass=*' dn ${VERB}" &&
2647    {
2648	[ $DEBUG -eq 1 ] && ${ECHO} "Suffix mapping already exists"
2649	# get_backend() either gets IDS_DATABASE or exits
2650	get_backend
2651	return 0
2652    }
2653
2654    # no suffix mapping, just in case check ldbm backends consistency -
2655    # there are must be NO any databases pointing to LDAP_SUFFIX
2656    [ -n "`${EVAL} \"${LDAPSEARCH} ${LDAP_ARGS} \
2657	-b 'cn=ldbm database,cn=plugins,cn=config' \
2658	-s one 'nsslapd-suffix=${LDAP_SUFFIX}' dn\" 2>/dev/null`" ] &&
2659    {
2660	display_msg sfx_config_incons
2661	return 1
2662    }
2663
2664    # ok, no suffix mapping, no ldbm database
2665    [ $DEBUG -eq 1 ] && ${ECHO} "DEBUG: backend needs to be created ..."
2666    NEED_CREATE_BACKEND=1
2667    return 0
2668}
2669
2670#
2671# prepare for the suffix backend creation
2672#
2673# input  : IDS_DATABASE - requested ldbm db name (must be not null)
2674# in/out : IDS_DATABASE_AVAIL - available ldbm db name
2675# return : 0 - ldbm db name ok
2676#          1 - IDS_DATABASE exists,
2677#              so IDS_DATABASE_AVAIL contains available name
2678#          2 - unable to find any available name
2679#
2680prep_create_sfx_backend()
2681{
2682    [ $DEBUG -eq 1 ] && ${ECHO} "In prep_create_sfx_backend()"
2683
2684    # check if requested name available
2685    [ "${IDS_DATABASE}" = "${IDS_DATABASE_AVAIL}" ] && return 0
2686
2687    # get the list of database names start with a requested name
2688    _LDBM_DBS=`${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} \
2689	-b 'cn=ldbm database,cn=plugins,cn=config' \
2690	-s one 'cn=${IDS_DATABASE}*' cn"` 2>/dev/null
2691
2692    # find available db name based on a requested name
2693    _i=""; _i_MAX=10
2694    while [ ${_i:-0} -lt ${_i_MAX} ]
2695    do
2696	_name="${IDS_DATABASE}${_i}"
2697	${ECHO} "${_LDBM_DBS}" | ${GREP} -i "^cn=${_name}$" >/dev/null 2>&1 ||
2698	{
2699		IDS_DATABASE_AVAIL="${_name}"
2700		break
2701	}
2702	_i=`expr ${_i:-0} + 1`
2703    done
2704
2705    [ "${IDS_DATABASE}" = "${IDS_DATABASE_AVAIL}" ] && return 0
2706
2707    [ -n "${IDS_DATABASE_AVAIL}" ] &&
2708    {
2709	display_msg ldbm_db_exist
2710	return 1
2711    }
2712
2713    display_msg unable_find_db_name
2714    return 2
2715}
2716
2717#
2718# add suffix if needed,
2719#     suffix entry and backend MUST be prepared by
2720#     prep_create_sfx_entry and prep_create_sfx_backend correspondingly
2721#
2722# input  : NEED_CREATE_SUFFIX, LDAP_SUFFIX, LDAP_SUFFIX_OBJ, _ATT, _VAL
2723#          LDAP_SUFFIX_ACI, NEED_CREATE_BACKEND, IDS_DATABASE
2724# return : 0 - suffix successfully created, otherwise error occured
2725#
2726add_suffix()
2727{
2728    [ $DEBUG -eq 1 ] && ${ECHO} "In add_suffix()"
2729
2730    [ -n "${NEED_CREATE_SUFFIX}" ] || return 0
2731
2732    [ -n "${NEED_CREATE_BACKEND}" ] &&
2733    {
2734	${EVAL} "${LDAPADD} ${LDAP_ARGS} ${VERB}" <<EOF
2735dn: cn="${LDAP_SUFFIX}",cn=mapping tree,cn=config
2736objectclass: top
2737objectclass: extensibleObject
2738objectclass: nsMappingTree
2739cn: ${LDAP_SUFFIX}
2740nsslapd-state: backend
2741nsslapd-backend: ${IDS_DATABASE}
2742
2743dn: cn=${IDS_DATABASE},cn=ldbm database,cn=plugins,cn=config
2744objectclass: top
2745objectclass: extensibleObject
2746objectclass: nsBackendInstance
2747cn: ${IDS_DATABASE}
2748nsslapd-suffix: ${LDAP_SUFFIX}
2749EOF
2750	[ $? -ne 0 ] &&
2751	{
2752		display_msg create_ldbm_db_error
2753		return 1
2754	}
2755
2756	${ECHO} "  ${STEP}. Database ${IDS_DATABASE} successfully created"
2757	STEP=`expr $STEP + 1`
2758    }
2759
2760    ${EVAL} "${LDAPADD} ${LDAP_ARGS} ${VERB}" <<EOF
2761dn: ${LDAP_SUFFIX}
2762objectclass: ${LDAP_SUFFIX_OBJ}
2763${_ATT}: ${_VAL}
2764${LDAP_SUFFIX_ACI}
2765EOF
2766    [ $? -ne 0 ] &&
2767    {
2768	display_msg create_suffix_entry_error
2769	return 1
2770    }
2771
2772    ${ECHO} "  ${STEP}. Suffix ${LDAP_SUFFIX} successfully created"
2773    STEP=`expr $STEP + 1`
2774    return 0
2775}
2776
2777#
2778# interactively get suffix and related info from a user
2779#
2780# input  : LDAP_BASEDN - Base DN
2781# output : LDAP_SUFFIX - Suffix, _ATT, _VAL - id attribute and its value;
2782#          LDAP_SUFFIX_OBJ, LDAP_SUFFIX_ACI - objectclass and aci;
2783#          NEED_CREATE_BACKEND - tells whether backend needs to be created;
2784#          IDS_DATABASE - prepared ldbm db name
2785# return : 0 - user gave a correct suffix
2786#          1 - suffix given by user cann't be created
2787#
2788get_suffix()
2789{
2790    [ $DEBUG -eq 1 ] && ${ECHO} "In get_suffix()"
2791
2792    while :
2793    do
2794	get_ans "Enter suffix to be created (b=back/h=help):" ${LDAP_BASEDN}
2795	case "${ANS}" in
2796	[Hh] | Help | help | \? ) display_msg create_suffix_help ;;
2797	[Bb] | Back | back | \< ) return 1 ;;
2798	* )
2799		format_string "${ANS}"
2800		LDAP_SUFFIX=${FMT_STR}
2801		prep_create_sfx_entry || continue
2802
2803		[ -n "${NEED_CREATE_BACKEND}" ] &&
2804		{
2805		    IDS_DATABASE_AVAIL= # reset the available db name
2806
2807		    reenter_suffix=
2808		    while :
2809		    do
2810			get_ans "Enter ldbm database name (b=back/h=help):" \
2811				${IDS_DATABASE_AVAIL:-${_VAL}}
2812			case "${ANS}" in
2813			[Hh] | \? ) display_msg enter_ldbm_db_help ;;
2814			[Bb] | \< ) reenter_suffix=1; break ;;
2815			* )
2816				IDS_DATABASE="${ANS}"
2817				prep_create_sfx_backend && break
2818			esac
2819		    done
2820		    [ -n "${reenter_suffix}" ] && continue
2821
2822		    [ $DEBUG -eq 1 ] && cat <<EOF
2823DEBUG: backend name for suffix ${LDAP_SUFFIX} will be ${IDS_DATABASE}
2824EOF
2825		}
2826
2827		# eventually everything is prepared
2828		return 0
2829		;;
2830	esac
2831    done
2832}
2833
2834#
2835# print out a script which sets LDAP suffix related preferences
2836#
2837print_suffix_config()
2838{
2839    cat <<EOF2
2840# LDAP suffix related preferences used only if needed
2841IDS_DATABASE="${IDS_DATABASE}" 
2842LDAP_SUFFIX_OBJ="$LDAP_SUFFIX_OBJ"
2843LDAP_SUFFIX_ACI=\`cat <<EOF
2844${LDAP_SUFFIX_ACI}
2845EOF
2846\`
2847export IDS_DATABASE LDAP_SUFFIX_OBJ LDAP_SUFFIX_ACI
2848EOF2
2849}
2850
2851#
2852# check_basedn_suffix(): check that there is an existing
2853# valid suffix to hold current base DN
2854# return:
2855#   0: valid suffix found or new one should be created,
2856#      NEED_CREATE_SUFFIX flag actually indicates that
2857#   1: some error occures
2858#
2859check_basedn_suffix()
2860{
2861    [ $DEBUG -eq 1 ] && ${ECHO} "In check_basedn_suffix()"
2862
2863    NEED_CREATE_SUFFIX=
2864
2865    # find out existing suffixes
2866    discover_serv_suffix
2867
2868    ${ECHO} "  Validating LDAP Base DN and Suffix ..."
2869
2870    # check that LDAP Base DN might be added
2871    cur_ldap_entry=${LDAP_BASEDN}
2872    prev_ldap_entry=
2873    while [ "${cur_ldap_entry}" != "${prev_ldap_entry}" ]
2874    do
2875	[ $DEBUG -eq 1 ] && ${ECHO} "testing LDAP entry: ${cur_ldap_entry}"
2876	${LDAPSEARCH} ${SERVER_ARGS} -b "${cur_ldap_entry}" \
2877		-s one "objectclass=*" > /dev/null 2>&1
2878	if [ $? -eq 0 ]; then
2879	    break
2880	else
2881	    prev_ldap_entry=${cur_ldap_entry}
2882	    cur_ldap_entry=`${ECHO} ${cur_ldap_entry} | cut -f2- -d','`
2883	fi
2884    done
2885
2886    if [ "${cur_ldap_entry}" = "${prev_ldap_entry}" ]; then
2887	${ECHO} "  No valid suffixes were found for Base DN ${LDAP_BASEDN}"
2888
2889	NEED_CREATE_SUFFIX=1
2890	return 0
2891
2892    else
2893	[ $DEBUG -eq 1 ] && ${ECHO} "found valid LDAP entry: ${cur_ldap_entry}"
2894
2895	# Now looking for relevant suffix for this entry.
2896	# LDAP_SUFFIX will then be used to add necessary
2897	# base objects. See add_base_objects().
2898	format_string "${cur_ldap_entry}"
2899	lower_entry="${FMT_STR}"
2900	[ $DEBUG -eq 1 ] && ${ECHO} "final suffix list: ${LDAP_SUFFIX_LIST}"
2901	oIFS=$IFS
2902	[ $DEBUG -eq 1 ] && ${ECHO} "setting IFS to new line"
2903	IFS='
2904'
2905	for suff in ${LDAP_SUFFIX_LIST}
2906	do
2907	    [ $DEBUG -eq 1 ] && ${ECHO} "testing suffix: ${suff}"
2908	    format_string "${suff}"
2909	    lower_suff="${FMT_STR}"
2910	    if [ "${lower_entry}" = "${lower_suff}" ]; then
2911		LDAP_SUFFIX="${suff}"
2912		break
2913	    else
2914		dcstmp=`basename "${lower_entry}" "${lower_suff}"`
2915		if [ "${dcstmp}" = "${lower_entry}" ]; then
2916		    # invalid suffix, try next one
2917		    continue
2918		else
2919		    # valid suffix found
2920		    LDAP_SUFFIX="${suff}"
2921		    break
2922		fi
2923	    fi
2924	done
2925	[ $DEBUG -eq 1 ] && ${ECHO} "setting IFS to original value"
2926	IFS=$oIFS
2927
2928	[ $DEBUG -eq 1 ] && ${ECHO} "LDAP_SUFFIX: ${LDAP_SUFFIX}"
2929
2930	if [ -z "${LDAP_SUFFIX}" ]; then
2931	    # should not happen, since we found the entry
2932	    ${ECHO} "Could not find a valid suffix for ${LDAP_BASEDN}."
2933	    ${ECHO} "Exiting."
2934	    return 1
2935	fi
2936
2937	# Getting relevant database (backend)
2938	# IDS_DATABASE will then be used to create indexes.
2939	get_backend
2940
2941	return 0
2942    fi
2943}
2944
2945#
2946# discover_serv_suffix(): This function queries the server to find
2947#    suffixes available
2948#  return: 0: OK, suffix found
2949#          1: suffix not determined
2950discover_serv_suffix()
2951{
2952    [ $DEBUG -eq 1 ] && ${ECHO} "In discover_serv_suffix()"
2953
2954    # Search the server for the TOP of the TREE.
2955    ${LDAPSEARCH} ${SERVER_ARGS} -b "" -s base "objectclass=*" > ${TMPDIR}/checkTOP 2>&1
2956    ${GREP} -i namingcontexts ${TMPDIR}/checkTOP | \
2957	${GREP} -i -v NetscapeRoot > ${TMPDIR}/treeTOP
2958    NUM_TOP=`wc -l ${TMPDIR}/treeTOP | awk '{print $1}'`
2959    case $NUM_TOP in
2960	0)
2961	    [ $DEBUG -eq 1 ] && ${ECHO} "DEBUG: No suffix found in LDAP tree"
2962	    return 1
2963	    ;;
2964	*)  # build the list of suffixes; take out 'namingContexts=' in
2965	    # each line of ${TMPDIR}/treeTOP
2966	    LDAP_SUFFIX_LIST=`cat ${TMPDIR}/treeTOP |
2967		awk '{ printf("%s\n",substr($0,16,length-15)) }'`
2968	    ;;
2969    esac
2970
2971    [ $DEBUG -eq 1 ] && ${ECHO} "  LDAP_SUFFIX_LIST = $LDAP_SUFFIX_LIST"
2972    return 0
2973}
2974
2975
2976#
2977# modify_cn(): Change the cn from MUST to MAY in ipNetwork.
2978#
2979modify_cn()
2980{
2981    [ $DEBUG -eq 1 ] && ${ECHO} "In modify_cn()"
2982
2983    ( cat <<EOF
2984dn: cn=schema
2985changetype: modify
2986add: objectclasses
2987objectclasses: ( 1.3.6.1.1.1.2.7 NAME 'ipNetwork' DESC 'Standard LDAP objectclass' SUP top STRUCTURAL MUST ( ipNetworkNumber ) MAY ( ipNetmaskNumber $ manager $ cn $ l $ description ) X-ORIGIN 'RFC 2307' ))
2988EOF
2989) > ${TMPDIR}/ipNetwork_cn
2990
2991    # Modify the cn for ipNetwork.
2992    ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/ipNetwork_cn ${VERB}"
2993    if [ $? -ne 0 ]; then
2994	${ECHO} "  ERROR: update of cn for ipNetwork failed!"
2995	cleanup
2996	exit 1
2997    fi
2998}
2999
3000
3001# modify_timelimit(): Modify timelimit to user value.
3002modify_timelimit()
3003{
3004    [ $DEBUG -eq 1 ] && ${ECHO} "In modify_timelimit()"
3005
3006    # Here doc to modify timelimit.
3007    ( cat <<EOF
3008dn: cn=config
3009changetype: modify
3010replace: nsslapd-timelimit
3011nsslapd-timelimit: ${IDS_TIMELIMIT}
3012EOF
3013) > ${TMPDIR}/ids_timelimit
3014
3015    # Add the entry.
3016    ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/ids_timelimit ${VERB}"
3017    if [ $? -ne 0 ]; then
3018	${ECHO} "  ERROR: update of nsslapd-timelimit failed!"
3019	cleanup
3020	exit 1
3021    fi
3022
3023    # Display messages for modifications made in patch.
3024    ${ECHO} "  ${STEP}. Changed timelimit to ${IDS_TIMELIMIT} in cn=config."
3025    STEP=`expr $STEP + 1`
3026}
3027
3028
3029# modify_sizelimit(): Modify sizelimit to user value.
3030modify_sizelimit()
3031{
3032    [ $DEBUG -eq 1 ] && ${ECHO} "In modify_sizelimit()"
3033
3034    # Here doc to modify sizelimit.
3035    ( cat <<EOF
3036dn: cn=config
3037changetype: modify
3038replace: nsslapd-sizelimit
3039nsslapd-sizelimit: ${IDS_SIZELIMIT}
3040EOF
3041) > ${TMPDIR}/ids_sizelimit
3042
3043    # Add the entry.
3044    ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/ids_sizelimit ${VERB}"
3045    if [ $? -ne 0 ]; then
3046	${ECHO} "  ERROR: update of nsslapd-sizelimit failed!"
3047	cleanup
3048	exit 1
3049    fi
3050
3051    # Display messages for modifications made in patch.
3052    ${ECHO} "  ${STEP}. Changed sizelimit to ${IDS_SIZELIMIT} in cn=config."
3053    STEP=`expr $STEP + 1`
3054}
3055
3056
3057# modify_pwd_crypt(): Modify the passwd storage scheme to support CRYPT.
3058modify_pwd_crypt()
3059{
3060    [ $DEBUG -eq 1 ] && ${ECHO} "In modify_pwd_crypt()"
3061
3062    # Here doc to modify passwordstoragescheme.
3063    # IDS 5.2 moved passwordchangesceme off to a new data structure.
3064    if [ $IDS_MAJVER -le 5 ] && [ $IDS_MINVER -le 1 ]; then
3065	( cat <<EOF
3066dn: cn=config
3067changetype: modify
3068replace: passwordstoragescheme
3069passwordstoragescheme: crypt
3070EOF
3071	) > ${TMPDIR}/ids_crypt
3072    else
3073	( cat <<EOF
3074dn: cn=Password Policy,cn=config
3075changetype: modify
3076replace: passwordstoragescheme
3077passwordstoragescheme: crypt
3078EOF
3079	) > ${TMPDIR}/ids_crypt
3080    fi
3081
3082    # Add the entry.
3083    ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/ids_crypt ${VERB}"
3084    if [ $? -ne 0 ]; then
3085	${ECHO} "  ERROR: update of passwordstoragescheme failed!"
3086	cleanup
3087	exit 1
3088    fi
3089
3090    # Display messages for modifications made in patch.
3091    ${ECHO} "  ${STEP}. Changed passwordstoragescheme to \"crypt\" in cn=config."
3092    STEP=`expr $STEP + 1`
3093}
3094
3095
3096#
3097# add_eq_indexes(): Add indexes to improve search performance.
3098#
3099add_eq_indexes()
3100{
3101    [ $DEBUG -eq 1 ] && ${ECHO} "In add_eq_indexes()"
3102
3103    # Set eq indexes to add.
3104    _INDEXES="uidNumber ipNetworkNumber gidnumber oncrpcnumber automountKey"
3105
3106    # Set _EXT to use as shortcut.
3107    _EXT="cn=index,cn=${IDS_DATABASE},cn=ldbm database,cn=plugins,cn=config"
3108
3109
3110    # Display message to id current step.
3111    ${ECHO} "  ${STEP}. Processing eq,pres indexes:"
3112    STEP=`expr $STEP + 1`
3113
3114    # For loop to create indexes.
3115    for i in ${_INDEXES}; do
3116	[ $DEBUG -eq 1 ] && ${ECHO} "  Adding index for ${i}"
3117
3118	# Check if entry exists first, if so, skip to next.
3119	${LDAPSEARCH} ${SERVER_ARGS} -b "cn=${i},${_EXT}" -s base "objectclass=*" > /dev/null 2>&1
3120	if [ $? -eq 0 ]; then
3121	    # Display index skipped.
3122	    ${ECHO} "      ${i} (eq,pres) skipped already exists"
3123	    continue
3124	fi
3125
3126	# Here doc to create LDIF.
3127	( cat <<EOF
3128dn: cn=${i},${_EXT}
3129objectClass: top
3130objectClass: nsIndex
3131cn: ${i}
3132nsSystemIndex: false
3133nsIndexType: pres
3134nsIndexType: eq
3135EOF
3136) > ${TMPDIR}/index_${i}
3137
3138	# Add the index.
3139	${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/index_${i} ${VERB}"
3140	if [ $? -ne 0 ]; then
3141	    ${ECHO} "  ERROR: Adding EQ,PRES index for ${i} failed!"
3142	    cleanup
3143	    exit 1
3144	fi
3145
3146	# Build date for task name.
3147	_YR=`date '+%y'`
3148	_MN=`date '+%m'`
3149	_DY=`date '+%d'`
3150	_H=`date '+%H'`
3151	_M=`date '+%M'`
3152	_S=`date '+%S'`
3153
3154	# Build task name
3155	TASKNAME="${i}_${_YR}_${_MN}_${_DY}_${_H}_${_M}_${_S}"
3156
3157	# Build the task entry to add.
3158	( cat <<EOF
3159dn: cn=${TASKNAME}, cn=index, cn=tasks, cn=config
3160changetype: add
3161objectclass: top
3162objectclass: extensibleObject
3163cn: ${TASKNAME}
3164nsInstance: ${IDS_DATABASE}
3165nsIndexAttribute: ${i}
3166EOF
3167) > ${TMPDIR}/task_${i}
3168
3169	# Add the task.
3170	${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/task_${i} ${VERB}"
3171	if [ $? -ne 0 ]; then
3172	    ${ECHO} "  ERROR: Adding task for ${i} failed!"
3173	    cleanup
3174	    exit 1
3175	fi
3176
3177	# Wait for task to finish, display current status.
3178	while :
3179	do
3180	    eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=index, cn=tasks, cn=config\" -s sub \"objectclass=*\" > ${TMPDIR}/istask_${i} 2>&1"
3181	    ${GREP} ${TASKNAME} ${TMPDIR}/istask_${i} > /dev/null 2>&1
3182	    if [ $? -ne 0 ]; then
3183		break
3184	    fi
3185	    eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=index,cn=tasks,cn=config\" -s one \"objectclass=*\" nstaskstatus | ${GREP} -i nstaskstatus | cut -d\":\" -f2 > ${TMPDIR}/wait_task_${i}"
3186	    TASK_STATUS=`head -1 ${TMPDIR}/wait_task_${i}`
3187	    ${ECHO} "      ${i} (eq,pres)  $TASK_STATUS                  \r\c"
3188	    ${ECHO} "$TASK_STATUS" | ${GREP} "Finished" > /dev/null 2>&1
3189	    if [ $? -eq 0 ]; then
3190		break
3191	    fi
3192	    sleep 2
3193	done
3194
3195	# Print newline because of \c.
3196	${ECHO} " "
3197    done
3198}
3199
3200
3201#
3202# add_sub_indexes(): Add indexes to improve search performance.
3203#
3204add_sub_indexes()
3205{
3206    [ $DEBUG -eq 1 ] && ${ECHO} "In add_sub_indexes()"
3207
3208    # Set eq indexes to add.
3209    _INDEXES="ipHostNumber membernisnetgroup nisnetgrouptriple"
3210
3211    # Set _EXT to use as shortcut.
3212    _EXT="cn=index,cn=${IDS_DATABASE},cn=ldbm database,cn=plugins,cn=config"
3213
3214
3215    # Display message to id current step.
3216    ${ECHO} "  ${STEP}. Processing eq,pres,sub indexes:"
3217    STEP=`expr $STEP + 1`
3218
3219    # For loop to create indexes.
3220    for i in ${_INDEXES}; do
3221	[ $DEBUG -eq 1 ] && ${ECHO} "  Adding index for ${i}"
3222
3223	# Check if entry exists first, if so, skip to next.
3224	${LDAPSEARCH} ${SERVER_ARGS} -b "cn=${i},${_EXT}" -s base "objectclass=*" > /dev/null 2>&1
3225	if [ $? -eq 0 ]; then
3226	    # Display index skipped.
3227	    ${ECHO} "      ${i} (eq,pres,sub) skipped already exists"
3228	    continue
3229	fi
3230
3231	# Here doc to create LDIF.
3232	( cat <<EOF
3233dn: cn=${i},${_EXT}
3234objectClass: top
3235objectClass: nsIndex
3236cn: ${i}
3237nsSystemIndex: false
3238nsIndexType: pres
3239nsIndexType: eq
3240nsIndexType: sub
3241EOF
3242) > ${TMPDIR}/index_${i}
3243
3244	# Add the index.
3245	${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/index_${i} ${VERB}"
3246	if [ $? -ne 0 ]; then
3247	    ${ECHO} "  ERROR: Adding EQ,PRES,SUB index for ${i} failed!"
3248	    cleanup
3249	    exit 1
3250	fi
3251
3252	# Build date for task name.
3253	_YR=`date '+%y'`
3254	_MN=`date '+%m'`
3255	_DY=`date '+%d'`
3256	_H=`date '+%H'`
3257	_M=`date '+%M'`
3258	_S=`date '+%S'`
3259
3260	# Build task name
3261	TASKNAME="${i}_${_YR}_${_MN}_${_DY}_${_H}_${_M}_${_S}"
3262
3263	# Build the task entry to add.
3264	( cat <<EOF
3265dn: cn=${TASKNAME}, cn=index, cn=tasks, cn=config
3266changetype: add
3267objectclass: top
3268objectclass: extensibleObject
3269cn: ${TASKNAME}
3270nsInstance: ${IDS_DATABASE}
3271nsIndexAttribute: ${i}
3272EOF
3273) > ${TMPDIR}/task_${i}
3274
3275	# Add the task.
3276	${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/task_${i} ${VERB}"
3277	if [ $? -ne 0 ]; then
3278	    ${ECHO} "  ERROR: Adding task for ${i} failed!"
3279	    cleanup
3280	    exit 1
3281	fi
3282
3283	# Wait for task to finish, display current status.
3284	while :
3285	do
3286	    eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=index, cn=tasks, cn=config\" -s sub \"objectclass=*\" > ${TMPDIR}/istask_${i} 2>&1"
3287	    ${GREP} ${TASKNAME} ${TMPDIR}/istask_${i} > /dev/null 2>&1
3288	    if [ $? -ne 0 ]; then
3289		break
3290	    fi
3291	    eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=index,cn=tasks,cn=config\" -s one \"objectclass=*\" nstaskstatus | ${GREP} -i nstaskstatus | cut -d\":\" -f2 > ${TMPDIR}/wait_task_${i}"
3292	    TASK_STATUS=`head -1 ${TMPDIR}/wait_task_${i}`
3293	    ${ECHO} "      ${i} (eq,pres,sub)  $TASK_STATUS                  \r\c"
3294	    ${ECHO} "$TASK_STATUS" | ${GREP} "Finished" > /dev/null 2>&1
3295	    if [ $? -eq 0 ]; then
3296		break
3297	    fi
3298	    sleep 2
3299	done
3300
3301	# Print newline because of \c.
3302	${ECHO} " "
3303    done
3304}
3305
3306
3307#
3308# add_vlv_indexes(): Add VLV indexes to improve search performance.
3309#
3310add_vlv_indexes()
3311{
3312    [ $DEBUG -eq 1 ] && ${ECHO} "In add_vlv_indexes()"
3313
3314    # Set eq indexes to add.
3315    # Note semi colon separators because some filters contain colons
3316    _INDEX1="${LDAP_DOMAIN}.getgrent;${LDAP_DOMAIN}_group_vlv_index;ou=group;objectClass=posixGroup"
3317    _INDEX2="${LDAP_DOMAIN}.gethostent;${LDAP_DOMAIN}_hosts_vlv_index;ou=hosts;objectClass=ipHost"
3318    _INDEX3="${LDAP_DOMAIN}.getnetent;${LDAP_DOMAIN}_networks_vlv_index;ou=networks;objectClass=ipNetwork"
3319    _INDEX4="${LDAP_DOMAIN}.getpwent;${LDAP_DOMAIN}_passwd_vlv_index;ou=people;objectClass=posixAccount"
3320    _INDEX5="${LDAP_DOMAIN}.getrpcent;${LDAP_DOMAIN}_rpc_vlv_index;ou=rpc;objectClass=oncRpc"
3321    _INDEX6="${LDAP_DOMAIN}.getspent;${LDAP_DOMAIN}_shadow_vlv_index;ou=people;objectClass=shadowAccount"
3322
3323    # Indexes added during NIS to LDAP transition
3324    _INDEX7="${LDAP_DOMAIN}.getauhoent;${LDAP_DOMAIN}_auho_vlv_index;automountmapname=auto_home;objectClass=automount"
3325    _INDEX8="${LDAP_DOMAIN}.getsoluent;${LDAP_DOMAIN}_solu_vlv_index;ou=people;objectClass=SolarisUserAttr"
3326    _INDEX9="${LDAP_DOMAIN}.getauduent;${LDAP_DOMAIN}_audu_vlv_index;ou=people;objectClass=SolarisAuditUser"
3327    _INDEX10="${LDAP_DOMAIN}.getauthent;${LDAP_DOMAIN}_auth_vlv_index;ou=SolarisAuthAttr;objectClass=SolarisAuthAttr"
3328    _INDEX11="${LDAP_DOMAIN}.getexecent;${LDAP_DOMAIN}_exec_vlv_index;ou=SolarisProfAttr;&(objectClass=SolarisExecAttr)(SolarisKernelSecurityPolicy=*)"
3329    _INDEX12="${LDAP_DOMAIN}.getprofent;${LDAP_DOMAIN}_prof_vlv_index;ou=SolarisProfAttr;&(objectClass=SolarisProfAttr)(SolarisAttrLongDesc=*)"
3330    _INDEX13="${LDAP_DOMAIN}.getmailent;${LDAP_DOMAIN}_mail_vlv_index;ou=aliases;objectClass=mailGroup"
3331    _INDEX14="${LDAP_DOMAIN}.getbootent;${LDAP_DOMAIN}__boot_vlv_index;ou=ethers;&(objectClass=bootableDevice)(bootParameter=*)"
3332    _INDEX15="${LDAP_DOMAIN}.getethent;${LDAP_DOMAIN}_ethers_vlv_index;ou=ethers;&(objectClass=ieee802Device)(macAddress=*)"
3333    _INDEX16="${LDAP_DOMAIN}.getngrpent;${LDAP_DOMAIN}_netgroup_vlv_index;ou=netgroup;objectClass=nisNetgroup"
3334    _INDEX17="${LDAP_DOMAIN}.getipnent;${LDAP_DOMAIN}_ipn_vlv_index;ou=networks;&(objectClass=ipNetwork)(cn=*)"
3335    _INDEX18="${LDAP_DOMAIN}.getmaskent;${LDAP_DOMAIN}_mask_vlv_index;ou=networks;&(objectClass=ipNetwork)(ipNetmaskNumber=*)"
3336    _INDEX19="${LDAP_DOMAIN}.getprent;${LDAP_DOMAIN}_pr_vlv_index;ou=printers;objectClass=printerService"
3337    _INDEX20="${LDAP_DOMAIN}.getip4ent;${LDAP_DOMAIN}_ip4_vlv_index;ou=hosts;&(objectClass=ipHost)(ipHostNumber=*.*)"
3338    _INDEX21="${LDAP_DOMAIN}.getip6ent;${LDAP_DOMAIN}_ip6_vlv_index;ou=hosts;&(objectClass=ipHost)(ipHostNumber=*:*)"
3339
3340    _INDEXES="$_INDEX1 $_INDEX2 $_INDEX3 $_INDEX4 $_INDEX5 $_INDEX6 $_INDEX7 $_INDEX8 $_INDEX9 $_INDEX10 $_INDEX11 $_INDEX12 $_INDEX13 $_INDEX14 $_INDEX15 $_INDEX16 $_INDEX17 $_INDEX18 $_INDEX19 $_INDEX20 $_INDEX21 "
3341
3342
3343    # Set _EXT to use as shortcut.
3344    _EXT="cn=${IDS_DATABASE},cn=ldbm database,cn=plugins,cn=config"
3345
3346
3347    # Display message to id current step.
3348    ${ECHO} "  ${STEP}. Processing VLV indexes:"
3349    STEP=`expr $STEP + 1`
3350
3351    # Reset temp file for vlvindex commands.
3352    [ -f ${TMPDIR}/vlvindex_list ] &&  rm ${TMPDIR}/vlvindex_list
3353    touch ${TMPDIR}/vlvindex_list
3354
3355    # Get the instance name from iDS server.
3356    _INSTANCE="<server-instance>"    # Default to old output.
3357
3358    eval "${LDAPSEARCH} -v ${LDAP_ARGS} -b \"cn=config\" -s base \"objectclass=*\" nsslapd-instancedir | ${GREP} 'nsslapd-instancedir=' | cut -d'=' -f2- > ${TMPDIR}/instance_name 2>&1"
3359
3360    ${GREP} "slapd-" ${TMPDIR}/instance_name > /dev/null 2>&1 # Check if seems right?
3361    if [ $? -eq 0 ]; then # If success, grab name after "slapd-".
3362	_INST_DIR=`cat ${TMPDIR}/instance_name`
3363	_INSTANCE=`basename "${_INST_DIR}" | cut -d'-' -f2-`
3364    fi
3365
3366    # For loop to create indexes.
3367    for p in ${_INDEXES}; do
3368	[ $DEBUG -eq 1 ] && ${ECHO} "  Adding index for ${i}"
3369
3370	# Break p (pair) into i and j parts.
3371        i=`${ECHO} $p | cut -d';' -f1`
3372        j=`${ECHO} $p | cut -d';' -f2`
3373        k=`${ECHO} $p | cut -d';' -f3`
3374        m=`${ECHO} $p | cut -d';' -f4`
3375
3376	# Set _jEXT to use as shortcut.
3377	_jEXT="cn=${j},${_EXT}"
3378
3379	# Check if entry exists first, if so, skip to next.
3380	${LDAPSEARCH} ${SERVER_ARGS} -b "cn=${i},${_jEXT}" -s base "objectclass=*" > /dev/null 2>&1
3381	if [ $? -eq 0 ]; then
3382	    # Display index skipped.
3383	    ${ECHO} "      ${i} vlv_index skipped already exists"
3384	    continue
3385	fi
3386
3387	# Compute the VLV Scope from the LDAP_SEARCH_SCOPE.
3388	# NOTE: A value of "base (0)" does not make sense.
3389        case "$LDAP_SEARCH_SCOPE" in
3390            sub) VLV_SCOPE="2" ;;
3391            *)   VLV_SCOPE="1" ;;
3392        esac
3393
3394	# Here doc to create LDIF.
3395	( cat <<EOF
3396dn: ${_jEXT}
3397objectClass: top
3398objectClass: vlvSearch
3399cn: ${j}
3400vlvbase: ${k},${LDAP_BASEDN}
3401vlvscope: ${VLV_SCOPE}
3402vlvfilter: (${m})
3403aci: (target="ldap:///${_jEXT}")(targetattr="*")(version 3.0; acl "Config";allow(read,search,compare)userdn="ldap:///anyone";)
3404
3405dn: cn=${i},${_jEXT}
3406cn: ${i}
3407vlvSort: cn uid
3408objectclass: top
3409objectclass: vlvIndex
3410EOF
3411) > ${TMPDIR}/vlv_index_${i}
3412
3413	# Add the index.
3414	${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/vlv_index_${i} ${VERB}"
3415	if [ $? -ne 0 ]; then
3416	    ${ECHO} "  ERROR: Adding VLV index for ${i} failed!"
3417	    cleanup
3418	    exit 1
3419	fi
3420
3421	# Print message that index was created.
3422	${ECHO} "      ${i} vlv_index   Entry created"
3423
3424	# Add command to list of vlvindex commands to run.
3425	${ECHO} "  directoryserver -s ${_INSTANCE} vlvindex -n ${IDS_DATABASE} -T ${i}" >> ${TMPDIR}/vlvindex_list
3426    done
3427}
3428
3429
3430#
3431# display_vlv_cmds(): Display VLV index commands to run on server.
3432#
3433display_vlv_cmds()
3434{
3435    if [ -s "${TMPDIR}/vlvindex_list" ]; then
3436	display_msg display_vlv_list
3437	cat ${TMPDIR}/vlvindex_list
3438    fi
3439}
3440
3441
3442#
3443# update_schema_attr(): Update Schema to support Naming.
3444#
3445update_schema_attr()
3446{
3447    [ $DEBUG -eq 1 ] && ${ECHO} "In update_schema_attr()"
3448
3449    ( cat <<EOF
3450dn: cn=schema
3451changetype: modify
3452add: attributetypes
3453attributetypes: ( 1.3.6.1.1.1.1.28 NAME 'nisPublickey' DESC 'NIS public key' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
3454attributetypes: ( 1.3.6.1.1.1.1.29 NAME 'nisSecretkey' DESC 'NIS secret key' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
3455attributetypes: ( 1.3.6.1.1.1.1.30 NAME 'nisDomain' DESC 'NIS domain' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
3456attributetypes: ( 1.3.6.1.1.1.1.31 NAME 'automountMapName' DESC 'automount Map Name' EQUALITY caseExactIA5Match SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' SINGLE-VALUE )
3457attributetypes: ( 1.3.6.1.1.1.1.32 NAME 'automountKey' DESC 'automount Key Value' EQUALITY caseExactIA5Match SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' SINGLE-VALUE )
3458attributetypes: ( 1.3.6.1.1.1.1.33 NAME 'automountInformation' DESC 'automount information' EQUALITY caseExactIA5Match SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' SINGLE-VALUE )
3459attributetypes: ( 1.3.6.1.4.1.42.2.27.1.1.12 NAME 'nisNetIdUser' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' )
3460attributetypes: ( 1.3.6.1.4.1.42.2.27.1.1.13 NAME 'nisNetIdGroup' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' )
3461attributetypes: ( 1.3.6.1.4.1.42.2.27.1.1.14 NAME 'nisNetIdHost' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' )
3462attributetypes: ( rfc822mailMember-oid NAME 'rfc822mailMember' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' )
3463attributetypes: ( 2.16.840.1.113730.3.1.30 NAME 'mgrpRFC822MailMember' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
3464attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.15 NAME 'SolarisLDAPServers' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
3465attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.16 NAME 'SolarisSearchBaseDN' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE )
3466attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.17 NAME 'SolarisCacheTTL' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3467attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.18 NAME 'SolarisBindDN' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE )
3468attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.19 NAME 'SolarisBindPassword' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' SINGLE-VALUE )
3469attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.20 NAME 'SolarisAuthMethod' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15')
3470attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.21 NAME 'SolarisTransportSecurity' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15')
3471attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.22 NAME 'SolarisCertificatePath' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' SINGLE-VALUE )
3472attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.23 NAME 'SolarisCertificatePassword' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' SINGLE-VALUE )
3473attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.24 NAME 'SolarisDataSearchDN' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15')
3474attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.25 NAME 'SolarisSearchScope' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3475attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.26 NAME 'SolarisSearchTimeLimit' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE )
3476attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.27 NAME 'SolarisPreferredServer' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15')
3477attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.28 NAME 'SolarisPreferredServerOnly' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3478attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.29 NAME 'SolarisSearchReferral' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3479attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.4 NAME 'SolarisAttrKeyValue' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3480attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.5 NAME 'SolarisAuditAlways' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3481attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.6 NAME 'SolarisAuditNever' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3482attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.7 NAME 'SolarisAttrShortDesc' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3483attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.8 NAME 'SolarisAttrLongDesc' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3484attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.9 NAME 'SolarisKernelSecurityPolicy' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3485attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.10 NAME 'SolarisProfileType' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3486attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.11 NAME 'SolarisProfileId' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' SINGLE-VALUE )
3487attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.12 NAME 'SolarisUserQualifier' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3488attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.13 NAME 'SolarisAttrReserved1' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3489attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.14 NAME 'SolarisAttrReserved2' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3490attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.1 NAME 'SolarisProjectID' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE )
3491attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.2 NAME 'SolarisProjectName' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' SINGLE-VALUE )
3492attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.3 NAME 'SolarisProjectAttr' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' )
3493attributetypes: ( memberGid-oid NAME 'memberGid' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' )
3494attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.0 NAME 'defaultServerList' DESC 'Default LDAP server host address used by a DUA' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3495attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.1 NAME 'defaultSearchBase' DESC 'Default LDAP base DN used by a DUA' SYNTAX '1.3.6.1.4.1.1466.115.121.1.12' SINGLE-VALUE )
3496attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.2 NAME 'preferredServerList' DESC 'Preferred LDAP server host addresses to be used by a DUA' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3497attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.3 NAME 'searchTimeLimit' DESC 'Maximum time in seconds a DUA should allow for a search to complete' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE )
3498attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.4 NAME 'bindTimeLimit' DESC 'Maximum time in seconds a DUA should allow for the bind operation to complete' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE )
3499attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.5 NAME 'followReferrals' DESC 'Tells DUA if it should follow referrals returned by a DSA search result' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3500attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.6 NAME 'authenticationMethod' DESC 'A keystring which identifies the type of authentication method used to contact the DSA' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3501attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.7 NAME 'profileTTL' DESC 'Time to live before a client DUA should re-read this configuration profile' SYNTAX '1.3.6.1.4.1.1466.115.121.1.27' SINGLE-VALUE )
3502attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.14 NAME 'serviceSearchDescriptor' DESC 'LDAP search descriptor list used by Naming-DUA' SYNTAX '1.3.6.1.4.1.1466.115.121.1.26' )
3503attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.9 NAME 'attributeMap' DESC 'Attribute mappings used by a Naming-DUA' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
3504attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.10 NAME 'credentialLevel' DESC 'Identifies type of credentials a DUA should use when binding to the LDAP server' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3505attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.11 NAME 'objectclassMap' DESC 'Objectclass mappings used by a Naming-DUA' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
3506attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.12 NAME 'defaultSearchScope' DESC 'Default search scope used by a DUA' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3507attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.13 NAME 'serviceCredentialLevel' DESC 'Search scope used by a service of the DUA' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
3508attributetypes: ( 1.3.6.1.4.1.11.1.3.1.1.15 NAME 'serviceAuthenticationMethod' DESC 'Authentication Method used by a service of the DUA' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
3509attributetypes:( 1.3.18.0.2.4.1140 NAME 'printer-uri' DESC 'A URI supported by this printer.  This URI SHOULD be used as a relative distinguished name (RDN).  If printer-xri-supported is implemented, then this URI value MUST be listed in a member value of printer-xri-supported.' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
3510attributetypes:( 1.3.18.0.2.4.1107 NAME 'printer-xri-supported' DESC 'The unordered list of XRI (extended resource identifiers) supported by this printer.  Each member of the list consists of a URI (uniform resource identifier) followed by optional authentication and security metaparameters.' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
3511attributetypes:( 1.3.18.0.2.4.1135 NAME 'printer-name' DESC 'The site-specific administrative name of this printer, more end-user friendly than a URI.' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127}  SINGLE-VALUE )
3512attributetypes:( 1.3.18.0.2.4.1119 NAME 'printer-natural-language-configured' DESC 'The configured language in which error and status messages will be generated (by default) by this printer.  Also, a possible language for printer string attributes set by operator, system administrator, or manufacturer.  Also, the (declared) language of the "printer-name", "printer-location", "printer-info", and "printer-make-and-model" attributes of this printer. For example: "en-us" (US English) or "fr-fr" (French in France) Legal values of language tags conform to [RFC3066] "Tags for the Identification of Languages".' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127}  SINGLE-VALUE )
3513attributetypes:( 1.3.18.0.2.4.1136 NAME 'printer-location' DESC 'Identifies the location of the printer. This could include things like: "in Room 123A", "second floor of building XYZ".' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127} SINGLE-VALUE )
3514attributetypes:( 1.3.18.0.2.4.1139 NAME 'printer-info' DESC 'Identifies the descriptive information about this printer.  This could include things like: "This printer can be used for printing color transparencies for HR presentations", or "Out of courtesy for others, please print only small (1-5 page) jobs at this printer", or even "This printer is going away on July 1, 1997, please find a new printer".' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127} SINGLE-VALUE )
3515attributetypes:( 1.3.18.0.2.4.1134 NAME 'printer-more-info' DESC 'A URI used to obtain more information about this specific printer.  For example, this could be an HTTP type URI referencing an HTML page accessible to a Web Browser.  The information obtained from this URI is intended for end user consumption.' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
3516attributetypes:( 1.3.18.0.2.4.1138 NAME 'printer-make-and-model' DESC 'Identifies the make and model of the device.  The device manufacturer MAY initially populate this attribute.' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127}  SINGLE-VALUE )
3517attributetypes:( 1.3.18.0.2.4.1133 NAME 'printer-ipp-versions-supported' DESC 'Identifies the IPP protocol version(s) that this printer supports, including major and minor versions, i.e., the version numbers for which this Printer implementation meets the conformance requirements.' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127} )
3518attributetypes:( 1.3.18.0.2.4.1132 NAME 'printer-multiple-document-jobs-supported' DESC 'Indicates whether or not the printer supports more than one document per job, i.e., more than one Send-Document or Send-Data operation with document data.' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
3519attributetypes:( 1.3.18.0.2.4.1109 NAME 'printer-charset-configured' DESC 'The configured charset in which error and status messages will be generated (by default) by this printer.  Also, a possible charset for printer string attributes set by operator, system administrator, or manufacturer.  For example: "utf-8" (ISO 10646/Unicode) or "iso-8859-1" (Latin1).  Legal values are defined by the IANA Registry of Coded Character Sets and the "(preferred MIME name)" SHALL be used as the tag.  For coherence with IPP Model, charset tags in this attribute SHALL be lowercase normalized.  This attribute SHOULD be static (time of registration) and SHOULD NOT be dynamically refreshed attributetypes: (subsequently).' EQUALITY caseIgnoreMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{63} SINGLE-VALUE )
3520attributetypes:( 1.3.18.0.2.4.1131 NAME 'printer-charset-supported' DESC 'Identifies the set of charsets supported for attribute type values of type Directory String for this directory entry.  For example: "utf-8" (ISO 10646/Unicode) or "iso-8859-1" (Latin1).  Legal values are defined by the IANA Registry of Coded Character Sets and the preferred MIME name.' EQUALITY caseIgnoreMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{63} )
3521attributetypes:( 1.3.18.0.2.4.1137 NAME 'printer-generated-natural-language-supported' DESC 'Identifies the natural language(s) supported for this directory entry.  For example: "en-us" (US English) or "fr-fr" (French in France).  Legal values conform to [RFC3066], Tags for the Identification of Languages.' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{63} )
3522attributetypes:( 1.3.18.0.2.4.1130 NAME 'printer-document-format-supported' DESC 'The possible document formats in which data may be interpreted and printed by this printer.  Legal values are MIME types come from the IANA Registry of Internet Media Types.' EQUALITY caseIgnoreMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127} )
3523attributetypes:( 1.3.18.0.2.4.1129 NAME 'printer-color-supported' DESC 'Indicates whether this printer is capable of any type of color printing at all, including highlight color.' EQUALITY booleanMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.7  SINGLE-VALUE )
3524attributetypes:( 1.3.18.0.2.4.1128 NAME 'printer-compression-supported' DESC 'Compression algorithms supported by this printer.  For example: "deflate, gzip".  Legal values include; "none", "deflate" attributetypes: (public domain ZIP), "gzip" (GNU ZIP), "compress" (UNIX).' EQUALITY caseIgnoreMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{255} )
3525attributetypes:( 1.3.18.0.2.4.1127 NAME 'printer-pages-per-minute' DESC 'The nominal number of pages per minute which may be output by this printer (e.g., a simplex or black-and-white printer).  This attribute is informative, NOT a service guarantee.  Typically, it is the value used in marketing literature to describe this printer.' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.27  SINGLE-VALUE )
3526attributetypes:( 1.3.18.0.2.4.1126 NAME 'printer-pages-per-minute-color' DESC 'The nominal number of color pages per minute which may be output by this printer (e.g., a simplex or color printer).  This attribute is informative, NOT a service guarantee.  Typically, it is the value used in marketing literature to describe this printer.' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.27  SINGLE-VALUE )
3527attributetypes:( 1.3.18.0.2.4.1125 NAME 'printer-finishings-supported' DESC 'The possible finishing operations supported by this printer. Legal values include; "none", "staple", "punch", "cover", "bind", "saddle-stitch", "edge-stitch", "staple-top-left", "staple-bottom-left", "staple-top-right", "staple-bottom-right", "edge-stitch-left", "edge-stitch-top", "edge-stitch-right", "edge-stitch-bottom", "staple-dual-left", "staple-dual-top", "staple-dual-right", "staple-dual-bottom".' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{255} )
3528attributetypes:( 1.3.18.0.2.4.1124 NAME 'printer-number-up-supported' DESC 'The possible numbers of print-stream pages to impose upon a single side of an instance of a selected medium. Legal values include; 1, 2, and 4.  Implementations may support other values.' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.27 )
3529attributetypes:( 1.3.18.0.2.4.1123 NAME 'printer-sides-supported' DESC 'The number of impression sides (one or two) and the two-sided impression rotations supported by this printer.  Legal values include; "one-sided", "two-sided-long-edge", "two-sided-short-edge".' EQUALITY caseIgnoreMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127} )
3530attributetypes:( 1.3.18.0.2.4.1122 NAME 'printer-media-supported' DESC 'The standard names/types/sizes (and optional color suffixes) of the media supported by this printer.  For example: "iso-a4",  "envelope", or "na-letter-white".  Legal values  conform to ISO 10175, Document Printing Application (DPA), and any IANA registered extensions.' EQUALITY caseIgnoreMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{255} )
3531attributetypes:( 1.3.18.0.2.4.1117 NAME 'printer-media-local-supported' DESC 'Site-specific names of media supported by this printer, in the language in "printer-natural-language-configured".  For example: "purchasing-form" (site-specific name) as opposed to (in "printer-media-supported"): "na-letter" (standard keyword from ISO 10175).' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{255} )
3532attributetypes:( 1.3.18.0.2.4.1121 NAME 'printer-resolution-supported' DESC 'List of resolutions supported for printing documents by this printer.  Each resolution value is a string with 3 fields:  1) Cross feed direction resolution (positive integer), 2) Feed direction resolution (positive integer), 3) Resolution unit.  Legal values are "dpi" (dots per inch) and "dpcm" (dots per centimeter).  Each resolution field is delimited by ">".  For example:  "300> 300> dpi>".' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{255} )
3533attributetypes:( 1.3.18.0.2.4.1120 NAME 'printer-print-quality-supported' DESC 'List of print qualities supported for printing documents on this printer.  For example: "draft, normal".  Legal values include; "unknown", "draft", "normal", "high".' EQUALITY caseIgnoreMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127} )
3534attributetypes:( 1.3.18.0.2.4.1110 NAME 'printer-job-priority-supported' DESC 'Indicates the number of job priority levels supported.  An IPP conformant printer which supports job priority must always support a full range of priorities from "1" to "100" (to ensure consistent behavior), therefore this attribute describes the "granularity".  Legal values of this attribute are from "1" to "100".' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.27  SINGLE-VALUE )
3535attributetypes:( 1.3.18.0.2.4.1118 NAME 'printer-copies-supported' DESC 'The maximum number of copies of a document that may be printed as a single job.  A value of "0" indicates no maximum limit.  A value of "-1" indicates unknown.' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.27  SINGLE-VALUE )
3536attributetypes:( 1.3.18.0.2.4.1111 NAME 'printer-job-k-octets-supported' DESC 'The maximum size in kilobytes (1,024 octets actually) incoming print job that this printer will accept.  A value of "0" indicates no maximum limit.  A value of "-1" indicates unknown.' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.27  SINGLE-VALUE )
3537attributetypes:( 1.3.18.0.2.4.1112 NAME 'printer-current-operator' DESC 'The name of the current human operator responsible for operating this printer.  It is suggested that this string include information that would enable other humans to reach the operator, such as a phone number.' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127} SINGLE-VALUE )
3538attributetypes:( 1.3.18.0.2.4.1113 NAME 'printer-service-person' DESC 'The name of the current human service person responsible for servicing this printer.  It is suggested that this string include information that would enable other humans to reach the service person, such as a phone number.' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127}  SINGLE-VALUE )
3539attributetypes:( 1.3.18.0.2.4.1114 NAME 'printer-delivery-orientation-supported' DESC 'The possible delivery orientations of pages as they are printed and ejected from this printer.  Legal values include; "unknown", "face-up", and "face-down".' EQUALITY caseIgnoreMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127} )
3540attributetypes:( 1.3.18.0.2.4.1115 NAME 'printer-stacking-order-supported' DESC 'The possible stacking order of pages as they are printed and ejected from this printer. Legal values include; "unknown", "first-to-last", "last-to-first".' EQUALITY caseIgnoreMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127} )
3541attributetypes:( 1.3.18.0.2.4.1116 NAME 'printer-output-features-supported' DESC 'The possible output features supported by this printer. Legal values include; "unknown", "bursting", "decollating", "page-collating", "offset-stacking".' EQUALITY caseIgnoreMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127} )
3542attributetypes:( 1.3.18.0.2.4.1108 NAME 'printer-aliases' DESC 'Site-specific administrative names of this printer in addition the printer name specified for printer-name.' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX  1.3.6.1.4.1.1466.115.121.1.15{127} )
3543attributetypes:( 1.3.6.1.4.1.42.2.27.5.1.63 NAME 'sun-printer-bsdaddr' DESC 'Sets the server, print queue destination name and whether the client generates protocol extensions. "Solaris" specifies a Solaris print server extension. The value is represented by the following value: server "," destination ", Solaris".' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' SINGLE-VALUE )
3544attributetypes:( 1.3.6.1.4.1.42.2.27.5.1.64 NAME 'sun-printer-kvp' DESC 'This attribute contains a set of key value pairs which may have meaning to the print subsystem or may be user defined. Each value is represented by the following: key "=" value.' SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )
3545attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.57 NAME 'nisplusTimeZone' DESC 'tzone column from NIS+ timezone table' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
3546attributetypes:( 1.3.6.1.4.1.42.2.27.5.1.67 NAME 'ipTnetTemplateName' DESC 'Trusted Solaris network template template_name' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
3547attributetypes:( 1.3.6.1.4.1.42.2.27.5.1.68 NAME 'ipTnetNumber' DESC 'Trusted Solaris network template ip_address' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
3548EOF
3549) > ${TMPDIR}/schema_attr
3550
3551    # Add the entry.
3552    ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/schema_attr ${VERB}"
3553    if [ $? -ne 0 ]; then
3554	${ECHO} "  ERROR: update of schema attributes failed!"
3555	cleanup
3556	exit 1
3557    fi
3558
3559    # Display message that schema is updated.
3560    ${ECHO} "  ${STEP}. Schema attributes have been updated."
3561    STEP=`expr $STEP + 1`
3562}
3563
3564
3565#
3566# update_schema_obj(): Update the schema objectclass definitions.
3567#
3568update_schema_obj()
3569{
3570    [ $DEBUG -eq 1 ] && ${ECHO} "In update_schema_obj()"
3571
3572    # Add the objectclass definitions.
3573    ( cat <<EOF
3574dn: cn=schema
3575changetype: modify
3576add: objectclasses
3577objectclasses: ( 1.3.6.1.1.1.2.14 NAME 'NisKeyObject' SUP 'top' MUST (objectclass $ cn $ nisPublickey $ nisSecretkey) MAY (uidNumber $ description))
3578
3579dn: cn=schema
3580changetype: modify
3581add: objectclasses
3582objectclasses: ( 1.3.6.1.1.1.2.15 NAME 'nisDomainObject' SUP 'top' MUST (objectclass $ nisDomain) MAY ())
3583
3584dn: cn=schema
3585changetype: modify
3586add: objectclasses
3587objectclasses: ( 1.3.6.1.1.1.2.16 NAME 'automountMap' SUP 'top' MUST (objectclass $ automountMapName) MAY (description))
3588
3589dn: cn=schema
3590changetype: modify
3591add: objectclasses
3592objectclasses: ( 1.3.6.1.1.1.2.17 NAME 'automount' SUP 'top' MUST (objectclass $ automountKey $ automountInformation ) MAY (description))
3593
3594dn: cn=schema
3595changetype: modify
3596add: objectclasses
3597objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.7 NAME 'SolarisNamingProfile' SUP 'top' MUST (objectclass $ cn $ SolarisLDAPservers $ SolarisSearchBaseDN) MAY (SolarisBindDN $ SolarisBindPassword $ SolarisAuthMethod $ SolarisTransportSecurity $ SolarisCertificatePath $ SolarisCertificatePassword $ SolarisDataSearchDN $ SolarisSearchScope $ SolarisSearchTimeLimit $ SolarisPreferredServer $ SolarisPreferredServerOnly $ SolarisCacheTTL $ SolarisSearchReferral))
3598
3599dn: cn=schema
3600changetype: modify
3601add: objectclasses
3602objectclasses: ( 2.16.840.1.113730.3.2.4 NAME 'mailGroup' SUP 'top' MUST (objectclass $ mail) MAY (cn $ mgrpRFC822MailMember))
3603
3604dn: cn=schema
3605changetype: modify
3606add: objectclasses
3607objectclasses: ( 1.3.6.1.4.1.42.2.27.1.2.5 NAME 'nisMailAlias' SUP 'top' MUST (objectclass $ cn) MAY (rfc822mailMember))
3608
3609dn: cn=schema
3610changetype: modify
3611add: objectclasses
3612objectclasses: ( 1.3.6.1.4.1.42.2.27.1.2.6 NAME 'nisNetId' SUP 'top' MUST (objectclass $ cn) MAY (nisNetIdUser $ nisNetIdGroup $ nisNetIdHost))
3613
3614dn: cn=schema
3615changetype: modify
3616add: objectclasses
3617objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.2 NAME 'SolarisAuditUser' SUP 'top' AUXILIARY MUST (objectclass) MAY (SolarisAuditAlways $ SolarisAuditNever))
3618
3619dn: cn=schema
3620changetype: modify
3621add: objectclasses
3622objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.3 NAME 'SolarisUserAttr' SUP 'top' AUXILIARY MUST (objectclass) MAY (SolarisUserQualifier $ SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrKeyValue))
3623
3624dn: cn=schema
3625changetype: modify
3626add: objectclasses
3627objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.4 NAME 'SolarisAuthAttr' SUP 'top' MUST (objectclass $ cn) MAY (SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrShortDesc $ SolarisAttrLongDesc $ SolarisAttrKeyValue))
3628
3629dn: cn=schema
3630changetype: modify
3631add: objectclasses
3632objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.5 NAME 'SolarisProfAttr' SUP 'top' MUST (objectclass $ cn) MAY (SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrLongDesc $ SolarisAttrKeyValue))
3633
3634dn: cn=schema
3635changetype: modify
3636add: objectclasses
3637objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.6 NAME 'SolarisExecAttr' SUP 'top' AUXILIARY MUST (objectclass) MAY (SolarisKernelSecurityPolicy $ SolarisProfileType $ SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisProfileID $ SolarisAttrKeyValue))
3638
3639dn: cn=schema
3640changetype: modify
3641add: objectclasses
3642objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.1 NAME 'SolarisProject' SUP 'top' MUST (objectclass $ SolarisProjectID $ SolarisProjectName) MAY (memberUid $ memberGid $ description $ SolarisProjectAttr))
3643
3644dn: cn=schema
3645changetype: modify
3646add: objectclasses
3647objectclasses: ( 1.3.6.1.4.1.11.1.3.1.2.4 NAME 'DUAConfigProfile' SUP 'top' DESC 'Abstraction of a base configuration for a DUA' MUST (cn) MAY (defaultServerList $ preferredServerList $ defaultSearchBase $ defaultSearchScope $ searchTimeLimit $ bindTimeLimit $ credentialLevel $ authenticationMethod $ followReferrals $ serviceSearchDescriptor $ serviceCredentialLevel $ serviceAuthenticationMethod $ objectclassMap $ attributeMap $ profileTTL))
3648
3649dn: cn=schema
3650changetype: modify
3651add: objectclasses
3652objectclasses: ( 1.3.18.0.2.6.2549 NAME 'slpService' DESC 'DUMMY definition' SUP 'top' MUST (objectclass) MAY ())
3653
3654dn: cn=schema
3655changetype: modify
3656add: objectclasses
3657objectclasses: ( 1.3.18.0.2.6.254 NAME 'slpServicePrinter' DESC 'Service Location Protocol (SLP) information.' AUXILIARY SUP 'slpService')
3658
3659dn: cn=schema
3660changetype: modify
3661add: objectclasses
3662objectclasses: ( 1.3.18.0.2.6.258 NAME 'printerAbstract' DESC 'Printer related information.' ABSTRACT SUP 'top' MAY ( printer-name $ printer-natural-language-configured $ printer-location $ printer-info $ printer-more-info $ printer-make-and-model $ printer-multiple-document-jobs-supported $ printer-charset-configured $ printer-charset-supported $ printer-generated-natural-language-supported $ printer-document-format-supported $ printer-color-supported $ printer-compression-supported $ printer-pages-per-minute $ printer-pages-per-minute-color $ printer-finishings-supported $ printer-number-up-supported $ printer-sides-supported $ printer-media-supported $ printer-media-local-supported $ printer-resolution-supported $ printer-print-quality-supported $ printer-job-priority-supported $ printer-copies-supported $ printer-job-k-octets-supported $ printer-current-operator $ printer-service-person $ printer-delivery-orientation-supported $ printer-stacking-order-supported $ printer-output-features-supported ))
3663
3664dn: cn=schema
3665changetype: modify
3666add: objectclasses
3667objectclasses: ( 1.3.18.0.2.6.255 NAME 'printerService' DESC 'Printer information.' STRUCTURAL SUP 'printerAbstract' MAY ( printer-uri $ printer-xri-supported ))
3668
3669dn: cn=schema
3670changetype: modify
3671add: objectclasses
3672objectclasses: ( 1.3.18.0.2.6.257 NAME 'printerServiceAuxClass' DESC 'Printer information.' AUXILIARY SUP 'printerAbstract' MAY ( printer-uri $ printer-xri-supported ))
3673
3674dn: cn=schema
3675changetype: modify
3676add: objectclasses
3677objectclasses: ( 1.3.18.0.2.6.256 NAME 'printerIPP' DESC 'Internet Printing Protocol (IPP) information.' AUXILIARY SUP 'top' MAY   ( printer-ipp-versions-supported $ printer-multiple-document-jobs-supported ))
3678
3679dn: cn=schema
3680changetype: modify
3681add: objectclasses
3682objectclasses: ( 1.3.18.0.2.6.253 NAME 'printerLPR' DESC 'LPR information.' AUXILIARY SUP 'top' MUST ( printer-name ) MAY ( printer-aliases))
3683
3684dn: cn=schema
3685changetype: modify
3686add: objectclasses
3687objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.14 NAME 'sunPrinter' DESC 'Sun printer information' SUP 'top' AUXILIARY MUST (objectclass $ printer-name)  MAY (sun-printer-bsdaddr $ sun-printer-kvp))
3688
3689dn: cn=schema
3690changetype: modify
3691add: objectclasses
3692objectclasses:	( 1.3.6.1.4.1.42.2.27.5.2.12 NAME 'nisplusTimeZoneData' DESC 'NIS+ timezone table data' SUP top STRUCTURAL MUST ( cn ) MAY ( nisplusTimeZone $ description ) )
3693
3694dn: cn=schema
3695changetype: modify
3696add: objectclasses
3697objectclasses:  ( 1.3.6.1.4.1.42.2.27.5.2.8 NAME 'ipTnetTemplate' DESC 'Object class for TSOL network templates' SUP 'top' MUST ( objectclass $ ipTnetTemplateName ) MAY ( SolarisAttrKeyValue ) )
3698
3699dn: cn=schema
3700changetype: modify
3701add: objectclasses
3702objectclasses:	( 1.3.6.1.4.1.42.2.27.5.2.9 NAME 'ipTnetHost' DESC 'Associates an IP address or wildcard with a TSOL template_name' SUP 'top' AUXILIARY MUST ( objectclass $ ipTnetNumber ) )
3703EOF
3704) > ${TMPDIR}/schema_obj
3705
3706    # Add the entry.
3707    ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/schema_obj ${VERB}"
3708    if [ $? -ne 0 ]; then
3709	${ECHO} "  ERROR: update of schema objectclass definitions failed!"
3710	cleanup
3711	exit 1
3712    fi
3713
3714    # Display message that schema is updated.
3715    ${ECHO} "  ${STEP}. Schema objectclass definitions have been added."
3716    STEP=`expr $STEP + 1`
3717}
3718
3719
3720#
3721# modify_top_aci(): Modify the ACI for the top entry to disable self modify
3722#                   of user attributes.
3723#
3724modify_top_aci()
3725{
3726    [ $DEBUG -eq 1 ] && ${ECHO} "In modify_top_aci()"
3727
3728    # Set ACI Name
3729    ACI_NAME="LDAP_Naming_Services_deny_write_access"
3730
3731    # Search for ACI_NAME
3732    eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_BASEDN}\" -s base objectclass=* aci > ${TMPDIR}/chk_top_aci 2>&1"
3733    if [ $? -ne 0 ]; then
3734	${ECHO} "Error searching aci for ${LDAP_BASEDN}"
3735	cat ${TMPDIR}/chk_top_aci
3736	cleanup
3737	exit 1
3738    fi
3739    ${GREP} "${ACI_NAME}" ${TMPDIR}/chk_top_aci > /dev/null 2>&1
3740    if [ $? -eq 0 ]; then
3741	${ECHO} "  ${STEP}. Top level ACI ${ACI_NAME} already exists for ${LDAP_BASEDN}."
3742	STEP=`expr $STEP + 1`
3743	return 0
3744    fi
3745
3746    # Crate LDIF for top level ACI.
3747    ( cat <<EOF
3748dn: ${LDAP_BASEDN}
3749changetype: modify
3750add: aci
3751aci: (targetattr = "cn||uid||uidNumber||gidNumber||homeDirectory||shadowLastChange||shadowMin||shadowMax||shadowWarning||shadowInactive||shadowExpire||shadowFlag||memberUid")(version 3.0; acl ${ACI_NAME}; deny (write) userdn = "ldap:///self";)
3752-
3753EOF
3754) > ${TMPDIR}/top_aci
3755
3756    # Add the entry.
3757    ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/top_aci ${VERB}"
3758    if [ $? -ne 0 ]; then
3759	${ECHO} "  ERROR: Modify of top level ACI failed! (restricts self modify)"
3760	cleanup
3761	exit 1
3762    fi
3763
3764    # Display message that schema is updated.
3765    ${ECHO} "  ${STEP}. ACI for ${LDAP_BASEDN} modified to disable self modify."
3766    STEP=`expr $STEP + 1`
3767}
3768
3769
3770#
3771# add_vlv_aci(): Add access control information (aci) for VLV.
3772#
3773add_vlv_aci()
3774{
3775    [ $DEBUG -eq 1 ] && ${ECHO} "In add_vlv_aci()"
3776
3777    # Add the VLV ACI.
3778    ( cat <<EOF
3779dn: oid=2.16.840.1.113730.3.4.9,cn=features,cn=config
3780changetype: modify
3781replace: aci
3782aci: (targetattr != "aci") (version 3.0; acl "VLV Request Control"; allow(read,search,compare) userdn = "ldap:///anyone";)
3783EOF
3784) > ${TMPDIR}/vlv_aci
3785
3786    # Add the entry.
3787    ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/vlv_aci ${VERB}"
3788    if [ $? -ne 0 ]; then
3789	${ECHO} "  ERROR: Add of VLV ACI failed!"
3790	cleanup
3791	exit 1
3792    fi
3793
3794    # Display message that schema is updated.
3795    ${ECHO} "  ${STEP}. Add of VLV Access Control Information (ACI)."
3796    STEP=`expr $STEP + 1`
3797}
3798
3799
3800#
3801# set_nisdomain(): Add the NisDomainObject to the Base DN.
3802#
3803set_nisdomain()
3804{
3805    [ $DEBUG -eq 1 ] && ${ECHO} "In set_nisdomain()"
3806
3807    # Check if nisDomain is already set.
3808    ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_BASEDN}\" -s base \
3809	\"objectclass=*\"" > ${TMPDIR}/chk_nisdomain 2>&1
3810    ${EVAL} "${GREP} -i nisDomain ${TMPDIR}/chk_nisdomain ${VERB}"
3811    if [ $? -eq 0 ]; then
3812	${ECHO} "  ${STEP}. NisDomainObject for ${LDAP_BASEDN} was already set."
3813	STEP=`expr $STEP + 1`
3814	return 0
3815    fi
3816
3817    # Add the new top level containers.
3818    ( cat <<EOF
3819dn: ${LDAP_BASEDN}
3820changetype: modify
3821objectclass: nisDomainObject
3822nisdomain: ${LDAP_DOMAIN}
3823EOF
3824) > ${TMPDIR}/nis_domain
3825
3826    # Add the entry.
3827    ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/nis_domain ${VERB}"
3828    if [ $? -ne 0 ]; then
3829	${ECHO} "  ERROR: update of NisDomainObject in ${LDAP_BASEDN} failed."
3830	cleanup
3831	exit 1
3832    fi
3833
3834    # Display message that schema is updated.
3835    ${ECHO} "  ${STEP}. NisDomainObject added to ${LDAP_BASEDN}."
3836    STEP=`expr $STEP + 1`
3837}
3838
3839
3840#
3841# check_attrName(): Check that the attribute name is valid.
3842#              $1   Key to check.
3843#         Returns   0 : valid name	1 : invalid name
3844#
3845check_attrName()
3846{
3847    [ $DEBUG -eq 1 ] && ${ECHO} "In check_attrName()"
3848    [ $DEBUG -eq 1 ] && ${ECHO} "check_attrName: Input Param = $1"
3849
3850    ${ECHO} $1 | ${EGREP} '^[0-9]+(\.[0-9]+)*$' > /dev/null 2>&1
3851    if [ $? -eq 0 ]; then
3852	${EVAL} "${LDAPSEARCH} ${SERVER_ARGS} -b cn=schema -s base \"objectclass=*\" \
3853			attributeTypes | ${EGREP} -i '^attributetypes[ ]*=[ ]*\([ ]*$1 ' ${VERB}"
3854    else
3855	${EVAL} "${LDAPSEARCH} ${SERVER_ARGS} -b cn=schema -s base \"objectclass=*\" \
3856			attributeTypes | ${EGREP} -i \"'$1'\" ${VERB}"
3857    fi
3858
3859    if [ $? -ne 0 ]; then
3860	return 1
3861    else
3862	return 0
3863    fi
3864}
3865
3866
3867#
3868# get_objectclass():   Determine the objectclass for the given attribute name
3869#              $1   Attribute name to check.
3870#      _ATTR_NAME   Return value, Object Name or NULL if unknown to idsconfig.
3871#
3872#      NOTE: An attribute name can be valid but still we might not be able
3873#            to determine the objectclass from the table.
3874#            In such cases, the user needs to create the necessary object(s).
3875#
3876get_objectclass()
3877{
3878    [ $DEBUG -eq 1 ] && ${ECHO} "In get_objectclass()"
3879    [ $DEBUG -eq 1 ] && ${ECHO} "get_objectclass: Input Param = $1"
3880
3881    # Set return value to NULL string.
3882    _ATTR_NAME=""
3883
3884    # Test key for type:
3885    case `${ECHO} ${1} | tr '[A-Z]' '[a-z]'` in
3886	ou | organizationalunitname | 2.5.4.11) _ATTR_NAME="organizationalUnit" ;;
3887	dc | domaincomponent | 0.9.2342.19200300.100.1.25) _ATTR_NAME="domain" ;;
3888	 o | organizationname | 2.5.4.10) _ATTR_NAME="organization" ;;
3889	 c | countryname | 2.5.4.6) _ATTR_NAME="country" ;;
3890	 *)  _ATTR_NAME="" ;;
3891    esac
3892
3893    [ $DEBUG -eq 1 ] && ${ECHO} "get_objectclass: _ATTR_NAME = $_ATTR_NAME"
3894}
3895
3896
3897#
3898# add_base_objects(): Add any necessary base objects.
3899#
3900add_base_objects()
3901{
3902    [ $DEBUG -eq 1 ] && ${ECHO} "In add_base_objects()"
3903
3904    # Convert to lower case for basename.
3905    format_string "${LDAP_BASEDN}"
3906    LOWER_BASEDN="${FMT_STR}"
3907    format_string "${LDAP_SUFFIX}"
3908    LOWER_SUFFIX="${FMT_STR}"
3909
3910    [ $DEBUG -eq 1 ] && ${ECHO} "LOWER_BASEDN: ${LOWER_BASEDN}"
3911    [ $DEBUG -eq 1 ] && ${ECHO} "LOWER_SUFFIX: ${LOWER_SUFFIX}"
3912
3913    # Create additional components.
3914    if [ "${LOWER_BASEDN}" = "${LOWER_SUFFIX}" ]; then
3915	[ $DEBUG -eq 1 ] && ${ECHO} "Base DN and Suffix equivalent"
3916    else
3917	# first, test that the suffix is valid
3918	dcstmp=`basename "${LOWER_BASEDN}" "${LOWER_SUFFIX}"`
3919	if [ "$dcstmp" = "${LOWER_BASEDN}" ]; then
3920	    # should not happen since check_basedn_suffix() succeeded
3921	    ${ECHO} "Invalid suffix ${LOWER_SUFFIX}"
3922	    ${ECHO} "for Base DN ${LOWER_BASEDN}"
3923	    cleanup
3924	    exit 1
3925	fi
3926	# OK, suffix is valid, start working with LDAP_BASEDN
3927	# field separator is ',' (i.e., space is a valid character)
3928	dcstmp2="`${ECHO} ${LDAP_BASEDN} |
3929		sed -e 's/[ ]*,[ ]*/,/g' -e 's/[ ]*=[ ]*/=/g'`"
3930	dcs=""
3931	# use dcstmp to count the loop, and dcstmp2 to get the correct
3932	# string case
3933	# dcs should be in reverse order, only for these components
3934	# that need to be added
3935	while [ -n "${dcstmp}" ]
3936	do
3937	    i2=`${ECHO} "$dcstmp2" | cut -f1 -d','`
3938	    dk=`${ECHO} $i2 | awk -F= '{print $1}'`
3939	    dc=`${ECHO} $i2 | awk -F= '{print $2}'`
3940	    dcs="$dk=$dc,$dcs";
3941	    dcstmp2=`${ECHO} "$dcstmp2" | cut -f2- -d','`
3942	    dcstmp=`${ECHO} "$dcstmp" | cut -f2- -d','`
3943	    [ $DEBUG -eq 1 ] && \
3944		${ECHO} "dcs: ${dcs}\ndcstmp: ${dcstmp}\ndcstmp2: ${dcstmp2}\n"
3945	done
3946
3947
3948
3949	lastdc=${LDAP_SUFFIX}
3950	dc=`${ECHO} "${dcs}" | cut -f1 -d','`
3951	dcstmp=`${ECHO} "${dcs}" | cut -f2- -d','`
3952	while [ -n "${dc}" ]; do
3953	    # Get Key and component from $dc.
3954	    dk2=`${ECHO} $dc | awk -F= '{print $1}'`
3955	    dc2=`${ECHO} $dc | awk -F= '{print $2}'`
3956
3957	    # At this point, ${dk2} is a valid attribute name
3958
3959	    # Check if entry exists first, if so, skip to next.
3960	    ${LDAPSEARCH} ${SERVER_ARGS} -b "${dk2}=${dc2},$lastdc" -s base "objectclass=*" > /dev/null 2>&1
3961	    if [ $? -eq 0 ]; then
3962	        # Set the $lastdc to new dc.
3963	        lastdc="${dk2}=${dc2},$lastdc"
3964
3965		# Process next component.
3966		dc=`${ECHO} "${dcstmp}" | cut -f1 -d','`
3967		dcstmp=`${ECHO} "${dcstmp}" | cut -f2- -d','`
3968		continue
3969
3970	    fi
3971
3972	    # Determine the objectclass for the entry.
3973            get_objectclass $dk2
3974	    OBJ_Name=${_ATTR_NAME}
3975	    if [ "${OBJ_Name}" = "" ]; then
3976	        ${ECHO} "Cannot determine objectclass for $dk2"
3977	        ${ECHO} "Please create ${dk2}=${dc2},$lastdc entry and rerun idsconfig"
3978	        exit 1
3979	    fi
3980
3981	    # Add the new container.
3982	    ( cat <<EOF
3983dn: ${dk2}=${dc2},$lastdc
3984${dk2}: $dc2
3985objectClass: top
3986objectClass: ${OBJ_Name}
3987EOF
3988) > ${TMPDIR}/base_objects
3989
3990
3991	    # Set the $lastdc to new dc.
3992	    lastdc="${dk2}=${dc2},$lastdc"
3993
3994	    # Add the entry.
3995	    ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/base_objects ${VERB}"
3996	    if [ $? -ne 0 ]; then
3997		${ECHO} "  ERROR: update of base objects ${dc} failed."
3998		cleanup
3999		exit 1
4000	    fi
4001
4002	    # Display message that schema is updated.
4003	    ${ECHO} "  ${STEP}. Created DN component ${dc}."
4004	    STEP=`expr $STEP + 1`
4005
4006	    # Process next component.
4007	    dc=`${ECHO} "${dcstmp}" | cut -f1 -d','`
4008	    dcstmp=`${ECHO} "${dcstmp}" | cut -f2- -d','`
4009	done
4010    fi
4011}
4012
4013
4014#
4015# add_new_containers(): Add the top level classes.
4016#
4017#    $1 = Base DN
4018#
4019add_new_containers()
4020{
4021    [ $DEBUG -eq 1 ] && ${ECHO} "In add_new_containers()"
4022
4023    for ou in people group rpc protocols networks netgroup \
4024	aliases hosts services ethers profile printers \
4025	SolarisAuthAttr SolarisProfAttr Timezone ipTnet ; do
4026
4027	# Check if nismaps already exist.
4028	eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"ou=${ou},${LDAP_BASEDN}\" -s base \"objectclass=*\" ${VERB}"
4029	if [ $? -eq 0 ]; then
4030	    continue
4031	fi
4032
4033	# Create TMP file to add.
4034	( cat <<EOF
4035dn: ou=${ou},${LDAP_BASEDN}
4036ou: ${ou}
4037objectClass: top
4038objectClass: organizationalUnit
4039EOF
4040) > ${TMPDIR}/toplevel.${ou}
4041
4042	# Add the entry.
4043	${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/toplevel.${ou} ${VERB}"
4044	if [ $? -ne 0 ]; then
4045	    ${ECHO} "  ERROR: Add of ou=${ou} container failed!"
4046	    cleanup
4047	    exit 1
4048	fi
4049    done
4050
4051    # Display message that top level OU containers complete.
4052    ${ECHO} "  ${STEP}. Top level \"ou\" containers complete."
4053    STEP=`expr $STEP + 1`
4054}
4055
4056
4057#
4058# add_auto_maps(): Add the automount map entries.
4059#
4060# auto_home, auto_direct, auto_master, auto_shared
4061#
4062add_auto_maps()
4063{
4064    [ $DEBUG -eq 1 ] && ${ECHO} "In add_auto_maps()"
4065
4066    # Set AUTO_MAPS for maps to create.
4067    AUTO_MAPS="auto_home auto_direct auto_master auto_shared"
4068
4069    for automap in $AUTO_MAPS; do
4070	# Check if automaps already exist.
4071	eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"automountMapName=${automap},${LDAP_BASEDN}\" -s base \"objectclass=*\" ${VERB}"
4072	if [ $? -eq 0 ]; then
4073	    continue
4074	fi
4075
4076	# Create the tmp file to add.
4077	( cat <<EOF
4078dn: automountMapName=${automap},${LDAP_BASEDN}
4079automountMapName: ${automap}
4080objectClass: top
4081objectClass: automountMap
4082EOF
4083) > ${TMPDIR}/automap.${automap}
4084
4085	# Add the entry.
4086	${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/automap.${automap} ${VERB}"
4087	if [ $? -ne 0 ]; then
4088	    ${ECHO} "  ERROR: Add of automap ${automap} failed!"
4089	    cleanup
4090	    exit 1
4091	fi
4092    done
4093
4094    # Display message that automount entries are updated.
4095    ${ECHO} "  ${STEP}. automount maps: $AUTO_MAPS processed."
4096    STEP=`expr $STEP + 1`
4097}
4098
4099
4100#
4101# add_proxyagent(): Add entry for nameservice to use to access server.
4102#
4103add_proxyagent()
4104{
4105    [ $DEBUG -eq 1 ] && ${ECHO} "In add_proxyagent()"
4106
4107    # Check if nismaps already exist.
4108    eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_PROXYAGENT}\" -s base \"objectclass=*\" ${VERB}"
4109    if [ $? -eq 0 ]; then
4110	${ECHO} "  ${STEP}. Proxy Agent ${LDAP_PROXYAGENT} already exists."
4111	STEP=`expr $STEP + 1`
4112	return 0
4113    fi
4114
4115    # Get cn and sn names from LDAP_PROXYAGENT.
4116    cn_tmp=`${ECHO} ${LDAP_PROXYAGENT} | cut -f1 -d, | cut -f2 -d=`
4117
4118    # Create the tmp file to add.
4119    ( cat <<EOF
4120dn: ${LDAP_PROXYAGENT}
4121cn: ${cn_tmp}
4122sn: ${cn_tmp}
4123objectclass: top
4124objectclass: person
4125userpassword: ${LDAP_PROXYAGENT_CRED}
4126EOF
4127) > ${TMPDIR}/proxyagent
4128
4129    # Add the entry.
4130    ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/proxyagent ${VERB}"
4131    if [ $? -ne 0 ]; then
4132	${ECHO} "  ERROR: Adding proxyagent failed!"
4133	cleanup
4134	exit 1
4135    fi
4136
4137    # Display message that schema is updated.
4138    ${ECHO} "  ${STEP}. Proxy Agent ${LDAP_PROXYAGENT} added."
4139    STEP=`expr $STEP + 1`
4140}
4141
4142
4143#
4144# allow_proxy_read_pw(): Give Proxy Agent read permission for password.
4145#
4146allow_proxy_read_pw()
4147{
4148    [ $DEBUG -eq 1 ] && ${ECHO} "In allow_proxy_read_pw()"
4149
4150    # Set ACI Name
4151    PROXY_ACI_NAME="LDAP_Naming_Services_proxy_password_read"
4152
4153    # Search for ACI_NAME
4154    eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_BASEDN}\" -s base objectclass=* aci > ${TMPDIR}/chk_proxyread_aci 2>&1"
4155    ${GREP} "${PROXY_ACI_NAME}" ${TMPDIR}/chk_proxyread_aci > /dev/null 2>&1
4156    if [ $? -eq 0 ]; then
4157	${ECHO} "  ${STEP}. Proxy ACI ${PROXY_ACI_NAME=} already exists for ${LDAP_BASEDN}."
4158	STEP=`expr $STEP + 1`
4159	return 0
4160    fi
4161
4162    # Create the tmp file to add.
4163    ( cat <<EOF
4164dn: ${LDAP_BASEDN}
4165changetype: modify
4166add: aci
4167aci: (target="ldap:///${LDAP_BASEDN}")(targetattr="userPassword")(version 3.0; acl ${PROXY_ACI_NAME}; allow (compare,read,search) userdn = "ldap:///${LDAP_PROXYAGENT}";)
4168EOF
4169) > ${TMPDIR}/proxy_read
4170
4171    # Add the entry.
4172    ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/proxy_read ${VERB}"
4173    if [ $? -ne 0 ]; then
4174	${ECHO} "  ERROR: Allow ${LDAP_PROXYAGENT} to read password failed!"
4175	cleanup
4176	exit 1
4177    fi
4178
4179    # Display message that schema is updated.
4180    ${ECHO} "  ${STEP}. Give ${LDAP_PROXYAGENT} read permission for password."
4181    STEP=`expr $STEP + 1`
4182}
4183
4184
4185#
4186# add_profile(): Add client profile to server.
4187#
4188add_profile()
4189{
4190    [ $DEBUG -eq 1 ] && ${ECHO} "In add_profile()"
4191
4192    # If profile name already exists, DELETE it, and add new one.
4193    eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=${LDAP_PROFILE_NAME},ou=profile,${LDAP_BASEDN}\" -s base \"objectclass=*\" ${VERB}"
4194    if [ $? -eq 0 ]; then
4195	# Create Delete file.
4196	( cat <<EOF
4197cn=${LDAP_PROFILE_NAME},ou=profile,${LDAP_BASEDN}
4198EOF
4199) > ${TMPDIR}/del_profile
4200
4201	# Check if DEL_OLD_PROFILE is set.  (If not ERROR)
4202	if [ $DEL_OLD_PROFILE -eq 0 ]; then
4203	    ${ECHO} "ERROR: Profile name ${LDAP_PROFILE_NAME} exists! Add failed!"
4204	    exit 1
4205	fi
4206
4207	# Delete the OLD profile.
4208	${EVAL} "${LDAPDELETE} ${LDAP_ARGS} -f ${TMPDIR}/del_profile ${VERB}"
4209	if [ $? -ne 0 ]; then
4210	    ${ECHO} "  ERROR: Attempt to DELETE profile failed!"
4211	    cleanup
4212	    exit 1
4213	fi
4214    fi
4215
4216    # Build the "ldapclient genprofile" command string to execute.
4217    GEN_CMD="ldapclient genprofile -a \"profileName=${LDAP_PROFILE_NAME}\""
4218
4219    # Add required argument defaultSearchBase.
4220    GEN_CMD="${GEN_CMD} -a \"defaultSearchBase=${LDAP_BASEDN}\""
4221
4222    # Add optional parameters.
4223    [ -n "$LDAP_SERVER_LIST" ] && \
4224	GEN_CMD="${GEN_CMD} -a \"defaultServerList=${LDAP_SERVER_LIST}\""
4225    [ -n "$LDAP_SEARCH_SCOPE" ] && \
4226	GEN_CMD="${GEN_CMD} -a \"defaultSearchScope=${LDAP_SEARCH_SCOPE}\""
4227    [ -n "$LDAP_CRED_LEVEL" ] && \
4228	GEN_CMD="${GEN_CMD} -a \"credentialLevel=${LDAP_CRED_LEVEL}\""
4229    [ -n "$LDAP_AUTHMETHOD" ] && \
4230	GEN_CMD="${GEN_CMD} -a \"authenticationMethod=${LDAP_AUTHMETHOD}\""
4231    [ -n "$LDAP_FOLLOWREF" ] && \
4232	GEN_CMD="${GEN_CMD} -a \"followReferrals=${LDAP_FOLLOWREF}\""
4233    [ -n "$LDAP_SEARCH_TIME_LIMIT" ] && \
4234	GEN_CMD="${GEN_CMD} -a \"searchTimeLimit=${LDAP_SEARCH_TIME_LIMIT}\""
4235    [ -n "$LDAP_PROFILE_TTL" ] && \
4236	GEN_CMD="${GEN_CMD} -a \"profileTTL=${LDAP_PROFILE_TTL}\""
4237    [ -n "$LDAP_BIND_LIMIT" ] && \
4238	GEN_CMD="${GEN_CMD} -a \"bindTimeLimit=${LDAP_BIND_LIMIT}\""
4239    [ -n "$LDAP_PREF_SRVLIST" ] && \
4240	GEN_CMD="${GEN_CMD} -a \"preferredServerList=${LDAP_PREF_SRVLIST}\""
4241    [ -n "$LDAP_SRV_AUTHMETHOD_PAM" ] && \
4242	GEN_CMD="${GEN_CMD} -a \"serviceAuthenticationMethod=${LDAP_SRV_AUTHMETHOD_PAM}\""
4243    [ -n "$LDAP_SRV_AUTHMETHOD_KEY" ] && \
4244	GEN_CMD="${GEN_CMD} -a \"serviceAuthenticationMethod=${LDAP_SRV_AUTHMETHOD_KEY}\""
4245    [ -n "$LDAP_SRV_AUTHMETHOD_CMD" ] && \
4246	GEN_CMD="${GEN_CMD} -a \"serviceAuthenticationMethod=${LDAP_SRV_AUTHMETHOD_CMD}\""
4247
4248    # Check if there are any service search descriptors to ad.
4249    if [ -s "${SSD_FILE}" ]; then
4250	ssd_2_profile
4251    fi
4252
4253    # Execute "ldapclient genprofile" to create profile.
4254    eval ${GEN_CMD} > ${TMPDIR}/gen_profile 2> ${TMPDIR}/gen_profile_ERR
4255    if [ $? -ne 0 ]; then
4256	${ECHO} "  ERROR: ldapclient genprofile failed!"
4257	cleanup
4258	exit 1
4259    fi
4260
4261    # Add the generated profile..
4262    ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/gen_profile ${VERB}"
4263    if [ $? -ne 0 ]; then
4264	${ECHO} "  ERROR: Attempt to add profile failed!"
4265	cleanup
4266	exit 1
4267    fi
4268
4269    # Display message that schema is updated.
4270    ${ECHO} "  ${STEP}. Generated client profile and loaded on server."
4271    STEP=`expr $STEP + 1`
4272}
4273
4274
4275#
4276# cleanup(): Remove the TMPDIR and all files in it.
4277#
4278cleanup()
4279{
4280    [ $DEBUG -eq 1 ] && ${ECHO} "In cleanup()"
4281
4282    rm -fr ${TMPDIR}
4283}
4284
4285
4286#
4287# 			* * * MAIN * * *
4288#
4289# Description:
4290# This script assumes that the iPlanet Directory Server (iDS) is
4291# installed and that setup has been run.  This script takes the
4292# iDS server from that point and sets up the infrastructure for
4293# LDAP Naming Services.  After running this script, ldapaddent(1M)
4294# or some other tools can be used to populate data.
4295
4296# Initialize the variables that need to be set to NULL, or some
4297# other initial value before the rest of the functions can be called.
4298init
4299
4300# Parse command line arguments.
4301parse_arg $*
4302shift $?
4303
4304# Print extra line to separate from prompt.
4305${ECHO} " "
4306
4307# Either Load the user specified config file
4308# or prompt user for config info.
4309if [ -n "$INPUT_FILE" ]
4310then
4311    load_config_file
4312    INTERACTIVE=0      # Turns off prompts that occur later.
4313    validate_info      # Validate basic info in file.
4314    chk_ids_version    # Check iDS version for compatibility.
4315else
4316    # Display BACKUP warning to user.
4317    display_msg backup_server
4318    get_confirm "Do you wish to continue with server setup (y/n/h)?" "n" "backup_help"
4319    if [ $? -eq 0 ]; then    # if No, cleanup and exit.
4320	cleanup ; exit 1
4321    fi
4322
4323    # Prompt for values.
4324    prompt_config_info
4325    display_summary    # Allow user to modify results.
4326    INTERACTIVE=1      # Insures future prompting.
4327fi
4328
4329# Modify slapd.oc.conf to ALLOW cn instead of REQUIRE.
4330modify_cn
4331
4332# Modify timelimit to user value.
4333[ $NEED_TIME -eq 1 ] && modify_timelimit
4334
4335# Modify sizelimit to user value.
4336[ $NEED_SIZE -eq 1 ] && modify_sizelimit
4337
4338# Modify the password storage scheme to support CRYPT.
4339if [ "$NEED_CRYPT" = "TRUE" ]; then
4340    modify_pwd_crypt
4341fi
4342
4343# Update the schema (Attributes, Objectclass Definitions)
4344update_schema_attr
4345update_schema_obj
4346
4347# Add suffix together with its root entry (if needed)
4348add_suffix ||
4349{
4350	cleanup
4351	exit 1
4352}
4353
4354# Add base objects (if needed)
4355add_base_objects
4356
4357# Update the NisDomainObject.
4358#   The Base DN might of just been created, so this MUST happen after
4359#   the base objects have been added!
4360set_nisdomain
4361
4362# Add top level classes (new containers)
4363add_new_containers
4364
4365# Add common nismaps.
4366add_auto_maps
4367
4368# Modify top ACI.
4369modify_top_aci
4370
4371# Add Access Control Information for VLV.
4372add_vlv_aci
4373
4374# if Proxy needed, Add Proxy Agent and give read permission for password.
4375if [ $NEED_PROXY -eq 1 ]; then
4376    add_proxyagent
4377    allow_proxy_read_pw
4378fi
4379
4380# Generate client profile and add it to the server.
4381add_profile
4382
4383# Add Indexes to improve Search Performance.
4384add_eq_indexes
4385add_sub_indexes
4386add_vlv_indexes
4387
4388# Display setup complete message
4389display_msg setup_complete
4390
4391# Display VLV index commands to be executed on server.
4392display_vlv_cmds
4393
4394# Create config file if requested.
4395[ -n "$OUTPUT_FILE" ] && create_config_file
4396
4397# Removed the TMPDIR and all files in it.
4398cleanup
4399
4400exit 0
4401# end of MAIN.
4402