qmail-valid-addresses security: scan read dot-qmail files as owner
[qmail] / qmail-valid-addresses
CommitLineData
ca51b51d
MW
1#! /usr/bin/python
2
3import os
4import cdb
7651970e 5from errno import *
ca51b51d
MW
6
7def sort(l):
8 l = [] + l
9 l.sort()
10 return l
11class struct (object):
12 def __init__(me, **kw):
13 me.__dict__.update(kw)
14 def __repr__(me):
15 return (type(me).__name__ +
16 '(' +
17 ', '.join(['%s = %r' % (k, me.__dict__[k])
18 for k in me.__dict__
19 if k[0] != '_']) +
20 ')')
21class userentry (struct):
22 pass
23
24os.chdir('/var/qmail')
25
26umap = {}
27udb = cdb.init('users/cdb')
28for k in udb.keys():
29 if len(k) == 0 or k[0] != '!':
30 continue
31 v = udb[k].split('\0')
32 u = userentry(user = v[0], uid = int(v[1]), gid = int(v[2]), home = v[3],
33 dash = v[4], pre = v[5])
34 if k[-1] == '\0':
35 u.name = k[1:-1]
36 u.wild = 0
37 else:
38 u.name = k[1:]
39 u.wild = 1
40 umap[u.name] = u
41del udb
42
43map = {}
0a045fc1 44def addlocal(u, p, l, forcep = False):
ca51b51d 45 l = 'L' + l
19de3a72 46 p = os.path.join(u.home, p)
ca51b51d
MW
47 if not os.path.exists(p):
48 if forcep:
49 map[l] = '+'
50 return
19de3a72
MW
51 qm = file(os.path.join(u.home, p)).readline()
52 if len(qm) > 1 and qm[0:2] == '#!':
ca51b51d 53 map[l] = '-'
19de3a72
MW
54 elif len(qm) > 1 and qm[0:2] == '#?':
55 name = u.user
0a045fc1 56 map[l] = '?' + name
ca51b51d
MW
57 else:
58 map[l] = '+'
19de3a72
MW
59
60def allfiles(pre, dir):
61 for f in os.listdir(dir):
62 ff = os.path.join(dir, f)
63 if os.path.isdir(ff):
64 for sub in allfiles(f, ff):
65 yield sub
66 elif os.path.isfile(ff):
67 yield f
68
69def qmfiles(pre, dir):
70 for f in os.listdir(dir):
71 if not f.startswith(pre):
72 continue
73 ff = os.path.join(dir, f)
74 if os.path.isdir(ff):
75 for sub in allfiles(f, ff):
76 yield sub
77 elif os.path.isfile(ff):
78 yield f
79
ca51b51d 80for k in sort(umap.keys()):
19de3a72 81 ouid = os.geteuid()
ca51b51d 82 u = umap[k]
19de3a72
MW
83 try:
84 try:
85 os.seteuid(u.uid)
86 except OSError:
87 pass
88 qm = '.qmail' + u.dash + u.pre
89 qmlen = len(qm)
90 if u.wild:
91 try:
92 for p in qmfiles(qm, u.home):
93 ext = p[qmlen:]
94 addlocal(u, p, u.name + ext)
95 except IOError:
96 pass
97 else:
98 addlocal(u, qm, u.name, u.dash == '')
99 finally:
100 os.seteuid(ouid)
ca51b51d 101
7651970e 102me = open('control/me').readline()
ca51b51d 103
7651970e
MW
104try:
105 for dom in open('control/locals'):
106 if len(dom) and dom[-1] == '\n':
107 dom = dom[:-1]
108 map['@' + dom] = ''
109except IOError, exc:
110 if exc.errno != ENOENT:
111 raise
112 map['@' + me] = ''
113
114try:
115 for v in open('control/virtualdomains'):
116 if len(v) and v[-1] == '\n':
117 v = v[:-1]
118 (addr, pre) = v.split(':', 2)
119 map['V' + addr] = pre
120except IOError, exc:
121 if exc.errno != ENOENT:
122 raise
ca51b51d
MW
123
124for l in sort(map.keys()):
125 print '%s:%s' % (l, map[l])