freedombone-controlpanel 63KB

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