#define __SMARTCARD_CPP #ifdef WIN32 #include #endif #include #include #include #include #include #include #ifdef WIN32 #include typedef unsigned long (ASEMEM_API FASEListReaders)(char * readersList, unsigned long * length); typedef unsigned long (ASEMEM_API FASEWaitForCardEvent)(char * reader, unsigned char inOut, unsigned long timeOut); typedef unsigned long (ASEMEM_API FASEMemConnect)(ASEMEM_HANDLE * hCard, char * reader, unsigned long connectMode, unsigned long * cardType); typedef unsigned long (ASEMEM_API FASEMemDisconnect)(ASEMEM_HANDLE hCard, char mode); typedef unsigned long (ASEMEM_API FASEMemWrite)(ASEMEM_HANDLE hCard, unsigned long address, unsigned char * writeBuffer, unsigned long lenWrite, char protect); typedef unsigned long (ASEMEM_API FASEMemRead)(ASEMEM_HANDLE hCard, unsigned long address, unsigned char * readBuffer, unsigned char * protReadBuffer, unsigned long lenRead); typedef unsigned long (ASEMEM_API FASEMemVerifyPassword)(ASEMEM_HANDLE hCard, unsigned char * password, unsigned long length, int * attempts); typedef unsigned long (ASEMEM_API FASEMemChangePassword)(ASEMEM_HANDLE hCard,unsigned char * oldPassword, unsigned char * newPassword, unsigned long length, int * attempts); typedef FASEListReaders * LPASEListReaders; typedef FASEWaitForCardEvent * LPASEWaitForCardEvent; typedef FASEMemConnect * LPASEMemConnect; typedef FASEMemDisconnect * LPASEMemDisconnect; typedef FASEMemWrite * LPASEMemWrite; typedef FASEMemRead * LPASEMemRead; typedef FASEMemVerifyPassword * LPASEMemVerifyPassword; typedef FASEMemChangePassword * LPASEMemChangePassword; HINSTANCE _hlibASE = NULL; LPASEListReaders lpfnASEListReaders = NULL; LPASEWaitForCardEvent lpfnASEWaitForCardEvent = NULL; LPASEMemConnect lpfnASEMemConnect = NULL; LPASEMemDisconnect lpfnASEMemDisconnect = NULL; LPASEMemWrite lpfnASEMemWrite = NULL; LPASEMemRead lpfnASEMemRead = NULL; LPASEMemVerifyPassword lpfnASEMemVerifyPassword = NULL; LPASEMemChangePassword lpfnASEMemChangePassword = NULL; #endif bool TSmart_card::ASEloadlibrary() { #ifdef WIN32 if (_hlibASE) // Check in already loaded return TRUE; UINT fuError = SetErrorMode(SEM_NOOPENFILEERRORBOX); _hlibASE = LoadLibrary("ASEMemory.dll"); SetErrorMode(fuError); if (_hlibASE < (HINSTANCE)HINSTANCE_ERROR) { DWORD err = *((DWORD*)_hlibASE) & 0xFFFF; _hlibASE = NULL; return error_box("Errore di caricamento di ASEMemory.dll: %lu", err); } if (!(lpfnASEListReaders = (LPASEListReaders)GetProcAddress (_hlibASE, "ASEListReaders"))) return FALSE; if (!(lpfnASEWaitForCardEvent = (LPASEWaitForCardEvent)GetProcAddress (_hlibASE, "ASEWaitForCardEvent"))) return FALSE; if (!(lpfnASEMemConnect = (LPASEMemConnect)GetProcAddress (_hlibASE, "ASEMemConnect"))) return FALSE; if (!(lpfnASEMemDisconnect = (LPASEMemDisconnect)GetProcAddress (_hlibASE, "ASEMemDisconnect"))) return FALSE; if (!(lpfnASEMemWrite = (LPASEMemWrite)GetProcAddress (_hlibASE, "ASEMemWrite"))) return FALSE; if (!(lpfnASEMemRead = (LPASEMemRead)GetProcAddress (_hlibASE, "ASEMemRead"))) return FALSE; if (!(lpfnASEMemVerifyPassword = (LPASEMemVerifyPassword)GetProcAddress (_hlibASE, "ASEMemVerifyPassword"))) return FALSE; if (!(lpfnASEMemChangePassword = (LPASEMemChangePassword)GetProcAddress (_hlibASE, "ASEMemChangePassword"))) return FALSE; #endif return TRUE; } TSmart_card::TSmart_card() { init(); } unsigned long TSmart_card::ASEsearch() { _ASE_reader_name.cut(0); unsigned long len; unsigned long status = lpfnASEListReaders(NULL, &len); if (status != ASEMEM_S_SUCCESS) return status; char * readerList = new(char[len]); if (readerList == NULL) return ASEMEM_E_NO_MEMORY; status = lpfnASEListReaders(readerList, &len); if (status == ASEMEM_S_SUCCESS) { _ASE_reader_name = readerList; if (_ASE_reader_name.empty()) status = ASEMEM_E_NO_READERS_AVAILABLE; } _has_pwd = false; delete readerList; return status; } unsigned long TSmart_card::ASEread(char ** buffer) { ASEMEM_HANDLE hcard; unsigned long type; unsigned long status = lpfnASEMemConnect(&hcard, (char *)(const char *)_ASE_reader_name, ASEMEM_SHARE_SHARED, &type); unsigned char stdpassword[3] = {0xFF, 0xFF, 0xFF}; if (status != ASEMEM_S_SUCCESS) return status; _has_pwd = type == ASEMEM_CARD_TYPE_2BUS || type != ASEMEM_CARD_TYPE_3BUS; if (_has_pwd) { unsigned long passwordLength = (type == ASEMEM_CARD_TYPE_2BUS) ? ASEMEM_2BUS_PASSWORD_LENGTH : ASEMEM_3BUS_PASSWORD_LENGTH; int attempts = 0; status = lpfnASEMemVerifyPassword(hcard, stdpassword, passwordLength, &attempts); if (status == ASEMEM_E_PASSWORD_VERIFICATION_FAILED) { lpfnASEMemDisconnect(&hcard, ASEMEM_RESET_CARD); return status; } } unsigned char len; const int offset = _has_pwd ? 32 : 0; status = lpfnASEMemRead(hcard, offset, &len, NULL, 1); if (status == ASEMEM_S_SUCCESS && len == 1) { status = lpfnASEMemRead(hcard, offset+1, &len, NULL, 1); if (status == ASEMEM_S_SUCCESS) { if (*buffer == NULL) *buffer = new(char[len+1]); status = lpfnASEMemRead(hcard, offset+2, (unsigned char *) *buffer, NULL, (int) len); if (status == ASEMEM_S_SUCCESS) (*buffer)[len] = '\0'; else (*buffer)[0] = '\0'; } } else ASEwrite("0"); lpfnASEMemDisconnect(&hcard, ASEMEM_LEAVE_CARD); return status; } unsigned long TSmart_card::ASEwrite(char * buffer) const { ASEMEM_HANDLE hcard; unsigned long type; unsigned long status = lpfnASEMemConnect(&hcard, (char *)(const char *)_ASE_reader_name, ASEMEM_SHARE_SHARED, &type); if (status != ASEMEM_S_SUCCESS) return status; unsigned char len = 1; const int offset = _has_pwd ? 32 : 0; status = lpfnASEMemWrite(hcard, offset, &len, 1, ASEMEM_WRITE_MODE); if (status == ASEMEM_S_SUCCESS) { len = strlen(buffer); status = lpfnASEMemWrite(hcard, offset+1, &len, 1, ASEMEM_WRITE_MODE); if (status == ASEMEM_S_SUCCESS) status = lpfnASEMemWrite(hcard, offset+2, (unsigned char *)buffer, (int) len, ASEMEM_WRITE_MODE); } lpfnASEMemDisconnect(&hcard, ASEMEM_LEAVE_CARD); return status; } static smartcard_error ASEmap_error(unsigned long error) { switch (error) { case ASEMEM_S_SUCCESS: return no_smarterror; case ASEMEM_E_FUNCTION_NOT_SUPPORTED: return wrong_function; case ASEMEM_E_REMOVED_CARD: return card_removed; case ASEMEM_E_UNPOWERED_CARD: return no_power; case ASEMEM_E_UNSUPPORTED_CARD: return wrong_card; case ASEMEM_E_PASSWORD_VERIFICATION_FAILED: return wrong_password; case ASEMEM_E_PASSWORD_BLOCKED: return password_blocked; case ASEMEM_E_INVALID_HANDLE: return invelid_handle; case ASEMEM_E_INVALID_PARAMETER: return invalid_parameter; case ASEMEM_E_NO_SMARTCARD: return no_card; case ASEMEM_E_RESET_CARD: return reset_card; case ASEMEM_E_SHARING_VIOLATION: return protection_error; case ASEMEM_E_UNKNOWN_READER: return unknown_reader; case ASEMEM_E_NO_READERS_AVAILABLE: return no_reader; case ASEMEM_E_INSUFFICIENT_BUFFER: return buffer_overflow; case ASEMEM_E_SERVICE_STOPPED: return sevice_stopped; case ASEMEM_E_TIMEOUT : return timeout_err; case ASEMEM_E_NO_MEMORY: return no_memory; case ASEMEM_E_UNKNOWN_ERROR: default: return unknown_err; } } void TSmart_card::display_error(smartcard_error error) const { switch (error) { case no_smarterror: break; case wrong_function: error_box(TR("Funzione errata")); break; case card_removed: error_box(TR("Smartcard rimossa")); break; case no_power: error_box(TR("Smartcard non alimentata")); break; case wrong_card: error_box(TR("Smartcard errata")); break; case wrong_password: error_box(TR("Password errata")); break; case password_blocked: error_box(TR("Password bloccata")); break; case invelid_handle: error_box(TR("Handle errata")); break; case invalid_parameter: error_box(TR("Parametro errato")); break; case no_card: error_box(TR("Smartcard rimossa")); break; case reset_card: error_box(TR("Smartcard rinizializzata")); break; case protection_error: error_box(TR("Errore di protezione")); break; case unknown_reader: error_box(TR("Lettore sconosciuto")); break; case no_reader: error_box(TR("Nessun lettore rilevato")); break; case buffer_overflow: error_box(TR("Buffer overflow")); break; case sevice_stopped: error_box(TR("Servizio fermato")); break; case timeout_err: error_box(TR("Timeout")); break; case no_memory: error_box(TR("No memory")); break; case new_card: message_box(TR("Smartcard nuova")); break; case unknown_err: error_box(TR("Errore sconosciuto")); default: break; } } smartcard_error TSmart_card::read() { _values.destroy(); smartcard_error error = no_smarterror; if (_type == ase_smartcard) { char * buffer = NULL; error = ASEmap_error(ASEread(&buffer)); if (error == no_smarterror) { TToken_string t((const char *)buffer); for (const char * s = t.get(); s && *s != '\0'; s = t.get()) _values.add(s); if (t.empty()) error = new_card; } int i; for (i = _values.items(); i < _last_smart_field; i++) _values.add(""); const TRectype & tabrec = cache().get("SMC", _values.row(_key_field)); for (; i < _num_fields; i++) { const TString & val = tabrec.get(_tab_field.row(i)); _values.add(val); } if (buffer != NULL) delete buffer; } _card_connected = (error == no_smarterror || error == new_card); return error; } smartcard_error TSmart_card::connect_card() { return read(); } smartcard_error TSmart_card::disconnect_card() { _card_connected = false; return no_smarterror; } smartcard_error TSmart_card::write() const { TToken_string t; int i; smartcard_error error; for (i = 0; i < _last_smart_field; i++) t.add(_values.row(i)); TTable tab("SMC"); tab.put("CODTAB", _values.row(_key_field)); bool new_rec = tab.read(_isequal, _lock) != NOERR; for (i = 0 ; i < _num_fields; i++) if (!_tab_field.row(i).empty()) { if (i == _anno_field || i == _ndoc_field) { if (tab.get_int(_tab_field.row(i)) < atoi(_values.row(i))) tab.put(_tab_field.row(i), _values.row(i)); } else tab.put(_tab_field.row(i), _values.row(i)); } if (new_rec) tab.write(); else tab.rewrite(); if (_type == ase_smartcard) error = ASEmap_error(ASEwrite((char *)(const char *)t)); return error; } void TSmart_card::mask2card(const TMask & m) { _values.destroy(); for (int i = 0; i < _num_fields; i++) { const TString & val = m.get(_output_field[i]); _values.add(val, i); } } smartcard_error TSmart_card::check_key(const TMask & m) { const TString & card_key = _values.row(_key_field); const TString & mask_key = m.get(_input_field[_key_field]); const bool ok = (mask_key.empty() || card_key == mask_key); if (!ok) disconnect_card(); return ok ? no_smarterror : wrong_card; } void TSmart_card::card2mask(TMask & m) { for (int i = 0; i < _num_fields; i++) if (_input_field[i] >= 0) { if (_prog_field[i] > 0) { const int anno_fld = anno_field(); const int ndoc_fld = ndoc_field(); const int last_anno = get_int(anno_fld); const int last_ndoc = get_int(ndoc_fld); const int anno = m.get_int(_output_field[anno_fld]); const int ndoc = m.get_int(_output_field[ndoc_fld]); if (anno > last_anno) sub2field(i, m.get_real(_prog_field[i])); if (anno == last_anno && ndoc <= last_ndoc) sub2field(i, m.get_real(_prog_field[i])); } const TString & val = _values.row(i); m.set(_input_field[i], val, 3); } m.set(_check_field, card_connected()); } void TSmart_card::enable_prot_fields(TMask & m, bool on) const { for (int i = 0; i < _num_fields; i++) if (_prot_field[i]) m.enable(_input_field[i], on); } void TSmart_card::add2field(int field, real & val) { real field_val(_values.row(field)); field_val += val; _values.add(field_val.string(), field); } bool TSmart_card::init() { // Identify card _card_connected = false; TFilename f("smartcard.ini"); if (f.custom_path()) { TConfig c(f, "ve0100"); switch (c.get_int("Type")) { case 0: _type = no_smartcard; break; case 1: { if (ASEloadlibrary()) { smartcard_error err = ASEmap_error(ASEsearch()); if (err == no_reader) _type = no_smartcard; else _type = ase_smartcard; } else _type = no_smartcard; } break; default: _type = no_smartcard; break; } _last_smart_field = c.get_int("FieldsOnCard"); _password = c.get("Password").left(3); _anno_field = c.get_int("AnnoField"); _ndoc_field = c.get_int("NDocField"); _check_field = c.get_int("CheckField"); for (_num_fields = 0; _num_fields < MAX_SM_FIELDS; _num_fields++) { _input_field[_num_fields] = c.get_int("InputFld", NULL, _num_fields); if (_input_field[_num_fields] != 0) { _output_field[_num_fields] = c.get_int("OutputFld", NULL, _num_fields, _input_field[_num_fields]); _prog_field[_num_fields] = c.get_int("ProgFld", NULL, _num_fields); _prot_field.set(_num_fields, c.get_bool("ProtFld", NULL, _num_fields)); _tab_field.add(c.get("TabFld", NULL, _num_fields, ""), _num_fields); if (_tab_field.row(_num_fields) == "CODTAB") _key_field = _num_fields; } else break; } } return true; }