Merge lp:~jtaylor/ubuntu/lucid/gajim/multiple-CVE into lp:ubuntu/lucid/gajim

Proposed by Julian Taylor
Status: Merged
Merge reported by: Marc Deslauriers
Merged at revision: not available
Proposed branch: lp:~jtaylor/ubuntu/lucid/gajim/multiple-CVE
Merge into: lp:ubuntu/lucid/gajim
Diff against target: 376 lines (+347/-0)
5 files modified
debian/changelog (+19/-0)
debian/patches/00list (+3/-0)
debian/patches/CVE-2012-2085.dpatch (+54/-0)
debian/patches/CVE-2012-2086.dpatch (+157/-0)
debian/patches/CVE-2012-2093.dpatch (+114/-0)
To merge this branch: bzr merge lp:~jtaylor/ubuntu/lucid/gajim/multiple-CVE
Reviewer Review Type Date Requested Status
Ubuntu Development Team Pending
Review via email: mp+104264@code.launchpad.net
To post a comment you must log in.
54. By Julian Taylor

fix missing jid tuple in patch

55. By Julian Taylor

fix missing wait on process end

Revision history for this message
Marc Deslauriers (mdeslaur) wrote :

Julian, could you please update the status of this merge request so it gets removed from the sponsors list? Thanks.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2009-12-15 02:32:45 +0000
3+++ debian/changelog 2012-05-10 19:54:17 +0000
4@@ -1,3 +1,22 @@
5+gajim (0.13-0ubuntu2.10.04.1) lucid-security; urgency=low
6+
7+ * SECURITY UPDATE: assisted code execution (LP: #992618)
8+ - debian/patches/CVE-2012-2085.dpatch: fix subprocess call to prevent
9+ shell escape from via crafted messages
10+ https://trac.gajim.org/changeset/bc296e96ac10
11+ - CVE-2012-2085
12+ * SECURITY UPDATE: sql injection in logging code (LP: #992618)
13+ - debian/patches/CVE-2012-2086.dpatch: use a prepated statement
14+ https://trac.gajim.org/changeset/bfd5f94489d8
15+ - CVE-2012-2086
16+ * SECURITY UPDATE: insecure tmpfile creation (LP: #992613)
17+ - debian/patches/CVE-2012-2093.dpatch: use safe tmpfile functions
18+ when convering LaTeX IM messages to png images
19+ Thanks to Nico Golde
20+ - CVE-2012-2093
21+
22+ -- Julian Taylor <jtaylor@ubuntu.com> Tue, 01 May 2012 15:21:25 +0200
23+
24 gajim (0.13-0ubuntu2) lucid; urgency=low
25
26 * debian/control:
27
28=== modified file 'debian/patches/00list'
29--- debian/patches/00list 2009-11-25 08:33:47 +0000
30+++ debian/patches/00list 2012-05-10 19:54:17 +0000
31@@ -1,2 +1,5 @@
32 config-write-sync.patch
33 ubuntu-keyring.patch
34+CVE-2012-2085.dpatch
35+CVE-2012-2086.dpatch
36+CVE-2012-2093.dpatch
37
38=== added file 'debian/patches/CVE-2012-2085.dpatch'
39--- debian/patches/CVE-2012-2085.dpatch 1970-01-01 00:00:00 +0000
40+++ debian/patches/CVE-2012-2085.dpatch 2012-05-10 19:54:17 +0000
41@@ -0,0 +1,54 @@
42+#! /bin/sh /usr/share/dpatch/dpatch-run
43+## Description: prevent assisted code execution CVE-2012-2085
44+## Origin: https://trac.gajim.org/changeset/bc296e96ac10
45+## Bug: https://trac.gajim.org/ticket/7031
46+## CVE-2012-2085.dpatch by Julian Taylor <jtaylor@ubuntu.com>
47+##
48+## All lines beginning with `## DP:' are a description of the patch.
49+## DP: No description.
50+
51+@DPATCH@
52+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gajim-lucid.orig~/src/common/helpers.py gajim-lucid.orig/src/common/helpers.py
53+--- gajim-lucid.orig~/src/common/helpers.py 2012-05-01 15:19:52.000000000 +0200
54++++ gajim-lucid.orig/src/common/helpers.py 2012-05-01 15:20:49.347118151 +0200
55+@@ -39,6 +39,7 @@
56+ import base64
57+ import sys
58+ import hashlib
59++import shlex
60+
61+ from encodings.punycode import punycode_encode
62+
63+@@ -355,8 +356,18 @@
64+ pass
65+ return False
66+
67+-def exec_command(command):
68+- subprocess.Popen('%s &' % command, shell=True).wait()
69++def exec_command(command, use_shell=False):
70++ """
71++ execute a command. if use_shell is True, we run the command as is it was
72++ typed in a console. So it may be dangerous if you are not sure about what
73++ is executed.
74++ """
75++ if use_shell:
76++ subprocess.Popen('%s &' % command, shell=True).wait()
77++ else:
78++ args = shlex.split(command.encode('utf-8'))
79++ p = subprocess.Popen(args)
80++ gajim.thread_interface(p.wait)
81+
82+ def build_command(executable, parameter):
83+ # we add to the parameter (can hold path with spaces)
84+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gajim-lucid.orig~/src/notify.py gajim-lucid.orig/src/notify.py
85+--- gajim-lucid.orig~/src/notify.py 2012-05-01 15:19:52.000000000 +0200
86++++ gajim-lucid.orig/src/notify.py 2012-05-01 15:21:18.347117755 +0200
87+@@ -323,7 +323,7 @@
88+ command = gajim.config.get_per('notifications', str(advanced_notif_num),
89+ 'command')
90+ try:
91+- helpers.exec_command(command)
92++ helpers.exec_command(command, use_shell=True)
93+ except Exception:
94+ pass
95+
96
97=== added file 'debian/patches/CVE-2012-2086.dpatch'
98--- debian/patches/CVE-2012-2086.dpatch 1970-01-01 00:00:00 +0000
99+++ debian/patches/CVE-2012-2086.dpatch 2012-05-10 19:54:17 +0000
100@@ -0,0 +1,157 @@
101+#! /bin/sh /usr/share/dpatch/dpatch-run
102+## Description: prevent sql injections CVE-2012-2086
103+## Origin: https://trac.gajim.org/changeset/bc296e96ac10
104+## Bug: https://trac.gajim.org/ticket/7031
105+## CVE-2012-2086.dpatch by Julian Taylor <jtaylor@ubuntu.com>
106+##
107+## All lines beginning with `## DP:' are a description of the patch.
108+## DP: No description.
109+
110+@DPATCH@
111+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gajim-lucid.orig~/src/common/logger.py gajim-lucid.orig/src/common/logger.py
112+--- gajim-lucid.orig~/src/common/logger.py 2012-05-01 15:19:52.000000000 +0200
113++++ gajim-lucid.orig/src/common/logger.py 2012-05-01 15:23:03.891116311 +0200
114+@@ -527,7 +527,7 @@
115+ except exceptions.PysqliteOperationalError, e:
116+ # Error trying to create a new jid_id. This means there is no log
117+ return []
118+- where_sql = self._build_contact_where(account, jid)
119++ where_sql, jid_tuple = self._build_contact_where(account, jid)
120+
121+ now = int(float(time.time()))
122+ timed_out = now - (timeout * 60) # before that they are too old
123+@@ -539,10 +539,9 @@
124+ WHERE (%s) AND kind IN (%d, %d, %d, %d, %d) AND time > %d
125+ ORDER BY time DESC LIMIT %d OFFSET %d
126+ ''' % (where_sql, constants.KIND_SINGLE_MSG_RECV,
127+- constants.KIND_CHAT_MSG_RECV, constants.KIND_SINGLE_MSG_SENT,
128+- constants.KIND_CHAT_MSG_SENT, constants.KIND_ERROR,
129+- timed_out, restore_how_many_rows, pending_how_many)
130+- )
131++ constants.KIND_CHAT_MSG_RECV, constants.KIND_SINGLE_MSG_SENT,
132++ constants.KIND_CHAT_MSG_SENT, constants.KIND_ERROR, timed_out,
133++ restore_how_many_rows, pending_how_many), jid_tuple)
134+
135+ results = self.cur.fetchall()
136+ except sqlite.DatabaseError:
137+@@ -569,7 +568,7 @@
138+ except exceptions.PysqliteOperationalError, e:
139+ # Error trying to create a new jid_id. This means there is no log
140+ return []
141+- where_sql = self._build_contact_where(account, jid)
142++ where_sql, jid_tuple = self._build_contact_where(account, jid)
143+
144+ start_of_day = self.get_unix_time_from_date(year, month, day)
145+ seconds_in_a_day = 86400 # 60 * 60 * 24
146+@@ -580,7 +579,7 @@
147+ WHERE (%s)
148+ AND time BETWEEN %d AND %d
149+ ORDER BY time
150+- ''' % (where_sql, start_of_day, last_second_of_day))
151++ ''' % (where_sql, start_of_day, last_second_of_day), jid_tuple)
152+
153+ results = self.cur.fetchall()
154+ return results
155+@@ -603,13 +602,13 @@
156+ return results
157+
158+ else: # user just typed something, we search in message column
159+- where_sql = self._build_contact_where(account, jid)
160++ where_sql, jid_tuple = self._build_contact_where(account, jid)
161+ like_sql = '%' + query.replace("'", "''") + '%'
162+ self.cur.execute('''
163+ SELECT contact_name, time, kind, show, message, subject FROM logs
164+ WHERE (%s) AND message LIKE '%s'
165+ ORDER BY time
166+- ''' % (where_sql, like_sql))
167++ ''' % (where_sql, like_sql), jid_tuple)
168+
169+ results = self.cur.fetchall()
170+ return results
171+@@ -622,7 +621,7 @@
172+ # Error trying to create a new jid_id. This means there is no log
173+ return []
174+ days_with_logs = []
175+- where_sql = self._build_contact_where(account, jid)
176++ where_sql, jid_tuple = self._build_contact_where(account, jid)
177+
178+ # First select all date of month whith logs we want
179+ start_of_month = self.get_unix_time_from_date(year, month, 1)
180+@@ -640,7 +639,7 @@
181+ AND kind NOT IN (%d, %d)
182+ ORDER BY time
183+ ''' % (where_sql, start_of_month, last_second_of_month,
184+- constants.KIND_STATUS, constants.KIND_GCSTATUS))
185++ constants.KIND_STATUS, constants.KIND_GCSTATUS), jid_tuple)
186+ result = self.cur.fetchall()
187+
188+ # convert timestamps to day of month
189+@@ -654,19 +653,21 @@
190+ we had logs (excluding statuses)'''
191+ where_sql = ''
192+ if not is_room:
193+- where_sql = self._build_contact_where(account, jid)
194++ where_sql, jid_tuple = self._build_contact_where(account, jid)
195+ else:
196+ try:
197+ jid_id = self.get_jid_id(jid, 'ROOM')
198+ except exceptions.PysqliteOperationalError, e:
199+ # Error trying to create a new jid_id. This means there is no log
200+ return None
201+- where_sql = 'jid_id = %s' % jid_id
202++ where_sql = 'jid_id = ?'
203++ jid_tuple = (jid_id,)
204+ self.cur.execute('''
205+ SELECT MAX(time) FROM logs
206+ WHERE (%s)
207+ AND kind NOT IN (%d, %d)
208+- ''' % (where_sql, constants.KIND_STATUS, constants.KIND_GCSTATUS))
209++ ''' % (where_sql, constants.KIND_STATUS, constants.KIND_GCSTATUS),
210++ jid_tuple)
211+
212+ results = self.cur.fetchone()
213+ if results is not None:
214+@@ -683,11 +684,13 @@
215+ except exceptions.PysqliteOperationalError, e:
216+ # Error trying to create a new jid_id. This means there is no log
217+ return None
218+- where_sql = 'jid_id = %s' % jid_id
219++ where_sql = 'jid_id = ?'
220++ jid_tuple = (jid_id,)
221++
222+ self.cur.execute('''
223+ SELECT time FROM rooms_last_message_time
224+ WHERE (%s)
225+- ''' % (where_sql))
226++ ''' % (where_sql), jid_tuple)
227+
228+ results = self.cur.fetchone()
229+ if results is not None:
230+@@ -709,6 +712,7 @@
231+ '''build the where clause for a jid, including metacontacts
232+ jid(s) if any'''
233+ where_sql = ''
234++ jid_tuple = ()
235+ # will return empty list if jid is not associated with
236+ # any metacontacts
237+ family = gajim.contacts.get_metacontacts_family(account, jid)
238+@@ -718,13 +722,15 @@
239+ jid_id = self.get_jid_id(user['jid'])
240+ except exceptions.PysqliteOperationalError, e:
241+ continue
242+- where_sql += 'jid_id = %s' % jid_id
243++ where_sql += 'jid_id = ?'
244++ jid_tuple += (jid_id,)
245+ if user != family[-1]:
246+ where_sql += ' OR '
247+ else: # if jid was not associated with metacontacts
248+ jid_id = self.get_jid_id(jid)
249+- where_sql = 'jid_id = %s' % jid_id
250+- return where_sql
251++ where_sql = 'jid_id = ?'
252++ jid_tuple += (jid_id,)
253++ return where_sql,jid_tuple
254+
255+ def save_transport_type(self, jid, type_):
256+ '''save the type of the transport in DB'''
257+
258
259=== added file 'debian/patches/CVE-2012-2093.dpatch'
260--- debian/patches/CVE-2012-2093.dpatch 1970-01-01 00:00:00 +0000
261+++ debian/patches/CVE-2012-2093.dpatch 2012-05-10 19:54:17 +0000
262@@ -0,0 +1,114 @@
263+#! /bin/sh /usr/share/dpatch/dpatch-run
264+## Description: fix insecure tmpfile creation CVE-2012-2093
265+## Origin: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=668710
266+## Bug: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=668710
267+## CVE-2012-2093.dpatch by Julian Taylor <jtaylor@ubuntu.com>
268+##
269+## All lines beginning with `## DP:' are a description of the patch.
270+## DP: No description.
271+
272+@DPATCH@
273+diff -urNad '--exclude=CVS' '--exclude=.svn' '--exclude=.git' '--exclude=.arch' '--exclude=.hg' '--exclude=_darcs' '--exclude=.bzr' gajim-lucid.orig~/src/common/latex.py gajim-lucid.orig/src/common/latex.py
274+--- gajim-lucid.orig~/src/common/latex.py 2012-05-01 15:19:52.000000000 +0200
275++++ gajim-lucid.orig/src/common/latex.py 2012-05-01 15:26:22.031113594 +0200
276+@@ -29,7 +29,7 @@
277+
278+ import os
279+ import random
280+-from tempfile import gettempdir
281++from tempfile import gettempdir,mkstemp,mkdtemp
282+ from subprocess import Popen, PIPE
283+
284+ import logging
285+@@ -57,10 +57,10 @@
286+ return True
287+ return False
288+
289+-def get_tmpfile_name():
290++def get_tmpfile_name(tmpdir):
291+ random.seed()
292+ int_ = random.randint(0, 100)
293+- return os.path.join(gettempdir(), 'gajimtex_' + int_.__str__())
294++ return os.path.join(tmpdir, 'gajimtex_' + int_.__str__())
295+
296+ def write_latex(filename, str_):
297+ texstr = '\\documentclass[12pt]{article}\\usepackage[dvips]{graphicx}'
298+@@ -78,12 +78,12 @@
299+ # a wrapper for Popen so that no window gets opened on Windows
300+ # (i think this is the reason we're using Popen rather than just system())
301+ # stdout goes to a pipe so that it can be read
302+-def popen_nt_friendly(command):
303++def popen_nt_friendly(command, directory):
304+ if os.name == 'nt':
305+ # CREATE_NO_WINDOW
306+- return Popen(command, creationflags=0x08000000, cwd=gettempdir(), stdout=PIPE)
307++ return Popen(command, creationflags=0x08000000, cwd=directory, stdout=PIPE)
308+ else:
309+- return Popen(command, cwd=gettempdir(), stdout=PIPE)
310++ return Popen(command, cwd=directory, stdout=PIPE)
311+
312+ def check_for_latex_support():
313+ '''check is latex is available and if it can create a picture.'''
314+@@ -98,9 +98,9 @@
315+ except LatexError:
316+ return False
317+
318+-def try_run(argv):
319++def try_run(argv, directory):
320+ try:
321+- p = popen_nt_friendly(argv)
322++ p = popen_nt_friendly(argv, directory)
323+ out = p.communicate()[0]
324+ log.info(out)
325+ return p.wait()
326+@@ -125,21 +125,28 @@
327+ # we triggered the blacklist, immediately return None
328+ return None
329+
330+- tmpfile = get_tmpfile_name()
331++ tmpdir = ""
332++ tmppng = ""
333++ try:
334++ tmpdir = mkdtemp(prefix="gajim")
335++ tmppng = mkstemp(suffix=".png")[1]
336++ except Exception:
337++ raise LatexError("could not securely create one or more temporary files for LaTeX conversion")
338+
339++ tmpfile = get_tmpfile_name(tmpdir)
340+ # build latex string
341+ write_latex(os.path.join(tmpfile + '.tex'), str_)
342+
343+ # convert TeX to dvi
344+ exitcode = try_run(['latex', '--interaction=nonstopmode',
345+- tmpfile + '.tex'])
346++ tmpfile + '.tex'], tmpdir)
347+
348+ if exitcode == 0:
349+ # convert dvi to png
350+ latex_png_dpi = gajim.config.get('latex_png_dpi')
351+ exitcode = try_run(['dvipng', '-bg', bg_str, '-fg', fg_str, '-T',
352+ 'tight', '-D', latex_png_dpi, tmpfile + '.dvi', '-o',
353+- tmpfile + '.png'])
354++ tmpfile + '.png'], tmpdir)
355+
356+ # remove temp files created by us and TeX
357+ extensions = ['.tex', '.log', '.aux', '.dvi']
358+@@ -149,11 +156,17 @@
359+ except Exception:
360+ pass
361+
362++ if exitcode == 0:
363++ os.rename(tmpfile + '.png', tmppng)
364++ else:
365++ os.remove(tmppng)
366++
367++ os.rmdir(tmpdir)
368+ if isinstance(exitcode, (unicode, str)):
369+ raise LatexError(exitcode)
370+
371+ if exitcode == 0:
372+- result = tmpfile + '.png'
373++ result = tmppng
374+
375+ return result
376+

Subscribers

People subscribed via source and target branches

to all changes: