レポジトリ種類: Mercurial
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/fl_ask.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Text_Display.H>
#include <FL/Fl_Text_Buffer.H>
#include <FL/Fl_Scrollbar.H>
#include <string>
#include <thread>
#include <algorithm>
#include "common.hh"
#include "chkpass.hh"
#include "../main.hh"
#include "showpass.hh"
Chkpass chk;
std::vector<std::string> foundRes;
std::vector<std::string> duppath;
std::vector<std::string> 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<unsigned char>(ch))) isUpper = true;
if (std::islower(static_cast<unsigned char>(ch))) isLower = true;
if (std::isdigit(static_cast<unsigned char>(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() {
// パスワードをスキャンして
Showpass show;
for (const auto &dispath : Common::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 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<Fl_Window*>(win)->hide();
}, win);
win->add(okBtn);
win->end();
win->show();
}
void Chkpass::chk_cb(Fl_Widget *, void *data) {
InputData *inputs = (InputData *)data;
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;
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);
}