public void Identify(string database) { using (var xdrStream = CreateXdrStreamImpl(false)) { try { xdrStream.Write(IscCodes.op_connect); xdrStream.Write(IscCodes.op_attach); xdrStream.Write(IscCodes.CONNECT_VERSION3); xdrStream.Write(IscCodes.GenericAchitectureClient); xdrStream.Write(database); var protocols = ProtocolsSupported.Get(_compression); xdrStream.Write(protocols.Count()); xdrStream.WriteBuffer(UserIdentificationData()); var priority = 0; foreach (var protocol in protocols) { xdrStream.Write(protocol.Version); xdrStream.Write(IscCodes.GenericAchitectureClient); xdrStream.Write(protocol.MinPType); xdrStream.Write(protocol.MaxPType); xdrStream.Write(priority); priority++; } xdrStream.Flush(); var operation = xdrStream.ReadOperation(); if (operation == IscCodes.op_accept || operation == IscCodes.op_cond_accept || operation == IscCodes.op_accept_data) { _protocolVersion = xdrStream.ReadInt32(); _protocolArchitecture = xdrStream.ReadInt32(); _protocolMinimunType = xdrStream.ReadInt32(); if (_protocolVersion < 0) { _protocolVersion = (ushort)(_protocolVersion & IscCodes.FB_PROTOCOL_MASK) | IscCodes.FB_PROTOCOL_FLAG; } if (_compression && !((_protocolMinimunType & IscCodes.pflag_compress) != 0)) { _compression = false; } if (operation == IscCodes.op_cond_accept || operation == IscCodes.op_accept_data) { var data = xdrStream.ReadBuffer(); var acceptPluginName = xdrStream.ReadString(); var isAuthenticated = xdrStream.ReadBoolean(); var keys = xdrStream.ReadString(); if (!isAuthenticated) { switch (acceptPluginName) { case SrpClient.PluginName: _authData = Encoding.ASCII.GetBytes(_srp.ClientProof(NormalizeLogin(_userID), _password, data).ToHexString()); break; case SspiHelper.PluginName: _authData = _sspi.GetClientSecurity(data); break; default: throw new ArgumentOutOfRangeException(nameof(acceptPluginName), $"{nameof(acceptPluginName)}={acceptPluginName}"); } } } } else if (operation == IscCodes.op_response) { var response = (GenericResponse)ProcessOperation(operation, xdrStream); throw response.Exception; } else { try { Disconnect(); } catch { } finally { throw IscException.ForErrorCode(IscCodes.isc_connect_reject); } } } catch (IOException ex) { throw IscException.ForErrorCode(IscCodes.isc_network_error, ex); } finally { // UserIdentificationData might allocate these _srp = null; _sspi?.Dispose(); _sspi = null; } } }
public void Identify(string database) { try { Xdr.Write(IscCodes.op_connect); Xdr.Write(IscCodes.op_attach); Xdr.Write(IscCodes.CONNECT_VERSION3); Xdr.Write(IscCodes.GenericAchitectureClient); Xdr.Write(database); var protocols = ProtocolsSupported.Get(_compression); Xdr.Write(protocols.Count()); #warning These out params are ugly, refactor var userIdentificationData = UserIdentificationData(out var srp, out var sspi); using (sspi) { Xdr.WriteBuffer(userIdentificationData); var priority = 0; foreach (var protocol in protocols) { Xdr.Write(protocol.Version); Xdr.Write(IscCodes.GenericAchitectureClient); Xdr.Write(protocol.MinPType); Xdr.Write(protocol.MaxPType); Xdr.Write(priority); priority++; } Xdr.Flush(); var operation = Xdr.ReadOperation(); if (operation == IscCodes.op_accept || operation == IscCodes.op_cond_accept || operation == IscCodes.op_accept_data) { var wireCryptInitialized = false; ProtocolVersion = Xdr.ReadInt32(); ProtocolArchitecture = Xdr.ReadInt32(); ProtocolMinimunType = Xdr.ReadInt32(); if (ProtocolVersion < 0) { ProtocolVersion = (ushort)(ProtocolVersion & IscCodes.FB_PROTOCOL_MASK) | IscCodes.FB_PROTOCOL_FLAG; } if (_compression && !((ProtocolMinimunType & IscCodes.pflag_compress) != 0)) { _compression = false; } if (operation == IscCodes.op_cond_accept || operation == IscCodes.op_accept_data) { var serverData = Xdr.ReadBuffer(); var acceptPluginName = Xdr.ReadString(); var isAuthenticated = Xdr.ReadBoolean(); var serverKeys = Xdr.ReadBuffer(); if (!isAuthenticated) { switch (acceptPluginName) { case SrpClient.PluginName: AuthData = Encoding.ASCII.GetBytes(srp.ClientProof(NormalizeLogin(_userID), Password, serverData).ToHexString()); break; case SspiHelper.PluginName: AuthData = sspi.GetClientSecurity(serverData); break; default: throw new ArgumentOutOfRangeException(nameof(acceptPluginName), $"{nameof(acceptPluginName)}={acceptPluginName}"); } } if (_compression) { // after reading before writing _firebirdNetworkStream.StartCompression(); } if (operation == IscCodes.op_cond_accept) { Xdr.Write(IscCodes.op_cont_auth); Xdr.WriteBuffer(AuthData); Xdr.Write(acceptPluginName); // like CNCT_plugin_name Xdr.Write(acceptPluginName); // like CNCT_plugin_list Xdr.WriteBuffer(serverKeys); Xdr.Flush(); var response = (GenericResponse)ProcessOperation(Xdr.ReadOperation(), Xdr); serverKeys = response.Data; isAuthenticated = true; if (_wireCrypt != WireCryptOption.Disabled) { Xdr.Write(IscCodes.op_crypt); Xdr.Write(FirebirdNetworkStream.EncryptionName); Xdr.Write(SrpClient.SessionKeyName); Xdr.Flush(); // after writing before reading _firebirdNetworkStream.StartEncryption(srp.SessionKey); ProcessOperation(Xdr.ReadOperation(), Xdr); wireCryptInitialized = true; } } } // fbclient does not care about wirecrypt in older protocols either if (ProtocolVersion == IscCodes.PROTOCOL_VERSION13 && _wireCrypt == WireCryptOption.Required && !wireCryptInitialized) { throw IscException.ForErrorCode(IscCodes.isc_wirecrypt_incompatible); } } else if (operation == IscCodes.op_response) { var response = (GenericResponse)ProcessOperation(operation, Xdr); throw response.Exception; } else { try { Disconnect(); } catch { } finally { throw IscException.ForErrorCode(IscCodes.isc_connect_reject); } } } } catch (IOException ex) { throw IscException.ForErrorCode(IscCodes.isc_network_error, ex); } }