freedombone-controlpanel 66KB

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