#include "common.hh" #include "chkpass.hh" #include "../main.hh" #include "showpass.hh" #include #include #include #include #include #include #include #include #include #include #include Chkpass chk; std::vector foundRes; std::vector duppath; std::vector duppasswd; struct InputData { Fl_Radio_Button *all; Fl_Radio_Button *len; Fl_Radio_Button *chr; Fl_Radio_Button *dup; Fl_Window *dialog; }; void Chkpass::lenPass(const std::string &path, const std::string &pass, const std::string &lang) { if (pass.length() > 0 && pass.length() < minimumlen) { std::string res = "【E】"; res += (lang.compare(0, 2, "en") == 0 ? "The password \"" + path + "\" is too short, minimum length should be " + std::to_string(minimumlen) + " characters, recommended is " + std::to_string(recommendlen) + " characters.": "パスワード「" + path + "」は短すぎます。最短パスワードの長さは" + std::to_string(minimumlen) + "文字ですが、勧めが" + std::to_string(recommendlen) + "文字です。"); foundRes.push_back(res); weaklencount++; vulncount++; } else if (pass.length() >= minimumlen && pass.length() < recommendlen) { std::string res = "【W】"; res += (lang.compare(0, 2, "en") == 0 ? "The password \"" + path + "\" is long enough, but for optimal security, " + std::to_string(recommendlen) + " characters is recommended.\n" : "パスワード「" + path + "」の長さは十分ですが、最強のセキュリティには" + std::to_string(recommendlen) + "文字が勧めします。\n"); foundRes.push_back(res); } } void Chkpass::charPass(const std::string &path, const std::string &pass, const std::string &lang) { bool isUpper = false; bool isLower = false; bool isDigit = false; bool isSpecial = false; for (char ch : pass) { if (std::isupper(static_cast(ch))) isUpper = true; if (std::islower(static_cast(ch))) isLower = true; if (std::isdigit(static_cast(ch))) isDigit = true; if (std::find(spchar.begin(), spchar.end(), ch) != spchar.end()) isSpecial = true; } if (!isUpper || !isLower || !isDigit || !isSpecial) { std::string res = "【E】"; res += (lang.compare(0, 2, "en") == 0 ? "The password \"" + path + "\" is too weak! A strong password contains " + "at least 1 uppercase, 1 lowercase, 1 digit, and 1 special character." : "パスワード「" + path + "」は弱すぎます!強いパスワードは最大1大文字、" + "1小文字、1数字、及び1記号の文字が含みます。"); foundRes.push_back(res); weakcharcount++; vulncount++; } } void Chkpass::dupPass(const std::string &path, const std::string &pass, const std::string &lang) { for (std::size_t k = 0; k < duppasswd.size(); k++) { if (pass.compare(duppasswd[k]) == 0) { std::string res = "【E】"; res += (lang.compare(0, 2, "en") == 0 ? "The password \"" + path + "\" is the same as \"" + duppath[k] + "\". " + "For security, please keep passwords unique!": "パスワード「" + path + "」は「" + duppath[k] + "」と一致しています。" + "セキュリティの為、各パスワードはユニークにする様にして下さい!"); foundRes.push_back(res); duppasscount++; vulncount++; } } duppath.push_back(path); duppasswd.push_back(pass); } bool Chkpass::exec() { std::string lang = Common::getlang(); // パスワードをスキャンして Showpass show; for (const auto &dispath : dispaths) { std::string fullpath = Common::getbasedir(true) + dispath + ".gpg"; std::string pass = show.exec(fullpath.c_str(), true); if (pass.empty()) continue; if (pass.rfind("otpauth://totp/", 0) == 0) continue; if (isAll) { lenPass(dispath, pass, lang); charPass(dispath, pass, lang); dupPass(dispath, pass, lang); } else if (isLen) { lenPass(dispath, pass, lang); } else if (isChar) { charPass(dispath, pass, lang); } else if (isDup) { dupPass(dispath, pass, lang); } } return true; } void Chkpass::showRes() { std::string lang = Common::getlang(); std::string res; if (lang.compare(0, 2, "en") == 0) { res = "Weak passwords:\n"; } else { res = "不安定なパスワード:\n"; } for (const auto &path : foundRes) { res += path + "\n"; } if (lang.compare(0, 2, "en") == 0) { res += "Short password count: " + std::to_string(weaklencount) + "\n"; res += "Weak password count: " + std::to_string(weakcharcount) + "\n"; res += "Duplicate password count: " + std::to_string(duppasscount) + "\n"; res += "Total: " + std::to_string(duppath.size()) + "\n"; res += "It's advised to change any of the"; res += "weak passwords as soon as possible!"; } else { res += "短いパスワード数: " + std::to_string(weaklencount) + "\n"; res += "弱いパスワード数: " + std::to_string(weakcharcount) + "\n"; res += "同じパスワード数: " + std::to_string(duppasscount) + "\n"; res += "合計: " + std::to_string(duppath.size()) + "\n"; res += "不安定なパスワードは出来るだけ早く変更する事をお勧めします!"; } Fl_Window *win = new Fl_Window(500, 440, lang.compare(0, 2, "en") == 0 ? "Results" : "結果"); Fl_Text_Display *display = new Fl_Text_Display(10, 10, 480, 380); Fl_Text_Buffer *textbuf = new Fl_Text_Buffer(); textbuf->text(res.c_str()); display->buffer(textbuf); display->scrollbar_width(15); win->resizable(display); Fl_Button *okBtn = new Fl_Button(210, 400, 80, 30, "OK"); okBtn->callback([](Fl_Widget *widget, void *win) { (void)widget; reinterpret_cast(win)->hide(); }, win); win->add(okBtn); win->end(); win->show(); } void Chkpass::chk_cb(Fl_Widget *, void *data) { InputData *inputs = (InputData *)data; std::string lang = Common::getlang(); if (inputs) { isAll = inputs->all->value(); isLen = inputs->len->value(); isChar = inputs->chr->value(); isDup = inputs->dup->value(); } Fl_Window *dialog = new Fl_Window(400, 50, (lang.compare(0, 2, "en") == 0 ? "Checking for weak password" : "不安的なパスワードの確認中")); Fl_Box *box = new Fl_Box(10, 10, 380, 20, (lang.compare(0, 2, "en") == 0 ? "Checking, please wait for a while..." : "確認中。暫くお待ち下さい・・・")); dialog->add(box); dialog->end(); dialog->set_modal(); dialog->show(); std::thread checker([dialog]() { chk.exec(); Fl::lock(); dialog->hide(); chk.showRes(); Fl::unlock(); }); checker.detach(); } void Chkpass::dialog_cb(Fl_Widget *w, void *) { (void)w; std::string lang = Common::getlang(); Fl_Window *dialog = new Fl_Window(390, 145, (lang.compare(0, 2, "en") == 0 ? "Check for weak password" : "不安的なパスワードの確認")); Fl_Radio_Button *all = new Fl_Radio_Button(10, 10, 180, 30, (lang.compare(0, 2, "en") == 0) ? "Everything" : "全部"); Fl_Radio_Button *len = new Fl_Radio_Button(10, 50, 180, 30, (lang.compare(0, 2, "en") == 0) ? "Length" : "長さ"); Fl_Radio_Button *chr = new Fl_Radio_Button(200, 10, 180, 30, (lang.compare(0, 2, "en") == 0) ? "Strength" : "強さ"); Fl_Radio_Button *dup = new Fl_Radio_Button(200, 50, 180, 30, (lang.compare(0, 2, "en") == 0) ? "Duplicate" : "服数度"); dialog->add(all); dialog->add(len); dialog->add(chr); dialog->add(dup); InputData *inputs = new InputData(); inputs->all = all; inputs->len = len; inputs->chr = chr; inputs->dup = dup; inputs->dialog = dialog; Fl_Button *okbtn = new Fl_Button(105, 100, 80, 30, "OK"); Fl_Button *cancelbtn = new Fl_Button(205, 100, 80, 30, (lang.compare(0, 2, "en") == 0 ? "Cancel" : "キャンセル")); okbtn->callback(static_ok_cb, inputs); cancelbtn->callback(static_cancel_cb, dialog); dialog->add(okbtn); dialog->add(cancelbtn); dialog->end(); dialog->set_modal(); dialog->show(); } void Chkpass::static_ok_cb(Fl_Widget *w, void *data) { (void)w; InputData *inputs = (InputData *)data; chk.chk_cb(nullptr, inputs); } void Chkpass::static_cancel_cb(Fl_Widget *w, void *data) { ((Chkpass *)data)->cancel_cb(w, data); }