From 88c747372529e37da72ae6bcdc1a222d97ee9102 Mon Sep 17 00:00:00 2001 From: localhost_frssoft Date: Fri, 21 Jul 2023 20:56:12 +0300 Subject: [PATCH] initial commit --- README.nd | 13 ++++++++++ bbs.sh | 7 ++++++ config.example | 5 ++++ executor.sh | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 README.nd create mode 100755 bbs.sh create mode 100644 config.example create mode 100755 executor.sh diff --git a/README.nd b/README.nd new file mode 100644 index 0000000..8c20e15 --- /dev/null +++ b/README.nd @@ -0,0 +1,13 @@ +BBS-like simulator +It can be used with nc, telnet, socat clients +Useful for ancient devices, but TOTALLY NOT SECURE! + +```copy example config and edit +cp config.example config +$EDITOR config +``` + +```run server (socat required) +./bss.sh +``` + diff --git a/bbs.sh b/bbs.sh new file mode 100755 index 0000000..d64fbc4 --- /dev/null +++ b/bbs.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +echo "listening for commands on 0.0.0.0:$1" + +socat -v -v TCP-LISTEN:$1,reuseaddr,pktinfo,fork SYSTEM:"./executor.sh" + + diff --git a/config.example b/config.example new file mode 100644 index 0000000..f283100 --- /dev/null +++ b/config.example @@ -0,0 +1,5 @@ +instance='example.com' +instance_token="aaaaaaaaaaaaaaaaaa" +pass_for_bbs='naive_unsecured_password' +system_dict='./words.gz' # /usr/share/dict/words or /usr/dict/words or internal + diff --git a/executor.sh b/executor.sh new file mode 100755 index 0000000..8490729 --- /dev/null +++ b/executor.sh @@ -0,0 +1,65 @@ +#!/bin/sh + +. ./config + +toot(){ + curl -s -X POST -F in_reply_to_id=$reply -F status="$1" -F visibility='unlisted' -H "Authorization: Bearer $instance_token" https://$instance/api/v1/statuses +} + +timeline_home(){ + curl -s -H "Authorization: Bearer $instance_token" "https://$instance/api/v1/timelines/home?limit=40&max_id=$1" | + jq -r '.[] | + if .reblog then + (["bump", .reblog.id, .reblog.account.acct] | join(" ")), .reblog.pleroma.content."text/plain", (.reblog.media_attachments[] | "attach", .url, .description // empty) + else [.id, .account.acct], .pleroma.content."text/plain", (.media_attachments[] | "attach", .url, .description // empty) + end | @text' +} + +remote_ip=$SOCAT_PEERADDR +die(){ + rm access_granted/"$remote_ip" + pkill executor.sh +} + +mkdir -p -m 700 access_granted +generator_session=$(zcat -f $system_dict | shuf -n 2 | tr -d "\n'") +randpadding=$(head -c 8 /dev/urandom | base64) +printf "$randpadding\t$generator_session\n" +cat - | + while read -r cmd mesg; do + if [ "$cmd" = "reg" ]; then + key=$(echo "$mesg" | cut -d' ' -f 2) + session=$(echo "$mesg" | cut -d' ' -f 1) + if [ "$session" = "$generator_session" ] && [ "$key" = "$pass_for_bbs" ]; then + touch access_granted/"$remote_ip" + echo hi $remote_ip + else + die + fi + fi + if [ ! -f access_granted/"$remote_ip" ]; then # Drop unregistred handshake + die + fi + # --- + case $cmd in + "post") toot "$mesg" | jq '.id, .errors' ;; + "reply") + reply_id=$(echo "$mesg" | cut -d' ' -f 1) + status=$(echo "$mesg" | cut -d' ' -f 2-) + reply=$reply_id toot "$status" | jq '.id, .errors' + reply='' + ;; + "home") timeline_home "$mesg" ;; + "reg") printf 'bbs > '; continue ;; + "x") + case $mesg in + "http"*) w3m -dump -T text/html -cols 34 -o 'display_link_number=1' "$mesg" ;; + *) echo 'only http(s)' ;; + esac + ;; + *) die ;; + esac + printf 'bbs > ' + done +rm access_granted/"$remote_ip" +echo 'session was close'