예제 #1
0
        private static int GetIntegerSize(SSH2DataReader binr)
        {
            byte bt       = 0;
            byte lowbyte  = 0x00;
            byte highbyte = 0x00;
            int  count    = 0;

            bt = binr.ReadByte();
            if (bt != 0x02)             //expect integer
            {
                return(0);
            }
            bt = binr.ReadByte();

            if (bt == 0x81)
            {
                count = binr.ReadByte();        // data size in next byte
            }
            else
            if (bt == 0x82)
            {
                highbyte = binr.ReadByte();     // data size in next 2 bytes
                lowbyte  = binr.ReadByte();
                byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                count = BitConverter.ToInt32(modint, 0);
            }
            else
            {
                count = bt;             // we already have the data size
            }



            while (binr.ReadByte() == 0x00)
            {   //remove high order zeros in data
                count -= 1;
            }
            binr.Seek(-1);              //last ReadByte wasn't a removed zero, so back up a byte
            return(count);
        }
예제 #2
0
        public static bool IsPrivateKeyEncrypted(string filename)
        {
            bool returnVal    = false;
            var  fileToLaunch = StorageFile.GetFileFromPathAsync(filename);

            fileToLaunch.AsTask().Wait();
            var streamToLaunch = fileToLaunch.AsTask().Result.OpenStreamForReadAsync();

            streamToLaunch.Wait();
            using (Stream s = streamToLaunch.Result)
            {
                using (StreamReader r = new StreamReader(streamToLaunch.Result, Encoding.UTF8)) {
                    string l = r.ReadLine();
                    if (l == PKCS8_RSA_HEADER)
                    {
                        while (l != "-----END RSA PRIVATE KEY-----")
                        {
                            if (l.IndexOf("Proc-Type: 4,ENCRYPTED") != -1)
                            {
                                returnVal = true;
                                break;
                            }
                            l = r.ReadLine();
                            if (l == null)
                            {
                                break;
                            }
                        }
                    }
                    else if (l == PKCS8_DSA_HEADER)
                    {
                        while (l != "-----END DSA PRIVATE KEY-----")
                        {
                            if (l.IndexOf("Proc-Type: 4,ENCRYPTED") != -1)
                            {
                                returnVal = true;
                                break;
                            }
                            l = r.ReadLine();
                            if (l == null)
                            {
                                break;
                            }
                        }
                    }
                    else if (l == SSH_COM_HEADER)
                    {
                        l = r.ReadLine();
                        StringBuilder buf = new StringBuilder();
                        while (l != "---- END SSH2 ENCRYPTED PRIVATE KEY ----")
                        {
                            if (l.IndexOf(':') == -1)
                            {
                                buf.Append(l);
                            }
                            else
                            {
                                while (l.EndsWith("\\"))
                                {
                                    l = r.ReadLine();
                                }
                            }
                            l = r.ReadLine();
                            if (l == null)
                            {
                                break;
                            }
                        }
                        byte[] keydata = Base64.Decode(Encoding.UTF8.GetBytes(buf.ToString()));

                        SSH2DataReader re    = new SSH2DataReader(keydata);
                        int            magic = re.ReadInt32();
                        if (magic != SSH_COM_MAGIC_VAL)
                        {
                            return(false);                            // Magic number doesn't match so just say false because it will error-out anyway
                        }
                        int    privateKeyLen = re.ReadInt32();
                        byte[] tmpstr        = re.ReadString();
                        string type          = Encoding.UTF8.GetString(tmpstr, 0, tmpstr.Length);
                        tmpstr = re.ReadString();
                        string ciphername = Encoding.UTF8.GetString(tmpstr, 0, tmpstr.Length);
                        int    bufLen     = re.ReadInt32();
                        if (ciphername != "none")
                        {
                            returnVal = true;
                        }
                    }
                    r.Dispose();
                    s.Dispose();
                }
            }
            return(returnVal);
        }
예제 #3
0
        private bool ProcessKEXDHREPLY(SSH2Packet packet)
        {
            //Round2 receives response
            SSH2DataReader re = new SSH2DataReader(packet.Data);
            PacketType h = re.ReadPacketType();
            if(h!=PacketType.SSH_MSG_KEXDH_REPLY) throw new Exception(String.Format("KeyExchange response is not KEXDH_REPLY but {0}", h));
            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 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha1).HashData(wr.ToByteArray().AsBuffer()).ToArray();

            if(!VerifyHostKey(key_and_cert, signature, _hash)) return false;

            //Debug.WriteLine("hash="+DebugUtil.DumpByteArray(hash));
            if(_sessionID==null) _sessionID = _hash;
            return true;
        }
예제 #4
0
        private void ProcessKEXINIT(SSH2Packet packet)
        {
            _serverKEXINITPayload = packet.Data;
            SSH2DataReader re = new SSH2DataReader(_serverKEXINITPayload);
            byte[] head = re.Read(17); //Type and cookie
            if(head[0]!=(byte)PacketType.SSH_MSG_KEXINIT) throw new Exception(String.Format("Server response is not SSH_MSG_KEXINIT but {0}", head[0]));
            Encoding enc = Encoding.UTF8;
            byte[] tmpdata;

            tmpdata = re.ReadString();
            string kex = enc.GetString(tmpdata,0,tmpdata.Length);
            _cInfo._supportedKEXAlgorithms = kex;
            CheckAlgorithmSupport("keyexchange", kex, "diffie-hellman-group1-sha1");

            tmpdata = re.ReadString();
            string host_key = enc.GetString(tmpdata, 0, tmpdata.Length);
            _cInfo._supportedHostKeyAlgorithms = host_key;
            _cInfo._algorithmForHostKeyVerification = DecideHostKeyAlgorithm(host_key);

            tmpdata = re.ReadString();
            string enc_cs = enc.GetString(tmpdata, 0, tmpdata.Length);
            _cInfo._supportedCipherAlgorithms = enc_cs;
            _cInfo._algorithmForTransmittion = DecideCipherAlgorithm(enc_cs);

            tmpdata = re.ReadString();
            string enc_sc = enc.GetString(tmpdata, 0, tmpdata.Length);
            _cInfo._algorithmForReception = DecideCipherAlgorithm(enc_sc);

            tmpdata = re.ReadString();
            string mac_cs = enc.GetString(tmpdata, 0, tmpdata.Length);
            CheckAlgorithmSupport("mac", mac_cs, "hmac-sha1");

            tmpdata = re.ReadString();
            string mac_sc = enc.GetString(tmpdata, 0, tmpdata.Length);
            CheckAlgorithmSupport("mac", mac_sc, "hmac-sha1");

            tmpdata = re.ReadString();
            string comp_cs = enc.GetString(tmpdata, 0, tmpdata.Length);
            CheckAlgorithmSupport("compression", comp_cs, "none");
            tmpdata = re.ReadString();
            string comp_sc = enc.GetString(tmpdata, 0, tmpdata.Length);
            CheckAlgorithmSupport("compression", comp_sc, "none");

            tmpdata = re.ReadString();
            string lang_cs = enc.GetString(tmpdata, 0, tmpdata.Length);
            tmpdata = re.ReadString();
            string lang_sc = enc.GetString(tmpdata, 0, tmpdata.Length);
            bool flag = re.ReadBool();
            int reserved = re.ReadInt32();
            Debug.Assert(re.Rest==0);
            if(flag) throw new Exception(resLoader.GetString("AlgNegotiationFailed"));
        }
예제 #5
0
        private static int GetIntegerSize(SSH2DataReader binr)
        {
            byte bt = 0;
            byte lowbyte = 0x00;
            byte highbyte = 0x00;
            int count = 0;
            bt = binr.ReadByte();
            if (bt != 0x02)		//expect integer
                return 0;
            bt = binr.ReadByte();

            if (bt == 0x81)
                count = binr.ReadByte();	// data size in next byte
            else
                if (bt == 0x82)
                {
                    highbyte = binr.ReadByte();	// data size in next 2 bytes
                    lowbyte = binr.ReadByte();
                    byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
                    count = BitConverter.ToInt32(modint, 0);
                }
                else
                {
                    count = bt;		// we already have the data size
                }

            while (binr.ReadByte() == 0x00)
            {	//remove high order zeros in data
                count -= 1;
            }
            binr.Seek(-1);		//last ReadByte wasn't a removed zero, so back up a byte
            return count;
        }
예제 #6
0
        private void VerifyHostKeyByDSS(SSH2DataReader pubkey, byte[] sigbody, byte[] hash)
        {
            BigInteger p = pubkey.ReadMPInt();
            BigInteger q = pubkey.ReadMPInt();
            BigInteger g = pubkey.ReadMPInt();
            BigInteger y = pubkey.ReadMPInt();
            Debug.Assert(pubkey.Rest==0);

            //Debug.WriteLine(p.ToHexString());
            //Debug.WriteLine(q.ToHexString());
            //Debug.WriteLine(g.ToHexString());
            //Debug.WriteLine(y.ToHexString());

            DSAPublicKey pk = new DSAPublicKey(p,g,q,y);
            pk.Verify(sigbody, HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha1).HashData(hash.AsBuffer()).ToArray());
            _cInfo._hostkey = pk;
        }
예제 #7
0
        private AuthenticationResult ProcessAuthenticationResponse()
        {
            do {
                SSH2DataReader response = new SSH2DataReader(ReceivePacket().Data);
                PacketType h = response.ReadPacketType();
                if(h==PacketType.SSH_MSG_USERAUTH_FAILURE) {
                    byte[] tmpdata = response.ReadString();
                    string msg = Encoding.UTF8.GetString(tmpdata,0,tmpdata.Length);
                    _eventReceiver.OnDebugMessage(true, tmpdata);
                    bool partialSuccess = response.ReadBool();
                    return GranadosRT.Routrek.SSHC.AuthenticationResult.Failure;
                }
                else if(h==PacketType.SSH_MSG_USERAUTH_BANNER) {
                    //Debug.WriteLine("USERAUTH_BANNER");
                    byte[] tmpdata = response.ReadString();
                    _eventReceiver.OnDebugMessage(true, tmpdata);
                }
                else if(h==PacketType.SSH_MSG_USERAUTH_SUCCESS) {
                    _packetBuilder.Handler = new CallbackSSH2PacketHandler(this);
                    return GranadosRT.Routrek.SSHC.AuthenticationResult.Success; //successfully exit
                }
                else if (h == PacketType.SSH_MSG_USERAUTH_INFO_REQUEST)
                {
                    byte[] tmpdata = response.ReadString();
                    string name = Encoding.UTF8.GetString(tmpdata, 0, tmpdata.Length);
                    tmpdata = response.ReadString();
                    string inst = Encoding.UTF8.GetString(tmpdata, 0, tmpdata.Length);
                    tmpdata = response.ReadString();
                    string lang = Encoding.UTF8.GetString(tmpdata, 0, tmpdata.Length);
                    int num = response.ReadInt32();
                    string[] prompts = new string[num];
                    for (int i = 0; i < num; i++)
                    {
                        tmpdata = response.ReadString();
                        prompts[i] = Encoding.UTF8.GetString(tmpdata, 0, tmpdata.Length);
                        bool echo = response.ReadBool();
                    }
                    if (prompts.Length == 0)
                    {
                        //TODO 0 length response
                        SSH2DataWriter re = new SSH2DataWriter();
                        re.WritePacketType(PacketType.SSH_MSG_USERAUTH_INFO_RESPONSE);
                        re.Write(0);
                        byte[] ba = re.ToByteArray();
                        TransmitPacket(ba);

                        return ProcessAuthenticationResponse();
                    }
                    else
                    {
                        _eventReceiver.OnAuthenticationPrompt(prompts);
                        return GranadosRT.Routrek.SSHC.AuthenticationResult.Prompt;
                    }
                }
                else
                {
                    //throw new Exception(resLoader.GetString("ProtocolError") + resLoader.GetString("UnexpectedPacket") + h);
                }
            } while(true);
        }
예제 #8
0
        /*
         * Format style note
         *  ---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----
         *  Comment: *******
         *  <base64-encoded body>
         *  ---- END SSH2 ENCRYPTED PRIVATE KEY ----
         *
         *  body = MAGIC_VAL || body-length || type(string) || encryption-algorithm-name(string) || encrypted-body(string)
         *  encrypted-body = array of BigInteger(algorithm-specific)
         */
        internal static SSH2UserAuthKey FromRSAOpenSSHStyleStream(StreamReader r, string passphrase)
        {
            string l = r.ReadLine();
            StringBuilder buf = new StringBuilder();
            while (l != "-----END RSA PRIVATE KEY-----")
            {
                if (l.IndexOf(':') == -1)
                    buf.Append(l);
                else
                {
                    while (l.EndsWith("\\")) l = r.ReadLine();
                }
                l = r.ReadLine();
                if (l == null) throw new Exception(resLoader.GetString("BrokenKeyFile"));
            }
            //r.Close();

            byte[] keydata = CryptographicBuffer.DecodeFromBase64String(buf.ToString()).ToArray();
            if (passphrase != "")
            {
                r.BaseStream.Seek(0, SeekOrigin.Begin);
                r.ReadLine();//Get rid of header
                if (!r.ReadLine().StartsWith("Proc-Type: 4,ENCRYPTED"))
                    throw new Exception(resLoader.GetString("KeyFormatUnsupported"));
                String saltline = r.ReadLine();
                if (!saltline.StartsWith("DEK-Info: DES-EDE3-CBC,"))
                    throw new Exception(resLoader.GetString("KeyFormatUnsupported"));
                String saltstr = saltline.Substring(saltline.IndexOf(",") + 1).Trim();
                byte[] salt = new byte[saltstr.Length / 2];
                for (int i = 0; i < salt.Length; i++)
                    salt[i] = Convert.ToByte(saltstr.Substring(i * 2, 2), 16);
                byte[] deskey = GetOpenSSL3deskey(salt, passphrase, 1, 2);
                if (deskey == null)
                    return null;
                byte[] rsakey = DecryptKey(keydata, deskey, salt);
                keydata = rsakey;
            }
            r.Dispose();

            SSH2DataReader re = new SSH2DataReader(keydata);
            int magic = re.ReadInt16();
            if (magic != OPEN_SSH_MAGIC_VAL) throw new Exception(resLoader.GetString("BrokenKeyFile"));
            int length = re.ReadInt16();
            //Version
            re.ReadByte(); // tag: 2
            re.ReadByte(); // stored length: 1
            int version = (int)re.ReadByte(); // 0
            //Modulus
            length = GetIntegerSize(re); // tag: 2
            BigInteger n = new BigInteger(re.Read(length));
            length = GetIntegerSize(re); // tag: 2
            BigInteger e = new BigInteger(re.Read(length));
            length = GetIntegerSize(re); // tag: 2
            BigInteger d = new BigInteger(re.Read(length));
            length = GetIntegerSize(re); // tag: 2
            BigInteger p = new BigInteger(re.Read(length));
            length = GetIntegerSize(re); // tag: 2
            BigInteger q = new BigInteger(re.Read(length));
            //u ?? is not stored? calculated in special constructor
            /*
            length = GetIntegerSize(re); // tag: 2
            BigInteger u = re.ReadASNBigInt();
            */
            return new SSH2UserAuthKey(new RSAKeyPair(n, e, d, p, q));
        }
예제 #9
0
 private void ReceivePortForwardingResponse(ISSHChannelEventReceiver receiver, PacketType pt, SSH2DataReader reader)
 {
     if(_negotiationStatus==1) {
         if(pt!=PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
             if(pt!=PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE)
                 receiver.OnChannelError(null, "opening channel failed; packet type="+pt);
             else {
                 int errcode = reader.ReadInt32();
                 byte[] tmpdata = reader.ReadString();
                 string msg = Encoding.UTF8.GetString(tmpdata, 0, tmpdata.Length);
                 receiver.OnChannelError(null, msg);
             }
             Close();
         }
         else {
             _remoteID = reader.ReadInt32();
             _serverMaxPacketSize = reader.ReadInt32();
             _negotiationStatus = 0;
             receiver.OnChannelReady();
         }
     }
     else
         Debug.Assert(false);
 }
예제 #10
0
 //synchronous reception
 internal SSH2Packet ReceivePacket()
 {
     while(true) {
         SSH2Packet p = null;
         SynchronizedSSH2PacketHandler handler = (SynchronizedSSH2PacketHandler)_packetBuilder.Handler;
         try
         {
             if (!handler.HasPacket)
             {
                 handler.Wait();
                 if (handler.State == ReceiverState.Error)
                     throw new Exception(handler.ErrorMessage);
                 else if (handler.State == ReceiverState.Closed)
                     throw new Exception(resLoader.GetString("SocketClosed"));
             }
             p = handler.PopPacket();
         }
         catch (Exception e)
         {
             _eventReceiver.OnError(e, e.Message);
             return p;
         }
         SSH2DataReader r = new SSH2DataReader(p.Data);
         PacketType pt = r.ReadPacketType();
         if(pt==PacketType.SSH_MSG_IGNORE) {
             if(_eventReceiver!=null) _eventReceiver.OnIgnoreMessage(r.ReadString());
         }
         else if(pt==PacketType.SSH_MSG_DEBUG) {
             bool f = r.ReadBool();
             if(_eventReceiver!=null) _eventReceiver.OnDebugMessage(f, r.ReadString());
         }
         else
             return p;
     }
 }
예제 #11
0
        private void OpenShell(ISSHChannelEventReceiver receiver, PacketType pt, SSH2DataReader reader)
        {
            if(_negotiationStatus==3) {
                if(pt!=PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
                    if(pt!=PacketType.SSH_MSG_CHANNEL_OPEN_FAILURE)
                        receiver.OnChannelError(null, "opening channel failed; packet type="+pt);
                    else {
                        int errcode = reader.ReadInt32();
                        byte[] tmpdata = reader.ReadString();
                        string msg = Encoding.UTF8.GetString(tmpdata, 0, tmpdata.Length);
                        receiver.OnChannelError(null, msg);
                    }
                    Close();
                }
                else {
                    _remoteID = reader.ReadInt32();
                    _serverMaxPacketSize = reader.ReadInt32();

                    //open pty
                    SSH2DataWriter wr = new SSH2DataWriter();
                    wr.WritePacketType(PacketType.SSH_MSG_CHANNEL_REQUEST);
                    wr.Write(_remoteID);
                    wr.Write("pty-req");
                    wr.Write(true);
                    wr.Write(_connection.Param().TerminalName);
                    wr.Write(_connection.Param().TerminalWidth);
                    wr.Write(_connection.Param().TerminalHeight);
                    wr.Write(_connection.Param().TerminalPixelWidth);
                    wr.Write(_connection.Param().TerminalPixelHeight);
                    wr.WriteAsString(new byte[0]);
                    TransmitPacket(wr.ToByteArray());

                    _negotiationStatus = 2;
                }
            }
            else if(_negotiationStatus==2) {
                if(pt!=PacketType.SSH_MSG_CHANNEL_SUCCESS) {
                    receiver.OnChannelError(null, "opening pty failed");
                    Close();
                }
                else {
                    //open shell
                    SSH2DataWriter wr = new SSH2DataWriter();
                    wr.Write((byte)PacketType.SSH_MSG_CHANNEL_REQUEST);
                    wr.Write(_remoteID);
                    wr.Write("shell");
                    wr.Write(true);
                    TransmitPacket(wr.ToByteArray());

                    _negotiationStatus = 1;
                }
            }
            else if(_negotiationStatus==1) {
                if(pt!=PacketType.SSH_MSG_CHANNEL_SUCCESS) {
                    receiver.OnChannelError(null, "Opening shell failed: packet type="+pt.ToString());
                    Close();
                }
                else {
                    receiver.OnChannelReady();
                    _negotiationStatus = 0; //goal!
                }
            }
            else
                Debug.Assert(false);
        }
예제 #12
0
        internal void ProcessPacket(ISSHChannelEventReceiver receiver, PacketType pt, int data_length, SSH2DataReader re)
        {
            //NOTE: the offset of 're' is next to 'receipiant channel' field
            _leftWindowSize -= data_length;
            if (_negotiationStatus < 1)
            {
                while (_leftWindowSize <= _windowSize)
                {
                    SSH2DataWriter adj = new SSH2DataWriter();
                    adj.WritePacketType(PacketType.SSH_MSG_CHANNEL_WINDOW_ADJUST);
                    adj.Write(_remoteID);
                    adj.Write(_windowSize);
                    TransmitPacket(adj.ToByteArray());
                    _leftWindowSize += _windowSize;
                    Debug.WriteLine("Window size is adjusted to " + _leftWindowSize);
                }
            }
            if(pt==PacketType.SSH_MSG_CHANNEL_WINDOW_ADJUST) {
                int w = re.ReadInt32();
                //Debug.WriteLine(String.Format("Window Adjust +={0}",w));
            }
            else if(_negotiationStatus!=0) { //when the negotiation is not completed
                if(_type==ChannelType.Shell)
                    OpenShell(receiver, pt, re);
                else if(_type==ChannelType.ForwardedLocalToRemote)
                    ReceivePortForwardingResponse(receiver, pt, re);
                else if(_type==ChannelType.Session)
                    EstablishSession(receiver, pt, re);
            }
            else {
                switch(pt) {
                    case PacketType.SSH_MSG_CHANNEL_DATA: {
                        int len = re.ReadInt32();
                        //await receiver.OnData(re.Image, re.Offset, len);
                        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: {
                        byte[] tmpdata = re.ReadString();
                        string request = Encoding.UTF8.GetString(tmpdata, 0, tmpdata.Length);
                        bool reply = re.ReadBool();
                        if(request=="exit-status") {
                            int status = re.ReadInt32();
                        }
                    }
                        break;
                    case PacketType.SSH_MSG_CHANNEL_EOF:
                        receiver.OnChannelEOF();
                        break;
                    case PacketType.SSH_MSG_CHANNEL_CLOSE:
                        _connection.UnregisterChannelEventReceiver(_localID);
                        receiver.OnChannelClosed();
                        break;
                    case PacketType.SSH_MSG_CHANNEL_FAILURE:
                    case PacketType.SSH_MSG_CHANNEL_SUCCESS:
                        receiver.OnMiscPacket((byte)pt, re.Image, re.Offset, re.Rest);
                        break;
                    default:
                        receiver.OnMiscPacket((byte)pt, re.Image, re.Offset, re.Rest);
                        Debug.WriteLine(resLoader.GetString("UnexpectedPacket")+pt);
                        break;
                }

            }
        }
예제 #13
0
        private void VerifyHostKeyByRSA(SSH2DataReader pubkey, byte[] sigbody, byte[] hash)
        {
            BigInteger exp = pubkey.ReadMPInt();
            BigInteger mod = pubkey.ReadMPInt();
            Debug.Assert(pubkey.Rest==0);

            //Debug.WriteLine(exp.ToHexString());
            //Debug.WriteLine(mod.ToHexString());

            RSAPublicKey pk = new RSAPublicKey(exp, mod);
            pk.VerifyWithSHA1(sigbody, HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha1).HashData(hash.AsBuffer()).ToArray());
            _cInfo._hostkey = pk;
        }
예제 #14
0
        /*
         * Format style note
         *  ---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----
         *  Comment: *******
         *  <base64-encoded body>
         *  ---- END SSH2 ENCRYPTED PRIVATE KEY ----
         *
         *  body = MAGIC_VAL || body-length || type(string) || encryption-algorithm-name(string) || encrypted-body(string)
         *  encrypted-body = array of BigInteger(algorithm-specific)
         */
        internal static SSH2UserAuthKey FromRSAOpenSSHStyleStream(StreamReader r, string passphrase)
        {
            string        l   = r.ReadLine();
            StringBuilder buf = new StringBuilder();

            while (l != "-----END RSA PRIVATE KEY-----")
            {
                if (l.IndexOf(':') == -1)
                {
                    buf.Append(l);
                }
                else
                {
                    while (l.EndsWith("\\"))
                    {
                        l = r.ReadLine();
                    }
                }
                l = r.ReadLine();
                if (l == null)
                {
                    throw new Exception(resLoader.GetString("BrokenKeyFile"));
                }
            }
            //r.Close();

            byte[] keydata = CryptographicBuffer.DecodeFromBase64String(buf.ToString()).ToArray();
            if (passphrase != "")
            {
                r.BaseStream.Seek(0, SeekOrigin.Begin);
                r.ReadLine();//Get rid of header
                if (!r.ReadLine().StartsWith("Proc-Type: 4,ENCRYPTED"))
                {
                    throw new Exception(resLoader.GetString("KeyFormatUnsupported"));
                }
                String saltline = r.ReadLine();
                if (!saltline.StartsWith("DEK-Info: DES-EDE3-CBC,"))
                {
                    throw new Exception(resLoader.GetString("KeyFormatUnsupported"));
                }
                String saltstr = saltline.Substring(saltline.IndexOf(",") + 1).Trim();
                byte[] salt    = new byte[saltstr.Length / 2];
                for (int i = 0; i < salt.Length; i++)
                {
                    salt[i] = Convert.ToByte(saltstr.Substring(i * 2, 2), 16);
                }
                byte[] deskey = GetOpenSSL3deskey(salt, passphrase, 1, 2);
                if (deskey == null)
                {
                    return(null);
                }
                byte[] rsakey = DecryptKey(keydata, deskey, salt);
                keydata = rsakey;
            }
            r.Dispose();


            SSH2DataReader re    = new SSH2DataReader(keydata);
            int            magic = re.ReadInt16();

            if (magic != OPEN_SSH_MAGIC_VAL)
            {
                throw new Exception(resLoader.GetString("BrokenKeyFile"));
            }
            int length = re.ReadInt16();

            //Version
            re.ReadByte();                    // tag: 2
            re.ReadByte();                    // stored length: 1
            int version = (int)re.ReadByte(); // 0

            //Modulus
            length = GetIntegerSize(re); // tag: 2
            BigInteger n = new BigInteger(re.Read(length));

            length = GetIntegerSize(re); // tag: 2
            BigInteger e = new BigInteger(re.Read(length));

            length = GetIntegerSize(re); // tag: 2
            BigInteger d = new BigInteger(re.Read(length));

            length = GetIntegerSize(re); // tag: 2
            BigInteger p = new BigInteger(re.Read(length));

            length = GetIntegerSize(re); // tag: 2
            BigInteger q = new BigInteger(re.Read(length));

            //u ?? is not stored? calculated in special constructor

            /*
             * length = GetIntegerSize(re); // tag: 2
             * BigInteger u = re.ReadASNBigInt();
             */
            return(new SSH2UserAuthKey(new RSAKeyPair(n, e, d, p, q)));
        }
예제 #15
0
        private bool ProcessPacket(SSH2Packet packet)
        {
            //Debug.WriteLine("ProcessPacket pt="+pt);
            SSH2DataReader r = new SSH2DataReader(packet.Data);
            PacketType pt = r.ReadPacketType();

            if(pt==PacketType.SSH_MSG_DISCONNECT) {
                int errorcode = r.ReadInt32();
                byte[] tmpdata = r.ReadString();
                string description = Encoding.UTF8.GetString(tmpdata, 0 ,tmpdata.Length);
                _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) {
                ProcessPortforwardingRequest(_eventReceiver, r);
                return true;
            }
            else if(pt>=PacketType.SSH_MSG_CHANNEL_OPEN_CONFIRMATION && pt<=PacketType.SSH_MSG_CHANNEL_FAILURE) {
                int local_channel = r.ReadInt32();
                ChannelEntry e = FindChannelEntry(local_channel);
                if(e!=null) //throw new Exception("Unknown channel "+local_channel);
                    ((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;
            }
        }
예제 #16
0
        /*
         * Format style note
         *  ---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----
         *  Comment: *******
         *  <base64-encoded body>
         *  ---- END SSH2 ENCRYPTED PRIVATE KEY ----
         *
         *  body = MAGIC_VAL || body-length || type(string) || encryption-algorithm-name(string) || encrypted-body(string)
         *  encrypted-body = array of BigInteger(algorithm-specific)
         */
        internal static SSH2UserAuthKey FromSECSHStyleStream(StreamReader r, string passphrase)
        {
            string        l   = r.ReadLine();
            StringBuilder buf = new StringBuilder();

            while (l != "---- END SSH2 ENCRYPTED PRIVATE KEY ----")
            {
                if (l.IndexOf(':') == -1)
                {
                    buf.Append(l);
                }
                else
                {
                    while (l.EndsWith("\\"))
                    {
                        l = r.ReadLine();
                    }
                }
                l = r.ReadLine();
                if (l == null)
                {
                    throw new Exception(resLoader.GetString("BrokenKeyFile"));
                }
            }
            //r.Close();
            r.Dispose();

            byte[] keydata = Base64.Decode(Encoding.UTF8.GetBytes(buf.ToString()));

            SSH2DataReader re    = new SSH2DataReader(keydata);
            int            magic = re.ReadInt32();

            if (magic != SSH_COM_MAGIC_VAL)
            {
                throw new Exception(resLoader.GetString("BrokenKeyFile"));
            }
            int privateKeyLen = re.ReadInt32();

            byte[] tmpstr = re.ReadString();
            string type   = Encoding.UTF8.GetString(tmpstr, 0, tmpstr.Length);

            tmpstr = re.ReadString();
            string ciphername = Encoding.UTF8.GetString(tmpstr, 0, tmpstr.Length);
            int    bufLen     = re.ReadInt32();

            if (ciphername != "none")
            {
                CipherAlgorithm algo = CipherFactory.SSH2NameToAlgorithm(ciphername);
                byte[]          key  = PassphraseToKey(passphrase, CipherFactory.GetKeySize(algo));
                Cipher          c    = CipherFactory.CreateCipher(SSHProtocol.SSH2, algo, key);
                byte[]          tmp  = new Byte[re.Image.Length - re.Offset];
                c.Decrypt(re.Image, re.Offset, re.Image.Length - re.Offset, tmp, 0);
                re = new SSH2DataReader(tmp);
            }

            int parmLen = re.ReadInt32();

            if (parmLen < 0 || parmLen > re.Rest)
            {
                throw new Exception(resLoader.GetString("WrongPassphrase"));
            }

            if (type.IndexOf("if-modn") != -1)
            {
                //mindterm mistaken this order of BigIntegers
                BigInteger e = re.ReadBigIntWithBits();
                BigInteger d = re.ReadBigIntWithBits();
                BigInteger n = re.ReadBigIntWithBits();
                BigInteger u = re.ReadBigIntWithBits();
                BigInteger p = re.ReadBigIntWithBits();
                BigInteger q = re.ReadBigIntWithBits();
                return(new SSH2UserAuthKey(new RSAKeyPair(e, d, n, u, p, q)));
            }
            else if (type.IndexOf("dl-modp") != -1)
            {
                if (re.ReadInt32() != 0)
                {
                    throw new Exception(resLoader.GetString("BrokenKeyFile"));
                }
                BigInteger p = re.ReadBigIntWithBits();
                BigInteger g = re.ReadBigIntWithBits();
                BigInteger q = re.ReadBigIntWithBits();
                BigInteger y = re.ReadBigIntWithBits();
                BigInteger x = re.ReadBigIntWithBits();
                return(new SSH2UserAuthKey(new DSAKeyPair(p, g, q, y, x)));
            }
            else
            {
                throw new Exception(resLoader.GetString("KeyFormatUnknown"));
            }
        }
예제 #17
0
        private void ProcessPortforwardingRequest(ISSHConnectionEventReceiver receiver, SSH2DataReader reader)
        {
            byte[] tmpdata = reader.ReadString();
            string method = Encoding.UTF8.GetString(tmpdata, 0, tmpdata.Length);

            int remote_channel = reader.ReadInt32();
            int window_size = reader.ReadInt32(); //skip initial window size
            int servermaxpacketsize = reader.ReadInt32();
            tmpdata = reader.ReadString();
            string host = Encoding.UTF8.GetString(tmpdata, 0, tmpdata.Length);
            int port = reader.ReadInt32();
            tmpdata = reader.ReadString();
            string originator_ip = Encoding.UTF8.GetString(tmpdata, 0, tmpdata.Length);
            int originator_port = reader.ReadInt32();

            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, 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);
            }
            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
            }
            TransmitPacket(wr.ToByteArray());
        }
예제 #18
0
        /*
         * Format style note
         *  ---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----
         *  Comment: *******
         *  <base64-encoded body>
         *  ---- END SSH2 ENCRYPTED PRIVATE KEY ----
         *
         *  body = MAGIC_VAL || body-length || type(string) || encryption-algorithm-name(string) || encrypted-body(string)
         *  encrypted-body = array of BigInteger(algorithm-specific)
         */
        internal static SSH2UserAuthKey FromSECSHStyleStream(StreamReader r, string passphrase)
        {
            string l = r.ReadLine();
            StringBuilder buf = new StringBuilder();
            while(l!="---- END SSH2 ENCRYPTED PRIVATE KEY ----") {
                if(l.IndexOf(':')==-1)
                    buf.Append(l);
                else {
                    while(l.EndsWith("\\")) l = r.ReadLine();
                }
                l = r.ReadLine();
                if (l == null) throw new Exception(resLoader.GetString("BrokenKeyFile"));
            }
            //r.Close();
            r.Dispose();

            byte[] keydata = Base64.Decode(Encoding.UTF8.GetBytes(buf.ToString()));

            SSH2DataReader re = new SSH2DataReader(keydata);
            int    magic         = re.ReadInt32();
            if (magic != SSH_COM_MAGIC_VAL) throw new Exception(resLoader.GetString("BrokenKeyFile"));
            int    privateKeyLen = re.ReadInt32();
            byte[] tmpstr = re.ReadString();
            string type = Encoding.UTF8.GetString(tmpstr, 0, tmpstr.Length);
            tmpstr = re.ReadString();
            string ciphername = Encoding.UTF8.GetString(tmpstr, 0, tmpstr.Length);
            int    bufLen        = re.ReadInt32();
            if(ciphername!="none") {
                CipherAlgorithm algo = CipherFactory.SSH2NameToAlgorithm(ciphername);
                byte[] key = PassphraseToKey(passphrase, CipherFactory.GetKeySize(algo));
                Cipher c = CipherFactory.CreateCipher(SSHProtocol.SSH2, algo, key);
                byte[] tmp = new Byte[re.Image.Length-re.Offset];
                c.Decrypt(re.Image, re.Offset, re.Image.Length-re.Offset, tmp, 0);
                re = new SSH2DataReader(tmp);
            }

            int parmLen          = re.ReadInt32();
            if(parmLen<0 || parmLen>re.Rest)
                throw new Exception(resLoader.GetString("WrongPassphrase"));

            if(type.IndexOf("if-modn")!=-1) {
                //mindterm mistaken this order of BigIntegers
                BigInteger e = re.ReadBigIntWithBits();
                BigInteger d = re.ReadBigIntWithBits();
                BigInteger n = re.ReadBigIntWithBits();
                BigInteger u = re.ReadBigIntWithBits();
                BigInteger p = re.ReadBigIntWithBits();
                BigInteger q = re.ReadBigIntWithBits();
                return new SSH2UserAuthKey(new RSAKeyPair(e, d, n, u, p, q));
            }
            else if(type.IndexOf("dl-modp")!=-1) {
                if (re.ReadInt32() != 0) throw new Exception(resLoader.GetString("BrokenKeyFile"));
                BigInteger p = re.ReadBigIntWithBits();
                BigInteger g = re.ReadBigIntWithBits();
                BigInteger q = re.ReadBigIntWithBits();
                BigInteger y = re.ReadBigIntWithBits();
                BigInteger x = re.ReadBigIntWithBits();
                return new SSH2UserAuthKey(new DSAKeyPair(p, g, q, y, x));
            }
            else
                throw new Exception(resLoader.GetString("KeyFormatUnknown"));
        }
예제 #19
0
        private void ServiceRequest(string servicename)
        {
            SSH2DataWriter wr = new SSH2DataWriter();
            wr.WritePacketType(PacketType.SSH_MSG_SERVICE_REQUEST);
            wr.Write(servicename);
            TransmitPacket(wr.ToByteArray());

            byte[] response = ReceivePacket().Data;
            SSH2DataReader re = new SSH2DataReader(response);
            PacketType t = re.ReadPacketType();
            if(t!=PacketType.SSH_MSG_SERVICE_ACCEPT) {
                throw new Exception("service establishment failed "+t);
            }

            byte[] tmpdata = re.ReadString();
            string s = Encoding.UTF8.GetString(tmpdata,0,tmpdata.Length);
            if(servicename!=s)
                throw new Exception(resLoader.GetString("ProtocolError"));
        }
예제 #20
0
        public static bool IsPrivateKeyEncrypted(string filename)
        {
            bool returnVal = false;
            var fileToLaunch = StorageFile.GetFileFromPathAsync(filename);
            fileToLaunch.AsTask().Wait();
            var streamToLaunch = fileToLaunch.AsTask().Result.OpenStreamForReadAsync();
            streamToLaunch.Wait();
            using (Stream s = streamToLaunch.Result)
            {
                using (StreamReader r = new StreamReader(streamToLaunch.Result, Encoding.UTF8)) {
                    string l = r.ReadLine();
                    if (l == PKCS8_RSA_HEADER)
                    {
                        while (l != "-----END RSA PRIVATE KEY-----")
                        {
                            if (l.IndexOf("Proc-Type: 4,ENCRYPTED") != -1)
                            {
                                returnVal = true;
                                break;
                            }
                            l = r.ReadLine();
                            if (l == null) break;
                        }
                    }
                    else if (l == PKCS8_DSA_HEADER)
                    {
                        while (l != "-----END DSA PRIVATE KEY-----")
                        {
                            if (l.IndexOf("Proc-Type: 4,ENCRYPTED") != -1)
                            {
                                returnVal = true;
                                break;
                            }
                            l = r.ReadLine();
                            if (l == null) break;
                        }
                    }
                    else if (l == SSH_COM_HEADER)
                    {
                        l = r.ReadLine();
                        StringBuilder buf = new StringBuilder();
                        while(l!="---- END SSH2 ENCRYPTED PRIVATE KEY ----") {
                            if(l.IndexOf(':')==-1)
                                buf.Append(l);
                            else {
                                while(l.EndsWith("\\")) l = r.ReadLine();
                            }
                            l = r.ReadLine();
                            if(l==null) break;
                        }
                        byte[] keydata = Base64.Decode(Encoding.UTF8.GetBytes(buf.ToString()));

                        SSH2DataReader re = new SSH2DataReader(keydata);
                        int    magic         = re.ReadInt32();
                        if (magic != SSH_COM_MAGIC_VAL) return false; // Magic number doesn't match so just say false because it will error-out anyway
                        int    privateKeyLen = re.ReadInt32();
                        byte[] tmpstr = re.ReadString();
                        string type = Encoding.UTF8.GetString(tmpstr, 0, tmpstr.Length);
                        tmpstr = re.ReadString();
                        string ciphername = Encoding.UTF8.GetString(tmpstr, 0, tmpstr.Length);
                        int    bufLen        = re.ReadInt32();
                        if (ciphername != "none")
                        {
                            returnVal = true;
                        }
                    }
                    r.Dispose();
                    s.Dispose();
                }
            }
            return returnVal;
        }
예제 #21
0
        private bool VerifyHostKey(byte[] K_S, byte[] signature, byte[] hash)
        {
            SSH2DataReader re1 = new SSH2DataReader(K_S);
            byte[] tmpdata = re1.ReadString();
            string algorithm = Encoding.UTF8.GetString(tmpdata,0,tmpdata.Length);
            if(algorithm!=SSH2Util.PublicKeyAlgorithmName(_cInfo._algorithmForHostKeyVerification))
                throw new Exception("Protocol Error: Host Key Algorithm Mismatch");

            SSH2DataReader re2 = new SSH2DataReader(signature);
            tmpdata = re2.ReadString();
            algorithm = Encoding.UTF8.GetString(tmpdata, 0, tmpdata.Length);
            if(algorithm!=SSH2Util.PublicKeyAlgorithmName(_cInfo._algorithmForHostKeyVerification))
                throw new Exception("Protocol Error: Host Key Algorithm Mismatch");
            byte[] sigbody = re2.ReadString();
            Debug.Assert(re2.Rest==0);

            if(_cInfo._algorithmForHostKeyVerification==PublicKeyAlgorithm.RSA)
                VerifyHostKeyByRSA(re1, sigbody, hash);
            else if(_cInfo._algorithmForHostKeyVerification==PublicKeyAlgorithm.DSA)
                VerifyHostKeyByDSS(re1, sigbody, hash);
            else
                throw new Exception("Bad host key algorithm "+_cInfo._algorithmForHostKeyVerification);

            //ask the client whether he accepts the host key
            if(!_startedByHost && _param.KeyCheck!=null && !_param.KeyCheck(_cInfo))
                return false;
            else
                return true;
        }