private void SendSign(SSH2DataReader r) { byte[] blob = r.ReadByteString(); byte[] data = r.ReadByteString(); //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); } }
public SSH2TransmissionPacket() { _writer = new SSH2DataWriter(); _dataFragment = new DataFragment(null, 0, 0); _isOpen = false; }
private string FormatBase64EncodedPublicKeyBody() { SSH2DataWriter wr = new SSH2DataWriter(); wr.WriteString(SSH2Util.PublicKeyAlgorithmName(_keypair.Algorithm)); _keypair.PublicKey.WriteTo(wr); return Encoding.ASCII.GetString(Base64.Encode(wr.ToByteArray())); }
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(); } else { _remoteID = reader.ReadInt32(); _allowedDataSize = reader.ReadInt32(); _serverMaxPacketSize = reader.ReadInt32(); //open pty SSH2DataWriter wr = new SSH2DataWriter(); SSHConnectionParameter param = _connection.Param; wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_REQUEST); wr.Write(_remoteID); wr.Write("pty-req"); wr.Write(true); wr.Write(param.TerminalName); wr.Write(param.TerminalWidth); wr.Write(param.TerminalHeight); wr.Write(param.TerminalPixelWidth); wr.Write(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.Write(_remoteID); wr.Write("*****@*****.**"); wr.Write(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! } } }
// sending "exec" service for SCP protocol. private void ExecCommand(ISSHChannelEventReceiver receiver, PacketType pt, SSH2DataReader reader) { 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(); } else { _remoteID = reader.ReadInt32(); _allowedDataSize = reader.ReadInt32(); _serverMaxPacketSize = reader.ReadInt32(); // exec command SSH2DataWriter wr = new SSH2DataWriter(); SSHConnectionParameter param = _connection.Param; wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_REQUEST); wr.Write(_remoteID); wr.Write("exec"); // "exec" wr.Write(false); // want confirm is disabled. (*) wr.Write(_command); if (_connection.IsEventTracerAvailable) _connection.TraceTransmissionEvent("exec command","cmd={0}", _command); TransmitPayload(wr.ToByteArray()); //confirmation is omitted receiver.OnChannelReady(); _negotiationStatus = NegotiationStatus.Ready; //goal! } } else if(_negotiationStatus==NegotiationStatus.WaitingExecCmdConfirmation) { if(pt!=PacketType.SSH_MSG_CHANNEL_DATA) { receiver.OnChannelError(new SSHException("exec command failed")); Close(); } else { receiver.OnChannelReady(); _negotiationStatus = NegotiationStatus.Ready; //goal! } } else throw new SSHException("internal state error"); }
private bool ProcessPacket(DataFragment packet) { if(_readerForProcessPacket==null) _readerForProcessPacket = new SSH2DataReader(packet); else _readerForProcessPacket.Recycle(packet); //avoid 'new' SSH2DataReader r = _readerForProcessPacket; //rename for frequently use PacketType pt = r.ReadPacketType(); if(pt==PacketType.SSH_MSG_DISCONNECT) { int errorcode = r.ReadInt32(); _eventReceiver.OnConnectionClosed(); return false; } else if(_waitingForPortForwardingResponse) { if(pt!=PacketType.SSH_MSG_REQUEST_SUCCESS) _eventReceiver.OnUnknownMessage((byte)pt, r.Image); _waitingForPortForwardingResponse = false; return true; } else if(pt==PacketType.SSH_MSG_CHANNEL_OPEN) { string method = Encoding.ASCII.GetString(r.ReadString()); if(method=="forwarded-tcpip") ProcessPortforwardingRequest(_eventReceiver, r); else if(method.StartsWith("auth-agent")) //in most cases, method is "*****@*****.**" ProcessAgentForwardRequest(_eventReceiver, r); else { SSH2DataWriter wr = new SSH2DataWriter(); wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE); wr.Write(r.ReadInt32()); wr.Write(0); wr.Write("unknown method"); wr.Write(""); //lang tag TraceReceptionEvent("SSH_MSG_CHANNEL_OPEN rejected", "method={0}", method); } return true; } else if(pt>=PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION && pt<=PacketType.SSH_MSG_CHANNEL_FAILURE) { int local_channel = r.ReadInt32(); ChannelCollection.Entry e = this.ChannelCollection.FindChannelEntry(local_channel); if(e!=null) ((SSH2Channel)e.Channel).ProcessPacket(e.Receiver, pt, 5+r.Rest, r); else Debug.WriteLine("unexpected channel pt="+pt+" local_channel="+local_channel.ToString()); return true; } else if(pt==PacketType.SSH_MSG_IGNORE) { _eventReceiver.OnIgnoreMessage(r.ReadString()); return true; } else if(_asyncKeyExchanger!=null) { _asyncKeyExchanger.AsyncProcessPacket(packet); return true; } else if(pt==PacketType.SSH_MSG_KEXINIT) { //Debug.WriteLine("Host sent KEXINIT"); _asyncKeyExchanger = new KeyExchanger(this, _sessionID); _asyncKeyExchanger.AsyncProcessPacket(packet); return true; } else { _eventReceiver.OnUnknownMessage((byte)pt, r.Image); return false; } }
private void ProcessChannelLocalData(ISSHChannelEventReceiver receiver, PacketType pt, SSH2DataReader re) { switch(pt) { case PacketType.SSH_MSG_CHANNEL_DATA: { int len = re.ReadInt32(); receiver.OnData(re.Image, re.Offset, len); } break; case PacketType.SSH_MSG_CHANNEL_EXTENDED_DATA: { int t = re.ReadInt32(); byte[] data = re.ReadString(); receiver.OnExtendedData(t, data); } break; case PacketType.SSH_MSG_CHANNEL_REQUEST: { string request = Encoding.ASCII.GetString(re.ReadString()); bool reply = re.ReadBool(); if(request=="exit-status") { int status = re.ReadInt32(); } else if(reply) { //we reject unknown requests including keep-alive check SSH2DataWriter wr = new SSH2DataWriter(); wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_FAILURE); wr.Write(_remoteID); TransmitPayload(wr.ToByteArray()); } } break; case PacketType.SSH_MSG_CHANNEL_EOF: receiver.OnChannelEOF(); break; case PacketType.SSH_MSG_CHANNEL_CLOSE: _connection.ChannelCollection.UnregisterChannelEventReceiver(_localID); receiver.OnChannelClosed(); break; case PacketType.SSH_MSG_CHANNEL_FAILURE: receiver.OnMiscPacket((byte)pt, re.Image, re.Offset, re.Rest); break; default: receiver.OnMiscPacket((byte)pt, re.Image, re.Offset, re.Rest); Debug.WriteLine("Unknown Packet "+pt); break; } }
private DataFragment SendKEXDHINIT(Mode mode) { //Round1 computes and sends [e] byte[] sx = new byte[16]; _param.Random.NextBytes(sx); _x = new BigInteger(sx); _e = new BigInteger(2).modPow(_x, DH_PRIME); SSH2DataWriter wr = new SSH2DataWriter(); wr.WritePacketType(PacketType.SSH_MSG_KEXDH_INIT); wr.WriteBigInteger(_e); _status = Status.WAIT_KEXDH_REPLY; TraceTransmissionNegotiation(PacketType.SSH_MSG_KEXDH_INIT, ""); if (mode == Mode.Synchronized) return SynchronizedTransmitRawPayload(wr.ToByteArray()); else { TransmitRawPayload(wr.ToByteArray()); return null; } }
public byte[] ToByteArray(string passphrase) { //step1 key body SSH2DataWriter wr = new SSH2DataWriter(); wr.Write(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.Write(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) { Cipher c = CipherFactory.CreateCipher(SSHProtocol.SSH2, CipherAlgorithm.TripleDES, PassphraseToKey(passphrase, 24)); Debug.Assert(encrypted_body.Length % 8 == 0); byte[] 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.Write(MAGIC_VAL); wr.Write(0); //for total size wr.Write(_keypair.Algorithm == PublicKeyAlgorithm.RSA ? "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}" : "dl-modp{sign{dsa-nist-sha1},dh{plain}}"); wr.Write(passphrase == null ? "none" : "3des-cbc"); wr.WriteAsString(encrypted_body); byte[] rawdata = wr.ToByteArray(); SSHUtil.WriteIntToByteArray(rawdata, 4, rawdata.Length); //fix total length return rawdata; }
/// <summary> /// Signing /// </summary> /// <param name="data">data to sign</param> /// <returns>signature blob</returns> public byte[] Sign(byte[] data) { BigInteger order = _curve.Order; byte[] hash = _publicKey.HashForSigning(data, _curve); BigInteger e = new BigInteger(hash); using (var rng = new RNGCryptoServiceProvider()) { BigInteger.ModulusRing nring = new BigInteger.ModulusRing(order); for (int tries = 0; tries < 10; ++tries) { try { ECDSAKeyPair tempKeyPair = _curve.GenerateKeyPair(rng); BigInteger r = tempKeyPair.PublicKeyPoint.X % order; if (r == 0) { continue; } BigInteger k = tempKeyPair.PrivateKey; BigInteger s = nring.Multiply(k.ModInverse(order), e + nring.Multiply(r, _privateKey)); if (s == 0) { continue; } SSH2DataWriter writer = new SSH2DataWriter(); writer.WriteBigInteger(r); writer.WriteBigInteger(s); return writer.ToByteArray(); } catch (Exception ex) { Debug.WriteLine(ex); } } } throw new SSHException(Strings.GetString("FailedSigning")); }
// Tests signature verification using test vectors from NIST CAVP. // http://csrc.nist.gov/groups/STM/cavp/digital-signatures.html internal static void TestSignatureVerification() { using (var reader = new System.IO.StreamReader(@"186-3ecdsatestvectors\SigVer.rsp")) { EllipticCurve curve = null; byte[] msg = null; BigInteger qx = null; BigInteger qy = null; BigInteger r = null; BigInteger s = null; string result = null; int testCount = 0; while (true) { string line = reader.ReadLine(); if (line == null) { break; } var match = System.Text.RegularExpressions.Regex.Match(line, @"\[([-\w]+),(SHA-\d+)\]"); if (match.Success) { string curveName = "nist" + match.Groups[1].Value.ToLowerInvariant().Replace("-", ""); curve = FindByName(curveName); if (curve != null) { using (var hashFunc = ECDSAHashAlgorithmChooser.Choose(curve)) { var hashName = "SHA-" + hashFunc.HashSize.ToString(); if (hashName == match.Groups[2].Value) { Debug.WriteLine("Test " + curve.CurveName); } else { // hash function doesn't match curve = null; } } } msg = null; qx = qy = r = s = null; result = null; testCount = 0; continue; } if (line.StartsWith("Msg = ") && curve != null) { msg = BigIntegerConverter.ParseHex(line.Substring(6).Trim()); continue; } if (line.StartsWith("Qx = ") && curve != null) { qx = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(5).Trim())); continue; } if (line.StartsWith("Qy = ") && curve != null) { qy = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(5).Trim())); continue; } if (line.StartsWith("R = ") && curve != null) { r = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(4).Trim())); continue; } if (line.StartsWith("S = ") && curve != null) { s = new BigInteger(BigIntegerConverter.ParseHex(line.Substring(4).Trim())); continue; } if (line.StartsWith("Result = ") && curve != null) { result = line.Substring(9, 1); if (msg != null && qx != null && qy != null && r != null && s != null) { var pk = new ECDSAPublicKey(curve, new ECPoint(qx, qy)); var buf = new SSH2DataWriter(); buf.WriteBigInteger(r); buf.WriteBigInteger(s); var sig = buf.ToByteArray(); string verRes; try { pk.Verify(sig, msg); verRes = "P"; } catch (VerifyException) { verRes = "F"; } if (verRes != result) { throw new Exception("verification result doesn't match"); } ++testCount; Debug.WriteLine("Pass #{0}", testCount); } msg = null; qx = qy = r = s = null; result = null; } } } }
public SSH2TransmissionPacket() { _padding = new byte[32]; _writer = new SSH2DataWriter(); _is_open = false; }
private DataFragment SendKEXDHINIT(Mode mode) { //Round1 computes and sends [e] byte[] sx = new byte[32]; RngManager.GetSecureRng().GetBytes(sx); _x = new BigInteger(sx); _e = new BigInteger(2).modPow(_x, GetDiffieHellmanPrime(_cInfo._kexAlgorithm)); SSH2DataWriter wr = new SSH2DataWriter(); wr.WritePacketType(PacketType.SSH_MSG_KEXDH_INIT); wr.WriteBigInteger(_e); _status = Status.WAIT_KEXDH_REPLY; TraceTransmissionNegotiation(PacketType.SSH_MSG_KEXDH_INIT, ""); if (mode == Mode.Synchronized) return SynchronizedTransmitRawPayload(wr.ToByteArray()); else { TransmitRawPayload(wr.ToByteArray()); return null; } }
private void TransmitWriter(SSH2DataWriter wr) { int o = wr.Length; wr.SetOffset(0); wr.WriteInt32(o - 4); //length of int32 _channel.Transmit(wr.UnderlyingBuffer, 0, o); }
internal void TransmitPacket(SSH2DataWriter payload) { lock(this) { Debug.Assert(payload==_transmissionPacket.UnderlyingWriter); _transmissionPacket.Close(_tCipher, _param.Random, _tMAC, _tSequence++, _transmissionImage); _stream.Write(_transmissionImage.Data, _transmissionImage.Offset, _transmissionImage.Length); } }
private DataFragment SynchronizedTransmitPacket(SSH2DataWriter wr) { return _connection.SynchronizedTransmitPacket(wr); }
internal DataFragment SynchronizedTransmitPacket(SSH2DataWriter payload) { lock(this) { Debug.Assert(payload==_transmissionPacket.UnderlyingWriter); _transmissionPacket.Close(_tCipher, _param.Random, _tMAC, _tSequence++, _transmissionImage); return _packetReceiver.SendAndWaitResponse(_transmissionImage); } }
private void SendKEXINIT(Mode mode) { const string kex_algorithm = "diffie-hellman-group1-sha1"; const string mac_algorithm = "hmac-sha1"; SSH2DataWriter wr = new SSH2DataWriter(); wr.WritePacketType(PacketType.SSH_MSG_KEXINIT); byte[] cookie = new byte[16]; _param.Random.NextBytes(cookie); wr.Write(cookie); wr.Write(kex_algorithm); // kex_algorithms wr.Write(FormatHostKeyAlgorithmDescription()); // server_host_key_algorithms wr.Write(FormatCipherAlgorithmDescription()); // encryption_algorithms_client_to_server wr.Write(FormatCipherAlgorithmDescription()); // encryption_algorithms_server_to_client wr.Write(mac_algorithm); // mac_algorithms_client_to_server wr.Write(mac_algorithm); // mac_algorithms_server_to_client wr.Write("none"); // compression_algorithms_client_to_server wr.Write("none"); // compression_algorithms_server_to_client wr.Write(""); // languages_client_to_server wr.Write(""); // languages_server_to_client wr.Write(false); //Indicates whether a guessed key exchange packet follows wr.Write(0); //reserved for future extension _clientKEXINITPayload = wr.ToByteArray(); _status = Status.WAIT_KEXINIT; if(_connection.IsEventTracerAvailable) { StringBuilder bld = new StringBuilder(); bld.Append("kex_algorithm="); bld.Append(kex_algorithm); bld.Append("; server_host_key_algorithms="); bld.Append(FormatHostKeyAlgorithmDescription()); bld.Append("; encryption_algorithms_client_to_server="); bld.Append(FormatCipherAlgorithmDescription()); bld.Append("; encryption_algorithms_server_to_client="); bld.Append(FormatCipherAlgorithmDescription()); bld.Append("; mac_algorithms_client_to_server="); bld.Append(mac_algorithm); bld.Append("; mac_algorithms_server_to_client="); bld.Append(mac_algorithm); TraceTransmissionNegotiation(PacketType.SSH_MSG_KEXINIT, bld.ToString()); } TransmitRawPayload(_clientKEXINITPayload); }
private void AdjustWindowSize(PacketType pt, int data_length) { _leftWindowSize -= data_length; if(pt==PacketType.SSH_MSG_CHANNEL_EOF || pt==PacketType.SSH_MSG_CHANNEL_CLOSE) return; //window adjust is not necessary if the channel is being closed // need not send window size to server when the channel is not opened. if (_negotiationStatus!=NegotiationStatus.Ready) return; while(_leftWindowSize <= _windowSize) { SSH2DataWriter adj = new SSH2DataWriter(); adj.WritePacketType(PacketType.SSH_MSG_CHANNEL_WINDOW_ADJUST); adj.Write(_remoteID); adj.Write(_windowSize); TransmitPayload(adj.ToByteArray()); _leftWindowSize += _windowSize; if(_connection.IsEventTracerAvailable) _connection.TraceTransmissionEvent("SSH_MSG_CHANNEL_WINDOW_ADJUST", "adjusted to {0} by increasing {1}", _leftWindowSize, _windowSize); } }
private AuthenticationResult UserAuth() { const string sn = "ssh-connection"; if(_param.AuthenticationType==AuthenticationType.KeyboardInteractive) { SSH2DataWriter wr = OpenTransmissionPacket(); wr.WritePacketType(PacketType.SSH_MSG_USERAUTH_REQUEST); wr.Write(_param.UserName); wr.Write(sn); wr.Write("keyboard-interactive"); wr.Write(""); //lang wr.Write(""); //submethod TraceTransmissionEvent(PacketType.SSH_MSG_USERAUTH_REQUEST, "starting keyboard-interactive authentication"); TransmitPacket(wr); _authenticationResult = ProcessAuthenticationResponse(); } else { SSH2DataWriter wr = OpenTransmissionPacket(); wr.WritePacketType(PacketType.SSH_MSG_USERAUTH_REQUEST); wr.Write(_param.UserName); if(_param.AuthenticationType==AuthenticationType.Password) { //Password authentication wr.Write(sn); wr.Write("password"); wr.Write(false); wr.Write(_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.Write(_param.UserName); signsource.Write(sn); signsource.Write("publickey"); signsource.Write(true); signsource.Write(SSH2Util.PublicKeyAlgorithmName(kp.Algorithm)); signsource.WriteAsString(kp.GetPublicKeyBlob()); SSH2DataWriter signpack = new SSH2DataWriter(); signpack.Write(SSH2Util.PublicKeyAlgorithmName(kp.Algorithm)); signpack.WriteAsString(kp.Sign(signsource.ToByteArray())); wr.Write(sn); wr.Write("publickey"); wr.Write(true); wr.Write(SSH2Util.PublicKeyAlgorithmName(kp.Algorithm)); wr.WriteAsString(kp.GetPublicKeyBlob()); wr.WriteAsString(signpack.ToByteArray()); TraceTransmissionEvent(PacketType.SSH_MSG_USERAUTH_REQUEST, "starting public key authentication"); } TransmitPacket(wr); _authenticationResult = ProcessAuthenticationResponse(); if(_authenticationResult==AuthenticationResult.Failure) throw new SSHException(Strings.GetString("AuthenticationFailed")); } return _authenticationResult; }
private void TransmitPacket(SSH2DataWriter writer) { _allowedDataSize -= writer.Length - SSH2TransmissionPacket.INITIAL_OFFSET; _connection.TransmitPacket(writer); }
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, DH_PRIME); wr = new SSH2DataWriter(); wr.Write(_cInfo._clientVersionString); wr.Write(_cInfo._serverVersionString); wr.WriteAsString(_clientKEXINITPayload); wr.WriteAsString(_serverKEXINITPayload); wr.WriteAsString(key_and_cert); wr.Write(_e); wr.Write(f); wr.Write(_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; }
private void OpenScheme(string scheme) { //open shell / subsystem SSH2DataWriter wr = new SSH2DataWriter(); wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_REQUEST); wr.Write(_remoteID); wr.Write(scheme); wr.Write(true); if(_command!=null) wr.Write(_command); TransmitPayload(wr.ToByteArray()); }
private byte[] DeriveKey(BigInteger key, byte[] hash, char ch, int length) { byte[] result = new byte[length]; SSH2DataWriter wr = new SSH2DataWriter(); wr.Write(key); wr.Write(hash); wr.Write((byte)ch); wr.Write(_sessionID); byte[] h1 = new SHA1CryptoServiceProvider().ComputeHash(wr.ToByteArray()); if(h1.Length >= length) { Array.Copy(h1, 0, result, 0, length); return result; } else { wr = new SSH2DataWriter(); wr.Write(key); wr.Write(_sessionID); wr.Write(h1); byte[] h2 = new SHA1CryptoServiceProvider().ComputeHash(wr.ToByteArray()); if(h1.Length+h2.Length >= length) { Array.Copy(h1, 0, result, 0, h1.Length); Array.Copy(h2, 0, result, h1.Length, length-h1.Length); return result; } else throw new SSHException("necessary key length is too big"); //long key is not supported } }
private byte[] WriteToDataWriter() { SSH2DataWriter wr = new SSH2DataWriter(); wr.WriteString(SSH2Util.PublicKeyAlgorithmName(_hostkey.Algorithm)); if (_hostkey.Algorithm == PublicKeyAlgorithm.RSA) { RSAPublicKey rsa = (RSAPublicKey)_hostkey; wr.WriteBigInteger(rsa.Exponent); wr.WriteBigInteger(rsa.Modulus); } else if (_hostkey.Algorithm == PublicKeyAlgorithm.DSA) { DSAPublicKey dsa = (DSAPublicKey)_hostkey; wr.WriteBigInteger(dsa.P); wr.WriteBigInteger(dsa.Q); wr.WriteBigInteger(dsa.G); wr.WriteBigInteger(dsa.Y); } else throw new SSHException("Host key algorithm is unsupported"); return wr.ToByteArray(); }
private void ProcessPortforwardingRequest(ISSHConnectionEventReceiver receiver, SSH2DataReader reader) { int remote_channel = reader.ReadInt32(); int window_size = reader.ReadInt32(); //skip initial window size int servermaxpacketsize = reader.ReadInt32(); string host = Encoding.ASCII.GetString(reader.ReadString()); int port = reader.ReadInt32(); string originator_ip = Encoding.ASCII.GetString(reader.ReadString()); int originator_port = reader.ReadInt32(); TraceReceptionEvent("port forwarding request", String.Format("host={0} port={1} originator-ip={2} originator-port={3}", host, port, originator_ip, originator_port)); PortForwardingCheckResult r = receiver.CheckPortForwardingRequest(host,port,originator_ip,originator_port); SSH2DataWriter wr = new SSH2DataWriter(); if(r.allowed) { //send OPEN_CONFIRMATION SSH2Channel channel = new SSH2Channel(this, ChannelType.ForwardedRemoteToLocal, this.ChannelCollection.RegisterChannelEventReceiver(null, r.channel).LocalID, remote_channel, servermaxpacketsize); wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION); wr.Write(remote_channel); wr.Write(channel.LocalChannelID); wr.Write(_param.WindowSize); //initial window size wr.Write(_param.MaxPacketSize); //max packet size receiver.EstablishPortforwarding(r.channel, channel); TraceTransmissionEvent("port-forwarding request is confirmed", "host={0} port={1} originator-ip={2} originator-port={3}", host, port, originator_ip, originator_port); } else { wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE); wr.Write(remote_channel); wr.Write(r.reason_code); wr.Write(r.reason_message); wr.Write(""); //lang tag TraceTransmissionEvent("port-forwarding request is rejected", "host={0} port={1} originator-ip={2} originator-port={3}", host, port, originator_ip, originator_port); } TransmitRawPayload(wr.ToByteArray()); }
public void WritePrivatePartInSECSHStyleFile(Stream dest, string comment, string 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) { Cipher c = CipherFactory.CreateCipher(SSHProtocol.SSH2, CipherAlgorithm.TripleDES, PassphraseToKey(passphrase, 24)); Debug.Assert(encrypted_body.Length % 8 == 0); byte[] 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); byte[] rawdata = wr.ToByteArray(); SSHUtil.WriteIntToByteArray(rawdata, 4, rawdata.Length); //fix total length //step3 write final data StreamWriter 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(); }
private void ProcessAgentForwardRequest(ISSHConnectionEventReceiver receiver, SSH2DataReader reader) { int remote_channel = reader.ReadInt32(); int window_size = reader.ReadInt32(); //skip initial window size int servermaxpacketsize = reader.ReadInt32(); TraceReceptionEvent("agent forward request", ""); SSH2DataWriter wr = new SSH2DataWriter(); IAgentForward af = _param.AgentForward; if(_agentForwardConfirmed && af!=null && af.CanAcceptForwarding()) { //send OPEN_CONFIRMATION AgentForwardingChannel ch = new AgentForwardingChannel(af); SSH2Channel channel = new SSH2Channel(this, ChannelType.AgentForward, this.ChannelCollection.RegisterChannelEventReceiver(null, ch).LocalID, remote_channel, servermaxpacketsize); ch.SetChannel(channel); wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION); wr.Write(remote_channel); wr.Write(channel.LocalChannelID); wr.Write(_param.WindowSize); //initial window size wr.Write(_param.MaxPacketSize); //max packet size TraceTransmissionEvent("granados confirmed agent-forwarding request", ""); } else { wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE); wr.Write(remote_channel); wr.Write(0); wr.Write("reject"); wr.Write(""); //lang tag TraceTransmissionEvent("granados rejected agent-forwarding request", ""); } TransmitRawPayload(wr.ToByteArray()); }
public byte[] GetPublicKeyBlob() { SSH2DataWriter w = new SSH2DataWriter(); w.WriteString(SSH2Util.PublicKeyAlgorithmName(_keypair.Algorithm)); _keypair.PublicKey.WriteTo(w); return w.ToByteArray(); }
//writer util private SSH2DataWriter OpenWriter(AgentForwadPacketType pt) { SSH2DataWriter wr = new SSH2DataWriter(); wr.WriteInt32(0); //length field wr.WriteByte((byte)pt); return wr; }