private void SendSign(SSH2DataReader r) { byte[] blob = r.ReadString(); byte[] data = r.ReadString(); //Debug.WriteLine(String.Format("SignRequest blobsize={0} datasize={1}", blob.Length, data.Length)); SSH2UserAuthKey[] keys = _client.GetAvailableSSH2UserAuthKeys(); SSH2UserAuthKey key = FindKey(keys, blob); if (key == null) { TransmitWriter(OpenWriter(AgentForwadPacketType.SSH_AGENT_FAILURE)); _client.NotifyPublicKeyDidNotMatch(); } else { SSH2DataWriter signpack = new SSH2DataWriter(); signpack.WriteString(SSH2Util.PublicKeyAlgorithmName(key.Algorithm)); signpack.WriteAsString(key.Sign(data)); SSH2DataWriter wr = OpenWriter(AgentForwadPacketType.SSH2_AGENT_SIGN_RESPONSE); wr.WriteAsString(signpack.ToByteArray()); TransmitWriter(wr); } }
private void OpenShellOrSubsystem(ISSHChannelEventReceiver receiver, PacketType pt, SSH2DataReader reader, string scheme) { if (_negotiationStatus == NegotiationStatus.WaitingChannelConfirmation) { if (pt != PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) { if (pt != PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE) receiver.OnChannelError(new SSHException("opening channel failed; packet type=" + pt)); else { int errcode = reader.ReadInt32(); string msg = Encoding.ASCII.GetString(reader.ReadString()); receiver.OnChannelError(new SSHException(msg)); } // Close() shouldn't be called because remote channel number is not given yet. // We just remove an event receiver from the collection of channels. // FIXME: _negotiationStatus sould be set an error status ? _connection.ChannelCollection.UnregisterChannelEventReceiver(_localID); } else { _remoteID = reader.ReadInt32(); _allowedDataSize = reader.ReadInt32(); _serverMaxPacketSize = reader.ReadInt32(); if (_type == ChannelType.Subsystem) { OpenScheme(scheme); _negotiationStatus = NegotiationStatus.WaitingSubsystemConfirmation; } else { //open pty SSH2DataWriter wr = new SSH2DataWriter(); SSHConnectionParameter param = _connection.Param; wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_REQUEST); wr.WriteInt32(_remoteID); wr.WriteString("pty-req"); wr.WriteBool(true); wr.WriteString(param.TerminalName); wr.WriteInt32(param.TerminalWidth); wr.WriteInt32(param.TerminalHeight); wr.WriteInt32(param.TerminalPixelWidth); wr.WriteInt32(param.TerminalPixelHeight); wr.WriteAsString(new byte[0]); if (_connection.IsEventTracerAvailable) _connection.TraceTransmissionEvent(PacketType.SSH_MSG_CHANNEL_REQUEST, "pty-req", "terminal={0} width={1} height={2}", param.TerminalName, param.TerminalWidth, param.TerminalHeight); TransmitPayload(wr.ToByteArray()); _negotiationStatus = NegotiationStatus.WaitingPtyReqConfirmation; } } } else if (_negotiationStatus == NegotiationStatus.WaitingPtyReqConfirmation) { if (pt != PacketType.SSH_MSG_CHANNEL_SUCCESS) { receiver.OnChannelError(new SSHException("opening pty failed")); Close(); } else { //agent request (optional) if (_connection.Param.AgentForward != null) { SSH2DataWriter wr = new SSH2DataWriter(); wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_REQUEST); wr.WriteInt32(_remoteID); wr.WriteString("*****@*****.**"); wr.WriteBool(true); _connection.TraceTransmissionEvent(PacketType.SSH_MSG_CHANNEL_REQUEST, "auth-agent-req", ""); TransmitPayload(wr.ToByteArray()); _negotiationStatus = NegotiationStatus.WaitingAuthAgentReqConfirmation; } else { OpenScheme(scheme); _negotiationStatus = NegotiationStatus.WaitingShellConfirmation; } } } else if (_negotiationStatus == NegotiationStatus.WaitingAuthAgentReqConfirmation) { if (pt != PacketType.SSH_MSG_CHANNEL_SUCCESS && pt != PacketType.SSH_MSG_CHANNEL_FAILURE) { receiver.OnChannelError(new SSHException("auth-agent-req error")); Close(); } else { //auth-agent-req is optional _connection.SetAgentForwardConfirmed(pt == PacketType.SSH_MSG_CHANNEL_SUCCESS); _connection.TraceReceptionEvent(pt, "auth-agent-req"); OpenScheme(scheme); _negotiationStatus = NegotiationStatus.WaitingShellConfirmation; } } else if (_negotiationStatus == NegotiationStatus.WaitingShellConfirmation) { if (pt != PacketType.SSH_MSG_CHANNEL_SUCCESS) { receiver.OnChannelError(new SSHException("Opening shell failed: packet type=" + pt.ToString())); Close(); } else { receiver.OnChannelReady(); _negotiationStatus = NegotiationStatus.Ready; //goal! } } else if (_negotiationStatus == NegotiationStatus.WaitingSubsystemConfirmation) { if (pt != PacketType.SSH_MSG_CHANNEL_SUCCESS) { receiver.OnChannelError(new SSHException("Opening subsystem failed: packet type=" + pt.ToString())); Close(); } else { receiver.OnChannelReady(); _negotiationStatus = NegotiationStatus.Ready; //goal! } } }
private AuthenticationResult UserAuth() { const string sn = "ssh-connection"; if (_param.AuthenticationType == AuthenticationType.KeyboardInteractive) { SSH2TransmissionPacket packet = OpenPacket(); SSH2DataWriter wr = packet.DataWriter; wr.WritePacketType(PacketType.SSH_MSG_USERAUTH_REQUEST); wr.WriteString(_param.UserName); wr.WriteString(sn); wr.WriteString("keyboard-interactive"); wr.WriteString(""); //lang wr.WriteString(""); //submethod TraceTransmissionEvent(PacketType.SSH_MSG_USERAUTH_REQUEST, "starting keyboard-interactive authentication"); TransmitPacket(packet); _authenticationResult = ProcessAuthenticationResponse(); } else { SSH2TransmissionPacket packet = OpenPacket(); SSH2DataWriter wr = packet.DataWriter; wr.WritePacketType(PacketType.SSH_MSG_USERAUTH_REQUEST); wr.WriteString(_param.UserName); if (_param.AuthenticationType == AuthenticationType.Password) { //Password authentication wr.WriteString(sn); wr.WriteString("password"); wr.WriteBool(false); wr.WriteString(_param.Password); TraceTransmissionEvent(PacketType.SSH_MSG_USERAUTH_REQUEST, "starting password authentication"); } else { //public key authentication SSH2UserAuthKey kp = SSH2UserAuthKey.FromSECSHStyleFile(_param.IdentityFile, _param.Password); SSH2DataWriter signsource = new SSH2DataWriter(); signsource.WriteAsString(_sessionID); signsource.WritePacketType(PacketType.SSH_MSG_USERAUTH_REQUEST); signsource.WriteString(_param.UserName); signsource.WriteString(sn); signsource.WriteString("publickey"); signsource.WriteBool(true); signsource.WriteString(SSH2Util.PublicKeyAlgorithmName(kp.Algorithm)); signsource.WriteAsString(kp.GetPublicKeyBlob()); SSH2DataWriter signpack = new SSH2DataWriter(); signpack.WriteString(SSH2Util.PublicKeyAlgorithmName(kp.Algorithm)); signpack.WriteAsString(kp.Sign(signsource.ToByteArray())); wr.WriteString(sn); wr.WriteString("publickey"); wr.WriteBool(true); wr.WriteString(SSH2Util.PublicKeyAlgorithmName(kp.Algorithm)); wr.WriteAsString(kp.GetPublicKeyBlob()); wr.WriteAsString(signpack.ToByteArray()); TraceTransmissionEvent(PacketType.SSH_MSG_USERAUTH_REQUEST, "starting public key authentication"); } TransmitPacket(packet); _authenticationResult = ProcessAuthenticationResponse(); if (_authenticationResult == AuthenticationResult.Failure) throw new SSHException(Strings.GetString("AuthenticationFailed")); } return _authenticationResult; }
private bool ProcessKEXDHREPLY(DataFragment packet) { //Round2 receives response SSH2DataReader re = null; PacketType h; do { re = new SSH2DataReader(packet); h = re.ReadPacketType(); if (h == PacketType.SSH_MSG_KEXDH_REPLY) break; //successfully exit else if (h == PacketType.SSH_MSG_IGNORE || h == PacketType.SSH_MSG_DEBUG) { //continue packet = _connection.ReceivePacket(); } else throw new SSHException(String.Format("KeyExchange response is not KEXDH_REPLY but {0}", h)); } while (true); byte[] key_and_cert = re.ReadString(); BigInteger f = re.ReadMPInt(); byte[] signature = re.ReadString(); Debug.Assert(re.Rest == 0); //Round3 calc hash H SSH2DataWriter wr = new SSH2DataWriter(); _k = f.modPow(_x, GetDiffieHellmanPrime(_cInfo._kexAlgorithm)); wr = new SSH2DataWriter(); wr.WriteString(_cInfo._clientVersionString); wr.WriteString(_cInfo._serverVersionString); wr.WriteAsString(_clientKEXINITPayload); wr.WriteAsString(_serverKEXINITPayload); wr.WriteAsString(key_and_cert); wr.WriteBigInteger(_e); wr.WriteBigInteger(f); wr.WriteBigInteger(_k); _hash = new SHA1CryptoServiceProvider().ComputeHash(wr.ToByteArray()); _connection.TraceReceptionEvent(h, "verifying host key"); if (!VerifyHostKey(key_and_cert, signature, _hash)) return false; //Debug.WriteLine("hash="+DebugUtil.DumpByteArray(hash)); if (_sessionID == null) _sessionID = _hash; return true; }
public void WritePrivatePartInSECSHStyleFile(Stream dest, string comment, SecureString passphrase) { //step1 key body SSH2DataWriter wr = new SSH2DataWriter(); wr.WriteInt32(0); //this field is filled later if (_keypair.Algorithm == PublicKeyAlgorithm.RSA) { RSAKeyPair rsa = (RSAKeyPair)_keypair; RSAPublicKey pub = (RSAPublicKey)_keypair.PublicKey; wr.WriteBigIntWithBits(pub.Exponent); wr.WriteBigIntWithBits(rsa.D); wr.WriteBigIntWithBits(pub.Modulus); wr.WriteBigIntWithBits(rsa.U); wr.WriteBigIntWithBits(rsa.P); wr.WriteBigIntWithBits(rsa.Q); } else { DSAKeyPair dsa = (DSAKeyPair)_keypair; DSAPublicKey pub = (DSAPublicKey)_keypair.PublicKey; wr.WriteInt32(0); wr.WriteBigIntWithBits(pub.P); wr.WriteBigIntWithBits(pub.G); wr.WriteBigIntWithBits(pub.Q); wr.WriteBigIntWithBits(pub.Y); wr.WriteBigIntWithBits(dsa.X); } int padding_len = 0; if (passphrase != null) { padding_len = 8 - (int)wr.Length%8; wr.Write(new byte[padding_len]); } byte[] encrypted_body = wr.ToByteArray(); SSHUtil.WriteIntToByteArray(encrypted_body, 0, encrypted_body.Length - padding_len - 4); //encrypt if necessary if (passphrase != null) { var c = CipherFactory.CreateCipher(SSHProtocol.SSH2, CipherAlgorithm.TripleDES, PassphraseToKey(passphrase, 24)); Debug.Assert(encrypted_body.Length%8 == 0); var tmp = new byte[encrypted_body.Length]; c.Encrypt(encrypted_body, 0, encrypted_body.Length, tmp, 0); encrypted_body = tmp; } //step2 make binary key data wr = new SSH2DataWriter(); wr.WriteInt32(MAGIC_VAL); wr.WriteInt32(0); //for total size wr.WriteString(_keypair.Algorithm == PublicKeyAlgorithm.RSA ? "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}" : "dl-modp{sign{dsa-nist-sha1},dh{plain}}"); wr.WriteString(passphrase == null ? "none" : "3des-cbc"); wr.WriteAsString(encrypted_body); var rawdata = wr.ToByteArray(); SSHUtil.WriteIntToByteArray(rawdata, 4, rawdata.Length); //fix total length //step3 write final data var sw = new StreamWriter(dest, Encoding.ASCII); sw.WriteLine("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"); if (comment != null) WriteKeyFileBlock(sw, "Comment: " + comment, true); WriteKeyFileBlock(sw, Encoding.ASCII.GetString(Base64.Encode(rawdata)), false); sw.WriteLine("---- END SSH2 ENCRYPTED PRIVATE KEY ----"); sw.Close(); }