diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | LICENSE.md | 24 | ||||
-rwxr-xr-x | compulation | 4 | ||||
-rw-r--r-- | easydir.c | 113 | ||||
-rw-r--r-- | easydir.h | 3 | ||||
-rw-r--r-- | handerror.c | 15 | ||||
-rw-r--r-- | handerror.h | 2 | ||||
-rw-r--r-- | main.c | 398 |
8 files changed, 562 insertions, 0 deletions
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 <http://unlicense.org/>
\ 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 <malloc.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/wait.h> +#include <errno.h> + +#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 <stdio.h> +#include <stdlib.h> + +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 @@ -0,0 +1,398 @@ +#include <stdio.h> +#include <termios.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/wait.h> +#include <getopt.h> +#include <errno.h> +#include <dirent.h> +#include <time.h> + +#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 |