Tommy 碎碎念

Tommy Wu's blog

« 上一篇 | 下一篇 »

讓 FileZilla 儲存所選擇的憑證, 而非只能儲存站台本身的憑證
post by tommy @ 28 五月, 2016 20:50

由於之前提到改用 Let's Encrypt 來產生憑證之後, 會造成平均每兩個月就會更換一次憑證, 而 FileZilla 本身只能儲存並信任站台本身的憑證, 所以... 變成每次更換憑證會就會要求再信任一次.

所以, 就改了一下 FileZilla, 把憑證儲存的地方, 改成依據目前選擇查閱的憑證來儲存 (這時會改存 CN 而不是 Host, 而 Port 一律為 0), 然後在每次檢查信任憑證的地方, 改成檢查所有的憑證, 只要有一個是信任的就可以.

diff -Nurp filezilla.orig/src/interface/verifycertdialog.cpp filezilla/src/interface/verifycertdialog.cpp
--- filezilla.orig/src/interface/verifycertdialog.cpp 2016-05-25 16:19:18.590183991 +0800
+++ filezilla/src/interface/verifycertdialog.cpp 2016-05-26 13:14:03.897443962 +0800
@@ -147,6 +147,7 @@ void CVerifyCertDialog::ShowVerification
XRCCTRL(*m_pDlg, "ID_ALWAYS", wxCheckBox)->Hide();
}
 
+ m_curSelect = 0;
m_certificates = notification.GetCertificates();
if (m_certificates.size() == 1) {
XRCCTRL(*m_pDlg, "ID_CHAIN_DESC", wxStaticText)->Hide();
@@ -230,6 +231,52 @@ void CVerifyCertDialog::ShowVerification
m_pDlg = 0;
}
 
+wxString CVerifyCertDialog::GetCNValue(const wxString& dn)
+{
+ wxStringTokenizer tokens(dn, _T(","));
+
+ std::list<wxString> tokenlist;
+ while (tokens.HasMoreTokens())
+ tokenlist.push_back(tokens.GetNextToken());
+
+ wxString prefix = _T("CN=");
+ int len = prefix.Length();
+
+ wxString value;
+
+ bool append = false;
+
+ auto iter = tokenlist.begin();
+ while (iter != tokenlist.end())
+ {
+ if (!append)
+ {
+ if (iter->Left(len) != prefix)
+ {
+ ++iter;
+ continue;
+ }
+ if (!value.empty())
+ value += _T("\n");
+ }
+ else
+ {
+ append = false;
+ value += _T(",");
+ }
+ value += iter->Mid(len);
+ if (iter->Last() == '\\')
+ {
+ value.RemoveLast();
+ append = true;
+ len = 0;
+ }
+ auto remove = iter++;
+ tokenlist.erase(remove);
+ }
+ return value;
+}
+
void CVerifyCertDialog::ParseDN(wxWindow* parent, const wxString& dn, wxSizer* pSizer)
{
pSizer->Clear(true);
@@ -329,11 +376,28 @@ bool CVerifyCertDialog::IsTrusted(CCerti
 
LoadTrustedCerts();
 
- unsigned int len;
- CCertificate cert = notification.GetCertificates()[0];
- const unsigned char* data = cert.GetRawData(len);
+ for (unsigned int i = 0; i < notification.GetCertificates().size(); ++i) {
+ if (i > 0) {
+ unsigned int len;
+ CCertificate cert = notification.GetCertificates()[i];
+ const unsigned char* data = cert.GetRawData(len);
+ wxString sCN = GetCNValue(cert.GetSubject());
 
- return IsTrusted(notification.GetHost(), notification.GetPort(), data, len, false);
+ if (IsTrusted(sCN, 0, data, len, false)) {
+ return true;
+ }
+ }
+ else {
+ unsigned int len;
+ CCertificate cert = notification.GetCertificates()[0];
+ const unsigned char* data = cert.GetRawData(len);
+
+ if (IsTrusted(notification.GetHost(), notification.GetPort(), data, len, false)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
 
bool CVerifyCertDialog::DoIsTrusted(const wxString& host, int port, const unsigned char* data, unsigned int len, std::list<CVerifyCertDialog::t_certData> const& trustedCerts)
@@ -465,7 +529,10 @@ void CVerifyCertDialog::LoadTrustedCerts
 
data.host = GetTextElement(cert, "Host");
data.port = GetTextElementInt(cert, "Port");
- if (data.host.empty() || data.port < 1 || data.port > 65535)
+ if (data.port == 0) {
+ // use for non-first cert
+ }
+ else if (data.host.empty() || data.port < 1 || data.port > 65535)
remove = cert;
 
int64_t activationTime = GetTextElementInt(cert, "ActivationTime", 0);
@@ -498,20 +565,35 @@ void CVerifyCertDialog::LoadTrustedCerts
 
void CVerifyCertDialog::SetPermanentlyTrusted(CCertificateNotification const& notification)
{
- const CCertificate certificate = notification.GetCertificates()[0];
+ wxString sCN = _T("");
+ const CCertificate certificate = notification.GetCertificates()[m_curSelect];
unsigned int len;
const unsigned char* const data = certificate.GetRawData(len);
 
CReentrantInterProcessMutexLocker mutex(MUTEX_TRUSTEDCERTS);
LoadTrustedCerts();
 
- if (IsTrusted(notification.GetHost(), notification.GetPort(), data, len, true)) {
- return;
+ if (m_curSelect > 0) {
+ sCN = GetCNValue(certificate.GetSubject());
+ if (IsTrusted(sCN, 0, data, len, true)) {
+ return;
+ }
+ }
+ else {
+ if (IsTrusted(notification.GetHost(), notification.GetPort(), data, len, true)) {
+ return;
+ }
}
 
t_certData cert;
- cert.host = notification.GetHost();
- cert.port = notification.GetPort();
+ if (m_curSelect > 0) {
+ cert.host = sCN;
+ cert.port = 0;
+ }
+ else {
+ cert.host = notification.GetHost();
+ cert.port = notification.GetPort();
+ }
cert.len = len;
cert.data = new unsigned char[len];
memcpy(cert.data, data, len);
@@ -534,8 +616,14 @@ void CVerifyCertDialog::SetPermanentlyTr
AddTextElement(xCert, "Data", ConvertHexToString(data, len));
AddTextElement(xCert, "ActivationTime", static_cast<int64_t>(certificate.GetActivationTime().get_time_t()));
AddTextElement(xCert, "ExpirationTime", static_cast<int64_t>(certificate.GetExpirationTime().get_time_t()));
- AddTextElement(xCert, "Host", notification.GetHost());
- AddTextElement(xCert, "Port", notification.GetPort());
+ if (m_curSelect > 0) {
+ AddTextElement(xCert, "Host", sCN);
+ AddTextElement(xCert, "Port", 0);
+ }
+ else {
+ AddTextElement(xCert, "Host", notification.GetHost());
+ AddTextElement(xCert, "Port", notification.GetPort());
+ }
 
m_xmlFile.Save(true);
}
@@ -590,6 +678,7 @@ void CVerifyCertDialog::OnCertificateCho
int sel = event.GetSelection();
if (sel < 0 || sel > (int)m_certificates.size())
return;
+ m_curSelect = sel;
DisplayCert(m_pDlg, m_certificates[sel]);
 
m_pDlg->Layout();
diff -Nurp filezilla.orig/src/interface/verifycertdialog.h filezilla/src/interface/verifycertdialog.h
--- filezilla.orig/src/interface/verifycertdialog.h 2016-05-25 15:15:10.164819057 +0800
+++ filezilla/src/interface/verifycertdialog.h 2016-05-26 13:14:03.897443962 +0800
@@ -28,6 +28,7 @@ private:
 
bool DisplayCert(wxDialogEx* pDlg, const CCertificate& cert);
 
+ wxString GetCNValue(const wxString& dn);
void ParseDN(wxWindow* parent, const wxString& dn, wxSizer* pSizer);
void ParseDN_by_prefix(wxWindow* parent, std::list<wxString>& tokens, wxString prefix, const wxString& name, wxSizer* pSizer, bool decode = false);
 
@@ -50,6 +51,7 @@ private:
wxSizer* m_pSubjectSizer{};
wxSizer* m_pIssuerSizer{};
int line_height_{};
+ unsigned int m_curSelect;
 
void OnCertificateChoice(wxCommandEvent& event);
};

patch 可以由這兒抓: http://www.teatime.com.tw/~tommy/mypatch/filezilla_3.18.0_trust_cert.patch

這個 patch 不久前送給作者, 不過被否決了. 所以.... 有需要就自己處理吧, 或到 FileZillaPV 去抓我做好的執行檔.

Del.icio.us Furl HEMiDEMi Technorati MyShare
迴響
暱稱:
標題:
個人網頁:
電子郵件:
authimage

迴響

  

Bad Behavior 已經阻擋了 90 個過去 7 天試圖闖關的垃圾迴響與引用。
Power by LifeType. Template design by JamesHuang. Valid XHTML and CSS