Beispiel #1
0
        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();

        }
Beispiel #2
0
 private void OpenScheme(string scheme) {
     //open shell / subsystem
     SSH2DataWriter wr = new SSH2DataWriter();
     wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_REQUEST);
     wr.WriteInt32(_remoteID);
     wr.WriteString(scheme);
     wr.WriteBool(true);
     if (_command != null)
         wr.WriteString(_command);
     TransmitPayload(wr.ToByteArray());
 }
Beispiel #3
0
        // 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.WriteInt32(_remoteID);
                    wr.WriteString("exec");  // "exec"
                    wr.WriteBool(false);   // want confirm is disabled. (*)
                    wr.WriteString(_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");
        }
Beispiel #4
0
 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.WriteInt32(_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;
     }
 }
Beispiel #5
0
        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!
                }
            }
        }
Beispiel #6
0
        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.WriteInt32(r.ReadInt32());
                    wr.WriteInt32(0);
                    wr.WriteString("unknown method");
                    wr.WriteString(""); //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;
            }
        }
Beispiel #7
0
        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.WriteInt32(_remoteID);
                adj.WriteInt32(_windowSize);
                TransmitPayload(adj.ToByteArray());
                _leftWindowSize += _windowSize;
                if (_connection.IsEventTracerAvailable)
                    _connection.TraceTransmissionEvent("SSH_MSG_CHANNEL_WINDOW_ADJUST", "adjusted to {0} by increasing {1}", _leftWindowSize, _windowSize);
            }
        }
Beispiel #8
0
        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.WriteInt32(remote_channel);
                wr.WriteInt32(channel.LocalChannelID);
                wr.WriteInt32(_param.WindowSize); //initial window size
                wr.WriteInt32(_param.MaxPacketSize); //max packet size
                TraceTransmissionEvent("granados confirmed agent-forwarding request", "");
            }
            else {
                wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE);
                wr.WriteInt32(remote_channel);
                wr.WriteInt32(0);
                wr.WriteString("reject");
                wr.WriteString(""); //lang tag
                TraceTransmissionEvent("granados rejected agent-forwarding request", "");
            }
            TransmitRawPayload(wr.ToByteArray());
        }
Beispiel #9
0
        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.WriteInt32(remote_channel);
                wr.WriteInt32(channel.LocalChannelID);
                wr.WriteInt32(_param.WindowSize); //initial window size
                wr.WriteInt32(_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.WriteInt32(remote_channel);
                wr.WriteInt32(r.reason_code);
                wr.WriteString(r.reason_message);
                wr.WriteString(""); //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());
        }
Beispiel #10
0
        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.WriteString(kex_algorithm); //    kex_algorithms
            wr.WriteString(FormatHostKeyAlgorithmDescription());            //    server_host_key_algorithms
            wr.WriteString(FormatCipherAlgorithmDescription());      //    encryption_algorithms_client_to_server
            wr.WriteString(FormatCipherAlgorithmDescription());      //    encryption_algorithms_server_to_client
            wr.WriteString(mac_algorithm);                  //    mac_algorithms_client_to_server
            wr.WriteString(mac_algorithm);                  //    mac_algorithms_server_to_client
            wr.WriteString("none");                       //    compression_algorithms_client_to_server
            wr.WriteString("none");                       //    compression_algorithms_server_to_client
            wr.WriteString("");                           //    languages_client_to_server
            wr.WriteString("");                           //    languages_server_to_client
            wr.WriteBool(false); //Indicates whether a guessed key exchange packet follows
            wr.WriteInt32(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);
        }
Beispiel #11
0
 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);
 }
Beispiel #12
0
 //writer util
 private SSH2DataWriter OpenWriter(AgentForwadPacketType pt)
 {
     SSH2DataWriter wr = new SSH2DataWriter();
     wr.WriteInt32(0); //length field
     wr.WriteByte((byte)pt);
     return wr;
 }