Back
Home
Up

Undocumented connection path on Win32.

    For years, the same complaint has been known: why is it necessary for the client to give the engine the full path of the database in the same machine (node) where the engine runs? Several people have pointed that it's inconvenient when the db's location is changed. Others argue that this is a low level that the client shouldn't be concerned about. Finally, developers have concerns with the security. Ideally, the physical location of the engine and the databases shouldn't be disclosed to the client. Only an alias should be visible.

While we still reach that point (although some free third party solutions that implement alias managers exists, see the tools section), we aren't there yet with native alias support. One reason is the discussion whether isc4 should be enhanced, ignored and left as it's or deprecated. It was introduced by Borland in IB4 to support Windows releases where an operating system authentication mechanism didn't exist at all. It works as a centralized place for users and passwords, but it introduces problems in itself. Also, there are in-place mechanisms (y-valve) that are candidates for alias resolution, too.

It's incredible that for years, a built-in solution in the engine (that works whenever the server is a NT machine) has been lying in the heart of the code and nobody made it public, less even documented in some help file. And funny as it sounds, the question has been thrown several times. Probably the problem is that this is a Win32 only solution, nothing that you can use on Linux, so the location of a gdb is not truly transparent.

The syntax is very simple. It has the form:

\\server\!share_name!\database.gdb

or the form

server:\!share_name!\database.gdb

It's not a true alias, since you still know the name of the database and of course, the server machine should be known. But it helps if you need to move the db around NT servers, without having to change configuration files or recompiling programs. Here, "server" is the NetBeui name of the NT machine, followed by the pseudo-UNC paths that IB/FB uses. Alternatively, "server" is the TCP/IP name of the NT machine, but followed by backslashes, not the typical slashes the IB's TCP syntax uses. (Really, using slashes or backslashes is not important in a typical full path, since the engine makes the adjustments, but in this case, the syntax to recognize the share demands backslashes.) The difference is that instead of a full path inside the server, a share's name in the server is used, surrounded by exclamation marks. This share points in turn to the full path of the db, so you only have to append the db's name. It has nothing do to with client-side mappings.

How it works: the client library recognizes a UNC-like path and knows it's Netbeui. Otherwise, it recognizes a TCP-like syntax thanks to the colon. Then it connects to the required server with the right network protocol and passes the remnant of the path, stripping the server's name. A routine inside the engine, named "expand_share_name", will look for the backslash followed by the exclamation point, then if a matching "!\" happens, it takes the name inside the two pairs ("\!" and "!\") and will open the registry (RegOpenKeyEx) at

SYSTEM\\CurrentControlSet\\Services\\LanmanServer\\Shares

to extract the data (RegQueryValueEx) in the value <share_name>, that's supposedly the name of a registered share in the server machine. It proceeds to decode the data and gets the "Path" component inside the multi-string data that's the physical path. It loads this path in its argument and returns to the caller that will continue testing to see finally if the db's name is valid and exists.

For example, given a share's name "myshare", the registry key shown above contains a list of values that denote shares. You can find there the implicit ones such as IAS1$ (very bad, get rid of it since it points to the IIS admin dir), the NETLOGON share and "myshare". Reading the data in the value "myshare", the following can be seen:

MaxUses=4294967295.Path=H:\PROY.Permissions=127.Remark=for fb.Type=0..

The dots denote the NULL ASCII value, since this is a multi-string. The engine looks for "path" and gets the string that follows, namely
H:\PROY, then appends the backlash if missing. Hence, the engine uses information in the server itself to decode the full path. This path will prefix the db name when the function expand_share_name returns to the caller.

An advantage is that you don't need to grant permissions on this share. You can deny anyone any right (even if NT prompts if you are sure) and you can go further: you can stop the service responsible for handling requests of NetBeui shares. The engine reads the registry directly, so it doesn't query the network layer. It's a true hack, a commodity to avoid the inclusion of hard coded paths in the client. If you want to change it, just change the share's information, without granting anyone any right on the share. Since the engine reads that registry location each time a connection string should be analyzed, it will get the changed name in the next attachment request. If you disabled some networks services so changing the share is not possible through high level interfaces, you can edit the registry directly and change the path. Beware that the each dot represents a NULL ASCII value in the example shown above, so your path should end with that value. A nicer feature even is that this works:

H:\ibdev\fbbuild\interbase\jrd>isql \\atenea\!myshare!\g
Database: \\atenea\!myshare!\g
SQL> ^Z

but it's not restricted to NetBeui. Indeed, as noted before, you can use TCP syntax:

H:\ibdev\fbbuild\interbase\jrd>isql localhost:\!myshare!\g
Database: localhost:\!myshare!\g
SQL> ^Z

(Remember that there's no restriction to the name of a gdb other than the file name conventions in the platform where the engine resides. In this case, it's simply named "g", although an extension helps the db admin.)

There are a couple of drawbacks: first, this hack is tied to Win32. (Furthermore, I don't have a way to test it on W2k or XP, but Martijn Tonies reported that Win2k honors the same trick.) Second, when I read that internal function expand_share_name(), I found a possible buffer overrun and closed it. Revisiting the code when I wrote this article, I found a registry key handle that wasn't closed if the function gives up prematurely for lack of RAM. (I solved this second glitch in FB at the time I was finishing this article.) Hence, I believe the lack of documentation comes from the untested nature of the facility. No company will (hopefully) release features that haven't been tested thoroughly. (Well, in Lewis Carrol's wonderland, the SW is perfect, but Murphy laws and empiric evidence show that you can only approximate logarithmically to bug-free SW: you put 100 times more effort in trying to isolate and kill the 5 latest bugs than when the first 5 bugs where found and sometimes your efforts backfire, introducing more bugs.)

 

This page was last updated on 2002-02-15 00:36:30