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