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 | 
