summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2002-12-20 20:42:08 +0000
committerAlexey Shchepin <alexey@process-one.net>2002-12-20 20:42:08 +0000
commitae30798efd9f802e43ec0495162acbe6f340aebd (patch)
tree50726dd86cb685817cf1f7313e13c13ded57500b /src
parent*** empty log message *** (diff)
*** empty log message ***
SVN Revision: 20
Diffstat (limited to '')
-rw-r--r--src/Makefile18
-rw-r--r--src/ejabberd.erl1
-rw-r--r--src/ejabberd_auth.erl26
-rw-r--r--src/ejabberd_c2s.erl49
-rw-r--r--src/ejabberd_router.erl10
-rw-r--r--src/ejabberd_s2s_in.erl63
-rw-r--r--src/ejabberd_sm.erl51
-rw-r--r--src/jlib.erl3
-rw-r--r--src/mod_roster.erl197
-rw-r--r--src/sha.erl42
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.
+
+