#!/bin/bash # Coypright (c) 2004-2005 by Fabian Franz . # 2005 by Jon Severinsson . # 2023 by Dmitry Borisov # # License: GNU GPL, version 2 HELP="no"; INSTALL="no"; SETUP_NOMACHINE_KEY="no" SETUP_UID=""; SETUP_GID=""; LOCAL_USER_OPTION="" # luseradd / luserdel are only available on RedHat [ -f /etc/redhat-release ] && LOCAL_USER_OPTION="yes" # altlinux have /etc/redhat-release file but don't have luseradd / luserdel commands [ -f /etc/altlinux-release ] && LOCAL_USER_OPTION="no" SETUP_LOCAL_USER="no"; CLEAN="no"; UNINSTALL="no" PURGE="no"; BUILD_KNOWN_HOSTS="yes"; AUTOMATIC="no" IGNORE_ERRORS="no"; MKDB="no" if [ $UID -ne 0 ]; then echo "You need to be root to use this program." exit 1 fi parse_cmdline() { while [ "$1" ]; do case "$1" in --help) HELP="yes"; shift ;; --install) INSTALL="yes"; shift ;; --mkdb|mkdb|--reload) MKDB="yes"; shift ;; --ignore-errors) IGNORE_ERRORS="yes"; shift;; --setup-nomachine-key) SETUP_NOMACHINE_KEY="yes"; shift ;; --dont-build-known-hosts) BUILD_KNOWN_HOSTS="no"; shift;; --uid) SETUP_UID=$2; shift 2 ;; --gid) SETUP_GID=$2; shift 2 ;; --localuser) SETUP_LOCAL_USER="yes"; shift;; --clean) CLEAN="yes"; shift ;; --uninstall) UNINSTALL="yes"; shift ;; --purge) PURGE="yes"; shift ;; --auto) AUTOMATIC="yes"; shift ;; --test) TEST="yes"; shift ;; --) shift ; break ;; *) echo "Invalid flag $1" ; HELP="yes"; shift ; break ;; esac done [ "$TEST" = "yes" ] && return # If we just test, we can return directly #Check for invalid combinations: [ "$SETUP_LOCAL_USER" = "yes" -a -z "$LOCAL_USER_OPTION" ] && HELP="yes" [ "$INSTALL" = "yes" -a "$UNINSTALL" = "yes" ] && HELP="yes" [ "$INSTALL" = "yes" -a "$CLEAN" = "no" -a "$PURGE" = "yes" ] && HELP="yes" [ "$UNINSTALL" = "yes" ] && [ "$SETUP_NOMACHINE_KEY" = "yes" -o \ -n "$SETUP_UID" -o "$CLEAN" = "yes" ] && HELP="yes" [ "$UNINSTALL" = "yes" -a "$CLEAN" = "yes" ] && HELP="yes" if [ "$INSTALL" = "no" -a "$UNINSTALL" = "no" -a \ "$AUTOMATIC" = "no" -a "$HELP" = "no" -a "$MKDB" = "no" ]; then HELP="yes" fi [ "$INSTALL" = "yes" -o "$AUTOMATIC" = "yes" ] && MKDB="yes" if [ "$HELP" = "yes" ]; then echo "nxsetup - Setup the FreeNX server." echo "Syntax: nxsetup --help" echo " nxsetup --reload" echo " nxsetup --mkdb" echo " nxsetup --test [--ignore-errors]" echo " nxsetup --install [--setup-nomachine-key] [--uid ] [--clean [--purge]]" echo " nxsetup --uninstall [--purge]" echo echo " --help Display this help message." echo " --reload Reload nxsettings db." echo " --mkdb Reload nxsettings db." echo " --test Test the configuration and connection to localhost NX Server." echo " --install Install necessary files and add the special user \"nx\"." echo " --ignore-errors Check for false configuration, but don't complain." echo " --setup-nomachine-key Allow login with the key shipped with the NoMachine" echo " client. This is fairly secure, and it simplifies the " echo " configuration of clients. (Using a custom key pair." echo " increases security even more, but complicates the" echo " configuration of clients.)" echo " Use this option at your own risk." echo " --uid Give the uid to the user \"nx\"." echo " --gid Give the gid to the user \"nx\"." [ -n "$LOCAL_USER_OPTION" ] && \ echo " --localuser The special user \"nx\" will be created locally using" echo " \"luseradd\", for use in NIS and NISplus environments." echo " --clean Perform an uninstallation prior to installation." echo " --uninstall Remove log and session files, as well as the special" echo " user \"nx\"." echo " --purge Remove extra configuration files and ssh keys when" echo " performing a \"--uninstall\"." echo " Note that node.conf will always be saved." echo " --auto Perform automatic installation without testing or asking." exit 0 fi #Undocumented # # --dont-build-known-hosts For system without /etc/ssh/ssh_host_key.rsa.pub and anyway # expect should handle nx-users known-hosts keys so why borther # in nxsetup? if [ "$INSTALL" = "yes" -a "$AUTOMATIC" = "no" -a \ "$SETUP_NOMACHINE_KEY" = "no" ]; then echo "------> It is recommended that you use the NoMachine key for" echo " easier setup. If you answer \"y\", FreeNX creates a custom" echo " KeyPair and expects you to setup your clients manually. " echo " \"N\" is default and uses the NoMachine key for installation." echo "" echo -n " Do you want to use your own custom KeyPair? [y/N] " read -n 1 CHOICE [ "$CHOICE" = "y" ] || SETUP_NOMACHINE_KEY="yes" fi } parse_cmdline "$@" #======================= nxsettings db manipulatios ========================= SHARED_CONFS="/usr/share/freenx-server" . $SHARED_CONFS/nxfuncs ex_rules_cols="val_type,val_depend,val_check"; acl_user="#ACL#" all_cols="user,key,value,$ex_rules_cols" conf_buf=""; txt_err=""; txt_warn=""; txt_info=""; qs_create_settings="CREATE TABLE IF NOT EXISTS nxsettings.settings(\ user TEXT, key TEXT NOT NULL, value, val_type TEXT, \ val_depend TEXT, val_check TEXT, PRIMARY KEY(user,key));" keyslst_for_user() { #arg: [username] [table='settings'] #ret: keynames delimited by '\n' local qstr res wstr table; [ -n "$1" ] && wstr="WHERE user='$1'" || wstr="WHERE user IS NULL" table="settings"; [ -n "$2" ] && table="$2" qstr="SELECT key FROM $table $wstr;" res=$(qa_dbe0 "$qstr"); echo "$res" } values_str_from_db() { #args: key [username] [table='settings'] local ucond table qstr r a res; ucond=" IS NULL"; [ -n "$3" -a "$3" != "NULL" ] && ucond="='$3'" table="settings"; [ -n "$4" ] && table="$4" qstr="SELECT $2 FROM $table WHERE user$ucond AND key='$1' LIMIT 1;" r=$(qa_dbe0 "$qstr"); OIFS="$IFS"; IFS='&'; local a=($r) res="${a[*]}"; IFS="$OIFS" echo "${res//\"/}" } values_update_db() { #args: key [username] [table='settings'] local ucond table qstr upd_s ins_s ik0="" iv0="" ik iv; ucond=" IS NULL"; [ -n "$4" -a "$4" != "NULL" ] && ucond="='$4'" table="settings"; [ -n "$5" ] && table="$5" qstr=$(colval_set_or_cond "$2" "$3"); [ -n "$qstr" ] || return upd_s="UPDATE $table SET $qstr WHERE user$ucond AND key='$1';" [ -n "$4" ] && { ik0="user,"; iv0="'$4',"; } qstr=$(colval_set_or_cond "$2" "$3" "INS"); ik=${qstr%&*}; iv=${qstr#*&} ins_s="INSERT INTO $table($ik0""key,$ik) SELECT $iv0""'$1',$iv WHERE (SELECT Changes()=0);" #echo "$upd_s" "$ins_s" q_dbe0 "$upd_s" "$ins_s" } # =========================================================================== parse_conf_buf() { #args: user [is_defs] [table='settings'] local ex_vals="type depend check" l0 l ukv="" ik="" iv=""; local key val a0 a first cn cv upd_s ins_s v; local table="settings"; [ -n "$3" ] && table="$3" while read l0; do [ -n "$l0" ] || continue l=($l0); first=${l[0]:0:1} if [ "$first" = "#" ]; then [ -z "$2" ] && continue # parse comment for extras l[0]=${l[0]:1} [ "${l[0]}" = "@" ] && { # set extra column unset l[0]; a0="${l[@]}"; OIFS="$IFS"; IFS=':'; a=($a0); IFS="$OIFS" cn=$(trim "${a[0]}"); stringinstring "$cn" "$ex_vals" || continue #cv=$(trim "${a[@]:1}"); # this kills all colons :( cv=$(trim "${l0#*:}"); cv=$(s2sq "$cv") ukv="$ukv,val_$cn='$cv'"; ik="$ik,val_$cn"; iv="$iv,'$cv'" #echo "!$cn !$cv" } continue fi [[ "${l[0]:0:1}" =~ [[:upper:]] ]] || continue # there can be more than one char '=' per line key=$(trim "${l%%=*}"); [ "$l" = "$key" ] && continue val=$(trim "${l[@]#*=}"); val=$(s2sq "$val") # fake upsert to db uk0="user IS NULL AND "; ik0=""; iv0=""; [ -n "$1" ] && { uk0="user='$1' AND "; ik0="user,"; iv0="'$1',"; } upd_s="UPDATE $table SET value='$val'""$ukv WHERE $uk0""key='$key';" ins_s="INSERT INTO $table($ik0""key,value""$ik) SELECT $iv0""'$key','$val'$iv WHERE (SELECT Changes()=0);" q_dbe0 "$upd_s" "$ins_s" ukv=""; ik=""; iv="" done <<< "$conf_buf" } check_value() { #args: [err_log] [ro=""] [table='settings'] local err_log="" msg="" key=$1 val="$2" cond="$4" nval="$2" umsg=""; local mpref="! $umsg""$key = '$val' " notempty="" act=""; local nump='^'"$num_pattern"'$' cl min max a OIFS; local cnd cval lst nexe ug local mode mask; local ma set_ug set_mode res st table; [ -n "$6" ] && err_log=$6; [ -n "$5" -a "$5" != "NULL" ] && umsg="[$5] " table="settings"; [ -n "$8" ] && table="$8" stringinstring "notempty" "$cond" && \ { notempty="1"; cond=$(trim "${cond/notempty/}"); } stringinstring "perform" "$cond" && \ { act="1"; cond=$(trim "${cond/perform/}"); } case "$3" in bool) [ "$val" = "0" -o "$val" = "1" ] || { msg="$mpref must be 0/1, forced to;"$'\n' [ -n "$val" ] && nval="1" || nval="0" } ;; int) [[ $val =~ $nump ]] || { msg="$mpref must be the number, forced to 0;"$'\n'; nval="0"; } [ -n "$cond" ] && { cl=($cond); min="${cl[0]}"; max="${cl[1]}"; [ -n "$min" ] && { if ! [[ $min =~ $nump ]]; then min="${!min}"; [[ $min =~ $nump ]] || min="" fi } [ -n "$max" ] && { if ! [[ $max =~ $nump ]]; then max="${!max}"; [[ $max =~ $nump ]] || max="" fi } [ -n "$min" ] && ((valmax)) && \ msg="$mpref is greater than MAX value $max;"$'\n' } ;; string) if [ -n "$notempty" ]; then [ -z "$val" ] && \ msg="$mpref. Is empty! Set it please;"$'\n' elif [ -n "$cond" ]; then cnd=($cond); cval=($val); [ "${cnd[0]}" = "path" ] && { cval[0]=${cval[0]%/*}; cnd[0]="dir"; } if [ "${cnd[0]}" = "list:" ]; then OIFS="$IFS"; local IFS='%'; a=($cond); IFS="$OIFS"; lst=${a[1]} stringinstring "${cval[0]}" "$lst" || \ msg="! $umsg""$key = '${cval[0]}' value is not in ($lst);"$'\n' elif stringinstring "${cnd[0]}" "dir,exe,file"; then if [ -z "${cval[0]}" ]; then msg="$mpref. Is empty! Set it;"$'\n' else if [ "${cnd[0]}" = "exe" -a ! -x "${cval[0]}" ]; then nexe="$(which ${cval[0]} 2>/dev/null)" [ -n "$nexe" ] && { cval[0]=$nexe; nval="${cval[@]}"; err_log="" } || \ msg="! $umsg""$key = '${cval[0]}': file is not executable;"$'\n' elif [ "${cnd[0]}" = "dir" ]; then [ -d "${cval[0]}" ] || \ msg="! $umsg""$key = '${cval[0]}': dir is not found;"$'\n' elif [ "${cnd[0]}" = "file" ]; then [ -f "${cval[0]}" ] || \ msg="! $umsg""$key = '${cval[0]}': file is not found;"$'\n' fi ug=""; mode=""; mask=""; if [ -n "${cnd[1]}" ]; then for ((i=1; i<${#cnd[*]}; i++)) do # to collect attrs if [ "${cnd[$i]:0:1}" = "&" ]; then cnd[$i]=${cnd[$i]:1}; mask="1"; fi if [[ ${cnd[$i]:0:1} =~ $nump ]]; then mode=${cnd[$i]}; while [ "${mode:0:1}" = "0" ]; do mode=${mode:1}; done else ug=${cnd[$i]} fi done ma=($(stat -c '%U:%G %a' "${cval[0]}" 2>/dev/null)); set_ug=""; set_mode=""; res=""; if [ -n "$msg" -a -n "$act" -a "${cnd[0]}" != "exe" ]; then if [ "${cnd[0]}" = "dir" ]; then mkdir -p "${cval[0]}" 2>/dev/null [ -d "${cval[0]}" ] && { set_mode="1"; set_ug="1"; } else touch "${cval[0]}" 2>/dev/null [ -f "${cval[0]}" ] && { set_mode="1"; set_ug="1"; } fi [ -n "$set_mode" ] && \ msg=" $umsg""$key = '${cval[0]}': ${cnd[0]} is not found > Created;"$'\n' else # check file attrs ma=($(stat -c '%U:%G %a' "${cval[0]}")); if [ -n "$ug" -a "$ug" != "${ma[0]}" ]; then msg+="! $umsg""$key = '${cval[0]}': owners [${ma[0]}] is not \"$ug\";"$'\n' [ -n "$act" ] && set_ug="1" fi if [ -n "$mode" ]; then if [ -n "$mask" ]; then res=$(printf '%o' $(( 0$mode & 0${ma[1]} ))) [ "$res" = "$mode" ] || { msg+="! $umsg""$key = '${cval[0]}': mode [${ma[1]}] does not match the mask '$mode';"$'\n' [ -n "$act" ] && set_mode="1" } elif [ "${ma[1]}" != "$mode" ]; then msg+="! $umsg""$key = '${cval[0]}': mode [${ma[1]}] is not equal '$mode';"$'\n' [ -n "$act" ] && set_mode="1" fi fi fi if [ -n "$set_ug" -a -n "$ug" ]; then msg+="$umsg"" $key = '${cval[0]}' < owners change to '$ug'" chown $ug "${cval[0]}" 2>/dev/null && st="OK" || st="FAILED" msg+=" > $st;"$'\n' fi if [ -n "$set_mode" -a -n "$mode" ]; then [ -n "$mask" ] && \ mode=$(printf '%o' $(( 0$mode | 0${ma[1]} ))) msg+="$umsg"" $key = '${cval[0]}' < mode change to '$mode'" [ "${#mode}" = "3" ] && mode="00$mode" chmod $mode "${cval[0]}" 2>/dev/null && st="OK" || st="FAILED" msg+=" > $st;"$'\n' fi fi fi fi fi #msg="$umsg"" key $key ($3)='$val' checking: '$cond'"$'\n' ;; esac [ "$val" = "$nval" ] || { [ -n "$7" ] || \ values_update_db $key "value" "$(s2sq "$nval")" "$5" "$table" msg+=" $key < '$nval';"$'\n'; val="$nval" } [ -n "$5" ] || declare -g $key="$val" # expand not user's vals only ??? [ -n "$msg" ] && { [ -n "$err_log" ] && txt_err+="$msg" || txt_warn+="$msg" } } check_value_advanced() { #args: [err_log] [ro=""] [table='settings'] local err_log=""; [ -n "$6" ] && err_log=$6 local msg="" key=$1 val="$2" nval="$2" local umsg=""; [ -n "$5" ] && umsg="[$5] " local table="settings"; [ -n "$8" ] && table="$8" local mpref="! $umsg""$key = '$val'" ver; case "$1" in NX_LICENSE) ver=$(rematchfn 'NXAGENT - Version ([[:digit:][:punct:]]+)' \ "$($COMMAND_NXAGENT -version 2>&1)") #' # it was "$(strings $COMMAND_NXAGENT)" if [ -n "$ver" ]; then nval=${NX_LICENSE/\%BACKEND\%/$ver}; err_log="" else msg="$mpref: backend version is not found;"$'\n' fi ;; COMMAND_GDM_X_SESSION) [ ! -x "${val%% *}" ] && { nval="/etc/X11/Xsession"; err_log="" } ;; esac #echo "# $1($3)='$2' advanced checking." #debug [ "$val" = "$nval" ] || { [ -n "$7" ] || \ values_update_db $key "value" "$(s2sq "$nval")" "$5" "$table" msg+=" $key < '$nval';"$'\n'; val="$nval" } [ -n "$4" ] || declare -g $key="$val" # expand not user's vals only ??? [ -n "$msg" ] && { [ -n "$err_log" ] && txt_err+="$msg" || txt_warn+="$msg" } } check_keyvals() { #args: [username] [ro=""] [table='settings'] #echo "$(date "+%T.%3N"): $FUNCNAME" #debug local table="settings"; [ -n "$3" ] && table="$3" local keys=$(keyslst_for_user "$1" "$table") r a ad; local value val_type val_depend val_check; local err_log dep_for_null vdep tdep nval; for key in $keys; do #echo "$(date "+%T.%3N"): ----- $key" #debug r=$(values_str_from_db $key "value,$ex_rules_cols" "$1" "$table") OIFS="$IFS"; IFS='&'; a=($r); IFS="$OIFS"; value=$(sq2s "${r%%&*}"); val_type=$(sq2s "${a[1]}"); val_depend=$(sq2s "${a[2]}"); val_check=$(sq2s "${a[3]}"); err_log=""; stringinstring "error" "$val_check" && \ { err_log="1"; val_check=$(trim "${val_check/error/}"); } # don't check if depend condition is set and not match dep_for_null="" [ -n "$val_depend" ] && { local first=${val_depend:0:1} [ "$first" = "!" ] && { val_depend=${val_depend:1}; dep_for_null="1"; } r=$(values_str_from_db $val_depend "value,val_type" "$1" "$table") OIFS="$IFS"; IFS='&'; ad=($r); IFS="$OIFS" vdep=${ad[0]}; tdep=${ad[1]} [ -z "$dep_for_null" ] && { case "$tdep" in bool) [ "$vdep" = "1" ] || continue ;; string) [ -n "$vdep" ] || continue ;; int) [ "$vdep" -ne "0" ] || continue ;; esac } || { case "$tdep" in bool) [ "$vdep" = "1" ] && continue ;; string) [ -n "$vdep" ] && continue ;; int) [ "$vdep" -ne "0" ] && continue ;; esac } #echo "$key -> $val_depend ($tdep): '$vdep' $dep_for_null" } if stringinstring "rt_expand" "$val_check"; then val_check=$(trim "${val_check/rt_expand/}") elif [ "$val_type" = "string" ]; then # expand if no rt_expand only #nval="${value@P}" # value from db (need to "ORDER BY rowid" in keylist) nval="${!key}" # expands/chg defaults by means 'bash source *.conf' [ -n "$nval" -a "$value" != "$nval" ] && { [ -n "$2" ] || \ values_update_db $key "value" "$(s2sq "$nval")" "$1" "$table" #txt_warn+=" $key ['$value'] < '$nval';"$'\n' txt_warn+=" $key < '$nval';"$'\n' value="$nval" } fi stringinstring "advanced" "$val_check" && { val_check=$(trim "${val_check/advanced/}") check_value_advanced $key "$value" "$val_type" \ "$val_check" "$1" "$err_log" "$2" "$table" continue } check_value "$key" "$value" "$val_type" \ "$val_check" "$1" "$err_log" "$2" "$table" #echo "$key ($val_type) /$val_check/: $value" done } parse_defaults() { #arg: [table='settings'] local table="settings"; [ -n "$1" ] && table="$1" local confd=$SHARED_CONFS/node.conf.def curd=$(pwd) echo "Parse default settings in $confd:"; cd $confd for fn in *.{cnf,conf}; do [ -r $fn ] && . $fn; done for fn in *.{cnf,conf}; do [ -r $fn ] || continue; echo -n " $fn .."; conf_buf="$(< $fn)"; parse_conf_buf "" 1 "$table"; echo " done." done cd $curd } parse_settings() { #arg: [table='settings'] local table="settings"; [ -n "$1" ] && table="$1" local confd="node.conf.d" fn; echo "Parse system settings in $NX_ETC_DIR:"; curd=$(pwd) cd $NX_ETC_DIR for fn in $confd/*.conf node.conf; do [ -r $fn ] && . $fn; done for fn in $confd/*.conf node.conf; do [ -r $fn ] || continue; echo -n " $fn ..."; conf_buf="$(< $fn)"; parse_conf_buf "" "" "$table"; echo " done." done cd $curd } parse_users_settings() { #arg: [table='settings'] local table="settings"; [ -n "$1" ] && table="$1" local fn un qstr ukeys key exvals; echo "Parse users settings:"; curd=$(pwd) cd $NX_ETC_DIR for fn in *.conf; do [ -r $fn ] || continue; un=${fn//.conf/} getent passwd "$un" >/dev/null || continue echo -n " $fn ..."; . $fn; conf_buf="$(< $fn)"; parse_conf_buf "$un" "" "$table" echo -n " check rules for $un ..." # user extras setup scrutch ukeys=$(keyslst_for_user "$un" "$table") for key in $ukeys; do echo -n " $key ..." qstr="SELECT $ex_rules_cols FROM "$table"" qstr+=" WHERE user IS NULL AND key='$key' LIMIT 1;" exvals=$(qa_dbe0 "$qstr"); exvals=${exvals//\"/} values_update_db $key "$ex_rules_cols" "$exvals" "$un" "$table" done done echo " done." cd $curd } parse_acl() { #args: filename [table='settings'] userlist grouplist local table="settings"; [ -n "$2" ] && table="$2" local un=${1##*/} user; un=${un%%\.*}; user="#$un" # user local buf l key val val_dep val_chk ns=0 upd_s ins_s v; local val_type i ca ans s ov a if [ "$un" = "all" ]; then user="@$un" elif ! stringinstring "$un" "$3"; then stringinstring "$un" "$4" && user="*$un" # group fi buf="$(< $1)" #echo $1 while read l; do l="$(trim "$l")"; ((ns++)) [ -n "$l" ] || continue [ "${l:0:1}" = "#" ] && continue #echo "$l" #debug key="$(trim "${l%%\%\%\%*}")"; key=$(s2sq "$key"); stringinstring "%%%" "$l" && l="$(trim "${l#*\%\%\%}")" || l="" val="$(trim "${l%%\%\%\%*}")"; if [ "$key" != "@shadow@" ]; then val=$(s2sq "$val"); val_type="" stringinstring "%%%" "$l" && l="$(trim "${l#*\%\%\%}")" || l="" val_dep="$(trim "${l%%\%\%\%*}")"; val_dep=$(s2sq "$val_dep") else # parse shadow acl val=$(trim "${val//\,/ }"); ans=($val); ca=${#ans[@]} val=""; val_type=""; val_dep=""; for ((i=0; i<$ca; i++)) { s=${ans[i]} [ "${s:0:1}" != "#" ] && ov=0 || { ov=1; s=${s:1}; } [ "${s:(-1):1}" != "!" ] && a=1 || { a=0; s=${s::-1}; } val+="${val:+,}$s"; val_type+="${val_type:+,}$ov"; val_dep+="${val_dep:+,}$a"; } fi val_chk=$(printf "%04d" $ns) #echo "$user; $key; $val; $val_dep; $val_chk"; #continue #debug # fake upsert to db upd_s="UPDATE $table SET value='$val',val_type='$val_type', \ val_depend='$val_dep', val_check='$val_chk' WHERE user='$user' AND key='$key';" ins_s="INSERT INTO $table(user,key,value,val_type,val_depend,val_check) \ SELECT '$user','$key','$val','$val_type','$val_dep','$val_chk' \ WHERE (SELECT Changes()=0);" q_dbe "$upd_s" "$ins_s" #echo "$upd_s" "$ins_s" #debug val=""; val_dep=""; val_chk="" done <<< "$buf" } parse_acl_dir() { #arg: [table='settings'] local table="settings"; [ -n "$1" ] && table="$1" local ffn str ulist="" glist="" while read str; do str=${str%%:*}; ulist+="${ulist:+$' '}$str" done <<< "$(getent passwd)" while read str; do str=${str%%:*}; glist+="${glist:+$' '}$str" done <<< "$(getent group)" echo "Parse $NX_ACL_DIR:"; for ffn in $NX_ACL_DIR/*; do stringinstring "README" "$ffn" && continue [ -r $ffn ] || continue; echo -n " ${ffn##*/} ..."; parse_acl "$ffn" "$table" "$ulist" "$glist"; done echo " done." } open_dbe $$ [ ! -f $sq_settings_fn ] && MKDB="yes" if [ "$MKDB" = "yes" ]; then table="mem.settings" echo "$(date "+%T.%3N"): mem.settings mkdb starting" q_dbe0 "ATTACH DATABASE ':memory:' AS mem;" \ "${qs_create_settings/nxsettings/mem}"; parse_defaults "$table"; parse_settings "$table"; parse_users_settings "$table"; check_keyvals "" "" "$table" [ -d "$NX_ACL_DIR" ] && parse_acl_dir "$table" [ -n "$txt_warn" ] && { echo; echo "Checking results:"; echo "$txt_warn"; } [ -n "$txt_err" ] && { echo; echo "!!! ERRORS !!!"; echo "$txt_err"; } txt_err=""; txt_warn=""; txt_info=""; echo "$(date "+%T.%3N"): nxsettings mkdb attach" attach_db "$sq_settings_fn"|| { echo "Unable to attach $sq_settings_fn"; exit_proc 1; } q_dbe0 "DROP TABLE IF EXISTS nxsettings.settings;" "$qs_create_settings" \ "INSERT INTO nxsettings.settings($all_cols) SELECT $all_cols FROM $table;" echo "$(date "+%T.%3N"): nxsettings mkdb stop" else attach_db "$sq_settings_fn" ro || { echo "Unable to attach db file $sq_settings_fn"; exit_proc 1; } set_vars_from_db fi #============================================================================ run_nscd() { NSCD="nscd" if [ -f /var/run/nscd/nscd.pid ]; then $NSCD "$@" 2>/dev/null || true fi } install_nx() { if [ ! -f $NX_ETC_DIR/users.id_dsa ]; then $COMMAND_SSH_KEYGEN -f $NX_ETC_DIR/users.id_dsa -t dsa -N "" fi echo "For backward compatibility to Nomachine, freenx works with dss-keys only." echo "Please add string \"PubkeyAcceptedKeyTypes=+ssh-dss\" in sshd_config" echo "and ssh_config if required. This is actual for modern openssh servers." echo -n "Setting up user and group nx ..." useradd -g nx -G utmp -d /var/lib/nxserver/home/ \ -s /usr/bin/nxserver -c "NX System User" nx 2>/dev/null echo "done" echo -n "Setting up $NX_SESS_DIR ..." chmod 770 $NX_SESS_DIR echo "done" echo -n "Setting up $NX_LOGFILE ..." mkdir -p $(dirname "$NX_LOGFILE") touch "$NX_LOGFILE" chmod 660 "$NX_LOGFILE" echo "done" echo -n "Setting up known_hosts and $SSH_AUTHORIZED_KEYS ..." SETUP_NX_KEY="no" mkdir -p $NX_HOME_DIR/.ssh chmod 700 $NX_HOME_DIR/ $NX_HOME_DIR/.ssh if [ ! -f $NX_HOME_DIR/.ssh/$SSH_AUTHORIZED_KEYS -o \ "$SETUP_NOMACHINE_KEY" = "yes" ]; then SETUP_NX_KEY="yes" if [ "$SETUP_NOMACHINE_KEY" = "yes" ]; then cat << EOF >$NX_HOME_DIR/.ssh/$SSH_AUTHORIZED_KEYS no-port-forwarding,no-agent-forwarding,command="$PATH_BIN/nxserver" ssh-dss AAAAB3NzaC1kc3MAAACBAJe/0DNBePG9dYLWq7cJ0SqyRf1iiZN/IbzrmBvgPTZnBa5FT/0Lcj39sRYt1paAlhchwUmwwIiSZaON5JnJOZ6jKkjWIuJ9MdTGfdvtY1aLwDMpxUVoGwEaKWOyin02IPWYSkDQb6cceuG9NfPulS9iuytdx0zIzqvGqfvudtufAAAAFQCwosRXR2QA8OSgFWSO6+kGrRJKiwAAAIEAjgvVNAYWSrnFD+cghyJbyx60AAjKtxZ0r/Pn9k94Qt2rvQoMnGgt/zU0v/y4hzg+g3JNEmO1PdHh/wDPVOxlZ6Hb5F4IQnENaAZ9uTZiFGqhBO1c8Wwjiq/MFZy3jZaidarLJvVs8EeT4mZcWxwm7nIVD4lRU2wQ2lj4aTPcepMAAACANlgcCuA4wrC+3Cic9CFkqiwO/Rn1vk8dvGuEQqFJ6f6LVfPfRTfaQU7TGVLk2CzY4dasrwxJ1f6FsT8DHTNGnxELPKRuLstGrFY/PR7KeafeFZDf+fJ3mbX5nxrld3wi5titTnX+8s4IKv29HJguPvOK/SI7cjzA+SqNfD7qEo8= root@nettuno EOF chmod 600 $NX_HOME_DIR/.ssh/$SSH_AUTHORIZED_KEYS cat << EOF >$NX_HOME_DIR/.ssh/client.id_dsa.key -----BEGIN DSA PRIVATE KEY----- MIIBuwIBAAKBgQCXv9AzQXjxvXWC1qu3CdEqskX9YomTfyG865gb4D02ZwWuRU/9 C3I9/bEWLdaWgJYXIcFJsMCIkmWjjeSZyTmeoypI1iLifTHUxn3b7WNWi8AzKcVF aBsBGiljsop9NiD1mEpA0G+nHHrhvTXz7pUvYrsrXcdMyM6rxqn77nbbnwIVALCi xFdHZADw5KAVZI7r6QatEkqLAoGBAI4L1TQGFkq5xQ/nIIciW8setAAIyrcWdK/z 5/ZPeELdq70KDJxoLf81NL/8uIc4PoNyTRJjtT3R4f8Az1TsZWeh2+ReCEJxDWgG fbk2YhRqoQTtXPFsI4qvzBWct42WonWqyyb1bPBHk+JmXFscJu5yFQ+JUVNsENpY +Gkz3HqTAoGANlgcCuA4wrC+3Cic9CFkqiwO/Rn1vk8dvGuEQqFJ6f6LVfPfRTfa QU7TGVLk2CzY4dasrwxJ1f6FsT8DHTNGnxELPKRuLstGrFY/PR7KeafeFZDf+fJ3 mbX5nxrld3wi5titTnX+8s4IKv29HJguPvOK/SI7cjzA+SqNfD7qEo8CFDIm1xRf 8xAPsSKs6yZ6j1FNklfu -----END DSA PRIVATE KEY----- EOF chmod 600 $NX_HOME_DIR/.ssh/client.id_dsa.key else # generate a new key, backup the old and copy it to $SSH_AUTHORIZED_KEYS $PATH_BIN/nxkeygen fi fi if [ ! -f $NX_HOME_DIR/.ssh/known_hosts -a "$BUILD_KNOWN_HOSTS" = "yes" ]; then echo -n "127.0.0.1 " > $NX_HOME_DIR/.ssh/known_hosts if [ -e "/etc/openssh/ssh_host_rsa_key.pub" ] ; then cat /etc/openssh/ssh_host_rsa_key.pub >> \ $NX_HOME_DIR/.ssh/known_hosts else [ -e "/etc/ssh/ssh_host_rsa_key.pub" ] && \ cat /etc/ssh/ssh_host_rsa_key.pub >> $NX_HOME_DIR/.ssh/known_hosts fi fi echo "done" echo -n "Setting up permissions ..." chown -R nx:nx /var/lib/nxserver chown -R nx:nx $NX_SESS_DIR chown -R nx:nx $NX_HOME_DIR chown nx:nx "$NX_LOGFILE" echo "done" } test_nx() { echo "" echo "----> Testing your nxserver connection ..." CONNECTION="" while read -t 3 line; do echo $line case "$line" in *"HELLO NXSERVER - Version $NX_VERSION"*) CONNECTION="yes" ;; *"HELLO NXSERVER - Version"*) echo "Warning: Version mismatch. Expected $NX_VERSION got: $line." CONNECTION="yes" ;; *"NX> 999 Bye"*) break; ;; esac done < <(NODE_PUBLICKEY="$NX_HOME_DIR/.ssh/client.id_dsa.key" \ $PATH_BIN/nxnode-login test-nx nx 22 nxserver --check) if [ -z "$CONNECTION" ]; then echo "Fatal error: Could not connect to NX Server." echo echo "Please check your ssh setup:" echo "" echo "The following are _examples_ of what you might need to check." echo "" echo " - Make sure \"nx\" is one of the AllowUsers in sshd_config." echo " (or that the line is outcommented/not there)" echo " - Make sure \"nx\" is one of the AllowGroups in sshd_config." echo " (or that the line is outcommented/not there)" echo " - Make sure your sshd allows public key authentication." echo " - Make sure your sshd is really running on port 22." echo " - Make sure your sshd_config AuthorizedKeysFile in sshd_config is set to $SSH_AUTHORIZED_KEYS." echo " (this should be a filename not a pathname+filename)" echo " - Make sure you allow ssh on localhost, this could come from some" echo " restriction of:" echo " -the tcp wrapper. Then add in /etc/hosts.allow: ALL:localhost" echo " -the iptables. add to it:" echo " $ iptables -A INPUT -i lo -j ACCEPT" echo " $ iptables -A OUTPUT -o lo -j ACCEPT" exit_proc 1 fi echo "<--- done" echo "" } uninstall_nx() { if [ -e "$NX_SESS_DIR" ]; then echo -n "Removing session database ..." rmdir -p $NX_SESS_DIR 2>/dev/null echo "done" fi if [ -e "$NX_LOGFILE" ]; then echo -n "Removing logfile ..." rm -f "$NX_LOGFILE" 2>/dev/null rmdir -p $(dirname "$NX_LOGFILE") 2>/dev/null echo "done" fi if [ "$PURGE" = "yes" -a -e "$NX_HOME_DIR" ]; then echo -n "Removing home directory of special user \"nx\" ..." rm -f -r "$NX_HOME_DIR" 2>/dev/null rmdir -p $(dirname "$NX_HOME_DIR") 2>/dev/null echo "done" fi if [ "$PURGE" = "yes" -a -e "$NX_ETC_DIR" ]; then echo -n "Removing configuration files ..." rm -f "$NX_ETC_DIR/users.id_dsa" \ "$NX_ETC_DIR/users.id_dsa.pub" 2>/dev/null for i in `ls $NX_ETC_DIR/*.node.conf 2>/dev/null`; do rm -f "$i" 2>/dev/null; done echo "done" fi } if [ "$TEST" = "yes" ]; then test_nx exit_proc 0 fi if [ "$INSTALL" = "yes" ]; then #Perform cleanup? [ "$CLEAN" = "yes" ] && uninstall_nx [ -f /etc/nscd.conf ] && { run_nscd --invalidate passwd; run_nscd --invalidate group; } install_nx [ "$AUTOMATIC" = "no" ] && test_nx echo "Ok, nxserver is ready." if [ "$SETUP_NOMACHINE_KEY" = "no" -a "$SETUP_NX_KEY" = "yes" ]; then echo echo "Warning: Clients will not be able to login to this server with the standard key." echo " Please replace /usr/NX/share/client.id_dsa.key on all clients you want" echo " to use with $NX_HOME_DIR/.ssh/client.id_dsa.key" echo " and protect it accordingly." echo "" echo " Since 1.5.0 you need to import the correct key via the GUI." echo echo " If you really want to use the NoMachine key please remove" echo " '$NX_HOME_DIR/.ssh/$SSH_AUTHORIZED_KEYS'" echo " and then run this script with the --setup-nomachine-key parameter." fi echo "Have Fun!" elif [ "$UNINSTALL" = "yes" ]; then uninstall_nx echo "Ok, nxserver is uninstalled" echo if [ "$PURGE" = "yes" ]; then echo "To complete the uninstallation process, remove the FreeNX scripts in $PATH_BIN" echo "and the $NX_ETC_DIR/node.conf configuration file." else echo "To complete the uninstallation process, remove the FreeNX scripts in $PATH_BIN" echo echo "Configuration files and ssh keys are saved in case you would like to reinstall" echo "freenx at a later time. To remove them, please run 'nxsetup --uninstall --purge'" fi fi exit_proc 0