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