BSP Trouble Shooting: HTTP Logging
Sometimes it’s practical to have a specific BSP application run anonymously. This is typically done with status-like applications, which a large group of people needs to access, and that contain no sensitive information. However, the Web AS does not support the concept of anonymous users. The trick is to configure a username and password for the BSP application in question. The Web AS will then use this information and not require any authentication from the user.
This is quickly done with transaction SICF.
With these settings, anybody can use this bcm00/* application without authorization.
WARNING IN BIG LETTERS: If you do this type of configuration, only do it on very specific leaf nodes. Do not do it on a higher-level node. This will result in the total sub-tree running under the defined user.
Confusion Warning: For security reasons, defined user authentication data is not transported to other systems. It has to be done individually for each system. It’s better to do it many times, rather than opening massive holes on the Web server by accident.
So what is the problem? Usually it works and everyone is happy. However, regularly, we get a problem description that the following popup appears:
We can see that the page is loaded, but then suddenly a popup appears asking us for a username and password. Why?
The reason is that although this BSP application is running as an anonymous user, it’s using/referring to other resources that are not anonymous. Remember, the authentication data was only configured for /sap/bc/bsp/sap/bcm00/*. So if any other URL is referenced, the server will ask for authentication information.
Now the problem is to find the URL (HTTP request) that triggers the authentication request.
Wouldn’t it be great if we could get a list of all URLs that are accessed on the Web AS? Then we can see the HTTP load on the server, and determine traffic that doesn’t fit our security profile (denial of service attacks, sniffing, etc.). Also, for the above problem, we would have a list of all URLs requested.
Web AS supports HTTP logging. Not only is the Common Log Format (CLF) supported, but also a large number of additional information can be logged. All of this is part of the ICM infrastructure. As usual, please read the fine documentation for the gory details!
HTTP logging is configured using the parameter icm/HTTP/logging_ in the profile. The “I” part is just a number sequence to support more than one logging criteria, often limiting logging to specific sub-trees of the server.
An example of such a configuration is:
icm/HTTP/logging_0 = PREFIX=/, LOGFILE=dev_http_access_log, SWITCHTF=day, FILEWRAP=on
If no log format is specified, the CLF string of ‘%h %l %u %t “%r” %s %b’ is used. This has the following meaning:
|%h||IP address of the remote host (the client, such as the browser)|
|%l||Specifies the remote logname. This name is the result of an IDENT query to the client. This only works if the identity check is active there.|
|%u||User name of 401 authentication.|
|%t||Time specification in CLF format: [15/Dec/2000:16:18:35 +0100]|
|%r||First row of an HTTP request: such as GET /bc/ping HTTP/1.0|
|%s||OK code of the response.|
|%b||Length of the response in bytes.|
So by using the CLF as a string for HTTP logging, we can get a complete list of all URLs accessed on the server, and other interesting information on these requests. (One interesting option to look at is %L = the duration of a request in milliseconds.)
Recommended: HTTP logging is not active by default. We highly recommend activating the HTTP logging feature and checking these logs at a regular interval. This is not the big brother mentality, but reality dictates that security for Web servers is critical. And HTTP logging should be part of any Web server security!
The HTTPlog files are stored on disk for each application server in the same directory where all other dev_* files are written. However, for normal access, ICM provides a transaction to display the current log. Use transaction SMICM, menu Go To –> HTTP Log –> Display.
A small extract of the HTTP log for this early morning shows some guy working at 05:45!
10.17.117.164 - - [15/Sep/2003:05:45:08 +0200] "GET /sap/bc/bsp/sap/bcm00/default.htm HTTP/1.1" 302 25 10.17.117.164 - - [15/Sep/2003:05:45:08 +0200] "GET /sap(bD1kZSZjPTAwMA==)/bc/bsp/sap/bcm00/default.htm HTTP/1.1" 302 0 10.17.117.164 - - [15/Sep/2003:05:45:08 +0200] "GET /sap(bD1kZSZjPTAwMA==)/bc/bsp/sap/bcm00/default.htm HTTP/1.1" 200 279 10.17.117.164 - - [15/Sep/2003:05:45:08 +0200] "GET /sap(bD1kZSZjPTAwMA==)/bc/bsp/sap/it00/father_son.jpg HTTP/1.1" 401 41
With HTTP logging active, we now have all the pieces of information needed to solve our problem above.
Let’s look at the log in slightly more detail, which in this case means a larger font, and only those bits and pieces that are relevant.
|IP Address||First Line of HTTP Request||RC||SIZE|
The BSP runtime answers the first HTTP request with return code = 302. This is a redirect statement giving a new URL that has been mangled (the hex stuff in the middle of the URL). See a previous Web log on BSP URL Mangling!
The second HTTP request from the browser is also answered with a redirect (rc = 302). However, in this case the URL is not changed and it looks funny! This is actually caused by the way that the SE80 starts BSP programs for testing. All programs (only from SE80) are started with a session command of “open”. The BSP runtime adds the second redirect to close any previous sessions and remove the session cookies, and then starts the application over again.
The third HTTP request is answered with OK (rc = 200). We also see a length of 279 bytes, which reflects the HTML sent to the browser.
The fourth HTTP request is answered with Unauthorized (rc = 401). And it’s this 401 return code that triggers the popup for username and password in the browser. (You can verify this easily by stopping all activity at the browser the moment you see the popup, then checking the last URL.)
And now for the magic question: why does the server require authentication for the fourth HTTP request? We look at the request and see that this image is actually loaded from another BSP application: …/sap/it00/father_son.jpg. Keep in mind that the logon data we configured before was only for the BSP application “bcm00”, and all pages of this application. This image is loaded from another branchof the ICF, where no default logon information is stored.
There are two possible solutions to this problem. Either add logon information for the it00 node also (which opens up another part of the ICF tree for anonymous access!), or move this image into the bcm00 application and slightly change the HTML coding.
This problem is typically caused by relative URLs using parent notation (“../”), for example: “../it00/father_son.jpg”, or by absolute URLs that point into another part of the ICF tree. (Note that the concept of relative URLs does not exist for HTTP requests. This is just a feature of the browser. Before the next HTTP request is sent from the browser, the relative URL is always changed to an absolute URL relative to the current URL being displayed.)
In summary: in all cases of unexpected popup dialogs requesting authentication data, look for an HTTP return code of 401! (Security aspect: a series of rc = 401 in the HTTP log is always an indication that somebody has “forgotten” their passwords. For each new attempt to log on, the server returns 401 again.)
Sidebar: HTTP Return Codes
There are a large number of predefined HTTP return codes. However, in practice only a few are actively used, and these can very quickly be memorized (recommended!):
|200||OK The request succeeded, and a valid response is returned for display.|
|302||Moved Temporarily This is effectively a redirect triggered from the server, requesting that the browser replace the current requested URL with a new URL.|
|401||Unauthorized This code is usually seen on the very first incoming request. It tells the browser that the server requires a username and password. For this, the browser will use a popup to ask for the information.|
|500||Internal Server Error The server encountered an unexpected condition, which prevented it from fulfilling the request. This is typically the return code for all types of problems. Usually, the error text gives a good description of what went wrong.|
ICM Configuration, specifically the entries on icm/HTTP/*.