freedombone-controlpanel 72KB

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