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") set(APPNAME "MistServer" CACHE STRING "Name of the application, as used in user agent strings and the like")
add_definitions(-DAPPNAME="${APPNAME}") 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)") option(WITH_THREADNAMES "Enable fancy names for threads (not supported on all platforms)")
if (WITH_THREADNAMES) if (WITH_THREADNAMES)
add_definitions(-DWITH_THREADNAMES=1) add_definitions(-DWITH_THREADNAMES=1)

View file

@ -59,6 +59,122 @@ void Util::logExitReason(const char *format, ...){
std::string Util::listenInterface; std::string Util::listenInterface;
uint32_t Util::listenPort = 0; 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(){ Util::Config::Config(){
// global options here // global options here
vals["debug"]["long"] = "debug"; vals["debug"]["long"] = "debug";
@ -443,6 +559,13 @@ int Util::Config::serveForkedSocket(int (*callback)(Socket::Connection &S)){
/// - Set is_active to true. /// - Set is_active to true.
/// - Set up a signal handler to set is_active to false for the SIGINT, SIGHUP and SIGTERM signals. /// - Set up a signal handler to set is_active to false for the SIGINT, SIGHUP and SIGTERM signals.
void Util::Config::activate(){ void Util::Config::activate(){
#ifdef DISKSERIAL
if (!checkSerial(DISKSERIAL)){
ERROR_MSG("Not licensed");
exit(1);
return;
}
#endif
if (vals.isMember("username")){ if (vals.isMember("username")){
setUser(getString("username")); setUser(getString("username"));
vals.removeMember("username"); vals.removeMember("username");