freedombone-controlpanel-user 33KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  1. #!/bin/bash
  2. # _____ _ _
  3. # | __|___ ___ ___ _| |___ _____| |_ ___ ___ ___
  4. # | __| _| -_| -_| . | . | | . | . | | -_|
  5. # |__| |_| |___|___|___|___|_|_|_|___|___|_|_|___|
  6. #
  7. # Freedom in the Cloud
  8. #
  9. # User control panel
  10. #
  11. # License
  12. # =======
  13. #
  14. # Copyright (C) 2018 Bob Mottram <bob@freedombone.net>
  15. #
  16. # This program is free software: you can redistribute it and/or modify
  17. # it under the terms of the GNU Affero General Public License as published by
  18. # the Free Software Foundation, either version 3 of the License, or
  19. # (at your option) any later version.
  20. #
  21. # This program is distributed in the hope that it will be useful,
  22. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. # GNU Affero General Public License for more details.
  25. #
  26. # You should have received a copy of the GNU Affero General Public License
  27. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  28. PROJECT_NAME='freedombone'
  29. export TEXTDOMAIN=${PROJECT_NAME}-controlpanel-user
  30. export TEXTDOMAINDIR="/usr/share/locale"
  31. MY_EMAIL_ADDRESS=$USER@$HOSTNAME
  32. GPG_ID=$(gpg --list-keys "$MY_EMAIL_ADDRESS" | sed -n '2p' | sed 's/^[ \t]*//')
  33. GPG_BACKUP_ID=$(gpg --list-keys "(backup key)" | sed -n '2p' | sed 's/^[ \t]*//')
  34. # If the default key is specified within gpg.conf
  35. if [ -f ~/.gnupg/gpg.conf ]; then
  36. if grep -q "default-key" ~/.gnupg/gpg.conf; then
  37. default_gpg_key=$(grep "default-key" ~/.gnupg/gpg.conf)
  38. if [[ "$default_gpg_key" != *'#'* ]]; then
  39. default_gpg_key=$(grep "default-key" ~/.gnupg/gpg.conf | awk -F ' ' '{print $2}')
  40. if [ ${#default_gpg_key} -gt 3 ]; then
  41. GPG_ID=$(gpg --list-keys "$default_gpg_key" | sed -n '2p' | sed 's/^[ \t]*//')
  42. fi
  43. fi
  44. fi
  45. fi
  46. # Start including files
  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. # End including files
  58. function any_key {
  59. echo ' '
  60. # shellcheck disable=SC2034
  61. read -n1 -r -p $"Press any key to continue..." key
  62. }
  63. function remove_user_from_mailing_list {
  64. # shellcheck disable=SC1003
  65. USER_MAILING_LISTS=$(grep '\[' "/home/$USER/.procmailrc" | grep '\]' | awk -F '\[' '{print $2}' | awk -F '\\' '{print $1}')
  66. i=0
  67. W=()
  68. list_name=()
  69. while read -r listname; do
  70. i=$((i+1))
  71. if [[ "$listname" != *']'* && "$listname" != *'['* ]]; then
  72. W+=("$i" "$listname")
  73. list_name+=("$listname")
  74. echo "$listname"
  75. fi
  76. done <<< "$USER_MAILING_LISTS"
  77. i=$((i+1))
  78. W+=("$i" $"Exit back to filtering rules menu")
  79. # shellcheck disable=SC2068
  80. list_selected=$(dialog --default-item "$i" --backtitle $"Freedombone User Control Panel" --title $"Remove yourself from a mailing list" --menu $"Select one of the following:" 24 50 17 ${W[@]} 3>&2 2>&1 1>&3)
  81. # shellcheck disable=SC2181
  82. if [ $? -eq 0 ]; then # Exit with OK
  83. if [ "${list_selected}" -ne "${i}" ]; then
  84. remove_list_name="${list_name[$((list_selected-1))]}"
  85. # find the line number where the list is defined
  86. line_number=0
  87. i=0
  88. while read -r line
  89. do
  90. if [[ "$line" == *"\\[${remove_list_name}\\]"* ]]; then
  91. line_number=${i}
  92. fi
  93. i=$((i+1))
  94. done < "/home/$USER/.procmailrc"
  95. if [ ${line_number} -eq 0 ]; then
  96. # no match was found
  97. return
  98. fi
  99. # recreate the file
  100. if [ -f "/home/${USER}/.procmailrc_new" ]; then
  101. rm "/home/${USER}/.procmailrc_new"
  102. fi
  103. i=0
  104. clip=0
  105. while read -r line
  106. do
  107. i=$((i+1))
  108. if [ ${i} -gt $((line_number-1)) ]; then
  109. if [ ${clip} -eq 0 ]; then
  110. clip=1
  111. fi
  112. if [ ${clip} -eq 1 ]; then
  113. if [ ${i} -lt $((line_number+2)) ]; then
  114. continue
  115. else
  116. if [ ${#line} -lt 1 ]; then
  117. clip=2
  118. continue
  119. fi
  120. if [[ "$line" == ":"* || "$line" == "#"* ]]; then
  121. clip=2
  122. else
  123. continue
  124. fi
  125. fi
  126. fi
  127. fi
  128. echo "$line" >> "/home/${USER}/.procmailrc_new"
  129. if [[ "$line" == *"\\[${remove_list_name}\\]"* ]]; then
  130. line_number=${i}
  131. fi
  132. done < "/home/$USER/.procmailrc"
  133. cp "/home/${USER}/.procmailrc_new" "/home/${USER}/.procmailrc"
  134. rm "/home/${USER}/.procmailrc_new"
  135. chown "${USER}":"${USER}" "/home/${USER}/.procmailrc"
  136. dialog --title $"Remove yourself from mailing list" \
  137. --msgbox $"You have been removed from ${remove_list_name}" 6 50
  138. fi
  139. fi
  140. }
  141. function add_to_mailing_list {
  142. data=$(mktemp 2>/dev/null)
  143. dialog --backtitle $"Freedombone User Control Panel" \
  144. --title $"Subscribe to a mailing list" \
  145. --form $"You can either enter a subject or an email address\\n" 11 68 4 \
  146. $"List folder name:" 1 1 "" 1 35 26 25 \
  147. $"Name between [] on subject line:" 2 1 "" 2 35 26 25 \
  148. $"List email address:" 3 1 "" 3 35 26 25 \
  149. $"Public:" 4 1 $"yes" 4 35 4 25 \
  150. 2> "$data"
  151. sel=$?
  152. case $sel in
  153. 1) rm -f "$data"
  154. return;;
  155. 255) rm -f "$data"
  156. return;;
  157. esac
  158. LIST_NAME=$(sed -n 1p < "$data")
  159. LIST_SUBJECT=$(sed -n 2p < "$data")
  160. LIST_EMAIL=$(sed -n 3p < "$data")
  161. LIST_PUBLIC=$(sed -n 4p < "$data")
  162. if [ ${#LIST_PUBLIC} -lt 1 ]; then
  163. LIST_PUBLIC='no'
  164. fi
  165. if [[ $LIST_PUBLIC == $'y' || $LIST_PUBLIC == $'Y' || $LIST_PUBLIC == $'true' || $LIST_PUBLIC == $'True' || $LIST_PUBLIC == $'yes' || $LIST_PUBLIC == $'Yes' || $LIST_PUBLIC == $'YES' ]]; then
  166. LIST_PUBLIC='yes'
  167. else
  168. LIST_PUBLIC='no'
  169. fi
  170. if [ ${#LIST_NAME} -lt 2 ]; then
  171. dialog --title $"Add mailing list" \
  172. --msgbox $"No mailing list name was given" 6 40
  173. rm -f "$data"
  174. return
  175. fi
  176. if [ ${#LIST_SUBJECT} -lt 2 ]; then
  177. if [ ${#LIST_EMAIL} -lt 2 ]; then
  178. dialog --title $"Add mailing list" \
  179. --msgbox $"No mailing list subject or address was given" 6 40
  180. rm -f "$data"
  181. return
  182. fi
  183. fi
  184. if [ ${#LIST_SUBJECT} -gt 1 ]; then
  185. "${PROJECT_NAME}-addlist" -u "$USER" -l "$LIST_NAME" \
  186. -s "$LIST_SUBJECT" --public "$LIST_PUBLIC"
  187. else
  188. if [[ "$LIST_EMAIL" != *"@"* || "$LIST_EMAIL" != *"."* ]]; then
  189. dialog --title $"Add mailing list" \
  190. --msgbox $"Unrecognised email address" 6 40
  191. rm -f "$data"
  192. return
  193. else
  194. "${PROJECT_NAME}-addlist" -u "$USER" -l "$LIST_NAME" \
  195. -e "$LIST_EMAIL" --public "$LIST_PUBLIC"
  196. fi
  197. fi
  198. dialog --title $"Add mailing list" \
  199. --msgbox $"$LIST_NAME list was added" 6 40
  200. rm -f "$data"
  201. }
  202. function email_rule_address {
  203. data=$(mktemp 2>/dev/null)
  204. dialog --backtitle $"Freedombone User Control Panel" \
  205. --title $"Create an email rule" \
  206. --form "\\n" 9 65 4 \
  207. $"When email arrives from address:" 1 1 "" 1 35 24 28 \
  208. $"Move to folder:" 2 1 "" 2 35 24 28 \
  209. $"Public:" 3 1 $"no" 3 35 4 25 \
  210. 2> "$data"
  211. sel=$?
  212. case $sel in
  213. 1) rm -f "$data"
  214. return;;
  215. 255) rm -f "$data"
  216. return;;
  217. esac
  218. RULE_EMAIL=$(sed -n 1p < "$data")
  219. RULE_FOLDER=$(sed -n 2p < "$data")
  220. RULE_PUBLIC=$(sed -n 3p < "$data")
  221. if [ ${#RULE_PUBLIC} -lt 1 ]; then
  222. RULE_PUBLIC='no'
  223. fi
  224. if [[ $RULE_PUBLIC == $'y' || $RULE_PUBLIC == $'Y' || $RULE_PUBLIC == $'true' || $RULE_PUBLIC == $'True' || $RULE_PUBLIC == $'yes' || $RULE_PUBLIC == $'Yes' || $RULE_PUBLIC == $'YES' ]]; then
  225. RULE_PUBLIC='yes'
  226. else
  227. RULE_PUBLIC='no'
  228. fi
  229. if [ ${#RULE_EMAIL} -lt 2 ]; then
  230. dialog --title $"Create an email rule" \
  231. --msgbox $"No email address was given" 6 40
  232. rm -f "$data"
  233. return
  234. fi
  235. if [ ${#RULE_FOLDER} -lt 2 ]; then
  236. dialog --title $"Create an email rule" \
  237. --msgbox $"No folder name was given" 6 40
  238. rm -f "$data"
  239. return
  240. fi
  241. if [[ "$RULE_EMAIL" != *"@"* || "$RULE_EMAIL" != *"."* ]]; then
  242. dialog --title $"Create an email rule" \
  243. --msgbox $"Unrecognised email address" 6 40
  244. rm -f "$data"
  245. return
  246. fi
  247. "${PROJECT_NAME}-addemail" -u "$USER" -e "$RULE_EMAIL" \
  248. -g "$RULE_FOLDER" --public $RULE_PUBLIC
  249. dialog --title $"Create an email rule" \
  250. --msgbox $"Email rule for $RULE_EMAIL was added" 6 40
  251. rm -f "$data"
  252. }
  253. function gpg_set_trust {
  254. TRUST_ADDRESS=$1
  255. fpr=$(gpg --with-colons --fingerprint "$TRUST_ADDRESS" | grep fpr | head -n 1 | awk -F ':' '{print $10}')
  256. if [ ${#fpr} -gt 2 ]; then
  257. W=(1 $"I don't know or won't say"
  258. 2 $"I do NOT trust"
  259. 3 $"I trust marginally"
  260. 4 $"I trust fully"
  261. 5 $"I trust ultimately")
  262. # shellcheck disable=SC2068
  263. TRUST_LEVEL=$(dialog --backtitle $"Freedombone User Control Panel" --title $"Trust a PGP/GPG key or website domain" --menu $"Set the trust level for $TRUST_ADDRESS:" 18 70 10 "${W[@]}" 3>&2 2>&1 1>&3)
  264. if [ ! "$TRUST_LEVEL" ]; then
  265. return;
  266. fi
  267. if echo -e "trust\\n${TRUST_LEVEL}\\ny\\nsave\\n" | gpg --command-fd 0 --edit-key "$fpr"; then
  268. gpg --update-trustdb
  269. dialog --title $"Trust a PGP/GPG key or website domain" \
  270. --backtitle $"Freedombone User Control Panel" \
  271. --msgbox $"$TRUST_ADDRESS was set to trust level ${TRUST_LEVEL}" 6 50
  272. fi
  273. fi
  274. }
  275. function email_rule_subject {
  276. data=$(mktemp 2>/dev/null)
  277. dialog --backtitle $"Freedombone User Control Panel" \
  278. --title $"Create an email rule" \
  279. --form "\\n" 9 75 4 \
  280. $"When email arrives with subject containing:" 1 1 "" 1 45 24 28 \
  281. $"Move to folder:" 2 1 "" 2 45 24 28 \
  282. $"Public:" 3 1 $"no" 3 45 4 25 \
  283. 2> "$data"
  284. sel=$?
  285. case $sel in
  286. 1) rm -f "$data"
  287. return;;
  288. 255) rm -f "$data"
  289. return;;
  290. esac
  291. RULE_SUBJECT=$(sed -n 1p < "$data")
  292. RULE_FOLDER=$(sed -n 2p < "$data")
  293. RULE_PUBLIC=$(sed -n 3p < "$data")
  294. if [ ${#RULE_PUBLIC} -lt 1 ]; then
  295. RULE_PUBLIC='no'
  296. fi
  297. if [[ $RULE_PUBLIC == $'y' || $RULE_PUBLIC == $'Y' || $RULE_PUBLIC == $'true' || $RULE_PUBLIC == $'True' || $RULE_PUBLIC == $'yes' || $RULE_PUBLIC == $'Yes' || $RULE_PUBLIC == $'YES' ]]; then
  298. RULE_PUBLIC='yes'
  299. else
  300. RULE_PUBLIC='no'
  301. fi
  302. if [ ${#RULE_SUBJECT} -lt 2 ]; then
  303. dialog --title $"Create an email rule" \
  304. --msgbox $"No subject text was given" 6 40
  305. rm -f "$data"
  306. return
  307. fi
  308. if [ ${#RULE_FOLDER} -lt 2 ]; then
  309. dialog --title $"Create an email rule" \
  310. --msgbox $"No folder name was given" 6 40
  311. rm -f "$data"
  312. return
  313. fi
  314. "${PROJECT_NAME}-addemail" -u "$USER" -s "$RULE_SUBJECT" \
  315. -g "$RULE_FOLDER" --public "$RULE_PUBLIC"
  316. dialog --title $"Create an email rule" \
  317. --msgbox $"Email rule for subject '$RULE_SUBJECT' was added" 6 40
  318. rm -f "$data"
  319. }
  320. function block_unblock_email {
  321. blockstr=$"Block or unblock emails from a given address"
  322. data=$(mktemp 2>/dev/null)
  323. dialog --backtitle $"Freedombone User Control Panel" \
  324. --title "$blockstr" \
  325. --form "\\n" 8 65 3 \
  326. $"When email arrives from address:" 1 1 "" 1 35 24 100 \
  327. $"Block it:" 2 1 "yes" 2 35 4 4 \
  328. 2> "$data"
  329. sel=$?
  330. case $sel in
  331. 1) rm -f "$data"
  332. return;;
  333. 255) rm -f "$data"
  334. return;;
  335. esac
  336. BLOCK_EMAIL=$(sed -n 1p < "$data")
  337. BLOCK=$(sed -n 2p < "$data")
  338. if [ ${#BLOCK_EMAIL} -lt 2 ]; then
  339. dialog --title "$blockstr" \
  340. --msgbox $"No email address was given" 6 40
  341. return
  342. fi
  343. if [[ "$BLOCK_EMAIL" != *"@"* || "$BLOCK_EMAIL" != *"."* ]]; then
  344. dialog --title "$blockstr" \
  345. --msgbox $"Unrecognised email address" 6 40
  346. rm -f "$data"
  347. return
  348. fi
  349. if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
  350. "${PROJECT_NAME}-ignore" -u "$USER" -e "$BLOCK_EMAIL"
  351. dialog --title $"Block an email" \
  352. --msgbox "Email from $BLOCK_EMAIL is now blocked" 6 75
  353. else
  354. "${PROJECT_NAME}-unignore" -u "$USER" -e "$BLOCK_EMAIL"
  355. dialog --title $"Unblock an email" \
  356. --msgbox "Email from $BLOCK_EMAIL is now unblocked" 6 75
  357. fi
  358. rm -f "$data"
  359. }
  360. function block_unblock_subject {
  361. blockstr=$"Block or unblock emails with text in the subject line"
  362. data=$(mktemp 2>/dev/null)
  363. dialog --backtitle $"Freedombone User Control Panel" \
  364. --title "$blockstr" \
  365. --form "\\n" 8 70 3 \
  366. $"When email arrives with subject text:" 1 1 "" 1 40 24 28 \
  367. $"Block it:" 2 1 "yes" 2 40 4 4 \
  368. 2> "$data"
  369. sel=$?
  370. case $sel in
  371. 1) rm -f "$data"
  372. return;;
  373. 255) rm -f "$data"
  374. return;;
  375. esac
  376. BLOCK_SUBJECT=$(sed -n 1p < "$data")
  377. BLOCK=$(sed -n 2p < "$data")
  378. if [ ${#BLOCK_SUBJECT} -lt 2 ]; then
  379. dialog --title "$blockstr" \
  380. --msgbox $"No subject was given" 6 40
  381. rm -f "$data"
  382. return
  383. fi
  384. if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
  385. "${PROJECT_NAME}-ignore" -u "$USER" -t "$BLOCK_SUBJECT"
  386. dialog --title $"Block an email" \
  387. --msgbox $"Email with subject $BLOCK_SUBJECT is now blocked" 6 40
  388. else
  389. "${PROJECT_NAME}-unignore" -u "$USER" -t "$BLOCK_SUBJECT"
  390. dialog --title $"Unblock an email" \
  391. --msgbox $"Email with subject $BLOCK_SUBJECT is now unblocked" 6 40
  392. fi
  393. rm -f "$data"
  394. }
  395. function show_gpg_key {
  396. GPG_FINGERPRINT=$(gpg --fingerprint "$GPG_ID" | sed -n '2p' | sed 's/^[ \t]*//')
  397. GPG_DATE=$(gpg --fingerprint "$GPG_ID" | grep -i "pub" | head -n 1 | awk -F ' ' '{print $3}')
  398. dialog --title $"My PGP/GPG Key" \
  399. --backtitle $"Freedombone User Control Panel" \
  400. --msgbox $"Email Address: $MY_EMAIL_ADDRESS\\n\\nKey ID: $GPG_ID\\n\\nFingerprint: $GPG_FINGERPRINT\\n\\nCreated: $GPG_DATE" 12 70
  401. clear
  402. echo $"Your GPG/PGP public key:"
  403. gpg --armor --export "$GPG_ID" | qrencode -t UTF8
  404. any_key
  405. }
  406. function show_full_gpg_key {
  407. clear
  408. echo ''
  409. echo ''
  410. echo ''
  411. gpg --armor --export "$GPG_ID"
  412. echo ''
  413. echo ''
  414. echo ''
  415. gpg --armor --export-secret-key "$GPG_ID"
  416. any_key
  417. }
  418. function publish_gpg_key {
  419. gpg --send-key "$GPG_ID"
  420. if [ "$GPG_BACKUP_ID" ]; then
  421. gpg --send-key "$GPG_BACKUP_ID"
  422. fi
  423. dialog --title $"Publish your PGP/GPG key" \
  424. --msgbox $"Your key has now been published" 6 40
  425. }
  426. function refresh_gpg_keys {
  427. gpg --refresh-keys
  428. dialog --title $"Refresh PGP/GPG keys" \
  429. --msgbox $"Your keys have been refreshed" 6 40
  430. }
  431. function add_gpg_key {
  432. data=$(mktemp 2>/dev/null)
  433. dialog --title $"Enter email address, Key ID or full key below" \
  434. --backtitle $"Freedombone User Control Panel" \
  435. --editbox "$data" 8 60
  436. sel=$?
  437. case $sel in
  438. 0)
  439. ADD_EMAIL_ADDRESS=$(<"$data")
  440. if [ ${#ADD_EMAIL_ADDRESS} -gt 2 ]; then
  441. address_is_valid=
  442. if [[ "$ADD_EMAIL_ADDRESS" == *"@"* && "$ADD_EMAIL_ADDRESS" == *"."* ]]; then
  443. address_is_valid=1
  444. fi
  445. if [[ "$ADD_EMAIL_ADDRESS" == "0x"* ]]; then
  446. address_is_valid=1
  447. fi
  448. publicstr=$"BEGIN PGP PUBLIC KEY BLOCK"
  449. if [[ "$ADD_EMAIL_ADDRESS" == *"$publicstr"* ]]; then
  450. address_is_valid=1
  451. fi
  452. if [ $address_is_valid ]; then
  453. clear
  454. if [[ "$ADD_EMAIL_ADDRESS" == *"$publicstr"* ]]; then
  455. echo "$ADD_EMAIL_ADDRESS" | gpg --import
  456. dialog --title $"Add someone's PGP/GPG key" \
  457. --backtitle $"Freedombone User Control Panel" \
  458. --msgbox $"GPG public key was imported" 6 50
  459. else
  460. gpg --search-keys "$ADD_EMAIL_ADDRESS"
  461. gpg_set_trust "$ADD_EMAIL_ADDRESS"
  462. fi
  463. else
  464. dialog --title $"Unrecognised email address" \
  465. --backtitle $"Freedombone User Control Panel" \
  466. --msgbox $"This doesn't look like an email address or key ID" 6 50
  467. fi
  468. fi
  469. ;;
  470. esac
  471. rm "$data"
  472. }
  473. function remove_gpg_key {
  474. data=$(mktemp 2>/dev/null)
  475. dialog --title $"Remove someone's PGP/GPG key" \
  476. --backtitle $"Freedombone User Control Panel" \
  477. --inputbox $"Enter their email address or key ID below" 8 60 2>"$data"
  478. sel=$?
  479. case $sel in
  480. 0)
  481. REMOVE_EMAIL_ADDRESS=$(<"$data")
  482. if [ ${#REMOVE_EMAIL_ADDRESS} -gt 2 ]; then
  483. if [[ $REMOVE_EMAIL_ADDRESS == *"@"* && $REMOVE_EMAIL_ADDRESS == *"."* ]]; then
  484. if [[ "$REMOVE_EMAIL_ADDRESS" != "$MY_EMAIL_ADDRESS" ]]; then
  485. clear
  486. gpg --delete-key "$REMOVE_EMAIL_ADDRESS"
  487. else
  488. dialog --title $"Remove someone's PGP/GPG key" \
  489. --backtitle $"Freedombone User Control Panel" \
  490. --msgbox $"It's not a good idea to remove your own encryption key" 6 65
  491. fi
  492. else
  493. if [[ $REMOVE_EMAIL_ADDRESS == "0x"* ]]; then
  494. clear
  495. gpg --delete-key "$REMOVE_EMAIL_ADDRESS"
  496. else
  497. dialog --title $"Unrecognised email address" \
  498. --backtitle $"Freedombone User Control Panel" \
  499. --msgbox $"This doesn't look like an email address" 6 50
  500. fi
  501. fi
  502. fi
  503. ;;
  504. esac
  505. rm -f "$data"
  506. }
  507. function add_ssh_key {
  508. data=$(mktemp 2>/dev/null)
  509. dialog --title $"Add an ssh key for logging in" \
  510. --backtitle $"Freedombone User Control Panel" \
  511. --inputbox $"This will allow you to log into ${PROJECT_NAME} if you have an ssh key on your system, and provides much stronger security than simply using a login password.\\n\\nWARNING: If you make any mistakes here then you may not be able to log in and will need to get the administrator to clear your ssh authorized_keys file." 15 60 2>"$data"
  512. sel=$?
  513. case $sel in
  514. 0)
  515. SSH_PUBLIC_KEY=$(<"$data")
  516. if [ ${#SSH_PUBLIC_KEY} -gt 20 ]; then
  517. if [[ "$SSH_PUBLIC_KEY" == "ssh-"* ]]; then
  518. if [ ! -d "/home/$USER/.ssh" ]; then
  519. mkdir "/home/$USER/.ssh"
  520. fi
  521. if [ ! -f "/home/$USER/.ssh/authorized_keys" ]; then
  522. touch "/home/$USER/.ssh/authorized_keys"
  523. fi
  524. if ! grep -q "$SSH_PUBLIC_KEY" "/home/$USER/.ssh/authorized_keys"; then
  525. echo "$SSH_PUBLIC_KEY" >> "/home/$USER/.ssh/authorized_keys"
  526. dialog --title $"New ssh key added" \
  527. --backtitle $"Freedombone User Control Panel" \
  528. --msgbox $"Your ssh key has now been added" 6 50
  529. else
  530. dialog --title $"ssh key already added" \
  531. --backtitle $"Freedombone User Control Panel" \
  532. --msgbox $"That ssh key has already been added" 6 50
  533. fi
  534. else
  535. dialog --title $"Unrecognised ssh public key" \
  536. --backtitle $"Freedombone User Control Panel" \
  537. --msgbox $"This doesn't look like an ssh key" 6 50
  538. fi
  539. fi
  540. ;;
  541. esac
  542. rm -f "$data"
  543. }
  544. function remove_ssh_key {
  545. data=$(mktemp 2>/dev/null)
  546. dialog --title $"Remove an ssh key for logging in" \
  547. --backtitle $"Freedombone User Control Panel" \
  548. --inputbox $"Enter the ssh public key which is to be removed. This can be just the address at the end.\\n\\nWARNING: If you make any mistakes here then you may not be able to log in and will need to get the administrator to clear your ssh authorized_keys file." 15 60 2>"$data"
  549. sel=$?
  550. case $sel in
  551. 0)
  552. SSH_PUBLIC_KEY=$(<"$data")
  553. if [ ${#SSH_PUBLIC_KEY} -gt 5 ]; then
  554. if [ -f "/home/$USER/.ssh/authorized_keys" ]; then
  555. sed -i "s|.*${SSH_PUBLIC_KEY}.*||g" "/home/$USER/.ssh/authorized_keys"
  556. dialog --title $"Remove an ssh public key" \
  557. --backtitle $"Freedombone User Control Panel" \
  558. --msgbox $"The ssh key has been removed" 6 50
  559. fi
  560. fi
  561. ;;
  562. esac
  563. rm -f "$data"
  564. }
  565. function smtp_proxy {
  566. MUTTRC_FILE=/home/$USER/.muttrc
  567. if [ ! -f "$MUTTRC_FILE" ]; then
  568. return
  569. fi
  570. SMTP_PROXY_ENABLE=$'no'
  571. SMTP_PROXY_PROTOCOL='smtps'
  572. SMTP_PROXY_SERVER='mail.myispdomain'
  573. SMTP_PROXY_PORT=465
  574. SMTP_PROXY_USERNAME=''
  575. SMTP_PROXY_PASSWORD=''
  576. if grep -q "set smtp_url" "$MUTTRC_FILE"; then
  577. if grep -q "#set smtp_url" "$MUTTRC_FILE"; then
  578. SMTP_PROXY_ENABLE=$'no'
  579. else
  580. SMTP_PROXY_ENABLE=$'yes'
  581. fi
  582. SMTP_PROXY_PROTOCOL=$(grep "set smtp_url" "$MUTTRC_FILE" | awk -F '"' '{print $2}' | awk -F ':' '{print $1}')
  583. SMTP_PROXY_SERVER=$(grep "set smtp_url" "$MUTTRC_FILE" | awk -F '"' '{print $2}' | awk -F '/' '{print $3}' | awk -F ':' '{print $2}' | awk -F '@' '{print $2}')
  584. SMTP_PROXY_PORT=$(grep "set smtp_url" "$MUTTRC_FILE" | awk -F ':' '{print $4}' | awk -F '/' '{print $1}')
  585. SMTP_PROXY_USERNAME=$(grep "set smtp_url" "$MUTTRC_FILE" | awk -F '"' '{print $2}' | awk -F '/' '{print $3}' | awk -F ':' '{print $1}')
  586. SMTP_PROXY_PASSWORD=$(grep "set smtp_url" "$MUTTRC_FILE" | awk -F '"' '{print $2}' | awk -F '/' '{print $3}' | awk -F ':' '{print $2}' | awk -F '@' '{print $1}')
  587. fi
  588. data=$(mktemp 2>/dev/null)
  589. dialog --backtitle $"Freedombone Control Panel" \
  590. --title $"SMTP Proxy for $USER" \
  591. --form $"You may need to proxy outgoing email via your ISP's mail server. If so enter the details below." 14 75 6 \
  592. $"Enable proxy:" 1 1 "$SMTP_PROXY_ENABLE" 1 24 5 5 \
  593. $"Protocol (smtp/smtps):" 2 1 "$SMTP_PROXY_PROTOCOL" 2 24 5 5 \
  594. $"ISP mail server:" 3 1 "$SMTP_PROXY_SERVER" 3 24 40 10000 \
  595. $"Port:" 4 1 "$SMTP_PROXY_PORT" 4 24 5 5 \
  596. $"Username:" 5 1 "$SMTP_PROXY_USERNAME" 5 24 40 10000 \
  597. $"Password:" 6 1 "$SMTP_PROXY_PASSWORD" 6 24 40 10000 \
  598. 2> "$data"
  599. sel=$?
  600. case $sel in
  601. 1) rm -f "$data"
  602. return;;
  603. 255) rm -f "$data"
  604. return;;
  605. esac
  606. SMTP_PROXY_ENABLE=$(sed -n 1p < "$data")
  607. SMTP_PROXY_PROTOCOL=$(sed -n 2p < "$data")
  608. SMTP_PROXY_SERVER=$(sed -n 3p < "$data")
  609. SMTP_PROXY_PORT=$(sed -n 4p < "$data")
  610. SMTP_PROXY_USERNAME=$(sed -n 5p < "$data")
  611. SMTP_PROXY_PASSWORD=$(sed -n 6p < "$data")
  612. # change muttrc
  613. if [ "$SMTP_PROXY_ENABLE" != $'no' ]; then
  614. if ! grep -q "set smtp_url" "$MUTTRC_FILE"; then
  615. echo "set smtp_url=\"${SMTP_PROXY_PROTOCOL}://${SMTP_PROXY_USERNAME}:${SMTP_PROXY_PASSWORD}@${SMTP_PROXY_SERVER}:${SMTP_PROXY_PORT}/\"" >> "$MUTTRC_FILE"
  616. else
  617. 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"
  618. fi
  619. sed -i 's|#set smtp_url|set smtp_url|g' "$MUTTRC_FILE"
  620. else
  621. if grep -q "set smtp_url" "$MUTTRC_FILE"; then
  622. sed -i 's|set smtp_url|#set smtp_url|g' "$MUTTRC_FILE"
  623. fi
  624. fi
  625. rm -f "$data"
  626. }
  627. function sign_gpg_key {
  628. data=$(mktemp 2>/dev/null)
  629. dialog --title $"Sign a PGP/GPG key or website domain" \
  630. --backtitle $"Freedombone User Control Panel" \
  631. --inputbox $"Enter the Key ID, address or domain to be signed.\\n\\nIf you are signing a website domain then include the https:// at the beginning.\\n\\nIf you are signing an ssh key then include ssh:// before the domain name." 14 75 2>"$data"
  632. sel=$?
  633. case $sel in
  634. 0)
  635. SIGN_ADDRESS=$(<"$data")
  636. if [ ${#SIGN_ADDRESS} -gt 2 ]; then
  637. clear
  638. gpg --search "$SIGN_ADDRESS"
  639. fpr=$(gpg --with-colons --fingerprint "$SIGN_ADDRESS" | grep fpr | head -n 1 | awk -F ':' '{print $10}')
  640. if [ ${#fpr} -gt 2 ]; then
  641. if gpg --sign-key "$fpr"; then
  642. gpg --update-trustdb
  643. dialog --title $"Sign a PGP/GPG key" \
  644. --backtitle $"Freedombone User Control Panel" \
  645. --msgbox $"$SIGN_ADDRESS was signed" 6 50
  646. fi
  647. fi
  648. fi
  649. ;;
  650. esac
  651. rm -f "$data"
  652. }
  653. function gpg_key_trust {
  654. data=$(mktemp 2>/dev/null)
  655. dialog --title $"Trust a PGP/GPG key or website domain" \
  656. --backtitle $"Freedombone User Control Panel" \
  657. --inputbox $"Enter the Key ID, address or domain to be trusted.\\n\\nIf you are trusting a website domain then include the https:// at the beginning.\\n\\nIf you are trusting an ssh key then include ssh:// before the domain name." 14 75 2>"$data"
  658. sel=$?
  659. case $sel in
  660. 0)
  661. TRUST_ADDRESS=$(<"$data")
  662. if [ ${#TRUST_ADDRESS} -gt 2 ]; then
  663. clear
  664. gpg --search "$TRUST_ADDRESS"
  665. gpg_set_trust "$TRUST_ADDRESS"
  666. fi
  667. ;;
  668. esac
  669. rm -f "$data"
  670. }
  671. function menu_encryption_keys {
  672. while true
  673. do
  674. W=(1 $"Show your PGP/GPG key"
  675. 2 $"Show your full PGP/GPG key, including private key"
  676. 3 $"Publish your PGP/GPG key so that others can find it"
  677. 4 $"Add someone's PGP/GPG key"
  678. 5 $"Remove someone's PGP/GPG key"
  679. 6 $"Sign a PGP/GPG key or website domain"
  680. 7 $"Refresh your PGP/GPG keys"
  681. 8 $"Add an ssh key for logging in"
  682. 9 $"Remove an ssh key for logging in"
  683. 10 $"Set the trust level for a PGP/GPG key")
  684. # shellcheck disable=SC2068
  685. selection=$(dialog --backtitle $"Freedombone User Control Panel" --title $"My Encryption Keys" --menu $"Choose an operation, or ESC for main menu:" 19 70 11 "${W[@]}" 3>&2 2>&1 1>&3)
  686. if [ ! "$selection" ]; then
  687. break
  688. fi
  689. case $selection in
  690. 1) show_gpg_key;;
  691. 2) show_full_gpg_key;;
  692. 3) publish_gpg_key;;
  693. 4) add_gpg_key;;
  694. 5) remove_gpg_key;;
  695. 6) sign_gpg_key;;
  696. 7) refresh_gpg_keys;;
  697. 8) add_ssh_key;;
  698. 9) remove_ssh_key;;
  699. 10) gpg_key_trust;;
  700. esac
  701. done
  702. }
  703. function menu_email {
  704. while true
  705. do
  706. W=(1 $"Add yourself to a mailing list"
  707. 2 $"Remove yourself from a mailing list"
  708. 3 $"Add an email rule for an address"
  709. 4 $"Add an email rule for a subject"
  710. 5 $"Block or unblock an email address"
  711. 6 $"Block or unblock email with subject text")
  712. # shellcheck disable=SC2068
  713. selection=$(dialog --backtitle $"Freedombone User Control Panel" --title $"Change Email Filtering Rules" --menu $"Choose an operation, or ESC for main menu:" 14 70 7 "${W[@]}" 3>&2 2>&1 1>&3)
  714. if [ ! "$selection" ]; then
  715. break
  716. fi
  717. case $selection in
  718. 1) add_to_mailing_list;;
  719. 2) remove_user_from_mailing_list;;
  720. 3) email_rule_address;;
  721. 4) email_rule_subject;;
  722. 5) block_unblock_email;;
  723. 6) block_unblock_subject;;
  724. esac
  725. done
  726. }
  727. function menu_admin {
  728. if [ ! -f /etc/sudoers ]; then
  729. clear
  730. exit 0
  731. fi
  732. sudo /usr/local/bin/control
  733. }
  734. function sign_keys {
  735. if [ ! -f "/home/$USER/.monkeysphere/server_keys" ]; then
  736. return
  737. fi
  738. dialog --title $"Monkeysphere sign server keys" \
  739. --backtitle $"Freedombone Security Configuration" \
  740. --defaultno \
  741. --yesno $"\\nMonkeysphere has been enabled and you will need to sign and trust the server keys. Do you want to do that now?" 8 60
  742. sel=$?
  743. case $sel in
  744. 0) "${PROJECT_NAME}-sec" --sign yes;;
  745. esac
  746. }
  747. function menu_run_client_app {
  748. detect_installable_apps
  749. W=()
  750. appnames=()
  751. n=1
  752. app_index=0
  753. # shellcheck disable=SC2068
  754. for a in ${APPS_AVAILABLE[@]}
  755. do
  756. if [[ ${APPS_INSTALLED[$app_index]} != "0" ]]; then
  757. if [[ $(function_exists "run_client_${a}") == "1" ]]; then
  758. W+=("$n" "$a")
  759. n=$((n+1))
  760. appnames+=("$a")
  761. fi
  762. fi
  763. app_index=$((app_index+1))
  764. done
  765. if [ $n -le 1 ]; then
  766. return
  767. fi
  768. # shellcheck disable=SC2086
  769. selection=$(dialog --backtitle $"Freedombone" --title $"Run an App" --menu $"Choose an operation, or ESC for main menu:" 16 70 20 "${W[@]}" 3>&2 2>&1 1>&3)
  770. if [ ! "$selection" ]; then
  771. return
  772. fi
  773. app_index=$((selection-1))
  774. chosen_app=${appnames[$app_index]}
  775. "run_client_${chosen_app}"
  776. }
  777. function show_your_email_address {
  778. GPG_FINGERPRINT=$(gpg --fingerprint "$GPG_ID" | sed -n '2p' | sed 's/^[ \t]*//')
  779. GPG_DATE=$(gpg --fingerprint "$GPG_ID" | grep -i "pub" | head -n 1 | awk -F ' ' '{print $3}')
  780. onion_domain=
  781. if [ -f "$HOME/.email_onion_domain" ]; then
  782. onion_domain=$(cat "$HOME/.email_onion_domain")
  783. fi
  784. dialog_height=14
  785. onionemailstr=
  786. if [[ "$HOSTNAME" != *'.onion' && "$onion_domain" ]]; then
  787. onionemailstr="\\n\\nOnion Email: ${USER}@${onion_domain}"
  788. dialog_height=$((dialog_height+3))
  789. fi
  790. msgstrbase=$"\\nYou can press SHIFT and then drag the mouse and right click to copy.\\n\\nEmail Address: ${MY_EMAIL_ADDRESS}${onionemailstr}\\n\\nKey ID: ${GPG_ID}\\n\\nFingerprint: ${GPG_FINGERPRINT}\\n\\nCreated: ${GPG_DATE}"
  791. bdsmail_address=
  792. bdsmailstr=
  793. if [ -f ~/.mutt/bdsmail ]; then
  794. bdsmail_address=$(grep 'set from=' ~/.mutt/bdsmail | awk -F '=' '{print $2}')
  795. bdsmailstr="\\n\\nI2P Address: ${bdsmail_address}"
  796. dialog_height=$((dialog_height+3))
  797. fi
  798. dialog --title $"Show your Email Address" \
  799. --backtitle $"Freedombone User Control Panel" \
  800. --msgbox "${msgstrbase}${bdsmailstr}" $dialog_height 100
  801. if [ "$onion_domain" ]; then
  802. clear
  803. echo ''
  804. echo $'Your onion email address:'
  805. echo ''
  806. echo -n "${USER}@${onion_domain}" | qrencode -t UTF8
  807. echo ''
  808. any_key
  809. fi
  810. if [ "${bdsmail_address}" ]; then
  811. clear
  812. echo ''
  813. echo $'Your bdsmail address:'
  814. echo ''
  815. echo -n "${bdsmail_address}" | qrencode -t UTF8
  816. echo ''
  817. any_key
  818. fi
  819. }
  820. function menu_top_level {
  821. while true
  822. do
  823. W=(1 $"Use Email"
  824. 2 $"Show your Email Address"
  825. 3 $"Change Email Filtering/Blocking Rules"
  826. 4 $"Run an App"
  827. 5 $"Browse the Web"
  828. 6 $"My Encryption Keys"
  829. 7 $"Set an outgoing email proxy"
  830. 8 $"Administrator controls"
  831. 9 $"Exit to the command line")
  832. # shellcheck disable=SC2068
  833. selection=$(dialog --backtitle $"Freedombone User Control Panel" --title $"User Control Panel" --menu $"Choose an operation, or ESC to log out:" 20 60 13 "${W[@]}" 3>&2 2>&1 1>&3)
  834. if [ ! "$selection" ]; then
  835. kill -HUP "$(pgrep -s 0 -o)"
  836. fi
  837. case $selection in
  838. 1) mutt;;
  839. 2) show_your_email_address;;
  840. 3) menu_email;;
  841. 4) menu_run_client_app;;
  842. 5) torify elinks -no-home;;
  843. 6) menu_encryption_keys;;
  844. 7) smtp_proxy;;
  845. 8) menu_admin;;
  846. 9) break;;
  847. esac
  848. done
  849. }
  850. sign_keys
  851. gpg_agent_enable "$USER"
  852. menu_top_level
  853. clear
  854. # shellcheck disable=SC1090
  855. . ~/.bashrc
  856. cat /etc/motd
  857. echo -e $'Type "sudo su" for root access, or "control" to restart\nthe control panel.'
  858. echo ''
  859. exit 0