Page 1 of 1

Preventing automatic reconnection

Posted: Tue 10 Feb 2009 15:07
by mstaszew
When a session is killed, times out, or otherwise becomes disconnected it seems that executing a query that is attached to it reconnects the session. Is there a way to prevent this behavior? When a session is disconnected then we would like for the user to explicitly issue the reconnection for security reasons.

Thanks,
Michael

Posted: Wed 11 Feb 2009 12:44
by Plash
You can disable the reconnect in the following way:
set the LocalFailover option of TOraSession to True;
write the following handler for the OnConnectionLost event:

Code: Select all

procedure TForm1.OraSession1ConnectionLost(Sender: TObject;
  Component: TComponent; ConnLostCause: TConnLostCause;
  var RetryMode: TRetryMode);
begin
  RetryMode := rmRaise;
end;
You need to add the MemData unit to 'uses' for this event.

Posted: Wed 11 Feb 2009 14:15
by mstaszew
Thanks, I'll give that a shot. I read about that event handler and was under the assumption that it wouldn't fire under all circumstances judging from other posts on the forum. Will this event fire under any circumstance? Even if we have open grids with unposted or uncommitted data? Prepared queries, etc.

Thanks,
Michael

Posted: Thu 12 Feb 2009 11:41
by Plash
If the event does not fire, the reconnect will not occur. If event fires, the reconnect depends on value of the RetryMode parameter. So if you set RetryMode to rmRaise, the reconnect will never occur.

Posted: Thu 12 Feb 2009 15:34
by mstaszew
This is not working. Maybe I'm doing something wrong, but I have a simple sample app that demonstrates the problem that I can send. I'll explain is in detail here.

I have a TOraSession and a TSmartQuery on a form. Both objects have default property values set except for TOraSession which has Options.LocalFailover set to True. I have implemented an OnConnectionLost event handler for the TOraSession which sets RetryMode to rmRaise.

I have one button on the form to connect the TOraSession.

I have another button on the form that executes the TSmartQuery which has the SQL.Text set to...

Code: Select all

SELECT COUNT(*) obj_count FROM user_objects
After successful execution I show a message that displays the value of obj_count.

Executing the sample app I do the following... click Connect (session is connected), click Execute (query is executed and obj_count is displayed), load a utility like SQLPlus, Toad, etc. and kill the session that was created to simulate a lost session. Similarly this could have been done with a profile that terminates the session after inactivity or by pulling the network cable on the PC to simulate a network issue. Now, if I click Execute again I get an "ORA-03113 - End of file communication channel" error which is expected. I click Execute again and the session is reconnected. I have placed a breakpoint in my OnConnectionLost handler and it is getting called and RetryMode is being set to rmRaise.

I then tried the following... I modified TCustomDAConnection.DoError in DBAccess.pas so that Reconnect and Reexceute were both set to False so that reconnect should not happen regardless of the value of RetryMode in my OnConnectionLost handler. This did not work either as you would expect since the setting of RetryMode to rmRaise did not work above.

It seems that the query is ensuring a connection before it executes. This is a security vulnerability for us. If a user of our product leaves their workstation and the session has been disconnected then it is not in our best interest to allow someone else to come by and use the tool and have disconnected sessions reconnect without asking for login credentials. Ideally the user should ensure that their workstations are properly locked down, but with government agencies, banking institutions, and other customers that have tight security policies in place it is such that we should not allow a reconnect to occur. We want the user to manually reconnect by supplying the password again. Subsequent execution attempts against a disconnected session should continually raise an exception and the user should be required to use our login window to reconnect it.

Edit:
I should also add that you noted if the event doesn't fire then a reconnect will not occur, but this is not the case. When I place a breakpoint in my OnConnectionLost event handler I get to the breakpoint once. Just after my ORA-03113 error. When I click Execute again and the session is reconnected it never stops on the breakpoint. In this case the event handler was not called and the session was reconnected.

I hope that I have explained the problem well.

I can send a sample app if you'd like.

Any ideas?

Thanks,
Michael

Posted: Thu 12 Feb 2009 15:48
by Plash
TOraSession component connects automatically when a query is executed.

You can add a handler for the BeforeConnect event, and check whether it is allowed to connect or show your login dialog:

Code: Select all

procedure TForm1.OraSession1BeforeConnect(Sender: TObject);
begin
  if not MyLoginDialog.Execute then
    Abort;
end;

Posted: Thu 12 Feb 2009 15:56
by mstaszew
That's what I was afraid of. That's the utmost simplistic approach to it in a simple application and unfortunately we have much more complex application than just a session on a form. We have an entire connection object data structure as well as numerous units that maintain our connection and related data. The architecture is such that it doesn't support just switching over to using the OnBeforeConnect. The application supplies a connection screen where the user supplies the login credentials before we set TOraSession.Connected to True. We have several hacks in place in CRAccess, DBAccess, and maybe another unit or two to achieve the desired results, but it gets messy and makes upgrading more difficult as we need to merge these changes in.

If you are part of the dev team I'd like to suggest a possible enhancement to introduce a property or option that prevents automatic connection (and reconnection) of the TOraSession. This would make it easier to develop secure applications using ODAC.

Thanks,
Michael

Posted: Tue 17 Feb 2009 12:27
by Plash
It is easy to use the BeforeConnect event to prevent automatic connection. You don't need to show the login dialog from the handler of this event. You can just raise an exception from this event. This way can be used even in a complex application.
For example, add variable

Code: Select all

  AllowConnect: boolean;
Before your application connects this variable is True. After the connect set it to False. Use the following code for the BeforeConnect event:

Code: Select all

procedure TForm1.OraSession1BeforeConnect(Sender: TObject);
begin
  if not AllowConnect then
    raise Exception.Create('Connect is not opened');
    //Abort;
end;