freedombone-controlpanel 70KB

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