From 5a8218b13fbe21e4c85a484933ca201b666323ee Mon Sep 17 00:00:00 2001 From: Joursoir Date: Wed, 21 Oct 2020 19:26:03 +0000 Subject: fix bug: work outside working dir; refactor --- Makefile | 3 - easydir.c | 100 ++------------------ easydir.h | 1 - handerror.c | 15 +++ handerror.h | 1 + implementation.c | 117 ++++++++++++----------- implementation.h | 1 + main.c | 275 ++++++++++++++++++++++++------------------------------- 8 files changed, 202 insertions(+), 311 deletions(-) diff --git a/Makefile b/Makefile index 775ad74..d4520b3 100755 --- a/Makefile +++ b/Makefile @@ -1,4 +1,3 @@ -VERSION = 1.01 PREFIX = /usr/local/bin CC = gcc CFLAGS = -Wall -g @@ -21,8 +20,6 @@ $(EXECUTABLE): $(OBJECTS) install: all @echo installing file to $(PREFIX) - #@mkdir -p $(PREFIX) - #@cp -f $(EXECUTABLE) $(PREFIX) @install $(EXECUTABLE) $(PREFIX) @chmod 755 $(PREFIX)/$(EXECUTABLE) diff --git a/easydir.c b/easydir.c index 921549e..08cac0f 100644 --- a/easydir.c +++ b/easydir.c @@ -7,106 +7,22 @@ #include "handerror.h" -/* Buff size: source == path = file -splitPath thinks, that in end path always stay FILE, not directory */ -char* splitPath(char *source, char *path, char *file) -{ - int fSymbol = 0, f = 0; - - char *main_path = malloc( sizeof(char) * (strlen(source)+1) ); - char *file_path = malloc( sizeof(char) * (strlen(source)+1) ); - - for(int i=0; i < strlen(source); i++) - { - if(fSymbol == 1) - { - switch(source[i]) - { - case '/': - { - fSymbol = 0; - f = 0; - - strcat(main_path, file_path); - strcat(main_path, "/"); - file_path[0] = '\0'; - break; - } - default: - { - file_path[f] = source[i]; - file_path[f+1] = '\0'; - f++; - - break; - } - - } - } - else // if it's beginning of string - { - // handling first symbol - switch(source[i]) - { - case '.': - case '\\': - case '/': - { - printError("lpass: You can't use these symbol at the beginning: '.', '/', '\\' \n"); - break; - } - default: - fSymbol = 1; - - // enter first symbol - file_path[0] = source[i]; - file_path[1] = '\0'; - f++; - - break; - } - } - } - - strcpy(path, main_path); - strcpy(file, file_path); - free(main_path); - free(file_path); - - if(*file) return file; - return NULL; -} - int deleteFile(char *file_path) { - int pid; - pid = fork(); - if(pid == -1) callError(112); - if(pid == 0) { /* new process */ - execlp("rm", "rm", file_path, NULL); - perror("rm"); - exit(4); - } - wait(&pid); + char *arguments[] = {"rm", file_path, NULL}; + easyFork("rm", arguments); return 1; } int deleteEmptyDir(char *dir_path) { - int pid; - pid = fork(); - if(pid == -1) callError(113); - if(pid == 0) { /* new process */ - #if defined(DEBUG) - execlp("rmdir", "rmdir", "-p", dir_path, NULL); - #else - execlp("rmdir", "rmdir", "-p", "--ignore-fail-on-non-empty", dir_path, NULL); - #endif - perror("rmdir"); - exit(4); - } - wait(&pid); + #if defined(DEBUG) + char *arguments[] = {"rmdir", "-p", dir_path, NULL}; + #else + char *arguments[] = {"rmdir", "-p", "--ignore-fail-on-non-empty", dir_path, NULL}; + #endif + easyFork("rmdir", arguments); return 1; } diff --git a/easydir.h b/easydir.h index 5db1965..2191d6a 100644 --- a/easydir.h +++ b/easydir.h @@ -1,7 +1,6 @@ #ifndef EASYDIR_H #define EASYDIR_H -char* splitPath(char *source, char *path, char *file); int deleteFile(char *file_path); int deleteEmptyDir(char *dir_path); int checkFileExist(char *path_to_file); diff --git a/handerror.c b/handerror.c index 753e834..35e8f28 100644 --- a/handerror.c +++ b/handerror.c @@ -1,5 +1,7 @@ #include #include +#include +#include void callError(int num) { @@ -13,3 +15,16 @@ void printError(char *text) exit(4); } +void easyFork(char *name, char *arguments[]) +{ + int pid; + pid = fork(); + if(pid == -1) callError(100); + if(pid == 0) { /* new process */ + execvp(name, arguments); + perror(name); + exit(4); + } + wait(&pid); +} + diff --git a/handerror.h b/handerror.h index e4c5039..6f75c7b 100644 --- a/handerror.h +++ b/handerror.h @@ -1,6 +1,7 @@ #ifndef HANDERROR_H #define HANDERROR_H +void easyFork(char *name, char *arguments[]); void callError(int num); void printError(char *text); diff --git a/implementation.c b/implementation.c index f695b01..1c636ae 100644 --- a/implementation.c +++ b/implementation.c @@ -4,40 +4,65 @@ #include #include #include -#include #include #include "handerror.h" #include "easydir.h" +#define GPG_OUTPUT_FILE ".gap" +#define GPG_PUBLICKEY_MAXLENGTH 1025 // +1 for '\0' + // == global var == -extern char *gPath_rootdir; -extern char *gSecret_gpgkey; +extern char *gPath_rootdir; // /home/[username]/.lockpassword/ +extern char *gPath_subdir; // example: programming/github.com +extern char *gPath_pass; // example: programming/github.com/joursoir.gpg + +void checkForbiddenPaths(char *path) // check two dot in path +{ + int firstdot = 0; + for(int i=0; i < strlen(path); i++) + { + if(path[i] == '.') + firstdot ? printError("Error: please, don't use forbidden paths\n") : firstdot++; + else firstdot = 0; + } +} -char* getPassword(char *path, char *password, int maxlen) +static char *getGPGKey(char *dest, size_t size) { - // gpg - int pid = fork(); - if(pid == 1) callError(126); - if(pid == 0) { - execlp("gpg", "-d", "--quiet", "-r", gSecret_gpgkey, "-o", "gap", path, NULL); - perror("gpg"); - exit(4); + FILE *fileGPG = fopen(".gpg-key", "r"); + if(fileGPG == NULL) { + if(errno == ENOENT) printError("error: No GPG key exists\n"); + callError(121); } - wait(&pid); - FILE *filePass = fopen("gap", "r"); + if(!fgets(dest, size, fileGPG)) { + callError(122); + } + fclose(fileGPG); + + return dest; +} + +char* getPassword(char *path_pass, char *password, size_t size) // path_pass is not used +{ + int size_gpgkey = sizeof(char) * GPG_PUBLICKEY_MAXLENGTH; + char *secret_gpgkey = (char *) malloc(size_gpgkey); + getGPGKey(secret_gpgkey, size_gpgkey); + + char *arguments[] = {"gpg", "-d", "--quiet", "-r", secret_gpgkey, "-o", GPG_OUTPUT_FILE, gPath_pass, NULL}; + easyFork("gpg", arguments); + + FILE *filePass = fopen(GPG_OUTPUT_FILE, "r"); if(filePass == NULL) callError(127); - char sign[maxlen]; - if(!fgets(sign, sizeof(sign), filePass)) { + if(!fgets(password, size, filePass)) { callError(111); } - - strcpy(password, sign); fclose(filePass); - remove("gap"); + free(secret_gpgkey); + remove(GPG_OUTPUT_FILE); return password; } @@ -56,61 +81,33 @@ void nonvisibleEnter(int status) void insertPass(char *add_path, char *password) { - /* gPath_rootdir = /home/[username]/.lock-password/Password-Storage/ + /* gPath_rootdir = /home/[username]/.lock-password/ add_path = banks/france/[number] - main_path = banks/france - file_path = [number] */ - - char *main_path = malloc( sizeof(char) * (strlen(add_path)+1) ); - char *file_path = malloc( sizeof(char) * (strlen(add_path)+1) ); - - if(splitPath(add_path, main_path, file_path) == NULL) { - printError("lpass: The path you specified is incorrect\n"); - } + gPath_pass = banks/france/[number].gpg + gPath_subdir = banks/france */ - int pass_buf = strlen(gPath_rootdir) + strlen(add_path) + 1; - char *final_path = (char*) malloc(sizeof(char) * pass_buf); + int size_gpgkey = sizeof(char) * GPG_PUBLICKEY_MAXLENGTH; + char *secret_gpgkey = (char *) malloc(size_gpgkey); + getGPGKey(secret_gpgkey, size_gpgkey); - strcpy(final_path, gPath_rootdir); - strcat(final_path, main_path); - - if(strcmp(main_path, "") != 0) { - int pid = fork(); - if(pid == -1) callError(103); - if(pid == 0) { /* new process */ - execlp("mkdir", "mkdir", "-p", main_path, NULL); - perror("mkdir"); - exit(4); - } - wait(&pid); - } - - if(chdir(final_path) != 0) { - callError(107); - } + char *arguments1[] = {"mkdir", "-p", gPath_subdir, NULL}; + easyFork("mkdir", arguments1); // create file, copy password there FILE *filePass; - filePass = fopen(file_path, "w"); + filePass = fopen(add_path, "w"); if(filePass == NULL) { callError(108); } fputs(password, filePass); fclose(filePass); - // gpg - int pid = fork(); - if(pid == 1) callError(225); - if(pid == 0) { - execlp("gpg", "-a", "-r", gSecret_gpgkey, "-e", file_path, NULL); - perror("gpg"); - exit(4); - } - wait(&pid); - remove(file_path); + // encryption + char *arguments2[] = {"gpg", "-r", secret_gpgkey, "-e", add_path, NULL}; + easyFork("gpg", arguments2); - free(main_path); - free(file_path); + remove(add_path); + free(secret_gpgkey); } char *typePass(char *text, char *dest, int minlen, int maxlen) diff --git a/implementation.h b/implementation.h index cb0b401..4136f32 100644 --- a/implementation.h +++ b/implementation.h @@ -1,6 +1,7 @@ #ifndef IMPLEMENTATION_H #define IMPLEMENTATION_H +void checkForbiddenPaths(char *path); char* getPassword(char *path, char *password, int maxlen); void nonvisibleEnter(int status); void insertPass(char *add_path, char *password); diff --git a/main.c b/main.c index cace9d0..fee2b4c 100644 --- a/main.c +++ b/main.c @@ -1,3 +1,10 @@ +/* +** Code written by Joursoir +** +** This is free and unencumbered software released into the public domain. +** (C) The Unlicense +*/ + #include #include #include @@ -5,35 +12,58 @@ #include #include #include -#include +#include #include "easydir.h" #include "handerror.h" #include "implementation.h" +#define VERSION "1.0" +#define DATE_RELEASE "21 October, 2020" //#define DEBUG #define MINLEN_PASSWORD 1 #define MAXLEN_PASSWORD 128 #define STANDARD_AMOUNT_GENERATE_SYMBOLS 10 #define LOCKPASS_DIR "/.lock-password/" -#define STORAGEPASS_DIR "Password-Storage/" #define GPGKEY_FILE "/.gpg-key" +#define TREE_OUTPUT_FILE ".tree" + #define HASH_INIT 6385337657 #define HASH_HELP 6385292014 #define HASH_VERSION 229486327000139 #define HASH_COPY 6385123360 #define HASH_EDIT 6385183019 +#define HASH_MV 5863624 #define HASH_MOVE 249844339311324255 #define HASH_GENERATE 7572409341523952 #define HASH_INSERT 6953633055386 +#define HASH_RM 5863780 #define HASH_REMOVE 6953974396019 #define HASH_DELETE 6953426453624 #define WITHOUT_ARGUMENTS 1 // == global var == -char *gPath_rootdir; -char *gSecret_gpgkey; +char *gPath_rootdir; // /home/[username]/.lockpassword/ +char *gPath_subdir; // example: programming/github.com +char *gPath_pass; // example: programming/github.com/joursoir.gpg + +static void globalSplitPath(char *source) +{ + int len_path = strlen(source) + strlen(".gpg") + 1; + + gPath_pass = malloc(sizeof(char) * len_path); // path without working dir + strcpy(gPath_pass, source); + strcat(gPath_pass, ".gpg"); + + gPath_subdir = malloc(sizeof(char) * len_path); // path without working dir and pass file + strcpy(gPath_subdir, source); + gPath_subdir = dirname(gPath_subdir); + + #if defined(DEBUG) + printf("dir: %s\n", gPath_subdir); + #endif +} static void cmd_init(int argc, char *argv[]) { @@ -45,17 +75,10 @@ static void cmd_init(int argc, char *argv[]) // create main directory: int len_init_storage = strlen(gPath_rootdir) + strlen(GPGKEY_FILE) + 1; // +1 for '\0' char *path_init_storage = (char *) malloc(sizeof(char) * len_init_storage); - strcpy(path_init_storage, gPath_rootdir); - int pid = fork(); - if(pid == -1) callError(100); - if(pid == 0) { /* new process */ - execlp("mkdir", "mkdir", "-vp", path_init_storage, NULL); - perror("mkdir"); - exit(4); - } - wait(&pid); + char *arguments[] = {"mkdir", "-vp", path_init_storage, NULL}; + easyFork("mkdir", arguments); strcat(path_init_storage, GPGKEY_FILE); @@ -83,13 +106,15 @@ static void cmd_edit(int argc, char *argv[]) if(path_to_password == NULL) printError("Use: lpass edit [path to password]\n"); + checkForbiddenPaths(path_to_password); - if(checkFileExist(path_to_password) == 0) { + globalSplitPath(path_to_password); + + if(checkFileExist(gPath_pass) == 0) printError("lpass: No such file exists\n"); - } /* ask user about change pass */ - int buffSize = (strlen("Do you want edit password in '' (Y/N)?") + strlen(path_to_password)) * sizeof(char) + sizeof(char); + int buffSize = (strlen("Do you want edit password in '' (Y/N)?") + strlen(path_to_password) + 1) * sizeof(char); char *str = malloc(buffSize); snprintf(str, buffSize, "Do you want edit password in '%s' (Y/N)?", path_to_password); @@ -105,14 +130,32 @@ static void cmd_edit(int argc, char *argv[]) printf("Passwords do not match\n"); } +static void cmd_move(int argc, char *argv[]) +{ + char *old_path = argv[2]; + char *new_path = argv[argc-1]; + + if(old_path == new_path) + printError("Use: lpass move/mv [old path] [new path]"); + + // soon ... +} + static void cmd_generate(int argc, char *argv[]) { char *len_pass = argv[2]; char *path_to_password = argv[argc-1]; - if(checkFileExist(path_to_password) == 1) { + if(path_to_password == NULL) + printError("Use: lpass generate [len pass] [path to password]\n"); + checkForbiddenPaths(path_to_password); + + globalSplitPath(path_to_password); + + if(checkFileExist(gPath_pass) == 1) { // ask user about change pass - int buffSize = (strlen("Do you want generate new password and paste it in '' (Y/N)?") + strlen(path_to_password)) * sizeof(char) + sizeof(char); + int buffSize = (strlen("Do you want generate new password and paste it in '' (Y/N)?") + \ + strlen(path_to_password) - 4 + 1) * sizeof(char); char *str = malloc(buffSize); snprintf(str, buffSize, "Do you want generate new password and paste it in '%s' (Y/N)?", path_to_password); @@ -120,8 +163,7 @@ static void cmd_generate(int argc, char *argv[]) int answer = getAnswer(str); free(str); - if(answer != 1) - exit(EXIT_FAILURE); + if(answer != 1) exit(EXIT_SUCCESS); } int n_symbols = 0; @@ -129,7 +171,6 @@ static void cmd_generate(int argc, char *argv[]) n_symbols = STANDARD_AMOUNT_GENERATE_SYMBOLS; else n_symbols = atoi(len_pass); - if(n_symbols < MINLEN_PASSWORD || n_symbols > MAXLEN_PASSWORD) { printError("lpass: you typed an incorrect number"); } @@ -148,8 +189,11 @@ static void cmd_insert(int argc, char *argv[]) char *path_to_password = argv[2]; if(path_to_password == NULL) printError("Use: lpass insert [path to password]\n"); + checkForbiddenPaths(path_to_password); + + globalSplitPath(path_to_password); - if(checkFileExist(path_to_password) == 1) + if(checkFileExist(gPath_pass) == 1) printError("To change pass use: lpass change [path to password]\n"); if(userEnterPassword(MINLEN_PASSWORD, MAXLEN_PASSWORD, path_to_password) == 1) @@ -161,77 +205,54 @@ static void cmd_insert(int argc, char *argv[]) static void cmd_remove(int argc, char *argv[]) { char *path_to_password = argv[2]; + if(path_to_password == NULL) + printError("Use: lpass remove/rm/delete [path to password]\n"); + checkForbiddenPaths(path_to_password); - char *path_with_gpg = malloc( sizeof(char) * (strlen(path_to_password)+1+4) ); - strcpy(path_with_gpg, path_to_password); - strcat(path_with_gpg, ".gpg"); + globalSplitPath(path_to_password); - if(checkFileExist(path_with_gpg) == 0) { + if(checkFileExist(gPath_pass) == 0) { printError("lpass: No such file exists\n"); } - // check working - char *main_path, *file_path; - main_path = (char *) malloc( sizeof(char) * (strlen(path_to_password)+1) ); - file_path = (char *) malloc( sizeof(char) * (strlen(path_to_password)+1) ); - - if(splitPath(path_to_password, main_path, file_path) == NULL) { // check correct input - printError("lpass: The path you specified is incorrect\n"); - } - - if(deleteFile(path_with_gpg)) { - deleteEmptyDir(main_path); + if(deleteFile(gPath_pass)) { + deleteEmptyDir(gPath_subdir); } - - free(path_with_gpg); - free(main_path); - free(file_path); } static void cmd_showtree(char *path) { - if(opendir(path) != NULL) { // if it's directory - int pid; - pid = fork(); - if(pid == -1) callError(101); - if(pid == 0) { /* new process */ - execlp("tree", "tree", "-C", "--noreport", path, "-o", "tree", NULL); - perror("tree"); - exit(4); - } - wait(&pid); - - pid = fork(); - if(pid == -1) callError(130); - if(pid == 0) { - execlp("sed", "sed", "-E", "s/\\.gpg(\\x1B\\[[0-9]+m)?( ->|$)/\\1\\2/g", "tree", NULL); - perror("sed"); - exit(4); - } - wait(&pid); + if(opendir(path) != NULL ) // if it's directory + { + char *arg1[] = {"tree", "-C", "--noreport", path, "-o", TREE_OUTPUT_FILE, NULL}; + easyFork("tree", arg1); - remove("tree"); - } - else { - char *path_with_gpg = (char *) malloc( sizeof(char) * (strlen(path)+1+4) ); // +4 for ".gpg" - strcpy(path_with_gpg, path); - strcat(path_with_gpg, ".gpg"); + char *arg2[] = {"sed", "-i", "-E", "s/\\.gpg(\\x1B\\[[0-9]+m)?( ->|$)/\\1\\2/g", TREE_OUTPUT_FILE, NULL}; + easyFork("sed", arg2); // remove .gpg at the pass name - char password[MAXLEN_PASSWORD]; - getPassword(path_with_gpg, password, MAXLEN_PASSWORD); + if(strcmp(path, ".") == 0) printf("Password Storage\n"); + else printf("Password Storage/%s\n", path); - free(path_with_gpg); + char *arg3[] = {"tail", "-n", "+2", TREE_OUTPUT_FILE, NULL}; + easyFork("tail", arg3); // remove working directory - printf("%s\n", password); + remove(TREE_OUTPUT_FILE); } -} - -static void cmd_help() -{ + else + { + globalSplitPath(path); + if(checkFileExist(gPath_pass) == 1) // exist + { + char password[MAXLEN_PASSWORD]; + getPassword(path, password, sizeof(char)*MAXLEN_PASSWORD); + printf("%s\n", password); + } + else printf("Error: %s is not in the password storage\n", path); + } } -static void cmd_version() +static void cmd_help() { } @@ -243,110 +264,54 @@ int main(int argc, char *argv[]) } /* init global path to root directory */ - int len_rootdir = strlen(getenv("HOME")) + strlen(LOCKPASS_DIR) + strlen(STORAGEPASS_DIR) + 1; // +1 for '\0' + int len_rootdir = strlen(getenv("HOME")) + strlen(LOCKPASS_DIR) + 1; // +1 for '\0' gPath_rootdir = (char *) malloc(sizeof(char) * len_rootdir); strcpy(gPath_rootdir, getenv("HOME")); strcat(gPath_rootdir, LOCKPASS_DIR); - strcat(gPath_rootdir, STORAGEPASS_DIR); /* end init */ unsigned long ihash = WITHOUT_ARGUMENTS; if(argv[1] != NULL) ihash = hash(argv[1]); - if(ihash != HASH_INIT) - { - if(chdir(gPath_rootdir) != 0) - printError("Before starting work, you must initialize LockPassword\nUse: lpass init [gpg key]\n"); - else { - /* init GPG key */ - FILE *fileGPG; - fileGPG = fopen(".gpg-key", "r"); - if(fileGPG == NULL) { - if(errno == ENOENT) printError("lpass: No GPG key exists\n"); - callError(121); - } - - gSecret_gpgkey = (char *) malloc( sizeof(char) * (MAXLEN_PASSWORD+1) ); - - char sign[MAXLEN_PASSWORD]; - if(!fgets(sign, sizeof(sign), fileGPG)) { - callError(122); - } - strcpy(gSecret_gpgkey, sign); - /* end init */ - } - } - - if( (chdir(gPath_rootdir) != 0) && (ihash != HASH_INIT) ) { + if(chdir(gPath_rootdir) != 0 && ihash != HASH_INIT) printError("Before starting work, you must initialize LockPassword\nUse: lpass init [gpg key]\n"); - } switch(ihash) { - case HASH_INIT: { - cmd_init(argc, argv); - break; - } - case HASH_COPY: { - cmd_copy(argc, argv); - break; - } - case HASH_EDIT: { - cmd_edit(argc, argv); - break; - } - case HASH_MOVE: - break; - case HASH_GENERATE: { - cmd_generate(argc, argv); - break; - } - case HASH_INSERT: { - cmd_insert(argc, argv); - break; - } + case HASH_INIT: { cmd_init(argc, argv); break; } + case HASH_COPY: { cmd_copy(argc, argv); break; } + case HASH_EDIT: { cmd_edit(argc, argv); break; } + case HASH_MV: + case HASH_MOVE: { cmd_move(argc, argv); break; } + case HASH_GENERATE: { cmd_generate(argc, argv); break; } + case HASH_INSERT: { cmd_insert(argc, argv); break; } + case HASH_RM: case HASH_REMOVE: - case HASH_DELETE: { - cmd_remove(argc, argv); - break; - } - case HASH_HELP: { - cmd_help(); - break; - } + case HASH_DELETE: { cmd_remove(argc, argv); break; } + case HASH_HELP: { cmd_help(); break; } case HASH_VERSION: { - cmd_version(); + printf("LockPassword v%s\n", VERSION); + printf("Release date: %s\n\n", DATE_RELEASE); + printf("Code written by Joursoir\n"); + printf("This is free and unencumbered software released into the public domain.\n\n"); break; } default: { - // fix [./lpass ..] - int newlen_rootdir = len_rootdir - strlen(STORAGEPASS_DIR) - 1; - gPath_rootdir[newlen_rootdir-1] = '\0'; - - if(chdir(gPath_rootdir) != 0) - callError(123); - - char *ptr; - if(ihash == WITHOUT_ARGUMENTS) { - ptr = malloc(sizeof(char) * (strlen(STORAGEPASS_DIR)+1) ); - strcpy(ptr, STORAGEPASS_DIR); - } - else { - int buff_tree = strlen(STORAGEPASS_DIR) + strlen(argv[argc-1]) + 1; - ptr = malloc(sizeof(char) * buff_tree); - strcpy(ptr, STORAGEPASS_DIR); - strcat(ptr, argv[argc-1]); - } - cmd_showtree(ptr); - - free(ptr); + if(ihash == WITHOUT_ARGUMENTS) strcpy(argv[argc-1], "."); + else checkForbiddenPaths(argv[argc-1]); + + cmd_showtree(argv[argc-1]); break; } } + if(gPath_subdir != NULL) { + free(gPath_subdir); + free(gPath_pass); + } free(gPath_rootdir); return EXIT_SUCCESS; } \ No newline at end of file -- cgit v1.2.3-18-g5258