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