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[] 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(); } }
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()); }
protected override void OnGetPacket(SshDataWorker writer) { writer.Write(RecipientChannel); writer.WriteBinary(Data); }
protected override void OnGetPacket(SshDataWorker writer) { writer.Write(KeyAlgorithmName, Encoding.ASCII); writer.WriteBinary(PublicKey); }
protected override void OnGetPacket(SshDataWorker writer) { writer.WriteBinary(this.HostKey); writer.WriteMpint(this.F); writer.WriteBinary(this.Signature); }
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; } } }
protected override void OnGetPacket(SshDataWorker writer) { writer.WriteBinary(HostKey); writer.WriteMpint(F); writer.WriteBinary(Signature); }