Skip to content

Commit 3b04288

Browse files
committed
Fix connected/connecting semantics
In case a connection is established, but the stream negotiation has not completed yet, a user may think that they can start sending data, but this is not the case. All of the following quotes originate in RFC6120. As of Ch. 8: > After a client and a server (or two servers) have completed stream > negotiation, either party can send XML stanzas. As of Ch. 7.3.1: > The parties to a stream MUST consider resource binding as > mandatory-to-negotiate. As of Ch. 6.3.1: > The parties to a stream MUST consider SASL as mandatory-to-negotiate. As of Ch. 4.3.5: > The initiating entity MUST NOT attempt to send XML stanzas to entities > other than itself (i.e., the client's connected resource or any other > authenticated resource of the client's account) or the server to which > it is connected until stream negotiation has been completed. > Even if the initiating entity does attempt to do so, the receiving > entity MUST NOT accept such stanzas and MUST close the stream with a > <not-authorized/> stream error [...] Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
1 parent a21a4f7 commit 3b04288

4 files changed

Lines changed: 29 additions & 16 deletions

File tree

src/auth.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ static void _auth(xmpp_conn_t *conn)
816816
static void _auth_success(xmpp_conn_t *conn)
817817
{
818818
tls_clear_password_cache(conn);
819-
conn->authenticated = 1;
819+
conn->stream_negotiation_completed = 1;
820820
/* call connection handler */
821821
conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
822822
}

src/common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ struct _xmpp_conn_t {
272272
xmpp_open_handler open_handler;
273273

274274
/* user handlers only get called after authentication */
275-
int authenticated;
275+
int stream_negotiation_completed;
276276

277277
/* connection events handler */
278278
xmpp_conn_handler conn_handler;

src/conn.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
#define KEEPALIVE_COUNT 3
7979
#endif
8080

81+
static int _is_connected(xmpp_conn_t *conn, xmpp_send_queue_owner_t owner);
8182
static int _disconnect_cleanup(xmpp_conn_t *conn, void *userdata);
8283
static void _reset_sm_state_for_reconnect(xmpp_conn_t *conn);
8384
static char *_conn_build_stream_tag(xmpp_conn_t *conn,
@@ -207,7 +208,7 @@ xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx)
207208
_handle_stream_stanza, conn);
208209
conn->reset_parser = 0;
209210

210-
conn->authenticated = 0;
211+
conn->stream_negotiation_completed = 0;
211212
conn->conn_handler = NULL;
212213
conn->userdata = NULL;
213214
conn->timed_handlers = NULL;
@@ -865,9 +866,10 @@ void conn_established(xmpp_conn_t *conn)
865866

866867
if (conn->is_raw) {
867868
handler_reset_timed(conn, 0);
868-
/* we skip authentication for a "raw" connection, but the event loop
869-
ignores user's handlers when conn->authenticated is not set. */
870-
conn->authenticated = 1;
869+
/* we skip all the mandatory steps of the stream negotiation for a "raw"
870+
connection, but the event loop ignores user's handlers when
871+
conn->stream_negotiation_completed is not set. */
872+
conn->stream_negotiation_completed = 1;
871873
conn->conn_handler(conn, XMPP_CONN_RAW_CONNECT, 0, NULL,
872874
conn->userdata);
873875
} else {
@@ -961,6 +963,7 @@ void conn_disconnect(xmpp_conn_t *conn)
961963
{
962964
strophe_debug(conn->ctx, "xmpp", "Closing socket.");
963965
conn->state = XMPP_STATE_DISCONNECTED;
966+
conn->stream_negotiation_completed = 0;
964967
if (conn->tls) {
965968
tls_stop(conn->tls);
966969
tls_free(conn->tls);
@@ -1029,7 +1032,7 @@ void xmpp_send_raw_string(xmpp_conn_t *conn, const char *fmt, ...)
10291032
{
10301033
va_list ap;
10311034

1032-
if (conn->state != XMPP_STATE_CONNECTED)
1035+
if (!_is_connected(conn, XMPP_QUEUE_USER))
10331036
return;
10341037

10351038
va_start(ap, fmt);
@@ -1223,17 +1226,26 @@ int xmpp_conn_is_secured(xmpp_conn_t *conn)
12231226
*/
12241227
int xmpp_conn_is_connecting(xmpp_conn_t *conn)
12251228
{
1226-
return conn->state == XMPP_STATE_CONNECTING;
1229+
return conn->state == XMPP_STATE_CONNECTING ||
1230+
(conn->state == XMPP_STATE_CONNECTED &&
1231+
conn->stream_negotiation_completed == 0);
1232+
}
1233+
1234+
static int _is_connected(xmpp_conn_t *conn, xmpp_send_queue_owner_t owner)
1235+
{
1236+
return conn->state == XMPP_STATE_CONNECTED &&
1237+
(owner != XMPP_QUEUE_USER ||
1238+
conn->stream_negotiation_completed == 1);
12271239
}
12281240

12291241
/**
1230-
* @return TRUE if connection is in connected state and FALSE otherwise
1242+
* @return TRUE if connection is established and FALSE otherwise
12311243
*
12321244
* @ingroup Connections
12331245
*/
12341246
int xmpp_conn_is_connected(xmpp_conn_t *conn)
12351247
{
1236-
return conn->state == XMPP_STATE_CONNECTED;
1248+
return _is_connected(conn, XMPP_QUEUE_USER);
12371249
}
12381250

12391251
/**
@@ -1794,7 +1806,7 @@ static void _conn_reset(xmpp_conn_t *conn)
17941806
strophe_free_and_null(ctx, conn->domain);
17951807
strophe_free_and_null(ctx, conn->bound_jid);
17961808
strophe_free_and_null(ctx, conn->stream_id);
1797-
conn->authenticated = 0;
1809+
conn->stream_negotiation_completed = 0;
17981810
conn->secured = 0;
17991811
conn->tls_failed = 0;
18001812
conn->error = 0;
@@ -1881,7 +1893,7 @@ static void _send_valist(xmpp_conn_t *conn,
18811893
char buf[1024]; /* small buffer for common case */
18821894
char *bigbuf;
18831895

1884-
if (conn->state != XMPP_STATE_CONNECTED)
1896+
if (!_is_connected(conn, owner))
18851897
return;
18861898

18871899
va_copy(apdup, ap);
@@ -1929,7 +1941,7 @@ void send_stanza(xmpp_conn_t *conn,
19291941
char *buf = NULL;
19301942
size_t len;
19311943

1932-
if (conn->state != XMPP_STATE_CONNECTED)
1944+
if (!_is_connected(conn, owner))
19331945
goto out;
19341946

19351947
if (xmpp_stanza_to_text(stanza, &buf, &len) != 0) {

src/handler.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ void handler_fire_stanza(xmpp_conn_t *conn, xmpp_stanza_t *stanza)
8383
while (item) {
8484
/* don't fire user handlers until authentication succeeds and
8585
and skip newly added handlers */
86-
if ((item->user_handler && !conn->authenticated) ||
86+
if ((item->user_handler && !conn->stream_negotiation_completed) ||
8787
!item->enabled) {
8888
item = item->next;
8989
continue;
@@ -119,7 +119,8 @@ void handler_fire_stanza(xmpp_conn_t *conn, xmpp_stanza_t *stanza)
119119
while (item) {
120120
/* don't fire user handlers until authentication succeeds and
121121
skip newly added handlers */
122-
if ((item->user_handler && !conn->authenticated) || !item->enabled) {
122+
if ((item->user_handler && !conn->stream_negotiation_completed) ||
123+
!item->enabled) {
123124
item = item->next;
124125
continue;
125126
}
@@ -177,7 +178,7 @@ uint64_t handler_fire_timed(xmpp_ctx_t *ctx)
177178
while (item) {
178179
/* don't fire user handlers until authentication succeeds and
179180
skip newly added handlers */
180-
if ((item->user_handler && !conn->authenticated) ||
181+
if ((item->user_handler && !conn->stream_negotiation_completed) ||
181182
!item->enabled) {
182183
item = item->next;
183184
continue;

0 commit comments

Comments
 (0)