Ticket #10842: filezilla_trust_cert.patch

File filezilla_trust_cert.patch, 5.7 KB (added by Tommy Wu, 4 years ago)

patch allow to save non-first certificate in chain, and IsTrust() will check all certificate in chain

  • src/interface/verifycertdialog.cpp

    diff -Nur filezilla.orig/src/interface/verifycertdialog.cpp filezilla/src/interface/verifycertdialog.cpp
    old new  
    147147            XRCCTRL(*m_pDlg, "ID_ALWAYS", wxCheckBox)->Hide();
    148148    }
    149149
     150    m_curSelect = 0;
    150151    m_certificates = notification.GetCertificates();
    151152    if (m_certificates.size() == 1) {
    152153        XRCCTRL(*m_pDlg, "ID_CHAIN_DESC", wxStaticText)->Hide();
     
    230231    m_pDlg = 0;
    231232}
    232233
     234wxString CVerifyCertDialog::GetCNValue(const wxString& dn)
     235{
     236    wxStringTokenizer tokens(dn, _T(","));
     237
     238    std::list<wxString> tokenlist;
     239    while (tokens.HasMoreTokens())
     240        tokenlist.push_back(tokens.GetNextToken());
     241
     242    wxString prefix = _T("CN=");
     243    int len = prefix.Length();
     244
     245    wxString value;
     246
     247    bool append = false;
     248
     249    auto iter = tokenlist.begin();
     250    while (iter != tokenlist.end())
     251    {
     252        if (!append)
     253        {
     254            if (iter->Left(len) != prefix)
     255            {
     256                ++iter;
     257                continue;
     258            }
     259            if (!value.empty())
     260                value += _T("\n");
     261        }
     262        else
     263        {
     264            append = false;
     265            value += _T(",");
     266        }
     267        value += iter->Mid(len);
     268        if (iter->Last() == '\\')
     269        {
     270            value.RemoveLast();
     271            append = true;
     272            len = 0;
     273        }
     274        auto remove = iter++;
     275        tokenlist.erase(remove);
     276    }
     277    return value;
     278}
     279
    233280void CVerifyCertDialog::ParseDN(wxWindow* parent, const wxString& dn, wxSizer* pSizer)
    234281{
    235282    pSizer->Clear(true);
     
    329376
    330377    LoadTrustedCerts();
    331378
    332     unsigned int len;
    333     CCertificate cert =  notification.GetCertificates()[0];
    334     const unsigned char* data = cert.GetRawData(len);
     379    for (unsigned int i = 0; i < notification.GetCertificates().size(); ++i) {
     380        if (i > 0) {
     381            unsigned int len;
     382            CCertificate cert =  notification.GetCertificates()[i];
     383            const unsigned char* data = cert.GetRawData(len);
     384            wxString sCN = GetCNValue(cert.GetSubject());
    335385
    336     return IsTrusted(notification.GetHost(), notification.GetPort(), data, len, false);
     386            if (IsTrusted(sCN, 0, data, len, false)) {
     387                return true;
     388            }
     389        }
     390        else {
     391            unsigned int len;
     392            CCertificate cert =  notification.GetCertificates()[0];
     393            const unsigned char* data = cert.GetRawData(len);
     394
     395            if (IsTrusted(notification.GetHost(), notification.GetPort(), data, len, false)) {
     396                return true;
     397            }
     398        }
     399        }
     400    return false;
    337401}
    338402
    339403bool CVerifyCertDialog::DoIsTrusted(const wxString& host, int port, const unsigned char* data, unsigned int len, std::list<CVerifyCertDialog::t_certData> const& trustedCerts)
     
    465529
    466530        data.host = GetTextElement(cert, "Host");
    467531        data.port = GetTextElementInt(cert, "Port");
    468         if (data.host.empty() || data.port < 1 || data.port > 65535)
     532        if (data.port == 0) {
     533            // use for non-first cert
     534        }
     535        else if (data.host.empty() || data.port < 1 || data.port > 65535)
    469536            remove = cert;
    470537
    471538        int64_t activationTime = GetTextElementInt(cert, "ActivationTime", 0);
     
    498565
    499566void CVerifyCertDialog::SetPermanentlyTrusted(CCertificateNotification const& notification)
    500567{
    501     const CCertificate certificate = notification.GetCertificates()[0];
     568    wxString sCN = _T("");
     569    const CCertificate certificate = notification.GetCertificates()[m_curSelect];
    502570    unsigned int len;
    503571    const unsigned char* const data = certificate.GetRawData(len);
    504572
    505573    CReentrantInterProcessMutexLocker mutex(MUTEX_TRUSTEDCERTS);
    506574    LoadTrustedCerts();
    507575
    508     if (IsTrusted(notification.GetHost(), notification.GetPort(), data, len, true)) {
    509         return;
     576    if (m_curSelect > 0) {
     577        sCN = GetCNValue(certificate.GetSubject());
     578        if (IsTrusted(sCN, 0, data, len, true)) {
     579            return;
     580        }
     581    }
     582    else {
     583        if (IsTrusted(notification.GetHost(), notification.GetPort(), data, len, true)) {
     584            return;
     585        }
    510586    }
    511587
    512588    t_certData cert;
    513     cert.host = notification.GetHost();
    514     cert.port = notification.GetPort();
     589    if (m_curSelect > 0) {
     590        cert.host = sCN;
     591        cert.port = 0;
     592    }
     593    else {
     594        cert.host = notification.GetHost();
     595        cert.port = notification.GetPort();
     596    }
    515597    cert.len = len;
    516598    cert.data = new unsigned char[len];
    517599    memcpy(cert.data, data, len);
     
    534616    AddTextElement(xCert, "Data", ConvertHexToString(data, len));
    535617    AddTextElement(xCert, "ActivationTime", static_cast<int64_t>(certificate.GetActivationTime().get_time_t()));
    536618    AddTextElement(xCert, "ExpirationTime", static_cast<int64_t>(certificate.GetExpirationTime().get_time_t()));
    537     AddTextElement(xCert, "Host", notification.GetHost());
    538     AddTextElement(xCert, "Port", notification.GetPort());
     619    if (m_curSelect > 0) {
     620        AddTextElement(xCert, "Host", sCN);
     621        AddTextElement(xCert, "Port", 0);
     622    }
     623    else {
     624        AddTextElement(xCert, "Host", notification.GetHost());
     625        AddTextElement(xCert, "Port", notification.GetPort());
     626    }
    539627
    540628    m_xmlFile.Save(true);
    541629}
     
    590678    int sel = event.GetSelection();
    591679    if (sel < 0 || sel > (int)m_certificates.size())
    592680        return;
     681    m_curSelect = sel;
    593682    DisplayCert(m_pDlg, m_certificates[sel]);
    594683
    595684    m_pDlg->Layout();
  • src/interface/verifycertdialog.h

    diff -Nur filezilla.orig/src/interface/verifycertdialog.h filezilla/src/interface/verifycertdialog.h
    old new  
    2828
    2929    bool DisplayCert(wxDialogEx* pDlg, const CCertificate& cert);
    3030
     31    wxString GetCNValue(const wxString& dn);
    3132    void ParseDN(wxWindow* parent, const wxString& dn, wxSizer* pSizer);
    3233    void ParseDN_by_prefix(wxWindow* parent, std::list<wxString>& tokens, wxString prefix, const wxString& name, wxSizer* pSizer, bool decode = false);
    3334
     
    5051    wxSizer* m_pSubjectSizer{};
    5152    wxSizer* m_pIssuerSizer{};
    5253    int line_height_{};
     54    unsigned int m_curSelect;
    5355
    5456    void OnCertificateChoice(wxCommandEvent& event);
    5557};