Exemplo n.º 1
0
int
seaf_passwd_manager_set_passwd (SeafPasswdManager *mgr,
                                const char *repo_id,
                                const char *user,
                                const char *passwd,
                                GError **error)
{
    SeafRepo *repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);
    DecryptKey *crypt_key;
    GString *hash_key;

    if (!repo) {
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
                     "Invalid repo");
        return -1;
    }

    if (!repo->encrypted) {
        seaf_repo_unref (repo);
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
                     "Repo is not encrypted");
        return -1;
    }

    if (repo->enc_version != 1 && repo->enc_version != 2) {
        seaf_repo_unref (repo);
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
                     "Unsupported encryption version");
        return -1;
    }

    if (seafile_verify_repo_passwd (repo->id, passwd,
                                    repo->magic, repo->enc_version) < 0) {
        seaf_repo_unref (repo);
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Incorrect password");
        return -1;
    }

    crypt_key = g_new0 (DecryptKey, 1);
    if (!crypt_key) {
        g_warning ("Failed to alloc crypt key struct.\n");
        seaf_repo_unref (repo);
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_INTERNAL,
                     "Internal server error");
        return -1;
    }

    if (seafile_decrypt_repo_enc_key (repo->enc_version, passwd, repo->random_key,
                                      crypt_key->key, crypt_key->iv) < 0) {
        seaf_repo_unref (repo);
        g_free (crypt_key);
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Incorrect password");
        return -1;
    }
    crypt_key->expire_time = (guint64)time(NULL) + REAP_THRESHOLD;
    crypt_key->enc_version = repo->enc_version;

    hash_key = g_string_new (NULL);
    g_string_printf (hash_key, "%s.%s", repo_id, user);

    /* g_debug ("[passwd mgr] Set passwd for %s\n", hash_key->str); */

    g_hash_table_insert (mgr->priv->decrypt_keys,
                         g_string_free (hash_key, FALSE),
                         crypt_key);
    seaf_repo_unref (repo);

    return 0;
}
Exemplo n.º 2
0
char *
seaf_clone_manager_add_download_task (SeafCloneManager *mgr, 
                                      const char *repo_id,
                                      int repo_version,
                                      const char *peer_id,
                                      const char *repo_name,
                                      const char *token,
                                      const char *passwd,
                                      const char *magic,
                                      int enc_version,
                                      const char *random_key,
                                      const char *wt_parent,
                                      const char *peer_addr,
                                      const char *peer_port,
                                      const char *email,
                                      const char *more_info,
                                      GError **error)
{
    SeafRepo *repo;
    char *wt_tmp, *worktree;
    char *ret;

    if (!seaf->started) {
        seaf_message ("System not started, skip adding clone task.\n");
        return NULL;
    }

#ifdef USE_GPL_CRYPTO
    if (repo_version == 0 || (passwd && enc_version < 2)) {
        seaf_warning ("Don't support syncing old version libraries.\n");
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
                     "Don't support syncing old version libraries");
        return NULL;
    }
#endif

    if (passwd &&
        !check_encryption_args (magic, enc_version, random_key, error))
        return NULL;

    /* After a repo was unsynced, the sync task may still be blocked in the
     * network, so the repo is not actually deleted yet.
     * In this case just return an error to the user.
     */
    SyncInfo *sync_info = seaf_sync_manager_get_sync_info (seaf->sync_mgr,
                                                           repo_id);
    if (sync_info && sync_info->in_sync) {
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Repo already exists");
        return NULL;
    }

    repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);

    if (repo != NULL && repo->head != NULL) {
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Repo already exists");
        return NULL;
    }

    if (is_duplicate_task (mgr, repo_id)) {
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, 
                     "Task is already in progress");
        return NULL;
    }

    if (passwd &&
        seafile_verify_repo_passwd(repo_id, passwd, magic, enc_version) < 0) {
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Incorrect password");
        return NULL;
    }

    IgnoreReason reason;
    if (should_ignore_on_checkout (repo_name, &reason)) {
        if (reason == IGNORE_REASON_END_SPACE_PERIOD)
            g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
                         "Library name ends with space or period character");
        else
            g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
                         "Library name contains invalid characters such as ':', '*', '|', '?'");
        return NULL;
    }

    wt_tmp = g_build_filename (wt_parent, repo_name, NULL);

    worktree = make_worktree_for_download (mgr, wt_tmp, error);
    if (!worktree) {
        g_free (wt_tmp);
        return NULL;
    }

    /* If a repo was unsynced and then downloaded again, there may be
     * a garbage record for this repo. We don't want the downloaded blocks
     * be removed by GC.
     */
    if (repo_version > 0)
        seaf_repo_manager_remove_garbage_repo (seaf->repo_mgr, repo_id);

    /* Delete orphan information in the db in case the repo was corrupt. */
    if (!repo)
        seaf_repo_manager_remove_repo_ondisk (seaf->repo_mgr, repo_id, FALSE);

    ret = add_task_common (mgr, repo_id, repo_version,
                           peer_id, repo_name, token, passwd,
                           enc_version, random_key,
                           worktree, peer_addr, peer_port,
                           email, more_info, TRUE, error);
    g_free (worktree);
    g_free (wt_tmp);

    return ret;
}
Exemplo n.º 3
0
char *
seaf_repo_manager_create_virtual_repo (SeafRepoManager *mgr,
                                       const char *origin_repo_id,
                                       const char *path,
                                       const char *repo_name,
                                       const char *repo_desc,
                                       const char *owner,
                                       const char *passwd,
                                       GError **error)
{
    SeafRepo *origin_repo = NULL;
    SeafCommit *origin_head = NULL;
    char *repo_id = NULL;
    char *dir_id = NULL;
    char *orig_owner = NULL;

    if (seaf_repo_manager_is_virtual_repo (mgr, origin_repo_id)) {
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Cannot create sub-library from a sub-library");
        return NULL;
    }

    repo_id = get_existing_virtual_repo (mgr, origin_repo_id, path);
    if (repo_id) {
        return repo_id;
    }

    origin_repo = seaf_repo_manager_get_repo (mgr, origin_repo_id);
    if (!origin_repo) {
        seaf_warning ("Failed to get origin repo %.10s\n", origin_repo_id);
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Origin library not exists");
        return NULL;
    }

    if (origin_repo->encrypted) {
        if (origin_repo->enc_version < 2) {
            g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
                         "Library encryption version must be higher than 2");
            seaf_repo_unref (origin_repo);
            return NULL;
        }

        if (!passwd || passwd[0] == 0) {
            g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
                         "Password is not set");
            seaf_repo_unref (origin_repo);
            return NULL;
        }

        if (seafile_verify_repo_passwd (origin_repo_id,
                                        passwd,
                                        origin_repo->magic,
                                        origin_repo->enc_version) < 0) {
            g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                         "Incorrect password");
            seaf_repo_unref (origin_repo);
            return NULL;
        }
    }

    origin_head = seaf_commit_manager_get_commit (seaf->commit_mgr,
                                                  origin_repo->id,
                                                  origin_repo->version,
                                                  origin_repo->head->commit_id);
    if (!origin_head) {
        seaf_warning ("Failed to get head commit %.8s of repo %s.\n",
                      origin_repo->head->commit_id, origin_repo->id);
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Bad origin repo head");
        goto error;
    }

    dir_id = seaf_fs_manager_get_seafdir_id_by_path (seaf->fs_mgr,
                                                     origin_repo->store_id,
                                                     origin_repo->version,
                                                     origin_head->root_id,
                                                     path, NULL);
    if (!dir_id) {
        seaf_warning ("Path %s doesn't exist or is not a dir in repo %.10s.\n",
                      path, origin_repo_id);
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Bad path");
        goto error;
    }

    repo_id = gen_uuid();

    /* Save virtual repo info before actually create the repo.
     */
    if (save_virtual_repo_info (mgr, repo_id, origin_repo_id,
                                path, origin_head->commit_id) < 0) {
        seaf_warning ("Failed to save virtual repo info for %.10s:%s",
                      origin_repo_id, path);
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "Internal error");
        goto error;
    }

    orig_owner = seaf_repo_manager_get_repo_owner (mgr, origin_repo_id);

    if (do_create_virtual_repo (mgr, origin_repo, repo_id, repo_name, repo_desc,
                                dir_id, orig_owner, passwd, error) < 0)
        goto error;

    if (seaf_repo_manager_set_repo_owner (mgr, repo_id, orig_owner) < 0) {
        seaf_warning ("Failed to set repo owner for %.10s.\n", repo_id);
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Failed to set repo owner.");
        goto error;
    }

    /* The size of virtual repo is non-zero at the beginning. */
    update_repo_size (repo_id);

    seaf_repo_unref (origin_repo);
    seaf_commit_unref (origin_head);
    g_free (dir_id);
    g_free (orig_owner);
    return repo_id;

error:
    seaf_repo_unref (origin_repo);
    seaf_commit_unref (origin_head);
    g_free (repo_id);
    g_free (dir_id);
    g_free (orig_owner);
    return NULL;
}
Exemplo n.º 4
0
char *
seaf_clone_manager_add_task (SeafCloneManager *mgr, 
                             const char *repo_id,
                             int repo_version,
                             const char *peer_id,
                             const char *repo_name,
                             const char *token,
                             const char *passwd,
                             const char *magic,
                             int enc_version,
                             const char *random_key,
                             const char *worktree_in,
                             const char *peer_addr,
                             const char *peer_port,
                             const char *email,
                             const char *more_info,
                             GError **error)
{
    SeafRepo *repo;
    char *worktree;
    char *ret;
    gboolean sync_wt_name = FALSE;

    if (!seaf->started) {
        seaf_message ("System not started, skip adding clone task.\n");
        return NULL;
    }

#ifdef USE_GPL_CRYPTO
    if (repo_version == 0 || (passwd && enc_version < 2)) {
        seaf_warning ("Don't support syncing old version libraries.\n");
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS,
                     "Don't support syncing old version libraries");
        return NULL;
    }
#endif

    if (passwd &&
        !check_encryption_args (magic, enc_version, random_key, error))
        return NULL;

    /* After a repo was unsynced, the sync task may still be blocked in the
     * network, so the repo is not actually deleted yet.
     * In this case just return an error to the user.
     */
    SyncInfo *sync_info = seaf_sync_manager_get_sync_info (seaf->sync_mgr,
                                                           repo_id);
    if (sync_info && sync_info->in_sync) {
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Repo already exists");
        return NULL;
    }

    repo = seaf_repo_manager_get_repo (seaf->repo_mgr, repo_id);

    if (repo != NULL && repo->head != NULL) {
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Repo already exists");
        return NULL;
    }   

    if (is_duplicate_task (mgr, repo_id)) {
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, 
                     "Task is already in progress");
        return NULL;
    }

    if (passwd &&
        seafile_verify_repo_passwd(repo_id, passwd, magic, enc_version) < 0) {
        g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL,
                     "Incorrect password");
        return NULL;
    }

    if (!seaf_clone_manager_check_worktree_path (mgr, worktree_in, error))
        return NULL;

    /* Return error if worktree_in conflicts with another repo or
     * is not a directory.
     */
    worktree = make_worktree (mgr, worktree_in, FALSE, error);
    if (!worktree) {
        return NULL;
    }

    /* Don't sync worktree folder name with library name later if they're not the same
     * at the beginning.
     */
    sync_wt_name = is_wt_repo_name_same (worktree, repo_name);

    /* If a repo was unsynced and then downloaded again, there may be
     * a garbage record for this repo. We don't want the downloaded blocks
     * be removed by GC.
     */
    if (repo_version > 0)
        seaf_repo_manager_remove_garbage_repo (seaf->repo_mgr, repo_id);

    /* Delete orphan information in the db in case the repo was corrupt. */
    if (!repo)
        seaf_repo_manager_remove_repo_ondisk (seaf->repo_mgr, repo_id, FALSE);

    ret = add_task_common (mgr, repo_id, repo_version,
                           peer_id, repo_name, token, passwd,
                           enc_version, random_key,
                           worktree, peer_addr, peer_port,
                           email, more_info,
                           sync_wt_name,
                           error);
    g_free (worktree);

    return ret;
}