レポジトリ種類: Mercurial
#include "addpass.h"
void cleanup(gpgme_ctx_t ctx, gpgme_key_t key, gpgme_data_t in, gpgme_data_t out) {
gpgme_data_release(in);
gpgme_data_release(out);
gpgme_release(ctx);
gpgme_key_release(key);
}
void getpasswd(char *prompt, char *pw, size_t pwlen) {
struct termios old, new;
printf("%s", prompt);
// 端末設定を受け取る
tcgetattr(fileno(stdin), &old);
new = old;
// echoを無効にして
new.c_lflag &= ~ECHO;
tcsetattr(fileno(stdin), TCSANOW, &new);
// パスワードを読み込む
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);
}
int addpass(char *file) {
// パスを準備
char *basedir = getbasedir(1);
char *ext = ".gpg";
char pass[256];
char knin[256];
int alllen = snprintf(NULL, 0, "%s%s%s", basedir, file, ext) + 1;
char *gpgpathchk = malloc(alllen);
if (gpgpathchk == NULL) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to allocate memory" : "メモリを割当に失敗");
fprintf(stderr, "%s\n", ero);
return -1;
}
// ファイルが既に存在するかどうか確認
snprintf(gpgpathchk, alllen, "%s%s%s", basedir, file, ext);
if (access(gpgpathchk, F_OK) != -1) {
if (strncmp(lang, "en", 2) == 0)
fprintf(
stderr,
"Password already exist.\nTo edit, please run ' sp -e %s '.\n",
file
);
else
fprintf(
stderr,
"%s\n変更するには、「 sp -e %s 」を実行して下さい。\n",
"パスワードが既に存在しています。",
file
);
free(gpgpathchk);
return -1;
}
free(gpgpathchk);
// パスワードを受け取る
if (strncmp(lang, "en", 2) == 0)
getpasswd("Password: ", pass, sizeof(pass));
else getpasswd("パスワード: ", pass, sizeof(pass));
puts("");
if (strncmp(lang, "en", 2) == 0)
getpasswd("Password (for verification): ", knin, sizeof(knin));
else getpasswd("パスワード(確認用): ", knin, sizeof(knin));
puts("");
// パスワードが一致するかどうか確認
if (strcmp(pass, knin) != 0) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Password does not match. Terminating..." :
"パスワードが一致していません。終了…");
fprintf(stderr, "%s\n", ero);
return -1;
}
// パスワードを保存する
gpgme_ctx_t ctx;
gpgme_error_t err;
gpgme_key_t key[2] = {NULL, NULL};
gpgme_data_t in, out;
FILE *gpgfile;
// GPGMEライブラリを設置
setlocale(LC_ALL, "");
gpgme_check_version(NULL);
gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
// GPGMEを創作
err = gpgme_new(&ctx);
if (err) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to generate GPGME" : "GPGMEを創作に失敗");
fprintf(stderr, "%s: %s\n", ero, gpgme_strerror(err));
return -1;
}
// GPGMEは非対話的モードに設定
err = gpgme_set_pinentry_mode(ctx, GPGME_PINENTRY_MODE_LOOPBACK);
if (err) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to set pinentry mode" : "pinentryモードを設定に失敗");
fprintf(stderr, "%s: %s\n", ero, gpgme_strerror(err));
gpgme_release(ctx);
return -1;
}
// パスワードからデータオブジェクトを創作
err = gpgme_data_new_from_mem(&in, pass, strlen(pass), 0);
if (err) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to make data object" : "データオブジェクトを創作に失敗");
fprintf(stderr, "%s: %s\n", ero, gpgme_strerror(err));
gpgme_release(ctx);
return -1;
}
gpgme_data_new(&out);
// 鍵を受け取る
char keypath[256];
snprintf(keypath, sizeof(keypath), "%s%s", basedir, ".gpg-id");
keypath[sizeof(keypath) - 1] = '\0';
FILE* keyfile = fopen(keypath, "rb");
if (keyfile == NULL) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to open .gpg-id file" : ".gpg-idファイルを開くに失敗");
fprintf(stderr, "%s\n", ero);
return -1;
}
char *keyid = malloc(256);
if (!fgets(keyid, 256, keyfile)) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to reading key ID" : "鍵IDを読込に失敗");
fprintf(stderr, "%s\n", ero);
fclose(keyfile);
free(keyid);
return -1;
}
keyid[strcspn(keyid, "\n")] = 0;
fclose(keyfile);
err = gpgme_get_key(ctx, keyid, &key[0], 0);
if (err) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to get key" : "鍵Dを受取に失敗");
fprintf(stderr, "%s: %s\n", ero, gpgme_strerror(err));
free(keyid);
return -1;
}
if (key[0] == NULL) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Error: Key is NULL" : "エラー:鍵はNULLです");
fprintf(stderr, "%s\n", ero);
free(keyid);
return -1;
}
free(keyid);
// 暗号化
err = gpgme_op_encrypt(ctx, &key[0], GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
if (err) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to encrypt" : "暗号化に失敗");
fprintf(stderr, "%s: %s\n", ero, gpgme_strerror(err));
cleanup(ctx, key[0], in, out);
return -1;
}
// 暗号化したファイルを開く
char *gpgpath = malloc(alllen);
if (gpgpath == NULL) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to allocate memory" : "メモリを割当に失敗");
fprintf(stderr, "%s\n", ero);
cleanup(ctx, key[0], in, out);
return -1;
}
// ディレクトリを創作
char dirpath[512];
snprintf(dirpath, sizeof(dirpath), "%s%s", basedir, file);
dirpath[sizeof(dirpath) - 1] = '\0';
char *lastsla = strrchr(dirpath, '/');
if (lastsla != NULL) {
*lastsla = '\0';
if (mkdir_r(dirpath, 0755) != 0) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to create directory" : "ディレクトリを創作に失敗");
fprintf(stderr, "%s\n", ero);
free(gpgpath);
cleanup(ctx, key[0], in, out);
return -1;
}
}
snprintf(gpgpath, alllen, "%s%s%s", basedir, file, ext);
struct stat statbuf;
if (stat(gpgpath, &statbuf) == 0) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Password already exists" : "パスワードは既に存在しています");
fprintf(stderr, "%s\n", ero);
free(gpgpath);
cleanup(ctx, key[0], in, out);
return -1;
}
gpgfile = fopen(gpgpath, "wb");
if (gpgfile == NULL) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to open file." : "ファイルを開くに失敗。");
fprintf(stderr, "%s\n", ero);
free(gpgpath);
cleanup(ctx, key[0], in, out);
return -1;
}
// データが保存したかどうか確認
ssize_t encrypted_data_size = gpgme_data_seek(out, 0, SEEK_END);
if (encrypted_data_size <= 0) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to store the data" : "データを保存に失敗");
fprintf(stderr, "%s\n", ero);
fclose(gpgfile);
free(gpgpath);
cleanup(ctx, key[0], in, out);
return -1;
}
// 復号化したパスワードを表示する
gpgme_data_seek(out, 0, SEEK_SET);
char buffer[512];
ssize_t read_bytes;
while ((read_bytes = gpgme_data_read(out, buffer, sizeof(buffer))) > 0) {
if (fwrite(buffer, 1, (size_t)read_bytes, gpgfile) != (size_t)read_bytes) {
const char *ero = (strncmp(lang, "en", 2) == 0 ?
"Failed to write password" : "パスワードを書き込みに失敗");
fprintf(stderr, "%s\n", ero);
free(gpgpath);
cleanup(ctx, key[0], in, out);
return -1;
}
}
// 掃除
fclose(gpgfile);
free(gpgpath);
cleanup(ctx, key[0], in, out);
const char *msg = (strncmp(lang, "en", 2) == 0 ?
"The password got saved." : "パスワードを保存出来ました。");
printf("%s\n", msg);
return 0;
}