@ -6,6 +6,7 @@ from threading import Thread
import tempfile
import argparse
from string import printable
from base64 import b85decode , b85encode
import socks
from stem . control import Controller
@ -15,6 +16,7 @@ try:
except ModuleNotFoundError :
pass
from youandme . commands import terminator
from youandme . server import server
from youandme . client import client
@ -22,31 +24,37 @@ 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
# taken from (but modified) stackoverflow.com/a/2838309
# by stackoverflow.com/users/133374/albert
# ccy-by-sa-3 creativecommons.org/licenses/by-sa/3.0/
# changes from source: import moved to top of file, bind to localhost
# vulnerable to race condition
s = socket . socket ( socket . AF_INET , socket . SOCK_STREAM )
s . bind ( ( " 127.0.0.1 " , 0 ) )
s . bind ( ( " 127.0.0.1 " , 0 ) )
s . listen ( 1 )
port = s . getsockname ( ) [ 1 ]
s . close ( )
return port
def connector ( host , send_data , recv_data , address = " " , control_port = 1337 , socks_port = 1338 ) :
def connector ( host , send_data , recv_data ,
address = " " , control_port = 1337 , socks_port = 1338 ) :
sock = socket . socket ( socket . AF_INET , socket . SOCK_STREAM )
result = sock . connect_ex ( ( ' 127.0.0.1 ' , socks_port ) )
sock . close ( )
if result != 0 :
try :
launch_tor ( control_port = control_port , socks_port = socks_port )
except OSError :
with tempfile . TemporaryDirectory ( ) as tmpdirname :
launch_tor ( control_port = control_port , socks_port = socks_port , data_dir = tmpdirname )
launch_tor ( control_port = control_port ,
socks_port = socks_port , data_dir = tmpdirname )
if host :
with Controller . from_port ( port = control_port ) as controller :
controller . authenticate ( )
@ -62,7 +70,8 @@ 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 , Connection )
server ( 0.01 , controller , conn , send_data , recv_data ,
Connection )
else :
if not address . endswith ( ' .onion ' ) :
address + = ' .onion '
@ -71,8 +80,10 @@ def connector(host, send_data, recv_data, address="", control_port=1337, socks_p
except socks . GeneralProxyError :
Connection . connected = False
def chat ( mode , send_data , recv_data , alpha ) :
print ( " A notice will be shown when connection is established, but messages may be typed now. " )
print ( " A notice will be shown when connection is established, " +
" but messages may be typed now. " )
display_buffer = [ ]
if mode == ' host ' :
@ -83,27 +94,16 @@ def chat(mode, send_data, recv_data, alpha):
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 :
while len ( display_buffer ) != 0 :
char = display_buffer . pop ( 0 )
if alpha and char not in printable :
continue
print ( " \033 [1;33m " + char + " \033 [0m " , end = " " )
except IndexError :
pass
sleep ( 0.1 )
for message in get_messages
Thread ( target = display_new , daemon = True ) . start ( )
def make_message ( ) :
while True :
new = input ( " \033 [0m " ) . encode ( ' utf-8 ' )
new = input ( " \033 [0m " ) . encode ( ' utf-8 ' ) # nosec
for b in new :
send_data . append ( b )
send_data . append ( ord ( b " \n " ) )
Thread ( target = make_message , daemon = True ) . start ( )
while True :
try :
@ -113,15 +113,25 @@ def chat(mode, send_data, recv_data, alpha):
sleep ( 1 )
except KeyboardInterrupt :
break
PORT_MESSAGE = " Specify any free ports above 1023 "
if __name__ == " __main__ " :
parser = argparse . ArgumentParser ( description = ' End-to-end encrypted instant messaging with metadata privacy and perfect forward secrecy ' )
parser = argparse . ArgumentParser (
description = ' End-to-end encrypted messaging with metadata privacy ' )
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 = ' ' )
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 stdout en-us typical characters ' ,
default = False , type = bool )
parser . add_argument ( ' --address ' ,
help = ' Address to connect to. No port. ' , default = ' ' )
args = parser . parse_args ( )
if args . socks_port == 0 : args . socks_port = _get_open_port ( )
@ -130,16 +140,17 @@ if __name__ == "__main__":
recv_data = bytearray ( )
if args . connection == ' conn ' :
if not args . address :
print ( " Must specify address if connecting (--address) " , file = sys . stderr )
print ( " Must specify address if connecting (--address) " ,
file = sys . stderr )
sys . exit ( 3 )
Thread ( target = connector ,
args = [ False , send_data , recv_data ] ,
kwargs = { ' address ' : args . address ,
' socks_port ' : args . socks_port ,
' control_port ' : args . control_port } , daemon = True ) . start ( )
' control_port ' : args . control_port } , daemon = True ) . start ( )
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 ( )
' control_port ' : args . control_port } , daemon = True ) . start ( )
chat ( ' host ' , send_data , recv_data , args . alphanum_only )