freedombone-controlpanel 71KB

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