Restruct project directories - postreich - Unnamed repository; edit this file 'description' to name the repository. DIR Log DIR Files DIR Refs DIR README --- DIR commit 4e6ef2335c7010e481927b7f4a708c42788d2090 DIR parent e3b970d4f9ad336f7eaa8894e28a789c35082020 HTML Author: Scarlett McAllister <no+reply@roygbyte.com> Date: Sun, 28 Jan 2024 18:07:36 -0400 Restruct project directories Diffstat: D geomyidae/postreich/api/send-mail | 64 ------------------------------- D geomyidae/postreich/api/templates/… | 2 -- D geomyidae/postreich/api/templates/… | 97 ------------------------------ D geomyidae/postreich/index.dcgi | 39 ------------------------------- D geomyidae/postreich/sendmail.dcgi | 57 ------------------------------- D main.sh | 54 ------------------------------- A src/cli/main.sh | 55 +++++++++++++++++++++++++++++++ A src/geomyidae/#sendmail.dcgi# | 52 +++++++++++++++++++++++++++++++ A src/geomyidae/.#sendmail.dcgi | 2 ++ R geomyidae/postreich/api/common -> … | 0 R geomyidae/postreich/api/create-mai… | 0 R geomyidae/postreich/api/get-mailbo… | 0 R geomyidae/postreich/api/index.cgi … | 0 A src/geomyidae/api/send-mail | 59 +++++++++++++++++++++++++++++++ R geomyidae/postreich/api/templates/… | 0 A src/geomyidae/api/templates/valent… | 2 ++ R geomyidae/postreich/api/templates/… | 0 A src/geomyidae/api/templates/valent… | 98 +++++++++++++++++++++++++++++++ R geomyidae/postreich/api/templates/… | 0 A src/geomyidae/getmail.dcgi | 0 A src/geomyidae/index.dcgi | 40 +++++++++++++++++++++++++++++++ A src/geomyidae/mailboxes.dcgi | 2 ++ A src/geomyidae/sendmail.dcgi | 52 +++++++++++++++++++++++++++++++ A src/log.txt | 1 + A src/serve-geomyidae.sh | 16 ++++++++++++++++ D start-server.sh | 16 ---------------- 26 files changed, 379 insertions(+), 329 deletions(-) --- DIR diff --git a/geomyidae/postreich/api/send-mail b/geomyidae/postreich/api/send-mail @@ -1,64 +0,0 @@ -#!/bin/sh -# -# Example: send-mail -h roygbyte -t 1 -m ":)" -. ./common - -handle="" -message="" -template="" - -while getopts "h:t:m:" f; do - case $f in - h) handle="$OPTARG" ;; - t) - template="$OPTARG" - result=$( verify_template "$template" ) - if [ $? -eq 1 ]; then - printf "$result\n" - exit - fi - ;; - m) message=$( sanitize_message "$OPTARG" ) ;; - esac -done - -# verify message accocrding to type -result=$( printf "%s\n" | "$TEMPLATES/$template/main" ) -if [ ! $? -eq 0 ]; then - printf "$result" - return 1 -fi -printf "%s\n" "$result" - -result=$( ./get-mailbox -k "$handle" ) -if [ ! $? -eq 0 ]; then - printf "$result" - return 1 -fi -pubkey="$result" - -result=$( ./get-mailbox "$handle" ) -if [ ! $? -eq 0 ]; then - printf "$result" - return 1 -fi -mailbox="$result" - -result=$( printf "%s" "$message" \ - | encrypt_with_key_and_encode "$pubkey" ) -if [ ! $? ]; then - printf "Encryption or encoding failed.\n" - return 1 -fi - -timestamp=$( date ) -printf "%s,%s\n" "$timestamp" "$result" >> "$mailbox" - -# what if... there is a `type` of mail option. and the first `type` to -# implement will be the `vday card`. there could also be like.. -# `snail mail` or `hate mail` or... `love letters` or... -# `fan mail` - - - - DIR diff --git a/geomyidae/postreich/api/templates/valentine/common b/geomyidae/postreich/api/templates/valentine/common @@ -1 +0,0 @@ -../../common -\ No newline at end of file DIR diff --git a/geomyidae/postreich/api/templates/valentine/main b/geomyidae/postreich/api/templates/valentine/main @@ -1,97 +0,0 @@ -#!/bin/sh -# -# The template's `main` file does all validation -# -# via gopher, this script will be executed from /postoffice direction, not -# the directory where the file is actually located. -# i could cd into the template dir... bad idea? - -. ./api/common # this directory is based on sendmail.dcgi PWD - -WIDTH=45 -MESSAGE_BYTE_LIMIT=69 -SWEETHEARTS="api/$TEMPLATES/valentine/sweethearts.txt" - -validate_text() { - len=$( printf "%s" "$1" \ - | wc --bytes ) - if [ $len -gt $MESSAGE_BYTE_LIMIT -o \ - $len -le 1 ]; then - return 1 - fi - return 0 -} - -validate_border() { - echo $1 -} - -validate_sweetheart() { - grep -xc "$1" "$SWEETHEARTS" 2> /dev/null - return $? -} - -path="$1" -query="$2" -# read message - -border=$( find_value_in_args "border" "$path" ) -text=$( find_value_in_args "text" "$path" ) -if [ -z "$text" ]; then - # text might be in the query (if it was just entered), so check that next. - text="$query" -fi -sweetheart=$( find_value_in_args "sweetheart" "$path" ) - -choose_sweetheart() { - cat "$SWEETHEARTS" \ - | awk -v args="$path" \ - 'BEGIN {FS = "\t"} { printf "[1|%s|sendmail.dcgi?%s?sweetheart=%s|localhost|70]\n", $1, args, $1 }' -} - -write_text() { - printf "[7|Write your message|sendmail.dcgi?$path|localhost|70]\n" -} - -echo $sweetheart # debug -echo $text # debug - -if [ -z "$sweetheart" ]; then - printf "Choose the letter's sweetheart:\n" - choose_sweetheart - return 1 -fi - -if [ -z "$text" ]; then - write_text - printf "Limit is $MESSAGE_BYTE_LIMIT bytes.\n" - return 1 -fi - -validate_sweetheart "$sweetheart" -if [ ! $? -eq 0 ]; then - printf "Incorrect sweetheart\n" - return 1 -fi - -validate_text "$text" -if [ ! $? -eq 0 ]; then - printf "Message not within limit of 1-%s bytes.\n" \ - $MESSAGE_BYTE_LIMIT - return 1 -fi -return 0 - -# valentine's template will expect a single record with two fields. -# the fields should be separated with a tab. -# (ignore remaining tabs? or replace them by another char) - -#echo $message - -# need to verify the message is below a certain length -# need to verify the chosen border exists -# these two things shoLd be extracted from message, which -# probably isn't a great variable name. -# border=1?message=blah blah bla - -# verify message length, and the border... DIR diff --git a/geomyidae/postreich/index.dcgi b/geomyidae/postreich/index.dcgi @@ -1,39 +0,0 @@ -#!/bin/sh -. ./api/common - -# -# |\ /\ -# | \/ \/ -# |_/\ /\/\ -# | \/ / -# -# -# Mailboxes can be setup with a 2048 bit PEM format RSA key. -# Simply cr -# - -echo "Welcome to Postreich, Bitreich's gopher powered mail service.\n" \ - "Here you can setup a mailbox and receive mail over the gopher protocol.\n" - -echo "[1|Send mail|sendmail.dcgi|localhost|70]" -echo "[1|Get mail|getmail.dcgi|localhost|70]" - -echo ' - ~~| _.,, - ~~~| C`-o-o_ - ~~~| \ )_/ - ~~| .=|_|=, - ~| / \ \ x \ -*************** -' - -echo ' -This month we are featuring a special promotion of valentines letters.' - -echo 'Setup a mailbox with your handle and a base64 encoded 2048 bit -PEM format RSA public key' - -echo 'Message are encryted at REST. We do not guarentee any sort of security -or privacy of messages received or stored. However, if you access this service -over gophers you can expect your communications to be sent over tls, of course. -This is more like a community mailbox.' DIR diff --git a/geomyidae/postreich/sendmail.dcgi b/geomyidae/postreich/sendmail.dcgi @@ -1,57 +0,0 @@ -#!/bin/sh - -. ./api/common - -handle=$( find_value_in_args "handle" "$2" ) -template=$( find_value_in_args "template" "$2" ) -message=$( find_value_in_args "message" "$2" ) - -choose_mailbox() { - ls -x1 "api/$MAILBOXES" \ - | awk -v t="$template" \ - '{ printf "[1|%s|sendmail.dcgi?handle=%s?template=%s|localhost|70]\n", $1, $1, t }' -} - -choose_template() { - ls -x1 "api/$TEMPLATES" \ - | xargs -d '\n' -I x cat "api/$TEMPLATES/"x"/info" \ - | awk -F '\t' -v h="$handle" \ - '{ printf "[1|%s|sendmail.dcgi?template=%s?handle=%s|localhost|70]\n", $2, $1, h }' -} - -show_footer() { - printf "\n\n[1|Start over|sendmail.dcgi|localhost|70]" -} - -if [ -z "$handle" ]; then - printf "Pick recipient:\n" - choose_mailbox - show_footer - return 0 -fi - -if [ -z "$template" ]; then - printf "Pick template:\n" - choose_template - show_footer - return 0 -fi - -# first positional argument will be the rest query, second positional -# argument will be search query string, if present. -result=$( printf "%s" "$message" | api/$TEMPLATES/$template/main "$2" "$1" ) -if [ ! $? -eq 0 ]; then - printf "%s" "$result" - return 0 -fi - -echo "ready to send" - -# echo $handle #debugging -# echo $template #debugging - -show_footer - - - - DIR diff --git a/main.sh b/main.sh @@ -1,54 +0,0 @@ -#!/bin/sh - -# extract dependencies - -# handle must be less than 16 bytes - -# set password to ENV variable so it's hidden in the code. Check if it's empty -# before generating the key. - -create_mailbox_url="gopher://localhost/7/postoffice/mailbox/create" -get_mailbox_url="gopher://localhost/0/postoffice/mailbox/get" - -cupid_encryption() { - # printf "%s" $1 | \ - return 0 -} - -user_encryption() { - return 0 -} - -create_key_pair() { - # check if key exists already? - private_key_name="br_cupid.pem" - public_key_name=$( printf "%s" "$private_key_name" |\ - sed 's/pem$/pub/' ) - # Generate a 2048 bit key - # TODO: am i using safe primes? - openssl genpkey -algorithm RSA -out $private_key_name -pkeyopt -quiet - openssl pkey -in "$private_key_name" -pubout -out "$public_key_name" - if [ ! -r "$private_key_name" -o ! -r "$public_key_name" ]; then - printf "Did not generate private and public keys. Exiting.\n" - fi - return 0 -} - -create_mailbox() { - pub_key_contents=$( cat "br_cupid.pub" | base64 | tr -d "\n" ) - if [ $( printf "%s" "$pub_key_contents" | wc -c ) -gt 1024 ]; then - printf "Public key is larger than 1024 bits. Server might not get it all, \ - (geomyidae limit is 1024, rfc gopher limit is less) but trying anyways..." - fi - handle="definitelyroygbyte" - curl "$create_mailbox_url/$handle?$pub_key_contents" -} - -open_mailbox() { - result=$( curl "$get_mailbox_url/$1" -s \ - | awk -F ',' '{ system("printf '%s' " $2 "| base64 -d | openssl pkeyutl -decrypt -inkey br_cupid.pem"); print "" }' ) - echo "$result" -} - -open_mailbox "$1" - DIR diff --git a/src/cli/main.sh b/src/cli/main.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +# extract dependencies + +# handle must be less than 16 bytes + +# set password to ENV variable so it's hidden in the code. Check if it's empty +# before generating the key. + +create_mailbox_url="gopher://localhost/7/postoffice/mailbox/create" +get_mailbox_url="gopher://localhost/0/postoffice/mailbox/get" + +cupid_encryption() { + # printf "%s" $1 | \ + return 0 +} + +user_encryption() { + return 0 +} + +create_key_pair() { + # check if key exists already? + private_key_name="br_cupid.pem" + public_key_name=$( printf "%s" "$private_key_name" |\ + sed 's/pem$/pub/' ) + # Generate a 2048 bit key + # TODO: am i using safe primes? + openssl genpkey -algorithm RSA -out $private_key_name -pkeyopt -quiet + openssl pkey -in "$private_key_name" -pubout -out "$public_key_name" + if [ ! -r "$private_key_name" -o ! -r "$public_key_name" ]; then + printf "Did not generate private and public keys. Exiting.\n" + fi + return 0 +} + +create_mailbox() { + pub_key_contents=$( cat "br_cupid.pub" | base64 | tr -d "\n" ) + if [ $( printf "%s" "$pub_key_contents" | wc -c ) -gt 1024 ]; then + printf "Public key is larger than 1024 bits. Server might not get it all, \ + (geomyidae limit is 1024, rfc gopher limit is less) but trying anyways..." + fi + handle="roygbyte" + curl "$create_mailbox_url/$handle?$pub_key_contents" +} + +open_mailbox() { + result=$( curl "$get_mailbox_url/$1" -s \ + | awk -F ',' '{ system("printf '%s' " $2 "| base64 -d | openssl pkeyutl -decrypt -inkey br_cupid.pem"); print "" }' ) + echo "$result" +} + +create_mailbox +#open_mailbox "$1" + DIR diff --git a/src/geomyidae/#sendmail.dcgi# b/src/geomyidae/#sendmail.dcgi# @@ -0,0 +1,52 @@ +#!/bin/sh +. ./api/common + +path="$2" +query="$1" + +handle=$( find_value_in_args "handle" "$path" ) +template=$( find_value_in_args "template" "$path" ) + +choose_mailbox() { + ls -x1 "api/$MAILBOXES" \ + | awk -v t="$template" \ + '{ printf "[1|%s|sendmail.dcgi?handle=%s?template=%s|localhost|70]\n", $1, $1, t }' +} + +choose_template() { + ls -x1 "api/$TEMPLATES" \ + | xargs -d '\n' -I x cat "api/$TEMPLATES/"x"/info" \ + | awk -F '\t' -v h="$handle" \ + '{ printf "[1|%s|sendmail.dcgi?template=%s?handle=%s|localhost|70]\n", $2, $1, h }' +} + +show_footer() { + printf "\n\n[1|Start over|sendmail.dcgi|localhost|70]" +} + +if [ -z "$handle" ]; then + printf "Pick recipient:\n" + choose_mailbox + show_footer + return 0 +fi + +if [ -z "$template" ]; then + printf "Pick template:\n" + choose_template + show_footer + return 0 +fi + +result=$( api/$TEMPLATES/$template/main "$path" "$query" ) +if [ ! $? -eq 0 ]; then + printf "%s" "$result" + return 0 +fi + +echo $result + +echo "ready to send" + +show_footer + DIR diff --git a/src/geomyidae/.#sendmail.dcgi b/src/geomyidae/.#sendmail.dcgi @@ -0,0 +1 @@ +roygbyte@penny.1401:1706385642 +\ No newline at end of file DIR diff --git a/geomyidae/postreich/api/common b/src/geomyidae/api/common DIR diff --git a/geomyidae/postreich/api/create-mailbox b/src/geomyidae/api/create-mailbox DIR diff --git a/geomyidae/postreich/api/get-mailbox b/src/geomyidae/api/get-mailbox DIR diff --git a/geomyidae/postreich/api/index.cgi b/src/geomyidae/api/index.cgi DIR diff --git a/src/geomyidae/api/send-mail b/src/geomyidae/api/send-mail @@ -0,0 +1,59 @@ +#!/bin/sh +# +# Example: send-mail -h roygbyte -t 1 -m ":)" +. ./common + +handle="" +message="" +template="" + +while getopts "h:t:m:" f; do + case $f in + h) handle="$OPTARG" ;; + t) + template="$OPTARG" + result=$( verify_template "$template" ) + if [ $? -eq 1 ]; then + printf "$result\n" + exit + fi + ;; + m) message=$( sanitize_message "$OPTARG" ) ;; + esac +done + +# verify message accocrding to type +result=$( printf "%s\n" | "$TEMPLATES/$template/main" ) +if [ ! $? -eq 0 ]; then + printf "$result" + return 1 +fi +printf "%s\n" "$result" + +result=$( ./get-mailbox -k "$handle" ) +if [ ! $? -eq 0 ]; then + printf "$result" + return 1 +fi +pubkey="$result" + +result=$( ./get-mailbox "$handle" ) +if [ ! $? -eq 0 ]; then + printf "$result" + return 1 +fi +mailbox="$result" + +result=$( printf "%s" "$message" \ + | encrypt_with_key_and_encode "$pubkey" ) +if [ ! $? ]; then + printf "Encryption or encoding failed.\n" + return 1 +fi + +timestamp=$( date ) +printf "%s,%s\n" "$timestamp" "$result" >> "$mailbox" + + + + DIR diff --git a/geomyidae/postreich/api/templates/valentine/borders.txt b/src/geomyidae/api/templates/valentine/borders.txt DIR diff --git a/src/geomyidae/api/templates/valentine/common b/src/geomyidae/api/templates/valentine/common @@ -0,0 +1 @@ +../../common +\ No newline at end of file DIR diff --git a/geomyidae/postreich/api/templates/valentine/info b/src/geomyidae/api/templates/valentine/info DIR diff --git a/src/geomyidae/api/templates/valentine/main b/src/geomyidae/api/templates/valentine/main @@ -0,0 +1,98 @@ +#!/bin/sh +# +# The template's `main` file does all validation +# +# via gopher, this script will be executed from /postoffice direction, not +# the directory where the file is actually located. +# i could cd into the template dir... bad idea? + +. ./api/common # this directory is based on sendmail.dcgi PWD + +WIDTH=45 +MESSAGE_BYTE_LIMIT=69 +SWEETHEARTS="api/$TEMPLATES/valentine/sweethearts.txt" + +validate_text() { + len=$( printf "%s" "$1" \ + | wc --bytes ) + if [ $len -gt $MESSAGE_BYTE_LIMIT -o \ + $len -le 1 ]; then + return 1 + fi + return 0 +} + +validate_border() { + echo $1 +} + +validate_sweetheart() { + # todo: verify this correctly redirects stdout and stderr + grep -xc "$1" "$SWEETHEARTS" 2>&1 >/dev/null + return $? +} + +path="$1" +query="$2" +# read message + +border=$( find_value_in_args "border" "$path" ) +text=$( find_value_in_args "text" "$path" ) +if [ -z "$text" ]; then + # text might be in the query (if it was just entered), so check that next. + text="$query" +fi +sweetheart=$( find_value_in_args "sweetheart" "$path" ) + +choose_sweetheart() { + cat "$SWEETHEARTS" \ + | awk -v args="$path" \ + 'BEGIN {FS = "\t"} { printf "[1|%s|sendmail.dcgi?%s?sweetheart=%s|localhost|70]\n", $1, args, $1 }' +} + +write_text() { + printf "[7|Write your message|sendmail.dcgi?$path|localhost|70]\n" +} + +# echo $sweetheart # debug +# echo $text # debug + +if [ -z "$sweetheart" ]; then + printf "Choose the letter's sweetheart:\n" + choose_sweetheart + return 1 +fi + +if [ -z "$text" ]; then + write_text + printf "Limit is $MESSAGE_BYTE_LIMIT bytes.\n" + return 1 +fi + +validate_sweetheart "$sweetheart" +if [ ! $? -eq 0 ]; then + printf "Incorrect sweetheart\n" + return 1 +fi + +validate_text "$text" +if [ ! $? -eq 0 ]; then + printf "Message not within limit of 1-%s bytes.\n" \ + $MESSAGE_BYTE_LIMIT + return 1 +fi +return 0 + +# valentine's template will expect a single record with two fields. +# the fields should be separated with a tab. +# (ignore remaining tabs? or replace them by another char) + +#echo $message + +# need to verify the message is below a certain length +# need to verify the chosen border exists +# these two things shoLd be extracted from message, which +# probably isn't a great variable name. +# border=1?message=blah blah bla + +# verify message length, and the border... DIR diff --git a/geomyidae/postreich/api/templates/valentine/sweethearts.txt b/src/geomyidae/api/templates/valentine/sweethearts.txt DIR diff --git a/src/geomyidae/getmail.dcgi b/src/geomyidae/getmail.dcgi DIR diff --git a/src/geomyidae/index.dcgi b/src/geomyidae/index.dcgi @@ -0,0 +1,40 @@ +#!/bin/sh +. ./api/common + +# +# |\ /\ +# | \/ \/ +# |_/\ /\/\ +# | \/ / +# +# +# Mailboxes can be setup with a 2048 bit PEM format RSA key. +# Simply cr +# + +echo "Welcome to Postreich, Bitreich's gopher powered mail service.\n" \ + "Here you can setup a mailbox and receive mail over the gopher protocol.\n" + +echo "[1|Send mail|sendmail.dcgi|localhost|70]" +echo "[1|Get mail|getmail.dcgi|localhost|70]" + +echo ' + ~~| _.,, + ~~~| C`-o-o_ + ~~~| \ )_/ + ~~| .=|_|=, + ~| / \ \ x \ / +*************** +' + +echo ' +This month we are featuring a special promotion of valentines letters.' + +echo 'Setup a mailbox with your handle and a base64 encoded 2048 bit +PEM format RSA public key' + +echo 'Message are encryted at REST. We do not guarentee any sort of security +or privacy of messages received or stored. However, if you access this service +over gophers you can expect your communications to be sent over tls, of course. +This is more like a community mailbox.' + DIR diff --git a/src/geomyidae/mailboxes.dcgi b/src/geomyidae/mailboxes.dcgi @@ -0,0 +1,2 @@ +#!/bin/sh + DIR diff --git a/src/geomyidae/sendmail.dcgi b/src/geomyidae/sendmail.dcgi @@ -0,0 +1,52 @@ +#!/bin/sh +. ./api/common + +path="$2" +query="$1" + +handle=$( find_value_in_args "handle" "$path" ) +template=$( find_value_in_args "template" "$path" ) + +choose_mailbox() { + ls -x1 "api/$MAILBOXES" \ + | awk -v t="$template" \ + '{ printf "[1|%s|sendmail.dcgi?handle=%s?template=%s|localhost|70]\n", $1, $1, t }' +} + +choose_template() { + ls -x1 "api/$TEMPLATES" \ + | xargs -d '\n' -I x cat "api/$TEMPLATES/"x"/info" \ + | awk -F '\t' -v h="$handle" \ + '{ printf "[1|%s|sendmail.dcgi?template=%s?handle=%s|localhost|70]\n", $2, $1, h }' +} + +show_footer() { + printf "\n\n[1|Start over|sendmail.dcgi|localhost|70]" +} + +if [ -z "$handle" ]; then + printf "Pick recipient:\n" + choose_mailbox + show_footer + return 0 +fi + +if [ -z "$template" ]; then + printf "Pick template:\n" + choose_template + show_footer + return 0 +fi + +result=$( api/$TEMPLATES/$template/main "$path" "$query" ) +if [ ! $? -eq 0 ]; then + printf "%s" "$result" + return 0 +fi + +echo $result + +echo "ready to send" + +show_footer + DIR diff --git a/src/log.txt b/src/log.txt @@ -0,0 +1 @@ +[2024-01-28 21:57:35 +0000|::1|57872|serving] DIR diff --git a/src/serve-geomyidae.sh b/src/serve-geomyidae.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# +# Launch a server for testing. +# +pid=$( pgrep "geomyidae" ) +if [ ! -z "$pid" ]; then + printf "Found existing server with pid %s\n" $pid + # sudo kill $pid + # printf "Killed it\n" +fi +sudo geomyidae -p 70 -h localhost -b ./geomyidae/ -l ./log.txt +if [ $? ]; then + printf "Started new server\n" +else + printf "Could not start new server\n" +fi DIR diff --git a/start-server.sh b/start-server.sh @@ -1,16 +0,0 @@ -#!/bin/bash -# -# Launch a server for testing. -# -pid=$( pgrep geomyidae ) -if [ $? -eq 0 ]; then - printf "Found existing server with pi %s\n" $pid - sudo kill $pid - printf "Killed it\n" -fi -sudo geomyidae -p 70 -h localhost -b ./geomyidae/ -l log.txt -if [ $? ]; then - printf "Started new server\n" -else - printf "Could not start new server\n" -fi