/************************************************************************* * UrBackup - Client/Server backup system * Copyright (C) 2011-2016 Martin Raiber * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . **************************************************************************/ #ifndef CLIENT_ONLY #include "action_header.h" #include "../server_settings.h" #include "../../Interface/SettingsReader.h" #include "../../urlplugin/IUrlFactory.h" #include "../../urbackupcommon/os_functions.h" #include "../../cryptoplugin/ICryptoFactory.h" #include "../../urbackupcommon/settingslist.h" #include "../ClientMain.h" #include "../server_archive.h" #include "../dao/ServerBackupDao.h" #include "../server.h" extern IUrlFactory *url_fak; extern ICryptoFactory *crypto_fak; void updateRights(int t_userid, std::string s_rights, IDatabase *db) { str_map rights; ParseParamStrHttp(s_rights, &rights); IQuery *q_del=db->Prepare("DELETE FROM settings_db.si_permissions WHERE clientid=?"); q_del->Bind(t_userid); q_del->Write(); q_del->Reset(); str_map::iterator idx=rights.find("idx"); if(idx!=rights.end()) { std::vector elms; Tokenize(idx->second, elms, ","); if(!elms.empty()) { IQuery *q_insert=db->Prepare("INSERT INTO settings_db.si_permissions (t_domain, t_right, clientid) VALUES (?,?,?)"); for(size_t i=0;iBind(it_domain->second); q_insert->Bind(it_right->second); q_insert->Bind(t_userid); q_insert->Write(); q_insert->Reset(); } } } } } namespace { std::vector getMailSettingsList(void) { std::vector tmp; tmp.push_back("mail_servername"); tmp.push_back("mail_serverport"); tmp.push_back("mail_username"); tmp.push_back("mail_password"); tmp.push_back("mail_from"); tmp.push_back("mail_ssl_only"); tmp.push_back("mail_check_certificate"); tmp.push_back("mail_use_smtps"); tmp.push_back("mail_admin_addrs"); return tmp; } JSON::Array getAlertScripts(IDatabase* db) { db_results res_scripts = db->Read("SELECT id, name FROM alert_scripts"); IQuery* q_get_params = db->Prepare("SELECT name, label, default_value, has_translation, type FROM alert_script_params WHERE script_id=? ORDER BY idx ASC"); JSON::Array ret; for (size_t i = 0; i < res_scripts.size(); ++i) { q_get_params->Bind(res_scripts[i]["id"]); db_results res_params = q_get_params->Read(); q_get_params->Reset(); JSON::Object script; script.set("id", res_scripts[i]["id"]); script.set("name", res_scripts[i]["name"]); JSON::Array params; for (size_t j = 0; j < res_params.size(); ++j) { JSON::Object obj; obj.set("name", res_params[j]["name"]); obj.set("label", res_params[j]["label"]); obj.set("default_value", res_params[j]["default_value"]); obj.set("has_translation", watoi(res_params[j]["has_translation"])); obj.set("type", res_params[j]["type"]); params.add(obj); } script.set("params", params); ret.add(script); } return ret; } template T ret_identity(const T& str) { return str; } bool conv_bool_setting(const std::string& str) { if (str == "1" || str == "true") return true; else return false; } JSON::Object getJSONClientSettings(IDatabase *db, int t_clientid) { int group_id = 0; if (t_clientid > 0) { db_results res = db->Read("SELECT value FROM settings_db.settings WHERE clientid=" + convert(t_clientid) + " AND key='group_id'"); if (!res.empty()) { group_id = watoi(res[0]["value"])*-1; } } ServerSettings settings_group(db, group_id); std::unique_ptr settings_def; if (t_clientid == 0) { settings_def.reset(new ServerSettings(db, t_clientid)); } IQuery* q_get_setting = db->Prepare("SELECT value, value_client, use FROM settings_db.settings WHERE key=? AND clientid=" + convert(t_clientid)); JSON::Object ret; #define SET_SETTING(x, func1, func2) {\ q_get_setting->Bind(#x); \ db_results res = q_get_setting->Read(); \ q_get_setting->Reset(); \ JSON::Object j_obj; \ if(!res.empty()) \ { \ j_obj.set("value", func1(res[0]["value"])); \ if(t_clientid>0) {\ j_obj.set("value_client", func1(res[0]["value_client"])); \ } \ if(t_clientid!=0) {\ j_obj.set("use", watoi(res[0]["use"])); \ } \ } else if(t_clientid!=0) { \ j_obj.set("use", c_use_group); \ } else if(t_clientid==0) { \ j_obj.set("value", func2(settings_def->getSettings()->x) ); \ } \ if(t_clientid!=0) { \ j_obj.set("value_group", func2(settings_group.getSettings()->x)); \ } \ ret.set(#x, j_obj); } #define SET_SETTING_STR(x) SET_SETTING(x, ret_identity, ret_identity) #define SET_SETTING_INT(x) SET_SETTING(x, watoi, ret_identity) #define SET_SETTING_INT64(x) SET_SETTING(x, watoi64, ret_identity) #define SET_SETTING_BOOL(x) SET_SETTING(x, conv_bool_setting, ret_identity) SET_SETTING_STR(update_freq_incr); SET_SETTING_STR(update_freq_full); SET_SETTING_STR(update_freq_image_full); SET_SETTING_STR(update_freq_image_incr); SET_SETTING_INT(max_file_incr); SET_SETTING_BOOL(backup_dirs_optional); SET_SETTING_INT(min_file_incr); SET_SETTING_INT(max_file_full); SET_SETTING_INT(min_file_full); SET_SETTING_INT(min_image_incr); SET_SETTING_INT(max_image_incr); SET_SETTING_INT(min_image_full); SET_SETTING_INT(max_image_full); SET_SETTING_BOOL(allow_overwrite); SET_SETTING_INT(startup_backup_delay); SET_SETTING_STR(backup_window_incr_file); SET_SETTING_STR(backup_window_full_file); SET_SETTING_STR(backup_window_incr_image); SET_SETTING_STR(backup_window_full_image); SET_SETTING_STR(computername); SET_SETTING_STR(virtual_clients); SET_SETTING_STR(exclude_files); SET_SETTING_STR(include_files); SET_SETTING_STR(default_dirs); SET_SETTING_BOOL(allow_config_paths); SET_SETTING_BOOL(allow_starting_full_file_backups); SET_SETTING_BOOL(allow_starting_incr_file_backups); SET_SETTING_BOOL(allow_starting_full_image_backups); SET_SETTING_BOOL(allow_starting_incr_image_backups); SET_SETTING_BOOL(allow_pause); SET_SETTING_BOOL(allow_log_view); SET_SETTING_BOOL(allow_tray_exit); SET_SETTING_STR(image_letters); SET_SETTING_STR(internet_authkey); SET_SETTING_BOOL(client_set_settings); SET_SETTING_STR(internet_speed); SET_SETTING_STR(local_speed); SET_SETTING_BOOL(internet_mode_enabled); SET_SETTING_BOOL(internet_compress); SET_SETTING_BOOL(internet_encrypt); SET_SETTING_BOOL(internet_image_backups); SET_SETTING_BOOL(internet_full_file_backups); SET_SETTING_BOOL(silent_update); SET_SETTING_STR(client_quota); SET_SETTING_STR(local_full_file_transfer_mode); SET_SETTING_STR(internet_full_file_transfer_mode); SET_SETTING_STR(local_incr_file_transfer_mode); SET_SETTING_STR(internet_incr_file_transfer_mode); SET_SETTING_STR(local_image_transfer_mode); SET_SETTING_STR(internet_image_transfer_mode); SET_SETTING_BOOL(end_to_end_file_backup_verification); SET_SETTING_BOOL(internet_calculate_filehashes_on_client); SET_SETTING_BOOL(internet_parallel_file_hashing); SET_SETTING(image_file_format, settings_group.getImageFileFormatInt, settings_group.getImageFileFormatInt); SET_SETTING_BOOL(internet_connect_always); SET_SETTING_BOOL(verify_using_client_hashes); SET_SETTING_BOOL(internet_readd_file_entries); SET_SETTING_STR(local_incr_image_style); SET_SETTING_STR(local_full_image_style); SET_SETTING_BOOL(background_backups); SET_SETTING_STR(internet_incr_image_style); SET_SETTING_STR(internet_full_image_style); SET_SETTING_BOOL(create_linked_user_views); SET_SETTING_INT(max_running_jobs_per_client); SET_SETTING_STR(cbt_volumes); SET_SETTING_STR(cbt_crash_persistent_volumes); SET_SETTING_BOOL(ignore_disk_errors); SET_SETTING_STR(vss_select_components); SET_SETTING_BOOL(allow_component_config); SET_SETTING_BOOL(allow_component_restore); SET_SETTING_BOOL(allow_file_restore); SET_SETTING_STR(file_snapshot_groups); SET_SETTING_STR(image_snapshot_groups); SET_SETTING_INT64(internet_file_dataplan_limit); SET_SETTING_INT64(internet_image_dataplan_limit); SET_SETTING_STR(alert_script); SET_SETTING_STR(alert_params); SET_SETTING_STR(archive); SET_SETTING_STR(client_settings_tray_access_pw); SET_SETTING_BOOL(local_encrypt); SET_SETTING_BOOL(local_compress); SET_SETTING_INT(download_threads); SET_SETTING_INT(hash_threads); SET_SETTING_INT(client_hash_threads); SET_SETTING_INT(image_compress_threads); SET_SETTING_STR(ransomware_canary_paths); SET_SETTING_STR(backup_dest_url); SET_SETTING_STR(backup_dest_params); SET_SETTING_STR(backup_dest_secret_params); SET_SETTING_BOOL(pause_if_windows_unlocked); SET_SETTING_STR(backup_unlocked_window); #undef SET_SETTING return ret; } void addNextArchival(IDatabase* db, int clientid, JSON::Object& obj) { JSON::Value j_archive = obj.get("archive"); IQuery* get_next = db->Prepare("SELECT next_archival FROM settings_db.automatic_archival WHERE clientid=? AND uuid=?"); if (j_archive.getType() == JSON::str_type) { str_map params; std::string archive_str = j_archive.getString(); ParseParamStrHttp(archive_str, ¶ms); for (str_map::iterator it = params.begin(); it != params.end(); ++it) { if (next(it->first, 0, "uuid_")) { std::string idx = getafter("uuid_", it->first); get_next->Bind(clientid); get_next->Bind(it->second); db_results res = get_next->Read(); get_next->Reset(); if (!res.empty()) { int64 next_archival = watoi64(res[0]["next_archival"]); archive_str += "&next_archival_" + idx + "=" + res[0]["next_archival"]; archive_str += "&timeleft_" + idx + "=" + convert(next_archival - (_i64)Server->getTimeSeconds()); } } } obj.set("archive", archive_str); } } void getGeneralSettings(JSON::Object& obj, IDatabase *db, ServerSettings &settings) { std::unique_ptr settings_db(Server->createDBSettingsReader(db, "settings_db.settings", "SELECT value FROM settings_db.settings WHERE key=? AND clientid=0")); #define SET_SETTING(x) obj.set(#x, settings.getSettings()->x); #define SET_SETTING_DB(x, def) obj.set(#x, settings_db->getValue(#x, (def))) #define SET_SETTING_DB_BOOL(x, def) obj.set(#x, settings_db->getValue(#x, convert(def))=="true") SET_SETTING(backupfolder); SET_SETTING(no_images); SET_SETTING(no_file_backups); SET_SETTING(autoshutdown); SET_SETTING(download_client); SET_SETTING(autoupdate_clients); SET_SETTING(max_sim_backups); SET_SETTING(max_active_clients); SET_SETTING(cleanup_window); SET_SETTING(backup_database); SET_SETTING(internet_server); SET_SETTING(internet_server_port); SET_SETTING(internet_server_proxy); SET_SETTING(global_local_speed); SET_SETTING(global_soft_fs_quota); SET_SETTING(global_internet_speed); SET_SETTING(use_tmpfiles); SET_SETTING(use_tmpfiles_images); SET_SETTING(tmpdir); SET_SETTING(update_stats_cachesize); SET_SETTING(use_incremental_symlinks); SET_SETTING(show_server_updates); SET_SETTING(server_url); SET_SETTING_DB_BOOL(update_dataplan_db, true); SET_SETTING_DB(restore_authkey, std::string()); SET_SETTING_DB(internet_expect_endpoint, std::string()); SET_SETTING_DB(internet_server_bind_port, std::string()); SET_SETTING_DB(ransomware_canary_paths, std::string()); #undef SET_SETTING #undef SET_SETTING_DB } void getMailSettings(JSON::Object &obj, IDatabase *db) { std::vector slist=getMailSettingsList(); IQuery *q=db->Prepare("SELECT key, value FROM settings_db.settings WHERE clientid=0 AND key=?"); for(size_t i=0;iBind(slist[i]); db_results res=q->Read(); q->Reset(); if(!res.empty()) { obj.set((slist[i]), res[0]["value"]); } else { std::string v=""; if(slist[i]=="mail_serverport") v="25"; obj.set((slist[i]), v); } } } void getLdapSettings(JSON::Object &obj, IDatabase *db, ServerSettings &settings) { SLDAPSettings ldap_settings = settings.getLDAPSettings(); #define SET_SETTING(x) obj.set("ldap_" #x, ldap_settings.x); SET_SETTING(login_enabled); SET_SETTING(server_name); SET_SETTING(server_port); SET_SETTING(username_prefix); SET_SETTING(username_suffix); SET_SETTING(group_class_query); SET_SETTING(group_key_name); SET_SETTING(class_key_name); obj.set("ldap_group_rights_map", settings.ldapMapToString(ldap_settings.group_rights_map)); obj.set("ldap_class_rights_map", settings.ldapMapToString(ldap_settings.class_rights_map)); #undef SET_SETTING } void updateSetting(const std::string &key, const std::string &value, IQuery *q_get, IQuery *q_update, IQuery *q_insert, int* use=NULL, int64* use_last_modified=NULL) { q_get->Bind(key); db_results r_get=q_get->Read(); q_get->Reset(); bool use_mod = false; if (!r_get.empty() && use!=NULL) { int64 old_use_last_mod = watoi64(r_get[0]["use_last_modified"]); int old_use = watoi(r_get[0]["use"]); if (use_last_modified!=NULL && old_use_last_mod > *use_last_modified) { *use_last_modified = old_use_last_mod+1; } if (*use != c_use_undefined && old_use != *use) { use_mod = true; } else if (*use == c_use_undefined) { *use = old_use; } } if(r_get.empty()) { q_insert->Bind(key); q_insert->Bind(value); if (use != NULL) q_insert->Bind(*use); if (use_last_modified != NULL) q_insert->Bind(*use_last_modified); q_insert->Write(); q_insert->Reset(); } else if( r_get[0]["value"]!=value || use_mod) { q_update->Bind(value); if (use != NULL) q_update->Bind(*use); if (use_last_modified != NULL) q_update->Bind(*use_last_modified); q_update->Bind(key); q_update->Write(); q_update->Reset(); } } namespace { void updateSetting(const std::string &key, const std::string &value, IQuery *q_get, IQuery *q_update, IQuery *q_insert, int clientid) { q_get->Bind(key); q_get->Bind(clientid); db_results r_get=q_get->Read(); q_get->Reset(); if(r_get.empty()) { q_insert->Bind(key); q_insert->Bind(value); q_insert->Bind(clientid); q_insert->Write(); q_insert->Reset(); } else if( r_get[0]["value"]!=value ) { q_update->Bind(value); q_update->Bind(key); q_update->Bind(clientid); q_update->Write(); q_update->Reset(); } } std::string fixupBackupfolder(const std::string val, ServerBackupDao& backupdao, ServerSettings &server_settings, bool& changed_backupfolder) { if(val!=server_settings.getSettings()->backupfolder) { backupdao.addToOldBackupfolders(server_settings.getSettings()->backupfolder); changed_backupfolder = true; } if(val.find_last_of(os_file_sep())==val.size()-os_file_sep().size() && val.size()>1) { return val.substr(0, val.size()-os_file_sep().size()); } else { return val; } } } void saveGeneralSettings(str_map &POST, IDatabase *db, ServerBackupDao& backupdao, ServerSettings &server_settings, bool& changed_backupfolder) { IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid=0 AND key=?"); IQuery *q_update=db->Prepare("UPDATE settings_db.settings SET value=? WHERE key=? AND clientid=0"); IQuery *q_insert=db->Prepare("INSERT INTO settings_db.settings (key, value, clientid) VALUES (?,?,0)"); std::vector settings=getGlobalSettingsList(); for(size_t i=0;isecond); if(settings[i]=="backupfolder") { val = fixupBackupfolder(val, backupdao, server_settings, changed_backupfolder); #ifndef _WIN32 os_create_dir("/etc/urbackup"); writestring((val), "/etc/urbackup/backupfolder"); #endif } updateSetting(settings[i], val, q_get, q_update, q_insert); } } #ifdef _WIN32 std::string tmpdir=POST["tmpdir"]; if(!tmpdir.empty()) { os_create_dir(tmpdir+os_file_sep()+"urbackup_tmp"); Server->setTemporaryDirectory(tmpdir+os_file_sep()+"urbackup_tmp"); } #endif } void updateSettingsWithList(str_map &POST, IDatabase *db, const std::vector& settingsList) { IQuery *q_get=db->Prepare("SELECT value FROM settings_db.settings WHERE clientid=0 AND key=?"); IQuery *q_update=db->Prepare("UPDATE settings_db.settings SET value=? WHERE key=? AND clientid=0"); IQuery *q_insert=db->Prepare("INSERT INTO settings_db.settings (key, value, clientid) VALUES (?,?,0)"); for(size_t i=0;isecond), q_get, q_update, q_insert); } } } void updateClientGroup(int t_clientid, int groupid, IDatabase *db) { IQuery *q_get = db->Prepare("SELECT value FROM settings_db.settings WHERE key=? AND clientid=" + convert(t_clientid)); IQuery *q_update = db->Prepare("UPDATE settings_db.settings SET value=? WHERE key=? AND clientid=" + convert(t_clientid)); IQuery *q_insert = db->Prepare("INSERT INTO settings_db.settings (key, value, clientid) VALUES (?,?," + convert(t_clientid) + ")"); updateSetting("group_id", convert(groupid), q_get, q_update, q_insert); IQuery* q = db->Prepare("UPDATE clients SET groupid=? WHERE id=?"); q->Bind(groupid); q->Bind(t_clientid); q->Write(); q->Reset(); } void archiveParamsSetUuid(str_map& POST) { std::string archive = UnescapeSQLString(POST["archive"]); str_map params; ParseParamStrHttp(archive, ¶ms); bool mod = false; std::vector > new_uuids; for (str_map::iterator it = params.begin(); it != params.end(); ++it) { if (next(it->first, 0, "uuid_")) { if (it->second.size() % 2 != 0 || !IsHex(it->second)) { std::string uuid; uuid.resize(16); Server->secureRandomFill(&uuid[0], uuid.size()); it->second = uuid; mod = true; } } else if (next(it->first, 0, "backup_type_")) { std::string idx = getafter("backup_type_", it->first); if (params.find("uuid_" + idx) == params.end()) { std::string uuid; uuid.resize(16); Server->secureRandomFill(&uuid[0], uuid.size()); new_uuids.push_back(std::make_pair("uuid_" + idx, uuid)); mod = true; } } } if (!mod) return; for (size_t i = 0; i < new_uuids.size(); ++i) { params[new_uuids[i].first] = bytesToHex(new_uuids[i].second); } archive = ""; for (str_map::iterator it = params.begin(); it != params.end(); ++it) { if (!archive.empty()) archive += "&"; archive += it->first + "=" + EscapeParamString(it->second); } POST["archive"] = EscapeSQLString(archive); } void updateClientSettings(int t_clientid, str_map &POST, IDatabase *db) { archiveParamsSetUuid(POST); IQuery *q_get=db->Prepare("SELECT value, use, use_last_modified FROM settings_db.settings WHERE key=? AND clientid="+convert(t_clientid)); IQuery *q_update=db->Prepare("UPDATE settings_db.settings SET value=?, use=?, use_last_modified=? WHERE key=? AND clientid="+convert(t_clientid)); IQuery *q_insert=db->Prepare("INSERT INTO settings_db.settings (key, value, clientid, use, use_last_modified) VALUES (?,?,"+convert(t_clientid)+", ?, ?)"); int64 ctime = Server->getTimeSeconds(); std::vector sset_client_merge = getClientMergableSettingsList(); std::sort(sset_client_merge.begin(), sset_client_merge.end()); std::vector sset_client_use = getClientConfigurableSettingsList(); std::sort(sset_client_use.begin(), sset_client_use.end()); std::vector sset=getSettingsList(); sset.push_back("backup_dest_secret_params"); for(size_t i=0;isecond); if ( use != c_use_value && use!=c_use_group && use != (c_use_value|c_use_group) && !std::binary_search(sset_client_use.begin(), sset_client_use.end(), sset[i])) { use = c_use_value; } if ( (use!=c_use_group && use!=c_use_value && use!=c_use_value_client) && !std::binary_search(sset_client_merge.begin(), sset_client_merge.end(), sset[i])) { use = c_use_value; } int64 use_last_modified = ctime; updateSetting(sset[i], UnescapeSQLString(it->second), q_get, q_update, q_insert, &use, &use_last_modified); q_get->Bind(sset[i]); db_results res = q_get->Read(); q_get->Reset(); } } } void updateArchiveSettings(int clientid, IDatabase *db) { IQuery* q = db->Prepare("INSERT INTO settings_db.settings(key, value, clientid) VALUES ('archive_update', '1', ?)"); if (clientid == 0) { db_results res_ids = db->Read("SELECT id FROM clients"); for (size_t i = 0; i < res_ids.size(); ++i) { q->Bind(res_ids[i]["id"]); q->Write(); q->Reset(); } } else { q->Bind(clientid); q->Write(); } } void updateOnlineClientSettings(IDatabase *db, int clientid) { IQuery *q=db->Prepare("SELECT name FROM clients WHERE id=?"); q->Bind(clientid); db_results res = q->Read(); q->Reset(); if(!res.empty()) { std::string clientname = res[0]["name"]; IPipe* comm_pipe = ServerStatus::getStatus(clientname).comm_pipe; if(comm_pipe!=NULL) { comm_pipe->Write("UPDATE SETTINGS"); } } } void updateAllOnlineClientSettings(IDatabase *db) { IQuery *q=db->Prepare("SELECT name FROM clients"); db_results res = q->Read(); for(size_t i=0;iWrite("UPDATE SETTINGS"); } } } } ACTION_IMPL(settings) { Helper helper(tid, &POST, &PARAMS); JSON::Object ret; SUser *session=helper.getSession(); if(session!=NULL && session->id==SESSION_ID_INVALID) return; std::string sa=POST["sa"]; int t_clientid=watoi(POST["t_clientid"]); std::string rights=helper.getRights("client_settings"); std::vector clientid; IDatabase *db=helper.getDatabase(); ServerBackupDao backupdao(db); if(rights!="all" && rights!="none" ) { std::vector s_clientid; Tokenize(rights, s_clientid, ","); for(size_t i=0;i changes; Tokenize(group_mem_changes, changes, ";"); for (size_t i = 0; i < changes.size(); ++i) { int mod_clientid = watoi(getuntil("-", changes[i])); int mod_groupid = watoi(getafter("-", changes[i])); updateClientGroup(mod_clientid, mod_groupid, db); } } } else if (t_clientid > 0 && sa == "clientsettings_save" && helper.getRights("groupmod") == RIGHT_ALL && POST.find("memberof") != POST.end()) { updateClientGroup(t_clientid, watoi(POST["memberof"]), db); } else if (sa == "groupremove" && helper.getRights("groupmod") == RIGHT_ALL) { DBScopedWriteTransaction remove_transaction(db); int groupid = watoi(POST["id"]); IQuery* q1 = db->Prepare("UPDATE clients SET groupid=0 WHERE groupid=?"); q1->Bind(groupid); q1->Write(); q1->Reset(); IQuery* q2 = db->Prepare("UPDATE settings_db.settings SET value='0' WHERE key='group_id' AND value=?"); q2->Bind(groupid); q2->Write(); q2->Reset(); IQuery* q3 = db->Prepare("DELETE FROM settings_db.si_client_groups WHERE id=?"); q3->Bind(groupid); q3->Write(); q3->Reset(); IQuery* q4 = db->Prepare("DELETE FROM settings_db.settings WHERE clientid = ?"); q4->Bind(groupid*-1); q4->Write(); q4->Reset(); IQuery* q5 = db->Prepare("DELETE FROM settings_db.automatic_archival WHERE clientid = ?"); q5->Bind(groupid*-1); q5->Write(); q5->Reset(); remove_transaction.end(); ServerSettings::updateAll(); ret.set("delete_ok", true); sa = "general"; } //navitems { JSON::Object navitems; if(helper.getRights("usermod")=="all" ) { navitems.set("users", true); } if(helper.getRights("mail_settings")=="all" && url_fak!=NULL ) { navitems.set("mail", true); } if(helper.getRights("ldap_settings")=="all" && url_fak!=NULL ) { navitems.set("ldap", true); } if(crypto_fak!=NULL) { navitems.set("internet", true); } if(helper.getRights("disable_change_pw")=="all") { navitems.set("disable_change_pw", true); } if (helper.getRights("groupmod") == "all") { navitems.set("groupmod", true); } JSON::Array clients; IQuery *q_has_overwrite = db->Prepare("SELECT 1 FROM settings_db.settings WHERE clientid=? AND key!='internet_authkey' AND key!='client_access_key' AND key!='computername' AND key!='group_id' AND key!='group_name' AND use!=0 LIMIT 1"); const std::string clients_tab = " (clients c LEFT OUTER JOIN settings_db.si_client_groups cg ON " "c.groupid = cg.id) "; if(rights=="all" ) { IQuery *q=db->Prepare("SELECT c.id AS clientid, c.name AS clientname, groupid, cg.name AS groupname FROM " + clients_tab + "ORDER BY c.groupid, c.name"); db_results res=q->Read(); q->Reset(); for(size_t i=0;iBind(lclientid); db_results res_overwrite = q_has_overwrite->Read(); q_has_overwrite->Reset(); u.set("override", !res_overwrite.empty()); clients.add(u); } } else { std::map group_res; IQuery *q=db->Prepare("SELECT c.id AS clientid, c.name AS clientname, groupid, cg.name AS groupname FROM "+ clients_tab + " WHERE c.id=?"); for(size_t i=0;iBind(clientid[i]); db_results res=q->Read(); q->Reset(); if (!res.empty()) { group_res[watoi(res[0]["groupid"])] = res[0]; } } for (std::map::iterator it = group_res.begin(); it != group_res.end(); ++it) { JSON::Object u; int lclientid = watoi(it->second["clientid"]); ServerSettings client_settings(db, lclientid); u.set("id", lclientid); u.set("name", it->second["name"]); u.set("group", it->first); u.set("groupname", it->second["groupname"]); q_has_overwrite->Bind(lclientid); db_results res_overwrite = q_has_overwrite->Read(); q_has_overwrite->Reset(); u.set("override", !res_overwrite.empty()); clients.add(u); } } navitems.set("clients", clients); { JSON::Array groups; JSON::Object u; u.set("id", 0); u.set("name", ""); groups.add(u); db_results res = db->Read("SELECT id, name FROM settings_db.si_client_groups ORDER BY name"); for (size_t i = 0; iPrepare("SELECT id FROM settings_db.si_client_groups WHERE name=?"); q_find->Bind(name_lower); db_results res = q_find->Read(); q_find->Reset(); if (res.empty()) { IQuery *q = db->Prepare("INSERT INTO settings_db.si_client_groups (name) VALUES (?)"); q->Bind(POST["name"]); q->Write(); q->Reset(); ret.set("add_ok", true); JSON::Object u; int groupid = static_cast(db->getLastInsertID()); u.set("id", groupid); u.set("name", POST["name"]); ret.set("added_group", u); sa = "clientsettings"; t_clientid = -1 * groupid; q = db->Prepare("DELETE FROM settings_db.settings WHERE clientid = ?"); q->Bind(t_clientid); q->Write(); q->Reset(); q = db->Prepare("INSERT INTO settings_db.settings (key, value, clientid) SELECT key, value, ? AS clientid FROM settings_db.settings WHERE clientid = 0"); q->Bind(t_clientid); q->Write(); q->Reset(); q = db->Prepare("DELETE FROM settings_db.automatic_archival WHERE clientid = ?"); q->Bind(t_clientid); q->Write(); q->Reset(); q = db->Prepare("INSERT INTO settings_db.automatic_archival (clientid, interval, interval_unit, length, length_unit, backup_types, archive_window, letters) " "SELECT ? AS clientid, interval, interval_unit, length, length_unit, backup_types, archive_window, letters FROM settings_db.automatic_archival WHERE clientid=0"); q->Bind(t_clientid); q->Write(); q->Reset(); ServerSettings::updateAll(); } else { ret.set("already_exists", true); } } if(sa=="clientsettings" || sa=="clientsettings_save") { bool r_ok=false; if(rights=="all") { r_ok=true; } else { for(size_t i=0;iBeginWriteTransaction(); updateClientSettings(t_clientid, POST, db); if (POST["no_ok"] != "true") { updateArchiveSettings(t_clientid, db); } db->EndTransaction(); if (POST["no_ok"] != "true") { ret.set("saved_ok", true); } else { ret.set("saved_part", true); } if (t_clientid > 0) { ServerSettings::updateClient(t_clientid); } else { ServerSettings::updateAll(); } updateOnlineClientSettings(db, t_clientid); } ServerSettings settings(db, t_clientid); JSON::Object obj=getJSONClientSettings(db, t_clientid); addNextArchival(db, t_clientid, obj); obj.set("clientid", t_clientid); obj.set("alert_scripts", getAlertScripts(db)); if (helper.getRights(RIGHT_ALERT_SCRIPTS) == RIGHT_ALL) { obj.set("can_edit_scripts", true); } if (t_clientid <= 0) { obj.set("groupid", t_clientid*-1); obj.set("groupname", backupdao.getGroupName(t_clientid*-1).value); obj.set("overwrite", true); } else { ServerBackupDao::SClientName client_name = backupdao.getVirtualMainClientname(t_clientid); obj.set("main_client", client_name.virtualmain.empty()); obj.set("clientname", client_name.name); obj.set("memberof", backupdao.getClientGroup(t_clientid).value); } ret.set("cowraw_available", BackupServer::isImageSnapshotsEnabled() || BackupServer::canReflink() ); ret.set("settings", obj); sa="clientsettings"; ret.set("sa", sa); } } else if(sa=="useradd" && helper.getRights("usermod")=="all") { std::string name=strlower(POST["name"]); std::string salt=POST["salt"]; std::string pwmd5=(POST["pwmd5"]); IQuery *q_find=db->Prepare("SELECT id FROM settings_db.si_users WHERE name=?"); q_find->Bind(name); db_results res=q_find->Read(); q_find->Reset(); if(res.empty()) { size_t pbkdf2_rounds=0; if(crypto_fak!=NULL) { pbkdf2_rounds=10000; pwmd5 = strlower(crypto_fak->generatePasswordHash(hexToBytes(pwmd5), (salt), pbkdf2_rounds)); } IQuery *q=db->Prepare("INSERT INTO settings_db.si_users (name, password_md5, salt, pbkdf2_rounds) VALUES (?,?,?,?)"); q->Bind(name); q->Bind(pwmd5); q->Bind(salt); q->Bind(pbkdf2_rounds); q->Write(); q->Reset(); ret.set("add_ok", true); int t_userid=(int)db->getLastInsertID(); std::string s_rights = POST["rights"]; updateRights(t_userid, s_rights, db); } else { ret.set("alread_exists", true); } sa="listusers"; } if(sa=="changepw" && ( helper.getRights("usermod")=="all" || (POST["userid"]=="own" && helper.getRights("disable_change_pw")!="all") ) ) { bool ok=true; if(POST["userid"]=="own") { if(!helper.checkPassword(session->mStr["username"], POST["old_pw"], NULL, false) ) { ok=false; } } if(ok) { std::string salt=POST["salt"]; std::string pwmd5=(POST["pwmd5"]); int t_userid; if(POST["userid"]=="own") { t_userid=session->id; } else { t_userid=watoi(POST["userid"]); } size_t pbkdf2_rounds=0; if(crypto_fak!=NULL) { pbkdf2_rounds=10000; pwmd5 = strlower(crypto_fak->generatePasswordHash(hexToBytes(pwmd5), (salt), pbkdf2_rounds)); } IQuery *q=db->Prepare("UPDATE settings_db.si_users SET salt=?, password_md5=?, pbkdf2_rounds=? WHERE id=?"); q->Bind(salt); q->Bind(pwmd5); q->Bind(pbkdf2_rounds); q->Bind(t_userid); q->Write(); q->Reset(); ret.set("change_ok", true); if(POST["userid"]!="own") { sa="listusers"; } } else { ret.set("old_pw_wrong", true); } } if(sa=="updaterights" && helper.getRights("usermod")=="all") { int t_userid=watoi(POST["userid"]); std::string s_rights=(POST["rights"]); updateRights(t_userid, s_rights, db); sa="listusers"; ret.set("update_right", true); } if(sa=="removeuser" && helper.getRights("usermod")=="all") { int userid=watoi(POST["userid"]); IQuery *q=db->Prepare("DELETE FROM settings_db.si_users WHERE id=?"); q->Bind(userid); q->Write(); q->Reset(); ret.set("removeuser", true); sa="listusers"; } if(sa=="listusers" && helper.getRights("usermod")=="all" ) { IQuery *q=db->Prepare("SELECT id,name FROM settings_db.si_users"); db_results res=q->Read(); q->Reset(); q=db->Prepare("SELECT t_right, t_domain FROM settings_db.si_permissions WHERE clientid=?"); JSON::Array users; for(size_t i=0;iBind(res[i]["id"]); db_results res_r=q->Read(); q->Reset(); JSON::Array rights; for(size_t j=0;jBeginWriteTransaction(); updateClientSettings(0, POST, db); updateArchiveSettings(0, db); bool changed_backupfolder = false; saveGeneralSettings(POST, db, backupdao, serv_settings, changed_backupfolder); db->EndTransaction(); ServerSettings::updateAll(); updateAllOnlineClientSettings(db); if (changed_backupfolder) { BackupServer::testFilesystemThread(); } ret.set("saved_ok", true); sa="general"; } if((sa=="navitems" || sa=="general") ) { sa="general"; ret.set("sa", sa); JSON::Object obj=getJSONClientSettings(db, 0); obj.set("alert_scripts", getAlertScripts(db)); if (helper.getRights(RIGHT_ALERT_SCRIPTS) == RIGHT_ALL) { obj.set("can_edit_scripts", true); } ServerSettings serv_settings(db, 0); getGeneralSettings(obj, db, serv_settings); #ifdef _WIN32 obj.set("ONLY_WIN32_BEGIN",""); obj.set("ONLY_WIN32_END",""); #else obj.set("ONLY_WIN32_BEGIN",""); #endif //_WIN32 ret.set("cowraw_available", BackupServer::isImageSnapshotsEnabled() || BackupServer::canReflink() ); ret.set("settings", obj); } } if(sa=="mail_save" && helper.getRights("mail_settings")=="all") { updateSettingsWithList(POST, db, getMailSettingsList()); ret.set("saved_ok", true); std::string testmailaddr=POST["testmailaddr"]; if(!testmailaddr.empty()) { MailServer mail_server=ClientMain::getMailServerSettings(); if(url_fak!=NULL) { std::vector to; to.push_back((testmailaddr)); std::string errmsg; bool b=url_fak->sendMail(mail_server, to, "UrBackup mail test", "This is a test mail from UrBackup", &errmsg); if(!b) { ret.set("mail_test", errmsg); } else { ret.set("mail_test", "ok"); } } else { ret.set("mail_test", "Mail module not loaded"); } } sa="mail"; } if( sa=="mail" && helper.getRights("mail_settings")=="all") { JSON::Object obj; getMailSettings(obj, db); ret.set("settings", obj); ret.set("sa", sa); } if(sa=="ldap_save" && helper.getRights("ldap_settings")=="all") { updateSettingsWithList(POST, db, getLdapSettingsList()); ret.set("saved_ok", true); sa="ldap"; std::string testusername = POST["testusername"]; if(!testusername.empty() && helper.ldapEnabled()) { std::string testpassword = POST["testpassword"]; std::string errmsg; std::string rights; if(!helper.ldapLogin(testusername, testpassword, &errmsg, &rights, true)) { if(errmsg.empty()) { errmsg="unknown"; } ret.set("ldap_test", errmsg); } else { ret.set("ldap_test", "ok"); ret.set("ldap_rights", rights); } } else if(!testusername.empty() && !helper.ldapEnabled()) { ret.set("ldap_test", "Login via LDAP not enabled"); } } if( sa=="ldap" && helper.getRights("ldap_settings")=="all") { JSON::Object obj; ServerSettings serv_settings(db); getLdapSettings(obj, db, serv_settings); ret.set("settings", obj); ret.set("sa", sa); } } else { ret.set("error", 1); } #ifdef _WIN32 ret.set("ONLY_WIN32_BEGIN", ""); ret.set("ONLY_WIN32_END", ""); #else ret.set("ONLY_WIN32_BEGIN", ""); #endif helper.Write(ret.stringify(false)); } #endif //CLIENT_ONLY