@@ -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)
681728static 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 );
0 commit comments