@@ -1304,27 +1304,35 @@ callback_lws_login(struct lws *wsi, enum lws_callback_reasons reason,
13041304 const char * token = lws_spa_get_string (pss -> spa , EPN_TOKEN );
13051305 const char * target = lws_spa_get_string (pss -> spa , EPN_TARGET );
13061306
1307- char origin [128 ];
1308- if (token && vhd && vhd -> auth_server_url && lws_hdr_copy (wsi , origin , sizeof (origin ), WSI_TOKEN_ORIGIN ) > 0 ) {
1309- size_t olen = strlen (origin );
1310- if (olen == 4 && !strcmp (origin , "null" )) {
1311- char referer [256 ];
1312- if (lws_hdr_copy (wsi , referer , sizeof (referer ), WSI_TOKEN_HTTP_REFERER ) > 0 ) {
1313- if (strncmp (referer , vhd -> auth_server_url , strlen (vhd -> auth_server_url ))) {
1314- lwsl_err ("%s: blocking SSO CSRF due to bad Referer %s\n" , __func__ , referer );
1315- token = NULL ;
1316- } else {
1317- lwsl_notice ("%s: allowing null origin due to valid Referer\n" , __func__ );
1318- }
1319- } else {
1320- lwsl_err ("%s: blocking SSO CSRF due to null origin with missing Referer\n" , __func__ );
1307+ char origin [128 ], referer [256 ];
1308+ const char * chk_url = NULL ;
1309+ int has_origin = lws_hdr_copy (wsi , origin , sizeof (origin ), WSI_TOKEN_ORIGIN ) > 0 ;
1310+ int has_referer = lws_hdr_copy (wsi , referer , sizeof (referer ), WSI_TOKEN_HTTP_REFERER ) > 0 ;
1311+
1312+ if (has_origin && strcmp (origin , "null" )) {
1313+ chk_url = origin ;
1314+ } else if (has_referer ) {
1315+ chk_url = referer ;
1316+ }
1317+
1318+ if (token && vhd && vhd -> auth_server_url && chk_url ) {
1319+ lws_parse_uri_t * puri_auth = lws_parse_uri_create (vhd -> auth_server_url );
1320+ lws_parse_uri_t * puri_chk = lws_parse_uri_create (chk_url );
1321+
1322+ if (puri_auth && puri_chk ) {
1323+ if (strcmp (puri_auth -> scheme , puri_chk -> scheme ) ||
1324+ strcasecmp (puri_auth -> host , puri_chk -> host ) ||
1325+ puri_auth -> port != puri_chk -> port ) {
1326+ lwsl_err ("%s: blocking SSO CSRF from origin/referer %s (expected %s)\n" ,
1327+ __func__ , chk_url , vhd -> auth_server_url );
13211328 token = NULL ;
1329+ } else {
1330+ lwsl_notice ("%s: allowing SSO request matching auth server origin %s\n" ,
1331+ __func__ , chk_url );
13221332 }
1323- } else if (strncmp (origin , vhd -> auth_server_url , olen ) ||
1324- (vhd -> auth_server_url [olen ] != '\0' && vhd -> auth_server_url [olen ] != '/' )) {
1325- lwsl_err ("%s: blocking SSO CSRF from origin %s\n" , __func__ , origin );
1326- token = NULL ; /* Nullify to force failure */
13271333 }
1334+ if (puri_auth ) lws_parse_uri_destroy (& puri_auth );
1335+ if (puri_chk ) lws_parse_uri_destroy (& puri_chk );
13281336 }
13291337
13301338 if (token && target && vhd ) {
@@ -1342,11 +1350,31 @@ callback_lws_login(struct lws *wsi, enum lws_callback_reasons reason,
13421350 if (target && target [0 ]) {
13431351 if (target [0 ] == '/' && target [1 ] != '/' ) {
13441352 final_target = target ;
1345- } else if (vhd -> db ) {
1346- if (auth_verify_redirect_uri (vhd , target )) {
1347- final_target = target ;
1348- } else {
1349- lwsl_err ("%s: untrusted absolute target %s\n" , __func__ , target );
1353+ } else {
1354+ lws_parse_uri_t * puri_tgt = lws_parse_uri_create (target );
1355+ if (puri_tgt ) {
1356+ char host [128 ] = "" ;
1357+ const char * h = NULL ;
1358+ if (lws_hdr_copy (wsi , host , sizeof (host ), WSI_TOKEN_HOST ) > 0 )
1359+ h = host ;
1360+ #if defined(LWS_ROLE_H2 )
1361+ else if (lws_hdr_copy (wsi , host , sizeof (host ), WSI_TOKEN_HTTP_COLON_AUTHORITY ) > 0 )
1362+ h = host ;
1363+ #endif
1364+ if (!h ) {
1365+ struct lws_vhost * vh = lws_get_vhost (wsi );
1366+ if (vh ) h = lws_get_vhost_name (vh );
1367+ }
1368+ if (h && !strcasecmp (puri_tgt -> host , h )) {
1369+ final_target = target ;
1370+ } else if (vhd -> db ) {
1371+ if (auth_verify_redirect_uri (vhd , target )) {
1372+ final_target = target ;
1373+ } else {
1374+ lwsl_err ("%s: untrusted absolute target %s\n" , __func__ , target );
1375+ }
1376+ }
1377+ lws_parse_uri_destroy (& puri_tgt );
13501378 }
13511379 }
13521380 }
0 commit comments