From owner-freebsd-ports-bugs@FreeBSD.ORG Sun Nov 23 20:22:27 2008 Return-Path: Delivered-To: freebsd-ports-bugs@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1AE0A1065675; Sun, 23 Nov 2008 20:22:27 +0000 (UTC) (envelope-from rea-fbsd@codelabs.ru) Received: from 0.mx.codelabs.ru (0.mx.codelabs.ru [144.206.177.45]) by mx1.freebsd.org (Postfix) with ESMTP id 854B48FC16; Sun, 23 Nov 2008 20:22:26 +0000 (UTC) (envelope-from rea-fbsd@codelabs.ru) DomainKey-Signature: a=rsa-sha1; q=dns; c=simple; s=one; d=codelabs.ru; h=Received:Date:From:To:Cc:Subject:Message-ID:References:MIME-Version:Content-Type:Content-Disposition:In-Reply-To:Sender; b=JSSd4OZogD5YA8Q2ncfTzAHrU+0hvB6VVNL1lEn5i9Edp+cga13WdxGNROuVOlNATLMylSfW01lTOn8f5f2BQd0sWmQcLjd75A/xcHbLlg4IXqnr2m6pmtPaTaU/6sxcRQNxtSwAG1E2aOo467FppZ9MmuNpD7fg6DUwsc5F/gI=; Received: from phoenix.codelabs.ru (ppp83-237-105-112.pppoe.mtu-net.ru [83.237.105.112]) by 0.mx.codelabs.ru with esmtpsa (TLSv1:AES256-SHA:256) id 1L4LTM-000HNr-Lb; Sun, 23 Nov 2008 23:22:25 +0300 Date: Sun, 23 Nov 2008 23:22:21 +0300 From: Eygene Ryabinkin To: bug-followup@FreeBSD.org, freebsd-ports-bugs@FreeBSD.org Message-ID: <6rQsez7wYkguGr+AMLr6LWOVTxk@iXA9ZWPrtc2I2BMzBXoToMd7YdQ> References: <20081123184449.6801AF181D@phoenix.codelabs.ru> <200811231850.mANIo09F042711@freefall.freebsd.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Dxnq1zWXvFF0Q93v" Content-Disposition: inline In-Reply-To: <200811231850.mANIo09F042711@freefall.freebsd.org> Sender: rea-fbsd@codelabs.ru Cc: freebsd-security@freebsd.org Subject: Re: ports/129097: [vuxml] print/hplip: document CVE-2008-2940 and CVE-2008-2941 X-BeenThere: freebsd-ports-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Ports bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 23 Nov 2008 20:22:27 -0000 --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 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 --- 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--