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 Firebird-net-provider@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/firebird-net-provider