Skip to content

Commit

Permalink
Merge "[FAB-3683] SIGSEGV seen for MySQL empty certfiles"
Browse files Browse the repository at this point in the history
  • Loading branch information
christo4ferris authored and Gerrit Code Review committed May 31, 2017
2 parents 2c45212 + 5987a8e commit e4e0a0d
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 30 deletions.
62 changes: 32 additions & 30 deletions lib/dbutil/dbutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func NewUserRegistrySQLLite3(datasource string) (*sqlx.DB, bool, error) {
log.Debugf("Database (%s) does not exist", datasource)
err2 := createSQLiteDBTables(datasource)
if err2 != nil {
return nil, false, err2
return nil, false, fmt.Errorf("Failed to create SQLite3 database: %s", err2)
}
} else {
// database file exists. If os.Stat returned an error
Expand Down Expand Up @@ -82,23 +82,23 @@ func createSQLiteDBTables(datasource string) error {
log.Debug("Database location: ", datasource)
db, err := sqlx.Open("sqlite3", datasource)
if err != nil {
return fmt.Errorf("Failed to open database: %s", err)
return fmt.Errorf("Failed to open SQLite database: %s", err)
}
defer db.Close()

log.Debug("Creating tables...")
if _, err := db.Exec("CREATE TABLE IF NOT EXISTS users (id VARCHAR(64), token bytea, type VARCHAR(64), affiliation VARCHAR(64), attributes VARCHAR(256), state INTEGER, max_enrollments INTEGER)"); err != nil {
return err
return fmt.Errorf("Error creating users table: %s", err)
}
log.Debug("Created users table")

if _, err := db.Exec("CREATE TABLE IF NOT EXISTS affiliations (name VARCHAR(64) NOT NULL UNIQUE, prekey VARCHAR(64))"); err != nil {
return err
return fmt.Errorf("Error creating affiliations table: %s", err)
}
log.Debug("Created affiliation table")

if _, err := db.Exec("CREATE TABLE IF NOT EXISTS certificates (id VARCHAR(64), serial_number bytea NOT NULL, authority_key_identifier bytea NOT NULL, ca_label bytea, status bytea NOT NULL, reason int, expiry timestamp, revoked_at timestamp, pem bytea NOT NULL, PRIMARY KEY(serial_number, authority_key_identifier))"); err != nil {
return err
return fmt.Errorf("Error creating certificates table: %s", err)
}
log.Debug("Created certificates table")

Expand Down Expand Up @@ -134,13 +134,12 @@ func NewUserRegistryPostgres(datasource string, clientTLSConfig *tls.ClientTLSCo

db, err := sqlx.Open("postgres", connStr)
if err != nil {
return nil, false, fmt.Errorf("Failed to open database: %s", err)
return nil, false, fmt.Errorf("Failed to open Postgres database: %s", err)
}

err = db.Ping()
if err != nil {
log.Errorf("Failed to connect to Postgres database [error: %s]", err)
return nil, false, err
return nil, false, fmt.Errorf("Failed to connect to Postgres database: %s", err)
}

// Check if database exists
Expand All @@ -156,7 +155,7 @@ func NewUserRegistryPostgres(datasource string, clientTLSConfig *tls.ClientTLSCo
connStr = connStr + " dbname=" + dbName
err = createPostgresDBTables(connStr, dbName, db)
if err != nil {
return nil, false, err
return nil, false, fmt.Errorf("Failed to create Postgres database: %s", err)
}
} else {
log.Debugf("Database (%s) exists", dbName)
Expand All @@ -177,31 +176,31 @@ func createPostgresDBTables(datasource string, dbName string, db *sqlx.DB) error
query := "CREATE DATABASE " + dbName
_, err := db.Exec(query)
if err != nil {
return fmt.Errorf("Failed to create Postgres database: %s", err)
return fmt.Errorf("Failed to execute create database query: %s", err)
}

database, err := sqlx.Open("postgres", datasource)
if err != nil {
log.Errorf("Failed to open database (%s)", dbName)
return fmt.Errorf("Failed to open database (%s) in Postgres server: %s", dbName, err)
}

log.Debug("Creating Tables...")
if _, err := database.Exec("CREATE TABLE users (id VARCHAR(64), token bytea, type VARCHAR(64), affiliation VARCHAR(64), attributes VARCHAR(256), state INTEGER, max_enrollments INTEGER)"); err != nil {
log.Errorf("Error creating users table [error: %s] ", err)
return err
return fmt.Errorf("Error creating users table: %s", err)
}
log.Debug("Created users table")
if _, err := database.Exec("CREATE TABLE affiliations (name VARCHAR(64) NOT NULL UNIQUE, prekey VARCHAR(64))"); err != nil {
log.Errorf("Error creating affiliations table [error: %s] ", err)
return err
return fmt.Errorf("Error creating affiliations table: %s", err)
}
log.Debug("Created affiliations table")
if _, err := database.Exec("CREATE TABLE certificates (id VARCHAR(64), serial_number bytea NOT NULL, authority_key_identifier bytea NOT NULL, ca_label bytea, status bytea NOT NULL, reason int, expiry timestamp, revoked_at timestamp, pem bytea NOT NULL, PRIMARY KEY(serial_number, authority_key_identifier))"); err != nil {
log.Errorf("Error creating certificates table [error: %s] ", err)
return err
return fmt.Errorf("Error creating certificates table: %s", err)
}
log.Debug("Created certificates table")
return nil
}

// NewUserRegistryMySQL opens a connecton to a postgres database
// NewUserRegistryMySQL opens a connecton to a MySQL database
func NewUserRegistryMySQL(datasource string, clientTLSConfig *tls.ClientTLSConfig) (*sqlx.DB, bool, error) {
log.Debugf("Using MySQL database, connecting to database...")

Expand All @@ -215,7 +214,7 @@ func NewUserRegistryMySQL(datasource string, clientTLSConfig *tls.ClientTLSConfi
if clientTLSConfig.Enabled {
tlsConfig, err := tls.GetClientTLSConfig(clientTLSConfig)
if err != nil {
log.Errorf("Failed to create TLS configuration [error: %s]", err)
return nil, false, fmt.Errorf("Failed to get client TLS for MySQL: %s", err)
}

mysql.RegisterTLSConfig("custom", tlsConfig)
Expand All @@ -224,12 +223,12 @@ func NewUserRegistryMySQL(datasource string, clientTLSConfig *tls.ClientTLSConfi
log.Debug("Connection String: ", connStr)
db, err := sqlx.Open("mysql", connStr)
if err != nil {
return nil, false, fmt.Errorf("Failed to open database: %s", err)
return nil, false, fmt.Errorf("Failed to open MySQL database: %s", err)
}

err = db.Ping()
if err != nil {
log.Errorf("Failed to connect to MySQL database [error: %s]", err)
return nil, false, fmt.Errorf("Failed to connect to MySQL database: %s", err)
}

// Check if database exists
Expand All @@ -245,7 +244,10 @@ func NewUserRegistryMySQL(datasource string, clientTLSConfig *tls.ClientTLSConfi
}

if name == "" {
createMySQLTables(datasource, dbName, db)
err := createMySQLTables(datasource, dbName, db)
if err != nil {
return nil, false, fmt.Errorf("Failed to create MySQL database: %s", err)
}
} else {
log.Debugf("Database (%s) exists", dbName)
exists = true
Expand All @@ -264,26 +266,26 @@ func createMySQLTables(datasource string, dbName string, db *sqlx.DB) error {

_, err := db.Exec("CREATE DATABASE " + dbName)
if err != nil {
panic(err)
return fmt.Errorf("Failed to execute create database query: %s", err)
}

database, err := sqlx.Open("mysql", datasource)
if err != nil {
log.Errorf("Failed to open database (%s), err: %s", dbName, err)
return fmt.Errorf("Failed to open database (%s) in MySQL server: %s", dbName, err)
}
log.Debug("Creating Tables...")
if _, err := database.Exec("CREATE TABLE users (id VARCHAR(64) NOT NULL, token blob, type VARCHAR(64), affiliation VARCHAR(64), attributes VARCHAR(256), state INTEGER, max_enrollments INTEGER, PRIMARY KEY (id)) DEFAULT CHARSET=utf8 COLLATE utf8_bin"); err != nil {
log.Errorf("Error creating users table [error: %s] ", err)
return err
return fmt.Errorf("Error creating users table: %s", err)
}
log.Debug("Created users table")
if _, err := database.Exec("CREATE TABLE affiliations (name VARCHAR(64) NOT NULL UNIQUE, prekey VARCHAR(64))"); err != nil {
log.Errorf("Error creating affiliations table [error: %s] ", err)
return err
return fmt.Errorf("Error creating affiliations table: %s", err)
}
log.Debug("Created affiliations table")
if _, err := database.Exec("CREATE TABLE certificates (id VARCHAR(64), serial_number varbinary(128) NOT NULL, authority_key_identifier varbinary(128) NOT NULL, ca_label varbinary(128), status varbinary(128) NOT NULL, reason int, expiry timestamp DEFAULT '1970-01-01 00:00:01', revoked_at timestamp DEFAULT '1970-01-01 00:00:01', pem varbinary(4096) NOT NULL, PRIMARY KEY(serial_number, authority_key_identifier)) DEFAULT CHARSET=utf8 COLLATE utf8_bin"); err != nil {
log.Errorf("Error creating certificates table [error: %s] ", err)
return err
return fmt.Errorf("Error creating certificates table: %s", err)
}
log.Debug("Created certificates table")

return nil
}
Expand Down
50 changes: 50 additions & 0 deletions lib/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (

"github.com/hyperledger/fabric-ca/api"
. "github.com/hyperledger/fabric-ca/lib"
"github.com/hyperledger/fabric-ca/lib/dbutil"
"github.com/hyperledger/fabric-ca/lib/tls"
"github.com/hyperledger/fabric-ca/util"
"github.com/hyperledger/fabric/bccsp/factory"
Expand Down Expand Up @@ -866,6 +867,55 @@ func TestSqliteLocking(t *testing.T) {
}
}

func TestNewUserRegistryMySQL(t *testing.T) {
datasource := ""

// Test with no cert files specified
tlsConfig := &tls.ClientTLSConfig{
Enabled: true,
}
_, _, err := dbutil.NewUserRegistryMySQL(datasource, tlsConfig)
assert.Error(t, err)
assert.Contains(t, err.Error(), "No TLS certificate files were provided")

// Test with with a file that does not exist
tlsConfig = &tls.ClientTLSConfig{
Enabled: true,
CertFiles: []string{"doesnotexit.pem"},
}
_, _, err = dbutil.NewUserRegistryMySQL(datasource, tlsConfig)
assert.Error(t, err)
assert.Contains(t, err.Error(), "no such file or directory")

// Test with a file that is not of appropriate format
tlsConfig = &tls.ClientTLSConfig{
Enabled: true,
CertFiles: []string{"../testdata/empty.json"},
}
_, _, err = dbutil.NewUserRegistryMySQL(datasource, tlsConfig)
assert.Error(t, err)
assert.Contains(t, err.Error(), "Failed to process certificate from file")

// Test with a file that does not have read permissions
err = os.Chmod("../testdata/root.pem", 0000)
if err != nil {
fmt.Println(err)
}

tlsConfig = &tls.ClientTLSConfig{
Enabled: true,
CertFiles: []string{"../testdata/root.pem"},
}
_, _, err = dbutil.NewUserRegistryMySQL(datasource, tlsConfig)
assert.Error(t, err)
assert.Contains(t, err.Error(), "permission denied")

err = os.Chmod("../testdata/root.pem", 0644)
if err != nil {
fmt.Println(err)
}
}

func TestEnd(t *testing.T) {
os.Remove("../testdata/ca-cert.pem")
os.Remove("../testdata/ca-key.pem")
Expand Down

0 comments on commit e4e0a0d

Please sign in to comment.