freedombone-controlpanel 72KB

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