1 #include "otsdaq/WebUsersUtilities/WebUsers.h"
2 #include "otsdaq/XmlUtilities/HttpXmlDocument.h"
4 #include <openssl/sha.h>
18 #define WEB_LOGIN_BKUP_DB_PATH "bkup/"
20 #define SECURITY_FILE_NAME std::string(__ENV__("SERVICE_DATA_PATH")) + "/OtsWizardData/security.dat"
22 #define USERS_ACTIVE_SESSIONS_FILE USERS_DB_PATH + "/activeSessions.sv"
24 #define HASHES_DB_FILE HASHES_DB_PATH + "/hashes.xml"
25 #define USERS_DB_FILE USERS_DB_PATH + "/users.xml"
26 #define USERS_GLOBAL_HISTORY_FILE "__global"
27 #define USERS_LOGIN_HISTORY_FILETYPE "hist"
28 #define USERS_PREFERENCES_FILETYPE "pref"
29 #define SYSTEM_PREFERENCES_PREFIX "system.preset"
30 #define USER_WITH_LOCK_FILE WEB_LOGIN_DB_PATH + "/user_with_lock.dat"
31 #define IP_BLACKLIST_FILE WEB_LOGIN_DB_PATH + "/ip_generated_blacklist.dat"
32 #define IP_REJECT_FILE WEB_LOGIN_DB_PATH + "/ip_reject.dat"
33 #define IP_ACCEPT_FILE WEB_LOGIN_DB_PATH + "/ip_accept.dat"
35 #define SILENCE_ALL_TOOLTIPS_FILENAME "silenceTooltips"
37 #define HASHES_DB_GLOBAL_STRING "hashData"
38 #define HASHES_DB_ENTRY_STRING "hashEntry"
39 #define USERS_DB_GLOBAL_STRING "userData"
40 #define USERS_DB_ENTRY_STRING "userEntry"
41 #define USERS_DB_NEXT_UID_STRING "nextUserId"
44 #define PREF_XML_BGCOLOR_FIELD "pref_bgcolor"
45 #define PREF_XML_DBCOLOR_FIELD "pref_dbcolor"
46 #define PREF_XML_WINCOLOR_FIELD "pref_wincolor"
47 #define PREF_XML_LAYOUT_FIELD "pref_layout"
48 #define PREF_XML_SYSLAYOUT_FIELD "pref_syslayout"
49 #define PREF_XML_PERMISSIONS_FIELD "desktop_user_permissions"
50 #define PREF_XML_USERLOCK_FIELD "username_with_lock"
51 #define PREF_XML_USERNAME_FIELD "pref_username"
52 #define PREF_XML_OTS_OWNER_FIELD "ots_owner"
54 #define PREF_XML_BGCOLOR_DEFAULT "rgb(0,76,151)"
55 #define PREF_XML_DBCOLOR_DEFAULT "rgb(0,40,85)"
56 #define PREF_XML_WINCOLOR_DEFAULT "rgba(196,229,255,0.9)"
57 #define PREF_XML_LAYOUT_DEFAULT "0;0;0;0"
58 #define PREF_XML_SYSLAYOUT_DEFAULT "0;0"
60 #define PREF_XML_ACCOUNTS_FIELD "users_accounts"
61 #define PREF_XML_LOGIN_HISTORY_FIELD "login_entry"
64 const std::string WebUsers::DEFAULT_ADMIN_USERNAME =
"admin";
65 const std::string WebUsers::DEFAULT_ADMIN_DISPLAY_NAME =
"Administrator";
66 const std::string WebUsers::DEFAULT_ADMIN_EMAIL =
"root@otsdaq.fnal.gov";
67 const std::string WebUsers::DEFAULT_ITERATOR_USERNAME =
"iterator";
68 const std::string WebUsers::DEFAULT_STATECHANGER_USERNAME =
"statechanger";
69 const std::string WebUsers::DEFAULT_USER_GROUP =
"allUsers";
71 const std::string WebUsers::REQ_NO_LOGIN_RESPONSE =
"NoLogin";
72 const std::string WebUsers::REQ_NO_PERMISSION_RESPONSE =
"NoPermission";
73 const std::string WebUsers::REQ_USER_LOCKOUT_RESPONSE =
"UserLockout";
74 const std::string WebUsers::REQ_LOCK_REQUIRED_RESPONSE =
"LockRequired";
75 const std::string WebUsers::REQ_ALLOW_NO_USER =
"AllowNoUser";
77 const std::string WebUsers::SECURITY_TYPE_NONE =
"NoSecurity";
78 const std::string WebUsers::SECURITY_TYPE_DIGEST_ACCESS =
"DigestAccessAuthentication";
79 const std::string WebUsers::SECURITY_TYPE_DEFAULT = WebUsers::SECURITY_TYPE_NONE;
81 const std::vector<std::string> WebUsers::HashesDatabaseEntryFields_ = {
"hash",
"lastAccessTime"};
82 const std::vector<std::string> WebUsers::UsersDatabaseEntryFields_ = {
"username",
"displayName",
"salt",
83 "uid",
"permissions",
"lastLoginAttemptTime",
"accountCreatedTime",
84 "loginFailureCount",
"lastModifiedTime",
"lastModifierUsername",
"useremail"};
87 #define __MF_SUBJECT__ "WebUsers"
90 volatile bool WebUsers::CareAboutCookieCodes_ =
true;
100 usersNextUserId_ = 0;
101 usersUsernameWithLock_ =
"";
120 mkdir(((std::string)WEB_LOGIN_DB_PATH).c_str(), 0755);
121 mkdir(((std::string)WEB_LOGIN_DB_PATH +
"bkup/" + USERS_DB_PATH).c_str(), 0755);
122 mkdir(((std::string)WEB_LOGIN_DB_PATH + HASHES_DB_PATH).c_str(), 0755);
123 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH).c_str(), 0755);
124 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_LOGIN_HISTORY_PATH).c_str(), 0755);
125 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_PREFERENCES_PATH).c_str(), 0755);
128 __COUT__ <<
"FATAL USER DATABASE ERROR - failed to load!!!" << __E__;
130 loadSecuritySelection();
134 std::string user = DEFAULT_ADMIN_USERNAME;
135 if((i = searchUsersDatabaseForUsername(user)) == NOT_FOUND_IN_DATABASE)
137 __SS__ <<
"user: " << user <<
" is not found. This should be impossible!"
139 __COUT_ERR__ << ss.str();
142 else if(Users_[i].salt_ ==
144 securityType_ == SECURITY_TYPE_DIGEST_ACCESS)
150 [](
const std::string& nac,
const std::string& user) {
151 WebUsers::NACDisplayThread(nac, user);
153 Users_[i].getNewAccountCode(),
167 __COUT__ <<
"Done with Web Users initialization!" << __E__;
176 std::ostringstream* out,
180 std::lock_guard<std::mutex> lock(webUserMutex_);
188 userInfo.cookieCode_,
189 &userInfo.groupPermissionLevelMap_,
192 !userInfo.automatedCommand_ ,
196 &userInfo.usernameWithLock_,
199 *out << userInfo.cookieCode_;
200 goto HANDLE_ACCESS_FAILURE;
206 i = searchUsersDatabaseForUserId(userInfo.uid_);
207 if(i >= Users_.size())
209 __SS__ <<
"Illegal uid encountered in cookie codes!? " << i << __E__;
210 ss <<
"User size = " << Users_.size() << __E__;
214 userInfo.username_ = Users_[i].username_;
215 userInfo.displayName_ = Users_[i].displayName_;
218 goto HANDLE_ACCESS_FAILURE;
222 HANDLE_ACCESS_FAILURE:
224 if(!userInfo.automatedCommand_)
225 __COUT_ERR__ <<
"Failed request (requestType = " << userInfo.requestType_
226 <<
"): " << out->str() << __E__;
237 userInfo.ip_ = cgi.getEnvironment().getRemoteAddr();
240 userInfo.username_ =
"";
241 userInfo.displayName_ =
"";
242 userInfo.usernameWithLock_ =
"";
256 std::ostringstream* out,
260 const std::string& wizardModeSequence )
266 if(userInfo.requireSecurity_ && userInfo.permissionsThreshold_ > 1)
272 if(isWizardMode && wizardModeSequence.size() < 8)
275 *out << WebUsers::REQ_NO_PERMISSION_RESPONSE;
276 __COUT__ <<
"User (@" << userInfo.ip_ <<
") has attempted requestType '"
277 << userInfo.requestType_
278 <<
"' which requires sufficient security enabled. Please enable the "
280 " sequence of at least 8 characters."
285 else if(!isWizardMode &&
286 (userInfo.username_ == WebUsers::DEFAULT_ADMIN_USERNAME ||
287 userInfo.username_ == WebUsers::DEFAULT_ITERATOR_USERNAME ||
288 userInfo.username_ == WebUsers::DEFAULT_STATECHANGER_USERNAME))
291 *out << WebUsers::REQ_NO_PERMISSION_RESPONSE;
292 __COUT__ <<
"User (@" << userInfo.ip_ <<
") has attempted requestType '"
293 << userInfo.requestType_
294 <<
"' which requires sufficient security enabled. Please enable "
296 " logins (Note: the user admin is disallowed in an attempt to "
297 "force personal accountability for edits)."
305 if(!userInfo.automatedCommand_)
307 __COUTT__ <<
"requestType ==========>>> " << userInfo.requestType_ << __E__;
308 __COUTTV__((
unsigned int)userInfo.permissionLevel_);
309 __COUTTV__((
unsigned int)userInfo.permissionsThreshold_);
313 if(!isWizardMode && !userInfo.allowNoUser_ &&
314 userInfo.cookieCode_.length() != WebUsers::COOKIE_CODE_LENGTH &&
316 userInfo.cookieCode_ ==
320 __COUT__ <<
"User (@" << userInfo.ip_
321 <<
") has invalid cookie code: " << userInfo.cookieCode_ << std::endl;
322 *out << WebUsers::REQ_NO_LOGIN_RESPONSE;
326 if(!userInfo.allowNoUser_ &&
327 (userInfo.permissionLevel_ == 0 ||
328 userInfo.permissionsThreshold_ == 0 ||
329 userInfo.permissionLevel_ < userInfo.permissionsThreshold_))
332 *out << WebUsers::REQ_NO_PERMISSION_RESPONSE;
333 __COUT_INFO__ <<
"User (@" << userInfo.ip_
334 <<
") has insufficient permissions for requestType '"
335 << userInfo.requestType_ <<
"' : user level is "
336 << (
unsigned int)userInfo.permissionLevel_ <<
", "
337 << (
unsigned int)userInfo.permissionsThreshold_ <<
" required."
345 userInfo.username_ = WebUsers::DEFAULT_ADMIN_USERNAME;
346 userInfo.displayName_ =
"Admin";
347 userInfo.usernameWithLock_ = userInfo.username_;
355 if(userInfo.allowNoUser_)
356 xmldoc->setHeader(WebUsers::REQ_ALLOW_NO_USER);
358 xmldoc->setHeader(userInfo.cookieCode_);
361 if(userInfo.allowNoUser_)
363 if(userInfo.automatedCommand_)
364 __COUTT__ <<
"Allowing anonymous access." << __E__;
375 if((userInfo.checkLock_ || userInfo.requireLock_) &&
376 userInfo.usernameWithLock_ !=
"" &&
377 userInfo.usernameWithLock_ != userInfo.username_)
379 *out << WebUsers::REQ_USER_LOCKOUT_RESPONSE;
380 __COUT_INFO__ <<
"User '" << userInfo.username_ <<
"' is locked out. '"
381 << userInfo.usernameWithLock_ <<
"' has lock." << std::endl;
385 if(userInfo.requireLock_ && userInfo.usernameWithLock_ != userInfo.username_)
387 *out << WebUsers::REQ_LOCK_REQUIRED_RESPONSE;
388 __COUT_INFO__ <<
"User '" << userInfo.username_
389 <<
"' must have lock to proceed. ('" << userInfo.usernameWithLock_
390 <<
"' has lock.)" << std::endl;
406 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_ACTIVE_SESSIONS_FILE;
407 __COUT__ << fn << __E__;
409 FILE* fp = fopen(fn.c_str(),
"w");
412 __COUT_ERR__ <<
"Error! Persistent active sessions could not be saved to file: "
418 fprintf(fp,
"%d\n", version);
419 for(
unsigned int i = 0; i < ActiveSessions_.size(); ++i)
427 fprintf(fp,
"%s\n", ActiveSessions_[i].cookieCode_.c_str());
428 fprintf(fp,
"%s\n", ActiveSessions_[i].ip_.c_str());
429 fprintf(fp,
"%lu\n", ActiveSessions_[i].userId_);
430 fprintf(fp,
"%lu\n", ActiveSessions_[i].sessionIndex_);
431 fprintf(fp,
"%ld\n", ActiveSessions_[i].startTime_);
434 __COUT__ <<
"Active Sessions saved with size " << ActiveSessions_.size() << __E__;
446 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_ACTIVE_SESSIONS_FILE;
447 __COUT__ << fn << __E__;
448 FILE* fp = fopen(fn.c_str(),
"r");
452 <<
"Persistent active sessions were not found to be loaded at file: " << fn
459 const int LINELEN = 1000;
461 fgets(line, LINELEN, fp);
462 sscanf(line,
"%d", &version);
465 __COUT__ <<
"Extracting active sessions..." << __E__;
467 while(fgets(line, LINELEN, fp))
470 line[strlen(line) - 1] =
'\0';
471 if(strlen(line) != COOKIE_CODE_LENGTH)
473 __COUT__ <<
"Illegal cookie code found: " << line << __E__;
479 ActiveSessions_.back().cookieCode_ = line;
481 fgets(line, LINELEN, fp);
483 line[strlen(line) - 1] =
'\0';
484 ActiveSessions_.back().ip_ = line;
486 fgets(line, LINELEN, fp);
487 sscanf(line,
"%lu", &(ActiveSessions_.back().userId_));
489 fgets(line, LINELEN, fp);
490 sscanf(line,
"%lu", &(ActiveSessions_.back().sessionIndex_));
492 fgets(line, LINELEN, fp);
493 sscanf(line,
"%ld", &(ActiveSessions_.back().startTime_));
496 __COUT__ <<
"Active Sessions loaded with size " << ActiveSessions_.size() << __E__;
500 fp = fopen(fn.c_str(),
"w");
509 bool WebUsers::loadDatabases()
514 const unsigned int LINE_LEN = 1000;
516 unsigned int i, si, c, len, f;
527 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_FILE;
528 __COUT__ << fn << __E__;
529 fp = fopen(fn.c_str(),
"r");
532 mkdir(((std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_PATH).c_str(),
534 __COUT__ << ((std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_PATH).c_str()
536 fp = fopen(fn.c_str(),
"w");
539 __COUT__ <<
"Hashes database created: " << fn << __E__;
541 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING,
"", DB_SAVE_OPEN);
542 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING,
"", DB_SAVE_CLOSE);
549 while(fgets(line, LINE_LEN, fp))
551 if(strlen(line) < SHA512_DIGEST_LENGTH)
557 for(i = 0; i < len; ++i)
565 while(i < len && line[i] !=
'<')
577 Hashes_.push_back(Hash());
578 Hashes_.back().hash_ = &line[si];
581 sscanf(&line[si],
"%ld", &Hashes_.back().accessTime_);
584 __COUT__ << Hashes_.size() <<
" Hashes found." << __E__;
598 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_FILE;
599 fp = fopen(fn.c_str(),
"r");
602 mkdir(((std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_PATH).c_str(),
604 __COUT__ << ((std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_PATH).c_str()
606 fp = fopen(fn.c_str(),
"w");
609 __COUT__ <<
"Users database created: " << fn << __E__;
611 saveToDatabase(fp, USERS_DB_GLOBAL_STRING,
"", DB_SAVE_OPEN);
613 sprintf(nidStr,
"%lu", usersNextUserId_);
614 saveToDatabase(fp, USERS_DB_NEXT_UID_STRING, nidStr, DB_SAVE_OPEN_AND_CLOSE);
615 saveToDatabase(fp, USERS_DB_GLOBAL_STRING,
"", DB_SAVE_CLOSE);
619 DEFAULT_ADMIN_DISPLAY_NAME,
620 DEFAULT_ADMIN_EMAIL);
624 __COUT__ <<
"Users database: " << fn << __E__;
628 char salt[] =
"nextUserId";
629 while(fgets(line, LINE_LEN, fp))
631 if(strlen(line) < strlen(salt) * 2)
634 for(i = 0; i < strlen(salt); ++i)
635 if(line[i + 1] != salt[i])
638 if(i == strlen(salt))
643 while(i < LINE_LEN && line[i] !=
'\0' && line[i] !=
'<')
646 sscanf(&line[si],
"%lu", &usersNextUserId_);
651 __COUT__ <<
"Found Users database next user Id: " << usersNextUserId_ << __E__;
655 while(fgets(line, LINE_LEN, fp))
657 if(strlen(line) < 30)
665 __COUT__ <<
"Line buffer too small: " << len << __E__;
671 for(i = 0; i < len; ++i)
675 if(c == 0 || c % 2 == 1)
679 while(i < len && line[i] !=
'<')
691 Users_.push_back(User());
692 Users_.back().username_ = &line[si];
695 Users_.back().displayName_ = &line[si];
697 Users_.back().salt_ = &line[si];
699 sscanf(&line[si],
"%lu", &Users_.back().userId_);
702 std::map<std::string, permissionLevel_t>& lastPermissionsMap =
703 Users_.back().permissions_;
704 StringMacros::getMapFromString<permissionLevel_t>(
705 &line[si], lastPermissionsMap);
713 if(lastPermissionsMap.find(WebUsers::DEFAULT_USER_GROUP) ==
714 lastPermissionsMap.end())
717 <<
"User '" << Users_.back().username_
718 <<
"' is not a member of the default user group '"
719 << WebUsers::DEFAULT_USER_GROUP
720 <<
".' Assuming user account is inactive (permission "
722 << WebUsers::PERMISSION_LEVEL_INACTIVE <<
")." << __E__;
723 lastPermissionsMap[WebUsers::DEFAULT_USER_GROUP] =
724 WebUsers::PERMISSION_LEVEL_INACTIVE;
727 if(Users_.back().username_ == DEFAULT_ADMIN_USERNAME)
731 std::map<std::string ,
732 WebUsers::permissionLevel_t>
733 initPermissions = {{WebUsers::DEFAULT_USER_GROUP,
736 Users_.back().permissions_ = initPermissions;
740 sscanf(&line[si],
"%ld", &Users_.back().lastLoginAttempt_);
742 sscanf(&line[si],
"%ld", &Users_.back().accountCreationTime_);
744 sscanf(&line[si],
"%hhu", &Users_.back().loginFailureCount_);
746 sscanf(&line[si],
"%ld", &Users_.back().accessModifierTime());
748 Users_.back().loadModifierUsername(&line[si]);
750 Users_.back().email_ = &line[si];
757 __COUT__ << Users_.size() <<
" Users found." << __E__;
758 for(
size_t ii = 0; ii < Users_.size(); ++ii)
761 "User [" << Users_[ii].userId_ <<
"] \tName: " << std::left
762 << std::setfill(
' ') << std::setw(20) << Users_[ii].username_
763 <<
"\tDisplay Name: " << std::left << std::setfill(
' ') << std::setw(30)
764 << Users_[ii].displayName_ <<
"\tEmail: " << std::left
765 << std::setfill(
' ') << std::setw(30) << Users_[ii].email_
766 <<
"\tNAC: " << std::left << std::setfill(
' ') << std::setw(5)
767 << Users_[ii].getNewAccountCode()
768 <<
"\tFailedCount: " << (int)Users_[ii].loginFailureCount_
787 void WebUsers::saveToDatabase(FILE* fp,
788 const std::string& field,
789 const std::string& value,
796 std::string newLine = addNewLine ?
"\n" :
"";
798 if(type == DB_SAVE_OPEN_AND_CLOSE)
805 else if(type == DB_SAVE_OPEN)
806 fprintf(fp,
"<%s>%s%s", field.c_str(), value.c_str(), newLine.c_str());
807 else if(type == DB_SAVE_CLOSE)
808 fprintf(fp,
"</%s>%s", field.c_str(), newLine.c_str());
817 bool WebUsers::saveDatabaseToFile(uint8_t db)
822 (std::string)WEB_LOGIN_DB_PATH +
823 ((db == DB_USERS) ? (std::string)USERS_DB_FILE : (std::string)HASHES_DB_FILE);
825 __COUT__ <<
"Save Database Filename: " << fn << __E__;
831 sprintf(dayAppend,
".%lu.bkup", time(0) / (3600 * 24));
832 std::string bkup_fn = (std::string)WEB_LOGIN_DB_PATH +
833 (std::string)WEB_LOGIN_BKUP_DB_PATH +
834 ((db == DB_USERS) ? (std::string)USERS_DB_FILE
835 : (std::string)HASHES_DB_FILE) +
836 (std::string)dayAppend;
838 __COUT__ <<
"Backup file: " << bkup_fn << __E__;
840 std::string shell_command =
"mv " + fn +
" " + bkup_fn;
841 system(shell_command.c_str());
844 FILE* fp = fopen(fn.c_str(),
"wb");
852 saveToDatabase(fp, USERS_DB_GLOBAL_STRING,
"", DB_SAVE_OPEN);
854 sprintf(fldStr,
"%lu", usersNextUserId_);
855 saveToDatabase(fp, USERS_DB_NEXT_UID_STRING, fldStr, DB_SAVE_OPEN_AND_CLOSE);
857 __COUT__ <<
"Saving " << Users_.size() <<
" Users." << __E__;
859 for(uint64_t i = 0; i < Users_.size(); ++i)
863 saveToDatabase(fp, USERS_DB_ENTRY_STRING,
"", DB_SAVE_OPEN,
false);
865 for(
unsigned int f = 0; f < WebUsers::UsersDatabaseEntryFields_.size(); ++f)
870 WebUsers::UsersDatabaseEntryFields_[f],
872 DB_SAVE_OPEN_AND_CLOSE,
876 WebUsers::UsersDatabaseEntryFields_[f],
877 Users_[i].displayName_,
878 DB_SAVE_OPEN_AND_CLOSE,
882 WebUsers::UsersDatabaseEntryFields_[f],
884 DB_SAVE_OPEN_AND_CLOSE,
888 sprintf(fldStr,
"%lu", Users_[i].userId_);
890 WebUsers::UsersDatabaseEntryFields_[f],
892 DB_SAVE_OPEN_AND_CLOSE,
897 WebUsers::UsersDatabaseEntryFields_[f],
901 DB_SAVE_OPEN_AND_CLOSE,
905 sprintf(fldStr,
"%lu", Users_[i].lastLoginAttempt_);
907 WebUsers::UsersDatabaseEntryFields_[f],
909 DB_SAVE_OPEN_AND_CLOSE,
914 sprintf(fldStr,
"%lu", Users_[i].accountCreationTime_);
916 WebUsers::UsersDatabaseEntryFields_[f],
918 DB_SAVE_OPEN_AND_CLOSE,
923 sprintf(fldStr,
"%hhu", Users_[i].loginFailureCount_);
925 WebUsers::UsersDatabaseEntryFields_[f],
927 DB_SAVE_OPEN_AND_CLOSE,
932 sprintf(fldStr,
"%lu", Users_[i].getModifierTime());
934 WebUsers::UsersDatabaseEntryFields_[f],
936 DB_SAVE_OPEN_AND_CLOSE,
941 WebUsers::UsersDatabaseEntryFields_[f],
942 Users_[i].getModifierUsername(),
943 DB_SAVE_OPEN_AND_CLOSE,
947 WebUsers::UsersDatabaseEntryFields_[f],
949 DB_SAVE_OPEN_AND_CLOSE,
953 saveToDatabase(fp, USERS_DB_ENTRY_STRING,
"", DB_SAVE_CLOSE);
956 saveToDatabase(fp, USERS_DB_GLOBAL_STRING,
"", DB_SAVE_CLOSE);
960 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING,
"", DB_SAVE_OPEN);
962 __COUT__ <<
"Saving " << Hashes_.size() <<
" Hashes." << __E__;
963 for(uint64_t i = 0; i < Hashes_.size(); ++i)
965 __COUT__ <<
"Saving " << Hashes_[i].hash_ <<
" Hash." << __E__;
966 saveToDatabase(fp, HASHES_DB_ENTRY_STRING,
"", DB_SAVE_OPEN,
false);
967 for(
unsigned int f = 0; f < WebUsers::HashesDatabaseEntryFields_.size(); ++f)
971 WebUsers::HashesDatabaseEntryFields_[f],
973 DB_SAVE_OPEN_AND_CLOSE,
977 sprintf(fldStr,
"%lu", Hashes_[i].accessTime_);
979 WebUsers::HashesDatabaseEntryFields_[f],
981 DB_SAVE_OPEN_AND_CLOSE,
985 saveToDatabase(fp, HASHES_DB_ENTRY_STRING,
"", DB_SAVE_CLOSE);
988 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING,
"", DB_SAVE_CLOSE);
1004 const std::string& displayName,
1005 const std::string& email)
1007 __COUT__ <<
"Creating account: " << username << __E__;
1010 if((i = searchUsersDatabaseForUsername(username)) != NOT_FOUND_IN_DATABASE ||
1011 username == WebUsers::DEFAULT_ITERATOR_USERNAME ||
1012 username == WebUsers::DEFAULT_STATECHANGER_USERNAME)
1015 __SS__ <<
"Username '" << username
1016 <<
"' already exists! Please choose a unique username." << __E__;
1021 if((i = searchUsersDatabaseForDisplayName(displayName)) != NOT_FOUND_IN_DATABASE)
1024 __SS__ <<
"Display Name '" << displayName
1025 <<
"' already exists! Please choose a unique display name." << __E__;
1030 Users_.push_back(
User());
1032 Users_.back().username_ = username;
1033 Users_.back().displayName_ = displayName;
1034 Users_.back().email_ = email;
1037 std::map<std::string , WebUsers::permissionLevel_t> initPermissions = {
1038 {WebUsers::DEFAULT_USER_GROUP,
1039 (Users_.size() ? WebUsers::PERMISSION_LEVEL_NOVICE
1042 Users_.back().permissions_ = initPermissions;
1043 Users_.back().userId_ = usersNextUserId_++;
1044 if(usersNextUserId_ >= ACCOUNT_ERROR_THRESHOLD)
1046 __SS__ <<
"usersNextUserId_ wrap around!! Too many users??? Notify Admins."
1049 usersNextUserId_ = 1;
1053 Users_.back().accountCreationTime_ = time(0);
1055 if(!saveDatabaseToFile(DB_USERS))
1057 __SS__ <<
"Failed to save User DB!" << __E__;
1068 bool WebUsers::deleteAccount(
const std::string& username,
const std::string& displayName)
1070 uint64_t i = searchUsersDatabaseForUsername(username);
1071 if(i == NOT_FOUND_IN_DATABASE)
1073 if(Users_[i].displayName_ != displayName)
1078 Users_.erase(Users_.begin() + i);
1081 return saveDatabaseToFile(DB_USERS);
1085 unsigned int WebUsers::hexByteStrToInt(
const char* h)
1088 char hs[3] = {h[0], h[1],
'\0'};
1089 sscanf(hs,
"%X", &rv);
1094 void WebUsers::intToHexStr(
unsigned char i,
char* h) { sprintf(h,
"%2.2X", i); }
1107 std::string& jumbledUser,
1108 const std::string& jumbledPw,
1109 std::string& newAccountCode,
1110 const std::string& ip)
1115 __COUT_ERR__ <<
"rejected ip: " << ip << __E__;
1116 return ACCOUNT_BLACKLISTED;
1121 if(!CareAboutCookieCodes_)
1125 newAccountCode = genCookieCode();
1132 if((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
1134 __COUT_ERR__ <<
"uuid: " << uuid <<
" is not found" << __E__;
1135 newAccountCode =
"1";
1137 incrementIpBlacklistCount(ip);
1139 return NOT_FOUND_IN_DATABASE;
1141 ++LoginSessions_[i].loginAttempts_;
1143 std::string user = dejumble(jumbledUser, LoginSessions_[i].id_);
1145 std::string pw = dejumble(jumbledPw, LoginSessions_[i].id_);
1148 if((i = searchUsersDatabaseForUsername(user)) == NOT_FOUND_IN_DATABASE)
1150 __COUT_ERR__ <<
"user: " << user <<
" is not found" << __E__;
1152 incrementIpBlacklistCount(ip);
1154 return NOT_FOUND_IN_DATABASE;
1157 ipBlacklistCounts_[ip] = 0;
1159 Users_[i].lastLoginAttempt_ = time(0);
1161 if(isInactiveForGroup(Users_[i].permissions_))
1163 __COUT_ERR__ <<
"User '" << user
1164 <<
"' account INACTIVE (could be due to failed logins)" << __E__;
1165 return ACCOUNT_INACTIVE;
1168 if(Users_[i].salt_ ==
"")
1170 __COUT__ <<
"First login attempt for user: " << user << __E__;
1172 if(newAccountCode != Users_[i].getNewAccountCode())
1174 __COUT__ <<
"New account code did not match: "
1175 << Users_[i].getNewAccountCode() <<
" != " << newAccountCode
1177 saveDatabaseToFile(DB_USERS);
1178 return NOT_FOUND_IN_DATABASE;
1184 while(!addToHashesDatabase(
1185 sha512(user, pw, Users_[i].salt_)))
1190 Users_[i].salt_ =
"";
1193 __COUT__ <<
"\tHash added: " << Hashes_.back().hash_ << __E__;
1197 std::string salt = Users_[i].salt_;
1199 if(searchHashesDatabaseForHash(sha512(user, pw, salt)) == NOT_FOUND_IN_DATABASE)
1201 __COUT__ <<
"Failed login for " << user <<
" with permissions "
1205 if(++Users_[i].loginFailureCount_ != (
unsigned char)-1)
1206 ++Users_[i].loginFailureCount_;
1208 if(Users_[i].loginFailureCount_ >= USERS_MAX_LOGIN_FAILURES)
1209 Users_[i].permissions_[WebUsers::DEFAULT_USER_GROUP] =
1210 WebUsers::PERMISSION_LEVEL_INACTIVE;
1212 __COUT_INFO__ <<
"User/pw for user '" << user
1213 <<
"' was not correct (Failed Attempt #"
1214 << (int)Users_[i].loginFailureCount_ <<
" of "
1215 << (
int)USERS_MAX_LOGIN_FAILURES <<
" allowed)." << __E__;
1217 __COUTV__(isInactiveForGroup(Users_[i].permissions_));
1218 if(isInactiveForGroup(Users_[i].permissions_))
1219 __COUT_INFO__ <<
"Account '" << user
1220 <<
"' has been marked inactive due to too many failed "
1221 "login attempts (Failed Attempt #"
1222 << (int)Users_[i].loginFailureCount_
1223 <<
")! Note only admins can reactivate accounts." << __E__;
1225 saveDatabaseToFile(DB_USERS);
1226 return NOT_FOUND_IN_DATABASE;
1230 __COUT_INFO__ <<
"Login successful for: " << user << __E__;
1232 Users_[i].loginFailureCount_ = 0;
1235 for(
int h = 0; h < 2; ++h)
1237 std::string fn = (std::string)WEB_LOGIN_DB_PATH +
1238 (std::string)USERS_LOGIN_HISTORY_PATH +
1239 (h ? USERS_GLOBAL_HISTORY_FILE : Users_[i].username_) +
"." +
1240 (std::string)USERS_LOGIN_HISTORY_FILETYPE;
1247 (h ? USERS_GLOBAL_HISTORY_SIZE : USERS_LOGIN_HISTORY_SIZE))
1251 __COUT__ <<
"No previous login history found." << __E__;
1257 "Time=%lu Username=%s Permissions=%s UID=%lu",
1259 Users_[i].username_.c_str(),
1264 "Time=%lu displayName=%s Permissions=%s UID=%lu",
1266 Users_[i].displayName_.c_str(),
1269 histXml.addTextElementToData(PREF_XML_LOGIN_HISTORY_FIELD, entryStr);
1276 saveDatabaseToFile(DB_USERS);
1277 jumbledUser = Users_[i].displayName_;
1278 newAccountCode = createNewActiveSession(Users_[i].userId_,
1281 if(ActiveSessions_.size() ==
1284 __COUT__ <<
"Attempting to auto-lock for first login user '"
1285 << Users_[i].username_ <<
"'... " << __E__;
1289 return Users_[i].userId_;
1300 std::string& cookieCode,
1302 const std::string& ip)
1306 __COUT_ERR__ <<
"rejected ip: " << ip << __E__;
1307 return NOT_FOUND_IN_DATABASE;
1312 if(!CareAboutCookieCodes_)
1316 cookieCode = genCookieCode();
1322 __COUT__ <<
"Rejecting cert logon with blank fingerprint" << __E__;
1324 incrementIpBlacklistCount(ip);
1326 return NOT_FOUND_IN_DATABASE;
1332 if((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
1334 __COUT__ <<
"uuid: " << uuid <<
" is not found" << __E__;
1337 incrementIpBlacklistCount(ip);
1339 return NOT_FOUND_IN_DATABASE;
1341 ++LoginSessions_[i].loginAttempts_;
1343 email = getUserEmailFromFingerprint(email);
1344 __COUT__ <<
"DejumbledEmail = " << email << __E__;
1347 __COUT__ <<
"Rejecting logon with unknown fingerprint" << __E__;
1349 incrementIpBlacklistCount(ip);
1351 return NOT_FOUND_IN_DATABASE;
1355 if((i = searchUsersDatabaseForUserEmail(email)) == NOT_FOUND_IN_DATABASE)
1357 __COUT__ <<
"email: " << email <<
" is not found" << __E__;
1359 incrementIpBlacklistCount(ip);
1361 return NOT_FOUND_IN_DATABASE;
1364 ipBlacklistCounts_[ip] = 0;
1368 Users_[i].lastLoginAttempt_ = time(0);
1369 if(isInactiveForGroup(Users_[i].permissions_))
1371 __COUT__ <<
"User '" << user
1372 <<
"' account INACTIVE (could be due to failed logins)." << __E__;
1373 return NOT_FOUND_IN_DATABASE;
1376 if(Users_[i].salt_ ==
"")
1378 return NOT_FOUND_IN_DATABASE;
1381 __COUT__ <<
"Login successful for: " << user << __E__;
1383 Users_[i].loginFailureCount_ = 0;
1386 for(
int h = 0; h < 2; ++h)
1388 std::string fn = (std::string)WEB_LOGIN_DB_PATH +
1389 (std::string)USERS_LOGIN_HISTORY_PATH +
1390 (h ? USERS_GLOBAL_HISTORY_FILE : Users_[i].username_) +
"." +
1391 (std::string)USERS_LOGIN_HISTORY_FILETYPE;
1398 (h ? USERS_GLOBAL_HISTORY_SIZE : USERS_LOGIN_HISTORY_SIZE))
1402 __COUT__ <<
"No previous login history found." << __E__;
1408 "Time=%lu Username=%s Permissions=%s UID=%lu",
1410 Users_[i].username_.c_str(),
1415 "Time=%lu displayName=%s Permissions=%s UID=%lu",
1417 Users_[i].displayName_.c_str(),
1420 histXml.addTextElementToData(PREF_XML_LOGIN_HISTORY_FIELD, entryStr);
1427 saveDatabaseToFile(DB_USERS);
1428 email = Users_[i].displayName_;
1429 cookieCode = createNewActiveSession(Users_[i].userId_,
1431 return Users_[i].userId_;
1437 uint64_t WebUsers::searchActiveSessionDatabaseForCookie(
1438 const std::string& cookieCode)
const
1441 for(; i < ActiveSessions_.size(); ++i)
1442 if(ActiveSessions_[i].cookieCode_ == cookieCode)
1444 return (i == ActiveSessions_.size()) ? NOT_FOUND_IN_DATABASE : i;
1462 uint64_t WebUsers::checkRemoteLoginVerification(std::string& cookieCode,
1465 const std::string& ip)
1467 __COUTVS__(2, cookieCode);
1468 remoteLoginVerificationEnabledBlackoutTime_ = 0;
1469 if(!remoteLoginVerificationSocket_)
1474 <<
"Illegal remote login verification port found in remote destination "
1476 <<
". Please check remote settings." << __E__;
1479 __COUT_INFO__ <<
"Instantiating Remote Gateway login verification socket! "
1480 "Validation requests will go to "
1484 remoteLoginVerificationSocket_ =
1485 std::make_unique<TransceiverSocket>(remoteLoginVerificationIP_);
1486 remoteLoginVerificationSocket_->initialize();
1488 remoteLoginVerificationSocketTarget_ = std::make_unique<Socket>(
1494 __COUTTV__(cookieCode);
1495 __COUTTV__(RemoteSessions_.size());
1496 auto it = RemoteSessions_.find(cookieCode);
1497 if(it != RemoteSessions_.end())
1499 __COUTT__ <<
"cookieCode still active locally!" << __E__;
1500 __COUTV__(it->second.userId_);
1501 return it->second.userId_;
1505 __COUTTV__(doNotGoRemote);
1507 return NOT_FOUND_IN_DATABASE;
1518 std::string request =
"loginVerify," + cookieCode +
"," + (refresh ?
"1" :
"0") +
1524 std::string requestResponseString = remoteLoginVerificationSocket_->sendAndReceive(
1525 *remoteLoginVerificationSocketTarget_, request, 10 );
1526 __COUTV__(requestResponseString);
1529 std::vector<std::string> rxParams =
1533 if(rxParams.size() != 6)
1535 __COUT__ <<
"Remote login response indicates rejected: " << rxParams.size()
1537 return NOT_FOUND_IN_DATABASE;
1549 __COUTTV__(rxParams[2]);
1550 __COUTTV__(usersUsernameWithLock_);
1553 std::string username = rxParams[3];
1554 __COUTTV__(username);
1555 uint64_t j = searchUsersDatabaseForUsername(username);
1556 if(j == NOT_FOUND_IN_DATABASE)
1558 __COUT_INFO__ <<
"Creating User entry for remote user '" << username
1559 <<
"' in local user list to track user preferences." << __E__;
1563 j = Users_.size() - 1;
1566 Users_[j].lastLoginAttempt_ = time(0);
1567 Users_[j].setModifier(
"REMOTE_GATEWAY");
1572 .permissions_.clear();
1574 Users_[j].permissions_);
1576 __COUTV__(Users_[j].username_);
1577 __COUTV__(Users_[j].userId_);
1581 cookieCode = rxParams[0];
1582 __COUTTV__(cookieCode);
1583 ActiveSession& newRemoteSession =
1584 RemoteSessions_[cookieCode];
1585 newRemoteSession.cookieCode_ = cookieCode;
1586 newRemoteSession.ip_ = ip;
1587 newRemoteSession.userId_ = Users_[j].userId_;
1588 sscanf(rxParams[5].c_str(),
"%lu", &newRemoteSession.sessionIndex_);
1589 newRemoteSession.startTime_ = time(0);
1592 if(!CareAboutCookieCodes_ && refresh &&
1593 usersUsernameWithLock_ == DEFAULT_ADMIN_USERNAME &&
1594 usersUsernameWithLock_ != username)
1596 __COUT_INFO__ <<
"Overriding local user-with-lock '" << usersUsernameWithLock_
1597 <<
"' with remote user-with-lock 'Remote:" << username <<
"'"
1599 usersUsernameWithLock_ =
1603 getUserWithLock() +
" has locked REMOTE ots (overriding anonymous " +
1604 DEFAULT_ADMIN_USERNAME +
" user).");
1607 __COUTT__ <<
"Returning remote login success" << __E__;
1608 return Users_[j].userId_;
1617 if((u = searchUsersDatabaseForUsername(username)) == NOT_FOUND_IN_DATABASE)
1627 __COUTT__ <<
"isUserIdActive? " << uid << __E__;
1630 for(
const auto& remoteSession : RemoteSessions_)
1631 if(remoteSession.second.userId_ == uid)
1636 for(; i < ActiveSessions_.size(); ++i)
1637 if(ActiveSessions_[i].userId_ == uid)
1645 uint64_t WebUsers::searchUsersDatabaseForUsername(
const std::string& username)
const
1648 for(; i < Users_.size(); ++i)
1649 if(Users_[i].username_ == username)
1651 return (i == Users_.size()) ? NOT_FOUND_IN_DATABASE : i;
1657 uint64_t WebUsers::searchUsersDatabaseForDisplayName(
const std::string& displayName)
const
1660 for(; i < Users_.size(); ++i)
1661 if(Users_[i].displayName_ == displayName)
1663 return (i == Users_.size()) ? NOT_FOUND_IN_DATABASE : i;
1669 uint64_t WebUsers::searchUsersDatabaseForUserEmail(
const std::string& useremail)
const
1672 for(; i < Users_.size(); ++i)
1673 if(Users_[i].email_ == useremail)
1675 return (i == Users_.size()) ? NOT_FOUND_IN_DATABASE : i;
1681 uint64_t WebUsers::searchUsersDatabaseForUserId(uint64_t uid)
const
1684 for(; i < Users_.size(); ++i)
1685 if(Users_[i].userId_ == uid)
1687 return (i == Users_.size()) ? NOT_FOUND_IN_DATABASE : i;
1693 uint64_t WebUsers::searchLoginSessionDatabaseForUUID(
const std::string& uuid)
const
1696 for(; i < LoginSessions_.size(); ++i)
1697 if(LoginSessions_[i].uuid_ == uuid)
1699 return (i == LoginSessions_.size()) ? NOT_FOUND_IN_DATABASE : i;
1705 uint64_t WebUsers::searchHashesDatabaseForHash(
const std::string& hash)
1709 for(; i < Hashes_.size(); ++i)
1710 if(Hashes_[i].hash_ == hash)
1715 if(i < Hashes_.size())
1716 Hashes_[i].accessTime_ =
1717 ((time(0) + (rand() % 2 ? 1 : -1) * (rand() % 30 * 24 * 60 * 60)) &
1718 0x0FFFFFFFFFE000000);
1723 return (i == Hashes_.size()) ? NOT_FOUND_IN_DATABASE : i;
1730 bool WebUsers::addToHashesDatabase(
const std::string& hash)
1732 if(searchHashesDatabaseForHash(hash) != NOT_FOUND_IN_DATABASE)
1734 __COUT__ <<
"Hash collision: " << hash << __E__;
1737 Hashes_.push_back(Hash());
1738 Hashes_.back().hash_ = hash;
1739 Hashes_.back().accessTime_ =
1740 ((time(0) + (rand() % 2 ? 1 : -1) * (rand() % 30 * 24 * 60 * 60)) &
1741 0x0FFFFFFFFFE000000);
1744 return saveDatabaseToFile(DB_HASHES);
1749 std::string WebUsers::genCookieCode()
1752 std::string cc =
"";
1753 for(uint32_t i = 0; i < COOKIE_CODE_LENGTH / 2; ++i)
1755 intToHexStr(rand(), hexStr);
1765 std::string WebUsers::createNewActiveSession(uint64_t uid,
1766 const std::string& ip,
1770 ActiveSessions_.push_back(ActiveSession());
1771 ActiveSessions_.back().cookieCode_ = genCookieCode();
1772 ActiveSessions_.back().ip_ = ip;
1773 ActiveSessions_.back().userId_ = uid;
1774 ActiveSessions_.back().startTime_ = time(0);
1777 ActiveSessions_.back().sessionIndex_ = asIndex;
1782 for(uint64_t j = 0; j < ActiveSessions_.size(); ++j)
1783 if(ActiveSessions_[j].userId_ == uid &&
1784 max < ActiveSessions_[j].sessionIndex_)
1785 max = ActiveSessions_[j].sessionIndex_;
1787 ActiveSessions_.back().sessionIndex_ = (max ? max + 1 : 1);
1790 return ActiveSessions_.back().cookieCode_;
1817 std::string WebUsers::refreshCookieCode(
unsigned int i,
bool enableRefresh)
1820 for(uint64_t j = ActiveSessions_.size() - 1; j != (uint64_t)-1;
1822 if(ActiveSessions_[j].userId_ == ActiveSessions_[i].userId_ &&
1823 ActiveSessions_[j].sessionIndex_ ==
1824 ActiveSessions_[i].sessionIndex_)
1829 if(enableRefresh && (time(0) - ActiveSessions_[j].startTime_ >
1830 ACTIVE_SESSION_EXPIRATION_TIME / 2))
1834 ActiveSessions_[j].startTime_ =
1835 time(0) - ACTIVE_SESSION_EXPIRATION_TIME +
1836 ACTIVE_SESSION_COOKIE_OVERLAP_TIME;
1842 return createNewActiveSession(ActiveSessions_[i].userId_,
1843 ActiveSessions_[i].ip_,
1844 ActiveSessions_[i].sessionIndex_);
1847 return ActiveSessions_[j].cookieCode_;
1859 std::string& cookieCode,
1860 std::string& username)
1862 if(!CareAboutCookieCodes_)
1869 if(!ActiveSessions_.size())
1870 return NOT_FOUND_IN_DATABASE;
1875 if((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
1877 __COUT__ <<
"uuid not found: " << uuid << __E__;
1878 return NOT_FOUND_IN_DATABASE;
1882 dejumble(username, LoginSessions_[i].id_);
1885 if((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
1887 __COUT__ <<
"Cookie code not found" << __E__;
1888 return NOT_FOUND_IN_DATABASE;
1892 if((j = searchUsersDatabaseForUserId(ActiveSessions_[i].userId_)) ==
1893 NOT_FOUND_IN_DATABASE)
1895 __COUT__ <<
"User ID not found" << __E__;
1896 return NOT_FOUND_IN_DATABASE;
1900 if(Users_[j].username_ != username)
1902 __COUT__ <<
"cookieCode: " << cookieCode <<
" was.." << __E__;
1903 __COUT__ <<
"username: " << username <<
" is not found" << __E__;
1904 return NOT_FOUND_IN_DATABASE;
1907 username = Users_[j].displayName_;
1908 cookieCode = refreshCookieCode(i);
1909 return Users_[j].userId_;
1918 std::vector<uint64_t> uniqueAsi;
1921 for(i = 0; i < ActiveSessions_.size(); ++i)
1922 if(ActiveSessions_[i].userId_ == uid)
1927 for(j = 0; j < uniqueAsi.size(); ++j)
1928 if(uniqueAsi[j] == ActiveSessions_[i].sessionIndex_)
1935 uniqueAsi.push_back(ActiveSessions_[i].sessionIndex_);
1938 __COUT__ <<
"Found " << uniqueAsi.size() <<
" active sessions for uid " << uid
1941 return uniqueAsi.size();
1957 if(time(0) > ipSecurityLastLoadTime_ +
1960 ipSecurityLastLoadTime_ = time(0);
1961 loadIPAddressSecurity();
1964 for(
const auto& acceptIp : ipAccessAccept_)
1967 __COUTV__(acceptIp);
1970 for(
const auto& rejectIp : ipAccessReject_)
1973 __COUTV__(rejectIp);
1976 for(
const auto& blacklistIp : ipAccessBlacklist_)
1979 __COUTV__(blacklistIp);
1989 void WebUsers::incrementIpBlacklistCount(
const std::string& ip)
1991 if(ipAccessBlacklist_.find(ip) != ipAccessBlacklist_.end())
1995 auto it = ipBlacklistCounts_.find(ip);
1996 if(it == ipBlacklistCounts_.end())
1998 __COUT__ <<
"First error for ip '" << ip <<
"'" << __E__;
1999 ipBlacklistCounts_[ip] = 1;
2005 if(it->second >= IP_BLACKLIST_COUNT_THRESHOLD)
2007 __COUT_WARN__ <<
"Adding IP '" << ip <<
"' to blacklist!" << __E__;
2009 ipAccessBlacklist_.emplace(ip);
2010 __COUTV__(ipAccessBlacklist_.size());
2013 FILE* fp = fopen((IP_BLACKLIST_FILE).c_str(),
"a");
2016 __COUT_ERR__ <<
"IP black list file '" << IP_BLACKLIST_FILE
2017 <<
"' could not be opened." << __E__;
2020 fprintf(fp,
"%s\n", ip.c_str());
2031 if((i = searchUsersDatabaseForUserId(uid)) == NOT_FOUND_IN_DATABASE)
2033 return Users_[i].displayName_;
2041 if((i = searchUsersDatabaseForUserId(uid)) == NOT_FOUND_IN_DATABASE)
2043 return Users_[i].username_;
2058 bool logoutOtherUserSessions,
2060 const std::string& ip)
2065 if((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
2067 __COUT__ <<
"Cookie code not found" << __E__;
2069 incrementIpBlacklistCount(ip);
2071 return NOT_FOUND_IN_DATABASE;
2074 ipBlacklistCounts_[ip] = 0;
2077 if(ActiveSessions_[i].ip_ != ip)
2079 __COUT__ <<
"IP does not match active session" << __E__;
2080 return NOT_FOUND_IN_DATABASE;
2089 uint64_t asi = ActiveSessions_[i].sessionIndex_;
2090 uint64_t uid = ActiveSessions_[i].userId_;
2093 uint64_t logoutCount = 0;
2096 while(i < ActiveSessions_.size())
2098 if((logoutOtherUserSessions && ActiveSessions_[i].userId_ == uid &&
2099 ActiveSessions_[i].sessionIndex_ != asi) ||
2100 (!logoutOtherUserSessions && ActiveSessions_[i].userId_ == uid &&
2101 ActiveSessions_[i].sessionIndex_ == asi))
2103 __COUT__ <<
"Logging out of active session " << ActiveSessions_[i].userId_
2104 <<
"-" << ActiveSessions_[i].sessionIndex_ << __E__;
2105 ActiveSessions_.erase(ActiveSessions_.begin() + i);
2112 __COUT__ <<
"Found and removed active session count = " << logoutCount << __E__;
2131 std::string& cookieCode,
2132 std::map<std::string /*groupName*/, WebUsers::permissionLevel_t>* userPermissions,
2134 const std::string& ip,
2137 std::string* userWithLock,
2138 uint64_t* userSessionIndex)
2145 __COUT_ERR__ <<
"User IP rejected." << __E__;
2146 cookieCode = REQ_NO_LOGIN_RESPONSE;
2152 uint64_t i, j, userId = NOT_FOUND_IN_DATABASE, userSession = NOT_FOUND_IN_DATABASE;
2154 __COUTTV__(CareAboutCookieCodes_);
2155 __COUTT__ <<
"refresh=" << refresh <<
", doNotGoRemote=" << doNotGoRemote << __E__;
2156 __COUTVS__(2, cookieCode);
2160 __COUTTV__(localEnableRemoteLogin);
2165 if(localEnableRemoteLogin &&
2166 time(0) > remoteLoginVerificationEnabledBlackoutTime_ &&
2167 (userId = checkRemoteLoginVerification(
2168 cookieCode, refresh, doNotGoRemote, ip)) != NOT_FOUND_IN_DATABASE)
2171 __COUTT__ <<
"Remote login session verified." << __E__;
2172 userSession = RemoteSessions_.at(cookieCode).sessionIndex_;
2177 std::string err =
"";
2182 catch(
const std::exception& e)
2187 __COUT_WARN__ <<
"Ignoring exception during remote login verification. " << err
2191 if(!CareAboutCookieCodes_ && localEnableRemoteLogin &&
2192 remoteLoginVerificationEnabledBlackoutTime_ == 0)
2195 localEnableRemoteLogin =
false;
2196 remoteLoginVerificationEnabledBlackoutTime_ = time(0) + 10;
2197 __COUT_INFO__ <<
"Disabled remote login until "
2199 remoteLoginVerificationEnabledBlackoutTime_)
2203 __COUTTV__(localEnableRemoteLogin);
2205 if(localEnableRemoteLogin && userId == NOT_FOUND_IN_DATABASE)
2206 __COUTT__ <<
"Remote login verification failed." << __E__;
2208 if(!CareAboutCookieCodes_ &&
2209 userId == NOT_FOUND_IN_DATABASE)
2213 std::map<std::string , WebUsers::permissionLevel_t>(
2218 *userWithLock = usersUsernameWithLock_;
2219 if(userSessionIndex)
2220 *userSessionIndex = 0;
2222 if(cookieCode.size() != COOKIE_CODE_LENGTH)
2223 cookieCode = genCookieCode();
2225 if(localEnableRemoteLogin)
2227 cookieCode = WebUsers::
2235 if(userId == NOT_FOUND_IN_DATABASE)
2238 if((i = searchActiveSessionDatabaseForCookie(cookieCode)) ==
2239 NOT_FOUND_IN_DATABASE)
2241 __COUT_ERR__ <<
"Cookie code not found" << __E__;
2242 cookieCode = REQ_NO_LOGIN_RESPONSE;
2244 incrementIpBlacklistCount(ip);
2249 ipBlacklistCounts_[ip] = 0;
2252 if(ip !=
"0" && ActiveSessions_[i].ip_ != ip)
2254 __COUTV__(ActiveSessions_[i].ip_);
2256 __COUT_ERR__ <<
"IP does not match active session." << __E__;
2257 cookieCode = REQ_NO_LOGIN_RESPONSE;
2261 userId = ActiveSessions_[i].userId_;
2262 userSession = ActiveSessions_[i].sessionIndex_;
2263 cookieCode = refreshCookieCode(i, refresh);
2264 __COUTT__ <<
"Login session verified." << __E__;
2270 if((j = searchUsersDatabaseForUserId(userId)) == NOT_FOUND_IN_DATABASE)
2272 __COUT_ERR__ <<
"After login verification, User ID not found! Notify admins."
2274 cookieCode = REQ_NO_LOGIN_RESPONSE;
2278 std::map<std::string , WebUsers::permissionLevel_t> tmpPerm =
2281 if(isInactiveForGroup(tmpPerm))
2283 __COUTT__ <<
"Inactive user identified." << __E__;
2284 cookieCode = REQ_NO_PERMISSION_RESPONSE;
2290 *userPermissions = tmpPerm;
2294 *userWithLock = usersUsernameWithLock_;
2295 if(userSessionIndex)
2296 *userSessionIndex = userSession;
2313 if(loggedOutUsernames)
2315 for(i = 0; i < UsersLoggedOutUsernames_.size(); ++i)
2316 loggedOutUsernames->push_back(UsersLoggedOutUsernames_[i]);
2317 UsersLoggedOutUsernames_.clear();
2321 for(i = 0; i < LoginSessions_.size(); ++i)
2322 if(LoginSessions_[i].startTime_ + LOGIN_SESSION_EXPIRATION_TIME <
2324 LoginSessions_[i].loginAttempts_ > LOGIN_SESSION_ATTEMPTS_MAX)
2326 __COUT__ <<
"Found expired login sessions: #" << (i + 1) <<
" of "
2327 << LoginSessions_.size() << __E__;
2331 LoginSessions_.erase(LoginSessions_.begin() + i);
2344 for(i = 0; i < ActiveSessions_.size(); ++i)
2345 if(ActiveSessions_[i].startTime_ + ACTIVE_SESSION_EXPIRATION_TIME <=
2355 __COUT__ <<
"Found expired active sessions: #" << (i + 1) <<
" of "
2356 << ActiveSessions_.size() << __E__;
2357 __COUTTV__(ActiveSessions_[i].cookieCode_);
2359 tmpUid = ActiveSessions_[i].userId_;
2360 ActiveSessions_.erase(ActiveSessions_.begin() + i);
2365 if(loggedOutUsernames)
2366 loggedOutUsernames->push_back(
2367 Users_[searchUsersDatabaseForUserId(tmpUid)].username_);
2369 UsersLoggedOutUsernames_.push_back(
2370 Users_[searchUsersDatabaseForUserId(tmpUid)].username_);
2391 if(CareAboutCookieCodes_ && usersUsernameWithLock_ !=
"" &&
2399 usersUsernameWithLock_ =
"";
2409 std::vector<std::string> toErase;
2410 for(
const auto& remoteSession : RemoteSessions_)
2411 if(remoteSession.second.startTime_ + ACTIVE_SESSION_EXPIRATION_TIME / 4 <=
2414 __COUT__ <<
"Found expired remote active sessions: #" << remoteSession.first
2415 <<
" in " << RemoteSessions_.size() << __E__;
2416 toErase.push_back(remoteSession.first);
2418 for(
const auto& eraseId : toErase)
2419 RemoteSessions_.erase(eraseId);
2430 const std::string& ip)
2436 for(; i < LoginSessions_.size(); ++i)
2437 if(LoginSessions_[i].uuid_ == UUID)
2440 if(i != LoginSessions_.size())
2442 __COUT_ERR__ <<
"UUID: " << UUID <<
" is not unique" << __E__;
2448 LoginSessions_.back().uuid_ = UUID;
2452 std::string sid =
"";
2453 for(i = 0; i < SESSION_ID_LENGTH / 2; ++i)
2455 intToHexStr(rand(), hexStr);
2458 LoginSessions_.back().id_ = sid;
2459 LoginSessions_.back().ip_ = ip;
2460 LoginSessions_.back().startTime_ = time(0);
2461 LoginSessions_.back().loginAttempts_ = 0;
2471 std::string WebUsers::sha512(
const std::string& user,
2472 const std::string& password,
2475 SHA512_CTX sha512_context;
2480 SHA512_Init(&sha512_context);
2482 for(
unsigned int i = 0; i < 8; ++i)
2483 sha512_context.h[i] += rand();
2485 for(
unsigned int i = 0; i <
sizeof(SHA512_CTX); ++i)
2487 intToHexStr((uint8_t)(((uint8_t*)(&sha512_context))[i]), hexStr);
2489 salt.append(hexStr);
2497 for(
unsigned int i = 0; i <
sizeof(SHA512_CTX); ++i)
2498 ((uint8_t*)(&sha512_context))[i] = hexByteStrToInt(&(salt.c_str()[i * 2]));
2501 std::string strToHash = salt + user + password;
2504 unsigned char hash[SHA512_DIGEST_LENGTH];
2506 char retHash[SHA512_DIGEST_LENGTH * 2 + 1];
2510 SHA512_Update(&sha512_context, strToHash.c_str(), strToHash.length());
2512 SHA512_Final(hash, &sha512_context);
2516 for(i = 0; i < SHA512_DIGEST_LENGTH; i++)
2517 sprintf(retHash + (i * 2),
"%02x", hash[i]);
2520 retHash[SHA512_DIGEST_LENGTH * 2] =
'\0';
2531 std::string WebUsers::dejumble(
const std::string& u,
const std::string& s)
2533 if(s.length() != SESSION_ID_LENGTH)
2536 const int ss = s.length() / 2;
2537 int p = hexByteStrToInt(&(s.c_str()[0])) % ss;
2538 int n = hexByteStrToInt(&(s.c_str()[p * 2])) % ss;
2539 int len = (hexByteStrToInt(&(u.c_str()[p * 2])) - p - n + ss * 3) % ss;
2541 std::vector<bool> x(ss);
2542 for(
int i = 0; i < ss; ++i)
2546 int c = hexByteStrToInt(&(u.c_str()[p * 2]));
2548 std::string user =
"";
2550 for(
int l = 0; l < len; ++l)
2552 p = (p + hexByteStrToInt(&(s.c_str()[p * 2]))) % ss;
2556 n = hexByteStrToInt(&(s.c_str()[p * 2]));
2557 user.append(1, (hexByteStrToInt(&(u.c_str()[p * 2])) - c - n + ss * 4) % ss);
2558 c = hexByteStrToInt(&(u.c_str()[p * 2]));
2567 std::map<std::string , WebUsers::permissionLevel_t>
2570 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
2571 if(userIndex < Users_.size())
2572 return Users_[userIndex].permissions_;
2575 std::map<std::string , WebUsers::permissionLevel_t> retErrorMap;
2576 retErrorMap[WebUsers::DEFAULT_USER_GROUP] = WebUsers::PERMISSION_LEVEL_INACTIVE;
2613 WebUsers::permissionLevel_t WebUsers::getPermissionLevelForGroup(
2614 const std::map<std::string /*groupName*/, WebUsers::permissionLevel_t>& permissionMap,
2615 const std::string& groupName)
2617 auto it = permissionMap.find(groupName);
2618 if(it == permissionMap.end())
2620 __COUT__ <<
"Group name '" << groupName
2621 <<
"' not found - assuming inactive user in this group." << __E__;
2622 return WebUsers::PERMISSION_LEVEL_INACTIVE;
2628 bool WebUsers::isInactiveForGroup(
2629 const std::map<std::string /*groupName*/, WebUsers::permissionLevel_t>& permissionMap,
2630 const std::string& groupName)
2632 return getPermissionLevelForGroup(permissionMap, groupName) ==
2633 WebUsers::PERMISSION_LEVEL_INACTIVE;
2637 bool WebUsers::isAdminForGroup(
2638 const std::map<std::string /*groupName*/, WebUsers::permissionLevel_t>& permissionMap,
2639 const std::string& groupName)
2641 return getPermissionLevelForGroup(permissionMap, groupName) ==
2648 std::string WebUsers::getTooltipFilename(
const std::string& username,
2649 const std::string& srcFile,
2650 const std::string& srcFunc,
2651 const std::string& srcId)
2653 std::string filename = (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH +
"/";
2657 mkdir(((std::string)WEB_LOGIN_DB_PATH).c_str(), 0755);
2658 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH).c_str(), 0755);
2659 mkdir(filename.c_str(), 0755);
2661 for(
const char& c : username)
2663 (c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z') || (c >=
'0' && c <=
'9'))
2668 mkdir(filename.c_str(), 0755);
2670 for(
const char& c : srcFile)
2672 (c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z') || (c >=
'0' && c <=
'9'))
2675 for(
const char& c : srcFunc)
2677 (c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z') || (c >=
'0' && c <=
'9'))
2680 for(
const char& c : srcId)
2682 (c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z') || (c >=
'0' && c <=
'9'))
2689 std::string ots::WebUsers::getUserEmailFromFingerprint(
const std::string& fingerprint)
2691 __COUT__ <<
"Checking if user fingerprint " << fingerprint <<
" is in memory database"
2693 if(certFingerprints_.count(fingerprint))
2695 return certFingerprints_[fingerprint];
2698 __COUT__ <<
"Going to read credential database " << WEB_LOGIN_CERTDATA_PATH << __E__;
2699 std::ifstream f(WEB_LOGIN_CERTDATA_PATH);
2707 if(fp !=
"NOKEY" && fp !=
"")
2709 __COUT__ <<
"Adding user " << email <<
" to list with fingerprint " << fp
2711 certFingerprints_[fp] = email;
2717 remove(WEB_LOGIN_CERTDATA_PATH.c_str());
2720 __COUT__ <<
"Checking again if fingerprint is in memory database" << __E__;
2721 if(certFingerprints_.count(fingerprint))
2723 return certFingerprints_[fingerprint];
2726 __COUT__ <<
"Could not match fingerprint, returning null email" << __E__;
2735 const std::string& srcFile,
2736 const std::string& srcFunc,
2737 const std::string& srcId,
2739 bool temporarySilence)
2741 std::string filename;
2742 bool isForAll = (srcFile ==
"ALL" && srcFunc ==
"ALL" && srcId ==
"ALL");
2746 __COUT__ <<
"Disabling ALL tooltips for user '" << username <<
"' is now set to "
2747 << doNeverShow << __E__;
2748 filename = getTooltipFilename(username, SILENCE_ALL_TOOLTIPS_FILENAME,
"",
"");
2752 filename = getTooltipFilename(username, srcFile, srcFunc, srcId);
2753 __COUT__ <<
"Setting tooltip never show for user '" << username <<
"' to "
2754 << doNeverShow <<
" (temporarySilence=" << temporarySilence <<
")"
2758 FILE* fp = fopen(filename.c_str(),
"w");
2761 if(temporarySilence)
2764 time(0) + 7 * 24 * 60 * 60);
2765 else if(!isForAll && doNeverShow && username == WebUsers::DEFAULT_ADMIN_USERNAME)
2768 fprintf(fp,
"%ld", time(0) + 30 * 24 * 60 * 60);
2770 __COUT__ <<
"User '" << username
2771 <<
"' may be a shared account, so max silence duration for tooltips "
2772 "is 30 days. Silencing now."
2776 fputc(doNeverShow ?
'1' :
'0', fp);
2780 __COUT_ERR__ <<
"Big problem with tooltips! File not accessible: " << filename
2793 const std::string& srcFile,
2794 const std::string& srcFunc,
2795 const std::string& srcId)
2797 if(srcId ==
"ALWAYS")
2800 xmldoc->addTextElementToData(
"ShowTooltip",
"1");
2811 std::string silencefilename =
2812 getTooltipFilename(username, SILENCE_ALL_TOOLTIPS_FILENAME,
"",
"");
2814 FILE* silencefp = fopen(silencefilename.c_str(),
"r");
2815 if(silencefp != NULL)
2819 fgets(line, 100, silencefp);
2820 sscanf(line,
"%ld", &val);
2824 xmldoc->addTextElementToData(
"ShowTooltip",
"0");
2830 std::string filename = getTooltipFilename(username, srcFile, srcFunc, srcId);
2831 FILE* fp = fopen(filename.c_str(),
"r");
2836 fgets(line, 100, fp);
2837 sscanf(line,
"%ld", &val);
2840 __COUT__ <<
"tooltip value read = " << val <<
" vs time(0)=" << time(0) << __E__;
2844 xmldoc->addTextElementToData(
"ShowTooltip",
2845 val == 1 ?
"0" : (time(0) > val ?
"1" :
"0"));
2849 xmldoc->addTextElementToData(
"ShowTooltip",
"1");
2859 (
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH +
"/" + userNeedle)
2861 __COUT__ <<
"Successfully reset Tooltips for user " << userNeedle << __E__;
2869 std::string silencefilename = getTooltipFilename(
2870 username, SILENCE_ALL_TOOLTIPS_FILENAME,
"",
"");
2872 __COUTV__(silencefilename);
2873 FILE* silencefp = fopen(silencefilename.c_str(),
"w");
2874 if(silencefp != NULL)
2876 fputs(
"1", silencefp);
2904 bool includeAccounts)
2906 std::map<std::string , WebUsers::permissionLevel_t> permissionMap =
2910 if(isInactiveForGroup(permissionMap))
2913 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
2914 __COUT__ <<
"Gettings settings for user: " << Users_[userIndex].username_ << __E__;
2916 std::string fn = (std::string)WEB_LOGIN_DB_PATH +
2917 (std::string)USERS_PREFERENCES_PATH + Users_[userIndex].username_ +
2918 "." + (std::string)USERS_PREFERENCES_FILETYPE;
2922 __COUT__ <<
"Preferences file: " << fn << __E__;
2926 __COUT__ <<
"Preferences are defaults." << __E__;
2928 xmldoc->addTextElementToData(PREF_XML_BGCOLOR_FIELD, PREF_XML_BGCOLOR_DEFAULT);
2929 xmldoc->addTextElementToData(PREF_XML_DBCOLOR_FIELD, PREF_XML_DBCOLOR_DEFAULT);
2930 xmldoc->addTextElementToData(PREF_XML_WINCOLOR_FIELD, PREF_XML_WINCOLOR_DEFAULT);
2931 xmldoc->addTextElementToData(PREF_XML_LAYOUT_FIELD, PREF_XML_LAYOUT_DEFAULT);
2935 __COUT__ <<
"Saved Preferences found." << __E__;
2940 if(includeAccounts && isAdminForGroup(permissionMap))
2942 __COUT__ <<
"Admin on our hands" << __E__;
2944 xmldoc->addTextElementToData(PREF_XML_ACCOUNTS_FIELD,
"");
2946 if(Users_.size() == 0)
2948 __COUT__ <<
"Missing users? Attempting to load database" << __E__;
2953 for(uint64_t i = 0; i < Users_.size(); ++i)
2956 "username", Users_[i].username_, PREF_XML_ACCOUNTS_FIELD);
2958 "display_name", Users_[i].displayName_, PREF_XML_ACCOUNTS_FIELD);
2960 if(Users_[i].email_.size() > i)
2963 "useremail", Users_[i].email_, PREF_XML_ACCOUNTS_FIELD);
2973 PREF_XML_ACCOUNTS_FIELD);
2976 "nac", Users_[i].getNewAccountCode().c_str(), PREF_XML_ACCOUNTS_FIELD);
2981 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
2982 (std::string)SYSTEM_PREFERENCES_PREFIX +
"." +
2983 (std::string)USERS_PREFERENCES_FILETYPE;
2986 __COUT__ <<
"System Preferences are defaults." << __E__;
2988 xmldoc->addTextElementToData(PREF_XML_SYSLAYOUT_FIELD,
2989 PREF_XML_SYSLAYOUT_DEFAULT);
2993 __COUT__ <<
"Saved System Preferences found." << __E__;
3000 xmldoc->addTextElementToData(PREF_XML_PERMISSIONS_FIELD,
3004 xmldoc->addTextElementToData(PREF_XML_USERLOCK_FIELD, usersUsernameWithLock_);
3007 xmldoc->addTextElementToData(PREF_XML_USERNAME_FIELD,
getUsersUsername(uid));
3013 xmldoc->addTextElementToData(
"ots_remote_address",
3014 remoteLoginVerificationIP_ +
":" +
3023 const std::string& preferenceName,
3024 const std::string& preferenceValue)
3026 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
3031 std::string safePreferenceName =
"";
3032 for(
const auto& c : preferenceName)
3033 if((c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z') || (c >=
'0' && c <=
'9') ||
3034 (c >=
'-' || c <=
'_'))
3035 safePreferenceName += c;
3037 std::string dir = (std::string)WEB_LOGIN_DB_PATH +
3038 (std::string)USERS_PREFERENCES_PATH +
"generic_" +
3039 safePreferenceName +
"/";
3042 mkdir(dir.c_str(), 0755);
3044 std::string fn = Users_[userIndex].username_ +
"_" + safePreferenceName +
"." +
3045 (std::string)USERS_PREFERENCES_FILETYPE;
3047 __COUT__ <<
"Preferences file: " << (dir + fn) << __E__;
3049 FILE* fp = fopen((dir + fn).c_str(),
"w");
3052 fprintf(fp,
"%s", preferenceValue.c_str());
3056 __COUT_ERR__ <<
"Preferences file could not be opened for writing!" << __E__;
3064 const std::string& preferenceName,
3067 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
3072 std::string safePreferenceName =
"";
3073 for(
const auto& c : preferenceName)
3074 if((c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z') || (c >=
'0' && c <=
'9') ||
3075 (c >=
'-' || c <=
'_'))
3076 safePreferenceName += c;
3078 std::string dir = (std::string)WEB_LOGIN_DB_PATH +
3079 (std::string)USERS_PREFERENCES_PATH +
"generic_" +
3080 safePreferenceName +
"/";
3082 std::string fn = Users_[userIndex].username_ +
"_" + safePreferenceName +
"." +
3083 (std::string)USERS_PREFERENCES_FILETYPE;
3085 __COUT__ <<
"Preferences file: " << (dir + fn) << __E__;
3088 FILE* fp = fopen((dir + fn).c_str(),
"r");
3091 fseek(fp, 0, SEEK_END);
3092 const long size = ftell(fp);
3093 char* line =
new char
3097 fread(line, 1, size, fp);
3100 std::string retVal(line, size);
3103 __COUT__ <<
"Read value (sz = " << retVal.size() <<
") " << retVal << __E__;
3105 xmldoc->addTextElementToData(safePreferenceName, retVal);
3109 __COUT__ <<
"Using default value." << __E__;
3113 xmldoc->addTextElementToData(safePreferenceName,
"");
3120 const std::string& bgcolor,
3121 const std::string& dbcolor,
3122 const std::string& wincolor,
3123 const std::string& layout,
3124 const std::string& syslayout)
3126 std::map<std::string , WebUsers::permissionLevel_t> permissionMap =
3128 if(isInactiveForGroup(permissionMap))
3131 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
3132 __COUT__ <<
"Changing settings for user: " << Users_[userIndex].username_ << __E__;
3134 std::string fn = (std::string)WEB_LOGIN_DB_PATH +
3135 (std::string)USERS_PREFERENCES_PATH + Users_[userIndex].username_ +
3136 "." + (std::string)USERS_PREFERENCES_FILETYPE;
3138 __COUT__ <<
"Preferences file: " << fn << __E__;
3141 prefXml.addTextElementToData(PREF_XML_BGCOLOR_FIELD, bgcolor);
3142 prefXml.addTextElementToData(PREF_XML_DBCOLOR_FIELD, dbcolor);
3143 prefXml.addTextElementToData(PREF_XML_WINCOLOR_FIELD, wincolor);
3144 prefXml.addTextElementToData(PREF_XML_LAYOUT_FIELD, layout);
3149 if(!isAdminForGroup(permissionMap))
3153 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
3154 (std::string)SYSTEM_PREFERENCES_PREFIX +
"." +
3155 (std::string)USERS_PREFERENCES_FILETYPE;
3158 sysPrefXml.addTextElementToData(PREF_XML_SYSLAYOUT_FIELD, syslayout);
3170 std::map<std::string , WebUsers::permissionLevel_t> permissionMap =
3176 __COUTV__(actingUser);
3178 __COUTV__(usersUsernameWithLock_);
3180 __COUTV__(username);
3181 __COUTV__(isUserActive);
3183 if(lock && (isUserActive || !CareAboutCookieCodes_))
3185 if(!CareAboutCookieCodes_ && !isUserActive &&
3186 username != DEFAULT_ADMIN_USERNAME)
3189 <<
"User '" << actingUser
3190 <<
"' tried to lock for a user other than admin in wiz mode. Not allowed."
3194 else if(!isAdminForGroup(permissionMap) &&
3195 actingUser != username)
3197 __COUT_ERR__ <<
"A non-admin user '" << actingUser
3198 <<
"' tried to lock for a user other than self. Not allowed."
3202 usersUsernameWithLock_ = username;
3204 else if(!lock && usersUsernameWithLock_ == username)
3205 usersUsernameWithLock_ =
"";
3209 __COUT_ERR__ <<
"User '" << username <<
"' is inactive." << __E__;
3210 __COUT_ERR__ <<
"Failed to lock for user '" << username <<
".'" << __E__;
3214 __COUT_INFO__ <<
"User '" << username <<
"' has locked out the system!" << __E__;
3218 std::string securityFileName = USER_WITH_LOCK_FILE;
3219 FILE* fp = fopen(securityFileName.c_str(),
"w");
3222 __COUT_INFO__ <<
"USER_WITH_LOCK_FILE " << USER_WITH_LOCK_FILE
3223 <<
" not found. Ignoring." << __E__;
3227 fprintf(fp,
"%s", usersUsernameWithLock_.c_str());
3238 const std::string& username,
3239 const std::string& displayname,
3240 const std::string& email,
3241 const std::string& permissions)
3243 std::map<std::string , WebUsers::permissionLevel_t> permissionMap =
3245 if(!isAdminForGroup(permissionMap))
3248 __SS__ <<
"Only admins can modify user settings." << __E__;
3252 uint64_t i = searchUsersDatabaseForUserId(actingUid);
3253 uint64_t modi = searchUsersDatabaseForUsername(username);
3258 __COUT_INFO__ <<
"Admin password reset." << __E__;
3259 Users_[modi].setModifier(Users_[i].username_);
3260 Users_[modi].salt_ =
"";
3261 Users_[modi].loginFailureCount_ = 0;
3262 saveDatabaseToFile(DB_USERS);
3265 __SS__ <<
"Cannot modify first user" << __E__;
3269 if(username.length() < USERNAME_LENGTH)
3271 __SS__ <<
"Invalid Username, must be length " << USERNAME_LENGTH << __E__;
3274 if(displayname.length() < DISPLAY_NAME_LENGTH)
3276 __SS__ <<
"Invalid Display Name; must be length " << DISPLAY_NAME_LENGTH << __E__;
3280 __COUT__ <<
"Input Permissions: " << permissions << __E__;
3281 std::map<std::string , WebUsers::permissionLevel_t> newPermissionsMap;
3285 case MOD_TYPE_UPDATE:
3287 __COUT__ <<
"MOD_TYPE_UPDATE " << username <<
" := " << permissions << __E__;
3289 if(modi == NOT_FOUND_IN_DATABASE)
3291 __SS__ <<
"User not found!? Should not happen." << __E__;
3297 for(uint64_t i = 0; i < Users_.size(); ++i)
3300 else if(Users_[i].displayName_ == displayname)
3302 __SS__ <<
"Display Name '" << displayname
3303 <<
"' already exists! Please choose a unique display name."
3309 Users_[modi].displayName_ = displayname;
3310 Users_[modi].email_ = email;
3314 bool wasInactive = isInactiveForGroup(Users_[modi].permissions_);
3317 if(newPermissionsMap.size() == 0)
3318 Users_[modi].permissions_[WebUsers::DEFAULT_USER_GROUP] =
3319 std::atoi(permissions.c_str());
3320 else if(newPermissionsMap.size() == 1 &&
3321 newPermissionsMap.find(WebUsers::DEFAULT_USER_GROUP) ==
3322 newPermissionsMap.end())
3324 if(newPermissionsMap.begin()->first ==
"")
3325 Users_[modi].permissions_[WebUsers::DEFAULT_USER_GROUP] =
3326 newPermissionsMap.begin()->second;
3329 newPermissionsMap[WebUsers::DEFAULT_USER_GROUP] =
3330 newPermissionsMap.begin()->second;
3331 Users_[modi].permissions_ = newPermissionsMap;
3335 Users_[modi].permissions_ = newPermissionsMap;
3340 !isInactiveForGroup(Users_[modi].permissions_))
3342 __COUT__ <<
"Reactivating " << username << __E__;
3343 Users_[modi].loginFailureCount_ = 0;
3344 Users_[modi].salt_ =
"";
3350 if(i == NOT_FOUND_IN_DATABASE)
3352 __SS__ <<
"Master User not found!? Should not happen." << __E__;
3355 Users_[modi].setModifier(Users_[i].username_);
3361 __COUT__ <<
"MOD_TYPE_ADD " << username <<
" - " << displayname << __E__;
3366 if(i == NOT_FOUND_IN_DATABASE)
3368 __SS__ <<
"Master User not found!? Should not happen." << __E__;
3371 Users_.back().setModifier(Users_[i].username_);
3374 if(permissions.size())
3377 actingUid, MOD_TYPE_UPDATE, username, displayname, email, permissions);
3381 case MOD_TYPE_DELETE:
3382 __COUT__ <<
"MOD_TYPE_DELETE " << username <<
" - " << displayname << __E__;
3383 deleteAccount(username, displayname);
3386 __SS__ <<
"Undefined command - do nothing " << username << __E__;
3390 saveDatabaseToFile(DB_USERS);
3391 loadSecuritySelection();
3398 std::set<unsigned int> activeUserIndices;
3399 for(uint64_t i = 0; i < ActiveSessions_.size(); ++i)
3400 activeUserIndices.emplace(
3401 searchUsersDatabaseForUserId(ActiveSessions_[i].userId_));
3402 return activeUserIndices.size();
3410 std::set<unsigned int> activeUserIndices;
3411 for(uint64_t i = 0; i < ActiveSessions_.size(); ++i)
3412 activeUserIndices.emplace(
3413 searchUsersDatabaseForUserId(ActiveSessions_[i].userId_));
3415 std::string activeUsersString =
"";
3416 bool addComma =
false;
3417 for(
const auto& i : activeUserIndices)
3419 if(i >= Users_.size())
3423 activeUsersString +=
",";
3427 activeUsersString += Users_[i].displayName_;
3429 if(activeUserIndices.size() == 0 &&
3431 WebUsers::SECURITY_TYPE_NONE)
3432 activeUsersString += WebUsers::DEFAULT_ADMIN_DISPLAY_NAME;
3434 __COUTVS__(20, activeUsersString);
3435 return activeUsersString;
3443 uint64_t uid = searchUsersDatabaseForUsername(DEFAULT_ADMIN_USERNAME);
3450 void WebUsers::loadUserWithLock()
3452 char username[300] =
"";
3454 std::string securityFileName = USER_WITH_LOCK_FILE;
3455 FILE* fp = fopen(securityFileName.c_str(),
"r");
3458 __COUT_INFO__ <<
"USER_WITH_LOCK_FILE " << USER_WITH_LOCK_FILE
3459 <<
" not found. Defaulting to admin lock." << __E__;
3462 sprintf(username,
"%s", DEFAULT_ADMIN_USERNAME.c_str());
3466 fgets(username, 300, fp);
3473 __COUT__ <<
"Attempting to load username with lock: " << username << __E__;
3475 if(strlen(username) == 0)
3477 __COUT_INFO__ <<
"Loaded state for user-with-lock is unlocked." << __E__;
3481 uint64_t i = searchUsersDatabaseForUsername(username);
3482 if(i == NOT_FOUND_IN_DATABASE)
3484 __COUT_INFO__ <<
"username " << username <<
" not found in database. Ignoring."
3488 __COUT__ <<
"Setting lock" << __E__;
3496 const std::string& message)
3505 const std::string& subject,
3506 const std::string& message,
3509 std::vector<std::string> targetUsers;
3519 const std::string& subject,
3520 const std::string& message,
3523 systemMessageCleanup();
3525 std::string fullMessage = StringMacros::encodeURIComponent(
3526 (subject ==
"" ?
"" : (subject +
": ")) + message);
3529 std::cout << __COUT_HDR_FL__ <<
"addSystemMessage() fullMessage: " << fullMessage
3533 std::set<std::string> targetEmails;
3535 for(
const auto& targetUser : targetUsers)
3539 if(targetUser ==
"" || (targetUser !=
"*" && targetUser.size() < 3))
3541 __COUT__ <<
"Illegal username '" << targetUser <<
"'" << __E__;
3544 __COUTV__(targetUser);
3548 if(doEmail && targetUser ==
"*")
3551 for(
const auto& user : Users_)
3553 if(user.email_.size() > 5 &&
3554 user.email_.find(
'@') != std::string::npos &&
3555 user.email_.find(
'.') != std::string::npos)
3557 __COUT__ <<
"Adding " << user.displayName_
3558 <<
" email: " << user.email_ << __E__;
3559 targetEmails.emplace(user.email_);
3564 else if(targetUser.find(
':') != std::string::npos)
3567 __COUT__ <<
"Treating as group email target: " << targetUser << __E__;
3569 std::map<std::string, WebUsers::permissionLevel_t> targetGroupMap;
3576 if(targetGroupMap.size() == 1)
3581 for(
const auto& user : Users_)
3583 WebUsers::permissionLevel_t userLevel =
3585 targetGroupMap.begin()->first);
3589 __COUTV__((
int)userLevel);
3590 __COUTV__(targetGroupMap.begin()->first);
3592 if(userLevel != WebUsers::PERMISSION_LEVEL_INACTIVE &&
3593 userLevel >= targetGroupMap.begin()->second &&
3594 user.email_.size() > 5 &&
3595 user.email_.find(
'@') != std::string::npos &&
3596 user.email_.find(
'.') != std::string::npos)
3600 targetEmails.emplace(user.email_);
3601 __COUT__ <<
"Adding " << user.displayName_
3602 <<
" email: " << user.email_ << __E__;
3604 addSystemMessageToMap(user.displayName_, fullMessage);
3609 __COUT__ <<
"target Group Map from '" << targetUser <<
"' is empty."
3617 addSystemMessageToMap(targetUser, fullMessage);
3621 for(
const auto& user : Users_)
3623 if(user.displayName_ == targetUser)
3625 if(user.email_.size() > 5 &&
3626 user.email_.find(
'@') != std::string::npos &&
3627 user.email_.find(
'.') != std::string::npos)
3629 targetEmails.emplace(user.email_);
3630 __COUT__ <<
"Adding " << user.displayName_
3631 <<
" email: " << user.email_ << __E__;
3640 __COUTV__(targetEmails.size());
3642 if(doEmail && targetEmails.size())
3646 std::string toList =
"";
3647 bool addComma =
false;
3648 for(
const auto& email : targetEmails)
3657 std::string filename = (std::string)WEB_LOGIN_DB_PATH +
3658 (std::string)USERS_DB_PATH +
"/.tmp_email.txt";
3659 FILE* fp = fopen(filename.c_str(),
"w");
3662 __SS__ <<
"Could not open email file: " << filename << __E__;
3672 fprintf(fp,
"To: %s\n", toList.c_str());
3673 fprintf(fp,
"Subject: %s\n", subject.c_str());
3674 fprintf(fp,
"Content-Type: text/html\n");
3675 fprintf(fp,
"\n<html><pre>%s</pre></html>", message.c_str());
3681 __COUT_WARN__ <<
"Do email was attempted, but no target users had email "
3682 "addresses specified!"
3691 void WebUsers::addSystemMessageToMap(
const std::string& targetUser,
3692 const std::string& fullMessage)
3695 std::lock_guard<std::mutex> lock(systemMessageLock_);
3697 __COUT__ <<
"Before number of users with system messages: " << systemMessages_.size()
3698 <<
", first user has "
3699 << (systemMessages_.size() ? systemMessages_.begin()->second.size() : 0)
3700 <<
" messages." << __E__;
3702 auto it = systemMessages_.find(targetUser);
3705 if(it != systemMessages_.end() && it->second.size() &&
3706 it->second[it->second.size() - 1].message_ == fullMessage)
3709 if(it == systemMessages_.end())
3711 systemMessages_.emplace(
3712 std::pair<std::string , std::vector<SystemMessage>>(
3713 targetUser, std::vector<SystemMessage>({SystemMessage(fullMessage)})));
3714 __COUTT__ << targetUser <<
" Current System Messages count = " << 1 << __E__;
3719 it->second.push_back(SystemMessage(fullMessage));
3720 __COUTT__ << it->first <<
" Current System Messages count = " << it->second.size()
3724 __COUT__ <<
"After number of users with system messages: " << systemMessages_.size()
3725 <<
", first user has "
3726 << (systemMessages_.size() ? systemMessages_.begin()->second.size() : 0)
3727 <<
" messages." << __E__;
3736 std::lock_guard<std::mutex> lock(systemMessageLock_);
3738 __COUTT__ <<
"GetLast number of users with system messages: "
3739 << systemMessages_.size() <<
", first user has "
3740 << (systemMessages_.size() ? systemMessages_.begin()->second.size() : 0)
3741 <<
" messages." << __E__;
3743 auto it = systemMessages_.find(
"*");
3744 if(it == systemMessages_.end() || it->second.size() == 0)
3745 return std::make_pair(
"", 0);
3747 return std::make_pair(it->second.back().message_, it->second.back().creationTime_);
3756 std::string retStr =
"";
3759 std::lock_guard<std::mutex> lock(systemMessageLock_);
3761 for(
auto& userSysMessages : systemMessages_)
3763 for(
auto& userSysMessage : userSysMessages.second)
3765 if(userSysMessage.deliveredRemote_)
3770 retStr += userSysMessages.first;
3771 retStr +=
"|" + std::to_string(userSysMessage.creationTime_);
3772 retStr +=
"|" + userSysMessage.message_;
3773 userSysMessage.deliveredRemote_ =
true;
3788 __COUT_TYPE__(TLVL_DEBUG + 20)
3789 << __COUT_HDR__ <<
"Current System Messages: " << targetUser << __E__;
3790 std::string retStr =
"";
3796 std::lock_guard<std::mutex> lock(systemMessageLock_);
3798 __COUT_TYPE__(TLVL_DEBUG + 20)
3800 <<
"Number of users with system messages: " << systemMessages_.size()
3804 auto it = systemMessages_.find(
"*");
3805 for(uint64_t i = 0; it != systemMessages_.end() && i < it->second.size(); ++i)
3810 sprintf(tmp,
"%lu", it->second[i].creationTime_);
3811 retStr += std::string(tmp) +
"|" + it->second[i].message_;
3817 __COUTVS__(20, targetUser);
3818 it = systemMessages_.find(targetUser);
3821 for(
auto systemMessagePair : systemMessages_)
3822 __COUT_TYPE__(TLVL_DEBUG + 20)
3823 << __COUT_HDR__ << systemMessagePair.first <<
" "
3824 << systemMessagePair.second.size() <<
" "
3825 << (systemMessagePair.second.size()
3826 ? systemMessagePair.second[0].message_
3830 if(it != systemMessages_.end())
3832 __COUT_TYPE__(TLVL_DEBUG + 20)
3833 << __COUT_HDR__ <<
"Message count: " << it->second.size()
3834 <<
", Last Message: "
3835 << (it->second.size() ? it->second.back().message_ :
"") << __E__;
3838 for(uint64_t i = 0; it != systemMessages_.end() && i < it->second.size(); ++i)
3843 sprintf(tmp,
"%lu", it->second[i].creationTime_);
3844 retStr += std::string(tmp) +
"|" + it->second[i].message_;
3846 it->second[i].delivered_ =
true;
3851 __COUT_TYPE__(TLVL_DEBUG + 20) << __COUT_HDR__ <<
"retStr: " << retStr << __E__;
3853 systemMessageCleanup();
3861 void WebUsers::systemMessageCleanup()
3864 std::lock_guard<std::mutex> lock(systemMessageLock_);
3866 __COUTT__ <<
"Before cleanup number of users with system messages: "
3867 << systemMessages_.size() <<
", first user has "
3868 << (systemMessages_.size() ? systemMessages_.begin()->second.size() : 0)
3869 <<
" messages." << __E__;
3870 for(
auto& userMessagesPair : systemMessages_)
3872 for(uint64_t i = 0; i < userMessagesPair.second.size(); ++i)
3873 if((userMessagesPair.first !=
"*" &&
3874 userMessagesPair.second[i].delivered_) ||
3878 __COUTT__ << userMessagesPair.first
3879 <<
" at time: " << userMessagesPair.second[i].creationTime_
3880 <<
" system messages: " << userMessagesPair.second.size()
3884 userMessagesPair.second.erase(userMessagesPair.second.begin() + i);
3888 __COUTT__ <<
"User '" << userMessagesPair.first
3889 <<
"' remaining system messages: " << userMessagesPair.second.size()
3892 __COUTT__ <<
"After cleanup number of users with system messages: "
3893 << systemMessages_.size() <<
", first user has "
3894 << (systemMessages_.size() ? systemMessages_.begin()->second.size() : 0)
3895 <<
" messages." << __E__;
3903 void WebUsers::loadSecuritySelection()
3905 std::string securityFileName = SECURITY_FILE_NAME;
3906 FILE* fp = fopen(securityFileName.c_str(),
"r");
3907 char line[100] =
"";
3909 fgets(line, 100, fp);
3913 while(i < strlen(line) && line[i] >=
'A' && line[i] <=
'z')
3917 if(strcmp(line, SECURITY_TYPE_NONE.c_str()) == 0 ||
3918 strcmp(line, SECURITY_TYPE_DIGEST_ACCESS.c_str()) == 0)
3919 securityType_ = line;
3921 securityType_ = SECURITY_TYPE_DEFAULT;
3923 __COUT__ <<
"The current security type is " << securityType_ << __E__;
3928 if(securityType_ == SECURITY_TYPE_NONE)
3929 CareAboutCookieCodes_ =
false;
3931 CareAboutCookieCodes_ =
true;
3933 __COUT__ <<
"CareAboutCookieCodes_: " << CareAboutCookieCodes_ << __E__;
3935 loadIPAddressSecurity();
3941 void WebUsers::loadIPAddressSecurity()
3943 ipAccessAccept_.clear();
3944 ipAccessReject_.clear();
3945 ipAccessBlacklist_.clear();
3947 FILE* fp = fopen((IP_ACCEPT_FILE).c_str(),
"r");
3953 while(fgets(line, 300, fp))
3957 if(len > 2 && line[len - 1] ==
'\n')
3958 line[len - 1] =
'\0';
3959 ipAccessAccept_.emplace(line);
3966 __COUTV__(ipAccessAccept_.size());
3968 fp = fopen((IP_REJECT_FILE).c_str(),
"r");
3971 while(fgets(line, 300, fp))
3975 if(len > 2 && line[len - 1] ==
'\n')
3976 line[len - 1] =
'\0';
3977 ipAccessReject_.emplace(line);
3984 __COUTV__(ipAccessReject_.size());
3986 fp = fopen((IP_BLACKLIST_FILE).c_str(),
"r");
3989 while(fgets(line, 300, fp))
3993 if(len > 2 && line[len - 1] ==
'\n')
3994 line[len - 1] =
'\0';
3995 ipAccessBlacklist_.emplace(line);
4002 __COUTV__(ipAccessBlacklist_.size());
4006 void WebUsers::NACDisplayThread(
const std::string& nac,
const std::string& user)
4017 std::this_thread::sleep_for(std::chrono::seconds(2));
4019 <<
"\n******************************************************************** "
4022 <<
"\n******************************************************************** "
4024 __COUT__ <<
"\n\nNew account code = " << nac <<
" for user: " << user <<
"\n"
4027 <<
"\n******************************************************************** "
4030 <<
"\n******************************************************************** "
4036 void WebUsers::deleteUserData()
4038 __COUT__ <<
"$$$$$$$$$$$$$$ Deleting ALL service user data... $$$$$$$$$$$$" << __E__;
4042 (
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + HASHES_DB_PATH +
"/*").c_str());
4044 (
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH +
"/*").c_str());
4046 (
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_LOGIN_HISTORY_PATH +
"/*")
4049 (
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_PREFERENCES_PATH +
"/*")
4051 std::system((
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH).c_str());
4053 std::string serviceDataPath = __ENV__(
"SERVICE_DATA_PATH");
4055 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/MacroData/").c_str());
4056 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/MacroHistory/").c_str());
4057 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/MacroExport/").c_str());
4061 (
"rm -rf " + std::string(serviceDataPath) +
"/ConsolePreferences/").c_str());
4064 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/CodeEditorData/").c_str());
4067 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/OtsWizardData/").c_str());
4070 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/ProgressBarData/").c_str());
4073 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/RunNumber/").c_str());
4074 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/RunControlData/").c_str());
4077 std::system((
"rm -rf " + std::string(serviceDataPath) +
"/VisualizerData/").c_str());
4084 std::system((
"rm -rf " + std::string(__ENV__(
"LOGBOOK_DATA_PATH")) +
"/").c_str());
4086 __COUT__ <<
"$$$$$$$$$$$$$$ Successfully deleted ALL service user data $$$$$$$$$$$$"
void copyDataChildren(HttpXmlDocument &document)
void removeDataElement(unsigned int dataChildIndex=0)
default to first child
bool loadXmlDocument(const std::string &filePath)
unsigned int getChildrenCount(xercesc::DOMElement *parent=0)
void addSystemMessage(const std::string &targetUsersCSV, const std::string &message)
const std::string & getSecurity(void)
WebUsers::getSecurity.
std::string getGenericPreference(uint64_t uid, const std::string &preferenceName, HttpXmlDocument *xmldoc=0) const
bool setUserWithLock(uint64_t actingUid, bool lock, const std::string &username)
static bool checkRequestAccess(cgicc::Cgicc &cgi, std::ostringstream *out, HttpXmlDocument *xmldoc, WebUsers::RequestUserInfo &userInfo, bool isWizardMode=false, const std::string &wizardModeSequence="")
static void silenceAllUserTooltips(const std::string &username)
size_t getActiveUserCount(void)
std::map< std::string, WebUsers::permissionLevel_t > getPermissionsForUser(uint64_t uid)
from Gateway, use public version which considers remote users
uint64_t attemptActiveSession(const std::string &uuid, std::string &jumbledUser, const std::string &jumbledPw, std::string &newAccountCode, const std::string &ip)
void setGenericPreference(uint64_t uid, const std::string &preferenceName, const std::string &preferenceValue)
std::string getAllSystemMessages(void)
void cleanupExpiredEntries(std::vector< std::string > *loggedOutUsernames=0)
void changeSettingsForUser(uint64_t uid, const std::string &bgcolor, const std::string &dbcolor, const std::string &wincolor, const std::string &layout, const std::string &syslayout)
WebUsers::changeSettingsForUser.
uint64_t isCookieCodeActiveForLogin(const std::string &uuid, std::string &cookieCode, std::string &username)
std::string createNewLoginSession(const std::string &uuid, const std::string &ip)
std::string getActiveUsersString(void)
void createNewAccount(const std::string &username, const std::string &displayName, const std::string &email)
void modifyAccountSettings(uint64_t actingUid, uint8_t cmd_type, const std::string &username, const std::string &displayname, const std::string &email, const std::string &permissions)
WebUsers::modifyAccountSettings.
int remoteLoginVerificationPort_
Port of remote Gateway to be used for login verification.
bool isUsernameActive(const std::string &username) const
bool isUserIdActive(uint64_t uid) const
void saveActiveSessions(void)
static std::atomic< bool > remoteLoginVerificationEnabled_
true if this supervisor is under control of a remote supervisor
uint64_t getAdminUserID(void)
@ SYS_CLEANUP_WILDCARD_TIME
300 seconds
std::string getUsersUsername(uint64_t uid)
from Gateway, use public version which considers remote users
static void initializeRequestUserInfo(cgicc::Cgicc &cgi, WebUsers::RequestUserInfo &userInfo)
used by gateway and other supervisors to verify requests consistently
bool checkIpAccess(const std::string &ip)
bool xmlRequestOnGateway(cgicc::Cgicc &cgi, std::ostringstream *out, HttpXmlDocument *xmldoc, WebUsers::RequestUserInfo &userInfo)
uint64_t cookieCodeLogout(const std::string &cookieCode, bool logoutOtherUserSessions, uint64_t *uid=0, const std::string &ip="0")
std::string getSystemMessage(const std::string &targetUser)
uint64_t getActiveSessionCountForUser(uint64_t uid)
static void resetAllUserTooltips(const std::string &userNeedle="*")
WebUsers::resetAllUserTooltips.
static void tooltipSetNeverShowForUsername(const std::string &username, HttpXmlDocument *xmldoc, const std::string &srcFile, const std::string &srcFunc, const std::string &srcId, bool doNeverShow, bool temporarySilence)
void cleanupExpiredRemoteEntries(void)
std::string getUsersDisplayName(uint64_t uid)
from Gateway, use public version which considers remote users
void loadActiveSessions(void)
std::pair< std::string, time_t > getLastSystemMessage(void)
uint64_t attemptActiveSessionWithCert(const std::string &uuid, std::string &jumbledEmail, std::string &cookieCode, std::string &username, const std::string &ip)
static const std::string OTS_OWNER
defined by environment variable, e.g. experiment name
static void tooltipCheckForUsername(const std::string &username, HttpXmlDocument *xmldoc, const std::string &srcFile, const std::string &srcFunc, const std::string &srcId)
std::string remoteGatewaySelfName_
IP of remote Gateway to be used for login verification.
bool cookieCodeIsActiveForRequest(std::string &cookieCode, std::map< std::string, WebUsers::permissionLevel_t > *userPermissions=0, uint64_t *uid=0, const std::string &ip="0", bool refresh=true, bool doNotGoRemote=false, std::string *userWithLock=0, uint64_t *userSessionIndex=0)
void insertSettingsForUser(uint64_t uid, HttpXmlDocument *xmldoc, bool includeAccounts=false)
@ PERMISSION_LEVEL_ADMIN
max permission level!
xercesc::DOMElement * addTextElementToParent(const std::string &childName, const std::string &childText, xercesc::DOMElement *parent)
void saveXmlDocument(const std::string &filePath)
void INIT_MF(const char *name)
static std::string getTimestampString(const std::string &linuxTimeInSeconds)
static void getVectorFromString(const std::string &inputString, std::vector< std::string > &listToReturn, const std::set< char > &delimiter={',', '|', '&'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'}, std::vector< char > *listOfDelimiters=0, bool decodeURIComponents=false)
static std::string exec(const char *cmd)
static std::string setToString(const std::set< T > &setToReturn, const std::string &delimeter=", ")
setToString ~
static std::string vectorToString(const std::vector< T > &setToReturn, const std::string &delimeter=", ")
vectorToString ~
static std::string mapToString(const std::map< std::string, T > &mapToReturn, const std::string &primaryDelimeter=", ", const std::string &secondaryDelimeter=": ")
static void getMapFromString(const std::string &inputString, std::map< S, T > &mapToReturn, const std::set< char > &pairPairDelimiter={',', '|', '&'}, const std::set< char > &nameValueDelimiter={'=', ':'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'})
getMapFromString ~
static bool wildCardMatch(const std::string &needle, const std::string &haystack, unsigned int *priorityIndex=0)
static std::string decodeURIComponent(const std::string &data)
static std::string stackTrace(void)
uint64_t userSessionIndex_
can use session index to track a user's session on multiple devices/browsers
const WebUsers::permissionLevel_t & getGroupPermissionLevel()
bool setGroupPermissionLevels(const std::string &groupPermissionLevelsString)
end setGroupPermissionLevels()