Example #1
0
static gboolean
validate_passwd_pbkdf2_sha256 (const char *passwd, const char *db_passwd)
{
    char **tokens;
    char *salt_str, *hash;
    int iter;
    guint8 sha[SHA256_DIGEST_LENGTH];
    guint8 salt[SHA256_DIGEST_LENGTH];
    char hashed_passwd[SHA256_DIGEST_LENGTH*2+1];

    tokens = g_strsplit (db_passwd, "$", -1);
    if (!tokens || g_strv_length (tokens) != 4) {
        ccnet_warning ("Invalide db passwd format %s.\n", db_passwd);
        return FALSE;
    }

    iter = atoi (tokens[1]);
    salt_str = tokens[2];
    hash = tokens[3];

    hex_to_rawdata (salt_str, salt, SHA256_DIGEST_LENGTH);

    PKCS5_PBKDF2_HMAC (passwd, strlen(passwd),
                       salt, sizeof(salt),
                       iter,
                       EVP_sha256(),
                       sizeof(sha), sha);
    rawdata_to_hex (sha, hashed_passwd, SHA256_DIGEST_LENGTH);

    gboolean ret = (strcmp (hash, hashed_passwd) == 0);

    g_strfreev (tokens);
    return ret;
}
static int
decrypt_token (CcnetProcessor *processor)
{
    USE_PRIV;
    int hex_len, encrypted_len, token_len; 
    char *encrypted_token = NULL;
    SeafileCrypt *crypt = NULL;
    unsigned char key[16], iv[16];
    char *token = NULL;
    int ret = 0;

    /* raw data is half the length of hexidecimal */
    hex_len = strlen(priv->token);
    if (hex_len % 2 != 0) {
        seaf_warning ("[check tx slave v3] invalid length of encrypted token\n"); 
        ret = -1;
        goto out;
    }

    encrypted_len = hex_len / 2;
    encrypted_token = g_malloc (encrypted_len);
    hex_to_rawdata (priv->token,
                    (unsigned char *)encrypted_token,
                    encrypted_len);

    EVP_BytesToKey (EVP_aes_128_cbc(), /* cipher mode */
                    EVP_sha1(),        /* message digest */
                    NULL,              /* slat */
                    (unsigned char*)priv->session_key,
                    strlen(priv->session_key),
                    1,   /* iteration times */
                    key, /* the derived key */
                    iv); /* IV, initial vector */

    crypt = seafile_crypt_new (1, key, iv);
    
    if (seafile_decrypt (&token, &token_len, encrypted_token,
                         encrypted_len, crypt) < 0) {
        seaf_warning ("[check tx slave v3] failed to decrypt token\n");
        ret = -1;
        goto out;
    }

    g_free (priv->token);
    /* we can use the decrypted data directly, since the trailing null byte is
     * also included when encrypting in the client */
    priv->token = token;

out:
    g_free (crypt);
    g_free (encrypted_token);
    
    return ret;
}
Example #3
0
int
seafile_decrypt_repo_enc_key (int enc_version,
                              const char *passwd, const char *random_key,
                              unsigned char *key_out, unsigned char *iv_out)
{
    unsigned char key[32], iv[16];

    seafile_derive_key (passwd, strlen(passwd), enc_version, key, iv);

    if (enc_version == 1) {
        memcpy (key_out, key, 16);
        memcpy (iv_out, iv, 16);
        return 0;
    } else if (enc_version == 2) {
        unsigned char enc_random_key[48], *dec_random_key;
        int outlen;
        SeafileCrypt *crypt;

        if (random_key == NULL || random_key[0] == 0) {
            seaf_warning ("Empty random key.\n");
            return -1;
        }

        hex_to_rawdata (random_key, enc_random_key, 48);

        crypt = seafile_crypt_new (enc_version, key, iv);
        if (seafile_decrypt ((char **)&dec_random_key, &outlen,
                             (char *)enc_random_key, 48,
                             crypt) < 0) {
            seaf_warning ("Failed to decrypt random key.\n");
            g_free (crypt);
            return -1;
        }
        g_free (crypt);

        seafile_derive_key ((char *)dec_random_key, 32, enc_version,
                                  key, iv);
        memcpy (key_out, key, 32);
        memcpy (iv_out, iv, 16);

        g_free (dec_random_key);
        return 0;
    }

    return -1;
}
Example #4
0
int
seafile_update_random_key (const char *old_passwd, const char *old_random_key,
                           const char *new_passwd, char *new_random_key)
{
    unsigned char key[32], iv[16];
    unsigned char random_key_raw[48], *secret_key, *new_random_key_raw;
    int secret_key_len, random_key_len;
    SeafileCrypt *crypt;

    /* First, use old_passwd to decrypt secret key from old_random_key. */
    seafile_derive_key (old_passwd, strlen(old_passwd), 2, key, iv);

    hex_to_rawdata (old_random_key, random_key_raw, 48);

    crypt = seafile_crypt_new (2, key, iv);
    if (seafile_decrypt ((char **)&secret_key, &secret_key_len,
                         (char *)random_key_raw, 48,
                         crypt) < 0) {
        seaf_warning ("Failed to decrypt random key.\n");
        g_free (crypt);
        return -1;
    }
    g_free (crypt);

    /* Second, use new_passwd to encrypt secret key. */
    seafile_derive_key (new_passwd, strlen(new_passwd), 2, key, iv);

    crypt = seafile_crypt_new (2, key, iv);

    seafile_encrypt ((char **)&new_random_key_raw, &random_key_len,
                     (char *)secret_key, secret_key_len, crypt);

    rawdata_to_hex (new_random_key_raw, new_random_key, 48);

    g_free (secret_key);
    g_free (new_random_key_raw);
    g_free (crypt);

    return 0;
}
Example #5
0
int
commit_trees_cb (struct cache_tree *it, struct cache_entry **cache,
                 int entries, const char *base, int baselen)
{
    SeafDir *seaf_dir;
    GList *dirents = NULL;
    int i;

    for (i = 0; i < entries; i++) {
        SeafDirent *seaf_dent;
        char *dirname;
        struct cache_entry *ce = cache[i];
        struct cache_tree_sub *sub;
        const char *path, *slash;
        int pathlen, entlen;
        const unsigned char *sha1;
        char hex[41];
        unsigned mode;

        if (ce->ce_flags & CE_REMOVE)
            continue; /* entry being removed */

        path = ce->name;
        pathlen = ce_namelen(ce);
        if (pathlen <= baselen || memcmp(base, path, baselen))
            break; /* at the end of this level */

        slash = strchr(path + baselen, '/');
        if (slash) {
            entlen = slash - (path + baselen);
            sub = cache_tree_find_subtree(it, path + baselen, entlen, 0);
            g_assert (sub != NULL);
            /* Skip cache entries in the sub level. */
            i += sub->cache_tree->entry_count - 1;

            sha1 = sub->cache_tree->sha1;
            mode = S_IFDIR;
            dirname = g_strndup(path + baselen, entlen);

            rawdata_to_hex (sha1, hex, 20);
            seaf_dent = seaf_dirent_new (hex, mode, dirname);
            g_free(dirname);

            dirents = g_list_prepend (dirents, seaf_dent);
        } else {
            sha1 = ce->sha1;
            mode = ce->ce_mode;
            entlen = pathlen - baselen;

            dirname = g_strndup(path + baselen, entlen);
            rawdata_to_hex (sha1, hex, 20);
            seaf_dent = seaf_dirent_new (hex, mode, dirname);
            g_free(dirname);

            dirents = g_list_prepend (dirents, seaf_dent);
        }

#if DEBUG
        fprintf(stderr, "cache-tree update-one %o %.*s\n",
                mode, entlen, path + baselen);
#endif
    }

    /* Sort dirents in descending order. */
    dirents = g_list_sort (dirents, compare_dirents);

    seaf_dir = seaf_dir_new (NULL, dirents, 0);
    hex_to_rawdata (seaf_dir->dir_id, it->sha1, 20);

    seaf_dir_save (seaf->fs_mgr, seaf_dir);

#if DEBUG
    for (p = dirents; p; p = p->next) {
        SeafDirent *tmp = (SeafDirent *)p->data;
        fprintf(stderr, "dump dirent name %s id %s\n", tmp->name, tmp->id);
    }
#endif

    seaf_dir_free (seaf_dir);
    return 0;
}
static int
decrypt_token (CcnetProcessor *processor)
{
    USE_PRIV;
    int hex_len, encrypted_len, token_len; 
    char *encrypted_token = NULL;
    SeafileCrypt *crypt = NULL;
    unsigned char key[16], iv[16];
    char *token = NULL;
    int ret = 0;

    /* raw data is half the length of hexidecimal */
    hex_len = strlen(priv->token);
    if (hex_len % 2 != 0) {
        seaf_warning ("[check tx slave v2] invalid length of encrypted token\n"); 
        ret = -1;
        goto out;
    }

    token = seaf_repo_manager_get_decrypted_token (seaf->repo_mgr,
                                                   priv->token,
                                                   priv->session_key);
    if (token)
        goto found;
    
    encrypted_len = hex_len / 2;
    encrypted_token = g_malloc (encrypted_len);
    hex_to_rawdata (priv->token,
                    (unsigned char *)encrypted_token,
                    encrypted_len);

    seafile_generate_enc_key (priv->session_key,
                              strlen(priv->session_key),
                              CURRENT_ENC_VERSION, key, iv);
    crypt = seafile_crypt_new (CURRENT_ENC_VERSION, key, iv);
    
    if (seafile_decrypt (&token, &token_len, encrypted_token,
                         encrypted_len, crypt) < 0) {
        seaf_warning ("[check tx slave v2] failed to decrypt token\n");
        ret = -1;
        goto out;
    }

    /* Add to cache. */
    seaf_repo_manager_add_decrypted_token (seaf->repo_mgr,
                                           priv->token,
                                           priv->session_key,
                                           token);

found:
    g_free (priv->token);
    /* we can use the decrypted data directly, since the trailing null byte is
     * also included when encrypting in the client */
    priv->token = token;

out:
    g_free (crypt);
    g_free (encrypted_token);
    
    return ret;
}
Example #7
0
int
commit_trees_cb (const char *repo_id, int version,
                 const char *worktree,
                 struct cache_tree *it, struct cache_entry **cache,
                 int entries, const char *base, int baselen)
{
    SeafDir *seaf_dir;
    GList *dirents = NULL, *ptr;
    int i;

    for (i = 0; i < entries; i++) {
        SeafDirent *seaf_dent;
        char *name;
        struct cache_entry *ce = cache[i];
        struct cache_tree_sub *sub;
        const char *path, *slash;
        int pathlen, entlen;
        const unsigned char *sha1;
        char hex[41];
        unsigned mode;
        guint64 mtime;
        gint64 size;
        char *modifier;

        if (ce->ce_flags & CE_REMOVE)
            continue; /* entry being removed */

        path = ce->name;
        pathlen = ce_namelen(ce);
        if (pathlen <= baselen || memcmp(base, path, baselen))
            break; /* at the end of this level */

        slash = strchr(path + baselen, '/');
        if (slash) {
            entlen = slash - (path + baselen);
            sub = cache_tree_find_subtree(it, path + baselen, entlen, 0);
            g_return_val_if_fail (sub != NULL, -1);
            /* Skip cache entries in the sub level. */
            i += sub->cache_tree->entry_count - 1;

            sha1 = sub->cache_tree->sha1;
            mtime = sub->cache_tree->mtime;
            mode = S_IFDIR;
            name = g_strndup(path + baselen, entlen);

            rawdata_to_hex (sha1, hex, 20);
            seaf_dent = seaf_dirent_new (dir_version_from_repo_version(version),
                                         hex, mode, name, mtime, NULL, -1);
            g_free(name);

            dirents = g_list_prepend (dirents, seaf_dent);
        } else {
            sha1 = ce->sha1;
            mode = ce->ce_mode;
            mtime = ce->ce_mtime.sec;
            size = ce->ce_size;
            modifier = ce->modifier;
            entlen = pathlen - baselen;
            name = g_strndup(path + baselen, entlen);
            rawdata_to_hex (sha1, hex, 20);

            if (version > 0) {
                seaf_dent =
                    seaf_dirent_new (dir_version_from_repo_version(version),
                                     hex, mode, name, mtime, modifier, size);
            } else {
                seaf_dent = seaf_dirent_new (0, hex, mode, name, 0, NULL, -1);
            }

            g_free(name);

            dirents = g_list_prepend (dirents, seaf_dent);
        }

#if DEBUG
        fprintf(stderr, "cache-tree update-one %o %.*s\n",
                mode, entlen, path + baselen);
#endif
    }

    /* Sort dirents in descending order. */
    dirents = g_list_sort (dirents, compare_dirents);

    seaf_dir = seaf_dir_new (NULL, dirents, dir_version_from_repo_version(version));
    hex_to_rawdata (seaf_dir->dir_id, it->sha1, 20);

    /* Dir's mtime is the latest of all dir entires. */
    guint64 dir_mtime = 0;
    SeafDirent *dent;
    for (ptr = dirents; ptr; ptr = ptr->next) {
        dent = ptr->data;
        if (dent->mtime > dir_mtime)
            dir_mtime = dent->mtime;
    }
    it->mtime = dir_mtime;

    if (!seaf_fs_manager_object_exists (seaf->fs_mgr,
                                        repo_id, version,
                                        seaf_dir->dir_id))
        seaf_dir_save (seaf->fs_mgr, repo_id, version, seaf_dir);

#if DEBUG
    for (p = dirents; p; p = p->next) {
        SeafDirent *tmp = (SeafDirent *)p->data;
        fprintf(stderr, "dump dirent name %s id %s\n", tmp->name, tmp->id);
    }
#endif

    seaf_dir_free (seaf_dir);
    return 0;
}
Example #8
0
int
traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
{
    struct name_entry *entries = g_new0 (struct name_entry, n);
    GList **ptrs = g_new0 (GList *, n);
    int i;
    SeafDirent *dent;
    char *first_name;
    gboolean done;
    unsigned long mask = 0, dirmask = 0;
    int error = 0, ret;

    for (i = 0; i < n; ++i) {
        if (t[i].tree)
            ptrs[i] = t[i].tree->entries;
        else
            ptrs[i] = NULL;
    }

    while (1) {
        first_name = NULL;
        mask = dirmask = 0;
        memset (entries, 0, sizeof(entries[0])*n);
        done = TRUE;

        /* Find the "largest" name, assuming dirents are sorted. */
        for (i = 0; i < n; ++i) {
            if (ptrs[i] != NULL) {
                done = FALSE;
                dent = ptrs[i]->data;
                if (!first_name)
                    first_name = dent->name;
                else if (strcmp(dent->name, first_name) > 0)
                    first_name = dent->name;
            }
        }

        if (done)
            break;

        /*
         * Setup name entries for all names that equals first_name
         */
        for (i = 0; i < n; ++i) {
            if (ptrs[i] != NULL) {
                dent = ptrs[i]->data;
                if (strcmp(first_name, dent->name) == 0) {
                    mask |= 1 << i;
                    /* We treat empty dirs as a file. */
                    if (S_ISDIR(dent->mode) && 
                        memcmp (dent->id, EMPTY_SHA1, 40) != 0)
                        dirmask |= 1 << i;

                    hex_to_rawdata (dent->id, entries[i].sha1, 20);
                    entries[i].path = dent->name;
                    entries[i].pathlen = dent->name_len;
                    entries[i].mode = dent->mode;

                    ptrs[i] = ptrs[i]->next;
                }
            }
        }

        ret = info->fn (n, mask, dirmask, entries, info);
        if (ret < 0) {
            error = ret;
        }
    }

    g_free (entries);
    g_free (ptrs);
    return error;
}