예제 #1
0
파일: agent.c 프로젝트: JBTech/lastpass-cli
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;
}
예제 #2
0
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;
}
예제 #3
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;
}
예제 #4
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;
}
예제 #5
0
/* 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");
}