Add credential embedding in stream URLs for SSE events
Embed username:password@ credentials in discovered stream URLs for basic_auth and combined authentication methods, making URLs directly usable by clients without additional auth handling. **Changes:** - Add embedCredentialsInURL() function in scanner.go - Embed credentials for basic_auth and combined methods only - Skip embedding for no_auth, query_params, digest, url_embedded - Handle edge cases: empty credentials, existing credentials in URL - Apply in scanDirectStream() and testURLsConcurrently() **Security:** - URL encoding handled by url.UserPassword() - Checks prevent credential duplication - Only processes when username AND password are provided **Results:** Before: http://10.0.20.112/snapshot.jpg After: http://admin:password@10.0.20.112/snapshot.jpg Tested with Zosi ZG23213M camera - all 6 streams working correctly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -178,8 +178,12 @@ func (s *Scanner) scanDirectStream(ctx context.Context, req models.StreamDiscove
|
|||||||
|
|
||||||
if testResult.Working {
|
if testResult.Working {
|
||||||
result.TotalFound = 1
|
result.TotalFound = 1
|
||||||
|
|
||||||
|
// Embed credentials in URL for basic_auth and combined methods
|
||||||
|
finalURL := s.embedCredentialsInURL(testResult.URL, req.Username, req.Password, string(testResult.AuthMethod))
|
||||||
|
|
||||||
discoveredStream := models.DiscoveredStream{
|
discoveredStream := models.DiscoveredStream{
|
||||||
URL: testResult.URL,
|
URL: finalURL,
|
||||||
Type: testResult.Type,
|
Type: testResult.Type,
|
||||||
Protocol: testResult.Protocol,
|
Protocol: testResult.Protocol,
|
||||||
Working: true,
|
Working: true,
|
||||||
@@ -231,6 +235,46 @@ func (s *Scanner) extractIP(target string) string {
|
|||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// embedCredentialsInURL embeds username and password in URL for basic_auth and combined methods
|
||||||
|
func (s *Scanner) embedCredentialsInURL(streamURL, username, password, authMethod string) string {
|
||||||
|
// Only apply for basic_auth and combined methods
|
||||||
|
if authMethod != "basic_auth" && authMethod != "combined" {
|
||||||
|
return streamURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if credentials are provided
|
||||||
|
if username == "" || password == "" {
|
||||||
|
return streamURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse URL
|
||||||
|
u, err := url.Parse(streamURL)
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Debug("failed to parse URL for credential embedding",
|
||||||
|
"url", streamURL,
|
||||||
|
"error", err.Error())
|
||||||
|
return streamURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if credentials already exist in URL
|
||||||
|
if u.User != nil {
|
||||||
|
s.logger.Debug("credentials already exist in URL, skipping embedding",
|
||||||
|
"url", streamURL)
|
||||||
|
return streamURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Embed credentials
|
||||||
|
u.User = url.UserPassword(username, password)
|
||||||
|
embeddedURL := u.String()
|
||||||
|
|
||||||
|
s.logger.Debug("credentials embedded in URL",
|
||||||
|
"original_url", streamURL,
|
||||||
|
"embedded_url", embeddedURL,
|
||||||
|
"auth_method", authMethod)
|
||||||
|
|
||||||
|
return embeddedURL
|
||||||
|
}
|
||||||
|
|
||||||
// collectURLs collects all URLs to test
|
// collectURLs collects all URLs to test
|
||||||
func (s *Scanner) collectURLs(ctx context.Context, req models.StreamDiscoveryRequest, ip string) ([]string, error) {
|
func (s *Scanner) collectURLs(ctx context.Context, req models.StreamDiscoveryRequest, ip string) ([]string, error) {
|
||||||
var allURLs []string
|
var allURLs []string
|
||||||
@@ -444,8 +488,11 @@ func (s *Scanner) testURLsConcurrently(ctx context.Context, urls []string, req m
|
|||||||
if testResult.Working {
|
if testResult.Working {
|
||||||
atomic.AddInt32(&found, 1)
|
atomic.AddInt32(&found, 1)
|
||||||
|
|
||||||
|
// Embed credentials in URL for basic_auth and combined methods
|
||||||
|
finalURL := s.embedCredentialsInURL(testResult.URL, req.Username, req.Password, string(testResult.AuthMethod))
|
||||||
|
|
||||||
discoveredStream := models.DiscoveredStream{
|
discoveredStream := models.DiscoveredStream{
|
||||||
URL: testResult.URL,
|
URL: finalURL,
|
||||||
Type: testResult.Type,
|
Type: testResult.Type,
|
||||||
Protocol: testResult.Protocol,
|
Protocol: testResult.Protocol,
|
||||||
Port: 0, // Will be extracted from URL if needed
|
Port: 0, // Will be extracted from URL if needed
|
||||||
|
|||||||
Reference in New Issue
Block a user