-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.c
157 lines (134 loc) · 5.81 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <argp.h>
#include "crypto/decrypt_file.h"
#include "utils/logger.h"
#include "crypto/encrypt_file.h"
#include "utils/file_utils.h"
#define DEFAULT_OUTPUT_FILE "output.crypt"
/* Parsing command line arguments using argp. Code based on this examples:
* http://www.gnu.org/software/libc/manual/html_node/Argp-Example-3.html
* http://www.gnu.org/software/libc/manual/html_node/Argp-Example-4.html */
const char *argp_program_version = "libsodium-file-crypter version 1.0.0";
const char *argp_program_bug_address = "https://github.com/jpiechowka/libsodium-file-crypter/issues";
unsigned char crypto_key[crypto_secretstream_xchacha20poly1305_KEYBYTES];
// Program documentation
static char doc[] = "Linux file encryption utility written in C using libsodium";
// A description of the arguments we accept
static char args_doc[] = "FILE PASSWORD";
// The options we understand
static struct argp_option options[] = {
{"verbose", 'v', 0, 0, "Increase verbosity - show debug messages"},
{"debug", 0, 0, OPTION_ALIAS, 0},
{"output", 'o', "FILE", 0, "Specify output file instead of default: output.crypt"},
{"force", 'f', 0, 0, "Force overwrite of output file if it already exists"},
{"encrypt", 'e', 0, 0, "Encrypt the specified file. Specifying operation mode is mandatory for program to run"},
{"decrypt", 'd', 0, 0, "Decrypt the specified file. Specifying operation mode is mandatory for program to run"},
{0}
};
// Used by main to communicate with parse_opt
struct arguments {
char *args[2]; /* FILE & PASSWORD */
bool verbose;
bool forceOverwrite;
int operationMode; /* 1 for encryption, 2 for decryption, other values treated as invalid */
char *outputFile;
};
static error_t parse_opt(int key, char *arg, struct argp_state *state) {
/* Get the input argument from argp_parse, which we know is a pointer to our arguments structure */
struct arguments *arguments = state->input;
switch (key) {
case 'v':
arguments->verbose = true;
break;
case 'o':
arguments->outputFile = arg;
break;
case 'f':
arguments->forceOverwrite = true;
break;
case 'd':
arguments->operationMode = 2;
break;
case 'e':
arguments->operationMode = 1;
break;
case ARGP_KEY_ARG: {
if (state->arg_num >= 2) {
/* Too many arguments. */
log_error("Too many arguments provided");
argp_usage(state);
}
arguments->args[state->arg_num] = arg;
break;
}
case ARGP_KEY_END: {
if (state->arg_num < 2) {
/* Not enough arguments. */
log_error("Not enough arguments provided");
argp_usage(state);
}
break;
}
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
// Our argp parser
static struct argp argp = {options, parse_opt, args_doc, doc};
int main(int argc, char *argv[]) {
struct arguments arguments;
/* Default values */
arguments.verbose = false;
arguments.forceOverwrite = false;
arguments.operationMode = -1; /* Default is not specified. User needs to provide this value */
arguments.outputFile = DEFAULT_OUTPUT_FILE;
/* Parse our arguments; every option seen by parse_opt will be reflected in arguments */
argp_parse(&argp, argc, argv, 0, 0, &arguments);
if (arguments.verbose == true) {
toggle_debug_logging(true);
}
/* Check if operation mode is provided by user. If not exit */
if (!(arguments.operationMode == 1 || arguments.operationMode == 2)) {
log_error(
"No operation mode provided. Make sure to use [-d/--decrypt] or [-e/--encrypt] options to specify operation mode");
return 1;
}
/* Check if output file exists */
if (check_if_file_exists(arguments.outputFile)) {
if (arguments.forceOverwrite == false) {
log_error_concat_str(arguments.outputFile,
" exists. Use [-f/--force] option to force overwrite the output file");
return 1;
} else {
log_warning_concat_str("[-f/--force] option used. Overwriting output file: ", arguments.outputFile);
}
}
/* arguments.args[0] - FILE
* arguments.args[1] - PASSWORD*/
if (arguments.operationMode == 1) {
/* Encryption */
/* Check if file to encrypt is not the same as output file*/
if (are_two_file_paths_the_same(arguments.args[0], arguments.outputFile) == true) {
log_error("File to decrypt and output file are the same. Program cannot operate on the same file");
log_error("Specify output file with [-o/--output] option");
return 1;
}
if (encrypt_file(arguments.args[0], arguments.outputFile, arguments.args[1]) != 0) {
log_error_concat_str("There was an error while performing encryption of the file: ", arguments.args[0]);
return 1;
}
} else if (arguments.operationMode == 2) {
/* Decryption */
/* Check if file to decrypt is not the same as output file*/
if (are_two_file_paths_the_same(arguments.args[0], arguments.outputFile) == true) {
log_error("File to decrypt and output file are the same. Program cannot operate on the same file");
log_error("Specify output file with [-o/--output] option");
return 1;
}
if (decrypt_file(arguments.args[0], arguments.outputFile, arguments.args[1]) != 0) {
log_error_concat_str("There was an error while performing decryption of the file: ", arguments.args[0]);
return 1;
};
}
return 0;
}