freedombone-controlpanel 72KB

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