1if [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_INPUT_SUBR=1 2# 3# Copyright (c) 2012 Ron McDowell 4# Copyright (c) 2012-2014 Devin Teske 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28# $FreeBSD$ 29# 30############################################################ INCLUDES 31 32BSDCFG_SHARE="/usr/share/bsdconfig" 33. $BSDCFG_SHARE/common.subr || exit 1 34f_dprintf "%s: loading includes..." usermgmt/group_input.subr 35f_include $BSDCFG_SHARE/dialog.subr 36f_include $BSDCFG_SHARE/strings.subr 37 38BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt" 39f_include_lang $BSDCFG_LIBE/include/messages.subr 40f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr 41 42############################################################ FUNCTIONS 43 44# f_input_group $group 45# 46# Given $group name or id, create the environment variables group_name, 47# group_gid, and group_members (and group_password is reset to NULL). 48# 49f_input_group() 50{ 51 local funcname=f_input_group 52 local group="$1" 53 54 f_dprintf "$funcname: Getting info for group \`%s'" "$group" 55 eval "$( pw groupshow "$group" 2> /dev/null | awk -F: ' 56 function set_value(var, value) { 57 gsub(/'\''/, "'\''\\'\'\''", value) 58 printf "group_%s='\'%s\''\n", var, value 59 } 60 { 61 found = $1 != "" 62 set_value("name", $1) 63 set_value("password", "") 64 set_value("gid", $3) 65 set_value("members", $4) 66 exit 67 } 68 END { if (!found) print "false" }' )" 69} 70 71# f_dialog_menu_group_list [$default] 72# 73# Allows the user to select a group from a list. Optionally, if present and 74# non-NULL, initially highlight $default group. 75# 76f_dialog_menu_group_list() 77{ 78 local prompt= 79 local menu_list=" 80 'X $msg_exit' '' 81 " # END-QUOTE 82 local defaultitem="$1" 83 local hline="$hline_alnum_punc_tab_enter" 84 85 # Add groups from group(5) 86 menu_list="$menu_list $( pw groupshow -a | awk -F: ' 87 function mprint(tag, item) { 88 gsub(/'\''/, "'\''\\'\'\''", tag) 89 gsub(/'\''/, "'\''\\'\'\''", item) 90 printf "'\'%s\'\ \'%s\''\n", tag, item 91 } 92 !/^[[:space:]]*(#|$)/ { mprint($1, $1) } 93 ' )" 94 95 local height width rows 96 eval f_dialog_menu_size height width rows \ 97 \"\$DIALOG_TITLE\" \ 98 \"\$DIALOG_BACKTITLE\" \ 99 \"\$prompt\" \ 100 \"\$hline\" \ 101 $menu_list 102 103 local menu_choice 104 menu_choice=$( eval $DIALOG \ 105 --title \"\$DIALOG_TITLE\" \ 106 --backtitle \"\$DIALOG_BACKTITLE\" \ 107 --hline \"\$hline\" \ 108 --ok-label \"\$msg_ok\" \ 109 --cancel-label \"\$msg_cancel\" \ 110 --default-item \"\$defaultitem\" \ 111 --menu \"\$prompt\" \ 112 $height $width $rows \ 113 $menu_list \ 114 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 115 ) 116 local retval=$? 117 f_dialog_menutag_store -s "$menu_choice" 118 return $retval 119} 120 121# f_dialog_input_group_name $var_to_set [$group_name] 122# 123# Allows the user to enter a name for a new group. If the user does not cancel 124# or press ESC, the $var_to_set variable will hold the newly-configured value 125# upon return. 126# 127f_dialog_input_group_name() 128{ 129 local __var_to_set="$1" __name="$2" 130 131 # 132 # Loop until the user provides taint-free/valid input 133 # 134 local __input="$__name" 135 while :; do 136 # Return if user has either pressed ESC or chosen Cancel/No 137 f_dialog_input __input "$msg_group" "$__input" \ 138 "$hline_alnum_tab_enter" || return $? 139 140 # Check for no-change 141 if [ "$__input" = "$__name" ]; then 142 setvar "$__var_to_set" "$__input" 143 return $DIALOG_OK 144 fi 145 146 # Check for NULL entry 147 if [ ! "$__input" ]; then 148 f_show_msg "$msg_group_is_empty" 149 continue 150 fi 151 152 # Check for invalid entry 153 case "$__input" in [!a-zA-Z]*) 154 f_show_msg "$msg_group_must_start_with_letter" 155 continue 156 esac 157 158 # Check for duplicate entry 159 if f_quietly pw groupshow -n "$__input"; then 160 f_show_msg "$msg_group_already_used" "$__input" 161 continue 162 fi 163 164 setvar "$__var_to_set" "$__input" 165 break 166 done 167 168 return $DIALOG_OK 169} 170 171# f_dialog_input_group_password $var_to_set $dvar_to_set 172# 173# Prompt the user to enter a password (twice). If the user does not cancel or 174# press ESC, $var_to_set will hold the confirmed user entry. Otherwise, if the 175# user cancels or enters a NULL password (twice), they are given the choice to 176# disable password authentication for the given group, wherein $dvar_to_set has 177# a value of 1 to indicate password authentication should be disabled. 178# 179f_dialog_input_group_password() 180{ 181 local __var_to_set="$1" __dvar_to_set="$2" 182 local __prompt1="$msg_group_password" 183 local __prompt2="$msg_reenter_group_password" 184 local __hline="$hline_alnum_punc_tab_enter" 185 186 local __height1 __width1 187 f_dialog_inputbox_size __height1 __width1 \ 188 "$DIALOG_TITLE" \ 189 "$DIALOG_BACKTITLE" \ 190 "$__prompt1" \ 191 "" \ 192 "$__hline" 193 194 local __height2 __width2 195 f_dialog_inputbox_size __height2 __width2 \ 196 "$DIALOG_TITLE" \ 197 "$DIALOG_BACKTITLE" \ 198 "$__prompt2" \ 199 "" \ 200 "$__hline" 201 202 # 203 # Loop until the user provides taint-free/valid input 204 # 205 local __retval __password1 __password2 206 while :; do 207 __password1=$( $DIALOG \ 208 --title "$DIALOG_TITLE" \ 209 --backtitle "$DIALOG_BACKTITLE" \ 210 --hline "$__hline" \ 211 --ok-label "$msg_ok" \ 212 --cancel-label "$msg_cancel" \ 213 --insecure \ 214 --passwordbox "$__prompt1" \ 215 $__height1 $__width1 \ 216 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 217 ) 218 __retval=$? 219 debug= f_dialog_line_sanitize __password1 220 221 # Return if user has either pressed ESC or chosen Cancel/No 222 [ $__retval -eq $DIALOG_OK ] || return $__retval 223 224 __password2=$( $DIALOG \ 225 --title "$DIALOG_TITLE" \ 226 --backtitle "$DIALOG_BACKTITLE" \ 227 --hline "$__hline" \ 228 --ok-label "$msg_ok" \ 229 --cancel-label "$msg_cancel" \ 230 --insecure \ 231 --passwordbox "$__prompt2" \ 232 $__height2 $__width2 \ 233 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 234 ) 235 __retval=$? 236 debug= f_dialog_line_sanitize __password2 237 238 # Return if user has either pressed ESC or chosen Cancel/No 239 [ $__retval -eq $DIALOG_OK ] || return $__retval 240 241 # Check for password mismatch 242 if [ "$__password1" != "$__password2" ]; then 243 f_show_msg "$msg_group_passwords_do_not_match" 244 continue 245 fi 246 247 # Check for NULL entry 248 if [ ! "$__password1" ]; then 249 f_dialog_yesno "$msg_disable_password_auth_for_group" 250 __retval=$? 251 if [ $__retval -eq $DIALOG_ESC ]; then 252 return $__retval 253 elif [ $__retval -eq $DIALOG_OK ]; then 254 setvar "$__dvar_to_set" 1 255 else 256 continue # back to password prompt 257 fi 258 else 259 setvar "$__dvar_to_set" "" 260 fi 261 262 setvar "$__var_to_set" "$__password1" 263 break 264 done 265 266 return $DIALOG_OK 267} 268 269# f_dialog_input_group_gid $var_to_set [$group_gid] 270# 271# Allow the user to enter a new GID for a given group. If the user does not 272# cancel or press ESC, the $var_to_set variable will hold the newly-configured 273# value upon return. 274# 275f_dialog_input_group_gid() 276{ 277 local __var_to_set="$1" __input="$2" 278 279 # Return if user has either pressed ESC or chosen Cancel/No 280 f_dialog_input __input "$msg_group_id_leave_empty_for_default" \ 281 "$__input" "$hline_num_tab_enter" || return $? 282 283 setvar "$__var_to_set" "$__input" 284 return $DIALOG_OK 285} 286 287# f_dialog_input_group_members $var_to_set [$group_members] 288# 289# Allow the user to modify a list of members for a given group. If the user 290# does not cancel or press ESC, the $var_to_set variable will hold the newly- 291# configured value upon return. 292# 293f_dialog_input_group_members() 294{ 295 local __var_to_set="$1" __input="$2" 296 local __prompt="$msg_group_members:" 297 local __menu_list=" 298 'X' '$msg_continue' 299 '1' '$msg_select_group_members_from_list' 300 '2' '$msg_enter_group_members_manually' 301 " # END-QUOTE 302 local __defaultitem= 303 local __hline="$hline_num_arrows_tab_enter" 304 305 local __mheight __mwidth __mrows 306 eval f_dialog_menu_size __mheight __mwidth __mrows \ 307 \"\$DIALOG_TITLE\" \ 308 \"\$DIALOG_BACKTITLE\" \ 309 \"\$__prompt\" \ 310 \"\$__hline\" \ 311 $__menu_list 312 313 local __menu_choice __retval 314 while :; do 315 __menu_choice=$( eval $DIALOG \ 316 --title \"\$DIALOG_TITLE\" \ 317 --backtitle \"\$DIALOG_BACKTITLE\" \ 318 --hline \"\$__hline\" \ 319 --ok-label \"\$msg_ok\" \ 320 --cancel-label \"\$msg_cancel\" \ 321 --default-item \"\$__defaultitem\" \ 322 --menu \"\$__prompt\" \ 323 $__mheight $__mwidth $__mrows \ 324 $__menu_list \ 325 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 326 ) 327 __retval=$? 328 f_dialog_data_sanitize __menu_choice 329 __defaultitem="$__menu_choice" 330 f_dprintf "retval=%u menu_choice=[%s]" \ 331 $__retval "$__menu_choice" 332 333 # Return if user has either pressed ESC or chosen Cancel/No 334 [ $__retval -eq $DIALOG_OK ] || return $__retval 335 336 local __group_members 337 case "$__menu_choice" in 338 X) # Exit 339 break ;; 340 1) # Select Group Members from a list 341 local __check_list= # Calculated below 342 local __user_list __u __user __length=0 343 __user_list=$( pw usershow -a | 344 awk -F: '!/^[[:space:]]*(#|$)/{print $1}' ) 345 while [ $__length -ne ${#__user_list} ]; do 346 __u="${__user_list%%$NL*}" # First line 347 f_shell_escape "$__u" __user 348 349 # Format of a checklist entry: tag item status 350 __check_list="$__check_list '$__user' ''" 351 case "$__input" in 352 "$__u"|"$__u",*|*,"$__u",*|*,"$__u") 353 __check_list="$__check_list on" ;; 354 *) 355 __check_list="$__check_list off" 356 esac 357 358 __length=${#__user_list} 359 __user_list="${__user_list#*$NL}" # Kill line 360 done 361 362 local __cheight __cwidth __crows 363 eval f_dialog_checklist_size \ 364 __cheight __cwidth __crows \ 365 \"\$DIALOG_TITLE\" \ 366 \"\$DIALOG_BACKTITLE\" \ 367 \"\$__prompt\" \ 368 \"\$__hline\" \ 369 $__check_list 370 __group_members=$( eval $DIALOG \ 371 --title \"\$DIALOG_TITLE\" \ 372 --backtitle \"\$DIALOG_BACKTITLE\" \ 373 --separate-output \ 374 --hline \"\$__hline\" \ 375 --ok-label \"\$msg_ok\" \ 376 --cancel-label \"\$msg_cancel\" \ 377 --checklist \"\$__prompt\" \ 378 $__cheight $__cwidth $__crows \ 379 $__check_list \ 380 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 381 ) || continue 382 # Return to previous menu if user either 383 # pressed ESC or chose Cancel/No 384 f_dialog_data_sanitize __group_members 385 386 # 387 # Convert the newline separated list into a comma- 388 # separated one so that if the user switches over to 389 # manual editing, list reflects checklist selections 390 # 391 f_replaceall "$__group_members" "[$NL]" "," __input 392 ;; 393 2) # Enter Group Members manually 394 local __prompt2="$msg_group_members" 395 __prompt2="$__prompt2 ($msg_separated_by_commas)" 396 397 f_dialog_input __group_members \ 398 "$__prompt2" "$__input" \ 399 "$hline_num_tab_enter" || continue 400 # Return to previous menu if user either 401 # pressed ESC or chose Cancel/No 402 403 __input="$__group_members" 404 ;; 405 esac 406 done 407 408 setvar "$__var_to_set" "$__input" 409 return $DIALOG_OK 410} 411 412# f_dialog_menu_group_add [$defaultitem] 413# 414# Present a menu detailing the properties of a group that is about to be added. 415# The user's menu choice is available using f_dialog_menutag_fetch(). Returns 416# success unless the user chose Cancel or pressed ESC. Data to display is taken 417# from environment variables group_name, group_gid, and group_members. If 418# $defaultitem is present and non-NULL, initially highlight the item in the 419# menu. 420# 421f_dialog_menu_group_add() 422{ 423 local prompt="$msg_save_exit_or_cancel" 424 local menu_list # Calculated below 425 local defaultitem="$1" 426 local hline="$hline_arrows_tab_enter" 427 428 # Localize potentially hostile variables and escape their values 429 # to the local variable (see f_shell_escape() of `strings.subr') 430 local var 431 for var in gid members name; do 432 local _group_$var 433 eval f_shell_escape \"\$group_$var\" _group_$var 434 done 435 436 menu_list=" 437 'X' '$msg_add/$msg_exit' 438 '1' '$msg_group: $_group_name' 439 '2' '$msg_password: -----' 440 '3' '$msg_group_id: $_group_gid' 441 '4' '$msg_group_members: $_group_members' 442 " # END-QUOTE 443 444 local height width rows 445 eval f_dialog_menu_size height width rows \ 446 \"\$DIALOG_TITLE\" \ 447 \"\$DIALOG_BACKTITLE\" \ 448 \"\$prompt\" \ 449 \"\$hline\" \ 450 $menu_list 451 452 local menu_choice 453 menu_choice=$( eval $DIALOG \ 454 --title \"\$DIALOG_TITLE\" \ 455 --backtitle \"\$DIALOG_BACKTITLE\" \ 456 --hline \"\$hline\" \ 457 --ok-label \"\$msg_ok\" \ 458 --cancel-label \"\$msg_cancel\" \ 459 --default-item \"\$defaultitem\" \ 460 --menu \"\$prompt\" \ 461 $height $width $rows \ 462 $menu_list \ 463 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 464 ) 465 local retval=$? 466 f_dialog_data_sanitize menu_choice 467 f_dialog_menutag_store "$menu_choice" 468 return $retval 469} 470 471# f_dialog_menu_group_delete $group [$defaultitem] 472# 473# Present a menu detailing the properties of a group that is about to be 474# deleted. The user's menu choice is available using f_dialog_menutag_fetch(). 475# Returns success unless the user chose Cancel or pressed ESC. Data to display 476# is populated automatically from the system accounting database for the given 477# $group argument. If $defaultitem is present and non-NULL, initially highlight 478# the item in the menu. 479# 480f_dialog_menu_group_delete() 481{ 482 local prompt="$msg_delete_exit_or_cancel" 483 local menu_list # Calculated below 484 local defaultitem="$2" 485 local hline="$hline_arrows_tab_enter" 486 487 local group_name group_password group_gid group_members 488 f_input_group "$1" 489 490 # Localize potentially hostile variables and escape their values 491 # to the local variable (see f_shell_escape() of `strings.subr') 492 local var 493 for var in gid members name; do 494 local _group_$var 495 eval f_shell_escape \"\$group_$var\" _group_$var 496 done 497 498 menu_list=" 499 'X' '$msg_delete/$msg_exit' 500 '1' '$msg_group: $_group_name' 501 '-' '$msg_password: -----' 502 '-' '$msg_group_id: $_group_gid' 503 '-' '$msg_group_members: $_group_members' 504 " # END-QUOTE 505 506 local height width rows 507 eval f_dialog_menu_size height width rows \ 508 \"\$DIALOG_TITLE\" \ 509 \"\$DIALOG_BACKTITLE\" \ 510 \"\$prompt\" \ 511 \"\$hline\" \ 512 $menu_list 513 514 local menu_choice 515 menu_choice=$( eval $DIALOG \ 516 --title \"\$DIALOG_TITLE\" \ 517 --backtitle \"\$DIALOG_BACKTITLE\" \ 518 --hline \"\$hline\" \ 519 --ok-label \"\$msg_ok\" \ 520 --cancel-label \"\$msg_cancel\" \ 521 --default-item \"\$defaultitem\" \ 522 --menu \"\$prompt\" \ 523 $height $width $rows \ 524 $menu_list \ 525 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 526 ) 527 local retval=$? 528 f_dialog_data_sanitize menu_choice 529 f_dialog_menutag_store "$menu_choice" 530 return $retval 531} 532 533# f_dialog_menu_group_edit [$defaultitem] 534# 535# Present a menu detailing the properties of a group that is about to be 536# modified. The user's menu choice is available using f_dialog_menutag_fetch(). 537# Returns success unless the user chose Cancel or pressed ESC. Data to display 538# is taken from environment variables group_name, group_gid, and group_members. 539# If $defaultitem is present and non-NULL, initially highlight the item in the 540# menu. 541# 542f_dialog_menu_group_edit() 543{ 544 local prompt="$msg_save_exit_or_cancel" 545 local menu_list # Calculated below 546 local defaultitem="$1" 547 local hline="$hline_arrows_tab_enter" 548 549 # Localize potentially hostile variables and escape their values 550 # to the local variable (see f_shell_escape() of `strings.subr') 551 local var 552 for var in gid members name; do 553 local _group_$var 554 eval f_shell_escape \"\$group_$var\" _group_$var 555 done 556 557 menu_list=" 558 'X' '$msg_save/$msg_exit' 559 '1' '$msg_group: $_group_name' 560 '2' '$msg_password: -----' 561 '3' '$msg_group_id: $_group_gid' 562 '4' '$msg_group_members: $_group_members' 563 " # END-QUOTE 564 565 local height width rows 566 eval f_dialog_menu_size height width rows \ 567 \"\$DIALOG_TITLE\" \ 568 \"\$DIALOG_BACKTITLE\" \ 569 \"\$prompt\" \ 570 \"\$hline\" \ 571 $menu_list 572 573 local menu_choice 574 menu_choice=$( eval $DIALOG \ 575 --title \"\$DIALOG_TITLE\" \ 576 --backtitle \"\$DIALOG_BACKTITLE\" \ 577 --hline \"\$hline\" \ 578 --ok-label \"\$msg_ok\" \ 579 --cancel-label \"\$msg_cancel\" \ 580 --default-item \"\$defaultitem\" \ 581 --menu \"\$prompt\" \ 582 $height $width $rows \ 583 $menu_list \ 584 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD 585 ) 586 local retval=$? 587 f_dialog_data_sanitize menu_choice 588 f_dialog_menutag_store "$menu_choice" 589 return $retval 590} 591 592############################################################ MAIN 593 594f_dprintf "%s: Successfully loaded." usermgmt/group_input.subr 595 596fi # ! $_USERMGMT_GROUP_INPUT_SUBR 597