diff options
Diffstat (limited to 'src/implementation.c')
-rw-r--r-- | src/implementation.c | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/src/implementation.c b/src/implementation.c new file mode 100644 index 0000000..3ba2be7 --- /dev/null +++ b/src/implementation.c @@ -0,0 +1,256 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <termios.h> +#include <string.h> +#include <time.h> +#include <errno.h> + +#include "handerror.h" +#include "easydir.h" +#include "implementation.h" + +/* define in implementation.h */ +// GPG_PUBLICKEY_MAXLENGTH 1025 + +#define BASH_EXEC_COPY "lpass_copy.sh" + +// == global var == +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 + +static void copyText(char *password) +{ + size_t size = (strlen(password) + strlen(BASH_EXEC_COPY) + 1) * sizeof(char); + char *command = malloc(size); + + snprintf(command, size, "%s %s", BASH_EXEC_COPY, password); + system(command); + + free(command); +} + +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 *getGPGKey(char *dest, size_t size) +{ + FILE *fileGPG = fopen(".gpg-key", "r"); + if(fileGPG == NULL) { + if(errno == ENOENT) printError("error: No GPG key exists\n"); + callError(121); + } + + if(!fgets(dest, size, fileGPG)) { + callError(122); + } + fclose(fileGPG); + + return dest; +} + +char* getPassword(char *path_pass, char *password, size_t size, int flag_copy) +{ + 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", path_pass, gPath_pass, NULL}; + easyFork("gpg", arguments); + + FILE *filePass = fopen(path_pass, "r"); + if(filePass == NULL) callError(127); + + if(!fgets(password, size, filePass)) { + callError(111); + } + fclose(filePass); + + if(flag_copy) copyText(password); + + remove(path_pass); + free(secret_gpgkey); + return password; +} + +void nonvisibleEnter(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); +} + +void insertPass(char *add_path, char *password, int flag_copy) +{ + /* gPath_rootdir = /home/[username]/.lock-password/ + add_path = banks/france/[number] + gPath_pass = banks/france/[number].gpg + gPath_subdir = banks/france */ + + int size_gpgkey = sizeof(char) * GPG_PUBLICKEY_MAXLENGTH; + char *secret_gpgkey = (char *) malloc(size_gpgkey); + getGPGKey(secret_gpgkey, size_gpgkey); + + char *arguments1[] = {"mkdir", "-p", gPath_subdir, NULL}; + easyFork("mkdir", arguments1); + + // create file, copy password there + FILE *filePass; + filePass = fopen(add_path, "w"); + if(filePass == NULL) { + callError(108); + } + fputs(password, filePass); + fclose(filePass); + + if(flag_copy) copyText(password); + + // encryption + char *arguments2[] = {"gpg", "--quiet", "--yes", "-r", secret_gpgkey, "-e", add_path, NULL}; + easyFork("gpg", arguments2); + + remove(add_path); + free(secret_gpgkey); +} + +char *typePass(char *text, char *dest, int minlen, int maxlen) +{ + printf("%s", text); + if(fgets(dest, sizeof(char)*maxlen, stdin) == NULL) { + nonvisibleEnter(0); + printError("lpass: Unexpected end of file\n"); + } + + int len = strlen(dest); + if(len < minlen || len > maxlen) { + nonvisibleEnter(0); + printError("lpass: incorrect password\n"); + } + + if(dest[len-1] == '\n') { + dest[len-1] = '\0'; + } + + #if defined(DEBUG) + printf("%s", dest); + #endif + + printf("\n"); // for new line + return dest; +} + +int userEnterPassword(int minlen, int maxlen, char *path_insert, int flag_echo, int flag_copy) +{ + char *pass_one = (char *) malloc(sizeof(char) * maxlen); + int rvalue = 0; + if(!flag_echo) { + char *pass_two = (char *) malloc(sizeof(char) * maxlen); + + nonvisibleEnter(1); // change terminal work + typePass("Type your password: ", pass_one, minlen, maxlen); + typePass("Type your password again: ", pass_two, minlen, maxlen); + nonvisibleEnter(0); + + if(strcmp(pass_one, pass_two) == 0) { + insertPass(path_insert, pass_one, flag_copy); + rvalue = 1; + } + free(pass_two); + } + else { + typePass("Type your password: ", pass_one, minlen, maxlen); + insertPass(path_insert, pass_one, flag_copy); + rvalue = 1; + } + + free(pass_one); + return rvalue; +} + +char *generatePassword(char *dest, int amount, int max_len) +{ + 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[max_len]; + 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; +} + +unsigned long hash(char *str) +{ + unsigned long hash = 5381; + char c; + + while( (c = *str++) ) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} + +static void clearStdinBuff() +{ + char garbage; + + while( (garbage = fgetc(stdin)) != '\n' && garbage != EOF ) + ; +} + + +int getOverwriteAnswer(char *path) +{ + int buffSize = (strlen("Password for '' exists. Overwrite? (Y/N)") + strlen(path) + 1)* sizeof(char); + char *text = malloc(buffSize); + snprintf(text, buffSize, "Password for '%s' exists. Overwrite? (Y/N)", path); + printf("%s ", text); + + int answer; + while((answer = fgetc(stdin))) + { + clearStdinBuff(); + switch(answer) + { + case 'Y': + case 'y': { free(text); return 1; } + case 'N': + case 'n': { free(text); return 0; } + case EOF: printError("Error: Unexpected end of file\n"); + default: { printf("%s ", text); break; } + } + } + + free(text); + return -1; +} |