freedombone-controlpanel 70KB

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