Summary: 
I have a fast-cgi application and am running into an issue whereby inconsistent 
error codes (404/403) are returned by the webserver.  The issue seems to be  
with apr/file_io/unix/filepath.c and mappers/mod_alias.c when using long urls 
which approach the filesystem MAXPATHLEN (1024).  Specifically as the URI 
length  starts approaching this limit, 404 errors are returned and then as it 
exceeds the limit, 403 is returned. 



Version: 
The issue does not seem to be version specific although I was using httpd 
2.2.21.  



Details: 
My configuration (relevant parts) are as follows 

# ================================================= 
# Modules 
# ================================================= 
LoadModule authn_file_module modules/mod_authn_file.so 
LoadModule authn_dbm_module modules/mod_authn_dbm.so 
LoadModule authn_anon_module modules/mod_authn_anon.so 
LoadModule authn_default_module modules/mod_authn_default.so 
LoadModule authz_host_module modules/mod_authz_host.so 
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so 
LoadModule authz_user_module modules/mod_authz_user.so 
LoadModule authz_dbm_module modules/mod_authz_dbm.so 
LoadModule authz_owner_module modules/mod_authz_owner.so 
LoadModule authz_default_module modules/mod_authz_default.so 
LoadModule auth_basic_module modules/mod_auth_basic.so 
LoadModule auth_digest_module modules/mod_auth_digest.so 

LoadModule ssl_module modules/mod_ssl.so 
LoadModule log_config_module modules/mod_log_config.so 
LoadModule authz_host_module modules/mod_authz_host.so 
LoadModule setenvif_module modules/mod_setenvif.so 
LoadModule alias_module modules/mod_alias.so 
LoadModule mime_module modules/mod_mime.so 
LoadModule dir_module modules/mod_dir.so 
LoadModule rewrite_module modules/mod_rewrite.so 
LoadModule webkit_module modules/mod_webkit.so 
LoadModule deflate_module modules/mod_deflate.so 
LoadModule auth_kerb_module modules/mod_auth_kerb.so 
LoadModule fastcgi_module modules/mod_fastcgi.so 

[snip] 
... 
<IfModule fastcgi_module> 
    FastCgiExternalServer /usr/sbin/myapp_d -idle-timeout 4294967296 -socket 
/var/run/myapp_d.sock 
    Alias /myapp_api /usr/sbin/myapp_d 
</IfModule> 

<Location /myapp_api> 
    KrbMethodLsassd On 
    AuthType Kerberos 
    Require valid-user 
    SetHandler fastcgi-script 
    Options +ExecCGI 
    Allow from all 
</Location> 

<VirtualHost _default_:8888> 
    SSLEngine on 
    SSLProxyEngine on 
    DocumentRoot "/usr/local/www/ui" 
    LimitRequestFields 150 
    ErrorLog /var/log/apache2/webui_httpd_error.log 
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" 
combined 
    CustomLog /var/log/apache2/webui_httpd_access.log combined 

    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css 
text/javascript application/javascript application/x-javascript 
    BrowserMatch ^Mozilla/4 gzip-only-text/html 
    BrowserMatch ^Mozilla/4\.0[678] no-gzip 
    BrowserMatch \bMSIE !no-gzip !gzip-only-text/html 

    <IfModule rewrite_module> 
        RewriteEngine On 
    </IfModule> 

</VirtualHost> 

I instrumented modules and identified the issue as arising inside 
file.c:apr_file_path_merge()  through mod_alias.c:try_alias_list().  
Specifically, at the following 

static char *try_alias_list(request_rec *r, apr_array_header_t *aliases, 
                            int doesc, int *status) 
{  
  ... 
            /* XXX This is as SLOW as can be, next step, we optimize 
             * and merge to whatever part of the found path was already 
             * canonicalized.  After I finish eliminating os canonical. 
             * Better fail test for ap_server_root_relative needed here. 
             */ 
            if (!doesc) { 
                found = ap_server_root_relative(r->pool, found); 
  } 
  ... 
} 
This call to ap_server_root_relative() tries to create 'found'  as a 
subdirectory of the server root (/usr/sbin/apache2). 

ap_server_root_relative() in turn calls apr_filepath_merge().   The latter does 
the following 

{ 
... 
    rootlen = strlen(rootpath); 
    maxlen = rootlen + strlen(addpath) + 4; /* 4 for slashes at start, after 
                                             * root, and at end, plus trailing 
                                             * null */ 
    if (maxlen > APR_PATH_MAX) { 
        return APR_ENAMETOOLONG; 
    } 
... 
} 

This check IMHO is incorrect since it assumes that the merged path will be a 
combination of rootpath and addpath.  And so even when it would have been 
possible for the merged path to be less than APR_PATH_MAX, an ENAMETOOLONG 
error is returned from here, and mod_alias ends up assigning NULL to 'found'.  
Is there also another issue here in that the aliasing fails  but mod_alias does 
not return an error?   Eventually,  after mod_fastcgi  has tried to 
unsuccessfully handle this request,  a 404 error is returned to the client by 
mod_fastcgi: 
[Fri Nov 11 15:19:56 2011] [error] [client 10.238.112.119] (2)No such file or 
directory: FastCGI: stat() of "/usr/local/www/ui/myapp_api" failed 

In contrast when the requested URI is truly greater than PATH_MAX, this is 
caught in core.c:ap_core_translate() and returned as a 403 error: 
[Fri Nov 11 15:19:56 2011] [error] [client 10.238.112.119] (63)File name too 
long: Cannot map PUT /myapp_api/testmyapp_tc_01_myapp_create_4/NNNNNNN[more Ns 
follow...not shown]? HTTP/1.1 to file 

I have enclosed a proposed fix for apr/file_io/unix/filepath.c and look forward 
to your valuable input. 


Example input: 

http://10.45.65.34:8888/myapp_api/testmyapp_tc_01_myapp_create_4/NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
 
149d148
< 
151,160c150,152
<     if (addpath[0] == '/') {
< 	maxlen = strlen(addpath) + 1;
<     } else {
< 	maxlen = rootlen + strlen(addpath) + 1;
<     }
<     
<     /*
<      * a prelim sanity check to ensure that we will not allow impossible paths
<      * through
<      */ 
---
>     maxlen = rootlen + strlen(addpath) + 4; /* 4 for slashes at start, after
>                                              * root, and at end, plus trailing
>                                              * null */
164,167d155
<     
<     maxlen += 3; /* 3 for *max possible* slashes: at start, after
<                   * root, and at end; we will confirm actual length again */;
<                   
283,287d270
< 
<     /* final check for merged path*/
<     if (pathlen > APR_PATH_MAX) {
<         return APR_ENAMETOOLONG;
<     }

Reply via email to