Skip to content

Commit 7fbf507

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 <[email protected]>
1 parent 69f4236 commit 7fbf507

File tree

4 files changed

+29
-16
lines changed

4 files changed

+29
-16
lines changed

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;
@@ -864,9 +865,10 @@ void conn_established(xmpp_conn_t *conn)
864865

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

1031-
if (conn->state != XMPP_STATE_CONNECTED)
1034+
if (!_is_connected(conn, XMPP_QUEUE_USER))
10321035
return;
10331036

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

12281240
/**
1229-
* @return TRUE if connection is in connected state and FALSE otherwise
1241+
* @return TRUE if connection is established and FALSE otherwise
12301242
*
12311243
* @ingroup Connections
12321244
*/
12331245
int xmpp_conn_is_connected(xmpp_conn_t *conn)
12341246
{
1235-
return conn->state == XMPP_STATE_CONNECTED;
1247+
return _is_connected(conn, XMPP_QUEUE_USER);
12361248
}
12371249

12381250
/**
@@ -1793,7 +1805,7 @@ static void _conn_reset(xmpp_conn_t *conn)
17931805
strophe_free_and_null(ctx, conn->domain);
17941806
strophe_free_and_null(ctx, conn->bound_jid);
17951807
strophe_free_and_null(ctx, conn->stream_id);
1796-
conn->authenticated = 0;
1808+
conn->stream_negotiation_completed = 0;
17971809
conn->secured = 0;
17981810
conn->tls_failed = 0;
17991811
conn->error = 0;
@@ -1880,7 +1892,7 @@ static void _send_valist(xmpp_conn_t *conn,
18801892
char buf[1024]; /* small buffer for common case */
18811893
char *bigbuf;
18821894

1883-
if (conn->state != XMPP_STATE_CONNECTED)
1895+
if (!_is_connected(conn, owner))
18841896
return;
18851897

18861898
va_copy(apdup, ap);
@@ -1928,7 +1940,7 @@ void send_stanza(xmpp_conn_t *conn,
19281940
char *buf = NULL;
19291941
size_t len;
19301942

1931-
if (conn->state != XMPP_STATE_CONNECTED)
1943+
if (!_is_connected(conn, owner))
19321944
goto out;
19331945

19341946
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)