|
|
|
import re
|
|
|
|
import pwd
|
|
|
|
import lib.sqlitedb
|
|
|
|
import lib.CFG
|
|
|
|
|
|
|
|
|
|
|
|
def checkUsernameCharacters(username: str):
|
|
|
|
if " " not in username and "_" not in username and username.isascii() and username[:1].islower() and \
|
|
|
|
not username[0].isnumeric():
|
|
|
|
if not re.search(r"\W+", username):
|
|
|
|
if not re.search("[^a-zA-Z0-9]", username):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def checkUsernameLength(username: str):
|
|
|
|
if len(username) > 16:
|
|
|
|
return False
|
|
|
|
if len(username) < 3:
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def checkUserExists(username: str):
|
|
|
|
try:
|
|
|
|
pwd.getpwnam(username)
|
|
|
|
except KeyError:
|
|
|
|
return True # User already exists
|
|
|
|
else:
|
|
|
|
if checkUserInDB(username):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def checkUserInDB(username: str):
|
|
|
|
try:
|
|
|
|
ldb = lib.sqlitedb.SQLitedb(lib.CFG.config['DEFAULT']['applications_db'])
|
|
|
|
fetched = ldb.safequery("SELECT * FROM 'applications' WHERE username = ?", tuple([username]))
|
|
|
|
if fetched:
|
|
|
|
return True
|
|
|
|
except lib.sqlitedb.sqlite3.Error as e:
|
|
|
|
print(f"SQLite Exception: {e}")
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def checkSSHKey(key: str):
|
|
|
|
# taken from https://github.com/hashbang/provisor/blob/master/provisor/utils.py, all belongs to them! ;)
|
|
|
|
import base64
|
|
|
|
if len(key) > 8192 or len(key) < 80:
|
|
|
|
return False
|
|
|
|
|
|
|
|
key = key.replace("\"", "").replace("'", "").replace("\\\"", "")
|
|
|
|
key = key.split(' ')
|
|
|
|
types = ['ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384',
|
|
|
|
'ecdsa-sha2-nistp521', 'ssh-rsa', 'ssh-dss', 'ssh-ed25519']
|
|
|
|
if key[0] not in types:
|
|
|
|
return False
|
|
|
|
try:
|
|
|
|
base64.decodebytes(bytes(key[1], "utf-8"))
|
|
|
|
except TypeError:
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def checkEmail(mail: str):
|
|
|
|
if not re.match("(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)", mail):
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def checkDatetimeFormat(form: str):
|
|
|
|
import datetime
|
|
|
|
try:
|
|
|
|
datetime.datetime.strptime(form, "%Y-%m-%d %H:%M:%S")
|
|
|
|
except ValueError:
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def checkImportFile(f):
|
|
|
|
import csv
|
|
|
|
reador = csv.DictReader(f)
|
|
|
|
error_list = str()
|
|
|
|
valid = True
|
|
|
|
ln = 1 # line number
|
|
|
|
|
|
|
|
for row in reador:
|
|
|
|
# if any of this fails move on to the next user, just print a relatively helpful message lel
|
|
|
|
if not lib.validator.checkUsernameCharacters(row["username"]):
|
|
|
|
error_list += (f"Line {ln}: Username contains unsupported characters or starts with a number: '"
|
|
|
|
f"{row['username']}'.\n")
|
|
|
|
valid = False
|
|
|
|
if not lib.validator.checkUsernameLength(row["username"]):
|
|
|
|
error_list += f"Line {ln}: Username '{row['username']}' is either too long(>16) or short(<3)\n"
|
|
|
|
valid = False
|
|
|
|
if not lib.validator.checkSSHKey(row["pubkey"]):
|
|
|
|
error_list += f"Line {ln}: Following SSH-Key of user '{row['username']}' isn't valid: '{row['pubkey']}'."\
|
|
|
|
f"\n"
|
|
|
|
valid = False
|
|
|
|
if not lib.validator.checkEmail(row["email"]):
|
|
|
|
error_list += f"Line {ln}: E-Mail address of user '{row['username']}' '{row['email']}' is not valid.\n"
|
|
|
|
valid = False
|
|
|
|
if not lib.validator.checkUserExists(row["username"]):
|
|
|
|
error_list += f"Line {ln}: User '{row['username']}' already exists.\n"
|
|
|
|
valid = False
|
|
|
|
if not lib.validator.checkDatetimeFormat(row["timestamp"]):
|
|
|
|
error_list += f"Line {ln}: Timestamp '{row['timestamp']}' from user '{row['username']}' is invalid.\n"
|
|
|
|
valid = False
|
|
|
|
if int(row["status"]) > 1 or int(row["status"]) < 0:
|
|
|
|
error_list += f"Line {ln}: Status '{row['status']}' MUST be either 0 or 1.\n"
|
|
|
|
valid = False
|
|
|
|
ln += 1
|
|
|
|
if valid:
|
|
|
|
return True
|
|
|
|
else:
|
|
|
|
return error_list
|