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