Optional authentication by access token (#529)

* Added authentication by access token

* No authentication is required for getting the rascsi version

* Added comment

* Interface description update

* Manpage update

* Added error code

* Enum value update (backwards compatible)

* Error code update

* Error code update

* Added CHECK_AUTHENTICATION

* Comment update

* VERSION_INFO also requires authentication

* rasctl: Made token an optional parameter for -P

* Fixed interface comment
This commit is contained in:
Uwe Seimet 2021-12-19 11:54:10 +01:00 committed by GitHub
parent e32211ef73
commit ec31198d83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 159 additions and 62 deletions

View File

@ -5,6 +5,7 @@ rascsi \- Emulates SCSI devices using the Raspberry Pi GPIO pins
.B rascsi .B rascsi
[\fB\-F\f® \fIFOLDER\fR] [\fB\-F\f® \fIFOLDER\fR]
[\fB\-L\f® \fILOG_LEVEL\fR] [\fB\-L\f® \fILOG_LEVEL\fR]
[\fB\-P\f® \fIACCESS_TOKEN_FILE\fR]
[\fB\-R\fR \fISCAN_DEPTH\fR] [\fB\-R\fR \fISCAN_DEPTH\fR]
[\fB\-h\fR] [\fB\-h\fR]
[\fB\-n\fR \fIVENDOR:PRODUCT:REVISION\fR] [\fB\-n\fR \fIVENDOR:PRODUCT:REVISION\fR]
@ -53,8 +54,11 @@ The default folder for image files. For files in this folder no absolute path ne
.BR \-L\fI " " \fILOG_LEVEL .BR \-L\fI " " \fILOG_LEVEL
The rascsi log level (trace, debug, info, warn, err, critical, off). The default log level is 'info'. The rascsi log level (trace, debug, info, warn, err, critical, off). The default log level is 'info'.
.TP .TP
.BR \-P\fI " " \fIACCESS_TOKEN_FILE
Enable authentication and read the access token from the specified file. The access token file must be owned by root and must be readable by root only.
.TP
.BR \-R\fI " " \fISCAN_DEPTH .BR \-R\fI " " \fISCAN_DEPTH
Scan for image files recursively, up to a depth -f SCAN_DEPTH. Be careful when using this option with many sub-folders in the default image folder. Scan for image files recursively, up to a depth of SCAN_DEPTH. Be careful when using this option with many sub-folders in the default image folder.
.TP .TP
.BR \-h\fI " " \fI .BR \-h\fI " " \fI
Show a help page. Show a help page.

View File

@ -6,86 +6,92 @@ NAME
rascsi - Emulates SCSI devices using the Raspberry Pi GPIO pins rascsi - Emulates SCSI devices using the Raspberry Pi GPIO pins
SYNOPSIS SYNOPSIS
rascsi [-F[u00AE] FOLDER] [-L[u00AE] LOG_LEVEL] [-R SCAN_DEPTH] [-h] rascsi [-F[u00AE] FOLDER] [-L[u00AE] LOG_LEVEL] [-P[u00AE] ACCESS_TO
[-n VENDOR:PRODUCT:REVISION] [-p[u00AE] PORT] [-r RESERVED_IDS] [-n KEN_FILE] [-R SCAN_DEPTH] [-h] [-n VENDOR:PRODUCT:REVISION] [-p[u00AE]
TYPE] [-v] [-IDn:[u] FILE] [-HDn[:u] FILE]... PORT] [-r RESERVED_IDS] [-n TYPE] [-v] [-IDn:[u] FILE] [-HDn[:u]
FILE]...
DESCRIPTION DESCRIPTION
rascsi Emulates SCSI devices using the Raspberry Pi GPIO pins. rascsi Emulates SCSI devices using the Raspberry Pi GPIO pins.
In the arguments to RaSCSI, one or more SCSI (-IDn[:u]) or SASI In the arguments to RaSCSI, one or more SCSI (-IDn[:u]) or SASI
(-HDn[:u]) devices can be specified. The number (n) after the ID or HD (-HDn[:u]) devices can be specified. The number (n) after the ID or HD
identifier specifies the ID number for that device. The optional number identifier specifies the ID number for that device. The optional number
(u) specifies the LUN (logical unit) for that device. The default LUN (u) specifies the LUN (logical unit) for that device. The default LUN
is 0. For SCSI: The ID is limited from 0-7. However, typically SCSI ID is 0. For SCSI: The ID is limited from 0-7. However, typically SCSI ID
7 is reserved for the "initiator" (the host computer). The LUN is lim 7 is reserved for the "initiator" (the host computer). The LUN is lim
ited from 0-31. Note that SASI is considered rare and only used on very ited from 0-31. Note that SASI is considered rare and only used on very
early Sharp X68000 computers. early Sharp X68000 computers.
RaSCSI will determine the type of device based upon the file extension RaSCSI will determine the type of device based upon the file extension
of the FILE argument. of the FILE argument.
hdf: SASI Hard Disk image (XM6 SASI HD image - typically only used hdf: SASI Hard Disk image (XM6 SASI HD image - typically only used
with X68000) with X68000)
hds: SCSI Hard Disk image (generic, non-removable) hds: SCSI Hard Disk image (generic, non-removable)
hdr: SCSI Hard Disk image (generic, removable) hdr: SCSI Hard Disk image (generic, removable)
hdn: SCSI Hard Disk image (NEC GENUINE) hdn: SCSI Hard Disk image (NEC GENUINE)
hdi: SCSI Hard Disk image (Anex86 HD image) hdi: SCSI Hard Disk image (Anex86 HD image)
nhd: SCSI Hard Disk image (T98Next HD image) nhd: SCSI Hard Disk image (T98Next HD image)
hda: SCSI Hard Disk image (APPLE GENUINE - typically used with Mac hda: SCSI Hard Disk image (APPLE GENUINE - typically used with Mac
SCSI emulation) SCSI emulation)
mos: SCSI Magneto-optical image (XM6 SCSI MO image - typically only mos: SCSI Magneto-optical image (XM6 SCSI MO image - typically only
used with X68000) used with X68000)
iso: SCSI CD-ROM image (ISO 9660 image) iso: SCSI CD-ROM image (ISO 9660 image)
For example, if you want to specify an Apple-compatible HD image on ID For example, if you want to specify an Apple-compatible HD image on ID
0, you can use the following command: 0, you can use the following command:
sudo rascsi -ID0 /path/to/drive/hdimage.hda sudo rascsi -ID0 /path/to/drive/hdimage.hda
Once RaSCSI starts, it will open a socket (default port is 6868) to al Once RaSCSI starts, it will open a socket (default port is 6868) to al
low external management commands. If another process is using the low external management commands. If another process is using the
rascsi port, RaSCSI will terminate, since it is likely another instance rascsi port, RaSCSI will terminate, since it is likely another instance
of RaSCSI. Once RaSCSI has initialized, the rasctl utility can be used of RaSCSI. Once RaSCSI has initialized, the rasctl utility can be used
to send commands. to send commands.
To quit RaSCSI, press Control + C. If it is running in the background, To quit RaSCSI, press Control + C. If it is running in the background,
you can kill it using an INT signal. you can kill it using an INT signal.
OPTIONS OPTIONS
-b BLOCK_SIZE -b BLOCK_SIZE
The optional block size. For SCSI drives 512, 1024, 2048 or 4096 The optional block size. For SCSI drives 512, 1024, 2048 or 4096
bytes, default size is 512 bytes. For SASI drives 256 or 1024 bytes, default size is 512 bytes. For SASI drives 256 or 1024
bytes, default is 256 bytes. bytes, default is 256 bytes.
-F FOLDER -F FOLDER
The default folder for image files. For files in this folder no The default folder for image files. For files in this folder no
absolute path needs to be specified. The initial default folder absolute path needs to be specified. The initial default folder
is '~/images'. is '~/images'.
-L LOG_LEVEL -L LOG_LEVEL
The rascsi log level (trace, debug, info, warn, err, critical, The rascsi log level (trace, debug, info, warn, err, critical,
off). The default log level is 'info'. off). The default log level is 'info'.
-P ACCESS_TOKEN_FILE
Enable authentication and read the access token from the speci
fied file. The access token file must be owned by root and must
be readable by root only.
-R SCAN_DEPTH -R SCAN_DEPTH
Scan for image files recursively, up to a depth -f SCAN_DEPTH. Scan for image files recursively, up to a depth of SCAN_DEPTH.
Be careful when using this option with many sub-folders in the Be careful when using this option with many sub-folders in the
default image folder. default image folder.
-h Show a help page. -h Show a help page.
-n VENDOR:PRODUCT:REVISION -n VENDOR:PRODUCT:REVISION
Set the vendor, product and revision for the device, to be re Set the vendor, product and revision for the device, to be re
turned with the INQUIRY data. A complete set of name components turned with the INQUIRY data. A complete set of name components
must be provided. VENDOR may have up to 8, PRODUCT up to 16, RE must be provided. VENDOR may have up to 8, PRODUCT up to 16, RE
VISION up to 4 characters. Padding with blanks to the maxium VISION up to 4 characters. Padding with blanks to the maxium
length is automatically applied. Once set the name of a device length is automatically applied. Once set the name of a device
cannot be changed. cannot be changed.
-p PORT -p PORT
The rascsi server port, default is 6868. The rascsi server port, default is 6868.
-r RESERVED_IDS -r RESERVED_IDS
Comma-separated list of IDs to reserve. -p TYPE The optional Comma-separated list of IDs to reserve. -p TYPE The optional
case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO,
SCBR, SCDP). If no type is specified for devices that support an SCBR, SCDP). If no type is specified for devices that support an
image file, rascsi tries to derive the type from the file exten image file, rascsi tries to derive the type from the file exten
sion. sion.
@ -93,17 +99,17 @@ OPTIONS
-v Display the rascsi version. -v Display the rascsi version.
-IDn[:u] FILE -IDn[:u] FILE
n is the SCSI ID number (0-7). u (0-31) is the optional LUN n is the SCSI ID number (0-7). u (0-31) is the optional LUN
(logical unit). The default LUN is 0. (logical unit). The default LUN is 0.
FILE is the name of the image file to use for the SCSI device. FILE is the name of the image file to use for the SCSI device.
For devices that do not support an image file (SCBR, SCDP) a For devices that do not support an image file (SCBR, SCDP) a
dummy name must be provided. dummy name must be provided.
-HDn[:u] FILE -HDn[:u] FILE
n is the SASI ID number (0-15). The effective SASI ID is calcu n is the SASI ID number (0-15). The effective SASI ID is calcu
lated as n/2, the effective SASI LUN is calculated is the re lated as n/2, the effective SASI LUN is calculated is the re
mainder of n/2. Alternatively the n:u syntax can be used, where mainder of n/2. Alternatively the n:u syntax can be used, where
ns is the SASI ID (0-7) and u the LUN (0-1). ns is the SASI ID (0-7) and u the LUN (0-1).
FILE is the name of the image file to use for the SASI device. FILE is the name of the image file to use for the SASI device.
@ -120,7 +126,7 @@ EXAMPLES
rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso rascsi -ID0 /path/to/harddrive.hda -ID2 /path/to/cdimage.iso
Launch RaSCSI with a removable SCSI drive image as ID 0 and the raw de Launch RaSCSI with a removable SCSI drive image as ID 0 and the raw de
vice file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter vice file /dev/hdb (e.g. a USB stick) and a DaynaPort network adapter
as ID 6: as ID 6:
rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp DUMMY_FILENAME rascsi -ID0 -t scrm /dev/hdb -ID6 -t scdp DUMMY_FILENAME

View File

@ -12,6 +12,7 @@ rasctl \- Sends management commands to the rascsi process
\fB\-I\fR | \fB\-I\fR |
\fB\-L\fR | \fB\-L\fR |
\fB\-O\fR | \fB\-O\fR |
\fB\-P\fR |
\fB\-T\fR | \fB\-T\fR |
\fB\-V\fR | \fB\-V\fR |
\fB\-X\fR | \fB\-X\fR |
@ -72,6 +73,9 @@ Lists all available network interfaces provided that they are up.
.BR \-O\fI .BR \-O\fI
Display the available rascsi server log levels and the current log level. Display the available rascsi server log levels and the current log level.
.TP .TP
.BR \-P\fI
Prompt for the access token in case rascsi requires authentication.
.TP
.BR \-l\fI .BR \-l\fI
List all of the devices that are currently being emulated by RaSCSI, as well as their current status. List all of the devices that are currently being emulated by RaSCSI, as well as their current status.
.TP .TP

View File

@ -1,15 +1,13 @@
!! ------ THIS FILE IS AUTO_GENERATED! DO NOT MANUALLY UPDATE!!! !! ------ THIS FILE IS AUTO_GENERATED! DO NOT MANUALLY UPDATE!!!
!! ------ The native file is rasctl.1. Re-run 'make docs' after updating !! ------ The native file is rasctl.1. Re-run 'make docs' after updating\n\n
rascsi(1) General Commands Manual rascsi(1) rascsi(1) General Commands Manual rascsi(1)
NAME NAME
rasctl - Sends management commands to the rascsi process rasctl - Sends management commands to the rascsi process
SYNOPSIS SYNOPSIS
rasctl -e | -l | -m | -s | -v | -D | -I | -L | -O | -T | -V | -X | [-C rasctl -e | -l | -m | -s | -v | -D | -I | -L | -O | -P | -T | -V | -X |
FILENAME:FILESIZE] [-E FILENAME] [-F IMAGE_FOLDER] [-R CUR [-C FILENAME:FILESIZE] [-E FILENAME] [-F IMAGE_FOLDER] [-R CUR
RENT_NAME:NEW_NAME] [-c CMD] [-f FILE|PARAM] [-g LOG_LEVEL] [-h HOST] RENT_NAME:NEW_NAME] [-c CMD] [-f FILE|PARAM] [-g LOG_LEVEL] [-h HOST]
[-i ID [-n NAME] [-p PORT] [-r RESERVED_IDS] [-t TYPE] [-u UNIT] [-x [-i ID [-n NAME] [-p PORT] [-r RESERVED_IDS] [-t TYPE] [-u UNIT] [-x
CURRENT_NAME:NEW_NAME] CURRENT_NAME:NEW_NAME]
@ -55,10 +53,13 @@ OPTIONS
-O Display the available rascsi server log levels and the current -O Display the available rascsi server log levels and the current
log level. log level.
-l List all of the devices that are currently being emulated by -P Prompt for the access token in case rascsi requires authentica
tion.
-l List all of the devices that are currently being emulated by
RaSCSI, as well as their current status. RaSCSI, as well as their current status.
-m List all file extensions recognized by RaSCSI and the device -m List all file extensions recognized by RaSCSI and the device
types they map to. types they map to.
-R CURRENT_NAME:NEW_NAME -R CURRENT_NAME:NEW_NAME
@ -70,7 +71,7 @@ OPTIONS
-r RESERVED_IDS -r RESERVED_IDS
Comma-separated list of IDs to reserve. Comma-separated list of IDs to reserve.
-s Display server-side settings like available images or supported -s Display server-side settings like available images or supported
device types. device types.
-T Display all device types and their properties. -T Display all device types and their properties.
@ -94,7 +95,7 @@ OPTIONS
d(etach): Detach disk d(etach): Detach disk
i(nsert): Insert media (removable media devices only) i(nsert): Insert media (removable media devices only)
e(ject): Eject media (removable media devices only) e(ject): Eject media (removable media devices only)
p(rotect): Write protect the medium (not for CD-ROMs, which p(rotect): Write protect the medium (not for CD-ROMs, which
are always read-only) are always read-only)
u(nprotect): Remove write protection from the medium (not for u(nprotect): Remove write protection from the medium (not for
CD-ROMs, which are always read-only) CD-ROMs, which are always read-only)
@ -104,18 +105,18 @@ OPTIONS
-b BLOCK_SIZE -b BLOCK_SIZE
The optional block size. For SCSI drives 512, 1024, 2048 or 4096 The optional block size. For SCSI drives 512, 1024, 2048 or 4096
bytes, default size is 512 bytes. For SASI drives 256 or 1024 bytes, default size is 512 bytes. For SASI drives 256 or 1024
bytes, default is 256 bytes. bytes, default is 256 bytes.
-f FILE|PARAM -f FILE|PARAM
Device-specific: Either a path to a disk image file, or a param Device-specific: Either a path to a disk image file, or a param
eter for a non-disk device. See the rascsi(1) man page for per eter for a non-disk device. See the rascsi(1) man page for per
mitted file types. mitted file types.
-t TYPE -t TYPE
Specifies the device type. This type overrides the type derived Specifies the device type. This type overrides the type derived
from the file extension of the specified image. See the from the file extension of the specified image. See the
rascsi(1) man page for the available device types. For some rascsi(1) man page for the available device types. For some
types there are shortcuts (only the first letter is required): types there are shortcuts (only the first letter is required):
hd: SCSI hard disk drive hd: SCSI hard disk drive
rm: SCSI removable media drive rm: SCSI removable media drive
@ -125,16 +126,16 @@ OPTIONS
daynaport: DaynaPORT network adapter daynaport: DaynaPORT network adapter
-n VENDOR:PRODUCT:REVISION -n VENDOR:PRODUCT:REVISION
The vendor, product and revision for the device, to be returned The vendor, product and revision for the device, to be returned
with the INQUIRY data. A complete set of name components must be with the INQUIRY data. A complete set of name components must be
provided. VENDOR may have up to 8, PRODUCT up to 16, REVISION up provided. VENDOR may have up to 8, PRODUCT up to 16, REVISION up
to 4 characters. Padding with blanks to the maxium length is au to 4 characters. Padding with blanks to the maxium length is au
tomatically applied. Once set the name of a device cannot be tomatically applied. Once set the name of a device cannot be
changed. changed.
-u UNIT -u UNIT
Unit number (0-31). This will default to 0. This option is only Unit number (0-31). This will default to 0. This option is only
used when there are multiple SCSI devices on a shared SCSI con used when there are multiple SCSI devices on a shared SCSI con
troller. (This is not common) troller. (This is not common)
EXAMPLES EXAMPLES

View File

@ -120,7 +120,7 @@ int protobuf_util::ReadNBytes(int fd, uint8_t *buf, int n)
} }
bool protobuf_util::ReturnStatus(int fd, bool status, const string msg) bool protobuf_util::ReturnStatus(int fd, bool status, const string msg, const PbErrorCode error_code)
{ {
if (!status && !msg.empty()) { if (!status && !msg.empty()) {
LOGERROR("%s", msg.c_str()); LOGERROR("%s", msg.c_str());
@ -142,6 +142,7 @@ bool protobuf_util::ReturnStatus(int fd, bool status, const string msg)
else { else {
PbResult result; PbResult result;
result.set_status(status); result.set_status(status);
result.set_error_code(error_code);
result.set_msg(msg); result.set_msg(msg);
SerializeMessage(fd, result); SerializeMessage(fd, result);
} }

View File

@ -29,6 +29,6 @@ namespace protobuf_util
void SerializeMessage(int, const google::protobuf::Message&); void SerializeMessage(int, const google::protobuf::Message&);
void DeserializeMessage(int, google::protobuf::Message&); void DeserializeMessage(int, google::protobuf::Message&);
int ReadNBytes(int, uint8_t *, int); int ReadNBytes(int, uint8_t *, int);
bool ReturnStatus(int, bool = true, const string = ""); bool ReturnStatus(int, bool = true, const string = "", const PbErrorCode error_code = PbErrorCode::NO_ERROR_CODE);
bool ReturnStatus(int, bool, const ostringstream&); bool ReturnStatus(int, bool, const ostringstream&);
} }

View File

@ -33,6 +33,7 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <fstream>
#include <list> #include <list>
#include <vector> #include <vector>
#include <map> #include <map>
@ -67,6 +68,7 @@ pthread_t monthread; // Monitor Thread
pthread_mutex_t ctrl_mutex; // Semaphore for the ctrl array pthread_mutex_t ctrl_mutex; // Semaphore for the ctrl array
static void *MonThread(void *param); static void *MonThread(void *param);
string current_log_level; // Some versions of spdlog do not support get_log_level() string current_log_level; // Some versions of spdlog do not support get_log_level()
string access_token;
set<int> reserved_ids; set<int> reserved_ids;
int scan_depth = 0; int scan_depth = 0;
DeviceFactory& device_factory = DeviceFactory::instance(); DeviceFactory& device_factory = DeviceFactory::instance();
@ -374,6 +376,43 @@ bool MapController(Device **map)
return status; return status;
} }
bool ReadAccessToken(const char *filename)
{
struct stat st;
if (stat(filename, &st) || !S_ISREG(st.st_mode)) {
cerr << "Can't access token file '" << optarg << "'" << endl;
return false;
}
if (st.st_uid || st.st_gid || (st.st_mode & (S_IROTH | S_IWOTH | S_IRGRP | S_IWGRP))) {
cerr << "Access token file '" << optarg << "' must be owned by root and readable by root only" << endl;
return false;
}
ifstream token_file(filename, ifstream::in);
if (token_file.fail()) {
cerr << "Can't open access token file '" << optarg << "'" << endl;
return false;
}
getline(token_file, access_token);
if (token_file.fail()) {
token_file.close();
cerr << "Can't read access token file '" << optarg << "'" << endl;
return false;
}
if (access_token.empty()) {
token_file.close();
cerr << "Access token file '" << optarg << "' must not be empty" << endl;
return false;
}
token_file.close();
return true;
}
string ValidateLunSetup(const PbCommand& command, const vector<Device *>& existing_devices) string ValidateLunSetup(const PbCommand& command, const vector<Device *>& existing_devices)
{ {
// Mapping of available LUNs (bit vector) to devices // Mapping of available LUNs (bit vector) to devices
@ -973,7 +1012,8 @@ bool ProcessCmd(int fd, const PbDeviceDefinition& pb_device, const PbCommand& co
assert(dryRun); assert(dryRun);
break; break;
case NONE: case CHECK_AUTHENTICATION:
case NO_OPERATION:
// Do nothing, just log // Do nothing, just log
LOGTRACE("Received %s command", PbOperation_Name(operation).c_str()); LOGTRACE("Received %s command", PbOperation_Name(operation).c_str());
break; break;
@ -1160,7 +1200,7 @@ bool ParseArgument(int argc, char* argv[], int& port)
opterr = 1; opterr = 1;
int opt; int opt;
while ((opt = getopt(argc, argv, "-IiHhb:d:n:p:r:t:D:F:L:R:")) != -1) { while ((opt = getopt(argc, argv, "-IiHhb:d:n:p:r:t:D:F:L:P:R:")) != -1) {
switch (opt) { switch (opt) {
// The three options below are kind of a compound option with two letters // The three options below are kind of a compound option with two letters
case 'i': case 'i':
@ -1223,6 +1263,12 @@ bool ParseArgument(int argc, char* argv[], int& port)
} }
continue; continue;
case 'P':
if (!ReadAccessToken(optarg)) {
return false;
}
continue;
case 'r': { case 'r': {
string error = SetReservedIds(optarg); string error = SetReservedIds(optarg);
if (!error.empty()) { if (!error.empty()) {
@ -1378,6 +1424,13 @@ static void *MonThread(void *param)
PbCommand command; PbCommand command;
DeserializeMessage(fd, command); DeserializeMessage(fd, command);
if (!access_token.empty()) {
if (access_token != GetParam(command, "token")) {
ReturnStatus(fd, false, "Authentication failed", PbErrorCode::UNAUTHORIZED);
continue;
}
}
switch(command.operation()) { switch(command.operation()) {
case LOG_LEVEL: { case LOG_LEVEL: {
LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str()); LOGTRACE("Received %s command", PbOperation_Name(command.operation()).c_str());

View File

@ -2,6 +2,8 @@
// Each rascsi message sent to the rascsi server is preceded by the magic string "RASCSI". // Each rascsi message sent to the rascsi server is preceded by the magic string "RASCSI".
// A message starts with a little endian 32 bit header which contains the protobuf message size. // A message starts with a little endian 32 bit header which contains the protobuf message size.
// Unless explicitly specified the order of repeated data returned is undefined. // Unless explicitly specified the order of repeated data returned is undefined.
// All operations accept an optional access token, specified by the "token" parameter.
// Only the VERSION_INFO operation never requires authentication.
// //
syntax = "proto3"; syntax = "proto3";
@ -29,7 +31,7 @@ enum PbDeviceType {
// rascsi remote operations, returning PbResult // rascsi remote operations, returning PbResult
enum PbOperation { enum PbOperation {
NONE = 0; NO_OPERATION = 0;
// Attach devices and return the new device list (PbDevicesInfo) // Attach devices and return the new device list (PbDevicesInfo)
// Parameters (mutually exclusive): // Parameters (mutually exclusive):
@ -158,6 +160,19 @@ enum PbOperation {
// Parameters: // Parameters:
// "file": The filename, relative to the default image folder. It must not contain a slash. // "file": The filename, relative to the default image folder. It must not contain a slash.
UNPROTECT_IMAGE = 29; UNPROTECT_IMAGE = 29;
// Check whether an authentication token is valid. A client can use this in operation in order to
// find out whether rascsi authentication is enable or to use rascsi authentication for securing
// client-internal operations.
CHECK_AUTHENTICATION = 30;
}
// rascsi special purpose error codes for cases where a textual error message is not sufficient
enum PbErrorCode {
// No error code available
NO_ERROR_CODE = 0;
// Authentication/Authorization error
UNAUTHORIZED = 1;
} }
// The supported file extensions mapped to their respective device types // The supported file extensions mapped to their respective device types
@ -309,6 +324,8 @@ message PbResult {
bool status = 1; bool status = 1;
// An optional error or information message, depending on the status. A string without trailing CR/LF. // An optional error or information message, depending on the status. A string without trailing CR/LF.
string msg = 2; string msg = 2;
// An optional error code. Only to be used in cases where textual information is not sufficient.
PbErrorCode error_code = 13;
// Optional additional result data // Optional additional result data
oneof result { oneof result {
// The result of a SERVER_INFO command // The result of a SERVER_INFO command

View File

@ -52,7 +52,7 @@ PbOperation ParseOperation(const char *optarg)
return DEVICES_INFO; return DEVICES_INFO;
default: default:
return NONE; return NO_OPERATION;
} }
} }
@ -101,7 +101,7 @@ int main(int argc, char* argv[])
cerr << "version " << rascsi_get_version_string() << " (" << __DATE__ << ", " << __TIME__ << ")" << endl; cerr << "version " << rascsi_get_version_string() << " (" << __DATE__ << ", " << __TIME__ << ")" << endl;
cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-C FILE] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE|PARAM] "; cerr << "Usage: " << argv[0] << " -i ID [-u UNIT] [-c CMD] [-C FILE] [-t TYPE] [-b BLOCK_SIZE] [-n NAME] [-f FILE|PARAM] ";
cerr << "[-F IMAGE_FOLDER] [-L LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] "; cerr << "[-F IMAGE_FOLDER] [-L LOG_LEVEL] [-h HOST] [-p PORT] [-r RESERVED_IDS] ";
cerr << "[-C FILENAME:FILESIZE] [-d FILENAME] [-w FILENAME] [-R CURRENT_NAME:NEW_NAME] [-x CURRENT_NAME:NEW_NAME] "; cerr << "[-C FILENAME:FILESIZE] [-d FILENAME] [-w FILENAME] [-P TOKEN] [-R CURRENT_NAME:NEW_NAME] [-x CURRENT_NAME:NEW_NAME] ";
cerr << "[-e] [-E FILENAME] [-D] [-I] [-l] [-L] [-m] [-O] [-s] [-v] [-V] [-y] [-X]" << endl; cerr << "[-e] [-E FILENAME] [-D] [-I] [-l] [-L] [-m] [-O] [-s] [-v] [-V] [-y] [-X]" << endl;
cerr << " where ID := {0-7}" << endl; cerr << " where ID := {0-7}" << endl;
cerr << " UNIT := {0-31}, default is 0" << endl; cerr << " UNIT := {0-31}, default is 0" << endl;
@ -134,11 +134,12 @@ int main(int argc, char* argv[])
string reserved_ids; string reserved_ids;
string image_params; string image_params;
string filename; string filename;
string token;
bool list = false; bool list = false;
opterr = 1; opterr = 1;
int opt; int opt;
while ((opt = getopt(argc, argv, "elmsvDINOTVXa:b:c:d:f:h:i:n:p:r:t:u:x:C:E:F:L:R:")) != -1) { while ((opt = getopt(argc, argv, "elmsvDINOTVXa:b:c:d:f:h:i:n:p:r:t:u:x:C:E:F:L:R:P::")) != -1) {
switch (opt) { switch (opt) {
case 'i': { case 'i': {
int id; int id;
@ -176,7 +177,7 @@ int main(int argc, char* argv[])
case 'c': case 'c':
command.set_operation(ParseOperation(optarg)); command.set_operation(ParseOperation(optarg));
if (command.operation() == NONE) { if (command.operation() == NO_OPERATION) {
cerr << "Error: Unknown operation '" << optarg << "'" << endl; cerr << "Error: Unknown operation '" << optarg << "'" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -301,6 +302,10 @@ int main(int argc, char* argv[])
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
case 'P':
token = optarg ? optarg : getpass("Password: ");
break;
case 'V': case 'V':
command.set_operation(VERSION_INFO); command.set_operation(VERSION_INFO);
break; break;
@ -329,7 +334,7 @@ int main(int argc, char* argv[])
if (list) { if (list) {
PbCommand command_list; PbCommand command_list;
command_list.set_operation(DEVICES_INFO); command_list.set_operation(DEVICES_INFO);
RasctlCommands rasctl_commands(command_list, hostname, port); RasctlCommands rasctl_commands(command_list, hostname, port, token);
rasctl_commands.CommandDevicesInfo(); rasctl_commands.CommandDevicesInfo();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
@ -340,7 +345,7 @@ int main(int argc, char* argv[])
AddParam(*device, "file", param); AddParam(*device, "file", param);
} }
RasctlCommands rasctl_commands(command, hostname, port); RasctlCommands rasctl_commands(command, hostname, port, token);
switch(command.operation()) { switch(command.operation()) {
case LOG_LEVEL: case LOG_LEVEL:

View File

@ -25,15 +25,20 @@ using namespace std;
using namespace rascsi_interface; using namespace rascsi_interface;
using namespace protobuf_util; using namespace protobuf_util;
RasctlCommands::RasctlCommands(PbCommand& command, const string& hostname, int port) RasctlCommands::RasctlCommands(PbCommand& command, const string& hostname, int port, const string& token)
{ {
this->command = command; this->command = command;
this->hostname = hostname; this->hostname = hostname;
this->port = port; this->port = port;
this->token = token;
} }
void RasctlCommands::SendCommand() void RasctlCommands::SendCommand()
{ {
if (!token.empty()) {
AddParam(command, "token", token);
}
// Send command // Send command
int fd = -1; int fd = -1;
try { try {

View File

@ -20,7 +20,7 @@ class RasctlCommands
{ {
public: public:
RasctlCommands(PbCommand&, const string&, int); RasctlCommands(PbCommand&, const string&, int, const string&);
~RasctlCommands() {}; ~RasctlCommands() {};
void SendCommand(); void SendCommand();
@ -48,6 +48,7 @@ private:
PbCommand command; PbCommand command;
string hostname; string hostname;
int port; int port;
string token;
PbResult result; PbResult result;