8531c006d4
* enhancement: supporting http tunneled rtsp * refactor: simplify HTTP tunnel support per review feedback - Extract streamCandidate() for nmap port classification - Add isCommonHTTPPort() for masscan and nmap fallback - Move URL building to Stream.String() and Stream.URL() - Pass Stream directly to attack methods instead of individual args - Add TLS config for HTTPS tunnel support - Make auth detection non-fatal for tunneled streams - Rename HTTPTunnel to UseHTTPTunnel * - Testing the auth workflow for the tunneled streams is not blocking the rest of the pipeline since I changed the return values to Auth unknown and nil - added extra ports in the test according to suggestions * fixing some lint errors * removing the unused buildrtspurl * delayed the urlstream call for clarity removed error messages refactored the test that used the deprecated buildTRSPurl to use stream.URL and stream.String() methods * extracting iscommonHTTP port to pkg/ports (package ports) switching on u.scheme to create proper schemes for http and https * refactor: replace HTTP tunnel bool with scheme-based detection; enable TLS only for HTTPS-tunneled streams * chore: simnplify InferTunnelScheme and newRTSPClient * fix: remove rendundant check in streamCandidate * fix: typo in parseScheme * tests: coverage for new schemes * fix: use RTSP and not RTSPS for HTTPS URLs * fix: tunneled RTSP scheme handling and auth detection fallback * ui: render empty credentials as none in summary and TUI * chore: ignore duplicate-string warning for none literal * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix: rtsps probe headers --------- Co-authored-by: Brendan Le Glaunec <brendan@glaulabs.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
165 lines
3.9 KiB
Go
165 lines
3.9 KiB
Go
package attack
|
|
|
|
import (
|
|
"net/netip"
|
|
"net/url"
|
|
"testing"
|
|
|
|
"github.com/Ullaakut/cameradar/v6"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestStreamURL(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
stream cameradar.Stream
|
|
wantURL string
|
|
wantParsedScheme string
|
|
}{
|
|
{
|
|
name: "empty route",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
},
|
|
wantURL: "rtsp://192.168.0.10:554/",
|
|
},
|
|
{
|
|
name: "root route",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{"/"},
|
|
},
|
|
wantURL: "rtsp://192.168.0.10:554/",
|
|
},
|
|
{
|
|
name: "multiple leading slashes",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{"////"},
|
|
},
|
|
wantURL: "rtsp://192.168.0.10:554/",
|
|
},
|
|
{
|
|
name: "route with no leading slash",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{"stream"},
|
|
},
|
|
wantURL: "rtsp://192.168.0.10:554/stream",
|
|
},
|
|
{
|
|
name: "route with leading slash",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{"/stream"},
|
|
},
|
|
wantURL: "rtsp://192.168.0.10:554/stream",
|
|
},
|
|
{
|
|
name: "route with trailing slash",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{"stream/"},
|
|
},
|
|
wantURL: "rtsp://192.168.0.10:554/stream/",
|
|
},
|
|
{
|
|
name: "route with spaces",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{" /stream "},
|
|
},
|
|
wantURL: "rtsp://192.168.0.10:554/stream",
|
|
},
|
|
{
|
|
name: "username and password",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{"stream"},
|
|
Username: "admin",
|
|
Password: "admin123",
|
|
},
|
|
wantURL: "rtsp://admin:admin123@192.168.0.10:554/stream",
|
|
},
|
|
{
|
|
name: "empty username with password",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{"stream"},
|
|
Password: "pass",
|
|
},
|
|
wantURL: "rtsp://:pass@192.168.0.10:554/stream",
|
|
},
|
|
{
|
|
name: "username only",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{"stream"},
|
|
Username: "user",
|
|
},
|
|
wantURL: "rtsp://user:@192.168.0.10:554/stream",
|
|
},
|
|
{
|
|
name: "http scheme",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{"stream"},
|
|
Scheme: "http",
|
|
},
|
|
wantURL: "http://192.168.0.10:554/stream",
|
|
wantParsedScheme: "rtsp",
|
|
},
|
|
{
|
|
name: "https scheme",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{"stream"},
|
|
Scheme: "https",
|
|
},
|
|
wantURL: "https://192.168.0.10:554/stream",
|
|
wantParsedScheme: "rtsps",
|
|
},
|
|
{
|
|
name: "rtsps scheme",
|
|
stream: cameradar.Stream{
|
|
Address: netip.MustParseAddr("192.168.0.10"),
|
|
Port: 554,
|
|
Routes: []string{"stream"},
|
|
Scheme: "rtsps",
|
|
},
|
|
wantURL: "rtsps://192.168.0.10:554/stream",
|
|
wantParsedScheme: "rtsps",
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
gotURL := test.stream.String()
|
|
require.Equal(t, test.wantURL, gotURL)
|
|
|
|
parsedURL, err := test.stream.URL()
|
|
require.NoError(t, err)
|
|
|
|
expectedURL, err := url.Parse(test.wantURL)
|
|
require.NoError(t, err)
|
|
wantParsedScheme := test.wantParsedScheme
|
|
if wantParsedScheme == "" {
|
|
wantParsedScheme = expectedURL.Scheme
|
|
}
|
|
require.Equal(t, wantParsedScheme, parsedURL.Scheme)
|
|
})
|
|
}
|
|
}
|