Skip to content

Commit 0d2421c

Browse files
singpolymasjaeckel
authored andcommitted
1 parent 8992211 commit 0d2421c

3 files changed

Lines changed: 106 additions & 77 deletions

File tree

src/auth.c

Lines changed: 101 additions & 77 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,8 @@ 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 =
412+
conn->sasl_support & SASL_MASK_SASL2 ? XMPP_NS_SASL2 : XMPP_NS_SASL;
392413
text = xmpp_stanza_get_text(stanza);
393414
response = sasl_digest_md5(conn->ctx, text, conn->jid, conn->pass);
394415
if (!response) {
@@ -403,7 +424,7 @@ static int _handle_digestmd5_challenge(xmpp_conn_t *conn,
403424
return 0;
404425
}
405426
xmpp_stanza_set_name(auth, "response");
406-
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
427+
xmpp_stanza_set_ns(auth, sasl_ns);
407428

408429
authdata = xmpp_stanza_new(conn->ctx);
409430
if (!authdata) {
@@ -416,8 +437,7 @@ static int _handle_digestmd5_challenge(xmpp_conn_t *conn,
416437

417438
xmpp_stanza_add_child_ex(auth, authdata, 0);
418439

419-
handler_add(conn, _handle_digestmd5_rspauth, XMPP_NS_SASL, NULL, NULL,
420-
NULL);
440+
handler_add(conn, _handle_digestmd5_rspauth, sasl_ns, NULL, NULL, NULL);
421441

422442
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
423443

@@ -444,14 +464,16 @@ 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 =
468+
conn->sasl_support & SASL_MASK_SASL2 ? XMPP_NS_SASL2 : XMPP_NS_SASL;
447469
/* assume it's an rspauth response */
448470
auth = xmpp_stanza_new(conn->ctx);
449471
if (!auth) {
450472
disconnect_mem_error(conn);
451473
return 0;
452474
}
453475
xmpp_stanza_set_name(auth, "response");
454-
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
476+
xmpp_stanza_set_ns(auth, sasl_ns);
455477
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
456478
} else {
457479
return _handle_sasl_result(conn, stanza, "DIGEST-MD5");
@@ -488,6 +510,8 @@ static int _handle_scram_challenge(xmpp_conn_t *conn,
488510
scram_ctx->alg->scram_name, name);
489511

490512
if (strcmp(name, "challenge") == 0) {
513+
const char *sasl_ns =
514+
conn->sasl_support & SASL_MASK_SASL2 ? XMPP_NS_SASL2 : XMPP_NS_SASL;
491515
text = xmpp_stanza_get_text(stanza);
492516
if (!text)
493517
goto err;
@@ -508,7 +532,7 @@ static int _handle_scram_challenge(xmpp_conn_t *conn,
508532
if (!auth)
509533
goto err_free_response;
510534
xmpp_stanza_set_name(auth, "response");
511-
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
535+
xmpp_stanza_set_ns(auth, sasl_ns);
512536

513537
authdata = xmpp_stanza_new(conn->ctx);
514538
if (!authdata)
@@ -658,16 +682,48 @@ static xmpp_stanza_t *_make_starttls(xmpp_conn_t *conn)
658682
return starttls;
659683
}
660684

661-
static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t *conn, const char *mechanism)
685+
static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t *conn,
686+
const char *mechanism,
687+
const char *initial_data)
662688
{
663-
xmpp_stanza_t *auth;
689+
xmpp_stanza_t *auth, *init;
690+
xmpp_stanza_t *inittxt = NULL;
664691

665692
/* build auth stanza */
693+
if (initial_data) {
694+
inittxt = xmpp_stanza_new(conn->ctx);
695+
if (!inittxt)
696+
return NULL;
697+
}
666698
auth = xmpp_stanza_new(conn->ctx);
667699
if (auth) {
668-
xmpp_stanza_set_name(auth, "auth");
669-
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
700+
if (conn->sasl_support & SASL_MASK_SASL2) {
701+
xmpp_stanza_set_name(auth, "authenticate");
702+
xmpp_stanza_set_ns(auth, XMPP_NS_SASL2);
703+
if (initial_data) {
704+
init = xmpp_stanza_new(conn->ctx);
705+
if (!init) {
706+
xmpp_stanza_release(auth);
707+
return NULL;
708+
}
709+
xmpp_stanza_set_name(init, "initial-response");
710+
xmpp_stanza_set_ns(init, XMPP_NS_SASL2);
711+
xmpp_stanza_set_text(inittxt, initial_data);
712+
xmpp_stanza_add_child_ex(init, inittxt, 0);
713+
xmpp_stanza_add_child_ex(auth, init, 0);
714+
}
715+
} else {
716+
xmpp_stanza_set_name(auth, "auth");
717+
xmpp_stanza_set_ns(auth, XMPP_NS_SASL);
718+
if (initial_data) {
719+
xmpp_stanza_set_text(inittxt, initial_data);
720+
xmpp_stanza_add_child_ex(auth, inittxt, 0);
721+
}
722+
}
670723
xmpp_stanza_set_attribute(auth, "mechanism", mechanism);
724+
} else {
725+
if (inittxt)
726+
xmpp_stanza_release(inittxt);
671727
}
672728

673729
return auth;
@@ -681,7 +737,6 @@ static xmpp_stanza_t *_make_sasl_auth(xmpp_conn_t *conn, const char *mechanism)
681737
static void _auth(xmpp_conn_t *conn)
682738
{
683739
xmpp_stanza_t *auth;
684-
xmpp_stanza_t *authdata;
685740
struct scram_user_data *scram_ctx;
686741
char *authid;
687742
char *str;
@@ -734,15 +789,18 @@ static void _auth(xmpp_conn_t *conn)
734789
return;
735790
}
736791

792+
const char *sasl_ns =
793+
conn->sasl_support & SASL_MASK_SASL2 ? XMPP_NS_SASL2 : XMPP_NS_SASL;
794+
737795
if (anonjid && (conn->sasl_support & SASL_MASK_ANONYMOUS)) {
738796
/* some crap here */
739-
auth = _make_sasl_auth(conn, "ANONYMOUS");
797+
auth = _make_sasl_auth(conn, "ANONYMOUS", NULL);
740798
if (!auth) {
741799
disconnect_mem_error(conn);
742800
return;
743801
}
744802

745-
handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL,
803+
handler_add(conn, _handle_sasl_result, sasl_ns, NULL, NULL,
746804
"ANONYMOUS");
747805

748806
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
@@ -751,40 +809,28 @@ static void _auth(xmpp_conn_t *conn)
751809
conn->sasl_support &= ~SASL_MASK_ANONYMOUS;
752810
} else if (conn->sasl_support & SASL_MASK_EXTERNAL) {
753811
/* 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-
}
766812
str = tls_id_on_xmppaddr(conn, 0);
767813
if (!str || (tls_id_on_xmppaddr_num(conn) == 1 &&
768814
strcmp(str, conn->jid) == 0)) {
769-
xmpp_stanza_set_text(authdata, "=");
815+
str = strophe_strdup(conn->ctx, "=");
770816
} else {
771817
strophe_free(conn->ctx, str);
772818
str = xmpp_base64_encode(conn->ctx, (void *)conn->jid,
773819
strlen(conn->jid));
774820
if (!str) {
775-
xmpp_stanza_release(authdata);
776-
xmpp_stanza_release(auth);
777821
disconnect_mem_error(conn);
778822
return;
779823
}
780-
xmpp_stanza_set_text(authdata, str);
781824
}
782-
strophe_free(conn->ctx, str);
783825

784-
xmpp_stanza_add_child_ex(auth, authdata, 0);
826+
auth = _make_sasl_auth(conn, "EXTERNAL", str);
827+
strophe_free(conn->ctx, str);
828+
if (!auth) {
829+
disconnect_mem_error(conn);
830+
return;
831+
}
785832

786-
handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL,
787-
"EXTERNAL");
833+
handler_add(conn, _handle_sasl_result, sasl_ns, NULL, NULL, "EXTERNAL");
788834

789835
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
790836

@@ -810,18 +856,11 @@ static void _auth(xmpp_conn_t *conn)
810856
}
811857
}
812858

813-
auth = _make_sasl_auth(conn, scram_ctx->alg->scram_name);
814-
if (!auth) {
815-
disconnect_mem_error(conn);
816-
return;
817-
}
818-
819859
scram_ctx->conn = conn;
820860
scram_ctx->sasl_plus =
821861
scram_ctx->alg->mask & SASL_MASK_SCRAM_PLUS ? 1 : 0;
822862
if (_make_scram_init_msg(scram_ctx)) {
823863
strophe_free(conn->ctx, scram_ctx);
824-
xmpp_stanza_release(auth);
825864
disconnect_mem_error(conn);
826865
return;
827866
}
@@ -832,56 +871,39 @@ static void _auth(xmpp_conn_t *conn)
832871
if (!str) {
833872
strophe_free(conn->ctx, scram_ctx->scram_init);
834873
strophe_free(conn->ctx, scram_ctx);
835-
xmpp_stanza_release(auth);
836874
disconnect_mem_error(conn);
837875
return;
838876
}
839877

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);
878+
auth = _make_sasl_auth(conn, scram_ctx->alg->scram_name, str);
879+
strophe_free(conn->ctx, str);
880+
if (!auth) {
846881
disconnect_mem_error(conn);
847882
return;
848883
}
849-
xmpp_stanza_set_text(authdata, str);
850-
strophe_free(conn->ctx, str);
851-
xmpp_stanza_add_child_ex(auth, authdata, 0);
852884

853-
handler_add(conn, _handle_scram_challenge, XMPP_NS_SASL, NULL, NULL,
885+
handler_add(conn, _handle_scram_challenge, sasl_ns, NULL, NULL,
854886
(void *)scram_ctx);
855887

856888
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
857889

858890
/* SASL algorithm was tried, unset flag */
859891
conn->sasl_support &= ~scram_ctx->alg->mask;
860892
} else if (conn->sasl_support & SASL_MASK_DIGESTMD5) {
861-
auth = _make_sasl_auth(conn, "DIGEST-MD5");
893+
auth = _make_sasl_auth(conn, "DIGEST-MD5", NULL);
862894
if (!auth) {
863895
disconnect_mem_error(conn);
864896
return;
865897
}
866898

867-
handler_add(conn, _handle_digestmd5_challenge, XMPP_NS_SASL, NULL, NULL,
899+
handler_add(conn, _handle_digestmd5_challenge, sasl_ns, NULL, NULL,
868900
NULL);
869901

870902
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
871903

872904
/* SASL DIGEST-MD5 was tried, unset flag */
873905
conn->sasl_support &= ~SASL_MASK_DIGESTMD5;
874906
} 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-
}
885907
authid = _get_authid(conn);
886908
if (!authid) {
887909
disconnect_mem_error(conn);
@@ -892,14 +914,16 @@ static void _auth(xmpp_conn_t *conn)
892914
disconnect_mem_error(conn);
893915
return;
894916
}
895-
xmpp_stanza_set_text(authdata, str);
917+
918+
auth = _make_sasl_auth(conn, "PLAIN", str);
896919
strophe_free(conn->ctx, str);
897920
strophe_free(conn->ctx, authid);
921+
if (!auth) {
922+
disconnect_mem_error(conn);
923+
return;
924+
}
898925

899-
xmpp_stanza_add_child_ex(auth, authdata, 0);
900-
901-
handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL,
902-
"PLAIN");
926+
handler_add(conn, _handle_sasl_result, sasl_ns, NULL, NULL, "PLAIN");
903927

904928
send_stanza(conn, auth, XMPP_QUEUE_STROPHE);
905929

src/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ struct _xmpp_send_queue_t {
192192
#define SASL_MASK_SCRAMSHA1_PLUS (1 << 7)
193193
#define SASL_MASK_SCRAMSHA256_PLUS (1 << 8)
194194
#define SASL_MASK_SCRAMSHA512_PLUS (1 << 9)
195+
#define SASL_MASK_SASL2 (1 << 10)
195196

196197
#define SASL_MASK_SCRAM_PLUS \
197198
(SASL_MASK_SCRAMSHA1_PLUS | SASL_MASK_SCRAMSHA256_PLUS | \

strophe.h

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

0 commit comments

Comments
 (0)