private void ReceiveServerKeys() { DataFragment packet = ReceivePacket(); SSH1DataReader reader = new SSH1DataReader(packet); SSH1PacketType pt = (SSH1PacketType) reader.ReadByte(); if (pt != SSH1PacketType.SSH_SMSG_PUBLIC_KEY) throw new SSHException("unexpected SSH SSH1Packet type " + pt, packet.GetBytes()); _cInfo.AntiSpoofingCookie = reader.Read(8); _cInfo.ServerKeyBits = reader.ReadInt32(); BigInteger serverKeyExponent = reader.ReadMPInt(); BigInteger serverKeyModulus = reader.ReadMPInt(); _cInfo.ServerKey = new RSAPublicKey(serverKeyExponent, serverKeyModulus); _cInfo.HostKeyBits = reader.ReadInt32(); BigInteger hostKeyExponent = reader.ReadMPInt(); BigInteger hostKeyModulus = reader.ReadMPInt(); _cInfo.HostKey = new RSAPublicKey(hostKeyExponent, hostKeyModulus); //read protocol support parameters int protocol_flags = reader.ReadInt32(); int supported_ciphers_mask = reader.ReadInt32(); _cInfo.SupportedEncryptionAlgorithmsMask = supported_ciphers_mask; int supported_authentications_mask = reader.ReadInt32(); //Debug.WriteLine(String.Format("ServerOptions {0} {1} {2}", protocol_flags, supported_ciphers_mask, supported_authentications_mask)); if (reader.RemainingDataLength > 0) throw new SSHException("data length mismatch", packet.GetBytes()); bool found = false; foreach (CipherAlgorithm a in _param.PreferableCipherAlgorithms) { if (a != CipherAlgorithm.Blowfish && a != CipherAlgorithm.TripleDES) continue; else if (a == CipherAlgorithm.Blowfish && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.Blowfish)) == 0) continue; else if (a == CipherAlgorithm.TripleDES && (supported_ciphers_mask & (1 << (int)CipherAlgorithm.TripleDES)) == 0) continue; _cInfo.IncomingPacketCipher = _cInfo.OutgoingPacketCipher = a; found = true; break; } if (!found) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedX"), "Blowfish/TripleDES")); if (_param.AuthenticationType == AuthenticationType.Password && (supported_authentications_mask & (1 << (int)AuthenticationType.Password)) == 0) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedPassword")), packet.GetBytes()); if (_param.AuthenticationType == AuthenticationType.PublicKey && (supported_authentications_mask & (1 << (int)AuthenticationType.PublicKey)) == 0) throw new SSHException(String.Format(Strings.GetString("ServerNotSupportedRSA")), packet.GetBytes()); TraceReceptionEvent(pt, "received server key"); }
private DataFragment ReceivePacket() { while (true) { DataFragment data = _packetReceiver.WaitResponse(); SSH1PacketType pt = (SSH1PacketType)data[0]; //shortcut if (pt == SSH1PacketType.SSH_MSG_IGNORE) { SSH1DataReader r = new SSH1DataReader(data); r.ReadByte(); if (_eventReceiver != null) _eventReceiver.OnIgnoreMessage(r.ReadByteString()); } else if (pt == SSH1PacketType.SSH_MSG_DEBUG) { SSH1DataReader r = new SSH1DataReader(data); r.ReadByte(); if (_eventReceiver != null) _eventReceiver.OnDebugMessage(false, r.ReadByteString()); } else return data; } }
private bool ReceiveAuthenticationResult() { DataFragment packet = ReceivePacket(); SSH1DataReader r = new SSH1DataReader(packet); SSH1PacketType type = (SSH1PacketType) r.ReadByte(); TraceReceptionEvent(type, "user authentication response"); if (type == SSH1PacketType.SSH_MSG_DEBUG) { //Debug.WriteLine("receivedd debug message:"+Encoding.ASCII.GetString(r.ReadString())); return ReceiveAuthenticationResult(); } else if (type == SSH1PacketType.SSH_SMSG_SUCCESS) return true; else if (type == SSH1PacketType.SSH_SMSG_FAILURE) return false; else throw new SSHException("unexpected type: " + type); }
//RSA authentication private void DoRSAChallengeResponse() { //read key SSH1UserAuthKey key = new SSH1UserAuthKey(_param.IdentityFile, _param.Password); Transmit( new SSH1Packet(SSH1PacketType.SSH_CMSG_AUTH_RSA) .WriteBigInteger(key.PublicModulus) ); TraceTransmissionEvent(SSH1PacketType.SSH_CMSG_AUTH_RSA, "RSA challenge-reponse"); DataFragment response = ReceivePacket(); SSH1DataReader reader = new SSH1DataReader(response); SSH1PacketType pt = (SSH1PacketType) reader.ReadByte(); if (pt == SSH1PacketType.SSH_SMSG_FAILURE) throw new SSHException(Strings.GetString("ServerRefusedRSA")); else if (pt != SSH1PacketType.SSH_SMSG_AUTH_RSA_CHALLENGE) throw new SSHException(String.Format(Strings.GetString("UnexpectedResponse"), pt)); TraceReceptionEvent(SSH1PacketType.SSH_SMSG_AUTH_RSA_CHALLENGE, "received challenge"); //creating challenge BigInteger challenge = key.decryptChallenge(reader.ReadMPInt()); byte[] rawchallenge = RSAUtil.StripPKCS1Pad(challenge, 2).GetBytes(); //building response byte[] hash; using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider()) { md5.TransformBlock(rawchallenge, 0, rawchallenge.Length, rawchallenge, 0); md5.TransformFinalBlock(_sessionID, 0, _sessionID.Length); hash = md5.Hash; } Transmit( new SSH1Packet(SSH1PacketType.SSH_CMSG_AUTH_RSA_RESPONSE) .Write(hash) ); TraceReceptionEvent(SSH1PacketType.SSH_CMSG_AUTH_RSA_RESPONSE, "received response"); }
internal void AsyncReceivePacket(DataFragment data) { try { SSH1DataReader re = new SSH1DataReader(data); SSH1PacketType pt = (SSH1PacketType)re.ReadByte(); switch (pt) { case SSH1PacketType.SSH_SMSG_STDOUT_DATA: { int len = re.ReadInt32(); DataFragment frag = re.GetRemainingDataView(len); _channel_collection.FindChannelEntry(_shellID).Receiver.OnData(frag.Data, frag.Offset, frag.Length); } break; case SSH1PacketType.SSH_SMSG_STDERR_DATA: { _channel_collection.FindChannelEntry(_shellID).Receiver.OnExtendedData((int)SSH1PacketType.SSH_SMSG_STDERR_DATA, re.ReadByteString()); } break; case SSH1PacketType.SSH_MSG_CHANNEL_DATA: { int channel = re.ReadInt32(); int len = re.ReadInt32(); DataFragment frag = re.GetRemainingDataView(len); _channel_collection.FindChannelEntry(channel).Receiver.OnData(frag.Data, frag.Offset, frag.Length); } break; case SSH1PacketType.SSH_MSG_PORT_OPEN: ProcessPortforwardingRequest(_eventReceiver, re); break; case SSH1PacketType.SSH_MSG_CHANNEL_CLOSE: { int channel = re.ReadInt32(); ISSHChannelEventReceiver r = _channel_collection.FindChannelEntry(channel).Receiver; _channel_collection.UnregisterChannelEventReceiver(channel); r.OnChannelClosed(); } break; case SSH1PacketType.SSH_MSG_CHANNEL_CLOSE_CONFIRMATION: { int channel = re.ReadInt32(); } break; case SSH1PacketType.SSH_MSG_DISCONNECT: _eventReceiver.OnConnectionClosed(); break; case SSH1PacketType.SSH_SMSG_EXITSTATUS: _channel_collection.FindChannelEntry(_shellID).Receiver.OnChannelClosed(); break; case SSH1PacketType.SSH_MSG_DEBUG: _eventReceiver.OnDebugMessage(false, re.ReadByteString()); break; case SSH1PacketType.SSH_MSG_IGNORE: _eventReceiver.OnIgnoreMessage(re.ReadByteString()); break; case SSH1PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION: { int local = re.ReadInt32(); int remote = re.ReadInt32(); _channel_collection.FindChannelEntry(local).Receiver.OnChannelReady(); } break; case SSH1PacketType.SSH_SMSG_SUCCESS: if (_executingShell) { ExecShell(); _channel_collection.FindChannelEntry(_shellID).Receiver.OnChannelReady(); _executingShell = false; } break; default: _eventReceiver.OnUnknownMessage((byte)pt, data.GetBytes()); break; } } catch (Exception ex) { _eventReceiver.OnError(ex); } }
/// <summary> /// Process forwarded message. /// </summary> /// <param name="message">a forwarded message</param> private void ProcessMessage(DataFragment message) { if (_authKeyProvider == null || !_authKeyProvider.IsAuthKeyProviderEnabled) { SendFailure(); return; } SSH1DataReader reader = new SSH1DataReader(message); OpenSSHAgentForwardingMessageType messageType = (OpenSSHAgentForwardingMessageType)reader.ReadByte(); switch (messageType) { // for SSH1 keys case OpenSSHAgentForwardingMessageType.SSH_AGENTC_REQUEST_RSA_IDENTITIES: SSH1Identities(); break; case OpenSSHAgentForwardingMessageType.SSH_AGENTC_RSA_CHALLENGE: { reader.ReadUInt32(); // ignored BigInteger e = reader.ReadMPInt(); BigInteger n = reader.ReadMPInt(); BigInteger encryptedChallenge = reader.ReadMPInt(); byte[] sessionId = reader.Read(16); uint responseType = reader.ReadUInt32(); SSH1IRSAChallenge(e, n, encryptedChallenge, sessionId, responseType); } break; // for SSH2 keys case OpenSSHAgentForwardingMessageType.SSH2_AGENTC_REQUEST_IDENTITIES: SSH2Identities(); break; case OpenSSHAgentForwardingMessageType.SSH2_AGENTC_SIGN_REQUEST: { byte[] blob = reader.ReadByteString(); byte[] data = reader.ReadByteString(); uint flags = reader.ReadUInt32(); SSH2Sign(blob, data, flags); } break; default: SendFailure(); break; } }