qmail-valid-addresses security: scan read dot-qmail files as owner
[qmail] / qmail-valid-addresses
index d43cf85..8a36f58 100644 (file)
@@ -43,34 +43,61 @@ del udb
 map = {}
 def addlocal(u, p, l, forcep = False):
   l = 'L' + l
+  p = os.path.join(u.home, p)
   if not os.path.exists(p):
     if forcep:
       map[l] = '+'
     return
-  f = open(p)
-  top = f.readline()
-  f.close()
-  if len(top) > 1 and top[0:2] == '#!':
+  qm = file(os.path.join(u.home, p)).readline()
+  if len(qm) > 1 and qm[0:2] == '#!':
     map[l] = '-'
-  elif len(top) > 1 and top[0:2] == '#?':
-    name = u.name
-    if name[-1] == '-':
-      name = name[:-1]
+  elif len(qm) > 1 and qm[0:2] == '#?':
+    name = u.user
     map[l] = '?' + name
   else:
     map[l] = '+'
+
+def allfiles(pre, dir):
+  for f in os.listdir(dir):
+    ff = os.path.join(dir, f)
+    if os.path.isdir(ff):
+      for sub in allfiles(f, ff):
+        yield sub
+    elif os.path.isfile(ff):
+      yield f
+    
+def qmfiles(pre, dir):
+  for f in os.listdir(dir):
+    if not f.startswith(pre):
+      continue
+    ff = os.path.join(dir, f)
+    if os.path.isdir(ff):
+      for sub in allfiles(f, ff):
+        yield sub
+    elif os.path.isfile(ff):
+      yield f
+
 for k in sort(umap.keys()):
+  ouid = os.geteuid()
   u = umap[k]
-  qm = '.qmail' + u.dash + u.pre
-  qmlen = len(qm)
-  if u.wild:
-    for p in os.listdir(u.home):
-      if not p.startswith(qm):
-        continue
-      ext = p[qmlen:]
-      addlocal(u, os.path.join(u.home, p), u.name + ext)
-  else:
-    addlocal(u, os.path.join(u.home, qm), u.name, u.dash == '')
+  try:
+    try:
+      os.seteuid(u.uid)
+    except OSError:
+      pass
+    qm = '.qmail' + u.dash + u.pre
+    qmlen = len(qm)
+    if u.wild:
+      try:
+        for p in qmfiles(qm, u.home):
+          ext = p[qmlen:]
+          addlocal(u, p, u.name + ext)
+      except IOError:
+        pass
+    else:
+      addlocal(u, qm, u.name, u.dash == '')
+  finally:
+    os.seteuid(ouid)
 
 me = open('control/me').readline()