Print this page
- adds support for ForgeRock OpenDJ Directory Server (DS)
- does some jobs a little bit more intelligent (fixes all missing parts in a DS)
- improved readability/output (demystify, show what it does)
- optional recording of all commands used to initialize/fix the DS (option -k)
- creates backend and VLV indexes for OpenDJ on the fly (no need to exec a list
of DS specific commands after running the script)
- almost complete rewrite in ksh93 to reduce maintenance burden, support
much easier debugging/tracing (just in case), integrated documentation
and much much less forking of/dependencies on external tools
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/ldap/ns_ldap/idsconfig.sh
+++ new/usr/src/cmd/ldap/ns_ldap/idsconfig.sh
1 -#!/bin/sh
1 +#!/bin/ksh93
2 2 #
3 +# $Id: idsconfig.sh,v 66c6ff17d001 2013-09-24 00:35:53Z jel+illumos $
4 +#
3 5 # CDDL HEADER START
4 6 #
5 7 # The contents of this file are subject to the terms of the
6 8 # Common Development and Distribution License (the "License").
7 9 # You may not use this file except in compliance with the License.
8 10 #
9 11 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 12 # or http://www.opensolaris.org/os/licensing.
11 13 # See the License for the specific language governing permissions
12 14 # and limitations under the License.
13 15 #
14 16 # When distributing Covered Code, include this CDDL HEADER in each
15 17 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 18 # If applicable, add the following below this CDDL HEADER, with the
17 19 # fields enclosed by brackets "[]" replaced with your own identifying
18 20 # information: Portions Copyright [yyyy] [name of copyright owner]
19 21 #
20 22 # CDDL HEADER END
21 23 #
22 -#
23 -# idsconfig -- script to setup iDS 5.x/6.x/7.x for Native LDAP II.
24 -#
25 24 # Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
26 -#
25 +# Portions Copyright 2013 Jens Elkner.
27 26
28 -#
29 -# display_msg(): Displays message corresponding to the tag passed in.
30 -#
31 -display_msg()
32 -{
33 - case "$1" in
34 - usage) cat <<EOF
35 - $PROG: [ -v ] [ -i input file ] [ -o output file ]
36 - i <input file> Get setup info from input file.
37 - o <output file> Generate a server configuration output file.
38 - v Verbose mode
39 -EOF
40 - ;;
41 - backup_server) cat <<EOF
42 -It is strongly recommended that you BACKUP the directory server
43 -before running $PROG.
44 27
45 -Hit Ctrl-C at any time before the final confirmation to exit.
28 +#############################################################################
29 +# Main global vars
30 +#############################################################################
31 +LIC='[-?$Id: idsconfig.sh,v 66c6ff17d001 2013-09-24 00:35:53Z jel+illumos $ ]
32 +[-copyright?Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.]
33 +[-copyright?Portions Copyright (c) 2013 Jens Elkner.]
34 +[-license?CDDL 1.0]'
46 35
47 -EOF
48 - ;;
49 - setup_complete) cat <<EOF
36 +SDIR=${.sh.file%/*}
37 +typeset -r FPROG=${.sh.file}
38 +typeset -r PROG=${FPROG##*/}
50 39
51 -$PROG: Setup of iDS server ${IDS_SERVER} is complete.
40 +typeset -T LogObj_t=(
41 + typeset -Sh 'Color for info messages' GREEN='38;5;232;48;5;118' #'1;30;102';
42 + typeset -Sh 'Color for warning messages' BLUE='38;5;21;48;5;118' #'1;34;102';
43 + typeset -Sh 'Color for fatal messages' RED='38;5;9;48;5;118' #'1;31;102';
44 + typeset -Sih 'Flag, whether to use colored labels' COLORED=1
45 + typeset -Sih 'Flag, whether to print verbose infos' VERBOSE=0
52 46
53 -EOF
54 - ;;
55 - display_vlv_list) cat <<EOF
47 + function log {
48 + (( _.COLORED )) && print -u2 "\E[1;$2m${ date +%T; } $1:\E[0m $3" || \
49 + print -u2 "${ date +%T; } ${1}: $3"
50 + }
51 + typeset -Sfh ' log a message to stderr' log
52 + function verbose {
53 + (( _.VERBOSE )) && _.log "VERB" ${_.GREEN} " $*"
54 + }
55 + typeset -Sfh ' log a info message to stderr if verbose messages are enabled' info
56 56
57 -Note: idsconfig has created entries for VLV indexes.
57 + function info {
58 + _.log "INFO" ${_.GREEN} "$*"
59 + }
60 + typeset -Sfh ' log a info message to stderr' info
61 + function warn {
62 + _.log "WARN" ${_.BLUE} "$*"
63 + }
64 + typeset -Sfh ' log a warning message to stderr' warn
65 + function fatal {
66 + _.log "FATAL" ${_.RED} "$*"
67 + }
68 + typeset -Sfh ' log a fatal error message to stderr' fatal
69 + function printMarker {
70 + typeset COLOR="$1" L='----------------------------------------------------------------------------'
71 + (( _.COLORED )) && print "\E[1;${COLOR:-${_.GREEN}}m${L}\E[0m" || \
72 + print "${L}"
73 + }
74 + typeset -Sfh ' print a marker line to stdout' printMarker
75 +)
76 +LogObj_t Log
58 77
59 - For DS5.x, use the directoryserver(1m) script on ${IDS_SERVER}
60 - to stop the server. Then, using directoryserver, follow the
61 - directoryserver examples below to create the actual VLV indexes.
78 +typeset -T ManObj_t=(
79 + typeset -Ah 'Variable descriptions. Key: variable name' VAR
80 + typeset -Ah 'Function usages. Key: function name' FUNC
81 + function addVar {
82 + [[ -n ${_.VAR[$1]} ]] && Log.warn "Overwriting previous description for $1"
83 + _.VAR[$1]="[+$1?$2]"
84 + }
85 + typeset -fh 'Add a description (arg2) for the given variable name (arg1)' addVar
86 + function addFunc {
87 + typeset fname=$1
88 + typeset X="$2"
89 + [[ -n ${_.FUNC[$fname]} ]] && Log.warn "Overwriting previous usage info for $1()"
90 + [[ -z $X ]] && X="$LIC"
91 + shift 2
92 + while [[ -n $1 ]]; do
93 + X+="$1"
94 + shift
95 + done
96 + _.FUNC[$fname]+="$X"
97 + }
98 + typeset -fh $'Add usage info (arg3 ...) for the given function name (arg1). If implementation details (arg2) is empty, the value of \a$LIC\a gets used instead' addFunc
99 + function varUsage {
100 + typeset X=""
101 + [[ "$1" == '@' || "$1" == '*' ]] && set -- ${!_.VAR[@]}
102 + while [[ -n $1 ]]; do
103 + X+="${_.VAR[$1]}"
104 + shift
105 + done
106 + print "$X"
107 + }
108 + typeset -fh $'Get the variable usage info for the named variables (arg2 ...) if available as a concatenated string. See \baddVar()\b' varUsage
109 + function funcUsage {
110 + printf "${_.FUNC[$1]}"
111 + }
112 + typeset -fh 'Get the function usage info for the named function (arg1)' funcUsage
62 113
63 - For DS6.x or later, use dsadm command delivered with DS on ${IDS_SERVER}
64 - to stop the server. Then, using dsadm, follow the
65 - dsadm examples below to create the actual VLV indexes.
114 + function listVars {
115 + typeset ALL="${ print ${!_.VAR[*]} | tr ' ' '\n' | sort -u; }" VNAME
116 + for VNAME in $ALL; do
117 + [[ $VNAME == OLDENV || $VNAME == LASTENV ]] && continue
118 + typeset -n X=$VNAME
119 + print "$VNAME=$X"
120 + done
121 + unset -n X
122 + }
123 + typeset -fh 'List all registered environment variables and its current value, except for OLDENV and LASTENV.' listVars
124 +)
125 +ManObj_t Man
66 126
67 -EOF
68 - ;;
69 - cred_level_menu) cat <<EOF
70 -The following are the supported credential levels:
71 - 1 anonymous
72 - 2 proxy
73 - 3 proxy anonymous
74 - 4 self
75 -EOF
76 - ;;
77 - auth_method_menu) cat <<EOF
78 -The following are the supported Authentication Methods:
79 - 1 none
80 - 2 simple
81 - 3 sasl/DIGEST-MD5
82 - 4 tls:simple
83 - 5 tls:sasl/DIGEST-MD5
84 - 6 sasl/GSSAPI
85 -EOF
86 - ;;
87 - srvauth_method_menu) cat <<EOF
88 -The following are the supported Authentication Methods:
89 - 1 simple
90 - 2 sasl/DIGEST-MD5
91 - 3 tls:simple
92 - 4 tls:sasl/DIGEST-MD5
93 - 5 sasl/GSSAPI
94 -EOF
95 - ;;
96 - prompt_ssd_menu) cat <<EOF
97 - A Add a Service Search Descriptor
98 - D Delete a SSD
99 - M Modify a SSD
100 - P Display all SSD's
101 - H Help
102 - X Clear all SSD's
127 +Man.addFunc showUsage '' '[+NAME?showUsage - show usage info.]
128 +[+DESCRIPTION?Shows usage info for the given \afname\a if available.]
129 +\n\n\afname\a
130 +'
131 +function showUsage {
132 + typeset WHAT="$2"
133 + if (( Log.VERBOSE )) && [[ ${WHAT} == 'MAIN' ]]; then
134 + typeset PRE=${Man.FUNC[$WHAT]%%\[+NOTES*}
135 + typeset POST=${.sh.match}
136 + typeset E='[+ENVIRONMENT VARIABLES]{'"${ Man.varUsage '*' ; }"'}'
137 + getopts -a "${PROG}" "${ print ${PRE}${E}${POST} ; }" OPT --man
138 + else
139 + getopts -a "${PROG}" "${ print ${Man.FUNC[$WHAT]}; }" OPT --man
140 + fi
141 +}
103 142
104 - Q Exit menu
105 -EOF
106 - ;;
107 - summary_menu)
143 +Man.addVar PROG 'String. The basename of this script.'
108 144
109 - SUFFIX_INFO=
110 - DB_INFO=
145 +Man.addVar INT 'Associative array of Integers. Config relevant int values and flags.'
146 +typeset -A -i INT=( )
147 +Man.addVar STR 'Associative array of Strings. Config relevant string values.'
148 +typeset -A STR=( )
111 149
112 - [ -n "${NEED_CREATE_SUFFIX}" ] &&
113 - {
114 - SUFFIX_INFO=`cat <<EOF
150 +Man.addVar TMPF 'Associative array of Integers. Int values with a more or less a global character in this script.'
151 +typeset -A -i TMPF=( )
152 +Man.addVar TMP 'Associative array of Strings. String values whith a more or less a global character in this script.'
153 +typeset -A TMP=( )
115 154
116 - Suffix to create : $LDAP_SUFFIX
117 -EOF
118 -`
119 - [ -n "${NEED_CREATE_BACKEND}" ] &&
120 - DB_INFO=`cat <<EOF
155 +Man.addVar CON_ARGS 'String. Contains connection related options for ldap commands.'
156 +typeset CON_ARGS=''
121 157
122 - Database to create : $IDS_DATABASE
123 -EOF
124 -`
125 - }
158 +Man.addVar AUTH_ARGS 'Indexed array of Strings. Contains authentification related options for ldap commands.'
159 +typeset -a AUTH_ARGS=( )
126 160
127 - cat <<EOF
128 - Summary of Configuration
161 +Man.addVar SSD 'Indexed array of Strings. Contains the Service Search Decsriptors to use.'
162 +typeset -a SSD=( )
129 163
130 - 1 Domain to serve : $LDAP_DOMAIN
131 - 2 Base DN to setup : $LDAP_BASEDN$SUFFIX_INFO$DB_INFO
132 - 3 Profile name to create : $LDAP_PROFILE_NAME
133 - 4 Default Server List : $LDAP_SERVER_LIST
134 - 5 Preferred Server List : $LDAP_PREF_SRVLIST
135 - 6 Default Search Scope : $LDAP_SEARCH_SCOPE
136 - 7 Credential Level : $LDAP_CRED_LEVEL
137 - 8 Authentication Method : $LDAP_AUTHMETHOD
138 - 9 Enable Follow Referrals : $LDAP_FOLLOWREF
139 - 10 iDS Time Limit : $IDS_TIMELIMIT
140 - 11 iDS Size Limit : $IDS_SIZELIMIT
141 - 12 Enable crypt password storage : $NEED_CRYPT
142 - 13 Service Auth Method pam_ldap : $LDAP_SRV_AUTHMETHOD_PAM
143 - 14 Service Auth Method keyserv : $LDAP_SRV_AUTHMETHOD_KEY
144 - 15 Service Auth Method passwd-cmd: $LDAP_SRV_AUTHMETHOD_CMD
145 - 16 Search Time Limit : $LDAP_SEARCH_TIME_LIMIT
146 - 17 Profile Time to Live : $LDAP_PROFILE_TTL
147 - 18 Bind Limit : $LDAP_BIND_LIMIT
148 - 19 Enable shadow update : $LDAP_ENABLE_SHADOW_UPDATE
149 - 20 Service Search Descriptors Menu
164 +# NOTE: The ACI names are retained to be compatible to previous releases. If one
165 +# installs a completely new LDAP infrastructure changing the names should
166 +# not be a problem as long as they do not collide with existing aci names!
150 167
151 -EOF
152 - ;;
153 - sfx_not_suitable) cat <<EOF
168 +Man.addVar SFX_ANYONE_ACI_NAME 'String constant. The name of the suffix ACI rule, which allows anyone to read, search, compare.'
169 +typeset -r SFX_ANYONE_ACI_NAME='Anonymous access'
154 170
155 -Sorry, suffix ${LDAP_SUFFIX} is not suitable for Base DN ${LDAP_BASEDN}
171 +Man.addVar SFX_SELF_ACI_NAME 'String constant. The name of the suffix ACI rule, which allows a principal to modify its own attributes except those related to password state information and policy.'
172 +typeset -r SFX_SELF_ACI_NAME='Limited self entry modification'
156 173
157 -EOF
158 - ;;
159 - obj_not_found) cat <<EOF
174 +Man.addVar SFX_ADMIN_ACI_NAME 'String constant. The name of the suffix ACI rule, which allows the directory configuration administrator all operations on any entry.'
175 +typeset -r SFX_ADMINGRP_ACI_NAME='Configuration Administrator access'
160 176
161 -Sorry, ${PROG} can't find an objectclass for "$_ATT" attribute
177 +Man.addVar SFX_ADMINGRP_ACI_NAME 'String constant. The name of the suffix ACI rule, which allows the directory configuration administrator group all operations on any entry.'
178 +typeset -r SFX_ADMIN_ACI_NAME='Configuration Administrator Group access'
162 179
163 -EOF
164 - ;;
165 - sfx_config_incons) cat <<EOF
180 +Man.addVar PROXY_ACI_NAME 'String constant. The name of the ACI rule, which allows proxies to read passwords.'
181 +typeset -r PROXY_ACI_NAME='LDAP Naming Services proxy_password_read'
166 182
167 -Sorry, there is no suffix mapping for ${LDAP_SUFFIX},
168 -while ldbm database exists, server configuration needs to be fixed manually,
169 -look at cn=mapping tree,cn=config and cn=ldbm database,cn=plugins,cn=config
183 +Man.addVar HOST_ACI_NAME 'String constant. The name of the ACI rule, which allows host principals to write passwords.'
184 +typeset -r HOST_ACI_NAME='LDAP Naming Services host_shadow_write'
185 +Man.addVar NON_HOST_ACI_NAME 'String constant. The name of the ACI rule, which denies non-host principals access to shadow data.'
186 +typeset -r NON_HOST_ACI_NAME='LDAP Naming Services deny_non_host_shadow_access'
170 187
171 -EOF
172 - ;;
173 - ldbm_db_exist) cat <<EOF
188 +Man.addVar ADMIN_ACI_NAME 'String constant. The name of the ACI rule, which allows Admin principals access to shadow, rbac and mount data.'
189 +typeset -r ADMIN_ACI_NAME='LDAP Naming Services admin_shadow_write'
190 +Man.addVar NON_ADMIN_ACI_NAME 'String constant. The name of the ACI rule, which denies non-Admin principals access to shadow data.'
191 +typeset -r NON_ADMIN_ACI_NAME='LDAP Naming Services deny_non_admin_shadow_access'
192 +Man.addVar USER_ACI_NAME 'String constant. The name of the ACI rule, which prevents a user from changing administrative fields like uidNumber, homeDirectory, shadowExpire, etc..'
193 +typeset -r USER_ACI_NAME='LDAP Naming Services deny_write_access'
174 194
175 -Database "${IDS_DATABASE}" already exists,
176 -however "${IDS_DATABASE_AVAIL}" name is available
195 +Man.addVar VLV_ACI_NAME 'String constant. The name of the global ACI rule, which allows any user to use VLVs for read, search and compare.'
196 +typeset -r VLV_ACI_NAME='VLV Request Control'
177 197
178 -EOF
179 - ;;
180 - unable_find_db_name) cat <<EOF
181 -
182 -Unable to find any available database name close to "${IDS_DATABASE}"
198 +Man.addVar SELF_GSS_ACI_NAME 'String constant. The name of the ou=people ACI rule, which allows a via SASL/GSSAPI authenticated user read and search on passwords.'
199 +typeset -r SELF_GSS_ACI_NAME='self-read-pwd'
183 200
184 -EOF
185 - ;;
186 - create_ldbm_db_error) cat <<EOF
201 +Man.addVar HOST_GSS_ACI_NAME 'String constant. The name of the ou=people ACI rule, which allows a via SASL/GSSAPI authenticated hosts read and search on passwords.'
202 +typeset -r HOST_GSS_ACI_NAME='host-read-pwd'
187 203
188 -ERROR: unable to create suffix ${LDAP_SUFFIX}
189 - due to server error that occurred during creation of ldbm database
204 +Man.addVar AUTH_METHODS 'Indexed array of Strings. A list of currently supported authentication methods.'
205 +typeset -a -r AUTH_METHODS=(
206 + 'none' 'simple' 'sasl/DIGEST-MD5'
207 + 'tls:simple' 'tls:sasl/DIGEST-MD5' 'sasl/GSSAPI'
208 +) # order is important
190 209
191 -EOF
192 - ;;
193 - create_suffix_entry_error) cat <<EOF
210 +Man.addVar CRED_LEVELS 'Indexed array of Strings. A list of currently supported client credential levels.'
211 +typeset -a -r CRED_LEVELS=( 'anonymous' 'proxy' 'proxy anonymous' 'self' )
194 212
195 -ERROR: unable to create entry ${LDAP_SUFFIX} of ${LDAP_SUFFIX_OBJ} class
213 +Man.addVar OID2ADEF 'Associative array of Strings. Key: OID, Value: attribute definition. Used to cache attribute definitions of schemas currently installed on the DS. Gets lazy initialized, i.e. populated when needed.'
214 +typeset -A OID2ADEF=( )
215 +Man.addVar ANAME2OID 'Associative array of Strings. Key: attribute name (lowercase), Value: OID. Used to cache name to OID mappings. Gets initialized, when \bOID2ADEF\b gets populated.'
216 +typeset -A ANAME2OID=( )
196 217
197 -EOF
198 - ;;
199 - ldap_suffix_list) cat <<EOF
218 +Man.addVar OID2ODEF 'Associative array of Strings. Key: OID, Value: objectclass definition. Used to cache objectclass definitions of schemas currently installed on the DS. Gets lazy initialized, i.e. populated when needed.'
219 +typeset -A OID2ODEF=( )
200 220
201 -No valid suffixes (naming contexts) were found for LDAP base DN:
202 -${LDAP_BASEDN}
221 +Man.addFunc checkBinary '' '[+NAME?checkBinary - lookup a command.]
222 +[+DESCRIPTION?Check the standard path, whether it contains \acmd\a and if not, use \aPATH\a to lookup the command. If found the full path of the command gets printed to stdout, otherwise an error message to stderr.]
223 +[+RETURN VALUES]{
224 + [+0?\acmd\a found.]
225 + [+1?\acmd\a not found.]
226 +}
227 +[+SEE ALSO?\bwhence\b(1).]
228 +\n\n\acmd\a
229 +'
230 +function checkBinary {
231 + typeset CMD=$1 X=''
232 + for DIR in /usr/bin /usr/sbin ; do
233 + [[ -x ${DIR}/${CMD} ]] && print ${DIR}/${CMD} && return 0
234 + done
235 + X=${ whence -fp ${CMD} ; }
236 + [[ -n $X ]] && print "${X}" && return 0
237 + X="${.sh.file%/*}/${CMD}"
238 + [[ -x ${X} ]] && print "$X" && return 0
239 + print -u2 "Missing command '${CMD}'."
240 + return 1
241 +}
203 242
204 -Available suffixes are:
205 -${LDAP_SUFFIX_LIST}
243 +Man.addFunc init '' '[+NAME?init - initializes variables and options.]
244 +[+DESCRIPTION?Does some basic binary-avail checks and initializes certain values of \bSTR[]]\b, \bINT[]]\b and \bTMP[]]\b.]
245 +'
246 +function init {
247 + typeset X='' KEY VAL TAIL
248 + integer ERR=0
206 249
207 -EOF
208 - ;;
209 - sorry) cat <<EOF
250 + # General commands
251 + HOST=${ hostname ; }
252 + PING=${ checkBinary ping || (( ERR++ )) ; }
253 + STTY=${ checkBinary stty || (( ERR++ )) ; }
254 + GETENT=${ checkBinary getent || (( ERR++ )) ; }
210 255
211 -HELP - No help is available for this topic.
256 + # LDAP COMMANDS
257 + LDAPSEARCH=${ checkBinary ldapsearch || (( ERR++ )) ; }
258 + LDAPMODIFY=${ checkBinary ldapmodify || (( ERR++ )) ; }
259 + LDAPDELETE=${ checkBinary ldapdelete || (( ERR++ )) ; }
260 + LDAPCLIENT=${ checkBinary ldapclient || (( ERR++ )) ; }
212 261
213 -EOF
214 - ;;
215 - create_suffix_help) cat <<EOF
262 + if (( ERR )); then
263 + Log.fatal 'Please adjust your PATH and try again'
264 + return 66
265 + fi
266 + LDAPSEARCH+=' -r'
216 267
217 -HELP - Our Base DN is ${LDAP_BASEDN}
218 - and we need to create a Directory Suffix,
219 - which can be equal to Base DN itself or be any of Base DN parents.
220 - All intermediate entries up to suffix will be created on demand.
268 + # If DNS domain (resolv.conf) exists use that, otherwise use domainname.
269 + if [[ -f /etc/resolv.conf ]]; then
270 + while read KEY VAL TAIL ; do
271 + if [[ ${KEY} == 'domain' || ${KEY} == 'search' ]]; then
272 + X=${VAL}
273 + break;
274 + fi
275 + done < /etc/resolv.conf
276 + fi
221 277
222 -EOF
223 - ;;
224 - enter_ldbm_db_help) cat <<EOF
278 + # If for any reason the DOMAIN did not get set (error'd resolv.conf) set
279 + # X to the domainname or getent command's output.
280 + [[ -z $X ]] && X=${ domainname ; }
281 + if [[ -z $X ]]; then
282 + typeset -a AX=( ${ ${GETENT} hosts ${HOST} 2>/dev/null ; } )
283 + integer I
284 + for (( I=${#AX[@]}-1; I > 0; I++ )); do
285 + X=${AX[$I]#*.}
286 + [[ -n $X ]] && break
287 + done
288 + fi
225 289
226 -HELP - ldbm database is an internal database for storage of our suffix data.
227 - Database name must be alphanumeric due to Directory Server restriction.
290 + # Actually one needs to init non-null/zero values, only. However, we want
291 + # to have the keys registered ...
228 292
229 -EOF
230 - ;;
231 - backup_help) cat <<EOF
293 + # idsconfig specific variables.
294 + INT[LDAP_ENABLE_SHADOW_UPDATE]=0
295 + INT[NEED_PROXY]=0 # 0 = No Proxy, 1 = Create Proxy.
296 + INT[NEED_ADMIN]=0 # 0 = No Admin, 1 = Create Admin.
297 + INT[NEED_HOSTACL]=0 # 0 = No Host ACL, 1 = Create Host ACL.
298 + INT[EXISTING_PROFILE]=0
299 + (( INT[TASK_TIMEOUT] < 10 )) && INT[TASK_TIMEOUT]=60
300 + STR[LDAP_PROXYAGENT]=''
301 + STR[LDAP_PROXYAGENT_CRED]=''
302 + STR[LDAP_ADMINDN]=''
303 + STR[LDAP_ADMIN_CRED]='' # enableShadowUpdate flag and Admin credential
304 + STR[DS_DB]='' # storage backend name
305 + STR[LDAP_SUFFIX]='' # suffix within the backend
306 + STR[LDAP_DOMAIN]=${X%%.} # domainname on Server (default value)
307 +
308 + # DS specific information
309 + STR[DS_HOST]=''
310 + INT[DS_PORT]=389
311 + INT[NEED_TIME]=0
312 + INT[NEED_SIZE]=0
313 + INT[DS_TIMELIMIT]=0
314 + INT[DS_SIZELIMIT]=0
232 315
233 -HELP - Since idsconfig modifies the directory server configuration,
234 - it is strongly recommended that you backup the server prior
235 - to running this utility. This is especially true if the server
236 - being configured is a production server.
316 + # LDAP PROFILE related defaults
317 + STR[LDAP_ROOTDN]='cn=Directory Manager' # Provide common default.
318 + STR[LDAP_ROOTPWD]='' # NULL passwd (is invalid)
319 + STR[LDAP_PROFILE_NAME]='default'
320 + STR[LDAP_BASEDN]=''
321 + STR[LDAP_SERVER_LIST]=''
322 + STR[LDAP_AUTHMETHOD]=''
323 + INT[LDAP_FOLLOWREF]=0
324 + INT[NEED_CRYPT]=0
325 + INT[NEED_SRVAUTH_PAM]=0
326 + INT[NEED_SRVAUTH_KEY]=0
327 + INT[NEED_SRVAUTH_CMD]=0
328 + (( ! INT[NEED_CRYPT_IMPORT] )) && INT[NEED_CRYPT_IMPORT]=0
329 + STR[LDAP_SEARCH_SCOPE]='one'
330 + STR[LDAP_SRV_AUTHMETHOD_PAM]=''
331 + STR[LDAP_SRV_AUTHMETHOD_KEY]=''
332 + STR[LDAP_SRV_AUTHMETHOD_CMD]=''
333 + INT[LDAP_SEARCH_TIME_LIMIT]=30
334 + STR[LDAP_PREF_SRVLIST]=''
335 + INT[LDAP_PROFILE_TTL]=43200
336 + STR[LDAP_CRED_LEVEL]='proxy'
337 + INT[LDAP_BIND_LIMIT]=10
237 338
238 -EOF
239 - ;;
240 - port_help) cat <<EOF
339 + # Service Search Descriptors (just make sure it is empty)
340 + SSD=( ); unset SSD[0] # unset is required!
241 341
242 -HELP - Enter the port number the directory server is configured to
243 - use for LDAP.
342 + # GSSAPI setup
343 + INT[GSSAPI_ENABLE]=0
344 + STR[LDAP_KRB_REALM]=''
244 345
245 -EOF
246 - ;;
247 - domain_help) cat <<EOF
346 + # temp settings
347 + TMPF[STEP]=0 # internal file counter - see nextFile()
348 + TMPF[IS_OPENDJ]=0 # set if detected DS is OpenDS/OpenDJ
349 + TMPF[DEL_OLD_PROFILE]=0 # 0 = don't, 1 = delete old profile
350 + TMPF[STEP]=1 # simple progress indicator
351 + TMPF[GSSAPI_AUTH_MAY_BE_USED]=0 # DS GSSAPI SASL support
352 + TMPF[NEED_CREATE_SUFFIX]=0 # see add_suffix()
353 + TMPF[NEED_CREATE_BACKEND]=0 # see add_suffix()
354 + # schema completion syntax to use:
355 + # 0 .. detect, 1 .. force OpenDJ, 2 .. force DSEE
356 + (( TMPF[SYNTAX] < 0 || TMPF[SYNTAX] > 2 )) && TMPF[SYNTAX]=0
248 357
358 + TMP[FILE]='' # tmp output filename - see nextFile()
359 + TMP[LDAP_ROOTPWF]=${TMP[DIR]}/rootPWD # filename containing the root PW
360 + TMP[WARN]='' # set if possibly incompatible DS
361 + TMP[SUFFIX_OBJ]='' # suffix objectclass (long name)
362 + TMP[SUFFIX_ATT]='' # suffix RDN attr name
363 + TMP[SUFFIX_VAL]='' # suffix RDN attr value
364 + TMP[DS_DBS_AVAIL]='' # next available suffix DBs
365 + TMP[VLV_CMDS]='' # where VLV commands to exec are stored
366 + # Set via getopts - just make sure, they are registered
367 + [[ -z ${TMP[IN]} ]] && TMP[IN]='' # the config file to read
368 + [[ -z ${TMP[OUT]} ]] && TMP[OUT]='' # the config file to write
369 + # redirect ldap output to file instead of stdout
370 + if (( TMPF[FD] > 2 )); then
371 + exec 4>${TMP[DIR]}/ldap.out
372 + fi
373 + return 0
374 +}
375 +
376 +# internal
377 +function showProgress {
378 + typeset NUM=${ printf "%3d" TMPF[STEP] ; }
379 + Log.info "${NUM}. " "$*"
380 + (( TMPF[STEP]++ ))
381 +}
382 +
383 +# internal
384 +function nextFile {
385 + typeset CMD="$1" FN="${2// /_}" EXT='cmd'
386 + (( TMPF[STEP]++ ))
387 + case "$1" in
388 + add|modify|delete) CMD="ldap$1" EXT='ldif' ;;
389 + sh) EXT='sh'
390 + esac
391 + TMP[FILE]=${ printf "${TMP[DIR]}/%03d_${CMD}_${FN}.${EXT}" ${TMPF[STEP]} ; }
392 + [[ -e ${TMP[FILE]} ]] && Log.warn "Overwriting ${TMP[FILE]} ..."
393 +}
394 +
395 +Man.addFunc show_vars '' '[+NAME?show_vars - List of all config variables and their values.]
396 +[+DESCRIPTION?Lists all config variables and their current values in a more or less human readable manner.]
397 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage INT STR SSD ; }" '}
398 +'
399 +function show_vars {
400 + (( ! VERBOSE )) && return
401 +
402 + typeset S=${!STR[@]} OUT='Current non-NULL values:\n'
403 + S=${ print ${S// /$'\n'} | sort ; }
404 + for KEY in $S ; do
405 + [[ -n ${STR[$KEY]} ]] && \
406 + OUT+=${ printf "%32s = '%s'" ${KEY} "${STR[$KEY]}" ; }'\n'
407 + done
408 + S=${!INT[@]}
409 + S=${ print ${S// /$'\n'} | sort ; }
410 + for KEY in $S ; do
411 + (( INT[$KEY] )) && \
412 + OUT+=${ printf "%32s = %d" ${KEY} "${INT[$KEY]}" ; }'\n'
413 + done
414 + if (( ${#SSD[@]} )); then
415 + OUT+=${ printf "%32s = (" 'SSD' ; }
416 + for S in "${SSD[@]}" ; do
417 + OUT+="\t\t${S}\n"
418 + done
419 + OUT+='\t)\n'
420 + fi
421 + print -u2 "${OUT}"
422 +}
423 +
424 +Man.addFunc save_password '' '[+NAME?save_password - Save password to temporary file.]
425 +[+DESCRIPTION?Save the current password from \bSTR[LDAP_ROOTPWD]]\b to the file \bTMP[LDAP_ROOTPWF]]\b.]
426 +'
427 +function save_password {
428 + print "${STR[LDAP_ROOTPWD]}" >"${TMP[LDAP_ROOTPWF]}"
429 +}
430 +#############################################################################
431 +# EOG
432 +#############################################################################
433 +
434 +
435 +#############################################################################
436 +# config file stuff
437 +#############################################################################
438 +Man.addFunc create_config_file '' '[+NAME?create_config_file - Write config data to the specified file.]
439 +[+DESCRIPTION?Write config data to \afile\a.]
440 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage INT STR SSD ; }" '}
441 +[+RETURN VALUES]{
442 + [+0?file was written successfully.]
443 + [+>= 1?otherwise.]
444 +}
445 +[+SEE ALSO?\bload_config_file()\b.]
446 +\n\n\afile\a
447 +'
448 +function create_config_file {
449 + typeset OUT="$1" KEY
450 + [[ -z ${OUT} ]] && return 1
451 +
452 + # Create output file.
453 + (
454 + print '
455 +# '"${OUT}"' - This file contains configuration information for
456 +# LDAP naming services. Use the '"${PROG}"' tool to load it.
457 +#
458 +# WARNING: This file was generated by '"${PROG}"', and is intended to
459 +# be loaded by '"${PROG}"' as is. DO NOT EDIT THIS FILE!
460 +'
461 + print 'typeset -A -i IIN=( )'
462 + for KEY in "${!INT[@]}" ; do
463 + print "IIN[${KEY}]=${INT[${KEY}]}"
464 + done
465 + print '\ntypeset -A SIN=( )'
466 + for KEY in "${!STR[@]}" ; do
467 + printf "SIN[${KEY}]=%q\n" "${STR[${KEY}]}"
468 + done
469 + print '\ntypeset -a SIN_SSD=( )'
470 + for KEY in "${SSD[@]}" ; do
471 + [[ -n ${KEY} ]] && printf "SIN_SSD+=( %q )\n" "${KEY}"
472 + done
473 + print "\n# End of ${OUT}"
474 + ) >"${OUT}"
475 +}
476 +
477 +# for backward compatibilty, but not documented: old format is bogus and should
478 +# not be used anymore.
479 +function source_old_config {
480 + typeset IN="$1" TODO='' VNAME KEY VAL LINE
481 + typeset -A OLDMAP=(
482 + [DS_HOST]=IDS_SERVER
483 + [DS_PORT]=IDS_PORT
484 + [DS_DB]=IDS_DATABASE
485 + [DS_TIMELIMIT]=IDS_TIMELIMIT
486 + [DS_SIZELIMIT]=IDS_SIZELIMIT
487 + [SSD]=LDAP_SERV_SRCH_DES
488 + )
489 +
490 + for KEY in "${!INT[@]}" ; do
491 + VNAME=${OLDMAP[${KEY}]}
492 + [[ -z ${VNAME} ]] && VNAME=${KEY}
493 + typeset -n VAR=${VNAME}
494 + INT[${KEY}]=${VAR}
495 + TODO+="${VNAME} "
496 + done
497 + for KEY in "${!STR[@]}" ; do
498 + VNAME=${OLDMAP[${KEY}]}
499 + [[ -z ${VNAME} ]] && VNAME=${KEY}
500 + typeset -n VAR=${VNAME}
501 + STR[${KEY}]="${VAR}"
502 + TODO+="${VNAME} "
503 + done
504 + while read LINE; do
505 + if [[ ${LINE:0:19} == 'LDAP_SERV_SRCH_DES=' ]]; then
506 + VAL="${LINE:19}"
507 + [[ -n ${VAL} ]] && SSD+=( "${VAL}" )
508 + fi
509 + done < "${IN}"
510 +
511 + # cleanup "global" namespace
512 + [[ -n ${TODO} ]] && eval "unset ${TODO}"
513 +}
514 +
515 +Man.addFunc load_config_file '' '[+NAME?load_config_file - load an '"${PROG}"' config file.]
516 +[+DESCRIPTION?Loads the initial config from \afile\a, which has been generated in a previous run by '"${PROG}"'. Sets \bTMPF[DEL_OLD_PROFILE]]\b to 1 on success.]
517 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage INT STR SSD ; }" '}
518 +[+RETURN VALUES]{
519 + [+0?on success.]
520 + [+>= 66? \afile\a is not a file or unreadable.]
521 +}
522 +[+SEE ALSO?\bsave_password()\b, \bshow_vars()\b.]
523 +\n\n\afile\a
524 +'
525 +function load_config_file {
526 + typeset IN="$1" KEY VAL
527 + integer I
528 + [[ ! -f ${IN} ]] && Log.fatal "${IN} is not a file" && return 66
529 + [[ ! -r ${IN} ]] && Log.fatal "${IN} is not readable" && return 67
530 +
531 + # source in the stuff - not nice but less work ;-)
532 + . "${IN}"
533 +
534 + KEY=${ typeset -p IIN ; }
535 + if [[ -z ${KEY} ]]; then
536 + source_old_config "${IN}" || return 68
537 + else
538 + for KEY in "${!INT[@]}" ; do
539 + INT[${KEY}]=${IIN[${KEY}]}
540 + done
541 + for KEY in "${!STR[@]}" ; do
542 + STR[${KEY}]="${SIN[${KEY}]}"
543 + done
544 + for KEY in "${SIN_SSD[@]}" ; do
545 + [[ -n ${KEY} ]] && SSD+=( "${KEY}" )
546 + done
547 + # cleanup "global" namespace
548 + unset IIN SIN SIN_SSD
549 + fi
550 +
551 + TMPF[DEL_OLD_PROFILE]=1
552 + save_password
553 + show_vars
554 +
555 + return 0
556 +}
557 +#############################################################################
558 +# End Of config file stuff
559 +#############################################################################
560 +
561 +
562 +############################################################################
563 +# Basic [menu] stuff
564 +############################################################################
565 +Man.addFunc display_msg '' '[+NAME?display_msg - display a message]
566 +[+DESCRIPTION?Display a message corresponding to the \atag\a passed in.]
567 +[+ENVIRONMENT VARIABLES]{'"${ Man.varUsage INT STR TMP ; }" '}
568 +\n\n\atag\a
569 +'
570 +function display_msg {
571 + typeset X
572 + integer I
573 +
574 + case "$1" in
575 + backup_server)
576 + print '
577 +It is strongly recommended that you BACKUP the directory server
578 +before running '"${PROG}"'.
579 +
580 +Hit Ctrl-C at any time before the final confirmation to exit.\n'
581 + ;;
582 + cred_level_menu)
583 + print 'The following are the supported credential levels:'
584 + for (( I=0; I < ${#CRED_LEVELS[@]}; I++ )); do
585 + printf ' %2d %s\n' $((I+1)) "${CRED_LEVELS[I]}"
586 + done
587 + ;;
588 + auth_method_menu)
589 + print 'The following are the supported Client Authentication Methods:'
590 + for (( I=0; I < ${#AUTH_METHODS[@]}; I++ )); do
591 + printf ' %-2d %s\n' $((I+1)) "${AUTH_METHODS[I]}"
592 + done
593 + ;;
594 + srvauth_method_menu)
595 + print 'The following are the supported Service Authentication Methods:'
596 + # skip 'none'
597 + for (( I=1; I < ${#AUTH_METHODS[@]}; I++ )); do
598 + printf ' %-2d %s\n' $((I)) "${AUTH_METHODS[I]}"
599 + done
600 + ;;
601 + prompt_ssd_menu)
602 + print ' A Add a Service Search Descriptor (SSD)
603 + D Delete a SSD
604 + M Modify a SSD
605 + P Display all SSDs
606 + H Help
607 + X Clear all SSDs
608 +
609 + Q Exit menu'
610 + ;;
611 + summary_menu)
612 + typeset SUFFIX_INFO=''
613 + typeset DB_INFO=''
614 +
615 + if (( TMPF[NEED_CREATE_SUFFIX] )); then
616 + SUFFIX_INFO='
617 + Suffix to create : '"${STR[LDAP_SUFFIX]}"'\n'
618 + (( TMPF[NEED_CREATE_BACKEND] )) && DB_INFO='
619 + Database to create : '"${STR[DS_DB]}"'\n'
620 + fi
621 + typeset BASEDN
622 + BASEDN="${STR[LDAP_BASEDN]}${STR[SUFFIX_INFO]}${STR[DB_INFO]}"
623 +
624 + print ' Summary of Configuration
625 +
626 + 1 Domain to serve : '"${STR[LDAP_DOMAIN]}"'
627 + 2 Base DN to setup : '"${BASEDN}"'
628 + 3 Profile name to create : '"${STR[LDAP_PROFILE_NAME]}"'
629 + 4 Default Server List : '"${STR[LDAP_SERVER_LIST]}"'
630 + 5 Preferred Server List : '"${STR[LDAP_PREF_SRVLIST]}"'
631 + 6 Default Search Scope : '"${STR[LDAP_SEARCH_SCOPE]}"'
632 + 7 Credential Level : '"${STR[LDAP_CRED_LEVEL]}"'
633 + 8 Authentication Method : '"${STR[LDAP_AUTHMETHOD]}"'
634 + 9 Enable Follow Referrals : '"${INT[LDAP_FOLLOWREF]}"'
635 + 10 DS Time Limit : '"${INT[DS_TIMELIMIT]}"'
636 + 11 DS Size Limit : '"${INT[DS_SIZELIMIT]}"'
637 + 12 Enable crypt password storage : '"${INT[NEED_CRYPT]}"'
638 + 13 Service Auth Method pam_ldap : '"${STR[LDAP_SRV_AUTHMETHOD_PAM]}"'
639 + 14 Service Auth Method keyserv : '"${STR[LDAP_SRV_AUTHMETHOD_KEY]}"'
640 + 15 Service Auth Method passwd-cmd: '"${STR[LDAP_SRV_AUTHMETHOD_CMD]}"'
641 + 16 Search Time Limit : '"${INT[LDAP_SEARCH_TIME_LIMIT]}"'
642 + 17 Profile Time to Live : '"${INT[LDAP_PROFILE_TTL]}"'
643 + 18 Bind Limit : '"${INT[LDAP_BIND_LIMIT]}"'
644 + 19 Enable shadow update : '"${INT[LDAP_ENABLE_SHADOW_UPDATE]}"'
645 + 20 Service Search Descriptors Menu\n'
646 + ;;
647 + sorry)
648 + print '
649 +HELP - No help is available for this topic.\n'
650 + ;;
651 + create_suffix_help)
652 + print '
653 +HELP - Our Base DN is "'"${STR[LDAP_BASEDN]}"'"
654 + and we need to create a Directory Suffix,
655 + which can be equal to Base DN itself or be any of Base DN parents.
656 + All intermediate entries up to suffix will be created on demand.\n'
657 + ;;
658 + enter_ldbm_db_help)
659 + print '
660 +HELP - database backend is an internal database for storage of our suffix data.
661 + Backend name must be alphanumeric due to Directory Server restriction.
662 +'
663 + ;;
664 + backup_help)
665 + print '
666 +HELP - Since '"${PROG}"' modifies the directory server configuration,
667 + it is strongly recommended that you backup the server prior
668 + to running this utility. This is especially true if the server
669 + being configured is a production server.\n'
670 + ;;
671 + port_help)
672 + print '
673 +HELP - Enter the port number the directory server is configured to
674 + use for LDAP.\n'
675 + ;;
676 + adminport_help)
677 + print '
678 +HELP - Enter the Admin port number the directory server is configured to
679 + use for for DS administration commands.\n'
680 + ;;
681 + domain_help)
682 + print '
249 683 HELP - This is the DNS domain name this server will be serving. You
250 684 must provide this name even if the server is not going to be populated
251 685 with hostnames. Any unqualified hostname stored in the directory
252 - will be fully qualified using this DNS domain name.
253 -
254 -EOF
255 - ;;
256 - basedn_help) cat <<EOF
257 -
686 + will be fully qualified using this DNS domain name.\n'
687 + ;;
688 + basedn_help)
689 + print '
258 690 HELP - This parameter defines the default location in the directory tree for
259 691 the naming services entries. You can override this default by using
260 - serviceSearchDescriptors (SSD). You will be given the option to set up
261 - an SSD later on in the setup.
262 -
263 -EOF
264 - ;;
265 - profile_help) cat <<EOF
266 -
692 + Service Search Descriptors (SSD). You will be given the option to set up
693 + an SSD later on in the setup.\n'
694 + ;;
695 + profile_help)
696 + print '
267 697 HELP - Name of the configuration profile with which the clients will be
268 698 configured. A directory server can store various profiles for multiple
269 699 groups of clients. The initialization tool, (ldapclient(1M)), assumes
270 - "default" unless another is specified.
271 -
272 -EOF
273 - ;;
274 - def_srvlist_help) cat <<EOF
275 -
700 + "default" unless another is specified.\n'
701 + ;;
702 + def_srvlist_help)
703 + print '
276 704 HELP - Provide a list of directory servers to serve clients using this profile.
277 705 All these servers should contain consistent data and provide similar
278 706 functionality. This list is not ordered, and clients might change the
279 707 order given in this list. Note that this is a space separated list of
280 - *IP addresses* (not host names). Providing port numbers is optional.
281 -
282 -EOF
283 - ;;
284 - pref_srvlist_help) cat <<EOF
285 -
708 + *IP addresses* (not host names). Providing port numbers is optional.\n'
709 + ;;
710 + pref_srvlist_help)
711 + print '
286 712 HELP - Provide a list of directory servers to serve this client profile.
287 713 Unlike the default server list, which is not ordered, the preferred
288 714 servers must be entered IN THE ORDER you wish to have them contacted.
289 715 If you do specify a preferred server list, clients will always contact
290 716 them before attempting to contact any of the servers on the default
291 717 server list. Note that you must enter the preferred server list as a
292 718 space-separated list of *IP addresses* (not host names). Providing port
293 - numbers is optional.
294 -
295 -EOF
296 - ;;
297 - srch_scope_help) cat <<EOF
298 -
719 + numbers is optional.\n'
720 + ;;
721 + srch_scope_help)
722 + print '
299 723 HELP - Default search scope to be used for all searches unless they are
300 724 overwritten using serviceSearchDescriptors. The valid options
301 725 are "one", which would specify the search will only be performed
302 726 at the base DN for the given service, or "sub", which would specify
303 727 the search will be performed through *all* levels below the base DN
304 - for the given service.
305 -
306 -EOF
307 - ;;
308 - cred_lvl_help) cat <<EOF
309 -
310 -HELP - This parameter defines what credentials the clients use to
311 - authenticate to the directory server. This list might contain
312 - multiple credential levels and is ordered. If a proxy level
313 - is configured, you will also be prompted to enter a bind DN
314 - for the proxy agent along with a password. This proxy agent
315 - will be created if it does not exist.
316 -
317 -EOF
318 - ;;
319 - auth_help) cat <<EOF
320 -
321 -HELP - The default authentication method(s) to be used by all services
728 + for the given service. If you use the default DIT layout, "one" should
729 + be ok and probably a little bit faster.\n'
730 + ;;
731 + cred_lvl_help)
732 + print '
733 +HELP - This parameter defines what credentials (identity) the clients use to
734 + authenticate (bind) to the directory server. This list might contain
735 + multiple credential levels and is ordered. If a proxy level is
736 + configured, you will also be prompted to enter a bind DN for the
737 + proxy agent along with a password. This proxy agent will be created
738 + if it does not exist. See also ldapclient(1M).\n'
739 + ;;
740 + auth_help)
741 + print '
742 +HELP - The default authentication (bind) method(s) to be used by all services
322 743 in the client using this profile. This is a ordered list of
323 - authentication methods separated by a ';'. The supported methods
324 - are provided in a menu. Note that sasl/DIGEST-MD5 binds require
325 - passwords to be stored un-encrypted on the server.
326 -
327 -EOF
328 - ;;
329 - srvauth_help) cat <<EOF
330 -
331 -HELP - The authentication methods to be used by a given service. Currently
332 - 3 services support this feature: pam_ldap, keyserv, and passwd-cmd.
333 - The authentication method specified in this attribute overrides
744 + authentication methods separated by a ";". The supported methods are
745 + provided in a menu. Note that sasl/DIGEST-MD5 binds require passwords
746 + to be stored un-encrypted on the server. See also ldapclient(1M).\n'
747 + ;;
748 + srvauth_help)
749 + print '
750 +HELP - The non-default authentication (bind) methods to be used by certain
751 + services (for now pam_ldap, keyserv, and passwd-cmd are supported).
752 + The authentication methods specified in this attribute overrides
334 753 the default authentication method defined in the profile. This
335 754 feature can be used to select stronger authentication methods for
336 - services which require increased security.
337 -
338 -EOF
339 - ;;
340 - pam_ldap_help) cat <<EOF
341 -
342 -HELP - The authentication method(s) to be used by pam_ldap when contacting
343 - the directory server. This is a ordered list, and, if provided, will
344 - override the default authentication method parameter.
345 -
346 -EOF
347 - ;;
348 - keyserv_help) cat <<EOF
349 -
350 -HELP - The authentication method(s) to be used by newkey(1M) and chkey(1)
351 - when contacting the directory server. This is a ordered list and
352 - if provided will override the default authentication method
353 - parameter.
354 -
355 -EOF
356 - ;;
357 - passwd-cmd_help) cat <<EOF
358 -
359 -HELP - The authentication method(s) to be used by passwd(1) command when
755 + services which require increased security.\n'
756 + ;;
757 + pam_ldap_help)
758 + print '
759 +HELP - The authentication (bind) method(s) to be used by pam_ldap when
760 + contacting the directory server. This is a ordered list, and, if
761 + provided, will override the default authentication method parameter.\n'
762 + ;;
763 + keyserv_help)
764 + print '
765 +HELP - The authentication (bind) method(s) to be used by newkey(1M) and chkey(1)
766 + when contacting the directory server. This is a ordered list and if
767 + provided will override the default authentication method parameter.\n'
768 + ;;
769 + passwd-cmd_help)
770 + print '
771 +HELP - The authentication (bind) method(s) to be used by passwd(1) command when
360 772 contacting the directory server. This is a ordered list and if
361 - provided will override the default authentication method parameter.
362 -
363 -EOF
364 - ;;
365 - referrals_help) cat <<EOF
366 -
773 + provided will override the default authentication method parameter.\n'
774 + ;;
775 + referrals_help)
776 + print '
367 777 HELP - This parameter indicates whether the client should follow
368 - ldap referrals if it encounters one during naming lookups.
369 -
370 -EOF
371 - ;;
372 - tlim_help) cat <<EOF
373 -
778 + ldap referrals if it encounters one during naming lookups.\n'
779 + ;;
780 + tlim_help)
781 + print '
374 782 HELP - The server time limit value indicates the maximum amount of time the
375 783 server would spend on a query from the client before abandoning it.
376 - A value of '-1' indicates no limit.
377 -
378 -EOF
379 - ;;
380 - slim_help) cat <<EOF
381 -
784 + A value of "-1" indicates no limit.\n'
785 + ;;
786 + slim_help)
787 + print '
382 788 HELP - The server sizelimit value indicates the maximum number of entries
383 789 the server would return in respond to a query from the client. A
384 - value of '-1' indicates no limit.
385 -
386 -EOF
387 - ;;
388 - crypt_help) cat <<EOF
389 -
390 -HELP - By default iDS does not store userPassword attribute values using
391 - unix "crypt" format. If you need to keep your passwords in the crypt
392 - format for NIS/NIS+ and pam_unix compatibility, choose 'yes'. If
393 - passwords are stored using any other format than crypt, pam_ldap
790 + value of "-1" indicates no limit.\n'
791 + ;;
792 + crypt_help)
793 + print '
794 +HELP - By default a DS does not store userPassword attribute values using
795 + unix "crypt" formats (like bsdmd5, sunmd5, sha256, sha512, old crypt,
796 + etc. - see crypt.conf(4)). If you need to keep your passwords in the
797 + crypt formats for backward or pam_unix compatibility, choose "yes".
798 + If any other password storage scheme than crypt is used, pam_ldap
394 799 MUST be used by clients to authenticate users to the system. Note
395 - that if you wish to use sasl/DIGEST-MD5 in conjunction with pam_ldap,
396 - user passwords must be stored in the clear format.
397 -
398 -EOF
399 - ;;
400 - srchtime_help) cat <<EOF
401 -
402 -HELP - The search time limit the client will enforce for directory
403 - lookups.
404 -
405 -EOF
406 - ;;
407 - profttl_help) cat <<EOF
408 -
800 + that if you wish to use sasl/*-MD5 in conjunction with pam_ldap,
801 + user passwords are/must be stored in the clear text.\n'
802 + ;;
803 + srchtime_help)
804 + print '
805 +HELP - The search time limit the client will enforce for directory lookups.\n'
806 + ;;
807 + profttl_help)
808 + print '
409 809 HELP - The time to live value for profile. The client will refresh its
410 - cached version of the configuration profile at this TTL interval.
411 -
412 -EOF
413 - ;;
414 - bindlim_help) cat <<EOF
415 -
810 + cached version of the configuration profile at this TTL interval.\n'
811 + ;;
812 + bindlim_help)
813 + print '
416 814 HELP - The time limit for the bind operation to the directory. This
417 815 value controls the responsiveness of the client in case a server
418 816 becomes unavailable. The smallest timeout value for a given
419 817 network architecture/conditions would work best. This is very
420 - similar to setting TCP timeout, but only for LDAP bind operation.
421 -
422 -EOF
423 - ;;
424 - ssd_help) cat <<EOF
425 -
818 + similar to setting TCP timeout, but only for LDAP bind operation.\n'
819 + ;;
820 + ssd_help)
821 + print '
426 822 HELP - Using Service Search Descriptors (SSD), you can override the
427 823 default configuration for a given service. The SSD can be
428 824 used to override the default search base DN, the default search
429 825 scope, and the default search filter to be used for directory
430 826 lookups. SSD are supported for all services (databases)
431 - defined in nsswitch.conf(4). The default base DN is defined
432 - in ldap(1).
827 + defined in nsswitch.conf(4). See also ldapclient(1M).
433 828
434 829 Note: SSD are powerful tools in defining configuration profiles
435 830 and provide a great deal of flexibility. However, care
436 831 must be taken in creating them. If you decide to make use
437 - of SSDs, consult the documentation first.
438 -
439 -EOF
440 - ;;
441 - ssd_menu_help) cat <<EOF
442 -
832 + of SSDs, consult the documentation first.\n'
833 + ;;
834 + ssd_menu_help)
835 + print '
443 836 HELP - Using this menu SSD can be added, updated, or deleted from
444 837 the profile.
445 838
446 839 A - This option creates a new SSD by prompting for the
447 840 service name, base DN, and scope. Service name is
448 841 any valid service as defined in ldap(1). base is
449 842 either the distinguished name to the container where
450 843 this service will use, or a relative DN followed
451 - by a ','.
844 + by a ",". For more information see ldapclient(1M).
452 845 D - Delete a previously created SSD.
453 846 M - Modify a previously created SSD.
454 847 P - Display a list of all the previously created SSD.
455 848 X - Delete all of the previously created SSD.
456 849
457 - Q - Exit the menu and continue with the server configuration.
458 -
459 -EOF
460 - ;;
461 - ldap_suffix_list_help) cat <<EOF
462 -
463 -HELP - No valid suffixes (naming contexts) are available on server
464 - ${IDS_SERVER}:${IDS_PORT}.
465 - You must set an LDAP Base DN that can be contained in
466 - an existing suffix.
467 -
468 -EOF
469 - ;;
470 - enable_shadow_update_help) cat <<EOF
471 -
472 -HELP - Enter 'y' to set up the LDAP server for shadow update.
850 + Q - Exit the menu and continue with the server configuration.\n'
851 + ;;
852 + enable_shadow_update_help)
853 + print '
854 +HELP - Enter "y" to set up the LDAP server for shadow update.
473 855 The setup will add an administrator identity/credential
474 856 and modify the necessary access controls for the client
475 - to update shadow(4) data on the LDAP server. If sasl/GSSAPI
476 - is in use, the Kerberos host principal will be used as the
477 - administrator identity.
857 + to update shadow(4), auth_attr(4), exec_attr(4), prof_attr(4),
858 + user_attr(4), and project(4) data on the LDAP server. If
859 + sasl/GSSAPI is in use, the Kerberos host principal will be used
860 + as the administrator identity.
478 861
479 862 Shadow data is used for password aging and account locking.
480 - Please refer to the shadow(4) manual page for details.
481 -
482 -EOF
483 - ;;
484 - add_admin_cred_help) cat <<EOF
485 -
863 + Please refer to the shadow(4) manual page for details.\n'
864 + ;;
865 + add_admin_cred_help)
866 + print '
486 867 HELP - Start the setup to add an administrator identity/credential
487 868 and to modify access controls for the client to update
488 - shadow(4) data on the LDAP server.
869 + shadow(4), auth_attr(4), exec_attr(4), prof_attr(4),
870 + user_attr(4), and project(4) data on the LDAP server.
489 871
490 872 Shadow data is used for password aging and account locking.
491 - Please refer to the shadow(4) manual page for details.
492 -
493 -EOF
494 - ;;
495 - use_host_principal_help) cat <<EOF
496 -
497 -HELP - A profile with a 'sasl/GSSAPI' authentication method and a 'self'
498 - credential level is detected, enter 'y' to modify the necessary
873 + Please refer to the shadow(4) manual page for details.\n'
874 + ;;
875 + use_host_principal_help)
876 + print '
877 +HELP - A profile with a "sasl/GSSAPI" authentication method and a "self"
878 + credential level is detected, enter "y" to modify the necessary
499 879 access controls for allowing the client to update shadow(4) data
500 880 on the LDAP server.
501 881
502 882 Shadow data is used for password aging and account locking.
503 - Please refer to the shadow(4) manual page for details.
883 + Please refer to the shadow(4) manual page for details.\n'
884 + ;;
885 + esac
886 +}
504 887
505 -EOF
506 - ;;
507 - esac
888 +Man.addVar ANS 'Variable used to return the user input.'
889 +Man.addFunc get_ans '' '[+NAME?get_ans - gets an answer from the user.]
890 +[+DESCRIPTION?Read a string from stdin. Arguments:]{
891 + [+prompt?instruction/comment/description/question to show.]
892 + [+default?Default value to use if no answer/empty string was read.]
508 893 }
894 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage ANS ; }" '}
895 +\n\n\aprompt\a [\adefault\a]
896 +'
897 +function get_ans {
898 + typeset PROMPT="$1 "
899 + [[ -n $2 ]] && PROMPT+="[$2] "
509 900
901 + read ANS?"${PROMPT}"
902 + [[ -z ${ANS} ]] && ANS="$2"
903 +}
510 904
511 -#
512 -# get_ans(): gets an answer from the user.
513 -# $1 instruction/comment/description/question
514 -# $2 default value
515 -#
516 -get_ans()
517 -{
518 - if [ -z "$2" ]
519 - then
520 - ${ECHO} "$1 \c"
521 - else
522 - ${ECHO} "$1 [$2] \c"
523 - fi
524 905
525 - read ANS
526 - if [ -z "$ANS" ]
527 - then
528 - ANS=$2
529 - fi
906 +Man.addFunc get_ans_req '' '[+NAME?get_ans_req - get a non-empty answer from the user.]
907 +[+DESCRIPTION?Read a string from stdin. Does not return until the string is a non-empty string or a \adefault\a value is given. Arguments:]{
908 + [+prompt?instruction/comment/description/question to show.]
909 + [+default?Default value to use if no answer/empty string was read.]
530 910 }
911 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage ANS ; }" '}
912 +[+SEE ALSO?\bget_ans()\b]
913 +\n\n\aprompt\a [\adefault\a]
914 +'
915 +function get_ans_req {
916 + ANS=''
917 + while [[ -z ${ANS} ]]; do
918 + get_ans "$@"
919 + [[ -z ${ANS} ]] && Log.warn 'NULL value not allowed'
920 + done
921 +}
531 922
923 +Man.addFunc is_numeric '' '[+NAME?is_numeric - check whether arg is a numeric string]
924 +[+DESCRIPTION?Check whether the given \astring\a is a numeric string.]
925 +[+RETURN VALUES]{
926 + [+0?If the string is a numeric string.]
927 + [+1?Otherwise.]
928 +}
929 +[+SEE ALSO?\bnot_numeric()\b]
930 +\n\n\astring\a
931 +'
932 +function is_numeric {
933 + (( $# != 1 )) && return 1
934 + [[ $1 =~ ^[0-9]+$ ]] && return 0 || return 1
935 +}
532 936
533 -#
534 -# get_ans_req(): gets an answer (required) from the user, NULL value not allowed.
535 -# $@ instruction/comment/description/question
536 -#
537 -get_ans_req()
538 -{
539 - ANS="" # Set ANS to NULL.
540 - while [ "$ANS" = "" ]
541 - do
542 - get_ans "$@"
543 - [ "$ANS" = "" ] && ${ECHO} "NULL value not allowed!"
544 - done
937 +Man.addFunc not_numeric '' '[+NAME?not_numeric - check whether arg is NOT a numeric string]
938 +[+DESCRIPTION?Check whether the given \astring\a is NOT a numeric string. Useful for if and while statements that want to test for non-numeric data.]
939 +[+RETURN VALUES]{
940 + [+0?If the string is NOT a numeric string.]
941 + [+1?Otherwise.]
545 942 }
943 +[+SEE ALSO?\bis_numeric()\b]
944 +\n\n\astring\a
945 +'
946 +function not_numeric {
947 + is_numeric $1 && return 1 || return 0
948 +}
546 949
547 -
548 -#
549 -# get_number(): Querys and verifies that number entered is numeric.
550 -# Function will repeat prompt user for number value.
551 -# $1 Message text.
552 -# $2 default value.
553 -# $3 Help argument.
554 -#
555 -get_number()
950 +Man.addVar NUM 'Variable used to return the user input as a number.'
951 +integer NUM
952 +Man.addFunc get_number '' '[+NAME?get_number - get a number from the user.]
953 +[+DESCRIPTION?Read a string from stdin until it represents a number. Arguments:]
556 954 {
557 - ANS="" # Set ANS to NULL.
558 - NUM=""
955 + [+prompt?instruction/comment/description/question to show.]
956 + [+default?Default value to use if no answer/empty string was read.]
957 + [+helpTag?Tag of the help message to show, when the string read is h|H|?|help|Help.]
958 +}
959 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage NUM ANS ; }" '}
960 +[+SEE ALSO?\bget_ans()\b, \bis_numeric()\b, \bdisplay_msg()\b]
961 +\n\n\aprompt\a \adefault\a [\ahelpTag\a]
962 +'
963 +function get_number {
964 + ANS=''
559 965
560 - get_ans "$1" "$2"
966 + get_ans "$1" "$2"
561 967
562 - # Verify that value is numeric.
563 - while not_numeric $ANS
564 - do
565 - case "$ANS" in
566 - [Hh] | help | Help | \?) display_msg ${3:-sorry} ;;
567 - * ) ${ECHO} "Invalid value: \"${ANS}\". \c"
568 - ;;
569 - esac
570 - # Get a new value.
571 - get_ans "Enter a numeric value:" "$2"
572 - done
573 - NUM=$ANS
968 + while not_numeric $ANS ; do
969 + case "${ANS}" in
970 + [Hh?] | help | Help) display_msg ${3:-sorry} ;;
971 + * ) Log.warn "Invalid value: '${ANS}'" ;;
972 + esac
973 + get_ans 'Enter a numeric value:' "$2"
974 + done
975 + NUM=${ANS}
574 976 }
575 977
576 978
577 -#
578 -# get_negone_num(): Only allows a -1 or positive integer.
579 -# Used for values where -1 has special meaning.
580 -#
581 -# $1 - Prompt message.
582 -# $2 - Default value (require).
583 -# $3 - Optional help argument.
584 -get_negone_num()
979 +Man.addFunc get_negone_num '' '[+NAME?get_negone_num - get a number >= -1 from the user.]
980 +[+DESCRIPTION?Read a string from stdin until it represents a number >= -1. Arguments:]
585 981 {
586 - while :
587 - do
588 - get_number "$1" "$2" "$3"
589 - if is_negative $ANS
590 - then
591 - if [ "$ANS" = "-1" ]; then
592 - break # -1 is OK, so break.
593 - else # Need to re-enter number.
594 - ${ECHO} "Invalid number: please enter -1 or positive number."
595 - fi
596 - else
597 - break # Positive number
598 - fi
599 - done
982 + [+prompt?instruction/comment/description/question to show.]
983 + [+default?Default value to use if no answer/empty string was read.]
984 + [+helpTag?Tag of the help message to show, when the string read is h|H|?|help|Help.]
600 985 }
986 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage NUM ANS ; }" '}
987 +[+SEE ALSO?\bget_number()\b]
988 +\n\n\aprompt\a \adefault\a [\ahelpTag\a]
989 +'
990 +function get_negone_num {
991 + while : ; do
992 + get_number "$1" "$2" "$3"
993 + (( NUM >= -1 )) && break
994 + Log.warn 'Invalid number! Enter a number >= -1'
995 + done
996 +}
601 997
602 -
603 -#
604 -# get_passwd(): Reads a password from the user and verify with second.
605 -# $@ instruction/comment/description/question
606 -#
607 -get_passwd()
998 +Man.addFunc get_passwd '' '[+NAME?get_passwd - get a password from the user.]
999 +[+DESCRIPTION?Read a password from stdin and verify with second until both match. Password gets not echoed to stdout. Arguments:]
608 1000 {
609 - [ $DEBUG -eq 1 ] && ${ECHO} "In get_passwd()"
1001 + [+prompt?instruction/comment/description/question to show.]
1002 + [+default?Default value to use if no answer/empty string was read.]
1003 +}
1004 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage ANS ; }" '}
1005 +[+SEE ALSO?\bget_ans()\b]
1006 +\n\n\aprompt\a [\adefault\a]
1007 +'
1008 +function get_passwd {
1009 + typeset _PASS1='' _PASS2=''
610 1010
611 - # Temporary PASSWD variables
612 - _PASS1=""
613 - _PASS2=""
1011 + ${STTY} -echo # Turn echo OFF
614 1012
615 - /usr/bin/stty -echo # Turn echo OFF
1013 + # continue until passwd and re-entered passwd match
1014 + while : ; do
1015 + ANS=''
1016 + # Don't allow NULL for first try.
1017 + while [[ -z ${ANS} ]]; do
1018 + get_ans "$@"
1019 + [[ -z ${ANS} ]] && \
1020 + print -u2 && Log.warn 'Empty password not allowed'
1021 + done
1022 + _PASS1="${ANS}" # Store first try.
616 1023
617 - # Endless loop that continues until passwd and re-entered passwd
618 - # match.
619 - while :
620 - do
621 - ANS="" # Set ANS to NULL.
1024 + print
1025 + get_ans 'Re-enter password:'
1026 + _PASS2="${ANS}"
622 1027
623 - # Don't allow NULL for first try.
624 - while [ "$ANS" = "" ]
625 - do
626 - get_ans "$@"
627 - [ "$ANS" = "" ] && ${ECHO} "" && ${ECHO} "NULL passwd not allowed!"
1028 + [[ ${_PASS1} == ${_PASS2} ]] && break
1029 + print -u2 && Log.warn "passwords don't match - try again"
628 1030 done
629 - _PASS1=$ANS # Store first try.
630 1031
631 - # Get second try.
632 - ${ECHO} ""
633 - get_ans "Re-enter passwd:"
634 - _PASS2=$ANS
1032 + ${STTY} echo # Turn echo ON
635 1033
636 - # Test if passwords are identical.
637 - if [ "$_PASS1" = "$_PASS2" ]; then
638 - break
639 - fi
640 -
641 - # Move cursor down to next line and print ERROR message.
642 - ${ECHO} ""
643 - ${ECHO} "ERROR: passwords don't match; try again."
644 - done
645 -
646 - /usr/bin/stty echo # Turn echo ON
647 -
648 - ${ECHO} ""
1034 + print
649 1035 }
650 1036
651 -
652 -#
653 -# get_passwd_nochk(): Reads a password from the user w/o check.
654 -# $@ instruction/comment/description/question
655 -#
656 -get_passwd_nochk()
1037 +Man.addFunc get_passwd_nochk '' '[+NAME?get_passwd_nochk - get a password from the user w/o check.]
1038 +[+DESCRIPTION?Read a password from stdin. Actually the same as \bget_ans()\b but echoing characters read to stdout is switched off. Arguments:]
657 1039 {
658 - [ $DEBUG -eq 1 ] && ${ECHO} "In get_passwd_nochk()"
659 -
660 - /usr/bin/stty -echo # Turn echo OFF
661 -
662 - get_ans "$@"
663 -
664 - /usr/bin/stty echo # Turn echo ON
665 -
666 - ${ECHO} ""
1040 + [+prompt?instruction/comment/description/question to show.]
1041 + [+default?Default value to use if no answer/empty string was read.]
667 1042 }
1043 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage ANS ; }" '}
1044 +[+SEE ALSO?\bget_ans()\b]
1045 +\n\n\aprompt\a [\adefault\a]
1046 +'
1047 +function get_passwd_nochk {
1048 + ${STTY} -echo # Turn echo OFF
1049 + get_ans "$@"
1050 + ${STTY} echo # Turn echo ON
1051 + print
1052 +}
668 1053
669 -
670 -#
671 -# get_menu_choice(): Get a menu choice from user. Continue prompting
672 -# till the choice is in required range.
673 -# $1 .. Message text.
674 -# $2 .. min value
675 -# $3 .. max value
676 -# $4 .. OPTIONAL: default value
677 -#
678 -# Return value:
679 -# MN_CH will contain the value selected.
680 -#
681 -get_menu_choice()
1054 +Man.addFunc get_menu_choice '' '[+NAME?get_menu_choice - get a valid menu choice number.]
1055 +[+DESCRIPTION?Get a menu choice from user. Continue prompting until the choice is in required range. Arguments:]
682 1056 {
683 - # Check for req parameter.
684 - if [ $# -lt 3 ]; then
685 - ${ECHO} "get_menu_choice(): Did not get required parameters."
686 - return 1
687 - fi
1057 + [+prompt?Message text.]
1058 + [+min?Min value.]
1059 + [+max?Max value.]
1060 + [+default?Default value to use if no answer/empty string was read.]
1061 + [+helpTag?If given, "h" is allowed as well and the help message for this tag gets shown, when it got typed and before the prompt is shown the first time. The prompt should contain a hint in this case.]
1062 + [+menuTag?If given the menu choices for the given menu gest displayed at start and after each help text.]
1063 +}
1064 +[+RETURN VALUES]{
1065 + [+-1?on error (invalid parameters).]
1066 + [+>= \amin\a?the selected value.]
1067 +}
1068 +[+SEE ALSO?\bis_numeric()\b, \bget_ans()\b, \bdisplay_msg()\b.]
1069 +\n\n\aprompt\a \amin\a \amax\a [\adefault\a [\ahelpTag\a]]
1070 +'
1071 +function get_menu_choice {
1072 + if (( $# < 3 )); then
1073 + Log.warn "${.sh.fun}(): Did not get required parameters"
1074 + return -1
1075 + fi
688 1076
689 - while :
690 - do
691 - get_ans "$1" "$4"
692 - MN_CH=$ANS
693 - is_negative $MN_CH
694 - if [ $? -eq 1 ]; then
695 - if [ $MN_CH -ge $2 ]; then
696 - if [ $MN_CH -le $3 ]; then
697 - return
1077 + [[ -n $6 ]] && display_msg "$6"
1078 + while : ; do
1079 + get_ans "$1" "$4"
1080 + if is_numeric ${ANS} && NUM=${ANS} && (( NUM >= $2 )) && (( NUM <= $3 ))
1081 + then
1082 + return ${NUM}
698 1083 fi
699 - fi
700 - fi
701 - ${ECHO} "Invalid choice: $MN_CH"
702 - done
1084 + if [[ -n $5 && ${ANS} == 'h' ]]; then
1085 + display_msg "$5"
1086 + [[ -n $6 ]] && display_msg "$6"
1087 + continue
1088 + fi
1089 + Log.warn "Invalid choice! Enter a number in the range $2 .. $3"
1090 + done
1091 + return -1
703 1092 }
704 1093
705 -
706 -#
707 -# get_confirm(): Get confirmation from the user. (Y/Yes or N/No)
708 -# $1 - Message
709 -# $2 - default value.
710 -#
711 -get_confirm()
1094 +Man.addFunc get_confirm '' '[+NAME?get_confirm - Get confirmation from the user.]
1095 +[+DESCRIPTION?Read a string from stdin until it matches Y|y|Yes|yes|YES|N|n|No|no|NO or an empty string. Arguments:]
712 1096 {
713 - _ANSWER=
1097 + [+prompt?instruction/comment/description/question to show.]
1098 + [+default?Default value to use if no answer/empty string was read.]
1099 + [+helpTag?Tag of the help message to show, when the string read is h|H|?|help|Help.]
1100 +}
1101 +[+RETURN VALUES]{
1102 + [+0?for NO]
1103 + [+1?for YES]
1104 +}
1105 +[+SEE ALSO?\bdisplay_msg()\b]
1106 +\n\n\aprompt\a \adefault\a [\ahelpTag\a]
1107 +'
1108 +function get_confirm {
1109 + typeset _ANSWER=''
714 1110
715 - while :
716 - do
717 - # Display Internal ERROR if $2 not set.
718 - if [ -z "$2" ]
719 - then
720 - ${ECHO} "INTERNAL ERROR: get_confirm requires 2 args, 3rd is optional."
721 - exit 2
1111 + if [[ -z $2 ]]; then
1112 + Log.fatal "INTERNAL ERROR: ${.sh.fun} requires 2 args, 3rd is optional"
1113 + exit 2
722 1114 fi
723 1115
724 - # Display prompt.
725 - ${ECHO} "$1 [$2] \c"
1116 + while : ; do
1117 + read _ANSWER?"$1 [$2] "
1118 + [[ -z ${_ANSWER} ]] && _ANSWER="$2"
726 1119
727 - # Get the ANSWER.
728 - read _ANSWER
729 - if [ "$_ANSWER" = "" ] && [ -n "$2" ] ; then
730 - _ANSWER=$2
731 - fi
732 - case "$_ANSWER" in
733 - [Yy] | yes | Yes | YES) return 1 ;;
734 - [Nn] | no | No | NO) return 0 ;;
735 - [Hh] | help | Help | \?) display_msg ${3:-sorry};;
736 - * ) ${ECHO} "Please enter y or n." ;;
737 - esac
738 - done
1120 + case "${_ANSWER}" in
1121 + [Yy] | yes | Yes | YES) return 1 ;;
1122 + [Nn] | no | No | NO) return 0 ;;
1123 + [Hh?] | help | Help) display_msg ${3:-sorry} ;;
1124 + * ) Log.warn 'Please enter y or n' ;;
1125 + esac
1126 + done
739 1127 }
740 1128
741 -
742 -#
743 -# get_confirm_nodef(): Get confirmation from the user. (Y/Yes or N/No)
744 -# No default value supported.
745 -#
746 -get_confirm_nodef()
1129 +Man.addFunc get_confirm_nodef '' '[+NAME?get_confirm_nodef - Get confirmation from the user.]
1130 +[+DESCRIPTION?Read a string from stdin until it matches Y|y|Yes|yes|YES|N|n|No|no|NO. No default value and help tag supported. Arguments:]
747 1131 {
748 - _ANSWER=
1132 + [+prompt?instruction/comment/description/question to show.]
1133 +}
1134 +[+RETURN VALUES]{
1135 + [+0?for NO]
1136 + [+1?for YES]
1137 +}
1138 +\n\n[\aprompt\a]...
1139 +'
1140 +function get_confirm_nodef {
1141 + typeset _ANSWER=''
749 1142
750 - while :
751 - do
752 - ${ECHO} "$@ \c"
753 - read _ANSWER
754 - case "$_ANSWER" in
755 - [Yy] | yes | Yes | YES) return 1 ;;
756 - [Nn] | no | No | NO) return 0 ;;
757 - * ) ${ECHO} "Please enter y or n." ;;
758 - esac
759 - done
1143 + while : ; do
1144 + read _ANSWER?"$@ "
1145 + case "${_ANSWER}" in
1146 + [Yy] | yes | Yes | YES) return 1 ;;
1147 + [Nn] | no | No | NO) return 0 ;;
1148 + * ) Log.warn 'Please enter y or n' ;;
1149 + esac
1150 + done
760 1151 }
1152 +############################################################################
1153 +# End of basic [menu] stuff
1154 +############################################################################
761 1155
762 1156
763 -#
764 -# is_numeric(): Tells is a string is numeric.
765 -# 0 = Numeric
766 -# 1 = NOT Numeric
767 -#
768 -is_numeric()
769 -{
770 - # Check for parameter.
771 - if [ $# -ne 1 ]; then
772 - return 1
773 - fi
1157 +######################################################################
1158 +# FUNCTIONS FOR prompt_config_info() START HERE.
1159 +######################################################################
1160 +Man.addFunc get_ids_server '' '[+NAME?get_ids_server - Prompt for DS server name.]
1161 +[+DESCRIPTION?Ask the user for the DS hostname, store it into \bSTR[DS_HOST]]\b and adjusts \bCON_ARGS\b.]
1162 +[+ENVIRONMENT VARIABLES]{'"${ Man.varUsage CON_ARGS ; }"'}
1163 +[+SEE ALSO?\bget_ans()\b, \bget_ids_port()\b, \bping\b(1M).]
1164 +'
1165 +function get_ids_server {
1166 + typeset SRV="${STR[DS_HOST]}"
1167 + typeset OS=${ uname -s ; }
774 1168
775 - # Determine if numeric.
776 - expr "$1" + 1 > /dev/null 2>&1
777 - if [ $? -ge 2 ]; then
778 - return 1
779 - fi
1169 + while : ; do
1170 + get_ans "Enter the Directory Server's hostname to setup:" \
1171 + "${STR[DS_HOST]}"
1172 + SRV="${ANS}"
780 1173
781 - # Made it here, it's Numeric.
782 - return 0
1174 + # Ping server to see if alive. If reachable break out of loop
1175 + if [[ ${OS} == 'SunOS' ]]; then
1176 + ${PING} "${SRV}" 3 >/dev/null 2>&1 && break
1177 + else
1178 + # assume Linux
1179 + ${PING} -W 3 "${SRV}" >/dev/null 2>&1 && break
1180 + fi
1181 + Log.warn "Server '${SRV}' is invalid or unreachable"
1182 + done
1183 + STR[DS_HOST]="${SRV}"
1184 +
1185 + # Set CON_ARGS since values might have changed
1186 + CON_ARGS="-h ${SRV} -p ${INT[DS_PORT]}"
783 1187 }
784 1188
1189 +Man.addFunc get_ids_port '' '[+NAME?get_ids_port - Prompt for DS port number.]
1190 +[+DESCRIPTION?Ask the user for the DS port number and host, store it into \bINT[DS_PORT]]\b, \bSTR[DS_HOST]]\b and adjust \bCON_ARGS\b.]
1191 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage CON_ARGS ; }" '}
1192 +[+SEE ALSO?\bget_number()\b, \bget_ids_server()\b, \bldapsearch\b(1).]
1193 +\n\n\aarg\a'
1194 +function get_ids_port {
1195 + typeset ASK='Enter the port number for the directory server (h=help):'
1196 + typeset HELP='port_help' KEY='DS_PORT'
785 1197
786 -#
787 -# not_numeric(): Reverses the return values of is_numeric. Useful
788 -# for if and while statements that want to test for
789 -# non-numeric data.
790 -# 0 = NOT Numeric
791 -# 1 = Numeric
792 -#
793 -not_numeric()
794 -{
795 - is_numeric $1
796 - if [ $? -eq 0 ]; then
797 - return 1
798 - else
799 - return 0
800 - fi
1198 + integer PORT
1199 + while : ; do
1200 + # Enter port number
1201 + get_number "${ASK}" ${INT[${KEY}]} "${HELP}"
1202 + PORT=${ANS}
1203 + # Do a simple search to check hostname and LDAP port number
1204 + if [[ -z $1 ]]; then
1205 + if ${LDAPSEARCH} -h ${STR[DS_HOST]} -p ${PORT} -b '' \
1206 + -s base 'objectclass=*' > /dev/null 2>&1
1207 + then
1208 + break
1209 + fi
1210 + Log.warn "Invalid host or port '${STR[DS_HOST]}:${PORT}'"
1211 + get_ids_server
1212 + else
1213 + break
1214 + fi
1215 + done
1216 + INT[${KEY}]=${PORT}
1217 + [[ -n $1 ]] && return
1218 +
1219 + # Set CON_ARGS since values might have changed
1220 + CON_ARGS="-h ${STR[DS_HOST]} -p ${PORT}"
801 1221 }
802 1222
1223 +Man.addFunc chk_ids_version '' '[+NAME?chk_ids_version - Read the DS version info.]
1224 +[+DESCRIPTION?Query the DS for version info and store it into \bTMP[DS_INFO]]\b as "ProductName MajorVersionNum MinorVersionNum". If the DS is OpenDS or OpenDJ \bTMPF[IS_OPENDJ]]\b gets set to 1, 0 otherwise. If the DS seems to be unsupported by this script, an appropriate message gets stored into \bTMP[WARN]]\b.]
1225 +[+RETURN VALUES]{
1226 + [+0?on success.]
1227 + [+>= 66?on fatal error (got no info).]
1228 +}
1229 +[+SEE ALSO?\bldapsearch\b(1).]
1230 +'
1231 +function chk_ids_version {
1232 + typeset PROD='' X LINE
1233 + typeset -a SPLIT=( )
1234 + integer MAJOR=0 MINOR=0
1235 + ${LDAPSEARCH} ${CON_ARGS} -b cn=monitor -s base 'objectclass=*' \
1236 + 2>/dev/null | \
1237 + while read LINE ; do
1238 + if [[ ${LINE:0:14} == 'vendorVersion=' ]]; then
1239 + # OpenD*
1240 + X=${LINE:14}
1241 + X=${X//Directory Server } # usually <= 2.3.x
1242 + PROD=${X%% *}
1243 + SPLIT=( ${.sh.match//./ } )
1244 + MAJOR=${SPLIT[0]}
1245 + MINOR=${SPLIT[1]}
1246 + break
1247 + elif [[ ${LINE:0:8} == 'version=' ]]; then
1248 + # *DSEE
1249 + X=${LINE:8}
1250 + PROD=${X%%/*}
1251 + X=${.sh.match#/}
1252 + SPLIT=( ${X//./ } )
1253 + MAJOR=${SPLIT[0]}
1254 + MINOR=${SPLIT[1]}
1255 + break
1256 + fi
1257 + done
1258 + if [[ -z ${PROD} ]] || (( MAJOR == 0 )); then
1259 + Log.fatal 'Can not determine the version number of the DS'
1260 + return 66
1261 + fi
803 1262
804 -#
805 -# is_negative(): Tells is a Numeric value is less than zero.
806 -# 0 = Negative Numeric
807 -# 1 = Positive Numeric
808 -# 2 = NOT Numeric
809 -#
810 -is_negative()
811 -{
812 - # Check for parameter.
813 - if [ $# -ne 1 ]; then
814 - return 1
815 - fi
1263 + TMP[DS_INFO]="${PROD} ${MAJOR} ${MINOR}"
816 1264
817 - # Determine if numeric. Can't use expr because -0 is
818 - # considered positive??
819 - if is_numeric $1; then
820 - case "$1" in
821 - -*) return 0 ;; # Negative Numeric
822 - *) return 1 ;; # Positive Numeric
823 - esac
824 - else
825 - return 2
1265 + # for easier maintainance we don't put it into a single expr
1266 + X=''
1267 + if [[ ${PROD} == 'OpenDS' || ${PROD} == 'OpenDJ' ]]; then
1268 + TMPF[IS_OPENDJ]=1
1269 + (( MAJOR < 2 )) && X='1'
1270 + elif (( MAJOR < 5 || (7 < MAJOR && MAJOR < 11) )); then
1271 + # not a supported DSEE version
1272 + TMPF[IS_OPENDJ]=0
1273 + X='1'
826 1274 fi
1275 + if [[ -n ${X} ]]; then
1276 + TMP[WARN]="$PROG only works with DSEE version 5.x, 6.x, 7.x, "
1277 + TMP[WARN]+='ODSEE 11g and OpenDS/OpenDJ 2.x'
1278 + Log.warn "${TMP[WARN]}"
1279 + fi
1280 + Log.printMarker
1281 + Log.info "Detected DS: ${PROD} ${MAJOR}.${MINOR}"
1282 + Log.printMarker
1283 + return 0
827 1284 }
828 1285
829 -
830 -#
831 -# check_domainname(): check validity of a domain name. Currently we check
832 -# that it has at least two components.
833 -# $1 the domain name to be checked
834 -#
835 -check_domainname()
836 -{
837 - if [ ! -z "$1" ]
838 - then
839 - t=`expr "$1" : '[^.]\{1,\}[.][^.]\{1,\}'`
840 - if [ "$t" = 0 ]
841 - then
842 - return 1
843 - fi
844 - fi
845 - return 0
1286 +Man.addFunc get_dirmgr_dn '' '[+NAME?get_dirmgr_dn - get the directory manger DN.]
1287 +[+DESCRIPTION?Ask the user for the directory manger DN and store it into \bSTR[LDAP_ROOTDN]]\b and adjust \bAUTH_ARGS\b.]
1288 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage AUTH_ARGS ; }" '}
1289 +[+SEE ALSO?\bget_ans()\b.]
1290 +'
1291 +function get_dirmgr_dn {
1292 + get_ans 'Enter the directory manager DN:' "${STR[LDAP_ROOTDN]}"
1293 + STR[LDAP_ROOTDN]="${ANS}"
1294 + AUTH_ARGS=( '-D' "${STR[LDAP_ROOTDN]}" '-j' "${TMP[LDAP_ROOTPWF]}" )
846 1295 }
847 1296
1297 +Man.addFunc get_dirmgr_pw '' '[+NAME?get_dirmgr_pw - get the Root DN password.]
1298 +[+DESCRIPTION?Ask the user for the Root DN (\bSTR[LDAP_ROOTDN]]\b), store it into \bSTR[LDAP_ROOTPWD]]\b as well as a temp file for later use. Finally adjust \bAUTH_ARGS\b and check, whether the changes work.]
1299 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage AUTH_ARGS ; }" '}
1300 +[+SEE ALSO?\bget_passwd_nochk()\b, \bsave_password()\b, \bldapsearch\b(1).]
1301 +'
1302 +function get_dirmgr_pw {
1303 + typeset RES
848 1304
849 -#
850 -# check_baseDN(): check validity of the baseDN name.
851 -# $1 the baseDN name to be checked
852 -#
853 -# NOTE: The check_baseDN function does not catch all invalid DN's.
854 -# Its purpose is to reduce the number of invalid DN's to
855 -# get past the input routine. The invalid DN's will be
856 -# caught by the LDAP server when they are attempted to be
857 -# created.
858 -#
859 -check_baseDN()
860 -{
861 - ck_DN=$1
862 - ${ECHO} " Checking LDAP Base DN ..."
863 - if [ ! -z "$ck_DN" ]; then
864 - [ $DEBUG -eq 1 ] && ${ECHO} "Checking baseDN: $ck_DN"
865 - # Check for = (assignment operator)
866 - ${ECHO} "$ck_DN" | ${GREP} "=" > /dev/null 2>&1
867 - if [ $? -ne 0 ]; then
868 - [ $DEBUG -eq 1 ] && ${ECHO} "check_baseDN: No '=' in baseDN."
869 - return 1
870 - fi
871 -
872 - # Check all keys.
873 - while :
874 - do
875 - # Get first key.
876 - dkey=`${ECHO} $ck_DN | cut -d'=' -f1`
1305 + while : ; do
1306 + get_passwd_nochk "Enter passwd for ${STR[LDAP_ROOTDN]} :"
1307 + STR[LDAP_ROOTPWD]="${ANS}" # stored for create_config_file(), only
1308 + save_password
1309 + AUTH_ARGS=( '-D' "${STR[LDAP_ROOTDN]}" '-j' "${TMP[LDAP_ROOTPWF]}" )
877 1310
878 - # Check that the key string is valid
879 - check_attrName $dkey
880 - if [ $? -ne 0 ]; then
881 - [ $DEBUG -eq 1 ] && ${ECHO} "check_baseDN: invalid key=${dkey}"
882 - return 1
883 - fi
1311 + # Verify that ROOTDN and ROOTPWD are valid
1312 + RES=${ ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
1313 + -b '' -s base 'objectclass=*' supportedLDAPVersion 2>&1 ; }
1314 + (( $? == 0 )) && break # Both are valid.
884 1315
885 - [ $DEBUG -eq 1 ] && ${ECHO} "check_baseDN: valid key=${dkey}"
886 -
887 - # Remove first key from DN
888 - ck_DN=`${ECHO} $ck_DN | cut -s -d',' -f2-`
889 -
890 - # Break loop if nothing left.
891 - if [ "$ck_DN" = "" ]; then
892 - break
893 - fi
894 - done
895 - fi
896 - return 0
1316 + if [[ ${RES} =~ (credential|no password) ]]; then
1317 + Log.warn 'Password for Root DN is invalid'
1318 + else
1319 + Log.warn "Root DN '${STR[LDAP_ROOTDN]}' is invalid"
1320 + get_dirmgr_dn
1321 + fi
1322 + done
897 1323 }
898 1324
899 -
900 -#
901 -# domain_2_dc(): Convert a domain name into dc string.
902 -# $1 .. Domain name.
903 -#
904 -domain_2_dc()
905 -{
906 - _DOM=$1 # Domain parameter.
907 - _DOM_2_DC="" # Return value from function.
908 - _FIRST=1 # Flag for first time.
909 -
910 - export _DOM_2_DC # Make visible for others.
911 -
912 - # Convert "."'s to spaces for "for" loop.
913 - domtmp="`${ECHO} ${_DOM} | tr '.' ' '`"
914 - for i in $domtmp; do
915 - if [ $_FIRST -eq 1 ]; then
916 - _DOM_2_DC="dc=${i}"
917 - _FIRST=0
918 - else
919 - _DOM_2_DC="${_DOM_2_DC},dc=${i}"
920 - fi
1325 +Man.addFunc get_domain '' '[+NAME?get_domain - Ask user for domain to be served.]
1326 +[+DESCRIPTION?Ask the user for the Domain that will be served by the LDAP server and store it into \bSTR[LDAP_DOMAIN]]\b.]
1327 +[+SEE ALSO?\bget_ans()\b.]
1328 +'
1329 +function get_domain {
1330 + while : ; do
1331 + get_ans 'Enter the domainname to be served (h=help):' \
1332 + "${STR[LDAP_DOMAIN]}"
1333 + case "${ANS}" in
1334 + [Hh?] | help | Help) display_msg 'domain_help' ; continue ;;
1335 + esac
1336 + # check, whether it has at least 2 dot separated components
1337 + [[ ${ANS} =~ [^.]+\.[^.]+ ]] && break
1338 + Log.warn "Invalid domainname '${ANS}'"
921 1339 done
1340 + STR[LDAP_DOMAIN]="${ANS}"
922 1341 }
923 1342
1343 +Man.addFunc getDSobjectclasses '' '[+NAME?getDSobjectclasses - get all DS schema objectclasses.]
1344 +[+DESCRIPTION?Fetch all objectclasses definitions of the DS via \bcn=schema\b and cache them into \bOID2ODEF\b. Once successfully fetched, this function does nothing but return 0.]
1345 +[+RETURN VALUES]{
1346 + [+0?on success.]
1347 + [+>0?failed to retrieve attribute definitions.]
1348 +}
1349 +'
1350 +function getDSobjectclasses {
1351 + (( ${#OID2ODEF[@]} )) && return 0
924 1352
925 -#
926 -# is_root_user(): Check to see if logged in as root user.
927 -#
928 -is_root_user()
929 -{
930 - case `id` in
931 - uid=0\(root\)*) return 0 ;;
932 - * ) return 1 ;;
933 - esac
1353 + typeset AT OID NAME TAIL
1354 + set -o pipefail
1355 + ${LDAPSEARCH} ${CON_ARGS} -b cn=schema -s base 'objectclass=*' \
1356 + objectclasses 2>/dev/null | \
1357 + while read AT OID NAME TAIL ; do
1358 + [[ ${AT} != 'objectclasses=(' ]] && continue
1359 + TAIL=${TAIL%%+( )$')'};
1360 + OID2ODEF["${OID}"]="${TAIL}"
1361 + : # always return 0
1362 + done
934 1363 }
935 1364
1365 +Man.addFunc getDSattributes '' '[+NAME?getDSattributes - get all DS schema attributes.]
1366 +[+DESCRIPTION?Fetch all attribute definitions of the DS via \bcn=schema\b and cache them into \bOID2ADEF\b. Also populate the hash map \bANAME2OID\b for all the attributes definied. Once successfully fetched, this function does nothing but return 0.]
1367 +[+RETURN VALUES]{
1368 + [+0?on success.]
1369 + [+>0?failed to retrieve attribute definitions.]
1370 +}
1371 +'
1372 +function getDSattributes {
1373 + (( ${#ANAME2OID[@]} )) && return 0
936 1374
937 -#
938 -# parse_arg(): Parses the command line arguments and sets the
939 -# appropriate variables.
940 -#
941 -parse_arg()
942 -{
943 - while getopts "dvhi:o:" ARG
944 - do
945 - case $ARG in
946 - d) DEBUG=1;;
947 - v) VERB="";;
948 - i) INPUT_FILE=$OPTARG;;
949 - o) OUTPUT_FILE=$OPTARG;;
950 - \?) display_msg usage
951 - exit 1;;
952 - *) ${ECHO} "**ERROR: Supported option missing handler!"
953 - display_msg usage
954 - exit 1;;
955 - esac
956 - done
957 - return `expr $OPTIND - 1`
1375 + typeset AT OID NAME TAIL
1376 + typeset -l ALIAS
1377 + set -o pipefail
1378 + ${LDAPSEARCH} ${CON_ARGS} -b cn=schema -s base 'objectclass=*' \
1379 + attributeTypes 2>/dev/null | \
1380 + while read AT OID NAME TAIL ; do
1381 + [[ ${AT} != 'attributeTypes=(' ]] && continue
1382 + TAIL=${TAIL%%+( )$')'};
1383 + OID2ADEF["${OID}"]="${TAIL}"
1384 + # 'name'
1385 + if [[ ${TAIL:0:1} == "'" ]]; then
1386 + NAME=${TAIL:1}
1387 + ALIAS=${NAME%%"'"*}
1388 + ANAME2OID["${ALIAS}"]="${OID}"
1389 + continue
1390 + fi
1391 + # ( 'name' 'name 1' ... )
1392 + NAME=${TAIL%%$')'*}
1393 + NAME=${NAME##$'('*([[:space:]])}
1394 + while [[ ${NAME} == ~(E)"'"([^"'"]+)"'" ]]; do
1395 + ALIAS=${.sh.match[1]}
1396 + ANAME2OID["${ALIAS}"]="${OID}"
1397 + NAME=${NAME:${#ALIAS}+2}
1398 + NAME=${NAME#*([[:space:]])}
1399 + done
1400 + : # always return 0
1401 + done
958 1402 }
959 1403
1404 +Man.addFunc check_attrName '' '[+NAME?check_attrName - validate an attribute name.]
1405 +[+DESCRIPTION?Check that \akey\a is a valid attribute name.]
1406 +[+RETURN VALUES]{
1407 + [0?key is a valid name.]
1408 + [1?key is a invalid name.]
1409 + [66?failed to fetch attribute definitions from server.]
1410 +}
1411 +[+SEE ALSO?\bldapsearch\b(1).]
1412 +\n\n\akey\a
1413 +'
1414 +function check_attrName {
1415 + typeset KEY=$1
960 1416
961 -#
962 -# init(): initializes variables and options
963 -#
964 -init()
965 -{
966 - # General variables.
967 - PROG=`basename $0` # Program name
968 - PID=$$ # Program ID
969 - VERB='> /dev/null 2>&1' # NULL or "> /dev/null"
970 - ECHO="/bin/echo" # print message on screen
971 - EVAL="eval" # eval or echo
972 - EGREP="/usr/bin/egrep"
973 - GREP="/usr/bin/grep"
974 - DEBUG=0 # Set Debug OFF
975 - BACKUP=no_ldap # backup suffix
976 - HOST="" # NULL or <hostname>
977 - NAWK="/usr/bin/nawk"
978 - RM="/usr/bin/rm"
979 - WC="/usr/bin/wc"
980 - CAT="/usr/bin/cat"
981 - SED="/usr/bin/sed"
982 - MV="/usr/bin/mv"
1417 + if ! getDSattributes ; then
1418 + Log.fatal 'Unable to fetch attribute definitions from server'
1419 + return 66
1420 + fi
1421 + [[ -z ${KEY} ]] && return 1
1422 + if [[ ${KEY} =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
1423 + # OID value
1424 + [[ -n ${OID2ADEF[${KEY}]} ]] && return 0
1425 + else
1426 + # symbol. name
1427 + KEY=${ANAME2OID[${KEY}]}
1428 + # if have a mapping, than we also have a definition for it - no need
1429 + # to double check
1430 + [[ -n ${KEY} ]] && return 0
1431 + fi
1432 + return 1
1433 +}
983 1434
984 - DOM="" # Set to NULL
985 - # If DNS domain (resolv.conf) exists use that, otherwise use domainname.
986 - if [ -f /etc/resolv.conf ]; then
987 - DOM=`/usr/xpg4/bin/grep -i -E '^domain|^search' /etc/resolv.conf \
988 - | awk '{ print $2 }' | tail -1`
989 - fi
1435 +Man.addFunc check_baseDN '' '[+NAME?check_baseDN - check validity of the baseDN name.]
1436 +[+DESCRIPTION?Check that \abaseDN\a is a valid base DN.]
1437 +[+RETURN VALUES]{
1438 + [+0?baseDN is a valid.]
1439 + [+>= 1?baseDN is a invalid.]
1440 +}
1441 +[+SEE ALSO?\bcheck_attrName()\b.]
1442 +[+NOTES?This function does not catch all invalid DNs. Its purpose is to reduce the number of invalid DNs to get past the input routine. The invalid DNs will be caught by the LDAP server when they are attempted to be created.]
1443 +\n\n\abaseDN\a
1444 +'
1445 +function check_baseDN {
1446 + # NOTE: we preserve spaces! And try to report all errors instead of just one
1447 + Log.info 'Checking LDAP Base DN ...'
1448 + [[ -z $1 ]] && return 0
990 1449
991 - # If for any reason the DOM did not get set (error'd resolv.conf) set
992 - # DOM to the domainname command's output.
993 - if [ "$DOM" = "" ]; then
994 - DOM=`domainname` # domain from domainname command.
995 - fi
1450 + # NOTE: when fancy debug via trap is enabled, splitting via IFS does not
1451 + # work: IFS=',' PAIRS=( $1 ) - so we do it manually
996 1452
997 - STEP=1
998 - INTERACTIVE=1 # 0 = on, 1 = off (For input file mode)
999 - DEL_OLD_PROFILE=0 # 0 (default), 1 = delete old profile.
1453 + typeset PAIR KEY VAL TAIL="${1},"
1454 + typeset -A UNIQ_KEYS=( ) # avoid repeated lookup of the same attrName
1455 + integer ERR=0
1456 + while [[ -n ${TAIL} ]]; do
1457 + TAIL=${TAIL#*,}
1458 + PAIR=${.sh.match%,}
1459 + VAL=${PAIR#*=}
1460 + KEY=${.sh.match%=}
1461 + if [[ -z ${KEY} || -z ${VAL} ]]; then
1462 + Log.warn "Invalid key=value pair '${PAIR}'"
1463 + (( ERR++ ))
1464 + continue
1465 + fi
1466 + UNIQ_KEYS[${KEY}]=1
1467 + done
1000 1468
1001 - # idsconfig specific variables.
1002 - INPUT_FILE=""
1003 - OUTPUT_FILE=""
1004 - LDAP_ENABLE_SHADOW_UPDATE="FALSE"
1005 - NEED_PROXY=0 # 0 = No Proxy, 1 = Create Proxy.
1006 - NEED_ADMIN=0 # 0 = No Admin, 1 = Create Admin.
1007 - NEED_HOSTACL=0 # 0 = No Host ACL, 1 = Create Host ACL.
1008 - EXISTING_PROFILE=0
1009 - LDAP_PROXYAGENT=""
1010 - LDAP_ADMINDN=""
1011 - LDAP_SUFFIX=""
1012 - LDAP_DOMAIN=$DOM # domainname on Server (default value)
1013 - GEN_CMD=""
1014 - PROXY_ACI_NAME="LDAP_Naming_Services_proxy_password_read"
1469 + for KEY in "${!UNIQ_KEYS[@]}" ; do
1470 + if ! check_attrName "${KEY}" ; then
1471 + Log.warn "Unknown attribute name '${KEY}'"
1472 + fi
1473 + done
1474 + return ${ERR}
1475 +}
1015 1476
1016 - # LDAP COMMANDS
1017 - LDAPSEARCH="/bin/ldapsearch -r"
1018 - LDAPMODIFY=/bin/ldapmodify
1019 - LDAPADD=/bin/ldapadd
1020 - LDAPDELETE=/bin/ldapdelete
1021 - LDAP_GEN_PROFILE=/usr/sbin/ldap_gen_profile
1477 +Man.addFunc discover_serv_suffix '' '[+NAME?discover_serv_suffix - query the DS to find suffixes available.]
1478 +[+DESCRIPTION?Query the DS to find suffixes available. All suffixes found are stored into the variable \avname\a which must be an indexed array.]
1479 +[+RETURN VALUES]{
1480 + [+0?at least one suffix was found.]
1481 + [+1?no suffix found.]
1482 +}
1483 +[+SEE ALSO?\bldapsearch\b(1).]
1484 +\n\n\avname\a
1485 +'
1486 +function discover_serv_suffix {
1487 + typeset LINE
1488 + integer NUM_TOP=0
1489 + typeset -n DST=$1
1490 + DST=( ); unset DST[0]
1022 1491
1023 - # iDS specific information
1024 - IDS_SERVER=""
1025 - IDS_PORT=389
1026 - NEED_TIME=0
1027 - NEED_SIZE=0
1028 - NEED_SRVAUTH_PAM=0
1029 - NEED_SRVAUTH_KEY=0
1030 - NEED_SRVAUTH_CMD=0
1031 - IDS_TIMELIMIT=""
1032 - IDS_SIZELIMIT=""
1492 + # Search the server for the TOP of the TREE. Usually none for virgin DS
1493 + ${LDAPSEARCH} ${CON_ARGS} -b '' -s base 'objectclass=*' namingContexts \
1494 + 2>/dev/null | \
1495 + while read LINE ; do
1496 + if [[ -n ${LINE} && ${LINE} != ~(Ei)NetscapeRoot ]]; then
1497 + (( NUM_TOP++ ))
1498 + DST+=( "${LINE#*=}\n" ) # strip off '^namingContexts='
1499 + fi
1500 + done
1033 1501
1034 - # LDAP PROFILE related defaults
1035 - LDAP_ROOTDN="cn=Directory Manager" # Provide common default.
1036 - LDAP_ROOTPWD="" # NULL passwd as default (i.e. invalid)
1037 - LDAP_PROFILE_NAME="default"
1038 - LDAP_BASEDN=""
1039 - LDAP_SERVER_LIST=""
1040 - LDAP_AUTHMETHOD=""
1041 - LDAP_FOLLOWREF="FALSE"
1042 - NEED_CRYPT=""
1043 - LDAP_SEARCH_SCOPE="one"
1044 - LDAP_SRV_AUTHMETHOD_PAM=""
1045 - LDAP_SRV_AUTHMETHOD_KEY=""
1046 - LDAP_SRV_AUTHMETHOD_CMD=""
1047 - LDAP_SEARCH_TIME_LIMIT=30
1048 - LDAP_PREF_SRVLIST=""
1049 - LDAP_PROFILE_TTL=43200
1050 - LDAP_CRED_LEVEL="proxy"
1051 - LDAP_BIND_LIMIT=10
1502 + if (( NUM_TOP == 0 )); then
1503 + Log.verbose 'No suffix found in LDAP tree'
1504 + return 1
1505 + fi
1052 1506
1053 - # Prevent new files from being read by group or others.
1054 - umask 077
1055 -
1056 - # Service Search Descriptors
1057 - LDAP_SERV_SRCH_DES=""
1058 -
1059 - # Set and create TMPDIR.
1060 - TMPDIR="/tmp/idsconfig.${PID}"
1061 - if mkdir -m 700 ${TMPDIR}
1062 - then
1063 - # Cleanup on exit.
1064 - trap 'rm -rf ${TMPDIR}; /usr/bin/stty echo; exit' 1 2 3 6 15
1065 - else
1066 - echo "ERROR: unable to create a safe temporary directory."
1067 - exit 1
1068 - fi
1069 - LDAP_ROOTPWF=${TMPDIR}/rootPWD
1070 -
1071 - # Set the SSD file name after setting TMPDIR.
1072 - SSD_FILE=${TMPDIR}/ssd_list
1073 -
1074 - # GSSAPI setup
1075 - GSSAPI_ENABLE=0
1076 - LDAP_KRB_REALM=""
1077 - SCHEMA_UPDATED=0
1078 -
1079 - export DEBUG VERB ECHO EVAL EGREP GREP STEP TMPDIR
1080 - export IDS_SERVER IDS_PORT LDAP_ROOTDN LDAP_ROOTPWD LDAP_SERVER_LIST
1081 - export LDAP_BASEDN LDAP_ROOTPWF
1082 - export LDAP_DOMAIN LDAP_SUFFIX LDAP_PROXYAGENT LDAP_PROXYAGENT_CRED
1083 - export NEED_PROXY
1084 - export LDAP_ENABLE_SHADOW_UPDATE LDAP_ADMINDN LDAP_ADMIN_CRED
1085 - export NEED_ADMIN NEED_HOSTACL EXISTING_PROFILE
1086 - export LDAP_PROFILE_NAME LDAP_BASEDN LDAP_SERVER_LIST
1087 - export LDAP_AUTHMETHOD LDAP_FOLLOWREF LDAP_SEARCH_SCOPE LDAP_SEARCH_TIME_LIMIT
1088 - export LDAP_PREF_SRVLIST LDAP_PROFILE_TTL LDAP_CRED_LEVEL LDAP_BIND_LIMIT
1089 - export NEED_SRVAUTH_PAM NEED_SRVAUTH_KEY NEED_SRVAUTH_CMD
1090 - export LDAP_SRV_AUTHMETHOD_PAM LDAP_SRV_AUTHMETHOD_KEY LDAP_SRV_AUTHMETHOD_CMD
1091 - export LDAP_SERV_SRCH_DES SSD_FILE
1092 - export GEN_CMD GSSAPI_ENABLE LDAP_KRB_REALM SCHEMA_UPDATED
1507 + Log.verbose "LDAP_SUFFIX_LIST = ${DST[@]}"
1508 + return 0
1093 1509 }
1094 1510
1095 -
1096 -#
1097 -# disp_full_debug(): List of all debug variables usually interested in.
1098 -# Grouped to avoid MASSIVE code duplication.
1099 -#
1100 -disp_full_debug()
1101 -{
1102 - [ $DEBUG -eq 1 ] && ${ECHO} " IDS_SERVER = $IDS_SERVER"
1103 - [ $DEBUG -eq 1 ] && ${ECHO} " IDS_PORT = $IDS_PORT"
1104 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_ROOTDN = $LDAP_ROOTDN"
1105 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_ROOTPWD = $LDAP_ROOTPWD"
1106 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_DOMAIN = $LDAP_DOMAIN"
1107 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_SUFFIX = $LDAP_SUFFIX"
1108 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_BASEDN = $LDAP_BASEDN"
1109 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_PROFILE_NAME = $LDAP_PROFILE_NAME"
1110 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_SERVER_LIST = $LDAP_SERVER_LIST"
1111 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_PREF_SRVLIST = $LDAP_PREF_SRVLIST"
1112 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_SEARCH_SCOPE = $LDAP_SEARCH_SCOPE"
1113 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_CRED_LEVEL = $LDAP_CRED_LEVEL"
1114 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_AUTHMETHOD = $LDAP_AUTHMETHOD"
1115 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_FOLLOWREF = $LDAP_FOLLOWREF"
1116 - [ $DEBUG -eq 1 ] && ${ECHO} " IDS_TIMELIMIT = $IDS_TIMELIMIT"
1117 - [ $DEBUG -eq 1 ] && ${ECHO} " IDS_SIZELIMIT = $IDS_SIZELIMIT"
1118 - [ $DEBUG -eq 1 ] && ${ECHO} " NEED_CRYPT = $NEED_CRYPT"
1119 - [ $DEBUG -eq 1 ] && ${ECHO} " NEED_SRVAUTH_PAM = $NEED_SRVAUTH_PAM"
1120 - [ $DEBUG -eq 1 ] && ${ECHO} " NEED_SRVAUTH_KEY = $NEED_SRVAUTH_KEY"
1121 - [ $DEBUG -eq 1 ] && ${ECHO} " NEED_SRVAUTH_CMD = $NEED_SRVAUTH_CMD"
1122 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_SRV_AUTHMETHOD_PAM = $LDAP_SRV_AUTHMETHOD_PAM"
1123 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_SRV_AUTHMETHOD_KEY = $LDAP_SRV_AUTHMETHOD_KEY"
1124 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_SRV_AUTHMETHOD_CMD = $LDAP_SRV_AUTHMETHOD_CMD"
1125 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_SEARCH_TIME_LIMIT = $LDAP_SEARCH_TIME_LIMIT"
1126 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_PROFILE_TTL = $LDAP_PROFILE_TTL"
1127 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_BIND_LIMIT = $LDAP_BIND_LIMIT"
1128 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_ENABLE_SHADOW_UPDATE = $LDAP_ENABLE_SHADOW_UPDATE"
1129 -
1130 - # Only display proxy stuff if needed.
1131 - [ $DEBUG -eq 1 ] && ${ECHO} " NEED_PROXY = $NEED_PROXY"
1132 - if [ $NEED_PROXY -eq 1 ]; then
1133 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_PROXYAGENT = $LDAP_PROXYAGENT"
1134 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_PROXYAGENT_CRED = $LDAP_PROXYAGENT_CRED"
1135 - fi
1136 -
1137 - # Only display admin credential if needed.
1138 - [ $DEBUG -eq 1 ] && ${ECHO} " NEED_ADMIN = $NEED_ADMIN"
1139 - [ $DEBUG -eq 1 ] && ${ECHO} " NEED_HOSTACL = $NEED_HOSTACL"
1140 - if [ $NEED_ADMIN -eq 1 ]; then
1141 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_ADMINDN = $LDAP_ADMINDN"
1142 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_ADMIN_CRED = $LDAP_ADMIN_CRED"
1143 - fi
1144 -
1145 - # Service Search Descriptors are a special case.
1146 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_SERV_SRCH_DES = $LDAP_SERV_SRCH_DES"
1511 +Man.addFunc get_backend '' '[+NAME?get_backend - get the relevant database backend for the Base DN.]
1512 +[+DESCRIPTION?Get the relevant database backend name for the Base DN and store it into \bSTR[DS_DB]]\b.]
1513 +[+?Prerequisite: \bSTR[LDAP_BASEDN]]\b must be set and valid.]
1514 +[+?backend is retrieved from suffixes and subsuffixes defined under "cn=mapping tree,cn=config". The nsslapd-state attribute of these suffixes entries is filled with either Backend, Disabled or referrals related values. We only want those that have a true backend database to select the relevant backend.]
1515 +[+RETURN VALUES]{
1516 + [+0?on success.]
1517 + [+>= 66?an fatal error occured.]
1147 1518 }
1519 +[+SEE ALSO?\bldapsearch\b(1).]
1520 +'
1521 +function get_backend {
1522 + typeset CUR_DN=${STR[LDAP_BASEDN]} PREV_DN='' FILTER
1148 1523
1524 + while [[ ${CUR_DN} != ${PREV_DN} ]]; do
1525 + typeset -a DB=( )
1526 + Log.verbose "Testing LDAP suffix: ${CUR_DN} ..."
1149 1527
1150 -#
1151 -# load_config_file(): Loads the config file.
1152 -#
1153 -load_config_file()
1154 -{
1155 - [ $DEBUG -eq 1 ] && ${ECHO} "In load_config_file()"
1528 + if (( TMPF[IS_OPENDJ] )); then
1529 + FILTER='(&(&(objectclass=ds-cfg-backend)(ds-cfg-base-dn='"${CUR_DN}"
1530 + FILTER+='))(objectClass=ds-cfg-local-db-backend))'
1531 + ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
1532 + -b 'cn=Backends,cn=config' -s one "${FILTER}" 2>/dev/null | \
1533 + while read LINE ; do
1534 + [[ ${LINE:0:18} == 'ds-cfg-backend-id=' && \
1535 + ${LINE: -10} != ',cn=config' ]] && DB+=( "${LINE:18}" )
1536 + done
1537 + else
1156 1538
1157 - # Remove SSD lines from input file before sourcing.
1158 - # The SSD lines must be removed because some forms of the
1159 - # data could cause SHELL errors.
1160 - ${GREP} -v "LDAP_SERV_SRCH_DES=" ${INPUT_FILE} > ${TMPDIR}/inputfile.noSSD
1539 + ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
1540 + -b "cn=${CUR_DN},cn=mapping tree,cn=config" \
1541 + -s base 'nsslapd-state=Backend' 'nsslapd-backend' 2>/dev/null |\
1542 + while read LINE ; do
1543 + [[ ${LINE:0:16} == 'nsslapd-backend=' ]] && DB+=( "${LINE:16}" )
1544 + done
1545 + fi
1161 1546
1162 - # Source the input file.
1163 - . ${TMPDIR}/inputfile.noSSD
1547 + if (( ${#DB[@]} == 0 )); then
1548 + # not a suffix, or suffix not activated; try next
1549 + PREV_DN=${CUR_DN}
1550 + CUR_DN="${CUR_DN#*,}"
1551 + elif (( ${#DB[@]} == 1 )); then
1552 + break
1553 + else
1554 + Log.fatal "More than one database is configured for '${CUR_DN}'!" \
1555 + "$PROG can not configure suffixes where" \
1556 + 'more than one database is used for one suffix'
1557 + return 66
1558 + fi
1559 + done
1164 1560
1165 - # If LDAP_SUFFIX is no set, try to utilize LDAP_TREETOP since older
1166 - # config files use LDAP_TREETOP
1167 - LDAP_SUFFIX="${LDAP_SUFFIX:-$LDAP_TREETOP}"
1561 + if (( ${#DB[@]} == 0 )); then
1562 + # should not happen, since STR[LDAP_BASEDN] is supposed to be valid
1563 + Log.fatal "Could not find a valid backend for '${STR[LDAP_BASEDN]}'"
1564 + if (( TMPF[IS_OPENDJ] )); then
1565 + Log.fatal 'Check the "Creating a New Database Backend" section in the Administration Guide'
1566 + fi
1567 + return 67
1568 + fi
1569 + STR[DS_DB]="${DB[0]}"
1168 1570
1169 - # Save password to temporary file.
1170 - save_password
1571 + Log.verbose "DB backend '${STR[DS_DB]}' selected"
1171 1572
1172 - # Create the SSD file.
1173 - create_ssd_file
1573 + return 0
1574 +}
1174 1575
1175 - # Display FULL debugging info.
1176 - disp_full_debug
1576 +Man.addFunc normalizeDN '' '[+NAME?normalizeDN - normalize a [relative]] distinguished name.]
1577 +[+DESCRIPTION?Strip off unnecessary spaces around \b,\b and \b=\b as well as at the beginning and end of the given \adn\a, optionally convert it to lower or upper case (if either \bl\b or \bu\b is given) and print it to stdout.]
1578 +\n\n\adn\a [\bl\b|\bu\b]
1579 +'
1580 +function normalizeDN {
1581 + [[ -z $1 ]] && return
1582 + typeset VAL=",${1},"
1583 + VAL="${VAL//*( ),*( )/,}"
1584 + VAL="${VAL//*( )=*( )/=}"
1585 + if [[ $2 == 'l' ]]; then
1586 + typeset -l LC="${VAL}"
1587 + VAL="${LC}"
1588 + elif [[ $2 == 'u' ]]; then
1589 + typeset -u UC="${VAL}"
1590 + VAL="${UC}"
1591 + fi
1592 + print -- "${VAL:1:${#VAL}-2}"
1177 1593 }
1178 1594
1179 -#
1180 -# save_password(): Save password to temporary file.
1181 -#
1182 -save_password()
1183 -{
1184 - cat > ${LDAP_ROOTPWF} <<EOF
1185 -${LDAP_ROOTPWD}
1186 -EOF
1595 +Man.addFunc check_basedn_suffix '' '[+NAME?check_basedn_suffix - check that there is an existing valid suffix to hold current base DN.]
1596 +[+DESCRIPTION?Check that there is an existing valid suffix for \bSTR[LDAP_BASEDN]]\b. If one is found, store it into \bSTR[LDAP_SUFFIX]]\b and make a corresponding backend check.]
1597 +[+RETURN VALUES]{
1598 + [+0?valid suffix found or new one should be created (\bTMPF[NEED_CREATE_SUFFIX]]\b flag actually indicates that).]
1599 + [+>= 66?a fatal error occured.]
1187 1600 }
1601 +[+SEE ALSO?\bdiscover_serv_suffix()\b, \bldapsearch\b(1), \bnormalizeDN()\b, \bget_backend()\b.]
1602 +'
1603 +function check_basedn_suffix {
1604 + Log.info 'Validating LDAP Base DN and Suffix ...'
1605 + TMPF[NEED_CREATE_SUFFIX]=0
1188 1606
1189 -######################################################################
1190 -# FUNCTIONS FOR prompt_config_info() START HERE.
1191 -######################################################################
1607 + # check that LDAP Base DN might be added
1608 + typeset CUR_DN="${STR[LDAP_BASEDN]}" PREV_DN=''
1192 1609
1193 -#
1194 -# get_ids_server(): Prompt for iDS server name.
1195 -#
1196 -get_ids_server()
1197 -{
1198 - while :
1199 - do
1200 - # Prompt for server name.
1201 - get_ans "Enter the JES Directory Server's hostname to setup:" "$IDS_SERVER"
1202 - IDS_SERVER="$ANS"
1610 + while [[ ${CUR_DN} != ${PREV_DN} ]]; do
1611 + ${LDAPSEARCH} ${CON_ARGS} -b "${CUR_DN}" -s one 'objectclass=*' \
1612 + >/dev/null 2>&1 && break
1613 + PREV_DN=${CUR_DN}
1614 + CUR_DN="${CUR_DN#*,}" # remove leading component
1615 + done
1203 1616
1204 - # Ping server to see if live. If valid break out of loop.
1205 - ping $IDS_SERVER > /dev/null 2>&1
1206 - if [ $? -eq 0 ]; then
1207 - break
1617 + if [[ ${CUR_DN} == ${PREV_DN} ]]; then
1618 + Log.info "No valid suffixes were found for Base DN '${STR[LDAP_BASEDN]}'"
1619 + TMPF[NEED_CREATE_SUFFIX]=1
1620 + return 0
1208 1621 fi
1209 1622
1210 - # Invalid server, enter a new name.
1211 - ${ECHO} "ERROR: Server '${IDS_SERVER}' is invalid or unreachable."
1212 - IDS_SERVER=""
1213 - done
1623 + # find out existing suffixes
1624 + typeset -a SUFFIXES=( )
1625 + discover_serv_suffix SUFFIXES
1214 1626
1215 - # Set SERVER_ARGS and LDAP_ARGS since values might of changed.
1216 - SERVER_ARGS="-h ${IDS_SERVER} -p ${IDS_PORT}"
1217 - LDAP_ARGS="${SERVER_ARGS} ${AUTH_ARGS}"
1218 - export SERVER_ARGS
1627 + # Now looking for relevant suffix for this entry (using lower case - LC).
1628 + # STR[LDAP_SUFFIX] will then be used to add necessary base objects via
1629 + # add_base_objects().
1630 + typeset LC_DN=,${ normalizeDN "${CUR_DN}" l ; }
1631 + typeset SFX LC_SFX
1632 + for SFX in "${SUFFIXES[@]}" ; do
1633 + Log.verbose "Testing suffix: ${SFX} ..."
1634 + # LC_DN ends with ,SFX ?
1635 + LC_SFX=,${ normalizeDN "${SFX}" l ; }
1636 + if [[ ${LC_DN: -${#LC_SFX}} == ${LC_SFX} ]]; then
1637 + STR[LDAP_SUFFIX]="${SFX}"
1638 + break
1639 + fi
1640 + done
1219 1641
1220 -}
1221 -
1222 -#
1223 -# get_ids_port(): Prompt for iDS port number.
1224 -#
1225 -get_ids_port()
1226 -{
1227 - # Get a valid iDS port number.
1228 - while :
1229 - do
1230 - # Enter port number.
1231 - get_number "Enter the port number for iDS (h=help):" "$IDS_PORT" "port_help"
1232 - IDS_PORT=$ANS
1233 - # Do a simple search to check hostname and port number.
1234 - # If search returns SUCCESS, break out, host and port must
1235 - # be valid.
1236 - ${LDAPSEARCH} -h ${IDS_SERVER} -p ${IDS_PORT} -b "" -s base "objectclass=*" > /dev/null 2>&1
1237 - if [ $? -eq 0 ]; then
1238 - break
1642 + if [[ -z ${STR[LDAP_SUFFIX]} ]]; then
1643 + # should not happen, since we found the entry
1644 + Log.fatal "Could not find a valid suffix for '${STR[LDAP_BASEDN]}'"
1645 + return 66
1239 1646 fi
1240 1647
1241 - # Invalid host/port pair, Re-enter.
1242 - ${ECHO} "ERROR: Invalid host or port: ${IDS_SERVER}:${IDS_PORT}, Please re-enter!"
1243 - get_ids_server
1244 - done
1648 + # Getting relevant database (backend)
1649 + # DS_DB will then be used to create indexes.
1650 + get_backend || return 67
1245 1651
1246 - # Set SERVER_ARGS and LDAP_ARGS since values might of changed.
1247 - SERVER_ARGS="-h ${IDS_SERVER} -p ${IDS_PORT}"
1248 - LDAP_ARGS="${SERVER_ARGS} ${AUTH_ARGS}"
1249 - export SERVER_ARGS
1652 + return 0
1250 1653 }
1251 1654
1655 +Man.addFunc get_objectclass '' '[+NAME?get_objectclass - get the objectclass for the given attribute name.]
1656 +[+DESCRIPTION?Get the objectclass for the given attribute name \aattrName\a and print it to stdout. Right now ou, dc, o, and c and related aliases/OIDs are supported, only. For all others nothing will be printed.]
1657 +[+NOTES?An attribute name can be valid but still we might not be able to determine the objectclass from the table. In such cases, the user needs to create the necessary object(s).]
1658 +\n\n\aattrName\a
1659 +'
1660 +function get_objectclass {
1661 + typeset -l ANAME="$1"
1252 1662
1253 -#
1254 -# chk_ids_version(): Read the slapd config file and set variables
1255 -#
1256 -chk_ids_version()
1257 -{
1258 - [ $DEBUG -eq 1 ] && ${ECHO} "In chk_ids_version()"
1663 + case "${ANAME}" in
1664 + ou | organizationalunitname | 2.5.4.11)
1665 + print 'organizationalUnit'
1666 + ;;
1667 + dc | domaincomponent | 0.9.2342.19200300.100.1.25)
1668 + print 'domain'
1669 + ;;
1670 + o | organizationname | 2.5.4.10)
1671 + print 'organization'
1672 + ;;
1673 + c | countryname | 2.5.4.6)
1674 + print 'country'
1675 + ;;
1676 + esac
1677 +}
1259 1678
1260 - # check iDS version number.
1261 - eval "${LDAPSEARCH} ${SERVER_ARGS} -b cn=monitor -s base \"objectclass=*\" version | ${GREP} \"^version=\" | cut -f2 -d'/' | cut -f1 -d' ' > ${TMPDIR}/checkDSver 2>&1"
1262 - if [ $? -ne 0 ]; then
1263 - ${ECHO} "ERROR: Can not determine the version number of iDS!"
1264 - exit 1
1265 - fi
1266 - IDS_VER=`cat ${TMPDIR}/checkDSver`
1267 - IDS_MAJVER=`${ECHO} ${IDS_VER} | cut -f1 -d.`
1268 - IDS_MINVER=`${ECHO} ${IDS_VER} | cut -f2 -d.`
1269 - case "${IDS_MAJVER}" in
1270 - 5|6|7) : ;;
1271 - *) ${ECHO} "ERROR: $PROG only works with JES DS version 5.x, 6.x or 7.x, not ${IDS_VER}."; exit 1;;
1272 - esac
1273 -
1274 - if [ $DEBUG -eq 1 ]; then
1275 - ${ECHO} " IDS_MAJVER = $IDS_MAJVER"
1276 - ${ECHO} " IDS_MINVER = $IDS_MINVER"
1277 - fi
1679 +function checkSuffixRDN {
1680 + typeset RDN="${STR[LDAP_SUFFIX]%%,*}"
1681 + TMP[SUFFIX_VAL]="${RDN#*=}"
1682 + TMP[SUFFIX_ATT]="${.sh.match%=}"
1683 +
1684 + # find out an objectclass for suffix entry if it is not defined yet
1685 + TMP[SUFFIX_OBJ]=${ get_objectclass "${TMP[SUFFIX_ATT]}" ; }
1686 + if [[ -z ${TMP[SUFFIX_OBJ]} ]]; then
1687 + Log.fatal 'Unable to find an objectclass for' "'${TMP[SUFFIX_ATT]}'" \
1688 + 'attribute'
1689 + return 1
1690 + fi
1691 + return 0
1278 1692 }
1279 1693
1280 -
1281 -#
1282 -# get_dirmgr_dn(): Get the directory manger DN.
1283 -#
1284 -get_dirmgr_dn()
1285 -{
1286 - get_ans "Enter the directory manager DN:" "$LDAP_ROOTDN"
1287 - LDAP_ROOTDN=$ANS
1288 -
1289 - # Update ENV variables using DN.
1290 - AUTH_ARGS="-D \"${LDAP_ROOTDN}\" -j ${LDAP_ROOTPWF}"
1291 - LDAP_ARGS="${SERVER_ARGS} ${AUTH_ARGS}"
1292 - export AUTH_ARGS LDAP_ARGS
1694 +Man.addFunc prep_create_sfx_entry '' '[+NAME?prep_create_sfx_entry - prepare for the suffix entry creation.]
1695 +[+DESCRIPTION?Prepare suffix entry creation based on \bSTR[LDAP_BASEDN|LDAP_SUFFIX]]\b and \bTMP[SUFFIX_OBJ]]\b. If the latter are unset (no config file read), set them to defaults depending on the baseDN. Finally check, whether the suffix entry already exists and if so check for consistency with the current config. This function sets:]{
1696 + [+TMPF[NEED_CREATE_BACKEND]]?0 .. backend already exists. 1 .. create a backend.]
1697 + [+TMP[SUFFIX_ATT]]?The attribute name of the leading RDN of the suffix (ID).]
1698 + [+TMP[SUFFIX_VAL]]?The attribute value of the leading RDN of the suffix (ID).]
1293 1699 }
1700 +[+RETURN VALUES]{
1701 + [+0?on success.]
1702 + [+1?an attribute/consistence related error occured.]
1703 + [+>= 66?a fatal error occured.]
1704 +}
1705 +[+SEE ALSO?\bnormalizeDN()\b, \bdisplay_msg()\b, \badd_suffix()\b, \bldapsearch\b(1)]
1706 +'
1707 +function prep_create_sfx_entry {
1708 + # check whether suffix corresponds to base dn (i.e. baseDN ends with suffix)
1709 + typeset X=,${ normalizeDN "${STR[LDAP_BASEDN]}" l ; }
1710 + typeset SFX=,${STR[LDAP_SUFFIX]}
1711 + if [[ ${X: -${#SFX}} != ${SFX} ]]; then
1712 + Log.warn "Sorry, suffix '${STR[LDAP_SUFFIX]}' is not suitable for" \
1713 + "Base DN '${STR[LDAP_BASEDN]}'"
1714 + return 1
1715 + fi
1294 1716
1717 + checkSuffixRDN || return 66
1718 + Log.verbose "Suffix entry object: '${TMP[SUFFIX_OBJ]}'"
1295 1719
1296 -#
1297 -# get_dirmgr_pw(): Get the Root DN passwd. (Root DN found in slapd.conf)
1298 -#
1299 -get_dirmgr_pw()
1300 -{
1301 - while :
1302 - do
1303 - # Get passwd.
1304 - get_passwd_nochk "Enter passwd for ${LDAP_ROOTDN} :"
1305 - LDAP_ROOTPWD=$ANS
1720 + TMPF[NEED_CREATE_BACKEND]=0
1306 1721
1307 - # Store password in file.
1308 - save_password
1309 -
1310 - # Update ENV variables using DN's PW.
1311 - AUTH_ARGS="-D \"${LDAP_ROOTDN}\" -j ${LDAP_ROOTPWF}"
1312 - LDAP_ARGS="${SERVER_ARGS} ${AUTH_ARGS}"
1313 - export AUTH_ARGS LDAP_ARGS
1314 -
1315 - # Verify that ROOTDN and ROOTPWD are valid.
1316 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"\" -s base \"objectclass=*\" > ${TMPDIR}/checkDN 2>&1"
1317 - if [ $? -ne 0 ]; then
1318 - eval "${GREP} credential ${TMPDIR}/checkDN ${VERB}"
1319 - if [ $? -eq 0 ]; then
1320 - ${ECHO} "ERROR: Root DN passwd is invalid."
1321 - else
1322 - ${ECHO} "ERROR: Invalid Root DN <${LDAP_ROOTDN}>."
1323 - get_dirmgr_dn
1324 - fi
1722 + if (( TMPF[IS_OPENDJ] )); then
1723 + # 1st just check, whether any backend matches the suffix
1724 + typeset FILTER='(&(objectClass=ds-cfg-local-db-backend)'
1725 + FILTER+="(|(ds-cfg-base-dn=${STR[LDAP_SUFFIX]})"
1726 + FILTER+="(ds-cfg-base-dn=*,${STR[LDAP_SUFFIX]})))"
1727 + X=${ ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
1728 + -b 'cn=Backends,cn=config' -s one "${FILTER}" 2>/dev/null ; }
1729 + if [[ -n ${X} ]]; then
1730 + Log.verbose 'Suffix backend already exists'
1731 + get_backend || return 66
1732 + return 0
1733 + fi
1325 1734 else
1326 - break # Both are valid.
1735 + # DSEE: check the suffix mapping tree ...
1736 + # If mapping exists, suffix should work, otherwise DSEE inconsistent
1737 + # NOTE: -b 'cn=mapping tree,cn=config' -s one 'cn=\"$1\"' won't work
1738 + # in case of 'cn' value in LDAP is not quoted by '"',
1739 + # -b 'cn=\"$1\",cn=mapping tree,cn=config' works in all cases
1740 + if ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
1741 + -b "cn=\"${STR[LDAP_SUFFIX]}\",cn=mapping tree,cn=config" \
1742 + -s base 'objectclass=*' dn 2>/dev/null
1743 + then
1744 + Log.verbose 'Suffix mapping already exists'
1745 + get_backend || return 66
1746 + return 0
1747 + fi
1748 +
1749 + # no suffix mapping, just in case check ldbm backends consistency -
1750 + # there are must be NO any databases pointing to STR[LDAP_SUFFIX]
1751 + X=${ ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
1752 + -b 'cn=ldbm database,cn=plugins,cn=config' \
1753 + -s one "nsslapd-suffix=${STR[LDAP_SUFFIX]}" dn 2>/dev/null ; }
1754 + if [[ -n ${X} ]]; then
1755 + Log.warn 'Sorry, there is no suffix mapping for' \
1756 + "'${STR[LDAP_SUFFIX]}', while ldbm database exists, server" \
1757 + 'configuration needs to be fixed manually, look at cn=mapping' \
1758 + 'tree,cn=config and cn=ldbm database,cn=plugins,cn=config'
1759 + return 1
1760 + fi
1327 1761 fi
1328 - done
1329 1762
1330 -
1763 + Log.verbose 'Backend needs to be created ...'
1764 + TMPF[NEED_CREATE_BACKEND]=1
1765 + return 0
1331 1766 }
1332 1767
1333 -
1334 -#
1335 -# get_domain(): Get the Domain that will be served by the LDAP server.
1336 -# $1 - Help argument.
1337 -#
1338 -get_domain()
1339 -{
1340 - # Use LDAP_DOMAIN as default.
1341 - get_ans "Enter the domainname to be served (h=help):" $LDAP_DOMAIN
1342 -
1343 - # Check domainname, and have user re-enter if not valid.
1344 - check_domainname $ANS
1345 - while [ $? -ne 0 ]
1346 - do
1347 - case "$ANS" in
1348 - [Hh] | help | Help | \?) display_msg ${1:-sorry} ;;
1349 - * ) ${ECHO} "Invalid domainname: \"${ANS}\"."
1350 - ;;
1351 - esac
1352 - get_ans "Enter domainname to be served (h=help):" $DOM
1353 -
1354 - check_domainname $ANS
1355 - done
1356 -
1357 - # Set the domainname to valid name.
1358 - LDAP_DOMAIN=$ANS
1768 +Man.addFunc prep_create_sfx_backend '' '[+NAME?prep_create_sfx_backend - prepare for the suffix backend creation.]
1769 +[+DESCRIPTION?Prepare for the suffix backend creation by checking available DBs starting with \bSTR[DS_DB]]\b. Sets \bTMP[DS_DB_AVAIL]]\b if not yet set or != \bSTR[DS_DB]]\b.]
1770 +[+RETURN VALUES]{
1771 + [+0?backend db name is ok.]
1772 + [+1?\bSTR[DS_DB]]\b exists, so \bTMP[DS_DB_AVAIL]]\b contains available name.]
1773 + [+2?unable to find any available name.]
1359 1774 }
1775 +[+SEE ALSO?\bldapsearch\b(1).]
1776 +'
1777 +function prep_create_sfx_backend {
1778 + # check if requested name available
1779 + [[ ${STR[DS_DB]} == ${TMP[DS_DBS_AVAIL]} ]] && return 0
1360 1780
1781 + # get the list of database names start with a requested name
1782 + typeset -a DBS=( )
1783 + if (( TMPF[IS_OPENDJ] )); then
1784 + typeset FILTER='(&(objectclass=ds-cfg-local-db-backend)'
1785 + FILTER+="(ds-cfg-backend-id=${STR[DS_DB]}*))"
1786 + ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
1787 + -b 'cn=Backends,cn=config' -s one "${FILTER}" ds-cfg-backend-id \
1788 + 2>/dev/null | \
1789 + while read LINE ; do
1790 + [[ -n ${LINE} && ${LINE: -10} != ',cn=config' ]] && \
1791 + DBS+=( "${LINE#ds-cfg-backend-id=}" )
1792 + done
1793 + else
1794 + ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
1795 + -b 'cn=ldbm database,cn=plugins,cn=config' \
1796 + -s one "cn=${STR[DS_DB]}*" cn 2>/dev/null | \
1797 + while read LINE ; do
1798 + [[ -n ${LINE} && ${LINE: -10} != ',cn=config' ]] && \
1799 + DBS+=( "${LINE#cn=}" )
1800 + done
1801 + fi
1802 + if (( ${#DBS[@]} == 0 )); then
1803 + # no backend name starts with STR[DS_DB]
1804 + TMP[DS_DBS_AVAIL]="${STR[DS_DB]}"
1805 + return 0
1806 + fi
1361 1807
1362 -#
1363 -# get_basedn(): Query for the Base DN.
1364 -#
1365 -get_basedn()
1366 -{
1367 - # Set the $_DOM_2_DC and assign to LDAP_BASEDN as default.
1368 - # Then call get_basedn(). This method remakes the default
1369 - # each time just in case the domain changed.
1370 - domain_2_dc $LDAP_DOMAIN
1371 - LDAP_BASEDN=$_DOM_2_DC
1372 -
1373 - # Get Base DN.
1374 - while :
1375 - do
1376 - get_ans_req "Enter LDAP Base DN (h=help):" "${_DOM_2_DC}"
1377 - check_baseDN "$ANS"
1378 - while [ $? -ne 0 ]
1379 - do
1380 - case "$ANS" in
1381 - [Hh] | help | Help | \?) display_msg basedn_help ;;
1382 - * ) ${ECHO} "Invalid base DN: \"${ANS}\"."
1383 - ;;
1384 - esac
1385 -
1386 - # Re-Enter the BaseDN
1387 - get_ans_req "Enter LDAP Base DN (h=help):" "${_DOM_2_DC}"
1388 - check_baseDN "$ANS"
1808 + # find a non-existing db name based on a requested name
1809 + integer I FOUND
1810 + typeset -l NAME DB
1811 + for (( I=0 ; I < 10; I++ )); do
1812 + (( I )) && NAME="${STR[DS_DB]}${I}" || NAME="${STR[DS_DB]}"
1813 + FOUND=0
1814 + for DB in "${DBS[@]}" ; do
1815 + [[ ${DB} == ${NAME} ]] && FOUND=1 && break
1816 + done
1817 + if (( ! FOUND )); then
1818 + if (( I == 0 )); then
1819 + TMP[DS_DBS_AVAIL]="${STR[DS_DB]}"
1820 + return 0 # requested name is available
1821 + fi
1822 + TMP[DS_DBS_AVAIL]="${STR[DS_DB]}${I}"
1823 + break
1824 + fi
1389 1825 done
1390 1826
1391 - # Set base DN and check its suffix
1392 - LDAP_BASEDN=${ANS}
1393 - check_basedn_suffix ||
1394 - {
1395 - cleanup
1396 - exit 1
1397 - }
1827 + if [[ -n ${TMP[DS_DBS_AVAIL]} ]]; then
1828 + Log.warn "Database backend '${STR[DS_DB]}' already exists," \
1829 + "however '${TMP[DS_DBS_AVAIL]}' is available"
1830 + return 1
1831 + fi
1398 1832
1399 - # suffix may need to be created, in that case get suffix from user
1400 - [ -n "${NEED_CREATE_SUFFIX}" ] &&
1401 - {
1402 - get_suffix || continue
1403 - }
1404 -
1405 - # suffix is ok, break out of the base dn inquire loop
1406 - break
1407 - done
1833 + Log.warn 'Unable to find any available database backend close to' \
1834 + "'${STR[DS_DB]}'"
1835 + return 2
1408 1836 }
1409 1837
1410 -#
1411 -# get_want_shadow_update(): Ask user if want to enable shadow update?
1412 -#
1413 -get_want_shadow_update()
1414 -{
1415 - MSG="Do you want to enable shadow update (y/n/h)?"
1416 - get_confirm "$MSG" "n" "enable_shadow_update_help"
1417 - if [ $? -eq 1 ]; then
1418 - LDAP_ENABLE_SHADOW_UPDATE="TRUE"
1419 - else
1420 - LDAP_ENABLE_SHADOW_UPDATE="FALSE"
1421 - fi
1838 +Man.addFunc get_suffix '' '[+NAME?get_suffix - Ask user for suffix and related backend.]
1839 +[+DESCRIPTION?Ask the user for the suffix (default: \bSTR[LDAP_BASEDN]]\b) to create and the db name if it does not yet exist. \bTMP[DS_DBS_AVAIL]]\b gets set to the given db name (if any), \bSTR[DS_DB]]\b to the prepared db name and \bSTR[LDAP_SUFFIX]]\b to the given suffix.]
1840 +[+RETURN VALUES]{
1841 + [+0?on success (user gave a correct suffix).]
1842 + [+1?unable to create suffix given by user.]
1843 + [+>= 66?a fatal error occured.]
1422 1844 }
1845 +[+SEE ALSO?\bget_ans()\b, \bdisplay_msg()\b, \bnormalizeDN()\b, \bprep_create_sfx_entry()\b, \bprep_create_sfx_backend()\b.]
1846 +'
1847 +function get_suffix {
1848 + while : ; do
1849 + get_ans 'Enter suffix to be created (b=back/h=help):' \
1850 + "${STR[LDAP_BASEDN]}"
1851 + case "${ANS}" in
1852 + [Hh?] | Help | help)
1853 + display_msg 'create_suffix_help'
1854 + continue
1855 + ;;
1856 + [Bb] | '<' | Back | back)
1857 + return 1
1858 + ;;
1859 + esac
1860 + STR[LDAP_SUFFIX]=${ normalizeDN "${ANS}" l ; }
1861 + prep_create_sfx_entry
1862 + integer REDO=$?
1863 + (( REDO >= 66 )) && return 66
1864 + (( REDO )) && continue
1423 1865
1424 -get_krb_realm() {
1866 + if (( TMPF[NEED_CREATE_BACKEND] )); then
1867 + TMP[DS_DBS_AVAIL]='' # reset the available db name
1868 + REDO=0
1869 + while : ; do
1870 + X=${TMP[DS_DBS_AVAIL]}
1871 + # Basically for OpenDJ we could use 'userRoot' as default aka
1872 + # TMP[SUFFIX_VAL], however, users may use it for trying out
1873 + # examples from the docs
1874 + get_ans 'Enter local database backend name (b=back/h=help):' \
1875 + "${X:-${TMP[SUFFIX_VAL]}}"
1876 + case "${ANS}" in
1877 + [Hh?])
1878 + display_msg 'enter_ldbm_db_help'
1879 + continue
1880 + ;;
1881 + [Bb] | '<')
1882 + REDO=1
1883 + break
1884 + ;;
1885 + esac
1886 + STR[DS_DB]="${ANS}"
1887 + prep_create_sfx_backend && break
1888 + done
1425 1889
1426 - # To upper cases
1427 - LDAP_KRB_REALM=`${ECHO} ${LDAP_DOMAIN} | ${NAWK} '{ print toupper($0) }'`
1428 - get_ans_req "Enter Kerberos Realm:" "$LDAP_KRB_REALM"
1429 - # To upper cases
1430 - LDAP_KRB_REALM=`${ECHO} ${ANS} | ${NAWK} '{ print toupper($0) }'`
1890 + (( REDO )) && continue
1891 +
1892 + Log.verbose 'Databse backend name for suffix ${STR[LDAP_SUFFIX]}:' \
1893 + "${DS_DB}"
1894 + fi
1895 + # eventually everything is prepared
1896 + break
1897 + done
1898 + return 0
1431 1899 }
1432 1900
1433 -# $1: DN
1434 -# $2: ldif file
1435 -add_entry_by_DN() {
1901 +Man.addFunc domain_2_dc '' '[+NAME?domain_2_dc - Convert a domain name into dc string.]
1902 +[+DESCRIPTION?Convert a domain name \adomain\a into a dc=...,dc=... string and print it to stdout.]
1903 +\n\n\adomain\a
1904 +'
1905 +function domain_2_dc {
1906 + [[ -z $1 ]] && return
1907 + typeset DC='' SD
1908 + for SD in ${1//./ } ; do # removes leading && trailing && double dots
1909 + DC+=",dc=${SD}"
1910 + done
1911 + print -- "${DC:1}"
1912 +}
1436 1913
1437 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"${1}\" -s base \"objectclass=*\" ${VERB}"
1438 - if [ $? -eq 0 ]; then
1439 - ${ECHO} " ${1} already exists"
1440 - return 0
1441 - else
1442 - ${EVAL} "${LDAPADD} ${LDAP_ARGS} -f ${2} ${VERB}"
1443 - if [ $? -eq 0 ]; then
1444 - ${ECHO} " ${1} is added"
1445 - return 0
1446 - else
1447 - ${ECHO} " ERROR: failed to add ${1}"
1448 - return 1
1449 - fi
1450 - fi
1451 -
1914 +Man.addFunc get_basedn '' '[+NAME?get_basedn - Ask user for Base DN.]
1915 +[+DESCRIPTION?Ask the user for the BaseDN to use, check whether to create a suffix and store the value into \bSTR[LDAP_BASEDN]]\b.]
1916 +[+RETURN VALUES]{
1917 + [+0?on success.]
1918 + [+>= 66?a fatal error occured.]
1452 1919 }
1453 -#
1454 -# Kerberos princiapl to DN mapping rules
1455 -#
1456 -# Add rules for host credentails and user credentials
1457 -#
1458 -add_id_mapping_rules() {
1920 +[+SEE ALSO?\bget_ans_req()\b, \bdisplay_msg()\b, \bcheck_baseDN()\b, \bcheck_basedn_suffix()\b, \bget_suffix()\b.]
1921 +'
1922 +function get_basedn {
1923 + typeset BASEDN=${ domain_2_dc ${STR[LDAP_DOMAIN]} ; }
1924 + integer RES
1459 1925
1460 - ${ECHO} " Adding Kerberos principal to DN mapping rules..."
1926 + while : ; do
1927 + # Get Base DN.
1928 + while : ; do
1929 + get_ans_req 'Enter LDAP Base DN (h=help):' "${BASEDN}"
1930 + case "${ANS}" in
1931 + [Hh?] | help | Help) display_msg 'basedn_help' ; continue ;;
1932 + esac
1933 + check_baseDN "${ANS}" && break
1934 + Log.warn "Invalid base DN: '${ANS}'"
1935 + done
1461 1936
1462 - _C_DN="cn=GSSAPI,cn=identity mapping,cn=config"
1463 - ( cat << EOF
1464 -dn: cn=GSSAPI,cn=identity mapping,cn=config
1465 -objectClass: top
1466 -objectClass: nsContainer
1467 -cn: GSSAPI
1468 -EOF
1469 -) > ${TMPDIR}/GSSAPI_container.ldif
1937 + # Set base DN and check its suffix
1938 + STR[LDAP_BASEDN]="${ANS}"
1939 + check_basedn_suffix || return 66
1470 1940
1471 - add_entry_by_DN "${_C_DN}" "${TMPDIR}/GSSAPI_container.ldif"
1472 - if [ $? -ne 0 ];
1473 - then
1474 - ${RM} ${TMPDIR}/GSSAPI_container.ldif
1475 - return
1476 - fi
1941 + # suffix may need to be created, in that case get suffix from user
1942 + if (( TMPF[NEED_CREATE_SUFFIX] )); then
1943 + get_suffix
1944 + RES=$?
1945 + (( RES >= 66 )) && return 67
1946 + (( RES )) && continue
1947 + fi
1477 1948
1478 - _H_CN="host_auth_${LDAP_KRB_REALM}"
1479 - _H_DN="cn=${_H_CN}, ${_C_DN}"
1480 - ( cat << EOF
1481 -dn: ${_H_DN}
1482 -objectClass: top
1483 -objectClass: nsContainer
1484 -objectClass: dsIdentityMapping
1485 -objectClass: dsPatternMatching
1486 -cn: ${_H_CN}
1487 -dsMatching-pattern: \${Principal}
1488 -dsMatching-regexp: host\/(.*).${LDAP_DOMAIN}@${LDAP_KRB_REALM}
1489 -dsSearchBaseDN: ou=hosts,${LDAP_BASEDN}
1490 -dsSearchFilter: (&(objectClass=ipHost)(cn=\$1))
1491 -dsSearchScope: one
1949 + # suffix is ok, break out of the base dn inquire loop
1950 + break
1951 + done
1952 + return 0
1953 +}
1492 1954
1493 -EOF
1494 -) > ${TMPDIR}/${_H_CN}.ldif
1955 +Man.addFunc chk_vlv_indexes '' '[+NAME?chk_vlv_indexes - check if server supports VLV.]
1956 +[+DESCRIPTION?Checks, whether the DS supports Virtual List Views (VLV).]
1957 +[+RETURN VALUES]{
1958 + [+0?if VLVs are supported.]
1959 + [+>= 66?if VLVs are not supported.]
1960 +}
1961 +[+SEE ALSO?\bldapsearch\b(1).]
1962 +'
1963 +function chk_vlv_indexes {
1964 + typeset ATTR=''
1965 + ${LDAPSEARCH} ${CON_ARGS} -b '' -s base 'objectclass=*' \
1966 + supportedControl 2>/dev/null | \
1967 + while read LINE ; do
1968 + if [[ ${LINE#*=} == '2.16.840.1.113730.3.4.9' ]]; then
1969 + ATTR=${.sh.match%=}
1970 + break
1971 + fi
1972 + done
1973 + if [[ -z ${ATTR} ]]; then
1974 + Log.fatal 'VLV is not supported on LDAP server'
1975 + return 66
1976 + fi
1977 + return 0
1978 +}
1495 1979
1496 - add_entry_by_DN "${_H_DN}" "${TMPDIR}/${_H_CN}.ldif"
1497 -
1498 - _U_CN="user_auth_${LDAP_KRB_REALM}"
1499 - _U_DN="cn=${_U_CN}, ${_C_DN}"
1500 - ( cat << EOF
1501 -dn: ${_U_DN}
1502 -objectClass: top
1503 -objectClass: nsContainer
1504 -objectClass: dsIdentityMapping
1505 -objectClass: dsPatternMatching
1506 -cn: ${_U_CN}
1507 -dsMatching-pattern: \${Principal}
1508 -dsMatching-regexp: (.*)@${LDAP_KRB_REALM}
1509 -dsMappedDN: uid=\$1,ou=People,${LDAP_BASEDN}
1510 -
1511 -EOF
1512 -) > ${TMPDIR}/${_U_CN}.ldif
1513 -
1514 - add_entry_by_DN "${_U_DN}" "${TMPDIR}/${_U_CN}.ldif"
1515 -
1980 +Man.addFunc validate_suffix '' '[+NAME?validate_suffix - validate suffix obtained via config file.]
1981 +[+DESCRIPTION?This function validates STR[LDAP_SUFFIX]] AFTER THE LOAD OF A CONFIG FILE (should not be used for interactive use). Also does a consistency check wrt. \bSTR[LDAP_BASEDN]]\b.]
1982 +[+RETURN VALUES]{
1983 + [+0?on success.]
1984 + [+>= 66?a fatal error occured.]
1516 1985 }
1986 +[+SEE ALSO?\bnormalizeDN()\b, \bldapsearch\b(1), \bprep_create_sfx_entry()\b, \bprep_create_sfx_backend()\b.]
1987 +'
1988 +function validate_suffix {
1989 + # Check STR[LDAP_SUFFIX] is not null
1990 + if [[ -z ${STR[LDAP_SUFFIX]} ]]; then
1991 + Log.fatal 'Invalid suffix (null suffix)'
1992 + return 66
1993 + fi
1517 1994
1995 + # STR[LDAP_SUFFIX] and STR[LDAP_BASEDN] are consistent ?
1996 + typeset X=,${ normalizeDN "${STR[LDAP_BASEDN]}" l ; }
1997 + typeset SFX=,${ normalizeDN "${STR[LDAP_SUFFIX]}" l ; }
1998 + if [[ ${X: -${#SFX}} != ${SFX} ]]; then
1999 + Log.fatal "Invalid suffix '${SFX}' for Base DN '${X}'"
2000 + return 67
2001 + fi
1518 2002
1519 -#
1520 -# Modify ACL to allow root to read all the password and only self can read
1521 -# its own password when sasl/GSSAPI bind is used
1522 -#
1523 -modify_userpassword_acl_for_gssapi() {
2003 + # STR[LDAP_SUFFIX] does exist ?
2004 + if ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b "${STR[LDAP_SUFFIX]}" \
2005 + -s base 'objectclass=*' >/dev/null 2>&1
2006 + then
2007 + checkSuffixRDN && return 0 || return 68
2008 + fi
1524 2009
1525 - _P_DN="ou=People,${LDAP_BASEDN}"
1526 - _H_DN="ou=Hosts,${LDAP_BASEDN}"
1527 - _P_ACI="self-read-pwd"
2010 + # Well, suffix does not exist, try to prepare create it ...
2011 + TMPF[NEED_CREATE_SUFFIX]=1
2012 + prep_create_sfx_entry || return 69
2013 + if (( TMPF[NEED_CREATE_BACKEND] )); then
2014 + if [[ -z ${STR[DS_DB]} ]]; then
2015 + Log.fatal 'Database backend name is not set. Either set SIN[DS_DB]'\
2016 + 'in the input file to a valid, i.e. non-existing DB name, or' \
2017 + 'create the backend with the default DS tools'
2018 + return 70
2019 + fi
2020 + # too risky, even if a available backend name could be found
2021 + prep_create_sfx_backend || return 71
2022 + fi
1528 2023
1529 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"${_P_DN}\" -s base \"objectclass=*\" > /dev/null 2>&1"
1530 - if [ $? -ne 0 ]; then
1531 - ${ECHO} " ${_P_DN} does not exist"
1532 - # Not Found. Create a new entry
1533 - ( cat << EOF
1534 -dn: ${_P_DN}
1535 -ou: People
1536 -objectClass: top
1537 -objectClass: organizationalUnit
1538 -EOF
1539 -) > ${TMPDIR}/gssapi_people.ldif
1540 -
1541 - add_entry_by_DN "${_P_DN}" "${TMPDIR}/gssapi_people.ldif"
1542 - else
1543 - ${ECHO} " ${_P_DN} already exists"
1544 - fi
1545 -
1546 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"${_P_DN}\" -s base \"objectclass=*\" aci > ${TMPDIR}/chk_gssapi_aci 2>&1"
1547 -
1548 - if [ $? -eq 0 ]; then
1549 - ${EVAL} "${GREP} ${_P_ACI} ${TMPDIR}/chk_gssapi_aci > /dev/null 2>&1"
1550 - if [ $? -eq 0 ]; then
1551 - ${ECHO} " userpassword ACL ${_P_ACI} already exists."
1552 - return
1553 - else
1554 - ${ECHO} " userpassword ACL ${_P_ACI} not found. Create a new one."
1555 - fi
1556 - else
1557 - ${ECHO} " Error searching aci for ${_P_DN}"
1558 - cat ${TMPDIR}/chk_gssapi_aci
1559 - cleanup
1560 - exit 1
1561 - fi
1562 - ( cat << EOF
1563 -dn: ${_P_DN}
1564 -changetype: modify
1565 -add: aci
1566 -aci: (targetattr="userPassword")(version 3.0; acl self-read-pwd; allow (read,search) userdn="ldap:///self" and authmethod="sasl GSSAPI";)
1567 --
1568 -add: aci
1569 -aci: (targetattr="userPassword")(version 3.0; acl host-read-pwd; allow (read,search) userdn="ldap:///cn=*+ipHostNumber=*,ou=Hosts,${LDAP_BASEDN}" and authmethod="sasl GSSAPI";)
1570 -EOF
1571 -) > ${TMPDIR}/user_gssapi.ldif
1572 - LDAP_TYPE_OR_VALUE_EXISTS=20
1573 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/user_gssapi.ldif ${VERB}"
1574 -
1575 - case $? in
1576 - 0)
1577 - ${ECHO} " ${_P_DN} uaserpassword ACL is updated."
1578 - ;;
1579 - 20)
1580 - ${ECHO} " ${_P_DN} uaserpassword ACL already exists."
1581 - ;;
1582 - *)
1583 - ${ECHO} " ERROR: update of userpassword ACL for ${_P_DN} failed!"
1584 - cleanup
1585 - exit 1
1586 - ;;
1587 - esac
2024 + Log.verbose "Suffix: '${STR[LDAP_SUFFIX]}' Database: '${STR[DS_DB]}'"
2025 + return 0
1588 2026 }
1589 -#
1590 -# $1: objectclass or attributetyp
1591 -# $2: name
1592 -search_update_schema() {
1593 2027
1594 - ATTR="${1}es"
1595 -
1596 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b cn=schema -s base \"objectclass=*\" ${ATTR} | ${GREP} -i \"${2}\" ${VERB}"
1597 - if [ $? -ne 0 ]; then
1598 - ${ECHO} "${1} ${2} does not exist."
1599 - update_schema_attr
1600 - update_schema_obj
1601 - SCHEMA_UPDATED=1
1602 - else
1603 - ${ECHO} "${1} ${2} already exists. Schema has been updated"
1604 - fi
2028 +Man.addFunc validate_info '' '[+NAME?validate_info - validate basic info obtained via config file.]
2029 +[+DESCRIPTION?This function updates \bCON_ARGS\b as well as \bAUTH_ARGS\b, checks, whether they work so that some problems are caught right away AFTER THE LOAD OF A CONFIG FILE (should not be used for interactive use). It also validates the obtained suffix and whether the DS supports VLVs.]
2030 +[+RETURN VALUES]{
2031 + [+0?on success.]
2032 + [+>= 66?a fatal error occured.]
1605 2033 }
2034 +[+SEE ALSO?\bldapsearch\b(1), \bchk_vlv_indexes()\b, \bvalidate_suffix()\b.]
2035 +'
2036 +function validate_info {
2037 + # Set CON_ARGS and AUTH_ARGS for the config file.
2038 + CON_ARGS="-h ${STR[DS_HOST]} -p ${INT[DS_PORT]}"
2039 + AUTH_ARGS=( '-D' "${STR[LDAP_ROOTDN]}" '-j' "${TMP[LDAP_ROOTPWF]}" )
2040 + chk_ids_version || return 1 # Check DSEE version for compatibility
1606 2041
1607 -#
1608 -# Set up GSSAPI if necessary
1609 -#
1610 -gssapi_setup() {
2042 + # Check the Root DN and Root DN passwd.o Same as for get_dirmgr_pw()
2043 + RES=${ ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b '' -s base \
2044 + 'objectclass=*' supportedLDAPVersion 2>&1 ; }
2045 + if (( $? )); then
2046 + if [[ ${RES} =~ credential ]]; then
2047 + Log.fatal 'Root DN passwd is invalid'
2048 + else
2049 + Log.fatal "Invalid Root DN '${STR[LDAP_ROOTDN]}'"
2050 + fi
2051 + return 66
2052 + fi
2053 + Log.verbose 'RootDN: ok RootDN passwd: ok'
1611 2054
1612 - GSSAPI_ENABLE=0
2055 + # Check if the server supports the VLV
2056 + chk_vlv_indexes || return 67
2057 + Log.verbose 'VLV indexes ... ok'
1613 2058
1614 - # assume sasl/GSSAPI is supported by the ldap server and may be used
1615 - GSSAPI_AUTH_MAY_BE_USED=1
2059 + # Check LDAP suffix
2060 + validate_suffix || return 66
2061 + Log.verbose 'LDAP suffix ... ok'
2062 + return 0
2063 +}
1616 2064
1617 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"\" -s base \"objectclass=*\" supportedSASLMechanisms | ${GREP} GSSAPI ${VERB}"
1618 - if [ $? -ne 0 ]; then
1619 - GSSAPI_AUTH_MAY_BE_USED=0
1620 - ${ECHO} " sasl/GSSAPI is not supported by this LDAP server"
2065 +Man.addFunc gssapi_setup '' '[+NAME?gssapi_setup - set up GSSAPI if necessary.]
2066 +[+DESCRIPTION?Check, whether the DS supports the SASL mechanism \bGSSAPI\b. If so, ask the user whether it should be enabled and depending on the answer ask for related Kerberos realm info. \bINT[GSSAPI_ENABLE]]\b and \bTMPF[GSSAPI_AUTH_MAY_BE_USED]]\b and optionally \bSTR[LDAP_KRB_REALM]]\b are set accordingly.]
2067 +[+SEE ALSO?\bldapsearch\b(1), \bget_ans_req()\b.]
2068 +'
2069 +function gssapi_setup {
2070 + INT[GSSAPI_ENABLE]=0
2071 + TMPF[GSSAPI_AUTH_MAY_BE_USED]=0
2072 +
2073 + ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b '' -s base 'objectclass=*' \
2074 + supportedSASLMechanisms 2>/dev/null | \
2075 + while read LINE ; do
2076 + if [[ ${LINE:0:24} == 'supportedSASLMechanisms=' && \
2077 + ${LINE:24} == 'GSSAPI' ]]
2078 + then
2079 + TMPF[GSSAPI_AUTH_MAY_BE_USED]=1
2080 + break
2081 + fi
2082 + done
2083 + if (( ! TMPF[GSSAPI_AUTH_MAY_BE_USED] )); then
2084 + Log.info 'sasl/GSSAPI is not supported by this LDAP server'
1621 2085 return
1622 2086 fi
1623 2087
1624 - get_confirm "GSSAPI is supported. Do you want to set up gssapi:(y/n)" "n"
1625 - if [ $? -eq 0 ]; then
1626 - GSSAPI_ENABLE=0
1627 - ${ECHO}
1628 - ${ECHO} "GSSAPI is not set up."
1629 - ${ECHO} "sasl/GSSAPI bind may not work if it's not set up first."
2088 + get_confirm 'GSSAPI is supported. Do you want to set up GSSAPI:(y/n)' 'n'
2089 + if (( $? )); then
2090 + INT[GSSAPI_ENABLE]=1
2091 + # get kerberos realm
2092 + typeset -u REALM=${STR[LDAP_DOMAIN]}
2093 + get_ans_req "Enter Kerberos Realm:" "${REALM}"
2094 + REALM="${ANS}" # make sure, it is upper case
2095 + STR[LDAP_KRB_REALM]="${REALM}"
1630 2096 else
1631 - GSSAPI_ENABLE=1
1632 - get_krb_realm
2097 + Log.info 'GSSAPI is not set up - ' \
2098 + 'sasl/GSSAPI bind may not work if it is not set up first'
1633 2099 fi
1634 -
1635 2100 }
1636 -#
1637 -# get_profile_name(): Enter the profile name.
1638 -#
1639 -get_profile_name()
1640 -{
1641 - # Reset Delete Old Profile since getting new profile name.
1642 - DEL_OLD_PROFILE=0
1643 2101
1644 - # Loop until valid profile name, or replace.
1645 - while :
1646 - do
1647 - # Prompt for profile name.
1648 - get_ans "Enter the profile name (h=help):" "$LDAP_PROFILE_NAME"
2102 +Man.addFunc get_profile_name '' '[+NAME?get_profile_name - Ask user for client profile name.]
2103 +[+DESCRIPTION?Ask the user for the name of the client profile to create, check whether it already exists, and if so ask whether it should be overwritten. Sets \bSTR[LDAP_PROFILE_NAME]]\b, \bTMPF[DEL_OLD_PROFILE]]\b and if the user wants to just enable shadow update \bINT[LDAP_ENABLE_SHADOW_UPDATE]]\b and \bINT[EXISTING_PROFILE]]\b.]
2104 +[+SEE ALSO?\bget_ans()\b, \bldapsearch\b(1), \bget_confirm()\b, \bget_confirm_nodef()\b, \bdisplay_msg()\b.]
2105 +'
2106 +function get_profile_name {
2107 + TMPF[DEL_OLD_PROFILE]=0 # Reset since getting new profile name
1649 2108
1650 - # Check for Help.
1651 - case "$ANS" in
1652 - [Hh] | help | Help | \?) display_msg profile_help
1653 - continue ;;
1654 - * ) ;;
1655 - esac
2109 + typeset PNAME="${STR[LDAP_PROFILE_NAME]}"
2110 + # Loop until valid profile name, or replace.
2111 + while : ; do
2112 + get_ans 'Enter the client profile name (h=help):' "${PNAME}"
2113 + case "${ANS}" in
2114 + [Hh] | help | Help | '?') display_msg 'profile_help' ; continue ;;
2115 + esac
1656 2116
1657 - # Search to see if profile name already exists.
1658 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=${ANS},ou=profile,${LDAP_BASEDN}\" -s base \"objectclass=*\" ${VERB}"
1659 - if [ $? -eq 0 ]; then
2117 + # Search to see if profile name already exists.
2118 + if ! ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
2119 + -b "cn=${ANS},ou=profile,${STR[LDAP_BASEDN]}" -s base \
2120 + 'objectclass=*' >/dev/null 2>&1
2121 + then
2122 + break # Unique profile name (does not yet exist)
2123 + fi
1660 2124
1661 - cat << EOF
2125 + Log.info 'Profile "'"${ANS}"'" already exists, it is possible to' \
2126 + 'enable shadow update now.' "${PROG}" 'will exit after shadow' \
2127 + 'update is enabled. You can also continue to overwrite the' \
2128 + 'profile or create a new one and be given the chance to enable' \
2129 + 'shadow update later.'
1662 2130
1663 -Profile '${ANS}' already exists, it is possible to enable
1664 -shadow update now. idsconfig will exit after shadow update
1665 -is enabled. You can also continue to overwrite the profile
1666 -or create a new one and be given the chance to enable
1667 -shadow update later.
2131 + get_confirm 'Just enable shadow update (y/n/h)?' 'n' \
2132 + 'enable_shadow_update_help'
2133 + if (( $? )); then
2134 + # set up credentials for shadow update
2135 + INT[LDAP_ENABLE_SHADOW_UPDATE]=1
2136 + # display alternate messages
2137 + INT[EXISTING_PROFILE]=1
2138 + break
2139 + fi
1668 2140
1669 -EOF
2141 + get_confirm_nodef \
2142 + "Are you sure you want to overwrite profile 'cn=${ANS}'?"
2143 + if (( $? )); then
2144 + TMPF[DEL_OLD_PROFILE]=1 # Replace old profile name
2145 + break
2146 + fi
2147 + done
1670 2148
1671 - MSG="Just enable shadow update (y/n/h)?"
1672 - get_confirm "$MSG" "n" "enable_shadow_update_help"
1673 - if [ $? -eq 1 ]; then
1674 - [ $DEBUG -eq 1 ] && ${ECHO} "set up shadow update"
1675 - LDAP_ENABLE_SHADOW_UPDATE=TRUE
1676 - # display alternate messages
1677 - EXISTING_PROFILE=1
1678 - # Set Profile Name.
1679 - LDAP_PROFILE_NAME=$ANS
1680 - return 0 # set up credentials for shadow update.
1681 - fi
2149 + STR[LDAP_PROFILE_NAME]="${ANS}"
2150 +}
1682 2151
1683 - get_confirm_nodef "Are you sure you want to overwrite profile cn=${ANS}?"
1684 - if [ $? -eq 1 ]; then
1685 - DEL_OLD_PROFILE=1
1686 - return 0 # Replace old profile name.
1687 - else
1688 - ${ECHO} "Please re-enter a new profile name."
1689 - fi
1690 - else
1691 - break # Unique profile name.
1692 - fi
1693 - done
1694 -
1695 - # Set Profile Name.
1696 - LDAP_PROFILE_NAME=$ANS
2152 +Man.addFunc getACIs '' '[+NAME?getACIs - get ACIs for the current base DN.]
2153 +[+DESCRIPTION?Get all ACIs for \abaseDN\a and append them to the indexed array of strings \avname\a. If \abaseDN\a is not given, \bSTR[LDAP_BASEDN]]\b will be used instead. If \ascope\a is set to \bGlobal\b this method queries for "ds-cfg-global-aci" instead of "aci" unless \bTMPF[IS_OPENDJ]]\b is \b0\b.]
2154 +[+RETURN VALUES]{
2155 + [+-1?invalid function usage.]
2156 + [+0?on success.]
2157 + [+1?an error occured when executing the ldapsearch operation.]
1697 2158 }
2159 +\n\n\avname\a [\abaseDN\a] [\ascope\a]
2160 +'
2161 +function getACIs {
2162 + set -o pipefail # wanna have the exit code of ldapsearch
2163 + [[ -z $1 ]] && Log.warn "${.sh.fun}(): invalid function usage" && \
2164 + return -1
2165 + typeset -n ACILIST=$1
2166 + typeset LINE
2167 + typeset DN="$2" ACI='aci'
2168 + [[ -z ${DN} ]] && DN="${STR[LDAP_BASEDN]}"
2169 + [[ $3 == 'Global' ]] && (( TMPF[IS_OPENDJ] )) && ACI='ds-cfg-global-aci'
1698 2170
1699 -
1700 -#
1701 -# get_srv_list(): Get the default server list.
1702 -#
1703 -get_srv_list()
1704 -{
1705 - # If LDAP_SERVER_LIST is NULL, then set, otherwise leave alone.
1706 - if [ -z "${LDAP_SERVER_LIST}" ]; then
1707 - LDAP_SERVER_LIST=`getent hosts ${IDS_SERVER} | awk '{print $1}'`
1708 - if [ ${IDS_PORT} -ne 389 ]; then
1709 - LDAP_SERVER_LIST="${LDAP_SERVER_LIST}:${IDS_PORT}"
2171 + ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b "${DN}" -s base \
2172 + 'objectclass=*' ${ACI} 2>/dev/null | \
2173 + while read LINE ; do
2174 + # NOTE: the || : is required to always get success (pipe doesn't break)
2175 + [[ ${LINE:0:${#ACI}+1} == "${ACI}=" ]] && \
2176 + ACILIST+=( "${LINE:${#ACI}+1}" ) || :
2177 + done
2178 + if (( $? )); then
2179 + Log.fatal "Unable to get aci list for '${STR[LDAP_BASEDN]}'"
2180 + return 1
1710 2181 fi
1711 - fi
1712 -
1713 - # Prompt for new LDAP_SERVER_LIST.
1714 - while :
1715 - do
1716 - get_ans "Default server list (h=help):" $LDAP_SERVER_LIST
1717 -
1718 - # If help continue, otherwise break.
1719 - case "$ANS" in
1720 - [Hh] | help | Help | \?) display_msg def_srvlist_help ;;
1721 - * ) break ;;
1722 - esac
1723 - done
1724 - LDAP_SERVER_LIST=$ANS
2182 + return 0
1725 2183 }
1726 2184
1727 -
1728 -#
1729 -# get_pref_srv(): The preferred server list (Overrides the server list)
1730 -#
1731 -get_pref_srv()
1732 -{
1733 - while :
1734 - do
1735 - get_ans "Preferred server list (h=help):" $LDAP_PREF_SRVLIST
1736 -
1737 - # If help continue, otherwise break.
1738 - case "$ANS" in
1739 - [Hh] | help | Help | \?) display_msg pref_srvlist_help ;;
1740 - * ) break ;;
1741 - esac
1742 - done
1743 - LDAP_PREF_SRVLIST=$ANS
2185 +Man.addFunc findACI '' '[+NAME?findACI - find an ACI in the given list.]
2186 +[+DESCRIPTION?Find the first ACI which matches \aregex\a in the indexed array of ACIs \avname\a. If a match occurs, print out a message using the given \aaciName\a prefixed with \ascope\a. If \ascope\a is not given or empty, \bBaseDN\b will be used instead.]
2187 +[+RETURN VALUES]{
2188 + [+0?no ACI matched.]
2189 + [+>=1?the index+1 of the ACI matched.]
1744 2190 }
1745 -
1746 -
1747 -#
1748 -# get_search_scope(): Get the search scope from the user.
1749 -#
1750 -get_search_scope()
1751 -{
1752 - [ $DEBUG -eq 1 ] && ${ECHO} "In get_search_scope()"
1753 -
1754 - _MENU_CHOICE=0
1755 - while :
1756 - do
1757 - get_ans "Choose desired search scope (one, sub, h=help): " "one"
1758 - _MENU_CHOICE=$ANS
1759 - case "$_MENU_CHOICE" in
1760 - one) LDAP_SEARCH_SCOPE="one"
1761 - return 1 ;;
1762 - sub) LDAP_SEARCH_SCOPE="sub"
1763 - return 2 ;;
1764 - h) display_msg srch_scope_help ;;
1765 - *) ${ECHO} "Please enter \"one\", \"sub\", or \"h\"." ;;
1766 - esac
1767 - done
1768 -
2191 +[+SEE ALSO?\bgetACIs()\b, \bfindACI()\b, \bfind_and_delete_ACI\b()]
2192 +\n\n\avname\a \aaciName\a \aregex\a [\ascope\a]
2193 +'
2194 +function findACI {
2195 + typeset -n LIST=$1
2196 + typeset NAME="$2" REGEX="$3" SCOPE="$4"
2197 + integer MAX=${#LIST[@]} I
2198 + [[ -z ${SCOPE} ]] && SCOPE='BaseDN'
2199 + for (( I=0; I < MAX; I++ )); do
2200 + if [[ ${LIST[${I}]} =~ ${REGEX} ]]; then
2201 + showProgress "${SCOPE} ACI '${NAME}' exists."
2202 + return $((I+1))
2203 + fi
2204 + done
2205 + return 0
1769 2206 }
1770 2207
1771 -
1772 -#
1773 -# get_cred_level(): Function to display menu to user and get the
1774 -# credential level.
1775 -#
1776 -get_cred_level()
1777 -{
1778 - [ $DEBUG -eq 1 ] && ${ECHO} "In get_cred_level()"
1779 -
1780 - _MENU_CHOICE=0
1781 - display_msg cred_level_menu
1782 - while :
1783 - do
1784 - if [ $GSSAPI_ENABLE -eq 1 ]; then
1785 - ${ECHO} '"self" is needed for GSSAPI profile'
1786 - fi
1787 - get_ans "Choose Credential level [h=help]:" "1"
1788 - _MENU_CHOICE=$ANS
1789 - case "$_MENU_CHOICE" in
1790 - 1) LDAP_CRED_LEVEL="anonymous"
1791 - return 1 ;;
1792 - 2) LDAP_CRED_LEVEL="proxy"
1793 - return 2 ;;
1794 - 3) LDAP_CRED_LEVEL="proxy anonymous"
1795 - return 3 ;;
1796 - 4) LDAP_CRED_LEVEL="self"
1797 - return 4 ;;
1798 - h) display_msg cred_lvl_help ;;
1799 - *) ${ECHO} "Please enter 1, 2, 3 or 4." ;;
1800 - esac
1801 - done
2208 +Man.addFunc allow_proxy_read_pw '' '[+NAME?allow_proxy_read_pw - add Proxy Agent read permission for password.]
2209 +[+DESCRIPTION?Add the ACI \bPROXY_ACI_NAME\b for \bSTR[LDAP_PROXYAGENT]]\b to \bSTR[LDAP_BASEDN]]\b if it not already exists.]
2210 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage PROXY_ACI_NAME ; }" '}
2211 +[+RETURN VALUES]{
2212 + [+0?on success (ACI already exists or added successfully).]
2213 + [+>= 66?a fatal error occured.]
1802 2214 }
2215 +[+SEE ALSO?\bgetACIs()\b, \bldapmodify\b(1).]
2216 +'
2217 +function allow_proxy_read_pw {
2218 + typeset ACI PATTERN TARGET
1803 2219
2220 + typeset -a LIST=( )
2221 + getACIs LIST || return 66
1804 2222
1805 -#
1806 -# srvauth_menu_handler(): Enter the Service Authentication method.
1807 -#
1808 -srvauth_menu_handler()
1809 -{
1810 - # Display Auth menu
1811 - display_msg srvauth_method_menu
2223 + PATTERN='acl[ ]+"?('"${PROXY_ACI_NAME}|${PROXY_ACI_NAME// /_}"')"?'
2224 + findACI LIST "${PROXY_ACI_NAME}" "${PATTERN}" || return 0
1812 2225
1813 - # Get a Valid choice.
1814 - while :
1815 - do
1816 - # Display appropriate prompt and get answer.
1817 - if [ $_FIRST -eq 1 ]; then
1818 - get_ans "Choose Service Authentication Method:" "1"
2226 + PATTERN='userPassword'
2227 + if (( TMPF[IS_OPENDJ] )); then
2228 + PATTERN+=' || authPassword'
2229 + # At least in OpenDJ specifying the same target as where the ACI gets
2230 + # attached is redundant wrt. the result and causes minimal overhead
2231 + TARGET=''
1819 2232 else
1820 - get_ans "Choose Service Authentication Method (0=reset):"
2233 + TARGET='(target = "ldap:///'"${STR[LDAP_BASEDN]}"'")'
1821 2234 fi
2235 +
2236 + nextFile modify $0
2237 + print '
2238 +dn: '"${STR[LDAP_BASEDN]}"'
2239 +changetype: modify
2240 +add: aci
2241 +aci: '"${TARGET}"'(targetattr = "'"${PATTERN}"'")
2242 + (
2243 + version 3.0; acl "'"${PROXY_ACI_NAME}"'";
2244 + allow (compare,read,search) userdn = "ldap:///'"${STR[LDAP_PROXYAGENT]}"'";
2245 + )
2246 +' > ${TMP[FILE]}
2247 +
2248 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
2249 + >&${TMPF[FD]} 2>&1
2250 + then
2251 + Log.fatal "Adding '${PROXY_ACI_NAME}' ACI failed"
2252 + return 66
2253 + fi
1822 2254
1823 - # Determine choice.
1824 - _MENU_CHOICE=$ANS
1825 - case "$_MENU_CHOICE" in
1826 - 1) _AUTHMETHOD="simple"
1827 - break ;;
1828 - 2) _AUTHMETHOD="sasl/DIGEST-MD5"
1829 - break ;;
1830 - 3) _AUTHMETHOD="tls:simple"
1831 - break ;;
1832 - 4) _AUTHMETHOD="tls:sasl/DIGEST-MD5"
1833 - break ;;
1834 - 5) _AUTHMETHOD="sasl/GSSAPI"
1835 - break ;;
1836 - 0) _AUTHMETHOD=""
1837 - _FIRST=1
1838 - break ;;
1839 - *) ${ECHO} "Please enter 1-5 or 0 to reset." ;;
1840 - esac
1841 - done
2255 + showProgress "ACI '${PROXY_ACI_NAME}' added."
2256 + return 0
1842 2257 }
1843 2258
1844 -
1845 -#
1846 -# auth_menu_handler(): Enter the Authentication method.
1847 -#
1848 -auth_menu_handler()
1849 -{
1850 - # Display Auth menu
1851 - display_msg auth_method_menu
1852 -
1853 - # Get a Valid choice.
1854 - while :
1855 - do
1856 - if [ $GSSAPI_ENABLE -eq 1 ]; then
1857 - ${ECHO} '"sasl/GSSAPI" is needed for GSSAPI profile'
1858 - fi
1859 - # Display appropriate prompt and get answer.
1860 - if [ $_FIRST -eq 1 ]; then
1861 - get_ans "Choose Authentication Method (h=help):" "1"
1862 - else
1863 - get_ans "Choose Authentication Method (0=reset, h=help):"
1864 - fi
1865 -
1866 - # Determine choice.
1867 - _MENU_CHOICE=$ANS
1868 - case "$_MENU_CHOICE" in
1869 - 1) _AUTHMETHOD="none"
1870 - break ;;
1871 - 2) _AUTHMETHOD="simple"
1872 - break ;;
1873 - 3) _AUTHMETHOD="sasl/DIGEST-MD5"
1874 - break ;;
1875 - 4) _AUTHMETHOD="tls:simple"
1876 - break ;;
1877 - 5) _AUTHMETHOD="tls:sasl/DIGEST-MD5"
1878 - break ;;
1879 - 6) _AUTHMETHOD="sasl/GSSAPI"
1880 - break ;;
1881 - 0) _AUTHMETHOD=""
1882 - _FIRST=1
1883 - break ;;
1884 - h) display_msg auth_help ;;
1885 - *) ${ECHO} "Please enter 1-6, 0=reset, or h=help." ;;
1886 - esac
1887 - done
2259 +Man.addFunc delete_proxy_read_pw '' '[+NAME?delete_proxy_read_pw - delete Proxy Agent read permission for password.]
2260 +[+DESCRIPTION?Remove the ACI \bPROXY_ACI_NAME\b from \bSTR[LDAP_BASEDN]]\b if such an ACI exists.]
2261 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage PROXY_ACI_NAME ; }" '}
2262 +[+RETURN VALUES]{
2263 + [+0?on success (no delete required or ACI deleted).]
2264 + [+>= 66?a fatal error occured.]
1888 2265 }
2266 +[+SEE ALSO?\bgetACIs()\b, \bget_menu_choice()\b, \bldapmodify\b(1).]
2267 +'
2268 +function delete_proxy_read_pw {
2269 + typeset PROXY_ACI='' ACI PATTERN X
1889 2270
2271 + typeset -a LIST=( )
2272 + getACIs LIST || return 66
1890 2273
1891 -#
1892 -# get_auth(): Enter the Authentication method.
1893 -#
1894 -get_auth()
1895 -{
1896 - [ $DEBUG -eq 1 ] && ${ECHO} "In get_auth()"
2274 + # Search for ACI_NAME - no findACI() because we need ALL matching ACIs
2275 + typeset -a ACILIST=( )
2276 + PATTERN='acl[ ]+"?('"${PROXY_ACI_NAME}|${PROXY_ACI_NAME// /_}"')"?'
2277 + for ACI in "${LIST[@]}" ; do
2278 + [[ ${ACI} =~ ${PATTERN} ]] && ACILIST+=( "${ACI#*=}" )
2279 + done
1897 2280
1898 - _FIRST=1 # Flag for first time.
1899 - _MENU_CHOICE=0
1900 - _AUTHMETHOD="" # Tmp method.
2281 + # We need to remove proxy agent's read access to user passwords,
2282 + # but We do not know the value of the ${LDAP_PROXYAGENT} here, so
2283 + # 1. if only one match found, delete it
2284 + # 2. if more than one matches found, ask the user which one to delete
2285 + if (( ${#ACILIST[@]} == 0 )); then
2286 + Log.warn "ACI '${PROXY_ACI_NAME}' does not exist for" \
2287 + "'${STR[LDAP_BASEDN]}'"
2288 + return 0
2289 + fi
2290 + if (( ${#ACILIST[@]} == 1 ));then
2291 + PROXY_ACI="${ACI[0]}"
2292 + else
2293 + X='
2294 +Proxy agent is not allowed to read user passwords when shadow
2295 +update is enabled. There are more than one proxy agents found.
2296 +Please select the proxy agent currently being used, so that
2297 +'"${PROG}"' can remove its read access to user passwords.
1901 2298
1902 - while :
1903 - do
1904 - # Call Menu handler
1905 - auth_menu_handler
2299 +The proxy agents are:
2300 +'
2301 + # print the list of ACIs for selection
2302 + integer I MAX
2303 + MAX=${#ACILIST[@]}
2304 + for (( I=0; I < MAX; I++ )) ; do
2305 + ACI="${ACILIST[${I}]}"
2306 + if (( ! Log.VERBOSE )); then
2307 + # older versions used
2308 + # sed -e 's|.*ldap:///.*ldap:///||' -e 's|";)||'
2309 + ACI=${ACI##*ldap:///}
2310 + ACI=${ACI%\"*}
2311 + fi
2312 + X+=${ printf '%2d: %s\n' $((I+1)) "${ACI}" ; }
2313 + done
2314 + Log.warn "${X}"
1906 2315
1907 - # Add Auth Method to list.
1908 - if [ $_FIRST -eq 1 ]; then
1909 - LDAP_AUTHMETHOD="${_AUTHMETHOD}"
1910 - _FIRST=0
1911 - else
1912 - LDAP_AUTHMETHOD="${LDAP_AUTHMETHOD};${_AUTHMETHOD}"
2316 + # ask the user to pick one
2317 + get_menu_choice "Select the proxy agent (1-${MAX}): " 1 ${MAX}
2318 + I=$(( $? - 1 ))
2319 + PROXY_ACI="${ACILIST[$I]}"
1913 2320 fi
1914 2321
1915 - # Display current Authentication Method.
1916 - ${ECHO} ""
1917 - ${ECHO} "Current authenticationMethod: ${LDAP_AUTHMETHOD}"
1918 - ${ECHO} ""
2322 + nextFile modify $0
2323 + print '
2324 +dn: '"${STR[LDAP_BASEDN]}"'
2325 +changetype: modify
2326 +delete: aci
2327 +aci: '"${PROXY_ACI}"'
2328 +' >${TMP[FILE]}
1919 2329
1920 - # Prompt for another Auth Method, or break out.
1921 - get_confirm_nodef "Do you want to add another Authentication Method?"
1922 - if [ $? -eq 0 ]; then
1923 - break;
2330 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
2331 + >&${TMPF[FD]} 2>&1
2332 + then
2333 + Log.fatal "Remove of '${PROXY_ACI_NAME}' ACI failed"
2334 + cat ${TMP[FILE]}
2335 + return 66
1924 2336 fi
1925 - done
2337 +
2338 + Log.info "Removed '${PROXY_ACI_NAME}' ACI"
2339 + return 0
1926 2340 }
1927 2341
1928 -
1929 -#
1930 -# get_followref(): Whether or not to follow referrals.
1931 -#
1932 -get_followref()
1933 -{
1934 - get_confirm "Do you want the clients to follow referrals (y/n/h)?" "n" "referrals_help"
1935 - if [ $? -eq 1 ]; then
1936 - LDAP_FOLLOWREF="TRUE"
1937 - else
1938 - LDAP_FOLLOWREF="FALSE"
1939 - fi
2342 +Man.addFunc allow_host_read_write_shadow '' '[+NAME?allow_host_read_write_shadow - add host principal read/write permission for shadow data.]
2343 +[+DESCRIPTION?Add the ACI \bHOST_ACI_NAME\b to \bSTR[LDAP_BASEDN]]\b unless it already exists.]
2344 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage HOST_ACI_NAME ; }" '}
2345 +[+RETURN VALUES]{
2346 + [+0?on success (ACI already exists or added successfully).]
2347 + [+>= 66?a fatal error occured.]
1940 2348 }
2349 +[+SEE ALSO?\bgetACIs()\b, \bldapmodify\b(1).]
2350 +'
2351 +function allow_host_read_write_shadow {
2352 + typeset ACI PATTERN TARGET=''
1941 2353
2354 + typeset -a LIST=( )
2355 + getACIs LIST || return 66
1942 2356
1943 -#
1944 -# get_timelimit(): Set the time limit. -1 is max time.
1945 -#
1946 -get_timelimit()
1947 -{
1948 - # Get current timeout value from cn=config.
1949 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=config\" -s base \"objectclass=*\" nsslapd-timelimit > ${TMPDIR}/chk_timeout 2>&1"
1950 - if [ $? -ne 0 ]; then
1951 - ${ECHO} " ERROR: Could not reach LDAP server to check current timeout!"
1952 - cleanup
1953 - exit 1
1954 - fi
1955 - CURR_TIMELIMIT=`${GREP} timelimit ${TMPDIR}/chk_timeout | cut -f2 -d=`
1956 -
1957 - get_negone_num "Enter the time limit for iDS (current=${CURR_TIMELIMIT}):" "-1"
1958 - IDS_TIMELIMIT=$NUM
1959 -}
2357 + PATTERN='acl[ ]+"?('"${HOST_ACI_NAME}|${HOST_ACI_NAME// /_}"')"?'
2358 + findACI LIST "${HOST_ACI_NAME}" "${PATTERN}" || return 0
1960 2359
2360 + (( ! TMPF[IS_OPENDJ] )) && \
2361 + TARGET='(target = "ldap:///'"${STR[LDAP_BASEDN]}"'")' # OD: redundant
1961 2362
1962 -#
1963 -# get_sizelimit(): Set the size limit. -1 is max size.
1964 -#
1965 -get_sizelimit()
1966 -{
1967 - # Get current sizelimit value from cn=config.
1968 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=config\" -s base \"objectclass=*\" nsslapd-sizelimit > ${TMPDIR}/chk_sizelimit 2>&1"
1969 - if [ $? -ne 0 ]; then
1970 - ${ECHO} " ERROR: Could not reach LDAP server to check current sizelimit!"
1971 - cleanup
1972 - exit 1
1973 - fi
1974 - CURR_SIZELIMIT=`${GREP} sizelimit ${TMPDIR}/chk_sizelimit | cut -f2 -d=`
2363 + nextFile modify $0
2364 + print '
2365 +dn: '"${STR[LDAP_BASEDN]}"'
2366 +changetype: modify
2367 +add: aci
2368 +aci: '"${TARGET}"'(targetattr = "shadowLastChange || shadowMin || shadowMax || shadowWarning || shadowInactive || shadowExpire || shadowFlag || userPassword || loginShell || homeDirectory || gecos")
2369 + (
2370 + version 3.0; acl '"${HOST_ACI_NAME}"';
2371 + allow (write,compare,read,search) authmethod = "sasl GSSAPI" and userdn = "ldap:///cn=*+ipHostNumber=*,ou=Hosts,'"${STR[LDAP_BASEDN]}"';
2372 + )
2373 +' > ${TMP[FILE]}
2374 +
2375 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
2376 + >&${TMPF[FD]} 2>&1
2377 + then
2378 + Log.fatal 'Remove of '${ACI_NAME}' ACI failed'
2379 + return 66
2380 + fi
1975 2381
1976 - get_negone_num "Enter the size limit for iDS (current=${CURR_SIZELIMIT}):" "-1"
1977 - IDS_SIZELIMIT=$NUM
2382 + showProgress "ACI '${ACI_NAME}' added."
2383 + return 0
1978 2384 }
1979 2385
1980 -
1981 -#
1982 -# get_want_crypt(): Ask user if want to store passwords in crypt?
1983 -#
1984 -get_want_crypt()
1985 -{
1986 - get_confirm "Do you want to store passwords in \"crypt\" format (y/n/h)?" "n" "crypt_help"
1987 - if [ $? -eq 1 ]; then
1988 - NEED_CRYPT="TRUE"
1989 - else
1990 - NEED_CRYPT="FALSE"
1991 - fi
2386 +Man.addFunc find_and_delete_ACI '' '[+NAME?find_and_delete_ACI - find and delete an ACI in the given list.]
2387 +[+DESCRIPTION?Find the first ACI which matches \aregex\a in the indexed array of ACIs \avname\a and delete it. If no ACI matches, the function does nothing and returns. Otherwise it tries to delete it from \bSTR[LDAP_BASEDN]]\b and prints out a message using \aaciName\a.]
2388 +[+RETURN VALUES]{
2389 + [+0?on success (no ACI matched or ACI removed successfully).]
2390 + [+66?an error occured when removing the matched ACI.]
1992 2391 }
2392 +[+SEE ALSO?\bgetACIs()\b, \bldapmodify\b(1)]
2393 +\n\n\avname\a \aaciName\a \aregex\a
2394 +'
2395 +function find_and_delete_ACI {
2396 + typeset -n LIST=$1
2397 + typeset ACI_NAME="$2" REGEX="$3" DEL='' ACI
1993 2398
2399 + for ACI in "${LIST[@]}" ; do
2400 + [[ ${ACI} =~ ${REGEX} ]] && DEL="${ACI}" && break
2401 + done
2402 + [[ -z ${DEL} ]] && return 0
1994 2403
1995 -#
1996 -# get_srv_authMethod_pam(): Get the Service Auth Method for pam_ldap from user.
1997 -#
1998 -# NOTE: This function is base on get_auth().
1999 -#
2000 -get_srv_authMethod_pam()
2001 -{
2002 - [ $DEBUG -eq 1 ] && ${ECHO} "In get_srv_authMethod_pam()"
2404 + nextFile modify "${0}-${ACI_NAME}"
2405 + print '
2406 +dn: '"${STR[LDAP_BASEDN]}"'
2407 +changetype: modify
2408 +delete: aci
2409 +aci: '"${DEL}"'
2410 +' > ${TMP[FILE]}
2003 2411
2004 - _FIRST=1 # Flag for first time.
2005 - _MENU_CHOICE=0
2006 - _AUTHMETHOD="" # Tmp method.
2007 -
2008 - while :
2009 - do
2010 - # Call Menu handler
2011 - srvauth_menu_handler
2012 -
2013 - # Add Auth Method to list.
2014 - if [ $_FIRST -eq 1 ]; then
2015 - if [ "$_AUTHMETHOD" = "" ]; then
2016 - LDAP_SRV_AUTHMETHOD_PAM=""
2017 - else
2018 - LDAP_SRV_AUTHMETHOD_PAM="pam_ldap:${_AUTHMETHOD}"
2019 - fi
2020 - _FIRST=0
2021 - else
2022 - LDAP_SRV_AUTHMETHOD_PAM="${LDAP_SRV_AUTHMETHOD_PAM};${_AUTHMETHOD}"
2412 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
2413 + >&${TMPF[FD]} 2>&1
2414 + then
2415 + Log.fatal "Remove of '${ACI_NAME}' ACI failed"
2416 + return 66
2023 2417 fi
2024 2418
2025 - # Display current Authentication Method.
2026 - ${ECHO} ""
2027 - ${ECHO} "Current authenticationMethod: ${LDAP_SRV_AUTHMETHOD_PAM}"
2028 - ${ECHO} ""
2419 + showProgress "ACI '${ACI_NAME}' deleted."
2420 + return 0
2421 +}
2029 2422
2030 - # Prompt for another Auth Method, or break out.
2031 - get_confirm_nodef "Do you want to add another Authentication Method?"
2032 - if [ $? -eq 0 ]; then
2033 - break;
2034 - fi
2035 - done
2036 -
2037 - # Check in case user reset string and exited loop.
2038 - if [ "$LDAP_SRV_AUTHMETHOD_PAM" = "" ]; then
2039 - NEED_SRVAUTH_PAM=0
2040 - fi
2423 +Man.addFunc deny_non_host_shadow_access '' '[+NAME?deny_non_host_shadow_access - add a deny non-host access to shadow data.]
2424 +[+DESCRIPTION?Add the ACI \bNON_HOST_ACI_NAME\b to \bSTR[LDAP_BASEDN]]\b unless it already exists. If it does not exists the ACI \bNON_ADMIN_ACI_NAME\b gets deleted first if available.]
2425 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage NON_HOST_ACI_NAME NON_ADMIN_ACI_NAME ; }" '}
2426 +[+RETURN VALUES]{
2427 + [+0?on success (ACI already exists or added successfully).]
2428 + [+>= 66?a fatal error occured.]
2041 2429 }
2430 +[+SEE ALSO?\bgetACIs()\b, \bfind_and_delete_ACI()\b, \bldapmodify\b(1).]
2431 +'
2432 +function deny_non_host_shadow_access {
2433 + typeset ACI PATTERN TARGET=''
2042 2434
2435 + typeset -a LIST=( )
2436 + getACIs LIST || return 66
2043 2437
2044 -#
2045 -# get_srv_authMethod_key(): Get the Service Auth Method for keyserv from user.
2046 -#
2047 -# NOTE: This function is base on get_auth().
2048 -#
2049 -get_srv_authMethod_key()
2050 -{
2051 - [ $DEBUG -eq 1 ] && ${ECHO} "In get_srv_authMethod_key()"
2438 + # If an ACI with ${NON_HOST_ACI_NAME} already exists, we are done
2439 + PATTERN='acl[ ]+"?('"${NON_HOST_ACI_NAME}|${NON_HOST_ACI_NAME// /_}"')"?'
2440 + findACI LIST "${NON_HOST_ACI_NAME}" "${PATTERN}" || return 0
2052 2441
2053 - _FIRST=1 # Flag for first time.
2054 - _MENU_CHOICE=0
2055 - _AUTHMETHOD="" # Tmp method.
2442 + # The deny_non_admin_shadow_access and deny_non_host_shadow_access ACIs
2443 + # should be mutually exclusive, so if the former exists, delete it
2444 + PATTERN='acl[ ]+"?('"${NON_ADMIN_ACI_NAME}|${NON_ADMIN_ACI_NAME// /_}"')"?'
2445 + find_and_delete_ACI LIST "${NON_ADMIN_ACI_NAME}" "${PATTERN}" || return 67
2056 2446
2057 - while :
2058 - do
2059 - # Call Menu handler
2060 - srvauth_menu_handler
2447 + (( ! TMPF[IS_OPENDJ] )) && \
2448 + TARGET='(target = "ldap:///'"${STR[LDAP_BASEDN]}"'")' # OD: redundant
2061 2449
2062 - # Add Auth Method to list.
2063 - if [ $_FIRST -eq 1 ]; then
2064 - if [ "$_AUTHMETHOD" = "" ]; then
2065 - LDAP_SRV_AUTHMETHOD_KEY=""
2066 - else
2067 - LDAP_SRV_AUTHMETHOD_KEY="keyserv:${_AUTHMETHOD}"
2068 - fi
2069 - _FIRST=0
2070 - else
2071 - LDAP_SRV_AUTHMETHOD_KEY="${LDAP_SRV_AUTHMETHOD_KEY};${_AUTHMETHOD}"
2450 + nextFile modify $0
2451 + print '
2452 +dn: '"${STR[LDAP_BASEDN]}"'
2453 +changetype: modify
2454 +add: aci
2455 +aci: '"${TARGET}"'(targetattr = "shadowLastChange || shadowMin || shadowMax ||shadowWarning || shadowInactive || shadowExpire || shadowFlag || userPassword")
2456 + (
2457 + version 3.0; acl "'"${NON_HOST_ACI_NAME}"'";
2458 + deny (write,read,search,compare) userdn != "ldap:///cn=*+ipHostNumber=*,ou=Hosts,'"${STR[LDAP_BASEDN]}"'";
2459 + )
2460 +' > ${TMP[FILE]}
2461 +
2462 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
2463 + >&${TMPF[FD]} 2>&1
2464 + then
2465 + Log.fatal "Adding ACI '${NON_HOST_ACI_NAME}' failed"
2466 + return 67
2072 2467 fi
2073 2468
2074 - # Display current Authentication Method.
2075 - ${ECHO} ""
2076 - ${ECHO} "Current authenticationMethod: ${LDAP_SRV_AUTHMETHOD_KEY}"
2077 - ${ECHO} ""
2469 + showProgress "ACI '${NON_HOST_ACI_NAME}' added."
2470 + return 0
2471 +}
2078 2472
2079 - # Prompt for another Auth Method, or break out.
2080 - get_confirm_nodef "Do you want to add another Authentication Method?"
2081 - if [ $? -eq 0 ]; then
2082 - break;
2083 - fi
2084 - done
2473 +Man.addFunc get_adminDN '' '[+NAME?get_adminDN - ask user for Admin DN.]
2474 +[+DESCRIPTION?Ask the user for the Admin DN and store it into \bSTR[LDAP_BASEDN]]\b.]
2475 +[+SEE ALSO?\bget_ans()\b.]
2476 +'
2477 +function get_adminDN {
2478 + get_ans 'Enter DN for the administrator:' \
2479 + "cn=admin,ou=profile,${STR[LDAP_BASEDN]}"
2480 + STR[LDAP_ADMINDN]="${ANS}"
2481 +}
2085 2482
2086 - # Check in case user reset string and exited loop.
2087 - if [ "$LDAP_SRV_AUTHMETHOD_KEY" = "" ]; then
2088 - NEED_SRVAUTH_KEY=0
2089 - fi
2483 +Man.addFunc get_admin_pw '' '[+NAME?get_admin_pw - ask user for Admin password]
2484 +[+DESCRIPTION?Ask the user for the Admin password and store it into \bSTR[LDAP_ADMIN_CRED]]\b.]
2485 +[+SEE ALSO?\bget_passwd()\b.]
2486 +'
2487 +function get_admin_pw {
2488 + get_passwd 'Enter passwd for the administrator:'
2489 + STR[LDAP_ADMIN_CRED]="${ANS}"
2090 2490 }
2091 2491
2492 +Man.addFunc add_admin '' '[+NAME?add_admin - Add administrator identity.]
2493 +[+DESCRIPTION?Add the \bSTR[LDAP_ADMINDN]]\b entry with the password \bSTR[LDAP_ADMIN_CRED]]\b unless it already exists.]
2494 +[+RETURN VALUES]{
2495 + [+0?on success (entry already exists or added successfully).]
2496 + [+>= 66?a fatal error occured.]
2497 +}
2498 +[+SEE ALSO?\bldapsearch\b(1), \bldapmodify\b(1).]
2499 +'
2500 +function add_admin {
2501 + if ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b "${STR[LDAP_ADMINDN]}" \
2502 + -s base 'objectclass=*' >/dev/null 2>&1
2503 + then
2504 + showProgress "Administrator identity exists."
2505 + return 0
2506 + fi
2092 2507
2093 -#
2094 -# get_srv_authMethod_cmd(): Get the Service Auth Method for passwd-cmd from user.
2095 -#
2096 -# NOTE: This function is base on get_auth().
2097 -#
2098 -get_srv_authMethod_cmd()
2099 -{
2100 - [ $DEBUG -eq 1 ] && ${ECHO} "In get_srv_authMethod_cmd()"
2508 + typeset CN="${STR[LDAP_ADMINDN]%%,*}"
2509 + CN="${CN#*=}"
2101 2510
2102 - _FIRST=1 # Flag for first time.
2103 - _MENU_CHOICE=0
2104 - _AUTHMETHOD="" # Tmp method.
2511 + nextFile add $0
2512 + print '
2513 +dn: '"${STR[LDAP_ADMINDN]}"'
2514 +cn: '"${CN}"'
2515 +sn: '"${CN}"'
2516 +objectclass: top
2517 +objectclass: person
2518 +userpassword: '"${STR[LDAP_ADMIN_CRED]}"'
2519 +' > ${TMP[FILE]}
2105 2520
2106 - while :
2107 - do
2108 - # Call Menu handler
2109 - srvauth_menu_handler
2110 -
2111 - # Add Auth Method to list.
2112 - if [ $_FIRST -eq 1 ]; then
2113 - if [ "$_AUTHMETHOD" = "" ]; then
2114 - LDAP_SRV_AUTHMETHOD_CMD=""
2115 - else
2116 - LDAP_SRV_AUTHMETHOD_CMD="passwd-cmd:${_AUTHMETHOD}"
2117 - fi
2118 - _FIRST=0
2119 - else
2120 - LDAP_SRV_AUTHMETHOD_CMD="${LDAP_SRV_AUTHMETHOD_CMD};${_AUTHMETHOD}"
2521 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
2522 + >&${TMPF[FD]} 2>&1
2523 + then
2524 + Log.fatal 'Adding administrator identity failed'
2525 + return 66
2121 2526 fi
2122 2527
2123 - # Display current Authentication Method.
2124 - ${ECHO} ""
2125 - ${ECHO} "Current authenticationMethod: ${LDAP_SRV_AUTHMETHOD_CMD}"
2126 - ${ECHO} ""
2127 -
2128 - # Prompt for another Auth Method, or break out.
2129 - get_confirm_nodef "Do you want to add another Authentication Method?"
2130 - if [ $? -eq 0 ]; then
2131 - break;
2132 - fi
2133 - done
2134 -
2135 - # Check in case user reset string and exited loop.
2136 - if [ "$LDAP_SRV_AUTHMETHOD_CMD" = "" ]; then
2137 - NEED_SRVAUTH_CMD=0
2138 - fi
2528 + showProgress 'Administrator identity added.'
2529 + return 0
2139 2530 }
2140 2531
2141 -
2142 -#
2143 -# get_srch_time(): Amount of time to search.
2144 -#
2145 -get_srch_time()
2146 -{
2147 - get_negone_num "Client search time limit in seconds (h=help):" "$LDAP_SEARCH_TIME_LIMIT" "srchtime_help"
2148 - LDAP_SEARCH_TIME_LIMIT=$NUM
2532 +Man.addFunc allow_admin_read_write_shadow '' '[+NAME?allow_admin_read_write_shadow - add Admin read/write permission for shadow, rbac and mount data.]
2533 +[+DESCRIPTION?Add the ACI \bADMIN_ACI_NAME\b to \bSTR[LDAP_BASEDN]]\b unless it already exists. Also tries to remove old similar ACIs if they exist.]
2534 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage ADMIN_ACI_NAME ; }" '}
2535 +[+RETURN VALUES]{
2536 + [+0?on success (aci already exists or addition was successfull).]
2537 + [+>= 66?a fatal error occured.]
2149 2538 }
2539 +[+SEE ALSO?\bgetACIs()\b, \bfind_and_delete_ACI()\b, \bldapmodify\b(1).]
2540 +'
2541 +function allow_admin_read_write_shadow {
2542 + typeset PERMS='write,compare,read,search,add,delete' \
2543 + ACI RBAC PATTERN TARGET=''
2150 2544
2545 + typeset -a LIST=( )
2546 + getACIs LIST || return 66
2151 2547
2152 -#
2153 -# get_prof_ttl(): The profile time to live (TTL)
2154 -#
2155 -get_prof_ttl()
2156 -{
2157 - get_negone_num "Profile Time To Live in seconds (h=help):" "$LDAP_PROFILE_TTL" "profttl_help"
2158 - LDAP_PROFILE_TTL=$NUM
2159 -}
2548 + # If the ACI already exists, we are done
2549 + PATTERN='acl[ ]+"?('"${ADMIN_ACI_NAME}|${ADMIN_ACI_NAME// /_}"')"?'
2550 + PATTERN+='.*\('"${PERMS}"'\).*'"${STR[LDAP_ADMINDN]}"
2551 + findACI LIST "${ADMIN_ACI_NAME}" "${PATTERN}" || return 0
2160 2552
2553 + # If an ACI with ${ADMIN_ACI_NAME} and "(write|write,compare,read,search)"
2554 + # and ${LDAP_ADMINDN} exists, delete it
2555 + PATTERN='acl[ ]+"?('"${ADMIN_ACI_NAME}|${ADMIN_ACI_NAME// /_}"')"?'
2556 + PATTERN+='.*\(write\).*'"${STR[LDAP_ADMINDN]}"
2557 + find_and_delete_ACI LIST "${ADMIN_ACI_NAME}" "${PATTERN}" || return 67
2161 2558
2162 -#
2163 -# get_bind_limit(): Bind time limit
2164 -#
2165 -get_bind_limit()
2166 -{
2167 - get_negone_num "Bind time limit in seconds (h=help):" "$LDAP_BIND_LIMIT" "bindlim_help"
2168 - LDAP_BIND_LIMIT=$NUM
2169 -}
2559 + PATTERN='acl[ ]+"?('"${ADMIN_ACI_NAME}|${ADMIN_ACI_NAME// /_}"')"?'
2560 + PATTERN+='.*\(write,compare,read,search\).*'"${STR[LDAP_ADMINDN]}"
2561 + find_and_delete_ACI LIST "${ADMIN_ACI_NAME}" "${PATTERN}" || return 68
2170 2562
2563 + RBAC='objectClass || uid || uidNumber || gidNumber || cn'
2564 + RBAC+=' || SolarisAttrKeyValue || SolarisAttrShortDesc'
2565 + RBAC+=' || SolarisAttrLongDesc || SolarisKernelSecurityPolicy'
2566 + RBAC+=' || SolarisProfileType || SolarisProfileId || SolarisUserQualifier'
2567 + RBAC+=' || SolarisReserved1 || SolarisReserved2'
2568 + RBAC+=' || SolarisAttrReserved1 || SolarisAttrReserved2'
2569 + RBAC+=' || SolarisProjectID || SolarisProjectName'
2570 + RBAC+=' || SolarisProjectAttr || memberUid || memberGid || description'
2571 + RBAC+=' || automountKey || automountMapName || automountInformation'
2572 + RBAC+=' || ipTnetTemplateName || ipTnetNumber'
2171 2573
2172 -######################################################################
2173 -# FUNCTIONS FOR Service Search Descriptor's START HERE.
2174 -######################################################################
2574 + (( ! TMPF[IS_OPENDJ] )) && \
2575 + TARGET='(target = "ldap:///'"${STR[LDAP_BASEDN]}"'")' # OD: redundant
2175 2576
2176 -
2177 -#
2178 -# add_ssd(): Get SSD's from user and add to file.
2179 -#
2180 -add_ssd()
2181 -{
2182 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_ssd()"
2183 -
2184 - # Enter the service id. Loop til unique.
2185 - while :
2186 - do
2187 - get_ans "Enter the service id:"
2188 - _SERV_ID=$ANS
2189 -
2190 - # Grep for name existing.
2191 - ${GREP} -i "^$ANS:" ${SSD_FILE} > /dev/null 2>&1
2192 - if [ $? -eq 1 ]; then
2193 - break
2577 + nextFile modify $0
2578 + print '
2579 +dn: '"${STR[LDAP_BASEDN]}"'
2580 +changetype: modify
2581 +add: aci
2582 +aci: '"${TARGET}"'(targetattr = "shadowLastChange || shadowMin || shadowMax || shadowWarning || shadowInactive || shadowExpire || shadowFlag || userPassword || loginShell || homeDirectory || gecos || '"${RBAC}"'")
2583 + (
2584 + version 3.0; acl "'${ADMIN_ACI_NAME}'";
2585 + allow ('"${PERMS}"') userdn = "ldap:///'"${STR[LDAP_ADMINDN]}"'";
2586 + )
2587 +' > ${TMP[FILE]}
2588 +
2589 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
2590 + >&${TMPF[FD]} 2>&1
2591 + then
2592 + Log.fatal "Adding '${ADMIN_ACI_NAME}' ACI failed"
2593 + return 69
2194 2594 fi
2195 2595
2196 - # Name exists, print message, let user decide.
2197 - ${ECHO} "ERROR: Service id ${ANS} already exists."
2198 - done
2199 -
2200 - get_ans "Enter the base:"
2201 - _BASE=$ANS
2596 + showProgress "ACI '${ADMIN_ACI_NAME}' added."
2597 + return 0
2598 +}
2202 2599
2203 - # Get the scope and verify that its one or sub.
2204 - while :
2205 - do
2206 - get_ans "Enter the scope:"
2207 - _SCOPE=$ANS
2208 - case `${ECHO} ${_SCOPE} | tr '[A-Z]' '[a-z]'` in
2209 - one) break ;;
2210 - sub) break ;;
2211 - *) ${ECHO} "${_SCOPE} is Not valid - Enter 'one' or 'sub'" ;;
2212 - esac
2213 - done
2214 -
2215 - # Build SSD to add to file.
2216 - _SSD="${_SERV_ID}:${_BASE}?${_SCOPE}"
2217 -
2218 - # Add the SSD to the file.
2219 - ${ECHO} "${_SSD}" >> ${SSD_FILE}
2600 +Man.addFunc deny_non_admin_shadow_access '' '[+NAME?deny_non_admin_shadow_access - add a deny Admin access to shadow data.]
2601 +[+DESCRIPTION?Add the ACI \bNON_ADMIN_ACI_NAME\b to \bSTR[LDAP_BASEDN]]\b unless it already exists. If it does not exists the ACI \bNON_HOST_ACI_NAME\b gets deleted first if available.]
2602 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage NON_ADMIN_ACI_NAME NON_HOST_ACI_NAME ; }" '}
2603 +[+RETURN VALUES]{
2604 + [+0?on success (ACI already exists or added successfully).]
2605 + [+>= 66?a fatal error occured.]
2220 2606 }
2607 +[+SEE ALSO?\bgetACIs()\b, \bfind_and_delete_ACI()\b, \bldapmodify\b(1).]
2608 +'
2609 +function deny_non_admin_shadow_access {
2610 + typeset TARGET=''
2611 + typeset -a LIST=( )
2612 + getACIs LIST || return 66
2221 2613
2614 + # If the ACI already exists, we are done
2615 + PATTERN='acl[ ]+"?('"${NON_ADMIN_ACI_NAME}|${NON_ADMIN_ACI_NAME// /_}"')"?'
2616 + findACI LIST "${NON_ADMIN_ACI_NAME}" "${PATTERN}" || return 0
2222 2617
2223 -#
2224 -# delete_ssd(): Delete a SSD from the list.
2225 -#
2226 -delete_ssd()
2227 -{
2228 - [ $DEBUG -eq 1 ] && ${ECHO} "In delete_ssd()"
2618 + # The deny_non_admin_shadow_access and deny_non_host_shadow_access ACIs
2619 + # should be mutually exclusive, so if the latter exists, delete it
2620 + PATTERN='acl[ ]+"?('"${NON_HOST_ACI_NAME}|${NON_HOST_ACI_NAME// /_}"')"?'
2621 + find_and_delete_ACI LIST "${NON_HOST_ACI_NAME}" "${PATTERN}" || return 67
2229 2622
2230 - # Get service id name from user for SSD to delete.
2231 - get_ans_req "Enter service id to delete:"
2623 + (( ! TMPF[IS_OPENDJ] )) && \
2624 + TARGET='(target = "ldap:///'"${STR[LDAP_BASEDN]}"'")' # OD: redundant
2232 2625
2233 - # Make sure service id exists.
2234 - ${GREP} "$ANS" ${SSD_FILE} > /dev/null 2>&1
2235 - if [ $? -eq 1 ]; then
2236 - ${ECHO} "Invalid service id: $ANS not present in list."
2237 - return
2238 - fi
2626 + nextFile modify $0
2627 + print '
2628 +dn: '"${STR[LDAP_BASEDN]}"'
2629 +changetype: modify
2630 +add: aci
2631 +aci: '"${TARGET}"'(targetattr = "shadowLastChange || shadowMin || shadowMax || shadowWarning || shadowInactive || shadowExpire || shadowFlag || userPassword")
2632 + (
2633 + version 3.0; acl "'"${NON_ADMIN_ACI_NAME}"'";
2634 + deny (write,read,search,compare,add,delete) userdn != "ldap:///'"${STR[LDAP_ADMINDN]}"'";
2635 + )
2636 +' > ${TMP[FILE]}
2637 +
2638 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
2639 + >&${TMPF[FD]} 2>&1
2640 + then
2641 + Log.fatal "Adding '${NON_ADMIN_ACI_NAME}' ACI failed"
2642 + ${CAT} ${TMP[FILE]}
2643 + return 68
2644 + fi
2239 2645
2240 - # Create temporary back SSD file.
2241 - cp ${SSD_FILE} ${SSD_FILE}.bak
2242 - if [ $? -eq 1 ]; then
2243 - ${ECHO} "ERROR: could not create file: ${SSD_FILE}.bak"
2244 - exit 1
2245 - fi
2646 + showProgress "ACI '${NON_ADMIN_ACI_NAME}' added."
2647 + return 0
2648 +}
2246 2649
2247 - # Use ${GREP} to remove the SSD. Read from temp file
2248 - # and write to the orig file.
2249 - ${GREP} -v "$ANS" ${SSD_FILE}.bak > ${SSD_FILE}
2650 +Man.addFunc setup_shadow_update '' '[+NAME?setup_shadow_update - set up shadow update.]
2651 +[+DESCRIPTION?Check whether the profile \bSTR[LDAP_PROFILE_NAME]]\b for \bSTR[LDAP_BASEDN]]\b exists. If not simply notify the user and return. Otherwise check whether the profile uses authenticationMethod "GSSAPI" and credentialLevel "self". If so ask the user whether to use host or "Admin" user principal for shadow updates and collect the related info. Sets \bINT[NEED_HOSTACL]]\b if the host principal should be used for shadow update (requires that \bTMPF[GSSAPI_AUTH_MAY_BE_USED]]\b is already set).]
2652 +[+RETURN VALUES]{
2653 + [+0?on success.]
2654 + [+>= 66? a fatal error occured.]
2250 2655 }
2656 +[+SEE ALSO?\bldapsearch\b(1), \bget_confirm()\b, \bdelete_proxy_read_pw()\b, \ballow_host_read_write_shadow()\b, \bdeny_non_host_shadow_access()\b, \bget_adminDN()\b, \bget_admin_pw()\b, \badd_admin()\b, \ballow_admin_read_write_shadow()\b, \bdeny_non_admin_shadow_access()\b.]
2657 +'
2658 +function setup_shadow_update {
2659 + # get content of the profile
2660 + integer CN=0 GSSAPI=0 SELF=0
2661 + typeset -l LINE
2251 2662
2663 + ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
2664 + -b "cn=${STR[LDAP_PROFILE_NAME]},ou=profile,${STR[LDAP_BASEDN]}" \
2665 + -s base 'objectclass=*' 2>/dev/null | \
2666 + while read LINE ; do
2667 + [[ ${LINE:0:3} == 'cn=' ]] && CN=1
2668 + [[ ${LINE:0:21} == 'authenticationmethod=' && ${LINE:21} == 'GSSAPI' ]]\
2669 + && GSSAPI=1
2670 + [[ ${LINE:0:16} == 'credentiallevel=' && ${LINE:16} == 'self' ]] \
2671 + && SELF=1
2672 + done
2673 + if (( ! CN )); then
2674 + Log.verbose "Profile '${STR[LDAP_PROFILE_NAME]}' does not exist"
2675 + return 0
2676 + fi
2252 2677
2253 -#
2254 -# modify_ssd(): Allow user to modify a SSD.
2255 -#
2256 -modify_ssd()
2257 -{
2258 - [ $DEBUG -eq 1 ] && ${ECHO} "In modify_ssd()"
2678 + # If authenticationMethod has 'GSSAPI' and credentialLevel
2679 + # has 'self', ask to use the host principal for shadow update
2680 + if (( TMPF[GSSAPI_AUTH_MAY_BE_USED] && GSSAPI && SELF )); then
2681 + INT[NEED_HOSTACL]=1
2682 + fi
2683 + Log.verbose "NEED_HOSTACL = ${INT[NEED_HOSTACL]}"
2259 2684
2260 - # Prompt user for service id.
2261 - get_ans_req "Enter service id to modify:"
2262 -
2263 - # Put into temp _LINE.
2264 - _LINE=`${GREP} "^$ANS:" ${SSD_FILE}`
2265 - if [ "$_LINE" = "" ]; then
2266 - ${ECHO} "Invalid service id: $ANS"
2267 - return
2268 - fi
2685 + if (( INT[NEED_HOSTACL] )); then
2686 + get_confirm 'Use host principal for shadow data update (y/n/h)?' 'y' \
2687 + 'use_host_principal_help'
2688 + if (( $? )); then
2689 + delete_proxy_read_pw || return 66
2690 + allow_host_read_write_shadow || return 67
2691 + deny_non_host_shadow_access || return 68
2692 + Log.info 'Shadow update has been enabled'
2693 + else
2694 + Log.warn 'Shadow update may not work'
2695 + fi
2696 + return 0
2697 + fi
2269 2698
2270 - # Display current filter for user to see.
2271 - ${ECHO} ""
2272 - ${ECHO} "Current SSD: $_LINE"
2273 - ${ECHO} ""
2274 -
2275 - # Get the defaults.
2276 - _CURR_BASE=`${ECHO} $_LINE | cut -d: -f2 | cut -d'?' -f 1`
2277 - _CURR_SCOPE=`${ECHO} $_LINE | cut -d: -f2 | cut -d'?' -f 2`
2699 + get_confirm 'Add the administrator identity (y/n/h)?' 'y' \
2700 + 'add_admin_cred_help'
2701 + if (( $? )); then
2702 + get_adminDN
2703 + get_admin_pw
2704 + add_admin || return 69
2705 + delete_proxy_read_pw || return 66
2706 + allow_admin_read_write_shadow || return 70
2707 + deny_non_admin_shadow_access || return 71
2708 + Log.info 'Shadow update has been enabled'
2709 + else
2710 + Log.warn 'No administrator identity specified, shadow update may not' \
2711 + 'work'
2712 + fi
2713 + return 0
2714 +}
2278 2715
2279 - # Create temporary back SSD file.
2280 - cp ${SSD_FILE} ${SSD_FILE}.bak
2281 - if [ $? -eq 1 ]; then
2282 - ${ECHO} "ERROR: could not create file: ${SSD_FILE}.bak"
2283 - cleanup
2284 - exit 1
2285 - fi
2716 +Man.addFunc get_srv_list '' '[+NAME?get_srv_list - Ask user for default server list.]
2717 +[+DESCRIPTION?Ask the user for the default server list and store it into \bSTR[LDAP_SERVER_LIST]]\b.]
2718 +[+SEE ALSO?\bget_ans()\b, \bdisplay_msg()\b.]
2719 +'
2720 +function get_srv_list {
2721 + # If LDAP_SERVER_LIST is NULL, then set, otherwise leave alone
2722 + if [[ -z ${STR[LDAP_SERVER_LIST]} ]]; then
2723 + ANS=${ ${GETENT} hosts ${STR[DS_HOST]} ; }
2724 + STR[LDAP_SERVER_LIST]=${ANS%%[[:space:]]*}
2725 + if (( INT[DS_PORT] != 389 )); then
2726 + STR[LDAP_SERVER_LIST]="${STR[LDAP_SERVER_LIST]}:${INT[DS_PORT]}"
2727 + fi
2728 + fi
2286 2729
2287 - # Removed the old line.
2288 - ${GREP} -v "^$ANS:" ${SSD_FILE}.bak > ${SSD_FILE} 2>&1
2289 -
2290 - # New Entry
2291 - _SERV_ID=$ANS
2292 - get_ans_req "Enter the base:" "$_CURR_BASE"
2293 - _BASE=$ANS
2294 - get_ans_req "Enter the scope:" "$_CURR_SCOPE"
2295 - _SCOPE=$ANS
2730 + while : ; do
2731 + get_ans 'Default server list (h=help):' "${STR[LDAP_SERVER_LIST]}"
2732 + case "${ANS}" in
2733 + [Hh] | help | Help | '?') display_msg 'def_srvlist_help' ;;
2734 + * ) break ;;
2735 + esac
2736 + done
2737 + STR[LDAP_SERVER_LIST]="${ANS}"
2738 +}
2296 2739
2297 - # Build the new SSD.
2298 - _SSD="${_SERV_ID}:${_BASE}?${_SCOPE}"
2740 +Man.addFunc get_pref_srv '' '[+NAME?get_pref_srv - Ask user for preferred server list.]
2741 +[+DESCRIPTION?Ask the user for the preferred server list and store it into \bSTR[LDAP_PREF_SRVLIST]]\b (overrides the server list).]
2742 +[+SEE ALSO?\bget_ans()\b, \bdisplay_msg()\b.]
2743 +'
2744 +function get_pref_srv {
2745 + while : ; do
2746 + get_ans 'Preferred server list (h=help):' "${STR[LDAP_PREF_SRVLIST]}"
2747 + case "${ANS}" in
2748 + [Hh] | help | Help | '?') display_msg 'pref_srvlist_help' ;;
2749 + * ) break ;;
2750 + esac
2751 + done
2752 + STR[LDAP_PREF_SRVLIST]="${ANS}"
2753 +}
2299 2754
2300 - # Add the SSD to the file.
2301 - ${ECHO} "${_SSD}" >> ${SSD_FILE}
2755 +Man.addFunc get_search_scope '' '[+NAME?get_search_scope - Ask user for search scope.]
2756 +[+DESCRIPTION?Ask the user for the search scope and store it into \bSTR[LDAP_SEARCH_SCOPE]]\b.]
2757 +[+RETURN VALUES]{
2758 + [+1?search scope "one" selected.]
2759 + [+2?search scope "sub" selected.]
2302 2760 }
2761 +[+SEE ALSO?\bget_ans()\b, \bdisplay_msg()\b.]
2762 +'
2763 +function get_search_scope {
2764 + integer RES
2765 + get_menu_choice 'Choose desired search scope (1=one, 2=sub, h=help): ' \
2766 + 1 2 1 srch_scope_help
2767 + (( $? == 2 )) && { STR[LDAP_SEARCH_SCOPE]='sub' ; return 2 ; }
2768 + STR[LDAP_SEARCH_SCOPE]='one'
2769 + return 1
2770 +}
2303 2771
2772 +Man.addFunc get_cred_level '' '[+NAME?get_cred_level - Ask user for credential level.]
2773 +[+DESCRIPTION?Ask the user for the client credential level to use and store it into \bSTR[LDAP_CRED_LEVEL]]\b.]
2774 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage CRED_LEVELS STR ; }" '}
2775 +[+RETURN VALUES?The index wrt. \bCRED_LEVELS\b of the selected credential level \b+1\b.]
2776 +[+SEE ALSO?\bget_ans()\b, \bdisplay_msg()\b.]
2777 +'
2778 +function get_cred_level {
2779 + integer RES
2780 + typeset PROMPT=''
2781 + (( INT[GSSAPI_ENABLE] )) && PROMPT='"self" is needed for GSSAPI profile.\n'
2782 + PROMPT+='Choose Credential level (identity) [h=help]:'
2304 2783
2305 -#
2306 -# display_ssd(): Display the current SSD list.
2307 -#
2308 -display_ssd()
2309 -{
2310 - [ $DEBUG -eq 1 ] && ${ECHO} "In display_ssd()"
2784 + get_menu_choice "${PROMPT}" 1 4 1 'cred_lvl_help' 'cred_level_menu'
2785 + RES=$?
2786 + STR[LDAP_CRED_LEVEL]="${CRED_LEVELS[RES-1]}"
2787 + return ${RES}
2788 +}
2311 2789
2312 - ${ECHO} ""
2313 - ${ECHO} "Current Service Search Descriptors:"
2314 - ${ECHO} "=================================="
2315 - cat ${SSD_FILE}
2316 - ${ECHO} ""
2317 - ${ECHO} "Hit return to continue."
2318 - read __A
2790 +Man.addFunc get_auth '' '[+NAME?get_auth - ask user for authentication methods.]
2791 +[+DESCRIPTION?Ask the user for authentication methods to enable and store them as a semicolon separated list into \bSTR[LDAP_AUTHMETHOD | LDAP_SRV_AUTHMETHOD_{PAM|KEY|CMD}}]]\b and set \bINT[NEED_SRVAUTH_{PAM|KEY|CMD}]]\b to 0 depending on the given \atype\a (either "client", "pam_ldap", "keyserv", or "passwd-cmd") and selected methods.]
2792 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage AUTH_METHODS STR ; }" '}
2793 +[+RETURN VALUES]{
2794 + [+0?on success.]
2795 + [+-1?if an invalid \atype\a was given.]
2319 2796 }
2797 +[+SEE ALSO?\bget_menu_choice()\b, \bget_confirm_nodef()\b.]
2798 +\n\n\atype\a
2799 +'
2800 +function get_auth {
2801 + typeset TYPE=$1 VNAME HELPTAG MENU
2802 + integer RES MAX=${#AUTH_METHODS[@]} OFFSET=0
2803 + typeset -a SELECTED=( )
2804 + typeset -u UTYPE=${TYPE}
2320 2805
2806 + case "${TYPE}" in
2807 + client) VNAME=LDAP_AUTHMETHOD ; OFFSET=1 ; UTYPE='DEFAULT' ;;
2808 + pam_ldap) VNAME=LDAP_SRV_AUTHMETHOD_PAM ;;
2809 + keyserv) VNAME=LDAP_SRV_AUTHMETHOD_KEY ;;
2810 + passwd-cmd) VNAME=LDAP_SRV_AUTHMETHOD_CMD ;;
2811 + *) print -u2 "${.sh.fun}() bug: invalid type argument" && return -1 ;;
2812 + esac
2813 +
2814 + typeset ASK='' VAL='' M=''
2815 + if (( OFFSET )); then
2816 + # client
2817 + (( INT[GSSAPI_ENABLE] )) && \
2818 + ASK='"sasl/GSSAPI" is needed for GSSAPI profile.\n'
2819 + ASK+='Choose DEFAULT authentication (bind) method (0=reset, h=help):'
2820 + MENU='auth_method_menu'
2821 + HELPTAG='auth_help'
2822 + else
2823 + ASK="Choose ${UTYPE} authentication (bind) method (0=reset, h=help):"
2824 + (( MAX-- ))
2825 + MENU='srvauth_method_menu'
2826 + HELPTAG='srvauth_help'
2827 + fi
2321 2828
2322 -#
2323 -# prompt_ssd(): Get SSD's from user.
2324 -#
2325 -prompt_ssd()
2326 -{
2327 - [ $DEBUG -eq 1 ] && ${ECHO} "In prompt_ssd()"
2328 - # See if user wants SSD's?
2329 - get_confirm "Do you wish to setup Service Search Descriptors (y/n/h)?" "n" "ssd_help"
2330 - [ "$?" -eq 0 ] && return
2829 + while : ; do
2830 + get_menu_choice "${ASK}" 0 ${MAX} 1 ${HELPTAG} ${MENU}
2831 + RES=$?
2832 + if (( RES )); then
2833 + M=${AUTH_METHODS[RES - OFFSET]}
2834 + # avoid doubles
2835 + [[ ${VAL} != ~(E)[ ]${M}[ ] ]] && SELECTED+=( ${M} )
2836 + VAL=" ${SELECTED[@]} "
2837 + M=${VAL// /\;}
2838 + M=${M#\;}
2839 + else
2840 + typeset -a SELECTED=( ) # reset
2841 + VAL=''
2842 + M=''
2843 + fi
2844 + print && Log.info "Current authentication method(s): ${M%\;}\n"
2331 2845
2332 - # Display menu for SSD choices.
2333 - while :
2334 - do
2335 - display_msg prompt_ssd_menu
2336 - get_ans "Enter menu choice:" "Quit"
2337 - case "$ANS" in
2338 - [Aa] | add) add_ssd ;;
2339 - [Dd] | delete) delete_ssd ;;
2340 - [Mm] | modify) modify_ssd ;;
2341 - [Pp] | print | display) display_ssd ;;
2342 - [Xx] | reset | clear) reset_ssd_file ;;
2343 - [Hh] | Help | help) display_msg ssd_menu_help
2344 - ${ECHO} " Press return to continue."
2345 - read __A ;;
2346 - [Qq] | Quit | quit) return ;;
2347 - *) ${ECHO} "Invalid choice: $ANS please re-enter from menu." ;;
2348 - esac
2349 - done
2846 + get_confirm_nodef "Do you want to add another ${UTYPE} authentication method (y/n)?" \
2847 + && break
2848 + done
2849 + M=${M%\;}
2850 + if (( ! OFFSET )); then
2851 + M=${M//\;/\;${TYPE}:}
2852 + if [[ -n ${M} ]]; then
2853 + STR[${VNAME}]="${TYPE}:${M}"
2854 + else
2855 + STR[${VNAME}]=''
2856 + INT[NEED_SRVAUTH_${TYPE##*_}]=0
2857 + fi
2858 + else
2859 + STR[${VNAME}]="${M}"
2860 + fi
2861 + Log.verbose "Selected ${UTYPE} authentication methods: '${STR[${VNAME}]}'"
2862 + return 0
2350 2863 }
2351 2864
2865 +Man.addFunc get_followref '' '[+NAME?get_followref - Ask user whether or not to follow referrals.]
2866 +[+DESCRIPTION?Ask the user whether the client should follow referrals. Result gets stored into \bINT[LDAP_FOLLOWREF]]\b.]
2867 +[+SEE ALSO?\bget_confirm()\b, \bldapclient\b(1M).]
2868 +'
2869 +function get_followref {
2870 + get_confirm 'Do you want the clients to follow referrals (y/n/h)?' 'n' \
2871 + 'referrals_help'
2872 + INT[LDAP_FOLLOWREF]=$?
2873 +}
2352 2874
2353 -#
2354 -# reset_ssd_file(): Blank out current SSD file.
2355 -#
2356 -reset_ssd_file()
2357 -{
2358 - [ $DEBUG -eq 1 ] && ${ECHO} "In reset_ssd_file()"
2359 -
2360 - rm -f ${SSD_FILE}
2361 - touch ${SSD_FILE}
2875 +Man.addFunc get_timelimit '' '[+NAME?get_timelimit - Ask user for search time limit.]
2876 +[+DESCRIPTION?Ask the user for the max. time allowed to process a search operation and store it into \bINT[DS_TIMELIMIT]]\b.]
2877 +[+RETURN VALUES]{
2878 + [+0?on success.]
2879 + [+>= 66?a fatal error occured.]
2362 2880 }
2881 +[+SEE ALSO?\bis_numeric()\b, \bget_negone_num()\b.]
2882 +'
2883 +function get_timelimit {
2884 + typeset NAME='nsslapd-timelimit' VAL=''
2885 + (( TMPF[IS_OPENDJ] )) && NAME='ds-cfg-time-limit' # min val = 0
2363 2886
2887 + # Get current timeout value from cn=config
2888 + ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b 'cn=config' -s base \
2889 + 'objectclass=*' "${NAME}" 2>/dev/null | \
2890 + while read LINE; do
2891 + if [[ ${LINE%%=*} == ${NAME} ]]; then
2892 + VAL=${LINE#*=}
2893 + break
2894 + fi
2895 + done
2896 + if [[ -z ${VAL} ]]; then
2897 + Log.fatal 'Unable to check current search processing timeout of the DS'
2898 + return 66
2899 + fi
2900 + VAL=${VAL%%[[:space:]]*}
2901 + is_numeric ${VAL} && NUM=${VAL} || NUM=INT[DS_TIMELIMIT]
2902 +
2903 + get_negone_num "Enter the DS search processing time limit in seconds (current=${NUM})" \
2904 + '30'
2905 + (( TMPF[IS_OPENDJ] && NUM < 0 )) && NUM=0 # unlimited
2364 2906
2365 -#
2366 -# create_ssd_file(): Create a temporary file for SSD's.
2367 -#
2368 -create_ssd_file()
2369 -{
2370 - [ $DEBUG -eq 1 ] && ${ECHO} "In create_ssd_file()"
2907 + INT[DS_TIMELIMIT]=${NUM}
2908 + return 0
2909 +}
2371 2910
2372 - # Build a list of SSD's and store in temp file.
2373 - ${GREP} "LDAP_SERV_SRCH_DES=" ${INPUT_FILE} | \
2374 - sed 's/LDAP_SERV_SRCH_DES=//' \
2375 - > ${SSD_FILE}
2911 +Man.addFunc get_sizelimit '' '[+NAME?get_sizelimit - Ask user for search size limit.]
2912 +[+DESCRIPTION?Ask the user for the max. number of entries to return for a single search operation and store it into \bINT[DS_SIZELIMIT]]\b.]
2913 +[+RETURN VALUES]{
2914 + [+0?on success.]
2915 + [+>= 66?a fatal error occured.]
2376 2916 }
2917 +[+SEE ALSO?\bis_numeric()\b, \bget_negone_num()\b.]
2918 +'
2919 +function get_sizelimit {
2920 + typeset NAME='nsslapd-sizelimit' VAL=''
2921 + (( TMPF[IS_OPENDJ] )) && NAME='ds-cfg-size-limit' # min val = 0
2377 2922
2923 + # Get current search sizelimit
2924 + ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b 'cn=config' -s base \
2925 + 'objectclass=*' "${NAME}" 2>/dev/null | \
2926 + while read LINE; do
2927 + if [[ ${LINE%%=*} == ${NAME} ]]; then
2928 + VAL=${LINE#*=}
2929 + break
2930 + fi
2931 + done
2932 + if [[ -z ${VAL} ]]; then
2933 + Log.fatal 'Unable to check current search entry result limit of the DS'
2934 + return 66
2935 + fi
2936 + is_numeric ${VAL} && NUM=${VAL} || NUM=INT[DS_SIZELIMIT]
2378 2937
2379 -#
2380 -# ssd_2_config(): Append the SSD file to the output file.
2381 -#
2382 -ssd_2_config()
2383 -{
2384 - [ $DEBUG -eq 1 ] && ${ECHO} "In ssd_2_config()"
2385 -
2386 - # Convert to config file format using sed.
2387 - sed -e "s/^/LDAP_SERV_SRCH_DES=/" ${SSD_FILE} >> ${OUTPUT_FILE}
2938 + get_negone_num "Enter max. entries per search the DS returns (current=${NUM})" '1000'
2939 + (( TMPF[IS_OPENDJ] && NUM < 0 )) && NUM=0 # unlimited
2940 + INT[DS_SIZELIMIT]=${NUM}
2941 + return 0
2388 2942 }
2389 2943
2944 +Man.addFunc get_want_crypt '' '[+NAME?get_want_crypt - Ask user whether to store passwords in crypt.]
2945 +[+DESCRIPTION?Ask the user whether the default password storage scheme should be set to "CRYPT" and stores the result into \bINT[NEED_CRYPT]]\b.]
2946 +[+SEE ALSO?\bget_confirm()\b.]
2947 +'
2948 +function get_want_crypt {
2949 + get_confirm 'Do you want to store passwords in "CRYPT" formats (y/n/h)?' \
2950 + 'n' 'crypt_help'
2951 + INT[NEED_CRYPT]=$?
2952 +}
2390 2953
2391 -#
2392 -# ssd_2_profile(): Add SSD's to the GEN_CMD string.
2393 -#
2394 -ssd_2_profile()
2395 -{
2396 - [ $DEBUG -eq 1 ] && ${ECHO} "In ssd_2_profile()"
2954 +Man.addFunc get_srch_time '' '[+NAME?get_srch_time - Ask user for client search time limit.]
2955 +[+DESCRIPTION?Ask the user for the max. time in seconds a client waits for a search result and store it into \bINT[LDAP_SEARCH_TIME_LIMIT]]\b.]
2956 +[+SEE ALSO?\bget_negone_num()\b, \bldapclient\b(1M).]
2957 +'
2958 +function get_srch_time {
2959 + get_negone_num 'Client search time limit in seconds (h=help):' \
2960 + ${INT[LDAP_SEARCH_TIME_LIMIT]} 'srchtime_help'
2961 + INT[LDAP_SEARCH_TIME_LIMIT]=${NUM}
2962 +}
2397 2963
2398 - GEN_TMPFILE=${TMPDIR}/ssd_tmpfile
2399 - touch ${GEN_TMPFILE}
2400 -
2401 - # Add and convert each SSD to string.
2402 - while read SSD_LINE
2403 - do
2404 - ${ECHO} " -a \"serviceSearchDescriptor=${SSD_LINE}\"\c" >> ${GEN_TMPFILE}
2405 - done <${SSD_FILE}
2406 -
2407 - # Add SSD's to GEN_CMD.
2408 - GEN_CMD="${GEN_CMD} `cat ${GEN_TMPFILE}`"
2964 +Man.addFunc get_prof_ttl '' '[+NAME?get_prof_ttl - Ask user for client profile time to live (TTL).]
2965 +[+DESCRIPTION?Ask the user for the max. time in seconds a client may cache its profile before refreshing again and store it into \bINT[LDAP_PROFILE_TTL]]\b.]
2966 +[+SEE ALSO?\bget_negone_num()\b, \bldapclient\b(1M).]
2967 +'
2968 +function get_prof_ttl {
2969 + get_negone_num 'Client Profile Time To Live in seconds (h=help):' \
2970 + ${INT[LDAP_PROFILE_TTL]} 'profttl_help'
2971 + INT[LDAP_PROFILE_TTL]=${NUM}
2409 2972 }
2410 2973
2411 -#
2412 -# get_adminDN(): Get the admin DN.
2413 -#
2414 -get_adminDN()
2415 -{
2416 - LDAP_ADMINDN="cn=admin,ou=profile,${LDAP_BASEDN}" # default
2417 - get_ans "Enter DN for the administrator:" "$LDAP_ADMINDN"
2418 - LDAP_ADMINDN=$ANS
2419 - [ $DEBUG -eq 1 ] && ${ECHO} "LDAP_ADMINDN = $LDAP_ADMINDN"
2974 +Man.addFunc get_bind_limit '' '[+NAME?get_bind_limit - Ask user for client bind time limit.]
2975 +[+DESCRIPTION?Ask the user for the max. time in seconds a client may try to bind to the server and store it into \bINT[LDAP_BIND_LIMIT]]\b.]
2976 +[+SEE ALSO?\bget_negone_num()\b, \bldapclient\b(1M).]
2977 +'
2978 +function get_bind_limit {
2979 + get_negone_num 'Client bind time limit in seconds (h=help):' \
2980 + ${INT[LDAP_BIND_LIMIT]} 'bindlim_help'
2981 + INT[LDAP_BIND_LIMIT]=${NUM}
2420 2982 }
2421 2983
2422 -#
2423 -# get_admin_pw(): Get the admin passwd.
2424 -#
2425 -get_admin_pw()
2426 -{
2427 - get_passwd "Enter passwd for the administrator:"
2428 - LDAP_ADMIN_CRED=$ANS
2429 - [ $DEBUG -eq 1 ] && ${ECHO} "LDAP_ADMIN_CRED = $LDAP_ADMIN_CRED"
2984 +Man.addFunc get_want_shadow_update '' '[+NAME?get_want_shadow_update - Ask user whether to enable shadow update.]
2985 +[+DESCRIPTION?Ask the user whether to enable shadow update. Set \bINT[LDAP_ENABLE_SHADOW_UPDATE]]\b to 0 if not desired, to 1 otherwise.]
2986 +[+SEE ALSO?\bget_confirm()\b.]
2987 +'
2988 +function get_want_shadow_update {
2989 + get_confirm 'Do you want to enable shadow update (y/n/h)?' 'n' \
2990 + 'enable_shadow_update_help'
2991 + INT[LDAP_ENABLE_SHADOW_UPDATE]=$?
2430 2992 }
2431 2993
2432 -#
2433 -# add_admin(): Add an admin entry for nameservice for updating shadow data.
2434 -#
2435 -add_admin()
2436 -{
2437 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_admin()"
2994 + ######################################################################
2995 + # FUNCTIONS FOR Service Search Descriptor's START HERE.
2996 + ######################################################################
2997 +Man.addFunc add_ssd '' '[+NAME?add_ssd - Ask user for SSD to add.]
2998 +[+DESCRIPTION?Ask the user for the ID:BASE:SCOPE and add it to \bSSD\b list.]
2999 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage SSD ; }" '}
3000 +[+SEE ALSO?\bget_ans\b, \bget_ans_req()\b.]
3001 +'
3002 +function add_ssd {
3003 + typeset ID='' BASE='' X
3004 + typeset -l SCOPE=''
3005 + integer FOUND
2438 3006
2439 - # Check if the admin user already exists.
2440 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_ADMINDN}\" -s base \"objectclass=*\" ${VERB}"
2441 - if [ $? -eq 0 ]; then
2442 - MSG="Administrator ${LDAP_ADMINDN} already exists."
2443 - if [ $EXISTING_PROFILE -eq 1 ]; then
2444 - ${ECHO} " NOT ADDED: $MSG"
2445 - else
2446 - ${ECHO} " ${STEP}. $MSG"
2447 - STEP=`expr $STEP + 1`
2448 - fi
2449 - return 0
2450 - fi
3007 + while : ; do
3008 + get_ans 'Enter the service name (e.g. passwd):'
3009 + [[ -z ${ANS} ]] && return
3010 + [[ ${ANS} =~ [:] ]] && print 'Invalid service name' && continue
2451 3011
2452 - # Get cn and sn names from LDAP_ADMINDN.
2453 - cn_tmp=`${ECHO} ${LDAP_ADMINDN} | cut -f1 -d, | cut -f2 -d=`
2454 -
2455 - # Create the tmp file to add.
2456 - ( cat <<EOF
2457 -dn: ${LDAP_ADMINDN}
2458 -cn: ${cn_tmp}
2459 -sn: ${cn_tmp}
2460 -objectclass: top
2461 -objectclass: person
2462 -userpassword: ${LDAP_ADMIN_CRED}
2463 -EOF
2464 -) > ${TMPDIR}/admin
3012 + FOUND=0
3013 + for X in "${SSD[@]}" ; do
3014 + [[ ${X%%:*} == ${ANS} ]] && FOUND=1 && break
3015 + done
3016 + (( ! FOUND )) && break
3017 + Log.warn "An SSD for '${ANS}' already exists:\n${X}\n"
3018 + done
3019 + ID="${ANS}"
2465 3020
2466 - # Add the entry.
2467 - ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/admin ${VERB}"
2468 - if [ $? -ne 0 ]; then
2469 - ${ECHO} " ERROR: Adding administrator identity failed!"
2470 - cleanup
2471 - exit 1
2472 - fi
3021 + while : ; do
3022 + get_ans_req 'Enter the search base (e.g. ou=people,o=inet):'
3023 + [[ ${ANS} != ~(E)[:] ]] && break
3024 + Log.warn 'Invalid search base' && continue
3025 + done
3026 + BASE="${ANS}"
2473 3027
2474 - ${RM} -f ${TMPDIR}/admin
3028 + while : ; do
3029 + get_ans_req "Enter the search scope (one|sub):"
3030 + SCOPE=${ANS}
3031 + [[ ${SCOPE} == 'one' || ${SCOPE} == 'sub' ]] && break
3032 + Log.warn "'${ANS}' is NOT valid - Enter 'one' or 'sub'"
3033 + done
2475 3034
2476 - # Display message that the administrator identity is added.
2477 - MSG="Administrator identity ${LDAP_ADMINDN}"
2478 - if [ $EXISTING_PROFILE -eq 1 ]; then
2479 - ${ECHO} " ADDED: $MSG."
2480 - else
2481 - ${ECHO} " ${STEP}. $MSG added."
2482 - STEP=`expr $STEP + 1`
2483 - fi
3035 + SSD+=( "${ID}:${BASE}?${SCOPE}" )
2484 3036 }
2485 3037
2486 -#
2487 -# allow_admin_read_write_shadow(): Give Admin read/write permission
2488 -# to shadow data.
2489 -#
2490 -allow_admin_read_write_shadow()
2491 -{
2492 - [ $DEBUG -eq 1 ] && ${ECHO} "In allow_admin_read_write_shadow()"
3038 +Man.addFunc delete_ssd '' '[+NAME?delete_ssd - Ask user which SSD to delete.]
3039 +[+DESCRIPTION?Ask the user for the ID of the SSD to delete and remove it from \bSSD\b list.]
3040 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage SSD ; }" '}
3041 +[+SEE ALSO?\bget_ans()\b.]
3042 +'
3043 +function delete_ssd {
3044 + get_ans 'Enter the service name of the SSD to delete (e.g. passwd):'
3045 + [[ -z ${ANS} ]] && return
2493 3046
2494 - # Set ACI Name
2495 - ADMIN_ACI_NAME="LDAP_Naming_Services_admin_shadow_write"
3047 + typeset X
3048 + integer I FOUND=-1 MAX=${#SSD[@]}
2496 3049
2497 - # Search for ACI_NAME
2498 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_BASEDN}\" \
2499 - -s base objectclass=* aci > ${TMPDIR}/chk_adminwrite_aci 2>&1"
2500 -
2501 - # if an ACI with ${ADMIN_ACI_NAME} and "write,compare,read,search"
2502 - # and ${LDAP_ADMINDN} already exists, we are done
2503 - ${EGREP} ".*${ADMIN_ACI_NAME}.*write,compare,read,search.*${LDAP_ADMINDN}.*" \
2504 - ${TMPDIR}/chk_adminwrite_aci 2>&1 > /dev/null
2505 - if [ $? -eq 0 ]; then
2506 - MSG="Admin ACI ${ADMIN_ACI_NAME} already exists for ${LDAP_BASEDN}."
2507 - if [ $EXISTING_PROFILE -eq 1 ]; then
2508 - ${ECHO} " NOT SET: $MSG"
2509 - else
2510 - ${ECHO} " ${STEP}. $MSG"
2511 - STEP=`expr $STEP + 1`
3050 + for (( I=0; I < MAX ; I++ )); do
3051 + X=${SSD[I]}
3052 + [[ ${X%%:*} == ${ANS} ]] && FOUND=$I && break
3053 + done
3054 + if (( FOUND == -1 )); then
3055 + Log.warn "Invalid service name: '${ANS}' not present in list"
3056 + return
2512 3057 fi
2513 - return 0
2514 - fi
3058 + (( FOUND == 0 )) && unset SSD[0] && return
2515 3059
2516 - # If an ACI with ${ADMIN_ACI_NAME} and "(write)" and ${LDAP_ADMINDN}
2517 - # already exists, delete it first.
2518 - find_and_delete_ACI ".*${ADMIN_ACI_NAME}.*(write).*${LDAP_ADMINDN}.*" \
2519 - ${TMPDIR}/chk_adminwrite_aci ${ADMIN_ACI_NAME}
3060 + # need to do a little bit more, since ksh allows to remove the 1st entry,
3061 + # only (i.e. like "shift 1" for positional params)
3062 + for (( I=FOUND; I > 0; I-- )); do
3063 + SSD[${I}]="${SSD[I-1]}"
3064 + done
3065 + unset SSD[0]
3066 +}
2520 3067
2521 - # Create the tmp file to add.
2522 - ( cat <<EOF
2523 -dn: ${LDAP_BASEDN}
2524 -changetype: modify
2525 -add: aci
2526 -aci: (target="ldap:///${LDAP_BASEDN}")(targetattr="shadowLastChange
2527 - ||shadowMin||shadowMax||shadowWarning||shadowInactive||shadowExpire
2528 - ||shadowFlag||userPassword||loginShell||homeDirectory||gecos")
2529 - (version 3.0; acl ${ADMIN_ACI_NAME}; allow (write,compare,read,search)
2530 - userdn = "ldap:///${LDAP_ADMINDN}";)
2531 -EOF
2532 -) > ${TMPDIR}/admin_write
3068 +Man.addFunc modify_ssd '' '[+NAME?modify_ssd - Allow user to modify an SSD.]
3069 +[+DESCRIPTION?Ask the user for the ID of the SSD to modify, let the user modify it and finally save changes back to the \bSSD\b list.]
3070 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage SSD ; }" '}
3071 +[+SEE ALSO?\bget_ans()\b, \bread\b(1).]
3072 +'
3073 +function modify_ssd {
3074 + get_ans 'Enter the service name of the SSD to modify:'
3075 + [[ -z ${ANS} ]] && return
2533 3076
2534 - # Add the entry.
2535 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/admin_write ${VERB}"
2536 - if [ $? -ne 0 ]; then
2537 - ${ECHO} " ERROR: Allow ${LDAP_ADMINDN} read/write access to shadow data failed!"
2538 - cleanup
2539 - exit 1
2540 - fi
3077 + typeset ID BASE
3078 + typeset -l SCOPE
3079 + integer I FOUND=-1 MAX=${#SSD[@]}
3080 + for (( I=0; I < MAX ; I++ )); do
3081 + X=${SSD[I]}
3082 + [[ ${X%%:*} == ${ANS} ]] && FOUND=$I && break
3083 + done
3084 + if (( FOUND == -1 )); then
3085 + Log.warn "Invalid service name: '${ANS}'"
3086 + return 0
3087 + fi
2541 3088
2542 - ${RM} -f ${TMPDIR}/admin_write
2543 - # Display message that the administrator ACL is set.
2544 - MSG="Give ${LDAP_ADMINDN} read/write access to shadow data."
2545 - if [ $EXISTING_PROFILE -eq 1 ]; then
2546 - ${ECHO} " ACI SET: $MSG"
2547 - else
2548 - ${ECHO} " ${STEP}. $MSG"
2549 - STEP=`expr $STEP + 1`
2550 - fi
2551 -}
3089 + # most users expect emacs edit behavior (don't have a proper profile)
3090 + set -o emacs
3091 + read -v X?'Current SSD: '
2552 3092
2553 -#
2554 -# allow_host_read_write_shadow(): Give host principal read/write permission
2555 -# for shadow data.
2556 -#
2557 -allow_host_read_write_shadow()
2558 -{
2559 - [ $DEBUG -eq 1 ] && ${ECHO} "In allow_host_read_write_shadow()"
2560 -
2561 - # Set ACI Name
2562 - HOST_ACI_NAME="LDAP_Naming_Services_host_shadow_write"
2563 -
2564 - # Search for ACI_NAME
2565 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_BASEDN}\" -s base objectclass=* aci > ${TMPDIR}/chk_hostwrite_aci 2>&1"
2566 - ${GREP} "${HOST_ACI_NAME}" ${TMPDIR}/chk_hostwrite_aci > /dev/null 2>&1
2567 - if [ $? -eq 0 ]; then
2568 - MSG="Host ACI ${HOST_ACI_NAME} already exists for ${LDAP_BASEDN}."
2569 - if [ $EXISTING_PROFILE -eq 1 ]; then
2570 - ${ECHO} " NOT ADDED: $MSG"
2571 - else
2572 - ${ECHO} " ${STEP}. $MSG"
2573 - STEP=`expr $STEP + 1`
3093 + # now verify
3094 + ID=${X%%:*}
3095 + BASE=${.sh.match#:}
3096 + SCOPE=${BASE#*$'?'}
3097 + BASE=${.sh.match%$'?'}
3098 + if [[ -z ${ID} || -z ${BASE} || -z ${SCOPE} ]] || \
3099 + [[ ${SCOPE} != 'one' && ${SCOPE} != 'sub' ]]
3100 + then
3101 + Log.warn 'SSD is invalid. Change skipped'
3102 + return
2574 3103 fi
2575 - return 0
2576 - fi
3104 + SSD[${FOUND}]="${ID}:${BASE}?${SCOPE}"
3105 +}
2577 3106
2578 - # Create the tmp file to add.
2579 - ( cat <<EOF
2580 -dn: ${LDAP_BASEDN}
2581 -changetype: modify
2582 -add: aci
2583 -aci: (target="ldap:///${LDAP_BASEDN}")(targetattr="shadowLastChange||shadowMin||shadowMax||shadowWarning||shadowInactive||shadowExpire||shadowFlag||userPassword||loginShell||homeDirectory||gecos")(version 3.0; acl ${HOST_ACI_NAME}; allow (write,compare,read,search) authmethod="sasl GSSAPI" and userdn = "ldap:///cn=*+ipHostNumber=*,ou=Hosts,${LDAP_BASEDN}";)
2584 -EOF
2585 -) > ${TMPDIR}/host_read_write
2586 -
2587 - # Add the entry.
2588 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/host_read_write ${VERB}"
2589 - if [ $? -ne 0 ]; then
2590 - ${ECHO} " ERROR: Allow Host Principal to write shadow data failed!"
2591 - cleanup
2592 - exit 1
2593 - fi
3107 +Man.addFunc reset_ssd '' '[+NAME?reset_ssd - Blank out current list of SSDs.]
3108 +[+DESCRIPTION?Clear the \bSSD\b array.]
3109 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage SSD ; }" '}
3110 +'
3111 +function reset_ssd {
3112 + SSD=( )
3113 + unset SSD[0] # required otherwise it would contain a single '\n'. Bug?
3114 +}
2594 3115
2595 - ${RM} -f ${TMPDIR}/host_read_write
2596 - MSG="Give host principal read/write permission for shadow."
2597 - if [ $EXISTING_PROFILE -eq 1 ]; then
2598 - ${ECHO} " ACI SET: $MSG"
2599 - else
2600 - ${ECHO} " ${STEP}. $MSG"
2601 - STEP=`expr $STEP + 1`
2602 - fi
3116 +Man.addFunc display_ssd '' '[+NAME?display_ssd - Display current SSD list.]
3117 +[+DESCRIPTION?Display the current \bSSD\b list and return, when the user hit the enter key.]
3118 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage SSD ; }" '}
3119 +'
3120 +function display_ssd {
3121 + typeset X
3122 + print '
3123 +Current Service Search Descriptors:
3124 +=================================='
3125 + for X in "${SSD[@]}" ; do
3126 + print " ${X}"
3127 + done
3128 + print '\nHit return to continue.'
3129 + read
2603 3130 }
2604 3131
2605 -#
2606 -# Set up shadow update
2607 -#
2608 -setup_shadow_update() {
2609 - [ $DEBUG -eq 1 ] && ${ECHO} "In setup_shadow_update()"
2610 -
2611 - # get content of the profile
2612 - PROFILE_OUT=${TMPDIR}/prof_tmpfile
2613 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=${LDAP_PROFILE_NAME},ou=profile,${LDAP_BASEDN}\" -s base \"objectclass=*\" > $PROFILE_OUT 2>&1"
2614 - ${GREP} -i cn $PROFILE_OUT >/dev/null 2>&1
2615 - if [ $? -ne 0 ]; then
2616 - [ $DEBUG -eq 1 ] && ${ECHO} "Profile ${LDAP_PROFILE_NAME} does not exist"
2617 - ${RM} ${PROFILE_OUT}
2618 - return
2619 - fi
2620 -
2621 - # Search to see if authenticationMethod has 'GSSAPI' and
2622 - # credentialLevel has 'self'. If so, ask to use the
2623 - # host principal for shadow update
2624 - if [ $GSSAPI_AUTH_MAY_BE_USED -eq 1 ]; then
2625 - if ${GREP} authenticationMethod $PROFILE_OUT | ${GREP} GSSAPI >/dev/null 2>&1
3132 +Man.addFunc prompt_ssd '' '[+NAME?prompt_ssd - Get SSDs from user.]
3133 +[+DESCRIPTION?Ask the user whether to add/delete/modify/display one or more SSDs currently set and execute the corresponding action.]
3134 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage ANS ; }" '}
3135 +[+SEE ALSO?\bdisplay_msg()\b, \bget_ans()\b, \badd_ssd()\b, \bdelete_ssd()\b, \bmodify_ssd()\b, \bdisplay_ssd()\b, \breset_ssd()\b.]
3136 +'
3137 +function prompt_ssd {
3138 + if get_confirm 'Do you wish to setup Service Search Descriptors (y/n/h)?' \
3139 + 'n' 'ssd_help'
2626 3140 then
2627 - if ${GREP} credentialLevel $PROFILE_OUT | ${GREP} self >/dev/null 2>&1
2628 - then
2629 - NEED_HOSTACL=1
2630 - fi
3141 + return
2631 3142 fi
2632 - ${RM} ${PROFILE_OUT}
2633 - [ $DEBUG -eq 1 ] && ${ECHO} "NEED_HOSTACL = $NEED_HOSTACL"
2634 3143
2635 - if [ $NEED_HOSTACL -eq 1 ]; then
2636 - MSG="Use host principal for shadow data update (y/n/h)?"
2637 - get_confirm "$MSG" "y" "use_host_principal_help"
2638 - if [ $? -eq 1 ]; then
2639 - delete_proxy_read_pw
2640 - allow_host_read_write_shadow
2641 - deny_non_host_shadow_access
2642 - ${ECHO} ""
2643 - ${ECHO} " Shadow update has been enabled."
2644 - else
2645 - ${ECHO} ""
2646 - ${ECHO} " Shadow update may not work."
2647 - fi
2648 - return
2649 - fi
2650 - fi
3144 + # Display menu for SSD choices
3145 + while : ; do
3146 + display_msg prompt_ssd_menu
3147 + get_ans 'Enter menu choice:' 'Quit'
3148 + case "${ANS}" in
3149 + [Qq] | Quit | quit) return ;;
3150 + [Aa] | add) add_ssd ;;
3151 + [Dd] | delete) delete_ssd ;;
3152 + [Mm] | modify) modify_ssd ;;
3153 + [Pp] | print | display) display_ssd ;;
3154 + [Xx] | reset | clear) reset_ssd ;;
3155 + [Hh] | Help | help)
3156 + display_msg 'ssd_menu_help '
3157 + print ' Press return to continue.'
3158 + read
3159 + ;;
3160 + *) Log.warn "Invalid choice: '${ANS}' please re-enter from menu!" ;;
3161 + esac
3162 + done
3163 +}
2651 3164
2652 - MSG="Add the administrator identity (y/n/h)?"
2653 - get_confirm "$MSG" "y" "add_admin_cred_help"
2654 - if [ $? -eq 1 ]; then
2655 - get_adminDN
2656 - get_admin_pw
2657 - add_admin
2658 - delete_proxy_read_pw
2659 - allow_admin_read_write_shadow
2660 - deny_non_admin_shadow_access
2661 - ${ECHO} ""
2662 - ${ECHO} " Shadow update has been enabled."
2663 - return
2664 - fi
2665 -
2666 - ${ECHO} " No administrator identity specified, shadow update may not work."
3165 + ######################################################################
3166 + # End Of FUNCTIONS FOR Service Search Descriptor's
3167 + ######################################################################
3168 +Man.addFunc prompt_config_info '' '[+NAME?prompt_config_info - Ask user for missing config info.]
3169 +[+DESCRIPTION?Ask the user for the config info not yet available/read from an '"${PROG}"' config file.]
3170 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage INT STR SSD ; }" '}
3171 +[+RETURN VALUES]{
3172 + [+0?on success (all info aquired).]
3173 + [+>= 66?a fatal error occured.]
2667 3174 }
3175 +'
3176 +function prompt_config_info {
3177 + # Prompt for DS server name
3178 + get_ids_server
2668 3179
3180 + # Prompt for DS port number
3181 + get_ids_port
2669 3182
2670 -#
2671 -# prompt_config_info(): This function prompts the user for the config
2672 -# info that is not specified in the input file.
2673 -#
2674 -prompt_config_info()
2675 -{
2676 - [ $DEBUG -eq 1 ] && ${ECHO} "In prompt_config_info()"
3183 + # Check DS version for compatibility
3184 + chk_ids_version || return 66
2677 3185
2678 - # Prompt for iDS server name.
2679 - get_ids_server
3186 + # Check if the DS supports the VLV
3187 + chk_vlv_indexes || return 67
2680 3188
2681 - # Prompt for iDS port number.
2682 - get_ids_port
3189 + # Get the Directory manager DN and passwd
3190 + get_dirmgr_dn
3191 + get_dirmgr_pw
2683 3192
2684 - # Check iDS version for compatibility.
2685 - chk_ids_version
3193 + get_confirm 'Do you want to modify the DS timelimit for processing searches (y/n/h)?' 'n' 'tlim_help'
3194 + INT[NEED_TIME]=$?
3195 + if (( INT[NEED_TIME] )); then
3196 + get_timelimit || return 70
3197 + fi
2686 3198
2687 - # Check if the server supports the VLV.
2688 - chk_vlv_indexes
3199 + get_confirm 'Do you want to modify the DS sizelimit - max. entries to return (y/n/h)?' 'n' 'slim_help'
3200 + INT[NEED_SIZE]=$?
3201 + if (( INT[NEED_SIZE] )); then
3202 + get_sizelimit || return 71
3203 + fi
2689 3204
2690 - # Get the Directory manager DN and passwd.
2691 - get_dirmgr_dn
2692 - get_dirmgr_pw
2693 3205
2694 - #
2695 - # LDAP CLIENT PROFILE SPECIFIC INFORMATION.
2696 - # (i.e. The fields that show up in the profile.)
2697 - #
2698 - get_domain "domain_help"
3206 + # LDAP CLIENT PROFILE SPECIFIC INFORMATION
3207 + # (i.e. the fields that show up in the profile)
3208 + get_domain
3209 + get_basedn || return 68
2699 3210
2700 - get_basedn
2701 -
3211 + # Check/Get Kerberos infos
2702 3212 gssapi_setup
2703 3213
2704 3214 get_profile_name
2705 3215
2706 - if [ "$LDAP_ENABLE_SHADOW_UPDATE" = "TRUE" ];then
2707 - setup_shadow_update
2708 - cleanup
2709 - exit 0
2710 - fi
3216 + if (( INT[LDAP_ENABLE_SHADOW_UPDATE] ));then
3217 + setup_shadow_update || return 69
3218 + return 0
3219 + fi
2711 3220
2712 - get_srv_list
2713 - get_pref_srv
2714 - get_search_scope
2715 -
2716 - # If cred is "anonymous", make auth == "none"
2717 - get_cred_level
2718 - if [ "$LDAP_CRED_LEVEL" != "anonymous" ]; then
2719 - get_auth
2720 - fi
2721 -
3221 + get_srv_list
3222 + get_pref_srv
3223 + get_search_scope
2722 3224 get_followref
2723 3225
2724 - # Query user about timelimt.
2725 - get_confirm "Do you want to modify the server timelimit value (y/n/h)?" "n" "tlim_help"
2726 - NEED_TIME=$?
2727 - [ $NEED_TIME -eq 1 ] && get_timelimit
3226 + # Store passwords in crypt format?
3227 + get_want_crypt
2728 3228
2729 - # Query user about sizelimit.
2730 - get_confirm "Do you want to modify the server sizelimit value (y/n/h)?" "n" "slim_help"
2731 - NEED_SIZE=$?
2732 - [ $NEED_SIZE -eq 1 ] && get_sizelimit
3229 + # If cred is "anonymous", make auth == "none"
3230 + get_cred_level
3231 + [[ ${STR[LDAP_CRED_LEVEL]} != anonymous ]] && get_auth 'client'
2733 3232
2734 - # Does the user want to store passwords in crypt format?
2735 - get_want_crypt
3233 + get_confirm 'Do you want to setup any non-default Authentication Methods (y/n/h)?' 'n' 'srvauth_help'
3234 + if (( $? )); then
3235 + get_confirm 'Do you want to setup Authentication Methods for "pam_ldap" (y/n/h)?' 'n' 'pam_ldap_help'
3236 + INT[NEED_SRVAUTH_PAM]=$?
3237 + (( INT[NEED_SRVAUTH_PAM] )) && get_auth 'pam_ldap'
2736 3238
2737 - # Prompt for any Service Authentication Methods?
2738 - get_confirm "Do you want to setup a Service Authentication Methods (y/n/h)?" "n" "srvauth_help"
2739 - if [ $? -eq 1 ]; then
2740 - # Does the user want to set Service Authentication Method for pam_ldap?
2741 - get_confirm "Do you want to setup a Service Auth. Method for \"pam_ldap\" (y/n/h)?" "n" "pam_ldap_help"
2742 - NEED_SRVAUTH_PAM=$?
2743 - [ $NEED_SRVAUTH_PAM -eq 1 ] && get_srv_authMethod_pam
3239 + get_confirm 'Do you want to setup Authentication Methods for "keyserv" (y/n/h)?' 'n' 'keyserv_help'
3240 + INT[NEED_SRVAUTH_KEY]=$?
3241 + (( INT[NEED_SRVAUTH_KEY] )) && get_auth 'keyserv'
2744 3242
2745 - # Does the user want to set Service Authentication Method for keyserv?
2746 - get_confirm "Do you want to setup a Service Auth. Method for \"keyserv\" (y/n/h)?" "n" "keyserv_help"
2747 - NEED_SRVAUTH_KEY=$?
2748 - [ $NEED_SRVAUTH_KEY -eq 1 ] && get_srv_authMethod_key
3243 + get_confirm 'Do you want to setup Authentication Methods for "passwd-cmd (y/n/h)?' 'n' 'passwd-cmd_help'
3244 + INT[NEED_SRVAUTH_CMD]=$?
3245 + (( INT[NEED_SRVAUTH_CMD] )) && get_auth 'passwd-cmd'
3246 + fi
2749 3247
2750 - # Does the user want to set Service Authentication Method for passwd-cmd?
2751 - get_confirm "Do you want to setup a Service Auth. Method for \"passwd-cmd\" (y/n/h)?" "n" "passwd-cmd_help"
2752 - NEED_SRVAUTH_CMD=$?
2753 - [ $NEED_SRVAUTH_CMD -eq 1 ] && get_srv_authMethod_cmd
2754 - fi
2755 -
3248 + # Get client timeouts
3249 + get_srch_time
3250 + get_prof_ttl
3251 + get_bind_limit
2756 3252
2757 - # Get Timeouts
2758 - get_srch_time
2759 - get_prof_ttl
2760 - get_bind_limit
3253 + get_want_shadow_update
2761 3254
2762 - # Ask whether to enable shadow update
2763 - get_want_shadow_update
3255 + reset_ssd
3256 + prompt_ssd
2764 3257
2765 - # Reset the sdd_file and prompt user for SSD. Will use menus
2766 - # to build an SSD File.
2767 - reset_ssd_file
2768 - prompt_ssd
3258 + show_vars
2769 3259
2770 - # Display FULL debugging info.
2771 - disp_full_debug
2772 -
2773 - # Extra blank line to separate prompt lines from steps.
2774 - ${ECHO} " "
3260 + Log.printMarker
3261 + return 0
2775 3262 }
3263 +######################################################################
3264 +# End Of FUNCTIONS FOR prompt_config_info()
3265 +######################################################################
2776 3266
2777 3267
2778 3268 ######################################################################
2779 3269 # FUNCTIONS FOR display_summary() START HERE.
2780 3270 ######################################################################
2781 -
2782 -
2783 -#
2784 -# get_proxyagent(): Get the proxyagent DN.
2785 -#
2786 -get_proxyagent()
2787 -{
2788 - LDAP_PROXYAGENT="cn=proxyagent,ou=profile,${LDAP_BASEDN}" # default
2789 - get_ans "Enter DN for proxy agent:" "$LDAP_PROXYAGENT"
2790 - LDAP_PROXYAGENT=$ANS
3271 +Man.addFunc get_proxyagent '' '[+NAME?get_proxyagent - Ask user for the proxy agent DN and password.]
3272 +[+DESCRIPTION?Ask the user for the proxy agent DN and password to use and store it into \bSTR[LDAP_PROXYAGENT]]\b, \bSTR[LDAP_PROXYAGENT_CRED]]\b.]
3273 +[+SEE ALSO?\bget_ans()\b.]
3274 +'
3275 +function get_proxyagent {
3276 + STR[LDAP_PROXYAGENT]="cn=proxyagent,ou=profile,${STR[LDAP_BASEDN]}"
3277 + get_ans 'Enter DN for proxy agent:' "${STR[LDAP_PROXYAGENT]}"
3278 + STR[LDAP_PROXYAGENT]="${ANS}"
3279 + get_passwd 'Enter passwd for proxyagent:'
3280 + STR[LDAP_PROXYAGENT_CRED]="${ANS}"
2791 3281 }
2792 3282
3283 +Man.addFunc display_summary '' '[+NAME?display_summary - Display a summary of values entered and let the user modify values at will.]
3284 +[+DESCRIPTION?Display a summary of all configuration relevant info and let the user re-enter data if needed.]
3285 +'
3286 +function display_summary {
3287 + # Create lookup table for function names. Needs to be in sync with
3288 + # helpTag 'summary_menu' in display_msg()!
3289 + typeset -a FN=( 'dummy' ) # dummy for commit and quit
3290 + FN+=( 'get_domain' 'get_basedn' 'get_profile_name' )
3291 + FN+=( 'get_srv_list' 'get_pref_srv' 'get_search_scope' 'get_cred_level' )
3292 + FN+=( 'get_auth client' 'get_followref' )
3293 + FN+=( 'get_timelimit' 'get_sizelimit' 'get_want_crypt' )
3294 + FN+=( 'get_auth pam_ldap' 'get_auth keyserv' 'get_auth passwd-cmd' )
3295 + FN+=( 'get_srch_time' 'get_prof_ttl' 'get_bind_limit' )
3296 + FN+=( 'get_want_shadow_update' )
3297 + FN+=( 'prompt_ssd' )
2793 3298
2794 -#
2795 -# get_proxy_pw(): Get the proxyagent passwd.
2796 -#
2797 -get_proxy_pw()
2798 -{
2799 - get_passwd "Enter passwd for proxyagent:"
2800 - LDAP_PROXYAGENT_CRED=$ANS
2801 -}
3299 + # Since menu prompt string is long, set here
3300 + typeset PROMPT='Enter config value to change: (1-20 0=commit changes)'
3301 + integer RES MAX=${#FN[@]}
3302 + (( MAX-- ))
2802 3303
2803 -#
2804 -# display_summary(): Display a summary of values entered and let the
2805 -# user modify values at will.
2806 -#
2807 -display_summary()
2808 -{
2809 - [ $DEBUG -eq 1 ] && ${ECHO} "In display_summary()"
3304 + while : ; do
3305 + # Display menu and get value in range
3306 + get_menu_choice "${PROMPT}" '0' ${MAX} '0' '' 'summary_menu'
3307 + RES=$?
3308 +
3309 + # Make sure where not exiting
3310 + (( RES == 0 )) && break # quit selected
2810 3311
2811 - # Create lookup table for function names. First entry is dummy for
2812 - # shift.
2813 - TBL1="dummy"
2814 - TBL2="get_domain get_basedn get_profile_name"
2815 - TBL3="get_srv_list get_pref_srv get_search_scope get_cred_level"
2816 - TBL4="get_auth get_followref"
2817 - TBL5="get_timelimit get_sizelimit get_want_crypt"
2818 - TBL6="get_srv_authMethod_pam get_srv_authMethod_key get_srv_authMethod_cmd"
2819 - TBL7="get_srch_time get_prof_ttl get_bind_limit"
2820 - TBL8="get_want_shadow_update"
2821 - TBL9="prompt_ssd"
2822 - FUNC_TBL="$TBL1 $TBL2 $TBL3 $TBL4 $TBL5 $TBL6 $TBL7 $TBL8 $TBL9"
3312 + # Call appropriate function from function table
3313 + ${FN[RES]}
3314 + done
2823 3315
2824 - # Since menu prompt string is long, set here.
2825 - _MENU_PROMPT="Enter config value to change: (1-20 0=commit changes)"
3316 + # If credlevel is still proxy see if user wants a change?
3317 + if [[ ${STR[LDAP_CRED_LEVEL]:0:5} == 'proxy' ]]; then
3318 + if [[ ${STR[LDAP_AUTHMETHOD]} != none ]]; then
3319 + INT[NEED_PROXY]=1
3320 + get_proxyagent
3321 + else
3322 + Log.warn 'Since Authentication method is "none",' \
3323 + 'credential level will be set to "anonymous"'
3324 + STR[LDAP_CRED_LEVEL]='anonymous'
3325 + fi
3326 + fi
2826 3327
2827 - # Infinite loop. Test for 0, and break in loop.
2828 - while :
2829 - do
2830 - # Display menu and get value in range.
2831 - display_msg summary_menu
2832 - get_menu_choice "${_MENU_PROMPT}" "0" "20" "0"
2833 - _CH=$MN_CH
2834 -
2835 - # Make sure where not exiting.
2836 - if [ $_CH -eq 0 ]; then
2837 - break # Break out of loop if 0 selected.
3328 + # If shadow update is enabled, set up administrator credential
3329 + if (( INT[LDAP_ENABLE_SHADOW_UPDATE] )); then
3330 + INT[NEED_ADMIN]=1
3331 + if [[ ${STR[LDAP_CRED_LEVEL]} == 'self' && \
3332 + ${STR[LDAP_AUTHMETHOD]} == 'sasl/GSSAPI' ]];
3333 + then
3334 + INT[NEED_HOSTACL]=1
3335 + INT[NEED_ADMIN]=0
3336 + fi
3337 + if (( INT[NEED_ADMIN] )); then
3338 + get_adminDN
3339 + get_admin_pw
3340 + fi
2838 3341 fi
2839 3342
2840 - # Call appropriate function from function table.
2841 - set $FUNC_TBL
2842 - shift $_CH
2843 - $1 # Call the appropriate function.
2844 - done
3343 + show_vars
2845 3344
2846 - # If cred level is still see if user wants a change?
2847 - if ${ECHO} "$LDAP_CRED_LEVEL" | ${GREP} "proxy" > /dev/null 2>&1
2848 - then
2849 - if [ "$LDAP_AUTHMETHOD" != "none" ]; then
2850 - NEED_PROXY=1 # I assume integer test is faster?
2851 - get_proxyagent
2852 - get_proxy_pw
2853 - else
2854 - ${ECHO} "WARNING: Since Authentication method is 'none'."
2855 - ${ECHO} " Credential level will be set to 'anonymous'."
2856 - LDAP_CRED_LEVEL="anonymous"
3345 + get_confirm_nodef '
3346 +WARNING: About to start committing changes. (y=continue, n=EXIT)'
3347 + if (( ! $? )); then
3348 + Log.info 'Terminating setup without making changes at users request'
3349 + return 1
2857 3350 fi
2858 - fi
2859 3351
2860 - # If shadow update is enabled, set up administrator credential
2861 - if [ "$LDAP_ENABLE_SHADOW_UPDATE" = "TRUE" ]; then
2862 - NEED_ADMIN=1
2863 - if ${ECHO} "$LDAP_CRED_LEVEL" | ${GREP} "self" > /dev/null 2>&1; then
2864 - if ${ECHO} "$LDAP_AUTHMETHOD" | ${GREP} "GSSAPI" > /dev/null 2>&1; then
2865 - NEED_HOSTACL=1
2866 - NEED_ADMIN=0
2867 - fi
3352 + Log.printMarker
3353 + return 0
3354 +}
3355 +######################################################################
3356 +# End Of FUNCTIONS FOR display_summary()
3357 +######################################################################
3358 +
3359 +Man.addFunc modify_cn '' '[+NAME?modify_cn - modify objectclass "ipNetwork" to RFC 2307bis.]
3360 +[+DESCRIPTION?Change the cn from MUST to MAY in ipNetwork objectclass.]
3361 +[+RETURN VALUES]{
3362 + [+0?on success.]
3363 + [+>= 66?a fatal error occurred.]
3364 +}
3365 +[+SEE ALSO?\bldapmodify\b(1).]
3366 +'
3367 +function modify_cn {
3368 + getDSobjectclasses || return 66
3369 + typeset NEWDEF="'ipNetwork' SUP top STRUCTURAL DESC 'Abstraction of a network. The distinguished value of the cn attribute denotes the canonical name of the network' MUST ipNetworkNumber MAY "'( cn $ ipNetmaskNumber $ l $ description $ manager )'" X-ORIGIN 'draft-howard-rfc2307bis'"
3370 +
3371 + # bis-delta: MUST ( -cn ) MAY ( +cn )
3372 + typeset DEF=${OID2ODEF['1.3.6.1.1.1.2.7']}
3373 + if [[ -n ${DEF} ]]; then
3374 + DEF=${DEF##*MUST*([[:space:]])}
3375 + if [[ ${DEF:0:9} == 'ipNetwork' ]]; then
3376 + # assume no need to fix, old definition would start with a '('
3377 + showProgress 'Schema definition of ipNetwork ok (RFC2307bis).'
3378 + return 0
3379 + fi
2868 3380 fi
2869 - [ $DEBUG -eq 1 ] && ${ECHO} "NEED_HOSTACL = $NEED_HOSTACL"
2870 - [ $DEBUG -eq 1 ] && ${ECHO} "NEED_ADMIN = $NEED_ADMIN"
2871 - if [ $NEED_ADMIN -eq 1 ]; then
2872 - get_adminDN
2873 - get_admin_pw
2874 - fi
2875 - fi
2876 3381
2877 - # Display FULL debugging info.
2878 - disp_full_debug
3382 + nextFile modify $0
3383 + print '
3384 +dn: cn=schema
3385 +changetype: modify
3386 +add: objectclasses
3387 +objectclasses: ( 1.3.6.1.1.1.2.7 NAME '"${NEWDEF}"')
3388 +' > ${TMP[FILE]}
2879 3389
2880 - # Final confirmation message. (ARE YOU SURE!)
2881 - ${ECHO} " "
2882 - get_confirm_nodef "WARNING: About to start committing changes. (y=continue, n=EXIT)"
2883 - if [ $? -eq 0 ]; then
2884 - ${ECHO} "Terminating setup without making changes at users request."
2885 - cleanup
2886 - exit 1
2887 - fi
3390 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
3391 + >&${TMPF[FD]} 2>&1
3392 + then
3393 + Log.fatal 'Schema update of ipNetwork to RFC2307bis failed'
3394 + return 67
3395 + fi
3396 + showProgress 'Schema update of ipNetwork to RFC2307bis done.'
3397 + OID2ODEF['1.3.6.1.1.1.2.7']="${NEWDEF}"
3398 + return 0
3399 +}
2888 3400
2889 - # Print newline
2890 - ${ECHO} " "
3401 +Man.addFunc modify_timelimit '' '[+NAME?modify_timelimit - Set the DS timelimit.]
3402 +[+DESCRIPTION?Set the DS timelimit to \bINT[DS_TIMELIMIT]]\b.]
3403 +[+RETURN VALUES]{
3404 + [+0?on success.]
3405 + [+>= 66?a fatal error occurred.]
2891 3406 }
3407 +[+SEE ALSO?\bldapmodify\b(1).]
3408 +'
3409 +function modify_timelimit {
3410 + typeset NAME='nsslapd-timelimit'
3411 + (( TMPF[IS_OPENDJ] )) && NAME='ds-cfg-time-limit'
2892 3412
3413 + nextFile modify $0
3414 + print '
3415 +dn: cn=config
3416 +changetype: modify
3417 +replace: '"${NAME}"'
3418 +'"${NAME}"': '"${INT[DS_TIMELIMIT]}"' s
3419 +' > ${TMP[FILE]}
2893 3420
2894 -#
2895 -# create_config_file(): Write config data to config file specified.
2896 -#
2897 -create_config_file()
2898 -{
2899 - [ $DEBUG -eq 1 ] && ${ECHO} "In create_config_file()"
3421 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
3422 + >&${TMPF[FD]} 2>&1
3423 + then
3424 + Log.fatal 'Update of ${NAME} failed'
3425 + return 66
3426 + fi
2900 3427
2901 - # If output file exists, delete it.
2902 - [ -f $OUTPUT_FILE ] && rm $OUTPUT_FILE
3428 + showProgress "Changed ${NAME} to ${INT[DS_TIMELIMIT]} in 'cn=config'."
3429 + return 0
3430 +}
2903 3431
2904 - # Create output file.
2905 - cat > $OUTPUT_FILE <<EOF
2906 -#!/bin/sh
2907 -# $OUTPUT_FILE - This file contains configuration information for
2908 -# Native LDAP. Use the idsconfig tool to load it.
2909 -#
2910 -# WARNING: This file was generated by idsconfig, and is intended to
2911 -# be loaded by idsconfig as is. DO NOT EDIT THIS FILE!
2912 -#
2913 -IDS_SERVER="$IDS_SERVER"
2914 -IDS_PORT=$IDS_PORT
2915 -IDS_TIMELIMIT=$IDS_TIMELIMIT
2916 -IDS_SIZELIMIT=$IDS_SIZELIMIT
2917 -LDAP_ROOTDN="$LDAP_ROOTDN"
2918 -LDAP_ROOTPWD=$LDAP_ROOTPWD
2919 -LDAP_DOMAIN="$LDAP_DOMAIN"
2920 -LDAP_SUFFIX="$LDAP_SUFFIX"
2921 -GSSAPI_ENABLE=$GSSAPI_ENABLE
2922 -LDAP_KRB_REALM="$LDAP_KRB_REALM"
3432 +Man.addFunc modify_sizelimit '' '[+NAME?modify_sizelimit - Set the DS sizelimit.]
3433 +[+DESCRIPTION?Set the DS sizelimit to \bINT[DS_SIZELIMIT]]\b.]
3434 +[+RETURN VALUES]{
3435 + [+0?on success.]
3436 + [+>= 66?a fatal error occurred.]
3437 +}
3438 +[+SEE ALSO?\bldapmodify\b(1).]
3439 +'
3440 +function modify_sizelimit {
3441 + typeset NAME='nsslapd-sizelimit'
3442 + (( TMPF[IS_OPENDJ] )) && NAME='ds-cfg-size-limit'
2923 3443
2924 -# Internal program variables that need to be set.
2925 -NEED_PROXY=$NEED_PROXY
2926 -NEED_TIME=$NEED_TIME
2927 -NEED_SIZE=$NEED_SIZE
2928 -NEED_CRYPT=$NEED_CRYPT
2929 -NEED_ADMIN=$NEED_ADMIN
2930 -NEED_HOSTACL=$NEED_HOSTACL
2931 -EXISTING_PROFILE=$EXISTING_PROFILE
3444 + nextFile modify $0
3445 + print '
3446 +dn: cn=config
3447 +changetype: modify
3448 +replace: '"${NAME}"'
3449 +'"${NAME}"': '"${INT[DS_SIZELIMIT]}"'
3450 +' > ${TMP[FILE]}
2932 3451
2933 -# LDAP PROFILE related defaults
2934 -LDAP_PROFILE_NAME="$LDAP_PROFILE_NAME"
2935 -DEL_OLD_PROFILE=1
2936 -LDAP_BASEDN="$LDAP_BASEDN"
2937 -LDAP_SERVER_LIST="$LDAP_SERVER_LIST"
2938 -LDAP_AUTHMETHOD="$LDAP_AUTHMETHOD"
2939 -LDAP_FOLLOWREF=$LDAP_FOLLOWREF
2940 -LDAP_SEARCH_SCOPE="$LDAP_SEARCH_SCOPE"
2941 -NEED_SRVAUTH_PAM=$NEED_SRVAUTH_PAM
2942 -NEED_SRVAUTH_KEY=$NEED_SRVAUTH_KEY
2943 -NEED_SRVAUTH_CMD=$NEED_SRVAUTH_CMD
2944 -LDAP_SRV_AUTHMETHOD_PAM="$LDAP_SRV_AUTHMETHOD_PAM"
2945 -LDAP_SRV_AUTHMETHOD_KEY="$LDAP_SRV_AUTHMETHOD_KEY"
2946 -LDAP_SRV_AUTHMETHOD_CMD="$LDAP_SRV_AUTHMETHOD_CMD"
2947 -LDAP_SEARCH_TIME_LIMIT=$LDAP_SEARCH_TIME_LIMIT
2948 -LDAP_PREF_SRVLIST="$LDAP_PREF_SRVLIST"
2949 -LDAP_PROFILE_TTL=$LDAP_PROFILE_TTL
2950 -LDAP_CRED_LEVEL="$LDAP_CRED_LEVEL"
2951 -LDAP_BIND_LIMIT=$LDAP_BIND_LIMIT
3452 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
3453 + >&${TMPF[FD]} 2>&1
3454 + then
3455 + Log.fatal "Update of ${NAME} failed"
3456 + return 66
3457 + fi
2952 3458
2953 -# Proxy Agent
2954 -LDAP_PROXYAGENT="$LDAP_PROXYAGENT"
2955 -LDAP_PROXYAGENT_CRED=$LDAP_PROXYAGENT_CRED
3459 + showProgress "Changed ${NAME} to ${INT[DS_SIZELIMIT]} in 'cn=config'."
3460 + return 0
3461 +}
2956 3462
2957 -# enableShadowUpdate flag and Administrator credential
2958 -LDAP_ENABLE_SHADOW_UPDATE=$LDAP_ENABLE_SHADOW_UPDATE
2959 -LDAP_ADMINDN="$LDAP_ADMINDN"
2960 -LDAP_ADMIN_CRED=$LDAP_ADMIN_CRED
3463 +Man.addFunc modify_pwd_crypt '' '[+NAME?modify_pwd_crypt - modify the passwd storage scheme to use CRYPT.]
3464 +[+DESCRIPTION?Set the default password policy of the DS to CRYPT.]
3465 +[+RETURN VALUES]{
3466 + [+0?on success.]
3467 + [+>= 66?a fatal error occurred.]
3468 +}
3469 +[+SEE ALSO?\bldapmodify\b(1).]
3470 +'
3471 +function modify_pwd_crypt {
3472 + # DS 5.2 moved passwordchangescheme off to a new data structure
3473 + typeset -a INFO=( ${TMP[DS_INFO]} )
3474 + typeset DN='cn=config' TARGET='passwordStorageScheme' VALUE='CRYPT' MSG=''
3475 + typeset FMT='dn: %s\nchangetype: modify\nreplace: %s\n%s: %s\n\n'
3476 + nextFile modify $0
2961 3477
2962 -# Export all the variables (just in case)
2963 -export IDS_HOME IDS_PORT LDAP_ROOTDN LDAP_ROOTPWD LDAP_SERVER_LIST LDAP_BASEDN
2964 -export LDAP_DOMAIN LDAP_SUFFIX LDAP_PROXYAGENT LDAP_PROXYAGENT_CRED
2965 -export NEED_PROXY
2966 -export LDAP_ENABLE_SHADOW_UPDATE LDAP_ADMINDN LDAP_ADMIN_CRED
2967 -export NEED_ADMIN NEED_HOSTACL EXISTING_PROFILE
2968 -export LDAP_PROFILE_NAME LDAP_BASEDN LDAP_SERVER_LIST
2969 -export LDAP_AUTHMETHOD LDAP_FOLLOWREF LDAP_SEARCH_SCOPE LDAP_SEARCH_TIME_LIMIT
2970 -export LDAP_PREF_SRVLIST LDAP_PROFILE_TTL LDAP_CRED_LEVEL LDAP_BIND_LIMIT
2971 -export NEED_SRVAUTH_PAM NEED_SRVAUTH_KEY NEED_SRVAUTH_CMD
2972 -export LDAP_SRV_AUTHMETHOD_PAM LDAP_SRV_AUTHMETHOD_KEY LDAP_SRV_AUTHMETHOD_CMD
2973 -export LDAP_SERV_SRCH_DES SSD_FILE GSSAPI_ENABLE LDAP_KRB_REALM
3478 + if (( TMPF[IS_OPENDJ] )); then
3479 + DN='cn=Default Password Policy,cn=Password Policies,cn=config'
3480 + TARGET='ds-cfg-default-password-storage-scheme'
3481 + VALUE='cn=CRYPT,cn=Password Storage Schemes,cn=config'
3482 + else
3483 + # DSEE
3484 + integer VER=$(( ${INFO[1]} * 1000 + ${INFO[2]} ))
3485 + (( VER >= 5002 )) && DN='cn=Password Policy,cn=config'
3486 + fi
3487 + printf "${FMT}" "${DN}" "${TARGET}" "${TARGET}" "${VALUE}" >${TMP[FILE]}
3488 + MSG="Changed '${TARGET}' to 'CRYPT'"
2974 3489
2975 -# Service Search Descriptors start here if present:
2976 -EOF
2977 - # Add service search descriptors.
2978 - ssd_2_config "${OUTPUT_FILE}"
3490 + if (( TMPF[IS_OPENDJ] )); then
3491 + if (( INT[NEED_CRYPT_IMPORT] )); then
3492 + TARGET='ds-cfg-allow-pre-encoded-passwords'
3493 + printf "${FMT}" "${DN}" "${TARGET}" "${TARGET}" 'true'>>${TMP[FILE]}
3494 + MSG+="and '${TARGET}' to 'true'"
3495 + fi
3496 + DN='cn=Password Policy Import,cn=Plugins,cn=config'
3497 + TARGET='ds-cfg-default-user-password-storage-scheme'
3498 + printf "${FMT}" "${DN}" "${TARGET}" "${TARGET}" "${VALUE}">>${TMP[FILE]}
3499 + fi
2979 3500
2980 - # Add LDAP suffix preferences
2981 - print_suffix_config >> "${OUTPUT_FILE}"
3501 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
3502 + >&${TMPF[FD]} 2>&1
3503 + then
3504 + Log.fatal 'Update of passwordStorageScheme failed'
3505 + return 66
3506 + fi
2982 3507
2983 - # Add the end of FILE tag.
2984 - ${ECHO} "" >> ${OUTPUT_FILE}
2985 - ${ECHO} "# End of $OUTPUT_FILE" >> ${OUTPUT_FILE}
3508 + showProgress "${MSG}."
3509 + return 0
2986 3510 }
2987 3511
2988 -
2989 -#
2990 -# chk_vlv_indexes(): Do ldapsearch to see if server supports VLV.
2991 -#
2992 -chk_vlv_indexes()
2993 -{
2994 - # Do ldapsearch to see if server supports VLV.
2995 - ${LDAPSEARCH} ${SERVER_ARGS} -b "" -s base "objectclass=*" > ${TMPDIR}/checkVLV 2>&1
2996 - eval "${GREP} 2.16.840.1.113730.3.4.9 ${TMPDIR}/checkVLV ${VERB}"
2997 - if [ $? -ne 0 ]; then
2998 - ${ECHO} "ERROR: VLV is not supported on LDAP server!"
2999 - cleanup
3000 - exit 1
3001 - fi
3002 - [ $DEBUG -eq 1 ] && ${ECHO} " VLV controls found on LDAP server."
3512 +Man.addFunc update_schema_attr '' '[+NAME?update_schema_attr - Update DS schema to support Naming Services.]
3513 +[+DESCRIPTION?Update the schema of the DS with the attribute types required for the Solaris Naming Services. It just checks, whether the OID is defined in the server schema. If already defined, it is left as is, otherwise added.]
3514 +[+RETURN VALUES]{
3515 + [+0?on success.]
3516 + [+>= 66?a fatal error occurred.]
3003 3517 }
3518 +[+SEE ALSO?\bldapmodify\b(1), \bgetDSattributes()\b.]
3519 +'
3520 +function update_schema_attr {
3004 3521
3005 -#
3006 -# get_backend(): this function gets the relevant backend
3007 -# (database) for LDAP_BASED.
3008 -# Description: set IDS_DATABASE; exit on failure.
3009 -# Prerequisite: LDAP_BASEDN and LDAP_SUFFIX are
3010 -# valid.
3011 -#
3012 -# backend is retrieved from suffixes and subsuffixes
3013 -# defined under "cn=mapping tree,cn=config". The
3014 -# nsslapd-state attribute of these suffixes entries
3015 -# is filled with either Backend, Disabled or referrals
3016 -# related values. We only want those that have a true
3017 -# backend database to select the relevant backend.
3018 -#
3019 -get_backend()
3020 -{
3021 - [ $DEBUG -eq 1 ] && ${ECHO} "In get_backend()"
3522 + # incorporate former 'keep_backward_compatibility()'
3523 + getDSattributes || return 66
3524 + typeset MEMBERGID_OID='1.3.6.1.4.1.42.2.27.5.1.30'
3525 + typeset DEF=${ANAME2OID['membergid-oid']}
3526 + [[ -n ${DEF} ]] && MEMBERGID_OID='memberGid-oid'
3527 + typeset RFC822MAILMEMBER_OID='1.3.6.1.4.1.42.2.27.2.1.15'
3528 + DEF=${ANAME2OID['rfc822mailmember-oid']}
3529 + [[ -n ${DEF} ]] && RFC822MAILMEMBER_OID='rfc822mailMember-oid'
3022 3530
3023 - cur_suffix=${LDAP_BASEDN}
3024 - prev_suffix=
3025 - IDS_DATABASE=
3026 - while [ "${cur_suffix}" != "${prev_suffix}" ]
3027 - do
3028 - [ $DEBUG -eq 1 ] && ${ECHO} "testing LDAP suffix: ${cur_suffix}"
3029 - eval "${LDAPSEARCH} ${LDAP_ARGS} " \
3030 - "-b \"cn=\\\"${cur_suffix}\\\",cn=mapping tree,cn=config\" " \
3031 - "-s base nsslapd-state=Backend nsslapd-backend 2>&1 " \
3032 - "| ${GREP} 'nsslapd-backend=' " \
3033 - "> ${TMPDIR}/ids_database_name 2>&1"
3034 - NUM_DBS=`wc -l ${TMPDIR}/ids_database_name | awk '{print $1}'`
3035 - case ${NUM_DBS} in
3036 - 0) # not a suffix, or suffix not activated; try next
3037 - prev_suffix=${cur_suffix}
3038 - cur_suffix=`${ECHO} ${cur_suffix} | cut -f2- -d','`
3039 - ;;
3040 - 1) # suffix found; get database name
3041 - IDS_DATABASE=`cat ${TMPDIR}/ids_database_name | cut -d= -f2`
3042 - ;;
3043 - *) # can not handle more than one database per suffix
3044 - ${ECHO} "ERROR: More than one database is configured "
3045 - ${ECHO} " for $LDAP_SUFFIX!"
3046 - ${ECHO} " $PROG can not configure suffixes where "
3047 - ${ECHO} " more than one database is used for one suffix."
3048 - cleanup
3049 - exit 1
3050 - ;;
3051 - esac
3052 - if [ -n "${IDS_DATABASE}" ]; then
3053 - break
3054 - fi
3055 - done
3531 + # EE and OD definitions seem to be compatible wrt. to Solaris. However, the
3532 + # OD defs usually specifies explicitly the server behavior (what happens, if
3533 + # EQUALITY|SUBSTR is not specified => caseIgnore[Substring]Match)) and
3534 + # sometimes a different kind of String to use (see RFC 4517):
3535 + # IA5 String: ASCII character in the range of 0..127
3536 + # Octet String: byte collection (0..255), usually not human readable,
3537 + # bytewise comparision
3538 + # Directory String: an UTF-8 string
3539 + # DN: basically an UTF-8 string, but with some constraints wrt. backslash
3540 + # escaping '\0', '"', '+', ',', ';', '<', '>', and '\'
3541 + # Boolean String: TRUE|FALSE
3542 + typeset -A EE=( )
3543 + typeset -A OD=( )
3544 + EE['1.3.6.1.1.1.1.28']="'nisPublickey' DESC 'NIS public key' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15"
3545 + OD['1.3.6.1.1.1.1.28']="'nisPublicKey' DESC 'NIS public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE X-ORIGIN 'draft-howard-rfc2307bis'" # Directory vs. Octet String
3056 3546
3057 - if [ -z "${IDS_DATABASE}" ]; then
3058 - # should not happen, since LDAP_BASEDN is supposed to be valid
3059 - ${ECHO} "Could not find a valid backend for ${LDAP_BASEDN}."
3060 - ${ECHO} "Exiting."
3061 - cleanup
3062 - exit 1
3063 - fi
3547 + EE['1.3.6.1.1.1.1.29']="'nisSecretkey' DESC 'NIS secret key' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15"
3548 + OD['1.3.6.1.1.1.1.29']="'nisSecretKey' DESC 'NIS secret key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE X-ORIGIN 'draft-howard-rfc2307bis'" # Directory vs. Octet String
3064 3549
3065 - [ $DEBUG -eq 1 ] && ${ECHO} "IDS_DATABASE: ${IDS_DATABASE}"
3066 -}
3550 + EE['1.3.6.1.1.1.1.30']="'nisDomain' DESC 'NIS domain' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15"
3551 + OD['1.3.6.1.1.1.1.30']="'nisDomain' DESC 'NIS domain' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'draft-howard-rfc2307bis'" # Directory vs. IA5 String
3067 3552
3068 -#
3069 -# validate_suffix(): This function validates ${LDAP_SUFFIX}
3070 -# THIS FUNCTION IS FOR THE LOAD CONFIG FILE OPTION.
3071 -#
3072 -validate_suffix()
3073 -{
3074 - [ $DEBUG -eq 1 ] && ${ECHO} "In validate_suffix()"
3553 + EE['1.3.6.1.1.1.1.31']="'automountMapName' DESC 'automount Map Name' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE"
3554 + OD['1.3.6.1.1.1.1.31']="'automountMapName' DESC 'automount Map Name' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'draft-howard-rfc2307bis'"
3075 3555
3076 - # Check LDAP_SUFFIX is not null
3077 - if [ -z "${LDAP_SUFFIX}" ]; then
3078 - ${ECHO} "Invalid suffix (null suffix)"
3079 - cleanup
3080 - exit 1
3081 - fi
3556 + EE['1.3.6.1.1.1.1.32']="'automountKey' DESC 'automount Key Value' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE"
3557 + OD['1.3.6.1.1.1.1.32']="'automountKey' DESC 'Automount Key value' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'draft-howard-rfc2307bis'"
3082 3558
3083 - # Check LDAP_SUFFIX and LDAP_BASEDN are consistent
3084 - # Convert to lower case for basename.
3085 - format_string "${LDAP_BASEDN}"
3086 - LOWER_BASEDN="${FMT_STR}"
3087 - format_string "${LDAP_SUFFIX}"
3088 - LOWER_SUFFIX="${FMT_STR}"
3559 + EE['1.3.6.1.1.1.1.33']="'automountInformation' DESC 'automount information' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE"
3560 + OD['1.3.6.1.1.1.1.33']="'automountInformation' DESC 'Automount information' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'draft-howard-rfc2307bis'"
3089 3561
3090 - [ $DEBUG -eq 1 ] && ${ECHO} "LOWER_BASEDN: ${LOWER_BASEDN}"
3091 - [ $DEBUG -eq 1 ] && ${ECHO} "LOWER_SUFFIX: ${LOWER_SUFFIX}"
3562 + EE['1.3.6.1.4.1.42.2.27.1.1.12']="'nisNetIdUser' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26"
3563 + OD['1.3.6.1.4.1.42.2.27.1.1.12']="'nisNetIdUser' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Solaris Specific'"
3092 3564
3093 - if [ "${LOWER_BASEDN}" != "${LOWER_SUFFIX}" ]; then
3094 - sub_basedn=`basename "${LOWER_BASEDN}" "${LOWER_SUFFIX}"`
3095 - if [ "$sub_basedn" = "${LOWER_BASEDN}" ]; then
3096 - ${ECHO} "Invalid suffix ${LOWER_SUFFIX}"
3097 - ${ECHO} "for Base DN ${LOWER_BASEDN}"
3098 - cleanup
3099 - exit 1
3100 - fi
3101 - fi
3565 + EE['1.3.6.1.4.1.42.2.27.1.1.13']="'nisNetIdGroup' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26"
3566 + OD['1.3.6.1.4.1.42.2.27.1.1.13']="'nisNetIdGroup' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Solaris Specific'"
3102 3567
3103 - # Check LDAP_SUFFIX does exist
3104 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_SUFFIX}\" -s base \"objectclass=*\" > ${TMPDIR}/checkSuffix 2>&1" && return 0
3568 + EE['1.3.6.1.4.1.42.2.27.1.1.14']="'nisNetIdHost' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26"
3569 + OD['1.3.6.1.4.1.42.2.27.1.1.14']="'nisNetIdHost' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Solaris Specific'"
3105 3570
3106 - # Well, suffix does not exist, try to prepare create it ...
3107 - NEED_CREATE_SUFFIX=1
3108 - prep_create_sfx_entry ||
3109 - {
3110 - cleanup
3111 - exit 1
3112 - }
3113 - [ -n "${NEED_CREATE_BACKEND}" ] &&
3114 - {
3115 - # try to use id attr value of the suffix as a database name
3116 - IDS_DATABASE=${_VAL}
3117 - prep_create_sfx_backend
3118 - case $? in
3119 - 1) # cann't use the name we want, so we can either exit or use
3120 - # some another available name - doing the last ...
3121 - IDS_DATABASE=${IDS_DATABASE_AVAIL}
3122 - ;;
3123 - 2) # unable to determine database name
3124 - cleanup
3125 - exit 1
3126 - ;;
3127 - esac
3128 - }
3571 + EE[${RFC822MAILMEMBER_OID}]="'rfc822mailMember' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26"
3572 + OD[${RFC822MAILMEMBER_OID}]="'rfc822mailMember' DESC 'rfc822 mail addresss of group member' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Solaris Specific'"
3129 3573
3130 - [ $DEBUG -eq 1 ] && ${ECHO} "Suffix $LDAP_SUFFIX, Database $IDS_DATABASE"
3131 -}
3574 + EE['2.16.840.1.113730.3.1.30']="'mgrpRFC822MailMember' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15"
3575 + OD['2.16.840.1.113730.3.1.30']="'mgrpRFC822MailMember' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Solaris Specific'"
3132 3576
3133 -#
3134 -# validate_info(): This function validates the basic info collected
3135 -# So that some problems are caught right away.
3136 -# THIS FUNCTION IS FOR THE LOAD CONFIG FILE OPTION.
3137 -#
3138 -validate_info()
3139 -{
3140 - [ $DEBUG -eq 1 ] && ${ECHO} "In validate_info()"
3577 + EE['1.3.6.1.4.1.42.2.27.5.1.15']="'SolarisLDAPServers' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15"
3578 + OD['1.3.6.1.4.1.42.2.27.5.1.15']="'SolarisLDAPServers' DESC 'LDAP Server address eg. 76.234.3.1:389' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3141 3579
3142 - # Set SERVER_ARGS, AUTH_ARGS, and LDAP_ARGS for the config file.
3143 - SERVER_ARGS="-h ${IDS_SERVER} -p ${IDS_PORT}"
3144 - AUTH_ARGS="-D \"${LDAP_ROOTDN}\" -j ${LDAP_ROOTPWF}"
3145 - LDAP_ARGS="${SERVER_ARGS} ${AUTH_ARGS}"
3146 - export SERVER_ARGS
3580 + EE['1.3.6.1.4.1.42.2.27.5.1.16']="'SolarisSearchBaseDN' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE"
3581 + OD['1.3.6.1.4.1.42.2.27.5.1.16']="'SolarisSearchBaseDN' DESC 'Search Base Distinguished Name' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # DN vs. Directory String
3147 3582
3148 - # Check the Root DN and Root DN passwd.
3149 - # Use eval instead of $EVAL because not part of setup. (validate)
3150 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"\" -s base \"objectclass=*\" > ${TMPDIR}/checkDN 2>&1"
3151 - if [ $? -ne 0 ]; then
3152 - eval "${GREP} credential ${TMPDIR}/checkDN ${VERB}"
3153 - if [ $? -eq 0 ]; then
3154 - ${ECHO} "ERROR: Root DN passwd is invalid."
3155 - else
3156 - ${ECHO} "ERROR2: Invalid Root DN <${LDAP_ROOTDN}>."
3157 - fi
3158 - cleanup
3159 - exit 1
3160 - fi
3161 - [ $DEBUG -eq 1 ] && ${ECHO} " RootDN ... OK"
3162 - [ $DEBUG -eq 1 ] && ${ECHO} " RootDN passwd ... OK"
3583 + EE['1.3.6.1.4.1.42.2.27.5.1.17']="'SolarisCacheTTL' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3584 + OD['1.3.6.1.4.1.42.2.27.5.1.17']="'SolarisCacheTTL' DESC 'TTL value for the Domain information eg. 1w, 2d, 3h, 10m, or 5s' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3163 3585
3164 - # Check if the server supports the VLV.
3165 - chk_vlv_indexes
3166 - [ $DEBUG -eq 1 ] && ${ECHO} " VLV indexes ... OK"
3586 + EE['1.3.6.1.4.1.42.2.27.5.1.18']="'SolarisBindDN' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE"
3587 + OD['1.3.6.1.4.1.42.2.27.5.1.18']="'SolarisBindDN' DESC 'DN to be used to bind to the directory as proxy' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # DN vs. Directory String
3167 3588
3168 - # Check LDAP suffix
3169 - validate_suffix
3170 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP suffix ... OK"
3171 -}
3589 + EE['1.3.6.1.4.1.42.2.27.5.1.19']="'SolarisBindPassword' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE"
3590 + OD['1.3.6.1.4.1.42.2.27.5.1.19']="'SolarisBindPassword' DESC 'Password for bindDN to authenticate to the directory' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # IA5 vs. Octet String
3172 3591
3173 -#
3174 -# format_string(): take a string as argument and set FMT_STR
3175 -# to be the same string formatted as follow:
3176 -# - only lower case characters
3177 -# - no unnecessary spaces around , and =
3178 -#
3179 -format_string()
3180 -{
3181 - FMT_STR=`${ECHO} "$1" | tr '[A-Z]' '[a-z]' |
3182 - sed -e 's/[ ]*,[ ]*/,/g' -e 's/[ ]*=[ ]*/=/g'`
3183 -}
3592 + EE['1.3.6.1.4.1.42.2.27.5.1.20']="'SolarisAuthMethod' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15"
3593 + OD['1.3.6.1.4.1.42.2.27.5.1.20']="'SolarisAuthMethod' DESC 'Authentication method to be used eg. \"NS_LDAP_AUTH_NONE\", \"NS_LDAP_AUTH_SIMPLE\" or \"NS_LDAP_AUTH_SASL_CRAM_MD5\"' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3184 3594
3185 -#
3186 -# prepare for the suffix entry creation
3187 -#
3188 -# input : LDAP_BASEDN, LDAP_SUFFIX - base dn and suffix;
3189 -# in/out : LDAP_SUFFIX_OBJ, LDAP_SUFFIX_ACI - initially may come from config.
3190 -# output : NEED_CREATE_BACKEND - backend for this suffix needs to be created;
3191 -# _RDN, _ATT, _VAL - suffix's RDN, id attribute name and its value.
3192 -# return : 0 - success, otherwise error.
3193 -#
3194 -prep_create_sfx_entry()
3195 -{
3196 - [ $DEBUG -eq 1 ] && ${ECHO} "In prep_create_sfx_entry()"
3595 + EE['1.3.6.1.4.1.42.2.27.5.1.21']="'SolarisTransportSecurity' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15"
3596 + OD['1.3.6.1.4.1.42.2.27.5.1.21']="'SolarisTransportSecurity' DESC 'Transport Level Security method to be used eg. \"NS_LDAP_SEC_NONE\" or \"NS_LDAP_SEC_SASL_TLS\"' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3197 3597
3198 - # check whether suffix corresponds to base dn
3199 - format_string "${LDAP_BASEDN}"
3200 - ${ECHO} ",${FMT_STR}" | ${GREP} ",${LDAP_SUFFIX}$" >/dev/null 2>&1 ||
3201 - {
3202 - display_msg sfx_not_suitable
3203 - return 1
3204 - }
3598 + EE['1.3.6.1.4.1.42.2.27.5.1.22']="'SolarisCertificatePath' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE"
3599 + OD['1.3.6.1.4.1.42.2.27.5.1.22']="'SolarisCertificatePath' DESC 'Path to certificate file/device' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'"
3205 3600
3206 - # parse LDAP_SUFFIX
3207 - _RDN=`${ECHO} "${LDAP_SUFFIX}" | cut -d, -f1`
3208 - _ATT=`${ECHO} "${_RDN}" | cut -d= -f1`
3209 - _VAL=`${ECHO} "${_RDN}" | cut -d= -f2-`
3601 + EE['1.3.6.1.4.1.42.2.27.5.1.23']="'SolarisCertificatePassword' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE"
3602 + OD['1.3.6.1.4.1.42.2.27.5.1.23']="'SolarisCertificatePassword' DESC 'Password or PIN that grants access to certificate.' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # IA5 vs. Octet String
3210 3603
3211 - # find out an objectclass for suffix entry if it is not defined yet
3212 - [ -z "${LDAP_SUFFIX_OBJ}" ] &&
3213 - {
3214 - get_objectclass ${_ATT}
3215 - [ -z "${_ATTR_NAME}" ] &&
3216 - {
3217 - display_msg obj_not_found
3218 - return 1
3219 - }
3220 - LDAP_SUFFIX_OBJ=${_ATTR_NAME}
3221 - }
3222 - [ $DEBUG -eq 1 ] && ${ECHO} "Suffix entry object is ${LDAP_SUFFIX_OBJ}"
3604 + EE['1.3.6.1.4.1.42.2.27.5.1.24']="'SolarisDataSearchDN' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15"
3605 + OD['1.3.6.1.4.1.42.2.27.5.1.24']="'SolarisDataSearchDN' DESC 'Search DN for data lookup in \":(DN0),(DN1),...\" format' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Solaris Specific'"
3223 3606
3224 - # find out an aci for suffix entry if it is not defined yet
3225 - [ -z "${LDAP_SUFFIX_ACI}" ] &&
3226 - {
3227 - # set Directory Server default aci
3228 - LDAP_SUFFIX_ACI=`cat <<EOF
3229 -aci: (targetattr != "userPassword || passwordHistory || passwordExpirationTime
3230 - || passwordExpWarned || passwordRetryCount || retryCountResetTime ||
3231 - accountUnlockTime || passwordAllowChangeTime")
3232 - (
3233 - version 3.0;
3234 - acl "Anonymous access";
3235 - allow (read, search, compare) userdn = "ldap:///anyone";
3236 - )
3237 -aci: (targetattr != "nsroledn || aci || nsLookThroughLimit || nsSizeLimit ||
3238 - nsTimeLimit || nsIdleTimeout || passwordPolicySubentry ||
3239 - passwordExpirationTime || passwordExpWarned || passwordRetryCount ||
3240 - retryCountResetTime || accountUnlockTime || passwordHistory ||
3241 - passwordAllowChangeTime")
3242 - (
3243 - version 3.0;
3244 - acl "Allow self entry modification except for some attributes";
3245 - allow (write) userdn = "ldap:///self";
3246 - )
3247 -aci: (targetattr = "*")
3248 - (
3249 - version 3.0;
3250 - acl "Configuration Administrator";
3251 - allow (all) userdn = "ldap:///uid=admin,ou=Administrators,
3252 - ou=TopologyManagement,o=NetscapeRoot";
3253 - )
3254 -aci: (targetattr ="*")
3255 - (
3256 - version 3.0;
3257 - acl "Configuration Administrators Group";
3258 - allow (all) groupdn = "ldap:///cn=Configuration Administrators,
3259 - ou=Groups,ou=TopologyManagement,o=NetscapeRoot";
3260 - )
3261 -EOF
3262 -`
3263 - }
3264 - [ $DEBUG -eq 1 ] && cat <<EOF
3265 -DEBUG: ACI for ${LDAP_SUFFIX} is
3266 -${LDAP_SUFFIX_ACI}
3267 -EOF
3607 + EE['1.3.6.1.4.1.42.2.27.5.1.25']="'SolarisSearchScope' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3608 + OD['1.3.6.1.4.1.42.2.27.5.1.25']="'SolarisSearchScope' DESC 'Scope to be used for search operations eg. \"NS_LDAP_SCOPE_BASE\", \"NS_LDAP_SCOPE_ONELEVEL\" or \"NS_LDAP_SCOPE_SUBTREE\"' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3268 3609
3269 - NEED_CREATE_BACKEND=
3610 + EE['1.3.6.1.4.1.42.2.27.5.1.26']="'SolarisSearchTimeLimit' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE"
3611 + OD['1.3.6.1.4.1.42.2.27.5.1.26']="'SolarisSearchTimeLimit' DESC 'Time Limit in seconds for search operations' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Solaris Specific'"
3270 3612
3271 - # check the suffix mapping tree ...
3272 - # if mapping exists, suffix should work, otherwise DS inconsistent
3273 - # NOTE: -b 'cn=mapping tree,cn=config' -s one 'cn=\"$1\"' won't work
3274 - # in case of 'cn' value in LDAP is not quoted by '"',
3275 - # -b 'cn=\"$1\",cn=mapping tree,cn=config' works in all cases
3276 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} \
3277 - -b 'cn=\"${LDAP_SUFFIX}\",cn=mapping tree,cn=config' \
3278 - -s base 'objectclass=*' dn ${VERB}" &&
3279 - {
3280 - [ $DEBUG -eq 1 ] && ${ECHO} "Suffix mapping already exists"
3281 - # get_backend() either gets IDS_DATABASE or exits
3282 - get_backend
3283 - return 0
3284 - }
3613 + EE['1.3.6.1.4.1.42.2.27.5.1.27']="'SolarisPreferredServer' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15"
3614 + OD['1.3.6.1.4.1.42.2.27.5.1.27']="'SolarisPreferredServer' DESC 'Preferred LDAP Server address or network number' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3285 3615
3286 - # no suffix mapping, just in case check ldbm backends consistency -
3287 - # there are must be NO any databases pointing to LDAP_SUFFIX
3288 - [ -n "`${EVAL} \"${LDAPSEARCH} ${LDAP_ARGS} \
3289 - -b 'cn=ldbm database,cn=plugins,cn=config' \
3290 - -s one 'nsslapd-suffix=${LDAP_SUFFIX}' dn\" 2>/dev/null`" ] &&
3291 - {
3292 - display_msg sfx_config_incons
3293 - return 1
3294 - }
3616 + EE['1.3.6.1.4.1.42.2.27.5.1.28']="'SolarisPreferredServerOnly' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3617 + OD['1.3.6.1.4.1.42.2.27.5.1.28']="'SolarisPreferredServerOnly' DESC 'Boolean flag for use of preferredServer or not' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. Boolean String
3295 3618
3296 - # ok, no suffix mapping, no ldbm database
3297 - [ $DEBUG -eq 1 ] && ${ECHO} "DEBUG: backend needs to be created ..."
3298 - NEED_CREATE_BACKEND=1
3299 - return 0
3300 -}
3619 + EE['1.3.6.1.4.1.42.2.27.5.1.29']="'SolarisSearchReferral' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3620 + OD['1.3.6.1.4.1.42.2.27.5.1.29']="'SolarisSearchReferral' DESC 'referral chasing option eg. \"NS_LDAP_NOREF\" or \"NS_LDAP_FOLLOWREF\"' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3301 3621
3302 -#
3303 -# prepare for the suffix backend creation
3304 -#
3305 -# input : IDS_DATABASE - requested ldbm db name (must be not null)
3306 -# in/out : IDS_DATABASE_AVAIL - available ldbm db name
3307 -# return : 0 - ldbm db name ok
3308 -# 1 - IDS_DATABASE exists,
3309 -# so IDS_DATABASE_AVAIL contains available name
3310 -# 2 - unable to find any available name
3311 -#
3312 -prep_create_sfx_backend()
3313 -{
3314 - [ $DEBUG -eq 1 ] && ${ECHO} "In prep_create_sfx_backend()"
3622 + EE['1.3.6.1.4.1.42.2.27.5.1.4']="'SolarisAttrKeyValue' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3623 + OD['1.3.6.1.4.1.42.2.27.5.1.4']="'SolarisAttrKeyValue' DESC 'Semi-colon separated key=value pairs of attributes' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3315 3624
3316 - # check if requested name available
3317 - [ "${IDS_DATABASE}" = "${IDS_DATABASE_AVAIL}" ] && return 0
3625 + EE['1.3.6.1.4.1.42.2.27.5.1.5']="'SolarisAuditAlways' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3626 + OD['1.3.6.1.4.1.42.2.27.5.1.5']="'SolarisAuditAlways' DESC 'Always audited attributes per-user' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3318 3627
3319 - # get the list of database names start with a requested name
3320 - _LDBM_DBS=`${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} \
3321 - -b 'cn=ldbm database,cn=plugins,cn=config' \
3322 - -s one 'cn=${IDS_DATABASE}*' cn"` 2>/dev/null
3628 + EE['1.3.6.1.4.1.42.2.27.5.1.6']="'SolarisAuditNever' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3629 + OD['1.3.6.1.4.1.42.2.27.5.1.6']="'SolarisAuditNever' DESC 'Never audited attributes per-user' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3323 3630
3324 - # find available db name based on a requested name
3325 - _i=""; _i_MAX=10
3326 - while [ ${_i:-0} -lt ${_i_MAX} ]
3327 - do
3328 - _name="${IDS_DATABASE}${_i}"
3329 - ${ECHO} "${_LDBM_DBS}" | ${GREP} -i "^cn=${_name}$" >/dev/null 2>&1 ||
3330 - {
3331 - IDS_DATABASE_AVAIL="${_name}"
3332 - break
3333 - }
3334 - _i=`expr ${_i:-0} + 1`
3335 - done
3631 + EE['1.3.6.1.4.1.42.2.27.5.1.7']="'SolarisAttrShortDesc' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3632 + OD['1.3.6.1.4.1.42.2.27.5.1.7']="'SolarisAttrShortDesc' DESC 'Short description about an entry, used by GUIs' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3336 3633
3337 - [ "${IDS_DATABASE}" = "${IDS_DATABASE_AVAIL}" ] && return 0
3634 + EE['1.3.6.1.4.1.42.2.27.5.1.8']="'SolarisAttrLongDesc' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3635 + OD['1.3.6.1.4.1.42.2.27.5.1.8']="'SolarisAttrLongDesc' DESC 'Detail description about an entry' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3338 3636
3339 - [ -n "${IDS_DATABASE_AVAIL}" ] &&
3340 - {
3341 - display_msg ldbm_db_exist
3342 - return 1
3343 - }
3637 + EE['1.3.6.1.4.1.42.2.27.5.1.9']="'SolarisKernelSecurityPolicy' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3638 + OD['1.3.6.1.4.1.42.2.27.5.1.9']="'SolarisKernelSecurityPolicy' DESC 'Solaris kernel security policy' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3344 3639
3345 - display_msg unable_find_db_name
3346 - return 2
3347 -}
3640 + EE['1.3.6.1.4.1.42.2.27.5.1.10']="'SolarisProfileType' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3641 + OD['1.3.6.1.4.1.42.2.27.5.1.10']="'SolarisProfileType' DESC 'Type of object defined in profile'EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3348 3642
3349 -#
3350 -# add suffix if needed,
3351 -# suffix entry and backend MUST be prepared by
3352 -# prep_create_sfx_entry and prep_create_sfx_backend correspondingly
3353 -#
3354 -# input : NEED_CREATE_SUFFIX, LDAP_SUFFIX, LDAP_SUFFIX_OBJ, _ATT, _VAL
3355 -# LDAP_SUFFIX_ACI, NEED_CREATE_BACKEND, IDS_DATABASE
3356 -# return : 0 - suffix successfully created, otherwise error occured
3357 -#
3358 -add_suffix()
3359 -{
3360 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_suffix()"
3643 + EE['1.3.6.1.4.1.42.2.27.5.1.11']="'SolarisProfileId' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE"
3644 + OD['1.3.6.1.4.1.42.2.27.5.1.11']="'SolarisProfileId' DESC 'Identifier of object defined in profile' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'"
3361 3645
3362 - [ -n "${NEED_CREATE_SUFFIX}" ] || return 0
3646 + EE['1.3.6.1.4.1.42.2.27.5.1.12']="'SolarisUserQualifier' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3647 + OD['1.3.6.1.4.1.42.2.27.5.1.12']="'SolarisUserQualifier' DESC 'Per-user login attributes' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3363 3648
3364 - [ -n "${NEED_CREATE_BACKEND}" ] &&
3365 - {
3366 - ${EVAL} "${LDAPADD} ${LDAP_ARGS} ${VERB}" <<EOF
3367 -dn: cn="${LDAP_SUFFIX}",cn=mapping tree,cn=config
3368 -objectclass: top
3369 -objectclass: extensibleObject
3370 -objectclass: nsMappingTree
3371 -cn: ${LDAP_SUFFIX}
3372 -nsslapd-state: backend
3373 -nsslapd-backend: ${IDS_DATABASE}
3649 + EE['1.3.6.1.4.1.42.2.27.5.1.13']="'SolarisAttrReserved1' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3650 + OD['1.3.6.1.4.1.42.2.27.5.1.13']="'SolarisAttrReserved1' DESC 'Reserved for future use' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3374 3651
3375 -dn: cn=${IDS_DATABASE},cn=ldbm database,cn=plugins,cn=config
3376 -objectclass: top
3377 -objectclass: extensibleObject
3378 -objectclass: nsBackendInstance
3379 -cn: ${IDS_DATABASE}
3380 -nsslapd-suffix: ${LDAP_SUFFIX}
3381 -EOF
3382 - [ $? -ne 0 ] &&
3383 - {
3384 - display_msg create_ldbm_db_error
3385 - return 1
3386 - }
3652 + EE['1.3.6.1.4.1.42.2.27.5.1.14']="'SolarisAttrReserved2' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3653 + OD['1.3.6.1.4.1.42.2.27.5.1.14']="'SolarisAttrReserved2' DESC 'Reserved for future use' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'" # Directory vs. IA5 String
3387 3654
3388 - ${ECHO} " ${STEP}. Database ${IDS_DATABASE} successfully created"
3389 - STEP=`expr $STEP + 1`
3390 - }
3655 + EE['1.3.6.1.4.1.42.2.27.5.1.1']="'SolarisProjectID' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE"
3656 + OD['1.3.6.1.4.1.42.2.27.5.1.1']="'SolarisProjectID' DESC 'Unique ID for a Solaris Project entry' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Solaris Specific'"
3391 3657
3392 - ${EVAL} "${LDAPADD} ${LDAP_ARGS} ${VERB}" <<EOF
3393 -dn: ${LDAP_SUFFIX}
3394 -objectclass: ${LDAP_SUFFIX_OBJ}
3395 -${_ATT}: ${_VAL}
3396 -${LDAP_SUFFIX_ACI}
3397 -EOF
3398 - [ $? -ne 0 ] &&
3399 - {
3400 - display_msg create_suffix_entry_error
3401 - return 1
3402 - }
3658 + EE['1.3.6.1.4.1.42.2.27.5.1.2']="'SolarisProjectName' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE"
3659 + OD['1.3.6.1.4.1.42.2.27.5.1.2']="'SolarisProjectName' DESC 'Name of a Solaris Project Entry' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'"
3403 3660
3404 - ${ECHO} " ${STEP}. Suffix ${LDAP_SUFFIX} successfully created"
3405 - STEP=`expr $STEP + 1`
3406 - return 0
3407 -}
3661 + EE['1.3.6.1.4.1.42.2.27.5.1.3']="'SolarisProjectAttr' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26"
3662 + OD['1.3.6.1.4.1.42.2.27.5.1.3']="'SolarisProjectAttr' DESC 'Attributes of a Solaris Project entry' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'"
3408 3663
3409 -#
3410 -# interactively get suffix and related info from a user
3411 -#
3412 -# input : LDAP_BASEDN - Base DN
3413 -# output : LDAP_SUFFIX - Suffix, _ATT, _VAL - id attribute and its value;
3414 -# LDAP_SUFFIX_OBJ, LDAP_SUFFIX_ACI - objectclass and aci;
3415 -# NEED_CREATE_BACKEND - tells whether backend needs to be created;
3416 -# IDS_DATABASE - prepared ldbm db name
3417 -# return : 0 - user gave a correct suffix
3418 -# 1 - suffix given by user cann't be created
3419 -#
3420 -get_suffix()
3421 -{
3422 - [ $DEBUG -eq 1 ] && ${ECHO} "In get_suffix()"
3664 + EE[${MEMBERGID_OID}]="'memberGid' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26"
3665 + OD[${MEMBERGID_OID}]="'memberGid' DESC 'Posix Group Name' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'Solaris Specific'"
3423 3666
3424 - while :
3425 - do
3426 - get_ans "Enter suffix to be created (b=back/h=help):" ${LDAP_BASEDN}
3427 - case "${ANS}" in
3428 - [Hh] | Help | help | \? ) display_msg create_suffix_help ;;
3429 - [Bb] | Back | back | \< ) return 1 ;;
3430 - * )
3431 - format_string "${ANS}"
3432 - LDAP_SUFFIX=${FMT_STR}
3433 - prep_create_sfx_entry || continue
3667 + EE['1.3.6.1.4.1.11.1.3.1.1.0']="'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"
3668 + OD['1.3.6.1.4.1.11.1.3.1.1.0']="'defaultServerList' DESC 'List of default servers' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'RFC 4876'"
3434 3669
3435 - [ -n "${NEED_CREATE_BACKEND}" ] &&
3436 - {
3437 - IDS_DATABASE_AVAIL= # reset the available db name
3670 + EE['1.3.6.1.4.1.11.1.3.1.1.1']="'defaultSearchBase' DESC 'Default LDAP base DN used by a DUA' SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE"
3671 + OD['1.3.6.1.4.1.11.1.3.1.1.1']="'defaultSearchBase' DESC 'Default base for searches' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN 'RFC 4876'"
3438 3672
3439 - reenter_suffix=
3440 - while :
3441 - do
3442 - get_ans "Enter ldbm database name (b=back/h=help):" \
3443 - ${IDS_DATABASE_AVAIL:-${_VAL}}
3444 - case "${ANS}" in
3445 - [Hh] | \? ) display_msg enter_ldbm_db_help ;;
3446 - [Bb] | \< ) reenter_suffix=1; break ;;
3447 - * )
3448 - IDS_DATABASE="${ANS}"
3449 - prep_create_sfx_backend && break
3450 - esac
3451 - done
3452 - [ -n "${reenter_suffix}" ] && continue
3673 + EE['1.3.6.1.4.1.11.1.3.1.1.2']="'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"
3674 + OD['1.3.6.1.4.1.11.1.3.1.1.2']="'preferredServerList' DESC 'List of preferred servers' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'RFC 4876'"
3453 3675
3454 - [ $DEBUG -eq 1 ] && cat <<EOF
3455 -DEBUG: backend name for suffix ${LDAP_SUFFIX} will be ${IDS_DATABASE}
3456 -EOF
3457 - }
3676 + EE['1.3.6.1.4.1.11.1.3.1.1.3']="'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"
3677 + OD['1.3.6.1.4.1.11.1.3.1.1.3']="'searchTimeLimit' DESC 'Maximum time an agent or service allows for a search to complete' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'RFC 4876'"
3458 3678
3459 - # eventually everything is prepared
3460 - return 0
3461 - ;;
3462 - esac
3463 - done
3464 -}
3679 + EE['1.3.6.1.4.1.11.1.3.1.1.4']="'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"
3680 + OD['1.3.6.1.4.1.11.1.3.1.1.4']="'bindTimeLimit' DESC 'Maximum time an agent or service allows for a bind operation to complete' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'RFC 4876'"
3465 3681
3466 -#
3467 -# print out a script which sets LDAP suffix related preferences
3468 -#
3469 -print_suffix_config()
3470 -{
3471 - cat <<EOF2
3472 -# LDAP suffix related preferences used only if needed
3473 -IDS_DATABASE="${IDS_DATABASE}"
3474 -LDAP_SUFFIX_OBJ="$LDAP_SUFFIX_OBJ"
3475 -LDAP_SUFFIX_ACI=\`cat <<EOF
3476 -${LDAP_SUFFIX_ACI}
3477 -EOF
3478 -\`
3479 -export IDS_DATABASE LDAP_SUFFIX_OBJ LDAP_SUFFIX_ACI
3480 -EOF2
3481 -}
3682 + EE['1.3.6.1.4.1.11.1.3.1.1.5']="'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"
3683 + OD['1.3.6.1.4.1.11.1.3.1.1.5']="'followReferrals' DESC 'An agent or service does or should follow referrals' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'RFC 4876'" # Directory vs. Boolean String
3482 3684
3483 -#
3484 -# check_basedn_suffix(): check that there is an existing
3485 -# valid suffix to hold current base DN
3486 -# return:
3487 -# 0: valid suffix found or new one should be created,
3488 -# NEED_CREATE_SUFFIX flag actually indicates that
3489 -# 1: some error occures
3490 -#
3491 -check_basedn_suffix()
3492 -{
3493 - [ $DEBUG -eq 1 ] && ${ECHO} "In check_basedn_suffix()"
3685 + EE['1.3.6.1.4.1.11.1.3.1.1.6']="'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"
3686 + OD['1.3.6.1.4.1.11.1.3.1.1.6']="'authenticationMethod' DESC 'Identifies the types of authentication methods either used, required, or provided by a service or peer' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'RFC 4876'"
3494 3687
3495 - NEED_CREATE_SUFFIX=
3688 + EE['1.3.6.1.4.1.11.1.3.1.1.7']="'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"
3689 + OD['1.3.6.1.4.1.11.1.3.1.1.7']="'profileTTL' DESC 'Time to live, in seconds, before a profile is considered stale' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'RFC 4876'"
3496 3690
3497 - # find out existing suffixes
3498 - discover_serv_suffix
3691 + EE['1.3.6.1.4.1.11.1.3.1.1.14']="'serviceSearchDescriptor' DESC 'LDAP search descriptor list used by Naming-DUA' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26"
3692 + OD['1.3.6.1.4.1.11.1.3.1.1.14']="'serviceSearchDescriptor' DESC 'Specifies search descriptors required, used, or supported by a particular service or agent' EQUALITY caseExactMatch SUBSTR caseExactSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 4876'" # IA5 vs. Directory String
3499 3693
3500 - ${ECHO} " Validating LDAP Base DN and Suffix ..."
3694 + EE['1.3.6.1.4.1.11.1.3.1.1.9']="'attributeMap' DESC 'Attribute mappings used by a Naming-DUA' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15"
3695 + OD['1.3.6.1.4.1.11.1.3.1.1.9']="'attributeMap' DESC 'Attribute mappings used, required, or supported by an agent or service' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'RFC 4876'" # Directory vs. IA5 String
3501 3696
3502 - # check that LDAP Base DN might be added
3503 - cur_ldap_entry=${LDAP_BASEDN}
3504 - prev_ldap_entry=
3505 - while [ "${cur_ldap_entry}" != "${prev_ldap_entry}" ]
3506 - do
3507 - [ $DEBUG -eq 1 ] && ${ECHO} "testing LDAP entry: ${cur_ldap_entry}"
3508 - ${LDAPSEARCH} ${SERVER_ARGS} -b "${cur_ldap_entry}" \
3509 - -s one "objectclass=*" > /dev/null 2>&1
3510 - if [ $? -eq 0 ]; then
3511 - break
3512 - else
3513 - prev_ldap_entry=${cur_ldap_entry}
3514 - cur_ldap_entry=`${ECHO} ${cur_ldap_entry} | cut -f2- -d','`
3515 - fi
3516 - done
3697 + EE['1.3.6.1.4.1.11.1.3.1.1.10']="'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"
3698 + OD['1.3.6.1.4.1.11.1.3.1.1.10']="'credentialLevel' DESC 'Identifies type of credentials either used, required, or supported by an agent or service' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'RFC 4876'" # Directory vs. IA5 String
3517 3699
3518 - if [ "${cur_ldap_entry}" = "${prev_ldap_entry}" ]; then
3519 - ${ECHO} " No valid suffixes were found for Base DN ${LDAP_BASEDN}"
3700 + EE['1.3.6.1.4.1.11.1.3.1.1.11']="'objectclassMap' DESC 'Objectclass mappings used by a Naming-DUA' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15"
3701 + OD['1.3.6.1.4.1.11.1.3.1.1.11']="'objectclassMap' DESC 'Object class mappings used, required, or supported by an agent or service' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'RFC 4876'" # Directory vs. IA5 String
3520 3702
3521 - NEED_CREATE_SUFFIX=1
3522 - return 0
3703 + EE['1.3.6.1.4.1.11.1.3.1.1.12']="'defaultSearchScope' DESC 'Default search scope used by a DUA' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
3704 + OD['1.3.6.1.4.1.11.1.3.1.1.12']="'defaultSearchScope' DESC 'Default scope used when performing a search' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'RFC 4876'" # Directory vs. IA5 String
3523 3705
3524 - else
3525 - [ $DEBUG -eq 1 ] && ${ECHO} "found valid LDAP entry: ${cur_ldap_entry}"
3706 + EE['1.3.6.1.4.1.11.1.3.1.1.13']="'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"
3707 + OD['1.3.6.1.4.1.11.1.3.1.1.13']="'serviceCredentialLevel' DESC 'Specifies the type of credentials either used, required, or supported by a specific service' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'RFC 4876'"
3526 3708
3527 - # Now looking for relevant suffix for this entry.
3528 - # LDAP_SUFFIX will then be used to add necessary
3529 - # base objects. See add_base_objects().
3530 - format_string "${cur_ldap_entry}"
3531 - lower_entry="${FMT_STR}"
3532 - [ $DEBUG -eq 1 ] && ${ECHO} "final suffix list: ${LDAP_SUFFIX_LIST}"
3533 - oIFS=$IFS
3534 - [ $DEBUG -eq 1 ] && ${ECHO} "setting IFS to new line"
3535 - IFS='
3536 -'
3537 - for suff in ${LDAP_SUFFIX_LIST}
3538 - do
3539 - [ $DEBUG -eq 1 ] && ${ECHO} "testing suffix: ${suff}"
3540 - format_string "${suff}"
3541 - lower_suff="${FMT_STR}"
3542 - if [ "${lower_entry}" = "${lower_suff}" ]; then
3543 - LDAP_SUFFIX="${suff}"
3544 - break
3545 - else
3546 - dcstmp=`basename "${lower_entry}" "${lower_suff}"`
3547 - if [ "${dcstmp}" = "${lower_entry}" ]; then
3548 - # invalid suffix, try next one
3549 - continue
3550 - else
3551 - # valid suffix found
3552 - LDAP_SUFFIX="${suff}"
3553 - break
3554 - fi
3555 - fi
3556 - done
3557 - [ $DEBUG -eq 1 ] && ${ECHO} "setting IFS to original value"
3558 - IFS=$oIFS
3709 + EE['1.3.6.1.4.1.11.1.3.1.1.15']="'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"
3710 + OD['1.3.6.1.4.1.11.1.3.1.1.15']="'serviceAuthenticationMethod' DESC 'Specifies types authentication methods either used, required, or supported by a particular service' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 4876'"
3559 3711
3560 - [ $DEBUG -eq 1 ] && ${ECHO} "LDAP_SUFFIX: ${LDAP_SUFFIX}"
3712 + EE['1.3.18.0.2.4.1140']="'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"
3713 + OD['1.3.18.0.2.4.1140']="'printer-uri' DESC 'A URI supported by this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3561 3714
3562 - if [ -z "${LDAP_SUFFIX}" ]; then
3563 - # should not happen, since we found the entry
3564 - ${ECHO} "Could not find a valid suffix for ${LDAP_BASEDN}."
3565 - ${ECHO} "Exiting."
3566 - return 1
3567 - fi
3568 -
3569 - # Getting relevant database (backend)
3570 - # IDS_DATABASE will then be used to create indexes.
3571 - get_backend
3715 + EE['1.3.18.0.2.4.1107']="'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"
3716 + OD['1.3.18.0.2.4.1107']="'printer-xri-supported' DESC 'The unordered list of XRI (extended resource identifiers) supported by this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'RFC 3712'"
3572 3717
3573 - return 0
3574 - fi
3575 -}
3718 + EE['1.3.18.0.2.4.1135']="'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"
3719 + OD['1.3.18.0.2.4.1135']="'printer-name' DESC 'The site-specific administrative name of this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3576 3720
3577 -#
3578 -# discover_serv_suffix(): This function queries the server to find
3579 -# suffixes available
3580 -# return: 0: OK, suffix found
3581 -# 1: suffix not determined
3582 -discover_serv_suffix()
3583 -{
3584 - [ $DEBUG -eq 1 ] && ${ECHO} "In discover_serv_suffix()"
3721 + EE['1.3.18.0.2.4.1119']="'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"
3722 + OD['1.3.18.0.2.4.1119']="'printer-natural-language-configured' DESC 'The configured natural language in which error and status messages will be generated (by default) by this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3585 3723
3586 - # Search the server for the TOP of the TREE.
3587 - ${LDAPSEARCH} ${SERVER_ARGS} -b "" -s base "objectclass=*" > ${TMPDIR}/checkTOP 2>&1
3588 - ${GREP} -i namingcontexts ${TMPDIR}/checkTOP | \
3589 - ${GREP} -i -v NetscapeRoot > ${TMPDIR}/treeTOP
3590 - NUM_TOP=`wc -l ${TMPDIR}/treeTOP | awk '{print $1}'`
3591 - case $NUM_TOP in
3592 - 0)
3593 - [ $DEBUG -eq 1 ] && ${ECHO} "DEBUG: No suffix found in LDAP tree"
3594 - return 1
3595 - ;;
3596 - *) # build the list of suffixes; take out 'namingContexts=' in
3597 - # each line of ${TMPDIR}/treeTOP
3598 - LDAP_SUFFIX_LIST=`cat ${TMPDIR}/treeTOP |
3599 - awk '{ printf("%s\n",substr($0,16,length-15)) }'`
3600 - ;;
3601 - esac
3724 + EE['1.3.18.0.2.4.1136']="'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"
3725 + OD['1.3.18.0.2.4.1136']="'printer-location' DESC 'The physical location of this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3602 3726
3603 - [ $DEBUG -eq 1 ] && ${ECHO} " LDAP_SUFFIX_LIST = $LDAP_SUFFIX_LIST"
3604 - return 0
3605 -}
3727 + EE['1.3.18.0.2.4.1139']="'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"
3728 + OD['1.3.18.0.2.4.1139']="'printer-info' DESC 'Descriptive information about this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3606 3729
3730 + EE['1.3.18.0.2.4.1134']="'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"
3731 + OD['1.3.18.0.2.4.1134']="'printer-more-info' DESC 'A URI for more information about this specific printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3607 3732
3608 -#
3609 -# modify_cn(): Change the cn from MUST to MAY in ipNetwork.
3610 -#
3611 -modify_cn()
3612 -{
3613 - [ $DEBUG -eq 1 ] && ${ECHO} "In modify_cn()"
3733 + EE['1.3.18.0.2.4.1138']="'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"
3734 + OD['1.3.18.0.2.4.1138']="'printer-make-and-model' DESC 'Make and model of this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3614 3735
3615 - ( cat <<EOF
3616 -dn: cn=schema
3617 -changetype: modify
3618 -add: objectclasses
3619 -objectclasses: ( 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' )
3620 -EOF
3621 -) > ${TMPDIR}/ipNetwork_cn
3736 + EE['1.3.18.0.2.4.1133']="'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}"
3737 + OD['1.3.18.0.2.4.1133']="'printer-ipp-versions-supported' DESC 'IPP protocol version(s) that this printer supports.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} X-ORIGIN 'RFC 3712'"
3622 3738
3623 - # Modify the cn for ipNetwork.
3624 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/ipNetwork_cn ${VERB}"
3625 - if [ $? -ne 0 ]; then
3626 - ${ECHO} " ERROR: update of cn for ipNetwork failed!"
3627 - cleanup
3628 - exit 1
3629 - fi
3630 -}
3739 + EE['1.3.18.0.2.4.1132']="'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"
3740 + OD['1.3.18.0.2.4.1132']="'printer-multiple-document-jobs-supported' DESC 'Indicates whether or not this printer supports more than one document per job.' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3631 3741
3742 + EE['1.3.18.0.2.4.1109']="'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"
3743 + OD['1.3.18.0.2.4.1109']="'printer-charset-configured' DESC 'The configured charset in which error and status messages will be generated (by default) by this printer.' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{63} SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3632 3744
3633 -# modify_timelimit(): Modify timelimit to user value.
3634 -modify_timelimit()
3635 -{
3636 - [ $DEBUG -eq 1 ] && ${ECHO} "In modify_timelimit()"
3745 + EE['1.3.18.0.2.4.1131']="'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}"
3746 + OD['1.3.18.0.2.4.1131']="'printer-charset-supported' DESC 'Set of charsets supported for the attribute values of syntax DirectoryString for this directory entry.' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{63} X-ORIGIN 'RFC 3712'"
3637 3747
3638 - # Here doc to modify timelimit.
3639 - ( cat <<EOF
3640 -dn: cn=config
3641 -changetype: modify
3642 -replace: nsslapd-timelimit
3643 -nsslapd-timelimit: ${IDS_TIMELIMIT}
3644 -EOF
3645 -) > ${TMPDIR}/ids_timelimit
3748 + EE['1.3.18.0.2.4.1137']="'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}"
3749 + OD['1.3.18.0.2.4.1137']="'printer-generated-natural-language-supported' DESC 'Natural language(s) supported for this directory entry.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{63} X-ORIGIN 'RFC 3712'"
3646 3750
3647 - # Add the entry.
3648 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/ids_timelimit ${VERB}"
3649 - if [ $? -ne 0 ]; then
3650 - ${ECHO} " ERROR: update of nsslapd-timelimit failed!"
3651 - cleanup
3652 - exit 1
3653 - fi
3751 + EE['1.3.18.0.2.4.1130']="'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}"
3752 + OD['1.3.18.0.2.4.1130']="'printer-document-format-supported' DESC 'The possible source document formats which may be interpreted and printed by this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} X-ORIGIN 'RFC 3712'"
3654 3753
3655 - # Display messages for modifications made in patch.
3656 - ${ECHO} " ${STEP}. Changed timelimit to ${IDS_TIMELIMIT} in cn=config."
3657 - STEP=`expr $STEP + 1`
3658 -}
3754 + EE['1.3.18.0.2.4.1129']="'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"
3755 + OD['1.3.18.0.2.4.1129']="'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 X-ORIGIN 'RFC 3712'"
3659 3756
3757 + EE['1.3.18.0.2.4.1128']="'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}"
3758 + OD['1.3.18.0.2.4.1128']="'printer-compression-supported' DESC 'Compression algorithms supported by this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} X-ORIGIN 'RFC 3712'"
3660 3759
3661 -# modify_sizelimit(): Modify sizelimit to user value.
3662 -modify_sizelimit()
3663 -{
3664 - [ $DEBUG -eq 1 ] && ${ECHO} "In modify_sizelimit()"
3760 + EE['1.3.18.0.2.4.1127']="'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"
3761 + OD['1.3.18.0.2.4.1127']="'printer-pages-per-minute' DESC 'The nominal number of pages per minute which may be output by this printer.' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3665 3762
3666 - # Here doc to modify sizelimit.
3667 - ( cat <<EOF
3668 -dn: cn=config
3669 -changetype: modify
3670 -replace: nsslapd-sizelimit
3671 -nsslapd-sizelimit: ${IDS_SIZELIMIT}
3672 -EOF
3673 -) > ${TMPDIR}/ids_sizelimit
3763 + EE['1.3.18.0.2.4.1126']="'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"
3764 + OD['1.3.18.0.2.4.1126']="'printer-pages-per-minute-color' DESC 'The nominal number of color pages per minute which may be output by this printer.' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3674 3765
3675 - # Add the entry.
3676 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/ids_sizelimit ${VERB}"
3677 - if [ $? -ne 0 ]; then
3678 - ${ECHO} " ERROR: update of nsslapd-sizelimit failed!"
3679 - cleanup
3680 - exit 1
3681 - fi
3766 + EE['1.3.18.0.2.4.1125']="'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}"
3767 + OD['1.3.18.0.2.4.1125']="'printer-finishings-supported' DESC 'The possible finishing operations supported by this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} X-ORIGIN 'RFC 3712'"
3682 3768
3683 - # Display messages for modifications made in patch.
3684 - ${ECHO} " ${STEP}. Changed sizelimit to ${IDS_SIZELIMIT} in cn=config."
3685 - STEP=`expr $STEP + 1`
3686 -}
3769 + EE['1.3.18.0.2.4.1124']="'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"
3770 + OD['1.3.18.0.2.4.1124']="'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.' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 X-ORIGIN 'RFC 3712'"
3687 3771
3772 + EE['1.3.18.0.2.4.1123']="'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}"
3773 + OD['1.3.18.0.2.4.1123']="'printer-sides-supported' DESC 'The number of impression sides (one or two) and the two-sided impression rotations supported by this printer.' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} X-ORIGIN 'RFC 3712'"
3688 3774
3689 -# modify_pwd_crypt(): Modify the passwd storage scheme to support CRYPT.
3690 -modify_pwd_crypt()
3691 -{
3692 - [ $DEBUG -eq 1 ] && ${ECHO} "In modify_pwd_crypt()"
3775 + EE['1.3.18.0.2.4.1122']="'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}"
3776 + OD['1.3.18.0.2.4.1122']="'printer-media-supported' DESC 'The standard names/types/sizes (and optional color suffixes) of the media supported by this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} X-ORIGIN 'RFC 3712'"
3693 3777
3694 - # Here doc to modify passwordstoragescheme.
3695 - # IDS 5.2 moved passwordchangesceme off to a new data structure.
3696 - if [ $IDS_MAJVER -le 5 ] && [ $IDS_MINVER -le 1 ]; then
3697 - ( cat <<EOF
3698 -dn: cn=config
3699 -changetype: modify
3700 -replace: passwordstoragescheme
3701 -passwordstoragescheme: crypt
3702 -EOF
3703 - ) > ${TMPDIR}/ids_crypt
3704 - else
3705 - ( cat <<EOF
3706 -dn: cn=Password Policy,cn=config
3707 -changetype: modify
3708 -replace: passwordstoragescheme
3709 -passwordstoragescheme: crypt
3710 -EOF
3711 - ) > ${TMPDIR}/ids_crypt
3712 - fi
3778 + EE['1.3.18.0.2.4.1117']="'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}"
3779 + OD['1.3.18.0.2.4.1117']="'printer-media-local-supported' DESC 'Site-specific names of media supported by this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} X-ORIGIN 'RFC 3712'"
3713 3780
3714 - # Add the entry.
3715 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/ids_crypt ${VERB}"
3716 - if [ $? -ne 0 ]; then
3717 - ${ECHO} " ERROR: update of passwordstoragescheme failed!"
3718 - cleanup
3719 - exit 1
3720 - fi
3781 + EE['1.3.18.0.2.4.1121']="'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}"
3782 + OD['1.3.18.0.2.4.1121']="'printer-resolution-supported' DESC 'List of resolutions supported for printing documents by this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} X-ORIGIN 'RFC 3712'"
3721 3783
3722 - # Display messages for modifications made in patch.
3723 - ${ECHO} " ${STEP}. Changed passwordstoragescheme to \"crypt\" in cn=config."
3724 - STEP=`expr $STEP + 1`
3725 -}
3784 + EE['1.3.18.0.2.4.1120']="'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}"
3785 + OD['1.3.18.0.2.4.1120']="'printer-print-quality-supported' DESC 'List of print qualities supported for printing documents on this printer.' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} X-ORIGIN 'RFC 3712'"
3726 3786
3787 + EE['1.3.18.0.2.4.1110']="'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"
3788 + OD['1.3.18.0.2.4.1110']="'printer-job-priority-supported' DESC 'Indicates the number of job priority levels supported by this printer.' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3727 3789
3728 -#
3729 -# add_eq_indexes(): Add indexes to improve search performance.
3730 -#
3731 -add_eq_indexes()
3732 -{
3733 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_eq_indexes()"
3790 + EE['1.3.18.0.2.4.1118']="'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"
3791 + OD['1.3.18.0.2.4.1118']="'printer-copies-supported' DESC 'The maximum number of copies of a document that may be printed as a single job on this printer.' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3734 3792
3735 - # Set eq indexes to add.
3736 - _INDEXES="uidNumber ipNetworkNumber gidnumber oncrpcnumber automountKey"
3793 + EE['1.3.18.0.2.4.1111']="'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"
3794 + OD['1.3.18.0.2.4.1111']="'printer-job-k-octets-supported' DESC 'The maximum size in kilobytes (1,024 octets actually) incoming print job that this printer will accept.' EQUALITY integerMatch ORDERING integerOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3737 3795
3738 - if [ -z "${IDS_DATABASE}" ]; then
3739 - get_backend
3740 - fi
3796 + EE['1.3.18.0.2.4.1112']="'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"
3797 + OD['1.3.18.0.2.4.1112']="'printer-current-operator' DESC 'The identity of the current human operator responsible for operating this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3741 3798
3742 - # Set _EXT to use as shortcut.
3743 - _EXT="cn=index,cn=${IDS_DATABASE},cn=ldbm database,cn=plugins,cn=config"
3799 + EE['1.3.18.0.2.4.1113']="'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"
3800 + OD['1.3.18.0.2.4.1113']="'printer-service-person' DESC 'The identity of the current human service person responsible for servicing this printer.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} SINGLE-VALUE X-ORIGIN 'RFC 3712'"
3744 3801
3745 - # Display message to id current step.
3746 - ${ECHO} " ${STEP}. Processing eq,pres indexes:"
3747 - STEP=`expr $STEP + 1`
3802 + EE['1.3.18.0.2.4.1114']="'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}"
3803 + OD['1.3.18.0.2.4.1114']="'printer-delivery-orientation-supported' DESC 'The possible delivery orientations of pages as they are printed and ejected from this printer.' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} X-ORIGIN 'RFC 3712'"
3748 3804
3749 - # For loop to create indexes.
3750 - for i in ${_INDEXES}; do
3751 - [ $DEBUG -eq 1 ] && ${ECHO} " Adding index for ${i}"
3805 + EE['1.3.18.0.2.4.1115']="'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}"
3806 + OD['1.3.18.0.2.4.1115']="'printer-stacking-order-supported' DESC 'The possible stacking order of pages as they are printed and ejected from this printer.' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} X-ORIGIN 'RFC 3712'"
3752 3807
3753 - # Check if entry exists first, if so, skip to next.
3754 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=${i},${_EXT}\" -s base \
3755 - \"objectclass=*\" > /dev/null 2>&1"
3756 - if [ $? -eq 0 ]; then
3757 - # Display index skipped.
3758 - ${ECHO} " ${i} (eq,pres) skipped already exists"
3759 - continue
3760 - fi
3808 + EE['1.3.18.0.2.4.1116']="'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}"
3809 + OD['1.3.18.0.2.4.1116']="'printer-output-features-supported' DESC 'The possible output features supported by this printer.' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} X-ORIGIN 'RFC 3712'"
3761 3810
3762 - # Here doc to create LDIF.
3763 - ( cat <<EOF
3764 -dn: cn=${i},${_EXT}
3765 -objectClass: top
3766 -objectClass: nsIndex
3767 -cn: ${i}
3768 -nsSystemIndex: false
3769 -nsIndexType: pres
3770 -nsIndexType: eq
3771 -EOF
3772 -) > ${TMPDIR}/index_${i}
3811 + EE['1.3.18.0.2.4.1108']="'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}"
3812 + OD['1.3.18.0.2.4.1108']="'printer-aliases' DESC 'List of site-specific administrative names of this printer in addition to the value specified for printer-name.' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{127} X-ORIGIN 'RFC 3712'"
3773 3813
3774 - # Add the index.
3775 - ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/index_${i} ${VERB}"
3776 - if [ $? -ne 0 ]; then
3777 - ${ECHO} " ERROR: Adding EQ,PRES index for ${i} failed!"
3778 - cleanup
3779 - exit 1
3780 - fi
3814 + EE['1.3.6.1.4.1.42.2.27.5.1.63']="'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"
3815 + OD['1.3.6.1.4.1.42.2.27.5.1.63']="'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 X-ORIGIN 'Solaris Specific'"
3781 3816
3782 - # Build date for task name.
3783 - _YR=`date '+%y'`
3784 - _MN=`date '+%m'`
3785 - _DY=`date '+%d'`
3786 - _H=`date '+%H'`
3787 - _M=`date '+%M'`
3788 - _S=`date '+%S'`
3817 + EE['1.3.6.1.4.1.42.2.27.5.1.64']="'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"
3818 + OD['1.3.6.1.4.1.42.2.27.5.1.64']="'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 X-ORIGIN 'Solaris Specific'"
3789 3819
3790 - # Build task name
3791 - TASKNAME="${i}_${_YR}_${_MN}_${_DY}_${_H}_${_M}_${_S}"
3820 + EE['1.3.6.1.4.1.42.2.27.5.1.57']="'nisplusTimeZone' DESC 'tzone column from NIS+ timezone table' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE"
3821 + OD['1.3.6.1.4.1.42.2.27.5.1.57']="'nisplusTimeZone' DESC 'tzone column from NIS+ timezone table' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'"
3792 3822
3793 - # Build the task entry to add.
3794 - ( cat <<EOF
3795 -dn: cn=${TASKNAME}, cn=index, cn=tasks, cn=config
3796 -changetype: add
3797 -objectclass: top
3798 -objectclass: extensibleObject
3799 -cn: ${TASKNAME}
3800 -nsInstance: ${IDS_DATABASE}
3801 -nsIndexAttribute: ${i}
3802 -EOF
3803 -) > ${TMPDIR}/task_${i}
3823 + EE['1.3.6.1.4.1.42.2.27.5.1.67']="'ipTnetTemplateName' DESC 'Trusted Solaris network template template_name' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE"
3824 + OD['1.3.6.1.4.1.42.2.27.5.1.67']="'ipTnetTemplateName' DESC 'Trusted Solaris network template template_name' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'"
3804 3825
3805 - # Add the task.
3806 - ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/task_${i} ${VERB}"
3807 - if [ $? -ne 0 ]; then
3808 - ${ECHO} " ERROR: Adding task for ${i} failed!"
3809 - cleanup
3810 - exit 1
3826 + EE['1.3.6.1.4.1.42.2.27.5.1.68']="'ipTnetNumber' DESC 'Trusted Solaris network template ip_address' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE"
3827 + OD['1.3.6.1.4.1.42.2.27.5.1.68']="'ipTnetNumber' DESC 'Trusted Solaris network template ip_address' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'Solaris Specific'"
3828 +
3829 + # obey CLI syntax force option (if any)
3830 + if (( TMPF[SYNTAX] == 1 )); then
3831 + typeset -n MAP=OD
3832 + elif (( TMPF[SYNTAX] == 2 )); then
3833 + typeset -n MAP=EE
3834 + elif (( TMPF[IS_OPENDJ] )); then
3835 + typeset -n MAP=OD
3836 + else
3837 + typeset -n MAP=EE
3811 3838 fi
3812 3839
3813 - # Wait for task to finish, display current status.
3814 - while :
3815 - do
3816 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} \
3817 - -b \"cn=${TASKNAME}, cn=index, cn=tasks, cn=config\" -s base \
3818 - \"objectclass=*\" nstaskstatus > \"${TMPDIR}/istask_${i}\" 2>&1"
3819 - ${GREP} "${TASKNAME}" "${TMPDIR}/istask_${i}" > /dev/null 2>&1
3820 - if [ $? -ne 0 ]; then
3821 - break
3822 - fi
3823 - TASK_STATUS=`${GREP} -i nstaskstatus "${TMPDIR}/istask_${i}" |
3824 - head -1 | cut -d: -f2`
3825 - ${ECHO} " ${i} (eq,pres) $TASK_STATUS \r\c"
3826 - ${ECHO} "$TASK_STATUS" | ${GREP} "Finished" > /dev/null 2>&1
3827 - if [ $? -eq 0 ]; then
3828 - break
3829 - fi
3830 - sleep 2
3840 + typeset TODO='' OID X
3841 + for OID in ${!MAP[@]}; do
3842 + [[ -n ${OID2ADEF[${OID}]} ]] && continue
3843 + X="${MAP[${OID}]}"
3844 + TODO+='attributetypes: ( '"${OID} NAME ${X}"' )\n'
3845 + OID2ADEF["${OID}"]="${X}"
3846 + X=${X:1}
3847 + X=${X%%"'"*} # we have no aliases above
3848 + ANAME2OID["${X}"]="${OID}"
3831 3849 done
3832 3850
3833 - # Print newline because of \c.
3834 - ${ECHO} " "
3835 - done
3851 + if [[ -z ${TODO} ]]; then
3852 + X='Schema contains all required attribute definitions'
3853 + else
3854 + nextFile add $0
3855 + print 'dn: cn=schema\nchangetype: modify\nadd: attributetypes' \
3856 + "\n${TODO}" >${TMP[FILE]}
3857 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
3858 + >&${TMPF[FD]} 2>&1
3859 + then
3860 + Log.fatal 'Adding attribute definitions to schema failed'
3861 + return 67
3862 + fi
3863 + X='Schema attribute definitions added'
3864 + fi
3865 + showProgress "${X}."
3866 + return 0
3836 3867 }
3837 3868
3869 +Man.addFunc update_schema_obj '' '[+NAME?update_schema_obj - Update DS schema to support Naming Services.]
3870 +[+DESCRIPTION?Update the schema of the DS with the objectclasses required for the Solaris Naming Services. It just checks, whether the OID is already defined on the server. If already defined, it is left as is, otherwise added.]
3871 +[+RETURN VALUES]{
3872 + [+0?on success.]
3873 + [+>= 66?a fatal error occurred.]
3874 +}
3875 +[+SEE ALSO?\bupdate_schema_attr()\b, \bldapmodify\b(1).]
3876 +'
3877 +function update_schema_obj {
3878 + getDSobjectclasses || return 66
3838 3879
3839 -#
3840 -# add_sub_indexes(): Add indexes to improve search performance.
3841 -#
3842 -add_sub_indexes()
3843 -{
3844 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_sub_indexes()"
3880 + typeset -A EE=( )
3881 + typeset -A OD=( )
3882 + EE['1.3.6.1.1.1.2.14']="'NisKeyObject' SUP top MUST "'( cn $ nisPublickey $ nisSecretkey ) MAY ( uidNumber $ description )'
3883 + OD['1.3.6.1.1.1.2.14']="'nisKeyObject' SUP top AUXILIARY DESC 'An object with a public and secret key' MUST "'( cn $ nisPublicKey $ nisSecretKey ) MAY ( uidNumber $ description )'" X-ORIGIN 'draft-howard-rfc2307bis'"
3845 3884
3846 - # Set eq indexes to add.
3847 - _INDEXES="ipHostNumber membernisnetgroup nisnetgrouptriple"
3885 + EE['1.3.6.1.1.1.2.15']="'nisDomainObject' SUP top MUST nisDomain"
3886 + OD['1.3.6.1.1.1.2.15']="'nisDomainObject' SUP top AUXILIARY DESC 'Associates a NIS domain with a naming context' MUST nisDomain X-ORIGIN 'draft-howard-rfc2307bis'"
3848 3887
3849 - # Set _EXT to use as shortcut.
3850 - _EXT="cn=index,cn=${IDS_DATABASE},cn=ldbm database,cn=plugins,cn=config"
3888 + EE['1.3.6.1.1.1.2.16']="'automountMap' SUP top MUST automountMapName MAY description"
3889 + OD['1.3.6.1.1.1.2.16']="'automountMap' SUP top STRUCTURAL MUST ( automountMapName ) MAY description X-ORIGIN 'draft-howard-rfc2307bis'"
3851 3890
3891 + EE['1.3.6.1.1.1.2.17']="'automount' SUP top MUST "'( automountKey $ automountInformation ) MAY description'
3892 + OD['1.3.6.1.1.1.2.17']="'automount' SUP top STRUCTURAL DESC 'Automount information' MUST "'( automountKey $ automountInformation )'" MAY description X-ORIGIN 'draft-howard-rfc2307bis'"
3852 3893
3853 - # Display message to id current step.
3854 - ${ECHO} " ${STEP}. Processing eq,pres,sub indexes:"
3855 - STEP=`expr $STEP + 1`
3894 + EE['1.3.6.1.4.1.42.2.27.5.2.7']="'SolarisNamingProfile' SUP top MUST "'( cn $ SolarisLDAPservers $ SolarisSearchBaseDN ) MAY ( SolarisBindDN $ SolarisBindPassword $ SolarisAuthMethod $ SolarisTransportSecurity $ SolarisCertificatePath $ SolarisCertificatePassword $ SolarisDataSearchDN $ SolarisSearchScope $ SolarisSearchTimeLimit $ SolarisPreferredServer $ SolarisPreferredServerOnly $ SolarisCacheTTL $ SolarisSearchReferral )'
3895 + OD['1.3.6.1.4.1.42.2.27.5.2.7']="'SolarisNamingProfile' SUP top STRUCTURAL DESC 'Solaris LDAP Naming client profile objectClass' MUST "'( cn $ SolarisLDAPServers $ SolarisSearchBaseDN ) MAY ( SolarisBindDN $ SolarisBindPassword $ SolarisAuthMethod $ SolarisTransportSecurity $ SolarisCertificatePath $ SolarisCertificatePassword $ SolarisDataSearchDN $ SolarisSearchScope $ SolarisSearchTimeLimit $ SolarisPreferredServer $ SolarisPreferredServerOnly $ SolarisCacheTTL $ SolarisSearchReferral $ SolarisBindTimeLimit )'" X-ORIGIN 'Solaris Specific'"
3856 3896
3857 - # For loop to create indexes.
3858 - for i in ${_INDEXES}; do
3859 - [ $DEBUG -eq 1 ] && ${ECHO} " Adding index for ${i}"
3897 + EE['2.16.840.1.113730.3.2.4']="'mailGroup' SUP top MUST mail MAY "'( cn $ mgrpRFC822MailMember )'
3898 + OD['2.16.840.1.113730.3.2.4']="'mailGroup' SUP top STRUCTURAL MUST mail MAY "'( cn $ mgrpRFC822MailMember )'" X-ORIGIN 'Solaris Specific'"
3860 3899
3861 - # Check if entry exists first, if so, skip to next.
3862 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=${i},${_EXT}\" \
3863 - -s base \"objectclass=*\" > /dev/null 2>&1"
3864 - if [ $? -eq 0 ]; then
3865 - # Display index skipped.
3866 - ${ECHO} " ${i} (eq,pres,sub) skipped already exists"
3867 - continue
3868 - fi
3900 + EE['1.3.6.1.4.1.42.2.27.1.2.5']="'nisMailAlias' SUP top MUST cn MAY rfc822mailMember"
3901 + OD['1.3.6.1.4.1.42.2.27.1.2.5']="'nisMailAlias' SUP top MUST cn MAY rfc822mailMember X-ORIGIN 'Solaris Specific'"
3869 3902
3870 - # Here doc to create LDIF.
3871 - ( cat <<EOF
3872 -dn: cn=${i},${_EXT}
3873 -objectClass: top
3874 -objectClass: nsIndex
3875 -cn: ${i}
3876 -nsSystemIndex: false
3877 -nsIndexType: pres
3878 -nsIndexType: eq
3879 -nsIndexType: sub
3880 -EOF
3881 -) > ${TMPDIR}/index_${i}
3903 + EE['1.3.6.1.4.1.42.2.27.1.2.6']="'nisNetId' SUP top MUST cn MAY "'( nisNetIdUser $ nisNetIdGroup $ nisNetIdHost )'
3904 + OD['1.3.6.1.4.1.42.2.27.1.2.6']="'nisNetId' SUP top MUST cn MAY "'( nisNetIdUser $ nisNetIdGroup $ nisNetIdHost )'" X-ORIGIN 'Solaris Specific'"
3882 3905
3883 - # Add the index.
3884 - ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/index_${i} ${VERB}"
3885 - if [ $? -ne 0 ]; then
3886 - ${ECHO} " ERROR: Adding EQ,PRES,SUB index for ${i} failed!"
3887 - cleanup
3888 - exit 1
3889 - fi
3906 + EE['1.3.6.1.4.1.42.2.27.5.2.2']="'SolarisAuditUser' SUP top AUXILIARY MAY "'( SolarisAuditAlways $ SolarisAuditNever )'
3907 + OD['1.3.6.1.4.1.42.2.27.5.2.2']="'SolarisAuditUser' SUP top AUXILIARY MAY "'( SolarisAuditAlways $ SolarisAuditNever )'" X-ORIGIN 'Solaris Specific'"
3890 3908
3891 - # Build date for task name.
3892 - _YR=`date '+%y'`
3893 - _MN=`date '+%m'`
3894 - _DY=`date '+%d'`
3895 - _H=`date '+%H'`
3896 - _M=`date '+%M'`
3897 - _S=`date '+%S'`
3909 + EE['1.3.6.1.4.1.42.2.27.5.2.3']="'SolarisUserAttr' SUP top AUXILIARY MAY "'( SolarisUserQualifier $ SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrKeyValue )'
3910 + OD['1.3.6.1.4.1.42.2.27.5.2.3']="'SolarisUserAttr' SUP top AUXILIARY DESC 'User attributes' MAY "'( SolarisUserQualifier $ SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrKeyValue )'" X-ORIGIN 'Solaris Specific'"
3898 3911
3899 - # Build task name
3900 - TASKNAME="${i}_${_YR}_${_MN}_${_DY}_${_H}_${_M}_${_S}"
3912 + EE['1.3.6.1.4.1.42.2.27.5.2.4']="'SolarisAuthAttr' SUP top MUST cn MAY "'( SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrShortDesc $ SolarisAttrLongDesc $ SolarisAttrKeyValue )'
3913 + OD['1.3.6.1.4.1.42.2.27.5.2.4']="'SolarisAuthAttr' SUP top STRUCTURAL DESC 'Authorizations data' MUST cn MAY "'( SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrShortDesc $ SolarisAttrLongDesc $ SolarisAttrKeyValue )'" X-ORIGIN 'Solaris Specific'"
3901 3914
3902 - # Build the task entry to add.
3903 - ( cat <<EOF
3904 -dn: cn=${TASKNAME}, cn=index, cn=tasks, cn=config
3905 -changetype: add
3906 -objectclass: top
3907 -objectclass: extensibleObject
3908 -cn: ${TASKNAME}
3909 -nsInstance: ${IDS_DATABASE}
3910 -nsIndexAttribute: ${i}
3911 -EOF
3912 -) > ${TMPDIR}/task_${i}
3915 + EE['1.3.6.1.4.1.42.2.27.5.2.5']="'SolarisProfAttr' SUP top MUST cn MAY "'( SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrLongDesc $ SolarisAttrKeyValue )'
3916 + OD['1.3.6.1.4.1.42.2.27.5.2.5']="'SolarisProfAttr' SUP top STRUCTURAL DESC 'Profiles data' MUST cn MAY "'( SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrLongDesc $ SolarisAttrKeyValue )'" X-ORIGIN 'Solaris Specific'"
3913 3917
3914 - # Add the task.
3915 - ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/task_${i} ${VERB}"
3916 - if [ $? -ne 0 ]; then
3917 - ${ECHO} " ERROR: Adding task for ${i} failed!"
3918 - cleanup
3919 - exit 1
3920 - fi
3918 + EE['1.3.6.1.4.1.42.2.27.5.2.6']="'SolarisExecAttr' SUP top AUXILIARY MAY "'( SolarisKernelSecurityPolicy $ SolarisProfileType $ SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisProfileID $ SolarisAttrKeyValue )'
3919 + OD['1.3.6.1.4.1.42.2.27.5.2.6']="'SolarisExecAttr' SUP top AUXILIARY DESC 'Profiles execution attributes' MAY "'( SolarisKernelSecurityPolicy $ SolarisProfileType $ SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisProfileId $ SolarisAttrKeyValue )'" X-ORIGIN 'Solaris Specific'"
3921 3920
3922 - # Wait for task to finish, display current status.
3923 - while :
3924 - do
3925 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} \
3926 - -b \"cn=${TASKNAME}, cn=index, cn=tasks, cn=config\" -s base \
3927 - \"objectclass=*\" nstaskstatus > \"${TMPDIR}/istask_${i}\" 2>&1"
3928 - ${GREP} "${TASKNAME}" "${TMPDIR}/istask_${i}" > /dev/null 2>&1
3929 - if [ $? -ne 0 ]; then
3930 - break
3931 - fi
3932 - TASK_STATUS=`${GREP} -i nstaskstatus "${TMPDIR}/istask_${i}" |
3933 - head -1 | cut -d: -f2`
3934 - ${ECHO} " ${i} (eq,pres,sub) $TASK_STATUS \r\c"
3935 - ${ECHO} "$TASK_STATUS" | ${GREP} "Finished" > /dev/null 2>&1
3936 - if [ $? -eq 0 ]; then
3937 - break
3938 - fi
3939 - sleep 2
3940 - done
3921 + EE['1.3.6.1.4.1.42.2.27.5.2.1']="'SolarisProject' SUP top MUST "'( SolarisProjectID $ SolarisProjectName ) MAY ( memberUid $ memberGid $ description $ SolarisProjectAttr )'
3922 + OD['1.3.6.1.4.1.42.2.27.5.2.1']="'SolarisProject' SUP top STRUCTURAL MUST "'( SolarisProjectID $ SolarisProjectName ) MAY ( memberUid $ memberGid $ description $ SolarisProjectAttr )'" X-ORIGIN 'Solaris Specific'"
3941 3923
3942 - # Print newline because of \c.
3943 - ${ECHO} " "
3944 - done
3945 -}
3924 + EE['1.3.6.1.4.1.11.1.3.1.2.4']="'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 )'
3925 + OD['1.3.6.1.4.1.11.1.3.1.2.4']="'DUAConfigProfile' SUP top STRUCTURAL DESC 'Abstraction of a base configuration for a DUA' MUST "'( cn ) MAY ( defaultServerList $ preferredServerList $ defaultSearchBase $ defaultSearchScope $ searchTimeLimit $ bindTimeLimit $ credentialLevel $ authenticationMethod $ followReferrals $ dereferenceAliases $ serviceSearchDescriptor $ serviceCredentialLevel $ serviceAuthenticationMethod $ objectclassMap $ attributeMap $ profileTTL )'" X-ORIGIN 'RFC 4876'"
3946 3926
3927 + EE['1.3.18.0.2.6.2549']="'slpService' DESC 'DUMMY definition' SUP top MUST objectclass"
3928 + OD['1.3.18.0.2.6.2549']="'slpService' DESC 'parent superclass for SLP services' SUP top ABSTRACT MUST "'( template-major-version-number $ template-minor-version-number $ description $ template-url-syntax $ service-advert-service-type $ service-advert-scopes ) MAY ( service-advert-url-authenticator $ service-advert-attribute-authenticator )'" X-ORIGIN 'RFC 2926'"
3947 3929
3948 -#
3949 -# add_vlv_indexes(): Add VLV indexes to improve search performance.
3950 -#
3951 -add_vlv_indexes()
3952 -{
3953 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_vlv_indexes()"
3930 + EE['1.3.18.0.2.6.254']="'slpServicePrinter' DESC 'Service Location Protocol (SLP) information.' SUP slpService AUXILIARY"
3931 + OD['1.3.18.0.2.6.254']="'slpServicePrinter' DESC 'Service Location Protocol (SLP) information.' SUP slpService AUXILIARY X-ORIGIN 'RFC 3712'"
3954 3932
3955 - # Set eq indexes to add.
3956 - # Note semi colon separators because some filters contain colons
3957 - _INDEX1="${LDAP_DOMAIN}.getgrent;${LDAP_DOMAIN}_group_vlv_index;ou=group;objectClass=posixGroup"
3958 - _INDEX2="${LDAP_DOMAIN}.gethostent;${LDAP_DOMAIN}_hosts_vlv_index;ou=hosts;objectClass=ipHost"
3959 - _INDEX3="${LDAP_DOMAIN}.getnetent;${LDAP_DOMAIN}_networks_vlv_index;ou=networks;objectClass=ipNetwork"
3960 - _INDEX4="${LDAP_DOMAIN}.getpwent;${LDAP_DOMAIN}_passwd_vlv_index;ou=people;objectClass=posixAccount"
3961 - _INDEX5="${LDAP_DOMAIN}.getrpcent;${LDAP_DOMAIN}_rpc_vlv_index;ou=rpc;objectClass=oncRpc"
3962 - _INDEX6="${LDAP_DOMAIN}.getspent;${LDAP_DOMAIN}_shadow_vlv_index;ou=people;objectClass=shadowAccount"
3933 + EE['1.3.18.0.2.6.258']="'printerAbstract' DESC 'Printer related information.' SUP top ABSTRACT MAY "'( printer-name $ printer-natural-language-configured $ printer-location $ printer-info $ printer-more-info $ printer-make-and-model $ printer-multiple-document-jobs-supported $ printer-charset-configured $ printer-charset-supported $ printer-generated-natural-language-supported $ printer-document-format-supported $ printer-color-supported $ printer-compression-supported $ printer-pages-per-minute $ printer-pages-per-minute-color $ printer-finishings-supported $ printer-number-up-supported $ printer-sides-supported $ printer-media-supported $ printer-media-local-supported $ printer-resolution-supported $ printer-print-quality-supported $ printer-job-priority-supported $ printer-copies-supported $ printer-job-k-octets-supported $ printer-current-operator $ printer-service-person $ printer-delivery-orientation-supported $ printer-stacking-order-supported $ printer-output-features-supported )'
3934 + OD['1.3.18.0.2.6.258']="'printerAbstract' DESC 'Printer related information.' SUP top ABSTRACT MAY "'( printer-name $ printer-natural-language-configured $ printer-location $ printer-info $ printer-more-info $ printer-make-and-model $ printer-multiple-document-jobs-supported $ printer-charset-configured $ printer-charset-supported $ printer-generated-natural-language-supported $ printer-document-format-supported $ printer-color-supported $ printer-compression-supported $ printer-pages-per-minute $ printer-pages-per-minute-color $ printer-finishings-supported $ printer-number-up-supported $ printer-sides-supported $ printer-media-supported $ printer-media-local-supported $ printer-resolution-supported $ printer-print-quality-supported $ printer-job-priority-supported $ printer-copies-supported $ printer-job-k-octets-supported $ printer-current-operator $ printer-service-person $ printer-delivery-orientation-supported $ printer-stacking-order-supported $ printer-output-features-supported )'" X-ORIGIN 'RFC 3712' )"
3963 3935
3964 - # Indexes added during NIS to LDAP transition
3965 - _INDEX7="${LDAP_DOMAIN}.getauhoent;${LDAP_DOMAIN}_auho_vlv_index;automountmapname=auto_home;objectClass=automount"
3966 - _INDEX8="${LDAP_DOMAIN}.getsoluent;${LDAP_DOMAIN}_solu_vlv_index;ou=people;objectClass=SolarisUserAttr"
3967 - _INDEX10="${LDAP_DOMAIN}.getauthent;${LDAP_DOMAIN}_auth_vlv_index;ou=SolarisAuthAttr;objectClass=SolarisAuthAttr"
3968 - _INDEX11="${LDAP_DOMAIN}.getexecent;${LDAP_DOMAIN}_exec_vlv_index;ou=SolarisProfAttr;&(objectClass=SolarisExecAttr)(SolarisKernelSecurityPolicy=*)"
3969 - _INDEX12="${LDAP_DOMAIN}.getprofent;${LDAP_DOMAIN}_prof_vlv_index;ou=SolarisProfAttr;&(objectClass=SolarisProfAttr)(SolarisAttrLongDesc=*)"
3970 - _INDEX13="${LDAP_DOMAIN}.getmailent;${LDAP_DOMAIN}_mail_vlv_index;ou=aliases;objectClass=mailGroup"
3971 - _INDEX14="${LDAP_DOMAIN}.getbootent;${LDAP_DOMAIN}__boot_vlv_index;ou=ethers;&(objectClass=bootableDevice)(bootParameter=*)"
3972 - _INDEX15="${LDAP_DOMAIN}.getethent;${LDAP_DOMAIN}_ethers_vlv_index;ou=ethers;&(objectClass=ieee802Device)(macAddress=*)"
3973 - _INDEX16="${LDAP_DOMAIN}.getngrpent;${LDAP_DOMAIN}_netgroup_vlv_index;ou=netgroup;objectClass=nisNetgroup"
3974 - _INDEX17="${LDAP_DOMAIN}.getipnent;${LDAP_DOMAIN}_ipn_vlv_index;ou=networks;&(objectClass=ipNetwork)(cn=*)"
3975 - _INDEX18="${LDAP_DOMAIN}.getmaskent;${LDAP_DOMAIN}_mask_vlv_index;ou=networks;&(objectClass=ipNetwork)(ipNetmaskNumber=*)"
3976 - _INDEX19="${LDAP_DOMAIN}.getprent;${LDAP_DOMAIN}_pr_vlv_index;ou=printers;objectClass=printerService"
3977 - _INDEX20="${LDAP_DOMAIN}.getip4ent;${LDAP_DOMAIN}_ip4_vlv_index;ou=hosts;&(objectClass=ipHost)(ipHostNumber=*.*)"
3978 - _INDEX21="${LDAP_DOMAIN}.getip6ent;${LDAP_DOMAIN}_ip6_vlv_index;ou=hosts;&(objectClass=ipHost)(ipHostNumber=*:*)"
3936 + EE['1.3.18.0.2.6.255']="'printerService' DESC 'Printer information.' SUP printerAbstract STRUCTURAL MAY "'( printer-uri $ printer-xri-supported )'
3937 + OD['1.3.18.0.2.6.255']="'printerService' DESC 'Printer information.' SUP printerAbstract STRUCTURAL MAY "'( printer-uri $ printer-xri-supported )'" X-ORIGIN 'RFC 3712'"
3979 3938
3980 - _INDEXES="$_INDEX1 $_INDEX2 $_INDEX3 $_INDEX4 $_INDEX5 $_INDEX6 $_INDEX7 $_INDEX8 $_INDEX9 $_INDEX10 $_INDEX11 $_INDEX12 $_INDEX13 $_INDEX14 $_INDEX15 $_INDEX16 $_INDEX17 $_INDEX18 $_INDEX19 $_INDEX20 $_INDEX21 "
3939 + EE['1.3.18.0.2.6.257']="'printerServiceAuxClass' DESC 'Printer information.' SUP printerAbstract AUXILIARY MAY "'( printer-uri $ printer-xri-supported )'
3940 + OD['1.3.18.0.2.6.257']="'printerServiceAuxClass' DESC 'Printer information.' SUP printerAbstract AUXILIARY MAY "'( printer-uri $ printer-xri-supported )'" X-ORIGIN 'RFC 3712'"
3981 3941
3942 + EE['1.3.18.0.2.6.256']="'printerIPP' DESC 'Internet Printing Protocol (IPP) information.' SUP top AUXILIARY MAY "'( printer-ipp-versions-supported $ printer-multiple-document-jobs-supported )'
3943 + OD['1.3.18.0.2.6.256']="'printerIPP' DESC 'Internet Printing Protocol (IPP) information.' SUP top AUXILIARY MAY "'( printer-ipp-versions-supported $ printer-multiple-document-jobs-supported )'" X-ORIGIN 'RFC 3712'"
3982 3944
3983 - # Set _EXT to use as shortcut.
3984 - _EXT="cn=${IDS_DATABASE},cn=ldbm database,cn=plugins,cn=config"
3945 + EE['1.3.18.0.2.6.253']="'printerLPR' DESC 'LPR information.' SUP top AUXILIARY MUST printer-name MAY printer-aliases"
3946 + OD['1.3.18.0.2.6.253']="'printerLPR' DESC 'LPR information.' SUP top AUXILIARY MUST ( printer-name ) MAY ( printer-aliases ) X-ORIGIN 'RFC 3712'"
3985 3947
3948 + EE['1.3.6.1.4.1.42.2.27.5.2.14']="'sunPrinter' DESC 'Sun printer information' SUP top AUXILIARY MUST printer-name MAY "'( sun-printer-bsdaddr $ sun-printer-kvp )'
3949 + OD['1.3.6.1.4.1.42.2.27.5.2.14']="'sunPrinter' DESC 'Sun printer information' SUP top AUXILIARY MUST printer-name MAY "'(sun-printer-bsdaddr $ sun-printer-kvp)'" X-ORIGIN 'Solaris Specific'"
3986 3950
3987 - # Display message to id current step.
3988 - ${ECHO} " ${STEP}. Processing VLV indexes:"
3989 - STEP=`expr $STEP + 1`
3951 + EE['1.3.6.1.4.1.42.2.27.5.2.12']="'nisplusTimeZoneData' DESC 'NIS+ timezone table data' SUP top STRUCTURAL MUST cn MAY "'( nisplusTimeZone $ description )'
3952 + OD['1.3.6.1.4.1.42.2.27.5.2.12']="'nisplusTimeZoneData' DESC 'NIS+ timezone table data' SUP top STRUCTURAL MUST cn MAY "'( nisplusTimeZone $ description )'" X-ORIGIN 'Solaris Specific'"
3990 3953
3991 - # Reset temp file for vlvindex commands.
3992 - [ -f ${TMPDIR}/ds5_vlvindex_list ] && rm ${TMPDIR}/ds5_vlvindex_list
3993 - touch ${TMPDIR}/ds5_vlvindex_list
3994 - [ -f ${TMPDIR}/ds6_vlvindex_list ] && rm ${TMPDIR}/ds6_vlvindex_list
3995 - touch ${TMPDIR}/ds6_vlvindex_list
3954 + EE['1.3.6.1.4.1.42.2.27.5.2.8']="'ipTnetTemplate' DESC 'Object class for TSOL network templates' SUP top MUST ipTnetTemplateName MAY SolarisAttrKeyValue"
3955 + OD['1.3.6.1.4.1.42.2.27.5.2.8']="'ipTnetTemplate' DESC 'Object class for TSOL network templates' SUP top STRUCTURAL MUST ipTnetTemplateName MAY SolarisAttrKeyValue X-ORIGIN 'Solaris Specific'"
3996 3956
3997 - # Get the instance name from iDS server.
3998 - _INSTANCE="<server-instance>" # Default to old output.
3957 + EE['1.3.6.1.4.1.42.2.27.5.2.9']="'ipTnetHost' DESC 'Associates an IP address or wildcard with a TSOL template_name' SUP top AUXILIARY MUST ipTnetNumber"
3958 + OD['1.3.6.1.4.1.42.2.27.5.2.9']="'ipTnetHost' DESC 'Associates an IP address or wildcard with a TSOL template_name' SUP top AUXILIARY MUST ipTnetNumber X-ORIGIN 'Solaris Specific'"
3999 3959
4000 - eval "${LDAPSEARCH} -v ${LDAP_ARGS} -b \"cn=config\" -s base \"objectclass=*\" nsslapd-instancedir | ${GREP} 'nsslapd-instancedir=' | cut -d'=' -f2- > ${TMPDIR}/instance_name 2>&1"
3960 + # obey CLI syntax force option (if any)
3961 + if (( TMPF[SYNTAX] == 1 )); then
3962 + typeset -n MAP=OD
3963 + elif (( TMPF[SYNTAX] == 2 )); then
3964 + typeset -n MAP=EE
3965 + elif (( TMPF[IS_OPENDJ] )); then
3966 + typeset -n MAP=OD
3967 + else
3968 + typeset -n MAP=EE
3969 + fi
4001 3970
4002 - ${GREP} "slapd-" ${TMPDIR}/instance_name > /dev/null 2>&1 # Check if seems right?
4003 - if [ $? -eq 0 ]; then # If success, grab name after "slapd-".
4004 - _INST_DIR=`cat ${TMPDIR}/instance_name`
4005 - _INSTANCE=`basename "${_INST_DIR}" | cut -d'-' -f2-`
4006 - fi
3971 + # we need to preserve order, so 2 passes
3972 + typeset TODO='' OID
3973 + for OID in ${!MAP[@]}; do
3974 + [[ -n ${OID2ODEF[${OID}]} ]] && continue
3975 + TODO+="${OID} "
3976 + done
4007 3977
4008 - # For loop to create indexes.
4009 - for p in ${_INDEXES}; do
4010 - [ $DEBUG -eq 1 ] && ${ECHO} " Adding index for ${i}"
3978 + if [[ -z ${TODO} ]]; then
3979 + X='Schema contains all required objectclass defintions'
3980 + else
3981 + # 2nd pass
3982 + typeset X SORTED
3983 + SORTED=${ print ${TODO// /$'\n'} | sort -n -t. ; }
3984 + TODO='' TODO2=''
3985 + for OID in ${SORTED} ; do
3986 + X="${MAP[${OID}]}"
3987 + OID2ODEF["${OID}"]="${X}"
3988 + # 1.3.18.0.2.6.254 requires 1.3.18.0.2.6.2549
3989 + # 1.3.18.0.2.6.255,1.3.18.0.2.6.257 require 1.3.18.0.2.6.258
3990 + [[ ${OID} == '1.3.18.0.2.6.254' \
3991 + || ${OID} == '1.3.18.0.2.6.255' \
3992 + || ${OID} == '1.3.18.0.2.6.257' ]] \
3993 + && TODO2+='objectclasses: ( '"${OID} NAME ${X}"' )\n' \
3994 + || TODO+='objectclasses: ( '"${OID} NAME ${X}"' )\n'
3995 + done
4011 3996
4012 - # Break p (pair) into i and j parts.
4013 - i=`${ECHO} $p | cut -d';' -f1`
4014 - j=`${ECHO} $p | cut -d';' -f2`
4015 - k=`${ECHO} $p | cut -d';' -f3`
4016 - m=`${ECHO} $p | cut -d';' -f4`
4017 -
4018 - # Set _jEXT to use as shortcut.
4019 - _jEXT="cn=${j},${_EXT}"
4020 -
4021 - # Check if entry exists first, if so, skip to next.
4022 - ${LDAPSEARCH} ${SERVER_ARGS} -b "cn=${i},${_jEXT}" -s base "objectclass=*" > /dev/null 2>&1
4023 - if [ $? -eq 0 ]; then
4024 - # Display index skipped.
4025 - ${ECHO} " ${i} vlv_index skipped already exists"
4026 - continue
3997 + nextFile modify $0
3998 + print 'dn: cn=schema\nchangetype: modify\nadd: objectclasses' \
3999 + "\n${TODO}${TODO2}" >${TMP[FILE]}
4000 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4001 + >&${TMPF[FD]} 2>&1
4002 + then
4003 + Log.fatal 'Adding objectclass definitions to schema failed'
4004 + return 67
4005 + fi
4006 + X='Schema objectclass definitions added'
4027 4007 fi
4028 4008
4029 - # Compute the VLV Scope from the LDAP_SEARCH_SCOPE.
4030 - # NOTE: A value of "base (0)" does not make sense.
4031 - case "$LDAP_SEARCH_SCOPE" in
4032 - sub) VLV_SCOPE="2" ;;
4033 - *) VLV_SCOPE="1" ;;
4034 - esac
4009 + showProgress "${X}."
4010 + return 0
4011 +}
4035 4012
4036 - # Here doc to create LDIF.
4037 - ( cat <<EOF
4038 -dn: ${_jEXT}
4039 -objectClass: top
4040 -objectClass: vlvSearch
4041 -cn: ${j}
4042 -vlvbase: ${k},${LDAP_BASEDN}
4043 -vlvscope: ${VLV_SCOPE}
4044 -vlvfilter: (${m})
4045 -aci: (target="ldap:///${_jEXT}")(targetattr="*")(version 3.0; acl "Config";allow(read,search,compare)userdn="ldap:///anyone";)
4013 +Man.addFunc add_suffix '' '[+NAME?add_suffix - add suffix to DS if needed.]
4014 +[+DESCRIPTION?Add a suffix to the DS if needed (\bTMPF[NEED_CREATE_SUFFIX]]\b is set) and optionally create the backend for it (\bTMPF[NEED_CREATE_BACKEND]]\b is set). Suffix entry and backend MUST be prepared by \bprep_create_sfx_entry()\b and \bprep_create_sfx_backend()\b correspondingly to have the following vars set:]{
4015 + [+STR[LDAP_SUFFIX]] ]
4016 + [+STR[DS_DB]] ]
4017 + [+TMP[SUFFIX_OBJ]] ]
4018 + [+TMP[SUFFIX_ATT]] ]
4019 + [+TMP[SUFFIX_VAL]] ]
4020 +}
4021 +[+RETURN VALUES]{
4022 + [+0?on success (suffix not needed or created successfully).]
4023 + [+1?otherwise (unable to create suffix).]
4024 +}
4025 +[+SEE ALSO?\bldapadd\b(1), \bdisplay_msg()\b.]
4026 +'
4027 +function add_suffix {
4028 + if (( ! TMPF[NEED_CREATE_BACKEND] )); then
4029 + showProgress "Database backend exists."
4030 + else
4031 + nextFile add "${0}-backend"
4032 + if (( TMPF[IS_OPENDJ] )); then
4033 + print '
4034 +dn: ds-cfg-backend-id='"${STR[DS_DB]}"',cn=Backends,cn=config
4035 +ds-cfg-backend-id: '"${STR[DS_DB]}"'
4036 +ds-cfg-base-dn: '"${STR[LDAP_SUFFIX]}"'
4037 +objectclass: top
4038 +objectclass: ds-cfg-backend
4039 +objectclass: ds-cfg-local-db-backend
4040 +ds-cfg-java-class: org.opends.server.backends.jeb.BackendImpl
4041 +ds-cfg-enabled: true
4042 +ds-cfg-writability-mode: enabled
4043 +ds-cfg-preload-time-limit: 0 ms
4044 +ds-cfg-compact-encoding: true
4045 +ds-cfg-entries-compressed: false
4046 +ds-cfg-index-entry-limit: 4000
4047 +ds-cfg-db-directory: db
4048 +ds-cfg-db-directory-permissions: 700
4049 +ds-cfg-disk-low-threshold: 100 mb
4050 +ds-cfg-disk-full-threshold: 20 mb
4051 +ds-cfg-db-run-cleaner: true
4052 +ds-cfg-db-cleaner-min-utilization: 50
4053 +ds-cfg-db-logging-file-handler-on: true
4054 +ds-cfg-db-logging-level: CONFIG
4055 +ds-cfg-db-log-filecache-size: 100
4056 +ds-cfg-db-log-file-max: 10 mb
4057 +ds-cfg-db-cache-size: 0 b
4058 +ds-cfg-db-cache-percent: 50
4059 +ds-cfg-db-evictor-core-threads: 1
4060 +ds-cfg-db-evictor-max-threads: 10
4061 +ds-cfg-db-evictor-nodes-per-scan: 10
4062 +ds-cfg-db-evictor-lru-only: true
4063 +ds-cfg-db-evictor-keep-alive: 600 s
4064 +ds-cfg-db-txn-no-sync: false
4065 +ds-cfg-db-txn-write-no-sync: true
4066 +ds-cfg-db-checkpointer-wakeup-interval: 30 s
4067 +ds-cfg-db-checkpointer-bytes-interval: 20 mb
4068 +' >${TMP[FILE]}
4069 + else
4070 + print '
4071 +dn: cn="'"${STR[LDAP_SUFFIX]}"'",cn=mapping tree,cn=config
4072 +objectclass: top
4073 +objectclass: extensibleObject
4074 +objectclass: nsMappingTree
4075 +cn: '"${STR[LDAP_SUFFIX]}"'
4076 +nsslapd-state: backend
4077 +nsslapd-backend: '"${STR[DS_DB]}"'
4046 4078
4047 -dn: cn=${i},${_jEXT}
4048 -cn: ${i}
4049 -vlvSort: cn uid
4079 +dn: cn='"${STR[DS_DB]}"',cn=ldbm database,cn=plugins,cn=config
4050 4080 objectclass: top
4051 -objectclass: vlvIndex
4052 -EOF
4053 -) > ${TMPDIR}/vlv_index_${i}
4081 +objectclass: extensibleObject
4082 +objectclass: nsBackendInstance
4083 +cn: '"${STR[DS_DB]}"'
4084 +nsslapd-suffix: '"${STR[LDAP_SUFFIX]}"'
4085 +' >${TMP[FILE]}
4086 + fi
4054 4087
4055 - # Add the index.
4056 - ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/vlv_index_${i} ${VERB}"
4057 - if [ $? -ne 0 ]; then
4058 - ${ECHO} " ERROR: Adding VLV index for ${i} failed!"
4059 - cleanup
4060 - exit 1
4088 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4089 + >&${TMPF[FD]} 2>&1
4090 + then
4091 + Log.fatal 'Unable to create backend' "'${STR[DS_DB]}'" \
4092 + 'with suffix' "'${STR[LDAP_SUFFIX]}'" 'due to server error.'
4093 + return 1
4094 + fi
4095 + showProgress "Database backend created."
4061 4096 fi
4062 4097
4063 - # Print message that index was created.
4064 - ${ECHO} " ${i} vlv_index Entry created"
4065 -
4066 - # Add command to list of vlvindex commands to run.
4067 - ${ECHO} " directoryserver -s ${_INSTANCE} vlvindex -n ${IDS_DATABASE} -T ${i}" >> ${TMPDIR}/ds5_vlvindex_list
4068 - ${ECHO} " <install-path>/bin/dsadm reindex -l -t ${i} <directory-instance-path> ${LDAP_SUFFIX}" >> ${TMPDIR}/ds6_vlvindex_list
4069 - done
4098 + if (( ! TMPF[NEED_CREATE_SUFFIX] )); then
4099 + showProgress "Suffix exists."
4100 + else
4101 + nextFile add $0
4102 + print '
4103 +dn: '"${STR[LDAP_SUFFIX]}"'
4104 +objectclass: top
4105 +objectclass: '"${TMP[SUFFIX_OBJ]}"'
4106 +'"${TMP[SUFFIX_ATT]}: ${TMP[SUFFIX_VAL]}"'
4107 +' >${TMP[FILE]}
4108 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4109 + >&${TMPF[FD]} 2>&1
4110 + then
4111 + Log.warn 'Unable to create entry' "'${STR[LDAP_SUFFIX]}'" 'of' \
4112 + "'${TMP[SUFFIX_OBJ]}'" 'class'
4113 + return 1
4114 + fi
4115 + showProgress "Suffix added."
4116 + fi
4117 + return 0
4070 4118 }
4071 4119
4120 +function add_suffix_aci {
4121 + typeset PW_STATE PW_STATE_RO ANY_NO_READ SELF_NO_WRITE
4122 + typeset ADMIN_DN ADMIN_GROUP_DN
4123 + if (( TMPF[IS_OPENDJ] )); then
4124 + # TBD: include Password Policy State extended ops ?
4072 4125
4073 -#
4074 -# display_vlv_cmds(): Display VLV index commands to run on server.
4075 -#
4076 -display_vlv_cmds()
4077 -{
4078 - if [ -s "${TMPDIR}/ds5_vlvindex_list" -o \
4079 - -s "${TMPDIR}/ds6_vlvindex_list" ]; then
4080 - display_msg display_vlv_list
4081 - fi
4126 + # password state information aka ds-pwp-*, pwd* and ds-pta-* WITHOUT
4127 + # attrs, which are schema flagged with NO-USER-MODIFICATION
4128 + PW_STATE=' ds-pwp-account-disabled || ds-pwp-account-expiration-time
4129 + || ds-pwp-last-login-time || ds-pwp-password-changed-by-required-time
4130 + || ds-pwp-password-policy-dn || ds-pwp-reset-time || ds-pwp-warned-time
4131 + || ds-privilege-name || pwdReset'
4132 + # password state information flagged with NO-USER-MODIFICATION
4133 + # ds-pwp-password-expiration-time is the same as pwdExpirationTime
4134 + # so save some parse time ;-)
4135 + PW_STATE_RO=' pwdExpirationTime || pwdChangedTime || pwdGraceUseTime
4136 + || pwdFailureTime || pwdHistory || pwdAccountLockedTime'
4137 + # People using PassThroughAuthentication probably wish that too:
4138 + #PW_STATE_RO+='|| ds-pta-cached-password || ds-pta-cached-password-time'
4082 4139
4083 - if [ -s "${TMPDIR}/ds5_vlvindex_list" ]; then
4084 - cat ${TMPDIR}/ds5_vlvindex_list
4085 - fi
4140 + # passwords + password state
4141 + ANY_NO_READ="userPassword || authPassword ||${PW_STATE}||${PW_STATE_RO}"
4142 + # aci + search limits aka ds-rlim-* + RW password state/policy
4143 + SELF_NO_WRITE='aci || ds-rlim-idle-time-limit
4144 + || ds-rlim-lookthrough-limit || ds-rlim-size-limit || ds-rlim-time-limit
4145 + || pwdPolicySubentry ||'"${PW_STATE}"
4146 + ADMIN_DN='uid=admin,cn=Administrators'
4147 + ADMIN_GROUP_DN='cn=Administrators'
4148 + ADMIN_DN+=',cn=admin data'
4149 + ADMIN_GROUP_DN+=',cn=admin data'
4150 + else
4151 + # DSEE
4152 + # password state information aka passwordObject
4153 + PW_STATE=' accountUnlockTime || passwordAllowChangeTime
4154 + || passwordExpWarned || passwordExpirationTime || passwordHistory
4155 + || passwordRetryCount || retryCountResetTime'
4086 4156
4087 - cat << EOF
4157 + # passwords + password state
4158 + ANY_NO_READ="userPassword ||${PW_STATE}"
4159 + # aci + search limits + password state/policy
4160 + SELF_NO_WRITE='aci || nsIdleTimeout || nsLookThroughLimit
4161 + || nsSizeLimit || nsTimeLimit || nsroledn || passwordPolicySubentry
4162 + ||'"${PW_STATE}"
4163 + ADMIN_DN='uid=admin,ou=Administrators'
4164 + ADMIN_GROUP_DN='cn=Configuration Administrators,ou=Groups'
4165 + ADMIN_DN+=',ou=TopologyManagement,o=NetscapeRoot'
4166 + ADMIN_GROUP_DN+=',ou=TopologyManagement,o=NetscapeRoot"'
4167 + fi
4088 4168
4169 + typeset -A RULES=(
4170 + [SFX_ANYONE_ACI_NAME]='aci: (targetattr != "'"${ANY_NO_READ//$'\n'}"'")
4171 + (
4172 + version 3.0; acl "'"${SFX_ANYONE_ACI_NAME}"'";
4173 + allow (read, search, compare) userdn = "ldap:///anyone";
4174 + )'
4175 + [SFX_SELF_ACI_NAME]='aci: (targetattr != "'"${SELF_NO_WRITE//$'\n'}"'")
4176 + (
4177 + version 3.0; acl "'"${SFX_SELF_ACI_NAME}"'";
4178 + allow (write) userdn = "ldap:///self";
4179 + )'
4180 + [SFX_ADMIN_ACI_NAME]='aci: (targetattr = "*")
4181 + (
4182 + version 3.0; acl "'"${SFX_ADMIN_ACI_NAME}"'";
4183 + allow (all) userdn = "ldap:///'"${ADMIN_DN}"'";
4184 + )'
4185 + [SFX_ADMINGRP_ACI_NAME]='aci: (targetattr ="*")
4186 + (
4187 + version 3.0; acl "'"${SFX_ADMINGRP_ACI_NAME}"'";
4188 + allow (all) groupdn = "ldap:///'"${ADMIN_GROUP_DN}"'";
4189 + )'
4190 + )
4089 4191
4090 -EOF
4192 + # Check and set if doesn't already exist
4193 + typeset -a LIST=( )
4194 + getACIs LIST "${STR[LDAP_SUFFIX]}"
4091 4195
4092 - if [ -s "${TMPDIR}/ds6_vlvindex_list" ]; then
4093 - cat ${TMPDIR}/ds6_vlvindex_list
4094 - fi
4196 + for ACI in "${!RULES[@]}" ; do
4197 + typeset -n NAME=${ACI}
4198 + [[ -z ${NAME} ]] && continue # if it has no name, ignore it
4199 + PATTERN='acl[ ]+"?'"${NAME}"'"?'
4200 + findACI LIST "${NAME}" "${PATTERN}" 'Suffix' || continue # exists
4201 + nextFile add "${0}-${NAME}"
4202 + print '
4203 +dn: '"${STR[LDAP_SUFFIX]}"'
4204 +changetype: modify
4205 +add: aci
4206 +'"${RULES[${ACI}]}"'
4207 +' >${TMP[FILE]}
4208 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4209 + >&${TMPF[FD]} 2>&1
4210 + then
4211 + Log.warn "Adding '${NAME}' suffix ACI failed"
4212 + return 1
4213 + fi
4214 + showProgress "Suffix ACI '${NAME}' added."
4215 + done
4216 + return 0
4095 4217 }
4096 4218
4097 -#
4098 -# keep_backward_compatibility(): Modify schema for the backward compatibility if
4099 -# there are the incompatible attributes already
4100 -#
4101 -keep_backward_compatibility()
4102 -{
4103 - ${EVAL} "${LDAPSEARCH} ${SERVER_ARGS} -b cn=schema -s base \
4104 - \"objectclass=*\" attributeTypes | ${GREP} -i memberGid-oid ${VERB}"
4105 - if [ $? -eq 0 ]; then
4106 - ${SED} -e 's/1\.3\.6\.1\.4\.1\.42\.2\.27\.5\.1\.30\ /memberGid-oid\ /' \
4107 - ${TMPDIR}/schema_attr > ${TMPDIR}/schema_attr.new
4108 - ${MV} ${TMPDIR}/schema_attr.new ${TMPDIR}/schema_attr
4109 - fi
4110 -
4111 - ${EVAL} "${LDAPSEARCH} ${SERVER_ARGS} -b cn=schema -s base \
4112 - \"objectclass=*\" attributeTypes | ${GREP} -i rfc822mailMember-oid \
4113 - ${VERB}"
4114 - if [ $? -eq 0 ]; then
4115 - ${SED} -e \
4116 - 's/1\.3\.6\.1\.4\.1\.42\.2\.27\.2\.1\.15\ /rfc822mailMember-oid\ /' \
4117 - ${TMPDIR}/schema_attr > ${TMPDIR}/schema_attr.new
4118 - ${MV} ${TMPDIR}/schema_attr.new ${TMPDIR}/schema_attr
4119 - fi
4219 +Man.addFunc add_base_objects '' '[+NAME?add_base_objects - add possibly missing, necessary base objects.]
4220 +[+DESCRIPTION?Determine all RDNs required to form the \bSTR[LDAP_BASEDN]]\b using the suffix \bSTR[LDAP_SUFFIX]]\b (RDN1,RDN2,...,suffix == baseDN) and create the missing entries.]
4221 +[+RETURN VALUES]{
4222 + [+0?on success (all entries available or created successfully).]
4223 + [+>= 66?a fatal error occured.]
4120 4224 }
4225 +[+SEE ALSO?\bnormalizeDN()\b, \bldapsearch\b(1), \bldapmodify\b(1).]
4226 +'
4227 +function add_base_objects {
4228 + # typeset -A STR
4229 + # STR[LDAP_BASEDN]=dc=x,dc=my,dc=do,dc=main,dc=de
4230 + # STR[LDAP_SUFFIX]=dc=do,dc=main,dc=de
4121 4231
4122 -#
4123 -# update_schema_attr(): Update Schema to support Naming.
4124 -#
4125 -update_schema_attr()
4126 -{
4127 - [ $DEBUG -eq 1 ] && ${ECHO} "In update_schema_attr()"
4232 + # Convert to lower case for basename.
4233 + typeset LC_DN=','${ normalizeDN "${STR[LDAP_BASEDN]}" l ; }
4234 + typeset LC_SFX=','${ normalizeDN "${STR[LDAP_SUFFIX]}" l ; }
4128 4235
4129 - ( cat <<EOF
4130 -dn: cn=schema
4131 -changetype: modify
4132 -add: attributetypes
4133 -attributetypes: ( 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 )
4134 -attributetypes: ( 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 )
4135 -attributetypes: ( 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 )
4136 -attributetypes: ( 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 )
4137 -attributetypes: ( 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 )
4138 -attributetypes: ( 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 )
4139 -attributetypes: ( 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 )
4140 -attributetypes: ( 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 )
4141 -attributetypes: ( 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 )
4142 -attributetypes: ( 1.3.6.1.4.1.42.2.27.2.1.15 NAME 'rfc822mailMember' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
4143 -attributetypes: ( 2.16.840.1.113730.3.1.30 NAME 'mgrpRFC822MailMember' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
4144 -attributetypes: ( 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 )
4145 -attributetypes: ( 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 )
4146 -attributetypes: ( 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 )
4147 -attributetypes: ( 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 )
4148 -attributetypes: ( 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 )
4149 -attributetypes: ( 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 )
4150 -attributetypes: ( 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 )
4151 -attributetypes: ( 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 )
4152 -attributetypes: ( 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 )
4153 -attributetypes: ( 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 )
4154 -attributetypes: ( 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 )
4155 -attributetypes: ( 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 )
4156 -attributetypes: ( 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 )
4157 -attributetypes: ( 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 )
4158 -attributetypes: ( 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 )
4159 -attributetypes: ( 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 )
4160 -attributetypes: ( 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 )
4161 -attributetypes: ( 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 )
4162 -attributetypes: ( 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 )
4163 -attributetypes: ( 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 )
4164 -attributetypes: ( 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 )
4165 -attributetypes: ( 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 )
4166 -attributetypes: ( 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 )
4167 -attributetypes: ( 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 )
4168 -attributetypes: ( 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 )
4169 -attributetypes: ( 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 )
4170 -attributetypes: ( 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 )
4171 -attributetypes: ( 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 )
4172 -attributetypes: ( 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 )
4173 -attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.30 NAME 'memberGid' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
4174 -attributetypes: ( 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 )
4175 -attributetypes: ( 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 )
4176 -attributetypes: ( 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 )
4177 -attributetypes: ( 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 )
4178 -attributetypes: ( 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 )
4179 -attributetypes: ( 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 )
4180 -attributetypes: ( 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 )
4181 -attributetypes: ( 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 )
4182 -attributetypes: ( 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 )
4183 -attributetypes: ( 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 )
4184 -attributetypes: ( 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 )
4185 -attributetypes: ( 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 )
4186 -attributetypes: ( 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 )
4187 -attributetypes: ( 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 )
4188 -attributetypes: ( 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 )
4189 -attributetypes: ( 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 )
4190 -attributetypes: ( 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 )
4191 -attributetypes: ( 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 )
4192 -attributetypes: ( 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 )
4193 -attributetypes: ( 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 )
4194 -attributetypes: ( 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 )
4195 -attributetypes: ( 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 )
4196 -attributetypes: ( 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 )
4197 -attributetypes: ( 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} )
4198 -attributetypes: ( 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 )
4199 -attributetypes: ( 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 )
4200 -attributetypes: ( 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} )
4201 -attributetypes: ( 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} )
4202 -attributetypes: ( 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} )
4203 -attributetypes: ( 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 )
4204 -attributetypes: ( 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} )
4205 -attributetypes: ( 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 )
4206 -attributetypes: ( 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 )
4207 -attributetypes: ( 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} )
4208 -attributetypes: ( 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 )
4209 -attributetypes: ( 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} )
4210 -attributetypes: ( 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} )
4211 -attributetypes: ( 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} )
4212 -attributetypes: ( 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} )
4213 -attributetypes: ( 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} )
4214 -attributetypes: ( 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 )
4215 -attributetypes: ( 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 )
4216 -attributetypes: ( 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 )
4217 -attributetypes: ( 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 )
4218 -attributetypes: ( 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 )
4219 -attributetypes: ( 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} )
4220 -attributetypes: ( 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} )
4221 -attributetypes: ( 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} )
4222 -attributetypes: ( 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} )
4223 -attributetypes: ( 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 )
4224 -attributetypes: ( 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 )
4225 -attributetypes: ( 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 )
4226 -attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.67 NAME 'ipTnetTemplateName' DESC 'Trusted Solaris network template template_name' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
4227 -attributetypes: ( 1.3.6.1.4.1.42.2.27.5.1.68 NAME 'ipTnetNumber' DESC 'Trusted Solaris network template ip_address' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
4228 -EOF
4229 -) > ${TMPDIR}/schema_attr
4236 + # first, test that baseDN ends with suffix
4237 + if [[ ${LC_DN: -${#LC_SFX}} != ${LC_SFX} ]]; then
4238 + # should not happen since check_basedn_suffix() succeeded
4239 + Log.fatal "Invalid suffix '${LC_SFX}' for Base DN '${LC_DN}'"
4240 + return 66
4241 + fi
4242 + # Save the stuff before LC_SFX w/o leading ',' -> further called prefix
4243 + LC_DN=${LC_DN:1:${#LC_DN}-${#LC_SFX}-1}
4230 4244
4231 - keep_backward_compatibility
4245 + # Remove redundant spaces around ',' and '=' first from LDAP_BASEDN
4246 + typeset DN=${ normalizeDN ${STR[LDAP_BASEDN]} ; }
4232 4247
4233 - # Add the entry.
4234 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/schema_attr ${VERB}"
4235 - if [ $? -ne 0 ]; then
4236 - ${ECHO} " ERROR: update of schema attributes failed!"
4237 - cleanup
4238 - exit 1
4239 - fi
4248 + # Now LC_DN and DN differ at most in lower vs. uppercase character and
4249 + # we can get the prefix of the baseDN by just copying corresponding chars
4250 + DN=",${DN:0:${#LC_DN}}"
4240 4251
4241 - # Display message that schema is updated.
4242 - ${ECHO} " ${STEP}. Schema attributes have been updated."
4243 - STEP=`expr $STEP + 1`
4244 -}
4252 + if [[ ${DN} == ',' ]]; then
4253 + X='No need to create a DN component (baseDN equals suffix)'
4254 + else
4255 + typeset LAST=${ normalizeDN ${STR[LDAP_SUFFIX]} ; } DC KEY VAL CLASS
4256 + X="Created DN components for ${DN#,}"
4257 + while [[ -n ${DN} ]]; do
4258 + # Get trailing key=val (DC) from DN and strip it off
4259 + DN=${DN%,*}
4260 + DC="${.sh.match#,}"
4261 + LAST="${DC},${LAST}"
4262 +
4263 + # Check if entry exists first, if so, skip to next.
4264 + ${LDAPSEARCH} ${CON_ARGS} -b "${LAST}" -s base \
4265 + 'objectclass=*' >/dev/null 2>&1 && continue
4266 +
4267 + VAL=${DC#*=}
4268 + KEY=${.sh.match%=}
4269 + # Determine the objectclass for the entry.
4270 + CLASS=${ get_objectclass ${KEY} ; }
4271 + if [[ -z ${CLASS} ]]; then
4272 + Log.fatal "Unable to determine objectClass for '${KEY}'." \
4273 + "Please create the following entry and re-run ${PROG}:" \
4274 + "${KEY}=${VAL},${LAST}"
4275 + return 66
4276 + fi
4245 4277
4278 + nextFile add "${0}-${LAST}"
4279 + print '
4280 +dn: '"${LAST}"'
4281 +'"${KEY}: ${VAL}"'
4282 +objectClass: top
4283 +objectClass: '"${CLASS}"'
4284 +' > ${TMP[FILE]}
4246 4285
4247 -#
4248 -# update_schema_obj(): Update the schema objectclass definitions.
4249 -#
4250 -update_schema_obj()
4251 -{
4252 - [ $DEBUG -eq 1 ] && ${ECHO} "In update_schema_obj()"
4286 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]}\
4287 + >&${TMPF[FD]} 2>&1
4288 + then
4289 + Log.fatal "Update of base objects '${DC}' failed"
4290 + return 66
4291 + fi
4292 + done
4293 + fi
4294 + showProgress "${X}."
4295 + return 0
4296 +}
4253 4297
4254 - # Add the objectclass definitions.
4255 - ( cat <<EOF
4256 -dn: cn=schema
4257 -changetype: modify
4258 -add: objectclasses
4259 -objectclasses: ( 1.3.6.1.1.1.2.14 NAME 'NisKeyObject' SUP top MUST ( cn $ nisPublickey $ nisSecretkey ) MAY ( uidNumber $ description ) )
4298 +Man.addFunc set_nisdomain '' '[+NAME?set_nisdomain - Add the NisDomainObject to the Base DN.]
4299 +[+DESCRIPTION?Add a NisDomainObject with nisdomain \bSTR[LDAP_DOMAIN]]\b to the \bSTR[LDAP_BASEDN]]\b unless there is already one.]
4300 +[+RETURN VALUES]{
4301 + [+0?on success.]
4302 + [+>= 66?a fatal error occured.]
4303 +}
4304 +[+SEE ALSO?\bldapsearch\b(1), \bldapmodify\b(1).]
4305 +'
4306 +function set_nisdomain {
4307 + # Check if nisDomain is already set
4308 + ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b "${STR[LDAP_BASEDN]}" \
4309 + -s base 'objectclass=*' 2>/dev/null | \
4310 + while read LINE ; do
4311 + if [[ ${LINE} == ~(Ei)^nisDomain= ]]; then
4312 + showProgress 'NisDomainObject was already set for' \
4313 + "'${STR[LDAP_BASEDN]}'."
4314 + return 0
4315 + fi
4316 + done
4260 4317
4261 -dn: cn=schema
4318 + nextFile modify $0
4319 + print '
4320 +dn: '"${STR[LDAP_BASEDN]}"'
4262 4321 changetype: modify
4263 -add: objectclasses
4264 -objectclasses: ( 1.3.6.1.1.1.2.15 NAME 'nisDomainObject' SUP top MUST nisDomain )
4322 +objectclass: nisDomainObject
4323 +nisdomain: '"${STR[LDAP_DOMAIN]}"'
4324 +' >${TMP[FILE]}
4265 4325
4266 -dn: cn=schema
4267 -changetype: modify
4268 -add: objectclasses
4269 -objectclasses: ( 1.3.6.1.1.1.2.16 NAME 'automountMap' SUP top MUST automountMapName MAY description )
4326 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4327 + >&${TMPF[FD]} 2>&1
4328 + then
4329 + Log.fatal "Update of NisDomainObject in '${STR[LDAP_BASEDN]}' failed"
4330 + return 66
4331 + fi
4270 4332
4271 -dn: cn=schema
4272 -changetype: modify
4273 -add: objectclasses
4274 -objectclasses: ( 1.3.6.1.1.1.2.17 NAME 'automount' SUP top MUST ( automountKey $ automountInformation ) MAY description )
4333 + showProgress "NisDomainObject added to '${STR[LDAP_BASEDN]}'."
4334 + return 0
4335 +}
4275 4336
4276 -dn: cn=schema
4277 -changetype: modify
4278 -add: objectclasses
4279 -objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.7 NAME 'SolarisNamingProfile' SUP top MUST ( cn $ SolarisLDAPservers $ SolarisSearchBaseDN ) MAY ( SolarisBindDN $ SolarisBindPassword $ SolarisAuthMethod $ SolarisTransportSecurity $ SolarisCertificatePath $ SolarisCertificatePassword $ SolarisDataSearchDN $ SolarisSearchScope $ SolarisSearchTimeLimit $ SolarisPreferredServer $ SolarisPreferredServerOnly $ SolarisCacheTTL $ SolarisSearchReferral ) )
4337 +Man.addFunc add_new_containers '' '[+NAME?add_new_containers - Add top level containers to the base DN.]
4338 +[+DESCRIPTION?Add the Name Service Switch top level containers to the \bSTR[LDAP_BASEDN]]\b unless they already exist.]
4339 +[+RETURN VALUES]{
4340 + [+0?on success.]
4341 + [+>= 66?a fatal error occured.]
4342 +}
4343 +[+SEE ALSO?\b/etc/nsswitch.ldap\b, \bldapsearch\b(1), \bldapmodify\b(1).]
4344 +'
4345 +function add_new_containers {
4346 + typeset OU
4280 4347
4281 -dn: cn=schema
4282 -changetype: modify
4283 -add: objectclasses
4284 -objectclasses: ( 2.16.840.1.113730.3.2.4 NAME 'mailGroup' SUP top MUST mail MAY ( cn $ mgrpRFC822MailMember ) )
4348 + for OU in people group rpc protocols networks netgroup \
4349 + aliases hosts services ethers profile printers projects \
4350 + SolarisAuthAttr SolarisProfAttr Timezone ipTnet
4351 + do
4352 + if ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
4353 + -b "ou=${OU},${STR[LDAP_BASEDN]}" -s base 'objectclass=*' \
4354 + >/dev/null 2>&1
4355 + then
4356 + showProgress "'ou=${OU}' exists."
4357 + continue
4358 + fi
4285 4359
4286 -dn: cn=schema
4287 -changetype: modify
4288 -add: objectclasses
4289 -objectclasses: ( 1.3.6.1.4.1.42.2.27.1.2.5 NAME 'nisMailAlias' SUP top MUST cn MAY rfc822mailMember )
4360 + nextFile add "${0}-${OU}"
4361 + print '
4362 +dn: ou='"${OU},${STR[LDAP_BASEDN]}"'
4363 +ou: '"${OU}"'
4364 +objectClass: top
4365 +objectClass: organizationalUnit
4366 +' > ${TMP[FILE]}
4290 4367
4291 -dn: cn=schema
4292 -changetype: modify
4293 -add: objectclasses
4294 -objectclasses: ( 1.3.6.1.4.1.42.2.27.1.2.6 NAME 'nisNetId' SUP top MUST cn MAY ( nisNetIdUser $ nisNetIdGroup $ nisNetIdHost ) )
4368 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4369 + >&${TMPF[FD]} 2>&1
4370 + then
4371 + Log.fatal "Adding 'ou=${OU}' failed"
4372 + return 66
4373 + fi
4374 + showProgress "'ou=${OU}' added."
4375 + done
4295 4376
4296 -dn: cn=schema
4297 -changetype: modify
4298 -add: objectclasses
4299 -objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.2 NAME 'SolarisAuditUser' SUP top AUXILIARY MAY ( SolarisAuditAlways $ SolarisAuditNever ) )
4377 + return 0
4378 +}
4300 4379
4301 -dn: cn=schema
4302 -changetype: modify
4303 -add: objectclasses
4304 -objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.3 NAME 'SolarisUserAttr' SUP top AUXILIARY MAY ( SolarisUserQualifier $ SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrKeyValue ) )
4380 +Man.addFunc add_auto_maps '' '[+NAME?add_auto_maps - Add the automount map entries.]
4381 +[+DESCRIPTION?Add the automount maps \bauto_home\b, \bauto_direct\b, \bauto_master\b, \bauto_shared\b to \bSTR[LDAP_BASEDN]]\b unless they already exist.]
4382 +[+RETURN VALUES]{
4383 + [+0?on success.]
4384 + [+>= 66?a fatal error occured.]
4385 +}
4386 +[+SEE ALSO?\bldapsearch\b(1), \bldapmodify\b(1).]
4387 +'
4388 +function add_auto_maps {
4389 + # AUTO_MAPS for maps to create
4390 + typeset AUTO_MAPS="auto_home auto_direct auto_master auto_shared" MAP
4305 4391
4306 -dn: cn=schema
4307 -changetype: modify
4308 -add: objectclasses
4309 -objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.4 NAME 'SolarisAuthAttr' SUP top MUST cn MAY ( SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrShortDesc $ SolarisAttrLongDesc $ SolarisAttrKeyValue ) )
4392 + for MAP in ${AUTO_MAPS}; do
4393 + # Check if automap already exist
4394 + if ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
4395 + -b "automountMapName=${MAP},${STR[LDAP_BASEDN]}" -s base \
4396 + 'objectclass=*' >/dev/null 2>&1
4397 + then
4398 + showProgress "'${MAP}' automount exists."
4399 + continue
4400 + fi
4310 4401
4311 -dn: cn=schema
4312 -changetype: modify
4313 -add: objectclasses
4314 -objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.5 NAME 'SolarisProfAttr' SUP top MUST cn MAY ( SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisAttrLongDesc $ SolarisAttrKeyValue ) )
4402 + nextFile add "${0}-${MAP}"
4403 + print '
4404 +dn: automountMapName='"${MAP},${STR[LDAP_BASEDN]}"'
4405 +automountMapName: '"${MAP}"'
4406 +objectClass: top
4407 +objectClass: automountMap
4408 +' > ${TMP[FILE]}
4409 +
4410 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4411 + >&${TMPF[FD]} 2>&1
4412 + then
4413 + Log.fatal "Adding '${MAP}' automount map failed"
4414 + return 66
4415 + fi
4416 + showProgress "'${MAP}' automount added."
4417 + done
4315 4418
4316 -dn: cn=schema
4317 -changetype: modify
4318 -add: objectclasses
4319 -objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.6 NAME 'SolarisExecAttr' SUP top AUXILIARY MAY ( SolarisKernelSecurityPolicy $ SolarisProfileType $ SolarisAttrReserved1 $ SolarisAttrReserved2 $ SolarisProfileID $ SolarisAttrKeyValue ) )
4419 + return 0
4420 +}
4320 4421
4321 -dn: cn=schema
4322 -changetype: modify
4323 -add: objectclasses
4324 -objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.1 NAME 'SolarisProject' SUP top MUST ( SolarisProjectID $ SolarisProjectName ) MAY ( memberUid $ memberGid $ description $ SolarisProjectAttr ) )
4422 +Man.addFunc modify_top_aci '' '[+NAME?modify_top_aci - add a deny self modify ACI.]
4423 +[+DESCRIPTION?Add the ACI \bUSER_ACI_NAME\b to \bSTR[LDAP_BASEDN]]\b to disable self modify of user attributes like uid, uidNumber, gidNumber, shadowExpire, etc. This does nothing if an ACI with the same name already exists for this entry.]
4424 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage USER_ACI_NAME ; }" '}
4425 +[+RETURN VALUES]{
4426 + [+0?on success (ACI already exists or added successfully).]
4427 + [+>= 66?a fatal error occured.]
4428 +}
4429 +[+SEE ALSO?\bgetACIs()\b, \bfindACI()\b, \bldapmodify\b(1).]
4430 +'
4431 +function modify_top_aci {
4432 + typeset PATTERN
4325 4433
4326 -dn: cn=schema
4327 -changetype: modify
4328 -add: objectclasses
4329 -objectclasses: ( 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 ) )
4434 + typeset -a LIST=( )
4435 + getACIs LIST || return 66
4330 4436
4331 -dn: cn=schema
4332 -changetype: modify
4333 -add: objectclasses
4334 -objectclasses: ( 1.3.18.0.2.6.2549 NAME 'slpService' DESC 'DUMMY definition' SUP top MUST objectclass )
4437 + # check, whether ACI already exists
4438 + PATTERN='acl[ ]+"?('"${USER_ACI_NAME}|${USER_ACI_NAME// /_}"')"?'
4439 + findACI LIST "${USER_ACI_NAME}" "${PATTERN}" || return 0 # exists
4335 4440
4336 -dn: cn=schema
4441 + # Create LDIF for top level ACI
4442 + nextFile modify $0
4443 + print '
4444 +dn: '"${STR[LDAP_BASEDN]}"'
4337 4445 changetype: modify
4338 -add: objectclasses
4339 -objectclasses: ( 1.3.18.0.2.6.254 NAME 'slpServicePrinter' DESC 'Service Location Protocol (SLP) information.' SUP slpService AUXILIARY )
4446 +add: aci
4447 +aci: (targetattr = "cn || uid || uidNumber || gidNumber || homeDirectory || shadowLastChange || shadowMin || shadowMax || shadowWarning || shadowInactive || shadowExpire || shadowFlag || memberUid || SolarisAttrKeyValue || SolarisAttrReserved1 || SolarisAttrReserved2 || SolarisUserQualifier")
4448 + (
4449 + version 3.0; acl "'"${USER_ACI_NAME}"'";
4450 + deny (write) userdn = "ldap:///self";
4451 + )
4452 +' > ${TMP[FILE]}
4340 4453
4341 -dn: cn=schema
4342 -changetype: modify
4343 -add: objectclasses
4344 -objectclasses: ( 1.3.18.0.2.6.258 NAME 'printerAbstract' DESC 'Printer related information.' SUP top ABSTRACT MAY ( printer-name $ printer-natural-language-configured $ printer-location $ printer-info $ printer-more-info $ printer-make-and-model $ printer-multiple-document-jobs-supported $ printer-charset-configured $ printer-charset-supported $ printer-generated-natural-language-supported $ printer-document-format-supported $ printer-color-supported $ printer-compression-supported $ printer-pages-per-minute $ printer-pages-per-minute-color $ printer-finishings-supported $ printer-number-up-supported $ printer-sides-supported $ printer-media-supported $ printer-media-local-supported $ printer-resolution-supported $ printer-print-quality-supported $ printer-job-priority-supported $ printer-copies-supported $ printer-job-k-octets-supported $ printer-current-operator $ printer-service-person $ printer-delivery-orientation-supported $ printer-stacking-order-supported $ printer-output-features-supported ) )
4454 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4455 + >&${TMPF[FD]} 2>&1
4456 + then
4457 + Log.fatal 'Deny user to change non-password attributes failed'
4458 + return 66
4459 + fi
4345 4460
4346 -dn: cn=schema
4347 -changetype: modify
4348 -add: objectclasses
4349 -objectclasses: ( 1.3.18.0.2.6.255 NAME 'printerService' DESC 'Printer information.' SUP printerAbstract STRUCTURAL MAY ( printer-uri $ printer-xri-supported ) )
4461 + showProgress "Self modify for non-password attributes disabled."
4462 + return 0
4463 +}
4350 4464
4351 -dn: cn=schema
4352 -changetype: modify
4353 -add: objectclasses
4354 -objectclasses: ( 1.3.18.0.2.6.257 NAME 'printerServiceAuxClass' DESC 'Printer information.' SUP printerAbstract AUXILIARY MAY ( printer-uri $ printer-xri-supported ) )
4465 +Man.addFunc add_vlv_aci '' '[+NAME?add_vlv_aci - Add ACI for VLV.]
4466 +[+DESCRIPTION?Add the global ACI to allow everyone read-only access to VLVs.]
4467 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage VLV_ACI_NAME ; }" '}
4468 +[+RETURN VALUES]{
4469 + [+0?on success (ACI added successfully).]
4470 + [+>= 66?a fatal error occured.]
4471 +}
4472 +[+SEE ALSO?\bldapmodify\b(1).]
4473 +'
4474 +function add_vlv_aci {
4475 + # VLV Request = 2.16.840.1.113730.3.4.9
4476 + typeset RULE='version 3.0; acl "'"${VLV_ACI_NAME}"'";\n\t'
4477 + RULE+='allow (read,search,compare) userdn = "ldap:///anyone";'
4478 + typeset DN='oid=2.16.840.1.113730.3.4.9,cn=features,cn=config'
4479 + (( TMPF[IS_OPENDJ] )) && DN='cn=Access Control Handler,cn=config'
4355 4480
4356 -dn: cn=schema
4357 -changetype: modify
4358 -add: objectclasses
4359 -objectclasses: ( 1.3.18.0.2.6.256 NAME 'printerIPP' DESC 'Internet Printing Protocol (IPP) information.' SUP top AUXILIARY MAY ( printer-ipp-versions-supported $ printer-multiple-document-jobs-supported ) )
4481 + typeset -a LIST=( )
4482 + getACIs LIST "${DN}" 'Global' || return 66
4360 4483
4361 -dn: cn=schema
4362 -changetype: modify
4363 -add: objectclasses
4364 -objectclasses: ( 1.3.18.0.2.6.253 NAME 'printerLPR' DESC 'LPR information.' SUP top AUXILIARY MUST printer-name MAY printer-aliases )
4484 + PATTERN='acl[ ]+"?('"${VLV_ACI_NAME}|${VLV_ACI_NAME// /_}"')"?'
4485 + findACI LIST "${VLV_ACI_NAME}" "${PATTERN}" 'Global' || return 0
4365 4486
4366 -dn: cn=schema
4487 + nextFile modify $0
4488 + if (( TMPF[IS_OPENDJ] )); then
4489 + print '
4490 +dn: '"${DN}"'
4367 4491 changetype: modify
4368 -add: objectclasses
4369 -objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.14 NAME 'sunPrinter' DESC 'Sun printer information' SUP top AUXILIARY MUST printer-name MAY ( sun-printer-bsdaddr $ sun-printer-kvp ) )
4370 -
4371 -dn: cn=schema
4492 +add: ds-cfg-global-aci
4493 +ds-cfg-global-aci: (targetcontrol = "2.16.840.1.113730.3.4.9")(targetattr != "aci")
4494 + (
4495 + '"${RULE}"'
4496 + )
4497 +' > ${TMP[FILE]}
4498 + else
4499 + print '
4500 +dn: '"${DN}"'
4372 4501 changetype: modify
4373 -add: objectclasses
4374 -objectclasses: ( 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 ) )
4502 +replace: aci
4503 +aci: (targetattr != "aci")
4504 + (
4505 + '"${RULE}"'
4506 + )
4507 +' > ${TMP[FILE]}
4508 + fi
4375 4509
4376 -dn: cn=schema
4377 -changetype: modify
4378 -add: objectclasses
4379 -objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.8 NAME 'ipTnetTemplate' DESC 'Object class for TSOL network templates' SUP top MUST ipTnetTemplateName MAY SolarisAttrKeyValue )
4510 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4511 + >&${TMPF[FD]} 2>&1
4512 + then
4513 + Log.fatal "Adding '${VLV_ACI_NAME}' global ACI failed"
4514 + return 66
4515 + fi
4380 4516
4381 -dn: cn=schema
4382 -changetype: modify
4383 -add: objectclasses
4384 -objectclasses: ( 1.3.6.1.4.1.42.2.27.5.2.9 NAME 'ipTnetHost' DESC 'Associates an IP address or wildcard with a TSOL template_name' SUP top AUXILIARY MUST ipTnetNumber )
4385 -EOF
4386 -) > ${TMPDIR}/schema_obj
4517 + showProgress "Global ACI '${VLV_ACI_NAME}' added."
4518 + return 0
4519 +}
4387 4520
4388 - # Add the entry.
4389 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/schema_obj ${VERB}"
4390 - if [ $? -ne 0 ]; then
4391 - ${ECHO} " ERROR: update of schema objectclass definitions failed!"
4392 - cleanup
4393 - exit 1
4394 - fi
4395 -
4396 - # Display message that schema is updated.
4397 - ${ECHO} " ${STEP}. Schema objectclass definitions have been added."
4398 - STEP=`expr $STEP + 1`
4521 +Man.addFunc add_proxyagent '' '[+NAME?add_proxyagent - Add proxy agent user to DS.]
4522 +[+DESCRIPTION?Add the proxy agent user \bSTR[LDAP_PROXYAGENT]]\b to the DS unless it already exists to allow nameservice access to the server.]
4523 +[+RETURN VALUES]{
4524 + [+0?on success (entry already exists or added successfully).]
4525 + [+>= 66?a fatal error occured.]
4399 4526 }
4527 +[+SEE ALSO?\bldapmodify\b(1).]
4528 +'
4529 +function add_proxyagent {
4530 + # Check if proxy agent already exists
4531 + if ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
4532 + -b "${STR[LDAP_PROXYAGENT]}" -s base 'objectclass=*' >/dev/null 2>&1
4533 + then
4534 + showProgress "Proxyagent identity exists."
4535 + return 0
4536 + fi
4400 4537
4401 -#
4402 -# modify_top_aci(): Modify the ACI for the top entry to disable self modify
4403 -# of user attributes.
4404 -#
4405 -modify_top_aci()
4406 -{
4407 - [ $DEBUG -eq 1 ] && ${ECHO} "In modify_top_aci()"
4538 + # Get cn and sn names from LDAP_PROXYAGENT.
4539 + typeset NAME="${STR[LDAP_PROXYAGENT]%%,*}"
4540 + NAME=${NAME#*=}
4408 4541
4409 - # Set ACI Name
4410 - ACI_NAME="LDAP_Naming_Services_deny_write_access"
4542 + # Add the entry
4543 + nextFile add $0
4544 + print '
4545 +dn: '"${STR[LDAP_PROXYAGENT]}"'
4546 +cn: '"${NAME}"'
4547 +sn: '"${NAME}"'
4548 +objectclass: top
4549 +objectclass: person
4550 +userpassword: '"${STR[LDAP_PROXYAGENT_CRED]}"'
4551 +' > ${TMP[FILE]}
4552 +
4553 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4554 + >&${TMPF[FD]} 2>&1
4555 + then
4556 + Log.fatal 'Adding proxyagent identity failed'
4557 + return 66
4558 + fi
4411 4559
4412 - # Search for ACI_NAME
4413 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_BASEDN}\" -s base objectclass=* aci > ${TMPDIR}/chk_top_aci 2>&1"
4414 - if [ $? -ne 0 ]; then
4415 - ${ECHO} "Error searching aci for ${LDAP_BASEDN}"
4416 - cat ${TMPDIR}/chk_top_aci
4417 - cleanup
4418 - exit 1
4419 - fi
4420 - ${GREP} "${ACI_NAME}" ${TMPDIR}/chk_top_aci > /dev/null 2>&1
4421 - if [ $? -eq 0 ]; then
4422 - ${ECHO} " ${STEP}. Top level ACI ${ACI_NAME} already exists for ${LDAP_BASEDN}."
4423 - STEP=`expr $STEP + 1`
4560 + showProgress 'Proxyagent identity added.'
4424 4561 return 0
4425 - fi
4562 +}
4426 4563
4427 - # Crate LDIF for top level ACI.
4428 - ( cat <<EOF
4429 -dn: ${LDAP_BASEDN}
4430 -changetype: modify
4431 -add: aci
4432 -aci: (targetattr = "cn||uid||uidNumber||gidNumber||homeDirectory||shadowLastChange||shadowMin||shadowMax||shadowWarning||shadowInactive||shadowExpire||shadowFlag||memberUid||SolarisAttrKeyValue||SolarisAttrReserved1||SolarisAttrReserved2||SolarisUserQualifier")(version 3.0; acl ${ACI_NAME}; deny (write) userdn = "ldap:///self";)
4433 --
4434 -EOF
4435 -) > ${TMPDIR}/top_aci
4436 -
4437 - # Add the entry.
4438 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/top_aci ${VERB}"
4439 - if [ $? -ne 0 ]; then
4440 - ${ECHO} " ERROR: Modify of top level ACI failed! (restricts self modify)"
4441 - cleanup
4442 - exit 1
4564 +Man.addFunc add_entry_by_DN '' '[+NAME?add_entry_by_DN - Add an ldif file by DN.]
4565 +[+DESCRIPTION?Add the entries in the given LDIF \afile\a to the DS unless a base entry for \aDN\a already exists.]
4566 +[+RETURN VALUES]{
4567 + [+0?on success (\aDN\a already exists or added successfully).]
4568 + [+1?on error (failed to add entries).]
4569 +}
4570 +[+SEE ALSO?\bldapsearch\b(1), \bldapadd\b(1).]
4571 +\n\n\aDN\a \afile\a
4572 +'
4573 +function add_entry_by_DN {
4574 + if ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b "$1" -s base \
4575 + 'objectclass=*' >/dev/null 2>&1
4576 + then
4577 + showProgress "'${1}' exists."
4578 + return 0
4443 4579 fi
4444 -
4445 - # Display message that ACI is updated.
4446 - MSG="ACI for ${LDAP_BASEDN} modified to disable self modify."
4447 - if [ $EXISTING_PROFILE -eq 1 ];then
4448 - ${ECHO} " ACI SET: $MSG"
4449 - else
4450 - ${ECHO} " ${STEP}. $MSG"
4451 - STEP=`expr $STEP + 1`
4452 - fi
4580 + if ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f "$2" >&${TMPF[FD]} 2>&1
4581 + then
4582 + showProgress "'${1}' added."
4583 + return 0
4584 + fi
4585 + Log.fatal "Adding '${1}' failed"
4586 + return 1
4453 4587 }
4454 4588
4455 -#
4456 -# find_and_delete_ACI(): Find an ACI in file $2 with a matching pattern $1.
4457 -# Delete the ACI and print a message using $3 as the ACI name. $3 is needed
4458 -# because it could have a different value than that of $1.
4459 -find_and_delete_ACI()
4460 -{
4461 - [ $DEBUG -eq 1 ] && ${ECHO} "In find_and_delete_ACI"
4589 +Man.addFunc add_id_mapping_rules '' '[+NAME?add_id_mapping_rules - Add Kerberos principal to DN mapping rules to the DS.]
4590 +[+DESCRIPTION?Add GSSAPI identity mapping rules for host credentails and user credentials to the DS config unless they already exists. Hosts are matched against \b*.STR[LDAP_DOMAIN]]@STR[LDAP_KRB_REALM]]\b and ou=hosts in \bSTR[LDAP_BASEDN]]\b, users against \b*.@STR[LDAP_KRB_REALM]]\b and uid=$1,ou=People in \bSTR[LDAP_BASEDN]]\b.]
4591 +[+SEE ALSO?\badd_entry_by_DN()\b.]
4592 +'
4593 +function add_id_mapping_rules {
4594 + Log.info 'Adding Kerberos principal to DN mapping rules ...'
4595 + typeset C_DN='cn=GSSAPI,cn=identity mapping,cn=config' OC='nsContainer'
4596 + if (( TMPF[IS_OPENDJ] )); then
4597 + # we create a new branch instead of reusing the default, possibly unused
4598 + # 'cn=Regular Expression,cn=Identity Mappers,cn=config' GSSAPI ID mapper
4599 + C_DN='cn=GSSAPI,cn=Identity Mappers,cn=config'
4600 + OC='ds-cfg-branch'
4601 + fi
4462 4602
4463 - # if an ACI with pattern $1 exists in file $2, delete it from ${LDAP_BASEDN}
4464 - ${EGREP} $1 $2 | ${SED} -e 's/aci=//' > ${TMPDIR}/grep_find_delete_aci 2>&1
4465 - if [ -s ${TMPDIR}/grep_find_delete_aci ]; then
4466 - aci_to_delete=`${CAT} ${TMPDIR}/grep_find_delete_aci`
4603 + nextFile add "${0}-krbPrincipal"
4604 + print '
4605 +dn: cn='"${C_DN}"'
4606 +objectClass: top
4607 +objectClass: '"${OC}"'
4608 +cn: GSSAPI
4609 +' > ${TMP[FILE]}
4610 + add_entry_by_DN "${C_DN}" ${TMP[FILE]} || return
4467 4611
4468 - # Create the tmp file to delete the ACI.
4469 - ( cat <<EOF
4470 -dn: ${LDAP_BASEDN}
4471 -changetype: modify
4472 -delete: aci
4473 -aci: ${aci_to_delete}
4474 -EOF
4475 - ) > ${TMPDIR}/find_delete_aci
4476 -
4477 - # Delete the ACI
4478 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/find_delete_aci ${VERB}"
4479 - if [ $? -ne 0 ]; then
4480 - ${ECHO} " ERROR: Remove of $3 ACI failed!"
4481 - cleanup
4482 - exit 1
4612 + typeset H_CN="host_auth_${STR[LDAP_KRB_REALM]}"
4613 + typeset H_DN="cn=${H_CN}, ${C_DN}"
4614 + nextFile add "${0}-krbHostAuth"
4615 + if (( TMPF[IS_OPENDJ] )); then
4616 + print '
4617 +# For now (2.6.0) OpenDJ supports a single-valued ds-cfg-identity-mapper, only.
4618 +# So either you merge this and the next Identity Mapper to something more useful
4619 +# together or just enable one of them until it gets fixed. For more information
4620 +# see https://bugster.forgerock.org/jira/browse/OPENDJ-521
4621 +dn: '"${H_DN}"'
4622 +cn: '"${H_CN}"'
4623 +objectClass: top
4624 +objectClass=ds-cfg-identity-mapper
4625 +objectClass=ds-cfg-regular-expression-identity-mapper
4626 +ds-cfg-java-class=org.opends.server.extensions.RegularExpressionIdentityMapper
4627 +ds-cfg-enabled=false
4628 +ds-cfg-match-base-dn=ou=hosts,'"${STR[LDAP_BASEDN]}"'
4629 +ds-cfg-match-pattern=host\/(.*).'"${STR[LDAP_DOMAIN]}@${STR[LDAP_KRB_REALM]}"'
4630 +ds-cfg-replace-pattern=$1
4631 +ds-cfg-match-attribute=cn
4632 +' > ${TMP[FILE]}
4633 + else
4634 + print '
4635 +dn: '"${H_DN}"'
4636 +objectClass: top
4637 +objectClass: nsContainer
4638 +objectClass: dsIdentityMapping
4639 +objectClass: dsPatternMatching
4640 +cn: '"${H_CN}"'
4641 +dsMatching-pattern: ${Principal}
4642 +dsMatching-regexp: host\/(.*).'"${STR[LDAP_DOMAIN]}@${STR[LDAP_KRB_REALM]}"'
4643 +dsSearchBaseDN: ou=hosts,'"${STR[LDAP_BASEDN]}"'
4644 +dsSearchFilter: (&(objectClass=ipHost)(cn=$1))
4645 +dsSearchScope: one
4646 +' > ${TMP[FILE]}
4483 4647 fi
4648 + add_entry_by_DN "${H_DN}" ${TMP[FILE]}
4484 4649
4485 - ${RM} -f ${TMPDIR}/find_delete_aci
4486 - # Display message that an ACL is deleted.
4487 - MSG="ACI $3 deleted."
4488 - if [ $EXISTING_PROFILE -eq 1 ]; then
4489 - ${ECHO} " ACI DELETED: $MSG"
4650 + typeset U_CN="user_auth_${STR[LDAP_KRB_REALM]}"
4651 + typeset U_DN="cn=${U_CN}, ${C_DN}"
4652 + nextFile add "${0}-krbUserAuth"
4653 + if (( TMPF[IS_OPENDJ] )); then
4654 + print '
4655 +dn: '"${U_DN}"'
4656 +cn: '"${U_CN}"'
4657 +objectClass: top
4658 +objectClass=ds-cfg-identity-mapper
4659 +objectClass=ds-cfg-regular-expression-identity-mapper
4660 +ds-cfg-java-class=org.opends.server.extensions.RegularExpressionIdentityMapper
4661 +ds-cfg-enabled=true
4662 +ds-cfg-match-base-dn=ou=People,'"${STR[LDAP_BASEDN]}"'
4663 +ds-cfg-match-pattern=(.*)@'"${STR[LDAP_KRB_REALM]}"'
4664 +ds-cfg-replace-pattern=$1
4665 +ds-cfg-match-attribute=uid
4666 +' > ${TMP[FILE]}
4490 4667 else
4491 - ${ECHO} " ${STEP}. $MSG"
4492 - STEP=`expr $STEP + 1`
4668 + print '
4669 +dn: '"${U_DN}"'
4670 +objectClass: top
4671 +objectClass: nsContainer
4672 +objectClass: dsIdentityMapping
4673 +objectClass: dsPatternMatching
4674 +cn: '"${U_CN}"'
4675 +dsMatching-pattern: ${Principal}
4676 +dsMatching-regexp: (.*)@'"${STR[LDAP_KRB_REALM]}"'
4677 +dsMappedDN: uid=$1,ou=People,'"${STR[LDAP_BASEDN]}"'
4678 +' > ${TMP[FILE]}
4493 4679 fi
4494 - fi
4680 + add_entry_by_DN "${U_DN}" ${TMP[FILE]}
4495 4681 }
4496 4682
4497 -#
4498 -# Add an ACI to deny non-admin access to shadow data when
4499 -# shadow update is enabled.
4500 -#
4501 -deny_non_admin_shadow_access()
4502 -{
4503 - [ $DEBUG -eq 1 ] && ${ECHO} "In deny_non_admin_shadow_access()"
4683 +Man.addFunc modify_userpassword_acl_for_gssapi '' '[+NAME?modify_userpassword_acl_for_gssapi - Allow hosts and user to read password(s).]
4684 +[+DESCRIPTION?Modify ACL to allow hosts to read all and a user to read its own password only, when sasl/GSSAPI bind is used.]
4685 +[+RETURN VALUES]{
4686 + [+0?on success (entries already exist or added successfully).]
4687 + [+>= 66?a fatal error occured.]
4688 +}
4689 +[+SEE ALSO?\badd_entry_by_DN()\b.]
4690 +'
4691 +function modify_userpassword_acl_for_gssapi {
4692 + typeset P_DN="ou=People,${STR[LDAP_BASEDN]}"
4693 + typeset H_DN="ou=Hosts,${STR[LDAP_BASEDN]}"
4504 4694
4505 - # Set ACI Names
4506 - ACI_TO_ADD="LDAP_Naming_Services_deny_non_admin_shadow_access"
4507 - ACI_TO_DEL="LDAP_Naming_Services_deny_non_host_shadow_access"
4695 + if ! ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b "${P_DN}" -s base \
4696 + 'objectclass=*' > /dev/null 2>&1
4697 + then
4698 + Log.verbose "'${P_DN}' does not exist"
4508 4699
4509 - # Search for ACI_TO_ADD
4510 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_BASEDN}\" -s base objectclass=* aci > ${TMPDIR}/chk_aci_non_admin 2>&1"
4511 - if [ $? -ne 0 ]; then
4512 - ${ECHO} "Error searching aci for ${LDAP_BASEDN}"
4513 - cleanup
4514 - exit 1
4515 - fi
4700 + nextFile add $0
4701 + print '
4702 +dn: '"${P_DN}"'
4703 +ou: People
4704 +objectClass: top
4705 +objectClass: organizationalUnit
4706 +' > ${TMP[FILE]}
4516 4707
4517 - # If an ACI with ${ACI_TO_ADD} already exists, we are done.
4518 - ${EGREP} ${ACI_TO_ADD} ${TMPDIR}/chk_aci_non_admin 2>&1 > /dev/null
4519 - if [ $? -eq 0 ]; then
4520 - MSG="ACI ${ACI_TO_ADD} already set for ${LDAP_BASEDN}."
4521 - if [ $EXISTING_PROFILE -eq 1 ]; then
4522 - ${ECHO} " NOT SET: $MSG"
4523 - else
4524 - ${ECHO} " ${STEP}. $MSG"
4525 - STEP=`expr $STEP + 1`
4708 + add_entry_by_DN "${P_DN}" ${TMP[FILE]}
4709 + else
4710 + Log.verbose "'${P_DN}' already exists"
4526 4711 fi
4527 - return 0
4528 - fi
4712 + typeset TARGET='userPassword' PATTERN
4713 + (( TMPF[IS_OPENDJ] )) && TARGET+=' || authPassword'
4529 4714
4530 - # The deny_non_admin_shadow_access and deny_non_host_shadow_access ACIs
4531 - # should be mutually exclusive, so if the latter exists, delete it.
4532 - find_and_delete_ACI ${ACI_TO_DEL} ${TMPDIR}/chk_aci_non_admin ${ACI_TO_DEL}
4715 + typeset -A RULES=(
4716 + [SELF_GSS_ACI_NAME]='aci: (targetattr = "'"${TARGET}"'")
4717 + (
4718 + version 3.0; acl self-read-pwd;
4719 + allow (read,search) userdn="ldap:///self" and authmethod="sasl GSSAPI";
4720 + )'
4721 + [HOST_GSS_ACI_NAME]='aci: (targetattr = "'"${TARGET}"'")
4722 + (
4723 + version 3.0; acl host-read-pwd;
4724 + allow (read,search) userdn="ldap:///cn=*+ipHostNumber=*,ou=Hosts,'"${STR[LDAP_BASEDN]}"'" and authmethod="sasl GSSAPI";
4725 + )'
4726 + )
4533 4727
4534 - # Create the tmp file to add.
4535 - ( cat <<EOF
4536 -dn: ${LDAP_BASEDN}
4728 + typeset -a LIST=( )
4729 + getACIs LIST "${P_DN}" || return 66
4730 +
4731 + for ACI in "${!RULES[@]}" ; do
4732 + typeset -n NAME=${ACI}
4733 + [[ -z ${NAME} ]] && continue # if it has no name, ignore it
4734 + PATTERN='acl[ ]+"?'"${NAME}"'"?'
4735 + findACI LIST "${NAME}" "${PATTERN}" 'ou=people' || continue # exists
4736 + nextFile add "${0}-${NAME}"
4737 + print '
4738 +dn: '"${P_DN}"'
4537 4739 changetype: modify
4538 4740 add: aci
4539 -aci: (target="ldap:///${LDAP_BASEDN}")(targetattr = "shadowLastChange||
4540 - shadowMin|| shadowMax||shadowWarning||shadowInactive||shadowExpire||
4541 - shadowFlag||userPassword") (version 3.0; acl ${ACI_TO_ADD};
4542 - deny (write,read,search,compare) userdn != "ldap:///${LDAP_ADMINDN}";)
4543 -EOF
4544 -) > ${TMPDIR}/non_admin_aci_write
4545 -
4546 - # Add the entry.
4547 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/non_admin_aci_write ${VERB}"
4548 - if [ $? -ne 0 ]; then
4549 - ${ECHO} " ERROR: Adding ACI ${ACI_TO_ADD} failed!"
4550 - ${CAT} ${TMPDIR}/non_admin_aci_write
4551 - cleanup
4552 - exit 1
4553 - fi
4741 +'"${RULES[${ACI}]}"'
4742 +' > ${TMP[FILE]}
4554 4743
4555 - ${RM} -f ${TMPDIR}/non_admin_aci_write
4556 - # Display message that the non-admin access to shadow data is denied.
4557 - MSG="Non-Admin access to shadow data denied."
4558 - if [ $EXISTING_PROFILE -eq 1 ]; then
4559 - ${ECHO} " ACI SET: $MSG"
4560 - else
4561 - ${ECHO} " ${STEP}. $MSG"
4562 - STEP=`expr $STEP + 1`
4563 - fi
4744 + if ! ${LDAPMODIFY} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4745 + >&${TMPF[FD]} 2>&1
4746 + then
4747 + Log.warn "Adding '${NAME}' ou=people ACI failed."
4748 + return 67
4749 + fi
4750 + showProgress "ou=people ACI '${NAME}' added."
4751 + done
4752 + return 0
4564 4753 }
4565 4754
4566 -#
4567 -# Add an ACI to deny non-host access to shadow data when
4568 -# shadow update is enabled and auth Method if gssapi.
4569 -#
4570 -deny_non_host_shadow_access()
4571 -{
4572 - [ $DEBUG -eq 1 ] && ${ECHO} "In deny_non_host_shadow_access()"
4755 +Man.addFunc add_profile '' '[+NAME?add_profile - Add client profile to server.]
4756 +[+DESCRIPTION?Generates a client profile and adds it to the DS as "\bcn=STR[LDAP_PROFILE_NAME]],ou=profile,STR[LDAP_BASEDN]]\b" unless it already exists and \bTMPF[DEL_OLD_PROFILE]]\b is not set. Other profile related variables are:]{
4757 + [+?STR[LDAP_SERVER_LIST]] ]
4758 + [+?STR[LDAP_SEARCH_SCOPE]] ]
4759 + [+?STR[LDAP_CRED_LEVEL]] ]
4760 + [+?STR[LDAP_AUTHMETHOD]] ]
4761 + [+?INT[LDAP_FOLLOWREF]] ]
4762 + [+?INT[LDAP_SEARCH_TIME_LIMIT]] ]
4763 + [+?INT[LDAP_PROFILE_TTL]] ]
4764 + [+?INT[LDAP_BIND_LIMIT]] ]
4765 + [+?STR[LDAP_PREF_SRVLIST]] ]
4766 + [+?STR[LDAP_SRV_AUTHMETHOD_PAM]] ]
4767 + [+?STR[LDAP_SRV_AUTHMETHOD_KEY]] ]
4768 + [+?STR[LDAP_SRV_AUTHMETHOD_CMD]] ]
4769 + [+?SSD]
4770 +}
4771 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage INT STR SSD ; }" '}
4772 +[+RETURN VALUES]{
4773 + [+0?on success.]
4774 + [+>= 66?fatal error.]
4775 +}
4776 +[+SEE ALSO?\bldapclient\b(1M), \bldapdelete\b(1), \bldapmodify\b(1).]
4777 +'
4778 +function add_profile {
4779 + # If profile name already exists, DELETE it, and add new one
4780 + if ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
4781 + -b "cn=${STR[LDAP_PROFILE_NAME]},ou=profile,${STR[LDAP_BASEDN]}" \
4782 + -s base 'objectclass=*' >/dev/null 2>&1
4783 + then
4784 + if (( ! TMPF[DEL_OLD_PROFILE] )); then
4785 + Log.fatal "Adding client profile name '${STR[LDAP_PROFILE_NAME]}'" \
4786 + 'failed (entry already exists)'
4787 + return 66
4788 + fi
4573 4789
4574 - # Set ACI Names
4575 - ACI_TO_ADD="LDAP_Naming_Services_deny_non_host_shadow_access"
4576 - ACI_TO_DEL="LDAP_Naming_Services_deny_non_admin_shadow_access"
4577 -
4578 - # Search for ACI_TO_ADD
4579 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_BASEDN}\" -s base objectclass=* aci > ${TMPDIR}/chk_aci_non_host 2>&1"
4580 - if [ $? -ne 0 ]; then
4581 - ${ECHO} "Error searching aci for ${LDAP_BASEDN}"
4582 - cleanup
4583 - exit 1
4584 - fi
4585 -
4586 - # If an ACI with ${ACI_TO_ADD} already exists, we are done.
4587 - ${EGREP} ${ACI_TO_ADD} ${TMPDIR}/chk_aci_non_host 2>&1 > /dev/null
4588 - if [ $? -eq 0 ]; then
4589 - MSG="ACI ${ACI_TO_ADD} already set for ${LDAP_BASEDN}."
4590 - if [ $EXISTING_PROFILE -eq 1 ]; then
4591 - ${ECHO} " NOT SET: $MSG"
4592 - else
4593 - ${ECHO} " ${STEP}. $MSG"
4594 - STEP=`expr $STEP + 1`
4790 + nextFile delete $0
4791 + print "cn=${STR[LDAP_PROFILE_NAME]},ou=profile,${STR[LDAP_BASEDN]}" \
4792 + >${TMP[FILE]}
4793 + if ! ${LDAPDELETE} ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4794 + >&${TMPF[FD]} 2>&1
4795 + then
4796 + Log.fatal 'Attempt to DELETE old client profile' \
4797 + "'${STR[LDAP_PROFILE_NAME]}' failed"
4798 + return 67
4799 + fi
4595 4800 fi
4596 - return 0
4597 - fi
4598 4801
4599 - # The deny_non_admin_shadow_access and deny_non_host_shadow_access ACIs
4600 - # should be mutually exclusive, so if the former exists, delete it.
4601 - find_and_delete_ACI ${ACI_TO_DEL} ${TMPDIR}/chk_aci_non_host ${ACI_TO_DEL}
4802 + # Build the "ldapclient genprofile" command string to execute
4803 + typeset -a ARG=( )
4804 + ARG+=( genprofile '-a' "profileName=${STR[LDAP_PROFILE_NAME]}" )
4602 4805
4603 - # Create the tmp file to add.
4604 - ( cat <<EOF
4605 -dn: ${LDAP_BASEDN}
4606 -changetype: modify
4607 -add: aci
4608 -aci: (target="ldap:///${LDAP_BASEDN}")(targetattr = "shadowLastChange||
4609 - shadowMin|| shadowMax||shadowWarning||shadowInactive||shadowExpire||
4610 - shadowFlag||userPassword") (version 3.0; acl ${ACI_TO_ADD};
4611 - deny (write,read,search,compare)
4612 - userdn != "ldap:///cn=*+ipHostNumber=*,ou=Hosts,${LDAP_BASEDN}";)
4613 -EOF
4614 -) > ${TMPDIR}/non_host_aci_write
4615 -
4616 - # Add the entry.
4617 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/non_host_aci_write ${VERB}"
4618 - if [ $? -ne 0 ]; then
4619 - ${ECHO} " ERROR: Adding ACI ${ACI_TO_ADD} failed!"
4620 - ${CAT} ${TMPDIR}/non_host_aci_write
4621 - cleanup
4622 - exit 1
4623 - fi
4806 + # Add required argument defaultSearchBase
4807 + ARG+=( -a "defaultSearchBase=${STR[LDAP_BASEDN]}" )
4624 4808
4625 - ${RM} -f ${TMPDIR}/non_host_aci_write
4626 - # Display message that the non-host access to shadow data is denied.
4627 - MSG="Non-host access to shadow data is denied."
4628 - if [ $EXISTING_PROFILE -eq 1 ]; then
4629 - ${ECHO} " ACI SET: $MSG"
4630 - else
4631 - ${ECHO} " ${STEP}. $MSG"
4632 - STEP=`expr $STEP + 1`
4633 - fi
4634 -}
4809 + # Add optional parameters
4810 + [[ -n ${STR[LDAP_SERVER_LIST]} ]] && \
4811 + ARG+=( -a "defaultServerList=${STR[LDAP_SERVER_LIST]}" )
4812 + [[ -n ${STR[LDAP_SEARCH_SCOPE]} ]] && \
4813 + ARG+=( -a "defaultSearchScope=${STR[LDAP_SEARCH_SCOPE]}" )
4814 + [[ -n ${STR[LDAP_CRED_LEVEL]} ]] && \
4815 + ARG+=( -a "credentialLevel=${STR[LDAP_CRED_LEVEL]}" )
4816 + [[ -n ${STR[LDAP_AUTHMETHOD]} ]] && \
4817 + ARG+=( -a "authenticationMethod=${STR[LDAP_AUTHMETHOD]}" )
4818 + (( INT[LDAP_FOLLOWREF] )) && X='TRUE"' || X='FALSE"'
4819 + ARG+=( -a "followReferrals=${X}" )
4820 + (( INT[LDAP_SEARCH_TIME_LIMIT] )) && \
4821 + ARG+=( -a "searchTimeLimit=${INT[LDAP_SEARCH_TIME_LIMIT]}" )
4822 + (( INT[LDAP_PROFILE_TTL] )) && \
4823 + ARG+=( -a "profileTTL=${INT[LDAP_PROFILE_TTL]}" )
4824 + [[ -n ${INT[LDAP_BIND_LIMIT]} ]] && \
4825 + ARG+=( -a "bindTimeLimit=${INT[LDAP_BIND_LIMIT]}" )
4826 + [[ -n ${STR[LDAP_PREF_SRVLIST]} ]] && \
4827 + ARG+=( -a "preferredServerList=${STR[LDAP_PREF_SRVLIST]}" )
4828 + [[ -n ${STR[LDAP_SRV_AUTHMETHOD_PAM]} ]] && \
4829 + ARG+=(-a "serviceAuthenticationMethod=${STR[LDAP_SRV_AUTHMETHOD_PAM]}")
4830 + [[ -n ${STR[LDAP_SRV_AUTHMETHOD_KEY]} ]] && \
4831 + ARG+=(-a "serviceAuthenticationMethod=${STR[LDAP_SRV_AUTHMETHOD_KEY]}")
4832 + [[ -n ${STR[LDAP_SRV_AUTHMETHOD_CMD]} ]] && \
4833 + ARG+=(-a "serviceAuthenticationMethod=${STR[LDAP_SRV_AUTHMETHOD_CMD]}")
4635 4834
4636 -#
4637 -# add_vlv_aci(): Add access control information (aci) for VLV.
4638 -#
4639 -add_vlv_aci()
4640 -{
4641 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_vlv_aci()"
4835 + # Add SSDs
4836 + typeset X
4837 + for X in "${SSD[@]}" ; do
4838 + ARG+=( -a "serviceSearchDescriptor=${X}" )
4839 + done
4642 4840
4643 - # Add the VLV ACI.
4644 - ( cat <<EOF
4645 -dn: oid=2.16.840.1.113730.3.4.9,cn=features,cn=config
4646 -changetype: modify
4647 -replace: aci
4648 -aci: (targetattr != "aci") (version 3.0; acl "VLV Request Control"; allow(read,search,compare) userdn = "ldap:///anyone";)
4649 -EOF
4650 -) > ${TMPDIR}/vlv_aci
4841 + # Execute "ldapclient genprofile" to create profile
4842 + nextFile add $0
4843 + if ! ${LDAPCLIENT} "${ARG[@]}" >${TMP[FILE]} 2>${TMP[DIR]}/gen_profile.err
4844 + then
4845 + Log.fatal 'ldapclient genprofile failed'
4846 + return 68
4847 + fi
4651 4848
4652 - # Add the entry.
4653 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/vlv_aci ${VERB}"
4654 - if [ $? -ne 0 ]; then
4655 - ${ECHO} " ERROR: Add of VLV ACI failed!"
4656 - cleanup
4657 - exit 1
4658 - fi
4849 + # Add the generated profile
4850 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4851 + >&${TMPF[FD]} 2>&1
4852 + then
4853 + log.fatal 'Attempt to add profile failed!'
4854 + return 69
4855 + fi
4659 4856
4660 - # Display message that schema is updated.
4661 - ${ECHO} " ${STEP}. Add of VLV Access Control Information (ACI)."
4662 - STEP=`expr $STEP + 1`
4857 + showProgress 'Client profile generated and pushed to the DS.'
4858 + return 0
4663 4859 }
4664 4860
4665 -
4666 -#
4667 -# set_nisdomain(): Add the NisDomainObject to the Base DN.
4668 -#
4669 -set_nisdomain()
4670 -{
4671 - [ $DEBUG -eq 1 ] && ${ECHO} "In set_nisdomain()"
4672 -
4673 - # Check if nisDomain is already set.
4674 - ${EVAL} "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_BASEDN}\" -s base \
4675 - \"objectclass=*\"" > ${TMPDIR}/chk_nisdomain 2>&1
4676 - ${EVAL} "${GREP} -i nisDomain ${TMPDIR}/chk_nisdomain ${VERB}"
4677 - if [ $? -eq 0 ]; then
4678 - ${ECHO} " ${STEP}. NisDomainObject for ${LDAP_BASEDN} was already set."
4679 - STEP=`expr $STEP + 1`
4680 - return 0
4681 - fi
4682 -
4683 - # Add the new top level containers.
4684 - ( cat <<EOF
4685 -dn: ${LDAP_BASEDN}
4686 -changetype: modify
4687 -objectclass: nisDomainObject
4688 -nisdomain: ${LDAP_DOMAIN}
4689 -EOF
4690 -) > ${TMPDIR}/nis_domain
4691 -
4692 - # Add the entry.
4693 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/nis_domain ${VERB}"
4694 - if [ $? -ne 0 ]; then
4695 - ${ECHO} " ERROR: update of NisDomainObject in ${LDAP_BASEDN} failed."
4696 - cleanup
4697 - exit 1
4698 - fi
4699 -
4700 - # Display message that schema is updated.
4701 - ${ECHO} " ${STEP}. NisDomainObject added to ${LDAP_BASEDN}."
4702 - STEP=`expr $STEP + 1`
4861 +Man.addFunc checkTaskCompletion '' '[+NAME?checkTaskCompletion - Wait and check completion of a DS task.]
4862 +[+DESCRIPTION?Checks the state of the DS task with the given \adn\a periodically until it got stopped due to an error or has been finished successfully, or the timeout has been hit. Timeout is an integer and specifies the number of seconds to max. wait for completion. If not given or invalid 60 will be used instead.]
4863 +[+RETURN VALUES]{
4864 + [+0?on success.]
4865 + [+1?task failed.]
4866 + [+2?timeout has been hit, task not yet finished or has an unknown state.]
4703 4867 }
4868 +[+See Also?\bldapsearch\b(1)]
4869 +\n\n\adn\a [\atimeout\a]
4870 +'
4871 +function checkTaskCompletion {
4872 + typeset DN="$1" STATUS='nstaskstatus=' TASKID X
4873 + integer TIMEOUT=${2:-${INT[TASK_TIMEOUT]}} RESULT=2 SEEN
4874 + (( TIMEOUT < 10 )) && TIMEOUT=60
4875 + (( TMPF[IS_OPENDJ] )) && STATUS='ds-task-state='
4876 + TASKID=${DN%%,*}
4877 + # Wait for task to finish, display current status.
4878 + while (( TIMEOUT > 0 )) ; do
4879 + SEEN=0 X=''
4880 + ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
4881 + -b "${DN}" -s base 'objectclass=*' ${STATUS%=} 2>/dev/null | \
4882 + while read LINE ; do
4883 + [[ ${LINE%%,*} == ${TASKID} ]] && SEEN=1 && continue
4884 + [[ -z ${X} && ${LINE:0:${#STATUS}} == ${STATUS} ]] && \
4885 + X=${LINE:${#STATUS}}
4886 + done
4887 + (( ! SEEN )) && break # an error occured
4888 + print -n '.'
4889 + [[ ${X} =~ Finished || ${X} == 'COMPLETED_SUCCESSFULLY' ]] && \
4890 + RESULT=0 && break
4891 + [[ ${X:0:12} == 'Index failed' || ${X:016} == 'STOPPED_BY_ERROR' ]] && \
4892 + RESULT=1 && break
4893 + sleep 1
4894 + (( TIMEOUT-=1 ))
4895 + done
4896 + # DSEE removes non-recurring tasks automagically, OpenDJ not
4897 + (( RESULT < 2 && TMPF[IS_OPENDJ] )) && \
4898 + ${LDAPDELETE} ${CON_ARGS} "${AUTH_ARGS[@]}" "${DN}" >&${TMPF[FD]} 2>&1
4899 + return ${RESULT}
4900 +}
4704 4901
4705 -
4706 -#
4707 -# check_attrName(): Check that the attribute name is valid.
4708 -# $1 Key to check.
4709 -# Returns 0 : valid name 1 : invalid name
4710 -#
4711 -check_attrName()
4712 -{
4713 - [ $DEBUG -eq 1 ] && ${ECHO} "In check_attrName()"
4714 - [ $DEBUG -eq 1 ] && ${ECHO} "check_attrName: Input Param = $1"
4715 -
4716 - ${ECHO} $1 | ${EGREP} '^[0-9]+(\.[0-9]+)*$' > /dev/null 2>&1
4717 - if [ $? -eq 0 ]; then
4718 - ${EVAL} "${LDAPSEARCH} ${SERVER_ARGS} -b cn=schema -s base \"objectclass=*\" \
4719 - attributeTypes | ${EGREP} -i '^attributetypes[ ]*=[ ]*\([ ]*$1 ' ${VERB}"
4720 - else
4721 - ${EVAL} "${LDAPSEARCH} ${SERVER_ARGS} -b cn=schema -s base \"objectclass=*\" \
4722 - attributeTypes | ${EGREP} -i \"'$1'\" ${VERB}"
4723 - fi
4724 -
4725 - if [ $? -ne 0 ]; then
4726 - return 1
4727 - else
4728 - return 0
4729 - fi
4902 +Man.addFunc rebuildIndex '' '[+NAME?rebuildIndex - Rebuild a single index.]
4903 +[+DESCRIPTION?Instruct the DS to rebuild the index with the name \aname\a. If the \aname\a starts with "vlv." it indicates a Virtual List View, which is supported for OpenDJ, only. Wrt. to OpenDJ and VLVs a return code of \b0\b does not necessaryly mean, that the index is finally in a non-degraded state. It just means, the task has been executed successfully.]
4904 +[+RETURN VALUES]{
4905 + [+0?on success.]
4906 + [+1?if a VLV index was specified, but the current DS is != OpenDJ/OpenDS.]
4907 + [+2?if the task failed or did not complete within 60 seconds.]
4908 + [+66?if scheduling a rebuild task on the DS failed.]
4730 4909 }
4910 +[+SEE ALSO?\bcheckTaskCompletion()\b, \bldapsearch\b(1), \bldapmodify\b(1).]
4911 +\n\n\aname\a
4912 +'
4913 +function rebuildIndex {
4914 + typeset IDX=$1
4915 + TASKNAME=${IDX}_${ date "+%Y_%m_%d_%H_%M_%S" ; }
4731 4916
4917 + if [[ ${IDX:0:4} == 'vlv.' ]] && (( ! TMPF[IS_OPENDJ] )) ; then
4918 + Log.warn 'Non-OpenDJ/OpenDS servers do not support VLV rebuildTasks'
4919 + return 1
4920 + fi
4732 4921
4733 -#
4734 -# get_objectclass(): Determine the objectclass for the given attribute name
4735 -# $1 Attribute name to check.
4736 -# _ATTR_NAME Return value, Object Name or NULL if unknown to idsconfig.
4737 -#
4738 -# NOTE: An attribute name can be valid but still we might not be able
4739 -# to determine the objectclass from the table.
4740 -# In such cases, the user needs to create the necessary object(s).
4741 -#
4742 -get_objectclass()
4743 -{
4744 - [ $DEBUG -eq 1 ] && ${ECHO} "In get_objectclass()"
4745 - [ $DEBUG -eq 1 ] && ${ECHO} "get_objectclass: Input Param = $1"
4922 + nextFile add "${0}-task-${TASKNAME}"
4923 + if (( TMPF[IS_OPENDJ] )); then
4924 + # NOTE: rebuildTask requires ldif-import LDAP privilege.
4925 + # It's a little bit inefficient: one could schedule a single task at
4926 + # the end of the function and use 'rebuildall' or a space separated
4927 + # list of all attributes in ds-task-rebuild-index to do it at once.
4928 + DN='ds-task-id='"${TASKNAME}"',cn=Scheduled Tasks,cn=Tasks'
4929 + print '
4930 +# rebuild-index --index '"${IDX}"' --baseDN '"${STR[LDAP_BASEDN]}"' \
4931 +# '"${CON_ARGS} ${AUTH_ARGS[@]}"' -X
4746 4932
4747 - # Set return value to NULL string.
4748 - _ATTR_NAME=""
4933 +dn: '"${DN}"'
4934 +ds-task-id: '"${TASKNAME}"'
4935 +objectClass: top
4936 +objectClass: ds-task
4937 +objectClass: ds-task-rebuild
4938 +ds-task-class-name: org.opends.server.tasks.RebuildTask
4939 +ds-task-rebuild-base-dn: '"${STR[LDAP_SUFFIX]}"'
4940 +ds-task-rebuild-index: '"${IDX}"'
4941 +#ds-task-rebuild-tmp-directory:
4942 +' > ${TMP[FILE]}
4943 + else
4944 + DN='cn='"${TASKNAME}"',cn=index,cn=tasks,cn=config'
4945 + print '
4946 +dn: '"${DN}"'
4947 +cn: '"${TASKNAME}"'
4948 +objectclass: top
4949 +objectclass: extensibleObject
4950 +nsInstance: '"${STR[DS_DB]}"'
4951 +nsIndexAttribute: '"${IDX}"'
4952 +' > ${TMP[FILE]}
4953 + fi
4749 4954
4750 - # Test key for type:
4751 - case `${ECHO} ${1} | tr '[A-Z]' '[a-z]'` in
4752 - ou | organizationalunitname | 2.5.4.11) _ATTR_NAME="organizationalUnit" ;;
4753 - dc | domaincomponent | 0.9.2342.19200300.100.1.25) _ATTR_NAME="domain" ;;
4754 - o | organizationname | 2.5.4.10) _ATTR_NAME="organization" ;;
4755 - c | countryname | 2.5.4.6) _ATTR_NAME="country" ;;
4756 - *) _ATTR_NAME="" ;;
4757 - esac
4955 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
4956 + >&${TMPF[FD]} 2>&1
4957 + then
4958 + Log.fatal "Adding task for '${IDX}' failed"
4959 + return 66
4960 + fi
4758 4961
4759 - [ $DEBUG -eq 1 ] && ${ECHO} "get_objectclass: _ATTR_NAME = $_ATTR_NAME"
4962 + checkTaskCompletion "${DN}" && print "" || { Log.warn 'FAILED'; return 2; }
4963 + return 0
4760 4964 }
4761 4965
4966 +Man.addFunc add_indexes '' '[+NAME?add_indexes - Add indexes.]
4967 +[+DESCRIPTION?Add indexes of the given \atypes\a (e.g. "pres eq") for the given \aattributes\a (e.g. "uidNumber gidnumber") and schedule corresponding tasks to actually create the indexes unless they already exist. Both arguments are handle as a whitespace separated list.]
4968 +[+RETURN VALUES]{
4969 + [+-1?syntax error (insufficient parameters).]
4970 + [+0?on success.]
4971 + [+>= 66?fatal error.]
4972 +}
4973 +[+SEE ALSO?\bldapsearch\b(1), \bldapmodify\b(1).]
4974 +\n\n\atypes\a \aattributes\a
4975 +'
4976 +function add_indexes {
4977 + if [[ -z ${STR[DS_DB]} ]]; then
4978 + get_backend || return 66
4979 + fi
4980 + [[ -z $1 || -z $2 ]] && Log.warn "${.sh.fun}(): syntax error" && return -1
4762 4981
4763 -#
4764 -# add_base_objects(): Add any necessary base objects.
4765 -#
4766 -add_base_objects()
4767 -{
4768 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_base_objects()"
4982 + typeset -l TYPES=${1//,/ } # we allow comma separated lists as well
4983 + typeset IDX=${2//,/ }
4769 4984
4770 - # Convert to lower case for basename.
4771 - format_string "${LDAP_BASEDN}"
4772 - LOWER_BASEDN="${FMT_STR}"
4773 - format_string "${LDAP_SUFFIX}"
4774 - LOWER_SUFFIX="${FMT_STR}"
4985 + Log.verbose "Processing '${TYPES// /,}' indexes ..."
4775 4986
4776 - [ $DEBUG -eq 1 ] && ${ECHO} "LOWER_BASEDN: ${LOWER_BASEDN}"
4777 - [ $DEBUG -eq 1 ] && ${ECHO} "LOWER_SUFFIX: ${LOWER_SUFFIX}"
4987 + typeset DN="cn=index,cn=${STR[DS_DB]},cn=ldbm database,cn=plugins,cn=config"
4988 + typeset LTYPE="nsIndexType: ${TYPES// /$'\n'nsIndexType: }"
4989 + typeset ATTR='cn' OC='extensibleObject' DST TASKNAME LINE X
4990 + integer SEEN
4991 + if (( TMPF[IS_OPENDJ] )); then
4992 + OC='ds-cfg-branch'
4993 + DN="cn=Index,ds-cfg-backend-id=${STR[DS_DB]},cn=Backends,cn=config"
4994 + ATTR='ds-cfg-attribute'
4995 + LTYPE=''
4996 + for X in ${TYPES}; do
4997 + [[ $X == 'eq' ]] && LTYPE+='ds-cfg-index-type: equality\n'
4998 + [[ $X == 'pres' ]] && LTYPE+='ds-cfg-index-type: presence\n'
4999 + [[ $X == 'sub' ]] && LTYPE+='ds-cfg-index-type: substring\n'
5000 + done
5001 + fi
4778 5002
4779 - # Create additional components.
4780 - if [ "${LOWER_BASEDN}" = "${LOWER_SUFFIX}" ]; then
4781 - [ $DEBUG -eq 1 ] && ${ECHO} "Base DN and Suffix equivalent"
4782 - else
4783 - # first, test that the suffix is valid
4784 - dcstmp=`basename "${LOWER_BASEDN}" "${LOWER_SUFFIX}"`
4785 - if [ "$dcstmp" = "${LOWER_BASEDN}" ]; then
4786 - # should not happen since check_basedn_suffix() succeeded
4787 - ${ECHO} "Invalid suffix ${LOWER_SUFFIX}"
4788 - ${ECHO} "for Base DN ${LOWER_BASEDN}"
4789 - cleanup
4790 - exit 1
5003 + # check, whether Index container exists - if not, create it
5004 + if ! ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b "${DN}" \
5005 + -s base 'objectclass=*' > /dev/null 2>&1
5006 + then
5007 + nextFile add $0
5008 + X=${DN%%,*}
5009 + print '
5010 +dn: '"${DN}"'
5011 +objectClass: top
5012 +objectClass: '"${OC}"'
5013 +cn: '"${X#*=}"'
5014 +' >${TMP[FILE]}
5015 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
5016 + >&${TMPF[FD]} 2>&1
5017 + then
5018 + Log.fatal 'Failed to add backend Index base'
5019 + return 66
5020 + fi
4791 5021 fi
4792 - # OK, suffix is valid, start working with LDAP_BASEDN
4793 - # field separator is ',' (i.e., space is a valid character)
4794 - dcstmp2="`${ECHO} ${LDAP_BASEDN} |
4795 - sed -e 's/[ ]*,[ ]*/,/g' -e 's/[ ]*=[ ]*/=/g'`"
4796 - dcs=""
4797 - # use dcstmp to count the loop, and dcstmp2 to get the correct
4798 - # string case
4799 - # dcs should be in reverse order, only for these components
4800 - # that need to be added
4801 - while [ -n "${dcstmp}" ]
4802 - do
4803 - i2=`${ECHO} "$dcstmp2" | cut -f1 -d','`
4804 - dk=`${ECHO} $i2 | awk -F= '{print $1}'`
4805 - dc=`${ECHO} $i2 | awk -F= '{print $2}'`
4806 - dcs="$dk=$dc,$dcs";
4807 - dcstmp2=`${ECHO} "$dcstmp2" | cut -f2- -d','`
4808 - dcstmp=`${ECHO} "$dcstmp" | cut -f2- -d','`
4809 - [ $DEBUG -eq 1 ] && \
4810 - ${ECHO} "dcs: ${dcs}\ndcstmp: ${dcstmp}\ndcstmp2: ${dcstmp2}\n"
4811 - done
4812 5022
5023 + for DST in ${IDX} ; do
5024 + # Check if entry exists first. If so, skip to next
5025 + if ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" \
5026 + -b "${ATTR}=${DST},${DN}" -s base 'objectclass=*' > /dev/null 2>&1
5027 + then
5028 + showProgress "'${DST}' index exists."
5029 + continue
5030 + fi
4813 5031
5032 + nextFile add "${0}-${DST}"
5033 + if (( TMPF[IS_OPENDJ] )); then
5034 + X=${LTYPE//'\n'/ }
5035 + X=${X//: /:}
5036 + print '
5037 +# dsconfig create-local-db-index '"${CON_ARGS} ${AUTH_ARGS[@]}"' -X \
5038 +# '"${X//ds-cfg-/--set }"' \
5039 +# --backend-name '"${STR[DS_DB]}"' --index-name '"${DST}"'
4814 5040
4815 - lastdc=${LDAP_SUFFIX}
4816 - dc=`${ECHO} "${dcs}" | cut -f1 -d','`
4817 - dcstmp=`${ECHO} "${dcs}" | cut -f2- -d','`
4818 - while [ -n "${dc}" ]; do
4819 - # Get Key and component from $dc.
4820 - dk2=`${ECHO} $dc | awk -F= '{print $1}'`
4821 - dc2=`${ECHO} $dc | awk -F= '{print $2}'`
5041 +dn: ds-cfg-attribute='"${DST},${DN}"'
5042 +ds-cfg-attribute: '"${DST}"'
5043 +objectClass: top
5044 +objectClass: ds-cfg-local-db-index
5045 +'"${LTYPE}"'
5046 +' > ${TMP[FILE]}
5047 + else
5048 + print '
5049 +dn: cn='"${DST},${DN}"'
5050 +objectClass: top
5051 +objectClass: nsIndex
5052 +cn: '"${DST}"'
5053 +nsSystemIndex: false
5054 +'"${LTYPE}"'
5055 +' > ${TMP[FILE]}
5056 + fi
5057 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
5058 + >&${TMPF[FD]} 2>&1
5059 + then
5060 + Log.fatal "Adding '${DST}' backend index failed"
5061 + return 67
5062 + fi
5063 + showProgress "'${DST}' backend index added."
5064 + rebuildIndex ${DST}
5065 + done
5066 + return 0
5067 +}
4822 5068
4823 - # At this point, ${dk2} is a valid attribute name
5069 +Man.addFunc add_eq_indexes '' '[+NAME?add_eq_indexes - Add indexes of type pres and eq.]
5070 +[+DESCRIPTION?Add eq,pres indexes and schedule corresponding tasks to actually create the indexes unless they already exist.]
5071 +[+RETURN VALUES]{
5072 + [+0?on success.]
5073 + [+>= 66?fatal error.]
5074 +}
5075 +[+SEE ALSO?\badd_indexes()\b.]
5076 +'
5077 +function add_eq_indexes {
5078 + add_indexes "pres eq" \
5079 + "uidNumber ipNetworkNumber gidnumber oncrpcnumber automountKey"
5080 +}
4824 5081
4825 - # Check if entry exists first, if so, skip to next.
4826 - ${LDAPSEARCH} ${SERVER_ARGS} -b "${dk2}=${dc2},$lastdc" -s base "objectclass=*" > /dev/null 2>&1
4827 - if [ $? -eq 0 ]; then
4828 - # Set the $lastdc to new dc.
4829 - lastdc="${dk2}=${dc2},$lastdc"
5082 +Man.addFunc add_sub_indexes '' '[+NAME?add_sub_indexes - Add indexes of type pres, eq and sub.]
5083 +[+DESCRIPTION?Add eq,pres,sub indexes and schedule corresponding tasks to actually create the indexes unless they already exist.]
5084 +[+RETURN VALUES]{
5085 + [+0?on success.]
5086 + [+>= 66?fatal error.]
5087 +}
5088 +[+SEE ALSO?\badd_indexes()\b.]
5089 +'
5090 +function add_sub_indexes {
5091 + add_indexes "pres eq sub" \
5092 + "ipHostNumber membernisnetgroup nisnetgrouptriple"
5093 +}
4830 5094
4831 - # Process next component.
4832 - dc=`${ECHO} "${dcstmp}" | cut -f1 -d','`
4833 - dcstmp=`${ECHO} "${dcstmp}" | cut -f2- -d','`
4834 - continue
5095 +Man.addFunc add_vlv_indexes_OpenDJ '' '[+NAME?add_vlv_indexes_OpenDJ - Add VLV indexes to OpenDS/OpenDJ.]
5096 +[+DESCRIPTION?OpenDS/OpenDJ specialized part of \badd_vlv_indexes()\b (pulled out for easier maintenance).]
5097 +[+SEE ALSO?\badd_vlv_indexes()\b, https://blogs.oracle.com/kanthi/entry/ldap_paged_results_more]
5098 +[+NOTES?\bpagedResultsControl\b and \bVLV\b is per default allowed for authenticated users, only. To check, try something like this:]{
5099 + [+?ldapsearch -r -j /tmp/pw -D "cn=Directory Manager" -h ldaphost \]
5100 + [+? -b "cn=Access Control Handler,cn=config" "objectclass=*" | \]
5101 + [+? egrep "1.2.840.113556.1.4.319|2.16.840.1.113730.3.4.9"]
5102 +}
5103 +\n\n\avname\a \afile\a
5104 +'
5105 +function add_vlv_indexes_OpenDJ {
5106 + typeset -n INDEX_TABLE=$1
5107 + typeset OUT="$2" ENTRY IDX_NAME CN SCOPE='single-level' BASE FILTER
4835 5108
4836 - fi
5109 + [[ ${STR[LDAP_SEARCH_SCOPE]} == sub ]] && SCOPE='subordinate-subtree'
5110 + BACKEND="cn=VLV Index,ds-cfg-backend-id=${STR[DS_DB]},cn=Backends,cn=config"
4837 5111
4838 - # Determine the objectclass for the entry.
4839 - get_objectclass $dk2
4840 - OBJ_Name=${_ATTR_NAME}
4841 - if [ "${OBJ_Name}" = "" ]; then
4842 - ${ECHO} "Cannot determine objectclass for $dk2"
4843 - ${ECHO} "Please create ${dk2}=${dc2},$lastdc entry and rerun idsconfig"
4844 - exit 1
4845 - fi
4846 -
4847 - # Add the new container.
4848 - ( cat <<EOF
4849 -dn: ${dk2}=${dc2},$lastdc
4850 -${dk2}: $dc2
5112 + # check, whether VLV Index container exists - if not, create it
5113 + if ! ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -b "${BACKEND}" \
5114 + -s base 'objectclass=*' > /dev/null 2>&1
5115 + then
5116 + nextFile add $0
5117 + print '
5118 +dn: '"${BACKEND}"'
4851 5119 objectClass: top
4852 -objectClass: ${OBJ_Name}
4853 -EOF
4854 -) > ${TMPDIR}/base_objects
5120 +objectClass: ds-cfg-branch
5121 +cn: VLV Index
5122 +' >${TMP[FILE]}
5123 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
5124 + >&${TMPF[FD]} 2>&1
5125 + then
5126 + Log.fatal 'Adding VLV Index base'
5127 + return 66
5128 + fi
5129 + fi
4855 5130
5131 + integer COUNT=0
5132 + # create index entries
5133 + for ENTRY in "${INDEX_TABLE[@]}" ; do
5134 + typeset -a F=( ${ENTRY} ) # split columns
5135 +
5136 + IDX_NAME="${STR[LDAP_DOMAIN]}.get${F[0]}"
5137 + BASE="ou=${F[2]},${STR[LDAP_BASEDN]}"
5138 + [[ ${F[2]} =~ = ]] && BASE="${BASE:3}" # cut out ou=
5139 + FILTER="objectClass=${F[3]}"
5140 + [[ ${F[3]:0:1} == '&' ]] && FILTER="&(objectClass=${F[3]:2}"
4856 5141
4857 - # Set the $lastdc to new dc.
4858 - lastdc="${dk2}=${dc2},$lastdc"
5142 + if ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -s base \
5143 + -b "ds-cfg-name=${IDX_NAME},${BACKEND}" 'objectclass=*' \
5144 + > /dev/null 2>&1
5145 + then
5146 + showProgress "'${IDX_NAME}' VLV index exists."
5147 + continue
5148 + fi
4859 5149
4860 - # Add the entry.
4861 - ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/base_objects ${VERB}"
4862 - if [ $? -ne 0 ]; then
4863 - ${ECHO} " ERROR: update of base objects ${dc} failed."
4864 - cleanup
4865 - exit 1
4866 - fi
5150 + nextFile add "${0}-${IDX_NAME}"
5151 + print '
5152 +# dsconfig create-local-db-vlv-index '"${CON_ARGS} ${AUTH_ARGS[@]}"' -X \
5153 +# --backend-name "'"${STR[DS_DB]}"'" \
5154 +# --set "base-dn:'"${BASE}"'" \
5155 +# --index-name '"${IDX_NAME}"' --set "sort-order:cn uid" \
5156 +# --set "scope:'"${SCOPE}"'" --set "filter:'"${FILTER}"'"
4867 5157
4868 - # Display message that schema is updated.
4869 - ${ECHO} " ${STEP}. Created DN component ${dc}."
4870 - STEP=`expr $STEP + 1`
5158 +dn: ds-cfg-name='"${IDX_NAME},${BACKEND}"'
5159 +objectClass: top
5160 +objectClass: ds-cfg-local-db-vlv-index
5161 +ds-cfg-name: '"${IDX_NAME}"'
5162 +ds-cfg-base-dn: '"${BASE}"'
5163 +ds-cfg-scope: '"${SCOPE}"'
5164 +ds-cfg-filter: '"${FILTER}"'
5165 +ds-cfg-sort-order: cn uid
5166 +aci: (targetattr = "*")
5167 + (
5168 + version 3.0; acl "Config";
5169 + allow (read,search,compare) userdn="ldap:///anyone";
5170 + )
5171 +' > ${TMP[FILE]}
4871 5172
4872 - # Process next component.
4873 - dc=`${ECHO} "${dcstmp}" | cut -f1 -d','`
4874 - dcstmp=`${ECHO} "${dcstmp}" | cut -f2- -d','`
5173 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
5174 + >&${TMPF[FD]} 2>&1
5175 + then
5176 + Log.fatal "Adding '${IDX_NAME}' VLV index failed"
5177 + return 67
5178 + fi
5179 + showProgress "'${IDX_NAME}' VLV index added."
5180 +
5181 + if rebuildIndex "vlv.${IDX_NAME}" ; then
5182 + (( COUNT++ ))
5183 + else
5184 + print "rebuild-index -b '${STR[LDAP_SUFFIX]}' " \
5185 + "--index 'vlv.${IDX_NAME}'" >>${OUT}
5186 + fi
4875 5187 done
4876 - fi
5188 + if (( COUNT )); then
5189 + # Bug or feature: Even if scheduled as task, VLV idx rebuild leaves
5190 + # the index in degraded state. So:
5191 + showProgress 'Rebuilding degraded indexes.'
5192 + if ! rebuildIndex rebuilddegraded ; then
5193 + print "svcadm disable opendj@VERS@\n" \
5194 + "rebuild-index -b '${STR[LDAP_SUFFIX]}' --rebuildDegraded\n" \
5195 + "svcadm enable opendj@VERS@"
5196 + >>${OUT}
5197 + fi
5198 + fi
4877 5199 }
4878 5200
5201 +Man.addFunc add_vlv_indexes_DSEE '' '[+NAME?add_vlv_indexes_DSEE - Add VLV indexes to DSEE.]
5202 +[+DESCRIPTION?DSEE specialized part of \badd_vlv_indexes()\b (pulled out for easier maintenance).]
5203 +[+SEE ALSO?\b\badd_vlv_indexes()\b.]
5204 +\n\n\avname\a \afile\a
5205 +'
5206 +function add_vlv_indexes_DSEE {
5207 + typeset -n INDEX_TABLE=$1
5208 + typeset OUT="$2" ENTRY IDX_NAME CN SCOPE=1 BASE FILTER
4879 5209
4880 -#
4881 -# add_new_containers(): Add the top level classes.
4882 -#
4883 -# $1 = Base DN
4884 -#
4885 -add_new_containers()
4886 -{
4887 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_new_containers()"
5210 + typeset INFO=( ${TMP[DS_INFO]} )
5211 + integer MAJOR=${INFO[${#INFO[@]}-2]}
5212 + typeset INSTANCE="@serverInstance@" LINE
5213 + ${LDAPSEARCH} -v ${CON_ARGS} "${AUTH_ARGS[@]}" -b 'cn=config' \
5214 + -s base 'objectclass=*' nsslapd-instancedir 2>/dev/null | \
5215 + while read LINE ; do
5216 + [[ ${LINE:0:20} == 'nsslapd-instancedir=' ]] && LINE=${LINE:20} && break
5217 + done
5218 + if (( MAJOR < 6 )); then
5219 + # DSEE 5.x only.
5220 + [[ ${LINE} =~ slapd- ]] && LINE=${LINE#*/} && INSTANCE=${LINE#*-}
5221 + else
5222 + # 6+ - the instance path
5223 + INSTANCE="${LINE}"
5224 + fi
5225 + [[ ${STR[LDAP_SEARCH_SCOPE]} == sub ]] && SCOPE=2
5226 + BACKEND="cn=${STR[DS_DB]},cn=ldbm database,cn=plugins,cn=config"
4888 5227
4889 - for ou in people group rpc protocols networks netgroup \
4890 - aliases hosts services ethers profile printers projects \
4891 - SolarisAuthAttr SolarisProfAttr Timezone ipTnet ; do
5228 + # create index entries
5229 + for ENTRY in "${INDEX_TABLE[@]}" ; do
5230 + typeset -a F=( ${ENTRY} ) # split columns
5231 +
5232 + IDX_NAME="${STR[LDAP_DOMAIN]}.get${F[0]}"
5233 + CN="${STR[LDAP_DOMAIN]}_${F[1]}_vlv_index"
5234 + BASE="ou=${F[2]},${STR[LDAP_BASEDN]}"
5235 + [[ ${F[2]} =~ = ]] && BASE="${BASE:3}" # cut out ou=
5236 + FILTER="objectClass=${F[3]}"
5237 + [[ ${F[3]:0:1} == '&' ]] && FILTER="&(objectClass=${F[3]:2}"
4892 5238
4893 - # Check if nismaps already exist.
4894 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"ou=${ou},${LDAP_BASEDN}\" -s base \"objectclass=*\" ${VERB}"
4895 - if [ $? -eq 0 ]; then
4896 - continue
4897 - fi
5239 + if ${LDAPSEARCH} ${CON_ARGS} "${AUTH_ARGS[@]}" -s base \
5240 + -b "cn=${IDX_NAME},cn=${CN},${BACKEND}" 'objectclass=*' \
5241 + > /dev/null 2>&1
5242 + then
5243 + showProgress "'${IDX_NAME}' VLV index exists."
5244 + continue
5245 + fi
4898 5246
4899 - # Create TMP file to add.
4900 - ( cat <<EOF
4901 -dn: ou=${ou},${LDAP_BASEDN}
4902 -ou: ${ou}
5247 + nextFile add "${0}-${IDX_NAME}"
5248 + print '
5249 +dn: '"cn=${CN},${BACKEND}"'
4903 5250 objectClass: top
4904 -objectClass: organizationalUnit
4905 -EOF
4906 -) > ${TMPDIR}/toplevel.${ou}
5251 +objectClass: vlvSearch
5252 +cn: '"${CN}"'
5253 +vlvbase: '"${BASE}"'
5254 +vlvscope: '${SCOPE}'
5255 +vlvfilter: ('"${FILTER}"')
5256 +aci: (target = "ldap:///'"cn=${CN},${BACKEND}"'") (targetattr = "*")
5257 + (
5258 + version 3.0; acl "Config";
5259 + allow (read,search,compare) userdn="ldap:///anyone";
5260 + )
4907 5261
4908 - # Add the entry.
4909 - ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/toplevel.${ou} ${VERB}"
4910 - if [ $? -ne 0 ]; then
4911 - ${ECHO} " ERROR: Add of ou=${ou} container failed!"
4912 - cleanup
4913 - exit 1
4914 - fi
4915 - done
5262 +dn: cn='"${IDX_NAME},cn=${CN},${BACKEND}"'
5263 +cn: '"${IDX_NAME}"'
5264 +vlvSort: cn uid
5265 +objectclass: top
5266 +objectclass: vlvIndex
5267 +' > ${TMP[FILE]}
4916 5268
4917 - # Display message that top level OU containers complete.
4918 - ${ECHO} " ${STEP}. Top level \"ou\" containers complete."
4919 - STEP=`expr $STEP + 1`
5269 + if ! ${LDAPMODIFY} -a ${CON_ARGS} "${AUTH_ARGS[@]}" -f ${TMP[FILE]} \
5270 + >&${TMPF[FD]} 2>&1
5271 + then
5272 + Log.fatal "Adding '${IDX_NAME}' VLV index failed"
5273 + return 66
5274 + fi
5275 + showProgress "'${IDX_NAME}' VLV index added."
5276 +
5277 + if (( MAJOR < 6 )); then
5278 + # DSEE 5.x
5279 + print "directoryserver -s '${INSTANCE}' vlvindex" \
5280 + "-n '${STR[DS_DB]}' -T '${IDX_NAME}'" >> ${OUT}
5281 + else
5282 + # assume DSEE 6+
5283 + print "dsadm reindex -l -t '${IDX_NAME}'" \
5284 + "'${INSTANCE}' '${STR[LDAP_SUFFIX]}'" >> ${OUT}
5285 + fi
5286 + done
4920 5287 }
4921 5288
5289 +Man.addFunc add_vlv_indexes '' '[+NAME?add_vlv_indexes - Add VLV indexes.]
5290 +[+DESCRIPTION?Create VLV indexes entries on the \bSTR[DS_DB]]\b for \bSTR[LDAP_DOMAIN]]\b with \bSTR[LDAP_SEARCH_SCOPE]]\b and create the script \bTMP[DIR]]/do_vlv_index\b to be started on the DS to actually re-index the DB.]
5291 +[+RETURN VALUES]{
5292 + [+0?on success.]
5293 + [+>= 66?fatal error.]
5294 +}
5295 +[+SEE ALSO?\bldapsearch\b(1), \bldapmodify\b(1).]
5296 +'
5297 +function add_vlv_indexes {
5298 + Log.verbose 'Processing VLV indexes ...'
4922 5299
4923 -#
4924 -# add_auto_maps(): Add the automount map entries.
4925 -#
4926 -# auto_home, auto_direct, auto_master, auto_shared
4927 -#
4928 -add_auto_maps()
4929 -{
4930 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_auto_maps()"
5300 + # F[0] F[1] F[2] F[3]
5301 + # ${LDAP_DOMAIN}.get ${LDAP_DOMAIN}_%s_vlv_index ou=%s objectClass=$1||&(%s)
5302 + typeset -a INDEXES=(
5303 + 'grent group group posixGroup'
5304 + 'hostent hosts hosts ipHost'
5305 + 'netent networks networks ipNetwork'
5306 + 'pwent passwd people posixAccount'
5307 + 'rpcent rpc rpc oncRpc'
5308 + 'spent shadow people shadowAccount'
5309 + # Indexes added during NIS to LDAP transition
5310 + 'auhoent auho automountMapName=auto_home automount'
5311 + 'soluent solu people SolarisUserAttr'
5312 + 'authent auth SolarisAuthAttr SolarisAuthAttr'
5313 + 'execent exec SolarisProfAttr &(SolarisExecAttr)(SolarisKernelSecurityPolicy=*)'
5314 + 'profent prof SolarisProfAttr &(SolarisProfAttr)(SolarisAttrLongDesc=*)'
5315 + 'mailent mail aliases mailGroup'
5316 + 'bootent _boot ethers &(bootableDevice)(bootParameter=*)'
5317 + 'ethent ethers ethers &(ieee802Device)(macAddress=*)'
5318 + 'ngrpent netgroup netgroup nisNetgroup'
5319 + 'ipnent ipn networks &(ipNetwork)(cn=*)'
5320 + 'maskent mask networks &(ipNetwork)(ipNetmaskNumber=*)'
5321 + 'prent pr printers printerService'
5322 + 'ip4ent ip4 hosts &(ipHost)(ipHostNumber=*.*)'
5323 + 'ip6ent ip6 hosts &(ipHost)(ipHostNumber=*:*)'
5324 + )
4931 5325
4932 - # Set AUTO_MAPS for maps to create.
4933 - AUTO_MAPS="auto_home auto_direct auto_master auto_shared"
5326 + # temp file for vlvindex commands
5327 + typeset OUT=${TMP[DIR]}/tmp
5328 + rm -f ${OUT} && touch ${OUT}
4934 5329
4935 - for automap in $AUTO_MAPS; do
4936 - # Check if automaps already exist.
4937 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"automountMapName=${automap},${LDAP_BASEDN}\" -s base \"objectclass=*\" ${VERB}"
4938 - if [ $? -eq 0 ]; then
4939 - continue
5330 + if (( TMPF[IS_OPENDJ] )); then
5331 + add_vlv_indexes_OpenDJ INDEXES ${OUT}
5332 + else
5333 + add_vlv_indexes_DSEE INDEXES ${OUT}
4940 5334 fi
4941 -
4942 - # Create the tmp file to add.
4943 - ( cat <<EOF
4944 -dn: automountMapName=${automap},${LDAP_BASEDN}
4945 -automountMapName: ${automap}
4946 -objectClass: top
4947 -objectClass: automountMap
4948 -EOF
4949 -) > ${TMPDIR}/automap.${automap}
4950 -
4951 - # Add the entry.
4952 - ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/automap.${automap} ${VERB}"
4953 - if [ $? -ne 0 ]; then
4954 - ${ECHO} " ERROR: Add of automap ${automap} failed!"
4955 - cleanup
4956 - exit 1
4957 - fi
4958 - done
4959 -
4960 - # Display message that automount entries are updated.
4961 - ${ECHO} " ${STEP}. automount maps: $AUTO_MAPS processed."
4962 - STEP=`expr $STEP + 1`
5335 + nextFile sh
5336 + mv ${OUT} ${TMP[FILE]}
5337 + TMP[VLV_CMDS]=${TMP[FILE]}
4963 5338 }
4964 5339
5340 +Man.addFunc display_vlv_cmds '' '[+NAME?display_vlv_cmds - Display VLV index commands to run on server.]
5341 +[+DESCRIPTION?Display VLV index commands to run on server and save the file to /var/tmp/doIndexVLV-\bSTR[DS_HOST]].sh\b.]
5342 +'
5343 +function display_vlv_cmds {
5344 + typeset SAV="/var/tmp/doIndexVLV-${STR[DS_HOST]}.sh"
4965 5345
4966 -#
4967 -# add_proxyagent(): Add entry for nameservice to use to access server.
4968 -#
4969 -add_proxyagent()
4970 -{
4971 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_proxyagent()"
5346 + [[ -s ${TMP[VLV_CMDS]} ]] || return
5347 + # some problems occured, so the file is not empty
5348 + [[ -e ${SAV} ]] && SAV="${SAV%.sh}-$$.sh"
5349 + cp -p ${TMP[VLV_CMDS]} "${SAV}"
4972 5350
4973 - # Check if proxy agent already exists.
4974 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_PROXYAGENT}\" -s base \"objectclass=*\" ${VERB}"
4975 - if [ $? -eq 0 ]; then
4976 - ${ECHO} " ${STEP}. Proxy Agent ${LDAP_PROXYAGENT} already exists."
4977 - STEP=`expr $STEP + 1`
4978 - return 0
5351 + typeset MSG='NOTE: '"${PROG}"'configured the entries for VLV indexes.'
5352 + if (( TMPF[IS_OPENDJ] )); then
5353 + MSG+='
5354 +To create the actual VLV indexes, you need to stop the DS on the host
5355 +'"'${STR[DS_HOST]}'"', e.g. using "svcadm disable -t opendj@VERS@"
5356 +or, if manually started, "ds-stop" and than run the commands shown in the file
5357 +'"'${SAV}'"'. Than restart the DS e.g. using
5358 +"svcadm enable opendj@VERS@" or "ds-start".
5359 +'
5360 + else
5361 + typeset INFO=( ${DS_INFO[@]} )
5362 + if (( INFO[1] >= 6 )); then
5363 + MSG+='
5364 +Use the dsadm command delivered with the DS on the host '"'${STR[DS_HOST]}'"'
5365 +to stop the server. Then, using dsadm, follow the dsadm examples shown in the
5366 +file '"'${SAV}'"' to create the actual VLV indexes.
5367 +'
5368 + else
5369 + MSG+='
5370 +Use the directoryserver(1m) script on the host '"'${STR[DS_HOST]}'"'
5371 +to stop the server. Then, using directoryserver, follow the directoryserver
5372 +examples shown in the file '"'${SAV}'"' to create the
5373 +actual VLV indexes.
5374 +'
5375 + fi
4979 5376 fi
4980 -
4981 - # Get cn and sn names from LDAP_PROXYAGENT.
4982 - cn_tmp=`${ECHO} ${LDAP_PROXYAGENT} | cut -f1 -d, | cut -f2 -d=`
4983 -
4984 - # Create the tmp file to add.
4985 - ( cat <<EOF
4986 -dn: ${LDAP_PROXYAGENT}
4987 -cn: ${cn_tmp}
4988 -sn: ${cn_tmp}
4989 -objectclass: top
4990 -objectclass: person
4991 -userpassword: ${LDAP_PROXYAGENT_CRED}
4992 -EOF
4993 -) > ${TMPDIR}/proxyagent
4994 -
4995 - # Add the entry.
4996 - ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/proxyagent ${VERB}"
4997 - if [ $? -ne 0 ]; then
4998 - ${ECHO} " ERROR: Adding proxyagent failed!"
4999 - cleanup
5000 - exit 1
5001 - fi
5002 -
5003 - # Display message that schema is updated.
5004 - ${ECHO} " ${STEP}. Proxy Agent ${LDAP_PROXYAGENT} added."
5005 - STEP=`expr $STEP + 1`
5377 + Log.info "\n\n${MSG}"
5006 5378 }
5007 5379
5008 -#
5009 -# allow_proxy_read_pw(): Give Proxy Agent read permission for password.
5010 -#
5011 -allow_proxy_read_pw()
5012 -{
5013 - [ $DEBUG -eq 1 ] && ${ECHO} "In allow_proxy_read_pw()"
5380 +Man.addFunc doMain '' '[+NAME?doMain - the main entry point.]
5381 +[+DESCRIPTION?The entry point, where the real work starts.]
5382 +'
5383 +function doMain {
5384 + # Initialize the variables that need to be set to NULL, or some
5385 + # other initial value before the rest of the functions can be called
5386 + init || return 1
5387 + show_vars
5014 5388
5015 - # Search for ACI_NAME
5016 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_BASEDN}\" -s base objectclass=* aci > ${TMPDIR}/chk_proxyread_aci 2>&1"
5017 - ${GREP} "${PROXY_ACI_NAME}" ${TMPDIR}/chk_proxyread_aci > /dev/null 2>&1
5018 - if [ $? -eq 0 ]; then
5019 - ${ECHO} " ${STEP}. Proxy ACI ${PROXY_ACI_NAME=} already exists for ${LDAP_BASEDN}."
5020 - STEP=`expr $STEP + 1`
5021 - return 0
5022 - fi
5389 + # Print extra line to separate from prompt
5390 + print
5023 5391
5024 - # Create the tmp file to add.
5025 - ( cat <<EOF
5026 -dn: ${LDAP_BASEDN}
5027 -changetype: modify
5028 -add: aci
5029 -aci: (target="ldap:///${LDAP_BASEDN}")(targetattr="userPassword")
5030 - (version 3.0; acl ${PROXY_ACI_NAME}; allow (compare,read,search)
5031 - userdn = "ldap:///${LDAP_PROXYAGENT}";)
5032 -EOF
5033 -) > ${TMPDIR}/proxy_read
5034 -
5035 - # Add the entry.
5036 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/proxy_read ${VERB}"
5037 - if [ $? -ne 0 ]; then
5038 - ${ECHO} " ERROR: Allow ${LDAP_PROXYAGENT} to read password failed!"
5039 - cleanup
5040 - exit 1
5041 - fi
5392 + # Either load the user specified config file or prompt user for config info
5393 + if [[ -n ${TMP[IN]} ]]; then
5394 + load_config_file "${TMP[IN]}"
5395 + validate_info || return 1 # Validate basic info in file
5396 + else
5397 + display_msg 'backup_server'
5398 + get_confirm 'Do you wish to continue with server setup (y/n/h)?' \
5399 + 'n' 'backup_help' && return 1
5042 5400
5043 - # Display message that schema is updated.
5044 - ${ECHO} " ${STEP}. Give ${LDAP_PROXYAGENT} read permission for password."
5045 - STEP=`expr $STEP + 1`
5046 -}
5401 + # Ask for all required infos
5402 + prompt_config_info || return 1
5403 + (( INT[LDAP_ENABLE_SHADOW_UPDATE] && INT[EXISTING_PROFILE] )) && \
5404 + return 0 # just enabled shadow update in an existing profile
5405 + # Allow user to modify results
5406 + integer RES
5407 + display_summary
5408 + RES=$?
5409 + # save the work for now, so that even on exit/errors it can be re-used
5410 + [[ -n ${TMP[OUT]} ]] && create_config_file "${TMP[OUT]}"
5411 + (( RES )) && return 1
5412 + fi
5047 5413
5048 -# Delete Proxy Agent read permission for password.
5049 -delete_proxy_read_pw()
5050 -{
5051 - [ $DEBUG -eq 1 ] && ${ECHO} "In delete_proxy_read_pw()"
5414 + if (( INT[NEED_TIME] )); then
5415 + modify_timelimit || return 1
5416 + fi
5052 5417
5053 - # Search for ACI_NAME
5054 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"${LDAP_BASEDN}\" -s base objectclass=* aci > ${TMPDIR}/chk_proxyread_aci 2>&1"
5055 - ${GREP} "${PROXY_ACI_NAME}" ${TMPDIR}/chk_proxyread_aci | \
5056 - ${SED} -e 's/aci=//' > ${TMPDIR}/grep_proxyread_aci 2>&1
5057 - if [ $? -ne 0 ]; then
5058 - ${ECHO} "Proxy ACI ${PROXY_ACI_NAME} does not exist for ${LDAP_BASEDN}."
5059 - return 0
5060 - fi
5418 + if (( INT[NEED_SIZE] )); then
5419 + modify_sizelimit || return 1
5420 + fi
5061 5421
5062 - # We need to remove proxy agent's read access to user passwords,
5063 - # but We do not know the value of the ${LDAP_PROXYAGENT} here, so
5064 - # 1. if only one match found, delete it
5065 - # 2. if more than one matches found, ask the user which one to delete
5066 - HOWMANY=`${WC} -l ${TMPDIR}/grep_proxyread_aci | ${NAWK} '{print $1}'`
5067 - if [ $HOWMANY -eq 0 ]; then
5068 - ${ECHO} "Proxy ACI ${PROXY_ACI_NAME} does not exist for ${LDAP_BASEDN}."
5069 - return 0
5070 - fi
5071 - if [ $HOWMANY -eq 1 ];then
5072 - proxy_aci=`${CAT} ${TMPDIR}/grep_proxyread_aci`
5073 - else
5074 - ${CAT} << EOF
5422 + # Modify the password storage scheme to support CRYPT
5423 + if (( INT[NEED_CRYPT] )); then
5424 + modify_pwd_crypt || return 1
5425 + fi
5075 5426
5076 -Proxy agent is not allowed to read user passwords when shadow
5077 -update is enabled. There are more than one proxy agents found.
5078 -Please select the currently proxy agent being used, so that
5079 -idsconfig can remove its read access to user passwords.
5427 + # schema modifications
5428 + modify_cn || return 1
5429 + update_schema_attr || return 1
5430 + update_schema_obj || return 1
5080 5431
5081 -The proxy agents are:
5432 + add_suffix || return 1
5082 5433
5083 -EOF
5084 - # generate the proxy agent list
5085 - ${SED} -e "s/.*ldap:\/\/\/.*ldap:\/\/\///" \
5086 - ${TMPDIR}/grep_proxyread_aci | ${SED} -e "s/\";)//" > \
5087 - ${TMPDIR}/proxy_agent_list
5434 + # Add missing suffix ACIs
5435 + add_suffix_aci || return 1
5088 5436
5089 - # print the proxy agent list
5090 - ${NAWK} '{print NR ": " $0}' ${TMPDIR}/proxy_agent_list
5437 + # Add base objects (if needed)
5438 + add_base_objects || return 1
5091 5439
5092 - # ask the user to pick one
5093 - _MENU_PROMPT="Select the proxy agent (1-$HOWMANY): "
5094 - get_menu_choice "${_MENU_PROMPT}" "0" "$HOWMANY"
5095 - _CH=$MN_CH
5096 - proxy_aci=`${SED} -n "$_CH p" ${TMPDIR}/grep_proxyread_aci`
5097 - fi
5440 + # Update the NisDomainObject.
5441 + # The Base DN might of just been created, so this MUST happen after
5442 + # the base objects have been added!
5443 + set_nisdomain || return 1
5098 5444
5099 - # Create the tmp file to delete the ACI.
5100 - ( cat <<EOF
5101 -dn: ${LDAP_BASEDN}
5102 -changetype: modify
5103 -delete: aci
5104 -aci: ${proxy_aci}
5105 -EOF
5106 - ) > ${TMPDIR}/proxy_delete
5445 + # Add top level classes (new containers)
5446 + add_new_containers || return 1
5107 5447
5108 - # Delete the ACI
5109 - ${EVAL} "${LDAPMODIFY} ${LDAP_ARGS} -f ${TMPDIR}/proxy_delete ${VERB}"
5110 - if [ $? -ne 0 ]; then
5111 - ${ECHO} " ERROR: Remove of ${PROXY_ACI_NAME} ACI failed!"
5112 - cat ${TMPDIR}/proxy_delete
5113 - cleanup
5114 - exit 1
5115 - fi
5448 + add_auto_maps || return 1
5116 5449
5117 - # Display message that ACI is updated.
5118 - MSG="Removed ${PROXY_ACI_NAME} ACI for proxyagent read permission for password."
5119 - ${ECHO} " "
5120 - ${ECHO} " ACI REMOVED: $MSG"
5121 - ${ECHO} " The ACI removed is $proxy_aci"
5122 - ${ECHO} " "
5123 -}
5450 + modify_top_aci || return 1
5124 5451
5125 -#
5126 -# add_profile(): Add client profile to server.
5127 -#
5128 -add_profile()
5129 -{
5130 - [ $DEBUG -eq 1 ] && ${ECHO} "In add_profile()"
5452 + add_vlv_aci || return 1
5131 5453
5132 - # If profile name already exists, DELETE it, and add new one.
5133 - eval "${LDAPSEARCH} ${LDAP_ARGS} -b \"cn=${LDAP_PROFILE_NAME},ou=profile,${LDAP_BASEDN}\" -s base \"objectclass=*\" ${VERB}"
5134 - if [ $? -eq 0 ]; then
5135 - # Create Delete file.
5136 - ( cat <<EOF
5137 -cn=${LDAP_PROFILE_NAME},ou=profile,${LDAP_BASEDN}
5138 -EOF
5139 -) > ${TMPDIR}/del_profile
5454 + if (( INT[NEED_PROXY] )); then
5455 + add_proxyagent || return 1
5456 + if (( ! INT[LDAP_ENABLE_SHADOW_UPDATE] )); then
5457 + allow_proxy_read_pw || return 1
5458 + fi
5459 + fi
5140 5460
5141 - # Check if DEL_OLD_PROFILE is set. (If not ERROR)
5142 - if [ $DEL_OLD_PROFILE -eq 0 ]; then
5143 - ${ECHO} "ERROR: Profile name ${LDAP_PROFILE_NAME} exists! Add failed!"
5144 - exit 1
5461 + if (( INT[NEED_ADMIN] )); then
5462 + add_admin || return 1
5463 + allow_admin_read_write_shadow || return 1
5464 + deny_non_admin_shadow_access || return 1
5145 5465 fi
5146 5466
5147 - # Delete the OLD profile.
5148 - ${EVAL} "${LDAPDELETE} ${LDAP_ARGS} -f ${TMPDIR}/del_profile ${VERB}"
5149 - if [ $? -ne 0 ]; then
5150 - ${ECHO} " ERROR: Attempt to DELETE profile failed!"
5151 - cleanup
5152 - exit 1
5467 + if (( INT[GSSAPI_ENABLE] )); then
5468 + add_id_mapping_rules
5469 + # do not modify ACI if "sasl/GSSAPI" and "self" are not selected
5470 + if [[ ${STR[LDAP_CRED_LEVEL]} == 'self' && \
5471 + ${STR[LDAP_AUTHMETHOD]} == 'sasl/GSSAPI' ]]
5472 + then
5473 + modify_userpassword_acl_for_gssapi || return 1
5474 + else
5475 + Log.warn 'ACL for GSSAPI was not set because of incompatibility' \
5476 + 'in profile'
5477 + fi
5153 5478 fi
5154 - fi
5155 5479
5156 - # Build the "ldapclient genprofile" command string to execute.
5157 - GEN_CMD="ldapclient genprofile -a \"profileName=${LDAP_PROFILE_NAME}\""
5480 + if (( INT[NEED_HOSTACL] )); then
5481 + allow_host_read_write_shadow || return 66
5482 + deny_non_host_shadow_access || return 67
5483 + fi
5158 5484
5159 - # Add required argument defaultSearchBase.
5160 - GEN_CMD="${GEN_CMD} -a \"defaultSearchBase=${LDAP_BASEDN}\""
5161 5485
5162 - # Add optional parameters.
5163 - [ -n "$LDAP_SERVER_LIST" ] && \
5164 - GEN_CMD="${GEN_CMD} -a \"defaultServerList=${LDAP_SERVER_LIST}\""
5165 - [ -n "$LDAP_SEARCH_SCOPE" ] && \
5166 - GEN_CMD="${GEN_CMD} -a \"defaultSearchScope=${LDAP_SEARCH_SCOPE}\""
5167 - [ -n "$LDAP_CRED_LEVEL" ] && \
5168 - GEN_CMD="${GEN_CMD} -a \"credentialLevel=${LDAP_CRED_LEVEL}\""
5169 - [ -n "$LDAP_AUTHMETHOD" ] && \
5170 - GEN_CMD="${GEN_CMD} -a \"authenticationMethod=${LDAP_AUTHMETHOD}\""
5171 - [ -n "$LDAP_FOLLOWREF" ] && \
5172 - GEN_CMD="${GEN_CMD} -a \"followReferrals=${LDAP_FOLLOWREF}\""
5173 - [ -n "$LDAP_SEARCH_TIME_LIMIT" ] && \
5174 - GEN_CMD="${GEN_CMD} -a \"searchTimeLimit=${LDAP_SEARCH_TIME_LIMIT}\""
5175 - [ -n "$LDAP_PROFILE_TTL" ] && \
5176 - GEN_CMD="${GEN_CMD} -a \"profileTTL=${LDAP_PROFILE_TTL}\""
5177 - [ -n "$LDAP_BIND_LIMIT" ] && \
5178 - GEN_CMD="${GEN_CMD} -a \"bindTimeLimit=${LDAP_BIND_LIMIT}\""
5179 - [ -n "$LDAP_PREF_SRVLIST" ] && \
5180 - GEN_CMD="${GEN_CMD} -a \"preferredServerList=${LDAP_PREF_SRVLIST}\""
5181 - [ -n "$LDAP_SRV_AUTHMETHOD_PAM" ] && \
5182 - GEN_CMD="${GEN_CMD} -a \"serviceAuthenticationMethod=${LDAP_SRV_AUTHMETHOD_PAM}\""
5183 - [ -n "$LDAP_SRV_AUTHMETHOD_KEY" ] && \
5184 - GEN_CMD="${GEN_CMD} -a \"serviceAuthenticationMethod=${LDAP_SRV_AUTHMETHOD_KEY}\""
5185 - [ -n "$LDAP_SRV_AUTHMETHOD_CMD" ] && \
5186 - GEN_CMD="${GEN_CMD} -a \"serviceAuthenticationMethod=${LDAP_SRV_AUTHMETHOD_CMD}\""
5486 + # Generate client profile and add it to the server
5487 + add_profile || return 1
5187 5488
5188 - # Check if there are any service search descriptors to ad.
5189 - if [ -s "${SSD_FILE}" ]; then
5190 - ssd_2_profile
5191 - fi
5489 + # Add Indexes to improve search performance
5490 + add_eq_indexes || return 1
5491 + add_sub_indexes || return 1
5492 + add_vlv_indexes || return 1
5192 5493
5193 - # Execute "ldapclient genprofile" to create profile.
5194 - eval ${GEN_CMD} > ${TMPDIR}/gen_profile 2> ${TMPDIR}/gen_profile_ERR
5195 - if [ $? -ne 0 ]; then
5196 - ${ECHO} " ERROR: ldapclient genprofile failed!"
5197 - cleanup
5198 - exit 1
5199 - fi
5494 + # Display setup complete message
5495 + Log.printMarker
5496 + Log.info 'Setup of DS server' "'${STR[DS_HOST]}'" 'is complete.'
5497 + Log.printMarker
5200 5498
5201 - # Add the generated profile..
5202 - ${EVAL} "${LDAPMODIFY} -a ${LDAP_ARGS} -f ${TMPDIR}/gen_profile ${VERB}"
5203 - if [ $? -ne 0 ]; then
5204 - ${ECHO} " ERROR: Attempt to add profile failed!"
5205 - cleanup
5206 - exit 1
5207 - fi
5499 + # Display VLV index commands to be executed on server (if any)
5500 + display_vlv_cmds
5208 5501
5209 - # Display message that schema is updated.
5210 - ${ECHO} " ${STEP}. Generated client profile and loaded on server."
5211 - STEP=`expr $STEP + 1`
5502 + # Create final config file if requested
5503 + [[ -n ${TMP[OUT]} ]] && create_config_file "${TMP[OUT]}"
5504 + return 0
5212 5505 }
5213 5506
5507 +Man.addFunc cleanup '' '[+NAME?cleanup - cleanup tempfiles, tty and exit.]
5508 +[+DESCRIPTION?Removes \aTMP[DIR]]\a unless \aTMPF[DEBUG]]\a is set and restores the echo for the tty.]
5509 +[+ENVIRONMENT VARIABLES]{' "${ Man.varUsage TMP TMPF ; }" '}
5510 +'
5511 +function cleanup {
5512 + (( TMPF[CLEANUP_DONE] )) && return
5513 + if (( TMPF[DEBUG] )); then
5514 + typeset X=${ ls -1 ${TMP[DIR]} 2>/dev/null ; }
5515 + if [[ -z $X || $X == 'rootPWD' ]]; then
5516 + rm -rf ${TMP[DIR]}
5517 + else
5518 + Log.info "Leaving temp dir ${TMP[DIR]} as is. Remove it manually"
5519 + fi
5520 + elif (( TMPF[KEEP] )); then
5521 + typeset X=${ ls -1 ${TMP[DIR]} 2>/dev/null ; }
5522 + if [[ -z $X || $X == 'rootPWD' ]]; then
5523 + rm -rf ${TMP[DIR]}
5524 + else
5525 + Log.info "Keeping setup scripts and files in ${TMP[DIR]}"
5526 + fi
5527 + elif [[ -d ${TMP[DIR]} ]]; then
5528 + rm -rf ${TMP[DIR]}
5529 + fi
5530 + ${STTY:-/usr/bin/stty} echo
5531 + trap - EXIT 1 2 3 6 15
5532 + # Might be trapped in the scope of a function which will stop executing
5533 + # the function itself but not the script. So:
5534 + [[ -z $1 ]] && kill $$
5535 + TMPF[CLEANUP_DONE]=1
5536 +}
5214 5537
5215 -#
5216 -# cleanup(): Remove the TMPDIR and all files in it.
5217 -#
5218 -cleanup()
5219 -{
5220 - [ $DEBUG -eq 1 ] && ${ECHO} "In cleanup()"
5221 -
5222 - rm -fr ${TMPDIR}
5538 +# debug helper function. Required to be not a 'function'!
5539 +showCommand() {
5540 + typeset CMD="${.sh.command}"
5541 + [[ -z ${CMD} ]] && return
5542 + print -n -u2 '\E[0;30;47m'
5543 + print -u2 -r -n "DEBUG: ${.sh.fun} '${CMD}'"
5544 + print '\E[0m'
5223 5545 }
5224 5546
5225 -
5226 -#
5227 -# * * * MAIN * * *
5228 -#
5229 -# Description:
5230 -# This script assumes that the iPlanet Directory Server (iDS) is
5231 -# installed and that setup has been run. This script takes the
5232 -# iDS server from that point and sets up the infrastructure for
5233 -# LDAP Naming Services. After running this script, ldapaddent(1M)
5234 -# or some other tools can be used to populate data.
5235 -
5236 -# Initialize the variables that need to be set to NULL, or some
5237 -# other initial value before the rest of the functions can be called.
5238 -init
5239 -
5240 -# Parse command line arguments.
5241 -parse_arg $*
5242 -shift $?
5243 -
5244 -# Print extra line to separate from prompt.
5245 -${ECHO} " "
5246 -
5247 -# Either Load the user specified config file
5248 -# or prompt user for config info.
5249 -if [ -n "$INPUT_FILE" ]
5250 -then
5251 - load_config_file
5252 - INTERACTIVE=0 # Turns off prompts that occur later.
5253 - validate_info # Validate basic info in file.
5254 - chk_ids_version # Check iDS version for compatibility.
5255 -else
5256 - # Display BACKUP warning to user.
5257 - display_msg backup_server
5258 - get_confirm "Do you wish to continue with server setup (y/n/h)?" "n" "backup_help"
5259 - if [ $? -eq 0 ]; then # if No, cleanup and exit.
5260 - cleanup ; exit 1
5261 - fi
5262 -
5263 - # Prompt for values.
5264 - prompt_config_info
5265 - display_summary # Allow user to modify results.
5266 - INTERACTIVE=1 # Insures future prompting.
5267 -fi
5268 -
5269 -# Modify slapd.oc.conf to ALLOW cn instead of REQUIRE.
5270 -modify_cn
5271 -
5272 -# Modify timelimit to user value.
5273 -[ $NEED_TIME -eq 1 ] && modify_timelimit
5274 -
5275 -# Modify sizelimit to user value.
5276 -[ $NEED_SIZE -eq 1 ] && modify_sizelimit
5277 -
5278 -# Modify the password storage scheme to support CRYPT.
5279 -if [ "$NEED_CRYPT" = "TRUE" ]; then
5280 - modify_pwd_crypt
5281 -fi
5282 -
5283 -# Update the schema (Attributes, Objectclass Definitions)
5284 -if [ ${SCHEMA_UPDATED} -eq 0 ]; then
5285 - update_schema_attr
5286 - update_schema_obj
5287 -fi
5288 -
5289 -# Add suffix together with its root entry (if needed)
5290 -add_suffix ||
5291 -{
5292 - cleanup
5293 - exit 1
5547 +Man.addFunc MAIN '' '[+NAME?'"${PROG}"' - setup the infrastructure of a directory server to provide data and security required by the Solaris (or similar OS) LDAP Naming Services.]
5548 +[+DESCRIPTION?This script assumes that the Sun/Oracle Directory Server Enterprise Edition (DSEE), or Sun OpenDS or Forgerock OpenDJ is installed and that its setup has been run. This script takes the directory server from that point and sets up the infrastructure for LDAP Naming Services. After running this script, \bldapaddent\b(1M) or some other tools can be used to populate data.]
5549 +[h:help?Print this help and exit.]
5550 +[F:functions?Print out a list of names of all currently defined script functions and exit (see \btypeset +f\b).]
5551 +[H:usage]:[function?Show the usage info for the function with the given name if available and exit. (see also option \b-F\b).]
5552 +[T:trace]:[fname_list?A comma or whitespace separated list of function names, which should be traced when running this script. If the list consist of the single word "ALL" or "*" all known functions get traced. "MAIN" is the special word to enable the trace of the main script. Gets activated as soon as this option gets processed, so option order might be important.]
5553 +[d:debug?Enable really verbose debug info.]
5554 +[C:no-color?Do not use ANSI escape codes to color the output.]
5555 +[k:keep?Keep the files used to modify the DS. Files are enumerated and prefixed with the command to use for executing it so that one is able to do the same manually what this script did and thus may help to fine tune the setup of your DS. Actually it is recommended to run this script against a virgin DS and than re-use/adjust everything you need on your production system.]
5556 +[I:importpwp?If specified, the storage scheme for Password Policy Import will be changed in the same way as the storage scheme for the Default Password Policy. If not specified, the storage scheme for Password Policy Import stays untouched. This option gets ignored for non-OpenDS/OpenDJ directory servers.]
5557 +[i:in]:[file?Get setup info from the given file.]
5558 +[o:out]:[file?Generate a server configuration output file.]
5559 +[s:djSyntax?If given, the OpenDJ schema defintions will be used to complement the servers schema if needed, no matter which kind of server has been detected.]
5560 +[S:eeSyntax?If given, the Sun DSEE schema defintions will be used to complement the servers schema if needed, no matter which kind of server has been detected.
5561 +Wrt. Solaris it should not make a difference, whether OpenDJ or DSEE syntax is used. OpenDJ syntax is usually a little bit more precise.]
5562 +[t:timeout]:[seconds:=60?When this script creates an index, it also schedules a task to rebuild the index immediately. The \atimeout\a specifies, how long to wait for task completion. If the task gets not finished within the given time, the script treats that as an error and continues its work.]
5563 +[v:verbose?Verbose mode - makes the script a little bit more chatty.]
5564 +[+NOTES?This script should work for the following DS:]{
5565 + [+?Sun DS 5.x]
5566 + [+?Sun DSEE 6.x/7.x]
5567 + [+?Oracle ODSEE 11g]
5568 + [+?Sun OpenDS 2.x]
5569 + [+?Forgerock OpenDJ 2.x]
5294 5570 }
5571 +'
5295 5572
5296 -# Add base objects (if needed)
5297 -add_base_objects
5573 +TMPF[DEBUG]=0 TMPF[KEEP]=0 TMPF[FD]=4
5298 5574
5299 -# Update the NisDomainObject.
5300 -# The Base DN might of just been created, so this MUST happen after
5301 -# the base objects have been added!
5302 -set_nisdomain
5575 +X="${ print ${Man.FUNC[MAIN]} ; }"
5576 +while getopts "${X}" option ; do
5577 + case "${option}" in
5578 + '?'|h) showUsage ${PROG} MAIN ; exit 0 ;;
5579 + F) typeset +f ; exit 0 ;;
5580 + T) if [[ ${OPTARG} == '*' || ${OPTARG} == 'ALL' ]]; then
5581 + typeset -ft ${ typeset +f ; }
5582 + elif [[ ${OPTARG} == 'MAIN' ]]; then
5583 + set -x
5584 + else
5585 + typeset -ft ${OPTARG//,/ }
5586 + fi
5587 + ;;
5588 + H) if [[ ${OPTARG%_t} != $OPTARG ]]; then
5589 + $OPTARG --man # self-defined types
5590 + else
5591 + showUsage "$OPTARG" "$OPTARG" # functions
5592 + fi
5593 + exit 0
5594 + ;;
5595 + C) Log.COLORED=0 ;;
5596 + d) TMPF[DEBUG]=1 ;;
5597 + k) TMPF[KEEP]=1 ;;
5598 + I) INT[NEED_CRYPT_IMPORT]=1 ;;
5599 + i) TMP[IN]="${OPTARG}" ;;
5600 + o) TMP[OUT]="${OPTARG}" ;;
5601 + S) TMPF[SYNTAX]=2 ; print DSEE ;;
5602 + s) TMPF[SYNTAX]=1 ; print DJ ;;
5603 + t) is_numeric "${OPTARG}" && INT[TASK_TIMEOUT]=${OPTARG} ;;
5604 + v) Log.VERBOSE=1 ; TMPF[FD]=1 ;;
5605 + *) Log.fatal '**Internal ERROR: Supported option missing handler'
5606 + exit 1
5607 + ;;
5608 + esac
5609 +done
5610 +X=$(( OPTIND - 1 ))
5611 +shift $X
5612 +(( TMPF[DEBUG] )) && Man.listVars
5303 5613
5304 -# Add top level classes (new containers)
5305 -add_new_containers
5614 +unset LC_ALL LC_LANG
5615 +export LC_CTYPE=C # avoid any surprises
5306 5616
5307 -# Add common nismaps.
5308 -add_auto_maps
5309 -
5310 -# Modify top ACI.
5311 -modify_top_aci
5312 -
5313 -# Add Access Control Information for VLV.
5314 -add_vlv_aci
5315 -
5316 -# if Proxy needed, Add Proxy Agent and give read permission for password.
5317 -if [ $NEED_PROXY -eq 1 ]; then
5318 - add_proxyagent
5319 - if [ "$LDAP_ENABLE_SHADOW_UPDATE" != "TRUE" ]; then
5320 - allow_proxy_read_pw
5321 - fi
5617 +# Create TMP[DIR]
5618 +TMP[DIR]=${ mktemp -d /tmp/${PROG}.XXXXX ; }
5619 +if [[ -z ${TMP[DIR]} ]]; then
5620 + Log.fatal 'Unable to create a safe temporary directory'
5621 + exit 1
5322 5622 fi
5323 -
5324 -# If admin needed for shadow update, Add the administrator identity and
5325 -# give read/write permission for shadow, and deny all others read/write
5326 -# access to it.
5327 -if [ $NEED_ADMIN -eq 1 ]; then
5328 - add_admin
5329 - allow_admin_read_write_shadow
5330 - # deny non-admin access to shadow data
5331 - deny_non_admin_shadow_access
5623 +trap cleanup EXIT 1 2 3 6 15 # and register to cleanup on exit/signal
5624 +if (( TMPF[DEBUG] )); then
5625 + trap 'typeset _CMD_="${.sh.command}"
5626 + print -u2 -n "\E[0;30;47m"
5627 + print -u2 -n -r "${.sh.fun:-MAIN}(): ${_CMD_}"
5628 + print -u2 "\E[0m"
5629 + ' TMPF[DEBUG]
5332 5630 fi
5333 5631
5334 -if [ $GSSAPI_ENABLE -eq 1 ]; then
5335 - add_id_mapping_rules
5336 - # do not modify ACI if "sasl/GSSAPI" and "self" are not selected
5337 - if [ "$LDAP_CRED_LEVEL" = "self" -a "$LDAP_AUTHMETHOD" = "sasl/GSSAPI" ]; then
5338 - modify_userpassword_acl_for_gssapi
5339 - else
5340 - ${ECHO} " ACL for GSSAPI was not set because of incompatibility in profile."
5341 - fi
5342 -fi
5632 +# Prevent new files from being read by group or others
5633 +umask 077
5343 5634
5344 -# If use host principal for shadow update, give read/write permission for
5345 -# shadow, and deny all others' read/write access to it.
5346 -if [ $NEED_HOSTACL -eq 1 ]; then
5347 - allow_host_read_write_shadow
5348 - # deny non-host access to shadow data
5349 - deny_non_host_shadow_access
5350 -fi
5635 +doMain
5636 +X=$?
5351 5637
5638 +cleanup NOKILL
5352 5639
5353 -# Generate client profile and add it to the server.
5354 -add_profile
5640 +exit ${X}
5355 5641
5356 -# Add Indexes to improve Search Performance.
5357 -add_eq_indexes
5358 -add_sub_indexes
5359 -add_vlv_indexes
5360 -
5361 -# Display setup complete message
5362 -display_msg setup_complete
5363 -
5364 -# Display VLV index commands to be executed on server.
5365 -display_vlv_cmds
5366 -
5367 -# Create config file if requested.
5368 -[ -n "$OUTPUT_FILE" ] && create_config_file
5369 -
5370 -# Removed the TMPDIR and all files in it.
5371 -cleanup
5372 -
5373 -exit 0
5374 -# end of MAIN.
5642 +# vim:ts=4 filetype=sh
5643 +# :syntax sync fromstart
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX