Commit 800ba190 by Dányi Bence

Merge branch 'master' of ssh://giccero.cloud.ik.bme.hu/cloud

parents ce14c31a 4f88dd69
#!/usr/bin/python #!/usr/bin/python
#TODO File permission checks # TODO File permission checks
from bottle import route, run, request, static_file, abort, redirect, app from bottle import route, run, request, static_file, abort, redirect, app
import json, os, shutil import json, os, shutil
...@@ -9,23 +9,19 @@ import subprocess ...@@ -9,23 +9,19 @@ import subprocess
import ConfigParser import ConfigParser
from pwd import getpwnam from pwd import getpwnam
#Get configuration file # Get configuration file
config = ConfigParser.ConfigParser() config = ConfigParser.ConfigParser()
config.read('/opt/webadmin/cloud/miscellaneous/store-server/store.config') config.read('/opt/webadmin/cloud/miscellaneous/store-server/store.config')
#ROOT_WWW_FOLDER='/var/www'
ROOT_WWW_FOLDER = config.get('store', 'root_www_folder') ROOT_WWW_FOLDER = config.get('store', 'root_www_folder')
#ROOT_BIN_FOLDER='/opt/store-server'
ROOT_BIN_FOLDER = config.get('store', 'root_bin_folder') ROOT_BIN_FOLDER = config.get('store', 'root_bin_folder')
#SITE_URL='http://store.cloud.ik.bme.hu:8080'
SITE_URL = config.get('store', 'site_url') SITE_URL = config.get('store', 'site_url')
#USER_MANAGER='UserManager.sh'
USER_MANAGER = config.get('store', 'user_manager') USER_MANAGER = config.get('store', 'user_manager')
#Standalone server # Standalone server
SITE_HOST = config.get('store', 'site_host') SITE_HOST = config.get('store', 'site_host')
SITE_PORT = config.get('store', 'site_port') SITE_PORT = config.get('store', 'site_port')
#Temporary dir for tar.gz # Temporary dir for tar.gz
TEMP_DIR = config.get('store', 'temp_dir') TEMP_DIR = config.get('store', 'temp_dir')
...@@ -38,7 +34,7 @@ def index(): ...@@ -38,7 +34,7 @@ def index():
pass pass
return "It works! SSL: "+response return "It works! SSL: "+response
#@route('/<neptun:re:[a-zA-Z0-9]{6}>', method='GET') # @route('/<neptun:re:[a-zA-Z0-9]{6}>', method='GET')
@route('/<neptun>', method='GET') @route('/<neptun>', method='GET')
def neptun_GET(neptun): def neptun_GET(neptun):
home_path = '/home/'+neptun+'/home' home_path = '/home/'+neptun+'/home'
...@@ -48,113 +44,129 @@ def neptun_GET(neptun): ...@@ -48,113 +44,129 @@ def neptun_GET(neptun):
statistics=getQuotaStatus(neptun) statistics=getQuotaStatus(neptun)
return { 'Used' : statistics[0], 'Soft' : statistics[1], 'Hard' : statistics[2]} return { 'Used' : statistics[0], 'Soft' : statistics[1], 'Hard' : statistics[2]}
COMMANDS = {}
@route('/<neptun>', method='POST') @route('/<neptun>', method='POST')
def neptun_POST(neptun): def neptun_POST(neptun):
#Check if user avaiable (home folder ready) # Check if user avaiable (home folder ready)
home_path = '/home/'+neptun+'/home' home_path = '/home/'+neptun+'/home'
if os.path.exists(home_path) != True: if os.path.exists(home_path) != True:
abort(401, 'The requested user does not exist!') abort(401, 'The requested user does not exist!')
else: else:
#Parse post try:
#LISTING return COMMANDS[request.json['CMD']](request, neptun, home_path)
if request.json['CMD'] == 'LIST': except KeyError:
list_path = home_path+request.json['PATH'] abort(400, "Command not found!")
if os.path.exists(list_path) != True:
abort(404, "Path not found!")
else: # LISTING
return list_directory(home_path, list_path) def cmd_list(request, neptun, home_path):
#DOWNLOAD LINK GENERATOR list_path = home_path+request.json['PATH']
elif request.json['CMD'] == 'DOWNLOAD': if os.path.exists(list_path) != True:
dl_path = home_path+'/'+request.json['PATH'] abort(404, "Path not found!")
dl_path = os.path.realpath(dl_path) else:
if not dl_path.startswith(home_path): return list_directory(home_path, list_path)
abort(400, 'Invalid download path.') COMMANDS['LIST'] = cmd_list
dl_hash = str(uuid.uuid4())
if( os.path.isfile(dl_path) ): # DOWNLOAD LINK GENERATOR
os.symlink(dl_path, ROOT_WWW_FOLDER+'/'+dl_hash) def cmd_download(request, neptun, home_path):
#Debug dl_path = home_path+'/'+request.json['PATH']
#redirect('http://store.cloud.ik.bme.hu:8080/dl/'+dl_hash) dl_path = os.path.realpath(dl_path)
return json.dumps({'LINK' : SITE_URL+'/dl/'+dl_hash}) if not dl_path.startswith(home_path):
else: abort(400, 'Invalid download path.')
try: dl_hash = str(uuid.uuid4())
os.makedirs(TEMP_DIR+'/'+neptun, 0700) if( os.path.isfile(dl_path) ):
except: os.symlink(dl_path, ROOT_WWW_FOLDER+'/'+dl_hash)
pass # Debug
folder_name = os.path.basename(dl_path) # redirect('http://store.cloud.ik.bme.hu:8080/dl/'+dl_hash)
temp_path = TEMP_DIR+'/'+neptun+'/'+folder_name+'.zip' return json.dumps({'LINK' : SITE_URL+'/dl/'+dl_hash})
with open(os.devnull, "w") as fnull: else:
# zip -rqDj vmi.zip /home/tarokkk/vpn-ik try:
result = subprocess.call(['/usr/bin/zip', '-rqDj', temp_path, dl_path], stdout = fnull, stderr = fnull) os.makedirs(TEMP_DIR+'/'+neptun, 0700)
os.symlink(temp_path, ROOT_WWW_FOLDER+'/'+dl_hash) except:
return json.dumps({'LINK' : SITE_URL+'/dl/'+dl_hash}) pass
#UPLOAD folder_name = os.path.basename(dl_path)
elif request.json['CMD'] == 'UPLOAD': temp_path = TEMP_DIR+'/'+neptun+'/'+folder_name+'.zip'
up_path = home_path+'/'+request.json['PATH'] with open(os.devnull, "w") as fnull:
up_path = os.path.realpath(up_path) # zip -rqDj vmi.zip /home/tarokkk/vpn-ik
if not up_path.startswith(home_path): result = subprocess.call(['/usr/bin/zip', '-rqDj', temp_path, dl_path], stdout = fnull, stderr = fnull)
abort(400, 'Invalid upload path.') os.symlink(temp_path, ROOT_WWW_FOLDER+'/'+dl_hash)
if os.path.exists(up_path) == True and os.path.isdir(up_path): return json.dumps({'LINK' : SITE_URL+'/dl/'+dl_hash})
up_hash = str(uuid.uuid4()) COMMANDS['DOWNLOAD'] = cmd_download
os.symlink(up_path, ROOT_WWW_FOLDER+'/'+up_hash)
return json.dumps({ 'LINK' : SITE_URL+'/ul/'+up_hash}) # UPLOAD
else: def cmd_upload(request, neptun, home_path):
abort(400, 'Upload directory not exists!') up_path = home_path+'/'+request.json['PATH']
#MOVE up_path = os.path.realpath(up_path)
elif request.json['CMD'] == 'MOVE': if not up_path.startswith(home_path):
src_path = home_path+'/'+request.json['SOURCE'] abort(400, 'Invalid upload path.')
dst_path = home_path+'/'+request.json['DESTINATION'] if os.path.exists(up_path) == True and os.path.isdir(up_path):
src_path = os.path.realpath(src_path) up_hash = str(uuid.uuid4())
dst_path = os.path.realpath(dst_path) os.symlink(up_path, ROOT_WWW_FOLDER+'/'+up_hash)
if not src_path.startswith(home_path): return json.dumps({ 'LINK' : SITE_URL+'/ul/'+up_hash})
abort(400, 'Invalid source path.') else:
if not dst_path.startswith(home_path): abort(400, 'Upload directory not exists!')
abort(400, 'Invalid destination path.') COMMANDS['UPLOAD'] = cmd_upload
if os.path.exists(src_path) == True and os.path.exists(dst_path) == True and os.path.isdir(dst_path) == True:
shutil.move(src_path, dst_path) # MOVE
return def cmd_move(request, neptun, home_path):
else: src_path = home_path+'/'+request.json['SOURCE']
#TODO dst_path = home_path+'/'+request.json['DESTINATION']
abort(400, "Can not move the file.") src_path = os.path.realpath(src_path)
#RENAME dst_path = os.path.realpath(dst_path)
elif request.json['CMD'] == 'RENAME': if not src_path.startswith(home_path):
src_path = home_path+'/'+request.json['PATH'] abort(400, 'Invalid source path.')
src_path = os.path.realpath(src_path) if not dst_path.startswith(home_path):
if not src_path.startswith(home_path): abort(400, 'Invalid destination path.')
abort(400, 'Invalid source path.') if os.path.exists(src_path) == True and os.path.exists(dst_path) == True and os.path.isdir(dst_path) == True:
dst_path = os.path.dirname(src_path)+'/'+request.json['NEW_NAME'] shutil.move(src_path, dst_path)
if os.path.exists(src_path) == True: return
os.rename(src_path, dst_path) else:
else: # TODO
abort(404, "File or Folder not found!") abort(400, "Can not move the file.")
COMMANDS['MOVE'] = cmd_move
# RENAME
def cmd_rename(request, neptun, home_path):
src_path = home_path+'/'+request.json['PATH']
src_path = os.path.realpath(src_path)
if not src_path.startswith(home_path):
abort(400, 'Invalid source path.')
dst_path = os.path.dirname(src_path)+'/'+request.json['NEW_NAME']
if os.path.exists(src_path) == True:
os.rename(src_path, dst_path)
else:
abort(404, "File or Folder not found!")
COMMANDS['RENAME'] = cmd_rename
# NEW FOLDER
def cmd_new_folder(request, neptun, home_path):
dir_path = home_path+'/'+request.json['PATH']
dir_path = os.path.realpath(dir_path)
if not dir_path.startswith(home_path):
abort(400, 'Invalid directory path.')
if os.path.exists(dir_path) == True:
abort(400, "Directory already exist!")
else:
os.mkdir(dir_path, 0755)
COMMANDS['NEW_FOLDER'] = cmd_new_folder
# REMOVE
def cmd_remove(request, neptun, home_path):
remove_path = home_path+'/'+request.json['PATH']
remove_path = os.path.realpath(remove_path)
if not remove_path.startswith(home_path):
abort(400, 'Invalid path.')
if os.path.exists(remove_path) != True:
abort(404, "Path not found!")
else:
if os.path.isdir(remove_path) == True:
shutil.rmtree(remove_path)
return return
#NEW FOLDER
elif request.json['CMD'] == 'NEW_FOLDER':
dir_path = home_path+'/'+request.json['PATH']
dir_path = os.path.realpath(dir_path)
if not dir_path.startswith(home_path):
abort(400, 'Invalid directory path.')
if os.path.exists(dir_path) == True:
abort(400, "Directory already exist!")
else:
os.mkdir(dir_path, 0755)
return
#REMOVE
elif request.json['CMD'] == 'REMOVE':
remove_path = home_path+'/'+request.json['PATH']
remove_path = os.path.realpath(remove_path)
if not remove_path.startswith(home_path):
abort(400, 'Invalid path.')
if os.path.exists(remove_path) != True:
abort(404, "Path not found!")
else:
if os.path.isdir(remove_path) == True:
shutil.rmtree(remove_path)
return
else:
os.remove(remove_path)
return
else: else:
abort(400, "Command not found!") os.remove(remove_path)
return
COMMANDS['REMOVE'] = cmd_remove
@route('/set/<neptun>', method='POST') @route('/set/<neptun>', method='POST')
def set_keys(neptun): def set_keys(neptun):
...@@ -166,9 +178,9 @@ def set_keys(neptun): ...@@ -166,9 +178,9 @@ def set_keys(neptun):
key_list.append(key) key_list.append(key)
except: except:
abort(400, 'Wrong syntax!') abort(400, 'Wrong syntax!')
result = subprocess.call([ROOT_BIN_FOLDER+'/'+USER_MANAGER,'set',neptun,smbpasswd]) result = subprocess.call([ROOT_BIN_FOLDER+'/'+USER_MANAGER, 'set', neptun, smbpasswd])
if result == 0: if result == 0:
updateSSHAuthorizedKeys(neptun,key_list) updateSSHAuthorizedKeys(neptun, key_list)
return return
elif result == 2: elif result == 2:
abort(403, 'User does not exist!') abort(403, 'User does not exist!')
...@@ -178,40 +190,40 @@ def set_keys(neptun): ...@@ -178,40 +190,40 @@ def set_keys(neptun):
def new_user(neptun): def new_user(neptun):
key_list = [] key_list = []
smbpasswd='' smbpasswd=''
try: try:
smbpasswd = request.json['SMBPASSWD'] smbpasswd = request.json['SMBPASSWD']
except: except:
abort(400, 'Invalid syntax') abort(400, 'Invalid syntax')
#Call user creator script # Call user creator script
result = subprocess.call([ROOT_BIN_FOLDER+'/'+USER_MANAGER,'add',neptun,smbpasswd]) result = subprocess.call([ROOT_BIN_FOLDER+'/'+USER_MANAGER, 'add', neptun, smbpasswd])
if result == 0: if result == 0:
try: try:
for key in request.json['KEYS']: for key in request.json['KEYS']:
key_list.append(key) key_list.append(key)
updateSSHAuthorizedKeys(neptun,key_list) updateSSHAuthorizedKeys(neptun, key_list)
except: except:
abort(400,'SSH') abort(400, 'SSH')
return return
elif result == 2: elif result == 2:
abort(403, 'User already exist!') abort(403, 'User already exist!')
else: else:
abort(400, 'An error occured!') abort(400, 'An error occured!')
#Static file
# Static file
@route('/dl/<hash_num>', method='GET') @route('/dl/<hash_num>', method='GET')
def dl_hash(hash_num): def dl_hash(hash_num):
hash_path = ROOT_WWW_FOLDER hash_path = ROOT_WWW_FOLDER
if os.path.exists(hash_path+'/'+hash_num) != True: if os.path.exists(hash_path+'/'+hash_num) != True:
abort(404, "File not found!") abort(404, "File not found!")
else: else:
filename = os.path.basename(os.path.realpath(hash_path+'/'+hash_num)) filename = os.path.basename(os.path.realpath(hash_path+'/'+hash_num))
return static_file(hash_num,root=hash_path,download=filename) return static_file(hash_num, root=hash_path, download=filename)
@route('/ul/<hash_num>', method='POST') @route('/ul/<hash_num>', method='POST')
def upload(hash_num): def upload(hash_num):
if not os.path.exists(ROOT_WWW_FOLDER+'/'+hash_num): if not os.path.exists(ROOT_WWW_FOLDER+'/'+hash_num):
abort (404,'Token not found!') abort (404, 'Token not found!')
try: try:
file_data = request.files.data file_data = request.files.data
file_name = file_data.filename file_name = file_data.filename
...@@ -222,79 +234,79 @@ def upload(hash_num): ...@@ -222,79 +234,79 @@ def upload(hash_num):
up_path = os.path.realpath(ROOT_WWW_FOLDER+'/'+hash_num+'/'+file_name) up_path = os.path.realpath(ROOT_WWW_FOLDER+'/'+hash_num+'/'+file_name)
if os.path.exists(up_path): if os.path.exists(up_path):
abort(400, 'File already exists') abort(400, 'File already exists')
#Check if upload path valid # Check if upload path valid
if not up_path.startswith('/home'): if not up_path.startswith('/home'):
abort(400, 'Invalid path.') abort(400, 'Invalid path.')
os.remove(ROOT_WWW_FOLDER+'/'+hash_num) os.remove(ROOT_WWW_FOLDER+'/'+hash_num)
#Get the real upload path # Get the real upload path
#Delete the hash link # Delete the hash link
#Get the username from path for proper ownership # Get the username from path for proper ownership
username=up_path.split('/',3)[2] username=up_path.split('/', 3)[2]
#os.setegid(getpwnam(username).pw_gid) # os.setegid(getpwnam(username).pw_gid)
#os.seteuid(getpwnam(username).pw_uid) # os.seteuid(getpwnam(username).pw_uid)
#TODO setuid subcommand # TODO setuid subcommand
#Check if file exist (root can overwrite anything not safe) # Check if file exist (root can overwrite anything not safe)
f = open(up_path , 'wb') f = open(up_path , 'wb')
datalength = 0 datalength = 0
for chunk in fbuffer(file_data.file): for chunk in fbuffer(file_data.file):
f.write(chunk) f.write(chunk)
datalength += len(chunk) datalength += len(chunk)
f.close() f.close()
os.chown(up_path,getpwnam(username).pw_uid,getpwnam(username).pw_gid) os.chown(up_path, getpwnam(username).pw_uid, getpwnam(username).pw_gid)
os.chmod(up_path,0644) os.chmod(up_path, 0644)
return 'Upload finished: '+file_name+' - '+str(datalength)+' Byte' return 'Upload finished: '+file_name+' - '+str(datalength)+' Byte'
#Define filebuffer for big uploads # Define filebuffer for big uploads
def fbuffer(f, chunk_size=4096): def fbuffer(f, chunk_size=4096):
while True: while True:
chunk = f.read(chunk_size) chunk = f.read(chunk_size)
if not chunk: break if not chunk: break
yield chunk yield chunk
#Update users .ssh/authorized_keys # Update users .ssh/authorized_keys
def updateSSHAuthorizedKeys(username,key_list): def updateSSHAuthorizedKeys(username, key_list):
user_home_ssh = '/home/'+username+'/home/.ssh' user_home_ssh = '/home/'+username+'/home/.ssh'
user_uid=getpwnam(username).pw_uid user_uid=getpwnam(username).pw_uid
user_gid=getpwnam(username).pw_gid user_gid=getpwnam(username).pw_gid
if not os.path.exists(user_home_ssh): if not os.path.exists(user_home_ssh):
os.mkdir(user_home_ssh, 0700) os.mkdir(user_home_ssh, 0700)
os.chown(user_home_ssh,user_uid,user_gid) os.chown(user_home_ssh, user_uid, user_gid)
auth_file_name = user_home_ssh+'/authorized_keys' auth_file_name = user_home_ssh+'/authorized_keys'
auth_file = open(auth_file_name,'w') auth_file = open(auth_file_name, 'w')
for key in key_list: for key in key_list:
auth_file.write(key+'\n') auth_file.write(key+'\n')
auth_file.close() auth_file.close()
os.chmod(auth_file_name,0600) os.chmod(auth_file_name, 0600)
os.chown(auth_file_name,user_uid,user_gid) os.chown(auth_file_name, user_uid, user_gid)
return return
#For debug purpose # For debug purpose
#@route('/ul/<hash_num>', method='GET') # @route('/ul/<hash_num>', method='GET')
#def upload_get(hash_num): # def upload_get(hash_num):
# return """<form method="POST" action="/ul/{hash}" enctype="multipart/form-data"> # return """<form method="POST" action="/ul/{hash}" enctype="multipart/form-data">
# <input name="data" type="file" /> # <input name="data" type="file" />
# <input type="submit" /> # <input type="submit" />
#</form>""".format(hash=hash_num) # </form>""".format(hash=hash_num)
def list_directory(home,path): def list_directory(home, path):
#Check for path breakout # Check for path breakout
if not os.path.realpath(path).startswith(home): if not os.path.realpath(path).startswith(home):
abort(400, 'Invalid path.') abort(400, 'Invalid path.')
#Check if path exist # Check if path exist
if os.path.exists(path) != True: if os.path.exists(path) != True:
abort(404,'No such file or directory') abort(404, 'No such file or directory')
else: else:
#If it's a file return with list # If it's a file return with list
if os.path.isdir(path) != True: if os.path.isdir(path) != True:
return json.dumps((os.path.basename(path), 'F', os.path.getsize(path), os.path.getmtime(path))) return json.dumps((os.path.basename(path), 'F', os.path.getsize(path), os.path.getmtime(path)))
#List directory and return list # List directory and return list
else: else:
tuplelist = [] tuplelist = []
filelist = os.listdir(path) filelist = os.listdir(path)
#Add type support # Add type support
for item in filelist: for item in filelist:
static_route = path+"/"+item static_route = path+"/"+item
if os.path.isdir(static_route): if os.path.isdir(static_route):
...@@ -306,9 +318,9 @@ def list_directory(home,path): ...@@ -306,9 +318,9 @@ def list_directory(home,path):
return json.dumps(tuplelist) return json.dumps(tuplelist)
def getQuotaStatus(neptun): def getQuotaStatus(neptun):
output=subprocess.check_output([ROOT_BIN_FOLDER+'/'+USER_MANAGER,'status',neptun], stderr=subprocess.STDOUT) output=subprocess.check_output([ROOT_BIN_FOLDER+'/'+USER_MANAGER, 'status', neptun], stderr=subprocess.STDOUT)
return output.split() return output.split()
if __name__ == "__main__": if __name__ == "__main__":
run(host=SITE_HOST, port=SITE_PORT) run(host=SITE_HOST, port=SITE_PORT)
else: else:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment