# vi: encoding=utf-8 ts=8 sts=4 sw=4 et import os import time import config import common import md5 import ftptree def parse(con): if '\0' not in con.data: return cmds=con.data.split('\0')[:-1] for cmd in cmds: con.data=con.data[len(cmd)+1:] cmdname=cmd[:4] if not con.authorized and cmdname not in ('linp', 'linc', 'name'): raise BailOut # TODO: log unauthorized access if cmdname in cmdlist_noargs: if len(cmd)==4: cmdlist_noargs[cmdname](con) else: pass # TODO: log malicious msg elif cmdname in cmdlist_args: if len(cmd)>5: cmdlist_args[cmdname](con, cmd[5:]) else: pass # TODO: log malicious msg else: raise BailOut # TODO: log this def lock(con, arg, hard): if arg not in locks: locks[arg]={'hard': hard, 'name': con.name, 'time': int(time.time())} con.sock.send("OK") elif locks[arg]['hard']: con.sock.send("HARD") # Hard lock - you can go get a cup of tea else: con.sock.send("SOFT") # Soft lock - try in a second or two def cmd_unlock(con, arg): if arg in locks: del locks[arg] con.sock.send("OK") else: con.sock.send("FAIL") def cmd_lock_soft(con, arg): lock(con, arg, False) def cmd_lock_hard(con, arg): lock(con, arg, True) def cmd_show_locks(con): cmd_log(con, "Dumping locks data:"); if len(locks): res = "" for lockdata in locks.iteritems(): tree, data = lockdata msg = "Tree: %s, Conn name: %s, Hard Lock: %s, Time: %s" % ( tree, data['name'], data['hard'], time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(data['time']))) cmd_log(con, msg) res = res + msg # con.sock.send("BLOB:%d" % len(res)) con.sock.send(res) else: cmd_log(con, "No locks found."); con.sock.send("NLCK"); def cmd_log(con, msg): logfile.write('%s [%s] -- %s\n' % (time.strftime('%Y-%m-%d %H:%M:%S'), con.name, msg)) logfile.flush() def cmd_name(con, name): con.name=name def load_creds(): global users, cookies users={} cookies={} if not common.fileexists(common.ftpadmdir+'/var/passwd'): return else: f=open(common.ftpadmdir+'/var/passwd', 'r') for line in f.xreadlines(): x=line.strip().split(':') if len(x)>=2: users[x[0]]=x[1] f.close() if not common.fileexists(common.ftpadmdir+'/var/cookies'): return else: f=open(common.ftpadmdir+'/var/cookies', 'r') for line in f.xreadlines(): x=line.strip().split(':') if len(x)>=2: users[x[0]]=x[1] f.close() def write_cookies(): f=open(common.ftpadmdir+'/var/cookies', 'w') for key in cookies.keys(): f.write('%s:%s\n' % (key, cookies[key])) f.close() def cmd_login_passwd(con, data): tmp=data.split('\n') if len(tmp)!=2: raise BailOut login=tmp[0] passwd=tmp[1] md5pass=md5.new(passwd).hexdigest() if login in users and users[login]==md5pass: cookie=`time.time()`.split('.')[0]+'_'+md5.new(md5pass+salt).hexdigest() cookies[cookie]=login write_cookies() con.username=login con.authorized=True con.sock.send('OK '+cookie) else: # TODO: log this con.sock.send('FAIL') raise BailOut def cmd_login_cookie(con, cookie): if cookie in cookies: con.cookie=cookie con.authorized=True con.username=cookies[cookie] con.sock.send('OK '+cookies[cookie]) else: # TODO: log this (or not) con.sock.send('FAIL') def cmd_logout(con): if con.cookie in cookies: del cookies[con.cookie] write_cookies() def reloadftptree(): global srctree, pkglist srctree=ftptree.FtpTree(config.value['default_to'], loadall=True) pkglist=srctree.keys() pkglist.sort() def cmd_gettree(con): buf='' for pkgnvr in pkglist: # TODO: show only user's own pkgs pkg=srctree[pkgnvr] line=pkgnvr if pkg.marked4moving: line=line+'\n1' else: line=line+'\n0' if pkg.marked4removal: line=line+'\n1' else: line=line+'\n0' buf=buf+'\0'+line if buf: con.sock.send('%.6d' % (len(buf)-1)) con.sock.send(buf[1:]) else: con.sock.send('000000') cmdlist_args={'lcks':cmd_lock_soft, 'lckh':cmd_lock_hard, 'ulck':cmd_unlock, 'log1':cmd_log, 'name':cmd_name, 'linp':cmd_login_passwd, 'linc':cmd_login_cookie} cmdlist_noargs={'lout':cmd_logout, 'gett':cmd_gettree, 'slck':cmd_show_locks} # Global stuff and initializations BailOut="BailOut" locks={} logfile=open(common.ftpadmdir+'/var/log', 'a') load_creds() reloadftptree() salt=md5.new(`time.time()`).hexdigest()