]> Nishi Git Mirror - sp.git/commitdiff
複数サイトで同じパスワードを利用かどうか、パスワードの長さ、又はパスワードの強さの確認 #3
author諏訪子 <suwako@076.moe>
Mon, 30 Sep 2024 09:02:32 +0000 (18:02 +0900)
committer諏訪子 <suwako@076.moe>
Mon, 30 Sep 2024 09:02:32 +0000 (18:02 +0900)
CHANGELOG.md
main.c
man/sp-en.1
man/sp-jp.1
src/chkpass.c [new file with mode: 0644]
src/chkpass.h [new file with mode: 0644]

index 4b8702ee03ba15e4b39a19387a3c72e27bcb8be0..1a9674a61d15e59c4b138f7072bd52c1e947e2c6 100644 (file)
@@ -1,6 +1,7 @@
 # 1.5.0
 * パスワード表示で、「OpenPGP」かどうかの確認の追加
 * 侵害されたパスワードの確認の追加
+* 複数サイトで同じパスワードを利用かどうか、パスワードの長さ、又はパスワードの強さの確認
 
 # 1.4.0
 * Haiku対応
diff --git a/main.c b/main.c
index 0c5aebb2a5e1c863764b41da53c2abb62466905f..1e585682e0e2586496cf4378ffd6e14c964766f8 100644 (file)
--- 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 <unistd.h>
 
 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;
index 6bd988cb0997921edf79145d7725826ae569ceb8..ee57b60931caaba3da0fdf9a309ad4c182c3797e 100644 (file)
@@ -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
index 879d5055640f19124f995c87e95fdcd7ca1163eb..79e03192d2d7c1c6caeceae3a84ef9dfcd2376e8 100644 (file)
@@ -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 (file)
index 0000000..9568575
--- /dev/null
@@ -0,0 +1,185 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+#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 (file)
index 0000000..06ba74a
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef CHKPASS_H
+#define CHKPASS_H
+
+#include <stdlib.h>
+
+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