83 lines
2.0 KiB
Go
83 lines
2.0 KiB
Go
package jdbc
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
|
|
logContext "github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
|
|
|
mssql "github.com/microsoft/go-mssqldb"
|
|
)
|
|
|
|
type sqlServerJDBC struct {
|
|
connStr string
|
|
}
|
|
|
|
func (s *sqlServerJDBC) ping(ctx context.Context) pingResult {
|
|
return ping(ctx, "mssql", isSqlServerErrorDeterminate,
|
|
s.connStr)
|
|
}
|
|
|
|
func isSqlServerErrorDeterminate(err error) bool {
|
|
// Error numbers from https://learn.microsoft.com/en-us/sql/relational-databases/errors-events/database-engine-events-and-errors?view=sql-server-ver16
|
|
var sqlErr mssql.Error
|
|
if errors.As(err, &sqlErr) {
|
|
switch sqlErr.Number {
|
|
case 18456:
|
|
// Login failed
|
|
// This is a determinate failure iff we tried to use a real user
|
|
return sqlErr.Message != "login error: Login failed for user ''."
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func parseSqlServer(ctx logContext.Context, subname string) (jdbc, error) {
|
|
if !strings.HasPrefix(subname, "//") {
|
|
return nil, errors.New("expected connection to start with //")
|
|
}
|
|
conn := strings.TrimPrefix(subname, "//")
|
|
|
|
port := "1433"
|
|
var password, host string
|
|
|
|
for i, param := range strings.Split(conn, ";") {
|
|
key, value, found := strings.Cut(param, "=")
|
|
if !found && i == 0 {
|
|
// String connectionUrl = "jdbc:sqlserver://<server>:<port>;encrypt=true;databaseName=AdventureWorks;user=<user>;password=<password>";
|
|
if split := strings.Split(param, ":"); len(split) > 1 {
|
|
host = split[0]
|
|
port = split[1]
|
|
} else {
|
|
host = param
|
|
}
|
|
continue
|
|
}
|
|
|
|
switch strings.ToLower(key) {
|
|
case "password":
|
|
password = value
|
|
case "spring.datasource.password":
|
|
password = value
|
|
case "server":
|
|
host = value
|
|
case "port":
|
|
port = value
|
|
}
|
|
}
|
|
|
|
urlStr := fmt.Sprintf("sqlserver://sa:%s@%s:%s?database=master&connection+timeout=5", password, host, port)
|
|
jdbcUrl, err := url.Parse(urlStr)
|
|
if err != nil {
|
|
ctx.Logger().WithName("jdbc").
|
|
V(3).
|
|
Info("Skipping invalid SQL Server URL", "url", urlStr, "err", err)
|
|
return nil, err
|
|
}
|
|
|
|
return &sqlServerJDBC{connStr: jdbcUrl.String()}, nil
|
|
}
|