freedombone-controlpanel 77KB

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