Skip to content

Commit 3b0c462

Browse files
committed
1 parent 5142eea commit 3b0c462

File tree

3 files changed

+95
-74
lines changed

3 files changed

+95
-74
lines changed

src/auth.c

Lines changed: 90 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,20 @@ _handle_features(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
277277
}
278278
}
279279

280-
/* check for SASL */
281-
child = xmpp_stanza_get_child_by_name_and_ns(stanza, "mechanisms",
282-
XMPP_NS_SASL);
280+
/* check for SASL2 */
281+
child = xmpp_stanza_get_child_by_name_and_ns(stanza, "authentication",
282+
XMPP_NS_SASL2);
283+
283284
if (child) {
285+
conn->sasl_support |= SASL_MASK_SASL2;
284286
_foreach_child(conn, child, "mechanism", _handle_sasl_children);
287+
} else {
288+
/* check for SASL */
289+
child = xmpp_stanza_get_child_by_name_and_ns(stanza, "mechanisms",
290+
XMPP_NS_SASL);
291+
if (child) {
292+
_foreach_child(conn, child, "mechanism", _handle_sasl_children);
293+
}
285294
}
286295

287296
/* Disable PLAIN when other secure mechanisms are supported */
@@ -350,17 +359,27 @@ _handle_sasl_result(xmpp_conn_t *conn, xmpp_stanza_t *stanza, void *userdata)
350359
/* fall back to next auth method */
351360
_auth(conn);
352361
} else if (strcmp(name, "success") == 0) {
353-
/* SASL auth successful, we need to restart the stream */
354362
strophe_debug(conn->ctx, "xmpp", "SASL %s auth successful",
355363
(char *)userdata);
356364

357-
/* reset parser */
358-
conn_prepare_reset(conn, conn->compression.allowed
359-
? _handle_open_compress
360-
: _handle_open_sasl);
365+
if (conn->sasl_support & SASL_MASK_SASL2) {
366+
/* New features will come, but no restart */
367+
if (conn->compression.allowed) {
368+
_handle_open_compress(conn);
369+
} else {
370+
_handle_open_sasl(conn);
371+
}
372+
} else {
373+
/* SASL auth successful, we need to restart the stream */
361374

362-
/* send stream tag */
363-
conn_open_stream(conn);
375+
/* reset parser */
376+
conn_prepare_reset(conn, conn->compression.allowed
377+
? _handle_open_compress
378+
: _handle_open_sasl);
379+
380+
/* send stream tag */
381+
conn_open_stream(conn);
382+
}
364383
} else {
365384
/* got unexpected reply */
366385
strophe_error(conn->ctx, "xmpp",
@@ -389,6 +408,7 @@ static int _handle_digestmd5_challenge(xmpp_conn_t *conn,
389408
"handle digest-md5 (challenge) called for %s", name);
390409

391410
if (strcmp(name, "challenge") == 0) {
411+
const char* sasl_ns = conn->sasl_support & SASL_MASK_SASL2 ? XMPP_NS_SASL2 : XMPP_NS_SASL;
392412
text = xmpp_stanza_get_text(stanza);
393413
response = sasl_digest_md5(conn->ctx, text, conn->jid, conn->pass);
394414
if (!response) {
@@ -403,7 +423,7 @@ static int _handle_digestmd5_challenge(xmpp_conn_t *conn,
403423
return 0;
404424
}
405425
xmpp_stanza_set_name(auth, "response");
406-
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
426+
xmpp_stanza_set_ns(auth, sasl_ns);
407427

408428
authdata = xmpp_stanza_new(conn->ctx);
409429
if (!authdata) {
@@ -416,7 +436,7 @@ static int _handle_digestmd5_challenge(xmpp_conn_t *conn,
416436

417437
xmpp_stanza_add_child_ex(auth, authdata, 0);
418438

419-
handler_add(conn, _handle_digestmd5_rspauth, XMPP_NS_SASL, NULL, NULL,
439+
handler_add(conn, _handle_digestmd5_rspauth, sasl_ns, NULL, NULL,
420440
NULL);
421441

422442
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
@@ -444,14 +464,15 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t *conn,
444464
"handle digest-md5 (rspauth) called for %s", name);
445465

446466
if (strcmp(name, "challenge") == 0) {
467+
const char* sasl_ns = conn->sasl_support & SASL_MASK_SASL2 ? XMPP_NS_SASL2 : XMPP_NS_SASL;
447468
/* assume it's an rspauth response */
448469
auth = xmpp_stanza_new(conn->ctx);
449470
if (!auth) {
450471
disconnect_mem_error(conn);
451472
return 0;
452473
}
453474
xmpp_stanza_set_name(auth, "response");
454-
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
475+
xmpp_stanza_set_ns(auth, sasl_ns);
455476
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
456477
} else {
457478
return _handle_sasl_result(conn, stanza, "DIGEST-MD5");
@@ -488,6 +509,7 @@ static int _handle_scram_challenge(xmpp_conn_t *conn,
488509
scram_ctx->alg->scram_name, name);
489510

490511
if (strcmp(name, "challenge") == 0) {
512+
const char* sasl_ns = conn->sasl_support & SASL_MASK_SASL2 ? XMPP_NS_SASL2 : XMPP_NS_SASL;
491513
text = xmpp_stanza_get_text(stanza);
492514
if (!text)
493515
goto err;
@@ -508,7 +530,7 @@ static int _handle_scram_challenge(xmpp_conn_t *conn,
508530
if (!auth)
509531
goto err_free_response;
510532
xmpp_stanza_set_name(auth, "response");
511-
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
533+
xmpp_stanza_set_ns(auth, sasl_ns);
512534

513535
authdata = xmpp_stanza_new(conn->ctx);
514536
if (!authdata)
@@ -658,16 +680,41 @@ static xmpp_stanza_t *_make_starttls(xmpp_conn_t *conn)
658680
return starttls;
659681
}
660682

661-
static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t *conn, const char *mechanism)
683+
static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t *conn, const char *mechanism, const char *initial_data)
662684
{
663-
xmpp_stanza_t *auth;
685+
xmpp_stanza_t *auth, *init, *inittxt;
664686

665687
/* build auth stanza */
688+
inittxt = xmpp_stanza_new(conn->ctx);
689+
if (!inittxt) return NULL;
666690
auth = xmpp_stanza_new(conn->ctx);
667691
if (auth) {
668-
xmpp_stanza_set_name(auth, "auth");
669-
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
692+
if (conn->sasl_support & SASL_MASK_SASL2) {
693+
xmpp_stanza_set_name(auth, "authenticate");
694+
xmpp_stanza_set_ns(auth, XMPP_NS_SASL2);
695+
if (initial_data) {
696+
init = xmpp_stanza_new(conn->ctx);
697+
if (!init) {
698+
xmpp_stanza_release(auth);
699+
return NULL;
700+
}
701+
xmpp_stanza_set_name(init, "initial-response");
702+
xmpp_stanza_set_ns(init, XMPP_NS_SASL2);
703+
xmpp_stanza_set_text(inittxt, initial_data);
704+
xmpp_stanza_add_child_ex(init, inittxt, 0);
705+
xmpp_stanza_add_child_ex(auth, init, 0);
706+
}
707+
} else {
708+
xmpp_stanza_set_name(auth, "auth");
709+
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
710+
if (initial_data) {
711+
xmpp_stanza_set_text(inittxt, initial_data);
712+
xmpp_stanza_add_child_ex(auth, inittxt, 0);
713+
}
714+
}
670715
xmpp_stanza_set_attribute(auth, "mechanism", mechanism);
716+
} else {
717+
xmpp_stanza_release(inittxt);
671718
}
672719

673720
return auth;
@@ -681,7 +728,6 @@ static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t *conn, const char *mechanism)
681728
static void _auth(xmpp_conn_t *conn)
682729
{
683730
xmpp_stanza_t *auth;
684-
xmpp_stanza_t *authdata;
685731
struct scram_user_data *scram_ctx;
686732
char *authid;
687733
char *str;
@@ -734,15 +780,17 @@ static void _auth(xmpp_conn_t *conn)
734780
return;
735781
}
736782

783+
const char* sasl_ns = conn->sasl_support & SASL_MASK_SASL2 ? XMPP_NS_SASL2 : XMPP_NS_SASL;
784+
737785
if (anonjid && (conn->sasl_support & SASL_MASK_ANONYMOUS)) {
738786
/* some crap here */
739-
auth = _make_sasl_auth(conn, "ANONYMOUS");
787+
auth = _make_sasl_auth(conn, "ANONYMOUS", NULL);
740788
if (!auth) {
741789
disconnect_mem_error(conn);
742790
return;
743791
}
744792

745-
handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL,
793+
handler_add(conn, _handle_sasl_result, sasl_ns, NULL, NULL,
746794
"ANONYMOUS");
747795

748796
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
@@ -751,39 +799,28 @@ static void _auth(xmpp_conn_t *conn)
751799
conn->sasl_support &= ~SASL_MASK_ANONYMOUS;
752800
} else if (conn->sasl_support & SASL_MASK_EXTERNAL) {
753801
/* more crap here */
754-
auth = _make_sasl_auth(conn, "EXTERNAL");
755-
if (!auth) {
756-
disconnect_mem_error(conn);
757-
return;
758-
}
759-
760-
authdata = xmpp_stanza_new(conn->ctx);
761-
if (!authdata) {
762-
xmpp_stanza_release(auth);
763-
disconnect_mem_error(conn);
764-
return;
765-
}
766802
str = tls_id_on_xmppaddr(conn, 0);
767803
if (!str || (tls_id_on_xmppaddr_num(conn) == 1 &&
768804
strcmp(str, conn->jid) == 0)) {
769-
xmpp_stanza_set_text(authdata, "=");
805+
str = strophe_strdup(conn->ctx, "=");
770806
} else {
771807
strophe_free(conn->ctx, str);
772808
str = xmpp_base64_encode(conn->ctx, (void *)conn->jid,
773809
strlen(conn->jid));
774810
if (!str) {
775-
xmpp_stanza_release(authdata);
776-
xmpp_stanza_release(auth);
777811
disconnect_mem_error(conn);
778812
return;
779813
}
780-
xmpp_stanza_set_text(authdata, str);
781814
}
782-
strophe_free(conn->ctx, str);
783815

784-
xmpp_stanza_add_child_ex(auth, authdata, 0);
816+
auth = _make_sasl_auth(conn, "EXTERNAL", str);
817+
strophe_free(conn->ctx, str);
818+
if (!auth) {
819+
disconnect_mem_error(conn);
820+
return;
821+
}
785822

786-
handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL,
823+
handler_add(conn, _handle_sasl_result, sasl_ns, NULL, NULL,
787824
"EXTERNAL");
788825

789826
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
@@ -810,18 +847,11 @@ static void _auth(xmpp_conn_t *conn)
810847
}
811848
}
812849

813-
auth = _make_sasl_auth(conn, scram_ctx->alg->scram_name);
814-
if (!auth) {
815-
disconnect_mem_error(conn);
816-
return;
817-
}
818-
819850
scram_ctx->conn = conn;
820851
scram_ctx->sasl_plus =
821852
scram_ctx->alg->mask & SASL_MASK_SCRAM_PLUS ? 1 : 0;
822853
if (_make_scram_init_msg(scram_ctx)) {
823854
strophe_free(conn->ctx, scram_ctx);
824-
xmpp_stanza_release(auth);
825855
disconnect_mem_error(conn);
826856
return;
827857
}
@@ -832,56 +862,39 @@ static void _auth(xmpp_conn_t *conn)
832862
if (!str) {
833863
strophe_free(conn->ctx, scram_ctx->scram_init);
834864
strophe_free(conn->ctx, scram_ctx);
835-
xmpp_stanza_release(auth);
836865
disconnect_mem_error(conn);
837866
return;
838867
}
839868

840-
authdata = xmpp_stanza_new(conn->ctx);
841-
if (!authdata) {
842-
strophe_free(conn->ctx, str);
843-
strophe_free(conn->ctx, scram_ctx->scram_init);
844-
strophe_free(conn->ctx, scram_ctx);
845-
xmpp_stanza_release(auth);
869+
auth = _make_sasl_auth(conn, scram_ctx->alg->scram_name, str);
870+
strophe_free(conn->ctx, str);
871+
if (!auth) {
846872
disconnect_mem_error(conn);
847873
return;
848874
}
849-
xmpp_stanza_set_text(authdata, str);
850-
strophe_free(conn->ctx, str);
851-
xmpp_stanza_add_child_ex(auth, authdata, 0);
852875

853-
handler_add(conn, _handle_scram_challenge, XMPP_NS_SASL, NULL, NULL,
876+
handler_add(conn, _handle_scram_challenge, sasl_ns, NULL, NULL,
854877
(void *)scram_ctx);
855878

856879
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
857880

858881
/* SASL algorithm was tried, unset flag */
859882
conn->sasl_support &= ~scram_ctx->alg->mask;
860883
} else if (conn->sasl_support & SASL_MASK_DIGESTMD5) {
861-
auth = _make_sasl_auth(conn, "DIGEST-MD5");
884+
auth = _make_sasl_auth(conn, "DIGEST-MD5", NULL);
862885
if (!auth) {
863886
disconnect_mem_error(conn);
864887
return;
865888
}
866889

867-
handler_add(conn, _handle_digestmd5_challenge, XMPP_NS_SASL, NULL, NULL,
890+
handler_add(conn, _handle_digestmd5_challenge, sasl_ns, NULL, NULL,
868891
NULL);
869892

870893
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
871894

872895
/* SASL DIGEST-MD5 was tried, unset flag */
873896
conn->sasl_support &= ~SASL_MASK_DIGESTMD5;
874897
} else if (conn->sasl_support & SASL_MASK_PLAIN) {
875-
auth = _make_sasl_auth(conn, "PLAIN");
876-
if (!auth) {
877-
disconnect_mem_error(conn);
878-
return;
879-
}
880-
authdata = xmpp_stanza_new(conn->ctx);
881-
if (!authdata) {
882-
disconnect_mem_error(conn);
883-
return;
884-
}
885898
authid = _get_authid(conn);
886899
if (!authid) {
887900
disconnect_mem_error(conn);
@@ -892,13 +905,16 @@ static void _auth(xmpp_conn_t *conn)
892905
disconnect_mem_error(conn);
893906
return;
894907
}
895-
xmpp_stanza_set_text(authdata, str);
908+
909+
auth = _make_sasl_auth(conn, "PLAIN", str);
896910
strophe_free(conn->ctx, str);
897911
strophe_free(conn->ctx, authid);
912+
if (!auth) {
913+
disconnect_mem_error(conn);
914+
return;
915+
}
898916

899-
xmpp_stanza_add_child_ex(auth, authdata, 0);
900-
901-
handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL,
917+
handler_add(conn, _handle_sasl_result, sasl_ns, NULL, NULL,
902918
"PLAIN");
903919

904920
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);

src/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ struct _xmpp_send_queue_t {
176176
#define SASL_MASK_SCRAMSHA1_PLUS (1 << 7)
177177
#define SASL_MASK_SCRAMSHA256_PLUS (1 << 8)
178178
#define SASL_MASK_SCRAMSHA512_PLUS (1 << 9)
179+
#define SASL_MASK_SASL2 (1 << 10)
179180

180181
#define SASL_MASK_SCRAM_PLUS \
181182
(SASL_MASK_SCRAMSHA1_PLUS | SASL_MASK_SCRAMSHA256_PLUS | \

strophe.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ extern "C" {
5252
* Namespace definition for 'urn:ietf:params:xml:ns:xmpp-sasl'.
5353
*/
5454
#define XMPP_NS_SASL "urn:ietf:params:xml:ns:xmpp-sasl"
55+
/** @def XMPP_NS_SASL2
56+
* Namespace definition for 'urn:xmpp:sasl:2'.
57+
*/
58+
#define XMPP_NS_SASL2 "urn:xmpp:sasl:2"
5559
/** @def XMPP_NS_BIND
5660
* Namespace definition for 'urn:ietf:params:xml:ns:xmpp-bind'.
5761
*/

0 commit comments

Comments
 (0)