freedombone-controlpanel 65KB

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