Browse Source

host MUD via ssh over tor with only menus (mostly)

main
deicidus 1 year ago
parent
commit
7f661d2f3f
  1. 2
      README.md
  2. 3
      mud
  3. 30
      spells/add-player
  4. 37
      spells/cantrips/menu
  5. 54
      spells/installers/setup-tor
  6. 26
      spells/menu/mud-admin
  7. 28
      spells/menu/mud-menu
  8. 26
      spells/menu/mud-settings
  9. 115
      spells/menu/network-menu
  10. 19
      spells/menu/select-player
  11. 0
      spells/menu/spellbook
  12. 37
      spells/menu/users-menu
  13. 16
      spells/new-player
  14. 30
      spells/open-portal
  15. 27
      spells/open-teletype
  16. 22
      spells/set-player
  17. 43
      spells/users-menu
  18. 36
      tutorials/00_terminal.sh
  19. 0
      tutorials/rosetta-stone

2
README.md

@ -66,4 +66,6 @@ To cast a spell, `cd` into the spells directory. Then, the first time you cast t
# How to Begin
To access the mud main menu, run chmod +x mud and then ./mud in this directory.
A tutorial is coming soon. For now, explore the `./spells` directory. Try reading or running the `rosetta-stone` script or the `jump` script.

3
mud

@ -0,0 +1,3 @@
#!/bin/sh
mud-menu

30
spells/add-player

@ -0,0 +1,30 @@
#!/bin/sh
# This script creates a new player in the MUD and associates them with an SSH key.
# It first prompts the user for a player name and an SSH key.
# It then checks if a user with that player name and SSH key already exists, and if so, exits.
# If the user and key combination do not already exist, it adds the key to the authorized_keys file and creates the corresponding user.
echo "Enter player name:"
read playername
echo "Enter SSH key:"
read sshkey
# check if user already exists
if id "$playername" >/dev/null 2>&1; then
echo "Error: user $playername already exists. Please delete the existing user first and try again."
exit 1
fi
# check if key already exists in authorized_keys file
if grep -q "$sshkey" ~/.ssh/authorized_keys; then
echo "Error: key already exists in authorized_keys file. Please delete the existing key first and try again."
exit 1
fi
# add key to authorized_keys file
echo "$sshkey $playername@mud" >> ~/.ssh/authorized_keys
# create user
useradd "$playername"

37
spells/cantrips/menu

@ -1,29 +1,34 @@
#!/usr/bin/env sh
# This script generates a menu from the given list of items. Choosing an item runs the command for that item.
# Usage: menu "Please choose" "choice one,choice two with\, a comma,item three" "ls -al,cat \"This string\, has a comma\",command3"
# Usage:
# change_my_password="Change my password%passwd"
# list_users="List all users%cut -d: -f1 /etc/passwd"
# exit="kill -2 $$"
# menu "User management options:" "$change_my_password" "$list_users" "$exit"
# Use up/down arrow keys to select a menu item, then press Enter. Or cancel with ESC.
# Todo: the menu only works with one-word items and commands. maybe this is a problem with loading the arrays? it should work with multi-word items and commands.
. colors
if [ ${#} -lt 2 ]; then
mud-menu
exit 0
fi
description=$1
#shift 1
#parse items array
IFS=',' read -r -a items <<< "$2"
items=("${items[@]//\\,/,}")
shift
# Parse args. Each arg is "name%command"
declare -a items
#parse commands array
IFS=',' read -r -a commands <<< "$3"
commands=("${commands[@]//\\,/,}")
# declare -a descriptions # not displayed so presently disabled
declare -a commands
#items=("$@")
#commands=("${items[@]:3}")
#items=("$2")
#commands=("$3")
#read -r -a items <<< "$2"
#read -r -a commands <<< "$3"
while [ ${#} -gt 0 ]; do
IFS='%' read -r -a option <<< "$1"
items+=("${option[0]}")
#descriptions+=("$(option[1])") # not displayed so presently disabled
commands+=("${option[1]}")
shift
done
selected=0
displayed=0

54
spells/installers/setup-tor

@ -0,0 +1,54 @@
#!/bin/bash
# Ask the user if they want to set up a hidden service
read -p "Do you want to set up a Tor hidden service? [y/n]: " choice
if [ "$choice" = "y" ]; then
# Detect the user's operating system
distro=$(detect-distro)
# Set the path to the Tor configuration file based on the operating system
if [ "$distro" = "arch" ]; then
tor_config_path="/etc/tor/torrc"
elif [ "$distro" = "debian" ]; then
tor_config_path="/etc/tor/torrc"
elif [ "$distro" = "fedora" ]; then
tor_config_path="/etc/tor/torrc"
elif [ "$distro" = "macos" ]; then
tor_config_path="/usr/local/etc/tor/torrc"
else
echo "Error: Unsupported operating system"
exit 1
fi
# Generate a new hidden service address
new_address=$(tor --quiet --hash-password mypassword | awk '{print $4}')
mud_dir="/var/lib/tor/mud/"
# Add the hidden service configuration to the Tor configuration file
echo "HiddenServiceDir $mud_dir" | sudo tee -a $tor_config_path
echo "HiddenServicePort 80 127.0.0.1:80" | sudo tee -a $tor_config_path
#echo "HiddenServiceAuthorizeClient stealth mypassword" | sudo tee -a $tor_config_path #obsolete
# Create the directory if it does not exist
mkdir -p $mud_dir
# Restart the tor service
if [ "$distro" = "arch" ]; then
sudo systemctl restart tor.service
elif [ "$distro" = "debian" ]; then
sudo service tor restart
elif [ "$distro" = "fedora" ]; then
sudo systemctl restart tor
elif [ "$distro" = "macos" ]; then
sudo brew services restart tor
fi
# Output the new hidden service address and path
echo "Your new hidden service address is: $new_address.onion"
echo "Your hidden service directory is located at: $mud_dir"
else
echo "Exiting without setting up a hidden service."
fi

26
spells/menu/mud-admin

@ -0,0 +1,26 @@
#!/bin/sh
# This spell displays the menu for adminning hosting a MUD server.
. colors
display_menu() {
add="Add authorized player%add-player"
list_players="List authorized players%new-player"
list_rooms="List shared rooms%list-rooms"
install="Install%mud-install-menu"
exit="Exit%kill -2 $$" # Commands are run with 'eval' by the menu script, so we can't simply say 'exit'. The keyword $$ gets this scripts PID and the -2 code is SIGINT aka Ctrl-C
menu "MUD main menu:" "$change" "$new" "$install" "$exit"
}
# Catch Ctrl-C and exit
handle_ctrl_c() {
trap 'echo exiting; exit' INT
}
handle_ctrl_c
while true; do
display_menu
done

28
spells/menu/mud-menu

@ -0,0 +1,28 @@
#!/bin/sh
# This spell displays the ao-mud main menu.
. colors
display_menu() {
look="Look Around%ls"
cast="Spellbook%spellbook"
home="Teleport Home%cd"
jump="Teleport to Marker%jump"
portal="Teleport to Portal Chamber%cd /mnt"
settings="MUD Settings%mud-settings"
exit="Exit%kill -2 $$" # Commands are run with 'eval' by the menu script, so we can't simply say 'exit'. The keyword $$ gets this scripts PID and the -2 code is SIGINT aka Ctrl-C
menu "MUD main menu:" "$look" "$cast" "$home" "$jump" "$portal" "$settings" "$exit"
}
# Catch Ctrl-C and exit
handle_ctrl_c() {
trap 'echo exiting; exit' INT
}
handle_ctrl_c
while true; do
display_menu
done

26
spells/menu/mud-settings

@ -0,0 +1,26 @@
#!/bin/sh
# This spell displays the ao-mud main menu.
. colors
display_menu() {
copy="Copy player key to clipboard%copy ~/.ssh/\$MUD_PLAYER.pub"
change="Change Player%select-player"
new="New Player%new-player"
install="Install%mud-install-menu"
exit="Exit%kill -2 $$" # Commands are run with 'eval' by the menu script, so we can't simply say 'exit'. The keyword $$ gets this scripts PID and the -2 code is SIGINT aka Ctrl-C
menu "MUD main menu:" "$copy" "$change" "$new" "$install" "$exit"
}
# Catch Ctrl-C and exit
handle_ctrl_c() {
trap 'echo exiting; exit' INT
}
handle_ctrl_c
while true; do
display_menu
done

115
spells/menu/network-menu

@ -0,0 +1,115 @@
configure_dhcp() {
# Ask for confirmation before proceeding
if ! ask_Yn "The spell of Dynamic Host Configuration Protocol will automatically configure your network settings based on the DHCP server. Would you like to proceed?"; then
return 1
fi
# Check if DHCP is already in use
if ip addr show | grep "dhclient" >/dev/null 2>&1 ; then
printf "DHCP is already in use.\n"
return 0
fi
# Backup the current network configuration
backup_file "/etc/network/interfaces"
# Configure the system to use DHCP
echo "auto lo" > /etc/network/interfaces
echo "iface lo inet loopback" >> /etc/network/interfaces
echo "auto eth0" >> /etc/network/interfaces
echo "iface eth0 inet dhcp" >> /etc/network/interfaces
service networking restart
printf "DHCP has been configured successfully.\n"
}
configure_static_ip() {
# Ask the user for the IP address, netmask, gateway, and DNS server
read -p "Enter the desired IP address: " ip_address
read -p "Enter the netmask (in CIDR notation, e.g. 24): " netmask
read -p "Enter the gateway IP: " gateway
read -p "Enter the DNS server IP: " dns_server
# Check if the static IP address is already configured
if ip addr show | grep -q "$ip_address/$netmask"; then
echo "The static IP address $ip_address/$netmask is already configured. Updating it."
# Delete the existing configuration
sudo ip addr del "$ip_address/$netmask" dev eth0
fi
# Add the new static IP address configuration
sudo ip addr add "$ip_address/$netmask" dev eth0
# Set the gateway
sudo ip route add default via "$gateway"
# Set the DNS server
sudo sed -i "s/^nameserver.*/nameserver $dns_server/" /etc/resolv.conf
echo "Static IP address configuration has been set to $ip_address/$netmask with gateway $gateway and DNS server $dns_server."
}
configure_dhcp() {
# Ask for confirmation before proceeding
ask_Yn "The spell of Dynamic Host Configuration Protocol will automatically configure your network settings based on the DHCP server. Would you like to proceed?"
if [ $? -ne 0 ]; then
return 1
fi
# Check if DHCP is already in use
ip addr show | grep "dhclient" &>/dev/null
if [ $? -eq 0 ]; then
echo -e "${RED}DHCP is already in use.${RESET}"
return 0
fi
# Backup the current network configuration
backup_file "/etc/network/interfaces"
# Configure the system to use DHCP
echo "auto lo" > /etc/network/interfaces
echo "iface lo inet loopback" >> /etc/network/interfaces
echo "auto eth0" >> /etc/network/interfaces
echo "iface eth0 inet dhcp" >> /etc/network/interfaces
service networking restart
echo -e "${GREEN}DHCP has been configured successfully.${RESET}"
}
display_menu() {
# Get the dimensions of the terminal window
window_width=$(tput cols)
window_height=$(tput lines)
# Calculate the number of rows that the menu will occupy
num_rows=$(( ${#items[@]}))
# Calculate the position of the menu
menu_x=$((0))
menu_y=$(row)
# Clear the area of the screen where the menu will be drawn
clear_area $menu_x $menu_y $num_rows $window_width
# Print the menu title
echo -en "\033[$menu_y;$((menu_x + (window_width / 2 - ${#title} / 2)))H$title"
# Print the items and commands
for i in "${!items[@]}"; do
echo -en "\033[$((menu_y + i + 1));$((menu_x + 2))H ${items[$i]}"
done
# Highlight the selected item
echo -en "\033[$((menu_y + selected + 1));$((menu_x + 2))H ${CYAN}${items[$selected]}${RESET}"
# Move the cursor to the selected item
echo -en "\033[$((menu_y + selected + 1));$((menu_x + 2))H"
}
display_menu() {
description="Please choose an option to configure your network settings"
options=("Configure static IP" "Configure DHCP" "Reset to DHCP" "Exit")
commands=("configure_static_ip" "configure_dhcp" "reset_dhcp" "exit")
menu "$description" "${options[@]}" "${commands[@]}"
}

19
spells/menu/select-player

@ -0,0 +1,19 @@
#!/bin/sh
# check if the $MUD_PLAYER environment variable is set
if [ -z "$MUD_PLAYER" ]; then
echo "MUD_PLAYER is not set."
else
echo "MUD_PLAYER is currently set to $MUD_PLAYER"
fi
# get a list of player names from the ~/.ssh/ directory
#options=()
declare -a options
for file in $(find ~/.ssh/ -name "*.pub"); do
player_name=$(basename "$file" ".pub")
options+=("$player_name%set-player $player_name")
done
options+=("Cancel%kill -2 $$")
menu "Choose your player:" "${options[@]}"

0
spells/spellbook → spells/menu/spellbook

37
spells/menu/users-menu

@ -0,0 +1,37 @@
#!/bin/sh
# This script presents a menu of options for managing users on the system.
. colors
display_menu() {
change_my_password="Change my password%passwd"
list_users="List all users%cut -d: -f1 /etc/passwd"
change_other_password="Change other user's password%read -p \"Enter username: \" username; sudo passwd \$username"
view_my_groups="View my group memberships%groups"
view_other_groups="View other user's group membership%read -p \"Enter username: \" username; groups \$username"
list_groups="List all groups%cut -d: -f1 /etc/group"
create_group="Create new group%read -p \"Enter new group name: \" groupname; sudo groupadd \$groupname"
delete_group="Delete group%read -p \"Enter group to delete: \" groupname; sudo groupdel \$groupname"
join_group="Join group%read -p \"Enter group name to join: \" groupname; sudo usermod -a -G \$groupname \$USER"
leave_group="Leave group%read -p \"Enter group name to leave: \" group; sudo gpasswd -d \$USER \$group"
list_users_in_group="List users in group%read -p \"Enter group name to list members: \" group; getent group \$group"
add_user_to_group="Add other user to group%read -p \"Enter username: \" username; read -p \"Enter group name to add them to: \" group; sudo usermod -a -G \$group \$username"
remove_user_from_group="Remove other user from group%read -p \"Enter username: \" username; read -p \"Enter group to remove them from: \" group; sudo gpasswd -d \$username \$group"
create_user="Create new user%read -p \"Enter new username: \" username; sudo useradd \$username; printf \"Please remember to set a password for the new user with the 'Change other user's password' option.\""
delete_user="Delete user%read -p \"Enter username of user to delete: \" username; sudo userdel \$username"
exit="Exit%kill -2 $$" # $$ is my pid. Commands are run with 'eval' by the menu script, so we can't simply say 'exit'. The keyword $$ gets this scripts PID and the -2 code is SIGINT aka Ctrl-C
menu "User management options:" "$change_my_password" "$list_users" "$change_other_password" "$view_my_groups" "$view_other_groups" "$list_groups" "$create_group" "$delete_group" "$join_group" "$leave_group" "$list_users_in_group" "$add_user_to_group" "$remove_user_from_group" "$create_user" "$delete_user" "$exit"
}
# Catch Ctrl-C and exit
handle_ctrl_c() {
trap 'echo exiting; exit' INT
}
handle_ctrl_c
while true; do
display_menu
done

16
spells/new-player

@ -0,0 +1,16 @@
#!/bin/sh
# Prompt user for player name
echo "Enter a player name:"
read player_name
# Check if key files already exist
if [ -f ~/.ssh/${player_name} ] && [ -f ~/.ssh/${player_name}.pub ]; then
echo "Key files for player ${player_name} already exist. Please enter a different player name:"
read player_name
fi
# Generate ssh key
ssh-keygen -t rsa -b 4096 -C "${player_name}@MUD" -f ~/.ssh/${player_name} -q -N ""
echo "New player ${player_name} created with ssh key files at ~/.ssh/${player_name} and ~/.ssh/${player_name}.pub"

30
spells/open-portal

@ -0,0 +1,30 @@
#!/bin/sh
# POSIX-compliant script for mounting a remote directory using sshfs over Tor
# Check for required commands
if ! command -v sshfs &> /dev/null; then
echo "Error: sshfs command not found. Please install sshfs and try again."
exit 1
fi
if ! command -v torify &> /dev/null; then
echo "Error: torify command not found. Please install tor and try again."
exit 1
fi
# Get player key
if [ -z "$MUD_PLAYER" ]; then
echo "Error: MUD_PLAYER environment variable not set."
exit 1
fi
player_key="$HOME/.ssh/$MUD_PLAYER"
# Get tor address and remote directory
read -p "Enter the Tor address of the remote server (e.g. onion.example.com): " tor_address
read -p "Enter the remote directory to mount (e.g. /mnt/remote): " remote_dir
# Strip or add trailing slashes as required by sshfs
remote_dir="${remote_dir%/}/"
# Mount the remote directory using sshfs over tor
torify sshfs -o IdentityFile="$player_key" "$tor_address:$remote_dir" "$remote_dir"

27
spells/open-teletype

@ -0,0 +1,27 @@
#!/bin/sh
# POSIX-compliant script for mounting a remote directory using sshfs over Tor
# Check for required commands
if ! command -v torify &> /dev/null; then
echo "Error: torify command not found. Please install tor and try again."
exit 1
fi
# Get player key
if [ -z "$MUD_PLAYER" ]; then
echo "Error: MUD_PLAYER environment variable not set."
exit 1
fi
# Prompt user for tor address and remote directory
echo "Enter the tor address:"
read tor_address
echo "Enter the remote directory:"
read remote_dir
# Strip or add trailing slashes as required
remote_dir="${remote_dir%/}/"
# Connect to remote directory via ssh through torify
torify ssh -i ~/.ssh/$MUD_PLAYER "$tor_address:$remote_dir"

22
spells/set-player

@ -0,0 +1,22 @@
#!/bin/sh
# This spell sets the current player in the MUD using an environment variable.
# You must source this script with ". ./set-player playername" to change it immediately (or open a new terminal window).
player="$1"
if [ -z "$player" ]; then
echo "Please provide a player name as an argument."
exit 1
fi
echo "Setting MUD_PLAYER to $player"
# Remove any existing line setting MUD_PLAYER in .bashrc
sed -i '/^export MUD_PLAYER/d' ~/.bashrc
# Append new line to .bashrc to set MUD_PLAYER and export it
echo "export MUD_PLAYER=$player" >> ~/.bashrc
# Set MUD_PLAYER in current shell session
export MUD_PLAYER="$player"

43
spells/users-menu

@ -1,43 +0,0 @@
# This script presents a menu of options for managing users on the system. The options available include:
# - Viewing the groups a user is in
# - Adding a user to a group
# - Changing a user's password
# - Creating a new user
# - Deleting an existing user
# - Exit the script
. colors
display_menu() {
options="Change my password,Change other user's password,View my group memberships,View other user's group membership,List all groups,Create new group,Delete group,Join group,Leave group,Add other user to group,Remove other user from group,Create new user,Delete user,Exit"
view_my_groups="groups"
view_other_groups="read -p \"Enter username: \" username; groups \$username"
change_my_password="passwd"
change_other_password="read -p \"Enter username: \" username; sudo passwd \$username"
list_groups="cut -d: -f1 /etc/group"
create_group="read -p \"Enter new group name: \" groupname; sudo groupadd \$groupname"
delete_group="read -p \"Enter group to delete: \" groupname; sudo groupdel \$groupname"
join_group="read -p \"Enter group name to join: \" groupname; sudo usermod -a -G \$groupname \$USER"
leave_group="read -p \"Enter group name to leave: \" group; sudo gpasswd -d \$USER \$group"
add_user_to_group="read -p \"Enter username: \" username; read -p \"Enter group name to add them to: \" group; sudo usermod -a -G \$group \$username"
remove_user_from_group="read -p \"Enter username: \" username; read -p \"Enter group to remove them from: \" group; sudo gpasswd -d \$username \$group"
create_user="read -p \"Enter new username: \" username; sudo useradd \$username; printf \"Please remember to set a password for the new user with the 'Change other user's password' option.\""
delete_user="read -p \"Enter username of user to delete: \" username; sudo userdel \$username"
my_pid=$$
exit="kill -2 $my_pid" # Commands are run with 'eval' by the menu script, so we can't simply say 'exit'. The keyword $$ gets this scripts PID and the -2 code is SIGINT aka Ctrl-C
commands="$change_my_password,$change_other_password,$view_my_groups,$view_other_groups,$list_groups,$create_group,$delete_group,$join_group,$leave_group,$add_user_to_group,$remove_user_from_group,$create_user,$delete_user,$exit"
menu "User management options:" "$options" "$commands"
}
# Catch Ctrl-C and exit
handle_ctrl_c() {
trap 'echo exiting; exit' INT
}
handle_ctrl_c
while true; do
display_menu
done

36
tutorials/00_terminal.sh

@ -0,0 +1,36 @@
#!/bin/sh
# To make this script executable, use the command: chmod +x 00_terminal.sh
# To run the script, use the command: ./00_terminal.sh
echo "Welcome, neophyte, to the AO-MUD POSIX-compliant bash tutorial series!"
echo "This spell will teach you some basic terminal tricks and keyboard shortcuts"
echo "To study the code of the examples, please use the command: cat 23_terminal.sh"
# Pressing up to get the last run command
echo "To get the last run command, press the up arrow key"
# Ctrl-R to search for commands
echo "To search for a command in your command history, press Ctrl-R and type in a search term"
# Entering multi-line input before running a command
echo "To enter multi-line input before running a command, press Ctrl-X followed by Ctrl-E"
# Moving the cursor around on the line
echo "To move the cursor around on the line, use the left and right arrow keys"
# Copying and pasting
echo "To copy, use Ctrl-Shift-C. To paste, use Ctrl-Shift-V"
#Clearing the terminal
echo "To clear the terminal, press Ctrl + L"
#Going to the beginning/end of a line
echo "Press Home or End to move to the beginning or end of a line respectively"
echo "Cast spell finished, check the code of the spell by using 'cat 23_terminal.sh' command"
# Use !! to repeat the last command
echo "To repeat the last command, use the command: !!"
echo "For example, to repeat the last command with 'sudo', use: sudo !!"
echo "Spell cast successfully!"

0
spells/rosetta-stone → tutorials/rosetta-stone

Loading…
Cancel
Save