#include #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////// // Dongle stuff /////////////////////////////////////////////////////////// //#define USERADR 26952 //#define AGAADR 26953 //#define REFKEY (unsigned char*)"CAMPOKEY" //#define VERKEY (unsigned char*)"ìpÙˆ¬cê<" /////////////////////////////////////////////////////////// // Current dongle /////////////////////////////////////////////////////////// static TDongle* _dongle = NULL; TDongle& dongle() { if (_dongle == NULL) _dongle = new TDongle; return *_dongle; } bool destroy_dongle() { bool ok = _dongle != NULL; if (ok) { delete _dongle; _dongle = NULL; } return ok; } /////////////////////////////////////////////////////////// // Bit helper functions /////////////////////////////////////////////////////////// inline bool test_bit(word w, int b) { bool on = (w & (1 << b)) != 0; return on; } inline void set_bit(word& w, int b, bool on = true) { if (on) w |= 1 << b; else w &= ~(1 << b); } inline void reset_bit(word& w, byte b) { w &= ~(1 << b); } /////////////////////////////////////////////////////////// // TDongle /////////////////////////////////////////////////////////// TDongle::TDongle() : _hardware(_dongle_unknown), _type(_no_dongle), _serno(0xFFFF), _max_users(1), _year_assist(2015), _dirty(false), _OEM(-1) { memset(_eprom, 0, sizeof(_eprom)); } TDongle::~TDongle() { if (_serno != 0xFFFF) logout(); } const TString& TDongle::administrator(TString* pwd) const { if (_admin.blank()) oem(); if (pwd) *pwd = _admpwd; return _admin; } // Data punta ad un array di 4 words // Deve essere cosi' per problemi del C, // non trasformare in array: pena di morte! void TDongle::garble(word* data) const { xvt_dongle_sa_crypt(data); // Reversible XOR encryption } bool TDongle::already_programmed() const { return true; } void TDongle::set_developer_permissions() { if (_serno == 0 && is_power_station()) { _module.set(255); // Last module on key _module.set(); // Activate all modules } else { _module.reset(-1); _module.set(0, true); } _shown.reset(); _max_users = 1; _last_update = TDate(TODAY); _year_assist = 3000; } bool TDongle::ssa_login(const char* mod) { if (mod && *mod) return xvt_dongle_sa_login(mod) == 0; _max_users = 1; _last_update = TDate(TODAY); _year_assist = _last_update.year(); _module.reset(); // Disattiva tutti i moduli ... _module.set(long(BAAUT)); // ... tranne la base const int err = xvt_dongle_sa_login(NULL); _serno = (err >= 0) ? err : 0xFFFF; if (_serno != 0xFFFF) { _hardware =_dongle_ssa; _type = _serno ? _user_dongle : _developer_dongle; if (_serno) { Tdninst dn; if (dn.find_serno()) _year_assist = dn.assist_year(); else _year_assist = 2091; // Vecchia versione for (word m = BAAUT+1; m < ENDAUT; m++) { const TString& name = module_code2name(m); if (xvt_dongle_sa_test(name) == 0) _module.set(long(m)); } } else set_developer_permissions(); } // else log_message("ssa_login() failed with code %d", err); return _serno != 0xFFFF; } bool TDongle::network_login(bool test_all_keys) { const char* appname = main_app().name(); if (network() && ok()) rpc_UserLogout(appname); TString server = "127.0.0.1"; if (!(xvt_sys_dongle_server_running() & 0x1)) server = ini_get_string(CONFIG_INSTALL, "Server", "Dongle"); // const char* guest = "******"; // const TString16 appname = main_app().name(); // const char* utente = (!main_app().is_running() && appname == "ba0100") ? guest : (const char *) user(); const char* utente = user(); bool ok = rpc_UserLogin(server, utente, "******", appname); if (ok) { _hardware = _dongle_network; _type = _user_dongle; _max_users = 1; _last_update = TDate(TODAY); // Let's try to spare some network band! ok = rpc_DongleInfo(_serno, _year_assist, _module); if (!ok) { _serno = rpc_DongleNumber(); _year_assist = rpc_DongleYear(); ok = rpc_DongleModules(_module); if (ok && main_app().name() == "ba0100") warning_box(TR("ATTENZIONE! Il server di protezione non è aggiornato:\n" "Controllare la corretta installazione del servizio")); } } else log_message("rpc_UserLogin(%s, %s) failed", (const char*)server, (const char*)utente); return ok; } bool TDongle::login(bool test_all_keys) { bool ok = true; if (_type != _no_dongle) // Already logged in logout(); TDongleHardware hw = _hardware; const int srv = xvt_sys_dongle_server_running(); if (srv != 0) { if (srv & 2) hw = _dongle_ssanet; else hw = _dongle_network; } else { const TString& port = ini_get_string(CONFIG_SSA, "", "SSA-PORT"); if (port.full()) hw = _dongle_ssanet; else { const TString& dongle = ini_get_string(CONFIG_INSTALL, "Server", "Dongle"); hw = dongle.full() ? _dongle_network : _dongle_ssa; } } if (hw == _dongle_network) ok = network_login(test_all_keys); else ok = ssa_login(NULL); if (ok) { _hardware = hw; ini_set_int(CONFIG_INSTALL, "Main", "Donglehw", (int)_hardware); } else { // DEMO _hardware = _dongle_unknown; _type = _no_dongle; _serno = 0xFFFF; //numero di serie più alto possibile (65535 in esadecimale: non sarà mai raggiunto da chiavi clienti...magari!) _max_users = 1; _last_update = TDate(TODAY); _year_assist = 3000; // anno di assistenza a 3000 per non avere problemi con le versioni nei vari anni _module.set(ENDAUT); // Last module on key _module.set(); // Activate all modules _shown.reset(); } if (!ok && local()) { TString_array ssa; const int n = list_files("*.ssa", ssa); switch (n) { case 0: error_box(FR("Non esistono file SSA validi")); break; case 1: error_box(FR("File SSA non valido:\n%s"), (const char*)ssa.row(0)); break; default: error_box(FR("Sono presenti troppi file SSA:\n%s,%s,..."), (const char*)ssa.row(0), (const char*)ssa.row(1)); break; } } return ok; } bool TDongle::login(const char* module) { const word code = module_name2code(module); bool ok = active(code); if (ok && _hardware == _dongle_ssa) ok = ssa_login(module); return ok; } bool TDongle::logout() { switch (_hardware) { case _dongle_network: rpc_UserLogout(main_app().name()); break; case _dongle_ssanet: case _dongle_ssa: xvt_dongle_sa_logout(NULL); break; default: break; } _type = _no_dongle; _serno = 0xFFFF; return true; } int TDongle::oem() const { if (_OEM < 0) { TString& firm = (TString&) _reseller; TString& campo = (TString&) _product; TString& breve = (TString&) _shortname; TString& admin = (TString&)_admin; TString& admpwd = (TString&)_admpwd; int& oem = (int&)_OEM; //nuovo metodo di rilevamento producer (dalla 10.0 in avanti); il producer sta nel file oem.ini sotto la cartella //setup, sia nel CD che soprattutto nel programma installato TConfig ini(CONFIG_OEM, "MAIN"); oem = ini.get_int("OEM", NULL, -1, -1); if (oem >= 0) { TString8 para; para << "OEM_" << oem; ini.set_paragraph(para); campo = decode(ini.get("Product")); firm = decode(ini.get("Reseller")); breve = decode(ini.get("Name")); admin = decode(ini.get("Administrator")); admpwd = decode(ini.get("Password")); } if (firm.blank()) //vecchio metodo di rilevamento del producer: sta in install.ini { firm = decode(ini_get_string(CONFIG_GENERAL, "Main", "Producer")); campo = breve = " "; } //nuovo metodo: cerca produttore (Name) e prodotto (Product) if (firm.blank()) { ignore_xvt_errors(true); char* p = firm.get_buffer(80); xvt_res_get_str(STR_FIRMNAME, p, firm.size()); ignore_xvt_errors(false); } if (admin.blank()) { admin = decode(ini_get_string(CONFIG_GENERAL, "Main", "Administrator")); if (admin.blank()) { admin = "ADMIN"; admpwd = "ad.min"; } } if (admpwd.blank()) { admpwd = decode(ini_get_string(CONFIG_GENERAL, "Main", "Password")); if (admpwd.blank()) { admpwd = admin; admpwd.lower(); admpwd.insert(".", 2); } } if (campo.blank()) campo = "Campo Enterprise"; if (firm.blank()) firm = "Sirio Informatica e Sistemi s.p.a."; if (breve.blank()) breve = "Campo"; if (oem < 0) oem = 1; } return _OEM; } // Ritorna il nome della ditta che vende il programma attuale const TString& TDongle::reseller() const { if (_reseller.empty()) oem(); return _reseller; } const TString& TDongle::product() const { if (_product.empty()) oem(); return _product; } const TString& TDongle::short_name() const { if (_shortname.empty()) oem(); return _shortname; } const TString& TDongle::server_name() const { if (network() && !xvt_sys_dongle_server_running()) { if (hardware() == _dongle_ssanet) return ini_get_string(CONFIG_SSA, NULL, "Port"); return ini_get_string(CONFIG_INSTALL, "Server", "Dongle"); } TString& tmp = get_tmp_string(50); xvt_sys_get_host_name(tmp.get_buffer(), tmp.size()); return tmp; } bool TDongle::active(word module) const { const bool yes = (module < ENDAUT) && _module[module] && shown(module); return yes; } bool TDongle::activate(word module, bool on) { bool ok = module < ENDAUT; if (ok) { _module.set(module, on && shown(module)); _dirty = true; } return ok; } const TString_array& TDongle::info() const { if (_info.empty()) { TScanner scanner("campo.aut"); for (int aut = 0; ; aut++) { const TString& row = scanner.line(); if (row.blank()) break; TToken_string* tok = new TToken_string; tok->strncpy(row, 3); const TString& name = row.mid(3); if (name.full()) *tok << dictionary_translate(name); ((TString_array&)_info).add(tok); } } return _info; } word TDongle::module_name2code(const char* mod) const { int i = BAAUT; if (mod && *mod && !xvt_str_same(mod, "sy")) { if (real::is_natural(mod)) { i = atoi(mod); // Trasforma il numero 77 nel codice M77AUT if (i == 77) i = M77AUT; } else { const TString_array& modinfo = info(); for (i = modinfo.last(); i >= 0; i--) { const TString& autstr = modinfo.row(i); if (autstr.starts_with(mod, true)) break; } } } return word(i); } const TString& TDongle::module_code2name(word mod) const { const TString_array& modinfo = info(); if (mod < modinfo.items()) return modinfo.row(mod).left(2); return EMPTY_STRING; } const TString& TDongle::module_code2desc(word mod) const { const TString_array& modinfo = info(); return mod < modinfo.items() ? modinfo.row(mod).mid(3) : EMPTY_STRING; } const TString& TDongle::module_name2desc(const char* mod) const { const word cod = module_name2code(mod); if (cod == 0) { if (xvt_str_same(mod, "sy")) return get_tmp_string() = TR("Sistema"); } return module_code2desc(cod); } bool TDongle::shown(word code) const { bool yes = code < ENDAUT; if (yes) { yes = _shown[code]; if (!yes) // Puo' voler dire "nascosto" ma anche "non ho mai controllato" { const TString4 mod = module_code2name(code); yes = mod.not_empty(); if (yes && code > BAAUT && code < ENDAUT) { TAuto_token_string ee = ini_get_string(CONFIG_GENERAL, mod, "OEM"); // Modern OEM handling if (ee.full()) yes = ee.get_pos(oem()) >= 0; } if (yes) ((TBit_array&)_shown).set(code); // Setto il flag di visibilta' per la prossima volta } } return yes; } bool TDongle::demo() const { return hardware() == _dongle_unknown && type() == _no_dongle; } /////////////////////////////////////////////////////////////////////////////// // TEnigma_machine /////////////////////////////////////////////////////////////////////////////// #define DNINST_PATH "setup/dninst.zip" class TEnigma_machine : public TObject { TScanner* _scan; int _year_assist; protected: void init_key(char key[8]) const; bool decode_string(const TString& datain, TString& dataout) const; bool encode_string(const TString& linein, TString& lineout) const; bool init(); void uninit(); public: virtual bool ok() const { return _scan != NULL && !_scan->eof(); } bool line(TString& data); bool find_serno(long serno); int year_assist() const { return _year_assist; } bool encode(const TString& txtfile); // dninst.txt -> dninst.zip TEnigma_machine(); ~TEnigma_machine(); }; void TEnigma_machine::init_key(char key[8]) const { for (int i = 0; i < 8; i++) key[i] = 'A' + ::rand() % 26; } bool TEnigma_machine::decode_string(const TString& datain, TString& dataout) const { dataout.cut(0); if (datain.not_empty()) { char* tmp = dataout.get_buffer(datain.len()); char key[8]; init_key(key); int i; for (i = 0; datain[i]; i++) tmp[i] = datain[i] - (i < 8 ? key[i] : tmp[i - 8]); tmp[i] = '\0'; } return dataout.full(); } bool TEnigma_machine::encode_string(const TString& linein, TString& lineout) const { lineout.cut(0); if (linein.full() && !linein.starts_with("//")) { char key[8]; init_key(key); char* buf = lineout.get_buffer(linein.len()); size_t i = 0; for (i = 0; linein[i]; i++) buf[i] = linein[i] + (i < 8 ? key[i] : linein[i - 8]); buf[i] = '\0'; } return lineout.full(); } bool TEnigma_machine::line(TString& data) { return _scan != NULL ? decode_string(_scan->line(), data) : false; } bool TEnigma_machine::find_serno(long serno) { if (serno == 0) return true; TToken_string row(80, ';'); if (_year_assist > 2100) { TString8 para; para << '[' << serno << ']'; while (line(row)) { if (row == para) return true; } } else { while (line(row)) { if (row.get_long(0) == serno) return true; } } return false; } bool TEnigma_machine::encode(const TString& txtfile) { uninit(); ofstream o(DNINST_PATH); TString lineout; TScanner s(txtfile); const TString& year = s.line(); ::srand(883); encode_string(year, lineout); o << lineout << endl; ::srand(atoi(year)); while (s.good()) { const TString& linein = s.line(); if (linein.empty()) break; encode_string(linein, lineout); o << lineout << endl; } init(); return o.good(); } void TEnigma_machine::uninit() { _year_assist = 0; if (_scan != NULL) { delete _scan; _scan = NULL; } } bool TEnigma_machine::init() { uninit(); if (fexist(DNINST_PATH)) { _scan = new TScanner(DNINST_PATH); ::srand(883); TString4 l1; line(l1); _year_assist = atoi(l1); ::srand(_year_assist); } return _scan != NULL; } TEnigma_machine::TEnigma_machine() : _scan(NULL), _year_assist(0) { init(); } TEnigma_machine::~TEnigma_machine() { uninit(); } int Tdninst::assistance_year2solar(int ay) const { return (ay/1000)*1000 + (ay%1000)/10; } int Tdninst::parse_date(const TString& line, TString& key, TDate& datascad) const { const int equal = line.find('='); if (equal > 0 && equal <= 16) { key = line.left(equal); key.trim(); TString16 strdate = line.mid(equal+1, 16); strdate.trim(); if (strdate.empty()) { datascad = TODAY; // Mettiamo una data valida comunque return key.full() ? 1 : 0; } int d, m, y; if (sscanf(strdate, "%2d-%2d-%4d", &d, &m, &y) == 3) { datascad = TDate(d, m, y); return datascad.ok() ? 2 : 0; } } return 0; } bool Tdninst::compare_cmdline(const TString& cmdline, const TString& pattern) const { if (cmdline == pattern) return true; bool is_pattern = false; if (pattern.len() > 2) { for (int i = 2; pattern[i]; i++) { if (pattern[i]=='*' || pattern[i] == '?') is_pattern = true; } } if (is_pattern) return cmdline.match(pattern, true); return false; } int Tdninst::test_cmdline(const TString& cmdline, bool key_must_exist, TString& msg) const { msg.cut(0); const TDongle& don = dongle(); const long serno = don.number(); if (serno == 0) { if (is_power_station()) return 0; // Solo chiavi per uso interno Sirio msg = TR("Chiave di sviluppo non autorizzata"); return 1; } const TString4 strmod = cmdline.left(2); if (!key_must_exist) // Le personalizzazioni non hanno un modulo vero e proprio { const int space_pos = cmdline.find(' '); if (space_pos < 0 || space_pos == 3) { const word codmod = don.module_name2code(strmod); if (codmod == BAAUT) return 0; } } TEnigma_machine em; const int dninst_ass = em.year_assist(); const TDate oggi(TODAY); bool bFound = false; if (dninst_ass > 2100) { if (em.find_serno(serno)) { TString80 dninst_line; TString16 key; TDate datascad; while (em.line(dninst_line)) { if (dninst_line.empty() || dninst_line.starts_with("[")) break; // Fine file o paragrafo if (parse_date(dninst_line, key, datascad)) { const bool scaduto = datascad < oggi; if (key == "*") { if (scaduto) { msg.format(FR("Chiave %ld scaduta il %s"), serno, datascad.string()); return 7; } } else if (compare_cmdline(cmdline, key)) { bFound = true; if (scaduto) { msg << TR("Applicazione scaduta il ") << datascad; return 8; } } else if (key == strmod) { if (scaduto) { msg << TR("Modulo scaduto il ") << datascad; return 9; } } } } } } else { TToken_string dninst_line(80, ';'); while (em.line(dninst_line)) { bFound = dninst_line.get_long(0) == serno; if (bFound) { if (dninst_line.get_pos(strmod) > 0) { msg << TR("Modulo non attivo in dninst.zip : ") << strmod; return 5; } break; } } } if (!bFound && key_must_exist) { msg << TR("Impossibile trovare ") << cmdline << TR(" tra i programmi abilitati"); return 6; } return 0; } bool Tdninst::can_I_run(const bool is_personal_program, const bool verbose) const { const TApplication& app = main_app(); TFilename cmdline = app.argv(0); cmdline = cmdline.name_only(); if (cmdline.starts_with("ba", true) || cmdline.ends_with("cnv", true)) return true; const char* option = app.argc() > 1 ? app.argv(1) : ""; if (*option == '-' && isdigit(*(option+1))) cmdline << ' ' << option; cmdline.lower(); TString msg; bool ok = test_cmdline(cmdline, is_personal_program, msg) == 0; if (!ok && verbose) error_box(msg); return ok; } bool Tdninst::find_serno() const { const word serno = dongle().number(); if (serno == 0) return true; const TDate oggi(TODAY); bool good = false; TEnigma_machine em; if (em.ok()) { if (em.year_assist() > 2100) { good = em.find_serno(serno); } else { TToken_string l(80, ';'); while (em.line(l)) { if (l.get_long(0) == serno) { good = true; break; } } } } return good; } bool Tdninst::find_killed(TToken_string& kill_list) const { kill_list.cut(0); const int serno = dongle().number(); if (serno == 0) return true; bool good = false; TEnigma_machine em; if (em.ok()) { if (em.year_assist() > 2100) { TToken_string l(80, '='); good = em.find_serno(serno); if (good) { const TDate oggi(TODAY); TString16 str; TDate ds; while (em.line(l)) { if (l.empty() || l[0] == '[') break; if (parse_date(l, str, ds) && ds < oggi) kill_list.add(str); } } } else { TToken_string l(80, ';'); while (em.line(l)) { if (l.get_long(0) == serno) { const int semicolon = l.find(l.separator()); if (semicolon > 0) { kill_list = l.mid(semicolon+1); kill_list.lower(); kill_list.replace(l.separator(), kill_list.separator()); } good = true; break; } } } } return good; } bool Tdninst::find_expiring(int days, TString& module, TDate& expires) const { const TDate oggi(TODAY); expires = oggi; expires += days; module.cut(0); const word serno = dongle().number(); if (serno == 0) return false; TEnigma_machine em; if (em.ok() && em.year_assist() > 2100 && em.find_serno(serno)) { TToken_string l(80, '='); TString16 str; TDate ds; while (em.line(l)) { if (l.empty() || l[0] == '[') break; if (parse_date(l, str, ds) && ds >= oggi && ds <= expires) { module = str; expires = ds; } } } return module.full(); } int Tdninst::check_customer() const { int error = 2; // Not found const word serno = dongle().number(); if (serno == 0) error = is_power_station() ? 0 : 2; else { TEnigma_machine em; if (em.ok() && em.year_assist() > 2100 && em.find_serno(serno)) { error = 0; TToken_string l(80, '='); while (em.line(l) && error == 0) { if (l.empty() || l[0] == '[') break; if (l[0]=='*' || l.starts_with("MustCall")) { const TDate oggi(TODAY); TString16 str; TDate ds; if (parse_date(l, str, ds) && oggi >= ds) error = (l[0] == '*') ? 2 : 1; } } } } return error; } bool Tdninst::decode(const TString& f) const { ofstream o(f); TEnigma_machine em; o << em.year_assist() << endl; size_t nlines = 0; TString256 l; while (em.line(l)) { o << l << endl; nlines++; } return nlines > 0; } bool Tdninst::encode(const TString& f) const { TEnigma_machine em; return em.encode(f); } Tdninst::Tdninst() : _year_assist(0) { TEnigma_machine s; _year_assist = s.year_assist(); // 2101, 2121, 2151 }