From 1ee6eae684c126b486c70a3cadd58fa282f517ad Mon Sep 17 00:00:00 2001 From: Badlop Date: Tue, 16 Aug 2011 00:26:49 +0200 Subject: Fix and improve support for SCRAM auth method (EJAB-1196) --- src/ejabberd_piefxis.erl | 53 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 12 deletions(-) (limited to 'src/ejabberd_piefxis.erl') diff --git a/src/ejabberd_piefxis.erl b/src/ejabberd_piefxis.erl index 02697163..cf5178bb 100644 --- a/src/ejabberd_piefxis.erl +++ b/src/ejabberd_piefxis.erl @@ -159,13 +159,13 @@ process_element(El=#xmlel{name=user, ns=_XMLNS}, State; process_element(H=#xmlel{name=host},State) -> - State#parsing_state{host=?BTL(exmpp_xml:get_attribute(H,"jid",none))}; + State#parsing_state{host=?BTL(exmpp_xml:get_attribute(H, <<"jid">>, none))}; process_element(#xmlel{name='server-data'},State) -> State; process_element(El=#xmlel{name=include, ns=?NS_XINCLUDE}, State=#parsing_state{dir=Dir}) -> - case exmpp_xml:get_attribute(El, href, none) of + case exmpp_xml:get_attribute(El, <<"href">>, none) of none -> ok; HrefB -> @@ -194,25 +194,26 @@ process_element(El,State) -> %%%% Add user add_user(El, Domain) -> - User = exmpp_xml:get_attribute(El,name,none), - Password = exmpp_xml:get_attribute(El,password,none), - add_user(El, Domain, User, Password). + User = exmpp_xml:get_attribute(El, <<"name">>, none), + PasswordFormat = exmpp_xml:get_attribute(El, <<"password-format">>, none), + Password = exmpp_xml:get_attribute(El, <<"password">>, none), + add_user(El, Domain, User, PasswordFormat, Password). %% @spec (El::xmlel(), Domain::string(), User::binary(), Password::binary() | none) %% -> ok | {error, ErrorText::string()} %% @doc Add a new user to the database. %% If user already exists, it will be only updated. -add_user(El, Domain, UserBinary, none) -> +add_user(El, Domain, UserBinary, <<"plaintext">>, none) -> User = ?BTL(UserBinary), io:format("Account ~s@~s will not be created, updating it...~n", [User, Domain]), io:format(""), populate_user_with_elements(El, Domain, User), ok; -add_user(El, Domain, UserBinary, PasswordBinary) -> +add_user(El, Domain, UserBinary, PasswordFormat, PasswordBinary) -> User = ?BTL(UserBinary), - Password = ?BTL(PasswordBinary), - case create_user(User,Password,Domain) of + Password2 = prepare_password(PasswordFormat, PasswordBinary, El), + case create_user(User,Password2,Domain) of ok -> populate_user_with_elements(El, Domain, User), ok; @@ -227,6 +228,21 @@ add_user(El, Domain, UserBinary, PasswordBinary) -> {error, Other} end. +prepare_password(<<"plaintext">>, PasswordBinary, _El) -> + ?BTL(PasswordBinary); +prepare_password(<<"scram">>, none, El) -> + ScramEl = exmpp_xml:get_element(El, 'scram-hash'), + #scram{storedkey = base64:decode(exmpp_xml:get_attribute( + ScramEl, <<"stored-key">>, none)), + serverkey = base64:decode(exmpp_xml:get_attribute( + ScramEl, <<"server-key">>, none)), + salt = base64:decode(exmpp_xml:get_attribute( + ScramEl, <<"salt">>, none)), + iterationcount = list_to_integer(exmpp_xml:get_attribute_as_list( + ScramEl, <<"iteration-count">>, + ?SCRAM_DEFAULT_ITERATION_COUNT)) + }. + populate_user_with_elements(El, Domain, User) -> exmpp_xml:foreach( fun (_,Child) -> @@ -346,7 +362,7 @@ populate_user(User,Domain,El=#xmlel{name='offline-messages'}) -> fun (_Element, {xmlcdata, _}) -> ok; (_Element, Child) -> - From = exmpp_xml:get_attribute(Child,from,none), + From = exmpp_xml:get_attribute(Child, <<"from">>,none), FullFrom = jid_to_old_jid(exmpp_jid:parse(From)), FullUser = jid_to_old_jid(exmpp_jid:make(User, Domain)), @@ -538,10 +554,23 @@ export_user(Fd, Username, Host) -> %% @spec (Username::string(), Host::string()) -> string() extract_user(Username, Host) -> - Password = ejabberd_auth:get_password_s(Username, Host), + Password = ejabberd_auth:get_password(Username, Host), + PasswordStr = build_password_string(Password), UserInfo = [extract_user_info(InfoName, Username, Host) || InfoName <- [roster, offline, private, vcard]], UserInfoString = lists:flatten(UserInfo), - io_lib:format("~s", [Username, Password, UserInfoString]). + io_lib:format("", + [Username, PasswordStr, UserInfoString]). + +build_password_string({StoredKey, ServerKey, Salt, IterationCount}) -> + io_lib:format("password-format='scram'>" + " ", + [base64:encode_to_string(StoredKey), + base64:encode_to_string(ServerKey), + base64:encode_to_string(Salt), + IterationCount]); +build_password_string(Password) when is_list(Password) -> + io_lib:format("password-format='plaintext' password='~s'>", [Password]). %% @spec (InfoName::atom(), Username::string(), Host::string()) -> string() extract_user_info(roster, Username, Host) -> -- cgit v1.2.3