M client/install.sh => client/install.sh +77 -40
@@ 9,50 9,73 @@ function poll_for_url() {
for i in {1..12}
do
- res=$(curl -s -o curl-out.txt -w "%{http_code}" "${baseurl}/states?q=${state}")
- case "$res" in
- 404)
- sleep 5
- ;;
- 200)
- cat curl-out.txt
- rm curl-out.txt
- exit 0
- ;;
- 407)
- cat curl-out.txt
- rm curl-out.txt
- exit 1
- ;;
- *)
- cat curl-out.txt
- rm curl-out.txt
- exit 2
- ;;
- esac
+ res=$(curl -s -o curl-out.txt -w "%{http_code}" "${baseurl}/states?q=${state}")
+ case "$res" in
+ 404)
+ sleep 5
+ ;;
+ 200)
+ cat curl-out.txt
+ rm curl-out.txt
+ return 0
+ ;;
+ 407)
+ cat curl-out.txt
+ rm curl-out.txt
+ return 1
+ ;;
+ *)
+ cat curl-out.txt
+ rm curl-out.txt
+ return 2
+ ;;
+ esac
done
exit 2
}
+# Given the discord webhook URL generates a notify.sh script that
+# omprog can use to send messages.
function generate_script_from_url() {
local url=$1
- echo '#!/bin/bash
+ echo "#!/bin/bash
-URL="${url}"
+URL=\"${url}\"
while read line
do
- if [[ "$line" == *"pam_unix(sshd:session): session opened for user"* ]]; then
- curl \
- -X POST \
- -H "Content-Type: application/json" \
- -d '{"content":"'"🚨 \`\${line}\`"'"}' \
- $URL
+ if [[ \"\$line\" == *\"pam_unix(sshd:session): session opened for user\"* ]]; then
+ curl \\
+ -X POST \\
+ -H \"Content-Type: application/json\" \\
+ -d '{\"content\":\"'\"🚨 \\\`\${line}\\\`\"'\"}' \\
+ \$URL
+ fi
+done"
+}
+
+# Checks if the omprog module is loaded by rsyslog.
+function omprog_module_loaded() {
+ if grep -E -- '^module\(load="omprog"\)|^\$ModLoad omprog' /etc/rsyslog.conf > /dev/null; then
+ return 0
+ else
+ return 1
+ fi
+}
+function install_rsyslog_conf() {
+ if omprog_module_loaded; then
+ echo "
+# Discord login notifications configuration.
+action(type=\"omprog\" binary=\"$HOME/.discord-login-notify.sh\")" >> /etc/rsyslog.conf
+ else
+ echo "
+# Discord login notifications configuration.
+module(load=\"omprog\")
+action(type=\"omprog\" binary=\"$HOME/.discord-login-notify.sh\")" >> /etc/rsyslog.conf
fi
-done'
}
# Generate some randomness that we will use as our state value while
@@ 64,6 87,15 @@ baseurl="https://discord.negativefour.com"
# webhook.
client_id="881307939367956552"
+# This script expects to be run as sudo but we want to place files in
+# the home directory of the calling user.
+HOME="/home/`who am i | awk '{print $1}'`"
+
+if grep -E -- "^action\(type=\"omprog\" binary=\"$HOME/.discord-login-notify.sh\"\)" /etc/rsyslog.conf > /dev/null; then
+ echo "It appears as if you have already installed this program."
+ exit 1
+fi
+
# Print this to stderr so we can use script output to pipe into a
# file.
>&2 echo "Please open the following URL in a web browser:
@@ 73,18 105,23 @@ https://discord.com/api/oauth2/authorize?response_type=code&client_id=${client_i
Waiting for authentication.."
res=$(poll_for_url $state $baseurl)
+
case "$?" in
1)
- echo "An authentication error occured while authenticating with Discord."
- echo "$res"
- exit 1
- ;;
+ echo "An authentication error occured while authenticating with Discord."
+ echo "$res"
+ exit 1
+ ;;
0)
- generate_script_from_url "$res"
- ;;
+ generate_script_from_url "$res" > "$HOME/.discord-login-notify.sh"
+ chmod +x "$HOME/.discord-login-notify.sh"
+ install_rsyslog_conf
+ systemctl restart rsyslog
+ exit 0
+ ;;
*)
- echo "An unexpected error occured:"
- echo "$res"
- exit 2
- ;;
+ echo "An unexpected error occured:"
+ echo "$res"
+ exit 2
+ ;;
esac
D discord-server/notify.sh => discord-server/notify.sh +0 -2
@@ 1,2 0,0 @@
-An unexpected error occured:
-
M discord-server/workers-site/states.js => discord-server/workers-site/states.js +7 -1
@@ 9,17 9,23 @@ export const handleStatesRequest = async (request) => {
}
const code = await STATES.get(state)
+
if (!code) {
return new Response("No matching state.", { status: 404 })
} else if (code === "FAIL") {
return new Response("A Discord authentication failure occured.", { status: 407 })
}
+ // Delete the state so that future requests will fail. This keeps
+ // the amount of time that we have the code stored as low as
+ // possible.
+ await STATES.delete(state)
+
+
// Exchange the state for some webhook information from the
// discord API. We do this lazily which has the technical
// advantage of meaning we don't ever need to store the webhook
// url in our database.
-
const response = await fetch("https://discord.com/api/oauth2/token?",
{
method: "POST",