#include "wxinc.h" #include "esigner.h" #include "gtDialog.h" #include "gtSSA.h" #include "MD5Checksum.h" #include #include #include #include #include #include /////////////////////////////////////////////////////////// // Utility /////////////////////////////////////////////////////////// #define APPFULLNAME wxAppConsole::GetInstance()->GetAppName() static wxString IniGetString(const char* sec, const char* var, const char* def = "") { wxString val; if (sec && *sec && var && *var) { const size_t sz = 256; char* buf = val.GetWriteBuf(sz); ::GetPrivateProfileString(sec, var, def, buf, sz, "./ESigner.ini"); val.UngetWriteBuf(); } return val; } static long IniGetLong(const char* sec, const char* var, long def = 0) { wxString str; if (def != 0) str.Printf("%ld", def); return wxAtol(IniGetString(sec, var, str)); } static bool IniSetString(const char* sec, const char* var, const wxString val) { if (sec && *sec && var && *var) { ::WritePrivateProfileString(sec, var, val, "./ESigner.ini"); return true; } return false; } static bool IniSetLong(const char* sec, const char* var, long val) { wxString str; str.Printf("%ld", val); return IniSetString(sec, var, str); } static bool IsOnline() { /* //stoppa il log di wxWidgets per non avere segnalazioni di errori incomprensibili! const bool bLogEnabled = wxLog::EnableLogging(false); bool bOnline = false; wxDialUpManager* dum = wxDialUpManager::Create(); if (dum != NULL) { if (dum->IsOk() && dum->IsOnline()) { wxIPV4address addr; if (addr.Hostname("www.google.com")) bOnline = true; } delete dum; } wxLog::EnableLogging(bLogEnabled); return bOnline; */ return true; } /////////////////////////////////////////////////////////// // TESignerDlg /////////////////////////////////////////////////////////// class TEsignerDlg : public gtPropertyDlg { wxString m_strUser; protected: virtual bool TransferDataToWindow(); virtual bool TransferDataFromWindow(); public: TEsignerDlg(const wxString& user); }; bool TEsignerDlg::TransferDataToWindow() { bool ok = gtPropertyDlg::TransferDataToWindow(); if (ok) { SetProperty("CER", IniGetString(m_strUser, "CER")); SetProperty("PEM", IniGetString(m_strUser, "PEM")); SetProperty("PFX", IniGetString(m_strUser, "PFX")); SetProperty("DLL", IniGetString(m_strUser, "DLL")); SetProperty("IDX", IniGetLong(m_strUser, "IDX")); SetProperty("URL", IniGetString(m_strUser, "URL")); SetProperty("USR", IniGetString(m_strUser, "USR")); SetProperty("PWD", IniGetString(m_strUser, "PWD")); SetProperty("POL", IniGetString(m_strUser, "POL")); SetProperty("DIR_IN", IniGetString(m_strUser, "DIR_IN")); SetProperty("DIR_OUT", IniGetString(m_strUser, "DIR_OUT")); SetProperty("DIR_BCK", IniGetString(m_strUser, "DIR_BCK")); SetProperty("BCK", IniGetLong (m_strUser, "BCK")); } return ok; } bool TEsignerDlg::TransferDataFromWindow() { bool ok = gtPropertyDlg::TransferDataFromWindow(); if (ok) { IniSetString(m_strUser, "CER", GetProperty("CER")); IniSetString(m_strUser, "PEM", GetProperty("PEM")); IniSetString(m_strUser, "PFX", GetProperty("PFX")); IniSetString(m_strUser, "DLL", GetProperty("DLL")); IniSetLong (m_strUser, "IDX", GetProperty("IDX")); IniSetString(m_strUser, "URL", GetProperty("URL")); IniSetString(m_strUser, "USR", GetProperty("USR")); IniSetString(m_strUser, "PWD", GetProperty("PWD")); IniSetString(m_strUser, "POL", GetProperty("POL")); IniSetString(m_strUser, "DIR_IN", GetProperty("DIR_IN")); IniSetString(m_strUser, "DIR_OUT", GetProperty("DIR_OUT")); IniSetString(m_strUser, "DIR_BCK", GetProperty("DIR_BCK")); IniSetLong (m_strUser, "BCK", GetProperty("BCK").GetInteger()); } return ok; } TEsignerDlg::TEsignerDlg(const wxString& user) : gtPropertyDlg(APPFULLNAME, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxSTAY_ON_TOP), m_strUser(user) { Init(); AddCategory("Cartelle"); AddPropertyDB("DIR_IN", wxEmptyString, "Input", 0, wxEmptyString, "*."); AddPropertyDB("DIR_OUT", wxEmptyString, "Output", 0, wxEmptyString, "*."); AddPropertyDB("DIR_BCK", wxEmptyString, "Backup", 0, wxEmptyString, "*."); wxArrayString aActions; aActions.Add("Nessuna operazione"); aActions.Add("Elimina file da firmare"); aActions.Add("Backup file da firmare"); AddProperty("BCK", aActions, 0, "Dopo la firma"); AddPage("Avanzate"); AddCategory("Certificati"); AddPropertyDB("CER", wxString(), wxT("File CER"), 0, wxEmptyString, "*.cer"); AddPropertyDB("PEM", wxString(), wxT("File PEM"), 0, wxEmptyString, "*.pem"); AddPropertyDB("PFX", wxString(), wxT("File PFX"), 0, wxEmptyString, "*.pfx"); AddCategory("Token"); AddProperty("IDX", 0, wxT("Numero certificato")); AddPropertyDB("DLL", wxString(), wxT("DLL driver"), 0, wxEmptyString, "*.dll"); AddCategory("Marcatura temporale"); const int nFlags = IsOnline() ? 0 : wxTE_READONLY; AddProperty("URL", wxString(), wxT("URL Autorità"), nFlags); AddProperty("USR", wxString(), wxT("Utente"), nFlags); AddProperty("PWD", wxString(), wxT("Password"), nFlags | wxTE_PASSWORD); AddProperty("POL", wxString(), wxT("Policy"), nFlags); wxArrayString aCoding; aCoding.Add("binary"); aCoding.Add("text"); AddProperty("ENC", aCoding, aCoding[0], wxT("Coding"), nFlags); } /////////////////////////////////////////////////////////// // TSignatureDlg /////////////////////////////////////////////////////////// class TSignatureDlg : public gtPropertyDlg { DECLARE_EVENT_TABLE(); protected: void OnMore(wxCommandEvent& evt); virtual bool OnValidateProperty(wxVariant& val); public: TSignatureDlg(); }; BEGIN_EVENT_TABLE(TSignatureDlg, gtPropertyDlg) EVT_BUTTON(wxID_MORE, TSignatureDlg::OnMore) END_EVENT_TABLE() bool TSignatureDlg::OnValidateProperty(wxVariant& val) { const wxString& name = val.GetName(); if (name == "USR") { if (val.GetString().IsEmpty()) return gtError("Occorre specificare un utente"); return true; } if (name == "PIN") { if (val.GetString().Len() < 2) return gtError("Occorre specificare un PIN"); return true; } return gtPropertyDlg::OnValidateProperty(val); } void TSignatureDlg::OnMore(wxCommandEvent& WXUNUSED(evt)) { wxVariant vUser = GetProperty("USR"); if (OnValidateProperty(vUser)) { Disable(); TEsignerDlg dlg(vUser.GetString()); dlg.SetParent(this); dlg.ShowModal(); Enable(); } } TSignatureDlg::TSignatureDlg() : gtPropertyDlg(APPFULLNAME) { Init(); wxString strUser = wxGetUserId(); AddProperty("USR", strUser, wxT("Utente"), wxTE_READONLY); AddProperty("PIN", wxString(), wxT("PIN"), wxTE_PASSWORD); const bool aol = IsOnline(); bool mrk = false; if (aol) mrk = IniGetString(strUser, "MRK", "0") == "1"; AddProperty("MRK", mrk, "Marcatura temporale", aol ? 0 : wxTE_READONLY); PrependButton(wxID_MORE, "Opzioni...", wxEmptyString); } /////////////////////////////////////////////////////////// // TEsigner /////////////////////////////////////////////////////////// class TEsigner { HMODULE m_hESigner; ESignerSignProto _SignPDF; ESignerVerifyProto _VerifyPDF; int m_nNum; wxString m_strUser, m_strPin, m_strDLL, m_strCER, m_strPEM, m_strPFX; wxString m_strTSAurl, m_strTSAuser, m_strTSApwd, m_strPolicy, m_strTSAcoding; bool m_bMark; protected: bool TestFile(const wxString& strFile) const; void Backup(const wxString& strInput, const wxString& strBackup) const; public: bool Init(bool on); bool GetPin(); bool Sign(const wxString& strInput, wxString& strOutput, const wxString& strBackup, int mode); bool Verify(const wxString& strInput); const wxString& User() const { return m_strUser; } TEsigner(); ~TEsigner(); }; TEsigner::TEsigner() : m_bMark(false), m_hESigner(NULL), _SignPDF(NULL), _VerifyPDF(NULL), m_nNum(0) {} TEsigner::~TEsigner() { Init(false); } bool TEsigner::TestFile(const wxString& strFile) const { bool ok = true; if (!strFile.IsEmpty()) { ok = wxFileExists(strFile); if (!ok) { wxString msg; msg << "Impossibile caricare il file " << strFile << "\nControllare il paragrafo [" << m_strUser << "] nel file ESigner.ini"; gtError(msg); } } return ok; } bool TEsigner::GetPin() { TSignatureDlg dlg; if (!m_strUser.IsEmpty()) dlg.SetProperty("USR", m_strUser); if (dlg.ShowModal() == wxID_OK) { m_strUser = dlg.GetString("USR"); m_strPin = dlg.GetString("PIN"); m_bMark = dlg.GetBool("MRK"); IniSetString(m_strUser, "MRK", m_bMark ? "1" : "0"); } else return false; m_nNum = IniGetLong(m_strUser, "IDX"); m_strDLL = IniGetString(m_strUser, "DLL"); m_strPFX = IniGetString(m_strUser, "PFX"); m_strCER = IniGetString(m_strUser, "CER"); m_strPEM = IniGetString(m_strUser, "PEM"); if (m_strDLL.IsEmpty() && m_strCER.IsEmpty() && m_strPFX.IsEmpty()) { TEsignerDlg dlg(m_strUser); if (dlg.ShowModal() == wxID_OK) { m_nNum = dlg.GetInt("IDX"); m_strDLL = dlg.GetString("DLL"); m_strPFX = dlg.GetString("PFX"); m_strCER = dlg.GetString("CER"); m_strPEM = dlg.GetString("PEM"); } } if (m_bMark) { m_strTSAurl = IniGetString(m_strUser, "TSA_URL"); m_strTSAuser = IniGetString(m_strUser, "TSA_USR"); m_strTSApwd = IniGetString(m_strUser, "TSA_PWD"); m_strPolicy = IniGetString(m_strUser, "TSA_POL"); m_strTSAcoding = IniGetString(m_strUser, "TSA_ENC", "binary"); if (m_strTSAurl.IsEmpty()) { wxString msg; msg << "Mancano i parametri per la marcatura temporale" << "\nControllare il paragrafo [" << m_strUser << "] del file ESigner.ini"; wxLogWarning(msg); m_bMark = false; } } return m_strPin.Len() >= 2; } bool TEsigner::Init(bool bLoad) { bool ok = false; if (bLoad) { if (m_hESigner == NULL) { m_hESigner = ::LoadLibrary("esigner.dll"); if (m_hESigner != NULL) { _SignPDF = (ESignerSignProto)::GetProcAddress(m_hESigner, "Sign"); _VerifyPDF = (ESignerVerifyProto)::GetProcAddress(m_hESigner, "Verify"); m_strPin.Empty(); GetPin(); } } ok = m_hESigner != NULL && _SignPDF != NULL && _VerifyPDF != NULL; if (!ok) gtError("Impossibile caricare 'ESigner.dll'"); else ok = TestFile(m_strDLL) && TestFile(m_strCER) && TestFile(m_strPEM) && TestFile(m_strPFX); } else { if (m_hESigner != NULL) { ::FreeLibrary(m_hESigner); m_hESigner = NULL; _SignPDF = NULL; _VerifyPDF = NULL; m_strPin.Empty(); } } return ok; } void TEsigner::Backup(const wxString& strInput, const wxString& strBackup) const { int mode = 3; if (strBackup.CmpNoCase("Cestino") == 0 || strBackup.CmpNoCase("NULL") == 0 || strBackup.CmpNoCase("Basket") == 0 || strBackup.CmpNoCase("Trash") == 0) mode = 1; else wxFileName::Mkdir(strBackup, 0777, wxPATH_MKDIR_FULL); if (mode & 2) { wxFileName fout = strInput; fout.SetPath(strBackup); if (!wxCopyFile(strInput, fout.GetFullPath())) mode = 0; } if (mode & 1) ::wxRemoveFile(strInput); } bool TEsigner::Sign(const wxString& strInput, wxString& strOutput, const wxString& strBackup, int mode) { if (m_strPin.Len() < 2) { if (!Init(true)) return false; if (!GetPin()) return gtError("PIN non valido"); } wxString strOperation = "S"; if (m_bMark && !m_strTSAurl.IsEmpty()) // Firma con marcatura temporale strOperation += "+T"; const bool bIsDir = wxDirExists(strInput); wxString strMethod; if (!m_strDLL.IsEmpty()) // Token strMethod = "T"; else if (!m_strPFX.IsEmpty()) strMethod = "P"; else if (!m_strCER.IsEmpty()) strMethod = "F"; else return false; wxString strIndex; strIndex.Printf("%d", m_nNum); char* operation = (char*)(const char*)strOperation; char* method = (char*)(const char*)strMethod; char* ext = ".p7m"; char* input = (char*)(const char*)strInput; char* output = (char*)(const char*)strOutput; char* cer = strMethod == "F" ? (char*)(const char*)m_strCER : NULL; char* pem = strMethod == "F" ? (char*)(const char*)m_strPEM : NULL; char* pfx = strMethod == "P" ? (char*)(const char*)m_strPFX : NULL; char* idx = (char*)(const char*)strIndex; char* pin = (char*)(const char*)m_strPin; char* dll = strMethod == "T" ? (char*)(const char*)m_strDLL : NULL; char* TSA_output = NULL; char* TSA_url = NULL; char* TSA_user = NULL; char* TSA_pwd = NULL; char* TSA_policy = NULL; char* TSA_coding = NULL; char* TSA_rootCA = NULL; if (strOperation.Find("+T") > 0) // Firma con marcatura temporale { TSA_url = (char*)(const char*)m_strTSAurl; TSA_user = (char*)(const char*)m_strTSAuser; TSA_pwd = (char*)(const char*)m_strTSApwd; TSA_policy = (char*)(const char*)m_strPolicy; TSA_coding = (char*)(const char*)m_strTSAcoding; } if (bIsDir) { if (strOutput.IsEmpty()) output = input; } else { //ext = strInput.Lower().EndsWith(".pdf") ? ".pdf.p7m" : ".p7m"; if (strOutput.IsEmpty()) strOutput = strInput + ".p7m"; ::wxRemoveFile(strOutput); // Altrimenti la fantastica dll s'incazza come una biscia strOutput = strOutput.BeforeFirst('.'); output = (char*)(const char*)strOutput; } int res = 0; if (bIsDir) { wxArrayString files; const size_t xmls = wxDir::GetAllFiles(strInput, &files, "*.xml", wxDIR_FILES); wxProgressDialog pd(APPFULLNAME, "Firma dei file in " + strInput); for (size_t i = 0; i < xmls && res == 0; i++) { input = (char*)(const char*)files[i]; wxFileName fnOutput = files[i]; fnOutput.SetPath(strOutput); fnOutput.SetExt(""); output = (char*)(const char*)fnOutput.GetFullPath(); res = _SignPDF(operation, method, input, output, NULL, ext, cer, pem, pfx, dll, pin, NULL, idx, TSA_url, TSA_user, TSA_pwd, TSA_policy, TSA_coding, NULL); if (res == 0) { if (!strBackup.IsEmpty()) Backup(files[i], strBackup); if (!pd.Update(i+1)) break; } } } else { res = _SignPDF(operation, method, input, output, NULL, ext, cer, pem, pfx, dll, pin, NULL, idx, TSA_url, TSA_user, TSA_pwd, TSA_policy, TSA_coding, NULL); if (res == 0 && !strBackup.IsEmpty()) Backup(strInput, strBackup); } if (res == 0) { gtMessage("Operazione di firma completata."); } else { const char* msg = NULL; switch (res) { case -2: msg = "Errore di lettura del certificato"; break; case -3: msg = "Errore di lettura della chiave privata"; break; case -4: msg = "Errore di lettura file PFX"; break; case -5: msg = "Errore recupero certificato da Token"; break; case -6: msg = "Errore apertura file"; break; case -7: case -8: case -9: msg = "Errore conatatto TSA"; break; case -10: msg = "Accesso al token fallito"; break; case -11: msg = "Impossibile trovare dll driver del token"; break; case -14: msg = "Il file di output esiste già"; break; case -15: case -16: msg = "Errore di marcatura temporale"; break; default : msg = "Errore di accesso alle operazioni di firma"; break; } wxString str; str.Printf("ESigner.dll errore %d:\n%s", res, msg); gtError(str); } return res == 0; } bool TEsigner::Verify(const wxString& strInput) { int res = -1; if (Init(!strInput.IsEmpty())) { char file[_MAX_PATH], result[_MAX_PATH]; wxStrncpy(file, strInput, _MAX_PATH); res = _VerifyPDF("V", file, NULL, NULL, NULL, result); } return res == 0; } /////////////////////////////////////////////////////////// // TMainDlg /////////////////////////////////////////////////////////// class TMainDlg : public gtPropertyDlg { wxString m_strUser; DECLARE_EVENT_TABLE(); protected: virtual bool TransferDataFromWindow(); virtual bool TransferDataToWindow(); public: TMainDlg(const wxString& strUser); }; BEGIN_EVENT_TABLE(TMainDlg, gtPropertyDlg) END_EVENT_TABLE() bool TMainDlg::TransferDataToWindow() { bool ok = gtPropertyDlg::TransferDataToWindow(); if (ok) { SetProperty("DIR_IN", IniGetString(m_strUser, "DIR_IN")); SetProperty("DIR_OUT", IniGetString(m_strUser, "DIR_OUT")); /* SetProperty("FILE_IN", IniGetString(m_strUser, "FILE_IN")); SetProperty("FILE_OUT", IniGetString(m_strUser, "FILE_OUT")); */ } return ok; } bool TMainDlg::TransferDataFromWindow() { bool ok = gtPropertyDlg::TransferDataFromWindow(); if (ok) { IniSetString(m_strUser, "DIR_IN", GetProperty("DIR_IN")); IniSetString(m_strUser, "DIR_OUT", GetProperty("DIR_OUT")); /* IniSetString(m_strUser, "FILE_IN", GetProperty("FILE_IN")); IniSetString(m_strUser, "FILE_OUT", GetProperty("FILE_OUT")); */ } return ok; } TMainDlg::TMainDlg(const wxString& strUser): gtPropertyDlg(APPFULLNAME), m_strUser(strUser) { Init(); AddCategory("Cartelle"); AddPropertyDB("DIR_IN", wxEmptyString, "Input", 0, wxEmptyString, "*."); AddPropertyDB("DIR_OUT", wxEmptyString, "Output", 0, wxEmptyString, "*."); /* AddCategory("File"); AddPropertyDB("FILE_IN", wxEmptyString, "Input", 0, wxEmptyString, "*.xml"); AddPropertyDB("FILE_OUT", wxEmptyString, "Output", 0, wxEmptyString, "*.xml"); */ } /////////////////////////////////////////////////////////// // TESigner_app /////////////////////////////////////////////////////////// class TESigner_app : public wxApp { TEsigner __TheSigner; public: virtual bool OnInit(); virtual int OnExit(); }; IMPLEMENT_APP(TESigner_app) bool TESigner_app::OnInit() { SetAppName("Firma digitale v11.9"); gtInitArtProvider(); if (SSA_Login() != 0) return gtError("Postazione non abilitata al modulo Firma Digitale"); const wxString strLogoMD5 = wxMD5Checksum::GetMD5(wxT("fd0logo.png")); if (strLogoMD5 != "7f4c28a0ef5f575e0e13b32ab137e43c") return gtError("Impossibile trovare un logo valido"); const bool done = __TheSigner.Init(true); if (done) { const wxString& usr = __TheSigner.User(); wxString inf, outf; for (int a = 1; a < __argc; a++) { const wxString f = __argv[a]; if (inf.IsEmpty() && (wxFileExists(f) || wxDirExists(f))) inf = f; else if (!inf.IsEmpty() && outf.IsEmpty()) { outf = f; break; } } if (inf.IsEmpty()) inf = IniGetString(usr, "DIR_IN"); if (outf.IsEmpty()) outf = IniGetString(usr, "DIR_OUT"); if (inf.IsEmpty() && !usr.IsEmpty()) { TMainDlg dlg(usr); if (dlg.ShowModal() == wxID_OK) { inf = dlg.GetString("DIR_IN"); outf = dlg.GetString("DIR_OUT"); } } while (!usr.IsEmpty() && !inf.IsEmpty()) { const wxString bckd = IniGetString(usr, "DIR_BCK"); const long mode = IniGetLong(usr, "BCK"); __TheSigner.Sign(inf, outf, bckd, mode); if (__TheSigner.GetPin()) { inf = IniGetString(usr, "DIR_IN"); outf = IniGetString(usr, "DIR_OUT"); } else break; } __TheSigner.Init(false); } SSA_Logout(); return false; } int TESigner_app::OnExit() { return wxApp::OnExit(); }