Accessing entities using EntityFramework on encrypted database failed
---------------------------------------------------------------------
Key: DNET-832
URL: http://tracker.firebirdsql.org/browse/DNET-832
Project: .NET Data provider
Issue Type: Bug
Affects Versions: 6.0.0.0
Environment: Issue occurred on develoment environment: Windows 10;
.NET 4.7.1; Firebird 3.0.3.32900 (32 Bit); Entity Framework 6.2.0-61023.0;
IBPhoenix Encryption Plugin 1.2.0
Reporter: Michael Wresche
Assignee: Jiri Cincura
Priority: Blocker
At first:
- We have an encrypted Firebird database which will be accessed from our
application by using Entity Framework
- The encryption plugin uses a file-based key so the connection string does
not contain any encryption information.
- Accessing the encrypted database by using FbConnection, FbCommand, etc.
works fine
- If the database is not encrypted and the encryption plugin is not configured
in Firebird, Entity Framework as well as FbConnection works fine
- If we access the encrypted database using Entity Framework, we got the
following exception (Unfortunately in german): Das Objekt des Typs
"FirebirdSql.Data.Client.Managed.Version13.CryptKeyCallbackReponse" kann nicht
in Typ "FirebirdSql.Data.Client.Managed.GenericResponse" umgewandelt werden.
You can find the callstack of the exception at the end of the bug description.
I have debugged the issue with the latest sources on GitHub and was able to
find the root cause (hopefully): The method GdsConnection.ProcessOperation
returned an CryptKeyCallbackResponse which will be casted to GenericResponse in
Version10.GdsDatabase.ReadGenericResponse and this fails.
After some short debugging sessions in order to find out what happened when I
access the encrypted database directly (without Entity Framework), I came to
the following conclusion:
Entity Framework invoked FbProviderServices.GetDbProviderManifestToken() with a
connection which is not yet open. Because of the connection state the requested
server version will be determined by using the FbServerProperties class
(FbProviderServices Line 130). This class uses the FbService to communicate
with the database. The FbService uses the GdsServiceManager and this class
creates an instance of the Version10.GdsDatabase class which is used to
communicate with the database. In my opinion, the instance of GdsDatabase
should be created by using the appropriate factory method. Anyway, it seems
that Version10.GdsDatabase is not able to communicate with encrypted databases.
I came to the conclusion that encryption is only compatible with Version13. I
made the following two changes in order to get working solution:
1. I changed the constructor of GdsServiceManager to create a
Version13.GdsDatabase class.
2. In class Version13.GdsDatabase, I override ReadGenericResponse:
public override GenericResponse ReadGenericResponse()
{
byte[] cryptKey = new byte[2096];
var response = ReadResponse();
while (response is CryptKeyCallbackReponse
cryptResponse)
{
XdrStream.Write(IscCodes.op_crypt_key_callback);
XdrStream.WriteBuffer(cryptKey);
XdrStream.Flush();
response = ReadResponse();
}
return response as GenericResponse;
}
I know that this solution is just a hack but I don't know the architecture of
the source code and I found no helpful source code comments. With the described
changes, I was able to access the database.
I was wondering why no other user has reported a similar behavior.
I do my best to add all required information. If you need further information,
feel free to contact me.
The callstack of the exception:
FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Client.Managed.Version10.GdsDatabase.ReadGenericResponse()
Line 602
at
C:\Users\michael.wresche\source\repos\FirebirdSql.Data.FirebirdClient\Provider\src\FirebirdSql.Data.FirebirdClient\Client\Managed\Version10\GdsDatabase.cs(602)
FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Client.Managed.Version10.GdsServiceManager.Attach(FirebirdSql.Data.Common.ServiceParameterBuffer
spb, string dataSource, int port, string service) Line 73
at
C:\Users\michael.wresche\source\repos\FirebirdSql.Data.FirebirdClient\Provider\src\FirebirdSql.Data.FirebirdClient\Client\Managed\Version10\GdsServiceManager.cs(73)
FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbService.Open()
Line 114
at
C:\Users\michael.wresche\source\repos\FirebirdSql.Data.FirebirdClient\Provider\src\FirebirdSql.Data.FirebirdClient\Services\FbService.cs(114)
FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbService.QueryService(byte[]
items) Line 341
at
C:\Users\michael.wresche\source\repos\FirebirdSql.Data.FirebirdClient\Provider\src\FirebirdSql.Data.FirebirdClient\Services\FbService.cs(341)
FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbService.ProcessQuery(byte[]
items, System.Action<bool, object> queryResponseAction) Line 231
at
C:\Users\michael.wresche\source\repos\FirebirdSql.Data.FirebirdClient\Provider\src\FirebirdSql.Data.FirebirdClient\Services\FbService.cs(231)
FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbService.Query(byte[]
items, System.Action<bool, object> resultAction) Line 200
at
C:\Users\michael.wresche\source\repos\FirebirdSql.Data.FirebirdClient\Provider\src\FirebirdSql.Data.FirebirdClient\Services\FbService.cs(200)
FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbService.Query(byte[]
items) Line 159
at
C:\Users\michael.wresche\source\repos\FirebirdSql.Data.FirebirdClient\Provider\src\FirebirdSql.Data.FirebirdClient\Services\FbService.cs(159)
FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbServerProperties.GetInfo(byte[]
items) Line 90
at
C:\Users\michael.wresche\source\repos\FirebirdSql.Data.FirebirdClient\Provider\src\FirebirdSql.Data.FirebirdClient\Services\FbServerProperties.cs(90)
FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbServerProperties.GetInfo(int
item) Line 85
at
C:\Users\michael.wresche\source\repos\FirebirdSql.Data.FirebirdClient\Provider\src\FirebirdSql.Data.FirebirdClient\Services\FbServerProperties.cs(85)
FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbServerProperties.GetString(int
item) Line 75
at
C:\Users\michael.wresche\source\repos\FirebirdSql.Data.FirebirdClient\Provider\src\FirebirdSql.Data.FirebirdClient\Services\FbServerProperties.cs(75)
FirebirdSql.Data.FirebirdClient.dll!FirebirdSql.Data.Services.FbServerProperties.GetServerVersion()
Line 40
at
C:\Users\michael.wresche\source\repos\FirebirdSql.Data.FirebirdClient\Provider\src\FirebirdSql.Data.FirebirdClient\Services\FbServerProperties.cs(40)
EntityFramework.Firebird.dll!EntityFramework.Firebird.FbProviderServices.GetDbProviderManifestToken(System.Data.Common.DbConnection
connection) Line 130
at
C:\Users\michael.wresche\Source\Repos\FirebirdSql.Data.FirebirdClient\Provider\src\EntityFramework.Firebird\FbProviderServices.cs(130)
EntityFramework.dll!System.Data.Entity.Core.Common.DbProviderServices.GetProviderManifestToken(System.Data.Common.DbConnection
connection)
EntityFramework.dll!System.Data.Entity.Utilities.DbProviderServicesExtensions.GetProviderManifestTokenChecked(System.Data.Entity.Core.Common.DbProviderServices
providerServices, System.Data.Common.DbConnection connection)
mscorlib.dll!System.Collections.Concurrent.ConcurrentDictionary<System.Tuple<System.Type,
string, string>, string>.GetOrAdd(System.Tuple<System.Type, string, string>
key, System.Func<System.Tuple<System.Type, string, string>, string>
valueFactory)
EntityFramework.dll!System.Data.Entity.Utilities.DbConnectionExtensions.GetProviderInfo(System.Data.Common.DbConnection
connection, out System.Data.Entity.Core.Common.DbProviderManifest
providerManifest)
EntityFramework.dll!System.Data.Entity.DbModelBuilder.Build(System.Data.Common.DbConnection
providerConnection)
EntityFramework.dll!System.Data.Entity.Internal.LazyInternalContext.CreateModel(System.Data.Entity.Internal.LazyInternalContext
internalContext)
EntityFramework.dll!System.Data.Entity.Internal.RetryLazy<System.Data.Entity.Internal.LazyInternalContext,
System.Data.Entity.Infrastructure.DbCompiledModel>.GetValue(System.Data.Entity.Internal.LazyInternalContext
input)
EntityFramework.dll!System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
EntityFramework.dll!System.Data.Entity.Internal.InternalContext.Initialize()
EntityFramework.dll!System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(System.Type
entityType)
EntityFramework.dll!System.Data.Entity.Internal.Linq.InternalSet<OTTO.IBA.Entities.DBVersion>.Initialize()
EntityFramework.dll!System.Data.Entity.Internal.Linq.InternalSet<OTTO.IBA.Entities.DBVersion>.AsNoTracking()
EntityFramework.dll!System.Data.Entity.Infrastructure.DbQuery<OTTO.IBA.Entities.DBVersion>.AsNoTracking()
OTTO.IBA.Datenbankzugriff.EntityFramework.dll!OTTO.IBA.Datenbankzugriff.EntityFramework.DAOs.DBVersionDAO.GetAktuelleDBVersion()
Line 45
at
C:\Projekte\Otto_IBA2\Development\Sources\App\Datenbankzugriff\OTTO.IBA.Datenbankzugriff.EntityFramework\DAOs\DBVersionDAO.cs(45)
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://tracker.firebirdsql.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Firebird-net-provider mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/firebird-net-provider