diff --git a/PUP/BSP/BSPChannel.cs b/PUP/BSP/BSPChannel.cs
index 175129c..c8c9c5b 100644
--- a/PUP/BSP/BSPChannel.cs
+++ b/PUP/BSP/BSPChannel.cs
@@ -508,6 +508,20 @@ namespace IFS.BSP
Log.Write(LogType.Verbose, LogComponent.BSP, "ACK sent.");
}
+ public void RecvError(PUP errorPup)
+ {
+ // For now, just log this.
+ Log.Write(LogType.Error, LogComponent.BSP,
+ "Error from client, unhandled.");
+ }
+
+ public void RecvInterrupt(PUP interruptPup)
+ {
+ // For now, just log this. No IFS protcols yet implemented require use of interrupts.
+ Log.Write(LogType.Error, LogComponent.BSP,
+ "Interrupt from client, unhandled.");
+ }
+
///
/// Sends a PUP. Will block if client is unable to receive data. If timeouts expire, channel will be shut down.
///
diff --git a/PUP/BSP/BSPManager.cs b/PUP/BSP/BSPManager.cs
index b2f0243..877bb23 100644
--- a/PUP/BSP/BSPManager.cs
+++ b/PUP/BSP/BSPManager.cs
@@ -17,17 +17,6 @@ namespace IFS.BSP
public ushort BytesSent;
}
- public abstract class BSPProtocol : PUPProtocolBase
- {
- public abstract void InitializeServerForChannel(BSPChannel channel);
- }
-
- public enum BSPState
- {
- Unconnected,
- Connected
- }
-
public delegate void WorkerExitDelegate(BSPWorkerBase destroyed);
public abstract class BSPWorkerBase
@@ -169,6 +158,18 @@ namespace IFS.BSP
}
break;
+ case PupType.Error:
+ {
+ channel.RecvError(p);
+ }
+ break;
+
+ case PupType.Interrupt:
+ {
+ channel.RecvInterrupt(p);
+ }
+ break;
+
default:
throw new NotImplementedException(String.Format("Unhandled BSP PUP type {0}.", p.Type));
diff --git a/PUP/Conf/ifs.cfg b/PUP/Conf/ifs.cfg
index f946d25..99fce23 100644
--- a/PUP/Conf/ifs.cfg
+++ b/PUP/Conf/ifs.cfg
@@ -6,7 +6,7 @@
# Debug settings
-LogTypes = Normal
+LogTypes = All
LogComponents = All
# Normal configuration
diff --git a/PUP/CopyDisk/CopyDiskServer.cs b/PUP/CopyDisk/CopyDiskServer.cs
index 11a972c..275a4bb 100644
--- a/PUP/CopyDisk/CopyDiskServer.cs
+++ b/PUP/CopyDisk/CopyDiskServer.cs
@@ -34,6 +34,10 @@ namespace IFS.CopyDisk
UnitWriteProtected = 2,
OverwriteNotAllowed = 3,
UnknownCommand = 4,
+ IllegalUserName = 16,
+ IllegalOrIncorrectPassword = 17,
+ IllegalConnectName = 18,
+ IllegalConnectPassword = 19,
}
struct VersionYesNoBlock
@@ -280,21 +284,30 @@ namespace IFS.CopyDisk
{
LoginBlock login = (LoginBlock)Serializer.Deserialize(data, typeof(LoginBlock));
- Log.Write(LogType.Verbose, LogComponent.CopyDisk, "Login is for user {0}, password {1}, connection {2}, connection password {3}.",
+ Log.Write(LogType.Verbose, LogComponent.CopyDisk, "Login is for user '{0}', password '{1}', connection '{2}', connection password '{3}'.",
login.UserName,
login.UserPassword,
login.ConnName,
login.ConnPassword);
- //
- // TODO: for now we allow anyone in with any username and password, this needs to be fixed once
- // an authentication mechanism is set up.
- //
+ _userToken = AuthenticateUser(login.UserName.ToString(), login.UserPassword.ToString());
- // Send a "Yes" response back.
- //
- VersionYesNoBlock yes = new VersionYesNoBlock(CopyDiskBlock.Yes, 0, "Come on in, the water's fine.");
- _channel.Send(Serializer.Serialize(yes));
+ if (_userToken != null)
+ {
+ //
+ // Send a "Yes" response back.
+ //
+ VersionYesNoBlock yes = new VersionYesNoBlock(CopyDiskBlock.Yes, 0, "Come on in, the water's fine.");
+ _channel.Send(Serializer.Serialize(yes));
+ }
+ else
+ {
+ //
+ // Send a "No" response back indicating the login failure.
+ //
+ VersionYesNoBlock no = new VersionYesNoBlock(CopyDiskBlock.No, (ushort)NoCode.IllegalOrIncorrectPassword, "Invalid username or password.");
+ _channel.Send(Serializer.Serialize(no), true);
+ }
}
break;
@@ -408,6 +421,17 @@ namespace IFS.CopyDisk
_startAddress = _pack.DiskAddressToVirtualAddress(transferParameters.StartAddress);
_endAddress = _pack.DiskAddressToVirtualAddress(transferParameters.EndAddress);
+ // Validate that the user is allowed to store.
+ if (blockType == CopyDiskBlock.StoreDisk)
+ {
+ if (_userToken.Privileges != IFSPrivileges.ReadWrite)
+ {
+ VersionYesNoBlock no = new VersionYesNoBlock(CopyDiskBlock.No, (ushort)NoCode.UnitWriteProtected, "You do not have permission to store disk images.");
+ _channel.Send(Serializer.Serialize(no));
+ break;
+ }
+ }
+
Log.Write(LogType.Verbose, LogComponent.CopyDisk, "Transfer is from block {0} to block {1}", transferParameters.StartAddress, transferParameters.EndAddress);
// Validate start/end parameters
@@ -419,7 +443,7 @@ namespace IFS.CopyDisk
_channel.Send(Serializer.Serialize(no));
}
else
- {
+ {
// We're OK. Save the parameters and send a Yes response.
VersionYesNoBlock yes = new VersionYesNoBlock(CopyDiskBlock.Yes, 0, "You are cleared for launch.");
_channel.Send(Serializer.Serialize(yes));
@@ -564,6 +588,22 @@ namespace IFS.CopyDisk
}
}
+ private UserToken AuthenticateUser(string userName, string password)
+ {
+ //
+ // If no username is specified then we default to the guest account.
+ //
+ if (string.IsNullOrEmpty(userName))
+ {
+ return UserToken.Guest;
+ }
+
+ UserToken user = Authentication.Authenticate(userName, password);
+
+ return user;
+
+ }
+
///
/// Builds a relative path to the directory that holds the disk images.
///
@@ -577,6 +617,9 @@ namespace IFS.CopyDisk
private Thread _workerThread;
private bool _running;
+ // The user token for this transaction. We assume guest access by default.
+ private UserToken _userToken = UserToken.Guest;
+
// The pack being read / stored by this server
private DiabloPack _pack = null;
diff --git a/PUP/FTP/FTPServer.cs b/PUP/FTP/FTPServer.cs
index 9f3ef62..c3892f5 100644
--- a/PUP/FTP/FTPServer.cs
+++ b/PUP/FTP/FTPServer.cs
@@ -839,6 +839,12 @@ namespace IFS.FTP
///
private bool IsUserDirectory(UserToken userToken, string fullPath)
{
+ if (string.IsNullOrEmpty(userToken.HomeDirectory))
+ {
+ // No home directory, so by default this cannot be the user's home directory.
+ return false;
+ }
+
string userDirPath = Path.Combine(Configuration.FTPRoot, userToken.HomeDirectory);
return fullPath.StartsWith(userDirPath, StringComparison.OrdinalIgnoreCase);
}