00001 #include "otsdaq-core/WebUsersUtilities/WebUsers.h"
00002 #include "otsdaq-core/MessageFacility/MessageFacility.h"
00003 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
00004 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
00005
00006 #include <sys/types.h>
00007 #include <sys/stat.h>
00008 #include <iostream>
00009 #include <openssl/sha.h>
00010 #include <cstdlib>
00011 #include <cstdio>
00012 #include <cassert>
00013
00014 #include <thread>
00015 #include <chrono>
00016 #include "WebUsers.h"
00017
00018 using namespace ots;
00019
00020
00021
00022 #define WEB_LOGIN_BKUP_DB_PATH "bkup/"
00023
00024 #define SECURITY_FILE_NAME std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData/security.dat"
00025
00026 #define USERS_ACTIVE_SESSIONS_FILE USERS_DB_PATH + "/activeSessions.sv"
00027
00028 #define HASHES_DB_FILE HASHES_DB_PATH + "/hashes.xml"
00029 #define USERS_DB_FILE USERS_DB_PATH + "/users.xml"
00030 #define USERS_GLOBAL_HISTORY_FILE "__global"
00031 #define USERS_LOGIN_HISTORY_FILETYPE "hist"
00032 #define USERS_PREFERENCES_FILETYPE "pref"
00033 #define SYSTEM_PREFERENCES_PREFIX "system.preset"
00034 #define USER_WITH_LOCK_FILE WEB_LOGIN_DB_PATH + "/user_with_lock.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 valud (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
00067 const std::string WebUsers::REQ_NO_LOGIN_RESPONSE = "NoLogin";
00068 const std::string WebUsers::REQ_NO_PERMISSION_RESPONSE = "NoPermission";
00069 const std::string WebUsers::REQ_USER_LOCKOUT_RESPONSE = "UserLockout";
00070
00071 const std::string WebUsers::SECURITY_TYPE_NONE = "NoSecurity";
00072 const std::string WebUsers::SECURITY_TYPE_DIGEST_ACCESS = "DigestAccessAuthentication";
00073
00074 #undef __MF_SUBJECT__
00075 #define __MF_SUBJECT__ "WebUsers"
00076
00077
00078 WebUsers::WebUsers()
00079 {
00080
00081
00082 usersNextUserId_ = 0;
00083 usersUsernameWithLock_ = "";
00084
00085
00086 HashesDatabaseEntryFields.push_back("hash");
00087 HashesDatabaseEntryFields.push_back("lastAccessTime");
00088
00089 UsersDatabaseEntryFields.push_back("username");
00090 UsersDatabaseEntryFields.push_back("displayName");
00091 UsersDatabaseEntryFields.push_back("salt");
00092 UsersDatabaseEntryFields.push_back("uid");
00093 UsersDatabaseEntryFields.push_back("permissions");
00094 UsersDatabaseEntryFields.push_back("lastLoginAttemptTime");
00095 UsersDatabaseEntryFields.push_back("accountCreatedTime");
00096 UsersDatabaseEntryFields.push_back("loginFailureCount");
00097 UsersDatabaseEntryFields.push_back("lastModifiedTime");
00098 UsersDatabaseEntryFields.push_back("lastModifierUsername");
00099 UsersDatabaseEntryFields.push_back("useremail");
00100
00101
00102 mkdir(((std::string)WEB_LOGIN_DB_PATH).c_str(), 0755);
00103 mkdir(((std::string)WEB_LOGIN_DB_PATH + "bkup/" + USERS_DB_PATH).c_str(), 0755);
00104 mkdir(((std::string)WEB_LOGIN_DB_PATH + HASHES_DB_PATH).c_str(), 0755);
00105 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH).c_str(), 0755);
00106 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_LOGIN_HISTORY_PATH).c_str(), 0755);
00107 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_PREFERENCES_PATH).c_str(), 0755);
00108
00109
00110 if (!loadDatabases())
00111 __COUT__ << "FATAL USER DATABASE ERROR - failed to load!!!" << std::endl;
00112
00113 loadSecuritySelection();
00114
00115
00116
00117 uint64_t i;
00118 std::string user = DEFAULT_ADMIN_USERNAME;
00119 if ((i = searchUsersDatabaseForUsername(user)) == NOT_FOUND_IN_DATABASE)
00120 {
00121 __SS__ << "user: " << user << " is not found" << std::endl;
00122 __COUT_ERR__ << ss.str();
00123 throw std::runtime_error(ss.str());
00124 exit(0);
00125 }
00126 else if (UsersSaltVector[i] == "" &&
00127 securityType_ == SECURITY_TYPE_DIGEST_ACCESS)
00128 {
00129 char charTimeStr[10];
00130 sprintf(charTimeStr, "%d", int(UsersAccountCreatedTimeVector[i] & 0xffff));
00131 std::string tmpTimeStr = charTimeStr;
00132
00134
00135
00136 std::thread([](std::string nac, std::string user) { WebUsers::NACDisplayThread(nac, user); },
00137 tmpTimeStr, user).detach();
00138
00139 }
00140
00141
00142
00143 loadActiveSessions();
00144
00145
00146
00147 loadUserWithLock();
00148
00149 srand(time(0));
00150
00151 __COUT__ << "Done with Web Users initialization!" << std::endl;
00152
00153
00154
00155
00156
00157
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 void WebUsers::saveActiveSessions()
00340 {
00341 std::string fn;
00342
00343 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_ACTIVE_SESSIONS_FILE;
00344 __COUT__ << fn << std::endl;
00345
00346 FILE *fp = fopen(fn.c_str(), "w");
00347 if (!fp)
00348 {
00349 __COUT_ERR__ << "Error! Persistent active sessions could not be saved." << std::endl;
00350 return;
00351 }
00352
00353 int version = 0;
00354 fprintf(fp, "%d\n", version);
00355 for (unsigned int i = 0; i < ActiveSessionCookieCodeVector.size(); ++i)
00356 {
00357
00358
00359
00360
00361
00362
00363 fprintf(fp, "%s\n", ActiveSessionCookieCodeVector[i].c_str());
00364 fprintf(fp, "%s\n", ActiveSessionIpVector[i].c_str());
00365 fprintf(fp, "%lu\n", ActiveSessionUserIdVector[i]);
00366 fprintf(fp, "%lu\n", ActiveSessionIndex[i]);
00367 fprintf(fp, "%ld\n", ActiveSessionStartTimeVector[i]);
00368 }
00369
00370 __COUT__ << "ActiveSessionCookieCodeVector saved with size " <<
00371 ActiveSessionCookieCodeVector.size() << std::endl;
00372
00373 fclose(fp);
00374 }
00375
00376
00377
00378
00379 void WebUsers::loadActiveSessions()
00380 {
00381 std::string fn;
00382
00383 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_ACTIVE_SESSIONS_FILE;
00384 __COUT__ << fn << std::endl;
00385 FILE *fp = fopen(fn.c_str(), "r");
00386 if (!fp)
00387 {
00388 __COUT_ERR__ << "Error! Persistent active sessions could not be saved." << std::endl;
00389 return;
00390 }
00391
00392 int version;
00393
00394 const int LINELEN = 1000;
00395 char line[LINELEN];
00396 fgets(line, LINELEN, fp);
00397 sscanf(line, "%d", &version);
00398 if (version == 0)
00399 {
00400 __COUT__ << "Extracting active sessions..." << std::endl;
00401
00402 }
00403 unsigned int i = 0;
00404 while (fgets(line, LINELEN, fp))
00405 {
00406 if (strlen(line)) line[strlen(line) - 1] = '\0';
00407 if (strlen(line) != COOKIE_CODE_LENGTH)
00408 {
00409 __COUT__ << "Illegal cookie code found: " << line << std::endl;
00410
00411 fclose(fp);
00412 return;
00413 }
00414 ActiveSessionCookieCodeVector.push_back(line);
00415
00416 fgets(line, LINELEN, fp);
00417 if (strlen(line)) line[strlen(line) - 1] = '\0';
00418 ActiveSessionIpVector.push_back(line);
00419
00420 fgets(line, LINELEN, fp);
00421 ActiveSessionUserIdVector.push_back(uint64_t());
00422 sscanf(line, "%lu", &(ActiveSessionUserIdVector[ActiveSessionUserIdVector.size() - 1]));
00423
00424 fgets(line, LINELEN, fp);
00425 ActiveSessionIndex.push_back(uint64_t());
00426 sscanf(line, "%lu", &(ActiveSessionIndex[ActiveSessionIndex.size() - 1]));
00427
00428 fgets(line, LINELEN, fp);
00429 ActiveSessionStartTimeVector.push_back(time_t());
00430 sscanf(line, "%ld", &(ActiveSessionStartTimeVector[ActiveSessionStartTimeVector.size() - 1]));
00431
00432
00433
00434
00435
00436
00437
00438 ++i;
00439 }
00440
00441 __COUT__ << "ActiveSessionCookieCodeVector loaded with size " <<
00442 ActiveSessionCookieCodeVector.size() << std::endl;
00443
00444
00445 fclose(fp);
00446
00447 fp = fopen(fn.c_str(), "w");
00448 if (fp)fclose(fp);
00449
00450 }
00451
00452
00453
00454
00455
00456 bool WebUsers::loadDatabases()
00457 {
00458 std::string fn;
00459 FILE *fp;
00460 const unsigned int LINE_LEN = 1000;
00461 char line[LINE_LEN];
00462 unsigned int i, si, c, len, f;
00463 uint64_t tmpInt64;
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_FILE;
00474 __COUT__ << fn << std::endl;
00475 fp = fopen(fn.c_str(), "r");
00476 if (!fp)
00477 {
00478 mkdir(((std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_PATH).c_str(), 0755);
00479 __COUT__ << ((std::string)WEB_LOGIN_DB_PATH + (std::string)HASHES_DB_PATH).c_str() << std::endl;
00480 fp = fopen(fn.c_str(), "w");
00481 if (!fp) return false;
00482 __COUT__ << "Hashes database created: " << fn << std::endl;
00483
00484 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING, "", DB_SAVE_OPEN);
00485 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING, "", DB_SAVE_CLOSE);
00486 fclose(fp);
00487 }
00488 else
00489 {
00490
00491
00492 while (fgets(line, LINE_LEN, fp))
00493 {
00494 if (strlen(line) < SHA512_DIGEST_LENGTH) continue;
00495
00496 c = 0;
00497 len = strlen(line);
00498 for (i = 0; i < len; ++i)
00499 if (line[i] == '>')
00500 {
00501 ++c;
00502 if (c != 2 && c != 4) continue;
00503
00504 si = ++i;
00505 while (i < len && line[i] != '<') ++i;
00506 if (i == len)
00507 break;
00508 line[i] = '\0';
00509
00510
00511
00512 f = c / 2 - 1;
00513 if (f == 0)
00514 HashesVector.push_back(&line[si]);
00515 else if (f == 1)
00516 {
00517 sscanf(&line[si], "%lu", &tmpInt64);
00518 HashesAccessTimeVector.push_back(tmpInt64);
00519 }
00520 }
00521 }
00522 __COUT__ << HashesAccessTimeVector.size() << " Hashes found." << std::endl;
00523
00524 fclose(fp);
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_FILE;
00537 fp = fopen(fn.c_str(), "r");
00538 if (!fp)
00539 {
00540 mkdir(((std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_PATH).c_str(), 0755);
00541 __COUT__ << ((std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_DB_PATH).c_str() << std::endl;
00542 fp = fopen(fn.c_str(), "w");
00543 if (!fp) return false;
00544 __COUT__ << "Users database created: " << fn << std::endl;
00545
00546 saveToDatabase(fp, USERS_DB_GLOBAL_STRING, "", DB_SAVE_OPEN);
00547 char nidStr[100];
00548 sprintf(nidStr, "%lu", usersNextUserId_);
00549 saveToDatabase(fp, USERS_DB_NEXT_UID_STRING, nidStr, DB_SAVE_OPEN_AND_CLOSE);
00550 saveToDatabase(fp, USERS_DB_GLOBAL_STRING, "", DB_SAVE_CLOSE);
00551 fclose(fp);
00552
00553 createNewAccount(DEFAULT_ADMIN_USERNAME, DEFAULT_ADMIN_DISPLAY_NAME, DEFAULT_ADMIN_EMAIL);
00554 }
00555 else
00556 {
00557
00558
00559
00560 char salt[] = "nextUserId";
00561 while (fgets(line, LINE_LEN, fp))
00562 {
00563 if (strlen(line) < strlen(salt) * 2) continue;
00564
00565 for (i = 0; i < strlen(salt); ++i)
00566 if (line[i + 1] != salt[i]) break;
00567
00568 if (i == strlen(salt))
00569 {
00570 i += 2;
00571 si = i;
00572 while (i < LINE_LEN && line[i] != '\0' && line[i] != '<') ++i;
00573 line[i] = '\0';
00574 sscanf(&line[si], "%lu", &usersNextUserId_);
00575 break;
00576 }
00577 }
00578
00579 __COUT__ << "Found Users database next user Id: " << usersNextUserId_ << std::endl;
00580
00581
00582 while (fgets(line, LINE_LEN, fp))
00583 {
00584 if (strlen(line) < 30) continue;
00585
00586 c = 0;
00587 len = strlen(line);
00588 if (len >= LINE_LEN)
00589 {
00590 __COUT__ << "Line buffer too small: " << len << std::endl;
00591 break;
00592 }
00593
00594
00595 f = 0;
00596 for (i = 0; i < len; ++i)
00597 if (line[i] == '>')
00598 {
00599 ++c;
00600 if (c == 0 || c % 2 == 1) continue;
00601
00602 si = ++i;
00603 while (i < len && line[i] != '<') ++i;
00604 if (i == len)
00605 break;
00606 line[i] = '\0';
00607 f = c / 2 - 1;
00608
00609
00610
00611 if (f == 0)
00612 UsersUsernameVector.push_back(&line[si]);
00613 else if (f == 1)
00614 UsersDisplayNameVector.push_back(&line[si]);
00615 else if (f == 2)
00616 UsersSaltVector.push_back(&line[si]);
00617 else if (f == 3)
00618 {
00619 sscanf(&line[si], "%lu", &tmpInt64);
00620 UsersUserIdVector.push_back(tmpInt64);
00621 }
00622 else if (f == 4)
00623 {
00624 sscanf(&line[si], "%lu", &tmpInt64);
00625 UsersPermissionsVector.push_back(tmpInt64);
00626 }
00627 else if (f == 5)
00628 {
00629 sscanf(&line[si], "%lu", &tmpInt64);
00630 UsersLastLoginAttemptVector.push_back(tmpInt64);
00631 }
00632 else if (f == 6)
00633 {
00634 sscanf(&line[si], "%lu", &tmpInt64);
00635 UsersAccountCreatedTimeVector.push_back(tmpInt64);
00636 }
00637 else if (f == 7)
00638 {
00639 sscanf(&line[si], "%lu", &tmpInt64);
00640 UsersLoginFailureCountVector.push_back(tmpInt64);
00641 }
00642 else if (f == 8)
00643 {
00644 sscanf(&line[si], "%lu", &tmpInt64);
00645 UsersLastModifiedTimeVector.push_back(tmpInt64);
00646 }
00647 else if (f == 9)
00648 UsersLastModifierUsernameVector.push_back(&line[si]);
00649 else if (f == 10)
00650 UsersUserEmailVector.push_back(&line[si]);
00651 }
00652
00653
00654
00655 if (f && f != UsersDatabaseEntryFields.size() - 1)
00656 {
00657 if (f != 7 && f != 9)
00658 {
00659 __COUT__ << "FATAL ERROR - invalid database found with field number " << f << std::endl;
00660 fclose(fp);
00661 return false;
00662 }
00663
00664 if (f == 7)
00665 {
00666
00667 __COUT__ << "Update database to current version - adding fields: " <<
00668 (UsersDatabaseEntryFields.size() - 1 - f) << std::endl;
00669
00670 UsersLastModifiedTimeVector.push_back(0);
00671 UsersLastModifierUsernameVector.push_back("");
00672 }
00673 else
00674 {
00675 UsersUserEmailVector.push_back("");
00676 }
00677 }
00678 }
00679 fclose(fp);
00680 }
00681
00682 __COUT__ << UsersLastModifiedTimeVector.size() << " Users found." << std::endl;
00683 for (size_t ii = 0; ii < UsersLastModifiedTimeVector.size(); ++ii)
00684 {
00685 __COUT__ << "User " << UsersUserIdVector[ii] << ": Name: " << UsersUsernameVector[ii] << "\t\tDisplay Name: " << UsersDisplayNameVector[ii] << "\t\tEmail: " << UsersUserEmailVector[ii] << "\t\tPermissions: " << std::to_string(UsersPermissionsVector[ii]) << std::endl;
00686 }
00687 return true;
00688 }
00689
00690
00691
00692 void WebUsers::saveToDatabase(FILE * fp, std::string field, std::string value, uint8_t type, bool addNewLine)
00693 {
00694 if (!fp) return;
00695
00696 std::string newLine = addNewLine ? "\n" : "";
00697
00698 if (type == DB_SAVE_OPEN_AND_CLOSE)
00699 fprintf(fp, "<%s>%s</%s>%s", field.c_str(), value.c_str(), field.c_str(), newLine.c_str());
00700 else if (type == DB_SAVE_OPEN)
00701 fprintf(fp, "<%s>%s%s", field.c_str(), value.c_str(), newLine.c_str());
00702 else if (type == DB_SAVE_CLOSE)
00703 fprintf(fp, "</%s>%s", field.c_str(), newLine.c_str());
00704 }
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 bool WebUsers::saveDatabaseToFile(uint8_t db)
00715 {
00716 __COUT__ << "Save Database: " << (int)db << std::endl;
00717
00718 std::string fn = (std::string)WEB_LOGIN_DB_PATH +
00719 ((db == DB_USERS) ? (std::string)USERS_DB_FILE : (std::string)HASHES_DB_FILE);
00720
00721 __COUT__ << "Save Database Filename: " << fn << std::endl;
00722
00723
00724 if (0)
00725 {
00726 char dayAppend[20];
00727 sprintf(dayAppend, ".%lu.bkup", time(0) / (3600 * 24));
00728 std::string bkup_fn = (std::string)WEB_LOGIN_DB_PATH +
00729 (std::string)WEB_LOGIN_BKUP_DB_PATH +
00730 ((db == DB_USERS) ? (std::string)USERS_DB_FILE : (std::string)HASHES_DB_FILE) +
00731 (std::string)dayAppend;
00732
00733 __COUT__ << "Backup file: " << bkup_fn << std::endl;
00734
00735 std::string shell_command = "mv " + fn + " " + bkup_fn;
00736 system(shell_command.c_str());
00737 }
00738
00739 FILE *fp = fopen(fn.c_str(), "wb");
00740 if (!fp) return false;
00741
00742 char fldStr[100];
00743
00744 if (db == DB_USERS)
00745 {
00746 saveToDatabase(fp, USERS_DB_GLOBAL_STRING, "", DB_SAVE_OPEN);
00747
00748 sprintf(fldStr, "%lu", usersNextUserId_);
00749 saveToDatabase(fp, USERS_DB_NEXT_UID_STRING, fldStr, DB_SAVE_OPEN_AND_CLOSE);
00750
00751 __COUT__ << "Saving " << UsersUsernameVector.size() << " Users." << std::endl;
00752
00753 for (uint64_t i = 0; i < UsersUsernameVector.size(); ++i)
00754 {
00755
00756
00757 saveToDatabase(fp, USERS_DB_ENTRY_STRING, "", DB_SAVE_OPEN, false);
00758
00759 for (unsigned int f = 0; f < UsersDatabaseEntryFields.size(); ++f)
00760 {
00761
00762 if (f == 0)
00763 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersUsernameVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
00764 else if (f == 1)
00765 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersDisplayNameVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
00766 else if (f == 2)
00767 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersSaltVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
00768 else if (f == 3)
00769 {
00770 sprintf(fldStr, "%lu", UsersUserIdVector[i]);
00771 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
00772 }
00773 else if (f == 4)
00774 {
00775 sprintf(fldStr, "%d", UsersPermissionsVector[i]);
00776 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
00777 }
00778 else if (f == 5)
00779 {
00780 sprintf(fldStr, "%lu", UsersLastLoginAttemptVector[i]);
00781 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
00782 }
00783 else if (f == 6)
00784 {
00785 sprintf(fldStr, "%lu", UsersAccountCreatedTimeVector[i]);
00786 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
00787 }
00788 else if (f == 7)
00789 {
00790 sprintf(fldStr, "%d", UsersLoginFailureCountVector[i]);
00791 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
00792 }
00793 else if (f == 8)
00794 {
00795 sprintf(fldStr, "%lu", UsersLastModifiedTimeVector[i]);
00796 saveToDatabase(fp, UsersDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
00797 }
00798 else if (f == 9)
00799 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersLastModifierUsernameVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
00800 else if (f == 10)
00801 saveToDatabase(fp, UsersDatabaseEntryFields[f], UsersUserEmailVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
00802 }
00803
00804 saveToDatabase(fp, USERS_DB_ENTRY_STRING, "", DB_SAVE_CLOSE);
00805 }
00806
00807 saveToDatabase(fp, USERS_DB_GLOBAL_STRING, "", DB_SAVE_CLOSE);
00808
00809 }
00810 else
00811 {
00812 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING, "", DB_SAVE_OPEN);
00813
00814 __COUT__ << "Saving " << HashesVector.size() << " Hashes." << std::endl;
00815 for (uint64_t i = 0; i < HashesVector.size(); ++i)
00816 {
00817 __COUT__ << "Saving " << HashesVector[i] << " Hashes." << std::endl;
00818 saveToDatabase(fp, HASHES_DB_ENTRY_STRING, "", DB_SAVE_OPEN, false);
00819 for (unsigned int f = 0; f < HashesDatabaseEntryFields.size(); ++f)
00820 {
00821 if (f == 0)
00822 saveToDatabase(fp, HashesDatabaseEntryFields[f], HashesVector[i], DB_SAVE_OPEN_AND_CLOSE, false);
00823 else if (f == 1)
00824 {
00825 sprintf(fldStr, "%lu", HashesAccessTimeVector[i]);
00826 saveToDatabase(fp, HashesDatabaseEntryFields[f], fldStr, DB_SAVE_OPEN_AND_CLOSE, false);
00827 }
00828 }
00829 saveToDatabase(fp, HASHES_DB_ENTRY_STRING, "", DB_SAVE_CLOSE);
00830 }
00831
00832 saveToDatabase(fp, HASHES_DB_GLOBAL_STRING, "", DB_SAVE_CLOSE);
00833 }
00834
00835
00836 fclose(fp);
00837 return true;
00838 }
00839
00840
00841
00842
00843
00844
00845
00846
00847 bool WebUsers::createNewAccount(std::string Username, std::string DisplayName, std::string Email)
00848 {
00849 __COUT__ << "Creating account: " << Username << std::endl;
00850
00851 uint64_t i;
00852 if ((i = searchUsersDatabaseForUsername(Username)) != NOT_FOUND_IN_DATABASE ||
00853 Username == WebUsers::DEFAULT_ITERATOR_USERNAME ||
00854 Username == WebUsers::DEFAULT_STATECHANGER_USERNAME)
00855 {
00856 __COUT__ << "Username: " << Username << " already exists" << std::endl;
00857 return false;
00858 }
00859
00860
00861 UsersUsernameVector.push_back(Username);
00862 UsersDisplayNameVector.push_back(DisplayName);
00863 UsersUserEmailVector.push_back(Email);
00864 UsersSaltVector.push_back("");
00865 UsersPermissionsVector.push_back(UsersPermissionsVector.size() ? 1 : -1);
00866 UsersUserIdVector.push_back(usersNextUserId_++);
00867 if (usersNextUserId_ == (uint64_t)-1)
00868 {
00869 __COUT__ << "usersNextUserId_ wrap around!! Too many users??? Notify Admins." << std::endl;
00870 usersNextUserId_ = 1;
00871 }
00872 UsersLastLoginAttemptVector.push_back(0);
00873 UsersLoginFailureCountVector.push_back(0);
00874 UsersAccountCreatedTimeVector.push_back(time(0));
00875 UsersLastModifiedTimeVector.push_back(0);
00876 UsersLastModifierUsernameVector.push_back("");
00877
00878 return saveDatabaseToFile(DB_USERS);
00879 }
00880
00881
00882
00883
00884
00885
00886
00887 bool WebUsers::deleteAccount(std::string username, std::string displayName)
00888 {
00889 uint64_t i = searchUsersDatabaseForUsername(username);
00890 if (i == NOT_FOUND_IN_DATABASE) return false;
00891 if (UsersDisplayNameVector[i] != displayName) return false;
00892
00893
00894
00895 UsersUsernameVector.erase(UsersUsernameVector.begin() + i);
00896 UsersUserEmailVector.erase(UsersUserEmailVector.begin() + i);
00897 UsersDisplayNameVector.erase(UsersDisplayNameVector.begin() + i);
00898 UsersSaltVector.erase(UsersSaltVector.begin() + i);
00899 UsersPermissionsVector.erase(UsersPermissionsVector.begin() + i);
00900 UsersUserIdVector.erase(UsersUserIdVector.begin() + i);
00901 UsersLastLoginAttemptVector.erase(UsersLastLoginAttemptVector.begin() + i);
00902 UsersAccountCreatedTimeVector.erase(UsersAccountCreatedTimeVector.begin() + i);
00903 UsersLoginFailureCountVector.erase(UsersLoginFailureCountVector.begin() + i);
00904 UsersLastModifierUsernameVector.erase(UsersLastModifierUsernameVector.begin() + i);
00905 UsersLastModifiedTimeVector.erase(UsersLastModifiedTimeVector.begin() + i);
00906
00907
00908 return saveDatabaseToFile(DB_USERS);
00909 }
00910
00911
00912 unsigned int WebUsers::hexByteStrToInt(const char *h)
00913 {
00914 unsigned int rv;
00915 char hs[3] = { h[0],h[1],'\0' };
00916 sscanf(hs, "%X", &rv);
00917 return rv;
00918 }
00919
00920
00921 void WebUsers::intToHexStr(unsigned char i, char *h)
00922 {
00923 sprintf(h, "%2.2X", i);
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935 uint64_t WebUsers::attemptActiveSession(std::string uuid, std::string &jumbledUser,
00936 std::string jumbledPw, std::string &newAccountCode)
00937 {
00938 cleanupExpiredEntries();
00939
00940 if (!CareAboutCookieCodes_)
00941 {
00942 uint64_t uid = getAdminUserID();
00943 jumbledUser = getUsersDisplayName(uid);
00944 newAccountCode = genCookieCode();
00945 return uid;
00946 }
00947
00948 uint64_t i;
00949
00950
00951 if ((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
00952 {
00953 __COUT__ << "uuid: " << uuid << " is not found" << std::endl;
00954 newAccountCode = "1";
00955 return NOT_FOUND_IN_DATABASE;
00956 }
00957 ++LoginSessionAttemptsVector[i];
00958
00959 std::string user = dejumble(jumbledUser, LoginSessionIdVector[i]);
00960 __COUT__ << "DejumbledUser = " << user << std::endl;
00961 std::string pw = dejumble(jumbledPw, LoginSessionIdVector[i]);
00962
00963
00964 if ((i = searchUsersDatabaseForUsername(user)) == NOT_FOUND_IN_DATABASE)
00965 {
00966 __COUT__ << "user: " << user << " is not found" << std::endl;
00967 return NOT_FOUND_IN_DATABASE;
00968 }
00969
00970 UsersLastLoginAttemptVector[i] = time(0);
00971 if (!UsersPermissionsVector[i])
00972 {
00973 __COUT__ << "user: " << user << " account INACTIVE (could be due to failed logins)" << std::endl;
00974 return NOT_FOUND_IN_DATABASE;
00975 }
00976
00977 if (UsersSaltVector[i] == "")
00978 {
00979 __COUT__ << "First login attempt for user: " << user << std::endl;
00980
00981 char charTimeStr[10];
00982 sprintf(charTimeStr, "%d", int(UsersAccountCreatedTimeVector[i] & 0xffff));
00983 std::string tmpTimeStr = charTimeStr;
00984 if (newAccountCode != tmpTimeStr)
00985 {
00986 __COUT__ << "New account code did not match: " << tmpTimeStr << " != " << newAccountCode << std::endl;
00987 saveDatabaseToFile(DB_USERS);
00988 return NOT_FOUND_IN_DATABASE;
00989 }
00990
00991
00992
00993
00994 while (!addToHashesDatabase(sha512(user, pw, UsersSaltVector[i])))
00995 {
00996
00997
00998 UsersSaltVector[i] = "";
00999 }
01000
01001
01002 __COUT__ << "\tHash added: " << HashesVector[HashesVector.size() - 1] << std::endl;
01003 }
01004 else
01005 {
01006 std::string salt = UsersSaltVector[i];
01007
01008 if (searchHashesDatabaseForHash(sha512(user, pw, salt)) == NOT_FOUND_IN_DATABASE)
01009 {
01010 __COUT__ << "not found?" << std::endl;
01011 ++UsersLoginFailureCountVector[i];
01012 if (UsersLoginFailureCountVector[i] >= USERS_MAX_LOGIN_FAILURES)
01013 UsersPermissionsVector[i] = 0;
01014
01015 __COUT__ << "\tUser/pw for user: " << user << " was not correct Failed Attempt #" << (int)(UsersLoginFailureCountVector[i]) << std::endl;
01016 if (!UsersPermissionsVector[i])
01017 __COUT__ << "Account is locked!" << std::endl;
01018
01019 saveDatabaseToFile(DB_USERS);
01020 return NOT_FOUND_IN_DATABASE;
01021 }
01022 }
01023
01024 __COUT__ << "Login successful for: " << user << std::endl;
01025
01026 UsersLoginFailureCountVector[i] = 0;
01027
01028
01029 for (int h = 0; h < 2; ++h)
01030 {
01031 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_LOGIN_HISTORY_PATH + (h ? USERS_GLOBAL_HISTORY_FILE : UsersUsernameVector[i])
01032 + "." + (std::string)USERS_LOGIN_HISTORY_FILETYPE;
01033
01034 HttpXmlDocument histXml;
01035
01036 if (histXml.loadXmlDocument(fn))
01037 {
01038 while (histXml.getChildrenCount() + 1 > (h ? USERS_GLOBAL_HISTORY_SIZE : USERS_LOGIN_HISTORY_SIZE))
01039 histXml.removeDataElement();
01040 }
01041 else
01042 __COUT__ << "No previous login history found." << std::endl;
01043
01044
01045 char entryStr[500];
01046 if (h)
01047 sprintf(entryStr, "Time=%lu Username=%s Permissions=%d UID=%lu",
01048 time(0), UsersUsernameVector[i].c_str(), UsersPermissionsVector[i], UsersUserIdVector[i]);
01049 else
01050 sprintf(entryStr, "Time=%lu DisplayName=%s Permissions=%d UID=%lu",
01051 time(0), UsersDisplayNameVector[i].c_str(), UsersPermissionsVector[i], UsersUserIdVector[i]);
01052 histXml.addTextElementToData(PREF_XML_LOGIN_HISTORY_FIELD, entryStr);
01053
01054
01055 histXml.saveXmlDocument(fn);
01056 }
01057
01058
01059 saveDatabaseToFile(DB_USERS);
01060 jumbledUser = UsersDisplayNameVector[i];
01061 newAccountCode = createNewActiveSession(UsersUserIdVector[i]);
01062 return UsersUserIdVector[i];
01063 }
01064
01065
01066
01067
01068
01069
01070 uint64_t WebUsers::attemptActiveSessionWithCert(std::string uuid, std::string &email,
01071 std::string &cookieCode, std::string& user)
01072 {
01073 cleanupExpiredEntries();
01074
01075 if (!CareAboutCookieCodes_)
01076 {
01077 uint64_t uid = getAdminUserID();
01078 email = getUsersDisplayName(uid);
01079 cookieCode = genCookieCode();
01080 return uid;
01081 }
01082
01083 if (email == "")
01084 {
01085 __COUT__ << "Rejecting logon with blank fingerprint" << std::endl;
01086 return NOT_FOUND_IN_DATABASE;
01087 }
01088
01089 uint64_t i;
01090
01091
01092 if ((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
01093 {
01094 __COUT__ << "uuid: " << uuid << " is not found" << std::endl;
01095 cookieCode = "1";
01096 return NOT_FOUND_IN_DATABASE;
01097 }
01098 ++LoginSessionAttemptsVector[i];
01099
01100 email = getUserEmailFromFingerprint(email);
01101 __COUT__ << "DejumbledEmail = " << email << std::endl;
01102 if (email == "")
01103 {
01104 __COUT__ << "Rejecting logon with unknown fingerprint" << std::endl;
01105 return NOT_FOUND_IN_DATABASE;
01106 }
01107
01108
01109 if ((i = searchUsersDatabaseForUserEmail(email)) == NOT_FOUND_IN_DATABASE)
01110 {
01111 __COUT__ << "email: " << email << " is not found" << std::endl;
01112 return NOT_FOUND_IN_DATABASE;
01113 }
01114
01115 user = getUsersUsername(i);
01116
01117 UsersLastLoginAttemptVector[i] = time(0);
01118 if (!UsersPermissionsVector[i])
01119 {
01120 __COUT__ << "user: " << user << " account INACTIVE (could be due to failed logins)" << std::endl;
01121 return NOT_FOUND_IN_DATABASE;
01122 }
01123
01124 if (UsersSaltVector[i] == "")
01125 {
01126 return NOT_FOUND_IN_DATABASE;
01127 }
01128
01129 __COUT__ << "Login successful for: " << user << std::endl;
01130
01131 UsersLoginFailureCountVector[i] = 0;
01132
01133
01134 for (int h = 0; h < 2; ++h)
01135 {
01136 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_LOGIN_HISTORY_PATH + (h ? USERS_GLOBAL_HISTORY_FILE : UsersUsernameVector[i])
01137 + "." + (std::string)USERS_LOGIN_HISTORY_FILETYPE;
01138
01139 HttpXmlDocument histXml;
01140
01141 if (histXml.loadXmlDocument(fn))
01142 {
01143 while (histXml.getChildrenCount() + 1 > (h ? USERS_GLOBAL_HISTORY_SIZE : USERS_LOGIN_HISTORY_SIZE))
01144 histXml.removeDataElement();
01145 }
01146 else
01147 __COUT__ << "No previous login history found." << std::endl;
01148
01149
01150 char entryStr[500];
01151 if (h)
01152 sprintf(entryStr, "Time=%lu Username=%s Permissions=%d UID=%lu",
01153 time(0), UsersUsernameVector[i].c_str(), UsersPermissionsVector[i], UsersUserIdVector[i]);
01154 else
01155 sprintf(entryStr, "Time=%lu DisplayName=%s Permissions=%d UID=%lu",
01156 time(0), UsersDisplayNameVector[i].c_str(), UsersPermissionsVector[i], UsersUserIdVector[i]);
01157 histXml.addTextElementToData(PREF_XML_LOGIN_HISTORY_FIELD, entryStr);
01158
01159
01160 histXml.saveXmlDocument(fn);
01161 }
01162
01163
01164 saveDatabaseToFile(DB_USERS);
01165 email = UsersDisplayNameVector[i];
01166 cookieCode = createNewActiveSession(UsersUserIdVector[i]);
01167 return UsersUserIdVector[i];
01168 }
01169
01170
01171
01172
01173 uint64_t WebUsers::searchActiveSessionDatabaseForCookie(std::string cookieCode) const
01174 {
01175 uint64_t i = 0;
01176 for (; i < ActiveSessionCookieCodeVector.size(); ++i)
01177 if (ActiveSessionCookieCodeVector[i] == cookieCode) break;
01178 return (i == ActiveSessionCookieCodeVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01179 }
01180
01181
01182
01183
01184
01185 bool WebUsers::isUsernameActive(std::string username) const
01186 {
01187 uint64_t u;
01188 if ((u = searchUsersDatabaseForUsername(username)) == NOT_FOUND_IN_DATABASE) return false;
01189 return isUserIdActive(UsersUserIdVector[u]);
01190 }
01191
01192
01193
01194
01195
01196 bool WebUsers::isUserIdActive(uint64_t uid) const
01197 {
01198 uint64_t i = 0;
01199 for (; i < ActiveSessionUserIdVector.size(); ++i)
01200 if (ActiveSessionUserIdVector[i] == uid) return true;
01201 return false;
01202 }
01203
01204
01205
01206
01207 uint64_t WebUsers::searchUsersDatabaseForUsername(std::string username) const
01208 {
01209 uint64_t i = 0;
01210 for (; i < UsersUsernameVector.size(); ++i)
01211 if (UsersUsernameVector[i] == username) break;
01212 return (i == UsersUsernameVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01213 }
01214
01215
01216
01217
01218 uint64_t WebUsers::searchUsersDatabaseForUserEmail(std::string useremail) const
01219 {
01220 uint64_t i = 0;
01221 for (; i < UsersUserEmailVector.size(); ++i)
01222 if (UsersUserEmailVector[i] == useremail) break;
01223 return (i == UsersUserEmailVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01224 }
01225
01226
01227
01228
01229 uint64_t WebUsers::searchUsersDatabaseForUserId(uint64_t uid) const
01230 {
01231 uint64_t i = 0;
01232 for (; i < UsersUserIdVector.size(); ++i)
01233 if (UsersUserIdVector[i] == uid) break;
01234 return (i == UsersUserIdVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01235 }
01236
01237
01238
01239
01240 uint64_t WebUsers::searchLoginSessionDatabaseForUUID(std::string uuid) const
01241 {
01242 uint64_t i = 0;
01243 for (; i < LoginSessionUUIDVector.size(); ++i)
01244 if (LoginSessionUUIDVector[i] == uuid) break;
01245 return (i == LoginSessionUUIDVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01246 }
01247
01248
01249
01250
01251 uint64_t WebUsers::searchHashesDatabaseForHash(std::string hash)
01252 {
01253 uint64_t i = 0;
01254
01255
01256 for (; i < HashesVector.size(); ++i)
01257 if (HashesVector[i] == hash) break;
01258
01259
01260
01261 if (i < HashesAccessTimeVector.size())
01262 HashesAccessTimeVector.push_back((time(0) + (rand() % 2 ? 1 : -1)*(rand() % 30 * 24 * 60 * 60)) & 0x0FFFFFFFFFE000000);
01263
01264
01265 return (i == HashesVector.size()) ? NOT_FOUND_IN_DATABASE : i;
01266 }
01267
01268
01269
01270
01271
01272 bool WebUsers::addToHashesDatabase(std::string hash)
01273 {
01274 if (searchHashesDatabaseForHash(hash) != NOT_FOUND_IN_DATABASE)
01275 {
01276 __COUT__ << "Hash collision: " << hash << std::endl;
01277 return false;
01278 }
01279 HashesVector.push_back(hash);
01280 HashesAccessTimeVector.push_back((time(0) + (rand() % 2 ? 1 : -1)*(rand() % 30 * 24 * 60 * 60)) & 0x0FFFFFFFFFE000000);
01281
01282 return saveDatabaseToFile(DB_HASHES);
01283 }
01284
01285
01286
01287 std::string WebUsers::genCookieCode()
01288 {
01289 char hexStr[3];
01290 std::string cc = "";
01291 for (uint32_t i = 0; i < COOKIE_CODE_LENGTH / 2; ++i)
01292 {
01293 intToHexStr(rand(), hexStr);
01294 cc.append(hexStr);
01295 }
01296 return cc;
01297 }
01298
01299
01300
01301 void WebUsers::removeLoginSessionEntry(unsigned int i)
01302 {
01303 LoginSessionIdVector.erase(LoginSessionIdVector.begin() + i);
01304 LoginSessionUUIDVector.erase(LoginSessionUUIDVector.begin() + i);
01305 LoginSessionIpVector.erase(LoginSessionIpVector.begin() + i);
01306 LoginSessionStartTimeVector.erase(LoginSessionStartTimeVector.begin() + i);
01307 LoginSessionAttemptsVector.erase(LoginSessionAttemptsVector.begin() + i);
01308 }
01309
01310
01311
01312
01313
01314 std::string WebUsers::createNewActiveSession(uint64_t uid, std::string ip, uint64_t asIndex)
01315 {
01316 ActiveSessionCookieCodeVector.push_back(genCookieCode());
01317 ActiveSessionIpVector.push_back(ip);
01318 ActiveSessionUserIdVector.push_back(uid);
01319 ActiveSessionStartTimeVector.push_back(time(0));
01320
01321 if (asIndex)
01322 ActiveSessionIndex.push_back(asIndex);
01323 else
01324 {
01325
01326 uint64_t max = 0;
01327 for (uint64_t j = 0; j < ActiveSessionIndex.size(); ++j)
01328 if (ActiveSessionUserIdVector[j] == uid && max < ActiveSessionIndex[j])
01329 max = ActiveSessionIndex[j];
01330
01331 ActiveSessionIndex.push_back(max ? max + 1 : 1);
01332 }
01333
01334 return ActiveSessionCookieCodeVector[ActiveSessionCookieCodeVector.size() - 1];
01335 }
01336
01337
01338
01339 void WebUsers::removeActiveSessionEntry(unsigned int i)
01340 {
01341 ActiveSessionCookieCodeVector.erase(ActiveSessionCookieCodeVector.begin() + i);
01342 ActiveSessionIpVector.erase(ActiveSessionIpVector.begin() + i);
01343 ActiveSessionUserIdVector.erase(ActiveSessionUserIdVector.begin() + i);
01344 ActiveSessionStartTimeVector.erase(ActiveSessionStartTimeVector.begin() + i);
01345 ActiveSessionIndex.erase(ActiveSessionIndex.begin() + i);
01346 }
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371 std::string WebUsers::refreshCookieCode(unsigned int i, bool enableRefresh)
01372 {
01373
01374 for (uint64_t j = ActiveSessionUserIdVector.size() - 1; j != (uint64_t)-1; --j)
01375 if (ActiveSessionUserIdVector[j] == ActiveSessionUserIdVector[i] &&
01376 ActiveSessionIndex[j] == ActiveSessionIndex[i])
01377 {
01378
01379
01380
01381 if (enableRefresh && (time(0) - ActiveSessionStartTimeVector[j] > ACTIVE_SESSION_EXPIRATION_TIME / 2))
01382 {
01383
01384 ActiveSessionStartTimeVector[j] = time(0) - ACTIVE_SESSION_EXPIRATION_TIME +
01385 ACTIVE_SESSION_COOKIE_OVERLAP_TIME;
01386
01387
01388 return createNewActiveSession(ActiveSessionUserIdVector[i], ActiveSessionIpVector[i], ActiveSessionIndex[i]);
01389 }
01390
01391 return ActiveSessionCookieCodeVector[j];
01392 }
01393
01394 return "0";
01395 }
01396
01397
01398
01399
01400
01401
01402 uint64_t WebUsers::isCookieCodeActiveForLogin(std::string uuid, std::string &cookieCode,
01403 std::string &username)
01404 {
01405 if (!CareAboutCookieCodes_)
01406 return getAdminUserID();
01407
01408
01409
01410
01411 if (!ActiveSessionStartTimeVector.size()) return NOT_FOUND_IN_DATABASE;
01412
01413 uint64_t i, j;
01414
01415
01416 if ((i = searchLoginSessionDatabaseForUUID(uuid)) == NOT_FOUND_IN_DATABASE)
01417 {
01418 __COUT__ << "uuid not found: " << uuid << std::endl;
01419 return NOT_FOUND_IN_DATABASE;
01420 }
01421
01422 username = dejumble(username, LoginSessionIdVector[i]);
01423
01424
01425 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
01426 {
01427 __COUT__ << "Cookie code not found" << std::endl;
01428 return NOT_FOUND_IN_DATABASE;
01429 }
01430
01431
01432 if ((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
01433 {
01434 __COUT__ << "User ID not found" << std::endl;
01435 return NOT_FOUND_IN_DATABASE;
01436 }
01437
01438
01439 if (UsersUsernameVector[j] != username)
01440 {
01441
01442 __COUT__ << "cookieCode: " << cookieCode << " was.." << std::endl;
01443 __COUT__ << "username: " << username << " is not found" << std::endl;
01444 return NOT_FOUND_IN_DATABASE;
01445 }
01446
01447 username = UsersDisplayNameVector[j];
01448 cookieCode = refreshCookieCode(i);
01449 return UsersUserIdVector[j];
01450 }
01451
01452
01453
01454
01455 uint64_t WebUsers::getActiveSessionCountForUser(uint64_t uid)
01456 {
01457 bool unique;
01458 std::vector<uint64_t> uniqueAsi;
01459
01460 uint64_t i, j;
01461 for (i = 0; i < ActiveSessionUserIdVector.size(); ++i)
01462 if (ActiveSessionUserIdVector[i] == uid)
01463 {
01464
01465 unique = true;
01466
01467 for (j = 0; j < uniqueAsi.size(); ++j)
01468 if (uniqueAsi[j] == ActiveSessionIndex[i])
01469 {
01470 unique = false; break;
01471 }
01472
01473 if (unique)
01474 uniqueAsi.push_back(ActiveSessionIndex[i]);
01475 }
01476
01477 __COUT__ << "Found " << uniqueAsi.size() << " active sessions for uid " << uid << std::endl;
01478
01479 return uniqueAsi.size();
01480 }
01481
01482
01483
01484 std::string WebUsers::getUsersDisplayName(uint64_t uid)
01485 {
01486 uint64_t i;
01487 if ((i = searchUsersDatabaseForUserId(uid)) == NOT_FOUND_IN_DATABASE) return "";
01488 return UsersDisplayNameVector[i];
01489 }
01490
01491
01492
01493 std::string WebUsers::getUsersUsername(uint64_t uid)
01494 {
01495 uint64_t i;
01496 if ((i = searchUsersDatabaseForUserId(uid)) == NOT_FOUND_IN_DATABASE) return "";
01497 return UsersUsernameVector[i];
01498 }
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510 uint64_t WebUsers::cookieCodeLogout(std::string cookieCode, bool logoutOtherUserSessions, uint64_t *userId, std::string ip)
01511 {
01512
01513
01514 uint64_t i;
01515
01516
01517 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
01518 {
01519 __COUT__ << "Cookie code not found" << std::endl;
01520 return NOT_FOUND_IN_DATABASE;
01521 }
01522
01523
01524 if (ActiveSessionIpVector[i] != ip)
01525 {
01526 __COUT__ << "IP does not match active session" << std::endl;
01527 return NOT_FOUND_IN_DATABASE;
01528 }
01529
01530
01531
01532
01533
01534
01535
01536 uint64_t asi = ActiveSessionIndex[i];
01537 uint64_t uid = ActiveSessionUserIdVector[i];
01538 if (userId) *userId = uid;
01539 uint64_t logoutCount = 0;
01540
01541 i = 0;
01542 while (i < ActiveSessionIndex.size())
01543 {
01544 if ((logoutOtherUserSessions && ActiveSessionUserIdVector[i] == uid &&
01545 ActiveSessionIndex[i] != asi) ||
01546 (!logoutOtherUserSessions && ActiveSessionUserIdVector[i] == uid &&
01547 ActiveSessionIndex[i] == asi))
01548 {
01549 __COUT__ << "Logging out of active session " << ActiveSessionUserIdVector[i]
01550 << "-" << ActiveSessionIndex[i] << std::endl;
01551 removeActiveSessionEntry(i);
01552 ++logoutCount;
01553 }
01554 else
01555 ++i;
01556 }
01557
01558 __COUT__ << "Found and removed active session count = " << logoutCount << std::endl;
01559
01560 return logoutCount;
01561 }
01562
01563
01564
01565 bool WebUsers::getUserInfoForCookie(std::string &cookieCode,
01566 std::string *userName, std::string *displayName,
01567 uint64_t *activeSessionIndex)
01568 {
01569 if (userName) *userName = "";
01570 if (displayName) *displayName = "";
01571
01572 if (!CareAboutCookieCodes_)
01573 {
01574 uint64_t uid = getAdminUserID();
01575 if (userName) *userName = getUsersUsername(uid);
01576 if (displayName) *displayName = getUsersDisplayName(uid);
01577 if (activeSessionIndex) *activeSessionIndex = -1;
01578 return true;
01579 }
01580
01581 uint64_t i, j;
01582
01583
01584 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
01585 {
01586 __COUT__ << "cookieCode NOT_FOUND_IN_DATABASE" << std::endl;
01587 return false;
01588 }
01589
01590
01591 if ((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
01592 {
01593 __COUT__ << "ActiveSessionUserIdVector NOT_FOUND_IN_DATABASE" << std::endl;
01594 return false;
01595 }
01596
01597 if (userName) *userName = UsersUsernameVector[j];
01598 if (displayName) *displayName = UsersDisplayNameVector[j];
01599 if (activeSessionIndex) *activeSessionIndex = ActiveSessionIndex[i];
01600 return true;
01601 }
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614 bool WebUsers::cookieCodeIsActiveForRequest(std::string &cookieCode,
01615 uint8_t *userPermissions, uint64_t *uid, std::string ip,
01616 bool refresh, std::string *userWithLock)
01617 {
01618
01619 cleanupExpiredEntries();
01620
01621 uint64_t i, j;
01622
01623
01624
01625
01626 if (!CareAboutCookieCodes_)
01627 {
01628 if (userPermissions) *userPermissions = -1;
01629 if (uid) *uid = getAdminUserID();
01630 if (userWithLock) *userWithLock = usersUsernameWithLock_;
01631
01632 if(cookieCode.size() != COOKIE_CODE_LENGTH)
01633 cookieCode = genCookieCode();
01634
01635 return true;
01636 }
01637
01638
01639
01640 if ((i = searchActiveSessionDatabaseForCookie(cookieCode)) == NOT_FOUND_IN_DATABASE)
01641 {
01642 __COUT__ << "Cookie code not found" << std::endl;
01643 cookieCode = REQ_NO_LOGIN_RESPONSE;
01644 return false;
01645 }
01646
01647
01648 if (ActiveSessionIpVector[i] != ip)
01649 {
01650 __COUT__ << "IP does not match active session" << std::endl;
01651 cookieCode = REQ_NO_LOGIN_RESPONSE;
01652 return false;
01653 }
01654
01655
01656 if ((j = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) == NOT_FOUND_IN_DATABASE)
01657 {
01658 __COUT__ << "User ID not found" << std::endl;
01659 cookieCode = REQ_NO_LOGIN_RESPONSE;
01660 return false;
01661 }
01662
01663 uint8_t tmpPerm = getPermissionsForUser(UsersUserIdVector[j]);
01664
01665 if (!tmpPerm)
01666 {
01667 cookieCode = REQ_NO_PERMISSION_RESPONSE;
01668 return false;
01669 }
01670
01671
01672 if (userPermissions) *userPermissions = tmpPerm;
01673 if (uid) *uid = UsersUserIdVector[j];
01674 if (userWithLock) *userWithLock = usersUsernameWithLock_;
01675
01676 cookieCode = refreshCookieCode(i, refresh);
01677
01678 return true;
01679 }
01680
01681
01682
01683
01684
01685
01686
01687 void WebUsers::cleanupExpiredEntries(std::vector<std::string> *loggedOutUsernames)
01688 {
01689 uint64_t i;
01690 uint64_t tmpUid;
01691
01692 if (loggedOutUsernames)
01693 {
01694 for (i = 0; i < UsersLoggedOutUsernames_.size(); ++i)
01695 loggedOutUsernames->push_back(UsersLoggedOutUsernames_[i]);
01696 UsersLoggedOutUsernames_.clear();
01697 }
01698
01699
01700
01701
01702 for (i = 0; i < LoginSessionStartTimeVector.size(); ++i)
01703 if (LoginSessionStartTimeVector[i] + LOGIN_SESSION_EXPIRATION_TIME < time(0) ||
01704 LoginSessionAttemptsVector[i] > LOGIN_SESSION_ATTEMPTS_MAX)
01705 {
01706
01707
01708
01709 removeLoginSessionEntry(i);
01710 --i;
01711 }
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722 for (i = 0; i < ActiveSessionStartTimeVector.size(); ++i)
01723 if (ActiveSessionStartTimeVector[i] + ACTIVE_SESSION_EXPIRATION_TIME <= time(0))
01724 {
01725
01726
01727
01728
01729
01730 tmpUid = ActiveSessionUserIdVector[i];
01731 removeActiveSessionEntry(i);
01732
01733
01734
01735 if (!isUserIdActive(tmpUid))
01736 {
01737 if (loggedOutUsernames)
01738 loggedOutUsernames->push_back(UsersUsernameVector[searchUsersDatabaseForUserId(tmpUid)]);
01739 else
01740 UsersLoggedOutUsernames_.push_back(UsersUsernameVector[searchUsersDatabaseForUserId(tmpUid)]);
01741 }
01742
01743 --i;
01744 }
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757 if (CareAboutCookieCodes_ && !isUsernameActive(usersUsernameWithLock_))
01758 usersUsernameWithLock_ = "";
01759 }
01760
01761
01762
01763
01764
01765
01766
01767
01768 std::string WebUsers::createNewLoginSession(std::string UUID, std::string ip)
01769 {
01770 __COUT__ << "UUID: " << UUID << std::endl << std::endl;
01771 uint64_t i = 0;
01772 for (; i < LoginSessionUUIDVector.size(); ++i)
01773 if (LoginSessionUUIDVector[i] == UUID) break;
01774
01775 if (i != LoginSessionUUIDVector.size())
01776 {
01777 __COUT__ << "UUID: " << UUID << " is not unique" << std::endl;
01778 return "";
01779 }
01780
01781
01782 LoginSessionUUIDVector.push_back(UUID);
01783
01784
01785 char hexStr[3];
01786 std::string sid = "";
01787 for (i = 0; i < SESSION_ID_LENGTH / 2; ++i)
01788 {
01789 intToHexStr(rand(), hexStr);
01790 sid.append(hexStr);
01791 }
01792 LoginSessionIdVector.push_back(sid);
01793 LoginSessionIpVector.push_back("");
01794 LoginSessionStartTimeVector.push_back(time(0));
01795 LoginSessionAttemptsVector.push_back(0);
01796
01797 return sid;
01798 }
01799
01800
01801
01802
01803
01804
01805
01806
01807 std::string WebUsers::sha512(std::string user, std::string password, std::string &salt)
01808 {
01809 SHA512_CTX sha512_context;
01810 char hexStr[3];
01811
01812 if (salt == "")
01813 {
01814 SHA512_Init(&sha512_context);
01815
01816 for (unsigned int i = 0; i < 8; ++i)
01817 sha512_context.h[i] += rand();
01818
01819 for (unsigned int i = 0; i < sizeof(SHA512_CTX); ++i)
01820 {
01821 intToHexStr((uint8_t)(((uint8_t *)(&sha512_context))[i]), hexStr);
01822
01823 salt.append(hexStr);
01824 }
01825
01826 }
01827 else
01828 {
01829
01830
01831
01832 for (unsigned int i = 0; i < sizeof(SHA512_CTX); ++i)
01833 ((uint8_t *)(&sha512_context))[i] = hexByteStrToInt(&(salt.c_str()[i * 2]));
01834 }
01835
01836 std::string strToHash = salt + user + password;
01837
01838
01839 unsigned char hash[SHA512_DIGEST_LENGTH];
01840
01841 char retHash[SHA512_DIGEST_LENGTH * 2 + 1];
01842
01843
01844
01845
01846 SHA512_Update(&sha512_context, strToHash.c_str(), strToHash.length());
01847
01848 SHA512_Final(hash, &sha512_context);
01849
01850
01851 int i = 0;
01852 for (i = 0; i < SHA512_DIGEST_LENGTH; i++)
01853 sprintf(retHash + (i * 2), "%02x", hash[i]);
01854
01855
01856 retHash[SHA512_DIGEST_LENGTH * 2] = '\0';
01857
01858
01859
01860
01861
01862 return retHash;
01863 }
01864
01865
01866
01867
01868
01869
01870 std::string WebUsers::dejumble(std::string u, std::string s)
01871 {
01872
01873 if (s.length() != SESSION_ID_LENGTH) return "";
01874
01875 const int ss = s.length() / 2;
01876 int p = hexByteStrToInt(&(s.c_str()[0])) % ss;
01877 int n = hexByteStrToInt(&(s.c_str()[p * 2])) % ss;
01878 int len = (hexByteStrToInt(&(u.c_str()[p * 2])) - p - n + ss * 3) % ss;
01879
01880 std::vector<bool> x(ss);
01881 for (int i = 0; i < ss; ++i) x[i] = 0;
01882 x[p] = 1;
01883
01884 int c = hexByteStrToInt(&(u.c_str()[p * 2]));
01885
01886 std::string user = "";
01887
01888 for (int l = 0; l < len; ++l)
01889 {
01890 p = (p + hexByteStrToInt(&(s.c_str()[p * 2]))) % ss;
01891 while (x[p]) p = (p + 1) % ss;
01892 x[p] = 1;
01893 n = hexByteStrToInt(&(s.c_str()[p * 2]));
01894 user.append(1, (hexByteStrToInt(&(u.c_str()[p * 2])) - c - n + ss * 4) % ss);
01895 c = hexByteStrToInt(&(u.c_str()[p * 2]));
01896 }
01897
01898 return user;
01899 }
01900
01901
01902
01903
01904 uint8_t WebUsers::getPermissionsForUser(uint64_t uid)
01905 {
01906 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
01907 return (userIndex < UsersPermissionsVector.size()) ? UsersPermissionsVector[userIndex] : 0;
01908 }
01909
01910
01911
01912
01913
01914 std::string WebUsers::getTooltipFilename(
01915 const std::string& username, const std::string &srcFile,
01916 const std::string &srcFunc, const std::string &srcId)
01917 {
01918 std::string filename = (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH + "/";
01919
01920
01921
01922 mkdir(((std::string)WEB_LOGIN_DB_PATH).c_str(), 0755);
01923 mkdir(((std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH).c_str(), 0755);
01924 mkdir(filename.c_str(), 0755);
01925
01926 for (const char& c : username)
01927 if (
01928 (c >= 'a' && c <= 'z') ||
01929 (c >= 'A' && c <= 'Z') ||
01930 (c >= '0' && c <= '9'))
01931 filename += c;
01932 filename += "/";
01933
01934
01935 mkdir(filename.c_str(), 0755);
01936
01937 for (const char& c : srcFile)
01938 if (
01939 (c >= 'a' && c <= 'z') ||
01940 (c >= 'A' && c <= 'Z') ||
01941 (c >= '0' && c <= '9'))
01942 filename += c;
01943 filename += "_";
01944 for (const char& c : srcFunc)
01945 if (
01946 (c >= 'a' && c <= 'z') ||
01947 (c >= 'A' && c <= 'Z') ||
01948 (c >= '0' && c <= '9'))
01949 filename += c;
01950 filename += "_";
01951 for (const char& c : srcId)
01952 if (
01953 (c >= 'a' && c <= 'z') ||
01954 (c >= 'A' && c <= 'Z') ||
01955 (c >= '0' && c <= '9'))
01956 filename += c;
01957 filename += ".tip";
01958 __COUT__ << "filename " << filename << std::endl;
01959 return filename;
01960 }
01961
01962 std::string ots::WebUsers::getUserEmailFromFingerprint(std::string fingerprint)
01963 {
01964 std::ifstream f(WEB_LOGIN_CERTDATA_PATH);
01965 if (f.is_open())
01966 {
01967 std::string email;
01968 std::string fp;
01969 getline(f, email);
01970 getline(f, fp);
01971 certFingerprints_[email] = fp;
01972 f.close();
01973 remove(WEB_LOGIN_CERTDATA_PATH.c_str());
01974 }
01975
01976 for (auto fp : certFingerprints_)
01977 {
01978 if (fp.second == fingerprint) return fp.first;
01979 }
01980 return "";
01981 }
01982
01983
01984
01985
01986 void WebUsers::tooltipSetNeverShowForUsername(const std::string& username,
01987 HttpXmlDocument *xmldoc,
01988 const std::string &srcFile, const std::string &srcFunc,
01989 const std::string &srcId, bool doNeverShow, bool temporarySilence)
01990 {
01991
01992 __COUT__ << "Setting tooltip never show for user: " << username <<
01993 " to " << doNeverShow << " (temporarySilence=" <<
01994 temporarySilence << ")" << std::endl;
01995
01996
01997 std::string filename = getTooltipFilename(username, srcFile, srcFunc, srcId);
01998 FILE *fp = fopen(filename.c_str(), "w");
01999 if (fp)
02000 {
02001 if (temporarySilence)
02002 fprintf(fp, "%ld", time(0) + 60 * 60);
02003 else
02004 fputc(doNeverShow ? '1' : '0', fp);
02005 fclose(fp);
02006 }
02007 else
02008 __COUT_ERR__ << "Big problme with tooltips! File not accessible: " << filename << std::endl;
02009 }
02010
02011
02012
02013
02014
02015
02016
02017
02018 void WebUsers::tooltipCheckForUsername(const std::string& username,
02019 HttpXmlDocument *xmldoc,
02020 const std::string &srcFile, const std::string &srcFunc,
02021 const std::string &srcId)
02022 {
02023 if (srcId == "ALWAYS")
02024 {
02025
02026 xmldoc->addTextElementToData("ShowTooltip", "1");
02027 return;
02028 }
02029
02030
02031
02032
02033
02034 __COUT__ << "Checking tooltip for user: " << username << std::endl;
02035
02036
02037
02038 std::string filename = getTooltipFilename(username, srcFile, srcFunc, srcId);
02039 FILE *fp = fopen(filename.c_str(), "r");
02040 if (fp)
02041 {
02042 time_t val;
02043 char line[100];
02044 fgets(line, 100, fp);
02045
02046 sscanf(line, "%ld", &val);
02047 __COUT__ << "tooltip value read = " << val << std::endl;
02048 fclose(fp);
02049
02050
02051
02052 xmldoc->addTextElementToData("ShowTooltip", val == 1 ? "0" :
02053 (time(0) > val ? "1" : "0"));
02054 }
02055 else
02056 xmldoc->addTextElementToData("ShowTooltip", "1");
02057 }
02058
02059
02060
02061 void WebUsers::resetAllUserTooltips(const std::string &userNeedle)
02062 {
02063 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH +
02064 "/" + userNeedle).c_str());
02065 __COUT__ << "Successfully reset Tooltips for user " << userNeedle << std::endl;
02066 }
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086 void WebUsers::insertSettingsForUser(uint64_t uid, HttpXmlDocument *xmldoc, bool includeAccounts)
02087 {
02088 uint8_t p = getPermissionsForUser(uid);
02089 if (!p) return;
02090
02091 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
02092 __COUT__ << "Gettings settings for user: " << UsersUsernameVector[userIndex] << std::endl;
02093
02094 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH + UsersUsernameVector[userIndex] + "." + (std::string)USERS_PREFERENCES_FILETYPE;
02095
02096 HttpXmlDocument prefXml;
02097
02098 __COUT__ << "Preferences file: " << fn << std::endl;
02099
02100 if (!prefXml.loadXmlDocument(fn))
02101 {
02102 __COUT__ << "Preferences are defaults." << std::endl;
02103
02104 xmldoc->addTextElementToData(PREF_XML_BGCOLOR_FIELD, PREF_XML_BGCOLOR_DEFAULT);
02105 xmldoc->addTextElementToData(PREF_XML_DBCOLOR_FIELD, PREF_XML_DBCOLOR_DEFAULT);
02106 xmldoc->addTextElementToData(PREF_XML_WINCOLOR_FIELD, PREF_XML_WINCOLOR_DEFAULT);
02107 xmldoc->addTextElementToData(PREF_XML_LAYOUT_FIELD, PREF_XML_LAYOUT_DEFAULT);
02108 }
02109 else
02110 {
02111 __COUT__ << "Saved Preferences found." << std::endl;
02112 xmldoc->copyDataChildren(prefXml);
02113 }
02114
02115 char permStr[10];
02116
02117
02118 if (includeAccounts && p == (uint8_t)-1)
02119 {
02120
02121 __COUT__ << "Super User on our hands" << std::endl;
02122
02123 xmldoc->addTextElementToData(PREF_XML_ACCOUNTS_FIELD, "");
02124
02125
02126
02127 for (uint64_t i = 0; i < UsersUsernameVector.size(); ++i)
02128 {
02129 xmldoc->addTextElementToParent("username", UsersUsernameVector[i], PREF_XML_ACCOUNTS_FIELD);
02130 xmldoc->addTextElementToParent("display_name", UsersDisplayNameVector[i], PREF_XML_ACCOUNTS_FIELD);
02131 if (UsersUserEmailVector.size() > i)
02132 {
02133 xmldoc->addTextElementToParent("useremail", UsersUserEmailVector[i], PREF_XML_ACCOUNTS_FIELD);
02134 }
02135 else
02136 {
02137 xmldoc->addTextElementToParent("useremail", "", PREF_XML_ACCOUNTS_FIELD);
02138
02139 }
02140 sprintf(permStr, "%d", UsersPermissionsVector[i]);
02141 xmldoc->addTextElementToParent("permissions", permStr, PREF_XML_ACCOUNTS_FIELD);
02142 if (UsersSaltVector[i] == "")
02143 sprintf(permStr, "%d", int(UsersAccountCreatedTimeVector[i] & 0xffff));
02144 else
02145 permStr[0] = '\0';
02146 xmldoc->addTextElementToParent("nac", permStr, PREF_XML_ACCOUNTS_FIELD);
02147 }
02148 }
02149
02150
02151 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
02152 (std::string)SYSTEM_PREFERENCES_PREFIX + "." + (std::string)USERS_PREFERENCES_FILETYPE;
02153 if (!prefXml.loadXmlDocument(fn))
02154 {
02155 __COUT__ << "System Preferences are defaults." << std::endl;
02156
02157 xmldoc->addTextElementToData(PREF_XML_SYSLAYOUT_FIELD, PREF_XML_SYSLAYOUT_DEFAULT);
02158 }
02159 else
02160 {
02161 __COUT__ << "Saved System Preferences found." << std::endl;
02162 xmldoc->copyDataChildren(prefXml);
02163 }
02164
02165
02166 sprintf(permStr, "%d", p);
02167 xmldoc->addTextElementToData(PREF_XML_PERMISSIONS_FIELD, permStr);
02168
02169
02170 xmldoc->addTextElementToData(PREF_XML_USERLOCK_FIELD, usersUsernameWithLock_);
02171
02172 xmldoc->addTextElementToData(PREF_XML_USERNAME_FIELD, getUsersUsername(uid));
02173 }
02174
02175
02176
02177
02178 void WebUsers::setGenericPreference(uint64_t uid, const std::string &preferenceName,
02179 const std::string &preferenceValue)
02180 {
02181 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
02182
02183
02184
02185 std::string safePreferenceName = "";
02186 for (const auto &c : preferenceName)
02187 if ((c >= 'a' && c <= 'z') ||
02188 (c >= 'A' && c <= 'Z') ||
02189 (c >= '0' && c <= '9') ||
02190 (c >= '-' || c <= '_'))
02191 safePreferenceName += c;
02192
02193 std::string dir = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
02194 "generic_" + safePreferenceName + "/";
02195
02196
02197 mkdir(dir.c_str(), 0755);
02198
02199 std::string fn = UsersUsernameVector[userIndex] + "_" + safePreferenceName +
02200 "." + (std::string)USERS_PREFERENCES_FILETYPE;
02201
02202 __COUT__ << "Preferences file: " << (dir + fn) << std::endl;
02203
02204 FILE *fp = fopen((dir + fn).c_str(), "w");
02205 if (fp)
02206 {
02207 fprintf(fp, "%s", preferenceValue.c_str());
02208 fclose(fp);
02209 }
02210 else
02211 __COUT_ERR__ << "Preferences file could not be opened for writing!" << std::endl;
02212 }
02213
02214
02215
02216
02217
02218 std::string WebUsers::getGenericPreference(uint64_t uid, const std::string &preferenceName,
02219 HttpXmlDocument *xmldoc) const
02220 {
02221 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
02222
02223
02224
02225 std::string safePreferenceName = "";
02226 for (const auto &c : preferenceName)
02227 if ((c >= 'a' && c <= 'z') ||
02228 (c >= 'A' && c <= 'Z') ||
02229 (c >= '0' && c <= '9') ||
02230 (c >= '-' || c <= '_'))
02231 safePreferenceName += c;
02232
02233 std::string dir = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
02234 "generic_" + safePreferenceName + "/";
02235
02236 std::string fn = UsersUsernameVector[userIndex] + "_" + safePreferenceName +
02237 "." + (std::string)USERS_PREFERENCES_FILETYPE;
02238
02239 __COUT__ << "Preferences file: " << (dir + fn) << std::endl;
02240
02241
02242 FILE *fp = fopen((dir + fn).c_str(), "rb");
02243 if (fp)
02244 {
02245 fseek(fp, 0, SEEK_END);
02246 long size = ftell(fp);
02247 std::string line;
02248 line.reserve(size + 1);
02249 rewind(fp);
02250 fgets(&line[0], size + 1, fp);
02251 fclose(fp);
02252
02253 __COUT__ << "Read value " << line << std::endl;
02254 if (xmldoc) xmldoc->addTextElementToData(safePreferenceName, line);
02255 return line;
02256 }
02257 else
02258 __COUT__ << "Using default value." << std::endl;
02259
02260
02261 if (xmldoc) xmldoc->addTextElementToData(safePreferenceName, "");
02262 return "";
02263 }
02264
02265
02266
02267 void WebUsers::changeSettingsForUser(uint64_t uid, const std::string &bgcolor, const std::string &dbcolor,
02268 const std::string &wincolor, const std::string &layout, const std::string &syslayout)
02269 {
02270 uint8_t p = getPermissionsForUser(uid);
02271 if (!p) return;
02272
02273 uint64_t userIndex = searchUsersDatabaseForUserId(uid);
02274 __COUT__ << "Changing settings for user: " << UsersUsernameVector[userIndex] << std::endl;
02275
02276 std::string fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH + UsersUsernameVector[userIndex] + "." + (std::string)USERS_PREFERENCES_FILETYPE;
02277
02278 __COUT__ << "Preferences file: " << fn << std::endl;
02279
02280 HttpXmlDocument prefXml;
02281 prefXml.addTextElementToData(PREF_XML_BGCOLOR_FIELD, bgcolor);
02282 prefXml.addTextElementToData(PREF_XML_DBCOLOR_FIELD, dbcolor);
02283 prefXml.addTextElementToData(PREF_XML_WINCOLOR_FIELD, wincolor);
02284 prefXml.addTextElementToData(PREF_XML_LAYOUT_FIELD, layout);
02285
02286 prefXml.saveXmlDocument(fn);
02287
02288
02289 if (p < 255) return;
02290
02291
02292 fn = (std::string)WEB_LOGIN_DB_PATH + (std::string)USERS_PREFERENCES_PATH +
02293 (std::string)SYSTEM_PREFERENCES_PREFIX + "." + (std::string)USERS_PREFERENCES_FILETYPE;
02294
02295 HttpXmlDocument sysPrefXml;
02296 sysPrefXml.addTextElementToData(PREF_XML_SYSLAYOUT_FIELD, syslayout);
02297
02298 sysPrefXml.saveXmlDocument(fn);
02299
02300 }
02301
02302
02303
02304
02305
02306
02307 bool WebUsers::setUserWithLock(uint64_t uid_master, bool lock, std::string username)
02308 {
02309 uint8_t p = getPermissionsForUser(uid_master);
02310
02311 __COUT__ << "permissions " << (int)p << std::endl;
02312 __COUT__ << "usersUsernameWithLock_ " << usersUsernameWithLock_ << std::endl;
02313 __COUT__ << "lock " << lock << std::endl;
02314 __COUT__ << "username " << username << std::endl;
02315 __COUT__ << "isUsernameActive(username) " << isUsernameActive(username) << std::endl;
02316
02317 if (p != (uint8_t)-1) return false;
02318
02319
02320 if (lock && (isUsernameActive(username) || !CareAboutCookieCodes_))
02321 {
02322 if (!CareAboutCookieCodes_ && username != DEFAULT_ADMIN_USERNAME)
02323 {
02324 __COUT__ << "User tried to lock for a user other than admin in wiz mode. Not allowed." << std::endl;
02325 return false;
02326 }
02327 usersUsernameWithLock_ = username;
02328 }
02329 else if (!lock && usersUsernameWithLock_ == username)
02330 usersUsernameWithLock_ = "";
02331 else
02332 {
02333 if (!isUsernameActive(username))
02334 __COUT__ << "User is inactive." << std::endl;
02335 __MOUT_WARN__ << "Failed to lock for user '" << username << ".'" << std::endl;
02336 return false;
02337 }
02338
02339 __MOUT_INFO__ << "User '" << username << "' has locked out the system!" << std::endl;
02340
02341
02342 {
02343 std::string securityFileName = USER_WITH_LOCK_FILE;
02344 FILE *fp = fopen(securityFileName.c_str(), "w");
02345 if (!fp)
02346 {
02347 __COUT_INFO__ << "USER_WITH_LOCK_FILE " << USER_WITH_LOCK_FILE <<
02348 " not found. Ignoring." << std::endl;
02349 }
02350 else
02351 {
02352 fprintf(fp, "%s", usersUsernameWithLock_.c_str());
02353 fclose(fp);
02354 }
02355 }
02356 return true;
02357 }
02358
02359
02360
02361 void WebUsers::modifyAccountSettings(uint64_t uid_master, uint8_t cmd_type, std::string username, std::string displayname, std::string email, std::string permissions)
02362 {
02363
02364 uint8_t p = getPermissionsForUser(uid_master);
02365 if (p != (uint8_t)-1) return;
02366
02367 uint64_t modi = searchUsersDatabaseForUsername(username);
02368 if (modi == 0)
02369 {
02370 __COUT__ << "Cannot modify first user" << std::endl;
02371 return;
02372 }
02373
02374 if (username.length() < USERNAME_LENGTH || displayname.length() < DISPLAY_NAME_LENGTH)
02375 {
02376 __COUT__ << "Invalid Username or Display Name must be length " << USERNAME_LENGTH << " or " << DISPLAY_NAME_LENGTH << std::endl;
02377 return;
02378 }
02379
02380 int inputp;
02381 sscanf(permissions.c_str(), "%d", &inputp);
02382
02383 __COUT__ << "Input Permissions " << inputp << std::endl;
02384
02385 switch (cmd_type)
02386 {
02387 case MOD_TYPE_UPDATE:
02388 __COUT__ << "MOD_TYPE_UPDATE " << username << " := " << inputp << std::endl;
02389 if (modi == NOT_FOUND_IN_DATABASE)
02390 {
02391 __COUT__ << "User not found!? Should not happen." << std::endl;
02392 return;
02393 }
02394
02395 UsersDisplayNameVector[modi] = displayname;
02396 UsersUserEmailVector[modi] = email;
02397
02398
02399
02400 if (!UsersPermissionsVector[modi] && inputp)
02401 {
02402 UsersLoginFailureCountVector[modi] = 0;
02403 UsersSaltVector[modi] = "";
02404 }
02405 UsersPermissionsVector[modi] = inputp;
02406
02407
02408 {
02409 uint64_t i = searchUsersDatabaseForUserId(uid_master);
02410 if (i == NOT_FOUND_IN_DATABASE)
02411 {
02412 __COUT__ << "Master User not found!? Should not happen." << std::endl;
02413 return;
02414 }
02415 UsersLastModifierUsernameVector[modi] = UsersUsernameVector[i];
02416 UsersLastModifiedTimeVector[modi] = time(0);
02417 }
02418 break;
02419 case MOD_TYPE_ADD:
02420 __COUT__ << "MOD_TYPE_ADD " << username << " - " << displayname << std::endl;
02421 createNewAccount(username, displayname, email);
02422 break;
02423 case MOD_TYPE_DELETE:
02424 __COUT__ << "MOD_TYPE_DELETE " << username << " - " << displayname << std::endl;
02425 deleteAccount(username, displayname);
02426 break;
02427 default:
02428 __COUT__ << "Undefined command - do nothing " << username << std::endl;
02429 }
02430
02431 saveDatabaseToFile(DB_USERS);
02432 }
02433
02434
02435
02436 std::string WebUsers::getActiveUsersString()
02437 {
02438 std::string ret = "";
02439 uint64_t u;
02440 bool repeat;
02441 for (uint64_t i = 0; i < ActiveSessionUserIdVector.size(); ++i)
02442 {
02443 repeat = false;
02444
02445 for (uint64_t j = 0; j < i; ++j)
02446 if (ActiveSessionUserIdVector[i] == ActiveSessionUserIdVector[j])
02447 {
02448 repeat = true; break;
02449 }
02450
02451 if (!repeat && (u = searchUsersDatabaseForUserId(ActiveSessionUserIdVector[i])) !=
02452 NOT_FOUND_IN_DATABASE)
02453 ret += UsersDisplayNameVector[u] + ",";
02454 }
02455 if (ret.length() > 1) ret.erase(ret.length() - 1);
02456 return ret;
02457 }
02458
02459
02460
02461 uint64_t WebUsers::getAdminUserID()
02462 {
02463 uint64_t uid = searchUsersDatabaseForUsername(DEFAULT_ADMIN_USERNAME);
02464 return uid;
02465 }
02466
02467
02468
02469
02470
02471 void WebUsers::loadUserWithLock()
02472 {
02473 char username[300] = "";
02474
02475 std::string securityFileName = USER_WITH_LOCK_FILE;
02476 FILE *fp = fopen(securityFileName.c_str(), "r");
02477 if (!fp)
02478 {
02479 __COUT_INFO__ << "USER_WITH_LOCK_FILE " << USER_WITH_LOCK_FILE <<
02480 " not found. Defaulting to admin lock." << std::endl;
02481
02482
02483 sprintf(username, "%s", DEFAULT_ADMIN_USERNAME.c_str());
02484 }
02485 else
02486 {
02487 fgets(username, 300, fp);
02488 username[299] = '\0';
02489 fclose(fp);
02490 }
02491
02492
02493 __COUT__ << "Attempting to load username with lock: " << username << std::endl;
02494
02495 if (strlen(username) == 0)
02496 {
02497 __COUT_INFO__ << "Loaded state for user-with-lock is unlocked." << std::endl;
02498 return;
02499 }
02500
02501 uint64_t i = searchUsersDatabaseForUsername(username);
02502 if (i == NOT_FOUND_IN_DATABASE)
02503 {
02504 __COUT_INFO__ << "username " << username <<
02505 " not found in database. Ignoring." << std::endl;
02506 return;
02507 }
02508 __COUT__ << "Setting lock" << std::endl;
02509 setUserWithLock(UsersUserIdVector[i], true, username);
02510 }
02511
02512
02513
02514
02515 std::string WebUsers::getSecurity()
02516 {
02517 return securityType_;
02518 }
02519
02520
02521
02522 void WebUsers::loadSecuritySelection()
02523 {
02524 std::string securityFileName = SECURITY_FILE_NAME;
02525 FILE *fp = fopen(securityFileName.c_str(), "r");
02526 char line[100] = "";
02527 if (fp) fgets(line, 100, fp);
02528 unsigned int i = 0;
02529
02530
02531 while (i < strlen(line) && line[i] >= 'A' && line[i] <= 'z') ++i;
02532 line[i] = '\0';
02533
02534
02535 if (strcmp(line, SECURITY_TYPE_NONE.c_str()) == 0 ||
02536 strcmp(line, SECURITY_TYPE_DIGEST_ACCESS.c_str()) == 0)
02537 securityType_ = line;
02538 else
02539 securityType_ = SECURITY_TYPE_DIGEST_ACCESS;
02540
02541 __COUT__ << "The current security type is " << securityType_ << std::endl;
02542
02543 if (fp) fclose(fp);
02544
02545
02546 if (securityType_ == SECURITY_TYPE_NONE)
02547 CareAboutCookieCodes_ = false;
02548 else
02549 CareAboutCookieCodes_ = true;
02550
02551 __COUT__ << "CareAboutCookieCodes_: " <<
02552 CareAboutCookieCodes_ << std::endl;
02553
02554 }
02555
02556
02557
02558
02559 void WebUsers::NACDisplayThread(std::string nac, std::string user)
02560 {
02561 INIT_MF("WebUsers_NAC");
02563
02564
02565
02566
02567 int i = 0;
02568 for (; i < 5; ++i)
02569 {
02570 std::this_thread::sleep_for(std::chrono::seconds(2));
02571 __COUT__ << __COUT_HDR_P__ << "\n******************************************************************** " << std::endl;
02572 __COUT__ << __COUT_HDR_P__ << "\n******************************************************************** " << std::endl;
02573 __COUT__ << __COUT_HDR_P__ << "\n\nNew account code = " << nac << " for user: " << user << "\n" << std::endl;
02574 __COUT__ << __COUT_HDR_P__ << "\n******************************************************************** " << std::endl;
02575 __COUT__ << __COUT_HDR_P__ << "\n******************************************************************** " << std::endl;
02576 }
02577 }
02578
02579
02580 void WebUsers::deleteUserData()
02581 {
02582
02583 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + HASHES_DB_PATH + "/*").c_str());
02584 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_DB_PATH + "/*").c_str());
02585 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_LOGIN_HISTORY_PATH + "/*").c_str());
02586 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + USERS_PREFERENCES_PATH + "/*").c_str());
02587 std::system(("rm -rf " + (std::string)WEB_LOGIN_DB_PATH + TOOLTIP_DB_PATH).c_str());
02588
02589 std::string serviceDataPath = getenv("SERVICE_DATA_PATH");
02590
02591 std::system(("rm -rf " + std::string(serviceDataPath) + "/MacroData/").c_str());
02592 std::system(("rm -rf " + std::string(serviceDataPath) + "/MacroHistory/").c_str());
02593 std::system(("rm -rf " + std::string(serviceDataPath) + "/MacroExport/").c_str());
02594
02595
02596 std::system(("rm -rf " + std::string(serviceDataPath) + "/ConsolePreferences/").c_str());
02597
02598
02599 std::system(("rm -rf " + std::string(serviceDataPath) + "/OtsWizardData/").c_str());
02600
02601
02602 std::system(("rm -rf " + std::string(serviceDataPath) + "/ProgressBarData/").c_str());
02603
02604
02605 std::system(("rm -rf " + std::string(serviceDataPath) + "/RunNumber/").c_str());
02606 std::system(("rm -rf " + std::string(serviceDataPath) + "/RunControlData/").c_str());
02607
02608
02609 std::system(("rm -rf " + std::string(serviceDataPath) + "/VisualizerData/").c_str());
02610
02611
02612 std::system(("rm -rf " + std::string(serviceDataPath) + "/ActiveConfigurationGroups.cfg").c_str());
02613
02614
02615 std::system(("rm -rf " + std::string(getenv("LOGBOOK_DATA_PATH")) + "/").c_str());
02616
02617 std::cout << __COUT_HDR_FL__ << "$$$$$$$$$$$$$$ Successfully deleted ALL service user data $$$$$$$$$$$$" << std::endl;
02618 }
02619
02620