Forum OpenACS Development: Problems with SuppressHttpPort

Collapse
Posted by Raul Rodriguez on

I am having problems suppressing the port on an OACS website.

On a new installation on debian 9 of Naviserver and OACS via the installation scripts (https://openacs.org/xowiki/naviserver-openacs)

  • on router forwarded ports 80,443 to 8070,8073
  • set proxy_mode true
  • SuppressHttpPort 1 in acs-tcl
  • RestrictToSSL *
  • Restarted OACS

First time going to http://example.com from Chrome redirected to https://example.com:8073 instead of https://example.com

I think the problem is in util::join_location

  • tested by commenting 'append result' as shown below
  • restarted server
ad_proc util::join_location {{-proto ""} {-hostname} {-port ""}} {
    Join hostname and port and use IP-literal notation when necessary.
    The function is the inverse function of  util::split_location.
    @return location consisting of hostname and optionally port
    @author Gustaf Neumann
    @see util::split_location
} {
    set result ""
    if {$proto ne ""} {
        append result $proto://
        #                                                                                                                                                                                                                                                          
        # When the specified port is equal to the default port,omit                                                                                                                                                                                               
	# it from the result.                                                                                                                                                                                                                                      
        #                                                                                                                                                                                                                                                          
        if {$port ne "" && $port eq [dict get {http 80 https 443} $proto]} {
            set port ""
        }
    }
    if {[string match *:* $hostname]} {
        append result "\[$hostname\]"
    } else {
	append result $hostname
    }
    if {$port ne ""} {
#        append result :$port                                                                                                                                                                                                                                      
    }
    return $result
}

This time redirect returned the expected https://example.com with no port

Does procedure logic need updating to suppress the port or is there another way?

Thank You

Collapse
Posted by Gustaf Neumann on

The function join_location is the wrong place to address the problem, since one might wish to use the function also for other servers, addressed e.g. via ns_http.

I am still not sure, why this happens in your installation. If I understand correctly, this happens via redirects, which should always go through ad_returnredirect, which calls for resolving util_current_location. In this function, ReverseProxyMode etc. is handled.

Did you only install NaviServer or as well OpenACS? If you installed OpenACS with the default configuration parameters, then you should have OpenACS 5.9.1 installed. Correct?

Collapse
Posted by Raul Rodriguez on

Yes I have OpenACS 5.9.1 installed following said installation.

After running OpenACS installation script I navigated to it via Firefox:

  • I entered the setup information and restarted the server.
  • A screen came up with a list of Applications and Subsites.
  • logged on to it and got a certificate via letscencrypt per README
  • At Main Site Parameters restricted site to ssl via set RestrictToSSL using '*'
  • in acs-tcl set SuppressHttpPort 1
  • Restarted OACS
  • Went to http:example.com from another browser (Chrome) that had never gone to the site.
  • Chrome showed url with port https://example.com:8073

I verified that util_current_location is returning a result with no port as expected.

The port is added at some point later. I think this is happening in rp_filter via security::redirect_to_secure via security::get_secure_location where join_location is called.

rp_filter:

    #                                                                                                         
    # Check, if we are supposed to upgrade insecure requests. This                                            
    # should be after the canonical check to avoid multiple redirects.                                        
    #                                                                                                         
    # ns_set get accepts a default value in 3rd argument only on                                              
    # NaviServer; so perform the check in two steps for AOLserver                                             
    # compatibility.                                                                                          
    set upgrade_insecure_requests_p [ns_set get [ns_conn headers] Upgrade-Insecure-Requests]                 \

    if {$upgrade_insecure_requests_p ne "" &&
        $upgrade_insecure_requests_p
        && [security::https_available_p]
        && ![security::secure_conn_p]
    } {
        security::redirect_to_secure -script_abort=false [ad_return_url -qualified]
        return filter_return
    }
Collapse
Posted by Gustaf Neumann on
Dear Raul, many thanks for the good report!

So, the problem is probably the upgrade to secure, i.e. when connecting via HTTP to a site requiring HTTPS , having SuppressHttpPort set. Can you apply the change [1] to your installation and check whether this helps? If so, i'll do the same change on HEAD and add some test cases.

all the best
-g

[1] http://cvs.openacs.org/browse/OpenACS/openacs-4/packages/acs-tcl/tcl/security-procs.tcl?r1=1.78.2.62&r2=1.78.2.63

Collapse
Posted by Raul Rodriguez on

I applied the patch and works as expected. Going to http://example.com returns https://example.com with no port.

Thank you

Collapse
Posted by Gustaf Neumann on
Great!

I've updated the oacs-5-9 branch, increased version number and re-tagged, such that OpenACS 5.9 users can also do a "upgrade from repository".

In the HEAD branch, i did similar (did some more cleanup, including a small regression test, ...)

all the best
-g

Collapse
Posted by Raul Rodriguez on

Went to https://example.com/admin/.

The "ACS Site-Wide Administration" link has the port, https://example.com:8073/acs-admin/.

Does the logic need to be updated to include a check for SuppressHttpPort?

The link uses util::configured_location

/var/www/my-site/packages/acs-subsite/www/admin/index.tcl:

ad_page_contract {
    @author Bryan Quinn (bquinn@arsdigita.com)
    @author Michael Bryzek (mbryzek@arsdigita.com)

    @creation-date August 15, 2000
    @cvs-id $Id: index.tcl,v 1.19.6.3 2016/09/02 17:33:19 gustafn Exp $
} {
} -properties {
    context:onevalue
    subsite_name:onevalue
    acs_admin_url:onevalue
    instance_name:onevalue
    acs_automated_testing_url:onevalue
    acs_lang_admin_url:onevalue
}

array set this_node [site_node::get -url [ad_conn url]]
set title "Subsite [_ acs-subsite.Administration]: $this_node(instance_name)"

set acs_admin_url [apm_package_url_from_key "acs-admin"]
array set acs_admin_node [site_node::get -url $acs_admin_url]
set acs_admin_name $acs_admin_node(instance_name)
set sw_admin_p [permission::permission_p -party_id [ad_conn user_id] -object_id $acs_admin_node(object_id) -privilege adm\
in]
set full_acs_admin_url [util::configured_location]$acs_admin_url

set convert_subsite_p [expr { [llength [apm::get_package_descendent_options [ad_conn package_key]]] > 0 }]

/var/www/my-site/packages/acs-tcl/tcl/utilities-procs.tcl:

ad_proc -public util::configured_location {} {

    Return the configured location as configured for the current
    network driver. While [util_current_location] honors the virtual
    host information of the host header field,
    util::configured_location returns the main configured location
    (probably the main subsite). This also differs from [ad_url],
    which returns always the same value from the kernel parameter,
    since it returns either the https or http result.

    @return the configured location in the form "proto://hostname?:port?"

    @see ad_url
    @see util_current_location
} {
    set driver_info [util_driver_info]
    return [util::join_location \
		-proto    [dict get $driver_info proto] \
		-hostname [dict get $driver_info hostname] \
		-port     [dict get $driver_info port]]
}

Thank You
Collapse
Posted by Gustaf Neumann on
The fix in [1] should repair this (oacs-5-9 branch). Hopefully, there are not much more such cases lurching around. We don't use the option SuppressHttpPort in our configurations, but nevertheless, as log as OpenACS offers this, it should work.

all the best
-gn

[1] http://cvs.openacs.org/changelog/OpenACS?cs=oacs-5-9%3Agustafn%3A20180914115634

Collapse
Posted by Raul Rodriguez on
That fixed it.

Thank you

Collapse
Posted by Gustaf Neumann on
Great. will do similar on HEAD. -gn