mirror of
http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/darknet-lantern.git
synced 2025-05-16 20:26:58 +00:00
290 lines
12 KiB
Python
290 lines
12 KiB
Python
import os, pwd
|
|
def main():
|
|
|
|
rootpath='/srv/darknet-onion-webring/'
|
|
urlpath=pwd.getpwuid(os.getuid()).pw_dir+"/.darknet_participant_url"
|
|
print(urlpath)
|
|
isitvalid="n"
|
|
|
|
#check if ~/.darknet_participant_url exists,
|
|
# if exists, instance= the content of ~/.darknet_participant_url (which is the url: such as uptime.nowherejez...onion)
|
|
|
|
while isitvalid != "y":
|
|
if os.path.isfile(urlpath):
|
|
with open(urlpath) as f:
|
|
instance = f.read()
|
|
# TODO check if the instance URL domain is valid
|
|
instancepath=rootpath+'www/participants/'+instance
|
|
print("[+] file exists, your Webring URL is ", instance)
|
|
isitvalid = "y"
|
|
else:
|
|
print("[+] Instance Path doesn't exist yet")
|
|
# and ask for the instance URL domain
|
|
instance = input("What is your Instance domain ? (ex: uptime.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion):")
|
|
instancepath=rootpath+'www/participants/'+instance
|
|
# TODO check if the instance URL domain is valid
|
|
|
|
# ask the user if the instance URL is valid ?
|
|
print()
|
|
print(instance)
|
|
isitvalid=input("Is your this your instance domain ?")
|
|
# if yes, then write it into ~/.darknet_participant_url
|
|
if isitvalid != "y" :
|
|
print("OK writing the instance url to ~/.darknet_participants_url")
|
|
with open(urlpath, "w") as file:
|
|
file.write(instance)
|
|
print("[+] file written, let's read it")
|
|
f = open(urlpath,"r")
|
|
print(f.read())
|
|
print("[+] Initial Setup Completed!")
|
|
|
|
print("[+] Welcome to the Darknet Onion Webring, where you are exploring the Darknet and helping others do the same.")
|
|
print("""
|
|
1) Add a new entry (into unverified.csv)
|
|
2) Verify an entry (move an entry from unverified to verified.csv)
|
|
3) Add a new webring participant (and download their files into their directory (without trusting them yet!))
|
|
4) Trust a webring participant (Potentially dangerous)
|
|
5) Add/Remove words in the sensitive list (ex: drug)
|
|
6) Add/Remove words in the blacklist (ex: porn)
|
|
""")
|
|
option = input("Select Option? (1-4)")
|
|
print(option)
|
|
match option:
|
|
case "1":
|
|
print("[+] Add a new Entry (into unverified.csv)")
|
|
# ask for the following:
|
|
unverifiedpath=instancepath+'/unverified.csv'
|
|
# the name of the website (required) + check if its valid
|
|
entry_name = input("What is the Website name ?")
|
|
# the url of the website (required) + check if its valid
|
|
entry_url = input("What is URL of the Website ? (ex: https://torproject.org or http://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion")
|
|
# a quick description (optional) + check if its valid
|
|
entry_url = input("(Optional) Description of the website ? (max 256 characters) (press enter to skip)"
|
|
# sensitive ? (y/n) + check if its valid
|
|
entry_url = input("is it a sensitive website ? (ex: website related to drugs)"
|
|
# (rest is automatic: status, score, instance is = '' because it is your own instance)
|
|
# check if the entry doesn't already exist in verified.csv and in unverified.csv
|
|
# if it doesnt exist, add it into unverified.csv
|
|
|
|
case "2":
|
|
print("[+] Verify an entry (move an entry from unverified.csv to verified.csv)")
|
|
# search for a word
|
|
searchterm = input("What is the Website name ?")
|
|
# and display only the matching entries in an array format (display it in CLI).
|
|
# Each of the rows must have an index,
|
|
# prompt the user to ask for with row they want to move to verified.csv
|
|
searchterm = input("What is the index of the entry that you want to move to verified.csv ?")
|
|
# once selected, it must be able to print that row, and:
|
|
# append it into verified.csv
|
|
# remove it from unverified.csv
|
|
# print("[+] completed! You are now listing [name] (url) (sensitive)")
|
|
|
|
case "3":
|
|
print("[+] Add a new webring participant (and download their files into their directory (without trusting them yet!))")
|
|
# ask for the url to the other webring participant
|
|
webring_participant_url = input("What is URL of the new webring participant? (ex: https://torproject.org or http://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion")
|
|
# check if the (onion only) url is valid or not: at http://URL.onion/participants/URL.onion/{verified.csv,unverified.csv,sensitive.csv,blacklist.csv,webring-participants.csv}
|
|
|
|
case "4":
|
|
print("[+] Trust a webring participant (Potentially dangerous)")
|
|
# list the existing webring participants from webring-participants.csv and
|
|
# ask the user to pick the index (0-9?) of the instance to trust
|
|
# if index is valid, then mark the instance as trusted in webring-participants.csv
|
|
searchterm = input("What is the index of the entry that you want to trust ?")
|
|
case "5":
|
|
print("[+] Add/Remove words in the sensitive list (ex: drug)")
|
|
print("do you want to 1) add words or 2) remove words ?")
|
|
option="0"
|
|
|
|
done = False
|
|
while(done == False):
|
|
while option not any((1,2,"exit")):
|
|
option=input("do you want to 1) add words or 2) remove words ? (type exit to exit)")
|
|
# display the contents of sensitive.csv file
|
|
if option == 1:
|
|
word=input("which word do you want to add? (write 0 to exit")
|
|
if word == "0":
|
|
done = True
|
|
#True to get out of the while loop
|
|
else
|
|
print("checking if word is valid")
|
|
#check if word is valid in a while loop (dont check if
|
|
# if invalid! remove word at index
|
|
else:
|
|
index=input("which word do you want to remove? (index 0 to (max index) (write exit to exit)")
|
|
if index == "exit":
|
|
done = True
|
|
#True to get out of the while loop
|
|
else
|
|
print("checking if index is valid")
|
|
#check if index is valid or not
|
|
# if valid! remove word at index
|
|
# if invalid! just pass to ask for another word
|
|
|
|
case "6":
|
|
print("[+] Add/Remove words in the blacklist list (ex: porn)")
|
|
# copy option 5
|
|
# print("do you want to 1) add words or 2) remove words ?")
|
|
# display the contents of blacklist.csv file
|
|
|
|
case _:
|
|
print("[-] ERROR, incorrect input")
|
|
|
|
|
|
#### PROTECTIONS AGAINST MALICIOUS CSV INPUTS ####
|
|
|
|
|
|
def IsOnionValid(url: str)-> bool:
|
|
"""
|
|
Checks if the domain(param) is a valid onion domain and return True else False.
|
|
"""
|
|
# check if the characters are only [a-zA-Z0-9.] with maximum 128 chars max?
|
|
# check that it is only url.onion or subdomain.url.onion,
|
|
# if OK return True
|
|
#if not : return False
|
|
try:
|
|
pattern = re.compile("^[A-Za-z0-9.]+(\.onion)?$")
|
|
url = url.strip().removesuffix('/')
|
|
if url.startswith('http://'):
|
|
print('URL starts with http')
|
|
# Removes the http://
|
|
domain = url.split('/')[2]
|
|
if pattern.fullmatch(domain) is not None:
|
|
if len(domain.split('.')) > 3:
|
|
n_subdomians = len(domain.split('.'))
|
|
# Checks if there is more than 1 subdomain. "subdomain.url.onion" only
|
|
print(f"This domain have more than one subdomain. There are {n_subdomians} subdomains")
|
|
return False
|
|
else:
|
|
if len(domain) < 62:
|
|
print("Domain length is less than 62.")
|
|
return False
|
|
return True
|
|
elif pattern.fullmatch(domain) is None:
|
|
print("Domain contains invalid character.")
|
|
print(domain)
|
|
return False
|
|
else:
|
|
print("Domain not valid")
|
|
return False
|
|
else:
|
|
print("URL doesn't start http")
|
|
if pattern.fullmatch(url) is not None:
|
|
if len(url.split('.')) > 3:
|
|
n_subdomians = len(url.split('.'))
|
|
# Checks if there is more than 1 subdomain. "subdomain.url.onion" only
|
|
print(f"This domain have more than one subdomain. There are {n_subdomians - 1} subdomains")
|
|
return False
|
|
else:
|
|
if len(url) < 62:
|
|
print("Domain length is less than 62.")
|
|
return False
|
|
return True
|
|
elif pattern.fullmatch(url) is None:
|
|
print("Domain contains invalid character.")
|
|
print(url)
|
|
return False
|
|
else:
|
|
print("Domain not valid")
|
|
return False
|
|
except Exception as e:
|
|
print(f"Error: {e}")
|
|
|
|
|
|
|
|
def IsUrlValid(url:str)->bool:
|
|
"""
|
|
Check if url is valid both dark net end clearnet.
|
|
"""
|
|
# check if the characters are only [a-zA-Z0-9.:/] with maximum 128 chars max?
|
|
# check that it is only http(s)://wordA.wordB or http(s)://WordC.WordB.WordC, (onion or not), clearnet is fine too (double check if those are fine!)
|
|
# if OK return True
|
|
#if not : return False
|
|
pattern = re.compile("^[A-Za-z0-9:/.]+$")
|
|
if url.endswith('.onion'):
|
|
return IsOnionValid(url)
|
|
else:
|
|
if not url.__contains__('.'):
|
|
print("No (DOT) in url")
|
|
return False
|
|
if pattern.fullmatch(url) is None:
|
|
print('Url contains invalid chars')
|
|
return False
|
|
return True
|
|
|
|
def IsStatusValid(status: str)-> bool:
|
|
"""
|
|
Checks if status contains only [v,w]. Verbose only if False is returned
|
|
"""
|
|
# check if the characters are only [vx] with maximum 1 chars max
|
|
# if OK return True
|
|
#if not : return False
|
|
pattern = ['v','x']
|
|
if len(status) != 1:
|
|
print("Got more than one character or nothing.")
|
|
return False
|
|
elif (status not in pattern):
|
|
print("Got an invalid character")
|
|
return False
|
|
return True
|
|
|
|
def IsDescriptionValid(desc:str)->bool:
|
|
"""
|
|
Check the categories are only [a-zA-Z0-9,.' ] with 256 max chars.
|
|
"""
|
|
# check if the characters are only [a-zA-Z0-9.,' ] with maximum 256 chars max
|
|
#(careful with the ' and , make sure you test if it fucks the csv up or else)
|
|
# if OK return True
|
|
#if not : return False
|
|
pattern = re.compile("^[A-Za-z0-9-.,' ]+$")
|
|
desc.strip()
|
|
if pattern.fullmatch(desc) is None:
|
|
print('Got an empty desc or invalid chars')
|
|
return False
|
|
elif len(desc) > 256:
|
|
print("desc is greater than 256 chars")
|
|
return False
|
|
return True
|
|
|
|
def IsCategoryValid(categories: list)-> bool:
|
|
"""
|
|
Check the categories are only [a-zA-Z0-9 ] with 64 max chars.
|
|
"""
|
|
# check if the characters are only [a-zA-Z0-9 ] with maximum 64 chars max
|
|
#(careful with the ' and , make sure you test if it fucks the csv up or else)
|
|
# if OK return True
|
|
#if not : return False
|
|
pattern = re.compile("^[A-Za-z0-9 ]+$")
|
|
for category in categories:
|
|
category.strip()
|
|
if pattern.fullmatch(category) is None:
|
|
print('Got an empty list or invalid chars')
|
|
return False
|
|
elif len(category) > 64:
|
|
print('Category is too long')
|
|
else:
|
|
return True
|
|
|
|
def IsNameValid(name: str)->bool:
|
|
"""
|
|
Check the parameter name only contains [a-zA-Z0-9 ] and is 64 chars long.
|
|
"""
|
|
# check if the characters are only [a-zA-Z0-9 ] with maximum 64 chars max
|
|
#(careful with the ' and , make sure you test if it fucks the csv up or else)
|
|
# if OK return True
|
|
#if not : return False
|
|
pattern = re.compile("^[A-Za-z0-9 ]+$")
|
|
name = name.strip()
|
|
if (pattern.fullmatch(name) is None):
|
|
print("Got an invalid character or nothing")
|
|
return False
|
|
elif len(name) > 64:
|
|
print(f'Got a name lenght greater than 64. {len(name)}')
|
|
return False
|
|
return True
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|