Compare commits

...

5 Commits

Author SHA1 Message Date
gashapwn
90e1a3a73b reworded some comments. removed some newlines. 2020-11-28 02:12:02 +00:00
gashapwn
2ad636e887 reformatted some more lambdas 2020-11-28 02:01:20 +00:00
gashapwn
d74d38a582 added validations for shell enum 2020-11-28 01:58:23 +00:00
gashapwn
8fafc34bcb reformatted req method 2020-11-28 01:46:10 +00:00
gashapwn
e8a9e53c35 added validations for sshkey pub_key email 2020-11-28 01:41:17 +00:00
2 changed files with 109 additions and 29 deletions

137
app.py
View File

@ -1,5 +1,9 @@
import glob import glob
import json import json
import re
import sshpubkeys
from flask import Flask, redirect, url_for, render_template, request from flask import Flask, redirect, url_for, render_template, request
# lyadmin # lyadmin
@ -25,6 +29,11 @@ ACCOUNT_DIR = "req/";
FULL_PATH = str(WORKING_DIR) + str(ACCOUNT_DIR) FULL_PATH = str(WORKING_DIR) + str(ACCOUNT_DIR)
CONF_PATH = str(WORKING_DIR) + "lyadmin.conf.json" CONF_PATH = str(WORKING_DIR) + "lyadmin.conf.json"
# validation stuff
MAX_PUB_KEY_LEN = 5000
EMAIL_REGEX = "^[a-z0-9]+[\._]?[a-z0-9]+[@]\w+[.]\w{2,10}$"
KEY_REGEX = "^[ -~]+$"
# Account requests are given ID numbers # Account requests are given ID numbers
# the first request will have the below # the first request will have the below
# id number # id number
@ -34,6 +43,14 @@ INIT_REQ_ID = "00000"
with open(CONF_PATH) as c: conf_json_str = c.read() with open(CONF_PATH) as c: conf_json_str = c.read()
conf_obj = json.loads(conf_json_str) conf_obj = json.loads(conf_json_str)
# A list of all the shell enums
conf_obj["shell_tup_list"] = list(map(
lambda k : (
k, conf_obj["shell"][k]
),
list(conf_obj["shell"].keys())
))
# The main home page # The main home page
@app.route("/") @app.route("/")
def home(): def home():
@ -48,22 +65,23 @@ def home():
return render_template("index.html", u_list=u_list, page_name="home") return render_template("index.html", u_list=u_list, page_name="home")
# Generates the page with rule. No logic needed.
# The page with rules
def rules(): def rules():
return render_template("rules.html") return render_template("rules.html")
# Generate HTML for a form widget # Generate HTML for a form widget
def widg_fun(widg): def widg_fun(widg):
if(widg.w_type == "input"): if(widg.w_type == "input"):
# Return HTML for a single line input return "input id=id_%s name=%s type=text></input"%(
return "input id=id_%s name=%s type=text></input"%(widg.w_name, widg.w_name) widg.w_name, widg.w_name
)
elif(widg.w_type == "textarea"): elif(widg.w_type == "textarea"):
# Return HTML for a big text input box return "textarea cols=40 id=id_%s name=%s rows=10 required=\"\""%(
return "textarea cols=40 id=id_%s name=%s rows=10 required=\"\""%(widg.w_name, widg.w_name) widg.w_name, widg.w_name
)
elif(widg.w_type == "check"): elif(widg.w_type == "check"):
# Return HTML for a check box return "input id=id_%s name=%s type=checkbox required=\"\""%(
return "input id=id_%s name=%s type=checkbox required=\"\""%(widg.w_name, widg.w_name) widg.w_name, widg.w_name)
return widg.w_type; return widg.w_type;
# Generate HTML for request form # Generate HTML for request form
@ -78,32 +96,57 @@ def req():
# Configuration for our request form # Configuration for our request form
rt = { rt = {
"username": Widg("username", "input", None), "username": Widg(
"email for account lockout / registration confirmation (optional)": Widg("email", "input", None), "username",
"SSH public key": Widg("pub_key", "textarea", None), "input",
"shell of choice": Widg("shell", "choice", map(lambda k : (k, conf_obj["shell"][k]), list(conf_obj["shell"].keys()))), None
"have you read the rules?": Widg("rule_read", "check", None) ),
"email for account lockout / registration confirmation (optional)": Widg(
"email",
"input",
None
),
"SSH public key": Widg(
"pub_key",
"textarea",
None
),
"shell of choice": Widg(
"shell",
"choice",
conf_obj["shell_tup_list"]
),
"have you read the rules?": Widg(
"rule_read", "check", None
)
}; };
return render_template("req.html", req_tab = rt, widg_fun = widg_fun, page_name="req") return render_template(
"req.html",
req_tab = rt,
widg_fun = widg_fun,
page_name="req"
)
# Process input from the /req page def handle_invalid_data(req):
# print(str(e))
return render_template("signup.html", is_email_user = False)
# Process input from user creation POST request
def signup(): def signup():
app.route('/req/signup') app.route('/req/signup')
# Get all the params from the POST # Get all the params from the POST
# request # request
username = request.form["username"] username = request.form["username"].strip()
email = request.form["email"] email = request.form["email"].strip()
pub_key = request.form["pub_key"] pub_key = request.form["pub_key"].strip()
shell = request.form["shell"] shell = request.form["shell"].strip()
rule_read = request.form["rule_read"] rule_read = request.form["rule_read"].strip()
is_email_user = False; is_email_user = False;
# If a user didnt read the rules # If a user didnt read the rules
# send them back # send them back
# Browser validations should
# prevent this....
if(rule_read != "on"): if(rule_read != "on"):
return redirect(url_for('req')) return redirect(url_for('req'))
@ -113,18 +156,54 @@ def signup():
else: else:
email = "NO_EMAIL" email = "NO_EMAIL"
# Validate shell
if(not shell in conf_obj["shell"]):
print("failed shell validation")
return handle_invalid_data(req)
# Validate email
if( is_email_user and not re.search(EMAIL_REGEX, email)):
print("failed email validation")
return handle_invalid_data(req)
# Validate the SSH pub key
# Most software only handles up to 4096 bit keys
if(len(pub_key) > MAX_PUB_KEY_LEN):
print("key failed len check")
return handle_invalid_data(req)
# Only printable ascii characters in
# a valid key
# if(not re.search("^[ -~]+$", pub_key)):
if(not re.search(KEY_REGEX, pub_key)):
print("key failed regex")
return handle_invalid_data(req)
# Check the key against a library
key = sshpubkeys.SSHKey(
pub_key,
strict_mode=False,
skip_option_parsing=True
)
try:
key.parse()
except Exception as e:
print("key failed lib validation")
return handle_invalid_data(request)
# All users requests have a sequential ID # All users requests have a sequential ID
# this checks how many requests we have # The below picks the next ID based on
# and gives us a free ID so we can save # how many requests we already have saved
# our request # to disk
# This sets the ID of the request we're
# abou to save to dsik
if(len(glob.glob(ACCOUNT_DIR + str("[0-9]*ident*"))) == 0): if(len(glob.glob(ACCOUNT_DIR + str("[0-9]*ident*"))) == 0):
new_id = int(INIT_REQ_ID) new_id = int(INIT_REQ_ID)
new_id_str = INIT_REQ_ID new_id_str = INIT_REQ_ID
else: else:
max_id = max(list(map( lambda path : path.split("/")[-1].split(".")[0] , glob.glob(str(ACCOUNT_DIR) + "[0-9]*ident*")))) max_id = max(
# max_id = max(list(map( lambda path : path.split("/")[-1].split(".")[0] , glob.glob("./test/[0-9]*ident*")))) list(map(
lambda path : path.split("/")[-1].split(".")[0],
glob.glob(str(ACCOUNT_DIR) + "[0-9]*ident*")))
)
zpad = len(max_id) zpad = len(max_id)
new_id = int(max_id)+1 new_id = int(max_id)+1
new_id_str = str(new_id).zfill(zpad) new_id_str = str(new_id).zfill(zpad)

View File

@ -1 +1,2 @@
Flask==1.1.2 Flask==1.1.2
sshpubkeys==3.1.0