]> Nishi Git Mirror - sp.git/commitdiff
メモリリークの修正+侵害されたパスワードの確認 #4
author諏訪子 <suwako@076.moe>
Sun, 29 Sep 2024 09:42:34 +0000 (18:42 +0900)
committer諏訪子 <suwako@076.moe>
Sun, 29 Sep 2024 09:43:51 +0000 (18:43 +0900)
CHANGELOG.md
main.c
src/common.c
src/common.h
src/findpass.c
src/findpass.h
src/showpass.c
src/vulnpass.c [new file with mode: 0644]
src/vulnpass.h [new file with mode: 0644]

index bcc465c85095570ff0282214d696b04074a0d843..94c512463fa581447b596879d6f1903f266fa71c 100644 (file)
@@ -1,3 +1,6 @@
+# 1.5.0
+* 侵害されたパスワードの確認の追加
+
 # 1.4.0
 * Haiku対応
 * macOS対応
diff --git a/main.c b/main.c
index 1c568eed80cb2e4d1d71d54461ad0e8a727c5c7a..0c5aebb2a5e1c863764b41da53c2abb62466905f 100644 (file)
--- a/main.c
+++ b/main.c
@@ -8,13 +8,14 @@
 #include "src/genpass.h"
 #include "src/otppass.h"
 #include "src/findpass.h"
+#include "src/vulnpass.h"
 
 #include <unistd.h>
 
 const char *sofname = "sp";
-const char *version = "1.4.0";
-const char *avalopt = "adefgilosvy";
-const char *madefor = "simpas 1.0.0";
+const char *version = "1.5.0";
+const char *avalopt = "abdefgilosvy";
+const char *madefor = "simpas 1.1.0";
 
 void usage() {
   printf("%s-%s (%s)\nusage: %s [-%s]\n",
@@ -127,10 +128,10 @@ int main(int argc, char *argv[]) {
     if (basePath == NULL) return -1;
 
     if      (strcmp(argv[1], "-l") == 0) listpass(basePath, 0);
+    else if (strcmp(argv[1], "-b") == 0) vulnpass(basePath);
     else if (strcmp(argv[1], "-v") == 0) {
       printf("%s-%s (%s)\n", sofname, version, madefor);
-    }
-    else {
+    } else {
       usage();
       free(basePath);
       return 1;
index 928e4f7eb19f60b2f2deccb348ad3147caa01e0b..58c975e6600d611fa643586a0c0047dd89a4f2e8 100644 (file)
@@ -1,6 +1,11 @@
 #include "common.h"
+
 #include <stdio.h>
 #include <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#define MAXFINDLEN 1024
 
 char *getbasedir(int trailing) {
   char *lang = getlang();
@@ -103,6 +108,73 @@ int tmpcopy(const char *inpath, const char *outpath) {
   return 0;
 }
 
+#if defined(__linux__)
+char *strcasestr(const char *haystack, const char *needle) {
+  size_t needle_len = strlen(needle);
+  if (needle_len == 0) {
+    return (char *)haystack;
+  }
+
+  while (*haystack) {
+    if (strncasecmp(haystack, needle, needle_len) == 0) {
+      return (char *)haystack;
+    }
+    haystack++;
+  }
+  return NULL;
+}
+#endif
+
+void rmext(char *filename) {
+  char *ext = strrchr(filename, '.');
+  if (ext != NULL && strcmp(ext, ".gpg") == 0) {
+    *ext = '\0';
+  }
+}
+
+void scanDir(const char *dpath, const char *rpath, List *fpaths,
+    List *fullpaths, List *dispaths) {
+  char *lang = getlang();
+
+  DIR *dir = opendir(dpath);
+  if (!dir) {
+    if (strncmp(lang, "en", 2) == 0)
+      perror("Could not open directory");
+    else perror("ディレクトリを開けられません");
+    exit(EXIT_FAILURE);
+  }
+
+  struct dirent *entry;
+  while ((entry = readdir(dir)) != NULL) {
+    const char *name = entry->d_name;
+    if (strncmp(name, ".", 1) == 0 || strncmp(name, "..", 2) == 0) continue;
+
+    char fpath[MAXFINDLEN];
+    snprintf(fpath, sizeof(fpath), "%s/%s", dpath, name);
+
+    struct stat s;
+    if (stat(fpath, &s) != 0) {
+      closedir(dir);
+      return;
+    }
+
+    if (S_ISDIR(s.st_mode)) {
+      scanDir(fpath, rpath, fpaths, fullpaths, dispaths);
+    } else if (strstr(name, ".gpg") != NULL) {
+      const char *rel = fpath + strlen(rpath) + 1;
+      addElement(fpaths, rel);
+      addElement(fullpaths, fpath);
+      char *disname = strdup(rel);
+      rmext(disname);
+      addElement(dispaths, disname);
+
+      free(disname);
+    }
+  }
+
+  closedir(dir);
+}
+
 void initList(List *list) {
   list->head = NULL;
   list->tail = NULL;
@@ -116,6 +188,10 @@ void addElement(List *list, const char *data) {
   }
 
   newNode->data = strdup(data);
+  if (!newNode->data) {
+    free(newNode);
+    return;
+  }
   newNode->next = NULL;
 
   if (list->tail) {
index 4b8650482f07df5184591733f2f532fe952c65a4..dead7fe8622ffdeededbf66d2cda2d020a5fe5a3 100644 (file)
@@ -25,6 +25,8 @@ char *getbasedir(int trailing);
 char *getlang();
 int mkdir_r(const char *path, mode_t mode);
 int tmpcopy(const char *inpath, const char *outpath);
+void scanDir(const char *dpath, const char *rpath, List *fpaths,
+    List *fullpaths, List *dispaths);
 
 // C言語のvector
 void initList(List *list);
index 69c56907cee8e7f8e05ad5bea353e6c5a37ba3ca..698f6c08cdb30def14ef3e440bae2fc4c4f6060d 100644 (file)
@@ -4,90 +4,20 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <dirent.h>
-#include <sys/stat.h>
 
-#define MAXFINDLEN 1024
-
-List fullpaths;
-List dispaths;
-
-#if defined(__linux__)
-char *strcasestr(const char *haystack, const char *needle) {
-  size_t needle_len = strlen(needle);
-  if (needle_len == 0) {
-    return (char *)haystack;
-  }
-
-  while (*haystack) {
-    if (strncasecmp(haystack, needle, needle_len) == 0) {
-      return (char *)haystack;
-    }
-    haystack++;
-  }
-  return NULL;
-}
-#endif
-
-void rmext(char *filename) {
-  char *ext = strrchr(filename, '.');
-  if (ext != NULL && strcmp(ext, ".gpg") == 0) {
-    *ext = '\0';
-  }
-}
-
-void scanDir(const char *dpath, const char *rpath, List *fpaths) {
-  char *lang = getlang();
-
-  DIR *dir = opendir(dpath);
-  if (!dir) {
-    if (strncmp(lang, "en", 2) == 0)
-      perror("Could not open directory");
-    else perror("ディレクトリを開けられません");
-    exit(EXIT_FAILURE);
-  }
-
-  struct dirent *entry;
-  while ((entry = readdir(dir)) != NULL) {
-    const char *name = entry->d_name;
-    if (strncmp(name, ".", 1) == 0 || strncmp(name, "..", 2) == 0) continue;
-
-    char fpath[MAXFINDLEN];
-    snprintf(fpath, sizeof(fpath), "%s/%s", dpath, name);
-
-    struct stat s;
-    if (stat(fpath, &s) != 0) {
-      closedir(dir);
-      return;
-    }
-
-    if (S_ISDIR(s.st_mode)) {
-      scanDir(fpath, rpath, fpaths);
-    } else if (strstr(name, ".gpg") != NULL) {
-      const char *rel = fpath + strlen(rpath) + 1;
-      addElement(fpaths, rel);
-      addElement(&fullpaths, fpath);
-      char *disname = strdup(rel);
-      rmext(disname);
-      addElement(&dispaths, disname);
-
-      free(disname);
-    }
-  }
-
-  closedir(dir);
-}
+List findFullpaths;
+List findDispaths;
 
 void findpass(const char *dpath, const char *txt) {
   List fpaths;
   initList(&fpaths);
-  initList(&fullpaths);
-  initList(&dispaths);
-  scanDir(dpath, dpath, &fpaths);
+  initList(&findFullpaths);
+  initList(&findDispaths);
+  scanDir(dpath, dpath, &fpaths, &findFullpaths, &findDispaths);
 
-  for (size_t i = 0; i < dispaths.size; i++) {
-    if (strcasestr(getElement(&dispaths, i), txt) != NULL) {
-      printf("%s\n", getElement(&dispaths, i));
+  for (size_t i = 0; i < findDispaths.size; i++) {
+    if (strcasestr(getElement(&findDispaths, i), txt) != NULL) {
+      printf("%s\n", getElement(&findDispaths, i));
     }
   }
 
index 7a34761906466ec1af34ef44ff1ebbe83abea2ee..338cc102d8d48d7b71c6335400adeb23b193bd9a 100644 (file)
@@ -3,7 +3,6 @@
 
 #include "common.h"
 
-void scanDir(const char *dpath, const char *rpath, List *fpaths);
 void findpass(const char *dpath, const char *txt);
 
 #endif
index 713d362bf84ad5f9426336b8a2b01bad3d8ff77d..e1b09c1a135c522d9a2b94981394b4b5d039b2b3 100644 (file)
@@ -23,6 +23,7 @@ const char *showpass(char *file) {
   gpgme_ctx_t ctx;
   gpgme_error_t err;
   gpgme_data_t in = NULL, out = NULL;
+  char *gpgpath = NULL;
   FILE *gpgfile;
 
   // GPGMEライブラリを設置
@@ -41,12 +42,19 @@ const char *showpass(char *file) {
 
   // OpenPGPプロトコールを設定
   gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP);
+  if (err) {
+    if (strncmp(lang, "en", 2) == 0)
+      fprintf(stderr, "Failed to set OpenPGP protocol: %s\n", gpgme_strerror(err));
+    else fprintf(stderr, "OpenPGP付トロコールの設置に失敗:%s\n", gpgme_strerror(err));
+    clean_up(ctx, in, out, gpgfile, gpgpath);
+    return NULL;
+  }
 
   // 暗号化したタイルを開く
   char *basedir = getbasedir(1);
   char *ext = ".gpg";
   int alllen = snprintf(NULL, 0, "%s%s%s", basedir, file, ext) + 1;
-  char *gpgpath = malloc(alllen);
+  gpgpath = malloc(alllen);
   if (gpgpath == NULL) {
     if (strncmp(lang, "en", 2) == 0)
       perror("Failed to allocate memeory");
@@ -92,8 +100,10 @@ const char *showpass(char *file) {
   err = gpgme_op_decrypt(ctx, in, out);
   if (err) {
     if (strncmp(lang, "en", 2) == 0)
-      fprintf(stderr, "Failed to decrypt: %s\n", gpgme_strerror(err));
-    else fprintf(stderr, "復号化に失敗: %s\n", gpgme_strerror(err));
+      fprintf(stderr, "Failed to decrypt: %s (source: %s)\n",
+          gpgme_strerror(err), gpgme_strsource(err));
+    else fprintf(stderr, "復号化に失敗: %s (元: %s)\n",
+          gpgme_strerror(err), gpgme_strsource(err));
 
     // 掃除
     clean_up(ctx, in, out, gpgfile, gpgpath);
@@ -102,8 +112,10 @@ const char *showpass(char *file) {
 
   // 復号化したパスワードを表示する
   gpgme_data_seek(out, 0, SEEK_SET);
+  size_t bufsize = 512;
+  size_t totsize = 0;
   char buffer[512];
-  char *res = malloc(512 * sizeof(char));
+  char *res = malloc(bufsize);
   if (res == NULL) {
     if (strncmp(lang, "en", 2) == 0)
       perror("Failed to allocate memory");
@@ -113,15 +125,22 @@ const char *showpass(char *file) {
   }
 
   ssize_t read_bytes;
-  int i = 0;
 
   while ((read_bytes = gpgme_data_read(out, buffer, sizeof(buffer) - 1)) > 0) {
-    memcpy(res + i, buffer, read_bytes);
-    i += read_bytes;
+    if (totsize + read_bytes >= bufsize) {
+      bufsize *= 2;
+      res = realloc(res, bufsize);
+      if (res == NULL) {
+        perror("Failed to reallocate memory");
+        clean_up(ctx, in, out, gpgfile, gpgpath);
+        return NULL;
+      }
+    }
+    memcpy(res + totsize, buffer, read_bytes);
+    totsize += read_bytes;
   }
 
-  res[i] = '\0';
-  if (res[i-1] == '\n') res[i-1] = '\0';
+  res[totsize] = '\0';
 
   // 掃除
   clean_up(ctx, in, out, gpgfile, gpgpath);
diff --git a/src/vulnpass.c b/src/vulnpass.c
new file mode 100644 (file)
index 0000000..0478092
--- /dev/null
@@ -0,0 +1,141 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <dirent.h>
+
+#include "vulnpass.h"
+#include "showpass.h"
+#include "common.h"
+
+List vulnFullpaths;
+List vulnDispaths;
+
+void vulnpass(const char *dpath) {
+  char *lang = getlang();
+
+  // pwndサーバに接続
+  int sock;
+  struct sockaddr_in srv;
+  struct addrinfo hints, *addr;
+
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_INET;
+  hints.ai_socktype = SOCK_STREAM;
+
+  int status = getaddrinfo("076.moe", NULL, &hints, &addr);
+  if (status != 0) {
+    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
+    return;
+  }
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  if (sock == -1) {
+    const char *ero = strncmp(lang, "en", 2) == 0 ?
+      "Failed to create socket" : "ソケットを作成に失敗";
+    perror(ero);
+    return;
+  }
+
+  srv.sin_addr = ((struct sockaddr_in *)(addr->ai_addr))->sin_addr;
+  srv.sin_family = AF_INET;
+  srv.sin_port = htons(9951);
+
+  freeaddrinfo(addr);
+
+  if (connect(sock, (struct sockaddr *)&srv, sizeof(srv)) < 0) {
+    const char *ero = strncmp(lang, "en", 2) == 0 ? "Failed to connect" : "接続に失敗";
+    perror(ero);
+    close(sock);
+    return;
+  }
+
+  // パスワードをスキャンして
+  List fpaths;
+  initList(&fpaths);
+  initList(&vulnFullpaths);
+  initList(&vulnDispaths);
+  scanDir(dpath, dpath, &fpaths, &vulnFullpaths, &vulnDispaths);
+  int vulncount = 0;
+
+  puts(strncmp(lang, "en", 2) == 0 ?
+      "Checking, please wait for a while..." : "確認中。暫くお待ち下さい・・・");
+
+  for (size_t i = 0; i < vulnDispaths.size; i++) {
+    const char *pass = showpass(getElement(&vulnDispaths, i));
+    if (!pass) continue;
+    char res[256];
+    int reslen = 0;
+
+    if (send(sock, pass, strlen(pass), 0) < 0) {
+      const char *ero = strncmp(lang, "en", 2) == 0 ?
+        "Failed to send" : "送信に失敗";
+      perror(ero);
+      close(sock);
+      freeList(&fpaths);
+      return;
+    }
+
+    reslen = recv(sock, res, sizeof(res) -1, 0);
+    if (reslen < 0) {
+      const char *ero = strncmp(lang, "en", 2) == 0 ?
+        "Failed to retreive" : "受取に失敗";
+      perror(ero);
+      close(sock);
+      freeList(&fpaths);
+      return;
+    }
+
+    res[reslen] = '\0';
+
+    if (strncmp(res, "0", 1) != 0) {
+      printf("【!】");
+      if (strncmp(lang, "en", 2) == 0) {
+        printf("The password \"%s\" has been breached %d times.\n",
+            getElement(&vulnDispaths, i), atoi(res));
+      } else {
+        printf("パスワード「%s」は%d回に漏洩されました。\n",
+            getElement(&vulnDispaths, i), atoi(res));
+      }
+
+      vulncount++;
+    }
+
+    close(sock);
+
+    // 再接続
+    sock = socket(AF_INET, SOCK_STREAM, 0);
+    if (sock == -1) {
+      const char *ero = strncmp(lang, "en", 2) == 0 ?
+        "Failed to create socket" : "ソケットを作成に失敗";
+      perror(ero);
+      return;
+    }
+
+    if (connect(sock, (struct sockaddr *)&srv, sizeof(srv)) < 0) {
+      const char *ero = strncmp(lang, "en", 2) == 0 ?
+        "Failed to reconnect" : "再接続に失敗";
+      perror(ero);
+      close(sock);
+      return;
+    }
+  }
+
+  if (strncmp(lang, "en", 2) == 0) {
+    printf("\nTotal breached: %d\n", vulncount);
+    if (vulncount > 0)
+      printf("It's advised to change any of the breached "
+             "passwords as soon as possible!\n");
+  } else {
+    printf("\n漏洩したパスワードの合計: %d\n", vulncount);
+    if (vulncount > 0)
+      printf("漏洩したパスワードは出来るだけ早く変更する事をお勧めします!\n");
+  }
+
+  freeList(&fpaths);
+}
diff --git a/src/vulnpass.h b/src/vulnpass.h
new file mode 100644 (file)
index 0000000..f87f2e6
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef VULNPASS_H
+#define VULNPASS_H
+
+void vulnpass(const char *dpath);
+
+#endif