freedombone-controlpanel 37KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115
  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 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 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 General Public License for more details.
  27. #
  28. # You should have received a copy of the GNU 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. COMPLETION_FILE=$HOME/${PROJECT_NAME}-completed.txt
  34. SELECTED_USERNAME=
  35. SIP_CONFIG_FILE=/etc/sipwitch.conf
  36. ADMIN_USER=
  37. UPGRADE_SCRIPT_NAME="${PROJECT_NAME}-upgrade"
  38. UPDATE_DATE_SCRIPT=/usr/bin/updatedate
  39. function any_key {
  40. echo ' '
  41. read -n1 -r -p $"Press any key to continue..." key
  42. }
  43. function check_for_updates {
  44. if [ ! -f /etc/cron.weekly/$UPGRADE_SCRIPT_NAME ]; then
  45. dialog --title $"Check for updates" \
  46. --msgbox $"Upgrade script was not found" 6 40
  47. return
  48. fi
  49. clear
  50. . /etc/cron.weekly/$UPGRADE_SCRIPT_NAME
  51. any_key
  52. }
  53. function add_user {
  54. data=$(tempfile 2>/dev/null)
  55. trap "rm -f $data" 0 1 2 5 15
  56. dialog --backtitle $"Freedombone Control Panel" \
  57. --title $"Add new user" \
  58. --form "\n" 8 40 3 \
  59. $"Username:" 1 1 "" 1 11 16 15 \
  60. $"ssh public key (optional):" 2 1 "" 3 1 40 10000 \
  61. 2> $data
  62. sel=$?
  63. case $sel in
  64. 1) return;;
  65. 255) return;;
  66. esac
  67. new_user_username=$(cat $data | sed -n 1p)
  68. new_user_ssh_public_key=$(cat $data | sed -n 2p)
  69. if [ ${#new_user_username} -lt 2 ]; then
  70. dialog --title $"New username" \
  71. --msgbox $"No username was given" 6 40
  72. return
  73. fi
  74. if [[ "$new_user_username" == *" "* ]]; then
  75. dialog --title $"Invalid username" \
  76. --msgbox $"The username should not contain any spaces" 6 40
  77. return
  78. fi
  79. if [ ${#new_user_ssh_public_key} -lt 20 ]; then
  80. clear
  81. ${PROJECT_NAME}-adduser "$new_user_username"
  82. any_key
  83. else
  84. if [[ "$new_user_ssh_public_key" == "ssh-"* ]]; then
  85. clear
  86. ${PROJECT_NAME}-adduser "$new_user_username" "$new_user_ssh_public_key"
  87. any_key
  88. else
  89. dialog --title $"ssh public key" \
  90. --msgbox $"This does not look like an ssh public key" 6 40
  91. fi
  92. fi
  93. }
  94. function show_sip_extensions {
  95. if [ ! -f $SIP_CONFIG_FILE ]; then
  96. return;
  97. fi
  98. clear
  99. echo $"SIP phone extensions:"
  100. echo " "
  101. while read ext; do
  102. if [[ $ext == *"user id"* ]]; then
  103. echo -n " "
  104. echo -n $(echo "$ext" | awk -F '"' '{print $2}' | awk -F '"' '{print $1}')
  105. echo -n " "
  106. fi
  107. if [[ $ext == *"extension"* ]]; then
  108. echo $(echo "$ext" | awk -F '>' '{print $2}' | awk -F '<' '{print $1}')
  109. fi
  110. done < $SIP_CONFIG_FILE
  111. any_key
  112. }
  113. function select_user {
  114. SELECTED_USERNAME=
  115. data=$(tempfile 2>/dev/null)
  116. trap "rm -f $data" 0 1 2 5 15
  117. dialog --title "Select a user" \
  118. --backtitle $"Freedombone Control Panel" \
  119. --dselect "/home/" 14 40 2> $data
  120. sel=$?
  121. case $sel in
  122. 0) SELECTED_USERNAME=$(cat $data | awk -F '/' '{print $3}');;
  123. 1) return;;
  124. 255) return;;
  125. esac
  126. if [ ${#SELECTED_USERNAME} -lt 2 ]; then
  127. SELECTED_USERNAME=
  128. fi
  129. if [ ! -d /home/$SELECTED_USERNAME/Maildir ]; then
  130. dialog --title $"User directory check" \
  131. --msgbox $"This does not look like a user directory" 6 40
  132. SELECTED_USERNAME=
  133. fi
  134. }
  135. function delete_user {
  136. select_user
  137. if [ ! $SELECTED_USERNAME ]; then
  138. return
  139. fi
  140. if grep -Fxq "Admin user:$SELECTED_USERNAME" $COMPLETION_FILE; then
  141. dialog --title $"Administrator user" \
  142. --msgbox $"You can't delete the administrator user" 6 40
  143. return
  144. fi
  145. clear
  146. ${PROJECT_NAME}-rmuser $SELECTED_USERNAME
  147. any_key
  148. }
  149. function configure_remote_backups {
  150. if ! grep -Fxq "Admin user:$SELECTED_USERNAME" $COMPLETION_FILE; then
  151. dialog --title $"Administrator user" \
  152. --msgbox $"No Administrator user found. Check $COMPLETION_FILE" 6 40
  153. return
  154. fi
  155. if [ ${#ADMIN} -lt 2 ]; then
  156. dialog --title $"Administrator user" \
  157. --msgbox $"Username not found" 6 40
  158. return
  159. fi
  160. if [ ! -d /home/$ADMIN_USER ]; then
  161. dialog --title $"Administrator user" \
  162. --msgbox $"Home directory not found" 6 40
  163. return
  164. fi
  165. ${PROJECT_NAME}-remote -u $ADMIN_USER
  166. }
  167. function change_password {
  168. select_user
  169. if [ ! $SELECTED_USERNAME ]; then
  170. return
  171. fi
  172. clear
  173. echo -n $"Change password for"
  174. echo " $SELECTED_USERNAME"
  175. echo ""
  176. su -c "passwd" - $SELECTED_USERNAME
  177. any_key
  178. }
  179. function irc_set_global_password {
  180. dialog --title $"IRC Password" \
  181. --clear \
  182. --backtitle $"Freedombone Control Panel" \
  183. --passwordbox $"Password for all IRC users" 10 50 2> $data
  184. sel=$?
  185. case $sel in
  186. 0)
  187. NEW_IRC_PASSWORD=$(<$data)
  188. sed -i "0,/RE/s/Password =.*/Password = $NEW_IRC_PASSWORD/" /etc/ngircd/ngircd.conf
  189. dialog --title $"IRC Password" \
  190. --msgbox $"The IRC password was changed" 6 40
  191. ;;
  192. esac
  193. }
  194. function change_ssh_public_key {
  195. select_user
  196. if [ ! $SELECTED_USERNAME ]; then
  197. return
  198. fi
  199. if grep -Fxq "Admin user:$SELECTED_USERNAME" $COMPLETION_FILE; then
  200. dialog --title $"Change ssh public key" \
  201. --backtitle $"Freedombone Control Panel" \
  202. --defaultno \
  203. --yesno $"\nThis is the administrator user.\n\nAre you sure you want to change the ssh public key for the administrator?" 10 60
  204. sel=$?
  205. case $sel in
  206. 1) return;;
  207. 255) return;;
  208. esac
  209. fi
  210. data=$(tempfile 2>/dev/null)
  211. trap "rm -f $data" 0 1 2 5 15
  212. dialog --title $"Change ssh public key for $SELECTED_USERNAME" \
  213. --backtitle $"Freedombone Control Panel" \
  214. --inputbox $"Paste the ssh public key below" 8 60 2>$data
  215. sel=$?
  216. case $sel in
  217. 0)
  218. SSH_PUBLIC_KEY=$(<$data)
  219. if [ "$SSH_PUBLIC_KEY" ]; then
  220. if [ ${#SSH_PUBLIC_KEY} -gt 5 ]; then
  221. if [ -f "$SSH_PUBLIC_KEY" ]; then
  222. if [ ! -d /home/$SELECTED_USERNAME/.ssh ]; then
  223. mkdir /home/$SELECTED_USERNAME/.ssh
  224. fi
  225. cp $SSH_PUBLIC_KEY \
  226. /home/$SELECTED_USERNAME/.ssh/authorized_keys
  227. chown -R $SELECTED_USERNAME:$SELECTED_USERNAME \
  228. /home/$SELECTED_USERNAME/.ssh
  229. dialog --title $"Change ssh public key" \
  230. --msgbox $"ssh public key was installed" 6 40
  231. else
  232. if [[ "$SSH_PUBLIC_KEY" == "ssh-"* ]]; then
  233. if [ ! -d /home/$SELECTED_USERNAME/.ssh ]; then
  234. mkdir /home/$SELECTED_USERNAME/.ssh
  235. fi
  236. echo "$SSH_PUBLIC_KEY" > \
  237. /home/$SELECTED_USERNAME/.ssh/authorized_keys
  238. chown -R $SELECTED_USERNAME:$SELECTED_USERNAME \
  239. /home/$SELECTED_USERNAME/.ssh
  240. dialog --title $"Change ssh public key" \
  241. --msgbox $"ssh public key was installed" 6 40
  242. fi
  243. fi
  244. fi
  245. fi
  246. ;;
  247. esac
  248. }
  249. function add_to_mailing_list {
  250. select_user
  251. if [ ! $SELECTED_USERNAME ]; then
  252. return
  253. fi
  254. data=$(tempfile 2>/dev/null)
  255. trap "rm -f $data" 0 1 2 5 15
  256. dialog --backtitle $"Freedombone Control Panel" \
  257. --title $"Subscribe $SELECTED_USERNAME to a mailing list" \
  258. --form "\n" 8 68 4 \
  259. $"List folder name:" 1 1 "" 1 35 26 25 \
  260. $"Name between [] on subject line:" 2 1 "" 2 35 26 25 \
  261. $"List email address:" 3 1 "" 3 35 26 25 \
  262. 2> $data
  263. sel=$?
  264. case $sel in
  265. 1) return;;
  266. 255) return;;
  267. esac
  268. LIST_NAME=$(cat $data | sed -n 1p)
  269. LIST_SUBJECT=$(cat $data | sed -n 2p)
  270. LIST_EMAIL=$(cat $data | sed -n 3p)
  271. if [ ${#LIST_NAME} -lt 2 ]; then
  272. dialog --title $"Add mailing list" \
  273. --msgbox $"No mailing list name was given" 6 40
  274. return
  275. fi
  276. if [ ${#LIST_SUBJECT} -lt 2 ]; then
  277. dialog --title $"Add mailing list" \
  278. --msgbox $"No mailing list subject was given" 6 40
  279. return
  280. fi
  281. if [ ${#LIST_EMAIL} -lt 2 ]; then
  282. dialog --title $"Add mailing list" \
  283. --msgbox $"No mailing list email address was given" 6 40
  284. return
  285. fi
  286. if [[ "$LIST_EMAIL" != *"@"* || "$LIST_EMAIL" != *"."* ]]; then
  287. dialog --title $"Add mailing list" \
  288. --msgbox $"Unrecognised email address" 6 40
  289. return
  290. fi
  291. ${PROJECT_NAME}-addlist -u $SELECTED_USERNAME -l "$LIST_NAME" \
  292. -s "$LIST_SUBJECT" -e "$LIST_EMAIL"
  293. dialog --title $"Add mailing list" \
  294. --msgbox $"$LIST_NAME list was added" 6 40
  295. }
  296. function email_rule {
  297. select_user
  298. if [ ! $SELECTED_USERNAME ]; then
  299. return
  300. fi
  301. data=$(tempfile 2>/dev/null)
  302. trap "rm -f $data" 0 1 2 5 15
  303. dialog --backtitle $"Freedombone Control Panel" \
  304. --title $"Email rule for user $SELECTED_USERNAME" \
  305. --form "\n" 8 65 3 \
  306. $"When email arrives from address:" 1 1 "" 1 35 24 28 \
  307. $"Move to folder:" 2 1 "" 2 35 24 28 \
  308. 2> $data
  309. sel=$?
  310. case $sel in
  311. 1) return;;
  312. 255) return;;
  313. esac
  314. RULE_EMAIL=$(cat $data | sed -n 1p)
  315. RULE_FOLDER=$(cat $data | sed -n 2p)
  316. if [ ${#RULE_EMAIL} -lt 2 ]; then
  317. dialog --title $"Add email rule" \
  318. --msgbox $"No email address was given" 6 40
  319. return
  320. fi
  321. if [ ${#RULE_FOLDER} -lt 2 ]; then
  322. dialog --title $"Add email rule" \
  323. --msgbox $"No folder name was given" 6 40
  324. return
  325. fi
  326. if [[ "$RULE_EMAIL" != *"@"* || "$RULE_EMAIL" != *"."* ]]; then
  327. dialog --title $"Add email rule" \
  328. --msgbox $"Unrecognised email address" 6 40
  329. return
  330. fi
  331. ${PROJECT_NAME}-addemail -u $SELECTED_USERNAME -e "$RULE_EMAIL" \
  332. -g "$RULE_FOLDER"
  333. dialog --title $"Add email rule" \
  334. --msgbox $"Email rule for $RULE_EMAIL was added" 6 40
  335. }
  336. function block_unblock_email {
  337. select_user
  338. if [ ! $SELECTED_USERNAME ]; then
  339. return
  340. fi
  341. blockstr=$"Block/Unblock email going to"
  342. data=$(tempfile 2>/dev/null)
  343. trap "rm -f $data" 0 1 2 5 15
  344. dialog --backtitle $"Freedombone Control Panel" \
  345. --title "$blockstr $SELECTED_USERNAME" \
  346. --form "\n" 8 65 3 \
  347. $"When email arrives from address:" 1 1 "" 1 35 24 28 \
  348. $"Block it:" 2 1 "yes" 2 35 4 4 \
  349. 2> $data
  350. sel=$?
  351. case $sel in
  352. 1) return;;
  353. 255) return;;
  354. esac
  355. BLOCK_EMAIL=$(cat $data | sed -n 1p)
  356. BLOCK=$(cat $data | sed -n 2p)
  357. if [ ${#BLOCK_EMAIL} -lt 2 ]; then
  358. dialog --title $"Block/Unblock an email" \
  359. --msgbox $"No email address was given" 6 40
  360. return
  361. fi
  362. if [[ "$BLOCK_EMAIL" != *"@"* || "$BLOCK_EMAIL" != *"."* ]]; then
  363. dialog --title $"Block/Unblock an email" \
  364. --msgbox $"Unrecognised email address" 6 40
  365. return
  366. fi
  367. if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
  368. ${PROJECT_NAME}-ignore -u $SELECTED_USERNAME -e "$BLOCK_EMAIL"
  369. dialog --title $"Block an email" \
  370. --msgbox "Email from $BLOCK_EMAIL to $SELECTED_USERNAME blocked" 6 40
  371. else
  372. ${PROJECT_NAME}-unignore -u $SELECTED_USERNAME -e "$BLOCK_EMAIL"
  373. dialog --title $"Unblock an email" \
  374. --msgbox "Email from $BLOCK_EMAIL to $SELECTED_USERNAME unblocked" 6 40
  375. fi
  376. }
  377. function block_unblock_subject {
  378. select_user
  379. if [ ! $SELECTED_USERNAME ]; then
  380. return
  381. fi
  382. blockstr=$"Block/Unblock email going to"
  383. data=$(tempfile 2>/dev/null)
  384. trap "rm -f $data" 0 1 2 5 15
  385. dialog --backtitle $"Freedombone Control Panel" \
  386. --title "$blockstr $SELECTED_USERNAME" \
  387. --form "\n" 8 70 3 \
  388. $"When email arrives with subject text:" 1 1 "" 1 40 24 28 \
  389. $"Block it:" 2 1 "yes" 2 40 4 4 \
  390. 2> $data
  391. sel=$?
  392. case $sel in
  393. 1) return;;
  394. 255) return;;
  395. esac
  396. BLOCK_SUBJECT=$(cat $data | sed -n 1p)
  397. BLOCK=$(cat $data | sed -n 2p)
  398. if [ ${#BLOCK_SUBJECT} -lt 2 ]; then
  399. dialog --title $"Block/Unblock an email" \
  400. --msgbox $"No subject was given" 6 40
  401. return
  402. fi
  403. if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
  404. ${PROJECT_NAME}-ignore -u $SELECTED_USERNAME -t "$BLOCK_SUBJECT"
  405. dialog --title $"Block an email" \
  406. --msgbox "Email with subject $BLOCK_SUBJECT to $SELECTED_USERNAME blocked" 6 40
  407. else
  408. ${PROJECT_NAME}-unignore -u $SELECTED_USERNAME -t "$BLOCK_SUBJECT"
  409. dialog --title $"Unblock an email" \
  410. --msgbox "Email with subject $BLOCK_SUBJECT to $SELECTED_USERNAME unblocked" 6 40
  411. fi
  412. }
  413. function create_keydrive_master {
  414. select_user
  415. if [ ! $SELECTED_USERNAME ]; then
  416. return
  417. fi
  418. dialog --title $"USB Master Keydrive" \
  419. --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
  420. clear
  421. ${PROJECT_NAME}-keydrive -u $SELECTED_USERNAME --master 'yes'
  422. any_key
  423. }
  424. function create_keydrive_fragment {
  425. select_user
  426. if [ ! $SELECTED_USERNAME ]; then
  427. return
  428. fi
  429. dialog --title $"USB Fragment Keydrive" \
  430. --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
  431. clear
  432. ${PROJECT_NAME}-keydrive -u $SELECTED_USERNAME
  433. any_key
  434. }
  435. function backup_data {
  436. dialog --title $"Backup data to USB" \
  437. --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
  438. clear
  439. echo ' '
  440. echo $'Enter the passphrase for your LUKS encrypted backup drive:'
  441. backup
  442. any_key
  443. }
  444. function restore_data {
  445. dialog --title $"Restore data from USB" \
  446. --msgbox $"Plug in your backup USB drive" 6 40
  447. clear
  448. echo ' '
  449. echo $'Enter the passphrase for your LUKS encrypted backup drive:'
  450. restore
  451. any_key
  452. }
  453. function restore_data_remote {
  454. if [ ! $ADMIN_USER ]; then
  455. dialog --title $"Restore data from remote server" \
  456. --msgbox $"Unknown admin user" 6 40
  457. return
  458. fi
  459. data=$(tempfile 2>/dev/null)
  460. trap "rm -f $data" 0 1 2 5 15
  461. dialog --title $"Restore from remote server" \
  462. --backtitle $"Freedombone Control Panel" \
  463. --inputbox $"Enter the domain name of the server from which you wish to restore" 8 60 2>$data
  464. sel=$?
  465. case $sel in
  466. 0)
  467. friend_server_domain_name=$(<$data)
  468. if [ ${#friend_server_domain_name} -lt 2 ]; then
  469. return
  470. fi
  471. if [[ $friend_server_domain_name != *"."* ]]; then
  472. dialog --title $"Remote server domain name" \
  473. --msgbox $"Invalid domain name" 6 40
  474. return
  475. fi
  476. restorefromfriend $friend_server_domain_name
  477. any_key
  478. ;;
  479. esac
  480. }
  481. function logging_on_off {
  482. logging="no"
  483. dialog --title $"Logging" \
  484. --backtitle $"Freedombone Control Panel" \
  485. --yesno $"\nDo you want to turn logging on?" 7 60
  486. sel=$?
  487. case $sel in
  488. 0) logging="yes";;
  489. 255) return;;
  490. esac
  491. clear
  492. echo ''
  493. echo $'This may take a few seconds. Please wait...'
  494. if [[ $logging == "no" ]]; then
  495. ${PROJECT_NAME}-logging off
  496. else
  497. ${PROJECT_NAME}-logging on
  498. fi
  499. }
  500. function restore_gpg_key {
  501. select_user
  502. if [ ! $SELECTED_USERNAME ]; then
  503. return
  504. fi
  505. restorestr=$"Restore GPG key for user"
  506. dialog --title "$restorestr $SELECTED_USERNAME" \
  507. --msgbox $"Plug in your USB keydrive" 6 40
  508. clear
  509. ${PROJECT_NAME}-recoverkey -u $SELECTED_USERNAME
  510. any_key
  511. }
  512. function security_settings {
  513. ${PROJECT_NAME}-sec
  514. any_key
  515. }
  516. function reset_tripwire {
  517. clear
  518. echo $'Resetting the Tripwire...'
  519. echo ' '
  520. echo '
  521. ' | reset-tripwire
  522. any_key
  523. }
  524. function hubzilla_renew_cert {
  525. dialog --title $"Renew SSL certificate" \
  526. --backtitle $"Freedombone Control Panel" \
  527. --yesno $"\nThis will renew a letsencrypt certificate. Select 'yes' to continue" 16 60
  528. sel=$?
  529. case $sel in
  530. 1) return;;
  531. 255) return;;
  532. esac
  533. HUBZILLA_DOMAIN_NAME=$(cat $COMPLETION_FILE | grep "Hubzilla domain" | awk -F ':' '{print $2}')
  534. if [ ! -d /var/www/$HUBZILLA_DOMAIN_NAME/htdocs ]; then
  535. dialog --title $"Renew SSL certificate" \
  536. --msgbox $"Hubzilla install directory not found" 6 40
  537. return
  538. fi
  539. ${PROJECT_NAME}-renew-cert -h $HUBZILLA_DOMAIN_NAME -p 'letsencrypt'
  540. if [ ! "$?" = "0" ]; then
  541. any_key
  542. else
  543. dialog --title $"Renew SSL certificate" \
  544. --msgbox $"Hubzilla certificate has been renewed" 6 40
  545. fi
  546. }
  547. function hubzilla_restore {
  548. dialog --title $"Restore hubzilla from USB backup" \
  549. --backtitle $"Freedombone Control Panel" \
  550. --yesno $"\nInsert your USB backup drive and select 'yes' to continue" 16 60
  551. sel=$?
  552. case $sel in
  553. 1) return;;
  554. 255) return;;
  555. esac
  556. clear
  557. echo $'Enter your backup drive password:'
  558. restorehubzilla
  559. }
  560. function hubzilla_channel_directory_server {
  561. if ! grep -q "Hubzilla domain" $COMPLETION_FILE; then
  562. dialog --title $"Hubzilla channel directory server" \
  563. --msgbox $"Hubzilla is not installed on this system" 6 40
  564. return
  565. fi
  566. HUBZILLA_DOMAIN_NAME=$(cat $COMPLETION_FILE | grep "Hubzilla domain" | awk -F ':' '{print $2}')
  567. if [ ! -d /var/www/$HUBZILLA_DOMAIN_NAME/htdocs ]; then
  568. dialog --title $"Hubzilla channel directory server" \
  569. --msgbox $"Hubzilla install directory not found" 6 40
  570. return
  571. fi
  572. data=$(tempfile 2>/dev/null)
  573. trap "rm -f $data" 0 1 2 5 15
  574. dialog --title $"Hubzilla channel directory server" \
  575. --backtitle $"Freedombone Control Panel" \
  576. --inputbox $"When you click on 'channel directory' this is where Hubzilla will obtain its list from" 8 60 2>$data
  577. sel=$?
  578. case $sel in
  579. 0)
  580. hubzilla_domain_server=$(<$data)
  581. if [[ $hubzilla_domain_server != *"."* ]]; then
  582. return
  583. fi
  584. if [[ $hubzilla_domain_server != "https"* ]]; then
  585. dialog --title $"Hubzilla channel directory server" \
  586. --msgbox $"Invalid domain - include the https://" 6 40
  587. return
  588. fi
  589. ./var/www/$HUBZILLA_DOMAIN_NAME/htdocs/util/config system directory_server $hubzilla_domain_server
  590. dialog --title $"Hubzilla channel directory server" \
  591. --msgbox $"Domain channel directory server changed to $hubzilla_domain_server" 6 40
  592. ;;
  593. esac
  594. }
  595. function format_drive {
  596. drive=
  597. data=$(tempfile 2>/dev/null)
  598. trap "rm -f $data" 0 1 2 5 15
  599. dialog --backtitle $"Freedombone Control Panel" \
  600. --title $"Format a USB drive (LUKS encrypted)" \
  601. --radiolist $"Choose a drive:" 12 70 5 \
  602. 1 $"sda (Beaglebone Black)" off \
  603. 2 $"sdb" off \
  604. 3 $"sdc" off \
  605. 4 $"sdd" off \
  606. 5 $"Back to Backup and Restore menu" on 2> $data
  607. sel=$?
  608. case $sel in
  609. 1) return;;
  610. 255) return;;
  611. esac
  612. case $(cat $data) in
  613. 1) drive='sda';;
  614. 2) drive='sdb';;
  615. 3) drive='sdc';;
  616. 4) drive='sdd';;
  617. 5) return;;
  618. esac
  619. dialog --title $"Format USB drive" \
  620. --backtitle $"Freedombone Control Panel" \
  621. --defaultno \
  622. --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
  623. sel=$?
  624. case $sel in
  625. 1) return;;
  626. 255) return;;
  627. esac
  628. clear
  629. ${PROJECT_NAME}-format $drive
  630. any_key
  631. }
  632. function remove_backups {
  633. drive=
  634. data=$(tempfile 2>/dev/null)
  635. trap "rm -f $data" 0 1 2 5 15
  636. dialog --backtitle $"Freedombone Control Panel" \
  637. --title $"Remove backups from a USB drive" \
  638. --radiolist $"Choose a drive:" 12 70 5 \
  639. 1 $"sda (Beaglebone Black)" off \
  640. 2 $"sdb" off \
  641. 3 $"sdc" off \
  642. 4 $"sdd" off \
  643. 5 $"Back to Backup and Restore menu" on 2> $data
  644. sel=$?
  645. case $sel in
  646. 1) return;;
  647. 255) return;;
  648. esac
  649. case $(cat $data) in
  650. 1) drive='sda';;
  651. 2) drive='sdb';;
  652. 3) drive='sdc';;
  653. 4) drive='sdd';;
  654. 5) return;;
  655. esac
  656. dialog --title $"Remove backups from a USB drive" \
  657. --backtitle $"Freedombone Control Panel" \
  658. --defaultno \
  659. --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
  660. sel=$?
  661. case $sel in
  662. 1) return;;
  663. 255) return;;
  664. esac
  665. clear
  666. ${PROJECT_NAME}-backup-local $drive remove
  667. any_key
  668. }
  669. function shut_down_system {
  670. dialog --title $"Power off the system" \
  671. --backtitle $"Freedombone Control Panel" \
  672. --defaultno \
  673. --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
  674. sel=$?
  675. case $sel in
  676. 1) return;;
  677. 255) return;;
  678. esac
  679. shutdown now
  680. }
  681. function restart_system {
  682. dialog --title $"Restart the system" \
  683. --backtitle $"Freedombone Control Panel" \
  684. --defaultno \
  685. --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
  686. sel=$?
  687. case $sel in
  688. 1) return;;
  689. 255) return;;
  690. esac
  691. reboot
  692. }
  693. function change_system_name {
  694. data=$(tempfile 2>/dev/null)
  695. trap "rm -f $data" 0 1 2 5 15
  696. dialog --title $"Change the name of this system" \
  697. --backtitle $"Freedombone Control Panel" \
  698. --inputbox $'Enter a new name for this system on your local network\n\nIt will appear as newname.local' 10 60 2>$data
  699. sel=$?
  700. case $sel in
  701. 0) NEW_SYSTEM_NAME=$(<$data)
  702. if [ "$NEW_SYSTEM_NAME" ]; then
  703. if [ ${#NEW_SYSTEM_NAME} -gt 1 ]; then
  704. sed -i "s|host-name=.*|host-name=$NEW_SYSTEM_NAME|g" /etc/avahi/avahi-daemon.conf
  705. systemctl restart avahi-daemon
  706. if grep -q "host-name=$NEW_SYSTEM_NAME" /etc/avahi/avahi-daemon.conf; then
  707. dialog --title $"New local network name" \
  708. --msgbox $"The name of this system on your local network was changed successfully" 6 70
  709. fi
  710. fi
  711. fi
  712. ;;
  713. esac
  714. }
  715. function set_tls_time_source {
  716. TLS_DATE_SOURCE=$(cat /usr/bin/updatedate | grep "TIMESOURCE='" | awk -F '=' '{print $2}' | awk -F "'" '{print $2}')
  717. data=$(tempfile 2>/dev/null)
  718. trap "rm -f $data" 0 1 2 5 15
  719. dialog --title $"Set the TLS date/time source" \
  720. --backtitle $"Freedombone Control Panel" \
  721. --inputbox $"Enter a domain name to use as a TLS time source.\n\nFactors to consider when choosing a source are whether you wish that site to know that your system is 'alive' and also what might happen if an adversary were to try to mess with the date/time from that domain (i.e. how much blowback would there be)." 14 60 "$TLS_DATE_SOURCE" 2>$data
  722. sel=$?
  723. case $sel in
  724. 0) NEW_TLS_DATE_SOURCE=$(<$data)
  725. if [[ $NEW_TLS_DATE_SOURCE == *"."* && $NEW_TLS_DATE_SOURCE != *'/'* ]]; then
  726. if [[ $NEW_TLS_DATE_SOURCE != "http"* ]]; then
  727. sed -i "s|TIMESOURCE='.*|TIMESOURCE='${NEW_TLS_DATE_SOURCE}'|g" $UPDATE_DATE_SCRIPT
  728. else
  729. dialog --title $"Invalid domain name" \
  730. --msgbox $"Don't include the 'https'" 6 70
  731. fi
  732. else
  733. dialog --title $"Invalid domain name" \
  734. --msgbox $"That doesn't look like a domain name" 6 70
  735. fi
  736. ;;
  737. esac
  738. }
  739. function set_static_IP {
  740. STATIC_IP='192.168.1.60'
  741. STATIC_GATEWAY='192.168.1.1'
  742. NEW_STATIC_IP=
  743. NEW_STATIC_GATEWAY=
  744. if grep -q 'iface eth0 inet static' /etc/network/interfaces; then
  745. STATIC_IP=$(cat /etc/network/interfaces | grep "address " | awk -F ' ' '{print $2}' | head -n 1)
  746. STATIC_GATEWAY=$(cat /etc/network/interfaces | grep "gateway " | awk -F ' ' '{print $2}' | head -n 1)
  747. fi
  748. # get the IP for the box
  749. data=$(tempfile 2>/dev/null)
  750. trap "rm -f $data" 0 1 2 5 15
  751. dialog --title $"Set a static local IP address" \
  752. --backtitle $"Freedombone Control Panel" \
  753. --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
  754. Enter a static local IP address for this system.\n\nIt will typically be 192.168.1.x" 15 60 "$STATIC_IP" 2>$data
  755. sel=$?
  756. case $sel in
  757. 0) NEW_STATIC_IP=$(<$data)
  758. if [[ "$NEW_STATIC_IP" != *"."* ]]; then
  759. return
  760. fi
  761. if grep -q 'iface eth0 inet static' /etc/network/interfaces; then
  762. if [[ "$NEW_STATIC_IP" != "$STATIC_IP" ]]; then
  763. sed -i "s|${STATIC_IP}|${NEW_STATIC_IP}|g" /etc/network/interfaces
  764. fi
  765. fi
  766. ;;
  767. esac
  768. # get the gateway
  769. data=$(tempfile 2>/dev/null)
  770. trap "rm -f $data" 0 1 2 5 15
  771. dialog --title $"Set the IP address of your internet router/modem" \
  772. --backtitle $"Freedombone Control Panel" \
  773. --inputbox $"Set the local IP address for your internet router or ADSL modem.\n\nIt will typically be 192.168.1.1, 192.168.1.254, or similar" 12 60 "$STATIC_GATEWAY" 2>$data
  774. sel=$?
  775. case $sel in
  776. 0) NEW_STATIC_GATEWAY=$(<$data)
  777. if [[ "$NEW_STATIC_GATEWAY" != *"."* ]]; then
  778. return
  779. fi
  780. if grep -q 'iface eth0 inet static' /etc/network/interfaces; then
  781. if [[ "$NEW_STATIC_GATEWAY" != "$STATIC_GATEWAY" ]]; then
  782. sed -i "s|${STATIC_GATEWAY}|${NEW_STATIC_GATEWAY}|g" /etc/network/interfaces
  783. fi
  784. return
  785. fi
  786. ;;
  787. esac
  788. if ! grep -q 'iface eth0 inet static' /etc/network/interfaces; then
  789. if [ "$NEW_STATIC_GATEWAY" && "$NEW_STATIC_IP" ]; then
  790. echo '# This file describes the network interfaces available on your system' > /etc/network/interfaces
  791. echo '# and how to activate them. For more information, see interfaces(5).' >> /etc/network/interfaces
  792. echo '' >> /etc/network/interfaces
  793. echo '# The loopback network interface' >> /etc/network/interfaces
  794. echo 'auto lo' >> /etc/network/interfaces
  795. echo 'iface lo inet loopback' >> /etc/network/interfaces
  796. echo '' >> /etc/network/interfaces
  797. echo '# The primary network interface' >> /etc/network/interfaces
  798. echo 'auto eth0' >> /etc/network/interfaces
  799. echo 'iface eth0 inet static' >> /etc/network/interfaces
  800. echo " address ${NEW_STATIC_IP}" >> /etc/network/interfaces
  801. echo ' netmask 255.255.255.0' >> /etc/network/interfaces
  802. echo " gateway ${NEW_STATIC_GATEWAY}" >> /etc/network/interfaces
  803. echo " dns-nameservers 213.73.91.35 85.214.20.141" >> /etc/network/interfaces
  804. echo '# Example to keep MAC address between reboots' >> /etc/network/interfaces
  805. echo '#hwaddress ether DE:AD:BE:EF:CA:FE' >> /etc/network/interfaces
  806. echo '' >> /etc/network/interfaces
  807. echo '# The secondary network interface' >> /etc/network/interfaces
  808. echo '#auto eth1' >> /etc/network/interfaces
  809. echo '#iface eth1 inet dhcp' >> /etc/network/interfaces
  810. echo '' >> /etc/network/interfaces
  811. echo '# WiFi Example' >> /etc/network/interfaces
  812. echo "#auto $WIFI_INTERFACE" >> /etc/network/interfaces
  813. echo "#iface $WIFI_INTERFACE inet dhcp" >> /etc/network/interfaces
  814. echo '# wpa-ssid "essid"' >> /etc/network/interfaces
  815. echo '# wpa-psk "password"' >> /etc/network/interfaces
  816. echo '' >> /etc/network/interfaces
  817. echo '# Ethernet/RNDIS gadget (g_ether)' >> /etc/network/interfaces
  818. echo '# ... or on host side, usbnet and random hwaddr' >> /etc/network/interfaces
  819. echo '# Note on some boards, usb0 is automaticly setup with an init script' >> /etc/network/interfaces
  820. echo '#iface usb0 inet static' >> /etc/network/interfaces
  821. echo '# address 192.168.7.2' >> /etc/network/interfaces
  822. echo '# netmask 255.255.255.0' >> /etc/network/interfaces
  823. echo '# network 192.168.7.0' >> /etc/network/interfaces
  824. echo '# gateway 192.168.7.1' >> /etc/network/interfaces
  825. fi
  826. fi
  827. }
  828. function menu_backup_restore {
  829. while true
  830. do
  831. data=$(tempfile 2>/dev/null)
  832. trap "rm -f $data" 0 1 2 5 15
  833. dialog --backtitle $"Freedombone Control Panel" \
  834. --title $"Backup and Restore" \
  835. --radiolist $"Choose an operation:" 18 70 11 \
  836. 1 $"Backup data to USB drive" off \
  837. 2 $"Restore GPG key from USB keydrive" off \
  838. 3 $"Restore data from USB drive" off \
  839. 4 $"Restore Hubzilla data from USB drive" off \
  840. 5 $"Configure remote backups" off \
  841. 6 $"Restore from remote backup" off \
  842. 7 $"Backup GPG key to USB (master keydrive)" off \
  843. 8 $"Backup GPG key to USB (fragment keydrive)" off \
  844. 9 $"Format a USB drive (LUKS encrypted)" off \
  845. 10 $"Remove backups from a USB drive" off \
  846. 11 $"Back to main menu" on 2> $data
  847. sel=$?
  848. case $sel in
  849. 1) break;;
  850. 255) break;;
  851. esac
  852. case $(cat $data) in
  853. 1) backup_data;;
  854. 2) restore_gpg_key;;
  855. 3) restore_data;;
  856. 4) hubzilla_restore;;
  857. 5) configure_remote_backups;;
  858. 6) restore_data_remote;;
  859. 7) create_keydrive_master;;
  860. 8) create_keydrive_fragment;;
  861. 9) format_drive;;
  862. 10) remove_backups;;
  863. 11) break;;
  864. esac
  865. done
  866. }
  867. function menu_email {
  868. while true
  869. do
  870. data=$(tempfile 2>/dev/null)
  871. trap "rm -f $data" 0 1 2 5 15
  872. dialog --backtitle $"Freedombone Control Panel" \
  873. --title $"Email Filtering Rules" \
  874. --radiolist $"Choose an operation:" 12 70 5 \
  875. 1 $"Add a user to a mailing list" off \
  876. 2 $"Add an email rule" off \
  877. 3 $"Block/Unblock an email address" off \
  878. 4 $"Block/Unblock email with subject text" off \
  879. 5 $"Back to main menu" on 2> $data
  880. sel=$?
  881. case $sel in
  882. 1) break;;
  883. 255) break;;
  884. esac
  885. case $(cat $data) in
  886. 1) add_to_mailing_list;;
  887. 2) email_rule;;
  888. 3) block_unblock_email;;
  889. 4) block_unblock_subject;;
  890. 5) break;;
  891. esac
  892. done
  893. }
  894. function menu_users {
  895. while true
  896. do
  897. data=$(tempfile 2>/dev/null)
  898. trap "rm -f $data" 0 1 2 5 15
  899. dialog --backtitle $"Freedombone Control Panel" \
  900. --title $"Manage Users" \
  901. --radiolist $"Choose an operation:" 12 70 5 \
  902. 1 $"Add a user" off \
  903. 2 $"Delete a user" off \
  904. 3 $"Change user password" off \
  905. 4 $"Change user ssh public key" off \
  906. 5 $"Back to main menu" on 2> $data
  907. sel=$?
  908. case $sel in
  909. 1) break;;
  910. 255) break;;
  911. esac
  912. case $(cat $data) in
  913. 1) add_user;;
  914. 2) delete_user;;
  915. 3) change_password;;
  916. 4) change_ssh_public_key;;
  917. 5) break;;
  918. esac
  919. done
  920. }
  921. function menu_hubzilla {
  922. while true
  923. do
  924. data=$(tempfile 2>/dev/null)
  925. trap "rm -f $data" 0 1 2 5 15
  926. dialog --backtitle $"Freedombone Control Panel" \
  927. --title $"Hubzilla" \
  928. --radiolist $"Choose an operation:" 13 70 4 \
  929. 1 $"Restore from usb backup" off \
  930. 2 $"Set channel directory server" off \
  931. 3 $"Renew SSL certificate" off \
  932. 4 $"Back to main menu" on 2> $data
  933. sel=$?
  934. case $sel in
  935. 1) break;;
  936. 255) break;;
  937. esac
  938. case $(cat $data) in
  939. 1) hubzilla_restore;;
  940. 2) hubzilla_channel_directory_server;;
  941. 3) hubzilla_renew_cert;;
  942. 4) break;;
  943. esac
  944. done
  945. }
  946. function menu_media {
  947. while true
  948. do
  949. data=$(tempfile 2>/dev/null)
  950. trap "rm -f $data" 0 1 2 5 15
  951. dialog --backtitle $"Freedombone Control Panel" \
  952. --title $"Media Menu" \
  953. --radiolist $"Choose an operation:" 13 70 3 \
  954. 1 $"Attach a drive containing playable media" off \
  955. 2 $"Remove a drive containing playable media" off \
  956. 3 $"Exit" on 2> $data
  957. sel=$?
  958. case $sel in
  959. 1) break;;
  960. 255) break;;
  961. esac
  962. case $(cat $data) in
  963. 1) remove-music
  964. attach-music;;
  965. 2) remove-music;;
  966. 3) break;;
  967. esac
  968. done
  969. }
  970. function menu_irc {
  971. while true
  972. do
  973. data=$(tempfile 2>/dev/null)
  974. trap "rm -f $data" 0 1 2 5 15
  975. dialog --backtitle $"Freedombone Control Panel" \
  976. --title $"IRC Menu" \
  977. --radiolist $"Choose an operation:" 13 70 3 \
  978. 1 $"Set a password for all IRC users" off \
  979. 2 $"Exit" on 2> $data
  980. sel=$?
  981. case $sel in
  982. 1) break;;
  983. 255) break;;
  984. esac
  985. case $(cat $data) in
  986. 1) irc_set_global_password;;
  987. 2) break;;
  988. esac
  989. done
  990. }
  991. function menu_top_level {
  992. while true
  993. do
  994. data=$(tempfile 2>/dev/null)
  995. trap "rm -f $data" 0 1 2 5 15
  996. dialog --backtitle $"Freedombone Control Panel" \
  997. --title $"Control Panel" \
  998. --radiolist $"Choose an operation:" 24 70 17 \
  999. 1 $"Backup and Restore" off \
  1000. 2 $"Show SIP Phone Extensions" off \
  1001. 3 $"Reset Tripwire" off \
  1002. 4 $"Logging on/off" off \
  1003. 5 $"Manage Users" off \
  1004. 6 $"Email Filtering Rules" off \
  1005. 7 $"Security Settings" off \
  1006. 8 $"Hubzilla" off \
  1007. 9 $"Media menu" off \
  1008. 10 $"IRC menu" off \
  1009. 11 $"Change the name of this system" off \
  1010. 12 $"Set the TLS date/time source" off \
  1011. 13 $"Set a static local IP address" off \
  1012. 14 $"Check for updates" off \
  1013. 15 $"Power off the system" off \
  1014. 16 $"Restart the system" off \
  1015. 17 $"Exit" on 2> $data
  1016. sel=$?
  1017. case $sel in
  1018. 1) exit 1;;
  1019. 255) exit 1;;
  1020. esac
  1021. case $(cat $data) in
  1022. 1) menu_backup_restore;;
  1023. 2) show_sip_extensions;;
  1024. 3) reset_tripwire;;
  1025. 4) logging_on_off;;
  1026. 5) menu_users;;
  1027. 6) menu_email;;
  1028. 7) security_settings;;
  1029. 8) menu_hubzilla;;
  1030. 9) menu_media;;
  1031. 10) menu_irc;;
  1032. 11) change_system_name;;
  1033. 12) set_tls_time_source;;
  1034. 13) set_static_IP;;
  1035. 14) check_for_updates;;
  1036. 15) shut_down_system;;
  1037. 16) restart_system;;
  1038. 17) break;;
  1039. esac
  1040. done
  1041. }
  1042. if [ ! -f $COMPLETION_FILE ]; then
  1043. echo $'This command should only be run on an installed Freedombone system'
  1044. exit 1
  1045. fi
  1046. ADMIN_USER=$(cat $COMPLETION_FILE | grep "Admin user" | awk -F ':' '{print $2}')
  1047. menu_top_level
  1048. clear
  1049. cat /etc/motd
  1050. exit 0