std::vector ParseJsonToSshKeys()

in src/oslogin_utils.cc [677:743]


std::vector<string> ParseJsonToSshKeys(const string& json) {
  std::vector<string> result;
  json_object* root = ParseJsonRoot(json);
  if (root == NULL) {
    return result;
  }

  // Locate the sshPublicKeys object.
  json_object* login_profiles;
  if (!json_object_object_get_ex(root, "loginProfiles", &login_profiles)) {
    goto cleanup;
  }
  if (json_object_get_type(login_profiles) != json_type_array) {
    goto cleanup;
  }
  login_profiles = json_object_array_get_idx(login_profiles, 0);

  json_object* ssh_public_keys;
  if (!json_object_object_get_ex(login_profiles, "sshPublicKeys", &ssh_public_keys)) {
    goto cleanup;
  }

  if (json_object_get_type(ssh_public_keys) != json_type_object) {
    goto cleanup;
  }

  {
  // Extra braces to indicate scope of key, obj below to compiler. Otherwise
  // g++ complains that `goto` bypasses initializers.
  json_object_object_foreach(ssh_public_keys, key, obj) {
    (void)(key);
    if (json_object_get_type(obj) != json_type_object) {
      continue;
    }
    string key_to_add = "";
    bool expired = false;
    json_object_object_foreach(obj, key, val) {
      string string_key(key);
      int val_type = json_object_get_type(val);
      if (string_key == "key") {
        if (val_type != json_type_string) {
          continue;
        }
        key_to_add = json_object_get_string(val);
      }
      if (string_key == "expirationTimeUsec") {
        if (val_type == json_type_int || val_type == json_type_string) {
          uint64_t expiry_usec = (uint64_t)json_object_get_int64(val);
          struct timeval tp;
          gettimeofday(&tp, NULL);
          uint64_t cur_usec = tp.tv_sec * 1000000 + tp.tv_usec;
          expired = cur_usec > expiry_usec;
        } else {
          continue;
        }
      }
    }
    if (!key_to_add.empty() && !expired) {
      result.push_back(key_to_add);
    }
  }
  }

cleanup:
  json_object_put(root);
  return result;
}