]> Nishi Git Mirror - sp.git/commitdiff
1.1.0
author諏訪子 <suwako@076.moe>
Thu, 30 Nov 2023 17:25:27 +0000 (02:25 +0900)
committer諏訪子 <suwako@076.moe>
Thu, 30 Nov 2023 17:25:27 +0000 (02:25 +0900)
CHANGELOG.md
Makefile
README.md
addpass.c
main.c
otppass.c [new file with mode: 0644]
otppass.h [new file with mode: 0644]
showpass.c
sp-completion.zsh [new file with mode: 0644]
yankpass.c

index 0a0d8705aa23a9e75bd730b79eb2d9d7923a281f..0274411b6697b86d6ba55bb9f1e882111e6af587 100644 (file)
@@ -1,2 +1,9 @@
+# 1.1.0
+* TOTP対応
+* READMEファイルで使い方を詳しく説明する
+* zshキャプチャー
+* パスワード追加関数を安定化
+* パスワード表示とパスワードのコピー関数で、GNU Passで保存したパスワードの場合は改行を追加しない様に
+
 # 1.0.0
 * 最初リリース
index 4c378f5d1ff4dd3bab07c8d9d177991b72ecff37..2a1c062b419e12f8574bf0c81ba8dcbe708b532f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,11 @@
 NAME=sp
-VERSION=1.0.0
+VERSION=1.1.0
 # Linux、Haiku、かIllumos = /usr、FreeBSDかOpenBSD = /usr/local、NetBSD = /usr/pkg
 PREFIX=/usr
 CC=cc
-FILES=main.c showpass.c yankpass.c addpass.c delpass.c listpass.c genpass.c initpass.c
+FILES=main.c showpass.c yankpass.c addpass.c delpass.c listpass.c genpass.c initpass.c otppass.c
 CFLAGS=-Wall -Wextra -g
-LDFLAGS=-lgpgme
+LDFLAGS=-lgpgme -lcrypto
 
 all:
        ${CC} ${CFLAGS} -o ${NAME} ${FILES} ${LDFLAGS}
@@ -25,6 +25,9 @@ install: all
        cp -f ${NAME} ${DESTDIR}${PREFIX}/bin
        chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}
 
+install-zsh:
+       cp sp-completion.zsh /usr/share/zsh/site-functions/_sp
+
 uninstall:
        rm -f ${DESTDIR}${PREFIX}/bin/${NAME}
 
index 82aa445f673585c6c9c0958a54c364c4386e0dd0..d7502a2df58336826ac146da16de6f9773367ea8 100644 (file)
--- a/README.md
+++ b/README.md
@@ -39,3 +39,63 @@ doas gmake install PREFIX=/usr/local
 
 ## 初期設定
 「gpg -k」でGPG鍵IDを確認して、「sp -i [GPG ID]」を実行して下さい。
+
+## 使い方
+### パスワードの作成
+#### 強いパスワードの場合
+```sh
+$ sp -g 64
+nSYGSF2lWGCUsqKCRB_~mZm+spaU<zvtt%um'01$tj4h,^nB6JqX#Cm$!U+s;c7:
+```
+又は
+```sh
+$ sp -g 64 secure
+nSYGSF2lWGCUsqKCRB_~mZm+spaU<zvtt%um'01$tj4h,^nB6JqX#Cm$!U+s;c7:
+```
+
+#### 弱いパスワードの場合
+```sh
+$ sp -g 12 risk
+2aKBwb858mzg
+```
+
+### パスワードの追加
+「suwako」というユーザー名の場合:
+```sh
+$ sp -a 076.moe/suwako
+パスワード: 
+パスワード(確認用): 
+パスワードを保存出来ました。
+```
+入力中は何も表示されないので、ご注意下さい。
+
+### パスワードの表示
+```sh
+$ sp -s 076.moe/suwako
+nSYGSF2lWGCUsqKCRB_~mZm+spaU<zvtt%um'01$tj4h,^nB6JqX#Cm$!U+s;c7:
+```
+表示せずコピーする場合は、「sp -y 076.moe/suwako」を使用して下さい。
+
+### パスワードの削除
+```sh
+$ sp -d 076.moe/suwako
+パスワード「076.moe/suwako」を本当に削除する事が宜しいでしょうか? (y/N): y
+パスワードを削除しました。
+```
+
+## TOTP(ワンタイムパスワード)
+### QRコードから
+QRコードをダウンロードし、zbarimgを使用して「QR-Code:」以降の部分をコピーし、spに追加して下さい。\
+`sp -a`を実行すると、「パスワード」を聞かれますが、TOTPの場合は「otpauth://」から始まる文字列をコピペして下さい。
+```sh
+$ zbarimg -q gitler.png
+QR-Code:otpauth://totp/Gitler%20%28gitler.moe%29:suwako?algorithm=SHA1&digits=6&issuer=Gitler%20%28gitler.moe%29&period=30&secret=〇〇
+
+$ sp -a gitler-otp
+パスワード: 
+パスワード(確認用): 
+パスワードを保存出来ました。
+
+$ sp -q gitler-otp
+123456
+```
index 2aed233d6b3ca6aa5e9aa2e8dec6ef016cca6d06..2a9a2e7146cab61eea7446b8521d52964cab534f 100644 (file)
--- a/addpass.c
+++ b/addpass.c
@@ -57,13 +57,20 @@ void getpasswd(char* prompt, char*pw, size_t pwlen) {
   tcsetattr(fileno(stdin), TCSANOW, &new);
 
   // パスワードを読み込む
-  fgets(pw, pwlen, stdin);
+  if (fgets(pw, pwlen, stdin) != NULL) {
+    // あれば、改行を取り消す
+    size_t len = strlen(pw);
+    if (len > 0 && pw[len - 1] == '\n') {
+      pw[len - 1] = '\0';
+    } else {
+      // 掃除
+      int c;
+      while ((c = getchar()) != '\n' && c != EOF);
+    }
+  }
 
   // 端末設定をもとに戻す
   tcsetattr(fileno(stdin), TCSANOW, &old);
-
-  // 改行文字を取り消す
-  pw[strcspn(pw, "\n")] = 0;
 }
 
 void addpass(char* file) {
@@ -233,8 +240,14 @@ void addpass(char* file) {
 
   char buffer[512];
   ssize_t read_bytes;
+
   while ((read_bytes = gpgme_data_read(out, buffer, sizeof(buffer))) > 0) {
-    fwrite(buffer, 1, read_bytes, gpgfile);
+    if (fwrite(buffer, 1, (size_t)read_bytes, gpgfile) != (size_t)read_bytes) {
+      perror("パスワードを書き込みに失敗");
+      free(gpgpath);
+      cleanup(ctx, key[0], in, out);
+      return;
+    }
   }
 
   // 掃除
diff --git a/main.c b/main.c
index 2dfb3ff2a5f87616abc019ab141df08d8e6abb0e..ad3e1c4f9e720c4c6c74ac6fb3da6fa7851c7e70 100644 (file)
--- a/main.c
+++ b/main.c
 #include "addpass.h"
 #include "delpass.h"
 #include "genpass.h"
-void otppass(char* file);
+#include "otppass.h"
 void helpme();
 
 const char* sofname = "sp";
-const char* version = "1.0.0";
+const char* version = "1.1.0";
 
 void helpme() {
   printf("076 sp - シンプルなパスワードマネージャー\n");
@@ -29,7 +29,7 @@ void helpme() {
   printf("%s -a <パスワード名>         :パスワードを追加\n", sofname);
   printf("%s -d <パスワード名>         :パスワードを削除\n", sofname);
   printf("%s -g <文字数> [risk|secure] :希望文字数でパスワードをランダムに作成する。risk=英数字のみ(不安)、secure=英数字+特別文字(デフォルト)を使用\n", sofname);
-  /* printf("%s -o <パスワード名>\n       :ワンタイムパスワード(TOTP)を表示。存在しなければ、創作する", sofname); */
+  printf("%s -o <パスワード名>\n       :ワンタイムパスワード(TOTP)を表示。存在しなければ、創作する\n", sofname);
   printf("%s -h                        :ヘルプを表示\n", sofname);
   printf("%s -v                        :バージョンを表示\n", sofname);
 }
@@ -64,7 +64,7 @@ int main (int argc, char* argv[]) {
     else if (argc == 4 && strcmp(argv[3], "secure") == 0) genpass(atoi(argv[2]), true);
     else helpme();
   }
-  else if (argc == 3 && strcmp(argv[1], "-o") == 0) printf("TODO: otp\n");
+  else if (argc == 3 && strcmp(argv[1], "-o") == 0) otppass(argv[2]);
   else if (argc == 2 && strcmp(argv[1], "-v") == 0) printf("%s-%s\n", sofname, version);
   else helpme();
 
diff --git a/otppass.c b/otppass.c
new file mode 100644 (file)
index 0000000..87c2b42
--- /dev/null
+++ b/otppass.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <openssl/hmac.h>
+
+unsigned long generate_totp(const unsigned char* secret, size_t keylen) {
+  unsigned long timestep = time(NULL) / 30;
+  unsigned char hmacres[20];
+
+  HMAC(EVP_sha1(), secret, keylen, (unsigned char*)&timestep, sizeof(timestep), hmacres, NULL);
+
+  int offset = hmacres[19] & 0xF;
+  unsigned long trunhash = (hmacres[offset] & 0x7F) << 24 |
+                           (hmacres[offset + 1] & 0xFF) << 16 |
+                           (hmacres[offset + 2] & 0xFF) << 8 |
+                           (hmacres[offset + 3] & 0xFF);
+  
+  unsigned long otp = trunhash % 1000000;
+  return otp;
+}
+
+void otppass(char* file) {
+  const char* secret = file;
+  unsigned long otp = generate_totp((unsigned char*)secret, strlen(secret));
+  printf("%06lu\n", otp);
+}
diff --git a/otppass.h b/otppass.h
new file mode 100644 (file)
index 0000000..b916b09
--- /dev/null
+++ b/otppass.h
@@ -0,0 +1,6 @@
+#ifndef OTPPASS_H
+#define OTPPASS_H
+
+void otppass(char* file);
+
+#endif
index 9cebc97058f93c5ed02c2b1a5e2b5422dad4cde0..76e00077b9fdbab488cbb970b45dbae258296df4 100644 (file)
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <locale.h>
 
 #include <gpgme.h>
@@ -83,9 +84,17 @@ void showpass(char* file) {
   gpgme_data_seek(out, 0, SEEK_SET);
   char buffer[512];
   ssize_t read_bytes;
+  bool islastnl = false;
+
   while ((read_bytes = gpgme_data_read(out, buffer, sizeof(buffer) - 1)) > 0) {
-    buffer[read_bytes] = '\0';
-    printf("%s", buffer);
+    fwrite(buffer, 1, read_bytes, stdout);
+    if (buffer[read_bytes - 1] == '\n') {
+      islastnl = true;
+    }
+  }
+
+  if (!islastnl) {
+    putchar('\n');
   }
 
   // 掃除
diff --git a/sp-completion.zsh b/sp-completion.zsh
new file mode 100644 (file)
index 0000000..412a735
--- /dev/null
@@ -0,0 +1,48 @@
+# compdef sp
+
+_sp () {
+  local state
+  local -a options
+  local -a entries
+
+  _arguments -C \
+    '-i[GPGと使ってパスワードストレージを初期設定]: :_sp_complete_keys' \
+    '-s[パスワードを表示]: :_sp_complete_entries' \
+    '-y[パスワードを表示せずクリップボードにコピーする]: :_sp_complete_entries' \
+    '-l[パスワード一覧を表示]' \
+    '-a[パスワードを追加]: :_sp_complete_entries' \
+    '-d[パスワードを削除]: :_sp_complete_entries' \
+    '-g[希望文字数でパスワードをランダムに作成する]: :_sp_complete_entries' \
+    '-o[ワンタイムパスワード(TOTP)を表示]: :_sp_complete_entries' \
+    '-h[ヘルプを表示]' \
+    '-v[バージョンを表示]' \
+    '*:: :->subcmds'
+    
+  case $state in
+    subcmds)
+      _message "no more arguments"
+      ;;
+  esac
+}
+
+_sp_cmd_show () {
+  _sp_complete_entries
+}
+
+_sp_complete_entries() {
+  _sp_complete_entries_helper -type f
+}
+
+_sp_complete_entries_helper () {
+  local IFS=$'\n'
+  local prefix="${SP_DIR:-$HOME/.local/share/sp}"
+  entries=("${(f)$(find -L "$prefix" \( -name .git -o -name .gpg-id \) -prune -o -type f -print 2>/dev/null | sed -e "s#${prefix}/##" -e 's#\.gpg$##')}")
+  _describe 'password entries' entries
+}
+
+_sp_complete_keys () {    
+  local IFS=$'\n'
+  _values 'gpg keys' $(gpg2 --list-secret-keys --with-colons | cut -d : -f 10 | sort -u | sed '/^$/d')
+}
+
+compdef _sp sp
index e79fc51dce011b2f9ad98267004420795f405ea5..b8df4de0a7e0c469ee88e366b0686b1076b91259 100644 (file)
@@ -98,12 +98,18 @@ void yankpass(char* file) {
 
   char buffer[512];
   ssize_t read_bytes;
-  while ((read_bytes = gpgme_data_read(out, buffer, 511)) > 0) {
+
+  while ((read_bytes = gpgme_data_read(out, buffer, sizeof(buffer))) > 0) {
+    if (buffer[read_bytes - 1] == '\n') {
+        read_bytes--;
+    }
     fwrite(buffer, 1, read_bytes, pipe);
   }
+
   pclose(pipe);
 
   // 45秒後、クリップボードから削除する
+  printf("パスワードをクリップボードに追加しました。\n45秒後はクリップボードから取り消されます。\n");
   sleep(45);
   system("echo -n | xclip -selection clipboard");