freedombone-controlpanel 72KB

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