If validation with the cygwin signing key fails for a purported private mirror, retry with other supplied keys. If this succeeds, silently change the status of the site to "user site" and put a note in the log file. This change will take effect on the next setup run or if the user selects 'Back'.
This uses a new optional argument 'retry_sig_ok' to ini.cc:check_ini_sig(). If this is 'true', don't destroy ini_file and ini_sig_file on a validation failure. --- ini.cc | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- site.h | 2 ++ 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/ini.cc b/ini.cc index 4be8263..62b7e83 100644 --- a/ini.cc +++ b/ini.cc @@ -18,6 +18,8 @@ flex parsers are provided also. We check to see if this setup.ini is older than the one we used last time, and if so, warn the user. */ +#include <algorithm> + #include "ini.h" #include "csu_util/rfc1738.h" @@ -173,7 +175,7 @@ decompress_ini (io_stream *ini_file) static io_stream* check_ini_sig (io_stream* ini_file, io_stream* ini_sig_file, bool& sig_fail, const char* site, const char* sig_name, - HWND owner, bool main_key_only = false) + HWND owner, bool main_key_only = false, bool retry_sig_ok = false) { /* Unless the NoVerifyOption is set, check the signature for the current setup and record the result. On a failed signature check @@ -195,12 +197,15 @@ check_ini_sig (io_stream* ini_file, io_stream* ini_sig_file, } else if (!verify_ini_file_sig (ini_file, ini_sig_file, owner, main_key_only)) { - note (owner, IDS_SIG_INVALID, sig_name, site); - delete ini_sig_file; - ini_sig_file = NULL; - delete ini_file; - ini_file = NULL; sig_fail = true; + if (!retry_sig_ok) + { + note (owner, IDS_SIG_INVALID, sig_name, site); + delete ini_sig_file; + ini_sig_file = NULL; + delete ini_file; + ini_file = NULL; + } } } return ini_file; @@ -265,6 +270,27 @@ do_local_ini (HWND owner) return ini_error; } +static void +mirror_warn (site_list_type site) +{ + Log (LOG_BABBLE) << "Signature validation failed for " << site.url + << " using the cygwin key but succeeded using other keys. " + << endLog; + Log (LOG_BABBLE) << "Changing status from 'mirror' to 'user site'." << endLog; + SiteList::iterator i = find (all_site_list.begin (), all_site_list.end (), site); + if (i != all_site_list.end ()) + { + all_site_list.erase (i); + site_list_type newsite (site.url, "", "", "", false, false); + all_site_list.push_back (newsite); + selected_usersite_list.push_back (newsite); + SiteList::iterator j = find (selected_mirror_list.begin (), + selected_mirror_list.end (), site); + if (j != selected_mirror_list.end ()) + selected_mirror_list.erase (j); + } +} + static bool do_remote_ini (HWND owner) { @@ -293,14 +319,33 @@ do_remote_ini (HWND owner) ini_sig_file = get_url_to_membuf (current_ini_sig_name, owner); ini_file = get_url_to_membuf (current_ini_name, owner); - // Official mirrors must be signed by the cygwin key. - bool main_key_only = n->from_mirrors_lst; + // Mirrors should be signed by the cygwin key. + bool main_key_only = n->is_mirror; + + // If this fails for a purported private mirror, allow a + // retry with additional keys; if this succeeds, reclassify + // the site as a user site. + bool retry_sig_ok = n->is_mirror && !n->from_mirrors_lst; + retry: ini_file = check_ini_sig (ini_file, ini_sig_file, sig_fail, - n->url.c_str (), current_ini_sig_name.c_str (), owner, main_key_only); + n->url.c_str (), + current_ini_sig_name.c_str (), owner, + main_key_only, retry_sig_ok); + if (retry_sig_ok && sig_fail) + { + sig_fail = false; + retry_sig_ok = false; + main_key_only = false; + goto retry; + } // stop searching as soon as we find a setup file if (ini_file) - break; + { + if (n->is_mirror && !main_key_only) + mirror_warn (*n); + break; + } } if (ini_file) ini_file = decompress_ini (ini_file); diff --git a/site.h b/site.h index 3525931..5b01829 100644 --- a/site.h +++ b/site.h @@ -79,6 +79,8 @@ typedef std::vector <site_list_type> SiteList; /* user chosen sites */ extern SiteList site_list; +extern SiteList selected_mirror_list; +extern SiteList selected_usersite_list; /* potential sites */ extern SiteList all_site_list; -- 2.15.1