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