From ac79cbd424d2339ff34112e142d289a51f90d3a6 Mon Sep 17 00:00:00 2001 From: Joursoir Date: Mon, 28 Sep 2020 15:37:00 +0300 Subject: init project --- .gitignore | 3 + LICENSE.md | 24 ++++ compulation | 4 + easydir.c | 113 +++++++++++++++++ easydir.h | 3 + handerror.c | 15 +++ handerror.h | 2 + main.c | 398 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 562 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE.md create mode 100755 compulation create mode 100644 easydir.c create mode 100644 easydir.h create mode 100644 handerror.c create mode 100644 handerror.h create mode 100644 main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d28ca88 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +documentation/ +*.o +lpass \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..00d2e13 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to \ No newline at end of file diff --git a/compulation b/compulation new file mode 100755 index 0000000..614c238 --- /dev/null +++ b/compulation @@ -0,0 +1,4 @@ +#!/bin/bash + +gcc -c -Wall -g *.c +gcc -Wall -g -o lpass *.o \ No newline at end of file diff --git a/easydir.c b/easydir.c new file mode 100644 index 0000000..a4ece76 --- /dev/null +++ b/easydir.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include + +#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 '/': + { + print_error("[Error] 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 delete_file(char *file_path) +{ + int pid; + pid = fork(); + if(pid == -1) call_error(112); + if(pid == 0) { /* new process */ + execlp("rm", "rm", file_path, NULL); + perror("rm"); + exit(4); + } + wait(&pid); + + return 1; +} + +int delete_emptydir(char *dir_path) +{ + int pid; + pid = fork(); + if(pid == -1) call_error(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); + + return 1; +} diff --git a/easydir.h b/easydir.h new file mode 100644 index 0000000..ed62da7 --- /dev/null +++ b/easydir.h @@ -0,0 +1,3 @@ +char* splitPath(char *source, char *path, char *file); +int delete_file(char *file_path); +int delete_emptydir(char *dir_path); \ No newline at end of file diff --git a/handerror.c b/handerror.c new file mode 100644 index 0000000..482b467 --- /dev/null +++ b/handerror.c @@ -0,0 +1,15 @@ +#include +#include + +void call_error(int num) +{ + fprintf(stderr, "Sorry, there was an error in the program [#%d]\n", num); + exit(3); +} + +void print_error(char *text) +{ + fprintf(stderr, "%s", text); + exit(4); +} + diff --git a/handerror.h b/handerror.h new file mode 100644 index 0000000..d4137a9 --- /dev/null +++ b/handerror.h @@ -0,0 +1,2 @@ +void call_error(int num); +void print_error(char *text); \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..5d579cd --- /dev/null +++ b/main.c @@ -0,0 +1,398 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "easydir.h" +#include "handerror.h" + +//#define DEBUG +#define MAXLEN_PASSWORD 128 +#define FULLNAMEFILE "/.lock-password/Password-Bank" +#define TREENAMEFILE "/.lock-password" +#define ADDNAMETOFULL "/Password-Bank" +#define NAMEFILE "Password-Bank" + +static char* get_password(char *path, char *password) +{ + FILE *filePass; + filePass = fopen(path, "r"); + if(filePass == NULL) { + call_error(110); + } + + char sign[MAXLEN_PASSWORD]; + if(!fgets(sign, sizeof(sign), filePass)) { + call_error(111); + } + + strcpy(password, sign); + fclose(filePass); + return password; +} + +static void show_tree(char *path) +{ + if(opendir(path) != NULL) { // if it's directory + int pid; + pid = fork(); + if(pid == -1) call_error(101); + if(pid == 0) { /* new process */ + execlp("tree", "tree", "-C", "--noreport", path, NULL); + perror("tree"); + exit(4); + } + wait(&pid); + } + else { + char password[MAXLEN_PASSWORD]; + get_password(path, password); + printf("%s\n", password); + } +} + +static void changePass(char *root_path, char *add_path, char *password) +{ + /* root_path = /home/[username]/ + 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) { + print_error("[Error] The path you specified is incorrect\n"); + } + + int pass_buf = strlen(root_path) + strlen(add_path); + char *final_path = (char*) malloc(sizeof(char) * pass_buf + 1); + + strcpy(final_path, root_path); + strcat(final_path, "/"); + strcat(final_path, main_path); + + if(chdir(final_path) != 0) { + call_error(107); + } + + FILE *filePass; + filePass = fopen(file_path, "r+"); + if(filePass == NULL) { + if(errno == ENOENT) { // file doesn't exist + print_error("Error: No such file exists\n"); + } + call_error(114); + } + fputs(password, filePass); + + free(main_path); + free(file_path); + fclose(filePass); +} + +static void insertPass(char *root_path, char *add_path, char *password) +{ + /* root_path = /home/[username]/ + 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) { + print_error("[Error] The path you specified is incorrect\n"); + } + + int pass_buf = strlen(root_path) + strlen(add_path); + char *final_path = (char*) malloc(sizeof(char) * pass_buf + 1); + + strcpy(final_path, root_path); + strcat(final_path, "/"); + strcat(final_path, main_path); + + int pid = fork(); + if(pid == -1) call_error(103); + if(pid == 0) { /* new process */ + execlp("mkdir", "mkdir", "-p", main_path, NULL); + perror("mkdir"); + exit(4); + } + wait(&pid); + + if(chdir(final_path) != 0) { + call_error(107); + } + + // create file, copy password there + FILE *filePass; + filePass = fopen(file_path, "w"); + if(filePass == NULL) { + call_error(108); + } + fputs(password, filePass); + + free(main_path); + free(file_path); + fclose(filePass); +} + +static char *generate_password(char *dest, int amount) +{ + char allowed_symbols[] = { + 'A','E','I','J','O','U','B','C','D','F','G','H', + 'K','L','M','N','P','Q','R','S','T','V','W','X', + 'Y','Z','a','e','i','j','o','u','b','c','d','f', + 'g','h','k','l','m','n','p','q','r','s','t','v', + 'w','x','y','z','1','2','3','4','5','6','7','8', + '9','0','!','#','$',';','%','^',':','&','?','*', + '(',')','-','_','+','=','<', '>' + }; + int max = sizeof(allowed_symbols); + srand(time(NULL)); + + char password[MAXLEN_PASSWORD]; + for(int i=0; i < amount; i++) + { + char c = allowed_symbols[rand() % max]; + + password[i] = c; + password[i+1] = '\0'; + } + + strcpy(dest, password); + return dest; +} + +static void nonvisible_enter(int status) +{ + struct termios term_settings; + tcgetattr(0, &term_settings); // get current settings + if(status == 1) { + term_settings.c_lflag &= ~ECHO; // flag reset + } + else { + term_settings.c_lflag |= ECHO; + } + tcsetattr(0, TCSANOW, &term_settings); +} + +int main(int argc, char *argv[]) +{ + if(!isatty(0)) { // stdin + print_error("Please, use a terminal to run this program\n"); + } + + #if defined(DEBUG) + char* short_options = "c:e:g:i:R:t"; + #else + char* short_options = "c:e:g:i:R:"; + #endif + + struct option long_options[] = { + {"init", no_argument, NULL, 'I'}, + {NULL, 0, NULL, 0} + }; + + int rootBuf = strlen(getenv("HOME")) + strlen(FULLNAMEFILE); + char *rootPath = (char *) malloc(sizeof(char) * rootBuf + 1); // +1 for '\0' + + int path_init = 0; + strcpy(rootPath, getenv("HOME")); + strcat(rootPath, TREENAMEFILE); + + if(chdir(rootPath) == 0) path_init = 1; + + int option_index = -1, result = -1; + result = getopt_long(argc, argv, short_options, long_options, &option_index); + if(!path_init) { + if(result != 'I') // if doesn't init + { + if(errno == ENOENT) { // file doesn't exist + print_error("Before starting work, you must initialize LockPassword\n\ + Use: lpass --init\n"); + } + call_error(102); + } + } + else { + if(result == 'I') { + print_error("You already initialized LockPassword\n"); + } + else if(result != -1) + { + strcat(rootPath, ADDNAMETOFULL); // complements to full path + if(chdir(rootPath) != 0) { + call_error(112); + } + } + } + + if(result != -1) + { + switch(result) { + case 'c': { + printf("Coming soon...\n"); + break; + } + case 'e': { + nonvisible_enter(1); /* change terminal work */ + + /* enter password */ + char pass_one[MAXLEN_PASSWORD], pass_two[MAXLEN_PASSWORD]; + + printf("Please type your new password: "); + if(!fgets(pass_one, sizeof(pass_one), stdin)) { + nonvisible_enter(0); + print_error("Unexpected end of file\n"); + } + printf("\n"); + + printf("Please type your new password again: "); + if(!fgets(pass_two, sizeof(pass_two), stdin)) { + nonvisible_enter(0); + print_error("Unexpected end of file\n"); + } + printf("\n"); + + nonvisible_enter(0); + + if(strcmp(pass_one, pass_two) == 0) { + printf("Password correct\n"); + + changePass(rootPath, optarg, pass_one); + printf("Password updated successfully for %s\n", optarg); + } + else printf("Passwords do not match\n"); + + break; + } + case 'g': { + int n_symbols = 0; + if(strcmp(optarg, argv[argc-1]) == 0) + n_symbols = 8; + else n_symbols = atoi(optarg); + + + if(n_symbols < 1 || n_symbols > 127) { + print_error("Error: you typed an incorrect number"); + } + + /* generate password */ + char gpass[MAXLEN_PASSWORD]; + generate_password(gpass, n_symbols); + + insertPass(rootPath, argv[argc-1], gpass); + printf("Generated password: %s\n", gpass); + printf("Password added successfully for %s\n", argv[argc-1]); + + break; + } + case 'i': { + nonvisible_enter(1); /* change terminal work */ + + /* enter password */ + char pass_one[MAXLEN_PASSWORD], pass_two[MAXLEN_PASSWORD]; + + printf("Please type your password: "); + if(!fgets(pass_one, sizeof(pass_one), stdin)) { + nonvisible_enter(0); + print_error("Unexpected end of file\n"); + } + printf("\n"); + + printf("Please type your password again: "); + if(!fgets(pass_two, sizeof(pass_two), stdin)) { + nonvisible_enter(0); + print_error("Unexpected end of file\n"); + } + printf("\n"); + + nonvisible_enter(0); + + if(strcmp(pass_one, pass_two) == 0) { + printf("Password correct\n"); + + insertPass(rootPath, optarg, pass_one); + printf("Password added successfully for %s\n", optarg); + } + else printf("Passwords do not match\n"); + + break; + } + case 'R': { + char *main_path = malloc(sizeof(char) * strlen(optarg) + 1); + char *file_path = malloc(sizeof(char) * strlen(optarg) + 1); + + if(splitPath(optarg, main_path, file_path) == NULL) { // check correct input + print_error("[Error] The path you specified is incorrect\n"); + } + + if(delete_file(optarg)) { + delete_emptydir(main_path); + } + + free(main_path); + free(file_path); + break; + } + case 'I': { + int pid; + + // create direction: + pid = fork(); + if(pid == -1) call_error(100); + if(pid == 0) { /* new process */ + execlp("mkdir", "mkdir", "-vp", rootPath, NULL); + perror("mkdir"); + exit(4); + } + wait(&pid); + printf("LockPassword initialized\n"); + break; + } + + #if defined(DEBUG) + case 't': + { + char *main_path = malloc(sizeof(char) * strlen(optarg) + 1); + char *file_path = malloc(sizeof(char) * strlen(optarg) + 1); + + if(splitPath(optarg, main_path, file_path) == NULL) + printf("NULL\n"); + break; + } + #endif + + default: break; + + } + } + else + { + char *ptr; + if(strcmp(argv[argc-1], argv[0]) == 0) { + ptr = malloc(sizeof(char) * strlen(NAMEFILE) + 1); + strcpy(ptr, NAMEFILE); + } + else { + int buff_tree = strlen(NAMEFILE) + strlen(argv[argc-1]); + ptr = malloc(sizeof(char) * buff_tree + 1 + 1); + strcpy(ptr, NAMEFILE); + strcat(ptr, "/"); + strcat(ptr, argv[argc-1]); + } + show_tree(ptr); + + free(ptr); + } + + return 0; +} \ No newline at end of file -- cgit v1.2.3-18-g5258