rtsp: do not send a learned session id to another origin
No binary (build failed)
—
(log yok)
| @@ -31,7 +31,8 @@ Session ID for the handle. Useful for resuming an in-progress session. Once | |
| this value is set to any non-NULL value, libcurl returns | |
| *CURLE_RTSP_SESSION_ERROR* if the ID received from the server does not match. | |
| If unset (or set to NULL), libcurl automatically sets the ID the first time | |
| - | the server sets it in a response. |
| + | the server sets it in a response. Such an ID is only sent back to the origin |
| + | that issued it, unless CURLOPT_UNRESTRICTED_AUTH(3) is set. |
| The application does not have to keep the string around after setting this | |
| option. | |
| @@ -41,6 +41,7 @@ | |
| #include "curlx/strdup.h" | |
| #include "bufref.h" | |
| #include "curlx/strparse.h" | |
| + | #include "peer.h" |
| /* meta key for storing protocol meta at easy handle */ | |
| #define CURL_META_RTSP_EASY "meta:proto:rtsp:easy" | |
| @@ -457,6 +458,12 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) | |
| result = rtsp_setup_request(data, &block, rtspreq); | |
| if(result) | |
| goto out; | |
| + | |
| + | if(block.session_id && data->state.rtsp_session_origin && |
| + | !data->set.allow_auth_to_other_hosts && |
| + | !Curl_peer_equal(data->state.origin, data->state.rtsp_session_origin)) |
| + | block.session_id = NULL; |
| + | |
| /* | |
| * Sanity check the custom headers | |
| */ | |
| @@ -1014,6 +1021,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header) | |
| if(!mem || | |
| CURL_EASY_STR_SETN(data, STRING_RTSP_SESSION_ID, mem)) | |
| return CURLE_OUT_OF_MEMORY; | |
| + | Curl_peer_link(&data->state.rtsp_session_origin, data->state.origin); |
| } | |
| } | |
| else if(checkprefix("Transport:", header)) { | |
| @@ -2417,6 +2417,7 @@ static CURLcode setopt_cptr_misc(struct Curl_easy *data, CURLoption option, | |
| return Curl_setstropt(data, STRING_SASL_AUTHZID, ptr); | |
| #ifndef CURL_DISABLE_RTSP | |
| case CURLOPT_RTSP_SESSION_ID: | |
| + | Curl_peer_unlink(&data->state.rtsp_session_origin); |
| return Curl_setstropt(data, STRING_RTSP_SESSION_ID, ptr); | |
| case CURLOPT_RTSP_STREAM_URI: | |
| return Curl_setstropt(data, STRING_RTSP_STREAM_URI, ptr); | |
| @@ -244,6 +244,9 @@ CURLcode Curl_close(struct Curl_easy **datap) | |
| Curl_ssl_close_all(data); | |
| Curl_peer_unlink(&data->state.origin); | |
| Curl_peer_unlink(&data->state.initial_origin); | |
| + | #ifndef CURL_DISABLE_RTSP |
| + | Curl_peer_unlink(&data->state.rtsp_session_origin); |
| + | #endif |
| Curl_ssl_free_certinfo(data); | |
| Curl_bufref_free(&data->state.referer); | |
| @@ -620,6 +620,8 @@ struct UrlState { | |
| #endif | |
| #ifndef CURL_DISABLE_RTSP | |
| /* This RTSP state information survives requests and connections */ | |
| + | struct Curl_peer *rtsp_session_origin; /* origin that issued the session id, |
| + | NULL when set by the application */ |
| uint8_t rtp_channel_mask[32]; /* for the correctness checking of the | |
| interleaved data */ | |
| uint32_t rtsp_next_client_CSeq; /* the session's next client CSeq */ | |
| @@ -2096,6 +2096,7 @@ TESTCASES = \ | |
| test3230 \ | |
| test3231 \ | |
| test3232 \ | |
| + | test3233 \ |
| \ | |
| test3300 \ | |
| test3301 \ | |
| @@ -0,0 +1,59 @@ | |
| + | <?xml version="1.0" encoding="US-ASCII"?> |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | RTSP |
| + | SESSION_ID |
| + | followlocation |
| + | </keywords> |
| + | </info> |
| + | |
| + | # Server-side |
| + | <reply> |
| + | <data1> |
| + | RTSP/1.0 302 Found |
| + | Server: RTSPD/libcurl-test |
| + | CSeq: 1 |
| + | Session: SHOULD-NOT-LEAK |
| + | Location: rtsp://example.com:%RTSPPORT/%TESTNUMBER |
| + | Curl-private: swsbounce swsclose |
| + | |
| + | </data1> |
| + | <data2> |
| + | RTSP/1.0 200 OK |
| + | Server: RTSPD/libcurl-test |
| + | CSeq: 2 |
| + | Curl-private: swsclose |
| + | |
| + | </data2> |
| + | </reply> |
| + | |
| + | # Client-Side |
| + | <client> |
| + | <server> |
| + | rtsp |
| + | </server> |
| + | <tool> |
| + | lib%TESTNUMBER |
| + | </tool> |
| + | |
| + | <name> |
| + | RTSP session id is not sent to another origin after a redirect |
| + | </name> |
| + | <command> |
| + | rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER0001 example.com:%RTSPPORT:%HOSTIP |
| + | </command> |
| + | </client> |
| + | |
| + | <verify> |
| + | <protocol crlf="headers"> |
| + | OPTIONS rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER0001 RTSP/1.0 |
| + | CSeq: 1 |
| + | |
| + | OPTIONS rtsp://%HOSTIP:%RTSPPORT/%TESTNUMBER0001 RTSP/1.0 |
| + | CSeq: 2 |
| + | |
| + | </protocol> |
| + | </verify> |
| + | |
| + | </testcase> |
| @@ -333,6 +333,7 @@ TESTS_C = \ | |
| lib3207.c \ | |
| lib3208.c \ | |
| lib3231.c \ | |
| + | lib3233.c \ |
| lib3595.c \ | |
| lib3596.c \ | |
| lib5000.c \ | |
| @@ -0,0 +1,70 @@ | |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| + | * |
| + | * This software is licensed as described in the file COPYING, which |
| + | * you should have received as part of this distribution. The terms |
| + | * are also available at https://curl.se/docs/copyright.html. |
| + | * |
| + | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| + | * copies of the Software, and permit persons to whom the Software is |
| + | * furnished to do so, under the terms of the COPYING file. |
| + | * |
| + | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| + | * KIND, either express or implied. |
| + | * |
| + | * SPDX-License-Identifier: curl |
| + | * |
| + | ***************************************************************************/ |
| + | #include "first.h" |
| + | |
| + | /* |
| + | * A session id learned from one origin must not be sent to another one |
| + | * after a redirect. |
| + | */ |
| + | static CURLcode test_lib3233(const char *URL) |
| + | { |
| + | CURLcode result; |
| + | CURL *curl; |
| + | struct curl_slist *resolve = NULL; |
| + | |
| + | if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { |
| + | curl_mfprintf(stderr, "curl_global_init() failed\n"); |
| + | return TEST_ERR_MAJOR_BAD; |
| + | } |
| + | |
| + | curl = curl_easy_init(); |
| + | if(!curl) { |
| + | curl_mfprintf(stderr, "curl_easy_init() failed\n"); |
| + | curl_global_cleanup(); |
| + | return TEST_ERR_MAJOR_BAD; |
| + | } |
| + | |
| + | resolve = curl_slist_append(resolve, libtest_arg2); |
| + | |
| + | easy_setopt(curl, CURLOPT_HEADERDATA, stdout); |
| + | easy_setopt(curl, CURLOPT_WRITEDATA, stdout); |
| + | easy_setopt(curl, CURLOPT_VERBOSE, 1L); |
| + | |
| + | easy_setopt(curl, CURLOPT_URL, URL); |
| + | easy_setopt(curl, CURLOPT_RTSP_STREAM_URI, URL); |
| + | easy_setopt(curl, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_OPTIONS); |
| + | easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); |
| + | easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "rtsp"); |
| + | easy_setopt(curl, CURLOPT_RESOLVE, resolve); |
| + | |
| + | result = curl_easy_perform(curl); |
| + | |
| + | test_cleanup: |
| + | |
| + | curl_slist_free_all(resolve); |
| + | curl_easy_cleanup(curl); |
| + | curl_global_cleanup(); |
| + | |
| + | return result; |
| + | } |