freedombone-controlpanel 65KB

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