1 #include "otsdaq-core/WebUsersUtilities/WebUsers.h"
2 #include "otsdaq-core/MessageFacility/MessageFacility.h"
3 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
4 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
9 #include <openssl/sha.h>
21 #define WEB_LOGIN_BKUP_DB_PATH "bkup/"
23 #define SECURITY_FILE_NAME std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData/security.dat"
26 #define HASHES_DB_FILE HASHES_DB_PATH + "/hashes.xml"
27 #define USERS_DB_FILE USERS_DB_PATH + "/users.xml"
28 #define USERS_GLOBAL_HISTORY_FILE "__global"
29 #define USERS_LOGIN_HISTORY_FILETYPE "hist"
30 #define USERS_PREFERENCES_FILETYPE "pref"
31 #define SYSTEM_PREFERENCES_PREFIX "system.preset"
32 #define USER_WITH_LOCK_FILE WEB_LOGIN_DB_PATH + "/user_with_lock.dat"
34 #define HASHES_DB_GLOBAL_STRING "hashData"
35 #define HASHES_DB_ENTRY_STRING "hashEntry"
36 #define USERS_DB_GLOBAL_STRING "userData"
37 #define USERS_DB_ENTRY_STRING "userEntry"
38 #define USERS_DB_NEXT_UID_STRING "nextUserId"
41 #define PREF_XML_BGCOLOR_FIELD "pref_bgcolor" // -background color
42 #define PREF_XML_DBCOLOR_FIELD "pref_dbcolor" // -dashboard color
43 #define PREF_XML_WINCOLOR_FIELD "pref_wincolor" // -window color
44 #define PREF_XML_LAYOUT_FIELD "pref_layout" // -3 defaults window layouts(and current)
45 #define PREF_XML_SYSLAYOUT_FIELD "pref_syslayout" // -2 defaults window layouts
46 #define PREF_XML_PERMISSIONS_FIELD "desktop_user_permissions" // 0-255 permissions valud (255 is admin super user)
47 #define PREF_XML_USERLOCK_FIELD "username_with_lock" // user with lock (to lockout others)
48 #define PREF_XML_USERNAME_FIELD "pref_username" // user with lock (to lockout others)
50 #define PREF_XML_BGCOLOR_DEFAULT "rgb(15,34,105)" // -background color
51 #define PREF_XML_DBCOLOR_DEFAULT "rgb(60,64,75)" // -dashboard color
52 #define PREF_XML_WINCOLOR_DEFAULT "rgba(196,229,255,0.9)" // -window color
53 #define PREF_XML_LAYOUT_DEFAULT "0;0;0;0" // 3 default window layouts(and current)
54 #define PREF_XML_SYSLAYOUT_DEFAULT "0;0" // 2 system default window layouts
56 #define PREF_XML_ACCOUNTS_FIELD "users_accounts" // user accounts field for super users
57 #define PREF_XML_LOGIN_HISTORY_FIELD "login_entry" // login history field for user login history data
59 const std::string WebUsers::DEFAULT_ADMIN_USERNAME =
"admin";
60 const std::string WebUsers::DEFAULT_ADMIN_DISPLAY_NAME =
"Administrator";
63 #define __MF_SUBJECT__ "WebUsers"
71 usersUsernameWithLock_ =
"";
74 HashesDatabaseEntryFields.push_back(
"hash");
75 HashesDatabaseEntryFields.push_back(
"lastAccessTime");
77 UsersDatabaseEntryFields.push_back(
"username");
78 UsersDatabaseEntryFields.push_back(
"displayName");
79 UsersDatabaseEntryFields.push_back(
"salt");
80 UsersDatabaseEntryFields.push_back(
"uid");
81 UsersDatabaseEntryFields.push_back(
"permissions");
82 UsersDatabaseEntryFields.push_back(
"lastLoginAttemptTime");
83 UsersDatabaseEntryFields.push_back(
"accountCreatedTime");
84 UsersDatabaseEntryFields.push_back(
"loginFailureCount");
85 UsersDatabaseEntryFields.push_back(
"lastModifiedTime");
86 UsersDatabaseEntryFields.push_back(
"lastModifierUsername");
89 mkdir(((std::string)WEB_LOGIN_DB_PATH).c_str(), 0755);
90 mkdir(((std::string)WEB_LOGIN_DB_PATH + HASHES_DB_PATH).c_str(), 0755);
91 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH).c_str(), 0755);
92 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_LOGIN_HISTORY_PATH).c_str(), 0755);
93 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_PREFERENCES_PATH).c_str(), 0755);
97 __MOUT__ <<
"FATAL USER DATABASE ERROR - failed to load!!!" << std::endl;
99 loadSecuritySelection();
104 std::string user = DEFAULT_ADMIN_USERNAME;
105 if((i = searchUsersDatabaseForUsername(user)) == NOT_FOUND_IN_DATABASE)
107 __MOUT__ <<
"user: " << user <<
" is not found" << std::endl;
111 else if(UsersSaltVector[i] ==
"" &&
112 securityType_ == SECURITY_TYPE_DIGEST_ACCESS)
114 char charTimeStr[10];
115 sprintf(charTimeStr,
"%d",
int(UsersAccountCreatedTimeVector[i] & 0xffff));
116 std::string tmpTimeStr = charTimeStr;
121 std::thread([](std::string nac, std::string user){ WebUsers::NACDisplayThread(nac,user); },
122 tmpTimeStr,user).detach();
131 __MOUT__ <<
"Done with Web Users initialization!" << std::endl;
321 bool WebUsers::loadDatabases()
325 unsigned int LINE_LEN = 1000;
327 unsigned int i,si,c,len,f;
338 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_FILE;
339 __MOUT__ << fn << std::endl;
340 fp = fopen(fn.c_str(),
"r");
343 mkdir(((std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_PATH).c_str(), 0755);
344 __MOUT__ << ((std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_PATH).c_str() << std::endl;
345 fp = fopen(fn.c_str(),"w");
346 if(!fp) return false;
347 __MOUT__ << "Hashes database created: " << fn << std::endl;
349 saveToDatabase(fp,HASHES_DB_GLOBAL_STRING,"",DB_SAVE_OPEN);
350 saveToDatabase(fp,HASHES_DB_GLOBAL_STRING,"",DB_SAVE_CLOSE);
357 while(fgets(line,LINE_LEN,fp))
359 if(strlen(line) < SHA512_DIGEST_LENGTH)
continue;
367 if(c != 2 && c != 4)
continue;
370 while(i<len && line[i] !=
'<') ++i;
379 HashesVector.push_back(&line[si]);
382 sscanf(&line[si],
"%lu",&tmpInt64);
383 HashesAccessTimeVector.push_back(tmpInt64);
387 __MOUT__ << HashesAccessTimeVector.size() <<
" Hashes found." << std::endl;
401 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_FILE;
402 fp = fopen(fn.c_str(),
"r");
405 mkdir(((std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_PATH).c_str(), 0755);
406 __MOUT__ << ((std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_PATH).c_str() << std::endl;
407 fp = fopen(fn.c_str(),"w");
408 if(!fp) return false;
409 __MOUT__ << "Users database created: " << fn << std::endl;
411 saveToDatabase(fp,USERS_DB_GLOBAL_STRING,"",DB_SAVE_OPEN);
413 sprintf(nidStr,"%lu",usersNextUserId_);
414 saveToDatabase(fp,USERS_DB_NEXT_UID_STRING,nidStr,DB_SAVE_OPEN_AND_CLOSE);
415 saveToDatabase(fp,USERS_DB_GLOBAL_STRING,"",DB_SAVE_CLOSE);
418 createNewAccount(DEFAULT_ADMIN_USERNAME,DEFAULT_ADMIN_DISPLAY_NAME);
425 char salt[] =
"nextUserId";
426 while(fgets(line,LINE_LEN,fp))
428 if(strlen(line) < strlen(salt)*2)
continue;
430 for(i=0;i<strlen(salt);++i)
431 if(line[i+1] != salt[i])
break;
433 if(i == strlen(salt))
437 while(i < LINE_LEN && line[i] !=
'\0' && line[i] !=
'<') ++i;
439 sscanf(&line[si],
"%lu",&usersNextUserId_);
444 __MOUT__ <<
"Found Users database next user Id: " << usersNextUserId_ << std::endl;
447 while(fgets(line,LINE_LEN,fp))
449 if(strlen(line) < 30)
continue;
455 __MOUT__ <<
"Line buffer too small: " << len << std::endl;
465 if(c == 0 || c%2 == 1)
continue;
468 while(i<len && line[i] !=
'<') ++i;
477 UsersUsernameVector.push_back(&line[si]);
479 UsersDisplayNameVector.push_back(&line[si]);
481 UsersSaltVector.push_back(&line[si]);
484 sscanf(&line[si],
"%lu",&tmpInt64);
485 UsersUserIdVector.push_back(tmpInt64);
489 sscanf(&line[si],
"%lu",&tmpInt64);
490 UsersPermissionsVector.push_back(tmpInt64);
494 sscanf(&line[si],
"%lu",&tmpInt64);
495 UsersLastLoginAttemptVector.push_back(tmpInt64);
499 sscanf(&line[si],
"%lu",&tmpInt64);
500 UsersAccountCreatedTimeVector.push_back(tmpInt64);
504 sscanf(&line[si],
"%lu",&tmpInt64);
505 UsersLoginFailureCountVector.push_back(tmpInt64);
509 sscanf(&line[si],
"%lu",&tmpInt64);
510 UsersLastModifiedTimeVector.push_back(tmpInt64);
513 UsersLastModifierUsernameVector.push_back(&line[si]);
518 if(f && f != UsersDatabaseEntryFields.size()-1)
522 __MOUT__ <<
"FATAL ERROR - invalid database found with field number " << f << std::endl;
528 __MOUT__ <<
"Update database to current version - adding fields: " <<
529 (UsersDatabaseEntryFields.size()-1-f) << std::endl;
531 UsersLastModifiedTimeVector.push_back(0);
532 UsersLastModifierUsernameVector.push_back(
"");
538 __MOUT__ << UsersLastModifiedTimeVector.size() <<
" Users found." << std::endl;
544 void WebUsers::saveToDatabase (FILE * fp,std::string field, std::string value, uint8_t type,
bool addNewLine)
548 std::string newLine = addNewLine?
"\n":
"";
550 if(type == DB_SAVE_OPEN_AND_CLOSE)
551 fprintf(fp,
"<%s>%s</%s>%s",field.c_str(),value.c_str(),field.c_str(),newLine.c_str());
552 else if(type == DB_SAVE_OPEN)
553 fprintf(fp,
"<%s>%s%s",field.c_str(),value.c_str(),newLine.c_str());
554 else if(type == DB_SAVE_CLOSE)
555 fprintf(fp,
"</%s>%s",field.c_str(),newLine.c_str());
566 bool WebUsers::saveDatabaseToFile (uint8_t db)
568 __MOUT__ <<
"Save Database: " << (int)db << std::endl;
570 std::string fn = (std::string)WEB_LOGIN_DB_PATH +
571 ((db==DB_USERS)?(std::string)USERS_DB_FILE:(std::string)HASHES_DB_FILE);
573 __MOUT__ <<
"Save Database Filename: " << fn << std::endl;
578 sprintf(dayAppend,
".%lu.bkup",time(0)/(3600*24));
579 std::string bkup_fn = (std::string)WEB_LOGIN_DB_PATH +
580 (std::string)WEB_LOGIN_BKUP_DB_PATH +
581 ((db==DB_USERS)?(std::string)USERS_DB_FILE:(std::
string)HASHES_DB_FILE) +
582 (std::
string)dayAppend;
584 __MOUT__ << "Backup file: " << bkup_fn << std::endl;
586 std::
string shell_command = "mv " + fn + " " + bkup_fn;
587 system(shell_command.c_str());
590 FILE *fp = fopen(fn.c_str(),"wb");
591 if(!fp) return false;
597 saveToDatabase(fp,USERS_DB_GLOBAL_STRING,
"",DB_SAVE_OPEN);
599 sprintf(fldStr,
"%lu",usersNextUserId_);
600 saveToDatabase(fp,USERS_DB_NEXT_UID_STRING,fldStr,DB_SAVE_OPEN_AND_CLOSE);
602 __MOUT__ <<
"Saving " << UsersUsernameVector.size() <<
" Users." << std::endl;
604 for(uint64_t i=0;i<UsersUsernameVector.size();++i)
608 saveToDatabase(fp,USERS_DB_ENTRY_STRING,
"",DB_SAVE_OPEN,
false);
610 for(
unsigned int f=0;f<UsersDatabaseEntryFields.size();++f)
614 saveToDatabase(fp,UsersDatabaseEntryFields[f],UsersUsernameVector[i],DB_SAVE_OPEN_AND_CLOSE,
false);
616 saveToDatabase(fp,UsersDatabaseEntryFields[f],UsersDisplayNameVector[i],DB_SAVE_OPEN_AND_CLOSE,
false);
618 saveToDatabase(fp,UsersDatabaseEntryFields[f],UsersSaltVector[i],DB_SAVE_OPEN_AND_CLOSE,
false);
621 sprintf(fldStr,
"%lu",UsersUserIdVector[i]);
622 saveToDatabase(fp,UsersDatabaseEntryFields[f],fldStr,DB_SAVE_OPEN_AND_CLOSE,
false);
626 sprintf(fldStr,
"%d",UsersPermissionsVector[i]);
627 saveToDatabase(fp,UsersDatabaseEntryFields[f],fldStr,DB_SAVE_OPEN_AND_CLOSE,
false);
631 sprintf(fldStr,
"%lu",UsersLastLoginAttemptVector[i]);
632 saveToDatabase(fp,UsersDatabaseEntryFields[f],fldStr,DB_SAVE_OPEN_AND_CLOSE,
false);
636 sprintf(fldStr,
"%lu",UsersAccountCreatedTimeVector[i]);
637 saveToDatabase(fp,UsersDatabaseEntryFields[f],fldStr,DB_SAVE_OPEN_AND_CLOSE,
false);
641 sprintf(fldStr,
"%d",UsersLoginFailureCountVector[i]);
642 saveToDatabase(fp,UsersDatabaseEntryFields[f],fldStr,DB_SAVE_OPEN_AND_CLOSE,
false);
646 sprintf(fldStr,
"%lu",UsersLastModifiedTimeVector[i]);
647 saveToDatabase(fp,UsersDatabaseEntryFields[f],fldStr,DB_SAVE_OPEN_AND_CLOSE,
false);
650 saveToDatabase(fp,UsersDatabaseEntryFields[f],UsersLastModifierUsernameVector[i],DB_SAVE_OPEN_AND_CLOSE,
false);
653 saveToDatabase(fp,USERS_DB_ENTRY_STRING,
"",DB_SAVE_CLOSE);
656 saveToDatabase(fp,USERS_DB_GLOBAL_STRING,
"",DB_SAVE_CLOSE);
661 saveToDatabase(fp,HASHES_DB_GLOBAL_STRING,
"",DB_SAVE_OPEN);
663 __MOUT__ <<
"Saving " << HashesVector.size() <<
" Hashes." << std::endl;
664 for(uint64_t i=0;i<HashesVector.size();++i)
666 __MOUT__ <<
"Saving " << HashesVector[i] <<
" Hashes." << std::endl;
667 saveToDatabase(fp,HASHES_DB_ENTRY_STRING,
"",DB_SAVE_OPEN,
false);
668 for(
unsigned int f=0;f<HashesDatabaseEntryFields.size();++f)
671 saveToDatabase(fp,HashesDatabaseEntryFields[f],HashesVector[i],DB_SAVE_OPEN_AND_CLOSE,
false);
674 sprintf(fldStr,
"%lu",HashesAccessTimeVector[i]);
675 saveToDatabase(fp,HashesDatabaseEntryFields[f],fldStr,DB_SAVE_OPEN_AND_CLOSE,
false);
678 saveToDatabase(fp,HASHES_DB_ENTRY_STRING,
"",DB_SAVE_CLOSE);
681 saveToDatabase(fp,HASHES_DB_GLOBAL_STRING,
"",DB_SAVE_CLOSE);
696 bool WebUsers::createNewAccount(std::string Username, std::string DisplayName)
698 __MOUT__ <<
"Creating account: " << Username << std::endl;
701 if((i = searchUsersDatabaseForUsername(Username)) != NOT_FOUND_IN_DATABASE)
703 __MOUT__ <<
"Username: " << Username <<
" already exists" << std::endl;
708 UsersUsernameVector.push_back(Username);
709 UsersDisplayNameVector.push_back(DisplayName);
710 UsersSaltVector.push_back(
"");
711 UsersPermissionsVector.push_back(UsersPermissionsVector.size()?0:-1);
712 UsersUserIdVector.push_back(usersNextUserId_++);
713 if(usersNextUserId_ == (uint64_t)-1)
715 __MOUT__ <<
"usersNextUserId_ wrap around!! Too many users??? Notify Admins." << std::endl;
716 usersNextUserId_ = 1;
718 UsersLastLoginAttemptVector.push_back(0);
719 UsersLoginFailureCountVector.push_back(0);
720 UsersAccountCreatedTimeVector.push_back(time(0));
721 UsersLastModifiedTimeVector.push_back(0);
722 UsersLastModifierUsernameVector.push_back(
"");
724 return saveDatabaseToFile(DB_USERS);
733 bool WebUsers::deleteAccount(std::string username, std::string displayName)
735 uint64_t i = searchUsersDatabaseForUsername(username);
736 if(i == NOT_FOUND_IN_DATABASE)
return false;
737 if(UsersDisplayNameVector[i] != displayName)
return false;
741 UsersUsernameVector.erase(UsersUsernameVector.begin()+i);
742 UsersDisplayNameVector.erase(UsersDisplayNameVector.begin()+i);
743 UsersSaltVector.erase(UsersSaltVector.begin()+i);
744 UsersPermissionsVector.erase(UsersPermissionsVector.begin()+i);
745 UsersUserIdVector.erase(UsersUserIdVector.begin()+i);
746 UsersLastLoginAttemptVector.erase(UsersLastLoginAttemptVector.begin()+i);
747 UsersAccountCreatedTimeVector.erase(UsersAccountCreatedTimeVector.begin()+i);
748 UsersLoginFailureCountVector.erase(UsersLoginFailureCountVector.begin()+i);
749 UsersLastModifierUsernameVector.erase(UsersLastModifierUsernameVector.begin()+i);
750 UsersLastModifiedTimeVector.erase(UsersLastModifiedTimeVector.begin()+i);
753 return saveDatabaseToFile(DB_USERS);
757 unsigned int WebUsers::hexByteStrToInt(
const char *h)
760 char hs[3] = {h[0],h[1],
'\0'};
766 void WebUsers::intToHexStr(
unsigned char i,
char *h)
768 sprintf(h,
"%2.2X",i);
780 uint64_t WebUsers::attemptActiveSession(std::string uuid, std::string &jumbledUser,
781 std::string jumbledPw, std::string &newAccountCode)
783 cleanupExpiredEntries();
785 if(!CareAboutCookieCodes_)
787 uint64_t uid = getAdminUserID();
788 jumbledUser = getUsersDisplayName(uid);
789 newAccountCode = genCookieCode();
793 if(securityType_ == SECURITY_TYPE_KERBEROS)
799 if((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
801 __MOUT__ <<
"uuid: " << uuid <<
" is not found" << std::endl;
802 newAccountCode =
"1";
803 return NOT_FOUND_IN_DATABASE;
805 ++LoginSessionAttemptsVector[i];
807 std::string user = dejumble(jumbledUser,LoginSessionIdVector[i]);
808 __MOUT__ <<
"DejumbledUser = " << user << std::endl;
809 std::string pw = dejumble(jumbledPw,LoginSessionIdVector[i]);
812 if((i = searchUsersDatabaseForUsername(user)) == NOT_FOUND_IN_DATABASE)
814 __MOUT__ <<
"user: " << user <<
" is not found" << std::endl;
815 return NOT_FOUND_IN_DATABASE;
818 UsersLastLoginAttemptVector[i] = time(0);
819 if(!UsersPermissionsVector[i])
821 __MOUT__ <<
"user: " << user <<
" account INACTIVE (could be due to failed logins)" << std::endl;
822 return NOT_FOUND_IN_DATABASE;
825 if(UsersSaltVector[i] ==
"")
827 __MOUT__ <<
"First login attempt for user: " << user << std::endl;
829 char charTimeStr[10];
830 sprintf(charTimeStr,
"%d",
int(UsersAccountCreatedTimeVector[i] & 0xffff));
831 std::string tmpTimeStr = charTimeStr;
832 if(newAccountCode != tmpTimeStr)
834 __MOUT__ <<
"New account code did not match: " << tmpTimeStr <<
" != " << newAccountCode << std::endl;
835 saveDatabaseToFile(DB_USERS);
836 return NOT_FOUND_IN_DATABASE;
842 while(!addToHashesDatabase(sha512(user,pw,UsersSaltVector[i])))
846 UsersSaltVector[i] =
"";
850 __MOUT__ <<
"\tHash added: " << HashesVector[HashesVector.size()-1] << std::endl;
854 std::string salt = UsersSaltVector[i];
855 __MOUT__ << salt<<
" " << i << std::endl;
856 if(searchHashesDatabaseForHash(sha512(user,pw,salt)) == NOT_FOUND_IN_DATABASE)
858 __MOUT__ <<
"not found?" << std::endl;
859 ++UsersLoginFailureCountVector[i];
860 if(UsersLoginFailureCountVector[i] >= USERS_MAX_LOGIN_FAILURES)
861 UsersPermissionsVector[i] = 0;
863 __MOUT__ <<
"\tUser/pw for user: " << user <<
" was not correct Failed Attempt #" << (int)(UsersLoginFailureCountVector[i]) << std::endl;
864 if(!UsersPermissionsVector[i])
865 __MOUT__ <<
"Account is locked!" << std::endl;
867 saveDatabaseToFile(DB_USERS);
868 return NOT_FOUND_IN_DATABASE;
872 __MOUT__ <<
"Login successful for: " << user << std::endl;
874 UsersLoginFailureCountVector[i] = 0;
879 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_LOGIN_HISTORY_PATH + (h?USERS_GLOBAL_HISTORY_FILE:UsersUsernameVector[i])
880 +
"." + (std::string)USERS_LOGIN_HISTORY_FILETYPE;
884 if(histXml.loadXmlDocument(fn))
886 while(histXml.getChildrenCount() + 1 > (h?USERS_GLOBAL_HISTORY_SIZE:USERS_LOGIN_HISTORY_SIZE))
887 histXml.removeDataElement();
890 __MOUT__ <<
"No previous login history found." << std::endl;
895 sprintf(entryStr,
"Time=%lu Username=%s Permissions=%d UID=%lu",
896 time(0),UsersUsernameVector[i].c_str(),UsersPermissionsVector[i],UsersUserIdVector[i]);
898 sprintf(entryStr,
"Time=%lu DisplayName=%s Permissions=%d UID=%lu",
899 time(0),UsersDisplayNameVector[i].c_str(),UsersPermissionsVector[i],UsersUserIdVector[i]);
900 histXml.addTextElementToData(PREF_XML_LOGIN_HISTORY_FIELD,entryStr);
903 histXml.saveXmlDocument(fn);
907 saveDatabaseToFile(DB_USERS);
908 jumbledUser = UsersDisplayNameVector[i];
909 newAccountCode = createNewActiveSession(UsersUserIdVector[i]);
910 return UsersUserIdVector[i];
916 uint64_t WebUsers::searchActiveSessionDatabaseForCookie(std::string cookieCode)
const
919 for(;i<ActiveSessionCookieCodeVector.size();++i)
920 if(ActiveSessionCookieCodeVector[i] == cookieCode)
break;
921 return (i == ActiveSessionCookieCodeVector.size())?NOT_FOUND_IN_DATABASE:i;
928 bool WebUsers::isUsernameActive (std::string username)
const
931 if((u = searchUsersDatabaseForUsername(username)) == NOT_FOUND_IN_DATABASE)
return false;
932 return isUserIdActive(UsersUserIdVector[u]);
939 bool WebUsers::isUserIdActive(uint64_t uid)
const
942 for(;i<ActiveSessionUserIdVector.size();++i)
943 if(ActiveSessionUserIdVector[i] == uid)
return true;
950 uint64_t WebUsers::searchUsersDatabaseForUsername(std::string username)
const
953 for(;i<UsersUsernameVector.size();++i)
954 if(UsersUsernameVector[i] == username)
break;
955 return (i == UsersUsernameVector.size())?NOT_FOUND_IN_DATABASE:i;
961 uint64_t WebUsers::searchUsersDatabaseForUserId(uint64_t uid)
const
964 for(;i<UsersUserIdVector.size();++i)
965 if(UsersUserIdVector[i] == uid)
break;
966 return (i == UsersUserIdVector.size())?NOT_FOUND_IN_DATABASE:i;
972 uint64_t WebUsers::searchLoginSessionDatabaseForUUID(std::string uuid)
const
975 for(;i<LoginSessionUUIDVector.size();++i)
976 if(LoginSessionUUIDVector[i] == uuid)
break;
977 return (i == LoginSessionUUIDVector.size())?NOT_FOUND_IN_DATABASE:i;
983 uint64_t WebUsers::searchHashesDatabaseForHash(std::string hash)
986 __MOUT__ << i <<
" " << HashesVector.size()<<
" " << HashesAccessTimeVector.size() <<
988 for(;i<HashesVector.size();++i)
989 if(HashesVector[i] == hash)
break;
991 __MOUT__ << HashesVector[i] <<
" ?????? " << std::endl;
992 __MOUT__ << i << std::endl;
993 if(i < HashesAccessTimeVector.size())
994 HashesAccessTimeVector.push_back((time(0) + (rand()%2?1:-1)*(rand() % 30*24*60*60)) & 0x0FFFFFFFFFE000000 );
996 __MOUT__ << i << std::endl;
997 return (i == HashesVector.size())?NOT_FOUND_IN_DATABASE:i;
1004 bool WebUsers::addToHashesDatabase(std::string hash)
1006 if(searchHashesDatabaseForHash(hash) != NOT_FOUND_IN_DATABASE)
1008 __MOUT__ <<
"Hash collision: " << hash << std::endl;
1011 HashesVector.push_back(hash);
1012 HashesAccessTimeVector.push_back((time(0) + (rand()%2?1:-1)*(rand() % 30*24*60*60)) & 0x0FFFFFFFFFE000000 );
1014 return saveDatabaseToFile(DB_HASHES);
1019 std::string WebUsers::genCookieCode()
1022 std::string cc =
"";
1023 for(uint32_t i=0;i<COOKIE_CODE_LENGTH/2;++i)
1025 intToHexStr(rand(),hexStr);
1033 void WebUsers::removeLoginSessionEntry(
unsigned int i)
1035 LoginSessionIdVector.erase (LoginSessionIdVector.begin()+i);
1036 LoginSessionUUIDVector.erase (LoginSessionUUIDVector.begin()+i);
1037 LoginSessionIpVector.erase (LoginSessionIpVector.begin()+i);
1038 LoginSessionStartTimeVector.erase (LoginSessionStartTimeVector.begin()+i);
1039 LoginSessionAttemptsVector.erase (LoginSessionAttemptsVector.begin()+i);
1046 std::string WebUsers::createNewActiveSession(uint64_t uid, std::string ip, uint64_t asIndex)
1048 ActiveSessionCookieCodeVector.push_back (genCookieCode());
1049 ActiveSessionIpVector.push_back (ip);
1050 ActiveSessionUserIdVector.push_back (uid);
1051 ActiveSessionStartTimeVector.push_back (time(0));
1054 ActiveSessionIndex.push_back (asIndex);
1059 for(uint64_t j=0;j<ActiveSessionIndex.size();++j)
1060 if(ActiveSessionUserIdVector[j] == uid && max < ActiveSessionIndex[j])
1061 max = ActiveSessionIndex[j];
1063 ActiveSessionIndex.push_back (max?max+1:1);
1066 return ActiveSessionCookieCodeVector[ActiveSessionCookieCodeVector.size()-1];
1071 void WebUsers::removeActiveSessionEntry(
unsigned int i)
1073 ActiveSessionCookieCodeVector.erase (ActiveSessionCookieCodeVector.begin()+i);
1074 ActiveSessionIpVector.erase (ActiveSessionIpVector.begin()+i);
1075 ActiveSessionUserIdVector.erase (ActiveSessionUserIdVector.begin()+i);
1076 ActiveSessionStartTimeVector.erase (ActiveSessionStartTimeVector.begin()+i);
1077 ActiveSessionIndex.erase (ActiveSessionIndex.begin()+i);
1103 std::string WebUsers::refreshCookieCode(
unsigned int i,
bool enableRefresh)
1106 for(uint64_t j=ActiveSessionUserIdVector.size()-1;j!=(uint64_t)-1;--j)
1107 if (ActiveSessionUserIdVector[j] == ActiveSessionUserIdVector[i] &&
1108 ActiveSessionIndex[j] == ActiveSessionIndex[i])
1113 if(enableRefresh && (time(0) - ActiveSessionStartTimeVector[j] > ACTIVE_SESSION_EXPIRATION_TIME/2))
1116 ActiveSessionStartTimeVector[j] = time(0) - ACTIVE_SESSION_EXPIRATION_TIME +
1117 ACTIVE_SESSION_COOKIE_OVERLAP_TIME;
1120 return createNewActiveSession(ActiveSessionUserIdVector[i],ActiveSessionIpVector[i],ActiveSessionIndex[i]);
1123 return ActiveSessionCookieCodeVector[j];
1134 uint64_t WebUsers::isCookieCodeActiveForLogin(std::string uuid,std::string &cookieCode,std::string &username)
1138 if(!CareAboutCookieCodes_)
1139 return getAdminUserID();
1144 if(!ActiveSessionStartTimeVector.size())
return NOT_FOUND_IN_DATABASE;
1149 if((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
1151 __MOUT__ <<
"uuid not found: " << uuid << std::endl;
1152 return NOT_FOUND_IN_DATABASE;
1155 username = dejumble(username,LoginSessionIdVector[i]);
1158 if((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
1160 __MOUT__ <<
"Cookie code not found" << std::endl;
1161 return NOT_FOUND_IN_DATABASE;
1165 if((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
1167 __MOUT__ <<
"User ID not found" << std::endl;
1168 return NOT_FOUND_IN_DATABASE;
1172 if(UsersUsernameVector[j] != username)
1174 __MOUT__ <<
"username: " << username <<
" is not found" << std::endl;
1175 return NOT_FOUND_IN_DATABASE;
1178 username = UsersDisplayNameVector[j];
1179 cookieCode = refreshCookieCode(i);
1180 return UsersUserIdVector[j];
1186 uint64_t WebUsers::getActiveSessionCountForUser(uint64_t uid)
1189 std::vector<uint64_t> uniqueAsi;
1192 for(i = 0; i<ActiveSessionUserIdVector.size(); ++i)
1193 if(ActiveSessionUserIdVector[i] == uid)
1198 for(j = 0; j<uniqueAsi.size(); ++j)
1199 if(uniqueAsi[j] == ActiveSessionIndex[i])
1201 unique =
false;
break;
1205 uniqueAsi.push_back(ActiveSessionIndex[i]);
1208 __MOUT__ <<
"Found " << uniqueAsi.size() <<
" active sessions for uid " << uid << std::endl;
1210 return uniqueAsi.size();
1215 std::string WebUsers::getUsersDisplayName(uint64_t uid)
1218 if((i = searchUsersDatabaseForUserId(uid)) == NOT_FOUND_IN_DATABASE)
return "";
1219 return UsersDisplayNameVector[i];
1224 std::string WebUsers::getUsersUsername(uint64_t uid)
1227 if((i = searchUsersDatabaseForUserId(uid)) == NOT_FOUND_IN_DATABASE)
return "";
1228 return UsersUsernameVector[i];
1241 uint64_t WebUsers::cookieCodeLogout(std::string cookieCode,
bool logoutOtherUserSessions, uint64_t *userId, std::string ip)
1248 if((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
1250 __MOUT__ <<
"Cookie code not found" << std::endl;
1251 return NOT_FOUND_IN_DATABASE;
1255 if(ActiveSessionIpVector[i] != ip)
1257 __MOUT__ <<
"IP does not match active session" << std::endl;
1258 return NOT_FOUND_IN_DATABASE;
1267 uint64_t asi = ActiveSessionIndex[i];
1268 uint64_t uid = ActiveSessionUserIdVector[i];
1269 if(userId) *userId = uid;
1270 uint64_t logoutCount = 0;
1273 while(i < ActiveSessionIndex.size())
1275 if( (logoutOtherUserSessions && ActiveSessionUserIdVector[i] == uid &&
1276 ActiveSessionIndex[i] != asi) ||
1277 (!logoutOtherUserSessions && ActiveSessionUserIdVector[i] == uid &&
1278 ActiveSessionIndex[i] == asi) )
1280 __MOUT__ <<
"Logging out of active session " << ActiveSessionUserIdVector[i]
1281 <<
"-" << ActiveSessionIndex[i] << std::endl;
1282 removeActiveSessionEntry(i);
1289 __MOUT__ <<
"Found and removed active session count = " << logoutCount << std::endl;
1296 bool WebUsers::getUserInfoForCookie(std::string &cookieCode,
1297 std::string *userName, std::string *displayName,
1298 uint64_t *activeSessionIndex)
1300 if(userName) *userName =
"";
1301 if(displayName) *displayName =
"";
1303 if(!CareAboutCookieCodes_)
1305 uint64_t uid = getAdminUserID();
1306 if(userName) *userName = getUsersUsername(uid);
1307 if(displayName) *displayName = getUsersDisplayName(uid);
1308 if(activeSessionIndex) *activeSessionIndex = -1;
1315 if((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
1317 __MOUT__ <<
"cookieCode NOT_FOUND_IN_DATABASE" << std::endl;
1322 if((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
1324 __MOUT__ <<
"ActiveSessionUserIdVector NOT_FOUND_IN_DATABASE" << std::endl;
1328 if(userName) *userName = UsersUsernameVector[j];
1329 if(displayName) *displayName = UsersDisplayNameVector[j];
1330 if(activeSessionIndex) *activeSessionIndex = ActiveSessionIndex[i];
1345 bool WebUsers::cookieCodeIsActiveForRequest(std::string &cookieCode,
1346 uint8_t *userPermissions, uint64_t *uid, std::string ip,
1347 bool refresh, std::string *userWithLock)
1350 cleanupExpiredEntries();
1357 if(!CareAboutCookieCodes_)
1359 if(userPermissions) *userPermissions = -1;
1360 if(uid) *uid = getAdminUserID();
1361 if(userWithLock) *userWithLock = usersUsernameWithLock_;
1363 cookieCode = genCookieCode();
1370 if((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
1372 __MOUT__ <<
"Cookie code not found" << std::endl;
1373 cookieCode = REQ_NO_LOGIN_RESPONSE;
1378 if(ActiveSessionIpVector[i] != ip)
1380 __MOUT__ <<
"IP does not match active session" << std::endl;
1381 cookieCode = REQ_NO_LOGIN_RESPONSE;
1386 if((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
1388 __MOUT__ <<
"User ID not found" << std::endl;
1389 cookieCode = REQ_NO_LOGIN_RESPONSE;
1393 uint8_t tmpPerm = getPermissionsForUser(UsersUserIdVector[j]);
1397 cookieCode = REQ_NO_PERMISSION_RESPONSE;
1402 if(userPermissions) *userPermissions = tmpPerm;
1403 if(uid) *uid = UsersUserIdVector[j];
1404 if(userWithLock) *userWithLock = usersUsernameWithLock_;
1406 cookieCode = refreshCookieCode(i,refresh);
1417 void WebUsers::cleanupExpiredEntries(std::vector<std::string> *loggedOutUsernames)
1422 if(loggedOutUsernames)
1424 for(i=0;i<UsersLoggedOutUsernames_.size();++i)
1425 loggedOutUsernames->push_back(UsersLoggedOutUsernames_[i]);
1426 UsersLoggedOutUsernames_.clear();
1432 for(i=0;i<LoginSessionStartTimeVector.size();++i)
1433 if(LoginSessionStartTimeVector[i] + LOGIN_SESSION_EXPIRATION_TIME < time(0) ||
1434 LoginSessionAttemptsVector[i] > LOGIN_SESSION_ATTEMPTS_MAX)
1439 removeLoginSessionEntry(i);
1452 for(i=0;i<ActiveSessionStartTimeVector.size();++i)
1453 if(ActiveSessionStartTimeVector[i] + ACTIVE_SESSION_EXPIRATION_TIME <= time(0))
1460 tmpUid = ActiveSessionUserIdVector[i];
1461 removeActiveSessionEntry(i);
1465 if(!isUserIdActive(tmpUid))
1467 if(loggedOutUsernames)
1468 loggedOutUsernames->push_back(UsersUsernameVector[searchUsersDatabaseForUserId(tmpUid)]);
1470 UsersLoggedOutUsernames_.push_back(UsersUsernameVector[searchUsersDatabaseForUserId(tmpUid)]);
1487 if(CareAboutCookieCodes_ && !isUsernameActive(usersUsernameWithLock_))
1488 usersUsernameWithLock_ =
"";
1498 std::string WebUsers::createNewLoginSession(std::string UUID,std::string ip)
1500 __MOUT__ <<
"UUID: " << UUID << std::endl << std::endl;
1502 for(;i<LoginSessionUUIDVector.size();++i)
1503 if(LoginSessionUUIDVector[i] == UUID)
break;
1505 if(i != LoginSessionUUIDVector.size())
1507 __MOUT__ <<
"UUID: " << UUID <<
" is not unique" << std::endl;
1512 LoginSessionUUIDVector.push_back(UUID);
1516 std::string sid =
"";
1517 for(i=0;i<SESSION_ID_LENGTH/2;++i)
1519 intToHexStr(rand(),hexStr);
1522 LoginSessionIdVector.push_back(sid);
1523 LoginSessionIpVector.push_back(
"");
1524 LoginSessionStartTimeVector.push_back(time(0));
1525 LoginSessionAttemptsVector.push_back(0);
1537 std::string WebUsers::sha512(std::string user, std::string password, std::string &salt)
1539 SHA512_CTX sha512_context;
1544 SHA512_Init(&sha512_context);
1546 for(
unsigned int i=0;i<8;++i)
1547 sha512_context.h[i] += rand();
1549 for(
unsigned int i=0;i<
sizeof(SHA512_CTX);++i)
1551 intToHexStr((uint8_t)(((uint8_t *)(&sha512_context))[i]),hexStr);
1553 salt.append(hexStr);
1555 __MOUT__ << salt << std::endl;
1560 __MOUT__ << salt << std::endl;
1562 for(
unsigned int i=0;i<
sizeof(SHA512_CTX);++i)
1563 ((uint8_t *)(&sha512_context))[i] = hexByteStrToInt(&(salt.c_str()[i*2]));
1566 std::string strToHash = salt + user + password;
1568 __MOUT__ << salt << std::endl;
1569 unsigned char hash[SHA512_DIGEST_LENGTH];
1570 __MOUT__ << salt << std::endl;
1571 char retHash[SHA512_DIGEST_LENGTH*2+1];
1572 __MOUT__ << strToHash.length() <<
" " << strToHash << std::endl;
1575 __MOUT__ <<
"If crashing occurs here, may be an illegal salt context." << std::endl;
1576 SHA512_Update(&sha512_context, strToHash.c_str(), strToHash.length());
1578 SHA512_Final(hash, &sha512_context);
1580 __MOUT__ << salt << std::endl;
1582 for(i = 0; i < SHA512_DIGEST_LENGTH; i++)
1583 sprintf(retHash + (i * 2),
"%02x", hash[i]);
1585 __MOUT__ << salt << std::endl;
1586 retHash[SHA512_DIGEST_LENGTH*2] =
'\0';
1589 __MOUT__ << salt << std::endl;
1600 std::string WebUsers::dejumble(std::string u, std::string s)
1603 if(s.length() != SESSION_ID_LENGTH)
return "";
1605 int ss = s.length()/2;
1606 int p = hexByteStrToInt(&(s.c_str()[0])) % ss;
1607 int n = hexByteStrToInt(&(s.c_str()[p*2])) % ss;
1608 int len = (hexByteStrToInt(&(u.c_str()[p*2])) - p - n + ss*3) % ss;
1611 for(
int i=0;i<ss;++i) x[i] = 0;
1614 int c = hexByteStrToInt(&(u.c_str()[p*2]));
1616 std::string user =
"";
1618 for(
int l=0;l<len;++l) {
1619 p = (p + hexByteStrToInt(&(s.c_str()[p*2]))) % ss;
1620 while(x[p]) p = (p+1) % ss;
1622 n = hexByteStrToInt(&(s.c_str()[p*2]));
1623 user.append(1,(hexByteStrToInt(&(u.c_str()[p*2])) - c - n + ss*4) % ss);
1624 c = hexByteStrToInt(&(u.c_str()[p*2]));
1633 uint8_t WebUsers::getPermissionsForUser(uint64_t uid)
1635 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
1636 return (userIndex < UsersPermissionsVector.size())?UsersPermissionsVector[userIndex]:0;
1643 std::string WebUsers::getTooltipFilename(
1644 const std::string& username,
const std::string &srcFile,
1645 const std::string &srcFunc,
const std::string &srcId)
1647 std::string filename = (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH +
"/";
1651 mkdir(((std::string)WEB_LOGIN_DB_PATH).c_str(), 0755);
1652 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH).c_str(), 0755);
1653 mkdir(filename.c_str(), 0755);
1655 for(
const char& c: username)
1657 (c >=
'a' && c <=
'z') ||
1658 (c >=
'A' && c <=
'Z') ||
1659 (c >=
'0' && c <=
'9') )
1664 mkdir(filename.c_str(), 0755);
1666 for(
const char& c: srcFile)
1668 (c >=
'a' && c <=
'z') ||
1669 (c >=
'A' && c <=
'Z') ||
1670 (c >=
'0' && c <=
'9') )
1673 for(
const char& c: srcFunc)
1675 (c >=
'a' && c <=
'z') ||
1676 (c >=
'A' && c <=
'Z') ||
1677 (c >=
'0' && c <=
'9') )
1680 for(
const char& c: srcId)
1682 (c >=
'a' && c <=
'z') ||
1683 (c >=
'A' && c <=
'Z') ||
1684 (c >=
'0' && c <=
'9') )
1687 __MOUT__ <<
"filename " << filename << std::endl;
1694 void WebUsers::tooltipSetNeverShowForUsername(
const std::string& username,
1696 const std::string &srcFile,
const std::string &srcFunc,
1697 const std::string &srcId,
bool doNeverShow,
bool temporarySilence)
1700 __MOUT__ <<
"Setting tooltip never show for user: " << username <<
1701 " to " << doNeverShow <<
" (temporarySilence=" <<
1702 temporarySilence <<
")" << std::endl;
1705 std::string filename = getTooltipFilename(username, srcFile, srcFunc, srcId);
1706 FILE *fp = fopen(filename.c_str(),
"w");
1709 if(temporarySilence)
1710 fprintf(fp,
"%ld",time(0)+60*60);
1712 fputc(doNeverShow?
'1':
'0',fp);
1716 __MOUT_ERR__ <<
"Big problme with tooltips! File not accessible: " << filename << std::endl;
1726 void WebUsers::tooltipCheckForUsername(
const std::string& username,
1728 const std::string &srcFile,
const std::string &srcFunc,
1729 const std::string &srcId)
1731 if(srcId ==
"ALWAYS")
1734 xmldoc->addTextElementToData(
"ShowTooltip",
"1");
1742 __MOUT__ <<
"Checking tooltip for user: " << username << std::endl;
1746 std::string filename = getTooltipFilename(username, srcFile, srcFunc, srcId);
1747 FILE *fp = fopen(filename.c_str(),
"r");
1754 sscanf(line,
"%ld",&val);
1755 __MOUT__ <<
"tooltip value read = " << val << std::endl;
1760 xmldoc->addTextElementToData(
"ShowTooltip",val==1?
"0":
1761 (time(0) > val?
"1":
"0"));
1764 xmldoc->addTextElementToData(
"ShowTooltip",
"1");
1769 void WebUsers::resetAllUserTooltips (
const std::string &userNeedle)
1771 std::system((
"rm -rf " + (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH +
1772 "/" + userNeedle).c_str());
1773 __MOUT__ <<
"Successfully reset Tooltips for user " << userNeedle << std::endl;
1794 void WebUsers::insertSettingsForUser(uint64_t uid,
HttpXmlDocument *xmldoc,
bool includeAccounts)
1796 uint8_t p = getPermissionsForUser(uid);
1799 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
1800 __MOUT__ <<
"Gettings settings for user: " << UsersUsernameVector[userIndex] << std::endl;
1802 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH + UsersUsernameVector[userIndex] +
"." + (std::string)USERS_PREFERENCES_FILETYPE;
1806 __MOUT__ <<
"Preferences file: " << fn << std::endl;
1808 if(!prefXml.loadXmlDocument(fn))
1810 __MOUT__ <<
"Preferences are defaults." << std::endl;
1812 xmldoc->addTextElementToData(PREF_XML_BGCOLOR_FIELD,PREF_XML_BGCOLOR_DEFAULT);
1813 xmldoc->addTextElementToData(PREF_XML_DBCOLOR_FIELD,PREF_XML_DBCOLOR_DEFAULT);
1814 xmldoc->addTextElementToData(PREF_XML_WINCOLOR_FIELD,PREF_XML_WINCOLOR_DEFAULT);
1815 xmldoc->addTextElementToData(PREF_XML_LAYOUT_FIELD,PREF_XML_LAYOUT_DEFAULT);
1819 __MOUT__ <<
"Saved Preferences found." << std::endl;
1820 xmldoc->copyDataChildren(prefXml);
1826 if (includeAccounts && p == (uint8_t)-1) {
1828 __MOUT__ <<
"Super User on our hands" << std::endl;
1830 xmldoc->addTextElementToData(PREF_XML_ACCOUNTS_FIELD,
"");
1834 for(uint64_t i=0;i<UsersUsernameVector.size();++i)
1836 xmldoc->addTextElementToParent(
"username",UsersUsernameVector[i],PREF_XML_ACCOUNTS_FIELD);
1837 xmldoc->addTextElementToParent(
"display_name",UsersDisplayNameVector[i],PREF_XML_ACCOUNTS_FIELD);
1838 sprintf(permStr,
"%d",UsersPermissionsVector[i]);
1839 xmldoc->addTextElementToParent(
"permissions",permStr,PREF_XML_ACCOUNTS_FIELD);
1840 if(UsersSaltVector[i] ==
"")
1841 sprintf(permStr,
"%d",
int(UsersAccountCreatedTimeVector[i] & 0xffff));
1844 xmldoc->addTextElementToParent(
"nac",permStr,PREF_XML_ACCOUNTS_FIELD);
1849 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
1850 (std::string)SYSTEM_PREFERENCES_PREFIX +
"." + (std::string)USERS_PREFERENCES_FILETYPE;
1851 if(!prefXml.loadXmlDocument(fn))
1853 __MOUT__ <<
"System Preferences are defaults." << std::endl;
1855 xmldoc->addTextElementToData(PREF_XML_SYSLAYOUT_FIELD,PREF_XML_SYSLAYOUT_DEFAULT);
1859 __MOUT__ <<
"Saved System Preferences found." << std::endl;
1860 xmldoc->copyDataChildren(prefXml);
1864 sprintf(permStr,
"%d",p);
1865 xmldoc->addTextElementToData(PREF_XML_PERMISSIONS_FIELD,permStr);
1868 xmldoc->addTextElementToData(PREF_XML_USERLOCK_FIELD,usersUsernameWithLock_);
1870 xmldoc->addTextElementToData(PREF_XML_USERNAME_FIELD,getUsersUsername(uid));
1876 void WebUsers::setGenericPreference (uint64_t uid,
const std::string &preferenceName,
1877 const std::string &preferenceValue)
1879 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
1883 std::string safePreferenceName =
"";
1884 for(
const auto &c:preferenceName)
1885 if((c >=
'a' && c <=
'z') ||
1886 (c >=
'A' && c <=
'Z') ||
1887 (c >=
'0' && c <=
'9') ||
1888 (c >=
'-' || c <=
'_'))
1889 safePreferenceName += c;
1891 std::string dir = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
1892 "generic_" + safePreferenceName +
"/";
1895 mkdir(dir.c_str(), 0755);
1897 std::string fn = UsersUsernameVector[userIndex] +
"_" + safePreferenceName +
1898 "." + (std::string)USERS_PREFERENCES_FILETYPE;
1900 __MOUT__ <<
"Preferences file: " << (dir+fn) << std::endl;
1902 FILE *fp = fopen((dir+fn).c_str(),
"w");
1905 fprintf(fp,
"%s",preferenceValue.c_str());
1909 __MOUT_ERR__ <<
"Preferences file could not be opened for writing!" << std::endl;
1916 std::string WebUsers::getGenericPreference (uint64_t uid,
const std::string &preferenceName,
1919 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
1923 std::string safePreferenceName =
"";
1924 for(
const auto &c:preferenceName)
1925 if((c >=
'a' && c <=
'z') ||
1926 (c >=
'A' && c <=
'Z') ||
1927 (c >=
'0' && c <=
'9') ||
1928 (c >=
'-' || c <=
'_'))
1929 safePreferenceName += c;
1931 std::string dir = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
1932 "generic_" + safePreferenceName +
"/";
1934 std::string fn = UsersUsernameVector[userIndex] +
"_" + safePreferenceName +
1935 "." + (std::string)USERS_PREFERENCES_FILETYPE;
1937 __MOUT__ <<
"Preferences file: " << (dir+fn) << std::endl;
1940 FILE *fp = fopen((dir+fn).c_str(),
"rb");
1943 fseek(fp, 0, SEEK_END);
1944 long size = ftell(fp);
1947 fgets(line,size+1,fp);
1950 __MOUT__ <<
"Read value " << line << std::endl;
1951 if(xmldoc) xmldoc->addTextElementToData(safePreferenceName,line);
1955 __MOUT__ <<
"Using default value." << std::endl;
1958 if(xmldoc) xmldoc->addTextElementToData(safePreferenceName,
"");
1964 void WebUsers::changeSettingsForUser (uint64_t uid,
const std::string &bgcolor,
const std::string &dbcolor,
1965 const std::string &wincolor,
const std::string &layout,
const std::string &syslayout)
1967 uint8_t p = getPermissionsForUser(uid);
1970 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
1971 __MOUT__ <<
"Changing settings for user: " << UsersUsernameVector[userIndex] << std::endl;
1973 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH + UsersUsernameVector[userIndex] +
"." + (std::string)USERS_PREFERENCES_FILETYPE;
1975 __MOUT__ <<
"Preferences file: " << fn << std::endl;
1978 prefXml.addTextElementToData(PREF_XML_BGCOLOR_FIELD,bgcolor);
1979 prefXml.addTextElementToData(PREF_XML_DBCOLOR_FIELD,dbcolor);
1980 prefXml.addTextElementToData(PREF_XML_WINCOLOR_FIELD,wincolor);
1981 prefXml.addTextElementToData(PREF_XML_LAYOUT_FIELD,layout);
1983 prefXml.saveXmlDocument(fn);
1989 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
1990 (std::string)SYSTEM_PREFERENCES_PREFIX +
"." + (std::string)USERS_PREFERENCES_FILETYPE;
1993 sysPrefXml.addTextElementToData(PREF_XML_SYSLAYOUT_FIELD,syslayout);
1995 sysPrefXml.saveXmlDocument(fn);
2004 bool WebUsers::setUserWithLock(uint64_t uid_master,
bool lock, std::
string username)
2006 uint8_t p = getPermissionsForUser(uid_master);
2008 __MOUT__ <<
"permissions " << (int)p << std::endl;
2009 __MOUT__ <<
"usersUsernameWithLock_ " << usersUsernameWithLock_ << std::endl;
2010 __MOUT__ <<
"lock " << lock << std::endl;
2011 __MOUT__ <<
"username " << username << std::endl;
2012 __MOUT__ <<
"isUsernameActive(username) " << isUsernameActive(username) << std::endl;
2014 if(p != (uint8_t)-1)
return false;
2016 if(lock && (isUsernameActive(username) || !CareAboutCookieCodes_))
2018 if(!CareAboutCookieCodes_ && username != DEFAULT_ADMIN_USERNAME)
2020 __MOUT__ <<
"User tried to lock for a user other than admin in wiz mode. Not allowed." << std::endl;
2023 usersUsernameWithLock_ = username;
2025 else if(!lock && usersUsernameWithLock_ == username)
2026 usersUsernameWithLock_ =
"";
2032 std::string securityFileName = USER_WITH_LOCK_FILE;
2033 FILE *fp = fopen(securityFileName.c_str(),
"w");
2036 __MOUT_INFO__ <<
"USER_WITH_LOCK_FILE " << USER_WITH_LOCK_FILE <<
2037 " not found. Ignoring." << std::endl;
2041 fprintf(fp,
"%s",usersUsernameWithLock_.c_str());
2050 void WebUsers::modifyAccountSettings (uint64_t uid_master, uint8_t cmd_type, std::string username, std::string displayname, std::string permissions)
2053 uint8_t p = getPermissionsForUser(uid_master);
2054 if(p != (uint8_t)-1)
return;
2056 uint64_t modi = searchUsersDatabaseForUsername(username);
2059 __MOUT__ <<
"Cannot modify first user" << std::endl;
2063 if(username.length() < USERNAME_LENGTH || displayname.length() < DISPLAY_NAME_LENGTH)
2065 __MOUT__ <<
"Invalid Username or Display Name must be length " << USERNAME_LENGTH <<
" or " << DISPLAY_NAME_LENGTH << std::endl;
2070 sscanf(permissions.c_str(),
"%d",&inputp);
2072 __MOUT__ <<
"Input Permissions " << inputp << std::endl;
2076 case MOD_TYPE_UPDATE:
2077 __MOUT__ <<
"MOD_TYPE_UPDATE " << username <<
" := " << inputp << std::endl;
2078 if(modi == NOT_FOUND_IN_DATABASE)
2080 __MOUT__ <<
"User not found!? Should not happen." << std::endl;
2084 UsersDisplayNameVector[modi] = displayname;
2088 if(!UsersPermissionsVector[modi] && inputp)
2090 UsersLoginFailureCountVector[modi] = 0;
2091 UsersSaltVector[modi] =
"";
2093 UsersPermissionsVector[modi] = inputp;
2097 uint64_t i = searchUsersDatabaseForUserId(uid_master);
2098 if(i == NOT_FOUND_IN_DATABASE)
2100 __MOUT__ <<
"Master User not found!? Should not happen." << std::endl;
2103 UsersLastModifierUsernameVector[modi] = UsersUsernameVector[i];
2104 UsersLastModifiedTimeVector[modi] = time(0);
2108 __MOUT__ <<
"MOD_TYPE_ADD " << username <<
" - " << displayname << std::endl;
2109 createNewAccount(username,displayname);
2111 case MOD_TYPE_DELETE:
2112 __MOUT__ <<
"MOD_TYPE_DELETE " << username <<
" - " << displayname << std::endl;
2113 deleteAccount(username,displayname);
2116 __MOUT__ <<
"Undefined command - do nothing " << username << std::endl;
2119 saveDatabaseToFile(DB_USERS);
2124 std::string WebUsers::getActiveUsersString()
2126 std::string ret =
"";
2129 for(uint64_t i=0; i<ActiveSessionUserIdVector.size(); ++i)
2133 for(uint64_t j=0; j<i; ++j)
2134 if(ActiveSessionUserIdVector[i] == ActiveSessionUserIdVector[j])
2135 { repeat =
true;
break;}
2137 if(!repeat && (u = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) !=
2138 NOT_FOUND_IN_DATABASE)
2139 ret += UsersDisplayNameVector[u] +
",";
2141 if(ret.length() > 1) ret.erase(ret.length()-1);
2147 uint64_t WebUsers::getAdminUserID()
2149 uint64_t uid = searchUsersDatabaseForUsername(DEFAULT_ADMIN_USERNAME);
2157 void WebUsers::loadUserWithLock()
2159 char username[300] =
"";
2161 std::string securityFileName = USER_WITH_LOCK_FILE;
2162 FILE *fp = fopen(securityFileName.c_str(),
"r");
2165 __MOUT_INFO__ <<
"USER_WITH_LOCK_FILE " << USER_WITH_LOCK_FILE <<
2166 " not found. Defaulting to admin lock." << std::endl;
2169 sprintf(username,
"%s",DEFAULT_ADMIN_USERNAME.c_str());
2173 fgets(username,300,fp);
2174 username[299] =
'\0';
2179 __MOUT__ <<
"Attempting to load username with lock: " << username << std::endl;
2181 if(strlen(username) == 0)
2183 __MOUT_INFO__ <<
"Loaded state for user-with-lock is unlocked." << std::endl;
2187 uint64_t i = searchUsersDatabaseForUsername(username);
2188 if(i == NOT_FOUND_IN_DATABASE)
2190 __MOUT_INFO__ <<
"username " << username <<
2191 " not found in database. Ignoring." << std::endl;
2194 setUserWithLock(UsersUserIdVector[i],
true,username);
2200 std::string WebUsers::getSecurity()
2202 return securityType_;
2207 void WebUsers::loadSecuritySelection()
2209 std::string securityFileName = SECURITY_FILE_NAME;
2210 FILE *fp = fopen(securityFileName.c_str(),
"r");
2211 char line[100] =
"";
2212 if(fp) fgets(line,100,fp);
2216 while(i<strlen(line) && line[i] >=
'A' && line[i] <=
'z') ++i;
2220 if(strcmp(line,SECURITY_TYPE_NONE.c_str()) == 0 ||
2221 strcmp(line,SECURITY_TYPE_DIGEST_ACCESS.c_str()) == 0 ||
2222 strcmp(line,SECURITY_TYPE_KERBEROS.c_str()) == 0)
2223 securityType_ = line;
2225 securityType_ = SECURITY_TYPE_DIGEST_ACCESS;
2227 __MOUT__ <<
"The current security type is " << securityType_ << std::endl;
2232 if(securityType_ == SECURITY_TYPE_NONE)
2233 CareAboutCookieCodes_ =
false;
2235 CareAboutCookieCodes_ =
true;
2237 __MOUT__ <<
"CareAboutCookieCodes_: " <<
2238 CareAboutCookieCodes_ << std::endl;
2245 void WebUsers::NACDisplayThread(std::string nac, std::string user)
2247 INIT_MF(
"WebUsers_NAC");
2256 std::this_thread::sleep_for (std::chrono::seconds(2));
2257 __MOUT__ << __COUT_HDR_P__ <<
"\n******************************************************************** " << std::endl;
2258 __MOUT__ << __COUT_HDR_P__ <<
"\n******************************************************************** " << std::endl;
2259 __MOUT__ << __COUT_HDR_P__ <<
"\n\nNew account code = " << nac <<
" for user: " << user <<
"\n" << std::endl;
2260 __MOUT__ << __COUT_HDR_P__ <<
"\n******************************************************************** " << std::endl;
2261 __MOUT__ << __COUT_HDR_P__ <<
"\n******************************************************************** " << std::endl;