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 (seaf_repo_verify_passwd (repo, passwd) < 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; } seafile_generate_enc_key (passwd, strlen(passwd), repo->enc_version, crypt_key->key, crypt_key->iv); crypt_key->passwd = g_strdup(passwd); crypt_key->expire_time = (guint64)time(NULL) + REAP_THRESHOLD; 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; }
/* token -> AES encrypt with session key -> rawdata_to_hex -> output */ static char * encrypt_token (CcnetProcessor *processor, const char *token) { CcnetPeer *peer = NULL; char *enc_out = NULL; SeafileCrypt *crypt = NULL; unsigned char key[16], iv[16]; int len; char *output = NULL; if (!token) goto out; peer = ccnet_get_peer(seaf->ccnetrpc_client, processor->peer_id); if (!peer || !peer->session_key) { seaf_warning ("[check tx v2] peer or peer session key not exist\n"); goto out; } seafile_generate_enc_key (peer->session_key, strlen(peer->session_key), CURRENT_ENC_VERSION, key, iv); crypt = seafile_crypt_new (CURRENT_ENC_VERSION, key, iv); /* encrypt the token with session key, including the trailing null byte */ if (seafile_encrypt (&enc_out, &len, token, strlen(token) + 1, crypt) < 0) { seaf_warning ("[check tx v2] failed to encrypt token\n"); goto out; } output = g_malloc (len * 2 + 1); rawdata_to_hex ((unsigned char *)enc_out, output, len); output[len * 2] = '\0'; out: g_free (crypt); g_free (enc_out); if (peer) g_object_unref(peer); return output; }
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; }