Пример #1
0
        private void HandleMessage(PublicKeyRequestMessage message)
        {
            if (Session._publicKeyAlgorithms.ContainsKey(message.KeyAlgorithmName))
            {
                var verifed = false;

                var keyAlg = Session._publicKeyAlgorithms[message.KeyAlgorithmName](null);
                keyAlg.LoadKeyAndCertificatesData(message.PublicKey);

                var args = new PKUserAuthArgs(base._session, message.Username, message.KeyAlgorithmName, keyAlg.GetFingerprint(), message.PublicKey);
                UserAuth?.Invoke(this, args);
                verifed = args.Result;

                if (!verifed)
                {
                    _session.SendMessage(new FailureMessage());
                    return;
                }

                if (!message.HasSignature)
                {
                    _session.SendMessage(new PublicKeyOkMessage {
                        KeyAlgorithmName = message.KeyAlgorithmName, PublicKey = message.PublicKey
                    });
                    return;
                }

                var sig = keyAlg.GetSignature(message.Signature);

                using (var worker = new SshDataWorker())
                {
                    worker.WriteBinary(_session.SessionId);
                    worker.Write(message.PayloadWithoutSignature);

                    verifed = keyAlg.VerifyData(worker.ToByteArray(), sig);
                }

                if (verifed && UserAuth != null)
                {
                    UserAuth(this, args);
                    verifed = args.Result;
                }

                if (verifed)
                {
                    _session.RegisterService(message.ServiceName, args);
                    Succeed?.Invoke(this, message.ServiceName);
                    _session.SendMessage(new SuccessMessage());
                    return;
                }
                else
                {
                    _session.SendMessage(new FailureMessage());
                    //throw new SshConnectionException("Authentication fail.", DisconnectReason.NoMoreAuthMethodsAvailable);
                }
            }
        }
Пример #2
0
        public byte[] GetPacket()
        {
            using (var worker = new SshDataWorker()) {
                worker.Write(this.MessageType);

                this.OnGetPacket(worker);

                return(worker.ToByteArray());
            }
        }
Пример #3
0
        private void SendStatus(uint requestId, SftpStatusType status)
        {
            SshDataWorker writer = new SshDataWorker();

            writer.Write((byte)RequestPacketType.SSH_FXP_STATUS);
            writer.Write(requestId);
            writer.Write((uint)status); // status code
            //writer.Write("", Encoding.UTF8);
            //writer.Write("", Encoding.UTF8);
            SendPacket(writer.ToByteArray());
        }
Пример #4
0
        private void SendAttributes(uint requestId, string path)
        {
            SshDataWorker writer = new SshDataWorker();

            writer.Write((byte)RequestPacketType.SSH_FXP_ATTRS);
            writer.Write(requestId);

            writer.Write(GetAttributes(path));

            SendPacket(writer.ToByteArray());
        }
Пример #5
0
        public override byte[] CreateKeyAndCertificatesData()
        {
            using (var worker = new SshDataWorker()) {
                var args = this.algorithm.ExportParameters(false);

                worker.Write(this.Name, Encoding.ASCII);
                worker.WriteMpint(args.Exponent);
                worker.WriteMpint(args.Modulus);

                return(worker.ToByteArray());
            }
        }
Пример #6
0
        public override byte[] CreateKeyAndCertificatesData()
        {
            using (var worker = new SshDataWorker())
            {
                var args = _algorithm.ExportParameters(false);

                worker.Write(this.Name, Encoding.ASCII);
                worker.WriteMpint(args.Exponent);
                worker.WriteMpint(args.Modulus);

                return worker.ToByteArray();
            }
        }
        public byte[] CreateSignatureData(byte[] data)
        {
            Contract.Requires(data != null);

            using (var worker = new SshDataWorker()) {
                var signature = this.SignData(data);

                worker.Write(this.Name, Encoding.ASCII);
                worker.WriteBinary(signature);

                return(worker.ToByteArray());
            }
        }
Пример #8
0
        public byte[] CreateSignatureData(byte[] data)
        {
            Contract.Requires(data != null);

            using (var worker = new SshDataWorker())
            {
                var signature = SignData(data);

                worker.Write(this.Name, Encoding.ASCII);
                worker.WriteBinary(signature);

                return worker.ToByteArray();
            }
        }
Пример #9
0
        /// <summary>
        /// calculates and add packet length uint to the beginning of the packet
        /// </summary>
        /// <param name="data"></param>
        internal void SendPacket(byte[] data)
        {
            var           packettosend       = data.ToList();
            var           length             = packettosend.Count();
            SshDataWorker packetlengthwriter = new SshDataWorker();

            packetlengthwriter.Write((uint)length);
            packettosend.InsertRange(0, packetlengthwriter.ToByteArray());

            if (OnOutput != null)
            {
                OnOutput(this, packettosend);
            }
        }
Пример #10
0
        private void HandleMessage(PublicKeyRequestMessage message)
        {
            if (Session._publicKeyAlgorithms.ContainsKey(message.KeyAlgorithmName))
            {
                if (!message.HasSignature)
                {
                    _session.SendMessage(new PublicKeyOkMessage { KeyAlgorithmName = message.KeyAlgorithmName, PublicKey = message.PublicKey });
                    return;
                }

                var keyAlg = Session._publicKeyAlgorithms[message.KeyAlgorithmName](null);
                keyAlg.LoadKeyAndCertificatesData(message.PublicKey);

                var sig = keyAlg.GetSignature(message.Signature);
                var verifed = false;

                using (var worker = new SshDataWorker())
                {
                    worker.WriteBinary(_session.SessionId);
                    worker.Write(message.PayloadWithoutSignature);

                    verifed = keyAlg.VerifyData(worker.ToByteArray(), sig);
                }

                var args = new UserauthArgs(message.KeyAlgorithmName, keyAlg.GetFingerprint(), message.PublicKey);
                if (verifed && Userauth != null)
                {
                    Userauth(this, args);
                    verifed = args.Result;
                }

                if (verifed)
                {
                    _session.RegisterService(message.ServiceName, args);
                    if (Succeed != null)
                        Succeed(this, message.ServiceName);
                    _session.SendMessage(new SuccessMessage());
                    return;
                }
                else
                {
                    _session.SendMessage(new FailureMessage());
                    throw new SshConnectionException("Authentication fail.", DisconnectReason.NoMoreAuthMethodsAvailable);
                }
            }
            _session.SendMessage(new FailureMessage());
        }
Пример #11
0
        private byte[] GetAttributes(string path)
        {
            SshDataWorker writer = new SshDataWorker();

            writer.Write(uint.MaxValue);                 // flags
            writer.Write((ulong)10);                     // size
            writer.Write(uint.MaxValue);                 // uid
            writer.Write(uint.MaxValue);                 // gid
            writer.Write(uint.MaxValue);                 // permissions
            writer.Write(GetUnixFileTime(DateTime.Now)); //atime
            writer.Write(GetUnixFileTime(DateTime.Now)); //mtime
            writer.Write((uint)0);                       // extended_count
                                                         //string   extended_type blank
                                                         //string   extended_data blank

            return(writer.ToByteArray());
        }
Пример #12
0
        private byte[] GetFileWithAttributes(System.IO.FileInfo file)
        {
            SshDataWorker writer = new SshDataWorker();

            writer.Write(file.Name, Encoding.UTF8);
            writer.Write($"-rwxr-xr-x   1 foo     foo      {file.Length} Mar 25 14:29 " + file.Name, Encoding.UTF8);
            writer.Write(uint.MaxValue);                        // flags
            writer.Write((ulong)10);                            // size
            writer.Write(uint.MaxValue);                        // uid
            writer.Write(uint.MaxValue);                        // gid
            writer.Write(uint.MaxValue);                        // permissions
            writer.Write(GetUnixFileTime(file.LastAccessTime)); //atime
            writer.Write(GetUnixFileTime(file.LastWriteTime));  //mtime
            writer.Write((uint)0);                              // extended_count
                                                                //string   extended_type blank
                                                                //string   extended_data blank

            return(writer.ToByteArray());
        }
Пример #13
0
        private void HandleMessage(PublicKeyRequestMessage message)
        {
            if (this.Session.AuthenticationMethods == null ||
                !this.Session.AuthenticationMethods.ContainsKey(AuthenticationMethod.PublicKey) ||
                !Session.PublicKeyAlgorithms.ContainsKey(message.KeyAlgorithmName))
            {
                this.Session.SendMessage(new FailureMessage());
                throw new SshConnectionException("Authentication fail.",
                                                 DisconnectReason.NoMoreAuthMethodsAvailable);
            }

            if (!message.HasSignature)
            {
                this.Session.SendMessage(new PublicKeyOkMessage {
                    KeyAlgorithmName = message.KeyAlgorithmName,
                    PublicKey        = message.PublicKey
                });
                return;
            }

            var keyAlg = Session.PublicKeyAlgorithms[message.KeyAlgorithmName](null);

            keyAlg.LoadKeyAndCertificatesData(message.PublicKey);
            var  sig = keyAlg.GetSignature(message.Signature);
            bool verifed;

            using (var worker = new SshDataWorker()) {
                worker.WriteBinary(this.Session.SessionId);
                worker.Write(message.PayloadWithoutSignature);
                verifed = keyAlg.VerifyData(worker.ToByteArray(), sig);
            }

            var args = new UserauthArgs(message.KeyAlgorithmName, keyAlg.GetFingerprint(), message.PublicKey);

            if (verifed && this.Userauth != null)
            {
                this.Userauth(this, args);
                verifed = args.Result;
            }

            if (!verifed)
            {
                this.Session.SendMessage(new FailureMessage());
                throw new SshConnectionException("Authentication fail.",
                                                 DisconnectReason.NoMoreAuthMethodsAvailable);
            }

            if (this.Session.clientKeyRepository != null &&
                this.Session.clientKeyRepository.GetKeyForClient(this.Username) != null)
            {
                var clientKey  = Encoding.ASCII.GetString(this.Session.clientKeyRepository.GetKeyForClient(this.Username));
                var messageKey = System.Convert.ToBase64String(message.PublicKey);
                if (clientKey == messageKey)
                {
                    this.AuthenticationSuccessful(message, args, AuthenticationMethod.PublicKey);
                    return;
                }
            }
            else
            {
                this.AuthenticationSuccessful(message, args, AuthenticationMethod.PublicKey);
                return;
            }

            throw new SshConnectionException("Authentication fail.",
                                             DisconnectReason.NoMoreAuthMethodsAvailable);
        }
Пример #14
0
        internal void OnInput(byte[] ee)
        {
            var input = Encoding.ASCII.GetString(ee);

            //uint32 length
            //byte type
            //byte[length - 1] data payload
            SshDataWorker reader = new SshDataWorker(ee);
            SshDataWorker writer = new SshDataWorker();

            if (reader.DataAvailable >= 5)
            {
                var msglength = reader.ReadUInt32();
                var msgtype   = (RequestPacketType)(int)reader.ReadByte();

                uint   requestId    = 0;
                string path         = "";
                string absolutepath = "";
                string handle       = Guid.NewGuid().ToString().Replace("-", "");

                switch (msgtype)
                {
                case RequestPacketType.SSH_FXP_INIT:
                    var sftpclientversion = reader.ReadUInt32();
                    writer.Write((byte)RequestPacketType.SSH_FXP_VERSION);
                    var version = Math.Max(3, sftpclientversion);
                    writer.Write((uint)version);     // SFTP protocol version
                    SendPacket(writer.ToByteArray());
                    break;

                case RequestPacketType.SSH_FXP_REALPATH:

                    requestId = reader.ReadUInt32();
                    path      = reader.ReadString(Encoding.UTF8);
                    // List files in root directory for this user
                    // foreach file create a response message
                    if (path == ".")
                    {
                        path = "/";     // replace with current filepath
                    }
                    writer.Write((byte)RequestPacketType.SSH_FXP_NAME);
                    writer.Write((uint)requestId);
                    writer.Write((uint)1);
                    // Dummy file for SSH_FXP_REALPATH request
                    writer.Write(path, Encoding.UTF8);
                    writer.Write(@"-rwxr-xr-x   1 mjos     staff      348911 Mar 25 14:29 " + path, Encoding.UTF8);

                    writer.Write((uint)requestId);
                    writer.Write(uint.MaxValue);                 // flags
                    writer.Write((ulong)0);                      // size
                    writer.Write(uint.MaxValue);                 // uid
                    writer.Write(uint.MaxValue);                 // gid
                    writer.Write(uint.MaxValue);                 // permissions
                    writer.Write(GetUnixFileTime(DateTime.Now)); //atime
                    writer.Write(GetUnixFileTime(DateTime.Now)); //mtime
                    writer.Write((uint)0);                       // extended_count
                                                                 //string   extended_type blank
                                                                 //string   extended_data blank


                    SendPacket(writer.ToByteArray());

                    break;

                case RequestPacketType.SSH_FXP_READDIR:
                    requestId = reader.ReadUInt32();
                    handle    = reader.ReadString(Encoding.UTF8);

                    if (HandleToPathDictionary.ContainsKey(handle))     // remove after handle is used first time
                    {
                        var relativepath = HandleToPathDictionary[handle];
                        absolutepath = UserRootDirectory + relativepath;

                        System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(absolutepath);
                        var allfiles = di.GetFiles();

                        // returns SSH_FXP_NAME or SSH_FXP_STATUS with SSH_FX_EOF
                        writer.Write((byte)RequestPacketType.SSH_FXP_NAME);
                        writer.Write((uint)requestId);
                        writer.Write((uint)allfiles.Count());     // all files at the same time

                        foreach (var file in allfiles)
                        {
                            writer.Write(GetFileWithAttributes(file));
                        }

                        SendPacket(writer.ToByteArray());

                        HandleToPathDictionary.Remove(handle);     // remove will return EOF next time
                    }
                    else
                    {
                        // return SSH_FXP_STATUS indicating SSH_FX_EOF  when all files have been listed
                        writer.Write((byte)RequestPacketType.SSH_FXP_STATUS);
                        writer.Write((uint)requestId);
                        writer.Write((uint)SftpStatusType.SSH_FX_EOF);     // status code
                        //writer.Write("", Encoding.UTF8);
                        //writer.Write("", Encoding.UTF8);
                        SendPacket(writer.ToByteArray());
                    }

                    break;

                case RequestPacketType.SSH_FXP_OPENDIR:
                    requestId = reader.ReadUInt32();
                    path      = reader.ReadString(Encoding.UTF8);

                    HandleToPathDictionary.Add(handle, path);

                    writer.Write((byte)RequestPacketType.SSH_FXP_HANDLE);
                    writer.Write((uint)requestId);
                    writer.Write(handle, Encoding.UTF8);
                    // returns SSH_FXP_HANDLE on success or a SSH_FXP_STATUS message on fail

                    SendPacket(writer.ToByteArray());

                    _logger.LogInformation($"sftp command {msgtype} request Id: \"{requestId}\". path: {path} on channel: {channel}");

                    break;

                case RequestPacketType.SSH_FXP_STAT:     // follows symbolic links
                case RequestPacketType.SSH_FXP_LSTAT:    // does not follow symbolic links
                    requestId = reader.ReadUInt32();
                    path      = reader.ReadString(Encoding.UTF8);

                    SendAttributes(requestId, path);

                    break;

                case RequestPacketType.SSH_FXP_FSTAT:     // SSH_FXP_FSTAT differs from the others in that it returns status information for an open file(identified by the file handle).
                    requestId = reader.ReadUInt32();
                    handle    = reader.ReadString(Encoding.UTF8);
                    if (HandleToPathDictionary.ContainsKey(handle))
                    {
                        path = HandleToPathDictionary[handle];
                        SendAttributes(requestId, path);
                    }
                    else
                    {
                        SendStatus(requestId, SftpStatusType.SSH_FX_NO_SUCH_FILE);
                    }

                    break;

                case RequestPacketType.SSH_FXP_CLOSE:
                    requestId = reader.ReadUInt32();
                    handle    = reader.ReadString(Encoding.UTF8);

                    if (HandleToPathDictionary.ContainsKey(handle))
                    {
                        HandleToPathDictionary.Remove(handle);
                    }

                    SendStatus(requestId, SftpStatusType.SSH_FX_OK);



                    break;

                case RequestPacketType.SSH_FXP_OPEN:

                    requestId = reader.ReadUInt32();              //uint32 request-id
                    path      = reader.ReadString(Encoding.UTF8); // //string filename [UTF-8]

                    HandleToPathDictionary.Add(handle, path);

                    var desired_access = reader.ReadUInt32();
                    var flags          = reader.ReadUInt32();

                    //uint32 desired-access
                    var write  = desired_access & (uint)FileSystemOperation.Write;
                    var read   = desired_access & (uint)FileSystemOperation.Read;
                    var create = desired_access & (uint)FileSystemOperation.Create;
                    //uint32 flags
                    //ATTRS  attrs
                    absolutepath = UserRootDirectory + path;
                    System.IO.FileInfo fi = new System.IO.FileInfo(absolutepath);

                    if (read > 0 && write == 0 && create == 0)
                    {
                        try
                        {
                            var fs = fi.OpenRead();
                            HandleToFileStreamDictionary.Add(handle, fs);
                        }
                        catch
                        {
                            SendStatus(requestId, SftpStatusType.SSH_FX_PERMISSION_DENIED);
                        }
                    }

                    writer.Write((byte)RequestPacketType.SSH_FXP_HANDLE);
                    writer.Write((uint)requestId);
                    writer.Write(handle, Encoding.UTF8);
                    // returns SSH_FXP_HANDLE on success or a SSH_FXP_STATUS message on fail

                    SendPacket(writer.ToByteArray());

                    break;

                case RequestPacketType.SSH_FXP_READ:
                    requestId = reader.ReadUInt32();     //uint32 request-id
                    handle    = reader.ReadString(Encoding.UTF8);
                    if (HandleToPathDictionary.ContainsKey(handle))
                    {
                        var fs     = HandleToFileStreamDictionary[handle];
                        var offset = (long)reader.ReadUInt64();
                        var length = (int)reader.ReadUInt32();
                        var buffer = new byte[length];



                        if (fs.Length - offset < 0)     // EOF already reached
                        {
                            SendStatus((uint)requestId, SftpStatusType.SSH_FX_EOF);

                            break;
                        }


                        writer.Write((byte)RequestPacketType.SSH_FXP_DATA);
                        writer.Write((uint)requestId);

                        if (fs.Length - offset < length)
                        {
                            buffer = new byte[fs.Length - offset];
                        }

                        fs.Seek(offset, SeekOrigin.Begin);
                        fs.Read(buffer);


                        writer.WriteBinary(buffer);


                        SendPacket(writer.ToByteArray());
                    }
                    else
                    {
                        // send invalid handle: SSH_FX_INVALID_HANDLE
                    }

                    break;

                default:
                    // unsupported command
                    _logger.LogWarning($"Unsupported sftp command {msgtype.ToString()} input: \"{input}\". on channel: {channel}");

                    SendStatus(requestId, SftpStatusType.SSH_FX_OP_UNSUPPORTED);
                    break;
                }
            }
        }