1 #include "otsdaq-core/WebUsersUtilities/WebUsers.h"
2 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
7 #include <openssl/sha.h>
19 #define WEB_LOGIN_BKUP_DB_PATH "bkup/"
21 #define SECURITY_FILE_NAME std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData/security.dat"
23 #define USERS_ACTIVE_SESSIONS_FILE USERS_DB_PATH + "/activeSessions.sv"
25 #define HASHES_DB_FILE HASHES_DB_PATH + "/hashes.xml"
26 #define USERS_DB_FILE USERS_DB_PATH + "/users.xml"
27 #define USERS_GLOBAL_HISTORY_FILE "__global"
28 #define USERS_LOGIN_HISTORY_FILETYPE "hist"
29 #define USERS_PREFERENCES_FILETYPE "pref"
30 #define SYSTEM_PREFERENCES_PREFIX "system.preset"
31 #define USER_WITH_LOCK_FILE WEB_LOGIN_DB_PATH + "/user_with_lock.dat"
32 #define IP_BLACKLIST_FILE WEB_LOGIN_DB_PATH + "/ip_generated_blacklist.dat"
33 #define IP_REJECT_FILE WEB_LOGIN_DB_PATH + "/ip_reject.dat"
34 #define IP_ACCEPT_FILE WEB_LOGIN_DB_PATH + "/ip_accept.dat"
36 #define HASHES_DB_GLOBAL_STRING "hashData"
37 #define HASHES_DB_ENTRY_STRING "hashEntry"
38 #define USERS_DB_GLOBAL_STRING "userData"
39 #define USERS_DB_ENTRY_STRING "userEntry"
40 #define USERS_DB_NEXT_UID_STRING "nextUserId"
43 #define PREF_XML_BGCOLOR_FIELD "pref_bgcolor" // -background color
44 #define PREF_XML_DBCOLOR_FIELD "pref_dbcolor" // -dashboard color
45 #define PREF_XML_WINCOLOR_FIELD "pref_wincolor" // -window color
46 #define PREF_XML_LAYOUT_FIELD "pref_layout" // -3 defaults window layouts(and current)
47 #define PREF_XML_SYSLAYOUT_FIELD "pref_syslayout" // -2 defaults window layouts
48 #define PREF_XML_PERMISSIONS_FIELD "desktop_user_permissions" // 0-255 permissions value (255 is admin super user)
49 #define PREF_XML_USERLOCK_FIELD "username_with_lock" // user with lock (to lockout others)
50 #define PREF_XML_USERNAME_FIELD "pref_username" // user with lock (to lockout others)
52 #define PREF_XML_BGCOLOR_DEFAULT "rgb(0,76,151)" // -background color
53 #define PREF_XML_DBCOLOR_DEFAULT "rgb(0,40,85)" // -dashboard color
54 #define PREF_XML_WINCOLOR_DEFAULT "rgba(196,229,255,0.9)" // -window color
55 #define PREF_XML_LAYOUT_DEFAULT "0;0;0;0" // 3 default window layouts(and current)
56 #define PREF_XML_SYSLAYOUT_DEFAULT "0;0" // 2 system default window layouts
58 #define PREF_XML_ACCOUNTS_FIELD "users_accounts" // user accounts field for super users
59 #define PREF_XML_LOGIN_HISTORY_FIELD "login_entry" // login history field for user login history data
61 const std::string WebUsers::DEFAULT_ADMIN_USERNAME =
"admin";
62 const std::string WebUsers::DEFAULT_ADMIN_DISPLAY_NAME =
"Administrator";
63 const std::string WebUsers::DEFAULT_ADMIN_EMAIL =
"root@otsdaq.fnal.gov";
64 const std::string WebUsers::DEFAULT_ITERATOR_USERNAME =
"iterator";
65 const std::string WebUsers::DEFAULT_STATECHANGER_USERNAME =
"statechanger";
66 const std::string WebUsers::DEFAULT_USER_GROUP =
"allUsers";
68 const std::string WebUsers::REQ_NO_LOGIN_RESPONSE =
"NoLogin";
69 const std::string WebUsers::REQ_NO_PERMISSION_RESPONSE =
"NoPermission";
70 const std::string WebUsers::REQ_USER_LOCKOUT_RESPONSE =
"UserLockout";
71 const std::string WebUsers::REQ_LOCK_REQUIRED_RESPONSE =
"LockRequired";
72 const std::string WebUsers::REQ_ALLOW_NO_USER =
"AllowNoUser";
74 const std::string WebUsers::SECURITY_TYPE_NONE =
"NoSecurity";
75 const std::string WebUsers::SECURITY_TYPE_DIGEST_ACCESS =
"DigestAccessAuthentication";
81 #define __MF_SUBJECT__ "WebUsers"
89 usersUsernameWithLock_ =
"";
92 HashesDatabaseEntryFields.push_back(
"hash");
93 HashesDatabaseEntryFields.push_back(
"lastAccessTime");
95 UsersDatabaseEntryFields.push_back(
"username");
96 UsersDatabaseEntryFields.push_back(
"displayName");
97 UsersDatabaseEntryFields.push_back(
"salt");
98 UsersDatabaseEntryFields.push_back(
"uid");
99 UsersDatabaseEntryFields.push_back(
"permissions");
100 UsersDatabaseEntryFields.push_back(
"lastLoginAttemptTime");
101 UsersDatabaseEntryFields.push_back(
"accountCreatedTime");
102 UsersDatabaseEntryFields.push_back(
"loginFailureCount");
103 UsersDatabaseEntryFields.push_back(
"lastModifiedTime");
104 UsersDatabaseEntryFields.push_back(
"lastModifierUsername");
105 UsersDatabaseEntryFields.push_back(
"useremail");
108 mkdir(((std::string)WEB_LOGIN_DB_PATH).c_str(), 0755);
109 mkdir(((std::string)WEB_LOGIN_DB_PATH +
"bkup/" + USERS_DB_PATH).c_str(), 0755);
110 mkdir(((std::string)WEB_LOGIN_DB_PATH + HASHES_DB_PATH).c_str(), 0755);
111 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH).c_str(), 0755);
112 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_LOGIN_HISTORY_PATH).c_str(), 0755);
113 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_PREFERENCES_PATH).c_str(), 0755);
116 if (!loadDatabases())
117 __COUT__ <<
"FATAL USER DATABASE ERROR - failed to load!!!" << __E__;
119 loadSecuritySelection();
124 std::string user = DEFAULT_ADMIN_USERNAME;
125 if ((i = searchUsersDatabaseForUsername(user)) == NOT_FOUND_IN_DATABASE)
127 __SS__ <<
"user: " << user <<
" is not found" << __E__;
128 __COUT_ERR__ << ss.str();
129 throw std::runtime_error(ss.str());
132 else if (UsersSaltVector[i] ==
"" &&
133 securityType_ == SECURITY_TYPE_DIGEST_ACCESS)
135 char charTimeStr[10];
136 sprintf(charTimeStr,
"%d",
int(UsersAccountCreatedTimeVector[i] & 0xffff));
137 std::string tmpTimeStr = charTimeStr;
142 std::thread([](
const std::string& nac,
const std::string& user) { WebUsers::NACDisplayThread(nac, user); },
143 tmpTimeStr, user).detach();
149 loadActiveSessions();
157 __COUT__ <<
"Done with Web Users initialization!" << __E__;
348 bool WebUsers::xmlRequestOnGateway(
350 std::ostringstream* out,
357 WebUsers::initializeRequestUserInfo(cgi,userInfo);
362 if (!cookieCodeIsActiveForRequest(
363 userInfo.cookieCode_,
364 &userInfo.groupPermissionLevelMap_,
367 !userInfo.automatedCommand_ ,
368 &userInfo.usernameWithLock_,
369 &userInfo.activeUserSessionIndex_))
371 *out << userInfo.cookieCode_;
372 goto HANDLE_ACCESS_FAILURE;
376 userInfo.getGroupPermissionLevel();
377 userInfo.username_ = UsersUsernameVector[userInfo.uid_];
378 userInfo.displayName_ = UsersDisplayNameVector[userInfo.uid_];
380 if(!WebUsers::checkRequestAccess(cgi,out,xmldoc,userInfo))
381 goto HANDLE_ACCESS_FAILURE;
386 HANDLE_ACCESS_FAILURE:
388 if(!userInfo.automatedCommand_)
389 __COUT_ERR__ <<
"Failed request (requestType = " << userInfo.requestType_ <<
390 "): " << out->str() << __E__;
398 void WebUsers::initializeRequestUserInfo(
402 userInfo.permissionLevel_ = 0;
403 userInfo.ip_ = cgi.getEnvironment().getRemoteAddr();
406 userInfo.username_ =
"";
407 userInfo.displayName_ =
"";
408 userInfo.usernameWithLock_ =
"";
409 userInfo.activeUserSessionIndex_ = -1;
410 userInfo.setGroupPermissionLevels(
"");
418 bool WebUsers::checkRequestAccess(
420 std::ostringstream* out,
430 if(!userInfo.automatedCommand_)
432 __COUT__ <<
"requestType ==========>>> " << userInfo.requestType_ << __E__;
433 __COUTV__((
unsigned int)userInfo.permissionLevel_);
434 __COUTV__((
unsigned int)userInfo.permissionsThreshold_);
438 if(!isWizardMode && !userInfo.allowNoUser_ &&
439 userInfo.cookieCode_.length() != WebUsers::COOKIE_CODE_LENGTH)
441 __COUT__ <<
"User (@" << userInfo.ip_ <<
") has invalid cookie code: " <<
442 userInfo.cookieCode_ << std::endl;
443 *out << WebUsers::REQ_NO_LOGIN_RESPONSE;
447 if(!userInfo.allowNoUser_ &&
448 (userInfo.permissionLevel_ == 0 ||
449 userInfo.permissionLevel_ < userInfo.permissionsThreshold_))
451 *out << WebUsers::REQ_NO_PERMISSION_RESPONSE;
452 __COUT__ <<
"User (@" << userInfo.ip_ <<
") has insufficient permissions for requestType '" <<
453 userInfo.requestType_ <<
455 (
unsigned int)userInfo.permissionLevel_ <<
"<" <<
456 (
unsigned int)userInfo.permissionsThreshold_ << std::endl;
463 userInfo.username_ =
"admin";
464 userInfo.displayName_ =
"Admin";
465 userInfo.usernameWithLock_ =
"admin";
466 userInfo.activeUserSessionIndex_ = 0;
473 if(userInfo.allowNoUser_)
474 xmldoc->setHeader(WebUsers::REQ_ALLOW_NO_USER);
476 xmldoc->setHeader(userInfo.cookieCode_);
479 if(userInfo.allowNoUser_)
return true;
488 if((userInfo.checkLock_ || userInfo.requireLock_) &&
489 userInfo.usernameWithLock_ !=
"" &&
490 userInfo.usernameWithLock_ != userInfo.username_)
492 *out << WebUsers::REQ_USER_LOCKOUT_RESPONSE;
493 __COUT__ <<
"User '" << userInfo.username_ <<
"' is locked out. '" <<
494 userInfo.usernameWithLock_ <<
"' has lock." << std::endl;
498 if(userInfo.requireLock_ &&
499 userInfo.usernameWithLock_ != userInfo.username_)
501 *out << WebUsers::REQ_LOCK_REQUIRED_RESPONSE;
502 __COUT__ <<
"User '" << userInfo.username_ <<
"' must have lock to proceed. ('" <<
503 userInfo.usernameWithLock_ <<
"' has lock.)" << std::endl;
514 void WebUsers::saveActiveSessions()
518 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_ACTIVE_SESSIONS_FILE;
519 __COUT__ << fn << __E__;
521 FILE *fp = fopen(fn.c_str(),
"w");
524 __COUT_ERR__ <<
"Error! Persistent active sessions could not be saved to file: " <<
530 fprintf(fp,
"%d\n", version);
531 for (
unsigned int i = 0; i < ActiveSessionCookieCodeVector.size(); ++i)
539 fprintf(fp,
"%s\n", ActiveSessionCookieCodeVector[i].c_str());
540 fprintf(fp,
"%s\n", ActiveSessionIpVector[i].c_str());
541 fprintf(fp,
"%lu\n", ActiveSessionUserIdVector[i]);
542 fprintf(fp,
"%lu\n", ActiveSessionIndex[i]);
543 fprintf(fp,
"%ld\n", ActiveSessionStartTimeVector[i]);
546 __COUT__ <<
"ActiveSessionCookieCodeVector saved with size " <<
547 ActiveSessionCookieCodeVector.size() << __E__;
555 void WebUsers::loadActiveSessions()
559 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_ACTIVE_SESSIONS_FILE;
560 __COUT__ << fn << __E__;
561 FILE *fp = fopen(fn.c_str(),
"r");
564 __COUT_INFO__ <<
"Persistent active sessions were not found to be loaded at file: " <<
571 const int LINELEN = 1000;
573 fgets(line, LINELEN, fp);
574 sscanf(line,
"%d", &version);
577 __COUT__ <<
"Extracting active sessions..." << __E__;
581 while (fgets(line, LINELEN, fp))
583 if (strlen(line)) line[strlen(line) - 1] =
'\0';
584 if (strlen(line) != COOKIE_CODE_LENGTH)
586 __COUT__ <<
"Illegal cookie code found: " << line << __E__;
591 ActiveSessionCookieCodeVector.push_back(line);
593 fgets(line, LINELEN, fp);
594 if (strlen(line)) line[strlen(line) - 1] =
'\0';
595 ActiveSessionIpVector.push_back(line);
597 fgets(line, LINELEN, fp);
598 ActiveSessionUserIdVector.push_back(uint64_t());
599 sscanf(line,
"%lu", &(ActiveSessionUserIdVector[ActiveSessionUserIdVector.size() - 1]));
601 fgets(line, LINELEN, fp);
602 ActiveSessionIndex.push_back(uint64_t());
603 sscanf(line,
"%lu", &(ActiveSessionIndex[ActiveSessionIndex.size() - 1]));
605 fgets(line, LINELEN, fp);
606 ActiveSessionStartTimeVector.push_back(time_t());
607 sscanf(line,
"%ld", &(ActiveSessionStartTimeVector[ActiveSessionStartTimeVector.size() - 1]));
618 __COUT__ <<
"ActiveSessionCookieCodeVector loaded with size " <<
619 ActiveSessionCookieCodeVector.size() << __E__;
624 fp = fopen(fn.c_str(),
"w");
633 bool WebUsers::loadDatabases()
638 const unsigned int LINE_LEN = 1000;
640 unsigned int i, si, c, len, f;
651 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_FILE;
652 __COUT__ << fn << __E__;
653 fp = fopen(fn.c_str(),
"r");
656 mkdir(((std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_PATH).c_str(), 0755);
657 __COUT__ << ((std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_PATH).c_str() << __E__;
658 fp = fopen(fn.c_str(), "w");
659 if (!fp) return false;
660 __COUT__ << "Hashes database created: " << fn << __E__;
662 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING, "", DB_SAVE_OPEN);
663 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING, "", DB_SAVE_CLOSE);
670 while (fgets(line, LINE_LEN, fp))
672 if (strlen(line) < SHA512_DIGEST_LENGTH)
continue;
676 for (i = 0; i < len; ++i)
680 if (c != 2 && c != 4)
continue;
683 while (i < len && line[i] !=
'<') ++i;
692 HashesVector.push_back(&line[si]);
695 sscanf(&line[si],
"%lu", &tmpInt64);
696 HashesAccessTimeVector.push_back(tmpInt64);
700 __COUT__ << HashesAccessTimeVector.size() <<
" Hashes found." << __E__;
714 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_FILE;
715 fp = fopen(fn.c_str(),
"r");
718 mkdir(((std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_PATH).c_str(), 0755);
719 __COUT__ << ((std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_PATH).c_str() << __E__;
720 fp = fopen(fn.c_str(), "w");
721 if (!fp) return false;
722 __COUT__ << "Users database created: " << fn << __E__;
724 saveToDatabase(fp, USERS_DB_GLOBAL_STRING, "", DB_SAVE_OPEN);
726 sprintf(nidStr, "%lu", usersNextUserId_);
727 saveToDatabase(fp, USERS_DB_NEXT_UID_STRING, nidStr, DB_SAVE_OPEN_AND_CLOSE);
728 saveToDatabase(fp, USERS_DB_GLOBAL_STRING, "", DB_SAVE_CLOSE);
731 createNewAccount(DEFAULT_ADMIN_USERNAME, DEFAULT_ADMIN_DISPLAY_NAME, DEFAULT_ADMIN_EMAIL);
738 char salt[] =
"nextUserId";
739 while (fgets(line, LINE_LEN, fp))
741 if (strlen(line) < strlen(salt) * 2)
continue;
743 for (i = 0; i < strlen(salt); ++i)
744 if (line[i + 1] != salt[i])
break;
746 if (i == strlen(salt))
750 while (i < LINE_LEN && line[i] !=
'\0' && line[i] !=
'<') ++i;
752 sscanf(&line[si],
"%lu", &usersNextUserId_);
757 __COUT__ <<
"Found Users database next user Id: " << usersNextUserId_ << __E__;
760 while (fgets(line, LINE_LEN, fp))
762 if (strlen(line) < 30)
continue;
768 __COUT__ <<
"Line buffer too small: " << len << __E__;
774 for (i = 0; i < len; ++i)
778 if (c == 0 || c % 2 == 1)
continue;
781 while (i < len && line[i] !=
'<') ++i;
790 UsersUsernameVector.push_back(&line[si]);
792 UsersDisplayNameVector.push_back(&line[si]);
794 UsersSaltVector.push_back(&line[si]);
797 sscanf(&line[si],
"%lu", &tmpInt64);
798 UsersUserIdVector.push_back(tmpInt64);
802 UsersPermissionsVector.push_back(std::map<std::string,uint8_t>());
803 std::map<std::string,uint8_t>& lastPermissionsMap = UsersPermissionsVector.back();
804 StringMacros::getMapFromString<uint8_t>(&line[si],
811 if(lastPermissionsMap.find(WebUsers::DEFAULT_USER_GROUP) ==
812 lastPermissionsMap.end())
816 sscanf(&line[si],
"%lu", &tmpInt64);
820 lastPermissionsMap.clear();
821 __COUT_INFO__ <<
"User '" <<
822 UsersUsernameVector.back() <<
"' is not a member of the default user group '" <<
823 WebUsers::DEFAULT_USER_GROUP <<
".' For backward compatibility, permission level assumed for default group (permission level := " <<
824 tmpInt64 <<
")." << __E__;
825 lastPermissionsMap[WebUsers::DEFAULT_USER_GROUP] = WebUsers::permissionLevel_t(tmpInt64);
829 __MCOUT_INFO__(
"User '" <<
830 UsersUsernameVector.back() <<
"' is not a member of the default user group '" <<
831 WebUsers::DEFAULT_USER_GROUP <<
".' Assuming user account is inactive (permission level := " <<
832 WebUsers::PERMISSION_LEVEL_INACTIVE <<
")." << __E__);
833 lastPermissionsMap[WebUsers::DEFAULT_USER_GROUP] = WebUsers::PERMISSION_LEVEL_INACTIVE;
839 sscanf(&line[si],
"%lu", &tmpInt64);
840 UsersLastLoginAttemptVector.push_back(tmpInt64);
844 sscanf(&line[si],
"%lu", &tmpInt64);
845 UsersAccountCreatedTimeVector.push_back(tmpInt64);
849 sscanf(&line[si],
"%lu", &tmpInt64);
850 UsersLoginFailureCountVector.push_back(tmpInt64);
854 sscanf(&line[si],
"%lu", &tmpInt64);
855 UsersLastModifiedTimeVector.push_back(tmpInt64);
858 UsersLastModifierUsernameVector.push_back(&line[si]);
860 UsersUserEmailVector.push_back(&line[si]);
865 if (f && f != UsersDatabaseEntryFields.size() - 1)
867 if (f != 7 && f != 9)
869 __SS__ <<
"FATAL ERROR - invalid user database found with field number " << f << __E__;
878 __COUT__ <<
"Update database to current version - adding fields: " <<
879 (UsersDatabaseEntryFields.size() - 1 - f) << __E__;
881 UsersLastModifiedTimeVector.push_back(0);
882 UsersLastModifierUsernameVector.push_back(
"");
886 UsersUserEmailVector.push_back(
"");
893 __COUT__ << UsersLastModifiedTimeVector.size() <<
" Users found." << __E__;
894 for (
size_t ii = 0; ii < UsersLastModifiedTimeVector.size(); ++ii)
896 __COUT__ <<
"User " << UsersUserIdVector[ii] <<
": Name: " << UsersUsernameVector[ii] <<
897 "\t\tDisplay Name: " << UsersDisplayNameVector[ii] <<
"\t\tEmail: " <<
898 UsersUserEmailVector[ii] <<
"\t\tPermissions: " <<
899 StringMacros::mapToString(UsersPermissionsVector[ii]) << __E__;
906 void WebUsers::saveToDatabase(FILE * fp,
const std::string& field,
const std::string& value, uint8_t type,
bool addNewLine)
910 std::string newLine = addNewLine ?
"\n" :
"";
912 if (type == DB_SAVE_OPEN_AND_CLOSE)
913 fprintf(fp,
"<%s>%s</%s>%s", field.c_str(), value.c_str(), field.c_str(), newLine.c_str());
914 else if (type == DB_SAVE_OPEN)
915 fprintf(fp,
"<%s>%s%s", field.c_str(), value.c_str(), newLine.c_str());
916 else if (type == DB_SAVE_CLOSE)
917 fprintf(fp,
"</%s>%s", field.c_str(), newLine.c_str());
928 bool WebUsers::saveDatabaseToFile(uint8_t db)
930 __COUT__ <<
"Save Database: " << (int)db << __E__;
932 std::string fn = (std::string)WEB_LOGIN_DB_PATH +
933 ((db == DB_USERS) ? (std::string)USERS_DB_FILE : (std::string)HASHES_DB_FILE);
935 __COUT__ <<
"Save Database Filename: " << fn << __E__;
941 sprintf(dayAppend,
".%lu.bkup", time(0) / (3600 * 24));
942 std::string bkup_fn = (std::string)WEB_LOGIN_DB_PATH +
943 (std::string)WEB_LOGIN_BKUP_DB_PATH +
944 ((db == DB_USERS) ? (std::string)USERS_DB_FILE : (std::
string)HASHES_DB_FILE) +
945 (std::
string)dayAppend;
947 __COUT__ << "Backup file: " << bkup_fn << __E__;
949 std::
string shell_command = "mv " + fn + " " + bkup_fn;
950 system(shell_command.c_str());
953 FILE *fp = fopen(fn.c_str(), "wb");
954 if (!fp) return false;
960 saveToDatabase(fp, USERS_DB_GLOBAL_STRING,
"", DB_SAVE_OPEN);
962 sprintf(fldStr,
"%lu", usersNextUserId_);
963 saveToDatabase(fp, USERS_DB_NEXT_UID_STRING, fldStr, DB_SAVE_OPEN_AND_CLOSE);
965 __COUT__ <<
"Saving " << UsersUsernameVector.size() <<
" Users." << __E__;
967 for (uint64_t i = 0; i < UsersUsernameVector.size(); ++i)
971 saveToDatabase(fp, USERS_DB_ENTRY_STRING,
"", DB_SAVE_OPEN,
false);
973 for (
unsigned int f = 0; f < UsersDatabaseEntryFields.size(); ++f)
977 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersUsernameVector[i], DB_SAVE_OPEN_AND_CLOSE,
false);
979 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersDisplayNameVector[i], DB_SAVE_OPEN_AND_CLOSE,
false);
981 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersSaltVector[i], DB_SAVE_OPEN_AND_CLOSE,
false);
984 sprintf(fldStr,
"%lu", UsersUserIdVector[i]);
985 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE,
false);
988 saveToDatabase(fp, UsersDatabaseEntryFields[f],
989 StringMacros::mapToString(UsersPermissionsVector[i],
",",
":"), DB_SAVE_OPEN_AND_CLOSE,
false);
992 sprintf(fldStr,
"%lu", UsersLastLoginAttemptVector[i]);
993 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE,
false);
997 sprintf(fldStr,
"%lu", UsersAccountCreatedTimeVector[i]);
998 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE,
false);
1002 sprintf(fldStr,
"%d", UsersLoginFailureCountVector[i]);
1003 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE,
false);
1007 sprintf(fldStr,
"%lu", UsersLastModifiedTimeVector[i]);
1008 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE,
false);
1011 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersLastModifierUsernameVector[i], DB_SAVE_OPEN_AND_CLOSE,
false);
1013 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersUserEmailVector[i], DB_SAVE_OPEN_AND_CLOSE,
false);
1016 saveToDatabase(fp, USERS_DB_ENTRY_STRING,
"", DB_SAVE_CLOSE);
1019 saveToDatabase(fp, USERS_DB_GLOBAL_STRING,
"", DB_SAVE_CLOSE);
1024 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING,
"", DB_SAVE_OPEN);
1026 __COUT__ <<
"Saving " << HashesVector.size() <<
" Hashes." << __E__;
1027 for (uint64_t i = 0; i < HashesVector.size(); ++i)
1029 __COUT__ <<
"Saving " << HashesVector[i] <<
" Hashes." << __E__;
1030 saveToDatabase(fp, HASHES_DB_ENTRY_STRING,
"", DB_SAVE_OPEN,
false);
1031 for (
unsigned int f = 0; f < HashesDatabaseEntryFields.size(); ++f)
1034 saveToDatabase(fp, HashesDatabaseEntryFields[f], HashesVector[i], DB_SAVE_OPEN_AND_CLOSE,
false);
1037 sprintf(fldStr,
"%lu", HashesAccessTimeVector[i]);
1038 saveToDatabase(fp, HashesDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE,
false);
1041 saveToDatabase(fp, HASHES_DB_ENTRY_STRING,
"", DB_SAVE_CLOSE);
1044 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING,
"", DB_SAVE_CLOSE);
1059 bool WebUsers::createNewAccount(
const std::string& username,
const std::string& displayName,
1060 const std::string& email)
1062 __COUT__ <<
"Creating account: " << username << __E__;
1065 if ((i = searchUsersDatabaseForUsername(username)) != NOT_FOUND_IN_DATABASE ||
1066 username == WebUsers::DEFAULT_ITERATOR_USERNAME ||
1067 username == WebUsers::DEFAULT_STATECHANGER_USERNAME)
1069 __COUT_ERR__ <<
"Username '" << username <<
"' already exists" << __E__;
1074 UsersUsernameVector.push_back(username);
1075 UsersDisplayNameVector.push_back(displayName);
1076 UsersUserEmailVector.push_back(email);
1077 UsersSaltVector.push_back(
"");
1078 std::map<std::string ,WebUsers::permissionLevel_t> initPermissions = {{
1079 WebUsers::DEFAULT_USER_GROUP,
1080 (UsersPermissionsVector.size() ?
1081 WebUsers::PERMISSION_LEVEL_NOVICE:
1082 WebUsers::PERMISSION_LEVEL_ADMIN)}};
1083 UsersPermissionsVector.push_back(initPermissions);
1085 UsersUserIdVector.push_back(usersNextUserId_++);
1086 if (usersNextUserId_ == (uint64_t)-1)
1088 __COUT__ <<
"usersNextUserId_ wrap around!! Too many users??? Notify Admins." << __E__;
1089 usersNextUserId_ = 1;
1091 UsersLastLoginAttemptVector.push_back(0);
1092 UsersLoginFailureCountVector.push_back(0);
1093 UsersAccountCreatedTimeVector.push_back(time(0));
1094 UsersLastModifiedTimeVector.push_back(0);
1095 UsersLastModifierUsernameVector.push_back(
"");
1097 return saveDatabaseToFile(DB_USERS);
1106 bool WebUsers::deleteAccount(
const std::string& username,
const std::string& displayName)
1108 uint64_t i = searchUsersDatabaseForUsername(username);
1109 if (i == NOT_FOUND_IN_DATABASE)
return false;
1110 if (UsersDisplayNameVector[i] != displayName)
return false;
1114 UsersUsernameVector.erase(UsersUsernameVector.begin() + i);
1115 UsersUserEmailVector.erase(UsersUserEmailVector.begin() + i);
1116 UsersDisplayNameVector.erase(UsersDisplayNameVector.begin() + i);
1117 UsersSaltVector.erase(UsersSaltVector.begin() + i);
1118 UsersPermissionsVector.erase(UsersPermissionsVector.begin() + i);
1119 UsersUserIdVector.erase(UsersUserIdVector.begin() + i);
1120 UsersLastLoginAttemptVector.erase(UsersLastLoginAttemptVector.begin() + i);
1121 UsersAccountCreatedTimeVector.erase(UsersAccountCreatedTimeVector.begin() + i);
1122 UsersLoginFailureCountVector.erase(UsersLoginFailureCountVector.begin() + i);
1123 UsersLastModifierUsernameVector.erase(UsersLastModifierUsernameVector.begin() + i);
1124 UsersLastModifiedTimeVector.erase(UsersLastModifiedTimeVector.begin() + i);
1127 return saveDatabaseToFile(DB_USERS);
1131 unsigned int WebUsers::hexByteStrToInt(
const char *h)
1134 char hs[3] = { h[0],h[1],
'\0' };
1135 sscanf(hs,
"%X", &rv);
1140 void WebUsers::intToHexStr(
unsigned char i,
char *h)
1142 sprintf(h,
"%2.2X", i);
1156 uint64_t WebUsers::attemptActiveSession(
const std::string& uuid, std::string& jumbledUser,
1157 const std::string& jumbledPw, std::string& newAccountCode,
const std::string& ip)
1160 if(!checkIpAccess(ip))
1162 __COUT_ERR__ <<
"rejected ip: " << ip << __E__;
1163 return NOT_FOUND_IN_DATABASE;
1166 cleanupExpiredEntries();
1168 if (!CareAboutCookieCodes_)
1170 uint64_t uid = getAdminUserID();
1171 jumbledUser = getUsersDisplayName(uid);
1172 newAccountCode = genCookieCode();
1179 if ((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
1181 __COUT_ERR__ <<
"uuid: " << uuid <<
" is not found" << __E__;
1182 newAccountCode =
"1";
1184 incrementIpBlacklistCount(ip);
1186 return NOT_FOUND_IN_DATABASE;
1188 ++LoginSessionAttemptsVector[i];
1190 std::string user = dejumble(jumbledUser, LoginSessionIdVector[i]);
1192 std::string pw = dejumble(jumbledPw, LoginSessionIdVector[i]);
1195 if ((i = searchUsersDatabaseForUsername(user)) == NOT_FOUND_IN_DATABASE)
1197 __COUT_ERR__ <<
"user: " << user <<
" is not found" << __E__;
1199 incrementIpBlacklistCount(ip);
1201 return NOT_FOUND_IN_DATABASE;
1204 ipBlacklistCounts_[ip] = 0;
1206 UsersLastLoginAttemptVector[i] = time(0);
1208 if (isInactiveForGroup(UsersPermissionsVector[i]))
1210 __MCOUT_ERR__(
"User '" << user <<
"' account INACTIVE (could be due to failed logins)" << __E__);
1211 return NOT_FOUND_IN_DATABASE;
1214 if (UsersSaltVector[i] ==
"")
1216 __MCOUT__(
"First login attempt for user: " << user << __E__);
1218 char charTimeStr[10];
1219 sprintf(charTimeStr,
"%d",
int(UsersAccountCreatedTimeVector[i] & 0xffff));
1220 std::string tmpTimeStr = charTimeStr;
1221 if (newAccountCode != tmpTimeStr)
1223 __COUT__ <<
"New account code did not match: " << tmpTimeStr <<
" != " << newAccountCode << __E__;
1224 saveDatabaseToFile(DB_USERS);
1225 return NOT_FOUND_IN_DATABASE;
1231 while (!addToHashesDatabase(sha512(user, pw, UsersSaltVector[i])))
1235 UsersSaltVector[i] =
"";
1238 __COUT__ <<
"\tHash added: " << HashesVector[HashesVector.size() - 1] << __E__;
1242 std::string salt = UsersSaltVector[i];
1244 if (searchHashesDatabaseForHash(sha512(user, pw, salt)) == NOT_FOUND_IN_DATABASE)
1246 __COUT__ <<
"Failed login for " << user <<
" with permissions " <<
1247 StringMacros::mapToString(UsersPermissionsVector[i]) << __E__;
1249 ++UsersLoginFailureCountVector[i];
1250 if (UsersLoginFailureCountVector[i] >= USERS_MAX_LOGIN_FAILURES)
1251 UsersPermissionsVector[i][WebUsers::DEFAULT_USER_GROUP] = WebUsers::PERMISSION_LEVEL_INACTIVE;
1253 __COUT_INFO__ <<
"User/pw for user '" << user <<
"' was not correct (Failed Attempt #" <<
1254 (int)UsersLoginFailureCountVector[i] <<
" of " <<
1255 (
int)USERS_MAX_LOGIN_FAILURES << ")." << __E__;
1257 __COUTV__(isInactiveForGroup(UsersPermissionsVector[i]));
1258 if (isInactiveForGroup(UsersPermissionsVector[i]))
1259 __MCOUT_INFO__("Account '" << user << "' has been marked inactive due to too many failed login attempts (Failed Attempt
#" <<
1260 (int)UsersLoginFailureCountVector[i] <<
1261 ")! Note only admins can reactivate accounts." << __E__);
1264 saveDatabaseToFile(DB_USERS);
1265 return NOT_FOUND_IN_DATABASE;
1269 __MCOUT_INFO__(
"Login successful for: " << user << __E__);
1271 UsersLoginFailureCountVector[i] = 0;
1274 for (
int h = 0; h < 2; ++h)
1276 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_LOGIN_HISTORY_PATH + (h ? USERS_GLOBAL_HISTORY_FILE : UsersUsernameVector[i])
1277 +
"." + (std::string)USERS_LOGIN_HISTORY_FILETYPE;
1281 if (histXml.loadXmlDocument(fn))
1283 while (histXml.getChildrenCount() + 1 > (h ? USERS_GLOBAL_HISTORY_SIZE : USERS_LOGIN_HISTORY_SIZE))
1284 histXml.removeDataElement();
1287 __COUT__ <<
"No previous login history found." << __E__;
1292 sprintf(entryStr,
"Time=%lu Username=%s Permissions=%s UID=%lu",
1293 time(0), UsersUsernameVector[i].c_str(),
1294 StringMacros::mapToString(UsersPermissionsVector[i]).c_str(), UsersUserIdVector[i]);
1296 sprintf(entryStr,
"Time=%lu displayName=%s Permissions=%s UID=%lu",
1297 time(0), UsersDisplayNameVector[i].c_str(),
1298 StringMacros::mapToString(UsersPermissionsVector[i]).c_str(), UsersUserIdVector[i]);
1299 histXml.addTextElementToData(PREF_XML_LOGIN_HISTORY_FIELD, entryStr);
1302 histXml.saveXmlDocument(fn);
1306 saveDatabaseToFile(DB_USERS);
1307 jumbledUser = UsersDisplayNameVector[i];
1308 newAccountCode = createNewActiveSession(UsersUserIdVector[i],ip);
1309 return UsersUserIdVector[i];
1319 uint64_t WebUsers::attemptActiveSessionWithCert(
const std::string& uuid, std::string& email,
1320 std::string& cookieCode, std::string& user,
const std::string& ip)
1322 if (!checkIpAccess(ip))
1324 __COUT_ERR__ <<
"rejected ip: " << ip << __E__;
1325 return NOT_FOUND_IN_DATABASE;
1328 cleanupExpiredEntries();
1330 if (!CareAboutCookieCodes_)
1332 uint64_t uid = getAdminUserID();
1333 email = getUsersDisplayName(uid);
1334 cookieCode = genCookieCode();
1340 __COUT__ <<
"Rejecting logon with blank fingerprint" << __E__;
1342 incrementIpBlacklistCount(ip);
1344 return NOT_FOUND_IN_DATABASE;
1350 if ((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
1352 __COUT__ <<
"uuid: " << uuid <<
" is not found" << __E__;
1355 incrementIpBlacklistCount(ip);
1357 return NOT_FOUND_IN_DATABASE;
1359 ++LoginSessionAttemptsVector[i];
1361 email = getUserEmailFromFingerprint(email);
1362 __COUT__ <<
"DejumbledEmail = " << email << __E__;
1365 __COUT__ <<
"Rejecting logon with unknown fingerprint" << __E__;
1367 incrementIpBlacklistCount(ip);
1369 return NOT_FOUND_IN_DATABASE;
1373 if ((i = searchUsersDatabaseForUserEmail(email)) == NOT_FOUND_IN_DATABASE)
1375 __COUT__ <<
"email: " << email <<
" is not found" << __E__;
1377 incrementIpBlacklistCount(ip);
1379 return NOT_FOUND_IN_DATABASE;
1382 ipBlacklistCounts_[ip] = 0;
1384 user = getUsersUsername(i);
1386 UsersLastLoginAttemptVector[i] = time(0);
1387 if (isInactiveForGroup(UsersPermissionsVector[i]))
1389 __MCOUT__ (
"User '" << user <<
"' account INACTIVE (could be due to failed logins)." << __E__);
1390 return NOT_FOUND_IN_DATABASE;
1393 if (UsersSaltVector[i] ==
"")
1395 return NOT_FOUND_IN_DATABASE;
1398 __MCOUT__(
"Login successful for: " << user << __E__);
1400 UsersLoginFailureCountVector[i] = 0;
1403 for (
int h = 0; h < 2; ++h)
1405 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_LOGIN_HISTORY_PATH + (h ? USERS_GLOBAL_HISTORY_FILE : UsersUsernameVector[i])
1406 +
"." + (std::string)USERS_LOGIN_HISTORY_FILETYPE;
1410 if (histXml.loadXmlDocument(fn))
1412 while (histXml.getChildrenCount() + 1 > (h ? USERS_GLOBAL_HISTORY_SIZE : USERS_LOGIN_HISTORY_SIZE))
1413 histXml.removeDataElement();
1416 __COUT__ <<
"No previous login history found." << __E__;
1421 sprintf(entryStr,
"Time=%lu Username=%s Permissions=%s UID=%lu",
1422 time(0), UsersUsernameVector[i].c_str(),
1423 StringMacros::mapToString(UsersPermissionsVector[i]).c_str(), UsersUserIdVector[i]);
1425 sprintf(entryStr,
"Time=%lu displayName=%s Permissions=%s UID=%lu",
1426 time(0), UsersDisplayNameVector[i].c_str(),
1427 StringMacros::mapToString(UsersPermissionsVector[i]).c_str(), UsersUserIdVector[i]);
1428 histXml.addTextElementToData(PREF_XML_LOGIN_HISTORY_FIELD, entryStr);
1431 histXml.saveXmlDocument(fn);
1435 saveDatabaseToFile(DB_USERS);
1436 email = UsersDisplayNameVector[i];
1437 cookieCode = createNewActiveSession(UsersUserIdVector[i],ip);
1438 return UsersUserIdVector[i];
1444 uint64_t WebUsers::searchActiveSessionDatabaseForCookie(
const std::string& cookieCode)
const
1447 for (; i < ActiveSessionCookieCodeVector.size(); ++i)
1448 if (ActiveSessionCookieCodeVector[i] == cookieCode)
break;
1449 return (i == ActiveSessionCookieCodeVector.size()) ? NOT_FOUND_IN_DATABASE : i;
1456 bool WebUsers::isUsernameActive(
const std::string& username)
const
1459 if ((u = searchUsersDatabaseForUsername(username)) == NOT_FOUND_IN_DATABASE)
return false;
1460 return isUserIdActive(UsersUserIdVector[u]);
1467 bool WebUsers::isUserIdActive(uint64_t uid)
const
1470 for (; i < ActiveSessionUserIdVector.size(); ++i)
1471 if (ActiveSessionUserIdVector[i] == uid)
return true;
1478 uint64_t WebUsers::searchUsersDatabaseForUsername(
const std::string& username)
const
1481 for (; i < UsersUsernameVector.size(); ++i)
1482 if (UsersUsernameVector[i] == username)
break;
1483 return (i == UsersUsernameVector.size()) ? NOT_FOUND_IN_DATABASE : i;
1489 uint64_t WebUsers::searchUsersDatabaseForUserEmail(
const std::string& useremail)
const
1492 for (; i < UsersUserEmailVector.size(); ++i)
1493 if (UsersUserEmailVector[i] == useremail)
break;
1494 return (i == UsersUserEmailVector.size()) ? NOT_FOUND_IN_DATABASE : i;
1500 uint64_t WebUsers::searchUsersDatabaseForUserId(uint64_t uid)
const
1503 for (; i < UsersUserIdVector.size(); ++i)
1504 if (UsersUserIdVector[i] == uid)
break;
1505 return (i == UsersUserIdVector.size()) ? NOT_FOUND_IN_DATABASE : i;
1511 uint64_t WebUsers::searchLoginSessionDatabaseForUUID(
const std::string& uuid)
const
1514 for (; i < LoginSessionUUIDVector.size(); ++i)
1515 if (LoginSessionUUIDVector[i] == uuid)
break;
1516 return (i == LoginSessionUUIDVector.size()) ? NOT_FOUND_IN_DATABASE : i;
1522 uint64_t WebUsers::searchHashesDatabaseForHash(
const std::string& hash)
1527 for (; i < HashesVector.size(); ++i)
1528 if (HashesVector[i] == hash)
break;
1532 if (i < HashesAccessTimeVector.size())
1533 HashesAccessTimeVector.push_back((time(0) + (rand() % 2 ? 1 : -1)*(rand() % 30 * 24 * 60 * 60)) & 0x0FFFFFFFFFE000000);
1536 return (i == HashesVector.size()) ? NOT_FOUND_IN_DATABASE : i;
1543 bool WebUsers::addToHashesDatabase(
const std::string& hash)
1545 if (searchHashesDatabaseForHash(hash) != NOT_FOUND_IN_DATABASE)
1547 __COUT__ <<
"Hash collision: " << hash << __E__;
1550 HashesVector.push_back(hash);
1551 HashesAccessTimeVector.push_back((time(0) + (rand() % 2 ? 1 : -1)*(rand() % 30 * 24 * 60 * 60)) & 0x0FFFFFFFFFE000000);
1553 return saveDatabaseToFile(DB_HASHES);
1558 std::string WebUsers::genCookieCode()
1561 std::string cc =
"";
1562 for (uint32_t i = 0; i < COOKIE_CODE_LENGTH / 2; ++i)
1564 intToHexStr(rand(), hexStr);
1572 void WebUsers::removeLoginSessionEntry(
unsigned int i)
1574 LoginSessionIdVector.erase(LoginSessionIdVector.begin() + i);
1575 LoginSessionUUIDVector.erase(LoginSessionUUIDVector.begin() + i);
1576 LoginSessionIpVector.erase(LoginSessionIpVector.begin() + i);
1577 LoginSessionStartTimeVector.erase(LoginSessionStartTimeVector.begin() + i);
1578 LoginSessionAttemptsVector.erase(LoginSessionAttemptsVector.begin() + i);
1585 std::string WebUsers::createNewActiveSession(uint64_t uid,
const std::string& ip, uint64_t asIndex)
1588 ActiveSessionCookieCodeVector.push_back(genCookieCode());
1589 ActiveSessionIpVector.push_back(ip);
1590 ActiveSessionUserIdVector.push_back(uid);
1591 ActiveSessionStartTimeVector.push_back(time(0));
1594 ActiveSessionIndex.push_back(asIndex);
1599 for (uint64_t j = 0; j < ActiveSessionIndex.size(); ++j)
1600 if (ActiveSessionUserIdVector[j] == uid && max < ActiveSessionIndex[j])
1601 max = ActiveSessionIndex[j];
1603 ActiveSessionIndex.push_back(max ? max + 1 : 1);
1606 return ActiveSessionCookieCodeVector[ActiveSessionCookieCodeVector.size() - 1];
1611 void WebUsers::removeActiveSessionEntry(
unsigned int i)
1613 ActiveSessionCookieCodeVector.erase(ActiveSessionCookieCodeVector.begin() + i);
1614 ActiveSessionIpVector.erase(ActiveSessionIpVector.begin() + i);
1615 ActiveSessionUserIdVector.erase(ActiveSessionUserIdVector.begin() + i);
1616 ActiveSessionStartTimeVector.erase(ActiveSessionStartTimeVector.begin() + i);
1617 ActiveSessionIndex.erase(ActiveSessionIndex.begin() + i);
1643 std::string WebUsers::refreshCookieCode(
unsigned int i,
bool enableRefresh)
1646 for (uint64_t j = ActiveSessionUserIdVector.size() - 1; j != (uint64_t)-1; --j)
1647 if (ActiveSessionUserIdVector[j] == ActiveSessionUserIdVector[i] &&
1648 ActiveSessionIndex[j] == ActiveSessionIndex[i])
1653 if (enableRefresh && (time(0) - ActiveSessionStartTimeVector[j] > ACTIVE_SESSION_EXPIRATION_TIME / 2))
1656 ActiveSessionStartTimeVector[j] = time(0) - ACTIVE_SESSION_EXPIRATION_TIME +
1657 ACTIVE_SESSION_COOKIE_OVERLAP_TIME;
1660 return createNewActiveSession(ActiveSessionUserIdVector[i], ActiveSessionIpVector[i], ActiveSessionIndex[i]);
1663 return ActiveSessionCookieCodeVector[j];
1674 uint64_t WebUsers::isCookieCodeActiveForLogin(
const std::string& uuid, std::string& cookieCode,
1675 std::string& username)
1677 if (!CareAboutCookieCodes_)
1678 return getAdminUserID();
1683 if (!ActiveSessionStartTimeVector.size())
return NOT_FOUND_IN_DATABASE;
1688 if ((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
1690 __COUT__ <<
"uuid not found: " << uuid << __E__;
1691 return NOT_FOUND_IN_DATABASE;
1694 username = dejumble(username, LoginSessionIdVector[i]);
1697 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
1699 __COUT__ <<
"Cookie code not found" << __E__;
1700 return NOT_FOUND_IN_DATABASE;
1704 if ((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
1706 __COUT__ <<
"User ID not found" << __E__;
1707 return NOT_FOUND_IN_DATABASE;
1711 if (UsersUsernameVector[j] != username)
1714 __COUT__ <<
"cookieCode: " << cookieCode <<
" was.." << __E__;
1715 __COUT__ <<
"username: " << username <<
" is not found" << __E__;
1716 return NOT_FOUND_IN_DATABASE;
1719 username = UsersDisplayNameVector[j];
1720 cookieCode = refreshCookieCode(i);
1721 return UsersUserIdVector[j];
1727 uint64_t WebUsers::getActiveSessionCountForUser(uint64_t uid)
1730 std::vector<uint64_t> uniqueAsi;
1733 for (i = 0; i < ActiveSessionUserIdVector.size(); ++i)
1734 if (ActiveSessionUserIdVector[i] == uid)
1739 for (j = 0; j < uniqueAsi.size(); ++j)
1740 if (uniqueAsi[j] == ActiveSessionIndex[i])
1742 unique =
false;
break;
1746 uniqueAsi.push_back(ActiveSessionIndex[i]);
1749 __COUT__ <<
"Found " << uniqueAsi.size() <<
" active sessions for uid " << uid << __E__;
1751 return uniqueAsi.size();
1760 bool WebUsers::checkIpAccess(
const std::string& ip)
1762 if(ip ==
"0")
return true;
1764 FILE *fp = fopen((IP_ACCEPT_FILE).c_str(),
"r");
1770 while(fgets(line,300,fp))
1774 if(len > 2 && line[len-1] ==
'\n')
1776 if(StringMacros::wildCardMatch(ip,line))
1783 fp = fopen((IP_REJECT_FILE).c_str(),
"r");
1786 while(fgets(line,300,fp))
1790 if(len > 2 && line[len-1] ==
'\n')
1792 if(StringMacros::wildCardMatch(ip,line))
1799 fp = fopen((IP_BLACKLIST_FILE).c_str(),
"r");
1802 while(fgets(line,300,fp))
1806 if(len > 2 && line[len-1] ==
'\n')
1808 if(StringMacros::wildCardMatch(ip,line))
1821 void WebUsers::incrementIpBlacklistCount(
const std::string& ip)
1824 auto it = ipBlacklistCounts_.find(ip);
1825 if(it == ipBlacklistCounts_.end())
1827 __COUT__ <<
"First error for ip '" << ip <<
"'" << __E__;
1828 ipBlacklistCounts_[ip] = 1;
1834 if(it->second >= IP_BLACKLIST_COUNT_THRESHOLD)
1836 __MCOUT__(
"Adding IP '" << ip <<
"' to blacklist!" << __E__);
1839 FILE *fp = fopen((IP_BLACKLIST_FILE).c_str(),
"a");
1842 __SS__ <<
"IP black list file '" << IP_BLACKLIST_FILE <<
"' could not be opened." << __E__;
1843 __MCOUT_ERR__(ss.str());
1846 fprintf(fp,
"%s\n",ip.c_str());
1854 std::string WebUsers::getUsersDisplayName(uint64_t uid)
1857 if ((i = searchUsersDatabaseForUserId(uid)) == NOT_FOUND_IN_DATABASE)
return "";
1858 return UsersDisplayNameVector[i];
1863 std::string WebUsers::getUsersUsername(uint64_t uid)
1866 if ((i = searchUsersDatabaseForUserId(uid)) == NOT_FOUND_IN_DATABASE)
return "";
1867 return UsersUsernameVector[i];
1880 uint64_t WebUsers::cookieCodeLogout(
const std::string& cookieCode,
bool logoutOtherUserSessions,
1881 uint64_t *userId,
const std::string& ip)
1886 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
1888 __COUT__ <<
"Cookie code not found" << __E__;
1890 incrementIpBlacklistCount(ip);
1892 return NOT_FOUND_IN_DATABASE;
1895 ipBlacklistCounts_[ip] = 0;
1899 if (ActiveSessionIpVector[i] != ip)
1901 __COUT__ <<
"IP does not match active session" << __E__;
1902 return NOT_FOUND_IN_DATABASE;
1911 uint64_t asi = ActiveSessionIndex[i];
1912 uint64_t uid = ActiveSessionUserIdVector[i];
1913 if (userId) *userId = uid;
1914 uint64_t logoutCount = 0;
1917 while (i < ActiveSessionIndex.size())
1919 if ((logoutOtherUserSessions && ActiveSessionUserIdVector[i] == uid &&
1920 ActiveSessionIndex[i] != asi) ||
1921 (!logoutOtherUserSessions && ActiveSessionUserIdVector[i] == uid &&
1922 ActiveSessionIndex[i] == asi))
1924 __COUT__ <<
"Logging out of active session " << ActiveSessionUserIdVector[i]
1925 <<
"-" << ActiveSessionIndex[i] << __E__;
1926 removeActiveSessionEntry(i);
1933 __COUT__ <<
"Found and removed active session count = " << logoutCount << __E__;
1940 bool WebUsers::getUserInfoForCookie(std::string& cookieCode,
1941 std::string *userName, std::string *displayName,
1942 uint64_t *activeSessionIndex)
1944 if (userName) *userName =
"";
1945 if (displayName) *displayName =
"";
1947 if (!CareAboutCookieCodes_)
1949 uint64_t uid = getAdminUserID();
1950 if (userName) *userName = getUsersUsername(uid);
1951 if (displayName) *displayName = getUsersDisplayName(uid);
1952 if (activeSessionIndex) *activeSessionIndex = -1;
1959 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
1961 __COUT__ <<
"cookieCode NOT_FOUND_IN_DATABASE" << __E__;
1966 if ((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
1968 __COUT__ <<
"ActiveSessionUserIdVector NOT_FOUND_IN_DATABASE" << __E__;
1972 if (userName) *userName = UsersUsernameVector[j];
1973 if (displayName) *displayName = UsersDisplayNameVector[j];
1974 if (activeSessionIndex) *activeSessionIndex = ActiveSessionIndex[i];
1989 bool WebUsers::cookieCodeIsActiveForRequest(std::string& cookieCode,
1990 std::map<std::string /*groupName*/,WebUsers::permissionLevel_t>* userPermissions,
1991 uint64_t *uid,
const std::string& ip,
1992 bool refresh, std::string *userWithLock,
1993 uint64_t* activeUserSessionIndex)
1998 if(!checkIpAccess(ip))
2000 __COUT_ERR__ <<
"User IP rejected." << __E__;
2001 cookieCode = REQ_NO_LOGIN_RESPONSE;
2005 cleanupExpiredEntries();
2012 if (!CareAboutCookieCodes_)
2014 if (userPermissions) *userPermissions =
2015 std::map<std::string ,WebUsers::permissionLevel_t>({{
2016 WebUsers::DEFAULT_USER_GROUP,
2017 WebUsers::PERMISSION_LEVEL_ADMIN
2019 if (uid) *uid = getAdminUserID();
2020 if (userWithLock) *userWithLock = usersUsernameWithLock_;
2021 if (activeUserSessionIndex) *activeUserSessionIndex = -1;
2023 if(cookieCode.size() != COOKIE_CODE_LENGTH)
2024 cookieCode = genCookieCode();
2031 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
2033 __COUT_ERR__ <<
"Cookie code not found" << __E__;
2034 cookieCode = REQ_NO_LOGIN_RESPONSE;
2036 incrementIpBlacklistCount(ip);
2041 ipBlacklistCounts_[ip] = 0;
2044 if (ip !=
"0" && ActiveSessionIpVector[i] != ip)
2046 __COUTV__(ActiveSessionIpVector[i]);
2048 __COUT_ERR__ <<
"IP does not match active session." << __E__;
2049 cookieCode = REQ_NO_LOGIN_RESPONSE;
2054 if ((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
2056 __COUT_ERR__ <<
"User ID not found" << __E__;
2057 cookieCode = REQ_NO_LOGIN_RESPONSE;
2061 std::map<std::string ,WebUsers::permissionLevel_t> tmpPerm =
2062 getPermissionsForUser(UsersUserIdVector[j]);
2064 if (isInactiveForGroup(tmpPerm))
2066 cookieCode = REQ_NO_PERMISSION_RESPONSE;
2071 if (userPermissions) *userPermissions = tmpPerm;
2072 if (uid) *uid = UsersUserIdVector[j];
2073 if (userWithLock) *userWithLock = usersUsernameWithLock_;
2074 if (activeUserSessionIndex) *activeUserSessionIndex = ActiveSessionIndex[i];
2076 cookieCode = refreshCookieCode(i, refresh);
2087 void WebUsers::cleanupExpiredEntries(std::vector<std::string> *loggedOutUsernames)
2092 if (loggedOutUsernames)
2094 for (i = 0; i < UsersLoggedOutUsernames_.size(); ++i)
2095 loggedOutUsernames->push_back(UsersLoggedOutUsernames_[i]);
2096 UsersLoggedOutUsernames_.clear();
2102 for (i = 0; i < LoginSessionStartTimeVector.size(); ++i)
2103 if (LoginSessionStartTimeVector[i] + LOGIN_SESSION_EXPIRATION_TIME < time(0) ||
2104 LoginSessionAttemptsVector[i] > LOGIN_SESSION_ATTEMPTS_MAX)
2109 removeLoginSessionEntry(i);
2122 for (i = 0; i < ActiveSessionStartTimeVector.size(); ++i)
2123 if (ActiveSessionStartTimeVector[i] + ACTIVE_SESSION_EXPIRATION_TIME <= time(0))
2130 tmpUid = ActiveSessionUserIdVector[i];
2131 removeActiveSessionEntry(i);
2135 if (!isUserIdActive(tmpUid))
2137 if (loggedOutUsernames)
2138 loggedOutUsernames->push_back(UsersUsernameVector[searchUsersDatabaseForUserId(tmpUid)]);
2140 UsersLoggedOutUsernames_.push_back(UsersUsernameVector[searchUsersDatabaseForUserId(tmpUid)]);
2157 if (CareAboutCookieCodes_ && !isUsernameActive(usersUsernameWithLock_))
2158 usersUsernameWithLock_ =
"";
2168 std::string WebUsers::createNewLoginSession(
const std::string& UUID,
const std::string& ip)
2174 for (; i < LoginSessionUUIDVector.size(); ++i)
2175 if (LoginSessionUUIDVector[i] == UUID)
break;
2177 if (i != LoginSessionUUIDVector.size())
2179 __COUT_ERR__ <<
"UUID: " << UUID <<
" is not unique" << __E__;
2184 LoginSessionUUIDVector.push_back(UUID);
2188 std::string sid =
"";
2189 for (i = 0; i < SESSION_ID_LENGTH / 2; ++i)
2191 intToHexStr(rand(), hexStr);
2194 LoginSessionIdVector.push_back(sid);
2195 LoginSessionIpVector.push_back(ip);
2196 LoginSessionStartTimeVector.push_back(time(0));
2197 LoginSessionAttemptsVector.push_back(0);
2209 std::string WebUsers::sha512(
const std::string& user,
const std::string& password, std::string& salt)
2211 SHA512_CTX sha512_context;
2216 SHA512_Init(&sha512_context);
2218 for (
unsigned int i = 0; i < 8; ++i)
2219 sha512_context.h[i] += rand();
2221 for (
unsigned int i = 0; i <
sizeof(SHA512_CTX); ++i)
2223 intToHexStr((uint8_t)(((uint8_t *)(&sha512_context))[i]), hexStr);
2225 salt.append(hexStr);
2234 for (
unsigned int i = 0; i <
sizeof(SHA512_CTX); ++i)
2235 ((uint8_t *)(&sha512_context))[i] = hexByteStrToInt(&(salt.c_str()[i * 2]));
2238 std::string strToHash = salt + user + password;
2241 unsigned char hash[SHA512_DIGEST_LENGTH];
2243 char retHash[SHA512_DIGEST_LENGTH * 2 + 1];
2248 SHA512_Update(&sha512_context, strToHash.c_str(), strToHash.length());
2250 SHA512_Final(hash, &sha512_context);
2254 for (i = 0; i < SHA512_DIGEST_LENGTH; i++)
2255 sprintf(retHash + (i * 2),
"%02x", hash[i]);
2258 retHash[SHA512_DIGEST_LENGTH * 2] =
'\0';
2272 std::string WebUsers::dejumble(
const std::string& u,
const std::string& s)
2275 if (s.length() != SESSION_ID_LENGTH)
return "";
2277 const int ss = s.length() / 2;
2278 int p = hexByteStrToInt(&(s.c_str()[0])) % ss;
2279 int n = hexByteStrToInt(&(s.c_str()[p * 2])) % ss;
2280 int len = (hexByteStrToInt(&(u.c_str()[p * 2])) - p - n + ss * 3) % ss;
2282 std::vector<bool> x(ss);
2283 for (
int i = 0; i < ss; ++i) x[i] = 0;
2286 int c = hexByteStrToInt(&(u.c_str()[p * 2]));
2288 std::string user =
"";
2290 for (
int l = 0; l < len; ++l)
2292 p = (p + hexByteStrToInt(&(s.c_str()[p * 2]))) % ss;
2293 while (x[p]) p = (p + 1) % ss;
2295 n = hexByteStrToInt(&(s.c_str()[p * 2]));
2296 user.append(1, (hexByteStrToInt(&(u.c_str()[p * 2])) - c - n + ss * 4) % ss);
2297 c = hexByteStrToInt(&(u.c_str()[p * 2]));
2306 std::map<std::string ,WebUsers::permissionLevel_t> WebUsers::getPermissionsForUser(
2310 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
2312 if (userIndex < UsersPermissionsVector.size())
2313 return UsersPermissionsVector[userIndex];
2316 std::map<std::string ,WebUsers::permissionLevel_t> retErrorMap;
2317 retErrorMap[WebUsers::DEFAULT_USER_GROUP] =
2318 WebUsers::PERMISSION_LEVEL_INACTIVE;
2323 WebUsers::permissionLevel_t WebUsers::getPermissionLevelForGroup(
2324 std::map<std::string /*groupName*/,WebUsers::permissionLevel_t>& permissionMap,
2325 const std::string& groupName)
2327 auto it = permissionMap.find(groupName);
2328 if(it == permissionMap.end())
2330 __COUT__ <<
"Group name '" << groupName <<
"' not found - assuming inactive user in this group." << __E__;
2331 return WebUsers::PERMISSION_LEVEL_INACTIVE;
2337 bool WebUsers::isInactiveForGroup(
2338 std::map<std::string /*groupName*/,WebUsers::permissionLevel_t>& permissionMap,
2339 const std::string& groupName)
2341 return getPermissionLevelForGroup(permissionMap,groupName) ==
2342 WebUsers::PERMISSION_LEVEL_INACTIVE;
2346 bool WebUsers::isAdminForGroup(
2347 std::map<std::string /*groupName*/,WebUsers::permissionLevel_t>& permissionMap,
2348 const std::string& groupName)
2350 return getPermissionLevelForGroup(permissionMap,groupName) ==
2351 WebUsers::PERMISSION_LEVEL_ADMIN;
2357 std::string WebUsers::getTooltipFilename(
2358 const std::string& username,
const std::string& srcFile,
2359 const std::string& srcFunc,
const std::string& srcId)
2361 std::string filename = (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH +
"/";
2365 mkdir(((std::string)WEB_LOGIN_DB_PATH).c_str(), 0755);
2366 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH).c_str(), 0755);
2367 mkdir(filename.c_str(), 0755);
2369 for (
const char& c : username)
2371 (c >=
'a' && c <=
'z') ||
2372 (c >=
'A' && c <=
'Z') ||
2373 (c >=
'0' && c <=
'9'))
2378 mkdir(filename.c_str(), 0755);
2380 for (
const char& c : srcFile)
2382 (c >=
'a' && c <=
'z') ||
2383 (c >=
'A' && c <=
'Z') ||
2384 (c >=
'0' && c <=
'9'))
2387 for (
const char& c : srcFunc)
2389 (c >=
'a' && c <=
'z') ||
2390 (c >=
'A' && c <=
'Z') ||
2391 (c >=
'0' && c <=
'9'))
2394 for (
const char& c : srcId)
2396 (c >=
'a' && c <=
'z') ||
2397 (c >=
'A' && c <=
'Z') ||
2398 (c >=
'0' && c <=
'9'))
2405 std::string ots::WebUsers::getUserEmailFromFingerprint(
const std::string& fingerprint)
2407 std::ifstream f(WEB_LOGIN_CERTDATA_PATH);
2414 certFingerprints_[email] = fp;
2416 remove(WEB_LOGIN_CERTDATA_PATH.c_str());
2419 for (
auto fp : certFingerprints_)
2421 if (fp.second == fingerprint)
return fp.first;
2429 void WebUsers::tooltipSetNeverShowForUsername(
const std::string& username,
2431 const std::string& srcFile,
const std::string& srcFunc,
2432 const std::string& srcId,
bool doNeverShow,
bool temporarySilence)
2435 __COUT__ <<
"Setting tooltip never show for user: " << username <<
2436 " to " << doNeverShow <<
" (temporarySilence=" <<
2437 temporarySilence <<
")" << __E__;
2440 std::string filename = getTooltipFilename(username, srcFile, srcFunc, srcId);
2441 FILE *fp = fopen(filename.c_str(),
"w");
2444 if (temporarySilence)
2445 fprintf(fp,
"%ld", time(0) + 60 * 60);
2447 fputc(doNeverShow ?
'1' :
'0', fp);
2451 __COUT_ERR__ <<
"Big problme with tooltips! File not accessible: " << filename << __E__;
2461 void WebUsers::tooltipCheckForUsername(
const std::string& username,
2463 const std::string& srcFile,
const std::string& srcFunc,
2464 const std::string& srcId)
2466 if (srcId ==
"ALWAYS")
2469 xmldoc->addTextElementToData(
"ShowTooltip",
"1");
2481 std::string filename = getTooltipFilename(username, srcFile, srcFunc, srcId);
2482 FILE *fp = fopen(filename.c_str(),
"r");
2487 fgets(line, 100, fp);
2489 sscanf(line,
"%ld", &val);
2490 __COUT__ <<
"tooltip value read = " << val << __E__;
2495 xmldoc->addTextElementToData(
"ShowTooltip", val == 1 ?
"0" :
2496 (time(0) > val ?
"1" :
"0"));
2499 xmldoc->addTextElementToData(
"ShowTooltip",
"1");
2504 void WebUsers::resetAllUserTooltips(
const std::string& userNeedle)
2506 std::system((
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH +
2507 "/" + userNeedle).c_str());
2508 __COUT__ <<
"Successfully reset Tooltips for user " << userNeedle << __E__;
2529 void WebUsers::insertSettingsForUser(uint64_t uid,
HttpXmlDocument *xmldoc,
bool includeAccounts)
2531 std::map<std::string ,WebUsers::permissionLevel_t> permissionMap =
2532 getPermissionsForUser(uid);
2533 __COUTV__(StringMacros::mapToString(permissionMap));
2534 if (isInactiveForGroup(permissionMap))
return;
2536 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
2537 __COUT__ <<
"Gettings settings for user: " << UsersUsernameVector[userIndex] << __E__;
2539 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH + UsersUsernameVector[userIndex] +
"." + (std::string)USERS_PREFERENCES_FILETYPE;
2543 __COUT__ <<
"Preferences file: " << fn << __E__;
2545 if (!prefXml.loadXmlDocument(fn))
2547 __COUT__ <<
"Preferences are defaults." << __E__;
2549 xmldoc->addTextElementToData(PREF_XML_BGCOLOR_FIELD, PREF_XML_BGCOLOR_DEFAULT);
2550 xmldoc->addTextElementToData(PREF_XML_DBCOLOR_FIELD, PREF_XML_DBCOLOR_DEFAULT);
2551 xmldoc->addTextElementToData(PREF_XML_WINCOLOR_FIELD, PREF_XML_WINCOLOR_DEFAULT);
2552 xmldoc->addTextElementToData(PREF_XML_LAYOUT_FIELD, PREF_XML_LAYOUT_DEFAULT);
2556 __COUT__ <<
"Saved Preferences found." << __E__;
2557 xmldoc->copyDataChildren(prefXml);
2563 if (includeAccounts &&
2564 isAdminForGroup(permissionMap))
2567 __COUT__ <<
"Admin on our hands" << __E__;
2569 xmldoc->addTextElementToData(PREF_XML_ACCOUNTS_FIELD,
"");
2573 for (uint64_t i = 0; i < UsersUsernameVector.size(); ++i)
2575 xmldoc->addTextElementToParent(
"username", UsersUsernameVector[i], PREF_XML_ACCOUNTS_FIELD);
2576 xmldoc->addTextElementToParent(
"display_name", UsersDisplayNameVector[i], PREF_XML_ACCOUNTS_FIELD);
2578 if (UsersUserEmailVector.size() > i)
2580 xmldoc->addTextElementToParent(
"useremail", UsersUserEmailVector[i], PREF_XML_ACCOUNTS_FIELD);
2584 xmldoc->addTextElementToParent(
"useremail",
"", PREF_XML_ACCOUNTS_FIELD);
2587 sprintf(permStr,
"%s", StringMacros::mapToString(
2588 UsersPermissionsVector[i]).c_str());
2589 xmldoc->addTextElementToParent(
"permissions", permStr, PREF_XML_ACCOUNTS_FIELD);
2590 if (UsersSaltVector[i] ==
"")
2591 sprintf(permStr,
"%d",
int(UsersAccountCreatedTimeVector[i] & 0xffff));
2594 xmldoc->addTextElementToParent(
"nac", permStr, PREF_XML_ACCOUNTS_FIELD);
2599 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
2600 (std::string)SYSTEM_PREFERENCES_PREFIX +
"." + (std::string)USERS_PREFERENCES_FILETYPE;
2601 if (!prefXml.loadXmlDocument(fn))
2603 __COUT__ <<
"System Preferences are defaults." << __E__;
2605 xmldoc->addTextElementToData(PREF_XML_SYSLAYOUT_FIELD, PREF_XML_SYSLAYOUT_DEFAULT);
2609 __COUT__ <<
"Saved System Preferences found." << __E__;
2610 xmldoc->copyDataChildren(prefXml);
2614 sprintf(permStr,
"%s", StringMacros::mapToString(permissionMap).c_str());
2615 xmldoc->addTextElementToData(PREF_XML_PERMISSIONS_FIELD, permStr);
2618 xmldoc->addTextElementToData(PREF_XML_USERLOCK_FIELD, usersUsernameWithLock_);
2620 xmldoc->addTextElementToData(PREF_XML_USERNAME_FIELD, getUsersUsername(uid));
2626 void WebUsers::setGenericPreference(uint64_t uid,
const std::string& preferenceName,
2627 const std::string& preferenceValue)
2629 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
2633 std::string safePreferenceName =
"";
2634 for (
const auto &c : preferenceName)
2635 if ((c >=
'a' && c <=
'z') ||
2636 (c >=
'A' && c <=
'Z') ||
2637 (c >=
'0' && c <=
'9') ||
2638 (c >=
'-' || c <=
'_'))
2639 safePreferenceName += c;
2641 std::string dir = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
2642 "generic_" + safePreferenceName +
"/";
2645 mkdir(dir.c_str(), 0755);
2647 std::string fn = UsersUsernameVector[userIndex] +
"_" + safePreferenceName +
2648 "." + (std::string)USERS_PREFERENCES_FILETYPE;
2650 __COUT__ <<
"Preferences file: " << (dir + fn) << __E__;
2652 FILE *fp = fopen((dir + fn).c_str(),
"w");
2655 fprintf(fp,
"%s", preferenceValue.c_str());
2659 __COUT_ERR__ <<
"Preferences file could not be opened for writing!" << __E__;
2666 std::string WebUsers::getGenericPreference(uint64_t uid,
const std::string& preferenceName,
2669 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
2673 std::string safePreferenceName =
"";
2674 for (
const auto &c : preferenceName)
2675 if ((c >=
'a' && c <=
'z') ||
2676 (c >=
'A' && c <=
'Z') ||
2677 (c >=
'0' && c <=
'9') ||
2678 (c >=
'-' || c <=
'_'))
2679 safePreferenceName += c;
2681 std::string dir = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
2682 "generic_" + safePreferenceName +
"/";
2684 std::string fn = UsersUsernameVector[userIndex] +
"_" + safePreferenceName +
2685 "." + (std::string)USERS_PREFERENCES_FILETYPE;
2687 __COUT__ <<
"Preferences file: " << (dir + fn) << __E__;
2690 FILE *fp = fopen((dir + fn).c_str(),
"rb");
2693 fseek(fp, 0, SEEK_END);
2694 long size = ftell(fp);
2696 line.reserve(size + 1);
2698 fgets(&line[0], size + 1, fp);
2701 __COUT__ <<
"Read value " << line << __E__;
2702 if (xmldoc) xmldoc->addTextElementToData(safePreferenceName, line);
2706 __COUT__ <<
"Using default value." << __E__;
2709 if (xmldoc) xmldoc->addTextElementToData(safePreferenceName,
"");
2715 void WebUsers::changeSettingsForUser(uint64_t uid,
const std::string& bgcolor,
const std::string& dbcolor,
2716 const std::string& wincolor,
const std::string& layout,
const std::string& syslayout)
2718 std::map<std::string ,WebUsers::permissionLevel_t> permissionMap =
2719 getPermissionsForUser(uid);
2720 if (isInactiveForGroup(permissionMap))
return;
2722 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
2723 __COUT__ <<
"Changing settings for user: " << UsersUsernameVector[userIndex] << __E__;
2725 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH + UsersUsernameVector[userIndex] +
"." + (std::string)USERS_PREFERENCES_FILETYPE;
2727 __COUT__ <<
"Preferences file: " << fn << __E__;
2730 prefXml.addTextElementToData(PREF_XML_BGCOLOR_FIELD, bgcolor);
2731 prefXml.addTextElementToData(PREF_XML_DBCOLOR_FIELD, dbcolor);
2732 prefXml.addTextElementToData(PREF_XML_WINCOLOR_FIELD, wincolor);
2733 prefXml.addTextElementToData(PREF_XML_LAYOUT_FIELD, layout);
2735 prefXml.saveXmlDocument(fn);
2738 if (!isAdminForGroup(permissionMap))
return;
2741 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
2742 (std::string)SYSTEM_PREFERENCES_PREFIX +
"." + (std::string)USERS_PREFERENCES_FILETYPE;
2745 sysPrefXml.addTextElementToData(PREF_XML_SYSLAYOUT_FIELD, syslayout);
2747 sysPrefXml.saveXmlDocument(fn);
2756 bool WebUsers::setUserWithLock(uint64_t actingUid,
bool lock,
2757 const std::
string& username)
2759 std::map<std::string ,WebUsers::permissionLevel_t> permissionMap =
2760 getPermissionsForUser(actingUid);
2762 std::string actingUser = getUsersUsername(actingUid);
2764 __COUTV__(actingUser);
2765 __COUT__ <<
"Permissions: " << StringMacros::mapToString(permissionMap) << __E__;
2766 __COUTV__(usersUsernameWithLock_);
2768 __COUTV__(username);
2769 __COUTV__(isUsernameActive(username));
2772 if (lock && (isUsernameActive(username) || !CareAboutCookieCodes_))
2774 if (!CareAboutCookieCodes_ && username != DEFAULT_ADMIN_USERNAME)
2776 __MCOUT_ERR__(
"User '" << actingUser <<
"' tried to lock for a user other than admin in wiz mode. Not allowed." << __E__);
2779 else if (!isAdminForGroup(permissionMap) && actingUser != username)
2781 __MCOUT_ERR__(
"A non-admin user '" << actingUser <<
2782 "' tried to lock for a user other than self. Not allowed." << __E__);
2785 usersUsernameWithLock_ = username;
2787 else if (!lock && usersUsernameWithLock_ == username)
2788 usersUsernameWithLock_ =
"";
2791 if (!isUsernameActive(username))
2792 __MCOUT_ERR__(
"User '" << username <<
"' is inactive." << __E__);
2793 __MCOUT_ERR__(
"Failed to lock for user '" << username <<
".'" << __E__);
2797 __MCOUT_INFO__(
"User '" << username <<
"' has locked out the system!" << __E__);
2801 std::string securityFileName = USER_WITH_LOCK_FILE;
2802 FILE *fp = fopen(securityFileName.c_str(),
"w");
2805 __COUT_INFO__ <<
"USER_WITH_LOCK_FILE " << USER_WITH_LOCK_FILE <<
2806 " not found. Ignoring." << __E__;
2810 fprintf(fp,
"%s", usersUsernameWithLock_.c_str());
2819 void WebUsers::modifyAccountSettings(uint64_t actingUid, uint8_t cmd_type,
2820 const std::string& username,
const std::string& displayname,
2821 const std::string& email,
const std::string& permissions)
2824 std::map<std::string ,WebUsers::permissionLevel_t> permissionMap =
2825 getPermissionsForUser(actingUid);
2826 if (!isAdminForGroup(permissionMap))
2828 __MCOUT_ERR__(
"Only admins can modify user settings." << __E__);
2832 uint64_t modi = searchUsersDatabaseForUsername(username);
2835 __MCOUT_ERR__(
"Cannot modify first user" << __E__);
2839 if (username.length() < USERNAME_LENGTH || displayname.length() < DISPLAY_NAME_LENGTH)
2841 __MCOUT_ERR__(
"Invalid Username or Display Name must be length " << USERNAME_LENGTH <<
2842 " or " << DISPLAY_NAME_LENGTH << __E__);
2846 __COUT__ <<
"Input Permissions: " << permissions << __E__;
2847 std::map<std::string ,WebUsers::permissionLevel_t> newPermissionsMap;
2851 case MOD_TYPE_UPDATE:
2853 __COUT__ <<
"MOD_TYPE_UPDATE " << username <<
" := " << permissions << __E__;
2855 if (modi == NOT_FOUND_IN_DATABASE)
2857 __COUT__ <<
"User not found!? Should not happen." << __E__;
2861 UsersDisplayNameVector[modi] = displayname;
2862 UsersUserEmailVector[modi] = email;
2864 StringMacros::getMapFromString(permissions,newPermissionsMap);
2868 if (isInactiveForGroup(UsersPermissionsVector[modi]) &&
2869 !isInactiveForGroup(newPermissionsMap))
2871 UsersLoginFailureCountVector[modi] = 0;
2872 UsersSaltVector[modi] =
"";
2874 UsersPermissionsVector[modi] = newPermissionsMap;
2878 uint64_t i = searchUsersDatabaseForUserId(actingUid);
2879 if (i == NOT_FOUND_IN_DATABASE)
2881 __COUT__ <<
"Master User not found!? Should not happen." << __E__;
2884 UsersLastModifierUsernameVector[modi] = UsersUsernameVector[i];
2885 UsersLastModifiedTimeVector[modi] = time(0);
2889 __COUT__ <<
"MOD_TYPE_ADD " << username <<
" - " << displayname << __E__;
2890 createNewAccount(username, displayname, email);
2892 case MOD_TYPE_DELETE:
2893 __COUT__ <<
"MOD_TYPE_DELETE " << username <<
" - " << displayname << __E__;
2894 deleteAccount(username, displayname);
2897 __COUT__ <<
"Undefined command - do nothing " << username << __E__;
2900 saveDatabaseToFile(DB_USERS);
2905 std::string WebUsers::getActiveUsersString()
2907 std::string ret =
"";
2910 for (uint64_t i = 0; i < ActiveSessionUserIdVector.size(); ++i)
2914 for (uint64_t j = 0; j < i; ++j)
2915 if (ActiveSessionUserIdVector[i] == ActiveSessionUserIdVector[j])
2917 repeat =
true;
break;
2920 if (!repeat && (u = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) !=
2921 NOT_FOUND_IN_DATABASE)
2922 ret += UsersDisplayNameVector[u] +
",";
2924 if (ret.length() > 1) ret.erase(ret.length() - 1);
2930 uint64_t WebUsers::getAdminUserID()
2932 uint64_t uid = searchUsersDatabaseForUsername(DEFAULT_ADMIN_USERNAME);
2940 void WebUsers::loadUserWithLock()
2942 char username[300] =
"";
2944 std::string securityFileName = USER_WITH_LOCK_FILE;
2945 FILE *fp = fopen(securityFileName.c_str(),
"r");
2948 __COUT_INFO__ <<
"USER_WITH_LOCK_FILE " << USER_WITH_LOCK_FILE <<
2949 " not found. Defaulting to admin lock." << __E__;
2952 sprintf(username,
"%s", DEFAULT_ADMIN_USERNAME.c_str());
2956 fgets(username, 300, fp);
2957 username[299] =
'\0';
2962 __COUT__ <<
"Attempting to load username with lock: " << username << __E__;
2964 if (strlen(username) == 0)
2966 __COUT_INFO__ <<
"Loaded state for user-with-lock is unlocked." << __E__;
2970 uint64_t i = searchUsersDatabaseForUsername(username);
2971 if (i == NOT_FOUND_IN_DATABASE)
2973 __COUT_INFO__ <<
"username " << username <<
2974 " not found in database. Ignoring." << __E__;
2977 __COUT__ <<
"Setting lock" << __E__;
2978 setUserWithLock(UsersUserIdVector[i],
true, username);
2984 std::string WebUsers::getSecurity()
2986 return securityType_;
2991 void WebUsers::loadSecuritySelection()
2993 std::string securityFileName = SECURITY_FILE_NAME;
2994 FILE *fp = fopen(securityFileName.c_str(),
"r");
2995 char line[100] =
"";
2996 if (fp) fgets(line, 100, fp);
3000 while (i < strlen(line) && line[i] >=
'A' && line[i] <=
'z') ++i;
3004 if (strcmp(line, SECURITY_TYPE_NONE.c_str()) == 0 ||
3005 strcmp(line, SECURITY_TYPE_DIGEST_ACCESS.c_str()) == 0)
3006 securityType_ = line;
3008 securityType_ = SECURITY_TYPE_NONE;
3010 __COUT__ <<
"The current security type is " << securityType_ << __E__;
3015 if (securityType_ == SECURITY_TYPE_NONE)
3016 CareAboutCookieCodes_ =
false;
3018 CareAboutCookieCodes_ =
true;
3020 __COUT__ <<
"CareAboutCookieCodes_: " <<
3021 CareAboutCookieCodes_ << __E__;
3028 void WebUsers::NACDisplayThread(
const std::string& nac,
const std::string& user)
3030 INIT_MF(
"WebUsers_NAC");
3039 std::this_thread::sleep_for(std::chrono::seconds(2));
3040 __COUT__ <<
"\n******************************************************************** " << __E__;
3041 __COUT__ <<
"\n******************************************************************** " << __E__;
3042 __COUT__ <<
"\n\nNew account code = " << nac <<
" for user: " << user <<
"\n" << __E__;
3043 __COUT__ <<
"\n******************************************************************** " << __E__;
3044 __COUT__ <<
"\n******************************************************************** " << __E__;
3049 void WebUsers::deleteUserData()
3052 std::system((
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + HASHES_DB_PATH +
"/*").c_str());
3053 std::system((
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH +
"/*").c_str());
3054 std::system((
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_LOGIN_HISTORY_PATH +
"/*").c_str());
3055 std::system((
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_PREFERENCES_PATH +
"/*").c_str());
3056 std::system((
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH).c_str());
3058 std::string serviceDataPath = getenv(
"SERVICE_DATA_PATH");
3060 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/MacroData/").c_str());
3061 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/MacroHistory/").c_str());
3062 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/MacroExport/").c_str());
3065 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/ConsolePreferences/").c_str());
3068 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/OtsWizardData/").c_str());
3071 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/ProgressBarData/").c_str());
3074 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/RunNumber/").c_str());
3075 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/RunControlData/").c_str());
3078 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/VisualizerData/").c_str());
3084 std::system((
"rm -rf " + std::string(getenv(
"LOGBOOK_DATA_PATH")) +
"/").c_str());
3086 std::cout << __COUT_HDR_FL__ <<
"$$$$$$$$$$$$$$ Successfully deleted ALL service user data $$$$$$$$$$$$" << __E__;