public void Start() { Licensing.Key = VecteurSettings.Default.SftpLicenseKey; fileServer = new FileServer { LogWriter = new SerilogWriter() }; var port = (int)VecteurSettings.Default.SftpPort; var rsaKey = ServerKey.GetServerPrivateKey(); fileServer.Keys.Add(rsaKey); var dirInfo = new DirectoryInfo(VecteurSettings.Default.BaseDirectory); if (!dirInfo.Exists) { dirInfo.Create(); } var fs = CreateFileSystem(dirInfo.FullName); var user = new FileServerUser("vecteur", VecteurSettings.Default.SftpPassword); fileServer.Users.Add(user); user.SetFileSystem(fs); fileServer.Settings.SshParameters.EncryptionModes &= ~SshEncryptionMode.CBC; // Disable CBC algorithm (security vulnerability) fileServer.Bind(port, FileServerProtocol.Sftp); fileServer.Start(); }
private void RemoveJobInternal(FileServerUser user) { if (user == null) { return; } try { Log.Information("Cleaning up after download..."); var di = GetJobDirectory(user.Name); if (di.Exists) { try { di.Delete(true); Log.Information("Folder '{FullName}' and contents removed", di.FullName); } catch (Exception e) { Log.Warning(e, "Unable to delete folder '{FullName}'", di.FullName); } } var jobInfo = GetJobInfo(user.Name); if (jobInfo == null) { return; } if (!jobStorage.ContainsKey(jobInfo.Result.JobGuid)) { return; } if (jobStorage.TryRemove(jobInfo.Result.JobGuid, out var jobDetails)) { Log.Information("JobInfo and conversion settings for job id '{JobGuid}' removed.", jobDetails.Result.JobGuid); } else { Log.Warning("Failed to remove jobInfo and conversion settings for job id '{JobGuid}'.", jobDetails.Result.JobGuid); } } catch (Exception e) { Log.Error(e, e.Message); } finally { fileServer.Users.Remove(user); Log.Information("User '{Name}' removed from sftp server", user.Name); } }
public JobInitResult RegisterNewJob(JobInitRequest jobInitRequest) { if (fileServer == null) { throw new InvalidOperationException("Sftp server is not configured and started"); } try { // Create a new unique user and a unique directory for that user var newJobGuid = Guid.NewGuid().ToString("N"); var user = new FileServerUser(newJobGuid, password); Debug.Assert(user != null); var di = GetJobDirectory(newJobGuid); di.Create(); // Create a sftp file system object and assign it to the user. var localFileSystem = CreateFileSystem(di.FullName); user.SetFileSystem(localFileSystem); lock (fileServerLock) { fileServer.Users.Add(user); } var jobInitResult = new JobInitResult { JobGuid = newJobGuid, User = user.Name, Password = password, UploadUrl = baseAddress, Port = port }; // Add the information about the job to our local in memory storage var jobInfoDetails = new JobInfoDetails { Request = jobInitRequest, Result = jobInitResult }; jobStorage.AddOrUpdate(newJobGuid, jobInfoDetails, (k, v) => v); return(jobInitResult); } catch (Exception e) { Log.Error(e, e.Message); return(new JobInitResult { IsInvalid = true, ErrorMessage = e.Message }); } }
public void Start() { Licensing.Key = Properties.CacheSettings.Default.SftpLicenseKey; fileServer = new FileServer { LogWriter = new SerilogWriter() }; var port = ((long?)Properties.CacheSettings.Default.Port).Value; var rsaKey = ServerKey.GetServerPrivateKey(); fileServer.Keys.Add(rsaKey); foreach (var category in Enum.GetNames(typeof(CacheRetentionCategory))) { var dirInfo = new DirectoryInfo(Path.Combine(Properties.CacheSettings.Default.BaseDirectory, category)); if (!dirInfo.Exists) { dirInfo.Create(); } var fs = CreateFileSystem(dirInfo.FullName); var user = new FileServerUser(category, Password.Current); fileServer.Users.Add(user); user.SetFileSystem(fs); } fileServer.Settings.SshParameters.EncryptionModes &= ~SshEncryptionMode.CBC; // Disable CBC algorithm (security vulnerability) fileServer.FileUploaded += FileServerOnFileUploaded; fileServer.FileDownloaded += FileServerOnFileDownloaded; fileServer.Bind((int)port, FileServerProtocol.Sftp); fileServer.Start(); }
private void FsUser_Authentication(object sender, AuthenticationEventArgs e) { /* * https://www.rebex.net/file-server/features/events.aspx#authentication */ try { var callPath = $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"; using (var scope = _factory.CreateScope()) { var conf = scope.ServiceProvider.GetRequiredService <IConfiguration>(); var log = scope.ServiceProvider.GetRequiredService <ILogger>(); var uow = scope.ServiceProvider.GetRequiredService <IUnitOfWork>(); var user = uow.Users.Get(QueryExpressionFactory.GetQueryExpression <tbl_User>() .Where(x => x.IdentityAlias == e.UserName).ToLambda(), new List <Expression <Func <tbl_User, object> > >() { x => x.tbl_PublicKey, x => x.tbl_UserMount, }).SingleOrDefault(); var admin = scope.ServiceProvider.GetRequiredService <IAdminService>(); var sts = scope.ServiceProvider.GetRequiredService <IStsService>(); if (e.Key != null) { Log.Information($"'{callPath}' '{e.UserName}' in-progress with public key"); if (UserHelper.ValidatePubKey(user.tbl_PublicKey.Where(x => x.Enabled).ToList(), e.Key) && admin.User_VerifyV1(user.IdentityId).Result) { Log.Information($"'{callPath}' '{e.UserName}' success with public key"); if (e.PartiallyAccepted || !user.RequirePassword) { /* * an smb mount will not succeed without a user password or ambassador credential. */ if (user.FileSystemType == FileSystemTypes.SMB.ToString() && !user.tbl_UserMount.CredentialId.HasValue) { Log.Warning($"'{callPath}' '{e.UserName}' failure no credential to create {FileSystemTypes.SMB} filesystem"); e.Reject(); return; } var fs = FileSystemFactory.CreateFileSystem(_factory, log, user, e.UserName, e.Password); var fsUser = new FileServerUser(e.UserName, e.Password); fsUser.SetFileSystem(fs); var fsNotify = fs.GetFileSystemNotifier(); fsNotify.CreatePreview += FsNotify_CreatePreview; fsNotify.CreateCompleted += FsNotify_CreateCompleted; fsNotify.DeletePreview += FsNotify_DeletePreview; fsNotify.DeleteCompleted += FsNotify_DeleteCompleted; e.Accept(fsUser); return; } else { /* * authenticate partially if another kind of credential has not been provided yet. */ e.AcceptPartially(); return; } } else { Log.Warning($"'{callPath}' '{e.UserName}' failure with public key"); e.Reject(); return; } } if (e.Password != null) { Log.Information($"'{callPath}' '{e.UserName}' in-progress with password"); try { var identity = admin.User_GetV1(user.IdentityId.ToString()).Result; var auth = sts.ResourceOwner_GrantV2( new ResourceOwnerV2() { issuer = conf["IdentityCredentials:IssuerName"], client = conf["IdentityCredentials:AudienceName"], grant_type = "password", user = identity.UserName, password = e.Password, }).Result; Log.Information($"'{callPath}' '{e.UserName}' success with password"); if (e.PartiallyAccepted || !user.RequirePublicKey) { var fs = FileSystemFactory.CreateFileSystem(_factory, log, user, e.UserName, e.Password); var fsUser = new FileServerUser(e.UserName, e.Password); fsUser.SetFileSystem(fs); var fsNotify = fs.GetFileSystemNotifier(); fsNotify.CreatePreview += FsNotify_CreatePreview; fsNotify.CreateCompleted += FsNotify_CreateCompleted; fsNotify.DeletePreview += FsNotify_DeletePreview; fsNotify.DeleteCompleted += FsNotify_DeleteCompleted; e.Accept(fsUser); return; } else { /* * authenticate partially if another kind of credential has not been provided yet. */ e.AcceptPartially(); return; } } catch (HttpRequestException) { Log.Warning($"'{callPath}' '{e.UserName}' failure with password"); e.Reject(); return; } } Log.Warning($"'{callPath}' '{e.UserName}' denied"); e.Reject(); return; } } catch (Exception ex) { Log.Error(ex.ToString()); } }
public void SetupServer() { try { // 1. Server keys // add private keys for server authentication Server.Keys.Add(LoadOrCreatePrivateKey(Config.RsaPrivateKeyFile, Config.RsaPrivateKeyPassword, useRsa: true)); Server.Keys.Add(LoadOrCreatePrivateKey(Config.DssPrivateKeyFile, Config.DssPrivateKeyPassword, useRsa: false)); // 2. Users // make sure that root path does exists if (!Directory.Exists(Config.UserRootDir)) { var dir = Config.UserRootDir; Log.Write(LogColor.Important, "User data root directory '{0}' does not exist.", dir); Log.Write("Creating data root directory..."); Directory.CreateDirectory(dir); // create test files Log.Write("Creating user test data..."); var testFileDataPath = Path.Combine(dir, "testfile.txt"); File.WriteAllText( testFileDataPath, "This is a test file created by Rebex Tiny SFTP server." + Environment.NewLine + Environment.NewLine + "https://www.rebex.net/tiny-sftp-server/" ); Log.Write("Done."); } // add user var user = new FileServerUser( Config.UserName, Config.UserPassword, Config.UserRootDir); Server.Users.Add(user); // 3. Check user key directory if (!string.IsNullOrEmpty(Config.UserPublicKeyDir)) { if (!Directory.Exists(Config.UserPublicKeyDir)) { Log.Write(LogColor.Important, "User public key directory '{0}' does not exist.", Config.UserPublicKeyDir); } } // 4. Register custom authentication handler Server.Authentication += Server_Authentication; // 5. Ready to start if (Config.AutoStart) { StartServer(); } else { Log.Write(""); Log.Write(@" Press ""Start"" button to begin."); Log.Write(""); } } catch (Exception ex) { Log.Write(ex); } UpdateUI(); }