summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--src/ejabberd_c2s.erl75
-rw-r--r--src/expat_erl.c4
-rw-r--r--src/jlib.hrl57
-rw-r--r--src/mod_muc/mod_muc_room.erl5
-rw-r--r--src/web/ejabberd_web_admin.erl2
-rw-r--r--src/xml_stream.erl55
7 files changed, 185 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog
index a2d0e248..72b29349 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2004-12-05 Alexey Shchepin <alexey@sevcom.net>
+
+ * src/web/ejabberd_web_admin.erl: Changed type of password field
+ to "password"
+
+ * src/jlib.hrl: More stream error defines (thanks to Sergei
+ Golovan)
+
+ * src/ejabberd_c2s.erl: Support for starttls_required option
+ (thanks to Sergei Golovan)
+
+ * src/mod_muc/mod_muc_room.erl: Fixed mistake in case condition
+ (thanks to Sergei Golovan)
+
+ * src/xml_stream.erl: Added function parse_element/1
+
+ * src/expat_erl.c: Added PARSE_FINAL_COMMAND
+
2004-12-03 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_listener.erl: Enable keepalive option
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 2084a05e..92b3fb21 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -46,6 +46,7 @@
access,
shaper,
tls = false,
+ tls_required = false,
tls_enabled = false,
tls_options = [],
authentificated = false,
@@ -82,6 +83,8 @@
xml:element_to_string(?SERR_INVALID_NAMESPACE)).
-define(INVALID_XML_ERR,
xml:element_to_string(?SERR_XML_NOT_WELL_FORMED)).
+-define(POLICY_VIOLATION_ERR(Lang, Text),
+ xml:element_to_string(?SERRT_POLICY_VIOLATION(Lang, Text))).
%%%----------------------------------------------------------------------
%%% API
@@ -117,8 +120,9 @@ init([{SockMod, Socket}, Opts]) ->
_ -> none
end,
StartTLS = lists:member(starttls, Opts),
+ StartTLSRequired = lists:member(starttls_required, Opts),
TLSEnabled = lists:member(tls, Opts),
- TLS = StartTLS orelse TLSEnabled,
+ TLS = StartTLS orelse StartTLSRequired orelse TLSEnabled,
TLSOpts = lists:filter(fun({certfile, _}) -> true;
(_) -> false
end, Opts),
@@ -132,15 +136,16 @@ init([{SockMod, Socket}, Opts]) ->
RecPid = ejabberd_receiver:start(Socket, SockMod, none),
{SockMod, Socket, RecPid}
end,
- {ok, wait_for_stream, #state{socket = Socket1,
- sockmod = SockMod1,
- receiver = ReceiverPid,
- tls = TLS,
- tls_enabled = TLSEnabled,
- tls_options = TLSOpts,
- streamid = new_id(),
- access = Access,
- shaper = Shaper}}.
+ {ok, wait_for_stream, #state{socket = Socket1,
+ sockmod = SockMod1,
+ receiver = ReceiverPid,
+ tls = TLS,
+ tls_required = StartTLSRequired,
+ tls_enabled = TLSEnabled,
+ tls_options = TLSOpts,
+ streamid = new_id(),
+ access = Access,
+ shaper = Shaper}}.
%%----------------------------------------------------------------------
@@ -179,14 +184,23 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, StateData) ->
end, cyrsasl:listmech()),
TLS = StateData#state.tls,
TLSEnabled = StateData#state.tls_enabled,
+ TLSRequired = StateData#state.tls_required,
SockMod = StateData#state.sockmod,
TLSFeature =
case (TLS == true) andalso
(TLSEnabled == false) andalso
(SockMod == gen_tcp) of
true ->
- [{xmlelement, "starttls",
- [{"xmlns", ?NS_TLS}], []}];
+ case TLSRequired of
+ true ->
+ [{xmlelement, "starttls",
+ [{"xmlns", ?NS_TLS}],
+ [{xmlelement, "required",
+ [], []}]}];
+ _ ->
+ [{xmlelement, "starttls",
+ [{"xmlns", ?NS_TLS}], []}]
+ end;
false ->
[]
end,
@@ -379,9 +393,10 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
{xmlelement, Name, Attrs, Els} = El,
TLS = StateData#state.tls,
TLSEnabled = StateData#state.tls_enabled,
+ TLSRequired = StateData#state.tls_required,
SockMod = StateData#state.sockmod,
case {xml:get_attr_s("xmlns", Attrs), Name} of
- {?NS_SASL, "auth"} ->
+ {?NS_SASL, "auth"} when not ((SockMod == gen_tcp) and TLSRequired) ->
Mech = xml:get_attr_s("mechanism", Attrs),
ClientIn = jlib:decode_base64(xml:get_cdata(Els)),
case cyrsasl:server_start(StateData#state.sasl_state,
@@ -429,18 +444,28 @@ wait_for_feature_request({xmlstreamelement, El}, StateData) ->
tls_enabled = true
}};
_ ->
- case jlib:iq_query_info(El) of
- #iq{xmlns = ?NS_REGISTER} = IQ ->
- ResIQ = mod_register:process_iq(
- {"", "", ""}, {"", ?MYNAME, ""}, IQ),
- Res1 = jlib:replace_from_to({"", ?MYNAME, ""},
- {"", "", ""},
- jlib:iq_to_xml(ResIQ)),
- Res = jlib:remove_attr("to", Res1),
- send_element(StateData, Res),
- {next_state, wait_for_feature_request, StateData};
- _ ->
- {next_state, wait_for_feature_request, StateData}
+ if
+ (SockMod == gen_tcp) and TLSRequired ->
+ Lang = StateData#state.lang,
+ send_text(StateData, ?POLICY_VIOLATION_ERR(
+ Lang,
+ "Use of STARTTLS required") ++
+ ?STREAM_TRAILER),
+ {stop, normal, StateData};
+ true ->
+ case jlib:iq_query_info(El) of
+ #iq{xmlns = ?NS_REGISTER} = IQ ->
+ ResIQ = mod_register:process_iq(
+ {"", "", ""}, {"", ?MYNAME, ""}, IQ),
+ Res1 = jlib:replace_from_to({"", ?MYNAME, ""},
+ {"", "", ""},
+ jlib:iq_to_xml(ResIQ)),
+ Res = jlib:remove_attr("to", Res1),
+ send_element(StateData, Res),
+ {next_state, wait_for_feature_request, StateData};
+ _ ->
+ {next_state, wait_for_feature_request, StateData}
+ end
end
end;
diff --git a/src/expat_erl.c b/src/expat_erl.c
index 8cc9f290..1b197dac 100644
--- a/src/expat_erl.c
+++ b/src/expat_erl.c
@@ -107,6 +107,7 @@ int ei_x_encode_string_fixed(ei_x_buff* x, const char* s)
#define XML_ERROR 3
#define PARSE_COMMAND 0
+#define PARSE_FINAL_COMMAND 1
ei_x_buff event_buf;
@@ -208,8 +209,9 @@ static int expat_erl_control(ErlDrvData drv_data,
switch (command)
{
case PARSE_COMMAND:
+ case PARSE_FINAL_COMMAND:
ei_x_new_with_version(&event_buf);
- res = XML_Parse(d->parser, buf, len, 0);
+ res = XML_Parse(d->parser, buf, len, command == PARSE_FINAL_COMMAND);
if(!res)
{
diff --git a/src/jlib.hrl b/src/jlib.hrl
index c2a9ba43..5f9e17b5 100644
--- a/src/jlib.hrl
+++ b/src/jlib.hrl
@@ -214,6 +214,63 @@
%-define(SERR_,
% ?STREAM_ERROR("")).
+-define(STREAM_ERRORT(Condition, Lang, Text),
+ {xmlelement, "stream:error",
+ [],
+ [{xmlelement, Condition, [{"xmlns", ?NS_STREAMS}], []},
+ {xmlelement, "text", [{"xml:lang", Lang}, {"xmlns", ?NS_STREAMS}],
+ [{xmlcdata, translate:translate(Lang, Text)}]}]}).
+
+-define(SERRT_BAD_FORMAT(Lang, Text),
+ ?STREAM_ERRORT("bad-format", Lang, Text)).
+-define(SERRT_BAD_NAMESPACE_PREFIX(Lang, Text),
+ ?STREAM_ERRORT("bad-namespace-prefix", Lang, Text)).
+-define(SERRT_CONFLICT(Lang, Text),
+ ?STREAM_ERRORT("conflict", Lang, Text)).
+-define(SERRT_CONNECTION_TIMEOUT(Lang, Text),
+ ?STREAM_ERRORT("connection-timeout", Lang, Text)).
+-define(SERRT_HOST_GONE(Lang, Text),
+ ?STREAM_ERRORT("host-gone", Lang, Text)).
+-define(SERRT_HOST_UNKNOWN(Lang, Text),
+ ?STREAM_ERRORT("host-unknown", Lang, Text)).
+-define(SERRT_IMPROPER_ADDRESSING(Lang, Text),
+ ?STREAM_ERRORT("improper-addressing", Lang, Text)).
+-define(SERRT_INTERNAL_SERVER_ERROR(Lang, Text),
+ ?STREAM_ERRORT("internal-server-error", Lang, Text)).
+-define(SERRT_INVALID_FROM(Lang, Text),
+ ?STREAM_ERRORT("invalid-from", Lang, Text)).
+-define(SERRT_INVALID_ID(Lang, Text),
+ ?STREAM_ERRORT("invalid-id", Lang, Text)).
+-define(SERRT_INVALID_NAMESPACE(Lang, Text),
+ ?STREAM_ERRORT("invalid-namespace", Lang, Text)).
+-define(SERRT_INVALID_XML(Lang, Text),
+ ?STREAM_ERRORT("invalid-xml", Lang, Text)).
+-define(SERRT_NOT_AUTHORIZED(Lang, Text),
+ ?STREAM_ERRORT("not-authorized", Lang, Text)).
+-define(SERRT_POLICY_VIOLATION(Lang, Text),
+ ?STREAM_ERRORT("policy-violation", Lang, Text)).
+-define(SERRT_REMOTE_CONNECTION_FAILED(Lang, Text),
+ ?STREAM_ERRORT("remote-connection-failed", Lang, Text)).
+-define(SERRT_RESOURSE_CONSTRAINT(Lang, Text),
+ ?STREAM_ERRORT("resource-constraint", Lang, Text)).
+-define(SERRT_RESTRICTED_XML(Lang, Text),
+ ?STREAM_ERRORT("restricted-xml", Lang, Text)).
+% TODO: include hostname or IP
+-define(SERRT_SEE_OTHER_HOST(Lang, Text),
+ ?STREAM_ERRORT("see-other-host", Lang, Text)).
+-define(SERRT_SYSTEM_SHUTDOWN(Lang, Text),
+ ?STREAM_ERRORT("system-shutdown", Lang, Text)).
+-define(SERRT_UNSUPPORTED_ENCODING(Lang, Text),
+ ?STREAM_ERRORT("unsupported-encoding", Lang, Text)).
+-define(SERRT_UNSUPPORTED_STANZA_TYPE(Lang, Text),
+ ?STREAM_ERRORT("unsupported-stanza-type", Lang, Text)).
+-define(SERRT_UNSUPPORTED_VERSION(Lang, Text),
+ ?STREAM_ERRORT("unsupported-version", Lang, Text)).
+-define(SERRT_XML_NOT_WELL_FORMED(Lang, Text),
+ ?STREAM_ERRORT("xml-not-well-formed", Lang, Text)).
+%-define(SERRT_(Lang, Text),
+% ?STREAM_ERRORT("", Lang, Text)).
+
-record(jid, {user, server, resource,
luser, lserver, lresource}).
diff --git a/src/mod_muc/mod_muc_room.erl b/src/mod_muc/mod_muc_room.erl
index 810f1d58..f41c4532 100644
--- a/src/mod_muc/mod_muc_room.erl
+++ b/src/mod_muc/mod_muc_room.erl
@@ -1023,7 +1023,6 @@ count_stanza_shift(Nick, Els, StateData) ->
_ ->
count_maxchars_shift(Nick, MaxChars, HL)
end,
-
lists:max([Shift0, Shift1, Shift2, Shift3]).
count_seconds_shift(Seconds, HistoryList) ->
@@ -1087,7 +1086,7 @@ extract_history([{xmlelement, _Name, Attrs, _SubEls} = El | Els], Type) ->
end;
_ ->
case catch list_to_integer(AttrVal) of
- IntVal when is_integer(IntVal) and IntVal >= 0 ->
+ IntVal when is_integer(IntVal) and (IntVal >= 0) ->
IntVal;
_ ->
false
@@ -1486,7 +1485,7 @@ process_admin_items_set(UJID, Items, Lang, StateData) ->
JID, outcast,
set_role(JID, none, SD));
{JID, affiliation, A, Reason} when
- (A == admin) or (A == owner)->
+ (A == admin) or (A == owner) ->
SD1 = set_affiliation(JID, A, SD),
SD2 = set_role(JID, moderator, SD1),
send_update_presence(JID, SD2),
diff --git a/src/web/ejabberd_web_admin.erl b/src/web/ejabberd_web_admin.erl
index 13e15eca..49531222 100644
--- a/src/web/ejabberd_web_admin.erl
+++ b/src/web/ejabberd_web_admin.erl
@@ -1228,7 +1228,7 @@ user_info(User, Query, Lang) ->
end, lists:sort(Resources)))]
end,
Password = ejabberd_auth:get_password_s(User),
- FPassword = [?INPUT("text", "password", Password), ?C(" "),
+ FPassword = [?INPUT("password", "password", Password), ?C(" "),
?INPUTT("submit", "chpassword", "Change Password")],
QueueLen = length(mnesia:dirty_read({offline_msg, User})),
FQueueLen = [?AC("queue/",
diff --git a/src/xml_stream.erl b/src/xml_stream.erl
index d5fbd937..d00fd4ca 100644
--- a/src/xml_stream.erl
+++ b/src/xml_stream.erl
@@ -15,7 +15,8 @@
send_text/2,
new/1,
parse/2,
- close/1]).
+ close/1,
+ parse_element/1]).
-define(XML_START, 0).
-define(XML_END, 1).
@@ -23,6 +24,7 @@
-define(XML_ERROR, 3).
-define(PARSE_COMMAND, 0).
+-define(PARSE_FINAL_COMMAND, 1).
-record(xml_stream_state, {callback_pid, port, stack}).
@@ -123,3 +125,54 @@ parse(#xml_stream_state{callback_pid = CallbackPid,
close(#xml_stream_state{port = Port}) ->
port_close(Port).
+
+
+parse_element(Str) ->
+ Port = open_port({spawn, expat_erl}, [binary]),
+ Res = port_control(Port, ?PARSE_FINAL_COMMAND, Str),
+ port_close(Port),
+ process_element_events(binary_to_term(Res)).
+
+process_element_events(Events) ->
+ process_element_events(Events, []).
+
+process_element_events([], _Stack) ->
+ {error, parse_error};
+process_element_events([Event | Events], Stack) ->
+ case Event of
+ {?XML_START, {Name, Attrs}} ->
+ process_element_events(
+ Events, [{xmlelement, Name, Attrs, []} | Stack]);
+ {?XML_END, _EndName} ->
+ case Stack of
+ [{xmlelement, Name, Attrs, Els} | Tail] ->
+ NewEl = {xmlelement, Name, Attrs, lists:reverse(Els)},
+ case Tail of
+ [] ->
+ if
+ Events == [] ->
+ NewEl;
+ true ->
+ {error, parse_error}
+ end;
+ [{xmlelement, Name1, Attrs1, Els1} | Tail1] ->
+ process_element_events(
+ Events,
+ [{xmlelement, Name1, Attrs1, [NewEl | Els1]} |
+ Tail1])
+ end
+ end;
+ {?XML_CDATA, CData} ->
+ case Stack of
+ [{xmlelement, Name, Attrs, Els} | Tail] ->
+ process_element_events(
+ Events,
+ [{xmlelement, Name, Attrs, [{xmlcdata, CData} | Els]} |
+ Tail]);
+ [] ->
+ process_element_events(Events, [])
+ end;
+ {?XML_ERROR, Err} ->
+ {error, Err}
+ end.
+