freedombone-controlpanel 76KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341
  1. #!/bin/bash
  2. #
  3. # .---. . .
  4. # | | |
  5. # |--- .--. .-. .-. .-.| .-. .--.--. |.-. .-. .--. .-.
  6. # | | (.-' (.-' ( | ( )| | | | )( )| | (.-'
  7. # ' ' --' --' -' - -' ' ' -' -' -' ' - --'
  8. #
  9. # Freedom in the Cloud
  10. #
  11. # Administrator control panel for the Freedombone system
  12. #
  13. # License
  14. # =======
  15. #
  16. # Copyright (C) 2015-2018 Bob Mottram <bob@freedombone.net>
  17. #
  18. # This program is free software: you can redistribute it and/or modify
  19. # it under the terms of the GNU Affero General Public License as published by
  20. # the Free Software Foundation, either version 3 of the License, or
  21. # (at your option) any later version.
  22. #
  23. # This program is distributed in the hope that it will be useful,
  24. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. # GNU Affero General Public License for more details.
  27. #
  28. # You should have received a copy of the GNU Affero General Public License
  29. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  30. PROJECT_NAME='freedombone'
  31. export TEXTDOMAIN=${PROJECT_NAME}-controlpanel
  32. export TEXTDOMAINDIR="/usr/share/locale"
  33. if [[ $USER != 'root' ]]; then
  34. # show the user version of the control panel
  35. #${PROJECT_NAME}-controlpanel-user
  36. controluser
  37. exit 0
  38. fi
  39. function please_wait {
  40. local str width height length
  41. width=$(tput cols)
  42. height=$(tput lines)
  43. str=$"Please wait"
  44. length=${#str}
  45. clear
  46. tput cup $((height / 2)) $(((width / 2) - (length / 2)))
  47. echo "$str"
  48. tput cup $((height * 3 / 5)) $(((width / 2)))
  49. echo -n ''
  50. }
  51. please_wait
  52. # Start including files
  53. source /usr/local/bin/${PROJECT_NAME}-vars
  54. UTILS_FILES="/usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-*"
  55. for f in $UTILS_FILES
  56. do
  57. source "$f"
  58. done
  59. APP_FILES="/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*"
  60. for f in $APP_FILES
  61. do
  62. source "$f"
  63. done
  64. # End including files
  65. COMPLETION_FILE="$HOME/${PROJECT_NAME}-completed.txt"
  66. SELECTED_USERNAME=
  67. ADMIN_USER=
  68. UPGRADE_SCRIPT_NAME="${PROJECT_NAME}-upgrade"
  69. UPDATE_DATE_SCRIPT=/usr/bin/updatedate
  70. # Minimum number of characters in a password
  71. MINIMUM_PASSWORD_LENGTH=$(grep 'MINIMUM_PASSWORD_LENGTH=' "/usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-passwords" | head -n 1 | awk -F '=' '{print $2}')
  72. # Mumble
  73. MUMBLE_PORT=64738
  74. MUMBLE_ONION_PORT=8095
  75. SSH_PORT=2222
  76. # outgoing SMTP proxy
  77. SMTP_PROXY_ENABLE=$'no'
  78. SMTP_PROXY_PROTOCOL='smtps'
  79. SMTP_PROXY_SERVER='mail.myispdomain'
  80. SMTP_PROXY_PORT=465
  81. SMTP_PROXY_USERNAME=''
  82. SMTP_PROXY_PASSWORD=''
  83. WIFI_INTERFACE=wlan0
  84. WIFI_SSID=
  85. WIFI_TYPE='wpa2-psk'
  86. WIFI_PASSPHRASE=
  87. WIFI_HOTSPOT='no'
  88. WIFI_NETWORKS_FILE="$HOME/${PROJECT_NAME}-wifi.cfg"
  89. USB_DRIVE=sdb
  90. # get default USB from config file
  91. CONFIGURATION_FILE="$HOME/${PROJECT_NAME}.cfg"
  92. read_config_param WIFI_HOTSPOT
  93. read_config_param WIFI_INTERFACE
  94. read_config_param WIFI_TYPE
  95. read_config_param WIFI_SSID
  96. read_config_param WIFI_PASSPHRASE
  97. read_config_param SSH_PORT
  98. read_config_param SMTP_PROXY_ENABLE
  99. read_config_param SMTP_PROXY_PROTOCOL
  100. read_config_param SMTP_PROXY_SERVER
  101. read_config_param SMTP_PROXY_PORT
  102. read_config_param SMTP_PROXY_USERNAME
  103. read_config_param SMTP_PROXY_PASSWORD
  104. read_config_param USB_DRIVE
  105. read_config_param MY_USERNAME
  106. read_config_param ONION_ONLY
  107. if [[ $USB_DRIVE == *"dev"* ]]; then
  108. USB_DRIVE=$(echo ${USB_DRIVE} | awk -F '/' '{print $3}' | sed 's|1||g' | sed 's|2||g')
  109. fi
  110. function any_key {
  111. echo ''
  112. read -n1 -rsp $"Press any key to continue..." key
  113. }
  114. function any_key_verify {
  115. echo ''
  116. read -n1 -rsp $"Press any key to continue or C to check a hash..." key
  117. if [[ "$key" != 'c' && "$key" != 'C' ]]; then
  118. return
  119. fi
  120. data=$(mktemp 2>/dev/null)
  121. dialog --title $"Check tripwire hash" \
  122. --backtitle $"Freedombone Control Panel" \
  123. --inputbox $"Paste your tripwire hash below and it will be checked against the current database" 12 60 2>"$data"
  124. sel=$?
  125. case $sel in
  126. 0)
  127. GIVEN_HASH=$(<"$data")
  128. if [ ${#GIVEN_HASH} -gt 8 ]; then
  129. if [[ "$GIVEN_HASH" == *' '* ]]; then
  130. dialog --title $"Check tripwire" \
  131. --msgbox $"\\nThe hash should not contain any spaces" 10 40
  132. else
  133. DBHASH=$(sha512sum "/var/lib/tripwire/${HOSTNAME}.twd" | awk -F ' ' '{print $1}')
  134. if [[ "$DBHASH" == "$GIVEN_HASH" ]]; then
  135. dialog --title $"Check tripwire" \
  136. --msgbox $"\\nSuccess\\n\\nThe hash you gave matches the current tripwire database" 10 40
  137. else
  138. dialog --title $"Check tripwire" \
  139. --msgbox $"\\nFailed\\n\\nThe hash you gave does not match the current tripwire database. This might be because you reset the tripwire, or there could have been an unauthorised modification of the system" 12 50
  140. fi
  141. fi
  142. fi
  143. ;;
  144. esac
  145. rm -f "$data"
  146. }
  147. function get_app_icann_address {
  148. app_name="$1"
  149. if grep -q "${app_name} domain" "$COMPLETION_FILE"; then
  150. grep "${app_name} domain" "${COMPLETION_FILE}" | head -n 1 | awk -F ':' '{print $2}'
  151. return
  152. else
  153. app_name_upper="$(echo "$app_name" | tr '[:lower:]' '[:upper:]')_DOMAIN_NAME"
  154. if [ "$app_name_upper" ]; then
  155. param_value=$(grep "${app_name_upper}=" "$CONFIGURATION_FILE" | head -n 1 | awk -F '=' '{print $2}')
  156. if [ "${param_value}" ]; then
  157. echo "${param_value}"
  158. return
  159. fi
  160. fi
  161. fi
  162. echo "${DEFAULT_DOMAIN_NAME}"
  163. }
  164. function passwords_select_user {
  165. SELECTED_USERNAME=
  166. # shellcheck disable=SC2207
  167. users_array=($(ls /home))
  168. delete=(git)
  169. # shellcheck disable=SC2068
  170. for del in ${delete[@]}
  171. do
  172. # shellcheck disable=SC2206
  173. users_array=(${users_array[@]/$del})
  174. done
  175. i=0
  176. W=()
  177. name=()
  178. # shellcheck disable=SC2068
  179. for u in ${users_array[@]}
  180. do
  181. if [[ $(is_valid_user "$u") == "1" ]]; then
  182. i=$((i+1))
  183. W+=("$i" "$u")
  184. name+=("$u")
  185. fi
  186. done
  187. if [ $i -eq 1 ]; then
  188. SELECTED_USERNAME="${name[0]}"
  189. else
  190. user_index=$(dialog --backtitle $"Freedombone Control Panel" --title $"Select User" --menu $"Select one of the following:" 24 40 17 "${W[@]}" 3>&2 2>&1 1>&3)
  191. # shellcheck disable=SC2181
  192. if [ $? -eq 0 ]; then
  193. SELECTED_USERNAME="${name[$((user_index-1))]}"
  194. fi
  195. fi
  196. }
  197. function passwords_show_apps {
  198. SELECTED_APP=
  199. i=0
  200. W=()
  201. name=()
  202. for a in "${APPS_AVAILABLE[@]}"
  203. do
  204. if [[ $(function_exists "change_password_${a}") == "1" ]]; then
  205. i=$((i+1))
  206. W+=("$i" "$a")
  207. name+=("$a")
  208. fi
  209. done
  210. i=$((i+1))
  211. W+=("$i" "mariadb")
  212. name+=("mariadb")
  213. selected_app_index=$(dialog --backtitle $"Freedombone Control Panel" --title $"Select App" --menu $"Select one of the following:" 24 40 17 "${W[@]}" 3>&2 2>&1 1>&3)
  214. # shellcheck disable=SC2181
  215. if [ $? -eq 0 ]; then
  216. SELECTED_APP="${name[$((selected_app_index-1))]}"
  217. fi
  218. }
  219. function reset_password_tries {
  220. passwords_select_user
  221. if [ ! "$SELECTED_USERNAME" ]; then
  222. return
  223. fi
  224. pam_tally --user "$SELECTED_USERNAME" --reset
  225. dialog --title $"Reset password tries" \
  226. --msgbox $"Password tries have been reset for $SELECTED_USERNAME" 6 60
  227. }
  228. function view_or_change_passwords {
  229. passwords_select_user
  230. if [ ! "$SELECTED_USERNAME" ]; then
  231. return
  232. fi
  233. detect_installed_apps
  234. passwords_show_apps
  235. if [ ! "$SELECTED_APP" ]; then
  236. return
  237. fi
  238. CURR_PASSWORD=$("${PROJECT_NAME}-pass" -u "${SELECTED_USERNAME}" -a "${SELECTED_APP}")
  239. icann_address=$(get_app_icann_address "${SELECTED_APP}")
  240. onion_address=$(get_app_onion_address "${SELECTED_APP}")
  241. titlestr=$"View or Change Password"
  242. if [ ${#onion_address} -gt 0 ]; then
  243. viewstr=$"${SELECTED_APP} password for ${SELECTED_USERNAME} on $icann_address or $onion_address\\n\\nCopy or change it if you wish."
  244. else
  245. viewstr=$"${SELECTED_APP} password for ${SELECTED_USERNAME} on $icann_address\\n\\nCopy or change it if you wish."
  246. fi
  247. if [ -f /root/.nostore ]; then
  248. titlestr=$"Change Password"
  249. if [ ${#onion_address} -gt 0 ]; then
  250. viewstr=$"Change the ${SELECTED_APP} password for ${SELECTED_USERNAME} on $icann_address or $onion_address."
  251. else
  252. viewstr=$"Change the ${SELECTED_APP} password for ${SELECTED_USERNAME} on $icann_address."
  253. fi
  254. fi
  255. if [[ "${SELECTED_APP}" == 'mariadb' ]]; then
  256. CURR_PASSWORD=$("${PROJECT_NAME}-pass" -u root -a mariadb)
  257. dialog --title $"MariaDB database password" \
  258. --msgbox "\\n ${CURR_PASSWORD}" 7 40
  259. return
  260. fi
  261. data=$(mktemp 2>/dev/null)
  262. dialog --title "$titlestr" \
  263. --backtitle $"Freedombone Control Panel" \
  264. --inputbox "$viewstr" 12 75 "$CURR_PASSWORD" 2>"$data"
  265. sel=$?
  266. case $sel in
  267. 0)
  268. CURR_PASSWORD=$(<"$data")
  269. if [ ${#CURR_PASSWORD} -gt 8 ]; then
  270. "${PROJECT_NAME}-pass" -u "${SELECTED_USERNAME}" -a "${SELECTED_APP}" -p "${CURR_PASSWORD}"
  271. "change_password_${SELECTED_APP}" "${SELECTED_USERNAME}" "${CURR_PASSWORD}"
  272. dialog --title $"Change password" \
  273. --msgbox $"The password was changed" 6 40
  274. else
  275. dialog --title $"Change password" \
  276. --msgbox $"The password given must be at least 8 characters" 6 40
  277. fi
  278. ;;
  279. esac
  280. rm -f "$data"
  281. }
  282. function check_for_updates {
  283. if [ ! -f "/etc/cron.weekly/$UPGRADE_SCRIPT_NAME" ]; then
  284. dialog --title $"Check for updates" \
  285. --msgbox $"Upgrade script was not found" 6 40
  286. return
  287. fi
  288. clear
  289. /etc/cron.weekly/$UPGRADE_SCRIPT_NAME
  290. any_key
  291. }
  292. function add_user {
  293. data=$(mktemp 2>/dev/null)
  294. dialog --backtitle $"Freedombone Control Panel" \
  295. --title $"Add new user" \
  296. --form "\\n" 8 60 3 \
  297. $"Username:" 1 1 "" 1 28 16 15 \
  298. $"ssh public key (optional):" 2 1 "" 2 28 40 10000 \
  299. 2> "$data"
  300. sel=$?
  301. case $sel in
  302. 1) rm -f "$data"
  303. return;;
  304. 255) rm -f "$data"
  305. return;;
  306. esac
  307. new_user_username=$(sed -n 1p < "$data")
  308. new_user_ssh_public_key=$(sed -n 2p < "$data")
  309. rm -f "$data"
  310. if [ ${#new_user_username} -lt 2 ]; then
  311. dialog --title $"New username" \
  312. --msgbox $"No username was given" 6 40
  313. return
  314. fi
  315. if [[ "$new_user_username" == *" "* ]]; then
  316. dialog --title $"Invalid username" \
  317. --msgbox $"The username should not contain any spaces" 6 40
  318. return
  319. fi
  320. if [ ${#new_user_ssh_public_key} -lt 20 ]; then
  321. clear
  322. "${PROJECT_NAME}-adduser" "$new_user_username"
  323. any_key
  324. else
  325. if [[ "$new_user_ssh_public_key" == "ssh-"* ]]; then
  326. clear
  327. "${PROJECT_NAME}-adduser" "$new_user_username" "$new_user_ssh_public_key"
  328. any_key
  329. else
  330. dialog --title $"ssh public key" \
  331. --msgbox $"This does not look like an ssh public key" 6 40
  332. fi
  333. fi
  334. }
  335. function pad_string {
  336. echo -n -e "$1" | sed -e :a -e 's/^.\{1,25\}$/& /;ta'
  337. }
  338. function show_domains {
  339. read_config_param "DEFAULT_DOMAIN_NAME"
  340. echo 'Domains'
  341. echo '======='
  342. echo ''
  343. echo -n -e "$(pad_string 'Name')"
  344. echo -n -e "$(pad_string 'ICANN')"
  345. echo -n -e "$(pad_string 'Tor')"
  346. echo ''
  347. echo '--------------------------------------------------------------------------'
  348. if grep -q "ssh onion domain" "$COMPLETION_FILE"; then
  349. echo -n -e "$(pad_string 'ssh')"
  350. echo -n -e "$(pad_string "${DEFAULT_DOMAIN_NAME}")"
  351. grep 'ssh onion domain' "${COMPLETION_FILE}" | awk -F ':' '{print $2}'
  352. fi
  353. if grep -q "email onion domain" "$COMPLETION_FILE"; then
  354. echo -n -e "$(pad_string 'Email')"
  355. echo -n -e "$(pad_string "${DEFAULT_DOMAIN_NAME}")"
  356. grep 'email onion domain' "${COMPLETION_FILE}" | awk -F ':' '{print $2}'
  357. fi
  358. if grep -q "sks onion domain" "$COMPLETION_FILE"; then
  359. read_config_param "KEYSERVER_DOMAIN_NAME"
  360. echo -n -e "$(pad_string 'SKS')"
  361. echo -n -e "$(pad_string "${KEYSERVER_DOMAIN_NAME}")"
  362. grep 'sks onion domain' "${COMPLETION_FILE}" | awk -F ':' '{print $2}'
  363. fi
  364. for app_name in "${APPS_INSTALLED_NAMES[@]}"
  365. do
  366. if ! grep -q "SHOW_ON_ABOUT=1" "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}"; then
  367. continue
  368. fi
  369. # handle the foibles of capitalisation
  370. if ! grep -q "${app_name} domain" "$COMPLETION_FILE"; then
  371. app_name_upper=$(echo "${app_name}" | awk '{print toupper($0)}')
  372. if grep -q "${app_name_upper} domain" "$COMPLETION_FILE"; then
  373. app_name=${app_name_upper}
  374. else
  375. app_name_first_upper="$(tr '[:lower:]' '[:upper:]' <<< "${app_name:0:1}")${app_name:1}"
  376. if grep -q "${app_name_first_upper} domain" "$COMPLETION_FILE"; then
  377. app_name=${app_name_first_upper}
  378. fi
  379. fi
  380. fi
  381. if [ ${#app_name} -gt 0 ]; then
  382. icann_address=$(get_app_icann_address "$app_name")
  383. if grep -q "SHOW_ICANN_ADDRESS_ON_ABOUT=0" "/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-${app_name}"; then
  384. icann_address='-'
  385. fi
  386. if [[ "$ONION_ONLY" != 'no' ]]; then
  387. if [[ "${icann_address}" != "${LOCAL_NAME}.local" ]]; then
  388. icann_address='-'
  389. fi
  390. fi
  391. onion_address=$(get_app_onion_address "$app_name")
  392. if [ ${#onion_address} -eq 0 ]; then
  393. onion_address="-"
  394. fi
  395. echo -n -e "$(pad_string "${app_name}")"
  396. echo -n -e "$(pad_string "${icann_address}")"
  397. echo "${onion_address}"
  398. if grep -q "mobile${app_name} onion domain" "$COMPLETION_FILE"; then
  399. onion_address=$(get_app_onion_address "${app_name}" "mobile")
  400. echo -n -e "$(pad_string "${app_name} (mobile)")"
  401. echo -n -e "$(pad_string "${icann_address}")"
  402. echo "${onion_address}"
  403. fi
  404. fi
  405. done
  406. if grep -q "rss reader domain" "$COMPLETION_FILE"; then
  407. if [ -d /var/lib/tor/hidden_service_ttrss ]; then
  408. echo -n -e "$(pad_string 'RSS reader')"
  409. RSSDOM='-'
  410. echo -n -e "$(pad_string ${RSSDOM})"
  411. echo -n "$(cat /var/lib/tor/hidden_service_ttrss/hostname)"
  412. echo ''
  413. fi
  414. if [ -d /var/lib/tor/hidden_service_mobilerss ]; then
  415. echo -n -e "$(pad_string 'RSS mobile')"
  416. RSSMOBILEDOM='-'
  417. echo -n -e "$(pad_string ${RSSMOBILEDOM})"
  418. echo -n "$(cat /var/lib/tor/hidden_service_mobilerss/hostname)"
  419. echo ''
  420. fi
  421. fi
  422. echo ''
  423. }
  424. function show_users {
  425. echo 'Users'
  426. echo '====='
  427. echo ''
  428. echo -n -e "$(pad_string 'Name')"
  429. echo -n -e "$(pad_string 'Data')"
  430. echo ''
  431. echo '----------------------------------'
  432. for d in /home/*/ ; do
  433. USRNAME=$(echo "$d" | awk -F '/' '{print $3}')
  434. if [[ $(is_valid_user "$USRNAME") == "1" ]]; then
  435. echo -n -e "$(pad_string "${USRNAME}")"
  436. # size of the home directory
  437. du -s -h "/home/${USRNAME}" | awk -F ' ' '{print $1}'
  438. fi
  439. done
  440. echo ''
  441. }
  442. function show_tahoelafs {
  443. if [ ! -f /home/tahoelafs/storage/private/storage.furl ]; then
  444. return
  445. fi
  446. echo 'Tahoe-LAFS Storage Node'
  447. echo '======================='
  448. echo ''
  449. echo "Hostname: $(get_tahoelafs_storage_hostname)"
  450. echo "Public key: $(get_tahoelafs_public_key)"
  451. echo "Nickname: $(get_tahoelafs_nick)"
  452. echo "FURL: $(get_tahoelafs_furl)"
  453. echo ''
  454. }
  455. function show_ip_addresses {
  456. echo $'IP/DNS addresses'
  457. echo '================'
  458. echo ''
  459. echo -n "IPv4: $(get_ipv4_address)/$(get_external_ipv4_address)"
  460. ipv6_address="$(get_ipv6_address)"
  461. if [ ${#ipv6_address} -gt 0 ]; then
  462. echo " IPv6: ${ipv6_address}"
  463. fi
  464. echo ''
  465. echo ''
  466. }
  467. function show_tor_bridges {
  468. bridges_list=$(grep "Bridge " /etc/tor/torrc | grep -v '##')
  469. if [ ${#bridges_list} -gt 0 ]; then
  470. echo $'Tor Bridges'
  471. echo '==========='
  472. echo ''
  473. echo "${bridges_list}"
  474. echo ''
  475. echo ''
  476. fi
  477. if ! grep -q "#BridgeRelay" /etc/tor/torrc; then
  478. if grep -q "BridgeRelay 1" /etc/tor/torrc; then
  479. read_config_param 'TOR_BRIDGE_PORT'
  480. read_config_param 'TOR_BRIDGE_NICKNAME'
  481. if [ ${#TOR_BRIDGE_NICKNAME} -gt 0 ]; then
  482. echo "Tor bridge on this system"
  483. echo '========================='
  484. echo ''
  485. echo "IP Address: $(get_ipv4_address)"
  486. echo "Port: ${TOR_BRIDGE_PORT}"
  487. echo "Nickname: ${TOR_BRIDGE_NICKNAME}"
  488. echo ''
  489. echo ''
  490. fi
  491. fi
  492. fi
  493. }
  494. function show_ssh_public_key {
  495. echo $'SSH Public Keys'
  496. echo '==============='
  497. echo ''
  498. get_ssh_server_key
  499. echo ''
  500. echo ''
  501. }
  502. function show_tahoelafs_introducer {
  503. INTRODUCER_FILENAME=/home/tahoelafs/data/private/introducer.furl
  504. if [ ! -f $INTRODUCER_FILENAME ]; then
  505. return
  506. fi
  507. echo $'Tahoe-LAFS introducer'
  508. echo '====================='
  509. echo ''
  510. cat $INTRODUCER_FILENAME
  511. echo ''
  512. echo ''
  513. }
  514. function show_about {
  515. detect_apps
  516. get_apps_installed_names
  517. clear
  518. echo "==== ${PROJECT_NAME} version ${VERSION} ($DEBIAN_VERSION) ===="
  519. echo ''
  520. show_ip_addresses
  521. show_tor_bridges
  522. show_ssh_public_key
  523. show_domains
  524. show_tahoelafs
  525. show_users
  526. any_key
  527. }
  528. function select_user {
  529. SELECTED_USERNAME=
  530. # shellcheck disable=SC2207
  531. users_array=($(ls /home))
  532. delete=(git)
  533. # shellcheck disable=SC2068
  534. for del in ${delete[@]}
  535. do
  536. # shellcheck disable=SC2206
  537. users_array=(${users_array[@]/$del})
  538. done
  539. i=0
  540. W=()
  541. name=()
  542. # shellcheck disable=SC2068
  543. for u in ${users_array[@]}
  544. do
  545. if [[ $(is_valid_user "$u") == "1" ]]; then
  546. i=$((i+1))
  547. W+=("$i" "$u")
  548. name+=("$u")
  549. fi
  550. done
  551. if [ $i -eq 1 ]; then
  552. SELECTED_USERNAME="${name[0]}"
  553. else
  554. user_index=$(dialog --backtitle $"Freedombone Control Panel" --title $"Select User" --menu $"Select one of the following:" 24 40 17 "${W[@]}" 3>&2 2>&1 1>&3)
  555. # shellcheck disable=SC2181
  556. if [ $? -eq 0 ]; then
  557. SELECTED_USERNAME="${name[$((user_index-1))]}"
  558. fi
  559. fi
  560. }
  561. function delete_user {
  562. select_user
  563. if [ ! "$SELECTED_USERNAME" ]; then
  564. return
  565. fi
  566. if grep -Fxq "Admin user:$SELECTED_USERNAME" "$COMPLETION_FILE"; then
  567. dialog --title $"Administrator user" \
  568. --msgbox $"You can't delete the administrator user" 6 40
  569. return
  570. fi
  571. clear
  572. "${PROJECT_NAME}-rmuser" "$SELECTED_USERNAME"
  573. any_key
  574. }
  575. function configure_remote_backups {
  576. if ! grep -Fxq "Admin user:$ADMIN_USER" "$COMPLETION_FILE"; then
  577. dialog --title $"Administrator user" \
  578. --msgbox $"No Administrator user found. Check $COMPLETION_FILE" 6 40
  579. return
  580. fi
  581. if [ ${#ADMIN_USER} -lt 2 ]; then
  582. dialog --title $"Administrator user" \
  583. --msgbox $"Username not found" 6 40
  584. return
  585. fi
  586. if [ ! -d "/home/$ADMIN_USER" ]; then
  587. dialog --title $"Administrator user" \
  588. --msgbox $"Home directory not found" 6 40
  589. return
  590. fi
  591. if ! "${PROJECT_NAME}-remote" -u "$ADMIN_USER"; then
  592. any_key
  593. fi
  594. }
  595. function change_password {
  596. select_user
  597. if [ ! "$SELECTED_USERNAME" ]; then
  598. return
  599. fi
  600. dialog --title $"Change password" \
  601. --passwordbox $"New password for user $SELECTED_USERNAME" 8 40 2> "$data"
  602. newpassword=$(<"$data")
  603. rm -f "$data"
  604. if [ "${#newpassword}" -lt "${MINIMUM_PASSWORD_LENGTH}" ]; then
  605. dialog --title $"Change password" \
  606. --msgbox $"The password should be ${MINIMUM_PASSWORD_LENGTH} or more characters" 6 40
  607. return
  608. fi
  609. echo "$SELECTED_USERNAME:$newpassword"|chpasswd
  610. dialog --title $"Change password" \
  611. --msgbox $"Password for $SELECTED_USERNAME was changed" 6 40
  612. }
  613. function change_ssh_public_key {
  614. select_user
  615. if [ ! "$SELECTED_USERNAME" ]; then
  616. return
  617. fi
  618. if grep -Fxq "Admin user:$SELECTED_USERNAME" "$COMPLETION_FILE"; then
  619. dialog --title $"Change ssh public key" \
  620. --backtitle $"Freedombone Control Panel" \
  621. --defaultno \
  622. --yesno $"\\nThis is the administrator user.\\n\\nAre you sure you want to change the ssh public key for the administrator?" 10 60
  623. sel=$?
  624. case $sel in
  625. 1) return;;
  626. 255) return;;
  627. esac
  628. fi
  629. data=$(mktemp 2>/dev/null)
  630. dialog --title $"Change ssh public key for $SELECTED_USERNAME" \
  631. --backtitle $"Freedombone Control Panel" \
  632. --inputbox $"Paste the ssh public key below" 8 60 2>"$data"
  633. sel=$?
  634. case $sel in
  635. 0)
  636. SSH_PUBLIC_KEY=$(<"$data")
  637. if [ "$SSH_PUBLIC_KEY" ]; then
  638. if [ ${#SSH_PUBLIC_KEY} -gt 5 ]; then
  639. if [ -f "$SSH_PUBLIC_KEY" ]; then
  640. if [ ! -d "/home/$SELECTED_USERNAME/.ssh" ]; then
  641. mkdir "/home/$SELECTED_USERNAME/.ssh"
  642. fi
  643. cp "$SSH_PUBLIC_KEY" \
  644. "/home/$SELECTED_USERNAME/.ssh/authorized_keys"
  645. chown -R "$SELECTED_USERNAME":"$SELECTED_USERNAME" \
  646. "/home/$SELECTED_USERNAME/.ssh"
  647. dialog --title $"Change ssh public key" \
  648. --msgbox $"ssh public key was installed" 6 40
  649. else
  650. if [[ "$SSH_PUBLIC_KEY" == "ssh-"* ]]; then
  651. if [ ! -d "/home/$SELECTED_USERNAME/.ssh" ]; then
  652. mkdir "/home/$SELECTED_USERNAME/.ssh"
  653. fi
  654. echo "$SSH_PUBLIC_KEY" > \
  655. "/home/$SELECTED_USERNAME/.ssh/authorized_keys"
  656. chown -R "$SELECTED_USERNAME":"$SELECTED_USERNAME" \
  657. "/home/$SELECTED_USERNAME/.ssh"
  658. dialog --title $"Change ssh public key" \
  659. --msgbox $"ssh public key was installed" 6 40
  660. fi
  661. fi
  662. fi
  663. fi
  664. ;;
  665. esac
  666. rm -f "$data"
  667. }
  668. function remove_user_from_mailing_list {
  669. select_user
  670. if [ ! "$SELECTED_USERNAME" ]; then
  671. return
  672. fi
  673. USER_MAILING_LISTS=$(grep '\[' "/home/$SELECTED_USERNAME/.procmailrc" | grep '\]' | awk -F '\[' '{print $2}' | awk -F '\\' '{print $1}')
  674. i=0
  675. W=()
  676. list_name=()
  677. while read -r listname; do
  678. i=$((i+1))
  679. W+=("$i" "$listname")
  680. list_name+=("$listname")
  681. echo "$listname"
  682. done <<< "$USER_MAILING_LISTS"
  683. i=$((i+1))
  684. W+=("$i" $"Exit back to user mainenance")
  685. list_selected=$(dialog --default-item "$i" --backtitle $"Freedombone Control Panel" --title $"Remove a mailing list for $SELECTED_USERNAME" --menu $"Select one of the following:" 24 50 17 "${W[@]}" 3>&2 2>&1 1>&3)
  686. # shellcheck disable=SC2181
  687. if [ $? -eq 0 ]; then # Exit with OK
  688. if [ "${list_selected}" -ne "${i}" ]; then
  689. remove_list_name="${list_name[$((list_selected-1))]}"
  690. # find the line number where the list is defined
  691. line_number=0
  692. i=0
  693. while read -r line
  694. do
  695. if [[ "$line" == *"\\[${remove_list_name}\\]"* ]]; then
  696. line_number=${i}
  697. fi
  698. i=$((i+1))
  699. done < "/home/$SELECTED_USERNAME/.procmailrc"
  700. if [ ${line_number} -eq 0 ]; then
  701. # no match was found
  702. return
  703. fi
  704. # recreate the file
  705. if [ -f "/home/${SELECTED_USERNAME}/.procmailrc_new" ]; then
  706. rm "/home/${SELECTED_USERNAME}/.procmailrc_new"
  707. fi
  708. i=0
  709. clip=0
  710. while read -r line
  711. do
  712. i=$((i+1))
  713. if [ ${i} -gt $((line_number-1)) ]; then
  714. if [ ${clip} -eq 0 ]; then
  715. clip=1
  716. fi
  717. if [ ${clip} -eq 1 ]; then
  718. if [ ${i} -lt $((line_number+2)) ]; then
  719. continue
  720. else
  721. if [ ${#line} -lt 1 ]; then
  722. clip=2
  723. continue
  724. fi
  725. if [[ "$line" == ":"* || "$line" == "#"* ]]; then
  726. clip=2
  727. else
  728. continue
  729. fi
  730. fi
  731. fi
  732. fi
  733. echo "$line" >> "/home/${SELECTED_USERNAME}/.procmailrc_new"
  734. if [[ "$line" == *"\\[${remove_list_name}\\]"* ]]; then
  735. line_number=${i}
  736. fi
  737. done < "/home/$SELECTED_USERNAME/.procmailrc"
  738. cp "/home/${SELECTED_USERNAME}/.procmailrc_new" "/home/${SELECTED_USERNAME}/.procmailrc"
  739. rm "/home/${SELECTED_USERNAME}/.procmailrc_new"
  740. chown "${SELECTED_USERNAME}":"${SELECTED_USERNAME}" "/home/${SELECTED_USERNAME}/.procmailrc"
  741. dialog --title $"Remove user from mailing list" \
  742. --msgbox $"${SELECTED_USERNAME} has been removed from ${remove_list_name}" 6 50
  743. fi
  744. fi
  745. }
  746. function add_to_mailing_list {
  747. select_user
  748. if [ ! "$SELECTED_USERNAME" ]; then
  749. return
  750. fi
  751. data=$(mktemp 2>/dev/null)
  752. dialog --backtitle $"Freedombone Control Panel" \
  753. --title $"Subscribe $SELECTED_USERNAME to a mailing list" \
  754. --form $"You can either enter a subject or an email address\\n" 11 68 4 \
  755. $"List folder name:" 1 1 "" 1 35 26 25 \
  756. $"Name between [] on subject line:" 2 1 "" 2 35 26 25 \
  757. $"List email address:" 3 1 "" 3 35 26 25 \
  758. $"Public:" 4 1 $"yes" 4 35 4 25 \
  759. 2> "$data"
  760. sel=$?
  761. case $sel in
  762. 1) rm -f "$data"
  763. return;;
  764. 255) rm -f "$data"
  765. return;;
  766. esac
  767. LIST_NAME=$(sed -n 1p < "$data")
  768. LIST_SUBJECT=$(sed -n 2p < "$data")
  769. LIST_EMAIL=$(sed -n 3p < "$data")
  770. LIST_PUBLIC=$(sed -n 4p < "$data")
  771. if [ ${#LIST_PUBLIC} -lt 1 ]; then
  772. LIST_PUBLIC='no'
  773. fi
  774. if [[ $LIST_PUBLIC == $'y' || $LIST_PUBLIC == $'Y' || $LIST_PUBLIC == $'true' || $LIST_PUBLIC == $'True' || $LIST_PUBLIC == $'yes' || $LIST_PUBLIC == $'Yes' || $LIST_PUBLIC == $'YES' ]]; then
  775. LIST_PUBLIC='yes'
  776. else
  777. LIST_PUBLIC='no'
  778. fi
  779. if [ ${#LIST_NAME} -lt 2 ]; then
  780. dialog --title $"Add mailing list" \
  781. --msgbox $"No mailing list name was given" 6 40
  782. rm -f "$data"
  783. return
  784. fi
  785. if [ ${#LIST_SUBJECT} -lt 2 ]; then
  786. if [ ${#LIST_EMAIL} -lt 2 ]; then
  787. dialog --title $"Add mailing list" \
  788. --msgbox $"No mailing list subject or address was given" 6 40
  789. rm -f "$data"
  790. return
  791. fi
  792. fi
  793. if [ ${#LIST_SUBJECT} -gt 1 ]; then
  794. "${PROJECT_NAME}-addlist" -u "$SELECTED_USERNAME" -l "$LIST_NAME" \
  795. -s "$LIST_SUBJECT" --public "$LIST_PUBLIC"
  796. else
  797. if [[ "$LIST_EMAIL" != *"@"* || "$LIST_EMAIL" != *"."* ]]; then
  798. dialog --title $"Add mailing list" \
  799. --msgbox $"Unrecognised email address" 6 40
  800. rm -f "$data"
  801. return
  802. else
  803. "${PROJECT_NAME}-addlist" -u "$SELECTED_USERNAME" -l "$LIST_NAME" \
  804. -e "$LIST_EMAIL" --public "$LIST_PUBLIC"
  805. fi
  806. fi
  807. dialog --title $"Add mailing list" \
  808. --msgbox $"$LIST_NAME list was added" 6 40
  809. rm -f "$data"
  810. }
  811. function email_rule {
  812. select_user
  813. if [ ! "$SELECTED_USERNAME" ]; then
  814. return
  815. fi
  816. data=$(mktemp 2>/dev/null)
  817. dialog --backtitle $"Freedombone Control Panel" \
  818. --title $"Email rule for user $SELECTED_USERNAME" \
  819. --form "\\n" 9 65 4 \
  820. $"When email arrives from address:" 1 1 "" 1 35 24 28 \
  821. $"Move to folder:" 2 1 "" 2 35 24 28 \
  822. $"Public:" 3 1 $"no" 3 35 4 25 \
  823. 2> "$data"
  824. sel=$?
  825. case $sel in
  826. 1) rm -f "$data"
  827. return;;
  828. 255) rm -f "$data"
  829. return;;
  830. esac
  831. RULE_EMAIL=$(sed -n 1p < "$data")
  832. RULE_FOLDER=$(sed -n 2p < "$data")
  833. RULE_PUBLIC=$(sed -n 3p < "$data")
  834. if [ ${#RULE_PUBLIC} -lt 1 ]; then
  835. RULE_PUBLIC='no'
  836. fi
  837. if [[ $RULE_PUBLIC == $'y' || $RULE_PUBLIC == $'Y' || $RULE_PUBLIC == $'true' || $RULE_PUBLIC == $'True' || $RULE_PUBLIC == $'yes' || $RULE_PUBLIC == $'Yes' || $RULE_PUBLIC == $'YES' ]]; then
  838. RULE_PUBLIC='yes'
  839. else
  840. RULE_PUBLIC='no'
  841. fi
  842. if [ ${#RULE_EMAIL} -lt 2 ]; then
  843. dialog --title $"Add email rule" \
  844. --msgbox $"No email address was given" 6 40
  845. rm -f "$data"
  846. return
  847. fi
  848. if [ ${#RULE_FOLDER} -lt 2 ]; then
  849. dialog --title $"Add email rule" \
  850. --msgbox $"No folder name was given" 6 40
  851. rm -f "$data"
  852. return
  853. fi
  854. if [[ "$RULE_EMAIL" != *"@"* || "$RULE_EMAIL" != *"."* ]]; then
  855. dialog --title $"Add email rule" \
  856. --msgbox $"Unrecognised email address" 6 40
  857. rm -f "$data"
  858. return
  859. fi
  860. "${PROJECT_NAME}-addemail" -u "$SELECTED_USERNAME" -e "$RULE_EMAIL" \
  861. -g "$RULE_FOLDER" --public $RULE_PUBLIC
  862. dialog --title $"Add email rule" \
  863. --msgbox $"Email rule for $RULE_EMAIL was added" 6 40
  864. rm -f "$data"
  865. }
  866. function block_unblock_email {
  867. select_user
  868. if [ ! "$SELECTED_USERNAME" ]; then
  869. return
  870. fi
  871. blockstr=$"Block/Unblock email going to"
  872. data=$(mktemp 2>/dev/null)
  873. dialog --backtitle $"Freedombone Control Panel" \
  874. --title "$blockstr $SELECTED_USERNAME" \
  875. --form "\\n" 8 65 3 \
  876. $"When email arrives from address:" 1 1 "" 1 35 24 100 \
  877. $"Block it:" 2 1 "yes" 2 35 4 4 \
  878. 2> "$data"
  879. sel=$?
  880. case $sel in
  881. 1) rm -f "$data"
  882. return;;
  883. 255) rm -f "$data"
  884. return;;
  885. esac
  886. BLOCK_EMAIL=$(sed -n 1p < "$data")
  887. BLOCK=$(sed -n 2p < "$data")
  888. rm -f "$data"
  889. if [ ${#BLOCK_EMAIL} -lt 2 ]; then
  890. dialog --title $"Block/Unblock an email" \
  891. --msgbox $"No email address was given" 6 40
  892. return
  893. fi
  894. if [[ "$BLOCK_EMAIL" != *"@"* || "$BLOCK_EMAIL" != *"."* ]]; then
  895. dialog --title $"Block/Unblock an email" \
  896. --msgbox $"Unrecognised email address" 6 40
  897. return
  898. fi
  899. if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
  900. "${PROJECT_NAME}-ignore" -u "$SELECTED_USERNAME" -e "$BLOCK_EMAIL"
  901. dialog --title $"Block an email" \
  902. --msgbox "Email from $BLOCK_EMAIL to $SELECTED_USERNAME blocked" 6 75
  903. else
  904. "${PROJECT_NAME}-unignore" -u "$SELECTED_USERNAME" -e "$BLOCK_EMAIL"
  905. dialog --title $"Unblock an email" \
  906. --msgbox "Email from $BLOCK_EMAIL to $SELECTED_USERNAME unblocked" 6 75
  907. fi
  908. }
  909. function block_unblock_subject {
  910. select_user
  911. if [ ! "$SELECTED_USERNAME" ]; then
  912. return
  913. fi
  914. blockstr=$"Block/Unblock email going to"
  915. data=$(mktemp 2>/dev/null)
  916. dialog --backtitle $"Freedombone Control Panel" \
  917. --title "$blockstr $SELECTED_USERNAME" \
  918. --form "\\n" 8 70 3 \
  919. $"When email arrives with subject text:" 1 1 "" 1 40 24 28 \
  920. $"Block it:" 2 1 "yes" 2 40 4 4 \
  921. 2> "$data"
  922. sel=$?
  923. case $sel in
  924. 1) rm -f "$data"
  925. return;;
  926. 255) rm -f "$data"
  927. return;;
  928. esac
  929. BLOCK_SUBJECT=$(sed -n 1p < "$data")
  930. BLOCK=$(sed -n 2p < "$data")
  931. rm -f "$data"
  932. if [ ${#BLOCK_SUBJECT} -lt 2 ]; then
  933. dialog --title $"Block/Unblock an email" \
  934. --msgbox $"No subject was given" 6 40
  935. return
  936. fi
  937. if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
  938. "${PROJECT_NAME}-ignore" -u "$SELECTED_USERNAME" -t "$BLOCK_SUBJECT"
  939. dialog --title $"Block an email" \
  940. --msgbox "Email with subject $BLOCK_SUBJECT to $SELECTED_USERNAME blocked" 6 40
  941. else
  942. "${PROJECT_NAME}-unignore" -u "$SELECTED_USERNAME" -t "$BLOCK_SUBJECT"
  943. dialog --title $"Unblock an email" \
  944. --msgbox "Email with subject $BLOCK_SUBJECT to $SELECTED_USERNAME unblocked" 6 40
  945. fi
  946. }
  947. function create_keydrive_master {
  948. select_user
  949. if [ ! "$SELECTED_USERNAME" ]; then
  950. return
  951. fi
  952. dialog --title $"USB Master Keydrive" \
  953. --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
  954. clear
  955. detect_usb_drive
  956. "${PROJECT_NAME}-keydrive" -u "$SELECTED_USERNAME" --master 'yes' -d "$USB_DRIVE"
  957. any_key
  958. }
  959. function create_keydrive_fragment {
  960. select_user
  961. if [ ! "$SELECTED_USERNAME" ]; then
  962. return
  963. fi
  964. dialog --title $"USB Fragment Keydrive" \
  965. --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
  966. clear
  967. detect_usb_drive
  968. "${PROJECT_NAME}-keydrive" -u "$SELECTED_USERNAME" -d "$USB_DRIVE"
  969. any_key
  970. }
  971. function backup_data {
  972. dialog --title $"Backup data to USB" \
  973. --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
  974. clear
  975. detect_usb_drive
  976. echo ''
  977. echo $"Detected USB drive $USB_DRIVE"
  978. echo ''
  979. echo $'Enter the passphrase for your LUKS encrypted backup drive:'
  980. "${PROJECT_NAME}-backup-local"
  981. any_key
  982. }
  983. function restore_data_from_storage {
  984. restore_type="$1"
  985. AllStr=$"all"
  986. ExitStr=$"Exit"
  987. RestoreStr=$"Restore apps"
  988. if [[ $restore_type != "local" ]]; then
  989. restore_command="${PROJECT_NAME}-restore-remote $remote_domain_name configuration;;"
  990. else
  991. remote_domain_name="$1"
  992. detect_usb_drive
  993. restore_command="${PROJECT_NAME}-restore-local $USB_DRIVE"
  994. RestoreStr=$"Restore apps from USB drive $USB_DRIVE"
  995. fi
  996. utils_installed=(configfiles
  997. blocklist
  998. mariadb
  999. postgresql
  1000. letsencrypt
  1001. passwords
  1002. mutt
  1003. gpg
  1004. procmail
  1005. spamassassin
  1006. readme
  1007. ssh
  1008. userconfig
  1009. userlocal
  1010. userfin
  1011. certs
  1012. personal
  1013. email)
  1014. detect_apps
  1015. while true
  1016. do
  1017. app_list=()
  1018. n=1
  1019. applist="$n $AllStr off"
  1020. n=$((n+1))
  1021. app_list+=("$AllStr")
  1022. util_index=0
  1023. for a in "${utils_installed[@]}"
  1024. do
  1025. applist="$applist $n $a off"
  1026. app_name=${utils_installed[util_index]}
  1027. n=$((n+1))
  1028. util_index=$((util_index+1))
  1029. app_list+=("$app_name")
  1030. done
  1031. app_index=0
  1032. for a in "${APPS_INSTALLED_NAMES[@]}"
  1033. do
  1034. applist="$applist $n $a off"
  1035. n=$((n+1))
  1036. app_name=${APPS_INSTALLED_NAMES[app_index]}
  1037. app_index=$((app_index+1))
  1038. app_list+=("$app_name")
  1039. done
  1040. applist="$applist $n $ExitStr on"
  1041. n=$((n+1))
  1042. app_list+=("$ExitStr")
  1043. choice=$(dialog --stdout --backtitle $"Freedombone" \
  1044. --title "$RestoreStr" \
  1045. --radiolist $'Choose:' \
  1046. 30 50 20 "$applist")
  1047. # shellcheck disable=SC2181
  1048. if [ $? -ne 0 ]; then
  1049. break
  1050. fi
  1051. app_index=$((choice-1))
  1052. app_name=${app_list[app_index]}
  1053. # exit
  1054. if [[ "$app_name" == "$ExitStr" ]]; then
  1055. break
  1056. fi
  1057. clear
  1058. # Restore all
  1059. if [[ "$app_name" == "$AllStr" ]]; then
  1060. $restore_command
  1061. retcode="$?"
  1062. if [[ "$retcode" != "0" ]]; then
  1063. any_key
  1064. if [[ "$1" == "local" ]]; then
  1065. dialog --title $"Restore all apps from USB" \
  1066. --msgbox $"Restore failed with code $retcode" 6 60
  1067. else
  1068. dialog --title $"Restore all apps from $1" \
  1069. --msgbox $"Restore failed with code $retcode" 6 60
  1070. fi
  1071. break
  1072. fi
  1073. if [[ "$1" == "local" ]]; then
  1074. dialog --title $"Restore all apps from USB" \
  1075. --msgbox $"Restore complete" 6 40
  1076. else
  1077. dialog --title $"Restore all apps from $1" \
  1078. --msgbox $"Restore complete" 6 40
  1079. fi
  1080. break
  1081. fi
  1082. # Restore an app
  1083. $restore_command "${app_name}"
  1084. retcode="$?"
  1085. if [[ "$retcode" != "0" ]]; then
  1086. any_key
  1087. dialog --title $"Restore apps from USB" \
  1088. --msgbox $"Restore of ${app_name} failed with code $retcode" 6 60
  1089. return
  1090. fi
  1091. # finished
  1092. if [[ "$1" == "local" ]]; then
  1093. dialog --title $"Restore apps from USB" \
  1094. --msgbox $"Restore complete" 6 40
  1095. else
  1096. dialog --title $"Restore apps from $1" \
  1097. --msgbox $"Restore complete" 6 40
  1098. fi
  1099. done
  1100. }
  1101. function restore_data {
  1102. dialog --title $"Restore data from USB" \
  1103. --msgbox $"Plug in your backup USB drive" 6 40
  1104. clear
  1105. echo ' '
  1106. echo $'Enter the passphrase for your LUKS encrypted backup drive:'
  1107. restore_data_from_storage local
  1108. }
  1109. function restore_data_remote {
  1110. if [ ! $ADMIN_USER ]; then
  1111. dialog --title $"Restore data from remote server" \
  1112. --msgbox $"Unknown admin user" 6 40
  1113. return
  1114. fi
  1115. data=$(mktemp 2>/dev/null)
  1116. dialog --title $"Restore from remote server" \
  1117. --backtitle $"Freedombone Control Panel" \
  1118. --inputbox $"Enter the domain name of the server from which you wish to restore" 8 60 2>"$data"
  1119. sel=$?
  1120. case $sel in
  1121. 0)
  1122. friend_server_domain_name=$(<"$data")
  1123. if [ ${#friend_server_domain_name} -lt 2 ]; then
  1124. rm -f "$data"
  1125. return
  1126. fi
  1127. if [[ $friend_server_domain_name != *"."* ]]; then
  1128. dialog --title $"Remote server domain name" \
  1129. --msgbox $"Invalid domain name" 6 40
  1130. rm -f "$data"
  1131. return
  1132. fi
  1133. restore_data_from_storage "$friend_server_domain_name"
  1134. ;;
  1135. esac
  1136. rm -f "$data"
  1137. }
  1138. function ping_enable_disable {
  1139. ping_str=$"\\nDo you want to enable other systems to ping this machine?\\n\\nPing may be useful for diagnostic purposes, but for added security you may not want to enable it."
  1140. enable_ping="no"
  1141. dialog --title $"Enable Ping / ICMP" \
  1142. --backtitle $"Freedombone Control Panel" \
  1143. --defaultno \
  1144. --yesno "$ping_str" 10 60
  1145. sel=$?
  1146. case $sel in
  1147. 0) enable_ping="yes";;
  1148. 255) return;;
  1149. esac
  1150. if [[ $enable_ping == "yes" ]]; then
  1151. iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
  1152. iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
  1153. echo "0" > /proc/sys/net/ipv4/icmp_echo_ignore_all
  1154. else
  1155. iptables -D INPUT -p icmp --icmp-type echo-request -j ACCEPT
  1156. iptables -D OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
  1157. echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_all
  1158. fi
  1159. }
  1160. function logging_on_off {
  1161. logging="no"
  1162. dialog --title $"Logging" \
  1163. --backtitle $"Freedombone Control Panel" \
  1164. --defaultno \
  1165. --yesno $"\\nDo you want to turn logging on?" 7 60
  1166. sel=$?
  1167. case $sel in
  1168. 0) logging="yes";;
  1169. 255) return;;
  1170. esac
  1171. clear
  1172. echo ''
  1173. echo $'This may take a few seconds. Please wait...'
  1174. if [[ $logging == "no" ]]; then
  1175. ${PROJECT_NAME}-logging off
  1176. else
  1177. ${PROJECT_NAME}-logging on
  1178. fi
  1179. }
  1180. function restore_gpg_key {
  1181. select_user
  1182. if [ ! "$SELECTED_USERNAME" ]; then
  1183. return
  1184. fi
  1185. restorestr=$"Restore GPG key for user"
  1186. dialog --title "$restorestr $SELECTED_USERNAME" \
  1187. --msgbox $"Plug in your USB keydrive" 6 40
  1188. clear
  1189. "${PROJECT_NAME}-recoverkey" -u "$SELECTED_USERNAME"
  1190. any_key
  1191. }
  1192. function security_settings {
  1193. "${PROJECT_NAME}-sec"
  1194. any_key
  1195. }
  1196. function show_tripwire_verification_code {
  1197. if [ ! -f "/var/lib/tripwire/${HOSTNAME}.twd" ]; then
  1198. return
  1199. fi
  1200. clear
  1201. echo ''
  1202. echo $'Tripwire Verification Code'
  1203. echo ''
  1204. DBHASH=$(sha512sum "/var/lib/tripwire/${HOSTNAME}.twd")
  1205. echo -n "$DBHASH" | qrencode -t UTF8
  1206. echo ''
  1207. echo "$DBHASH"
  1208. echo ''
  1209. }
  1210. function reset_tripwire {
  1211. if [ ! -f /usr/bin/reset-tripwire ]; then
  1212. echo $'Missing /usr/bin/reset-tripwire'
  1213. any_key
  1214. return
  1215. fi
  1216. if [ ! -f "/etc/tripwire/${HOSTNAME}-local.key" ]; then
  1217. if [ -f "/etc/tripwire/${PROJECT_NAME}-local.key" ]; then
  1218. mv "/etc/tripwire/${PROJECT_NAME}-local.key" "/etc/tripwire/${HOSTNAME}-local.key"
  1219. mv "/etc/tripwire/${PROJECT_NAME}-site.key" "/etc/tripwire/${HOSTNAME}-site.key"
  1220. else
  1221. echo $'Error: missing local key'
  1222. any_key
  1223. return
  1224. fi
  1225. fi
  1226. clear
  1227. echo $'Turing off logging...'
  1228. "${PROJECT_NAME}-logging" off
  1229. echo $'Locking down permissions...'
  1230. lockdown_permissions
  1231. echo $'Creating configuration...'
  1232. echo '
  1233. ' | twadmin --create-cfgfile -S "/etc/tripwire/${HOSTNAME}-site.key" /etc/tripwire/twcfg.txt
  1234. echo $'Resetting policy...'
  1235. echo '
  1236. ' | twadmin --create-polfile -S "/etc/tripwire/${HOSTNAME}-site.key" /etc/tripwire/twpol.txt
  1237. echo $'Creating tripwire database'
  1238. echo '
  1239. ' | tripwire --init --cfgfile /etc/tripwire/tw.cfg --polfile /etc/tripwire/tw.pol --dbfile "/var/lib/tripwire/${HOSTNAME}.twd"
  1240. echo $'Resetting the Tripwire...'
  1241. echo ''
  1242. echo '
  1243. ' | reset-tripwire
  1244. echo ''
  1245. # Sometimes nginx fails to restart if matrix is installed
  1246. # Restart matrix first
  1247. if [ -d /etc/matrix ]; then
  1248. systemctl restart matrix
  1249. systemctl restart nginx
  1250. fi
  1251. if [ -f "/var/lib/tripwire/${HOSTNAME}.twd" ]; then
  1252. show_tripwire_verification_code
  1253. echo $'Tripwire is now reset. Take a note of the above hash, or record'
  1254. echo $'the QR code using a mobile device. This will enable you to independently'
  1255. echo $'verify the integrity of the tripwire.'
  1256. else
  1257. echo $'ERROR: tripwire database was not created'
  1258. fi
  1259. any_key
  1260. }
  1261. function format_drive {
  1262. detect_usb_drive
  1263. dialog --title $"Format USB drive $USB_DRIVE" \
  1264. --backtitle $"Freedombone Control Panel" \
  1265. --defaultno \
  1266. --yesno $"\\nPlease confirm that you wish to format drive\\n\\n ${USB_DRIVE}\\n\\nAll current data on the drive will be lost, and you will be prompted to give a password used to encrypt the drive.\\n\\nDANGER: If you screw up here and format the wrong drive it's your own fault!" 16 60
  1267. sel=$?
  1268. case $sel in
  1269. 1) return;;
  1270. 255) return;;
  1271. esac
  1272. clear
  1273. echo ''
  1274. echo $"Formatting drive $USB_DRIVE. ALL CONTENTS WILL BE LOST."
  1275. echo ''
  1276. "${PROJECT_NAME}-format" "$USB_DRIVE"
  1277. any_key
  1278. }
  1279. function remove_backups {
  1280. detect_usb_drive
  1281. # shellcheck disable=SC2154
  1282. dialog --title $"Remove backups from a USB drive $USB_DRIVE" \
  1283. --backtitle $"Freedombone Control Panel" \
  1284. --defaultno \
  1285. --yesno $"\\nPlease confirm that you wish to remove backups from this drive\\n\\n ${drive}\\n\\nYou will not be able to recover them afterwards." 12 60
  1286. sel=$?
  1287. case $sel in
  1288. 1) return;;
  1289. 255) return;;
  1290. esac
  1291. clear
  1292. "${PROJECT_NAME}-backup-local" "$USB_DRIVE" remove
  1293. any_key
  1294. }
  1295. function shut_down_system {
  1296. dialog --title $"Power off the system" \
  1297. --backtitle $"Freedombone Control Panel" \
  1298. --defaultno \
  1299. --yesno $"\\nPlease confirm that you wish to power off the system.\\n\\nWARNING: to power on again you will need to have physical access to the hardware." 10 60
  1300. sel=$?
  1301. case $sel in
  1302. 1) return;;
  1303. 255) return;;
  1304. esac
  1305. systemctl poweroff
  1306. }
  1307. function restart_system {
  1308. dialog --title $"Restart the system" \
  1309. --backtitle $"Freedombone Control Panel" \
  1310. --defaultno \
  1311. --yesno $"\\nPlease confirm that you wish to restart the system.\\n\\nWARNING: If you are using full disk encryption then you will need physical access to the hardware to type in the password" 10 60
  1312. sel=$?
  1313. case $sel in
  1314. 1) return;;
  1315. 255) return;;
  1316. esac
  1317. systemctl reboot -i
  1318. }
  1319. function change_system_name {
  1320. data=$(mktemp 2>/dev/null)
  1321. dialog --title $"Change the name of this system" \
  1322. --backtitle $"Freedombone Control Panel" \
  1323. --inputbox $'Enter a new name for this system on your local network\\n\\nIt will appear as newname.local' 10 60 2>"$data"
  1324. sel=$?
  1325. case $sel in
  1326. 0) NEW_SYSTEM_NAME=$(<"$data")
  1327. if [ "$NEW_SYSTEM_NAME" ]; then
  1328. if [ ${#NEW_SYSTEM_NAME} -gt 1 ]; then
  1329. sed -i "s|host-name=.*|host-name=$NEW_SYSTEM_NAME|g" /etc/avahi/avahi-daemon.conf
  1330. systemctl restart avahi-daemon
  1331. if grep -q "host-name=$NEW_SYSTEM_NAME" /etc/avahi/avahi-daemon.conf; then
  1332. dialog --title $"New local network name" \
  1333. --msgbox $"The name of this system on your local network was changed successfully" 6 70
  1334. fi
  1335. fi
  1336. fi
  1337. ;;
  1338. esac
  1339. rm -f "$data"
  1340. }
  1341. function set_dynamic_IP {
  1342. revert_to_dynamic=
  1343. dialog --title $"Return to using a dynamic IP address" \
  1344. --backtitle $"Freedombone Control Panel" \
  1345. --yesno $"\\nDo you wish to go back to using a dynamic IP address?" 8 60
  1346. sel=$?
  1347. case $sel in
  1348. 0) revert_to_dynamic=1
  1349. ;;
  1350. 1) return;;
  1351. esac
  1352. if [ $revert_to_dynamic ]; then
  1353. wifi_original_network_settings
  1354. clear
  1355. echo ''
  1356. echo $'Changing to a dynamic IP address.'
  1357. echo ''
  1358. echo $"System is rebooting. You may need to close this terminal and log in from a new one."
  1359. systemctl reboot -i
  1360. fi
  1361. }
  1362. function set_static_IP {
  1363. IPv4_address=$(get_ipv4_address)
  1364. IPv4_address_base=$(echo "$IPv4_address" | awk -F '.' '{print $1"."$2"."$3}')
  1365. STATIC_IP="${IPv4_address_base}.60"
  1366. STATIC_GATEWAY="${IPv4_address_base}.1"
  1367. NEW_STATIC_IP=
  1368. NEW_STATIC_GATEWAY=
  1369. if [ -f /etc/network/interfaces.d/static ]; then
  1370. STATIC_IP=$(grep "address " /etc/network/interfaces.d/static | head -n 1 | awk -F ' ' '{print $2}')
  1371. STATIC_GATEWAY=$(grep "gateway " /etc/network/interfaces.d/static | head -n 1 | awk -F ' ' '{print $2}')
  1372. fi
  1373. # get the IP for the box
  1374. data=$(mktemp 2>/dev/null)
  1375. dialog --title $"Set a static local IP address" \
  1376. --backtitle $"Freedombone Control Panel" \
  1377. --inputbox $"In order to forward incoming internet traffic to this system most internet routers need to know a static local IP address to send the data to.\\n\\n
  1378. Enter a static local IP address for this system.\\n\\nIt will typically be ${IPv4_address_base}.x\\n\\nIf you leave this field blank then the system will revert to using a dynamic IP address." 18 60 "$STATIC_IP" 2>"$data"
  1379. sel=$?
  1380. case $sel in
  1381. 0) NEW_STATIC_IP=$(<"$data")
  1382. if [[ "$NEW_STATIC_IP" != *"."* ]]; then
  1383. set_dynamic_IP
  1384. rm -f "$data"
  1385. return
  1386. fi
  1387. ;;
  1388. 1) rm -f "$data"
  1389. return;;
  1390. esac
  1391. rm -f "$data"
  1392. # get the gateway
  1393. data=$(mktemp 2>/dev/null)
  1394. dialog --title $"Set the IP address of your internet router/modem" \
  1395. --backtitle $"Freedombone Control Panel" \
  1396. --inputbox $"Set the local IP address for your internet router or ADSL modem.\\n\\nIt will typically be ${IPv4_address_base}.1, ${IPv4_address_base}.254, or similar" 12 60 "$STATIC_GATEWAY" 2>"$data"
  1397. sel=$?
  1398. case $sel in
  1399. 0) NEW_STATIC_GATEWAY=$(<"$data")
  1400. if [[ "$NEW_STATIC_GATEWAY" != *"."* ]]; then
  1401. rm -f "$data"
  1402. return
  1403. fi
  1404. ;;
  1405. 1) rm -f "$data"
  1406. return;;
  1407. esac
  1408. if [[ "$NEW_STATIC_GATEWAY" == *"."* && "$NEW_STATIC_IP" == *"."* ]]; then
  1409. ip_addresses_have_changed=1
  1410. if [ -f /etc/network/interfaces.d/static ]; then
  1411. ip_addresses_have_changed=
  1412. if ! grep -q "address ${NEW_STATIC_IP}" /etc/network/interfaces.d/static; then
  1413. ip_addresses_have_changed=1
  1414. fi
  1415. if ! grep -q "gateway ${NEW_STATIC_GATEWAY}" /etc/network/interfaces.d/static; then
  1416. ip_addresses_have_changed=1
  1417. fi
  1418. fi
  1419. if [ $ip_addresses_have_changed ]; then
  1420. write_config_param "NETWORK_IS_STATIC" "1"
  1421. write_config_param "LOCAL_NETWORK_STATIC_IP_ADDRESS" "$NEW_STATIC_IP"
  1422. write_config_param "ROUTER_IP_ADDRESS" "$NEW_STATIC_GATEWAY"
  1423. email_change_relay "$NEW_STATIC_IP"
  1424. static_wifi_address=
  1425. if [[ $(config_param_exists "WIFI_INTERFACE") == "1" ]]; then
  1426. dialog --title $"Static local IP address" \
  1427. --backtitle $"Freedombone Control Panel" \
  1428. --yesno $"\\nSet a static address for the wifi adapter?\\n\\nIf you select 'no' then wired ethernet will be used." 10 60
  1429. sel=$?
  1430. case $sel in
  1431. 0) static_wifi_address=1
  1432. write_config_param "NETWORK_IS_STATIC" "1"
  1433. ;;
  1434. esac
  1435. fi
  1436. echo '# This file describes the network interfaces available on your system' > /etc/network/interfaces
  1437. echo '# and how to activate them. For more information, see interfaces(5).' >> /etc/network/interfaces
  1438. echo 'source /etc/network/interfaces.d/*' >> /etc/network/interfaces
  1439. if [ ! $static_wifi_address ]; then
  1440. # wired network
  1441. remove_wifi_startup_script
  1442. { echo 'auto eth0';
  1443. echo 'iface eth0 inet static';
  1444. echo " address ${NEW_STATIC_IP}";
  1445. echo ' netmask 255.255.255.0';
  1446. echo " gateway ${NEW_STATIC_GATEWAY}"; } >> /etc/network/interfaces.d/static
  1447. else
  1448. # wifi network
  1449. wifi_settings
  1450. fi
  1451. clear
  1452. echo ''
  1453. echo $'Restarting the network daemon.'
  1454. echo ''
  1455. echo $'If you logged in using the previous IP address then you may need to close this terminal and log in again on the new one.'
  1456. function_check pihole_change_ipv4
  1457. pihole_change_ipv4 "${NEW_STATIC_IP}"
  1458. dialog --title $"Static local IP address" \
  1459. --backtitle $"Freedombone Control Panel" \
  1460. --yesno $"\\nFor the change to take effect your system will now need to reboot. Do this now?" 8 60
  1461. sel=$?
  1462. case $sel in
  1463. 0) systemctl reboot -i;;
  1464. esac
  1465. fi
  1466. fi
  1467. rm -f "$data"
  1468. }
  1469. function wifi_settings {
  1470. if [ -f /etc/hostapd/hostapd.conf ]; then
  1471. return
  1472. fi
  1473. TEMP_WIFI_NETWORKS_FILE=~/.temp-${PROJECT_NAME}-wifi.cfg
  1474. ${PROJECT_NAME}-wifi --networksinteractive $TEMP_WIFI_NETWORKS_FILE
  1475. if [ -f $TEMP_WIFI_NETWORKS_FILE ]; then
  1476. cp "$TEMP_WIFI_NETWORKS_FILE" "$WIFI_NETWORKS_FILE"
  1477. rm $TEMP_WIFI_NETWORKS_FILE
  1478. "${PROJECT_NAME}-wifi" --networks "$WIFI_NETWORKS_FILE"
  1479. create_wifi_startup_script
  1480. if [[ $(wifi_is_running) == "1" ]]; then
  1481. dialog --title $"Wifi Settings" \
  1482. --msgbox $"Wifi settings were changed." 6 60
  1483. else
  1484. dialog --title $"Wifi Settings" \
  1485. --msgbox $"Wifi settings were changed. You will need to restart the system with ethernet cable removed for the changes to take effect." 7 60
  1486. fi
  1487. else
  1488. remove_wifi_startup_script
  1489. fi
  1490. }
  1491. function wifi_edit_networks {
  1492. if [ -f /etc/hostapd/hostapd.conf ]; then
  1493. return
  1494. fi
  1495. if [ ! -f "$WIFI_NETWORKS_FILE" ]; then
  1496. { echo $'# Add wifi networks as follows:';
  1497. echo '#';
  1498. echo $'# MySSID';
  1499. echo $'# wpa2-psk';
  1500. echo $'# myWifiPassphrase';
  1501. echo '#';
  1502. echo $'# AnotherSSID';
  1503. echo $'# none';
  1504. echo '#'; } > "$WIFI_NETWORKS_FILE"
  1505. fi
  1506. editor "$WIFI_NETWORKS_FILE"
  1507. "${PROJECT_NAME}-wifi" --networks "$WIFI_NETWORKS_FILE"
  1508. }
  1509. function hotspot_settings {
  1510. data=$(mktemp 2>/dev/null)
  1511. dialog --backtitle $"Freedombone Control Panel" \
  1512. --title $"Hotspot Settings" \
  1513. --form $"" 10 60 4 \
  1514. $"Enabled (yes/no):" 1 1 "$WIFI_HOTSPOT" 1 24 5 5 \
  1515. $"SSID:" 2 1 "$WIFI_SSID" 2 24 256 256 \
  1516. $"Type (wpa2-psk/none):" 3 1 "$WIFI_TYPE" 3 24 10 10 \
  1517. $"Passphrase:" 4 1 "$WIFI_PASSPHRASE" 4 24 256 256 \
  1518. 2> "$data"
  1519. sel=$?
  1520. case $sel in
  1521. 1) rm -f "$data"
  1522. return;;
  1523. 255) rm -f "$data"
  1524. return;;
  1525. esac
  1526. TEMP_WIFI_HOTSPOT=$(sed -n 1p < "$data")
  1527. TEMP_WIFI_SSID=$(sed -n 2p < "$data")
  1528. TEMP_WIFI_TYPE=$(sed -n 3p < "$data")
  1529. TEMP_WIFI_PASSPHRASE=$(sed -n 4p < "$data")
  1530. rm -f "$data"
  1531. if [ ${#TEMP_WIFI_SSID} -lt 2 ]; then
  1532. return
  1533. fi
  1534. if [ ${#TEMP_WIFI_TYPE} -lt 2 ]; then
  1535. return
  1536. fi
  1537. WIFI_EXTRA=''
  1538. if [[ $TEMP_WIFI_HOTSPOT == $'yes' || $TEMP_WIFI_HOTSPOT == $'y' || $TEMP_WIFI_HOTSPOT == $'on' ]]; then
  1539. TEMP_WIFI_HOTSPOT='yes'
  1540. else
  1541. TEMP_WIFI_HOTSPOT='no'
  1542. if [ -f "$WIFI_NETWORKS_FILE" ]; then
  1543. WIFI_EXTRA="--networks $WIFI_NETWORKS_FILE"
  1544. fi
  1545. fi
  1546. if [[ $TEMP_WIFI_TYPE != $'none' ]]; then
  1547. if [ ! "$TEMP_WIFI_PASSPHRASE" ]; then
  1548. dialog --title $"Wifi Settings" \
  1549. --msgbox $"No wifi hotspot passphrase was given" 6 40
  1550. return
  1551. fi
  1552. if [ ${#TEMP_WIFI_PASSPHRASE} -lt 2 ]; then
  1553. dialog --title $"Wifi Settings" \
  1554. --msgbox $"Wifi hotspot passphrase was too short" 6 40
  1555. return
  1556. fi
  1557. WIFI_HOTSPOT=$TEMP_WIFI_HOTSPOT
  1558. WIFI_SSID=$TEMP_WIFI_SSID
  1559. WIFI_TYPE=$TEMP_WIFI_TYPE
  1560. WIFI_PASSPHRASE=$TEMP_WIFI_PASSPHRASE
  1561. if ! "${PROJECT_NAME}-wifi" -i "$WIFI_INTERFACE" -s "$WIFI_SSID" -t "$WIFI_TYPE" -p "$WIFI_PASSPHRASE" --hotspot "$WIFI_HOTSPOT" "$WIFI_EXTRA"; then
  1562. echo $"Can't enable wifi hotspot"
  1563. any_key
  1564. fi
  1565. else
  1566. WIFI_HOTSPOT=$TEMP_WIFI_HOTSPOT
  1567. WIFI_SSID=$TEMP_WIFI_SSID
  1568. WIFI_TYPE=$TEMP_WIFI_TYPE
  1569. WIFI_PASSPHRASE=$TEMP_WIFI_PASSPHRASE
  1570. "${PROJECT_NAME}-wifi" -i "$WIFI_INTERFACE" -s "$WIFI_SSID" -t "$WIFI_TYPE" --hotspot "$WIFI_HOTSPOT" "$WIFI_EXTRA"
  1571. fi
  1572. # store any changes
  1573. write_config_param "WIFI_HOTSPOT" "$WIFI_HOTSPOT"
  1574. write_config_param "WIFI_SSID" "$WIFI_SSID"
  1575. write_config_param "WIFI_TYPE" "$WIFI_TYPE"
  1576. write_config_param "WIFI_PASSPHRASE" "$WIFI_PASSPHRASE"
  1577. dialog --title $"Wifi Settings" \
  1578. --msgbox $"Hotspot settings were changed" 6 40
  1579. }
  1580. function reinstall_mariadb {
  1581. dialog --title $"Reinstall MariaDB" \
  1582. --backtitle $"Freedombone Control Panel" \
  1583. --defaultno \
  1584. --yesno $"\\nThis should be a LAST RESORT, if the mysql daemon won't start. You will lose ALL databases and will then need to restore them from backup.\\n\\nAre you sure that you wish to continue?" 12 60
  1585. sel=$?
  1586. case $sel in
  1587. 1) return;;
  1588. 255) return;;
  1589. esac
  1590. clear
  1591. database_reinstall
  1592. dialog --title $"Reinstall MariaDB" \
  1593. --msgbox $"MariaDB has been reinstalled" 6 40
  1594. }
  1595. function show_firewall {
  1596. clear
  1597. echo $"Firewall Settings"
  1598. echo ''
  1599. while read -r line; do
  1600. firewall_name=$(awk "$line" -F '=' '{print $1}')
  1601. firewall_port=$(awk "$line" -F '=' '{print $2}')
  1602. echo -n -e "$(pad_string "${firewall_name}")"
  1603. echo "${firewall_port}"
  1604. done < "$FIREWALL_CONFIG"
  1605. any_key
  1606. }
  1607. function email_extra_domains {
  1608. email_hostnames=$(grep "dc_other_hostnames" /etc/exim4/update-exim4.conf.conf | awk -F "'" '{print $2}')
  1609. data=$(mktemp 2>/dev/null)
  1610. dialog --title $"Email Domains" \
  1611. --backtitle $"Freedombone Control Panel" \
  1612. --inputbox $"Enter the list of email domains to use, separated by semicolons" 8 60 "$email_hostnames" 2>"$data"
  1613. sel=$?
  1614. case $sel in
  1615. 0)
  1616. emailhostnames=$(<"$data")
  1617. if [ ${#emailhostnames} -gt 2 ]; then
  1618. if [[ "$email_hostnames" != "$emailhostnames" ]]; then
  1619. if [[ "$emailhostnames" == *"."* ]]; then
  1620. if [[ "$emailhostnames" != *" "* ]]; then
  1621. sed -i "s|dc_other_hostnames=.*|dc_other_hostnames='$emailhostnames'|g" /etc/exim4/update-exim4.conf.conf
  1622. update-exim4.conf
  1623. dpkg-reconfigure --frontend noninteractive exim4-config
  1624. systemctl restart saslauthd
  1625. dialog --title $"Email Domains" \
  1626. --backtitle $"Freedombone Control Panel" \
  1627. --msgbox $"Email domains were changed" 6 50
  1628. else
  1629. dialog --title $"Email Domains not set" \
  1630. --backtitle $"Freedombone Control Panel" \
  1631. --msgbox $"There should be no spaces in the list" 6 50
  1632. fi
  1633. fi
  1634. fi
  1635. fi
  1636. ;;
  1637. esac
  1638. rm -f "$data"
  1639. }
  1640. function email_smtp_proxy {
  1641. MUTTRC_FILE=/home/$ADMIN_USER/.muttrc
  1642. if [ ! -f $MUTTRC_FILE ]; then
  1643. return
  1644. fi
  1645. data=$(mktemp 2>/dev/null)
  1646. dialog --backtitle $"Freedombone Control Panel" \
  1647. --title $"SMTP Proxy for $ADMIN_USER" \
  1648. --form $"You may need to proxy outgoing email via your ISP's mail server. If so enter the details below." 14 75 6 \
  1649. $"Enable proxy:" 1 1 "$SMTP_PROXY_ENABLE" 1 24 5 5 \
  1650. $"Protocol (smtp/smtps):" 2 1 "$SMTP_PROXY_PROTOCOL" 2 24 5 5 \
  1651. $"ISP mail server:" 3 1 "$SMTP_PROXY_SERVER" 3 24 40 10000 \
  1652. $"Port:" 4 1 "$SMTP_PROXY_PORT" 4 24 5 5 \
  1653. $"Username:" 5 1 "$SMTP_PROXY_USERNAME" 5 24 40 10000 \
  1654. $"Password:" 6 1 "$SMTP_PROXY_PASSWORD" 6 24 40 10000 \
  1655. 2> "$data"
  1656. sel=$?
  1657. case $sel in
  1658. 1) rm -f "$data"
  1659. return;;
  1660. 255) rm -f "$data"
  1661. return;;
  1662. esac
  1663. SMTP_PROXY_ENABLE=$(sed -n 1p < "$data")
  1664. SMTP_PROXY_PROTOCOL=$(sed -n 2p < "$data")
  1665. SMTP_PROXY_SERVER=$(sed -n 3p < "$data")
  1666. SMTP_PROXY_PORT=$(sed -n 4p < "$data")
  1667. SMTP_PROXY_USERNAME=$(sed -n 5p < "$data")
  1668. SMTP_PROXY_PASSWORD=$(sed -n 6p < "$data")
  1669. rm -f "$data"
  1670. # change muttrc
  1671. if [ "$SMTP_PROXY_ENABLE" != $'no' ]; then
  1672. if ! grep -q "set smtp_url" "$MUTTRC_FILE"; then
  1673. echo "set smtp_url=\"${SMTP_PROXY_PROTOCOL}://${SMTP_PROXY_USERNAME}:${SMTP_PROXY_PASSWORD}@${SMTP_PROXY_SERVER}:${SMTP_PROXY_PORT}/\"" >> "$MUTTRC_FILE"
  1674. else
  1675. sed -i "s|set smtp_url=.*|set smtp_url=\"${SMTP_PROXY_PROTOCOL}://${SMTP_PROXY_USERNAME}:${SMTP_PROXY_PASSWORD}@${SMTP_PROXY_SERVER}:${SMTP_PROXY_PORT}/\"|g" "$MUTTRC_FILE"
  1676. fi
  1677. sed -i 's|#set smtp_url|set smtp_url|g' "$MUTTRC_FILE"
  1678. else
  1679. if grep -q "set smtp_url" "$MUTTRC_FILE"; then
  1680. sed -i 's|set smtp_url|#set smtp_url|g' "$MUTTRC_FILE"
  1681. fi
  1682. fi
  1683. # save settings within the main configuration file
  1684. write_config_param "SMTP_PROXY_ENABLE" "$SMTP_PROXY_ENABLE"
  1685. write_config_param "SMTP_PROXY_PROTOCOL" "$SMTP_PROXY_PROTOCOL"
  1686. write_config_param "SMTP_PROXY_SERVER" "$SMTP_PROXY_SERVER"
  1687. write_config_param "SMTP_PROXY_PORT" "$SMTP_PROXY_PORT"
  1688. write_config_param "SMTP_PROXY_USERNAME" "$SMTP_PROXY_USERNAME"
  1689. write_config_param "SMTP_PROXY_PASSWORD" "$SMTP_PROXY_PASSWORD"
  1690. }
  1691. function menu_backup_restore {
  1692. while true
  1693. do
  1694. data=$(mktemp 2>/dev/null)
  1695. dialog --backtitle $"Freedombone Control Panel" \
  1696. --title $"Backup and Restore" \
  1697. --radiolist $"Choose an operation:" 19 70 12 \
  1698. 1 $"Backup data to USB drive" off \
  1699. 2 $"Restore GPG key from USB keydrive" off \
  1700. 3 $"Restore data from USB drive" off \
  1701. 4 $"Reinstall mariadb" off \
  1702. 5 $"Configure remote backups" off \
  1703. 6 $"Restore from remote backup" off \
  1704. 7 $"Backup GPG key to USB (master keydrive)" off \
  1705. 8 $"Backup GPG key to USB (fragment keydrive)" off \
  1706. 9 $"Format a USB drive (LUKS encrypted)" off \
  1707. 10 $"Remove backups from a USB drive" off \
  1708. 11 $"Back to main menu" on 2> "$data"
  1709. sel=$?
  1710. case $sel in
  1711. 1) rm -f "$data"
  1712. break;;
  1713. 255) rm -f "$data"
  1714. break;;
  1715. esac
  1716. case $(cat "$data") in
  1717. 1) backup_data;;
  1718. 2) restore_gpg_key;;
  1719. 3) restore_data;;
  1720. 4) reinstall_mariadb;;
  1721. 5) configure_remote_backups;;
  1722. 6) restore_data_remote;;
  1723. 7) create_keydrive_master;;
  1724. 8) create_keydrive_fragment;;
  1725. 9) format_drive;;
  1726. 10) remove_backups;;
  1727. 11) rm -f "$data"
  1728. break;;
  1729. esac
  1730. rm -f "$data"
  1731. done
  1732. }
  1733. function menu_email {
  1734. while true
  1735. do
  1736. data=$(mktemp 2>/dev/null)
  1737. dialog --backtitle $"Freedombone Control Panel" \
  1738. --title $"Email Menu" \
  1739. --radiolist $"Choose an operation:" 15 70 8 \
  1740. 1 $"Add a user to a mailing list" off \
  1741. 2 $"Remove a user from a mailing list" off \
  1742. 3 $"Add an email rule" off \
  1743. 4 $"Block/Unblock an email address" off \
  1744. 5 $"Block/Unblock email with subject text" off \
  1745. 6 $"Outgoing Email Proxy" off \
  1746. 7 $"Extra email domains" off \
  1747. 8 $"Back to main menu" on 2> "$data"
  1748. sel=$?
  1749. case $sel in
  1750. 1) rm -f "$data"
  1751. break;;
  1752. 255) rm -f "$data"
  1753. break;;
  1754. esac
  1755. case $(cat "$data") in
  1756. 1) add_to_mailing_list;;
  1757. 2) remove_user_from_mailing_list;;
  1758. 3) email_rule;;
  1759. 4) block_unblock_email;;
  1760. 5) block_unblock_subject;;
  1761. 6) email_smtp_proxy;;
  1762. 7) email_extra_domains;;
  1763. 8) rm -f "$data"
  1764. break;;
  1765. esac
  1766. rm -f "$data"
  1767. done
  1768. }
  1769. function domain_blocking_add {
  1770. data=$(mktemp 2>/dev/null)
  1771. dialog --title $"Block a domain or user" \
  1772. --backtitle $"Freedombone Control Panel" \
  1773. --inputbox $"Enter the domain name or GNU Social/postActiv/Pleroma nick@domain that you wish to block" 8 60 "" 2>"$data"
  1774. sel=$?
  1775. case $sel in
  1776. 0)
  1777. blocked_domain=$(<"$data")
  1778. if [ ${#blocked_domain} -gt 2 ]; then
  1779. if [[ "${blocked_domain}" == *'.'* ]]; then
  1780. firewall_block_domain "$blocked_domain"
  1781. if [[ "${blocked_domain}" != *'@'* ]]; then
  1782. dialog --title $"Block a domain" \
  1783. --msgbox $"The domain $blocked_domain has been blocked" 6 40
  1784. else
  1785. dialog --title $"Block a GNU Social/postActiv/Pleroma nickname" \
  1786. --msgbox $"$blocked_domain has been blocked" 6 40
  1787. fi
  1788. fi
  1789. fi
  1790. ;;
  1791. esac
  1792. rm -f "$data"
  1793. }
  1794. function ip_blocking_add {
  1795. data=$(mktemp 2>/dev/null)
  1796. dialog --title $"Block an IP address" \
  1797. --backtitle $"Freedombone Control Panel" \
  1798. --inputbox $"Enter the IP address that you wish to block" 8 60 "" 2>"$data"
  1799. sel=$?
  1800. case $sel in
  1801. 0)
  1802. blocked_ip=$(<"$data")
  1803. if [ ${#blocked_ip} -gt 2 ]; then
  1804. if [[ "${blocked_ip}" == *'.'* ]]; then
  1805. firewall_block_ip "$blocked_ip"
  1806. if [[ "${blocked_ip}" != *'@'* ]]; then
  1807. dialog --title $"Block an IP address" \
  1808. --msgbox $"The IP address $blocked_ip has been blocked" 6 40
  1809. fi
  1810. fi
  1811. fi
  1812. ;;
  1813. esac
  1814. rm -f "$data"
  1815. }
  1816. function domain_blocking_remove {
  1817. data=$(mktemp 2>/dev/null)
  1818. dialog --title $"Unblock a domain or user" \
  1819. --backtitle $"Freedombone Control Panel" \
  1820. --inputbox $"Enter the domain name or GNU Social/postActiv nick@domain that you wish to unblock" 8 60 "" 2>"$data"
  1821. sel=$?
  1822. case $sel in
  1823. 0)
  1824. unblocked_domain=$(<"$data")
  1825. if [ ${#unblocked_domain} -gt 2 ]; then
  1826. if [[ "${unblocked_domain}" == *'.'* ]]; then
  1827. firewall_unblock_domain "$unblocked_domain"
  1828. if [[ "${unblocked_domain}" != *'@'* ]]; then
  1829. dialog --title $"Unblock a domain" \
  1830. --msgbox $"The domain $unblocked_domain has been unblocked" 6 40
  1831. else
  1832. dialog --title $"Unblock a GNU Social/postActiv nickname" \
  1833. --msgbox $"$unblocked_domain has been unblocked" 6 40
  1834. fi
  1835. fi
  1836. fi
  1837. ;;
  1838. esac
  1839. rm -f "$data"
  1840. }
  1841. function ip_blocking_remove {
  1842. data=$(mktemp 2>/dev/null)
  1843. dialog --title $"Unblock an IP address" \
  1844. --backtitle $"Freedombone Control Panel" \
  1845. --inputbox $"Enter the IP address that you wish to unblock" 8 60 "" 2>"$data"
  1846. sel=$?
  1847. case $sel in
  1848. 0)
  1849. unblocked_ip=$(<"$data")
  1850. if [ ${#unblocked_ip} -gt 2 ]; then
  1851. if [[ "${unblocked_ip}" == *'.'* ]]; then
  1852. firewall_unblock_ip "$unblocked_ip"
  1853. if [[ "${unblocked_ip}" != *'@'* ]]; then
  1854. dialog --title $"Unblock an IP address" \
  1855. --msgbox $"The IP address $unblocked_ip has been unblocked" 6 40
  1856. fi
  1857. fi
  1858. fi
  1859. ;;
  1860. esac
  1861. rm -f "$data"
  1862. }
  1863. function domain_blocking_show {
  1864. if [ -f "$FIREWALL_DOMAINS" ]; then
  1865. clear
  1866. echo ''
  1867. echo $'The following domains or users have been blocked:'
  1868. echo ''
  1869. sort < "$FIREWALL_DOMAINS"
  1870. any_key
  1871. else
  1872. dialog --title $"Show blocked domains or users" \
  1873. --msgbox $"No domains or users are currently blocked" 6 40
  1874. fi
  1875. }
  1876. function domain_blocking {
  1877. while true
  1878. do
  1879. data=$(mktemp 2>/dev/null)
  1880. dialog --backtitle $"Freedombone Control Panel" \
  1881. --title $"Domain or User Blocking" \
  1882. --radiolist $"Choose an operation:" 14 60 6 \
  1883. 1 $"Block a domain or user" off \
  1884. 2 $"Unblock a domain or user" off \
  1885. 3 $"Block an IP address" off \
  1886. 4 $"Unblock an IP address" off \
  1887. 5 $"Show blocked domains and users" off \
  1888. 6 $"Back to main menu" on 2> "$data"
  1889. sel=$?
  1890. case $sel in
  1891. 1) rm -f "$data"
  1892. break;;
  1893. 255) rm -f "$data"
  1894. break;;
  1895. esac
  1896. case $(cat "$data") in
  1897. 1) domain_blocking_add;;
  1898. 2) domain_blocking_remove;;
  1899. 3) ip_blocking_add;;
  1900. 4) ip_blocking_remove;;
  1901. 5) domain_blocking_show;;
  1902. 6) rm -f "$data"
  1903. break;;
  1904. esac
  1905. rm -f "$data"
  1906. done
  1907. }
  1908. function menu_users {
  1909. while true
  1910. do
  1911. data=$(mktemp 2>/dev/null)
  1912. dialog --backtitle $"Freedombone Control Panel" \
  1913. --title $"Manage Users" \
  1914. --radiolist $"Choose an operation:" 13 70 6 \
  1915. 1 $"Add a user" off \
  1916. 2 $"Delete a user" off \
  1917. 3 $"Change user password" off \
  1918. 4 $"Change user ssh public key" off \
  1919. 5 $"Reset password tries" off \
  1920. 6 $"Back to main menu" on 2> "$data"
  1921. sel=$?
  1922. case $sel in
  1923. 1) rm -f "$data"
  1924. break;;
  1925. 255) rm -f "$data"
  1926. break;;
  1927. esac
  1928. case $(cat "$data") in
  1929. 1) add_user;;
  1930. 2) delete_user;;
  1931. 3) change_password;;
  1932. 4) change_ssh_public_key;;
  1933. 5) reset_password_tries;;
  1934. 6) rm -f "$data"
  1935. break;;
  1936. esac
  1937. rm -f "$data"
  1938. done
  1939. }
  1940. function wifi_enable {
  1941. disable_wifi='yes'
  1942. dialog --title $"Enable Wifi" \
  1943. --backtitle $"Freedombone Control Panel" \
  1944. --defaultno \
  1945. --yesno $"\\nDo you wish to enable wifi?" 10 50
  1946. sel=$?
  1947. case $sel in
  1948. 0) disable_wifi='no';;
  1949. 1) disable_wifi='yes';;
  1950. 255) return;;
  1951. esac
  1952. "${PROJECT_NAME}-wifi" --disable $disable_wifi
  1953. }
  1954. function add_clacks {
  1955. clacks=
  1956. data=$(mktemp 2>/dev/null)
  1957. dialog --title $"Add Clacks Overhead" \
  1958. --backtitle $"Freedombone Control Panel" \
  1959. --inputbox $"" 7 60 2>"$data"
  1960. sel=$?
  1961. case $sel in
  1962. 0)
  1963. clacks=$(<"$data")
  1964. if [ ${#clacks} -gt 1 ]; then
  1965. WEB_FILES="/etc/nginx/sites-available/*"
  1966. for f in $WEB_FILES
  1967. do
  1968. if grep -q "X-Clacks-Overhead" "$f"; then
  1969. sed -i "s|X-Clacks-Overhead .*|X-Clacks-Overhead \"GNU $clacks\";|g" "$f"
  1970. else
  1971. sed -i "/X-Content-Type-Options/a add_header X-Clacks-Overhead \"GNU $clacks\";" "$f"
  1972. fi
  1973. done
  1974. systemctl restart nginx
  1975. dialog --title $"Add Clacks Overhead" \
  1976. --msgbox $"\\nAdded for $clacks" 10 60
  1977. fi
  1978. ;;
  1979. esac
  1980. rm -f "$data"
  1981. }
  1982. function menu_wifi {
  1983. if [[ "$(wifi_exists)" == "0" ]]; then
  1984. dialog --title $"Wifi" \
  1985. --msgbox $"No wifi adaptors were detected" 6 40
  1986. return
  1987. fi
  1988. while true
  1989. do
  1990. status_str=$'Wifi OFF'
  1991. if [ -f /etc/hostapd/hostapd.conf ]; then
  1992. status_str=$'Hotspot ON'
  1993. else
  1994. if [ -f /etc/network/interfaces.d/wifi ]; then
  1995. status_str=$'Wifi ON'
  1996. fi
  1997. fi
  1998. data=$(mktemp 2>/dev/null)
  1999. dialog --backtitle $"Freedombone Control Panel" \
  2000. --title $"Wifi Menu" \
  2001. --radiolist $"${status_str}\\n\\nChoose an operation:" 14 70 6 \
  2002. 1 $"Enable or disable Wifi" off \
  2003. 2 $"Configure wifi networks" off \
  2004. 3 $"Manually edit wifi networks file" off \
  2005. 4 $"Hotspot settings" off \
  2006. 5 $"Exit" on 2> "$data"
  2007. sel=$?
  2008. case $sel in
  2009. 1) rm -f "$data"
  2010. break;;
  2011. 255) rm -f "$data"
  2012. break;;
  2013. esac
  2014. case $(cat "$data") in
  2015. 1) wifi_enable;;
  2016. 2) wifi_settings;;
  2017. 3) wifi_edit_networks;;
  2018. 4) hotspot_settings;;
  2019. 5) rm -f "$data"
  2020. break;;
  2021. esac
  2022. rm -f "$data"
  2023. done
  2024. }
  2025. function menu_app_settings {
  2026. detect_installable_apps
  2027. applist=""
  2028. appnames=()
  2029. n=1
  2030. app_index=0
  2031. for a in "${APPS_AVAILABLE[@]}"
  2032. do
  2033. if [[ ${APPS_INSTALLED[$app_index]} != "0" ]]; then
  2034. if [[ $(function_exists "configure_interactive_${a}") == "1" ]]; then
  2035. applist="$applist $n $a off"
  2036. n=$((n+1))
  2037. appnames+=("$a")
  2038. fi
  2039. fi
  2040. app_index=$((app_index+1))
  2041. done
  2042. if [ $n -le 1 ]; then
  2043. return
  2044. fi
  2045. backstr=$'Exit'
  2046. applist="$applist $n $backstr on"
  2047. appnames+=("Exit")
  2048. choice=$(dialog --stdout --backtitle $"Freedombone" \
  2049. --title $"Change settings for an App" \
  2050. --radiolist $'Choose:' \
  2051. 26 40 30 "$applist")
  2052. # shellcheck disable=SC2181
  2053. if [ $? -eq 0 ]; then
  2054. app_index=$((choice-1))
  2055. chosen_app=${appnames[$app_index]}
  2056. if [[ $chosen_app != "Exit" ]]; then
  2057. "configure_interactive_${chosen_app}"
  2058. fi
  2059. fi
  2060. }
  2061. function menu_top_level {
  2062. while true
  2063. do
  2064. data=$(mktemp 2>/dev/null)
  2065. dialog --backtitle $"Freedombone Control Panel" \
  2066. --title $"Control Panel" \
  2067. --radiolist $"Choose an operation:" 30 70 22 \
  2068. 1 $"About this system" off \
  2069. 2 $"Passwords" off \
  2070. 3 $"Backup and Restore" off \
  2071. 4 $"Show Firewall" off \
  2072. 5 $"Verify Tripwire Code" off \
  2073. 6 $"Reset Tripwire" off \
  2074. 7 $"App Settings" off \
  2075. 8 $"Add/Remove Apps" off \
  2076. 9 $"Logging on/off" off \
  2077. 10 $"Ping enable/disable" off \
  2078. 11 $"Manage Users" off \
  2079. 12 $"Email Menu" off \
  2080. 13 $"Domain or User Blocking" off \
  2081. 14 $"Security Settings" off \
  2082. 15 $"Change the name of this system" off \
  2083. 16 $"Set a static local IP address" off \
  2084. 17 $"Wifi menu" off \
  2085. 18 $"Add Clacks" off \
  2086. 19 $"Check for updates" off \
  2087. 20 $"Power off the system" off \
  2088. 21 $"Restart the system" off \
  2089. 22 $"Exit" on 2> "$data"
  2090. sel=$?
  2091. case $sel in
  2092. 1) rm -f "$data"
  2093. exit 1;;
  2094. 255) rm -f "$data"
  2095. exit 1;;
  2096. esac
  2097. please_wait
  2098. case $(cat "$data") in
  2099. 1) show_about;;
  2100. 2) view_or_change_passwords;;
  2101. 3) menu_backup_restore;;
  2102. 4) show_firewall;;
  2103. 5) show_tripwire_verification_code
  2104. any_key_verify;;
  2105. 6) reset_tripwire;;
  2106. 7) menu_app_settings;;
  2107. 8) if ! /usr/local/bin/addremove; then
  2108. any_key
  2109. fi
  2110. ;;
  2111. 9) logging_on_off;;
  2112. 10) ping_enable_disable;;
  2113. 11) menu_users;;
  2114. 12) menu_email;;
  2115. 13) domain_blocking;;
  2116. 14) security_settings;;
  2117. 15) change_system_name;;
  2118. 16) set_static_IP;;
  2119. 17) menu_wifi;;
  2120. 18) add_clacks;;
  2121. 19) check_for_updates;;
  2122. 20) shut_down_system;;
  2123. 21) restart_system;;
  2124. 22) rm -f "$data"
  2125. break;;
  2126. esac
  2127. rm -f "$data"
  2128. done
  2129. }
  2130. if [ ! -f "$COMPLETION_FILE" ]; then
  2131. echo $'This command should only be run on an installed Freedombone system'
  2132. exit 1
  2133. fi
  2134. ADMIN_USER=$(get_completion_param "Admin user")
  2135. menu_top_level
  2136. clear
  2137. cat /etc/motd
  2138. exit 0