On Fri, Sep 02, 2011 at 11:52:02PM +0200, Guido Günther wrote:
> On Thu, Aug 25, 2011 at 12:22:04PM +0200, Josselin Mouette wrote:
> > Package: system-config-printer
> > Version: 1.2.3-3
> > Severity: grave
> > Tags: security squeeze
> > 
> > See https://bugzilla.redhat.com/show_bug.cgi?id=728348
> > 
> > The pysmb.py module in system-config-printer is vulnerable to a remote
> > security vulnerability.
> 
> I had a short look at the code now.
> 
> >From what I see the version in squeeze uses smbc instead of invoking
> nmblookup/smbclient directly. There's a leftover nmblookup in
> troubleshoot/CheckPrinterSanity.py though but this only gets input from
> the troubleshoot dialog.. 

Lenny should be fixed by this patch. I'd appreciate any review.
Cheers,
 -- Guido
>From ad21fcaa212f2ca546e2a2df04667b7d29b1674a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Guido=20G=C3=BCnther?= <a...@sigxcpu.org>
Date: Wed, 14 Sep 2011 13:37:18 +0200
Subject: [PATCH] Use subprocess.Popen with shell=False

instead of os.popen to avoid problems unsanitized input
---
 pysmb.py |   73 +++++++++++++++++++++++++++++--------------------------------
 1 files changed, 35 insertions(+), 38 deletions(-)

diff --git a/pysmb.py b/pysmb.py
index 2208678..b048283 100644
--- a/pysmb.py
+++ b/pysmb.py
@@ -30,6 +30,7 @@ import gobject
 import gtk
 import os
 import pwd
+import subprocess
 from debug import *
 
 class AuthContext:
@@ -160,6 +161,15 @@ smbclient = "/usr/bin/smbclient"
 
 wins = None
 
+def do_popen(cmd):
+    env = os.environ.copy()
+    env["LC_ALL"] = "C"
+
+    pipe = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE,
+                            stderr=subprocess.STDOUT, env=env)
+    return pipe.communicate()[0].splitlines(True)
+
+
 def get_wins_server():
         smbconf = "/etc/samba/smb.conf"
         wsregex = re.compile("\s*wins\s*server.*",re.IGNORECASE)
@@ -201,35 +211,31 @@ def get_domain_list ():
 
     ips = []
     if wins:
-    	os.environ['WINS'] = wins
-    	str = 'LC_ALL=C %s -U "$WINS" -M -- - 2>&1' % (nmblookup)
+        cmd = [ nmblookup, '-U', wins, '-M', '--', '-' ]
     else:
-    	str = "LC_ALL=C %s -M -- - 2>&1" % (nmblookup)
-    for l in os.popen (str, 'r').readlines ():
+        cmd = [ nmblookup, '-M', '--', '-' ]
+
+    for l in do_popen(cmd):
 	l = l.splitlines()[0]
 	if l.endswith("<01>"):
             ips.append (l.split(" ")[0])
     if len (ips) <= 0:
         if wins:
-	    os.environ['WINS'] = wins
-            str = 'LC_ALL=C %s -U "$WINS" "*" 2>&1' % (nmblookup)
+            cmd = [ nmblookup, '-U', wins, '*' ]
 	else:
-            str = "LC_ALL=C %s '*' 2>&1" % (nmblookup)
-	for l in os.popen (str, 'r').readlines ():
+            cmd = [ nmblookup,  '*' ]
+	for l in do_popen(cmd):
             l = l.splitlines()[0]
 	    ips.append (l.split(" ")[0])
 
     for ip in ips:
         dom = None
     	dict = { 'IP': ip }
-	os.environ["IP"] = ip
 	if wins:
-		os.environ["WINS"] = wins
-    		str = 'LC_ALL=C %s -U "$WINS" -A "$IP"' % (nmblookup)
+            cmd = [ 'nmblookup', '-U',  wins, '-A', ip ]
 	else:
-    		str = 'LC_ALL=C %s -A "$IP"' % (nmblookup)
-	str += " 2>&1"
-	for line in os.popen(str, 'r').readlines():
+            cmd = [ 'nmblookup', '-A', ip ]
+	for line in do_popen(cmd):
 		line = line.splitlines()[0]
 		if (line.find(" <00> ") != -1) and (line.find("<GROUP>") != -1):
 			dom = line.split(" ")[0]
@@ -252,9 +258,8 @@ def get_host_list(dmbip):
         serverregex = re.compile("\s*Server\s*Comment")
         domainregex = re.compile("\s*Workgroup\s*Master")
         commentregex = re.compile("(\s*-+)+")
-	os.environ["DMBIP"] = dmbip
-	str = 'LC_ALL=C %s -N -L "//$DMBIP" 2>/dev/null' % (smbclient)
-        for l in os.popen (str, 'r').readlines ():
+        cmd = [ smbclient, '-N', '-L', '//%s' % dmbip ]
+        for l in do_popen(cmd):
                 l = l.splitlines()[0]
 
                 if serverregex.match(l):
@@ -295,10 +300,10 @@ def get_host_list_from_domain (domain):
     global wins
     ips = []
     if wins:
-    	str = "LC_ALL=C %s -U %s -R '%s' 2>&1" % (nmblookup, wins, domain)
+        cmd = [ nmblookup, '-U', wins, '-R', domain ]
     else:
-    	str = "LC_ALL=C %s -R '%s' 2>&1" % (nmblookup, domain)
-    for l in os.popen (str, 'r').readlines ():
+        cmd = [ nmblookup, '-R', domain ]
+    for l in do_popen(cmd):
 	l = l.splitlines()[0]
 	if l.endswith("<00>"):
             ips.append (l.split(" ")[0])
@@ -306,14 +311,11 @@ def get_host_list_from_domain (domain):
     for ip in ips:
         name = None
     	dict = { 'IP': ip }
-	os.environ["IP"] = ip
 	if wins:
-    		os.environ["WINS"] = wins
-    		str = 'LC_ALL=C %s -U "$WINS" -A "$IP"' % (nmblookup)
+	    cmd = [ nmblookup, '-U', wins, '-A', ip ]
 	else:
-    		str = 'LC_ALL=C %s -A "$IP"' % (nmblookup)
-	str += " 2>&1"
-	for line in os.popen(str, 'r').readlines():
+	    cmd = [ nmblookup, '-A', ip ]
+	for line in do_popen(cmd):
 		line = line.splitlines()[0]
 		if (line.find(" <00> ") != -1) and (line.find("<GROUP>") == -1):
 			name = line.split(" ")[0]
@@ -331,13 +333,11 @@ def get_host_info (smbname):
     """Given an SMB name, returns a host dict for it."""
     dict = { 'NAME': smbname, 'IP': '', 'GROUP': '' }
     global wins
-    os.environ["SMBNAME"] = smbname
     if wins:
-    	os.environ["WINS"] = wins
-    	str = 'LC_ALL=C %s -U "$WINS" -S "$SMBNAME" 2>&1' % (nmblookup)
+        cmd = [ nmblookup, '-U', wins,  '-S', smbname ]
     else:
-    	str = 'LC_ALL=C %s -S "$SMBNAME" 2>&1' % (nmblookup)
-    for l in os.popen (str, 'r').readlines ():
+        cmd = [ nmblookup, '-S', smbname ]
+    for l in do_popen(cmd):
         l = l.strip ()
         if l.endswith ("<00>"):
             dict['IP'] = l.split (" ")[0]
@@ -362,20 +362,17 @@ def get_printer_list (host):
     if not os.access (smbclient, os.X_OK):
         return printers
 
-    os.environ["NAME"] = host['NAME']
-    str = 'LC_ALL=C %s -N -L "$NAME" 2>&1' % (smbclient)
+    cmd = [ smbclient, '-N', '-L', host['NAME'] ]
     if host.has_key ('IP'):
-	os.environ["IP"] = host['IP']
-	str += ' -I "$IP"'
+        cmd += [ '-I', host['IP'] ]
 
     if host.has_key ('GROUP'):
-        os.environ["GROUP"] = host['GROUP']
-        str += ' -W "$GROUP"'
+        cmd += [ '-W', host['GROUP'] ]
 
     section = 0
     typepos = 0
     commentpos = 0
-    for l in os.popen (str, 'r'):
+    for l in do_popen(cmd):
         l = l.strip ()
         if l == "":
             continue
-- 
1.7.5.4

Reply via email to