aboutsummaryrefslogtreecommitdiff
path: root/src/mod_register.erl
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2008-04-22 21:51:32 +0000
committerAlexey Shchepin <alexey@process-one.net>2008-04-22 21:51:32 +0000
commit797544333ca9c40eb4e8b36fb58aefff9b0ebe02 (patch)
tree983dda80f9b632ff897622f4d70df558f014bdc1 /src/mod_register.erl
parent* src/ejabberd_auth.erl: Improve anonymous authentication to not (diff)
* src/mod_register.erl: Restrict registration frequency per IP or
user * src/ejabberd_c2s.erl: Pass IP to the c2s_unauthenticated_iq hook * src/ejabberd_config.erl: Added registration_timeout option * src/treap.erl: Treaps implementation SVN Revision: 1299
Diffstat (limited to 'src/mod_register.erl')
-rw-r--r--src/mod_register.erl118
1 files changed, 98 insertions, 20 deletions
diff --git a/src/mod_register.erl b/src/mod_register.erl
index fc5dbc17e..b8f99df3f 100644
--- a/src/mod_register.erl
+++ b/src/mod_register.erl
@@ -32,7 +32,7 @@
-export([start/2,
stop/1,
stream_feature_register/1,
- unauthenticated_iq_register/3,
+ unauthenticated_iq_register/4,
process_iq/3]).
-include("ejabberd.hrl").
@@ -48,6 +48,10 @@ start(Host, Opts) ->
?MODULE, stream_feature_register, 50),
ejabberd_hooks:add(c2s_unauthenticated_iq, Host,
?MODULE, unauthenticated_iq_register, 50),
+ mnesia:create_table(mod_register_ip,
+ [{ram_copies, [node()]},
+ {local_content, true},
+ {attributes, [key, value]}]),
ok.
stop(Host) ->
@@ -63,20 +67,30 @@ stream_feature_register(Acc) ->
[{xmlelement, "register",
[{"xmlns", ?NS_FEATURE_IQREGISTER}], []} | Acc].
-unauthenticated_iq_register(_Acc, Server, #iq{xmlns = ?NS_REGISTER} = IQ) ->
+unauthenticated_iq_register(_Acc,
+ Server, #iq{xmlns = ?NS_REGISTER} = IQ, IP) ->
+ Address = case IP of
+ {A, _Port} -> A;
+ _ -> undefined
+ end,
ResIQ = process_iq(jlib:make_jid("", "", ""),
jlib:make_jid("", Server, ""),
- IQ),
+ IQ,
+ Address),
Res1 = jlib:replace_from_to(jlib:make_jid("", Server, ""),
jlib:make_jid("", "", ""),
jlib:iq_to_xml(ResIQ)),
jlib:remove_attr("to", Res1);
-unauthenticated_iq_register(Acc, _Server, _IQ) ->
+unauthenticated_iq_register(Acc, _Server, _IQ, _IP) ->
Acc.
+process_iq(From, To, IQ) ->
+ process_iq(From, To, IQ, jlib:jid_tolower(jlib:jid_remove_resource(From))).
+
process_iq(From, To,
- #iq{type = Type, lang = Lang, sub_el = SubEl, id = ID} = IQ) ->
+ #iq{type = Type, lang = Lang, sub_el = SubEl, id = ID} = IQ,
+ Source) ->
case Type of
set ->
UTag = xml:get_subtag(SubEl, "username"),
@@ -151,7 +165,8 @@ process_iq(From, To,
ejabberd_auth:set_password(User, Server, Password),
IQ#iq{type = result, sub_el = [SubEl]};
_ ->
- case try_register(User, Server, Password) of
+ case try_register(User, Server, Password,
+ Source) of
ok ->
IQ#iq{type = result, sub_el = [SubEl]};
{error, Error} ->
@@ -179,7 +194,7 @@ process_iq(From, To,
end.
-try_register(User, Server, Password) ->
+try_register(User, Server, Password, Source) ->
case jlib:is_nodename(User) of
false ->
{error, ?ERR_BAD_REQUEST};
@@ -190,19 +205,24 @@ try_register(User, Server, Password) ->
deny ->
{error, ?ERR_CONFLICT};
allow ->
- case ejabberd_auth:try_register(User, Server, Password) of
- {atomic, ok} ->
- send_welcome_message(JID),
- send_registration_notifications(JID),
- ok;
- {atomic, exists} ->
- {error, ?ERR_CONFLICT};
- {error, invalid_jid} ->
- {error, ?ERR_JID_MALFORMED};
- {error, not_allowed} ->
- {error, ?ERR_NOT_ALLOWED};
- {error, _Reason} ->
- {error, ?ERR_INTERNAL_SERVER_ERROR}
+ case check_timeout(Source) of
+ true ->
+ case ejabberd_auth:try_register(User, Server, Password) of
+ {atomic, ok} ->
+ send_welcome_message(JID),
+ send_registration_notifications(JID),
+ ok;
+ {atomic, exists} ->
+ {error, ?ERR_CONFLICT};
+ {error, invalid_jid} ->
+ {error, ?ERR_JID_MALFORMED};
+ {error, not_allowed} ->
+ {error, ?ERR_NOT_ALLOWED};
+ {error, _Reason} ->
+ {error, ?ERR_INTERNAL_SERVER_ERROR}
+ end;
+ false ->
+ {error, ?ERR_RESOURCE_CONSTRAINT}
end
end
end.
@@ -249,3 +269,61 @@ send_registration_notifications(UJID) ->
_ ->
ok
end.
+
+
+check_timeout(undefined) ->
+ true;
+check_timeout(Source) ->
+ Timeout = case ejabberd_config:get_local_option(registration_timeout) of
+ undefined -> 600;
+ TO -> TO
+ end,
+ if
+ is_integer(Timeout) ->
+ {MSec, Sec, _USec} = now(),
+ Priority = -(MSec * 1000000 + Sec),
+ CleanPriority = Priority + Timeout,
+ F = fun() ->
+ Treap = case mnesia:read(mod_register_ip, treap,
+ write) of
+ [] ->
+ treap:empty();
+ [{mod_register_ip, treap, T}] -> T
+ end,
+ Treap1 = clean_treap(Treap, CleanPriority),
+ case treap:lookup(Source, Treap1) of
+ error ->
+ Treap2 = treap:insert(Source, Priority, [],
+ Treap1),
+ mnesia:write({mod_register_ip, treap, Treap2}),
+ true;
+ {ok, _, _} ->
+ mnesia:write({mod_register_ip, treap, Treap1}),
+ false
+ end
+ end,
+ case mnesia:transaction(F) of
+ {atomic, Res} ->
+ Res;
+ {aborted, Reason} ->
+ ?ERROR_MSG("mod_register: timeout check error: ~p~n",
+ [Reason]),
+ true
+ end;
+ true ->
+ true
+ end.
+
+clean_treap(Treap, CleanPriority) ->
+ case treap:is_empty(Treap) of
+ true ->
+ Treap;
+ false ->
+ {_Key, Priority, _Value} = treap:get_root(Treap),
+ if
+ Priority > CleanPriority ->
+ clean_treap(treap:delete_root(Treap), CleanPriority);
+ true ->
+ Treap
+ end
+ end.