00001 #include "otsdaq-core/WebUsersUtilities/WebUsers.h"
00002 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
00003
00004 #include <sys/types.h>
00005 #include <sys/stat.h>
00006 #include <iostream>
00007 #include <openssl/sha.h>
00008 #include <cstdlib>
00009 #include <cstdio>
00010 #include <cassert>
00011
00012 #include <thread>
00013 #include <chrono>
00014
00015 using namespace ots;
00016
00017
00018
00019 #define WEB_LOGIN_BKUP_DB_PATH "bkup/"
00020
00021 #define SECURITY_FILE_NAME std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData/security.dat"
00022
00023 #define USERS_ACTIVE_SESSIONS_FILE USERS_DB_PATH + "/activeSessions.sv"
00024
00025 #define HASHES_DB_FILE HASHES_DB_PATH + "/hashes.xml"
00026 #define USERS_DB_FILE USERS_DB_PATH + "/users.xml"
00027 #define USERS_GLOBAL_HISTORY_FILE "__global"
00028 #define USERS_LOGIN_HISTORY_FILETYPE "hist"
00029 #define USERS_PREFERENCES_FILETYPE "pref"
00030 #define SYSTEM_PREFERENCES_PREFIX "system.preset"
00031 #define USER_WITH_LOCK_FILE WEB_LOGIN_DB_PATH + "/user_with_lock.dat"
00032 #define IP_BLACKLIST_FILE WEB_LOGIN_DB_PATH + "/ip_generated_blacklist.dat"
00033 #define IP_REJECT_FILE WEB_LOGIN_DB_PATH + "/ip_reject.dat"
00034 #define IP_ACCEPT_FILE WEB_LOGIN_DB_PATH + "/ip_accept.dat"
00035
00036 #define HASHES_DB_GLOBAL_STRING "hashData"
00037 #define HASHES_DB_ENTRY_STRING "hashEntry"
00038 #define USERS_DB_GLOBAL_STRING "userData"
00039 #define USERS_DB_ENTRY_STRING "userEntry"
00040 #define USERS_DB_NEXT_UID_STRING "nextUserId"
00041
00042
00043 #define PREF_XML_BGCOLOR_FIELD "pref_bgcolor" // -background color
00044 #define PREF_XML_DBCOLOR_FIELD "pref_dbcolor" // -dashboard color
00045 #define PREF_XML_WINCOLOR_FIELD "pref_wincolor" // -window color
00046 #define PREF_XML_LAYOUT_FIELD "pref_layout" // -3 defaults window layouts(and current)
00047 #define PREF_XML_SYSLAYOUT_FIELD "pref_syslayout" // -2 defaults window layouts
00048 #define PREF_XML_PERMISSIONS_FIELD "desktop_user_permissions" // 0-255 permissions value (255 is admin super user)
00049 #define PREF_XML_USERLOCK_FIELD "username_with_lock" // user with lock (to lockout others)
00050 #define PREF_XML_USERNAME_FIELD "pref_username" // user with lock (to lockout others)
00051
00052 #define PREF_XML_BGCOLOR_DEFAULT "rgb(0,76,151)" // -background color
00053 #define PREF_XML_DBCOLOR_DEFAULT "rgb(0,40,85)" // -dashboard color
00054 #define PREF_XML_WINCOLOR_DEFAULT "rgba(196,229,255,0.9)" // -window color
00055 #define PREF_XML_LAYOUT_DEFAULT "0;0;0;0" // 3 default window layouts(and current)
00056 #define PREF_XML_SYSLAYOUT_DEFAULT "0;0" // 2 system default window layouts
00057
00058 #define PREF_XML_ACCOUNTS_FIELD "users_accounts" // user accounts field for super users
00059 #define PREF_XML_LOGIN_HISTORY_FIELD "login_entry" // login history field for user login history data
00060
00061 const std::string WebUsers::DEFAULT_ADMIN_USERNAME = "admin";
00062 const std::string WebUsers::DEFAULT_ADMIN_DISPLAY_NAME = "Administrator";
00063 const std::string WebUsers::DEFAULT_ADMIN_EMAIL = "root@otsdaq.fnal.gov";
00064 const std::string WebUsers::DEFAULT_ITERATOR_USERNAME = "iterator";
00065 const std::string WebUsers::DEFAULT_STATECHANGER_USERNAME = "statechanger";
00066 const std::string WebUsers::DEFAULT_USER_GROUP = "allUsers";
00067
00068 const std::string WebUsers::REQ_NO_LOGIN_RESPONSE = "NoLogin";
00069 const std::string WebUsers::REQ_NO_PERMISSION_RESPONSE = "NoPermission";
00070 const std::string WebUsers::REQ_USER_LOCKOUT_RESPONSE = "UserLockout";
00071 const std::string WebUsers::REQ_LOCK_REQUIRED_RESPONSE = "LockRequired";
00072 const std::string WebUsers::REQ_ALLOW_NO_USER = "AllowNoUser";
00073
00074 const std::string WebUsers::SECURITY_TYPE_NONE = "NoSecurity";
00075 const std::string WebUsers::SECURITY_TYPE_DIGEST_ACCESS = "DigestAccessAuthentication";
00076
00077
00078
00079
00080 #undef __MF_SUBJECT__
00081 #define __MF_SUBJECT__ "WebUsers"
00082
00083
00084 WebUsers::WebUsers()
00085 {
00086
00087
00088 usersNextUserId_ = 0;
00089 usersUsernameWithLock_ = "";
00090
00091
00092 HashesDatabaseEntryFields.push_back("hash");
00093 HashesDatabaseEntryFields.push_back("lastAccessTime");
00094
00095 UsersDatabaseEntryFields.push_back("username");
00096 UsersDatabaseEntryFields.push_back("displayName");
00097 UsersDatabaseEntryFields.push_back("salt");
00098 UsersDatabaseEntryFields.push_back("uid");
00099 UsersDatabaseEntryFields.push_back("permissions");
00100 UsersDatabaseEntryFields.push_back("lastLoginAttemptTime");
00101 UsersDatabaseEntryFields.push_back("accountCreatedTime");
00102 UsersDatabaseEntryFields.push_back("loginFailureCount");
00103 UsersDatabaseEntryFields.push_back("lastModifiedTime");
00104 UsersDatabaseEntryFields.push_back("lastModifierUsername");
00105 UsersDatabaseEntryFields.push_back("useremail");
00106
00107
00108 mkdir(((std::string)WEB_LOGIN_DB_PATH).c_str(), 0755);
00109 mkdir(((std::string)WEB_LOGIN_DB_PATH + "bkup/" + USERS_DB_PATH).c_str(), 0755);
00110 mkdir(((std::string)WEB_LOGIN_DB_PATH + HASHES_DB_PATH).c_str(), 0755);
00111 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH).c_str(), 0755);
00112 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_LOGIN_HISTORY_PATH).c_str(), 0755);
00113 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_PREFERENCES_PATH).c_str(), 0755);
00114
00115
00116 if (!loadDatabases())
00117 __COUT__ << "FATAL USER DATABASE ERROR - failed to load!!!" << __E__;
00118
00119 loadSecuritySelection();
00120
00121
00122
00123 uint64_t i;
00124 std::string user = DEFAULT_ADMIN_USERNAME;
00125 if ((i = searchUsersDatabaseForUsername(user)) == NOT_FOUND_IN_DATABASE)
00126 {
00127 __SS__ << "user: " << user << " is not found" << __E__;
00128 __COUT_ERR__ << ss.str();
00129 throw std::runtime_error(ss.str());
00130 exit(0);
00131 }
00132 else if (UsersSaltVector[i] == "" &&
00133 securityType_ == SECURITY_TYPE_DIGEST_ACCESS)
00134 {
00135 char charTimeStr[10];
00136 sprintf(charTimeStr, "%d", int(UsersAccountCreatedTimeVector[i] & 0xffff));
00137 std::string tmpTimeStr = charTimeStr;
00138
00140
00141
00142 std::thread([](const std::string& nac, const std::string& user) { WebUsers::NACDisplayThread(nac, user); },
00143 tmpTimeStr, user).detach();
00144
00145 }
00146
00147
00148
00149 loadActiveSessions();
00150
00151
00152
00153 loadUserWithLock();
00154
00155 srand(time(0));
00156
00157 __COUT__ << "Done with Web Users initialization!" << __E__;
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 }
00341
00342
00343
00344
00345
00346
00347
00348 bool WebUsers::xmlRequestOnGateway(
00349 cgicc::Cgicc& cgi,
00350 std::ostringstream* out,
00351 HttpXmlDocument* xmldoc,
00352 WebUsers::RequestUserInfo& userInfo
00353 )
00354 {
00355
00356
00357 WebUsers::initializeRequestUserInfo(cgi,userInfo);
00358
00359
00360
00361
00362 if (!cookieCodeIsActiveForRequest(
00363 userInfo.cookieCode_,
00364 &userInfo.groupPermissionLevelMap_,
00365 &userInfo.uid_,
00366 userInfo.ip_,
00367 !userInfo.automatedCommand_ ,
00368 &userInfo.usernameWithLock_,
00369 &userInfo.activeUserSessionIndex_))
00370 {
00371 *out << userInfo.cookieCode_;
00372 goto HANDLE_ACCESS_FAILURE;
00373 }
00374
00375
00376 userInfo.getGroupPermissionLevel();
00377 userInfo.username_ = UsersUsernameVector[userInfo.uid_];
00378 userInfo.displayName_ = UsersDisplayNameVector[userInfo.uid_];
00379
00380 if(!WebUsers::checkRequestAccess(cgi,out,xmldoc,userInfo))
00381 goto HANDLE_ACCESS_FAILURE;
00382
00383 return true;
00384
00385
00386 HANDLE_ACCESS_FAILURE:
00387
00388 if(!userInfo.automatedCommand_)
00389 __COUT_ERR__ << "Failed request (requestType = " << userInfo.requestType_ <<
00390 "): " << out->str() << __E__;
00391 return false;
00392
00393 }
00394
00395
00396
00397
00398 void WebUsers::initializeRequestUserInfo(
00399 cgicc::Cgicc& cgi,
00400 WebUsers::RequestUserInfo& userInfo)
00401 {
00402 userInfo.permissionLevel_ = 0;
00403 userInfo.ip_ = cgi.getEnvironment().getRemoteAddr();
00404
00405
00406 userInfo.username_ = "";
00407 userInfo.displayName_ = "";
00408 userInfo.usernameWithLock_ = "";
00409 userInfo.activeUserSessionIndex_ = -1;
00410 userInfo.setGroupPermissionLevels("");
00411 }
00412
00413
00414
00415
00416
00417
00418 bool WebUsers::checkRequestAccess(
00419 cgicc::Cgicc& cgi,
00420 std::ostringstream* out,
00421 HttpXmlDocument* xmldoc,
00422 WebUsers::RequestUserInfo& userInfo,
00423 bool isWizardMode)
00424 {
00425
00426
00427
00428
00429
00430 if(!userInfo.automatedCommand_)
00431 {
00432 __COUT__ << "requestType ==========>>> " << userInfo.requestType_ << __E__;
00433 __COUTV__((unsigned int)userInfo.permissionLevel_);
00434 __COUTV__((unsigned int)userInfo.permissionsThreshold_);
00435 }
00436
00437
00438 if(!isWizardMode && !userInfo.allowNoUser_ &&
00439 userInfo.cookieCode_.length() != WebUsers::COOKIE_CODE_LENGTH)
00440 {
00441 __COUT__ << "User (@" << userInfo.ip_ << ") has invalid cookie code: " <<
00442 userInfo.cookieCode_ << std::endl;
00443 *out << WebUsers::REQ_NO_LOGIN_RESPONSE;
00444 return false;
00445 }
00446
00447 if(!userInfo.allowNoUser_ &&
00448 (userInfo.permissionLevel_ == 0 ||
00449 userInfo.permissionLevel_ < userInfo.permissionsThreshold_))
00450 {
00451 *out << WebUsers::REQ_NO_PERMISSION_RESPONSE;
00452 __COUT__ << "User (@" << userInfo.ip_ << ") has insufficient permissions for requestType '" <<
00453 userInfo.requestType_ <<
00454 "' : " <<
00455 (unsigned int)userInfo.permissionLevel_ << "<" <<
00456 (unsigned int)userInfo.permissionsThreshold_ << std::endl;
00457 return false;
00458 }
00459
00460
00461 if(isWizardMode)
00462 {
00463 userInfo.username_ = "admin";
00464 userInfo.displayName_ = "Admin";
00465 userInfo.usernameWithLock_ = "admin";
00466 userInfo.activeUserSessionIndex_ = 0;
00467 return true;
00468 }
00469
00470
00471 if(xmldoc)
00472 {
00473 if(userInfo.allowNoUser_)
00474 xmldoc->setHeader(WebUsers::REQ_ALLOW_NO_USER);
00475 else
00476 xmldoc->setHeader(userInfo.cookieCode_);
00477 }
00478
00479 if(userInfo.allowNoUser_) return true;
00480
00481
00482
00483
00484
00485
00486
00487
00488 if((userInfo.checkLock_ || userInfo.requireLock_) &&
00489 userInfo.usernameWithLock_ != "" &&
00490 userInfo.usernameWithLock_ != userInfo.username_)
00491 {
00492 *out << WebUsers::REQ_USER_LOCKOUT_RESPONSE;
00493 __COUT__ << "User '" << userInfo.username_ << "' is locked out. '" <<
00494 userInfo.usernameWithLock_ << "' has lock." << std::endl;
00495 return false;
00496 }
00497
00498 if(userInfo.requireLock_ &&
00499 userInfo.usernameWithLock_ != userInfo.username_)
00500 {
00501 *out << WebUsers::REQ_LOCK_REQUIRED_RESPONSE;
00502 __COUT__ << "User '" << userInfo.username_ << "' must have lock to proceed. ('" <<
00503 userInfo.usernameWithLock_ << "' has lock.)" << std::endl;
00504 return false;
00505 }
00506
00507 return true;
00508
00509 }
00510
00511
00512
00513
00514 void WebUsers::saveActiveSessions()
00515 {
00516 std::string fn;
00517
00518 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_ACTIVE_SESSIONS_FILE;
00519 __COUT__ << fn << __E__;
00520
00521 FILE *fp = fopen(fn.c_str(), "w");
00522 if (!fp)
00523 {
00524 __COUT_ERR__ << "Error! Persistent active sessions could not be saved to file: " <<
00525 fn << __E__;
00526 return;
00527 }
00528
00529 int version = 0;
00530 fprintf(fp, "%d\n", version);
00531 for (unsigned int i = 0; i < ActiveSessionCookieCodeVector.size(); ++i)
00532 {
00533
00534
00535
00536
00537
00538
00539 fprintf(fp, "%s\n", ActiveSessionCookieCodeVector[i].c_str());
00540 fprintf(fp, "%s\n", ActiveSessionIpVector[i].c_str());
00541 fprintf(fp, "%lu\n", ActiveSessionUserIdVector[i]);
00542 fprintf(fp, "%lu\n", ActiveSessionIndex[i]);
00543 fprintf(fp, "%ld\n", ActiveSessionStartTimeVector[i]);
00544 }
00545
00546 __COUT__ << "ActiveSessionCookieCodeVector saved with size " <<
00547 ActiveSessionCookieCodeVector.size() << __E__;
00548
00549 fclose(fp);
00550 }
00551
00552
00553
00554
00555 void WebUsers::loadActiveSessions()
00556 {
00557 std::string fn;
00558
00559 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_ACTIVE_SESSIONS_FILE;
00560 __COUT__ << fn << __E__;
00561 FILE *fp = fopen(fn.c_str(), "r");
00562 if (!fp)
00563 {
00564 __COUT_INFO__ << "Persistent active sessions were not found to be loaded at file: " <<
00565 fn << __E__;
00566 return;
00567 }
00568
00569 int version;
00570
00571 const int LINELEN = 1000;
00572 char line[LINELEN];
00573 fgets(line, LINELEN, fp);
00574 sscanf(line, "%d", &version);
00575 if (version == 0)
00576 {
00577 __COUT__ << "Extracting active sessions..." << __E__;
00578
00579 }
00580 unsigned int i = 0;
00581 while (fgets(line, LINELEN, fp))
00582 {
00583 if (strlen(line)) line[strlen(line) - 1] = '\0';
00584 if (strlen(line) != COOKIE_CODE_LENGTH)
00585 {
00586 __COUT__ << "Illegal cookie code found: " << line << __E__;
00587
00588 fclose(fp);
00589 return;
00590 }
00591 ActiveSessionCookieCodeVector.push_back(line);
00592
00593 fgets(line, LINELEN, fp);
00594 if (strlen(line)) line[strlen(line) - 1] = '\0';
00595 ActiveSessionIpVector.push_back(line);
00596
00597 fgets(line, LINELEN, fp);
00598 ActiveSessionUserIdVector.push_back(uint64_t());
00599 sscanf(line, "%lu", &(ActiveSessionUserIdVector[ActiveSessionUserIdVector.size() - 1]));
00600
00601 fgets(line, LINELEN, fp);
00602 ActiveSessionIndex.push_back(uint64_t());
00603 sscanf(line, "%lu", &(ActiveSessionIndex[ActiveSessionIndex.size() - 1]));
00604
00605 fgets(line, LINELEN, fp);
00606 ActiveSessionStartTimeVector.push_back(time_t());
00607 sscanf(line, "%ld", &(ActiveSessionStartTimeVector[ActiveSessionStartTimeVector.size() - 1]));
00608
00609
00610
00611
00612
00613
00614
00615 ++i;
00616 }
00617
00618 __COUT__ << "ActiveSessionCookieCodeVector loaded with size " <<
00619 ActiveSessionCookieCodeVector.size() << __E__;
00620
00621
00622 fclose(fp);
00623
00624 fp = fopen(fn.c_str(), "w");
00625 if (fp)fclose(fp);
00626
00627 }
00628
00629
00630
00631
00632
00633 bool WebUsers::loadDatabases()
00634 {
00635 std::string fn;
00636
00637 FILE *fp;
00638 const unsigned int LINE_LEN = 1000;
00639 char line[LINE_LEN];
00640 unsigned int i, si, c, len, f;
00641 uint64_t tmpInt64;
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_FILE;
00652 __COUT__ << fn << __E__;
00653 fp = fopen(fn.c_str(), "r");
00654 if (!fp)
00655 {
00656 mkdir(((std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_PATH).c_str(), 0755);
00657 __COUT__ << ((std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_PATH).c_str() << __E__;
00658 fp = fopen(fn.c_str(), "w");
00659 if (!fp) return false;
00660 __COUT__ << "Hashes database created: " << fn << __E__;
00661
00662 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING, "", DB_SAVE_OPEN);
00663 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING, "", DB_SAVE_CLOSE);
00664 fclose(fp);
00665 }
00666 else
00667 {
00668
00669
00670 while (fgets(line, LINE_LEN, fp))
00671 {
00672 if (strlen(line) < SHA512_DIGEST_LENGTH) continue;
00673
00674 c = 0;
00675 len = strlen(line);
00676 for (i = 0; i < len; ++i)
00677 if (line[i] == '>')
00678 {
00679 ++c;
00680 if (c != 2 && c != 4) continue;
00681
00682 si = ++i;
00683 while (i < len && line[i] != '<') ++i;
00684 if (i == len)
00685 break;
00686 line[i] = '\0';
00687
00688
00689
00690 f = c / 2 - 1;
00691 if (f == 0)
00692 HashesVector.push_back(&line[si]);
00693 else if (f == 1)
00694 {
00695 sscanf(&line[si], "%lu", &tmpInt64);
00696 HashesAccessTimeVector.push_back(tmpInt64);
00697 }
00698 }
00699 }
00700 __COUT__ << HashesAccessTimeVector.size() << " Hashes found." << __E__;
00701
00702 fclose(fp);
00703 }
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_FILE;
00715 fp = fopen(fn.c_str(), "r");
00716 if (!fp)
00717 {
00718 mkdir(((std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_PATH).c_str(), 0755);
00719 __COUT__ << ((std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_PATH).c_str() << __E__;
00720 fp = fopen(fn.c_str(), "w");
00721 if (!fp) return false;
00722 __COUT__ << "Users database created: " << fn << __E__;
00723
00724 saveToDatabase(fp, USERS_DB_GLOBAL_STRING, "", DB_SAVE_OPEN);
00725 char nidStr[100];
00726 sprintf(nidStr, "%lu", usersNextUserId_);
00727 saveToDatabase(fp, USERS_DB_NEXT_UID_STRING, nidStr, DB_SAVE_OPEN_AND_CLOSE);
00728 saveToDatabase(fp, USERS_DB_GLOBAL_STRING, "", DB_SAVE_CLOSE);
00729 fclose(fp);
00730
00731 createNewAccount(DEFAULT_ADMIN_USERNAME, DEFAULT_ADMIN_DISPLAY_NAME, DEFAULT_ADMIN_EMAIL);
00732 }
00733 else
00734 {
00735
00736
00737
00738 char salt[] = "nextUserId";
00739 while (fgets(line, LINE_LEN, fp))
00740 {
00741 if (strlen(line) < strlen(salt) * 2) continue;
00742
00743 for (i = 0; i < strlen(salt); ++i)
00744 if (line[i + 1] != salt[i]) break;
00745
00746 if (i == strlen(salt))
00747 {
00748 i += 2;
00749 si = i;
00750 while (i < LINE_LEN && line[i] != '\0' && line[i] != '<') ++i;
00751 line[i] = '\0';
00752 sscanf(&line[si], "%lu", &usersNextUserId_);
00753 break;
00754 }
00755 }
00756
00757 __COUT__ << "Found Users database next user Id: " << usersNextUserId_ << __E__;
00758
00759
00760 while (fgets(line, LINE_LEN, fp))
00761 {
00762 if (strlen(line) < 30) continue;
00763
00764 c = 0;
00765 len = strlen(line);
00766 if (len >= LINE_LEN)
00767 {
00768 __COUT__ << "Line buffer too small: " << len << __E__;
00769 break;
00770 }
00771
00772
00773 f = 0;
00774 for (i = 0; i < len; ++i)
00775 if (line[i] == '>')
00776 {
00777 ++c;
00778 if (c == 0 || c % 2 == 1) continue;
00779
00780 si = ++i;
00781 while (i < len && line[i] != '<') ++i;
00782 if (i == len)
00783 break;
00784 line[i] = '\0';
00785 f = c / 2 - 1;
00786
00787
00788
00789 if (f == 0)
00790 UsersUsernameVector.push_back(&line[si]);
00791 else if (f == 1)
00792 UsersDisplayNameVector.push_back(&line[si]);
00793 else if (f == 2)
00794 UsersSaltVector.push_back(&line[si]);
00795 else if (f == 3)
00796 {
00797 sscanf(&line[si], "%lu", &tmpInt64);
00798 UsersUserIdVector.push_back(tmpInt64);
00799 }
00800 else if (f == 4)
00801 {
00802 UsersPermissionsVector.push_back(std::map<std::string,uint8_t>());
00803 std::map<std::string,uint8_t>& lastPermissionsMap = UsersPermissionsVector.back();
00804 StringMacros::getMapFromString<uint8_t>(&line[si],
00805 lastPermissionsMap);
00806
00807
00808
00809
00810
00811 if(lastPermissionsMap.find(WebUsers::DEFAULT_USER_GROUP) ==
00812 lastPermissionsMap.end())
00813 {
00814
00815
00816 sscanf(&line[si], "%lu", &tmpInt64);
00817 tmpInt64 &= 0xFF;
00818 if(tmpInt64)
00819 {
00820 lastPermissionsMap.clear();
00821 __COUT_INFO__ << "User '" <<
00822 UsersUsernameVector.back() << "' is not a member of the default user group '" <<
00823 WebUsers::DEFAULT_USER_GROUP << ".' For backward compatibility, permission level assumed for default group (permission level := " <<
00824 tmpInt64 << ")." << __E__;
00825 lastPermissionsMap[WebUsers::DEFAULT_USER_GROUP] = WebUsers::permissionLevel_t(tmpInt64);
00826 }
00827 else
00828 {
00829 __MCOUT_INFO__( "User '" <<
00830 UsersUsernameVector.back() << "' is not a member of the default user group '" <<
00831 WebUsers::DEFAULT_USER_GROUP << ".' Assuming user account is inactive (permission level := " <<
00832 WebUsers::PERMISSION_LEVEL_INACTIVE << ")." << __E__);
00833 lastPermissionsMap[WebUsers::DEFAULT_USER_GROUP] = WebUsers::PERMISSION_LEVEL_INACTIVE;
00834 }
00835 }
00836 }
00837 else if (f == 5)
00838 {
00839 sscanf(&line[si], "%lu", &tmpInt64);
00840 UsersLastLoginAttemptVector.push_back(tmpInt64);
00841 }
00842 else if (f == 6)
00843 {
00844 sscanf(&line[si], "%lu", &tmpInt64);
00845 UsersAccountCreatedTimeVector.push_back(tmpInt64);
00846 }
00847 else if (f == 7)
00848 {
00849 sscanf(&line[si], "%lu", &tmpInt64);
00850 UsersLoginFailureCountVector.push_back(tmpInt64);
00851 }
00852 else if (f == 8)
00853 {
00854 sscanf(&line[si], "%lu", &tmpInt64);
00855 UsersLastModifiedTimeVector.push_back(tmpInt64);
00856 }
00857 else if (f == 9)
00858 UsersLastModifierUsernameVector.push_back(&line[si]);
00859 else if (f == 10)
00860 UsersUserEmailVector.push_back(&line[si]);
00861 }
00862
00863
00864
00865 if (f && f != UsersDatabaseEntryFields.size() - 1)
00866 {
00867 if (f != 7 && f != 9)
00868 {
00869 __SS__ << "FATAL ERROR - invalid user database found with field number " << f << __E__;
00870 fclose(fp);
00871 __SS_THROW__;
00872 return false;
00873 }
00874
00875 if (f == 7)
00876 {
00877
00878 __COUT__ << "Update database to current version - adding fields: " <<
00879 (UsersDatabaseEntryFields.size() - 1 - f) << __E__;
00880
00881 UsersLastModifiedTimeVector.push_back(0);
00882 UsersLastModifierUsernameVector.push_back("");
00883 }
00884 else
00885 {
00886 UsersUserEmailVector.push_back("");
00887 }
00888 }
00889 }
00890 fclose(fp);
00891 }
00892
00893 __COUT__ << UsersLastModifiedTimeVector.size() << " Users found." << __E__;
00894 for (size_t ii = 0; ii < UsersLastModifiedTimeVector.size(); ++ii)
00895 {
00896 __COUT__ << "User " << UsersUserIdVector[ii] << ": Name: " << UsersUsernameVector[ii] <<
00897 "\t\tDisplay Name: " << UsersDisplayNameVector[ii] << "\t\tEmail: " <<
00898 UsersUserEmailVector[ii] << "\t\tPermissions: " <<
00899 StringMacros::mapToString(UsersPermissionsVector[ii]) << __E__;
00900 }
00901 return true;
00902 }
00903
00904
00905
00906 void WebUsers::saveToDatabase(FILE * fp, const std::string& field, const std::string& value, uint8_t type, bool addNewLine)
00907 {
00908 if (!fp) return;
00909
00910 std::string newLine = addNewLine ? "\n" : "";
00911
00912 if (type == DB_SAVE_OPEN_AND_CLOSE)
00913 fprintf(fp, "<%s>%s</%s>%s", field.c_str(), value.c_str(), field.c_str(), newLine.c_str());
00914 else if (type == DB_SAVE_OPEN)
00915 fprintf(fp, "<%s>%s%s", field.c_str(), value.c_str(), newLine.c_str());
00916 else if (type == DB_SAVE_CLOSE)
00917 fprintf(fp, "</%s>%s", field.c_str(), newLine.c_str());
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928 bool WebUsers::saveDatabaseToFile(uint8_t db)
00929 {
00930 __COUT__ << "Save Database: " << (int)db << __E__;
00931
00932 std::string fn = (std::string)WEB_LOGIN_DB_PATH +
00933 ((db == DB_USERS) ? (std::string)USERS_DB_FILE : (std::string)HASHES_DB_FILE);
00934
00935 __COUT__ << "Save Database Filename: " << fn << __E__;
00936
00937
00938 if (0)
00939 {
00940 char dayAppend[20];
00941 sprintf(dayAppend, ".%lu.bkup", time(0) / (3600 * 24));
00942 std::string bkup_fn = (std::string)WEB_LOGIN_DB_PATH +
00943 (std::string)WEB_LOGIN_BKUP_DB_PATH +
00944 ((db == DB_USERS) ? (std::string)USERS_DB_FILE : (std::string)HASHES_DB_FILE) +
00945 (std::string)dayAppend;
00946
00947 __COUT__ << "Backup file: " << bkup_fn << __E__;
00948
00949 std::string shell_command = "mv " + fn + " " + bkup_fn;
00950 system(shell_command.c_str());
00951 }
00952
00953 FILE *fp = fopen(fn.c_str(), "wb");
00954 if (!fp) return false;
00955
00956 char fldStr[100];
00957
00958 if (db == DB_USERS)
00959 {
00960 saveToDatabase(fp, USERS_DB_GLOBAL_STRING, "", DB_SAVE_OPEN);
00961
00962 sprintf(fldStr, "%lu", usersNextUserId_);
00963 saveToDatabase(fp, USERS_DB_NEXT_UID_STRING, fldStr, DB_SAVE_OPEN_AND_CLOSE);
00964
00965 __COUT__ << "Saving " << UsersUsernameVector.size() << " Users." << __E__;
00966
00967 for (uint64_t i = 0; i < UsersUsernameVector.size(); ++i)
00968 {
00969
00970
00971 saveToDatabase(fp, USERS_DB_ENTRY_STRING, "", DB_SAVE_OPEN, false);
00972
00973 for (unsigned int f = 0; f < UsersDatabaseEntryFields.size(); ++f)
00974 {
00975
00976 if (f == 0)
00977 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersUsernameVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
00978 else if (f == 1)
00979 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersDisplayNameVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
00980 else if (f == 2)
00981 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersSaltVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
00982 else if (f == 3)
00983 {
00984 sprintf(fldStr, "%lu", UsersUserIdVector[i]);
00985 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
00986 }
00987 else if (f == 4)
00988 saveToDatabase(fp, UsersDatabaseEntryFields[f],
00989 StringMacros::mapToString(UsersPermissionsVector[i],",",":"), DB_SAVE_OPEN_AND_CLOSE, false);
00990 else if (f == 5)
00991 {
00992 sprintf(fldStr, "%lu", UsersLastLoginAttemptVector[i]);
00993 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
00994 }
00995 else if (f == 6)
00996 {
00997 sprintf(fldStr, "%lu", UsersAccountCreatedTimeVector[i]);
00998 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
00999 }
01000 else if (f == 7)
01001 {
01002 sprintf(fldStr, "%d", UsersLoginFailureCountVector[i]);
01003 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
01004 }
01005 else if (f == 8)
01006 {
01007 sprintf(fldStr, "%lu", UsersLastModifiedTimeVector[i]);
01008 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
01009 }
01010 else if (f == 9)
01011 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersLastModifierUsernameVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
01012 else if (f == 10)
01013 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersUserEmailVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
01014 }
01015
01016 saveToDatabase(fp, USERS_DB_ENTRY_STRING, "", DB_SAVE_CLOSE);
01017 }
01018
01019 saveToDatabase(fp, USERS_DB_GLOBAL_STRING, "", DB_SAVE_CLOSE);
01020
01021 }
01022 else
01023 {
01024 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING, "", DB_SAVE_OPEN);
01025
01026 __COUT__ << "Saving " << HashesVector.size() << " Hashes." << __E__;
01027 for (uint64_t i = 0; i < HashesVector.size(); ++i)
01028 {
01029 __COUT__ << "Saving " << HashesVector[i] << " Hashes." << __E__;
01030 saveToDatabase(fp, HASHES_DB_ENTRY_STRING, "", DB_SAVE_OPEN, false);
01031 for (unsigned int f = 0; f < HashesDatabaseEntryFields.size(); ++f)
01032 {
01033 if (f == 0)
01034 saveToDatabase(fp, HashesDatabaseEntryFields[f], HashesVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
01035 else if (f == 1)
01036 {
01037 sprintf(fldStr, "%lu", HashesAccessTimeVector[i]);
01038 saveToDatabase(fp, HashesDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
01039 }
01040 }
01041 saveToDatabase(fp, HASHES_DB_ENTRY_STRING, "", DB_SAVE_CLOSE);
01042 }
01043
01044 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING, "", DB_SAVE_CLOSE);
01045 }
01046
01047
01048 fclose(fp);
01049 return true;
01050 }
01051
01052
01053
01054
01055
01056
01057
01058
01059 bool WebUsers::createNewAccount(const std::string& username, const std::string& displayName,
01060 const std::string& email)
01061 {
01062 __COUT__ << "Creating account: " << username << __E__;
01063
01064 uint64_t i;
01065 if ((i = searchUsersDatabaseForUsername(username)) != NOT_FOUND_IN_DATABASE ||
01066 username == WebUsers::DEFAULT_ITERATOR_USERNAME ||
01067 username == WebUsers::DEFAULT_STATECHANGER_USERNAME)
01068 {
01069 __COUT_ERR__ << "Username '" << username << "' already exists" << __E__;
01070 return false;
01071 }
01072
01073
01074 UsersUsernameVector.push_back(username);
01075 UsersDisplayNameVector.push_back(displayName);
01076 UsersUserEmailVector.push_back(email);
01077 UsersSaltVector.push_back("");
01078 std::map<std::string ,WebUsers::permissionLevel_t> initPermissions = {{
01079 WebUsers::DEFAULT_USER_GROUP,
01080 (UsersPermissionsVector.size() ?
01081 WebUsers::PERMISSION_LEVEL_NOVICE:
01082 WebUsers::PERMISSION_LEVEL_ADMIN)}};
01083 UsersPermissionsVector.push_back(initPermissions);
01084
01085 UsersUserIdVector.push_back(usersNextUserId_++);
01086 if (usersNextUserId_ == (uint64_t)-1)
01087 {
01088 __COUT__ << "usersNextUserId_ wrap around!! Too many users??? Notify Admins." << __E__;
01089 usersNextUserId_ = 1;
01090 }
01091 UsersLastLoginAttemptVector.push_back(0);
01092 UsersLoginFailureCountVector.push_back(0);
01093 UsersAccountCreatedTimeVector.push_back(time(0));
01094 UsersLastModifiedTimeVector.push_back(0);
01095 UsersLastModifierUsernameVector.push_back("");
01096
01097 return saveDatabaseToFile(DB_USERS);
01098 }
01099
01100
01101
01102
01103
01104
01105
01106 bool WebUsers::deleteAccount(const std::string& username, const std::string& displayName)
01107 {
01108 uint64_t i = searchUsersDatabaseForUsername(username);
01109 if (i == NOT_FOUND_IN_DATABASE) return false;
01110 if (UsersDisplayNameVector[i] != displayName) return false;
01111
01112
01113
01114 UsersUsernameVector.erase(UsersUsernameVector.begin() + i);
01115 UsersUserEmailVector.erase(UsersUserEmailVector.begin() + i);
01116 UsersDisplayNameVector.erase(UsersDisplayNameVector.begin() + i);
01117 UsersSaltVector.erase(UsersSaltVector.begin() + i);
01118 UsersPermissionsVector.erase(UsersPermissionsVector.begin() + i);
01119 UsersUserIdVector.erase(UsersUserIdVector.begin() + i);
01120 UsersLastLoginAttemptVector.erase(UsersLastLoginAttemptVector.begin() + i);
01121 UsersAccountCreatedTimeVector.erase(UsersAccountCreatedTimeVector.begin() + i);
01122 UsersLoginFailureCountVector.erase(UsersLoginFailureCountVector.begin() + i);
01123 UsersLastModifierUsernameVector.erase(UsersLastModifierUsernameVector.begin() + i);
01124 UsersLastModifiedTimeVector.erase(UsersLastModifiedTimeVector.begin() + i);
01125
01126
01127 return saveDatabaseToFile(DB_USERS);
01128 }
01129
01130
01131 unsigned int WebUsers::hexByteStrToInt(const char *h)
01132 {
01133 unsigned int rv;
01134 char hs[3] = { h[0],h[1],'\0' };
01135 sscanf(hs, "%X", &rv);
01136 return rv;
01137 }
01138
01139
01140 void WebUsers::intToHexStr(unsigned char i, char *h)
01141 {
01142 sprintf(h, "%2.2X", i);
01143 }
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 uint64_t WebUsers::attemptActiveSession(const std::string& uuid, std::string& jumbledUser,
01157 const std::string& jumbledPw, std::string& newAccountCode, const std::string& ip)
01158 {
01159
01160 if(!checkIpAccess(ip))
01161 {
01162 __COUT_ERR__ << "rejected ip: " << ip << __E__;
01163 return NOT_FOUND_IN_DATABASE;
01164 }
01165
01166 cleanupExpiredEntries();
01167
01168 if (!CareAboutCookieCodes_)
01169 {
01170 uint64_t uid = getAdminUserID();
01171 jumbledUser = getUsersDisplayName(uid);
01172 newAccountCode = genCookieCode();
01173 return uid;
01174 }
01175
01176 uint64_t i;
01177
01178
01179 if ((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
01180 {
01181 __COUT_ERR__ << "uuid: " << uuid << " is not found" << __E__;
01182 newAccountCode = "1";
01183
01184 incrementIpBlacklistCount(ip);
01185
01186 return NOT_FOUND_IN_DATABASE;
01187 }
01188 ++LoginSessionAttemptsVector[i];
01189
01190 std::string user = dejumble(jumbledUser, LoginSessionIdVector[i]);
01191 __COUTV__(user);
01192 std::string pw = dejumble(jumbledPw, LoginSessionIdVector[i]);
01193
01194
01195 if ((i = searchUsersDatabaseForUsername(user)) == NOT_FOUND_IN_DATABASE)
01196 {
01197 __COUT_ERR__ << "user: " << user << " is not found" << __E__;
01198
01199 incrementIpBlacklistCount(ip);
01200
01201 return NOT_FOUND_IN_DATABASE;
01202 }
01203 else
01204 ipBlacklistCounts_[ip] = 0;
01205
01206 UsersLastLoginAttemptVector[i] = time(0);
01207
01208 if (isInactiveForGroup(UsersPermissionsVector[i]))
01209 {
01210 __MCOUT_ERR__("User '" << user << "' account INACTIVE (could be due to failed logins)" << __E__);
01211 return NOT_FOUND_IN_DATABASE;
01212 }
01213
01214 if (UsersSaltVector[i] == "")
01215 {
01216 __MCOUT__("First login attempt for user: " << user << __E__);
01217
01218 char charTimeStr[10];
01219 sprintf(charTimeStr, "%d", int(UsersAccountCreatedTimeVector[i] & 0xffff));
01220 std::string tmpTimeStr = charTimeStr;
01221 if (newAccountCode != tmpTimeStr)
01222 {
01223 __COUT__ << "New account code did not match: " << tmpTimeStr << " != " << newAccountCode << __E__;
01224 saveDatabaseToFile(DB_USERS);
01225 return NOT_FOUND_IN_DATABASE;
01226 }
01227
01228
01229
01230
01231 while (!addToHashesDatabase(sha512(user, pw, UsersSaltVector[i])))
01232 {
01233
01234
01235 UsersSaltVector[i] = "";
01236 }
01237
01238 __COUT__ << "\tHash added: " << HashesVector[HashesVector.size() - 1] << __E__;
01239 }
01240 else
01241 {
01242 std::string salt = UsersSaltVector[i];
01243
01244 if (searchHashesDatabaseForHash(sha512(user, pw, salt)) == NOT_FOUND_IN_DATABASE)
01245 {
01246 __COUT__ << "Failed login for " << user << " with permissions " <<
01247 StringMacros::mapToString(UsersPermissionsVector[i]) << __E__;
01248
01249 ++UsersLoginFailureCountVector[i];
01250 if (UsersLoginFailureCountVector[i] >= USERS_MAX_LOGIN_FAILURES)
01251 UsersPermissionsVector[i][WebUsers::DEFAULT_USER_GROUP] = WebUsers::PERMISSION_LEVEL_INACTIVE;
01252
01253 __COUT_INFO__ << "User/pw for user '" << user << "' was not correct (Failed Attempt #" <<
01254 (int)UsersLoginFailureCountVector[i] << " of " <<
01255 (int)USERS_MAX_LOGIN_FAILURES << ")." << __E__;
01256
01257 __COUTV__(isInactiveForGroup(UsersPermissionsVector[i]));
01258 if (isInactiveForGroup(UsersPermissionsVector[i]))
01259 __MCOUT_INFO__("Account '" << user << "' has been marked inactive due to too many failed login attempts (Failed Attempt #" <<
01260 (int)UsersLoginFailureCountVector[i] <<
01261 ")! Note only admins can reactivate accounts." << __E__);
01262
01263
01264 saveDatabaseToFile(DB_USERS);
01265 return NOT_FOUND_IN_DATABASE;
01266 }
01267 }
01268
01269 __MCOUT_INFO__("Login successful for: " << user << __E__);
01270
01271 UsersLoginFailureCountVector[i] = 0;
01272
01273
01274 for (int h = 0; h < 2; ++h)
01275 {
01276 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_LOGIN_HISTORY_PATH + (h ? USERS_GLOBAL_HISTORY_FILE : UsersUsernameVector[i])
01277 + "." + (std::string)USERS_LOGIN_HISTORY_FILETYPE;
01278
01279 HttpXmlDocument histXml;
01280
01281 if (histXml.loadXmlDocument(fn))
01282 {
01283 while (histXml.getChildrenCount() + 1 > (h ? USERS_GLOBAL_HISTORY_SIZE : USERS_LOGIN_HISTORY_SIZE))
01284 histXml.removeDataElement();
01285 }
01286 else
01287 __COUT__ << "No previous login history found." << __E__;
01288
01289
01290 char entryStr[500];
01291 if (h)
01292 sprintf(entryStr, "Time=%lu Username=%s Permissions=%s UID=%lu",
01293 time(0), UsersUsernameVector[i].c_str(),
01294 StringMacros::mapToString(UsersPermissionsVector[i]).c_str(), UsersUserIdVector[i]);
01295 else
01296 sprintf(entryStr, "Time=%lu displayName=%s Permissions=%s UID=%lu",
01297 time(0), UsersDisplayNameVector[i].c_str(),
01298 StringMacros::mapToString(UsersPermissionsVector[i]).c_str(), UsersUserIdVector[i]);
01299 histXml.addTextElementToData(PREF_XML_LOGIN_HISTORY_FIELD, entryStr);
01300
01301
01302 histXml.saveXmlDocument(fn);
01303 }
01304
01305
01306 saveDatabaseToFile(DB_USERS);
01307 jumbledUser = UsersDisplayNameVector[i];
01308 newAccountCode = createNewActiveSession(UsersUserIdVector[i],ip);
01309 return UsersUserIdVector[i];
01310 }
01311
01312
01313
01314
01315
01316
01317
01318
01319 uint64_t WebUsers::attemptActiveSessionWithCert(const std::string& uuid, std::string& email,
01320 std::string& cookieCode, std::string& user, const std::string& ip)
01321 {
01322 if (!checkIpAccess(ip))
01323 {
01324 __COUT_ERR__ << "rejected ip: " << ip << __E__;
01325 return NOT_FOUND_IN_DATABASE;
01326 }
01327
01328 cleanupExpiredEntries();
01329
01330 if (!CareAboutCookieCodes_)
01331 {
01332 uint64_t uid = getAdminUserID();
01333 email = getUsersDisplayName(uid);
01334 cookieCode = genCookieCode();
01335 return uid;
01336 }
01337
01338 if (email == "")
01339 {
01340 __COUT__ << "Rejecting logon with blank fingerprint" << __E__;
01341
01342 incrementIpBlacklistCount(ip);
01343
01344 return NOT_FOUND_IN_DATABASE;
01345 }
01346
01347 uint64_t i;
01348
01349
01350 if ((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
01351 {
01352 __COUT__ << "uuid: " << uuid << " is not found" << __E__;
01353 cookieCode = "1";
01354
01355 incrementIpBlacklistCount(ip);
01356
01357 return NOT_FOUND_IN_DATABASE;
01358 }
01359 ++LoginSessionAttemptsVector[i];
01360
01361 email = getUserEmailFromFingerprint(email);
01362 __COUT__ << "DejumbledEmail = " << email << __E__;
01363 if (email == "")
01364 {
01365 __COUT__ << "Rejecting logon with unknown fingerprint" << __E__;
01366
01367 incrementIpBlacklistCount(ip);
01368
01369 return NOT_FOUND_IN_DATABASE;
01370 }
01371
01372
01373 if ((i = searchUsersDatabaseForUserEmail(email)) == NOT_FOUND_IN_DATABASE)
01374 {
01375 __COUT__ << "email: " << email << " is not found" << __E__;
01376
01377 incrementIpBlacklistCount(ip);
01378
01379 return NOT_FOUND_IN_DATABASE;
01380 }
01381 else
01382 ipBlacklistCounts_[ip] = 0;
01383
01384 user = getUsersUsername(i);
01385
01386 UsersLastLoginAttemptVector[i] = time(0);
01387 if (isInactiveForGroup(UsersPermissionsVector[i]))
01388 {
01389 __MCOUT__ ("User '" << user << "' account INACTIVE (could be due to failed logins)." << __E__);
01390 return NOT_FOUND_IN_DATABASE;
01391 }
01392
01393 if (UsersSaltVector[i] == "")
01394 {
01395 return NOT_FOUND_IN_DATABASE;
01396 }
01397
01398 __MCOUT__("Login successful for: " << user << __E__);
01399
01400 UsersLoginFailureCountVector[i] = 0;
01401
01402
01403 for (int h = 0; h < 2; ++h)
01404 {
01405 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_LOGIN_HISTORY_PATH + (h ? USERS_GLOBAL_HISTORY_FILE : UsersUsernameVector[i])
01406 + "." + (std::string)USERS_LOGIN_HISTORY_FILETYPE;
01407
01408 HttpXmlDocument histXml;
01409
01410 if (histXml.loadXmlDocument(fn))
01411 {
01412 while (histXml.getChildrenCount() + 1 > (h ? USERS_GLOBAL_HISTORY_SIZE : USERS_LOGIN_HISTORY_SIZE))
01413 histXml.removeDataElement();
01414 }
01415 else
01416 __COUT__ << "No previous login history found." << __E__;
01417
01418
01419 char entryStr[500];
01420 if (h)
01421 sprintf(entryStr, "Time=%lu Username=%s Permissions=%s UID=%lu",
01422 time(0), UsersUsernameVector[i].c_str(),
01423 StringMacros::mapToString(UsersPermissionsVector[i]).c_str(), UsersUserIdVector[i]);
01424 else
01425 sprintf(entryStr, "Time=%lu displayName=%s Permissions=%s UID=%lu",
01426 time(0), UsersDisplayNameVector[i].c_str(),
01427 StringMacros::mapToString(UsersPermissionsVector[i]).c_str(), UsersUserIdVector[i]);
01428 histXml.addTextElementToData(PREF_XML_LOGIN_HISTORY_FIELD, entryStr);
01429
01430
01431 histXml.saveXmlDocument(fn);
01432 }
01433
01434
01435 saveDatabaseToFile(DB_USERS);
01436 email = UsersDisplayNameVector[i];
01437 cookieCode = createNewActiveSession(UsersUserIdVector[i],ip);
01438 return UsersUserIdVector[i];
01439 }
01440
01441
01442
01443
01444 uint64_t WebUsers::searchActiveSessionDatabaseForCookie(const std::string& cookieCode) const
01445 {
01446 uint64_t i = 0;
01447 for (; i < ActiveSessionCookieCodeVector.size(); ++i)
01448 if (ActiveSessionCookieCodeVector[i] == cookieCode) break;
01449 return (i == ActiveSessionCookieCodeVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01450 }
01451
01452
01453
01454
01455
01456 bool WebUsers::isUsernameActive(const std::string& username) const
01457 {
01458 uint64_t u;
01459 if ((u = searchUsersDatabaseForUsername(username)) == NOT_FOUND_IN_DATABASE) return false;
01460 return isUserIdActive(UsersUserIdVector[u]);
01461 }
01462
01463
01464
01465
01466
01467 bool WebUsers::isUserIdActive(uint64_t uid) const
01468 {
01469 uint64_t i = 0;
01470 for (; i < ActiveSessionUserIdVector.size(); ++i)
01471 if (ActiveSessionUserIdVector[i] == uid) return true;
01472 return false;
01473 }
01474
01475
01476
01477
01478 uint64_t WebUsers::searchUsersDatabaseForUsername(const std::string& username) const
01479 {
01480 uint64_t i = 0;
01481 for (; i < UsersUsernameVector.size(); ++i)
01482 if (UsersUsernameVector[i] == username) break;
01483 return (i == UsersUsernameVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01484 }
01485
01486
01487
01488
01489 uint64_t WebUsers::searchUsersDatabaseForUserEmail(const std::string& useremail) const
01490 {
01491 uint64_t i = 0;
01492 for (; i < UsersUserEmailVector.size(); ++i)
01493 if (UsersUserEmailVector[i] == useremail) break;
01494 return (i == UsersUserEmailVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01495 }
01496
01497
01498
01499
01500 uint64_t WebUsers::searchUsersDatabaseForUserId(uint64_t uid) const
01501 {
01502 uint64_t i = 0;
01503 for (; i < UsersUserIdVector.size(); ++i)
01504 if (UsersUserIdVector[i] == uid) break;
01505 return (i == UsersUserIdVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01506 }
01507
01508
01509
01510
01511 uint64_t WebUsers::searchLoginSessionDatabaseForUUID(const std::string& uuid) const
01512 {
01513 uint64_t i = 0;
01514 for (; i < LoginSessionUUIDVector.size(); ++i)
01515 if (LoginSessionUUIDVector[i] == uuid) break;
01516 return (i == LoginSessionUUIDVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01517 }
01518
01519
01520
01521
01522 uint64_t WebUsers::searchHashesDatabaseForHash(const std::string& hash)
01523 {
01524 uint64_t i = 0;
01525
01526
01527 for (; i < HashesVector.size(); ++i)
01528 if (HashesVector[i] == hash) break;
01529
01530
01531
01532 if (i < HashesAccessTimeVector.size())
01533 HashesAccessTimeVector.push_back((time(0) + (rand() % 2 ? 1 : -1)*(rand() % 30 * 24 * 60 * 60)) & 0x0FFFFFFFFFE000000);
01534
01535
01536 return (i == HashesVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01537 }
01538
01539
01540
01541
01542
01543 bool WebUsers::addToHashesDatabase(const std::string& hash)
01544 {
01545 if (searchHashesDatabaseForHash(hash) != NOT_FOUND_IN_DATABASE)
01546 {
01547 __COUT__ << "Hash collision: " << hash << __E__;
01548 return false;
01549 }
01550 HashesVector.push_back(hash);
01551 HashesAccessTimeVector.push_back((time(0) + (rand() % 2 ? 1 : -1)*(rand() % 30 * 24 * 60 * 60)) & 0x0FFFFFFFFFE000000);
01552
01553 return saveDatabaseToFile(DB_HASHES);
01554 }
01555
01556
01557
01558 std::string WebUsers::genCookieCode()
01559 {
01560 char hexStr[3];
01561 std::string cc = "";
01562 for (uint32_t i = 0; i < COOKIE_CODE_LENGTH / 2; ++i)
01563 {
01564 intToHexStr(rand(), hexStr);
01565 cc.append(hexStr);
01566 }
01567 return cc;
01568 }
01569
01570
01571
01572 void WebUsers::removeLoginSessionEntry(unsigned int i)
01573 {
01574 LoginSessionIdVector.erase(LoginSessionIdVector.begin() + i);
01575 LoginSessionUUIDVector.erase(LoginSessionUUIDVector.begin() + i);
01576 LoginSessionIpVector.erase(LoginSessionIpVector.begin() + i);
01577 LoginSessionStartTimeVector.erase(LoginSessionStartTimeVector.begin() + i);
01578 LoginSessionAttemptsVector.erase(LoginSessionAttemptsVector.begin() + i);
01579 }
01580
01581
01582
01583
01584
01585 std::string WebUsers::createNewActiveSession(uint64_t uid, const std::string& ip, uint64_t asIndex)
01586 {
01587
01588 ActiveSessionCookieCodeVector.push_back(genCookieCode());
01589 ActiveSessionIpVector.push_back(ip);
01590 ActiveSessionUserIdVector.push_back(uid);
01591 ActiveSessionStartTimeVector.push_back(time(0));
01592
01593 if (asIndex)
01594 ActiveSessionIndex.push_back(asIndex);
01595 else
01596 {
01597
01598 uint64_t max = 0;
01599 for (uint64_t j = 0; j < ActiveSessionIndex.size(); ++j)
01600 if (ActiveSessionUserIdVector[j] == uid && max < ActiveSessionIndex[j])
01601 max = ActiveSessionIndex[j];
01602
01603 ActiveSessionIndex.push_back(max ? max + 1 : 1);
01604 }
01605
01606 return ActiveSessionCookieCodeVector[ActiveSessionCookieCodeVector.size() - 1];
01607 }
01608
01609
01610
01611 void WebUsers::removeActiveSessionEntry(unsigned int i)
01612 {
01613 ActiveSessionCookieCodeVector.erase(ActiveSessionCookieCodeVector.begin() + i);
01614 ActiveSessionIpVector.erase(ActiveSessionIpVector.begin() + i);
01615 ActiveSessionUserIdVector.erase(ActiveSessionUserIdVector.begin() + i);
01616 ActiveSessionStartTimeVector.erase(ActiveSessionStartTimeVector.begin() + i);
01617 ActiveSessionIndex.erase(ActiveSessionIndex.begin() + i);
01618 }
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643 std::string WebUsers::refreshCookieCode(unsigned int i, bool enableRefresh)
01644 {
01645
01646 for (uint64_t j = ActiveSessionUserIdVector.size() - 1; j != (uint64_t)-1; --j)
01647 if (ActiveSessionUserIdVector[j] == ActiveSessionUserIdVector[i] &&
01648 ActiveSessionIndex[j] == ActiveSessionIndex[i])
01649 {
01650
01651
01652
01653 if (enableRefresh && (time(0) - ActiveSessionStartTimeVector[j] > ACTIVE_SESSION_EXPIRATION_TIME / 2))
01654 {
01655
01656 ActiveSessionStartTimeVector[j] = time(0) - ACTIVE_SESSION_EXPIRATION_TIME +
01657 ACTIVE_SESSION_COOKIE_OVERLAP_TIME;
01658
01659
01660 return createNewActiveSession(ActiveSessionUserIdVector[i], ActiveSessionIpVector[i], ActiveSessionIndex[i]);
01661 }
01662
01663 return ActiveSessionCookieCodeVector[j];
01664 }
01665
01666 return "0";
01667 }
01668
01669
01670
01671
01672
01673
01674 uint64_t WebUsers::isCookieCodeActiveForLogin(const std::string& uuid, std::string& cookieCode,
01675 std::string& username)
01676 {
01677 if (!CareAboutCookieCodes_)
01678 return getAdminUserID();
01679
01680
01681
01682
01683 if (!ActiveSessionStartTimeVector.size()) return NOT_FOUND_IN_DATABASE;
01684
01685 uint64_t i, j;
01686
01687
01688 if ((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
01689 {
01690 __COUT__ << "uuid not found: " << uuid << __E__;
01691 return NOT_FOUND_IN_DATABASE;
01692 }
01693
01694 username = dejumble(username, LoginSessionIdVector[i]);
01695
01696
01697 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
01698 {
01699 __COUT__ << "Cookie code not found" << __E__;
01700 return NOT_FOUND_IN_DATABASE;
01701 }
01702
01703
01704 if ((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
01705 {
01706 __COUT__ << "User ID not found" << __E__;
01707 return NOT_FOUND_IN_DATABASE;
01708 }
01709
01710
01711 if (UsersUsernameVector[j] != username)
01712 {
01713
01714 __COUT__ << "cookieCode: " << cookieCode << " was.." << __E__;
01715 __COUT__ << "username: " << username << " is not found" << __E__;
01716 return NOT_FOUND_IN_DATABASE;
01717 }
01718
01719 username = UsersDisplayNameVector[j];
01720 cookieCode = refreshCookieCode(i);
01721 return UsersUserIdVector[j];
01722 }
01723
01724
01725
01726
01727 uint64_t WebUsers::getActiveSessionCountForUser(uint64_t uid)
01728 {
01729 bool unique;
01730 std::vector<uint64_t> uniqueAsi;
01731
01732 uint64_t i, j;
01733 for (i = 0; i < ActiveSessionUserIdVector.size(); ++i)
01734 if (ActiveSessionUserIdVector[i] == uid)
01735 {
01736
01737 unique = true;
01738
01739 for (j = 0; j < uniqueAsi.size(); ++j)
01740 if (uniqueAsi[j] == ActiveSessionIndex[i])
01741 {
01742 unique = false; break;
01743 }
01744
01745 if (unique)
01746 uniqueAsi.push_back(ActiveSessionIndex[i]);
01747 }
01748
01749 __COUT__ << "Found " << uniqueAsi.size() << " active sessions for uid " << uid << __E__;
01750
01751 return uniqueAsi.size();
01752 }
01753
01754
01755
01756
01757
01758
01759
01760 bool WebUsers::checkIpAccess(const std::string& ip)
01761 {
01762 if(ip == "0") return true;
01763
01764 FILE *fp = fopen((IP_ACCEPT_FILE).c_str(),"r");
01765 char line[300];
01766 size_t len;
01767
01768 if(fp)
01769 {
01770 while(fgets(line,300,fp))
01771 {
01772 len = strlen(line);
01773
01774 if(len > 2 && line[len-1] == '\n')
01775 line[len-1] = '\0';
01776 if(StringMacros::wildCardMatch(ip,line))
01777 return true;
01778 }
01779
01780 fclose(fp);
01781 }
01782
01783 fp = fopen((IP_REJECT_FILE).c_str(),"r");
01784 if(fp)
01785 {
01786 while(fgets(line,300,fp))
01787 {
01788 len = strlen(line);
01789
01790 if(len > 2 && line[len-1] == '\n')
01791 line[len-1] = '\0';
01792 if(StringMacros::wildCardMatch(ip,line))
01793 return false;
01794 }
01795
01796 fclose(fp);
01797 }
01798
01799 fp = fopen((IP_BLACKLIST_FILE).c_str(),"r");
01800 if(fp)
01801 {
01802 while(fgets(line,300,fp))
01803 {
01804 len = strlen(line);
01805
01806 if(len > 2 && line[len-1] == '\n')
01807 line[len-1] = '\0';
01808 if(StringMacros::wildCardMatch(ip,line))
01809 return false;
01810 }
01811
01812 fclose(fp);
01813 }
01814
01815
01816 return true;
01817 }
01818
01819
01820
01821 void WebUsers::incrementIpBlacklistCount(const std::string& ip)
01822 {
01823
01824 auto it = ipBlacklistCounts_.find(ip);
01825 if(it == ipBlacklistCounts_.end())
01826 {
01827 __COUT__ << "First error for ip '" << ip << "'" << __E__;
01828 ipBlacklistCounts_[ip] = 1;
01829 }
01830 else
01831 {
01832 ++(it->second);
01833
01834 if(it->second >= IP_BLACKLIST_COUNT_THRESHOLD)
01835 {
01836 __MCOUT__("Adding IP '" << ip << "' to blacklist!" << __E__);
01837
01838
01839 FILE *fp = fopen((IP_BLACKLIST_FILE).c_str(),"a");
01840 if(!fp)
01841 {
01842 __SS__ << "IP black list file '" << IP_BLACKLIST_FILE << "' could not be opened." << __E__;
01843 __MCOUT_ERR__(ss.str());
01844 return;
01845 }
01846 fprintf(fp,"%s\n",ip.c_str());
01847 fclose(fp);
01848 }
01849 }
01850 }
01851
01852
01853
01854 std::string WebUsers::getUsersDisplayName(uint64_t uid)
01855 {
01856 uint64_t i;
01857 if ((i = searchUsersDatabaseForUserId(uid)) == NOT_FOUND_IN_DATABASE) return "";
01858 return UsersDisplayNameVector[i];
01859 }
01860
01861
01862
01863 std::string WebUsers::getUsersUsername(uint64_t uid)
01864 {
01865 uint64_t i;
01866 if ((i = searchUsersDatabaseForUserId(uid)) == NOT_FOUND_IN_DATABASE) return "";
01867 return UsersUsernameVector[i];
01868 }
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880 uint64_t WebUsers::cookieCodeLogout(const std::string& cookieCode, bool logoutOtherUserSessions,
01881 uint64_t *userId, const std::string& ip)
01882 {
01883 uint64_t i;
01884
01885
01886 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
01887 {
01888 __COUT__ << "Cookie code not found" << __E__;
01889
01890 incrementIpBlacklistCount(ip);
01891
01892 return NOT_FOUND_IN_DATABASE;
01893 }
01894 else
01895 ipBlacklistCounts_[ip] = 0;
01896
01897
01898
01899 if (ActiveSessionIpVector[i] != ip)
01900 {
01901 __COUT__ << "IP does not match active session" << __E__;
01902 return NOT_FOUND_IN_DATABASE;
01903 }
01904
01905
01906
01907
01908
01909
01910
01911 uint64_t asi = ActiveSessionIndex[i];
01912 uint64_t uid = ActiveSessionUserIdVector[i];
01913 if (userId) *userId = uid;
01914 uint64_t logoutCount = 0;
01915
01916 i = 0;
01917 while (i < ActiveSessionIndex.size())
01918 {
01919 if ((logoutOtherUserSessions && ActiveSessionUserIdVector[i] == uid &&
01920 ActiveSessionIndex[i] != asi) ||
01921 (!logoutOtherUserSessions && ActiveSessionUserIdVector[i] == uid &&
01922 ActiveSessionIndex[i] == asi))
01923 {
01924 __COUT__ << "Logging out of active session " << ActiveSessionUserIdVector[i]
01925 << "-" << ActiveSessionIndex[i] << __E__;
01926 removeActiveSessionEntry(i);
01927 ++logoutCount;
01928 }
01929 else
01930 ++i;
01931 }
01932
01933 __COUT__ << "Found and removed active session count = " << logoutCount << __E__;
01934
01935 return logoutCount;
01936 }
01937
01938
01939
01940 bool WebUsers::getUserInfoForCookie(std::string& cookieCode,
01941 std::string *userName, std::string *displayName,
01942 uint64_t *activeSessionIndex)
01943 {
01944 if (userName) *userName = "";
01945 if (displayName) *displayName = "";
01946
01947 if (!CareAboutCookieCodes_)
01948 {
01949 uint64_t uid = getAdminUserID();
01950 if (userName) *userName = getUsersUsername(uid);
01951 if (displayName) *displayName = getUsersDisplayName(uid);
01952 if (activeSessionIndex) *activeSessionIndex = -1;
01953 return true;
01954 }
01955
01956 uint64_t i, j;
01957
01958
01959 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
01960 {
01961 __COUT__ << "cookieCode NOT_FOUND_IN_DATABASE" << __E__;
01962 return false;
01963 }
01964
01965
01966 if ((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
01967 {
01968 __COUT__ << "ActiveSessionUserIdVector NOT_FOUND_IN_DATABASE" << __E__;
01969 return false;
01970 }
01971
01972 if (userName) *userName = UsersUsernameVector[j];
01973 if (displayName) *displayName = UsersDisplayNameVector[j];
01974 if (activeSessionIndex) *activeSessionIndex = ActiveSessionIndex[i];
01975 return true;
01976 }
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989 bool WebUsers::cookieCodeIsActiveForRequest(std::string& cookieCode,
01990 std::map<std::string /*groupName*/,WebUsers::permissionLevel_t>* userPermissions,
01991 uint64_t *uid, const std::string& ip,
01992 bool refresh, std::string *userWithLock,
01993 uint64_t* activeUserSessionIndex)
01994 {
01995
01996
01997
01998 if(!checkIpAccess(ip))
01999 {
02000 __COUT_ERR__ << "User IP rejected." << __E__;
02001 cookieCode = REQ_NO_LOGIN_RESPONSE;
02002 return false;
02003 }
02004
02005 cleanupExpiredEntries();
02006
02007 uint64_t i, j;
02008
02009
02010
02011
02012 if (!CareAboutCookieCodes_)
02013 {
02014 if (userPermissions) *userPermissions =
02015 std::map<std::string ,WebUsers::permissionLevel_t>({{
02016 WebUsers::DEFAULT_USER_GROUP,
02017 WebUsers::PERMISSION_LEVEL_ADMIN
02018 }});
02019 if (uid) *uid = getAdminUserID();
02020 if (userWithLock) *userWithLock = usersUsernameWithLock_;
02021 if (activeUserSessionIndex) *activeUserSessionIndex = -1;
02022
02023 if(cookieCode.size() != COOKIE_CODE_LENGTH)
02024 cookieCode = genCookieCode();
02025
02026 return true;
02027 }
02028
02029
02030
02031 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
02032 {
02033 __COUT_ERR__ << "Cookie code not found" << __E__;
02034 cookieCode = REQ_NO_LOGIN_RESPONSE;
02035
02036 incrementIpBlacklistCount(ip);
02037
02038 return false;
02039 }
02040 else
02041 ipBlacklistCounts_[ip] = 0;
02042
02043
02044 if (ip != "0" && ActiveSessionIpVector[i] != ip)
02045 {
02046 __COUTV__(ActiveSessionIpVector[i]);
02047
02048 __COUT_ERR__ << "IP does not match active session." << __E__;
02049 cookieCode = REQ_NO_LOGIN_RESPONSE;
02050 return false;
02051 }
02052
02053
02054 if ((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
02055 {
02056 __COUT_ERR__ << "User ID not found" << __E__;
02057 cookieCode = REQ_NO_LOGIN_RESPONSE;
02058 return false;
02059 }
02060
02061 std::map<std::string ,WebUsers::permissionLevel_t> tmpPerm =
02062 getPermissionsForUser(UsersUserIdVector[j]);
02063
02064 if (isInactiveForGroup(tmpPerm))
02065 {
02066 cookieCode = REQ_NO_PERMISSION_RESPONSE;
02067 return false;
02068 }
02069
02070
02071 if (userPermissions) *userPermissions = tmpPerm;
02072 if (uid) *uid = UsersUserIdVector[j];
02073 if (userWithLock) *userWithLock = usersUsernameWithLock_;
02074 if (activeUserSessionIndex) *activeUserSessionIndex = ActiveSessionIndex[i];
02075
02076 cookieCode = refreshCookieCode(i, refresh);
02077
02078 return true;
02079 }
02080
02081
02082
02083
02084
02085
02086
02087 void WebUsers::cleanupExpiredEntries(std::vector<std::string> *loggedOutUsernames)
02088 {
02089 uint64_t i;
02090 uint64_t tmpUid;
02091
02092 if (loggedOutUsernames)
02093 {
02094 for (i = 0; i < UsersLoggedOutUsernames_.size(); ++i)
02095 loggedOutUsernames->push_back(UsersLoggedOutUsernames_[i]);
02096 UsersLoggedOutUsernames_.clear();
02097 }
02098
02099
02100
02101
02102 for (i = 0; i < LoginSessionStartTimeVector.size(); ++i)
02103 if (LoginSessionStartTimeVector[i] + LOGIN_SESSION_EXPIRATION_TIME < time(0) ||
02104 LoginSessionAttemptsVector[i] > LOGIN_SESSION_ATTEMPTS_MAX)
02105 {
02106
02107
02108
02109 removeLoginSessionEntry(i);
02110 --i;
02111 }
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122 for (i = 0; i < ActiveSessionStartTimeVector.size(); ++i)
02123 if (ActiveSessionStartTimeVector[i] + ACTIVE_SESSION_EXPIRATION_TIME <= time(0))
02124 {
02125
02126
02127
02128
02129
02130 tmpUid = ActiveSessionUserIdVector[i];
02131 removeActiveSessionEntry(i);
02132
02133
02134
02135 if (!isUserIdActive(tmpUid))
02136 {
02137 if (loggedOutUsernames)
02138 loggedOutUsernames->push_back(UsersUsernameVector[searchUsersDatabaseForUserId(tmpUid)]);
02139 else
02140 UsersLoggedOutUsernames_.push_back(UsersUsernameVector[searchUsersDatabaseForUserId(tmpUid)]);
02141 }
02142
02143 --i;
02144 }
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157 if (CareAboutCookieCodes_ && !isUsernameActive(usersUsernameWithLock_))
02158 usersUsernameWithLock_ = "";
02159 }
02160
02161
02162
02163
02164
02165
02166
02167
02168 std::string WebUsers::createNewLoginSession(const std::string& UUID, const std::string& ip)
02169 {
02170 __COUTV__(UUID);
02171
02172
02173 uint64_t i = 0;
02174 for (; i < LoginSessionUUIDVector.size(); ++i)
02175 if (LoginSessionUUIDVector[i] == UUID) break;
02176
02177 if (i != LoginSessionUUIDVector.size())
02178 {
02179 __COUT_ERR__ << "UUID: " << UUID << " is not unique" << __E__;
02180 return "";
02181 }
02182
02183
02184 LoginSessionUUIDVector.push_back(UUID);
02185
02186
02187 char hexStr[3];
02188 std::string sid = "";
02189 for (i = 0; i < SESSION_ID_LENGTH / 2; ++i)
02190 {
02191 intToHexStr(rand(), hexStr);
02192 sid.append(hexStr);
02193 }
02194 LoginSessionIdVector.push_back(sid);
02195 LoginSessionIpVector.push_back(ip);
02196 LoginSessionStartTimeVector.push_back(time(0));
02197 LoginSessionAttemptsVector.push_back(0);
02198
02199 return sid;
02200 }
02201
02202
02203
02204
02205
02206
02207
02208
02209 std::string WebUsers::sha512(const std::string& user, const std::string& password, std::string& salt)
02210 {
02211 SHA512_CTX sha512_context;
02212 char hexStr[3];
02213
02214 if (salt == "")
02215 {
02216 SHA512_Init(&sha512_context);
02217
02218 for (unsigned int i = 0; i < 8; ++i)
02219 sha512_context.h[i] += rand();
02220
02221 for (unsigned int i = 0; i < sizeof(SHA512_CTX); ++i)
02222 {
02223 intToHexStr((uint8_t)(((uint8_t *)(&sha512_context))[i]), hexStr);
02224
02225 salt.append(hexStr);
02226 }
02227
02228 }
02229 else
02230 {
02231
02232
02233
02234 for (unsigned int i = 0; i < sizeof(SHA512_CTX); ++i)
02235 ((uint8_t *)(&sha512_context))[i] = hexByteStrToInt(&(salt.c_str()[i * 2]));
02236 }
02237
02238 std::string strToHash = salt + user + password;
02239
02240
02241 unsigned char hash[SHA512_DIGEST_LENGTH];
02242
02243 char retHash[SHA512_DIGEST_LENGTH * 2 + 1];
02244
02245
02246
02247
02248 SHA512_Update(&sha512_context, strToHash.c_str(), strToHash.length());
02249
02250 SHA512_Final(hash, &sha512_context);
02251
02252
02253 int i = 0;
02254 for (i = 0; i < SHA512_DIGEST_LENGTH; i++)
02255 sprintf(retHash + (i * 2), "%02x", hash[i]);
02256
02257
02258 retHash[SHA512_DIGEST_LENGTH * 2] = '\0';
02259
02260
02261
02262
02263
02264 return retHash;
02265 }
02266
02267
02268
02269
02270
02271
02272 std::string WebUsers::dejumble(const std::string& u, const std::string& s)
02273 {
02274
02275 if (s.length() != SESSION_ID_LENGTH) return "";
02276
02277 const int ss = s.length() / 2;
02278 int p = hexByteStrToInt(&(s.c_str()[0])) % ss;
02279 int n = hexByteStrToInt(&(s.c_str()[p * 2])) % ss;
02280 int len = (hexByteStrToInt(&(u.c_str()[p * 2])) - p - n + ss * 3) % ss;
02281
02282 std::vector<bool> x(ss);
02283 for (int i = 0; i < ss; ++i) x[i] = 0;
02284 x[p] = 1;
02285
02286 int c = hexByteStrToInt(&(u.c_str()[p * 2]));
02287
02288 std::string user = "";
02289
02290 for (int l = 0; l < len; ++l)
02291 {
02292 p = (p + hexByteStrToInt(&(s.c_str()[p * 2]))) % ss;
02293 while (x[p]) p = (p + 1) % ss;
02294 x[p] = 1;
02295 n = hexByteStrToInt(&(s.c_str()[p * 2]));
02296 user.append(1, (hexByteStrToInt(&(u.c_str()[p * 2])) - c - n + ss * 4) % ss);
02297 c = hexByteStrToInt(&(u.c_str()[p * 2]));
02298 }
02299
02300 return user;
02301 }
02302
02303
02304
02305
02306 std::map<std::string ,WebUsers::permissionLevel_t> WebUsers::getPermissionsForUser(
02307 uint64_t uid)
02308 {
02309
02310 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
02311
02312 if (userIndex < UsersPermissionsVector.size())
02313 return UsersPermissionsVector[userIndex];
02314
02315
02316 std::map<std::string ,WebUsers::permissionLevel_t> retErrorMap;
02317 retErrorMap[WebUsers::DEFAULT_USER_GROUP] =
02318 WebUsers::PERMISSION_LEVEL_INACTIVE;
02319 return retErrorMap;
02320 }
02321
02322
02323 WebUsers::permissionLevel_t WebUsers::getPermissionLevelForGroup(
02324 std::map<std::string /*groupName*/,WebUsers::permissionLevel_t>& permissionMap,
02325 const std::string& groupName)
02326 {
02327 auto it = permissionMap.find(groupName);
02328 if(it == permissionMap.end())
02329 {
02330 __COUT__ << "Group name '" << groupName << "' not found - assuming inactive user in this group." << __E__;
02331 return WebUsers::PERMISSION_LEVEL_INACTIVE;
02332 }
02333 return it->second;
02334 }
02335
02336
02337 bool WebUsers::isInactiveForGroup(
02338 std::map<std::string /*groupName*/,WebUsers::permissionLevel_t>& permissionMap,
02339 const std::string& groupName)
02340 {
02341 return getPermissionLevelForGroup(permissionMap,groupName) ==
02342 WebUsers::PERMISSION_LEVEL_INACTIVE;
02343 }
02344
02345
02346 bool WebUsers::isAdminForGroup(
02347 std::map<std::string /*groupName*/,WebUsers::permissionLevel_t>& permissionMap,
02348 const std::string& groupName)
02349 {
02350 return getPermissionLevelForGroup(permissionMap,groupName) ==
02351 WebUsers::PERMISSION_LEVEL_ADMIN;
02352 }
02353
02354
02355
02356
02357 std::string WebUsers::getTooltipFilename(
02358 const std::string& username, const std::string& srcFile,
02359 const std::string& srcFunc, const std::string& srcId)
02360 {
02361 std::string filename = (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH + "/";
02362
02363
02364
02365 mkdir(((std::string)WEB_LOGIN_DB_PATH).c_str(), 0755);
02366 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH).c_str(), 0755);
02367 mkdir(filename.c_str(), 0755);
02368
02369 for (const char& c : username)
02370 if (
02371 (c >= 'a' && c <= 'z') ||
02372 (c >= 'A' && c <= 'Z') ||
02373 (c >= '0' && c <= '9'))
02374 filename += c;
02375 filename += "/";
02376
02377
02378 mkdir(filename.c_str(), 0755);
02379
02380 for (const char& c : srcFile)
02381 if (
02382 (c >= 'a' && c <= 'z') ||
02383 (c >= 'A' && c <= 'Z') ||
02384 (c >= '0' && c <= '9'))
02385 filename += c;
02386 filename += "_";
02387 for (const char& c : srcFunc)
02388 if (
02389 (c >= 'a' && c <= 'z') ||
02390 (c >= 'A' && c <= 'Z') ||
02391 (c >= '0' && c <= '9'))
02392 filename += c;
02393 filename += "_";
02394 for (const char& c : srcId)
02395 if (
02396 (c >= 'a' && c <= 'z') ||
02397 (c >= 'A' && c <= 'Z') ||
02398 (c >= '0' && c <= '9'))
02399 filename += c;
02400 filename += ".tip";
02401
02402 return filename;
02403 }
02404
02405 std::string ots::WebUsers::getUserEmailFromFingerprint(const std::string& fingerprint)
02406 {
02407 std::ifstream f(WEB_LOGIN_CERTDATA_PATH);
02408 if (f.is_open())
02409 {
02410 std::string email;
02411 std::string fp;
02412 getline(f, email);
02413 getline(f, fp);
02414 certFingerprints_[email] = fp;
02415 f.close();
02416 remove(WEB_LOGIN_CERTDATA_PATH.c_str());
02417 }
02418
02419 for (auto fp : certFingerprints_)
02420 {
02421 if (fp.second == fingerprint) return fp.first;
02422 }
02423 return "";
02424 }
02425
02426
02427
02428
02429 void WebUsers::tooltipSetNeverShowForUsername(const std::string& username,
02430 HttpXmlDocument *xmldoc,
02431 const std::string& srcFile, const std::string& srcFunc,
02432 const std::string& srcId, bool doNeverShow, bool temporarySilence)
02433 {
02434
02435 __COUT__ << "Setting tooltip never show for user: " << username <<
02436 " to " << doNeverShow << " (temporarySilence=" <<
02437 temporarySilence << ")" << __E__;
02438
02439
02440 std::string filename = getTooltipFilename(username, srcFile, srcFunc, srcId);
02441 FILE *fp = fopen(filename.c_str(), "w");
02442 if (fp)
02443 {
02444 if (temporarySilence)
02445 fprintf(fp, "%ld", time(0) + 60 * 60);
02446 else
02447 fputc(doNeverShow ? '1' : '0', fp);
02448 fclose(fp);
02449 }
02450 else
02451 __COUT_ERR__ << "Big problme with tooltips! File not accessible: " << filename << __E__;
02452 }
02453
02454
02455
02456
02457
02458
02459
02460
02461 void WebUsers::tooltipCheckForUsername(const std::string& username,
02462 HttpXmlDocument *xmldoc,
02463 const std::string& srcFile, const std::string& srcFunc,
02464 const std::string& srcId)
02465 {
02466 if (srcId == "ALWAYS")
02467 {
02468
02469 xmldoc->addTextElementToData("ShowTooltip", "1");
02470 return;
02471 }
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481 std::string filename = getTooltipFilename(username, srcFile, srcFunc, srcId);
02482 FILE *fp = fopen(filename.c_str(), "r");
02483 if (fp)
02484 {
02485 time_t val;
02486 char line[100];
02487 fgets(line, 100, fp);
02488
02489 sscanf(line, "%ld", &val);
02490 __COUT__ << "tooltip value read = " << val << __E__;
02491 fclose(fp);
02492
02493
02494
02495 xmldoc->addTextElementToData("ShowTooltip", val == 1 ? "0" :
02496 (time(0) > val ? "1" : "0"));
02497 }
02498 else
02499 xmldoc->addTextElementToData("ShowTooltip", "1");
02500 }
02501
02502
02503
02504 void WebUsers::resetAllUserTooltips(const std::string& userNeedle)
02505 {
02506 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH +
02507 "/" + userNeedle).c_str());
02508 __COUT__ << "Successfully reset Tooltips for user " << userNeedle << __E__;
02509 }
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529 void WebUsers::insertSettingsForUser(uint64_t uid, HttpXmlDocument *xmldoc, bool includeAccounts)
02530 {
02531 std::map<std::string ,WebUsers::permissionLevel_t> permissionMap =
02532 getPermissionsForUser(uid);
02533 __COUTV__(StringMacros::mapToString(permissionMap));
02534 if (isInactiveForGroup(permissionMap)) return;
02535
02536 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
02537 __COUT__ << "Gettings settings for user: " << UsersUsernameVector[userIndex] << __E__;
02538
02539 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH + UsersUsernameVector[userIndex] + "." + (std::string)USERS_PREFERENCES_FILETYPE;
02540
02541 HttpXmlDocument prefXml;
02542
02543 __COUT__ << "Preferences file: " << fn << __E__;
02544
02545 if (!prefXml.loadXmlDocument(fn))
02546 {
02547 __COUT__ << "Preferences are defaults." << __E__;
02548
02549 xmldoc->addTextElementToData(PREF_XML_BGCOLOR_FIELD, PREF_XML_BGCOLOR_DEFAULT);
02550 xmldoc->addTextElementToData(PREF_XML_DBCOLOR_FIELD, PREF_XML_DBCOLOR_DEFAULT);
02551 xmldoc->addTextElementToData(PREF_XML_WINCOLOR_FIELD, PREF_XML_WINCOLOR_DEFAULT);
02552 xmldoc->addTextElementToData(PREF_XML_LAYOUT_FIELD, PREF_XML_LAYOUT_DEFAULT);
02553 }
02554 else
02555 {
02556 __COUT__ << "Saved Preferences found." << __E__;
02557 xmldoc->copyDataChildren(prefXml);
02558 }
02559
02560 char permStr[10];
02561
02562
02563 if (includeAccounts &&
02564 isAdminForGroup(permissionMap))
02565 {
02566
02567 __COUT__ << "Admin on our hands" << __E__;
02568
02569 xmldoc->addTextElementToData(PREF_XML_ACCOUNTS_FIELD, "");
02570
02571
02572
02573 for (uint64_t i = 0; i < UsersUsernameVector.size(); ++i)
02574 {
02575 xmldoc->addTextElementToParent("username", UsersUsernameVector[i], PREF_XML_ACCOUNTS_FIELD);
02576 xmldoc->addTextElementToParent("display_name", UsersDisplayNameVector[i], PREF_XML_ACCOUNTS_FIELD);
02577
02578 if (UsersUserEmailVector.size() > i)
02579 {
02580 xmldoc->addTextElementToParent("useremail", UsersUserEmailVector[i], PREF_XML_ACCOUNTS_FIELD);
02581 }
02582 else
02583 {
02584 xmldoc->addTextElementToParent("useremail", "", PREF_XML_ACCOUNTS_FIELD);
02585 }
02586
02587 sprintf(permStr, "%s", StringMacros::mapToString(
02588 UsersPermissionsVector[i]).c_str());
02589 xmldoc->addTextElementToParent("permissions", permStr, PREF_XML_ACCOUNTS_FIELD);
02590 if (UsersSaltVector[i] == "")
02591 sprintf(permStr, "%d", int(UsersAccountCreatedTimeVector[i] & 0xffff));
02592 else
02593 permStr[0] = '\0';
02594 xmldoc->addTextElementToParent("nac", permStr, PREF_XML_ACCOUNTS_FIELD);
02595 }
02596 }
02597
02598
02599 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
02600 (std::string)SYSTEM_PREFERENCES_PREFIX + "." + (std::string)USERS_PREFERENCES_FILETYPE;
02601 if (!prefXml.loadXmlDocument(fn))
02602 {
02603 __COUT__ << "System Preferences are defaults." << __E__;
02604
02605 xmldoc->addTextElementToData(PREF_XML_SYSLAYOUT_FIELD, PREF_XML_SYSLAYOUT_DEFAULT);
02606 }
02607 else
02608 {
02609 __COUT__ << "Saved System Preferences found." << __E__;
02610 xmldoc->copyDataChildren(prefXml);
02611 }
02612
02613
02614 sprintf(permStr, "%s", StringMacros::mapToString(permissionMap).c_str());
02615 xmldoc->addTextElementToData(PREF_XML_PERMISSIONS_FIELD, permStr);
02616
02617
02618 xmldoc->addTextElementToData(PREF_XML_USERLOCK_FIELD, usersUsernameWithLock_);
02619
02620 xmldoc->addTextElementToData(PREF_XML_USERNAME_FIELD, getUsersUsername(uid));
02621 }
02622
02623
02624
02625
02626 void WebUsers::setGenericPreference(uint64_t uid, const std::string& preferenceName,
02627 const std::string& preferenceValue)
02628 {
02629 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
02630
02631
02632
02633 std::string safePreferenceName = "";
02634 for (const auto &c : preferenceName)
02635 if ((c >= 'a' && c <= 'z') ||
02636 (c >= 'A' && c <= 'Z') ||
02637 (c >= '0' && c <= '9') ||
02638 (c >= '-' || c <= '_'))
02639 safePreferenceName += c;
02640
02641 std::string dir = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
02642 "generic_" + safePreferenceName + "/";
02643
02644
02645 mkdir(dir.c_str(), 0755);
02646
02647 std::string fn = UsersUsernameVector[userIndex] + "_" + safePreferenceName +
02648 "." + (std::string)USERS_PREFERENCES_FILETYPE;
02649
02650 __COUT__ << "Preferences file: " << (dir + fn) << __E__;
02651
02652 FILE *fp = fopen((dir + fn).c_str(), "w");
02653 if (fp)
02654 {
02655 fprintf(fp, "%s", preferenceValue.c_str());
02656 fclose(fp);
02657 }
02658 else
02659 __COUT_ERR__ << "Preferences file could not be opened for writing!" << __E__;
02660 }
02661
02662
02663
02664
02665
02666 std::string WebUsers::getGenericPreference(uint64_t uid, const std::string& preferenceName,
02667 HttpXmlDocument *xmldoc) const
02668 {
02669 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
02670
02671
02672
02673 std::string safePreferenceName = "";
02674 for (const auto &c : preferenceName)
02675 if ((c >= 'a' && c <= 'z') ||
02676 (c >= 'A' && c <= 'Z') ||
02677 (c >= '0' && c <= '9') ||
02678 (c >= '-' || c <= '_'))
02679 safePreferenceName += c;
02680
02681 std::string dir = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
02682 "generic_" + safePreferenceName + "/";
02683
02684 std::string fn = UsersUsernameVector[userIndex] + "_" + safePreferenceName +
02685 "." + (std::string)USERS_PREFERENCES_FILETYPE;
02686
02687 __COUT__ << "Preferences file: " << (dir + fn) << __E__;
02688
02689
02690 FILE *fp = fopen((dir + fn).c_str(), "rb");
02691 if (fp)
02692 {
02693 fseek(fp, 0, SEEK_END);
02694 long size = ftell(fp);
02695 std::string line;
02696 line.reserve(size + 1);
02697 rewind(fp);
02698 fgets(&line[0], size + 1, fp);
02699 fclose(fp);
02700
02701 __COUT__ << "Read value " << line << __E__;
02702 if (xmldoc) xmldoc->addTextElementToData(safePreferenceName, line);
02703 return line;
02704 }
02705 else
02706 __COUT__ << "Using default value." << __E__;
02707
02708
02709 if (xmldoc) xmldoc->addTextElementToData(safePreferenceName, "");
02710 return "";
02711 }
02712
02713
02714
02715 void WebUsers::changeSettingsForUser(uint64_t uid, const std::string& bgcolor, const std::string& dbcolor,
02716 const std::string& wincolor, const std::string& layout, const std::string& syslayout)
02717 {
02718 std::map<std::string ,WebUsers::permissionLevel_t> permissionMap =
02719 getPermissionsForUser(uid);
02720 if (isInactiveForGroup(permissionMap)) return;
02721
02722 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
02723 __COUT__ << "Changing settings for user: " << UsersUsernameVector[userIndex] << __E__;
02724
02725 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH + UsersUsernameVector[userIndex] + "." + (std::string)USERS_PREFERENCES_FILETYPE;
02726
02727 __COUT__ << "Preferences file: " << fn << __E__;
02728
02729 HttpXmlDocument prefXml;
02730 prefXml.addTextElementToData(PREF_XML_BGCOLOR_FIELD, bgcolor);
02731 prefXml.addTextElementToData(PREF_XML_DBCOLOR_FIELD, dbcolor);
02732 prefXml.addTextElementToData(PREF_XML_WINCOLOR_FIELD, wincolor);
02733 prefXml.addTextElementToData(PREF_XML_LAYOUT_FIELD, layout);
02734
02735 prefXml.saveXmlDocument(fn);
02736
02737
02738 if (!isAdminForGroup(permissionMap)) return;
02739
02740
02741 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
02742 (std::string)SYSTEM_PREFERENCES_PREFIX + "." + (std::string)USERS_PREFERENCES_FILETYPE;
02743
02744 HttpXmlDocument sysPrefXml;
02745 sysPrefXml.addTextElementToData(PREF_XML_SYSLAYOUT_FIELD, syslayout);
02746
02747 sysPrefXml.saveXmlDocument(fn);
02748
02749 }
02750
02751
02752
02753
02754
02755
02756 bool WebUsers::setUserWithLock(uint64_t actingUid, bool lock,
02757 const std::string& username)
02758 {
02759 std::map<std::string ,WebUsers::permissionLevel_t> permissionMap =
02760 getPermissionsForUser(actingUid);
02761
02762 std::string actingUser = getUsersUsername(actingUid);
02763
02764 __COUTV__(actingUser);
02765 __COUT__ << "Permissions: " << StringMacros::mapToString(permissionMap) << __E__;
02766 __COUTV__(usersUsernameWithLock_);
02767 __COUTV__(lock);
02768 __COUTV__(username);
02769 __COUTV__(isUsernameActive(username));
02770
02771
02772 if (lock && (isUsernameActive(username) || !CareAboutCookieCodes_))
02773 {
02774 if (!CareAboutCookieCodes_ && username != DEFAULT_ADMIN_USERNAME)
02775 {
02776 __MCOUT_ERR__("User '" << actingUser << "' tried to lock for a user other than admin in wiz mode. Not allowed." << __E__);
02777 return false;
02778 }
02779 else if (!isAdminForGroup(permissionMap) && actingUser != username)
02780 {
02781 __MCOUT_ERR__("A non-admin user '" << actingUser <<
02782 "' tried to lock for a user other than self. Not allowed." << __E__);
02783 return false;
02784 }
02785 usersUsernameWithLock_ = username;
02786 }
02787 else if (!lock && usersUsernameWithLock_ == username)
02788 usersUsernameWithLock_ = "";
02789 else
02790 {
02791 if (!isUsernameActive(username))
02792 __MCOUT_ERR__("User '" << username << "' is inactive." << __E__);
02793 __MCOUT_ERR__("Failed to lock for user '" << username << ".'" << __E__);
02794 return false;
02795 }
02796
02797 __MCOUT_INFO__("User '" << username << "' has locked out the system!" << __E__);
02798
02799
02800 {
02801 std::string securityFileName = USER_WITH_LOCK_FILE;
02802 FILE *fp = fopen(securityFileName.c_str(), "w");
02803 if (!fp)
02804 {
02805 __COUT_INFO__ << "USER_WITH_LOCK_FILE " << USER_WITH_LOCK_FILE <<
02806 " not found. Ignoring." << __E__;
02807 }
02808 else
02809 {
02810 fprintf(fp, "%s", usersUsernameWithLock_.c_str());
02811 fclose(fp);
02812 }
02813 }
02814 return true;
02815 }
02816
02817
02818
02819 void WebUsers::modifyAccountSettings(uint64_t actingUid, uint8_t cmd_type,
02820 const std::string& username, const std::string& displayname,
02821 const std::string& email, const std::string& permissions)
02822 {
02823
02824 std::map<std::string ,WebUsers::permissionLevel_t> permissionMap =
02825 getPermissionsForUser(actingUid);
02826 if (!isAdminForGroup(permissionMap))
02827 {
02828 __MCOUT_ERR__("Only admins can modify user settings." << __E__);
02829 return;
02830 }
02831
02832 uint64_t modi = searchUsersDatabaseForUsername(username);
02833 if (modi == 0)
02834 {
02835 __MCOUT_ERR__("Cannot modify first user" << __E__);
02836 return;
02837 }
02838
02839 if (username.length() < USERNAME_LENGTH || displayname.length() < DISPLAY_NAME_LENGTH)
02840 {
02841 __MCOUT_ERR__("Invalid Username or Display Name must be length " << USERNAME_LENGTH <<
02842 " or " << DISPLAY_NAME_LENGTH << __E__);
02843 return;
02844 }
02845
02846 __COUT__ << "Input Permissions: " << permissions << __E__;
02847 std::map<std::string ,WebUsers::permissionLevel_t> newPermissionsMap;
02848
02849 switch (cmd_type)
02850 {
02851 case MOD_TYPE_UPDATE:
02852
02853 __COUT__ << "MOD_TYPE_UPDATE " << username << " := " << permissions << __E__;
02854
02855 if (modi == NOT_FOUND_IN_DATABASE)
02856 {
02857 __COUT__ << "User not found!? Should not happen." << __E__;
02858 return;
02859 }
02860
02861 UsersDisplayNameVector[modi] = displayname;
02862 UsersUserEmailVector[modi] = email;
02863
02864 StringMacros::getMapFromString(permissions,newPermissionsMap);
02865
02866
02867
02868 if (isInactiveForGroup(UsersPermissionsVector[modi]) &&
02869 !isInactiveForGroup(newPermissionsMap))
02870 {
02871 UsersLoginFailureCountVector[modi] = 0;
02872 UsersSaltVector[modi] = "";
02873 }
02874 UsersPermissionsVector[modi] = newPermissionsMap;
02875
02876
02877 {
02878 uint64_t i = searchUsersDatabaseForUserId(actingUid);
02879 if (i == NOT_FOUND_IN_DATABASE)
02880 {
02881 __COUT__ << "Master User not found!? Should not happen." << __E__;
02882 return;
02883 }
02884 UsersLastModifierUsernameVector[modi] = UsersUsernameVector[i];
02885 UsersLastModifiedTimeVector[modi] = time(0);
02886 }
02887 break;
02888 case MOD_TYPE_ADD:
02889 __COUT__ << "MOD_TYPE_ADD " << username << " - " << displayname << __E__;
02890 createNewAccount(username, displayname, email);
02891 break;
02892 case MOD_TYPE_DELETE:
02893 __COUT__ << "MOD_TYPE_DELETE " << username << " - " << displayname << __E__;
02894 deleteAccount(username, displayname);
02895 break;
02896 default:
02897 __COUT__ << "Undefined command - do nothing " << username << __E__;
02898 }
02899
02900 saveDatabaseToFile(DB_USERS);
02901 }
02902
02903
02904
02905 std::string WebUsers::getActiveUsersString()
02906 {
02907 std::string ret = "";
02908 uint64_t u;
02909 bool repeat;
02910 for (uint64_t i = 0; i < ActiveSessionUserIdVector.size(); ++i)
02911 {
02912 repeat = false;
02913
02914 for (uint64_t j = 0; j < i; ++j)
02915 if (ActiveSessionUserIdVector[i] == ActiveSessionUserIdVector[j])
02916 {
02917 repeat = true; break;
02918 }
02919
02920 if (!repeat && (u = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) !=
02921 NOT_FOUND_IN_DATABASE)
02922 ret += UsersDisplayNameVector[u] + ",";
02923 }
02924 if (ret.length() > 1) ret.erase(ret.length() - 1);
02925 return ret;
02926 }
02927
02928
02929
02930 uint64_t WebUsers::getAdminUserID()
02931 {
02932 uint64_t uid = searchUsersDatabaseForUsername(DEFAULT_ADMIN_USERNAME);
02933 return uid;
02934 }
02935
02936
02937
02938
02939
02940 void WebUsers::loadUserWithLock()
02941 {
02942 char username[300] = "";
02943
02944 std::string securityFileName = USER_WITH_LOCK_FILE;
02945 FILE *fp = fopen(securityFileName.c_str(), "r");
02946 if (!fp)
02947 {
02948 __COUT_INFO__ << "USER_WITH_LOCK_FILE " << USER_WITH_LOCK_FILE <<
02949 " not found. Defaulting to admin lock." << __E__;
02950
02951
02952 sprintf(username, "%s", DEFAULT_ADMIN_USERNAME.c_str());
02953 }
02954 else
02955 {
02956 fgets(username, 300, fp);
02957 username[299] = '\0';
02958 fclose(fp);
02959 }
02960
02961
02962 __COUT__ << "Attempting to load username with lock: " << username << __E__;
02963
02964 if (strlen(username) == 0)
02965 {
02966 __COUT_INFO__ << "Loaded state for user-with-lock is unlocked." << __E__;
02967 return;
02968 }
02969
02970 uint64_t i = searchUsersDatabaseForUsername(username);
02971 if (i == NOT_FOUND_IN_DATABASE)
02972 {
02973 __COUT_INFO__ << "username " << username <<
02974 " not found in database. Ignoring." << __E__;
02975 return;
02976 }
02977 __COUT__ << "Setting lock" << __E__;
02978 setUserWithLock(UsersUserIdVector[i], true, username);
02979 }
02980
02981
02982
02983
02984 std::string WebUsers::getSecurity()
02985 {
02986 return securityType_;
02987 }
02988
02989
02990
02991 void WebUsers::loadSecuritySelection()
02992 {
02993 std::string securityFileName = SECURITY_FILE_NAME;
02994 FILE *fp = fopen(securityFileName.c_str(), "r");
02995 char line[100] = "";
02996 if (fp) fgets(line, 100, fp);
02997 unsigned int i = 0;
02998
02999
03000 while (i < strlen(line) && line[i] >= 'A' && line[i] <= 'z') ++i;
03001 line[i] = '\0';
03002
03003
03004 if (strcmp(line, SECURITY_TYPE_NONE.c_str()) == 0 ||
03005 strcmp(line, SECURITY_TYPE_DIGEST_ACCESS.c_str()) == 0)
03006 securityType_ = line;
03007 else
03008 securityType_ = SECURITY_TYPE_NONE;
03009
03010 __COUT__ << "The current security type is " << securityType_ << __E__;
03011
03012 if (fp) fclose(fp);
03013
03014
03015 if (securityType_ == SECURITY_TYPE_NONE)
03016 CareAboutCookieCodes_ = false;
03017 else
03018 CareAboutCookieCodes_ = true;
03019
03020 __COUT__ << "CareAboutCookieCodes_: " <<
03021 CareAboutCookieCodes_ << __E__;
03022
03023 }
03024
03025
03026
03027
03028 void WebUsers::NACDisplayThread(const std::string& nac, const std::string& user)
03029 {
03030 INIT_MF("WebUsers_NAC");
03032
03033
03034
03035
03036 int i = 0;
03037 for (; i < 5; ++i)
03038 {
03039 std::this_thread::sleep_for(std::chrono::seconds(2));
03040 __COUT__ << "\n******************************************************************** " << __E__;
03041 __COUT__ << "\n******************************************************************** " << __E__;
03042 __COUT__ << "\n\nNew account code = " << nac << " for user: " << user << "\n" << __E__;
03043 __COUT__ << "\n******************************************************************** " << __E__;
03044 __COUT__ << "\n******************************************************************** " << __E__;
03045 }
03046 }
03047
03048
03049 void WebUsers::deleteUserData()
03050 {
03051
03052 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + HASHES_DB_PATH + "/*").c_str());
03053 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH + "/*").c_str());
03054 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_LOGIN_HISTORY_PATH + "/*").c_str());
03055 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_PREFERENCES_PATH + "/*").c_str());
03056 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH).c_str());
03057
03058 std::string serviceDataPath = getenv("SERVICE_DATA_PATH");
03059
03060 std::system(("rm -rf " + std::string(serviceDataPath) + "/MacroData/").c_str());
03061 std::system(("rm -rf " + std::string(serviceDataPath) + "/MacroHistory/").c_str());
03062 std::system(("rm -rf " + std::string(serviceDataPath) + "/MacroExport/").c_str());
03063
03064
03065 std::system(("rm -rf " + std::string(serviceDataPath) + "/ConsolePreferences/").c_str());
03066
03067
03068 std::system(("rm -rf " + std::string(serviceDataPath) + "/OtsWizardData/").c_str());
03069
03070
03071 std::system(("rm -rf " + std::string(serviceDataPath) + "/ProgressBarData/").c_str());
03072
03073
03074 std::system(("rm -rf " + std::string(serviceDataPath) + "/RunNumber/").c_str());
03075 std::system(("rm -rf " + std::string(serviceDataPath) + "/RunControlData/").c_str());
03076
03077
03078 std::system(("rm -rf " + std::string(serviceDataPath) + "/VisualizerData/").c_str());
03079
03080
03081
03082
03083
03084 std::system(("rm -rf " + std::string(getenv("LOGBOOK_DATA_PATH")) + "/").c_str());
03085
03086 std::cout << __COUT_HDR_FL__ << "$$$$$$$$$$$$$$ Successfully deleted ALL service user data $$$$$$$$$$$$" << __E__;
03087 }
03088
03089