freedombone-controlpanel 77KB

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