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