freedombone-controlpanel 65KB

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