freedombone-controlpanel 65KB

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