]>
Commit | Line | Data |
---|---|---|
1 | # vi: encoding=utf-8 ts=8 sts=4 sw=4 et | |
2 | ||
3 | import os | |
4 | import time | |
5 | import config | |
6 | import common | |
7 | import md5 | |
8 | import ftptree | |
9 | ||
10 | ||
11 | def parse(con): | |
12 | if '\0' not in con.data: | |
13 | return | |
14 | cmds=con.data.split('\0')[:-1] | |
15 | ||
16 | for cmd in cmds: | |
17 | con.data=con.data[len(cmd)+1:] | |
18 | cmdname=cmd[:4] | |
19 | if not con.authorized and cmdname not in ('linp', 'linc', 'name'): | |
20 | raise BailOut | |
21 | # TODO: log unauthorized access | |
22 | if cmdname in cmdlist_noargs: | |
23 | if len(cmd)==4: | |
24 | cmdlist_noargs[cmdname](con) | |
25 | else: | |
26 | pass | |
27 | # TODO: log malicious msg | |
28 | elif cmdname in cmdlist_args: | |
29 | if len(cmd)>5: | |
30 | cmdlist_args[cmdname](con, cmd[5:]) | |
31 | else: | |
32 | pass | |
33 | # TODO: log malicious msg | |
34 | else: | |
35 | raise BailOut | |
36 | # TODO: log this | |
37 | ||
38 | ||
39 | def lock(con, arg, hard): | |
40 | if arg not in locks: | |
41 | locks[arg]={'hard': hard, 'name': con.name, 'time': int(time.time())} | |
42 | con.sock.send("OK") | |
43 | elif locks[arg]['hard']: | |
44 | con.sock.send("HARD") # Hard lock - you can go get a cup of tea | |
45 | else: | |
46 | con.sock.send("SOFT") # Soft lock - try in a second or two | |
47 | ||
48 | ||
49 | def cmd_unlock(con, arg): | |
50 | if arg in locks: | |
51 | del locks[arg] | |
52 | con.sock.send("OK") | |
53 | else: | |
54 | con.sock.send("FAIL") | |
55 | ||
56 | def cmd_lock_soft(con, arg): | |
57 | lock(con, arg, False) | |
58 | ||
59 | def cmd_lock_hard(con, arg): | |
60 | lock(con, arg, True) | |
61 | ||
62 | def cmd_show_locks(con): | |
63 | cmd_log(con, "Dumping locks data:"); | |
64 | if len(locks): | |
65 | for lockdata in locks.iteritems(): | |
66 | tree, data = lockdata | |
67 | cmd_log(con, "Tree: %s, Conn name: %s, Hard Lock: %s, Time: %s" | |
68 | % (tree, data['name'], data['hard'], time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(data['time'])))) | |
69 | else: | |
70 | cmd_log(con, "No locks found."); | |
71 | ||
72 | def cmd_log(con, msg): | |
73 | logfile.write('%s [%s] -- %s\n' % (time.strftime('%Y-%m-%d %H:%M:%S'), | |
74 | con.name, msg)) | |
75 | logfile.flush() | |
76 | ||
77 | def cmd_name(con, name): | |
78 | con.name=name | |
79 | ||
80 | def load_creds(): | |
81 | global users, cookies | |
82 | users={} | |
83 | cookies={} | |
84 | if not common.fileexists(common.ftpadmdir+'var/passwd'): | |
85 | return | |
86 | else: | |
87 | f=open(common.ftpadmdir+'var/passwd', 'r') | |
88 | for line in f.xreadlines(): | |
89 | x=line.strip().split(':') | |
90 | if len(x)>=2: | |
91 | users[x[0]]=x[1] | |
92 | f.close() | |
93 | if not common.fileexists(common.ftpadmdir+'var/cookies'): | |
94 | return | |
95 | else: | |
96 | f=open(common.ftpadmdir+'var/cookies', 'r') | |
97 | for line in f.xreadlines(): | |
98 | x=line.strip().split(':') | |
99 | if len(x)>=2: | |
100 | users[x[0]]=x[1] | |
101 | f.close() | |
102 | ||
103 | def write_cookies(): | |
104 | f=open(common.ftpadmdir+'var/cookies', 'w') | |
105 | for key in cookies.keys(): | |
106 | f.write('%s:%s\n' % (key, cookies[key])) | |
107 | f.close() | |
108 | ||
109 | def cmd_login_passwd(con, data): | |
110 | tmp=data.split('\n') | |
111 | if len(tmp)!=2: | |
112 | raise BailOut | |
113 | login=tmp[0] | |
114 | passwd=tmp[1] | |
115 | md5pass=md5.new(passwd).hexdigest() | |
116 | if login in users and users[login]==md5pass: | |
117 | cookie=`time.time()`.split('.')[0]+'_'+md5.new(md5pass+salt).hexdigest() | |
118 | cookies[cookie]=login | |
119 | write_cookies() | |
120 | con.username=login | |
121 | con.authorized=True | |
122 | con.sock.send('OK '+cookie) | |
123 | else: | |
124 | # TODO: log this | |
125 | con.sock.send('FAIL') | |
126 | raise BailOut | |
127 | ||
128 | def cmd_login_cookie(con, cookie): | |
129 | if cookie in cookies: | |
130 | con.cookie=cookie | |
131 | con.authorized=True | |
132 | con.username=cookies[cookie] | |
133 | con.sock.send('OK '+cookies[cookie]) | |
134 | else: | |
135 | # TODO: log this (or not) | |
136 | con.sock.send('FAIL') | |
137 | ||
138 | def cmd_logout(con): | |
139 | if con.cookie in cookies: | |
140 | del cookies[con.cookie] | |
141 | write_cookies() | |
142 | ||
143 | def reloadftptree(): | |
144 | global srctree, pkglist | |
145 | srctree=ftptree.FtpTree(config.value['default_to'], loadall=True) | |
146 | pkglist=srctree.keys() | |
147 | pkglist.sort() | |
148 | ||
149 | def cmd_gettree(con): | |
150 | buf='' | |
151 | for pkgnvr in pkglist: | |
152 | # TODO: show only user's own pkgs | |
153 | pkg=srctree[pkgnvr] | |
154 | line=pkgnvr | |
155 | if pkg.marked4moving: | |
156 | line=line+'\n1' | |
157 | else: | |
158 | line=line+'\n0' | |
159 | if pkg.marked4removal: | |
160 | line=line+'\n1' | |
161 | else: | |
162 | line=line+'\n0' | |
163 | buf=buf+'\0'+line | |
164 | if buf: | |
165 | con.sock.send('%.6d' % (len(buf)-1)) | |
166 | con.sock.send(buf[1:]) | |
167 | else: | |
168 | con.sock.send('000000') | |
169 | ||
170 | ||
171 | cmdlist_args={'lcks':cmd_lock_soft, 'lckh':cmd_lock_hard, 'ulck':cmd_unlock, | |
172 | 'log1':cmd_log, 'name':cmd_name, 'linp':cmd_login_passwd, | |
173 | 'linc':cmd_login_cookie} | |
174 | ||
175 | cmdlist_noargs={'lout':cmd_logout, 'gett':cmd_gettree, 'slck':cmd_show_locks} | |
176 | ||
177 | # Global stuff and initializations | |
178 | ||
179 | BailOut="BailOut" | |
180 | locks={} | |
181 | logfile=open(common.ftpadmdir+'var/log', 'a') | |
182 | load_creds() | |
183 | reloadftptree() | |
184 | salt=md5.new(`time.time()`).hexdigest() | |
185 |