Allow setting DISKSERIAL compile variable to lock build to specific HDD serial number

This commit is contained in:
Thulinma 2020-11-04 23:51:13 +01:00
parent f8f799422b
commit 1f390561c2
2 changed files with 128 additions and 0 deletions

View file

@ -131,6 +131,11 @@ endif()
set(APPNAME "MistServer" CACHE STRING "Name of the application, as used in user agent strings and the like")
add_definitions(-DAPPNAME="${APPNAME}")
set(DISKSERIAL "" CACHE STRING "Lock application to given disk serial number")
if (DISKSERIAL)
add_definitions(-DDISKSERIAL="${DISKSERIAL}")
endif()
option(WITH_THREADNAMES "Enable fancy names for threads (not supported on all platforms)")
if (WITH_THREADNAMES)
add_definitions(-DWITH_THREADNAMES=1)

View file

@ -59,6 +59,122 @@ void Util::logExitReason(const char *format, ...){
std::string Util::listenInterface;
uint32_t Util::listenPort = 0;
#ifdef DISKSERIAL
#ifdef __CYGWIN__
static bool checkSerial(const std::string &ser, const std::string & directory = "/proc/registry/HKEY_LOCAL_MACHINE/HARDWARE/DEVICEMAP"){
bool ret = false;
struct stat statbuf;
char serial[512];
DIR *d = opendir(directory.c_str());
if (!d){return false;}
struct dirent *dp;
do{
errno = 0;
if ((dp = readdir(d))){
std::string newFile = directory + "/" + dp->d_name;
if (dp->d_type == DT_DIR){
ret |= checkSerial(ser, newFile);
if (ret){break;}
continue;
}
if (strncmp(dp->d_name, "SerialNumber", 12) == 0){
if (!stat(newFile.c_str(), &statbuf)){
FILE * fd = fopen(newFile.c_str(), "r");
int len = fread(serial, 1, 512, fd);
std::string currSer(serial, len);
while (currSer.size() && (currSer[0] == ' ' || currSer[0] == 0)){currSer.erase(0, 1);}
while (currSer.size() && (currSer[currSer.size()-1] == ' ' || currSer[currSer.size()-1] == 0)){currSer.erase(currSer.size()-1);}
if (currSer == ser){ret = true;}
fclose(fd);
}
}
if (ret){break;}
}
}while (dp != NULL);
closedir(d);
return ret;
}
#else
static bool checkSerial(const std::string &ser){
//INFO_MSG("Checking serial: %s", ser.c_str());
bool ret = false;
char serFile[300];
struct stat statbuf;
char serial[300];
DIR *d = opendir("/sys/block");
struct dirent *dp;
if (d){
do{
errno = 0;
if ((dp = readdir(d))){
if (strncmp(dp->d_name, "loop", 4) != 0 && dp->d_name[0] != '.'){
snprintf(serFile, 300, "/sys/block/%s/device/serial", dp->d_name);
if (!stat(serFile, &statbuf)){
FILE * fd = fopen(serFile, "r");
int len = fread(serial, 1, 300, fd);
if (len && len >= ser.size()){
//INFO_MSG("Comparing with: %.*s", len, serial);
if (!strncmp(ser.data(), serial, ser.size())){
ret = true;
fclose(fd);
break;
}
}
fclose(fd);
}
snprintf(serFile, 300, "/sys/block/%s/device/wwid", dp->d_name);
if (!stat(serFile, &statbuf)){
FILE * fd = fopen(serFile, "r");
int len = fread(serial, 1, 300, fd);
if (len && len >= ser.size()){
std::string fullLine(serial, len);
while (fullLine.size() && fullLine[fullLine.size()-1] < 33){fullLine.erase(fullLine.size()-1);}
size_t lSpace = fullLine.rfind(' ');
if (lSpace != std::string::npos){
std::string curSer = fullLine.substr(lSpace+1);
if (curSer.size() > ser.size()){curSer = curSer.substr(0, ser.size());}
//INFO_MSG("Comparing with: %s", curSer.c_str());
if (ser == curSer){
ret = true;
fclose(fd);
break;
}
}else{
if (ser == fullLine){
ret = true;
fclose(fd);
break;
}
}
}
fclose(fd);
}
}
}
}while (dp != NULL);
closedir(d);
}
if (ret){return true;}
d = opendir("/dev/disk/by-id");
if (d){
do{
errno = 0;
if ((dp = readdir(d))){
std::string fn = dp->d_name;
if (fn.size() >= ser.size() && fn.substr(fn.size() - ser.size()) == ser){
ret = true;
break;
}
}
}while (dp != NULL);
closedir(d);
}
return ret;
}
#endif
#endif
Util::Config::Config(){
// global options here
vals["debug"]["long"] = "debug";
@ -443,6 +559,13 @@ int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection &S)){
/// - Set is_active to true.
/// - Set up a signal handler to set is_active to false for the SIGINT, SIGHUP and SIGTERM signals.
void Util::Config::activate(){
#ifdef DISKSERIAL
if (!checkSerial(DISKSERIAL)){
ERROR_MSG("Not licensed");
exit(1);
return;
}
#endif
if (vals.isMember("username")){
setUser(getString("username"));
vals.removeMember("username");