Bug 1451166

Summary: Incorrect "Host" header when connecting through a http proxy
Product: Red Hat Enterprise Linux 7 Reporter: Hao Chang Yu <hyu>
Component: python-rhsmAssignee: Kevin Howell <khowell>
Status: CLOSED ERRATA QA Contact: John Sefler <jsefler>
Severity: high Docs Contact:
Priority: high    
Version: 7.3CC: khowell, redakkan, skallesh
Target Milestone: rcKeywords: Triaged
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: python-rhsm-1.19.7-1 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2017-08-01 19:23:41 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
proxy_in_header
none
server_in_header none

Description Hao Chang Yu 2017-05-16 02:01:17 UTC
Description of problem:
When registering a host to RHSM through a http proxy, python-rhsm/M2Crypt set the wrong "Host" header in the http request.

https://hao-satellite62.usersys.bne.redhat.com:443/rhsm/consumers/7bea7510-9faa-42f6-b97e-6b5706514aa2

# subscription-manager register --org="hao_gss" --activationkey="default_key" --force
POST /rhsm/consumers?owner=hao_gss&activation_keys=default_key HTTP/1.1
Host: 10.64.1.171:3128 <================= This is the IP of the http proxy server
Accept-Encoding: identity
Content-Length: 5980
Accept-Language: en-au
x-subscription-manager-version: 1.17.15-1.el7
x-python-rhsm-version: 1.17.9-1.el7
Accept: application/json
User-Agent: RHSM/1.0 (cmd=subscription-manager)
Content-type: application/json


When using curl, this "Host" header is set to the "subscription.rhsm.redhat.com"

Example:
curl -v -k -u "hyu" --proxy "hyu:password.1.171:3128" https://subscription.rhsm.redhat.com:443/subscription/users/hyu@redhat.com/roles
* About to connect() to proxy 10.64.1.171 port 3128 (#0)
*   Trying 10.64.1.171...
* Connected to 10.64.1.171 (10.64.1.171) port 3128 (#0)
* Establish HTTP proxy tunnel to subscription.rhsm.redhat.com:443
* Proxy auth using Basic with user 'hyu'
* Server auth using Basic with user 'hyu'
> CONNECT subscription.rhsm.redhat.com:443 HTTP/1.1
> Host: subscription.rhsm.redhat.com:443
> Proxy-Authorization: <PROXY CREDENTIAL>
> User-Agent: curl/7.29.0
> Proxy-Connection: Keep-Alive
> 
< HTTP/1.1 200 Connection established
< 
* Proxy replied OK to CONNECT request
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* NSS: client certificate not found (nickname not specified)
* SSL connection using TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
...
* Server auth using Basic with user 'hyu'
> GET /subscription/users/hyu/roles HTTP/1.1
> Authorization: <CREDENTIAL>
> User-Agent: curl/7.29.0
> Host: subscription.rhsm.redhat.com  <========== Curl set the "Host" header to the rhsm hostname.
> Accept: */*
> 
---
* Connection #0 to host 10.64.1.171 left intact


There is a case(attached) that customer proxy is relying on this header to make request and the wrong "Host" header caused the proxy to send the request to itself and get an unexpected response from the proxy.

For example:
https://10.64.1.171:3128/subscription/users/hyu@redhat.com/roles

Expected
https://subscription.rhsm.redhat.com/subscription/users/hyu@redhat.com/roles


Actual results:
Proxy request "Host" header is set to the proxy hostname/IP


Expected results:
"Host" header should set to the RHSM hostname like curl

Comment 2 Hao Chang Yu 2017-05-16 02:11:04 UTC
For python-rhsm-1.17.9-1.el7.x86_64:

Customer can register to rhsm successfully with the following patch.

diff -u  /usr/lib64/python2.7/site-packages/rhsm/connection.py /tmp/connection.py 
--- /usr/lib64/python2.7/site-packages/rhsm/connection.py	2017-05-16 02:07:37.898000000 +0000
+++ /tmp/connection.py	2017-05-16 02:06:47.734000000 +0000
@@ -289,6 +289,13 @@
         else:
             httpslib.HTTPSConnection.endheaders(self)
 
+    def putrequest(self, *args, **kwargs):
+        httpslib.ProxyHTTPSConnection.putrequest(self, *args, **kwargs)
+        for i, header in enumerate(self._buffer):
+            if header.startswith("Host"):
+                del self._buffer[i]
+        self.putheader('Host', "%s:%s" % (self._real_host, self._real_port))
+
     def _get_connect_msg(self):
         """ Return an HTTP CONNECT request to send to the proxy. """
         port = safe_int(self._real_port)

Comment 3 Kevin Howell 2017-05-18 14:20:23 UTC
Note to dev: please verify whether this is still an issue with the following environments:
 - el6 (which uses m2crypto)
 - el7 (7.4 now uses python stdlib)

Note that 7.3 (described in comment 0) used m2crypto.

Depending on what we find, we may need to move this BZ to RHEL6 (where m2crypto is still in use) or clone.

Comment 5 Rehana 2017-06-01 14:29:32 UTC
Reproducing the failure:
=========================

subscription management server: 2.1.1-1
subscription management rules: 5.23
subscription-manager: 1.19.15-1.el7
python-rhsm: 1.19.6-1.el7

Used mitmproxy to verify this bug (configuration details in additional info section ) , set proxy details in the config 

[root@ibm-x3250m3-01 ~]# subscription-manager config --list | grep proxy_
   proxy_hostname = tyan-gt24-09.rhts.eng.bos.redhat.com
   proxy_password = []
   proxy_port = 8080
   proxy_user = []


[root@ibm-x3250m3-01 ~]# subscription-manager register --username=admin --password=**** --org=admin --force
Registering to: F21-candlepin.usersys.redhat.com:8443/candlepin
The system has been registered with ID: fb04d163-0f0c-494f-b714-563c93474323

Attached the screen shot from mitmproxy , where the HOST is replaced by the proxy name "tyan-gt24-09.rhts.eng.bos.redhat.com" ( proxy_in_header.png) 


Verifying with latest subscription-manager :
==========================================
subscription management server: 2.1.1-1
subscription management rules: 5.23
subscription-manager: 1.19.17-1.el7
python-rhsm: 1.19.8-1.el7


[root@dhcp151-206 ~]# subscription-manager register --username=admin --password=**** --org=admin  
Registering to: F21-candlepin.usersys.redhat.com:8443/candlepin
The system has been registered with ID: 8565c39e-96ee-49f4-a345-74e6b87feea8 


Attached the screen shot from mitmproxy , where the HOST is same as the server which is F21-candlepin.usersys.redhat.com  ( server_in_header.png) 

^^ Based on the above observation , moving the bug as verified!!

Additional notes on setting up mitmproxy:
=======================================

1)Install mitmproxy (see http://docs.mitmproxy.org/en/stable/install.html#installation-from-source-on-fedora)
2)Configure mitmproxy via ~/.mitmproxy/mitmproxy.conf (set bind-address to 0.0.0.0); set port if necessary. Config file is just plain key=values.
3)Run `mitmproxy --insecure`
4) Point subscription-manager at the mitmproxy instance (hostname - fedora box; port: 8080 (by default). make sure insecure in set to 1
5) Run some subscription-manager commands (example in the bug), and observe the headers in mitmproxy interface.
    unpatched, Host shows up as the proxy hostname/port
    patched, Host shows up as the server hostname/port

Comment 6 Rehana 2017-06-01 14:30:12 UTC
Created attachment 1284160 [details]
proxy_in_header

Comment 7 Rehana 2017-06-01 14:30:58 UTC
Created attachment 1284162 [details]
server_in_header

Comment 8 Kevin Howell 2017-06-29 18:02:45 UTC
*** Bug 1435331 has been marked as a duplicate of this bug. ***

Comment 9 errata-xmlrpc 2017-08-01 19:23:41 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2017:2083