From 81b70db66d844e6c9fe366bbabf35e29c92a74a7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E8=AB=8F=E8=A8=AA=E5=AD=90?= Date: Mon, 30 Sep 2024 18:02:32 +0900 Subject: [PATCH] =?utf8?q?=E8=A4=87=E6=95=B0=E3=82=B5=E3=82=A4=E3=83=88?= =?utf8?q?=E3=81=A7=E5=90=8C=E3=81=98=E3=83=91=E3=82=B9=E3=83=AF=E3=83=BC?= =?utf8?q?=E3=83=89=E3=82=92=E5=88=A9=E7=94=A8=E3=81=8B=E3=81=A9=E3=81=86?= =?utf8?q?=E3=81=8B=E3=80=81=E3=83=91=E3=82=B9=E3=83=AF=E3=83=BC=E3=83=89?= =?utf8?q?=E3=81=AE=E9=95=B7=E3=81=95=E3=80=81=E5=8F=88=E3=81=AF=E3=83=91?= =?utf8?q?=E3=82=B9=E3=83=AF=E3=83=BC=E3=83=89=E3=81=AE=E5=BC=B7=E3=81=95?= =?utf8?q?=E3=81=AE=E7=A2=BA=E8=AA=8D=20#3?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + main.c | 12 +++- man/sp-en.1 | 13 +++- man/sp-jp.1 | 13 +++- src/chkpass.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/chkpass.h | 18 +++++ 6 files changed, 237 insertions(+), 5 deletions(-) create mode 100644 src/chkpass.c create mode 100644 src/chkpass.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b8702e..1a9674a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # 1.5.0 * パスワード表示で、「OpenPGP」かどうかの確認の追加 * 侵害されたパスワードの確認の追加 +* 複数サイトで同じパスワードを利用かどうか、パスワードの長さ、又はパスワードの強さの確認 # 1.4.0 * Haiku対応 diff --git a/main.c b/main.c index 0c5aebb..1e58568 100644 --- a/main.c +++ b/main.c @@ -9,12 +9,13 @@ #include "src/otppass.h" #include "src/findpass.h" #include "src/vulnpass.h" +#include "src/chkpass.h" #include const char *sofname = "sp"; const char *version = "1.5.0"; -const char *avalopt = "abdefgilosvy"; +const char *avalopt = "abcdefgilosvy"; const char *madefor = "simpas 1.1.0"; void usage() { @@ -119,6 +120,11 @@ int main(int argc, char *argv[]) { if (fullPath == NULL) return -1; findpass(fullPath, argv[2]); free(fullPath); + } else if (strcmp(argv[1], "-c") == 0) { + char *fullPath = getfullpath(NULL); + if (fullPath == NULL) return -1; + chkpass(fullPath, argv[2]); + free(fullPath); } else { usage(); return 1; @@ -138,8 +144,8 @@ int main(int argc, char *argv[]) { } free(basePath); } else { - usage(); - return 1; + usage(); + return 1; } return 0; diff --git a/man/sp-en.1 b/man/sp-en.1 index 6bd988c..ee57b60 100644 --- a/man/sp-en.1 +++ b/man/sp-en.1 @@ -3,7 +3,7 @@ sp - Simple Password Manager .br .B sp -[-i] [-i \fI\,gpg-id\fR] [-adeosy \fI\,password\fR] [-g \fI\,length\fR [\fI\,secure\fR|\fI\,risk\fR]] +[-bfi] [-i \fI\,gpg-id\fR] [-adeosy \fI\,password\fR] [-c \fI,all\fR|\fI,length\fR|\fI,strength\fR|\fI,duplicate\fR] [-g [\fI\,length\fR] [\fI\,secure\fR|\fI\,risk\fR]] .SH DESCRIPTION .PP Simple Password Manager @@ -11,6 +11,17 @@ Simple Password Manager \fB\,a\fR \fI\,password\fR Add password .TP +\fB\,b\fR +Check for breached passwords (internet connection is required) +.TP +\fB\,c\fR \fI,all|length|strength|duplicate\fR +Check for password length, strength, or duplicates. +.br +length = Check for password length +strength = Check for password strength +duplicate = Check for duplicate passwords +all = Check all of the above +.TP \fB\,d\fR \fI\,password\fR Delete password .TP diff --git a/man/sp-jp.1 b/man/sp-jp.1 index 879d505..79e0319 100644 --- a/man/sp-jp.1 +++ b/man/sp-jp.1 @@ -3,7 +3,7 @@ sp - Simple Password Manager .br .B sp -[-i] [-i \fI\,gpg-id\fR] [-adeosy \fI\,password\fR] [-g \fI\,length\fR [\fI\,secure\fR|\fI\,risk\fR]] +[-bfi] [-i \fI\,gpg-id\fR] [-adeosy \fI\,password\fR] [-c \fI,all\fR|\fI,length\fR|\fI,strength\fR|\fI,duplicate\fR] [-g [\fI\,length\fR] [\fI\,secure\fR|\fI\,risk\fR]] .SH 説明 .PP シンプルなパスワードマネージャー。 @@ -11,6 +11,17 @@ sp - Simple Password Manager \fB\,a\fR \fI\,password\fR パスワードを追加 .TP +\fB\,b\fR +漏洩されたパスワードを確認(インターネット接続が必須) +.TP +\fB\,c\fR \fI,all|length|strength|duplicate\fR +パスワードの長さ、強さ、や服数度を確認 +.br +length=パスワードの長さの確認 +strength=パスワードの強さの確認 +duplicate=服数パスワードが同じかどうか確認 +all=上記の全部の確認 +.TP \fB\,d\fR \fI\,password\fR パスワードを削除 .TP diff --git a/src/chkpass.c b/src/chkpass.c new file mode 100644 index 0000000..9568575 --- /dev/null +++ b/src/chkpass.c @@ -0,0 +1,185 @@ +#include +#include +#include +#include +#include +#include + +#include "chkpass.h" +#include "showpass.h" +#include "common.h" + +List chkFullpaths; +List chkDispaths; +List dupPasswd; +List dupPath; + +int vulncount = 0; +int weaklencount = 0; +int weakcharcount = 0; +int duppasscount = 0; + +size_t minimumlen = 12; +size_t recommendlen = 64; + +const char *spchar = "!@#$%^&*()-_=+[]{}|;:'\",.<>?/\\`~"; + +void chkLenPass(const char *path, const char *pass, char *lang) { + if (strlen(pass) > 0 && strlen(pass) < minimumlen) { + printf("【E】"); + if (strncmp(lang, "en", 2) == 0) { + printf("The password \"%s\" is too short, minimum length should be " + "%ld characters, recommended is %ld characters.\n", + path, minimumlen, recommendlen); + } else { + printf("パスワード「%s」は短すぎます。最短パスワードの長さは%ld文字ですが、" + "勧めが%ld文字です。\n", + path, minimumlen, recommendlen); + } + + weaklencount++; + vulncount++; + } else if (strlen(pass) >= minimumlen && strlen(pass) < recommendlen) { + printf("【W】"); + if (strncmp(lang, "en", 2) == 0) { + printf("The password \"%s\" is long enough, but for optimal security," + "%ld characters is recommended.\n", + path, recommendlen); + } else { + printf("パスワード「%s」の長さは十分ですが、最強のセキュリティには%ld文字が" + "勧めします。\n", + path, recommendlen); + } + } +} + +void chkCharPass(const char *path, const char *pass, char *lang) { + int isUpper = 0; + int isLower = 0; + int isDigit = 0; + int isSpecial = 0; + + for (size_t j = 0; j < strlen(pass); j++) { + if (isupper(pass[j])) isUpper = 1; + else if (islower(pass[j])) isLower = 1; + else if (isdigit(pass[j])) isDigit = 1; + else if (strchr(spchar, pass[j])) isSpecial = 1; + } + + if (isUpper == 0 || isLower == 0 || isDigit == 0 || isSpecial == 0) { + printf("【E】"); + if (strncmp(lang, "en", 2) == 0) { + printf("The password \"%s\" is too weak! A strong password contains at least " + "1 uppercase, 1 lowercase, 1 digit, and 1 special character.\n", + path); + } else { + printf("パスワード「%s」は弱すぎます!強いパスワードは最大1大文字、1小文字、" + "1数字、及び1特別な文字が含みます。\n", + path); + } + + weakcharcount++; + vulncount++; + } +} + +void chkDupPass(const char *path, const char *pass, char *lang) { + for (size_t k = 0; k < dupPasswd.size; k++) { + if (strncmp(getElement(&dupPasswd, k), pass, strlen(pass)) == 0) { + printf("【E】"); + if (strncmp(lang, "en", 2) == 0) { + printf("The password \"%s\" is the same as \"%s\". " + "For security, please keep passwords unique!\n", + path, getElement(&dupPath, k)); + } else { + printf("パスワード「%s」は「%s」と一致しています。" + "セキュリティの為、各パスワードはユニークにする様にして下さい!\n", + path, getElement(&dupPath, k)); + } + + duppasscount++; + vulncount++; + } + } + + addElement(&dupPath, path); + addElement(&dupPasswd, pass); +} + +void chkpass(const char *dpath, const char *mode) { + char *lang = getlang(); + + if (strncmp(mode, "all", 3) != 0 && strncmp(mode, "length", 6) != 0 && + strncmp(mode, "strength", 8) != 0 && strncmp(mode, "duplicate", 9) != 0) { + if (strncmp(lang, "en", 2) == 0) + printf("Invalid mode. Possible modes: all, length, strength, duplicate\n"); + else + printf("不正なモード。可能なモード: all(全部)、length(長さ)、" + "strength(強さ)、duplicate(同じパスワードの確認)\n"); + return; + } + + // パスワードをスキャンして + List fpaths; + initList(&fpaths); + initList(&chkFullpaths); + initList(&chkDispaths); + initList(&dupPasswd); + initList(&dupPath); + scanDir(dpath, dpath, &fpaths, &chkFullpaths, &chkDispaths); + + puts(strncmp(lang, "en", 2) == 0 ? + "Checking, please wait for a while..." : "確認中。暫くお待ち下さい・・・"); + + for (size_t i = 0; i < chkDispaths.size; i++) { + const char *pass = showpass(getElement(&chkDispaths, i)); + if (!pass) continue; + if (strstr(pass, "otpauth://totp/")) continue; + + if (strncmp(mode, "all", 3) == 0) { + // 全部を確認する + chkLenPass(getElement(&chkDispaths, i), pass, lang); + chkCharPass(getElement(&chkDispaths, i), pass, lang); + chkDupPass(getElement(&chkDispaths, i), pass, lang); + } else if (strncmp(mode, "length", 6) == 0) { + // 長さの確認 + chkLenPass(getElement(&chkDispaths, i), pass, lang); + } else if (strncmp(mode, "strength", 8) == 0) { + // 強さの確認 + chkCharPass(getElement(&chkDispaths, i), pass, lang); + } else if (strncmp(mode, "duplicate", 9) == 0) { + // 複数回同じパスワードの確認 + chkDupPass(getElement(&chkDispaths, i), pass, lang); + } else { + } + } + + if (strncmp(lang, "en", 2) == 0) { + if (strncmp(mode, "all", 3) == 0 || strncmp(mode, "length", 6) == 0) + printf("\nShort password count: %d\n", weaklencount); + if (strncmp(mode, "all", 3) == 0 || strncmp(mode, "strength", 8) == 0) + printf("\nWeak password count: %d\n", weakcharcount); + if (strncmp(mode, "all", 3) == 0 || strncmp(mode, "duplicate", 9) == 0) + printf("\nDuplicate password count: %d\n", duppasscount); + + printf("\nTotal weak passwords: %d\n", vulncount); + if (vulncount > 0) + printf("It's advised to change any of the weak " + "passwords as soon as possible!\n"); + } else { + if (strncmp(mode, "all", 3) == 0 || strncmp(mode, "length", 6) == 0) + printf("\n短いパスワード数: %d\n", weaklencount); + if (strncmp(mode, "all", 3) == 0 || strncmp(mode, "strength", 8) == 0) + printf("\n弱いパスワード数: %d\n", weakcharcount); + if (strncmp(mode, "all", 3) == 0 || strncmp(mode, "duplicate", 9) == 0) + printf("\n同じパスワード数: %d\n", duppasscount); + + printf("\n不安のパスワードの合計: %d\n", vulncount); + if (vulncount > 0) + printf("不安的なパスワードは出来るだけ早く変更する事をお勧めします!\n"); + } + + freeList(&fpaths); + freeList(&dupPath); + freeList(&dupPasswd); +} diff --git a/src/chkpass.h b/src/chkpass.h new file mode 100644 index 0000000..06ba74a --- /dev/null +++ b/src/chkpass.h @@ -0,0 +1,18 @@ +#ifndef CHKPASS_H +#define CHKPASS_H + +#include + +void chkpass(const char *dpath, const char *mode); + +extern int vulncount; +extern int weaklencount; +extern int weakcharcount; +extern int duppasscount; + +extern size_t minimumlen; +extern size_t recommendlen; + +extern const char *spchar; + +#endif -- 2.43.0