diff options
| -rw-r--r-- | include/rabbit_cli.hrl | 13 | ||||
| -rw-r--r-- | src/rabbit_control_main.erl | 59 | ||||
| -rw-r--r-- | src/rabbit_pbe.erl | 11 | ||||
| -rw-r--r-- | test/unit_SUITE.erl | 18 |
4 files changed, 87 insertions, 14 deletions
diff --git a/include/rabbit_cli.hrl b/include/rabbit_cli.hrl index b1cf41261f..5a42b01bf2 100644 --- a/include/rabbit_cli.hrl +++ b/include/rabbit_cli.hrl @@ -31,6 +31,12 @@ -define(ONLINE_OPT, "--online"). -define(LOCAL_OPT, "--local"). +-define(DECODE_OPT, "--decode"). +-define(CIPHER_OPT, "--cipher"). +-define(HASH_OPT, "--hash"). +-define(ITERATIONS_OPT, "--iterations"). +-define(LIST_CIPHERS_OPT, "--list-ciphers"). +-define(LIST_HASHES_OPT, "--list-hashes"). -define(NODE_DEF(Node), {?NODE_OPT, {option, Node}}). -define(QUIET_DEF, {?QUIET_OPT, flag}). @@ -48,6 +54,13 @@ -define(OFFLINE_DEF, {?OFFLINE_OPT, flag}). -define(ONLINE_DEF, {?ONLINE_OPT, flag}). -define(LOCAL_DEF, {?LOCAL_OPT, flag}). +-define(DECODE_DEF, {?DECODE_OPT, flag}). +-define(CIPHER_DEF, {?CIPHER_OPT, {option, "aes_cbc256"}}). +-define(HASH_DEF, {?HASH_OPT, {option, "sha512"}}). +-define(ITERATIONS_DEF, {?ITERATIONS_OPT, {option, "1000"}}). +-define(LIST_CIPHERS_DEF, {?LIST_CIPHERS_OPT, flag}). +-define(LIST_HASHES_DEF, {?LIST_HASHES_OPT, flag}). + %% Subset of standartized exit codes from sysexits.h, see %% https://github.com/rabbitmq/rabbitmq-server/issues/396 for discussion. diff --git a/src/rabbit_control_main.erl b/src/rabbit_control_main.erl index 92898c2a2c..cb017c9452 100644 --- a/src/rabbit_control_main.erl +++ b/src/rabbit_control_main.erl @@ -92,7 +92,8 @@ {trace_off, [?VHOST_DEF]}, set_vm_memory_high_watermark, set_disk_free_limit, - help + help, + {encode, [?DECODE_DEF, ?CIPHER_DEF, ?HASH_DEF, ?ITERATIONS_DEF, ?LIST_CIPHERS_DEF, ?LIST_HASHES_DEF]} ]). -define(GLOBAL_QUERIES, @@ -114,7 +115,7 @@ [stop, stop_app, start_app, wait, reset, force_reset, rotate_logs, join_cluster, change_cluster_node_type, update_cluster_nodes, forget_cluster_node, rename_cluster_node, cluster_status, status, - environment, eval, force_boot, help, hipe_compile]). + environment, eval, force_boot, help, hipe_compile, encode]). %% [Command | {Command, DefaultTimeoutInMilliSeconds}] -define(COMMANDS_WITH_TIMEOUT, @@ -579,6 +580,16 @@ action(eval, Node, [Expr], _Opts, _Inform) -> action(help, _Node, _Args, _Opts, _Inform) -> io:format("~s", [rabbit_ctl_usage:usage()]); +action(encode, _Node, Args, Opts, _Inform) -> + ListCiphers = lists:member({?LIST_CIPHERS_OPT, true}, Opts), + ListHashes = lists:member({?LIST_HASHES_OPT, true}, Opts), + Decode = lists:member({?DECODE_OPT, true}, Opts), + Cipher = list_to_atom(proplists:get_value(?CIPHER_OPT, Opts)), + Hash = list_to_atom(proplists:get_value(?HASH_OPT, Opts)), + Iterations = list_to_integer(proplists:get_value(?ITERATIONS_OPT, Opts)), + + encode(ListCiphers, ListHashes, Decode, Cipher, Hash, Iterations, Args); + action(Command, Node, Args, Opts, Inform) -> %% For backward compatibility, run commands accepting a timeout with %% the default timeout. @@ -706,6 +717,50 @@ purge_queue(Q) -> ok end). +%% encode-related functions +encode(ListCiphers, _ListHashes, _Decode, _Cipher, _Hash, _Iterations, _Args) when ListCiphers -> + io:format("~p~n", [rabbit_pbe:supported_ciphers()]); + +encode(_ListCiphers, ListHashes, _Decode, _Cipher, _Hash, _Iterations, _Args) when ListHashes -> + io:format("~p~n", [rabbit_pbe:supported_hashes()]); + +encode(_ListCiphers, _ListHashes, Decode, Cipher, Hash, Iterations, Args) -> + CipherExists = lists:member(Cipher, rabbit_pbe:supported_ciphers()), + HashExists = lists:member(Hash, rabbit_pbe:supported_hashes()), + encode_encrypt_decrypt(CipherExists, HashExists, Decode, Cipher, Hash, Iterations, Args). + +encode_encrypt_decrypt(CipherExists, _HashExists, _Decode, _Cipher, _Hash, _Iterations, _Args) when CipherExists =:= false -> + io:format("The requested cipher is not supported~n"); + +encode_encrypt_decrypt(_CipherExists, HashExists, _Decode, _Cipher, _Hash, _Iterations, _Args) when HashExists =:= false -> + io:format("The requested hash is not supported~n"); + +encode_encrypt_decrypt(_CipherExists, _HashExists, _Decode, _Cipher, _Hash, Iterations, _Args) when Iterations =< 0; Iterations >= 1000000 -> + io:format("The requested number of iterations is incorrect~n"); + +encode_encrypt_decrypt(_CipherExists, _HashExists, Decode, Cipher, Hash, Iterations, Args) when length(Args) == 2, Decode =:= false -> + [Value, PassPhrase] = Args, + try begin + Result = rabbit_pbe:encrypt(Cipher, Hash, Iterations, list_to_binary(PassPhrase), list_to_binary(Value)), + io:format("~p~n", [Result]) + end + catch + _:_ -> io:format("Error during cipher operation~n") + end; + +encode_encrypt_decrypt(_CipherExists, _HashExists, Decode, Cipher, Hash, Iterations, Args) when length(Args) == 2, Decode -> + [Value, PassPhrase] = Args, + try begin + Result = rabbit_pbe:decrypt(Cipher, Hash, Iterations, list_to_binary(PassPhrase), list_to_binary(Value)), + io:format("~p~n", [Result]) + end + catch + _:_ -> io:format("Error during cipher operation~n") + end; + +encode_encrypt_decrypt(_CipherExists, _HashExists, _Decode, _Cipher, _Hash, _Iterations, _Args) -> + io:format("Please provide a value to encode/decode and a passphrase"). + %%---------------------------------------------------------------------------- require_mnesia_stopped(Node, Fun) -> diff --git a/src/rabbit_pbe.erl b/src/rabbit_pbe.erl index 5773faf9dc..b073d2e2d6 100644 --- a/src/rabbit_pbe.erl +++ b/src/rabbit_pbe.erl @@ -16,9 +16,20 @@ -module(rabbit_pbe). +-export([supported_ciphers/0, supported_hashes/0]). -export([encrypt_term/5, decrypt_term/5]). -export([encrypt/5, decrypt/5]). +%% Supported ciphers and hashes + +supported_ciphers() -> + proplists:get_value(ciphers, crypto:supports()) + -- [aes_ctr, aes_ecb, des_ecb, blowfish_ecb, rc4, aes_gcm]. + +supported_hashes() -> + proplists:get_value(hashs, crypto:supports()) + -- [md4, ripemd160]. + %% Encryption/decryption of arbitrary Erlang terms. encrypt_term(Cipher, Hash, Iterations, PassPhrase, Term) -> diff --git a/test/unit_SUITE.erl b/test/unit_SUITE.erl index 56d02d6da7..905a92a10b 100644 --- a/test/unit_SUITE.erl +++ b/test/unit_SUITE.erl @@ -262,10 +262,8 @@ prepend_check(HeaderKey, HeaderTable, Headers) -> encrypt_decrypt(_Config) -> %% Take all available block ciphers. - Hashes = proplists:get_value(hashs, crypto:supports()) - -- [md4, ripemd160], - Ciphers = proplists:get_value(ciphers, crypto:supports()) - -- [aes_ctr, aes_ecb, des_ecb, blowfish_ecb, rc4, aes_gcm], + Hashes = rabbit_pbe:supported_hashes(), + Ciphers = rabbit_pbe:supported_ciphers(), %% For each cipher, try to encrypt and decrypt data sizes from 0 to 64 bytes %% with a random passphrase. _ = [begin @@ -282,10 +280,8 @@ encrypt_decrypt(_Config) -> encrypt_decrypt_term(_Config) -> %% Take all available block ciphers. - Hashes = proplists:get_value(hashs, crypto:supports()) - -- [md4, ripemd160], - Ciphers = proplists:get_value(ciphers, crypto:supports()) - -- [aes_ctr, aes_ecb, des_ecb, blowfish_ecb, rc4, aes_gcm], + Hashes = rabbit_pbe:supported_hashes(), + Ciphers = rabbit_pbe:supported_ciphers(), %% Different Erlang terms to try encrypting. DataSet = [ 10000, @@ -310,10 +306,8 @@ encrypt_decrypt_term(_Config) -> decrypt_config(_Config) -> %% Take all available block ciphers. - Hashes = proplists:get_value(hashs, crypto:supports()) - -- [md4, ripemd160], - Ciphers = proplists:get_value(ciphers, crypto:supports()) - -- [aes_ctr, aes_ecb, des_ecb, blowfish_ecb, rc4, aes_gcm], + Hashes = rabbit_pbe:supported_hashes(), + Ciphers = rabbit_pbe:supported_ciphers(), Iterations = [1, 10, 100, 1000], %% Loop through all hashes, ciphers and iterations. _ = [begin |
