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); } } }
public byte[] GetPacket() { using (var worker = new SshDataWorker()) { worker.Write(this.MessageType); this.OnGetPacket(worker); return(worker.ToByteArray()); } }
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()); }
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()); }
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()); } }
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()); } }
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(); } }
/// <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); } }
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()); }
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()); }
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()); }
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); }
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; } } }