Skip to content

Commit

Permalink
refactor: improve api semantics and configurability
Browse files Browse the repository at this point in the history
  • Loading branch information
cad committed Aug 12, 2017
1 parent eb1c1e6 commit 87c8f6f
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 68 deletions.
2 changes: 1 addition & 1 deletion cmd/ovpmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func main() {
if c.GlobalBool("verbose") {
logrus.SetLevel(logrus.DebugLevel)
}
ovpm.SetupDB()
ovpm.SetupDB("sqlite3", "")
return nil
}
app.After = func(c *cli.Context) error {
Expand Down
5 changes: 3 additions & 2 deletions const.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ const (

// DefaultVPNPort is the default OpenVPN port to listen.
DefaultVPNPort = "1197"
etcBasePath = "/etc/ovpm/"
varBasePath = "/var/db/ovpm/"

etcBasePath = "/etc/ovpm/"
varBasePath = "/var/db/ovpm/"

_DefaultConfigPath = etcBasePath + "ovpm.ini"
_DefaultDBPath = varBasePath + "db.sqlite3"
Expand Down
9 changes: 6 additions & 3 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ var db *gorm.DB
// SetupDB prepares database for use.
//
// It should be run at the start of the program.
func SetupDB() {
func SetupDB(dialect string, args ...interface{}) {
if len(args) > 0 && args[0] == "" {
args[0] = _DefaultDBPath
}
var err error
db, err = gorm.Open("sqlite3", _DefaultDBPath)
db, err = gorm.Open(dialect, args...)
if err != nil {
logrus.Fatalf("couldn't open sqlite database %s: %v", _DefaultDBPath, err)
logrus.Fatalf("couldn't open sqlite database %v: %v", args, err)
}

db.AutoMigrate(&DBUser{})
Expand Down
9 changes: 9 additions & 0 deletions pki/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package pki

// PEM encoding types
const (
PEMCertificateBlockType string = "CERTIFICATE"
PEMRSAPrivateKeyBlockType = "RSA PRIVATE KEY"
PEMx509CRLBlockType = "X509 CRL"
PEMCSRBlockType = "CERTIFICATE REQUEST"
)
118 changes: 59 additions & 59 deletions pki/pki.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func NewCA() (*CA, error) {
}

csr := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE REQUEST", Bytes: csrCertificate,
Type: PEMCSRBlockType, Bytes: csrCertificate,
})

// Serial number
Expand Down Expand Up @@ -100,10 +100,10 @@ func NewCA() (*CA, error) {

var request bytes.Buffer
var privateKey bytes.Buffer
if err := pem.Encode(&request, &pem.Block{Type: "CERTIFICATE", Bytes: certificate}); err != nil {
if err := pem.Encode(&request, &pem.Block{Type: PEMCertificateBlockType, Bytes: certificate}); err != nil {
return nil, err
}
if err := pem.Encode(&privateKey, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)}); err != nil {
if err := pem.Encode(&privateKey, &pem.Block{Type: PEMRSAPrivateKeyBlockType, Bytes: x509.MarshalPKCS1PrivateKey(key)}); err != nil {
return nil, err
}

Expand All @@ -117,64 +117,18 @@ func NewCA() (*CA, error) {

}

// NewServerCertHolder generates a x509 certificate and a key-pair for the server.
// NewServerCertHolder generates a RSA key-pair and a x509 certificate signed by the CA for the server.
func NewServerCertHolder(ca *CA) (*CertHolder, error) {
return newCert("localhost", ca, true)
return newCert(ca, true, "localhost")
}

// NewClientCertHolder generates a x509 certificate and a key-pair for the client.
func NewClientCertHolder(username string, ca *CA) (*CertHolder, error) {
return newCert(username, ca, false)
// NewClientCertHolder generates a RSA key-pair and a x509 certificate signed by the CA for the client.
func NewClientCertHolder(ca *CA, username string) (*CertHolder, error) {
return newCert(ca, false, username)
}

// NewCRL takes in a list of certificate serial numbers to-be-revoked and a CA then makes a PEM encoded CRL and returns it as a string.
func NewCRL(serials []*big.Int, ca *CA) (string, error) {
caCrt, err := ReadCertFromPEM(ca.Cert)
if err != nil {
return "", err
}

block, _ := pem.Decode([]byte(ca.Key))
if block == nil {
return "", fmt.Errorf("failed to parse ca private key")
}

priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return "", fmt.Errorf("failed to parse ca private key: %s", err)
}
var revokedCertList []pkix.RevokedCertificate
for _, serial := range serials {
revokedCert := pkix.RevokedCertificate{
SerialNumber: serial,
RevocationTime: time.Now().UTC(),
}
revokedCertList = append(revokedCertList, revokedCert)
}
crl, err := caCrt.CreateCRL(rand.Reader, priv, revokedCertList, time.Now().UTC(), time.Now().Add(365*24*60*time.Minute).UTC())
if err != nil {
return "", err
}

crlPem := pem.EncodeToMemory(&pem.Block{
Type: "X509 CRL",
Bytes: crl,
})

return string(crlPem[:]), nil

}

// ReadCertFromPEM decodes a PEM encoded string into a x509.Certificate.
func ReadCertFromPEM(s string) (*x509.Certificate, error) {
block, _ := pem.Decode([]byte(s))
var cert *x509.Certificate
cert, _ = x509.ParseCertificate(block.Bytes)
return cert, nil
}

// newCert generates a private key and a certificate, that is signed by the given CA.
func newCert(cn string, ca *CA, server bool) (*CertHolder, error) {
// newCert generates a RSA key-pair and a x509 certificate signed by the CA.
func newCert(ca *CA, server bool, cn string) (*CertHolder, error) {
// Get CA private key
block, _ := pem.Decode([]byte(ca.Key))
if block == nil {
Expand Down Expand Up @@ -208,7 +162,7 @@ func newCert(cn string, ca *CA, server bool) (*CertHolder, error) {
SerialNumber: serial,
Subject: pkix.Name{
CommonName: cn,
Organization: []string{"Innovation"},
Organization: []string{"OVPM"},
},
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
Expand All @@ -225,12 +179,12 @@ func newCert(cn string, ca *CA, server bool) (*CertHolder, error) {
}

priKeyPem := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Type: PEMRSAPrivateKeyBlockType,
Bytes: x509.MarshalPKCS1PrivateKey(key),
})

certPem := pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Type: PEMCertificateBlockType,
Bytes: cert,
})

Expand All @@ -239,3 +193,49 @@ func newCert(cn string, ca *CA, server bool) (*CertHolder, error) {
Cert: string(certPem[:]),
}, nil
}

// NewCRL takes in a list of certificate serial numbers to-be-revoked and a CA then makes a PEM encoded CRL and returns it as a string.
func NewCRL(ca *CA, serials ...*big.Int) (string, error) {
caCrt, err := ReadCertFromPEM(ca.Cert)
if err != nil {
return "", err
}

block, _ := pem.Decode([]byte(ca.Key))
if block == nil {
return "", fmt.Errorf("failed to parse ca private key")
}

priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return "", fmt.Errorf("failed to parse ca private key: %s", err)
}
var revokedCertList []pkix.RevokedCertificate
for _, serial := range serials {
revokedCert := pkix.RevokedCertificate{
SerialNumber: serial,
RevocationTime: time.Now().UTC(),
}
revokedCertList = append(revokedCertList, revokedCert)
}
crl, err := caCrt.CreateCRL(rand.Reader, priv, revokedCertList, time.Now().UTC(), time.Now().Add(365*24*60*time.Minute).UTC())
if err != nil {
return "", err
}

crlPem := pem.EncodeToMemory(&pem.Block{
Type: PEMx509CRLBlockType,
Bytes: crl,
})

return string(crlPem[:]), nil

}

// ReadCertFromPEM decodes a PEM encoded string into a x509.Certificate.
func ReadCertFromPEM(s string) (*x509.Certificate, error) {
block, _ := pem.Decode([]byte(s))
var cert *x509.Certificate
cert, _ = x509.ParseCertificate(block.Bytes)
return cert, nil
}
8 changes: 6 additions & 2 deletions user.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ func (u *DBUser) setPassword(password string) error {
return nil
}

func (u *DBUser) checkPassword(password string) bool {
return u.Password == password
}

// GetUser finds and returns the user with the given username from database.
func GetUser(username string) (*DBUser, error) {
user := DBUser{}
Expand Down Expand Up @@ -81,7 +85,7 @@ func CreateNewUser(username, password string) (*DBUser, error) {
return nil, err
}

clientCert, err := pki.NewClientCertHolder(username, ca)
clientCert, err := pki.NewClientCertHolder(ca, username)
if err != nil {
return nil, fmt.Errorf("can not create client cert %s: %v", username, err)
}
Expand Down Expand Up @@ -161,7 +165,7 @@ func (u *DBUser) Sign() error {
return err
}

clientCert, err := pki.NewClientCertHolder(u.Username, ca)
clientCert, err := pki.NewClientCertHolder(ca, u.Username)
if err != nil {
return fmt.Errorf("can not create client cert %s: %v", u.Username, err)
}
Expand Down
10 changes: 9 additions & 1 deletion vpn.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ type _VPNServerConfig struct {

// Init regenerates keys and certs for a Root CA, and saves them in the database.
func Init(hostname string, port string) error {
if port == "" {
port = DefaultVPNPort
}

if !govalidator.IsNumeric(port) {
return fmt.Errorf("validation error: port:`%s` should be numeric", hostname)
}

serverName := "default"
if IsInitialized() {
if err := Deinit(); err != nil {
Expand Down Expand Up @@ -410,7 +418,7 @@ func emitCRL() error {
if err != nil {
return fmt.Errorf("can not emit CRL: %v", err)
}
crl, err := pki.NewCRL(revokedCertSerials, systemCA)
crl, err := pki.NewCRL(systemCA, revokedCertSerials...)
if err != nil {
return fmt.Errorf("can not emit crl: %v", err)
}
Expand Down

0 comments on commit 87c8f6f

Please sign in to comment.