added connection loss detection, strict printable character filter support

This commit is contained in:
Kevin Froman 2020-04-23 22:18:29 -05:00
parent e47173b586
commit 0173f136fb
6 changed files with 56 additions and 22 deletions

View File

@ -2,6 +2,17 @@
This project uses Semantic Versioning
## 1.1.1
Fixed setup.py project URL
## 1.1.0
Added detection of connection loss
Added --alphanum-only argument
## 1.0.0
Made yam a proper script (install and you can run from path with $ yam.py <args>)

View File

@ -7,7 +7,7 @@ with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:
packages = find_packages(exclude=['contrib', 'docs', 'tests'])
setup(name='youandme',
version='1.0.0',
version='1.1.1',
description='Simple private data sharing via bytearrays, Tor tunneling and metadata paranoia',
long_description=long_description,
long_description_content_type='text/markdown',
@ -15,7 +15,7 @@ setup(name='youandme',
packages=packages,
scripts=['src/yam/yam.py'],
author_email='beardog@mailbox.org',
url='https://chaoswebs.net',
url='http://github.com/beardog108/youandme',
install_requires=[
'stem',
'PySocks'

View File

@ -1,11 +1,13 @@
#!/usr/bin/env python3
import sys
import socket
from time import time, sleep
from time import sleep
from threading import Thread
import tempfile
import argparse
from string import printable
import socks
from stem.control import Controller
try:
@ -16,9 +18,15 @@ except ModuleNotFoundError:
from youandme.server import server
from youandme.client import client
class Connection:
connected = True
class _Address:
address = ""
def _get_open_port():
# taken from (but modified) https://stackoverflow.com/a/2838309 by https://stackoverflow.com/users/133374/albert ccy-by-sa-3 https://creativecommons.org/licenses/by-sa/3.0/
# changes from source: import moved to top of file, bind specifically to localhost
@ -54,29 +62,38 @@ def connector(host, send_data, recv_data, address="", control_port=1337, socks_p
)
_Address.address = serv.service_id
conn, addr = s.accept()
server(0.01, controller, conn, send_data, recv_data)
server(0.01, controller, conn, send_data, recv_data, Connection)
else:
if not address.endswith('.onion'):
address += '.onion'
client(0.01, address, socks_port, send_data, recv_data)
try:
client(0.01, address, socks_port, send_data, recv_data, Connection)
except socks.GeneralProxyError:
Connection.connected = False
def chat(mode, send_data, recv_data):
def chat(mode, send_data, recv_data, alpha):
print("A notice will be shown when connection is established, but messages may be typed now.")
display_buffer = []
if mode == 'host':
print('Creating tunnel...')
while _Address.address == "":
sleep(0.01)
print('Tunnel address:')
print(_Address.address)
def display_new():
while True:
try:
char = chr(recv_data.pop(0))
display_buffer.append(char)
if char == "\n" or char == "\r\n" or len(display_buffer) > 100:
#print("\033[1;33m", char, "\033[0m", end="\n")
while len(display_buffer) != 0:
#print("\033[1;33m", display_buffer.pop(0), "\033[0m", end='')
print("\033[1;33m" + display_buffer.pop(0) + "\033[0m", end="")
char = display_buffer.pop(0)
if alpha and char not in printable and \
char not in ('\n', '\r', ' ', '\t'):
continue
print("\033[1;33m" + char + "\033[0m", end="")
except IndexError:
pass
@ -91,8 +108,8 @@ def chat(mode, send_data, recv_data):
Thread(target=make_message, daemon=True).start()
while True:
try:
if send_data is None:
print("Well crap, we lost connection.")
if not Connection.connected:
print("Cease dancing ☹️")
break
sleep(1)
except KeyboardInterrupt:
@ -100,10 +117,11 @@ def chat(mode, send_data, recv_data):
PORT_MESSAGE = "Specify any free ports above 1023"
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='End-to-end encrpyted instant messaging with metadata privacy and perfect forward secrecy')
parser = argparse.ArgumentParser(description='End-to-end encrypted instant messaging with metadata privacy and perfect forward secrecy')
parser.add_argument('connection', choices=['host', 'conn'])
parser.add_argument('--socks-port', help='Socks proxy port (will use random if not given)', default=0, type=int)
parser.add_argument('--control-port', help='Tor control port (will use random if not given)', default=0, type=int)
parser.add_argument('--alphanum-only', help='Only allow english alpha-numeric characters and spaces/tabs/new lines', default=False, type=bool)
parser.add_argument('--address', help='Address to connect to. No port.', default='')
args = parser.parse_args()
@ -120,9 +138,9 @@ if __name__ == "__main__":
kwargs={'address': args.address,
'socks_port': args.socks_port,
'control_port': args.control_port}, daemon=True).start()
chat('conn', send_data, recv_data)
chat('conn', send_data, recv_data, args.alphanum_only)
else:
Thread(target=connector, args=[True, send_data, recv_data],
kwargs={'socks_port': args.socks_port,
'control_port': args.control_port}, daemon=True).start()
chat('host', send_data, recv_data)
chat('host', send_data, recv_data, args.alphanum_only)

View File

@ -4,14 +4,17 @@ from time import sleep
import socks
from .commands import garbage_character
from .commands import WELCOME_MESSAGE
def client(delay: int, hs_id, socks_port, send_data: bytearray, recv_data: bytearray):
def client(delay: int, hs_id, socks_port, send_data: bytearray, recv_data: bytearray, connection: "Connection"):
s = socks.socksocket() # Same API as socket.socket in the standard lib
s.set_proxy(socks.SOCKS5, "127.0.0.1", socks_port, rdns=True)
def send_loop():
for i in WELCOME_MESSAGE:
send_data.append(ord(i))
while True:
to_send = None
if send_data:
@ -27,9 +30,9 @@ def client(delay: int, hs_id, socks_port, send_data: bytearray, recv_data: bytea
s.send(to_send)
except BrokenPipeError:
# lost connection
pass
connection.connected = False
except BrokenPipeError:
pass
connection.connected = False
sleep(delay)
# Can be treated identical to a regular socket object

View File

@ -1 +1,2 @@
garbage_character = b'\x00'
garbage_character = b'\x00'
WELCOME_MESSAGE = "Connection established. Dance like no one is watching :)\n"

View File

@ -1,11 +1,12 @@
import socket
import time
from.commands import garbage_character
from.commands import WELCOME_MESSAGE
from threading import Thread
def server(delay: int, controller, conn, send_data: bytearray, recv_data: bytearray):
def server(delay: int, controller, conn, send_data: bytearray, recv_data: bytearray, connection: "Connection"):
def send_loop():
while True:
time.sleep(delay)
@ -22,15 +23,15 @@ def server(delay: int, controller, conn, send_data: bytearray, recv_data: bytear
except TypeError:
conn.sendall(chr(char).encode('utf-8'))
except OSError:
pass
connection.connected = False
first_rec = True
WELCOME_MESSAGE = "Connection established\n"
with conn:
Thread(target=send_loop, daemon=True).start()
while True:
try:
data = conn.recv(1)
except ConnectionResetError:
connection.connected = False
break
if not data: break
if first_rec: