How to Access NDS from HTML or ASP, Part 6
Articles and Tips: article
01 Sep 2001
This article, the last in our series, discusses how to track down possible problems, and the security concerns of an ASP application which accesses NDS. For Part 5 of this series, see http://support.novell.com/techcenter/articles/ana20010806.html.
directory services, NDS eDirectory, HTML, Active Server Pages (ASP), ActiveX, NWDir
familiarity with NDS
NetWare 4 or 5, Windows 95/98/NT/2000
This article will not cover default security concerns of an ASP application in the Internet world. There is sufficient documentation available on this topic. We will discuss one serious security concern developers have to take into account when writing an ASP application which accesses DS database.
It is in fact a kind of security hole and it is important to know that it appears not only when using Novell NWDir control; it is a kind of general security problem when accessing DS database from an ASP code. What is it?
If you remember we have already touched on it when discussing our first ASP WhoAmI? sample code. Typically, when a remote user connects to the IIS Web server with ASP application, an NT account IUSER_MACHINENAME (where MACHINENAME is the name of the Web server) is used to allow anonymous logons. All scripts and components belonging to the ASP application, including any instantiated NWDir control, run in the security context of this IUSR_MACHINENAME account.
Whenever we want to retrieve the data from the DS database via ASP and NWDir, we have to go through the interface provided by the NetWare client (NW client for NT in case of IIS). This NetWare client handles internally connection tables for all NT accounts on that PC. Each NT account has its own connection table in NW client, and each connection table is handled separately from all other connection tables. This way NetWare client assures that two different NT accounts (with different rights to the NT system) cannot share the same connection table and thus cannot share the same access level to NetWare servers (and to the NDS). The NetWare client for NT is capable to handle multiple connection tables for multiple NT accounts. So far, so good.
The problems comes from the ASP side. Each remote user who accesses ASP application on the Web server is handled by IIS internally under the same NT account - the already mentioned IUSER_MACHINENAME account. This means that all concurrently opened ASP sessions share the only one internal connection table in NetWare client. The security consequences of this fact can be far-reaching.
Imagine for example that user Joe, who is Admin equivalent, starts an ASP application, which accesses DS database. He logs in and works. At this moment another user, Bob from oversee, also starts the same ASP application. He does not need to log and in fact login will fail in his case because his ASP session is being handled under the same NT account as Joe's session. From NW client perspective he is already logged to the NDS as a user Joe, with all Joe's rights to the DS database! So Bob finds out surprisingly that he is granted full access to the DS database. Because Bob is a responsible user, he understands that there is something wrong with the application, so he tries to leave it by pressing the Logout button. And he succeeds. NW client in the background silently clears connection table for this NT account and everything seems to be OK for user Bob. But not for user Joe, which is in the middle of his work. Joe suddenly finds out that he has only [Public] rights to the application, in spite of the fact that he has successfully logged several minutes ago
What chances do we have to avoid this? Basically there are three possible workarounds of this problem:
We can handle the access to the DS database for each remote user internally in ASP application. For example an ASP application can create an internal service connection to the DS database when it is started (Administrator access level). Then each remote user is first examined against his rights to NDS prior his request is processed or refused. Disadvantages: this solution brings a bit more complexity in server side scripting code, it adds an additional overhead, and it may slow down the application response time.
Similarly to previous solution, we can handle the access to the DS database for each remote user using just one special connection, opened when the application starts. This way remote users would not require to be logged into DS, only their ID/password pairs would be verified at their session start. This approach can be used in case all remote users will access the same data in the NDS, with the same access level.
Last, we can resign using NWDir control and use LDAP based AX controls from Novell instead - NWIDir, NWIDirEntries, and NWIDirQuery. Because these controls access DS database by using LDAP protocol, they are totally independent on NetWare client for NT and so do not suffer from this type of security problem. Disadvantages: functionality of these LDAP controls, in comparison with NWDir, has some limitations. Also usage and syntax differs.
Tracking Down Problems
While tracking down the problems in the pure HTML document, which embeds NWDir can be an easy process, tracking down the problems which can appear in an ASP application is sometimes complicated and painful task.
ASP applications, which use Novell NWDir control, are typical client/server applications. Without the understanding of the client/server architecture developer may be puzzled by rather strange errors which can appear in what seems to be an easy and straight forwarding code. Next, mixing together the client side, the server side and remote scripting can be really confusing, especially for those developers who are just starting with this technology. And finally, programming to the DS environment can bring a lot of problems to the programmer who does not have deep understanding of DS processes and structures even without any HTML or ASP scripting!
The first important thing to determine, when the problem appears, is -where the error is occurring - is it on the client side, on the server side, during remote scripting, or perhaps is it a typical DS error?
Typos or wrong syntax used in ASP code are perhaps the most common errors. The information we get back from the ASP server in this situation is usually clear and points straight to the source of the problem, so that we can quickly fix it. Below is an example of error returned by ASP server in case wrong syntax (combined with typo) was found in the ASP code:
Error returned by ASP server in case wrong syntax (combined with typo) was found in the ASP code.
Rather worse is the situation with errors or typos in client scripting code. Imagine for illustration that we have made an error when typing valid path for remote scripting library in the client scripting code (<SCRIPT> block in browser.asp file in our last ASP sample code). The valid code line here is:
But we have mistakenly used non-existing directory path:
When we start the ASP application from IE (with default IE browser Internet Options), all we find out is that the application does not work as expected. Perhaps we are attentive enough, so we notice little warning in the left bottom corner of our IE Window:
Error on page.
This warning obviously indicates an error on our downloaded page. Unfortunately it quickly disappears with the first move of mouse after the document is displayed, so it is quite hard to catch it and notice it. It is replaced by much more neutral notice:
From these indicators above it is really hard to guess where our problem lies. Fortunately IE browser can be set up to display more talkative warning messages. It can be done in menu Tools->Internet Options->Advanced and the item is "Display a notification about every script error". So after setting this option and reloading our document we get the following message window:
It is followed immediately by another warning message:
Another warning message.
Finally we have got indices that on lines 97 and 166 of our code is something wrong. Looking forward to a quick fix we open our source file browser.asp - but strange thing - line 97 does not seem to be wrong, and line 166 does not even exist in our source file! What is that?
Well, what happens here is that we quite mistakenly open ASP source code, which is on the ASP server. But the IE browser counts lines of the document it has downloaded, because this is the only document it knows and can see. And because this HTML document was generated by ASP engine, lines of this generated document do not necessarily need to fit with original lines of ASP sample code. In our case several tenths lines of "code" has been added by ASP engine when available DS trees names were retrieved and sent to the combo1 combobox with the following code:
<% For each entry in NWSess1.TreeNames %> Combo1.addItem "<% =entry.FullName %>" <% Next %>
Also all source code lines with <%%> delimiters has not been sent to the browser, they belong to the ASP and so they has been processed on the server.
Perhaps the most problematic bugs to find and fix are those, which are caused by not properly handled errors on ASP server side. Typically, a not captured DS error can bubble out on the client side into this following rather strange looking error message:
Remote scripting error.
This is completely perplexing message. It looks like we did something wrong in our remote scripting code. You will see in a moment, that it is not exactly what happens. To find out more about the problem behind, we have to investigate in our client scripting code call object co returned by RSExecute() method, for example by sending its content into msgbox window:
set co= RSExecute("browser1.asp","ListContainer",context) If co.status<>0 Then msgbox("CALLBACK" & CHR(13) & CHR(13) & "status = " & co.status & CHR(13) & CHR(13) & "message = " & co.message & CHR(13) & CHR(13) & "context = " & co.context & CHR(13) & CHR(13) & "data = " & co.data & CHR(13) & CHR(13) & "return_value = " & co.return_value)
What we get now is much more descriptive, and although not very well arranged, it points to the source of problem:
Please notice the data property of this co object. It holds the error message, generated by ASP server, and the message is in HTML syntax. We can use this nice feature in our own scripting code, and send this data directly into new HTML browser window. In fact it is exactly what we did in our sample code for ASP browser:
set co= RSExecute("browser1.asp","ListContainer",context) If co.status<>0 Then set msgWindow=window.open("","","Height=400 width=400 left=300 top=300 titlebar=no toolbar=no menubar=no") msgWindow.document.write co.data
The output looks like this:
Now we know that we have encountered a NW client API error 34948 (0x8884) on line 37 in the file browser1.asp. This error stands for RESOLVE_SVC_FAILED, and in fact means that we have passed wrong (non-existing) DS tree name to the NWDir control.
In case we catch this error on the server side in its early stage, we can process it and send it back to the client, for example in the form of the following nice-looking message:
I would like to finish this article with several recommendations how to code and debug ASP applications accessing DS database:
You should always try your proposed code, which uses NWDir and manipulates NDS, first locally, in a pure Visual Basic application. This way you can avoid later any unpredictable and strange errors, which may bubble out from DS environment.
Write the important parts of your code first as a client scripting code and test it as a local HTML application.
Try to separate logic of your application into more distinctive and simple code files and test functionality of each of them separately. You can always merge them later after you have tested the functionality, but tracking down the problem in one highly complicated ASP code file, which combines client scripting with server scripting and remote scripting, can be very difficult, if not sometimes impossible.
When testing and debugging ASP application, don't worry to use frequently auxiliary control outputs whenever you need it, either to the log file on the server or simply by sending them to the client browser, using Response.Write() method.
To avoid any incidental communication problems caused by third parties on your network, always try and debug your ASP application first directly on the ASP server. This is perfectly possible. Simply start your IE browser on the ASP server where your ASP application is running.
In case you are not sure what data is exchanged between server and the client, use protocol analyzer to capture packets and find out what is sent as a request from the client side or what is received as a response from the server side.
* Originally published in Novell AppNotes
The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.