bool agent_load_key(unsigned char key[KDF_HASH_LEN]) { _cleanup_free_ char *iterationbuf = NULL; _cleanup_free_ char *verify = NULL; _cleanup_free_ char *username = NULL; _cleanup_free_ char *password = NULL; int iterations; iterationbuf = config_read_string("iterations"); username = config_read_string("username"); if (!iterationbuf || !username || !config_exists("verify")) return false; iterations = strtoul(iterationbuf, NULL, 10); if (iterations <= 0) return false; for (;;) { free(password); password = password_prompt("Master Password", password ? "Incorrect master password; please try again." : NULL, "Please enter the LastPass master password for <%s>.", username); if (!password) return false; kdf_decryption_key(username, password, iterations, key); /* no longer need password contents, zero it */ secure_clear_str(password); verify = config_read_encrypted_string("verify", key); if (verify && !strcmp(verify, AGENT_VERIFICATION_STRING)) break; } return true; }
int main(int argc, char **argv) { GnomeKeyringResult result; GList *results; char *host; int i, tried, verbose = 0, remove = 0, list = 0; int set_domain = 0, set_host = 0, set_server = 0; int set_protocol = 0, set_port = 0, set_passfd = 0; int dry = 0; char *user = default_user(); char *domain = NULL; char *server = NULL; char *object = NULL; char *protocol = NULL; char *authtype = NULL; guint32 port = 0; int passfd = 0; char *use_keyring = GNOME_KEYRING_DEFAULT; for (i = 1; i < argc; i++) { if (ARG(u) || LARG(user)) { S_OPT(user); } else if (ARG(h) || LARG(host)) { S_OPT_Q(host); } else if (ARG(s) || LARG(server)) { S_OPT_Q(server); } else if (ARG(d) || LARG(domain)) { S_OPT_Q(domain); } else if (ARG(P) || LARG(protocol)) { S_OPT_Q(protocol); } else if (ARG(p) || LARG(port)) { I_OPT_Q(port); } else if (LARG(passfd)) { I_OPT_Q(passfd); } else if (ARG(v) || LARG(verbose)) { verbose = 1; } else if (ARG(R) || LARG(remove)) { MODE(remove); } else if (ARG(l) || LARG(list)) { MODE(list); } else if (ARG(n) || LARG(dry)) { dry = 1; verbose++; } else if (ARG(k) || LARG(keyring)) { S_OPT(use_keyring); } else if (LARG(help)) { usage(); return 0; } else { fprintf(stderr, "Unknown argument: %s\n", argv[i]); return 1; } } if (set_host && !(set_domain && set_server)) { char *dot = index(host, '.'); if (dot) { dot[0] = '\0'; dot++; if (!set_domain) domain = dot; if (!set_server) server = host; } else { server = host; domain = ""; } } else if (set_domain && set_server) { host = NULL; } else if (!list) { fprintf(stderr, "Must set --host or (--server and --domain)\n"); return 1; } if ((set_port + set_protocol) == 1) { if (set_protocol) { set_port_by_protocol(&port, protocol); } else if (set_port) { set_protocol_by_port(&protocol, port); } } else if (!(set_port || set_protocol || list)) { fprintf(stderr, "Must set at least one of --port or --protocol\n"); return 1; } if (set_protocol && !port) { fprintf(stderr, "Couldn't determine port for --protocol %s\n", protocol); return 1; } if (verbose && !list) { #define VALUE(X) printf("%s: %s\n", #X, X ? X : "(null)") VALUE(user); VALUE(domain); VALUE(server); VALUE(host); VALUE(protocol); #undef VALUE printf("port: %d\n", port); if (dry) return 0; } if (!gnome_keyring_is_available()) { fprintf(stderr, "No keyring available\n"); return 1; } if (list) return key_listing(verbose); for (tried = 0; tried < 2; tried++) { result = gnome_keyring_find_network_password_sync( user, domain, server, object, protocol, authtype, port, &results ); if (verbose) printf("attempt #%d: ", tried); if (result == OK) { GList *current; GnomeKeyringNetworkPasswordData *passdata; char *password; for (i = 0, current = results; current; i++, current = current->next) { passdata = (GnomeKeyringNetworkPasswordData *)current->data; password = passdata->password; if (verbose) { printf("Result[%d]=%s\n", i, password); continue; } if (remove) { result = gnome_keyring_item_delete_sync( passdata->keyring, passdata->item_id ); if (verbose) printf("Remove %s %d -> %s\n", passdata->keyring, passdata->item_id, result == OK ? "OK" : "NOT OK"); if (!current->next) return 0; continue; } printf("%s", password); return 0; } if (password) break; } if (remove) { printf("No such password\n"); return 1; } if (verbose) printf("nope\n"); if (!tried) { char *password; if (set_passfd) { password = password_from(passfd); } else { password = password_prompt(user, server, domain, protocol, port); } if (password) { guint32 item_id; gnome_keyring_set_network_password_sync( use_keyring, user, domain, server, object, protocol, authtype, port, password, &item_id ); if (verbose) printf("Stored password? %s\n", item_id ? "yes" : "no"); } } } return 0; }
int cmd_login(int argc, char **argv) { static struct option long_options[] = { {"trust", no_argument, NULL, 't'}, {"plaintext-key", no_argument, NULL, 'P'}, {"force", no_argument, NULL, 'f'}, {"color", required_argument, NULL, 'C'}, {0, 0, 0, 0} }; int option; int option_index; bool trust = false; bool plaintext_key = false; bool force = false; char *username; _cleanup_free_ char *error = NULL; _cleanup_free_ char *password = NULL; int iterations; struct session *session; unsigned char key[KDF_HASH_LEN]; char hex[KDF_HEX_LEN]; while ((option = getopt_long(argc, argv, "f", long_options, &option_index)) != -1) { switch (option) { case 't': trust = true; break; case 'P': plaintext_key = true; break; case 'f': force = true; break; case 'C': terminal_set_color_mode( parse_color_mode_string(optarg)); break; case '?': default: die_usage(cmd_login_usage); } } if (argc - optind != 1) die_usage(cmd_login_usage); if (!force && plaintext_key && !ask_yes_no(false, "You have used the --plaintext-key option. This option will greatly reduce the security of your passwords. You are advised, instead, to use the agent, whose timeout can be disabled by settting LPASS_AGENT_TIMEOUT=0. Are you sure you would like to do this?")) die("Login aborted. Try again without --plaintext-key."); username = argv[optind]; iterations = lastpass_iterations(username); if (!iterations) die("Unable to fetch iteration count. Check your internet connection and be sure your username is valid."); do { free(password); password = password_prompt("Master Password", error, "Please enter the LastPass master password for <%s>.", username); if (!password) die("Failed to enter correct password."); kdf_login_key(username, password, iterations, hex); kdf_decryption_key(username, password, iterations, key); free(error); error = NULL; session = lastpass_login(username, hex, key, iterations, &error, trust); } while (!session_is_valid(session)); config_unlink("plaintext_key"); if (plaintext_key) config_write_buffer("plaintext_key", (char *)key, KDF_HASH_LEN); agent_save(username, iterations, key); session_save(session, key); session_free(session); session = NULL; terminal_printf(TERMINAL_FG_GREEN TERMINAL_BOLD "Success" TERMINAL_RESET ": Logged in as " TERMINAL_UNDERLINE "%s" TERMINAL_RESET ".\n", username); return 0; }
/* Returns a new Tox object on success. * If object fails to initialize the toxic process will terminate. */ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW *new_err) { Tox *m = NULL; FILE *fp = fopen(data_path, "rb"); if (fp != NULL) { /* Data file exists */ off_t len = file_size(data_path); if (len == 0) { fclose(fp); exit_toxic_err("failed in load_tox", FATALERR_FILEOP); } char data[len]; if (fread(data, sizeof(data), 1, fp) != 1) { fclose(fp); exit_toxic_err("failed in load_tox", FATALERR_FILEOP); } bool is_encrypted = tox_is_data_encrypted((uint8_t *) data); /* attempt to encrypt an already encrypted data file */ if (arg_opts.encrypt_data && is_encrypted) { fclose(fp); exit_toxic_err("failed in load_tox", FATALERR_ENCRYPT); } if (arg_opts.unencrypt_data && is_encrypted) queue_init_message("Data file '%s' has been unencrypted", data_path); else if (arg_opts.unencrypt_data) queue_init_message("Warning: passed --unencrypt-data option with unencrypted data file '%s'", data_path); if (is_encrypted) { if (!arg_opts.unencrypt_data) user_password.data_is_encrypted = true; size_t pwlen = 0; int pweval = user_settings->password_eval[0]; if (!pweval) { system("clear"); // TODO: is this portable? printf("Enter password (q to quit) "); } size_t plain_len = len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; char plain[plain_len]; while (true) { if (pweval) { pwlen = password_eval(user_password.pass, sizeof(user_password.pass)); } else { pwlen = password_prompt(user_password.pass, sizeof(user_password.pass)); } user_password.len = pwlen; if (strcasecmp(user_password.pass, "q") == 0) { fclose(fp); exit(0); } if (pwlen < MIN_PASSWORD_LEN) { system("clear"); sleep(1); printf("Invalid password. Try again. "); pweval = 0; continue; } TOX_ERR_DECRYPTION pwerr; tox_pass_decrypt((uint8_t *) data, len, (uint8_t *) user_password.pass, pwlen, (uint8_t *) plain, &pwerr); if (pwerr == TOX_ERR_DECRYPTION_OK) { tox_opts->savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE; tox_opts->savedata_data = (uint8_t *) plain; tox_opts->savedata_length = plain_len; m = tox_new(tox_opts, new_err); if (m == NULL) { fclose(fp); return NULL; } break; } else if (pwerr == TOX_ERR_DECRYPTION_FAILED) { system("clear"); sleep(1); printf("Invalid password. Try again. "); pweval = 0; } else { fclose(fp); exit_toxic_err("tox_pass_decrypt() failed", pwerr); } } } else { /* data is not encrypted */ tox_opts->savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE; tox_opts->savedata_data = (uint8_t *) data; tox_opts->savedata_length = len; m = tox_new(tox_opts, new_err); if (m == NULL) { fclose(fp); return NULL; } } fclose(fp); } else { /* Data file does not/should not exist */ if (file_exists(data_path)) exit_toxic_err("failed in load_tox", FATALERR_FILEOP); tox_opts->savedata_type = TOX_SAVEDATA_TYPE_NONE; m = tox_new(tox_opts, new_err); if (m == NULL) return NULL; if (store_data(m, data_path) == -1) exit_toxic_err("failed in load_tox", FATALERR_FILEOP); } return m; }
/* Ask user if they would like to encrypt the data file and set password */ static void first_time_encrypt(const char *msg) { char ch[256] = {0}; do { system("clear"); printf("%s ", msg); if (!strcasecmp(ch, "y\n") || !strcasecmp(ch, "n\n") || !strcasecmp(ch, "yes\n") || !strcasecmp(ch, "no\n") || !strcasecmp(ch, "q\n")) break; } while (fgets(ch, sizeof(ch), stdin)); printf("\n"); if (ch[0] == 'q' || ch[0] == 'Q') exit(0); if (ch[0] == 'y' || ch[0] == 'Y') { int len = 0; bool valid_password = false; char passconfirm[MAX_PASSWORD_LEN + 1] = {0}; printf("Enter a new password (must be at least %d characters) ", MIN_PASSWORD_LEN); while (valid_password == false) { len = password_prompt(user_password.pass, sizeof(user_password.pass)); user_password.len = len; if (strcasecmp(user_password.pass, "q") == 0) exit(0); if (string_is_empty(passconfirm) && (len < MIN_PASSWORD_LEN || len > MAX_PASSWORD_LEN)) { printf("Password must be between %d and %d characters long. ", MIN_PASSWORD_LEN, MAX_PASSWORD_LEN); continue; } if (string_is_empty(passconfirm)) { printf("Enter password again "); snprintf(passconfirm, sizeof(passconfirm), "%s", user_password.pass); continue; } if (strcmp(user_password.pass, passconfirm) != 0) { memset(passconfirm, 0, sizeof(passconfirm)); memset(user_password.pass, 0, sizeof(user_password.pass)); printf("Passwords don't match. Try again. "); continue; } valid_password = true; } queue_init_message("Data file '%s' is encrypted", DATA_FILE); memset(passconfirm, 0, sizeof(passconfirm)); user_password.data_is_encrypted = true; } system("clear"); }