From f14d50623ebdc1fde95bf67ca3468f4828104607 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E8=AB=8F=E8=A8=AA=E5=AD=90?= Date: Wed, 9 Oct 2024 14:44:11 +0900 Subject: [PATCH] =?utf8?q?=E3=83=AF=E3=83=B3=E3=82=BF=E3=82=A4=E3=83=A0?= =?utf8?q?=E3=83=91=E3=82=B9=E3=83=AF=E3=83=BC=E3=83=89=EF=BC=88OTP?= =?utf8?q?=EF=BC=89=E3=82=92=E8=A1=A8=E7=A4=BA=E3=81=9B=E3=81=9A=E3=81=AB?= =?utf8?q?=E3=82=B3=E3=83=94=E3=83=BC=E6=A9=9F=E8=83=BD=E6=80=A7=E3=81=AE?= =?utf8?q?=E8=BF=BD=E5=8A=A0=20(#31)?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + main.c | 16 ++++++++++++-- man/sp-en.1 | 8 +++++-- man/sp-jp.1 | 7 ++++++- src/otppass.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++--- src/otppass.h | 2 +- src/yankpass.c | 3 +-- 7 files changed, 83 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c06054f..ee0331f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ * 侵害されたパスワードの確認の追加 * 複数サイトで同じパスワードを利用かどうか、パスワードの長さ、又はパスワードの強さの確認 * パスワードコピーの期間を設定出来る様に +* ワンタイムパスワード(OTP)を表示せずにコピー機能性の追加 # 1.4.0 * Haiku対応 diff --git a/main.c b/main.c index 0d1dc41..5bc9d07 100644 --- a/main.c +++ b/main.c @@ -15,7 +15,7 @@ const char *sofname = "sp"; const char *version = "1.5.0"; -const char *avalopt = "abcdefgilosvy"; +const char *avalopt = "abcdefgiloOsvy"; const char *madefor = "simpas 1.1.0"; void usage() { @@ -113,7 +113,12 @@ int main(int argc, char *argv[]) { } else if (strcmp(argv[1], "-o") == 0) { char *fullPath = getfullpath(argv[2]); if (fullPath == NULL) return -1; - otppass(fullPath); + otppass(fullPath, 0, 0); + free(fullPath); + } else if (strcmp(argv[1], "-O") == 0) { + char *fullPath = getfullpath(argv[2]); + if (fullPath == NULL) return -1; + otppass(fullPath, 1, 30); free(fullPath); } else if (strcmp(argv[1], "-f") == 0) { char *fullPath = getfullpath(NULL); @@ -134,6 +139,13 @@ int main(int argc, char *argv[]) { int i; if (sscanf(argv[3], "%d", &i) == 0) yankpass(argv[2], 45); else yankpass(argv[2], atoi(argv[3])); + } else if (strcmp(argv[1], "-O") == 0) { + char *fullPath = getfullpath(argv[2]); + if (fullPath == NULL) return -1; + int i; + if (sscanf(argv[3], "%d", &i) == 0) otppass(fullPath, 1, 30); + else otppass(fullPath, 1, atoi(argv[3])); + free(fullPath); } } else if (argc == 2) { char *basePath = getfullpath(NULL); diff --git a/man/sp-en.1 b/man/sp-en.1 index 30affba..a942e49 100644 --- a/man/sp-en.1 +++ b/man/sp-en.1 @@ -3,7 +3,7 @@ sp - Simple Password Manager .br .B sp -[-bfi] [-i \fI\,gpg-id\fR] [-adeos \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]] [-y \fI\,password\fR [\fI,seconds\fR]] +[-bfi] [-i \fI\,gpg-id\fR] [-adeos \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]] [-Oy \fI\,password\fR [\fI,seconds\fR]] .SH DESCRIPTION .PP Simple Password Manager @@ -44,9 +44,13 @@ Initialize password storage using GPG Show a list of passwords .TP \fB\,o\fR \fI\,password\fR -ワンタイムパスワード(TOTP)を表示 Show one time password (TOTP) .TP +\fB\,O\fR \fI\,password\fR \fI\,seconds\fR +Copy one time password (TOTP) +.br +The default is 30 seconds. +.TP \fB\,s\fR \fI\,password\fR Show password .TP diff --git a/man/sp-jp.1 b/man/sp-jp.1 index 94fe122..a52d0b7 100644 --- a/man/sp-jp.1 +++ b/man/sp-jp.1 @@ -3,7 +3,7 @@ sp - Simple Password Manager .br .B sp -[-bfi] [-i \fI\,gpg-id\fR] [-adeos \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]] [-y \fI\,password\fR [\fI,seconds\fR]] +[-bfi] [-i \fI\,gpg-id\fR] [-adeos \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]] [-Oy \fI\,password\fR [\fI,seconds\fR]] .SH 説明 .PP シンプルなパスワードマネージャー。 @@ -46,6 +46,11 @@ GPGと使ってパスワードストレージを初期設定 \fB\,o\fR \fI\,password\fR ワンタイムパスワード(TOTP)を表示 .TP +\fB\,O\fR \fI\,password\fR \fI,seconds\fR +ワンタイムパスワード(TOTP)をコピー +.br +デフォルトは30秒です。 +.TP \fB\,s\fR \fI\,password\fR パスワードを表示 .TP diff --git a/src/otppass.c b/src/otppass.c index 4d15eb2..34e7126 100644 --- a/src/otppass.c +++ b/src/otppass.c @@ -1,6 +1,8 @@ #include #include +#include + #if defined(__APPLE) #include #define htobe64(x) OSSwapHostToBigInt64(x) @@ -107,9 +109,19 @@ uint32_t generate_totp(const char *secret, uint64_t counter) { return truncated_hash % 1000000; } -void otppass(char *file) { +void otppass(char *file, int isCopy, int copyTimeout) { + if (isCopy == 1 && copyTimeout > 300) copyTimeout = 300; char *lang = getlang(); + // Xセッションではない場合(例えば、SSH、TTY、Gayland等)、showpass()を実行して + if (isCopy == 1 && getenv("DISPLAY") == NULL) { + if (strncmp(lang, "en", 2) == 0) + puts("There is no X session, so running 'sp -o'."); + else puts("Xセッションではありませんので、「sp -o」を実行します。"); + otppass(file, 0, 0); + return; + } + gpgme_ctx_t ctx; gpgme_error_t err; gpgme_data_t in, out; @@ -129,6 +141,7 @@ void otppass(char *file) { if (strncmp(lang, "en", 2) == 0) perror("Failed to read the GPG file"); else perror("GPGファイルを読込に失敗"); + gpgme_release(ctx); exit(1); } @@ -137,6 +150,8 @@ void otppass(char *file) { if (strncmp(lang, "en", 2) == 0) perror("Failed to read the GPG data"); else perror("GPGデータを読込に失敗"); + gpgme_release(ctx); + gpgme_data_release(in); exit(1); } @@ -145,6 +160,8 @@ void otppass(char *file) { if (strncmp(lang, "en", 2) == 0) perror("Failed to decrypt the GPG"); else perror("GPGを復号化に失敗"); + gpgme_release(ctx); + gpgme_data_release(in); exit(1); } @@ -153,6 +170,8 @@ void otppass(char *file) { if (strncmp(lang, "en", 2) == 0) perror("Failed to get the GPG"); else perror("GPGを受取に失敗"); + gpgme_data_release(in); + gpgme_release(ctx); exit(1); } @@ -164,7 +183,9 @@ void otppass(char *file) { if (strncmp(lang, "en", 2) == 0) perror("Failed to decode or export secret"); else perror("シークレットの抽出又はデコードに失敗しました"); - free(secret); + gpgme_data_release(in); + gpgme_release(ctx); + gpgme_free(secret); exit(1); } @@ -179,5 +200,35 @@ void otppass(char *file) { gpgme_free(secret); free(secret_decoded); - printf("%06d\n", otp); + if (isCopy) { + char cmd[64]; + snprintf(cmd, sizeof(cmd), "echo -n %06d | xclip -selection clipboard", otp); + int ret = system(cmd); + if (ret != 0) { + char *ero = (strncmp(lang, "en", 2) == 0 ? + "Failed to copy OTP." : "OTPをコピーに失敗。"); + fprintf(stderr, "%s\n", ero); + } + + // 何(デフォルトは30)秒後、クリップボードから削除する + if (strncmp(lang, "en", 2) == 0) + printf( + "%s\n%s%d%s\n", + "Added the one time password to the clipboard.", + "After ", + copyTimeout, + " seconds it'll be deleted from the clipboard." + ); + else + printf( + "%s\n%d%s\n", + "ワンタイムパスワードをクリップボードに追加しました。", + copyTimeout, + "秒後はクリップボードから取り消されます。" + ); + sleep(copyTimeout); + system("echo -n \"\" | xclip -selection clipboard"); + } else { + printf("%06d\n", otp); + } } diff --git a/src/otppass.h b/src/otppass.h index b916b09..db96da9 100644 --- a/src/otppass.h +++ b/src/otppass.h @@ -1,6 +1,6 @@ #ifndef OTPPASS_H #define OTPPASS_H -void otppass(char* file); +void otppass(char* file, int isCopy, int copyTimeout); #endif diff --git a/src/yankpass.c b/src/yankpass.c index 0851f2c..6d64ad7 100644 --- a/src/yankpass.c +++ b/src/yankpass.c @@ -10,7 +10,7 @@ void yankpass(char *file, int copyTimeout) { char *lang = getlang(); // Xセッションではない場合(例えば、SSH、TTY、Gayland等)、showpass()を実行して - if (getenv("DISPLAY") == NULL) { + if (getenv("DISPLAY") == NULL) { if (strncmp(lang, "en", 2) == 0) puts("There is no X session, so running 'sp -s'."); else puts("Xセッションではありませんので、「sp -s」を実行します。"); @@ -89,7 +89,6 @@ void yankpass(char *file, int copyTimeout) { // xclipを準備して FILE *pipe = popen("xclip -selection clipboard", "w"); if (pipe == NULL) { - // 掃除 fclose(gpgfile); free(gpgpath); -- 2.43.0