Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 23 Nov 2008 23:22:21 +0300
From:      Eygene Ryabinkin <rea-fbsd@codelabs.ru>
To:        bug-followup@FreeBSD.org, freebsd-ports-bugs@FreeBSD.org
Cc:        freebsd-security@freebsd.org
Subject:   Re: ports/129097: [vuxml] print/hplip: document CVE-2008-2940 and CVE-2008-2941
Message-ID:  <6rQsez7wYkguGr%2BAMLr6LWOVTxk@iXA9ZWPrtc2I2BMzBXoToMd7YdQ>
In-Reply-To: <200811231850.mANIo09F042711@freefall.freebsd.org>
References:  <20081123184449.6801AF181D@phoenix.codelabs.ru> <200811231850.mANIo09F042711@freefall.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--Dxnq1zWXvFF0Q93v
Content-Type: text/plain; charset=koi8-r
Content-Disposition: inline

Martin Wilke asked me if I am planning to update the port.  My original
intention was to wait for a 2.8.10 (I am aware of ports/128914, but, to
my regret, it contains no patch now), but as the quick fix I had ported
RedHat's patches to the current port version.

Please note that the handling of alerts had been changed: now all alert
configuration is stored in /etc/hp/alers.conf and isn't
user-controllable anymore.

And I had to mention that whilst I had tested the port for building
and daemon for starting properly, I have no real hardware to test the
thing.  So maintainer's testing is needed.
-- 
Eygene
 _                ___       _.--.   #
 \`.|\..----...-'`   `-._.-'_.-'`   #  Remember that it is hard
 /  ' `         ,       __.--'      #  to read the on-line manual   
 )/' _/     \   `-_,   /            #  while single-stepping the kernel.
 `-'" `"\_  ,_.-;_.-\_ ',  fsc/as   #
     _.-'_./   {_.'   ; /           #    -- FreeBSD Developers handbook 
    {_.-``-'         {_/            #

--Dxnq1zWXvFF0Q93v
Content-Type: text/x-diff; charset=koi8-r
Content-Disposition: attachment;
	filename="apply-fixes-for-CVE-2008-2940-and-CVE-2941.diff"
Content-Transfer-Encoding: quoted-printable

=46rom e8f2e991adcde572e1c08951c9b973ca6759455f Mon Sep 17 00:00:00 2001
=46rom: Eygene Ryabinkin <rea-fbsd@codelabs.ru>
Date: Sun, 23 Nov 2008 23:02:17 +0300
Subject: [PATCH] print/hplip: apply fixes for CVE-2008-2940 and CVE-2008-29=
41

Fix for CVE-2008-2940 was taken from [1] and was slightly modified
to match the current code.

Fix for CVE-2008-2941 was written by hand, but was based on the patch
=66rom [2].  Note, that the mentioned patch fragility sits in the fact
that the parsed values can represent string, integer, etc and this is
user-controllable, but their values are manipulated as they are always
strings, numbers, etc.  So daemon gets some exceptions that he is not
prepared to handle and dies.

[1] https://bugzilla.redhat.com/show_bug.cgi?id=3D455235
[2] https://bugzilla.redhat.com/show_bug.cgi?id=3D457052

Signed-off-by: Eygene Ryabinkin <rea-fbsd@codelabs.ru>
---
 print/hplip/Makefile                  |    2 +-
 print/hplip/files/patch-CVE-2008-2940 |   74 ++++++++++++
 print/hplip/files/patch-CVE-2008-2941 |  210 +++++++++++++++++++++++++++++=
++++
 3 files changed, 285 insertions(+), 1 deletions(-)
 create mode 100644 print/hplip/files/patch-CVE-2008-2940
 create mode 100644 print/hplip/files/patch-CVE-2008-2941

diff --git a/print/hplip/Makefile b/print/hplip/Makefile
index 9845d37..683b285 100644
--- a/print/hplip/Makefile
+++ b/print/hplip/Makefile
@@ -7,7 +7,7 @@
=20
 PORTNAME=3D	hplip
 PORTVERSION=3D	2.8.2
-PORTREVISION=3D	2
+PORTREVISION=3D	3
 CATEGORIES=3D	print
 MASTER_SITES=3D	${MASTER_SITE_SOURCEFORGE}
 MASTER_SITE_SUBDIR=3D	hplip
diff --git a/print/hplip/files/patch-CVE-2008-2940 b/print/hplip/files/patc=
h-CVE-2008-2940
new file mode 100644
index 0000000..dbe14fa
--- /dev/null
+++ b/print/hplip/files/patch-CVE-2008-2940
@@ -0,0 +1,74 @@
+Patch for CVE-2008-2940
+
+Please note that alerts are now system-wide and they live in
+/etc/hp/alerts.conf
+
+See: http://cve.mitre.org/cgi-bin/cvename.cgi?name=3DCVE-2008-2940
+Obtained from: https://bugzilla.redhat.com/attachment.cgi?id=3D312878
+Obtained from: https://bugzilla.redhat.com/attachment.cgi?id=3D312880
+
+diff -up hplip-1.6.7/hpssd.py.validate-uri hplip-1.6.7/hpssd.py
+--- hpssd.py.validate-uri	2008-07-29 12:48:28.000000000 +0100
++++ hpssd.py	2008-07-29 13:41:29.000000000 +0100
+@@ -1021,6 +1021,9 @@ class hpssd_handler(dispatcher):
+         event_type =3D self.fields.get('event-type', 'event')
+         event_code =3D self.fields.get('event-code', 0)
+         device_uri =3D self.fields.get('device-uri', '').replace('hpfax:'=
, 'hp:')
++        result_code =3D self.__checkdevice(device_uri)
++        if result_code !=3D ERROR_SUCCESS:
++            return
+         log.debug("Device URI: %s" % device_uri)
+=20
+         try:
+diff -up hplip-1.6.7/base/g.py.static-alerts-table hplip-1.6.7/base/g.py
+--- base/g.py.orig	2008-01-18 02:10:29.000000000 +0300
++++ base/g.py	2008-11-23 22:39:11.000000000 +0300
+@@ -134,6 +134,7 @@
+ # Config file: directories and ports
+ prop.sys_config_file =3D '/etc/hp/hplip.conf'
+ prop.user_dir =3D os.path.expanduser('~/.hplip')
++prop.alerts_config_file =3D '/etc/hp/alerts.conf'
+=20
+ os.umask(0037)
+ try:
+@@ -154,6 +155,7 @@
+    =20
+ sys_cfg =3D Config(prop.sys_config_file, True)
+ user_cfg =3D Config(prop.user_config_file)
++alerts_cfg =3D Config(prop.alerts_config_file)
+=20
+=20
+ # Language settings
+diff -up hplip-1.6.7/hpssd.py.static-alerts-table hplip-1.6.7/hpssd.py
+--- hpssd.py.static-alerts-table	2008-07-29 14:57:04.000000000 +0100
++++ hpssd.py	2008-07-29 15:22:15.000000000 +0100
+@@ -71,6 +71,12 @@ from prnt import cups
+=20
+ # Per user alert settings
+ alerts =3D {}
++for user, cfg in alerts_cfg.iteritems ():
++    entry =3D {}
++    entry['email-alerts'] =3D utils.to_bool (cfg.get('email-alerts', 0))
++    entry['email-from-address'] =3D cfg.get('email-from-address', '')
++    entry['email-to-addresses'] =3D cfg.get('email-to-addresses', '')
++    alerts[user] =3D entry
+=20
+ # Fax temp files
+ fax_file =3D {}
+@@ -803,15 +809,10 @@ class hpssd_handler(dispatcher):
+         self.out_buffer =3D buildResultMessage('InjectValueResult', None,=
 result_code)
+        =20
+=20
+-    # TODO: Need to load alerts at start-up
+     def handle_setalerts(self):
+         result_code =3D ERROR_SUCCESS
+-        username =3D self.fields.get('username', '')
+=20
+-        alerts[username] =3D {'email-alerts'       : utils.to_bool(self.f=
ields.get('email-alerts', '0')),
+-                            'email-from-address' : self.fields.get('email=
-from-address', ''),
+-                            'email-to-addresses' : self.fields.get('email=
-to-addresses', ''),
+-                           }
++        # Do nothing.  We use the alerts table in /etc/hp/alerts.conf.
+=20
+         self.out_buffer =3D buildResultMessage('SetAlertsResult', None, r=
esult_code)
+=20
diff --git a/print/hplip/files/patch-CVE-2008-2941 b/print/hplip/files/patc=
h-CVE-2008-2941
new file mode 100644
index 0000000..f4bb8ee
--- /dev/null
+++ b/print/hplip/files/patch-CVE-2008-2941
@@ -0,0 +1,210 @@
+Patch for CVE-2008-2941
+
+Fixes parser fragility: original code expects only strings or numbers as
+the input values, but not both.  And hpssd client has the full control
+on the input data, so when number is tried to be transformed as string
+(by calling lower() method, for example) the unhandled exception
+terminates the daemon.
+
+Based on: https://bugzilla.redhat.com/attachment.cgi?id=3D312881
+
+--- hpssd.py.orig	2008-11-23 22:41:08.000000000 +0300
++++ hpssd.py	2008-11-23 22:57:51.000000000 +0300
+@@ -203,7 +203,7 @@
+                 log.debug(self.out_buffer)
+                 return True
+=20
+-            msg_type =3D self.fields.get('msg', 'unknown').lower()
++            msg_type =3D str(self.fields.get('msg', 'unknown')).lower()
+             log.debug("Handling: %s %s %s" % ("*"*20, msg_type, "*"*20))
+             log.debug(repr(self.in_buffer))
+=20
+@@ -260,9 +260,9 @@
+=20
+=20
+     def handle_getvalue(self):
+-        device_uri =3D self.fields.get('device-uri', '').replace('hpfax:'=
, 'hp:')
++        device_uri =3D str(self.fields.get('device-uri', '')).replace('hp=
fax:', 'hp:')
+         value =3D ''
+-        key =3D self.fields.get('key', '')
++        key =3D str(self.fields.get('key', ''))
+         result_code =3D self.__checkdevice(device_uri)
+=20
+         if result_code =3D=3D ERROR_SUCCESS:
+@@ -274,9 +274,9 @@
+         self.out_buffer =3D buildResultMessage('GetValueResult', value, r=
esult_code)
+=20
+     def handle_setvalue(self):
+-        device_uri =3D self.fields.get('device-uri', '').replace('hpfax:'=
, 'hp:')
+-        key =3D self.fields.get('key', '')
+-        value =3D self.fields.get('value', '')
++        device_uri =3D str(self.fields.get('device-uri', '')).replace('hp=
fax:', 'hp:')
++        key =3D str(self.fields.get('key', ''))
++        value =3D str(self.fields.get('value', ''))
+         result_code =3D self.__checkdevice(device_uri)
+=20
+         if result_code =3D=3D ERROR_SUCCESS:   =20
+@@ -285,7 +285,7 @@
+         self.out_buffer =3D buildResultMessage('SetValueResult', None, ER=
ROR_SUCCESS)
+=20
+     def handle_queryhistory(self):
+-        device_uri =3D self.fields.get('device-uri', '').replace('hpfax:'=
, 'hp:')
++        device_uri =3D str(self.fields.get('device-uri', '')).replace('hp=
fax:', 'hp:')
+         payload =3D ''
+         result_code =3D self.__checkdevice(device_uri)
+=20
+@@ -305,8 +305,8 @@
+=20
+     # EVENT
+     def handle_registerguievent(self):
+-        username =3D self.fields.get('username', '')
+-        typ =3D self.fields.get('type', 'unknown')
++        username =3D str(self.fields.get('username', ''))
++        typ =3D str(self.fields.get('type', 'unknown'))
+         self.typ =3D typ
+         self.username =3D username
+         self.send_events =3D True
+@@ -314,13 +314,13 @@
+=20
+     # EVENT
+     def handle_unregisterguievent(self):
+-        username =3D self.fields.get('username', '')
++        username =3D str(self.fields.get('username', ''))
+         self.send_events =3D False
+=20
+=20
+     def handle_test_email(self):
+         result_code =3D ERROR_SUCCESS
+-        username =3D self.fields.get('username', prop.username)
++        username =3D str(self.fields.get('username', prop.username))
+         message =3D device.queryString('email_test_message')
+         subject =3D device.queryString('email_test_subject')
+         result_code =3D self.sendEmail(username, subject, message, True)
+@@ -343,11 +343,14 @@
+=20
+     # sent by hpfax: to indicate the start of a complete fax rendering job
+     def handle_hpfaxbegin(self):
+-        username =3D self.fields.get('username', prop.username)
+-        job_id =3D self.fields.get('job-id', 0)
+-        printer_name =3D self.fields.get('printer', '')
+-        device_uri =3D self.fields.get('device-uri', '').replace('hp:', '=
hpfax:')
+-        title =3D self.fields.get('title', '')
++        username =3D str(self.fields.get('username', prop.username))
++        try:
++            job_id =3D int(self.fields.get('job-id', 0))
++        except ValueError:
++            job_id =3D 0
++        printer_name =3D str(self.fields.get('printer', ''))
++        device_uri =3D str(self.fields.get('device-uri', '')).replace('hp=
:', 'hpfax:')
++        title =3D str(self.fields.get('title', ''))
+=20
+         log.debug("Creating data store for %s:%d" % (username, job_id))
+         fax_file[(username, job_id)] =3D tempfile.NamedTemporaryFile(pref=
ix=3D"hpfax")
+@@ -360,8 +363,11 @@
+=20
+     # sent by hpfax: to transfer completed fax rendering data
+     def handle_hpfaxdata(self):
+-        username =3D self.fields.get('username', prop.username)
+-        job_id =3D self.fields.get('job-id', 0)
++        username =3D str(self.fields.get('username', prop.username))
++        try:
++            job_id =3D int(self.fields.get('job-id', 0))
++        except ValueError:
++            job_id =3D 0
+=20
+         if self.payload and (username, job_id) in fax_file and \
+             not fax_file_ready[(username, job_id)]:
+@@ -373,12 +379,18 @@
+=20
+     # sent by hpfax: to indicate the end of a complete fax rendering job
+     def handle_hpfaxend(self):
+-        username =3D self.fields.get('username', '')
+-        job_id =3D self.fields.get('job-id', 0)
+-        printer_name =3D self.fields.get('printer', '')
+-        device_uri =3D self.fields.get('device-uri', '').replace('hp:', '=
hpfax:')
+-        title =3D self.fields.get('title', '')
+-        job_size =3D self.fields.get('job-size', 0)
++        username =3D str(self.fields.get('username', ''))
++        try:
++            job_id =3D int(self.fields.get('job-id', 0))
++        except ValueError:
++            job_id =3D 0
++        printer_name =3D str(self.fields.get('printer', ''))
++        device_uri =3D str(self.fields.get('device-uri', '')).replace('hp=
:', 'hpfax:')
++        title =3D str(self.fields.get('title', ''))
++        try:
++            job_size =3D int(self.fields.get('job-size', 0))
++        except ValueError:
++            job_size =3D 0
+=20
+         fax_file[(username, job_id)].seek(0)
+         fax_file_ready[(username, job_id)] =3D True
+@@ -389,7 +401,7 @@
+=20
+     # sent by hp-sendfax to see if any faxes have been printed and need t=
o be picked up
+     def handle_faxcheck(self):
+-        username =3D self.fields.get('username', '')
++        username =3D str(self.fields.get('username', ''))
+         result_code =3D ERROR_NO_DATA_AVAILABLE
+         other_fields =3D {}
+=20
+@@ -413,8 +425,11 @@
+     # after being run with --job param, both after a hpfaxend message
+     def handle_faxgetdata(self):
+         result_code =3D ERROR_SUCCESS
+-        username =3D self.fields.get('username', '')
+-        job_id =3D self.fields.get('job-id', 0)
++        username =3D str(self.fields.get('username', ''))
++        try:
++            job_id =3D int(self.fields.get('job-id', 0))
++        except ValueError:
++            job_id =3D 0
+=20
+         try:
+             fax_file[(username, job_id)]
+@@ -442,15 +457,18 @@
+     # EVENT
+     def handle_event(self):
+         gui_port, gui_host =3D None, None
+-        event_type =3D self.fields.get('event-type', 'event')
++        event_type =3D str(self.fields.get('event-type', 'event'))
+        =20
+-        event_code =3D self.fields.get('event-code', STATUS_PRINTER_IDLE)
++        try:
++            event_code =3D int(self.fields.get('event-code', STATUS_PRINT=
ER_IDLE))
++        except ValueError:
++            event_code =3D STATUS_PRINTER_IDLE
+        =20
+         # If event-code > 10001, its a PJL error code, so convert it
+         if event_code > EVENT_MAX_EVENT:
+             event_code =3D status.MapPJLErrorCode(event_code)
+            =20
+-        device_uri =3D self.fields.get('device-uri', '').replace('hpfax:'=
, 'hp:')
++        device_uri =3D str(self.fields.get('device-uri', '')).replace('hp=
fax:', 'hp:')
+         result_code =3D self.__checkdevice(device_uri)
+         if result_code !=3D ERROR_SUCCESS:
+             return
+@@ -461,7 +479,10 @@
+=20
+         log.debug("Short/Long: %s/%s" % (error_string_short, error_string=
_long))
+=20
+-        job_id =3D self.fields.get('job-id', 0)
++        try:
++            job_id =3D int(self.fields.get('job-id', 0))
++        except ValueError:
++            job_id =3D 0
+=20
+         try:
+             username =3D self.fields['username']
+@@ -480,7 +501,10 @@
+=20
+         no_fwd =3D utils.to_bool(self.fields.get('no-fwd', '0'))
+         log.debug("Username (jobid): %s (%d)" % (username, job_id))
+-        retry_timeout =3D self.fields.get('retry-timeout', 0)
++        try:
++            retry_timeout =3D int(self.fields.get('retry-timeout', 0))
++        except ValueError:
++            retry_timeout =3D 0
+         user_alerts =3D alerts.get(username, {})       =20
+=20
+         dup_event =3D False
--=20
1.6.0.4


--Dxnq1zWXvFF0Q93v--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6rQsez7wYkguGr%2BAMLr6LWOVTxk>