diff options
-rw-r--r-- | src/cyrsasl_scram.erl | 79 | ||||
-rw-r--r-- | src/mod_muc/mod_muc_room.erl | 34 | ||||
-rw-r--r-- | src/mod_pubsub/mod_pubsub.erl | 8 |
3 files changed, 72 insertions, 49 deletions
diff --git a/src/cyrsasl_scram.erl b/src/cyrsasl_scram.erl index 33d18cd1a..ee68bed1e 100644 --- a/src/cyrsasl_scram.erl +++ b/src/cyrsasl_scram.erl @@ -32,6 +32,8 @@ -include("ejabberd.hrl"). +-include("jlib.hrl"). + -behaviour(cyrsasl). -record(state, @@ -60,8 +62,11 @@ mech_new(_Host, GetPassword, _CheckPassword, {ok, #state{step = 2, get_password = GetPassword}}. mech_step(#state{step = 2} = State, ClientIn) -> - case str:tokens(ClientIn, <<",">>) of - [CBind, UserNameAttribute, ClientNonceAttribute] + case re:split(ClientIn, <<",">>, [{return, binary}]) of + [_CBind, _AuthorizationIdentity, _UserNameAttribute, _ClientNonceAttribute, ExtensionAttribute | _] + when ExtensionAttribute /= [] -> + {error, <<"protocol-error-extension-not-supported">>}; + [CBind, _AuthorizationIdentity, UserNameAttribute, ClientNonceAttribute | _] when (CBind == <<"y">>) or (CBind == <<"n">>) -> case parse_attribute(UserNameAttribute) of {error, Reason} -> {error, Reason}; @@ -123,42 +128,44 @@ mech_step(#state{step = 4} = State, ClientIn) -> [GS2ChannelBindingAttribute, NonceAttribute, ClientProofAttribute] -> case parse_attribute(GS2ChannelBindingAttribute) of - {$c, CVal} when (CVal == <<"biws">>) or (CVal == <<"eSws">>) -> - %% biws is base64 for n,, => channelbinding not supported - %% eSws is base64 for y,, => channelbinding supported by client only - Nonce = <<(State#state.client_nonce)/binary, - (State#state.server_nonce)/binary>>, - case parse_attribute(NonceAttribute) of - {$r, CompareNonce} when CompareNonce == Nonce -> - case parse_attribute(ClientProofAttribute) of - {$p, ClientProofB64} -> - ClientProof = jlib:decode_base64(ClientProofB64), - AuthMessage = - iolist_to_binary( - [State#state.auth_message, - ",", - str:substr(ClientIn, 1, - str:str(ClientIn, <<",p=">>) - - 1)]), - ClientSignature = - scram:client_signature(State#state.stored_key, - AuthMessage), - ClientKey = scram:client_key(ClientProof, - ClientSignature), - CompareStoredKey = scram:stored_key(ClientKey), - if CompareStoredKey == State#state.stored_key -> - ServerSignature = - scram:server_signature(State#state.server_key, - AuthMessage), - {ok, [{username, State#state.username}], - <<"v=", - (jlib:encode_base64(ServerSignature))/binary>>}; - true -> {error, <<"bad-auth">>} + {$c, CVal} -> + ChannelBindingSupport = binary:at(jlib:decode_base64(CVal), 0), + if (ChannelBindingSupport == $n) + or (ChannelBindingSupport == $y) -> + Nonce = <<(State#state.client_nonce)/binary, + (State#state.server_nonce)/binary>>, + case parse_attribute(NonceAttribute) of + {$r, CompareNonce} when CompareNonce == Nonce -> + case parse_attribute(ClientProofAttribute) of + {$p, ClientProofB64} -> + ClientProof = jlib:decode_base64(ClientProofB64), + AuthMessage = iolist_to_binary( + [State#state.auth_message, + ",", + str:substr(ClientIn, 1, + str:str(ClientIn, <<",p=">>) + - 1)]), + ClientSignature = + scram:client_signature(State#state.stored_key, + AuthMessage), + ClientKey = scram:client_key(ClientProof, + ClientSignature), + CompareStoredKey = scram:stored_key(ClientKey), + if CompareStoredKey == State#state.stored_key -> + ServerSignature = + scram:server_signature(State#state.server_key, + AuthMessage), + {ok, [{username, State#state.username}], + <<"v=", + (jlib:encode_base64(ServerSignature))/binary>>}; + true -> {error, <<"bad-auth">>} + end; + _Else -> {error, <<"bad-protocol">>} end; + {$r, _} -> {error, <<"bad-nonce">>}; _Else -> {error, <<"bad-protocol">>} - end; - {$r, _} -> {error, <<"bad-nonce">>}; - _Else -> {error, <<"bad-protocol">>} + end; + true -> {error, <<"bad-channel-binding">>} end; _Else -> {error, <<"bad-protocol">>} end; diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl index d54143956..61ec57766 100644 --- a/src/mod_muc/mod_muc_room.erl +++ b/src/mod_muc/mod_muc_room.erl @@ -2593,7 +2593,7 @@ process_admin_items_set(UJID, Items, Lang, StateData) -> SD; {JID, role, none, Reason} -> catch - send_kickban_presence(JID, + send_kickban_presence(UJID, JID, Reason, <<"307">>, SD), @@ -2605,7 +2605,7 @@ process_admin_items_set(UJID, Items, Lang, StateData) -> of true -> catch - send_kickban_presence(JID, + send_kickban_presence(UJID, JID, Reason, <<"321">>, none, @@ -2628,7 +2628,7 @@ process_admin_items_set(UJID, Items, Lang, StateData) -> {JID, affiliation, outcast, Reason} -> catch - send_kickban_presence(JID, + send_kickban_presence(UJID, JID, Reason, <<"301">>, outcast, @@ -2979,12 +2979,12 @@ can_change_ra(_FAffiliation, _FRole, _TAffiliation, _TRole, role, _Value, _ServiceAf) -> false. -send_kickban_presence(JID, Reason, Code, StateData) -> +send_kickban_presence(UJID, JID, Reason, Code, StateData) -> NewAffiliation = get_affiliation(JID, StateData), - send_kickban_presence(JID, Reason, Code, NewAffiliation, + send_kickban_presence(UJID, JID, Reason, Code, NewAffiliation, StateData). -send_kickban_presence(JID, Reason, Code, NewAffiliation, +send_kickban_presence(UJID, JID, Reason, Code, NewAffiliation, StateData) -> LJID = jlib:jid_tolower(JID), LJIDs = case LJID of @@ -3007,18 +3007,26 @@ send_kickban_presence(JID, Reason, Code, NewAffiliation, StateData#state.users), add_to_log(kickban, {Nick, Reason, Code}, StateData), tab_remove_online_user(J, StateData), - send_kickban_presence1(J, Reason, Code, + send_kickban_presence1(UJID, J, Reason, Code, NewAffiliation, StateData) end, LJIDs). -send_kickban_presence1(UJID, Reason, Code, Affiliation, +send_kickban_presence1(MJID, UJID, Reason, Code, Affiliation, StateData) -> {ok, #user{jid = RealJID, nick = Nick}} = (?DICT):find(jlib:jid_tolower(UJID), StateData#state.users), SAffiliation = affiliation_to_list(Affiliation), BannedJIDString = jlib:jid_to_string(RealJID), + case MJID /= <<"">> of + true -> + {ok, #user{nick = ActorNick}} = + (?DICT):find(jlib:jid_tolower(MJID), + StateData#state.users); + false -> + ActorNick = <<"">> + end, lists:foreach(fun ({_LJID, Info}) -> JidAttrList = case Info#user.role == moderator orelse (StateData#state.config)#config.anonymous @@ -3039,6 +3047,12 @@ send_kickban_presence1(UJID, Reason, Code, Affiliation, children = [{xmlcdata, Reason}]}] end, + ItemElsActor = case MJID of + <<"">> -> []; + _ -> [#xmlel{name = <<"actor">>, + attrs = + [{<<"nick">>, ActorNick}]}] + end, Packet = #xmlel{name = <<"presence">>, attrs = [{<<"type">>, <<"unavailable">>}], @@ -3053,7 +3067,7 @@ send_kickban_presence1(UJID, Reason, Code, Affiliation, attrs = ItemAttrs, children = - ItemEls}, + ItemElsActor ++ ItemEls}, #xmlel{name = <<"status">>, attrs = @@ -3751,7 +3765,7 @@ remove_nonmembers(StateData) -> Affiliation = get_affiliation(JID, SD), case Affiliation of none -> - catch send_kickban_presence(JID, <<"">>, + catch send_kickban_presence(<<"">>, JID, <<"">>, <<"322">>, SD), set_role(JID, none, SD); _ -> SD diff --git a/src/mod_pubsub/mod_pubsub.erl b/src/mod_pubsub/mod_pubsub.erl index 5f1d38e7d..53b32d9de 100644 --- a/src/mod_pubsub/mod_pubsub.erl +++ b/src/mod_pubsub/mod_pubsub.erl @@ -1977,7 +1977,7 @@ iq_pubsub(Host, ServerHost, From, IQType, SubEl, Lang, Access, Plugins) -> [#xmlel{name = <<"item">>, attrs = ItemAttrs, children = Payload}] -> ItemId = xml:get_attr_s(<<"id">>, ItemAttrs), - publish_item(Host, ServerHost, Node, From, ItemId, Payload); + publish_item(Host, ServerHost, Node, From, ItemId, Payload, Access); [] -> {error, extended_error(?ERR_BAD_REQUEST, <<"item-required">>)}; @@ -2948,8 +2948,10 @@ unsubscribe_node(Host, Node, From, Subscriber, SubId) -> | {error, xmlel()} ). publish_item(Host, ServerHost, Node, Publisher, <<>>, Payload) -> - publish_item(Host, ServerHost, Node, Publisher, uniqid(), Payload); + publish_item(Host, ServerHost, Node, Publisher, uniqid(), Payload, all); publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> + publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, all). +publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload, Access) -> Action = fun (#pubsub_node{options = Options, type = Type, id = NodeId}) -> Features = features(Type), PublishFeature = lists:member(<<"publish">>, Features), @@ -3045,7 +3047,7 @@ publish_item(Host, ServerHost, Node, Publisher, ItemId, Payload) -> Type = select_type(ServerHost, Host, Node), case lists:member("auto-create", features(Type)) of true -> - case create_node(Host, ServerHost, Node, Publisher, Type) of + case create_node(Host, ServerHost, Node, Publisher, Type, Access, []) of {result, [#xmlel{name = <<"pubsub">>, attrs = [{<<"xmlns">>, ?NS_PUBSUB}], children = |