2020-04-11 19:13:03 +00:00
|
|
|
#!venv/bin/python
|
2020-06-04 13:24:17 +05:30
|
|
|
# replace the above line with the path to your virtual environment.
|
2020-04-11 18:42:11 +05:30
|
|
|
|
2020-04-11 21:09:58 +05:30
|
|
|
import os
|
|
|
|
|
import socket
|
|
|
|
|
import secrets
|
|
|
|
|
import sys
|
|
|
|
|
import getopt
|
|
|
|
|
import re
|
2020-04-11 23:54:57 +05:30
|
|
|
from time import gmtime, strftime
|
2020-04-11 19:32:52 +05:30
|
|
|
|
2020-04-11 20:46:22 +05:30
|
|
|
# Config
|
2020-04-11 23:54:57 +05:30
|
|
|
|
|
|
|
|
|
2020-04-11 20:46:22 +05:30
|
|
|
def main(theargs):
|
|
|
|
|
# where to serve this page.
|
|
|
|
|
# 127.0.0.1 / localhost => only accessible locally, on this machine
|
2020-04-11 21:09:58 +05:30
|
|
|
# 0.0.0.0 => accessible to the internet, by any host
|
2020-04-11 20:46:22 +05:30
|
|
|
hostname = "0.0.0.0"
|
|
|
|
|
|
|
|
|
|
# which port number to bind to
|
|
|
|
|
# choose a port number > 1000, to prevent interference with system processes
|
2020-04-11 22:15:44 +05:30
|
|
|
port = 8888
|
2020-04-11 20:46:22 +05:30
|
|
|
|
|
|
|
|
# maximum number of clients this can handle at any given time
|
|
|
|
|
queue_depth = 10
|
|
|
|
|
|
|
|
|
|
# directory path
|
2020-04-11 22:15:44 +05:30
|
|
|
# default is $HOME i.e. /home/username/socksbin
|
|
|
|
|
output_directory = os.path.join(os.path.expanduser("~"), "socksbin")
|
2020-04-11 21:09:58 +05:30
|
|
|
# specify the length of generated filename. multiples of 2 only
|
2020-04-11 20:46:22 +05:30
|
|
|
slug_size = 8
|
|
|
|
|
|
|
|
|
|
# amount of data transferred at a time, in bytes
|
2020-04-11 21:09:58 +05:30
|
|
|
# set between 4096 and 64000.
|
2020-04-11 20:46:22 +05:30
|
|
|
buffer_size = 32768
|
|
|
|
|
|
2020-04-11 22:15:44 +05:30
|
|
|
log = False
|
2020-04-11 20:46:22 +05:30
|
|
|
# path for log file
|
|
|
|
|
log_file = "/tmp/socklog.txt"
|
|
|
|
|
|
2020-04-11 22:15:44 +05:30
|
|
|
# base url where the file will be served to the user
|
2020-04-12 01:20:12 +05:30
|
|
|
base_url = "http://localhost/"
|
2020-04-11 22:15:44 +05:30
|
|
|
|
|
|
|
|
helpmessage = """
|
|
|
|
|
Welcome to SocksBin, the command line pastebin !
|
2020-04-11 20:46:22 +05:30
|
|
|
Released under GNU GPL.
|
|
|
|
|
|
2020-04-11 22:15:44 +05:30
|
|
|
-n --hostname\tSet the hostname to listen for. 0.0.0.0 by default.
|
2020-04-11 19:44:57 +00:00
|
|
|
-p --port\t\tExternel port number to listen on. 8888 by default
|
2020-04-11 20:46:22 +05:30
|
|
|
-q --queue_depth\tMax number of simultaneous connections to accept
|
2020-04-11 19:44:57 +00:00
|
|
|
-o --output_directory File storage location. $HOME/socksbin by default
|
2020-04-11 20:46:22 +05:30
|
|
|
-s --slug_size\tLength of url to generate.
|
2020-06-04 13:24:17 +05:30
|
|
|
-b --buffer_size\tPacket size in bytes.
|
2020-04-11 19:44:57 +00:00
|
|
|
-l --log_file\tPath to log file.
|
2020-04-11 20:46:22 +05:30
|
|
|
-h --help\t\tDisplay this message
|
2020-04-12 01:12:20 +05:30
|
|
|
-u --url\t\tSpecify the url to append to when giving the link to the user.
|
2020-04-11 20:46:22 +05:30
|
|
|
"""
|
|
|
|
|
try:
|
2020-04-11 22:15:44 +05:30
|
|
|
if theargs[0] == "-h" or theargs[0] == "--help":
|
|
|
|
|
print(helpmessage)
|
|
|
|
|
sys.exit()
|
|
|
|
|
except IndexError:
|
|
|
|
|
pass
|
|
|
|
|
try:
|
|
|
|
|
opts, args = getopt.getopt(theargs, "n:p:q:o:s:b:l:u:", [
|
|
|
|
|
"hostname=", "port=", "queue_depth=", "output_directory=", "slug_size=", "buffer_size=", "log_file=", "url="])
|
2020-04-11 20:46:22 +05:30
|
|
|
for opt, arg in opts:
|
|
|
|
|
if opt in ['-n', '--hostname']:
|
|
|
|
|
if arg.find('/') != -1:
|
|
|
|
|
print("Incorrect hostname. / not allowed. Run with -h for options")
|
|
|
|
|
sys.exit()
|
|
|
|
|
else:
|
|
|
|
|
hostname = arg
|
|
|
|
|
elif opt in ['-p', "--port"]:
|
|
|
|
|
if re.match("^ *\d[\d ]*$", arg) is None:
|
2020-04-11 21:09:58 +05:30
|
|
|
print(
|
|
|
|
|
"Incorrect port format. Choose a number between 0 and 64738. Warning: ports below 1000 could interfere with system processes.")
|
2020-04-11 20:46:22 +05:30
|
|
|
sys.exit()
|
|
|
|
|
elif int(arg) > 64738:
|
2020-04-11 21:09:58 +05:30
|
|
|
print(
|
|
|
|
|
"Incorrect port format. Choose a number between 0 and 64738. Warning: ports below 1000 could interfere with system processes.")
|
2020-04-11 20:46:22 +05:30
|
|
|
sys.exit()
|
|
|
|
|
elif int(arg) < 1000:
|
2020-04-11 21:09:58 +05:30
|
|
|
choice = input(
|
|
|
|
|
"Warning: ports below 1000 could interfere with system processes. Do you want to choose a different port ? (y/n): ")
|
2020-04-11 20:46:22 +05:30
|
|
|
|
|
|
|
|
if choice.lower() == "y":
|
|
|
|
|
arg = input("Please enter your new port number: ")
|
|
|
|
|
if re.match("^ *\d[\d ]*$", arg) is None:
|
2020-04-11 21:09:58 +05:30
|
|
|
print(
|
|
|
|
|
"Incorrect port format. Choose a number between 1000 and 64738")
|
2020-04-11 20:46:22 +05:30
|
|
|
sys.exit()
|
|
|
|
|
else:
|
2020-04-11 22:15:44 +05:30
|
|
|
port = int(arg)
|
2020-04-11 20:46:22 +05:30
|
|
|
elif choice.lower() == "n":
|
|
|
|
|
pass
|
|
|
|
|
|
2020-04-11 21:09:58 +05:30
|
|
|
port = int(arg)
|
2020-04-11 20:46:22 +05:30
|
|
|
elif opt in ['-q', "--queue_depth"]:
|
2020-04-11 21:09:58 +05:30
|
|
|
if not arg.isdigit():
|
|
|
|
|
print(
|
|
|
|
|
"Queue depth can only be an integer. Run with -h for more options")
|
|
|
|
|
sys.exit()
|
2020-04-11 22:15:44 +05:30
|
|
|
elif int(arg) > 1000 or int(arg) < 2:
|
|
|
|
|
print("Queue depth has to be between 2 and 1000")
|
|
|
|
|
sys.exit()
|
|
|
|
|
|
2020-04-11 21:09:58 +05:30
|
|
|
queue_depth = int(arg)
|
2020-04-11 20:46:22 +05:30
|
|
|
elif opt in ['-o', "--output_directory"]:
|
2020-04-11 21:09:58 +05:30
|
|
|
directory = arg
|
|
|
|
|
if os.path.isdir(directory):
|
|
|
|
|
permission = (isWritable(directory))
|
|
|
|
|
|
|
|
|
|
if not permission:
|
2020-04-11 22:15:44 +05:30
|
|
|
print(
|
|
|
|
|
f"You do not have permissions to write to {directory}")
|
2020-04-11 21:09:58 +05:30
|
|
|
sys.exit()
|
|
|
|
|
else:
|
|
|
|
|
output_directory = arg
|
|
|
|
|
else:
|
2020-04-11 22:15:44 +05:30
|
|
|
parent_dir = (os.path.abspath(
|
|
|
|
|
os.path.join(directory, os.pardir)))
|
2020-04-11 21:09:58 +05:30
|
|
|
|
|
|
|
|
if not os.path.isdir(parent_dir):
|
2020-04-11 22:15:44 +05:30
|
|
|
print(
|
|
|
|
|
f"The parent folder {parent_dir} does not exist. Please try again after creating it.")
|
2020-04-11 21:09:58 +05:30
|
|
|
sys.exit()
|
|
|
|
|
permission = (isWritable(parent_dir))
|
2020-04-11 22:15:44 +05:30
|
|
|
|
2020-04-11 21:09:58 +05:30
|
|
|
if not permission:
|
2020-04-11 22:15:44 +05:30
|
|
|
print(
|
|
|
|
|
f"You do not have permissions to write to {directory}, or the parent folder {parent_dir} does not exist")
|
2020-04-11 21:09:58 +05:30
|
|
|
sys.exit()
|
|
|
|
|
else:
|
|
|
|
|
try:
|
|
|
|
|
os.makedirs(directory)
|
|
|
|
|
print(f"> Directory {directory} created !")
|
|
|
|
|
output_directory = arg
|
|
|
|
|
except OSError:
|
2020-04-11 22:15:44 +05:30
|
|
|
print(
|
|
|
|
|
"unable to create directory. Please check your permissions.")
|
|
|
|
|
sys.exit()
|
2020-04-11 20:46:22 +05:30
|
|
|
elif opt in ['-s', "--slug_size"]:
|
2020-04-11 22:15:44 +05:30
|
|
|
if not arg.isdigit():
|
|
|
|
|
print("slug length can only be a integer, between 4 and 20")
|
|
|
|
|
sys.exit()
|
|
|
|
|
elif int(arg) > 20 or int(arg) < 2:
|
|
|
|
|
print("Slug length has to be between 4 and 20")
|
|
|
|
|
sys.exit()
|
|
|
|
|
else:
|
|
|
|
|
slug_size = int(arg)
|
2020-04-11 20:46:22 +05:30
|
|
|
elif opt in ['-b', "--buffer_size"]:
|
2020-04-11 22:15:44 +05:30
|
|
|
|
|
|
|
|
if not arg.isdigit():
|
|
|
|
|
print("buffer length can only be a integer, between 1024 and 60000")
|
|
|
|
|
sys.exit()
|
|
|
|
|
elif int(arg) > 60000 or int(arg) < 1024:
|
|
|
|
|
print("buffer length has to be between 1024 and 60000")
|
|
|
|
|
sys.exit()
|
|
|
|
|
else:
|
|
|
|
|
buffer_size = int(arg)
|
2020-04-11 20:46:22 +05:30
|
|
|
elif opt in ['-l', "--log_file"]:
|
2020-04-11 22:15:44 +05:30
|
|
|
try:
|
|
|
|
|
parent_dir = (os.path.abspath(
|
|
|
|
|
os.path.join(arg, os.pardir)))
|
|
|
|
|
except:
|
|
|
|
|
print("Error while creating log file. Incorrect format.")
|
|
|
|
|
sys.exit()
|
2020-04-11 21:09:58 +05:30
|
|
|
|
2020-04-11 22:15:44 +05:30
|
|
|
if not os.path.isdir(parent_dir):
|
|
|
|
|
print(
|
|
|
|
|
f"The parent folder {parent_dir} does not exist. Please try again after creating it.")
|
|
|
|
|
sys.exit()
|
|
|
|
|
permission = (isWritable(parent_dir))
|
|
|
|
|
|
|
|
|
|
if not permission:
|
|
|
|
|
print(
|
|
|
|
|
f"You do not have permissions to write to {arg}, or the parent folder {parent_dir} does not exist")
|
|
|
|
|
sys.exit()
|
|
|
|
|
log_file = arg
|
|
|
|
|
log = True
|
|
|
|
|
elif opt in ['-h', '--help']:
|
|
|
|
|
print(helpmessage)
|
|
|
|
|
sys.exit()
|
|
|
|
|
elif opt in ['-u', '--url']:
|
|
|
|
|
base_url = arg
|
|
|
|
|
|
|
|
|
|
constants = ({
|
2020-04-11 21:09:58 +05:30
|
|
|
"hostname": hostname,
|
|
|
|
|
"port": port,
|
2020-04-11 22:15:44 +05:30
|
|
|
"queue_depth": queue_depth,
|
|
|
|
|
"output_directory": output_directory,
|
|
|
|
|
"slug_size": slug_size,
|
|
|
|
|
"buffer_size": buffer_size,
|
|
|
|
|
"log": log,
|
|
|
|
|
"log_file": log_file,
|
|
|
|
|
"base_url": base_url
|
2020-04-11 20:46:22 +05:30
|
|
|
})
|
|
|
|
|
|
|
|
|
|
except getopt.GetoptError as err:
|
|
|
|
|
print(err)
|
|
|
|
|
print("Run with -h or --help to see the various options")
|
2020-04-11 19:32:52 +05:30
|
|
|
|
2020-04-11 22:15:44 +05:30
|
|
|
server(constants)
|
2020-04-11 19:32:52 +05:30
|
|
|
#######################################################################################
|
|
|
|
|
|
2020-04-11 22:15:44 +05:30
|
|
|
|
|
|
|
|
def server(config):
|
2020-04-11 19:32:52 +05:30
|
|
|
# create the socket
|
|
|
|
|
# AF_INET => IPv4
|
|
|
|
|
# SOCK_STREAM => TCP Connections
|
|
|
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
|
|
2020-04-11 22:15:44 +05:30
|
|
|
s.bind((config['hostname'], config['port']))
|
2020-04-11 19:32:52 +05:30
|
|
|
|
2020-04-11 22:15:44 +05:30
|
|
|
s.listen(config['queue_depth'])
|
2020-04-11 19:32:52 +05:30
|
|
|
|
|
|
|
|
while True:
|
2020-04-11 23:54:57 +05:30
|
|
|
try:
|
|
|
|
|
clientSocket, address = s.accept()
|
|
|
|
|
print(f"Connection from {address} has been established")
|
|
|
|
|
filepath = secrets.token_hex(config['slug_size'])
|
|
|
|
|
filepath = filepath[:config['slug_size']]
|
|
|
|
|
clientSocket.sendall(
|
2020-04-11 19:13:03 +00:00
|
|
|
bytes(config['base_url']+filepath+"\n", "utf-8"))
|
2020-04-11 23:54:57 +05:30
|
|
|
clientSocket.shutdown(socket.SHUT_WR)
|
|
|
|
|
|
|
|
|
|
full_message = ""
|
|
|
|
|
while True:
|
|
|
|
|
data = clientSocket.recv(config['buffer_size'])
|
|
|
|
|
if len(data) <= 0:
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
full_message += data.decode('utf-8')
|
|
|
|
|
|
|
|
|
|
with open(os.path.join(config['output_directory'], filepath), 'w') as writer:
|
|
|
|
|
writer.write(full_message)
|
|
|
|
|
|
2020-04-11 19:13:03 +00:00
|
|
|
with open(os.path.join(config['output_directory'], filepath + "_color"), 'w') as writer:
|
2020-04-11 23:54:57 +05:30
|
|
|
received_code = full_message
|
|
|
|
|
try:
|
|
|
|
|
from pygments.formatters.html import HtmlFormatter
|
|
|
|
|
from pygments import highlight
|
|
|
|
|
from pygments.lexers import guess_lexer
|
|
|
|
|
lexer = guess_lexer(received_code)
|
|
|
|
|
fmter = HtmlFormatter(
|
|
|
|
|
noclasses=True, style="colorful", linenos=True)
|
|
|
|
|
|
|
|
|
|
result = highlight(received_code, lexer, fmter)
|
|
|
|
|
|
|
|
|
|
writer.write(result)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print("unable to format")
|
|
|
|
|
print(e)
|
|
|
|
|
if config['log']:
|
|
|
|
|
showtime = strftime("%Y-%m-%d %H:%M:%S", gmtime())
|
|
|
|
|
with open(config['log_file'], 'a') as logFile:
|
|
|
|
|
logFile.write(f"Time: {showtime}\t")
|
|
|
|
|
logFile.write(f"Address: {address} \t")
|
|
|
|
|
logFile.write(f"file: {filepath} \n")
|
|
|
|
|
except Exception as e:
|
2020-06-04 13:21:38 +05:30
|
|
|
print(e)
|
2020-04-11 23:54:57 +05:30
|
|
|
if config['log']:
|
|
|
|
|
with open(config['log_file']+"_e.txt", 'a') as logFile:
|
|
|
|
|
logFile.write(f"# Address: {address}\t")
|
|
|
|
|
logFile.write(f"message: {full_message}\t")
|
|
|
|
|
logFile.write(f"Error: {e}")
|
2020-04-11 19:32:52 +05:30
|
|
|
|
|
|
|
|
|
2020-04-11 21:09:58 +05:30
|
|
|
def isWritable(directory):
|
|
|
|
|
|
|
|
|
|
try:
|
2020-04-11 22:15:44 +05:30
|
|
|
tmp_prefix = "write_tester"
|
2020-04-11 21:09:58 +05:30
|
|
|
count = 0
|
|
|
|
|
filename = os.path.join(directory, tmp_prefix)
|
|
|
|
|
while(os.path.exists(filename)):
|
2020-04-11 22:15:44 +05:30
|
|
|
filename = "{}.{}".format(
|
|
|
|
|
os.path.join(directory, tmp_prefix), count)
|
2020-04-11 21:09:58 +05:30
|
|
|
count = count + 1
|
2020-04-11 22:15:44 +05:30
|
|
|
f = open(filename, "w")
|
2020-04-11 21:09:58 +05:30
|
|
|
f.close()
|
|
|
|
|
os.remove(filename)
|
|
|
|
|
return True
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return False
|
|
|
|
|
|
2020-04-11 23:54:57 +05:30
|
|
|
|
2020-04-11 19:32:52 +05:30
|
|
|
if __name__ == "__main__":
|
2020-04-11 21:09:58 +05:30
|
|
|
main(sys.argv[1:])
|