Skip to content

Commit

Permalink
backport of commit f15715f
Browse files Browse the repository at this point in the history
  • Loading branch information
hghaf099 committed Mar 17, 2023
1 parent 3a6f316 commit dbc6709
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 7 deletions.
3 changes: 3 additions & 0 deletions changelog/19591.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
core: validate name identifiers in mssql physical storage backend prior use
```
30 changes: 25 additions & 5 deletions physical/mssql/mssql.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"fmt"
"regexp"
"sort"
"strconv"
"strings"
Expand All @@ -18,6 +19,7 @@ import (

// Verify MSSQLBackend satisfies the correct interfaces
var _ physical.Backend = (*MSSQLBackend)(nil)
var identifierRegex = regexp.MustCompile(`^[\p{L}_][\p{L}\p{Nd}@#$_]*$`)

type MSSQLBackend struct {
dbTable string
Expand All @@ -27,6 +29,13 @@ type MSSQLBackend struct {
permitPool *physical.PermitPool
}

func isInvalidIdentifier(name string) bool {
if !identifierRegex.MatchString(name) {
return true
}
return false
}

func NewMSSQLBackend(conf map[string]string, logger log.Logger) (physical.Backend, error) {
username, ok := conf["username"]
if !ok {
Expand Down Expand Up @@ -68,11 +77,19 @@ func NewMSSQLBackend(conf map[string]string, logger log.Logger) (physical.Backen
database = "Vault"
}

if isInvalidIdentifier(database) {
return nil, fmt.Errorf("invalid database name")
}

table, ok := conf["table"]
if !ok {
table = "Vault"
}

if isInvalidIdentifier(table) {
return nil, fmt.Errorf("invalid table name")
}

appname, ok := conf["appname"]
if !ok {
appname = "Vault"
Expand All @@ -93,6 +110,10 @@ func NewMSSQLBackend(conf map[string]string, logger log.Logger) (physical.Backen
schema = "dbo"
}

if isInvalidIdentifier(schema) {
return nil, fmt.Errorf("invalid schema name")
}

connectionString := fmt.Sprintf("server=%s;app name=%s;connection timeout=%s;log=%s", server, appname, connectionTimeout, logLevel)
if username != "" {
connectionString += ";user id=" + username
Expand All @@ -113,18 +134,17 @@ func NewMSSQLBackend(conf map[string]string, logger log.Logger) (physical.Backen

db.SetMaxOpenConns(maxParInt)

if _, err := db.Exec("IF NOT EXISTS(SELECT * FROM sys.databases WHERE name = '" + database + "') CREATE DATABASE " + database); err != nil {
if _, err := db.Exec("IF NOT EXISTS(SELECT * FROM sys.databases WHERE name = ?) CREATE DATABASE "+database, database); err != nil {
return nil, fmt.Errorf("failed to create mssql database: %w", err)
}

dbTable := database + "." + schema + "." + table
createQuery := "IF NOT EXISTS(SELECT 1 FROM " + database + ".INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND TABLE_NAME='" + table + "' AND TABLE_SCHEMA='" + schema +
"') CREATE TABLE " + dbTable + " (Path VARCHAR(512) PRIMARY KEY, Value VARBINARY(MAX))"
createQuery := "IF NOT EXISTS(SELECT 1 FROM " + database + ".INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE' AND TABLE_NAME=? AND TABLE_SCHEMA=?) CREATE TABLE " + dbTable + " (Path VARCHAR(512) PRIMARY KEY, Value VARBINARY(MAX))"

if schema != "dbo" {

var num int
err = db.QueryRow("SELECT 1 FROM " + database + ".sys.schemas WHERE name = '" + schema + "'").Scan(&num)
err = db.QueryRow("SELECT 1 FROM "+database+".sys.schemas WHERE name = ?", schema).Scan(&num)

switch {
case err == sql.ErrNoRows:
Expand All @@ -137,7 +157,7 @@ func NewMSSQLBackend(conf map[string]string, logger log.Logger) (physical.Backen
}
}

if _, err := db.Exec(createQuery); err != nil {
if _, err := db.Exec(createQuery, table, schema); err != nil {
return nil, fmt.Errorf("failed to create mssql table: %w", err)
}

Expand Down
44 changes: 42 additions & 2 deletions physical/mssql/mssql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,53 @@ import (
"os"
"testing"

_ "github.com/denisenkom/go-mssqldb"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/sdk/helper/logging"
"github.com/hashicorp/vault/sdk/physical"

_ "github.com/denisenkom/go-mssqldb"
)

// TestInvalidIdentifier checks validity of an identifier
func TestInvalidIdentifier(t *testing.T) {
testcases := map[string]bool{
"name": true,
"_name": true,
"Name": true,
"#name": false,
"?Name": false,
"9name": false,
"@name": false,
"$name": false,
" name": false,
"n ame": false,
"n4444444": true,
"_4321098765": true,
"_##$$@@__": true,
"_123name#@": true,
"name!": false,
"name%": false,
"name^": false,
"name&": false,
"name*": false,
"name(": false,
"name)": false,
"nåame": true,
"åname": true,
"name'": false,
"nam`e": false,
"пример": true,
"_#Āā@#$_ĂĄąćĈĉĊċ": true,
"ÛÜÝÞßàáâ": true,
"豈更滑a23$#@": true,
}

for i, expected := range testcases {
if !isInvalidIdentifier(i) != expected {
t.Fatalf("unexpected identifier %s: expected validity %v", i, expected)
}
}
}

func TestMSSQLBackend(t *testing.T) {
server := os.Getenv("MSSQL_SERVER")
if server == "" {
Expand Down

0 comments on commit dbc6709

Please sign in to comment.