diff --git a/src/friendlist.c b/src/friendlist.c index f3ff622..01ca0a5 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -999,7 +999,6 @@ static void friendlist_onAv(ToxWindow *self, ToxAv *av, int call_index) { int id = toxav_get_peer_id(av, call_index, 0); - /*id++;*/ if ( id != ErrorInternal && id >= Friends.max_idx) return; diff --git a/src/log.h b/src/log.h index 430705c..5cca27f 100644 --- a/src/log.h +++ b/src/log.h @@ -26,7 +26,6 @@ struct chatlog { FILE *file; uint64_t lastwrite; - int pos; bool log_on; /* specific to current chat window */ }; diff --git a/src/misc_tools.c b/src/misc_tools.c index 3817854..0729eb7 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -306,8 +306,8 @@ void bytes_convert_str(char *buf, int size, uint64_t bytes) } /* checks if a file exists. Returns true or false */ -bool file_exists(const char *fp) +bool file_exists(const char *path) { struct stat s; - return stat(fp, &s) == 0; + return stat(path, &s) == 0; } diff --git a/src/misc_tools.h b/src/misc_tools.h index ab7ddbd..8d14b61 100644 --- a/src/misc_tools.h +++ b/src/misc_tools.h @@ -110,6 +110,6 @@ int char_rfind(const char *s, char ch, int len); void bytes_convert_str(char *buf, int size, uint64_t bytes); /* checks if a file exists. Returns true or false */ -bool file_exists(const char *fp); +bool file_exists(const char *path); #endif /* #define _misc_tools_h */ diff --git a/src/toxic.c b/src/toxic.c index d32cd77..07e3b4d 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -38,8 +38,10 @@ #include #include #include +#include #include +#include #include "configdir.h" #include "toxic.h" @@ -79,6 +81,15 @@ struct _cqueue_thread cqueue_thread; struct arg_opts arg_opts; struct user_settings *user_settings_ = NULL; +#define MIN_PASSWORD_LEN 6 +#define MAX_PASSWORD_LEN 256 + +static struct _user_password { + bool data_is_encrypted; + char pass[MAX_STR_SIZE]; + int len; +} user_password; + static void catch_SIGINT(int sig) { Winthread.sig_exit_toxic = true; @@ -107,6 +118,7 @@ static void init_signal_catchers(void) void exit_toxic_success(Tox *m) { store_data(m, DATA_FILE); + memset(&user_password, 0, sizeof(struct _user_password)); close_all_file_senders(m); kill_all_windows(m); @@ -459,6 +471,69 @@ static void load_friendlist(Tox *m) sort_friendlist_index(); } +/* return length of password on success, 0 on failure */ +static int password_prompt(char *buf, int size) +{ + printf("> "); + + /* disable terminal echo */ + struct termios oflags, nflags; + tcgetattr(fileno(stdin), &oflags); + nflags = oflags; + nflags.c_lflag &= ~ECHO; + nflags.c_lflag |= ECHONL; + + if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) + return 0; + + fgets(buf, size, stdin); + int len = strlen(buf); + + if (len > 0) + buf[--len] = '\0'; /* rm newline char */ + + /* re-enable terminal echo */ + if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) + return 0; + + return len; +} + +/* Ask user if they would like to encrypt the data file on first usage */ +static void first_time_running(void) +{ + char ch[3] = {0}; + + do { + system("clear"); + printf("Encrypt data file? Y/n \n"); + + if (!strcasecmp(ch, "y\n") || !strcasecmp(ch, "n\n")) + break; + + } while (fgets(ch, sizeof(ch), stdin)); + + const char *msg = NULL; + int len = 0; + + if (ch[0] == 'y') { + do { + printf("Enter a new password (must be at least %d characters)\n", MIN_PASSWORD_LEN); + len = password_prompt(user_password.pass, sizeof(user_password.pass)); + user_password.len = len; + } while (len < MIN_PASSWORD_LEN || len > MAX_PASSWORD_LEN); + + user_password.data_is_encrypted = true; + msg = "Data file has been encrypted"; + } else { + user_password.data_is_encrypted = false; + msg = "Data file has not been encrypted"; + } + + system("clear"); + queue_init_message(msg); +} + /* * Store Messenger to given location * Return 0 stored successfully or ignoring data file @@ -467,7 +542,7 @@ static void load_friendlist(Tox *m) * Return -3 opening path failed * Return -4 fwrite failed */ -int store_data(Tox *m, char *path) +int store_data(Tox *m, const char *path) { if (arg_opts.ignore_data_file) return 0; @@ -475,13 +550,17 @@ int store_data(Tox *m, char *path) if (path == NULL) return -1; - int len = tox_size(m); + int len = user_password.data_is_encrypted ? tox_encrypted_size(m) : tox_size(m); char *buf = malloc(len); if (buf == NULL) return -2; - tox_save(m, (uint8_t *) buf); + if (user_password.data_is_encrypted) + tox_encrypted_save(m, (uint8_t *) buf, (uint8_t *) user_password.pass, + user_password.len); + else + tox_save(m, (uint8_t *) buf); FILE *fd = fopen(path, "wb"); @@ -526,7 +605,30 @@ static void load_data(Tox *m, char *path) exit_toxic_err("failed in load_data", FATALERR_FREAD); } - tox_load(m, (uint8_t *) buf, len); + user_password.data_is_encrypted = tox_is_data_encrypted((uint8_t *) buf); + int pwlen = 0; + + if (user_password.data_is_encrypted) { + system("clear"); + printf("Enter password\n"); + + do { + pwlen = password_prompt(user_password.pass, sizeof(user_password.pass)); + user_password.len = pwlen; + + if (-1 != tox_encrypted_load(m, (uint8_t *) buf, len, (uint8_t *) user_password.pass, pwlen)) { + break; + } else { + sleep(2); + printf("Invalid password. Try again.\n"); + } + } while (true); + + system("clear"); + } else { + tox_load(m, (uint8_t *) buf, len); + } + load_friendlist(m); load_blocklist(BLOCK_FILE); @@ -738,7 +840,7 @@ static void parse_args(int argc, char *argv[]) #define DATANAME "data" #define BLOCKNAME "data-blocklist" -static int init_data_files(void) +static int init_default_data_files(void) { if (arg_opts.use_custom_data) return 0; @@ -746,28 +848,26 @@ static int init_data_files(void) char *user_config_dir = get_user_config_dir(); int config_err = create_user_config_dirs(user_config_dir); - if (DATA_FILE == NULL ) { - if (config_err) { - DATA_FILE = strdup(DATANAME); - BLOCK_FILE = strdup(BLOCKNAME); + if (config_err) { + DATA_FILE = strdup(DATANAME); + BLOCK_FILE = strdup(BLOCKNAME); - if (DATA_FILE == NULL || BLOCK_FILE == NULL) - exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY); - } else { - DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(DATANAME) + 1); - BLOCK_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(BLOCKNAME) + 1); + if (DATA_FILE == NULL || BLOCK_FILE == NULL) + exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY); + } else { + DATA_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(DATANAME) + 1); + BLOCK_FILE = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen(BLOCKNAME) + 1); - if (DATA_FILE == NULL || BLOCK_FILE == NULL) - exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY); + if (DATA_FILE == NULL || BLOCK_FILE == NULL) + exit_toxic_err("failed in load_data_structures", FATALERR_MEMORY); - strcpy(DATA_FILE, user_config_dir); - strcat(DATA_FILE, CONFIGDIR); - strcat(DATA_FILE, DATANAME); + strcpy(DATA_FILE, user_config_dir); + strcat(DATA_FILE, CONFIGDIR); + strcat(DATA_FILE, DATANAME); - strcpy(BLOCK_FILE, user_config_dir); - strcat(BLOCK_FILE, CONFIGDIR); - strcat(BLOCK_FILE, BLOCKNAME); - } + strcpy(BLOCK_FILE, user_config_dir); + strcat(BLOCK_FILE, CONFIGDIR); + strcat(BLOCK_FILE, BLOCKNAME); } free(user_config_dir); @@ -800,7 +900,11 @@ int main(int argc, char *argv[]) /* Make sure all written files are read/writeable only by the current user. */ umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - int config_err = init_data_files(); + int config_err = init_default_data_files(); + bool first_run = !file_exists(DATA_FILE); + + if (first_run) + first_time_running(); /* init user_settings struct and load settings from conf file */ user_settings_ = calloc(1, sizeof(struct user_settings)); @@ -808,11 +912,10 @@ int main(int argc, char *argv[]) if (user_settings_ == NULL) exit_toxic_err("failed in main", FATALERR_MEMORY); - char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL; + const char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL; int settings_err = settings_load(user_settings_, p); Tox *m = init_tox(); - init_term(); /* enable stderr for debugging */ if (!arg_opts.debug) @@ -824,6 +927,7 @@ int main(int argc, char *argv[]) if (!arg_opts.ignore_data_file) load_data(m, DATA_FILE); + init_term(); prompt = init_windows(m); prompt_init_statusbar(prompt, m); diff --git a/src/toxic.h b/src/toxic.h index 7ee2c8e..f98f6b6 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -88,7 +88,7 @@ typedef enum _FATAL_ERRS { void exit_toxic_success(Tox *m); void exit_toxic_err(const char *errmsg, int errcode); -int store_data(Tox *m, char *path); +int store_data(Tox *m, const char *path); void on_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata); void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata);