Subject | Trusted authentication |
---|---|
Author | Alex Peshkov |
Post date | 2006-02-08T18:44:28Z |
A lot of SQL servers (starting with MS SQL) support windows trusted
authentication. I.e. user, who has already attached to windows server,
can use already existing credentials to attach to SQL server. People
want this feature in firebird too (this job was done up to the request
of Paul Beach). I have implemented experimental trusted authentication
on a code base of firebird2 in a private tree.
The main problem I've got was the iterative nature of trusted
authentication (not mentioning crazy MS API). Server, after receiving
authentication request, may ask 'additional question' to the client, and
delivery of it to the client and an answer to it to the server, is
user's (in this case my) responsibility. To perform this task one need
to implement additional packets' exchange between server and client.
Trusted authentication is completely network server thing - it has
nothing to do with embedded access. Moreover, any authentication in
embedded case is generally useless - it's very easy to build embedded
library without any authentication at all.
Taking into account all said, it seems reasonable to locate most of
related stuff in remote subsystem - interface.cpp for client and
server.cpp for server. Name of authenticated used is passed later to the
engine using special DPB tag. This makes absolutely no problems in fb2
monolyth, but I've initially worried about this from vulcan POV - it
means that any user can send SYSDBA login in such tag. But as soon as
any authentication is generally useless for embedded access, this is not
a real problem.
Current case is as follows (I want to specially mention that the fact
that it is written now in this way is not a reason to follow it in the
further discussion - just a way to start it).
Fbclient detects that it has no login/password in DPB. Any remote server
will currently disable user's login in this case. Therefore such state
of DPB is a reason to try trusted authentication. Client creates
authentication object (AuthSspi) and gets data from it to send to the
server. That data is added to the DPB (I've added isc_dpb_trusted_auth
tag). Server receives such DPB and the first thing it does when finds
isc_dpb_trusted_auth - removes it from dpb and sends to server's
AuthSspi object to validate credentials. At this moment server needs to
send some data to the client and get an answer to this question. To
implement such data exchange I had to add new packet type
(op_trusted_auth) with single field - authentication data. Here I want
to emphasize that nobody except windows API needs to know the format of
this bytes - we just transform it over the wire. Server sends a packet
to the client and waits for an answer from it. In case that everything
is OK server accepts clients credentials from the answer (there may be
more than 1 iteration) and knows the windows login name of the remote
user. It adds isc_dpb_trusted_auth tag to the dpb and now it contains
remote user's name. I had to modify engine a little to learn SCL_init
accept user's name from isc_dpb_trusted_auth tag without any validation
in the security database. And now I can:
..\bin> isql.exe ts/3055:pes
Database: ts/3055:pes
SQL> select current_user from rdb$database;
USER
===============================
DOM\pes
As a good results of current approach I'd like to mention:
1. It doesn't break remote protocol in any way - exchange with packets
of new format begin in that and only that case, when both client and
server understand what is trusted authentication.
2. It doesn't depend upon internals of authentication objects. Moreover,
it's easy to have trusted authentication of almost any kind, using
virtual authentication object - i.e. to have authentication plugins.
3. I've tried it with w2k3 server and various clients (starting from
w98), and I had no problems. I use NTLM credentials, and therefore I
suppose no problems for older servers, including NT4.
4. I don't see problems with this approach in the future firebird 3.
What main problem I see - if we decide to have plugins for trusted
authentication (now everything is inside client/server code, which is OK
for experimental version), we will have 2 places in firebird for
authentication plugins. One in fb_authenticate_user() and another in
remote susbsystem. That is not beautiful solution, but currently I don't
see a way to avoid this. Starting additional packets exchange from
fb_authenticate_user() through y-valve is too heavy-waited.
Related problem - we will have to have plugins not only at server, but
also at client side. I dislike very much any configuration files in the
client. It seems that a good solution will be to make server during
first handshake send to the client known methods of trusted
authentication - i.e. list of plugins (names of dynamic libraries to
try). When client wants to try trusted authentication, it tries plugins
from the list, and uses the first successful. In this way we can avoid
any configuration at the client. But this does require protocol version
change - which is anyway supposed for fb3.
Certainly, it is necessary to develop plugins' interface and detailed
format of message exchange before starting any programming in this
direction.
Alex.
authentication. I.e. user, who has already attached to windows server,
can use already existing credentials to attach to SQL server. People
want this feature in firebird too (this job was done up to the request
of Paul Beach). I have implemented experimental trusted authentication
on a code base of firebird2 in a private tree.
The main problem I've got was the iterative nature of trusted
authentication (not mentioning crazy MS API). Server, after receiving
authentication request, may ask 'additional question' to the client, and
delivery of it to the client and an answer to it to the server, is
user's (in this case my) responsibility. To perform this task one need
to implement additional packets' exchange between server and client.
Trusted authentication is completely network server thing - it has
nothing to do with embedded access. Moreover, any authentication in
embedded case is generally useless - it's very easy to build embedded
library without any authentication at all.
Taking into account all said, it seems reasonable to locate most of
related stuff in remote subsystem - interface.cpp for client and
server.cpp for server. Name of authenticated used is passed later to the
engine using special DPB tag. This makes absolutely no problems in fb2
monolyth, but I've initially worried about this from vulcan POV - it
means that any user can send SYSDBA login in such tag. But as soon as
any authentication is generally useless for embedded access, this is not
a real problem.
Current case is as follows (I want to specially mention that the fact
that it is written now in this way is not a reason to follow it in the
further discussion - just a way to start it).
Fbclient detects that it has no login/password in DPB. Any remote server
will currently disable user's login in this case. Therefore such state
of DPB is a reason to try trusted authentication. Client creates
authentication object (AuthSspi) and gets data from it to send to the
server. That data is added to the DPB (I've added isc_dpb_trusted_auth
tag). Server receives such DPB and the first thing it does when finds
isc_dpb_trusted_auth - removes it from dpb and sends to server's
AuthSspi object to validate credentials. At this moment server needs to
send some data to the client and get an answer to this question. To
implement such data exchange I had to add new packet type
(op_trusted_auth) with single field - authentication data. Here I want
to emphasize that nobody except windows API needs to know the format of
this bytes - we just transform it over the wire. Server sends a packet
to the client and waits for an answer from it. In case that everything
is OK server accepts clients credentials from the answer (there may be
more than 1 iteration) and knows the windows login name of the remote
user. It adds isc_dpb_trusted_auth tag to the dpb and now it contains
remote user's name. I had to modify engine a little to learn SCL_init
accept user's name from isc_dpb_trusted_auth tag without any validation
in the security database. And now I can:
..\bin> isql.exe ts/3055:pes
Database: ts/3055:pes
SQL> select current_user from rdb$database;
USER
===============================
DOM\pes
As a good results of current approach I'd like to mention:
1. It doesn't break remote protocol in any way - exchange with packets
of new format begin in that and only that case, when both client and
server understand what is trusted authentication.
2. It doesn't depend upon internals of authentication objects. Moreover,
it's easy to have trusted authentication of almost any kind, using
virtual authentication object - i.e. to have authentication plugins.
3. I've tried it with w2k3 server and various clients (starting from
w98), and I had no problems. I use NTLM credentials, and therefore I
suppose no problems for older servers, including NT4.
4. I don't see problems with this approach in the future firebird 3.
What main problem I see - if we decide to have plugins for trusted
authentication (now everything is inside client/server code, which is OK
for experimental version), we will have 2 places in firebird for
authentication plugins. One in fb_authenticate_user() and another in
remote susbsystem. That is not beautiful solution, but currently I don't
see a way to avoid this. Starting additional packets exchange from
fb_authenticate_user() through y-valve is too heavy-waited.
Related problem - we will have to have plugins not only at server, but
also at client side. I dislike very much any configuration files in the
client. It seems that a good solution will be to make server during
first handshake send to the client known methods of trusted
authentication - i.e. list of plugins (names of dynamic libraries to
try). When client wants to try trusted authentication, it tries plugins
from the list, and uses the first successful. In this way we can avoid
any configuration at the client. But this does require protocol version
change - which is anyway supposed for fb3.
Certainly, it is necessary to develop plugins' interface and detailed
format of message exchange before starting any programming in this
direction.
Alex.