freedombone-controlpanel 75KB

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