diff options
author | Alexey Shchepin <alexey@process-one.net> | 2002-12-20 20:42:08 +0000 |
---|---|---|
committer | Alexey Shchepin <alexey@process-one.net> | 2002-12-20 20:42:08 +0000 |
commit | ae30798efd9f802e43ec0495162acbe6f340aebd (patch) | |
tree | 50726dd86cb685817cf1f7313e13c13ded57500b /src | |
parent | *** empty log message *** (diff) |
*** empty log message ***
SVN Revision: 20
Diffstat (limited to '')
-rw-r--r-- | src/Makefile | 18 | ||||
-rw-r--r-- | src/ejabberd.erl | 1 | ||||
-rw-r--r-- | src/ejabberd_auth.erl | 26 | ||||
-rw-r--r-- | src/ejabberd_c2s.erl | 49 | ||||
-rw-r--r-- | src/ejabberd_router.erl | 10 | ||||
-rw-r--r-- | src/ejabberd_s2s_in.erl | 63 | ||||
-rw-r--r-- | src/ejabberd_sm.erl | 51 | ||||
-rw-r--r-- | src/jlib.erl | 3 | ||||
-rw-r--r-- | src/mod_roster.erl | 197 | ||||
-rw-r--r-- | src/sha.erl | 42 |
10 files changed, 360 insertions, 100 deletions
diff --git a/src/Makefile b/src/Makefile index ff57225b..12ff0b40 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,14 +5,16 @@ INCLUDES = -I/usr/lib/erlang/usr/include \ LIBDIRS = -L/usr/lib/erlang/lib/erl_interface-3.3.0/lib -all: expat_erl.so +ERLSHLIBS = expat_erl.so sha_erl.so + +all: $(ERLSHLIBS) erl -make -expat_erl.so: expat_erl.c - gcc -Wall $(INCLUDES) $(LIBDIRS) \ - -lexpat \ - expat_erl.c \ - -lerl_interface \ - -lei \ - -o expat_erl.so -fpic -shared \ +$(ERLSHLIBS): %.so: %.c + gcc -Wall $(INCLUDES) $(LIBDIRS) \ + -lexpat \ + $(subst .so,.c,$@) \ + -lerl_interface \ + -lei \ + -o $@ -fpic -shared \ diff --git a/src/ejabberd.erl b/src/ejabberd.erl index e313cec8..e560d79c 100644 --- a/src/ejabberd.erl +++ b/src/ejabberd.erl @@ -21,6 +21,7 @@ init() -> ok = erl_ddll:load_driver(".", expat_erl), Port = open_port({spawn, expat_erl}, [binary]), db_init(), + sha:start(), ejabberd_auth:start(), ejabberd_router:start(), ejabberd_sm:start(), diff --git a/src/ejabberd_auth.erl b/src/ejabberd_auth.erl index 4463932c..86b6d3b4 100644 --- a/src/ejabberd_auth.erl +++ b/src/ejabberd_auth.erl @@ -19,6 +19,7 @@ -export([start/0, start_link/0, set_password/2, check_password/2, + check_password/4, try_register/2]). %% gen_server callbacks @@ -110,6 +111,31 @@ check_password(User, Password) -> false end. +check_password(User, Password, StreamID, Digest) -> + LUser = jlib:tolower(User), + F = fun() -> + case mnesia:read({passwd, LUser}) of + [E] -> + E#passwd.password + end + end, + case mnesia:transaction(F) of + {atomic, Passwd} -> + DigRes = if + Digest /= "" -> + Digest == sha:sha(StreamID ++ Passwd); + true -> + false + end, + if DigRes -> + true; + true -> + Passwd == Password + end; + _ -> + false + end. + set_password(User, Password) -> LUser = jlib:tolower(User), diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 60946e4b..ddce27c5 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -113,9 +113,9 @@ wait_for_auth({xmlstreamelement, El}, StateData) -> {auth, ID, {U, P, D, R}} -> io:format("AUTH: ~p~n", [{U, P, D, R}]), % TODO: digested password - case ejabberd_auth:check_password(U, P) of + case ejabberd_auth:check_password(U, P, + StateData#state.streamid, D) of true -> - % TODO ejabberd_sm:open_session(U, R), Res = jlib:make_result_iq_reply(El), send_element(StateData#state.sender, Res), @@ -181,7 +181,9 @@ session_established({xmlstreamelement, El}, StateData) -> [FromJID, El, StateData]), presence_update(FromJID, El, StateData); _ -> - ejabberd_router:route(FromJID, ToJID, El), + ejabberd_router:route({StateData#state.user, + Server, ""}, + ToJID, El), presence_track(FromJID, ToJID, El, StateData) end; _ -> @@ -267,24 +269,12 @@ handle_info({route, From, To, Packet}, StateName, StateData) -> Attrs1 = lists:keydelete("type", 1, Attrs), {true, [{"type", "unavailable"} | Attrs1], StateData}; "subscribe" -> - mod_roster:in_subscription(StateData#state.user, - {FU, FS, ""}, - subscribe), {true, Attrs, StateData}; "subscribed" -> - mod_roster:in_subscription(StateData#state.user, - {FU, FS, ""}, - subscribed), {true, Attrs, StateData}; "unsubscribe" -> - mod_roster:in_subscription(StateData#state.user, - {FU, FS, ""}, - unsubscribe), {true, Attrs, StateData}; "unsubscribed" -> - mod_roster:in_subscription(StateData#state.user, - {FU, FS, ""}, - unsubscribed), {true, Attrs, StateData}; _ -> {true, Attrs, StateData} @@ -450,10 +440,17 @@ presence_update(From, Packet, StateData) -> true -> StateData end, - StateData; "error" -> StateData; + "subscribe" -> + StateData; + "subscribed" -> + StateData; + "unsubscribe" -> + StateData; + "unsubscribed" -> + StateData; _ -> FromUnavail = (StateData#state.pres_last == undefined) or StateData#state.pres_invis, @@ -479,28 +476,36 @@ presence_update(From, Packet, StateData) -> presence_track(From, To, Packet, StateData) -> {xmlelement, Name, Attrs, Els} = Packet, + LTo = jlib:jid_tolower(To), + User = StateData#state.user, case xml:get_attr_s("type", Attrs) of "unavailable" -> - I = remove_element(To, StateData#state.pres_i), - A = remove_element(To, StateData#state.pres_a), + I = remove_element(LTo, StateData#state.pres_i), + A = remove_element(LTo, StateData#state.pres_a), StateData#state{pres_i = I, pres_a = A}; "invisible" -> - I = ?SETS:add_element(To, StateData#state.pres_i), - A = remove_element(To, StateData#state.pres_a), + I = ?SETS:add_element(LTo, StateData#state.pres_i), + A = remove_element(LTo, StateData#state.pres_a), StateData#state{pres_i = I, pres_a = A}; "subscribe" -> + mod_roster:out_subscription(User, To, subscribe), StateData; "subscribed" -> + mod_roster:out_subscription(User, To, subscribed), StateData; "unsubscribe" -> + mod_roster:out_subscription(User, To, unsubscribe), StateData; "unsubscribed" -> + mod_roster:out_subscription(User, To, unsubscribed), + StateData; + "error" -> StateData; _ -> - I = remove_element(To, StateData#state.pres_i), - A = ?SETS:add_element(To, StateData#state.pres_a), + I = remove_element(LTo, StateData#state.pres_i), + A = ?SETS:add_element(LTo, StateData#state.pres_a), StateData#state{pres_i = I, pres_a = A} end. diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index b6657eff..e28eeb74 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -100,17 +100,7 @@ do_route(From, To, Packet) -> end, case mnesia:transaction(F) of {atomic, error} -> - % TODO: start s2s instead of below ejabberd_s2s ! {route, From, To, Packet}; - %{xmlelement, Name, Attrs, SubTags} = Packet, - %case xml:get_attr_s("type", Attrs) of - % "error" -> - % ok; - % _ -> - % Err = jlib:make_error_reply(Packet, - % "502", "Service Unavailable"), - % ejabberd_router ! {route, To, From, Err} - %end; {atomic, {ok, Node, Pid}} -> case node() of Node -> diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl index ca45cbbc..c032e24f 100644 --- a/src/ejabberd_s2s_in.erl +++ b/src/ejabberd_s2s_in.erl @@ -186,26 +186,49 @@ wait_for_verification(closed, StateData) -> stream_established({xmlstreamelement, El}, StateData) -> {xmlelement, Name, Attrs, Els} = El, - % TODO - From = xml:get_attr_s("from", Attrs), - FromJID1 = jlib:string_to_jid(From), - FromJID = case FromJID1 of - {Node, Server, Resource} -> - if Server == StateData#state.server -> FromJID1; - true -> error - end; - _ -> error - end, - To = xml:get_attr_s("to", Attrs), - ToJID = case To of - "" -> error; - _ -> jlib:string_to_jid(To) - end, - if ((Name == "iq") or (Name == "message") or (Name == "presence")) and - (ToJID /= error) and (FromJID /= error) -> - ejabberd_router:route(FromJID, ToJID, El); - true -> - error + case Name of + "db:verify" -> + case is_key_packet(El) of + {verify, To, From, Id, Key} -> + io:format("VERIFY KEY: ~p~n", [{To, From, Id, Key}]), + Key1 = ejabberd_s2s:get_key(From), + Type = if Key == Key1 -> "valid"; + true -> "invalid" + end, + send_element(StateData#state.socket, + {xmlelement, + "db:verify", + [{"from", ?MYNAME}, + {"to", From}, + {"id", Id}, + {"type", Type}], + []}); + _ -> + ok + end; + _ -> + From = xml:get_attr_s("from", Attrs), + FromJID1 = jlib:string_to_jid(From), + FromJID = case FromJID1 of + {Node, Server, Resource} -> + if Server == StateData#state.server -> FromJID1; + true -> error + end; + _ -> error + end, + To = xml:get_attr_s("to", Attrs), + ToJID = case To of + "" -> error; + _ -> jlib:string_to_jid(To) + end, + if ((Name == "iq") or + (Name == "message") or + (Name == "presence")) and + (ToJID /= error) and (FromJID /= error) -> + ejabberd_router:route(FromJID, ToJID, El); + true -> + error + end end, {next_state, stream_established, StateData}; diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 975be95f..ea767a39 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -169,18 +169,45 @@ do_route(From, To, Packet) -> % TODO case Name of "presence" -> - lists:foreach( - fun(R) -> - if From /= {User, Server, R} -> - ejabberd_sm ! {route, - From, - {User, Server, R}, - Packet}; - true -> - ok - end - end, get_user_resources(User)), - ok; + {FU, FS, FR} = From, + Pass = case xml:get_attr_s("type", Attrs) of + "subscribe" -> + mod_roster:in_subscription(User, + {FU, FS, ""}, + subscribe); + "subscribed" -> + mod_roster:in_subscription(User, + {FU, FS, ""}, + subscribed); + "unsubscribe" -> + mod_roster:in_subscription(User, + {FU, FS, ""}, + unsubscribe); + "unsubscribed" -> + mod_roster:in_subscription(User, + {FU, FS, ""}, + unsubscribed); + _ -> + true + end, + if Pass -> + LFrom = jlib:jid_tolower(From), + LUser = jlib:tolower(User), + LServer = jlib:tolower(Server), + lists:foreach( + fun(R) -> + if LFrom /= {LUser, LServer, R} -> + ejabberd_sm ! {route, + From, + {User, Server, R}, + Packet}; + true -> + ok + end + end, get_user_resources(User)); + true -> + ok + end; "message" -> % TODO ok; diff --git a/src/jlib.erl b/src/jlib.erl index 62910a12..e450b80b 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -20,6 +20,7 @@ string_to_jid/1, jid_to_string/1, tolower/1, + jid_tolower/1, get_iq_namespace/1, iq_query_info/1, is_iq_request_type/1, @@ -179,6 +180,8 @@ tolower(S) -> lists:map(fun tolower_c/1, S). +jid_tolower({U, S, R}) -> + {tolower(U), tolower(S), R}. get_iq_namespace({xmlelement, Name, Attrs, Els}) when Name == "iq" -> case xml:remove_cdata(Els) of diff --git a/src/mod_roster.erl b/src/mod_roster.erl index 197dc29e..6c23a0f1 100644 --- a/src/mod_roster.erl +++ b/src/mod_roster.erl @@ -15,15 +15,18 @@ -export([start/0, init/0, process_iq/3, get_subscription_lists/1, - in_subscription/3]). + in_subscription/3, + out_subscription/3]). -include_lib("mnemosyne/include/mnemosyne.hrl"). -include("ejabberd.hrl"). --record(roster, {user, +-record(roster, {uj, + user, jid, name = "", subscription = none, + ask = none, groups = [], xattrs = [], xs = []}). @@ -35,9 +38,8 @@ start() -> init() -> mnesia:create_table(roster,[{disc_copies, [node()]}, - {type, bag}, {attributes, record_info(fields, roster)}]), - mnesia:add_table_index(roster, jid), + mnesia:add_table_index(roster, user), ejabberd_local:register_iq_handler("jabber:iq:roster", ?MODULE, process_iq), loop(). @@ -83,7 +85,7 @@ process_iq_get(From, To, {iq, ID, Type, XMLNS, SubEl}) -> {User, _, _} = From, LUser = jlib:tolower(User), F = fun() -> - mnesia:read({roster, LUser}) + mnesia:index_read(roster, LUser, #roster.user) end, case mnesia:transaction(F) of {atomic, Items} -> @@ -108,15 +110,24 @@ item_to_xml(Item) -> Attrs3 = case Item#roster.subscription of none -> [{"subscription", "none"} | Attrs2]; + from -> + [{"subscription", "from"} | Attrs2]; + to -> + [{"subscription", "to"} | Attrs2]; both -> [{"subscription", "both"} | Attrs2]; remove -> - [{"subscription", "remove"} | Attrs2]; - _ -> - % TODO - Attrs2 + [{"subscription", "remove"} | Attrs2] end, - Attrs = Attrs3 ++ Item#roster.xattrs, + Attrs4 = case Item#roster.ask of + none -> + Attrs3; + subscribe -> + [{"ask", "subscribe"} | Attrs3]; + unsubscribe -> + [{"ask", "unsubscribe"} | Attrs3] + end, + Attrs = Attrs4 ++ Item#roster.xattrs, SubEls1 = lists:map(fun(G) -> {xmlelement, "group", [], [{xmlcdata, G}]} end, Item#roster.groups), @@ -139,21 +150,18 @@ process_item_set(User, To, XItem) -> error -> ok; _ -> + LJID = jlib:jid_tolower(JID), F = fun() -> - Res = mnemosyne:eval(query [X || X <- table(roster), - X.user = LUser, - X.jid = JID] - end), + Res = mnesia:read({roster, {LUser, LJID}}), Item = case Res of [] -> - #roster{user = LUser, - jid = JID, - groups = [], - xattrs = [], - xs = []}; + #roster{uj = {LUser, LJID}, + user = LUser, + jid = JID}; [I] -> - mnesia:delete_object(I), - I#roster{name = "", + I#roster{user = LUser, + jid = JID, + name = "", groups = [], xattrs = [], xs = []} @@ -162,7 +170,7 @@ process_item_set(User, To, XItem) -> Item2 = process_item_els(Item1, Els), case Item2#roster.subscription of remove -> - ok; + mnesia:delete({roster, {LUser, LJID}}); _ -> mnesia:write(Item2) end, @@ -249,7 +257,7 @@ push_item(User, Resource, From, Item) -> get_subscription_lists(User) -> LUser = jlib:tolower(User), F = fun() -> - mnesia:read({roster, LUser}) + mnesia:index_read(roster, LUser, #roster.user) end, case mnesia:transaction(F) of {atomic, Items} -> @@ -259,7 +267,8 @@ get_subscription_lists(User) -> end. fill_subscription_lists([I | Is], F, T) -> - J = I#roster.jid, + %J = I#roster.jid, + J = element(2, I#roster.uj), case I#roster.subscription of both -> fill_subscription_lists(Is, [J | F], [J | T]); @@ -276,14 +285,146 @@ fill_subscription_lists([], F, T) -> in_subscription(User, From, Type) -> LUser = jlib:tolower(User), + LFrom = jlib:jid_tolower(From), + {FU, FS, FR} = From, F = fun() -> - mnesia:read({roster, LUser}) + case mnesia:read({roster, {LUser, LFrom}}) of + [] -> + case Type of + subscribe -> + true; + unsubscribe -> + true; + unsubscribed -> + false; + subscribed -> + NewItem = #roster{uj = {LUser, LFrom}, + user = LUser, + jid = From}, + mnesia:write(NewItem), + true + end; + [I] -> + case Type of + subscribe -> + S = I#roster.subscription, + if + (S == both) or (S == from) -> + ejabberd_router:route( + {User, ?MYNAME, ""}, {FU, FS, ""}, + {xmlelement, "presence", + [{"type", "subscribed"}], []}), + % TODO: update presence + false; + true -> + true + end; + unsubscribe -> + S = I#roster.subscription, + if + (S == none) or (S == to) -> + ejabberd_router:route( + {User, ?MYNAME, ""}, {FU, FS, ""}, + {xmlelement, "presence", + [{"type", "unsubscribed"}], []}), + % TODO: update presence + false; + true -> + true + end; + _ -> + S = I#roster.subscription, + NS = case Type of + subscribed -> + case S of + from -> both; + none -> to; + _ -> S + end; + unsubscribed -> + case S of + both -> from; + to -> none; + _ -> S + end + end, + NewItem = I#roster{subscription = NS, + ask = none}, + mnesia:write(NewItem), + {push, NewItem} + end + end end, case mnesia:transaction(F) of - {atomic, Items} -> - % TODO + {atomic, true} -> + true; + {atomic, false} -> + false; + {atomic, {push, Item}} -> + push_item(User, {"", ?MYNAME, ""}, Item), + true; + _ -> + false + end. + +out_subscription(User, JID, Type) -> + LUser = jlib:tolower(User), + LJID = jlib:jid_tolower(JID), + F = fun() -> + Item = case mnesia:read({roster, {LUser, LJID}}) of + [] -> + if (Type == unsubscribe) or + (Type == unsubscribed) -> + false; + true -> + #roster{uj = {LUser, LJID}, + user = LUser, + jid = JID} + end; + [I] -> + I + end, + if Item == false -> + ok; + true -> + NewItem = + case Type of + subscribe -> + Item#roster{ask = subscribe}; + unsubscribe -> + Item#roster{ask = unsubscribe}; + subscribed -> + S = Item#roster.subscription, + NS = case S of + to -> both; + none -> from; + _ -> S + end, + % TODO: update presence + Item#roster{subscription = NS, + ask = none}; + unsubscribed -> + S = Item#roster.subscription, + NS = case S of + both -> to; + from -> none; + _ -> S + end, + % TODO: update presence + Item#roster{subscription = NS, + ask = none} + end, + mnesia:write(NewItem), + {push, NewItem} + end + end, + case mnesia:transaction(F) of + {atomic, ok} -> ok; + {atomic, {push, Item}} -> + push_item(User, {"", ?MYNAME, ""}, Item), + true; _ -> - ok + false end. diff --git a/src/sha.erl b/src/sha.erl new file mode 100644 index 00000000..b0339b1a --- /dev/null +++ b/src/sha.erl @@ -0,0 +1,42 @@ +%%%---------------------------------------------------------------------- +%%% File : sha.erl +%%% Author : Alexey Shchepin <alexey@sevcom.net> +%%% Purpose : +%%% Created : 20 Dec 2002 by Alexey Shchepin <alexey@sevcom.net> +%%% Id : $Id$ +%%%---------------------------------------------------------------------- + +-module(sha). +-author('alexey@sevcom.net'). +-vsn('$Revision$ '). + +-export([start/0, init/0, sha/1]). + +start() -> + register(sha, spawn(?MODULE, init, [])). + +init() -> + ok = erl_ddll:load_driver(".", sha_erl), + Port = open_port({spawn, sha_erl}, [binary]), + loop(Port). + +loop(Port) -> + receive + {From, {text, Str}} -> + Port ! {self(), {command, Str}}, + SHA = receive + {Port, {data, Bin}} -> + binary_to_term(Bin) + end, + From ! {sha, SHA}, + loop(Port) + end. + +sha(Text) -> + sha ! {self(), {text, Text}}, + receive + {sha, S} -> + S + end. + + |