summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/rabbit_cli.hrl13
-rw-r--r--src/rabbit_control_main.erl59
-rw-r--r--src/rabbit_pbe.erl11
-rw-r--r--test/unit_SUITE.erl18
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